| @@ -52,10 +52,19 @@ export default class App extends Vue { | |||||
| Charm: 60 | Charm: 60 | ||||
| } | } | ||||
| }) | }) | ||||
| const cleric = new Creatures.Human(new ProperNoun('Cleric'), FemalePronouns, { | |||||
| stats: { | |||||
| Toughness: 35, | |||||
| Power: 40, | |||||
| Speed: 25, | |||||
| Willpower: 90, | |||||
| Charm: 50 | |||||
| } | |||||
| }) | |||||
| this.left = fighter | this.left = fighter | ||||
| this.right = new Creatures.Withers() | this.right = new Creatures.Withers() | ||||
| this.combatants = [this.left, this.right, wizard, rogue] | |||||
| this.combatants = [this.left, this.right, wizard, rogue, cleric] | |||||
| console.log(this.left) | console.log(this.left) | ||||
| console.log(this.right) | console.log(this.right) | ||||
| } | } | ||||
| @@ -1,22 +1,25 @@ | |||||
| import { Creature, POV, Entity } from '../entity' | |||||
| import { Stat, Damage, DamageType, ConstantDamageFormula, Vigor, Stats } from '../combat' | |||||
| import { MalePronouns, ImproperNoun, POVPair, POVPairArgs, Noun, Pronoun } from '../language' | |||||
| import { LogLine, LogLines } from '../interface' | |||||
| import { VoreType, Stomach, Bowels } from '../vore' | |||||
| import { StatTest } from '../combat/tests' | |||||
| import { AttackAction, TransferAction, FeedAction } from '../combat/actions' | |||||
| import { Creature } from '../entity' | |||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Stats, Vigors } from '../combat' | |||||
| import { MalePronouns, Noun, Pronoun } from '../language' | |||||
| import { VoreType } from '../vore' | |||||
| import { AttackAction } from '../combat/actions' | |||||
| export class Human extends Creature { | export class Human extends Creature { | ||||
| constructor (name: Noun, pronouns: Pronoun, options: { | constructor (name: Noun, pronouns: Pronoun, options: { | ||||
| vigors?: Vigor; | |||||
| stats?: Stats; | stats?: Stats; | ||||
| } = {}) { | } = {}) { | ||||
| let stats | |||||
| let vigors: Vigors | |||||
| let stats: Stats | |||||
| if (options.vigors === undefined) { | |||||
| vigors = { Health: 100, Stamina: 100, Resolve: 100 } | |||||
| } | |||||
| if (options.stats === undefined) { | if (options.stats === undefined) { | ||||
| stats = { Toughness: 20, Power: 20, Speed: 20, Willpower: 20, Charm: 20 } | stats = { Toughness: 20, Power: 20, Speed: 20, Willpower: 20, Charm: 20 } | ||||
| } else { | } else { | ||||
| stats = options.stats | stats = options.stats | ||||
| } | } | ||||
| super(name, MalePronouns, stats, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 25) | |||||
| super(name, pronouns, stats, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 25) | |||||
| this.actions.push(new AttackAction(new ConstantDamageFormula( | this.actions.push(new AttackAction(new ConstantDamageFormula( | ||||
| new Damage( | new Damage( | ||||
| { amount: 20, target: Vigor.Health, type: DamageType.Slash } | { amount: 20, target: Vigor.Health, type: DamageType.Slash } | ||||
| @@ -1,6 +1,6 @@ | |||||
| import { Creature, POV, Entity } from '../entity' | import { Creature, POV, Entity } from '../entity' | ||||
| import { Stat, Damage, DamageType, ConstantDamageFormula, Vigor, Side, PairAction, CombatTest, GroupAction } from '../combat' | import { Stat, Damage, DamageType, ConstantDamageFormula, Vigor, Side, PairAction, CombatTest, GroupAction } from '../combat' | ||||
| import { MalePronouns, ImproperNoun, POVPair, POVPairArgs, ProperNoun, TheyPronouns, FemalePronouns } from '../language' | |||||
| import { MalePronouns, ImproperNoun, POVPair, POVPairArgs, ProperNoun, TheyPronouns, FemalePronouns, RandomWord, Adjective } from '../language' | |||||
| import { LogLine, LogLines, LogEntry } from '../interface' | import { LogLine, LogLines, LogEntry } from '../interface' | ||||
| import { VoreType, Stomach, Bowels, Container } from '../vore' | import { VoreType, Stomach, Bowels, Container } from '../vore' | ||||
| import { StatTest } from '../combat/tests' | import { StatTest } from '../combat/tests' | ||||
| @@ -8,6 +8,15 @@ import { AttackAction, TransferAction, FeedAction } from '../combat/actions' | |||||
| import { TogetherCondition } from '../combat/conditions' | import { TogetherCondition } from '../combat/conditions' | ||||
| import { InstantKill } from '../combat/effects' | import { InstantKill } from '../combat/effects' | ||||
| const huge = new RandomWord([ | |||||
| new Adjective('massive'), | |||||
| new Adjective('colossal'), | |||||
| new Adjective('big ol\''), | |||||
| new Adjective('heavy'), | |||||
| new Adjective('crushing'), | |||||
| new Adjective('huge') | |||||
| ]) | |||||
| class BiteAction extends AttackAction { | class BiteAction extends AttackAction { | ||||
| constructor () { | constructor () { | ||||
| super(new ConstantDamageFormula(new Damage({ amount: 50, type: DamageType.Slash, target: Vigor.Health }))) | super(new ConstantDamageFormula(new Damage({ amount: 50, type: DamageType.Slash, target: Vigor.Health }))) | ||||
| @@ -18,8 +27,8 @@ class BiteAction extends AttackAction { | |||||
| class StompAction extends GroupAction { | class StompAction extends GroupAction { | ||||
| lines: POVPair<Creature, Creature> = new POVPair([ | lines: POVPair<Creature, Creature> = new POVPair([ | ||||
| [[POV.First, POV.Third], (user: Creature, target: Creature) => new LogLine(`You flatten ${target.name} under your foot!`)], | [[POV.First, POV.Third], (user: Creature, target: Creature) => new LogLine(`You flatten ${target.name} under your foot!`)], | ||||
| [[POV.Third, POV.First], (user: Creature, target: Creature) => new LogLine(`${user.name.capital} flattens you under ${user.pronouns.possessive} foot!`)], | |||||
| [[POV.Third, POV.Third], (user: Creature, target: Creature) => new LogLine(`${user.name.capital} flattens ${target.name} under ${user.pronouns.possessive} foot!`)] | |||||
| [[POV.Third, POV.First], (user: Creature, target: Creature) => new LogLine(`${user.name.capital} flattens you under ${user.pronouns.possessive} ${huge} foot!`)], | |||||
| [[POV.Third, POV.Third], (user: Creature, target: Creature) => new LogLine(`${user.name.capital} flattens ${target.name} under ${user.pronouns.possessive} ${huge} foot!`)] | |||||
| ]) | ]) | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -73,6 +73,15 @@ interface WordOptions { | |||||
| count: boolean; | count: boolean; | ||||
| } | } | ||||
| const emptyConfig: WordOptions = { | |||||
| capital: false, | |||||
| count: false, | |||||
| kind: NounKind.Specific, | |||||
| plural: false, | |||||
| proper: false, | |||||
| vowel: VowelSound.Default | |||||
| } | |||||
| export type TextLike = { toString: () => string } | export type TextLike = { toString: () => string } | ||||
| // updates as needed | // updates as needed | ||||
| @@ -96,61 +105,98 @@ export class DynText { | |||||
| return (this.parts.map(part => part.toString())).join('') | return (this.parts.map(part => part.toString())).join('') | ||||
| } | } | ||||
| } | } | ||||
| export class Noun implements Pluralizable { | |||||
| constructor (private singularNoun: string, private pluralNoun: string|null = null, private options: WordOptions = { plural: false, capital: false, proper: false, kind: NounKind.Specific, vowel: VowelSound.Default, count: true }) { | |||||
| export abstract class Word { | |||||
| constructor (public opt: WordOptions = emptyConfig) { | |||||
| } | } | ||||
| get capital (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| abstract configure (opts: WordOptions): Word; | |||||
| abstract toString (): string; | |||||
| // These functions are pure; they don't mutate the original object. | |||||
| // This is necessary to avoid causing chaos. | |||||
| get capital (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.capital = true | opts.capital = true | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get plural (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get plural (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.plural = true | opts.plural = true | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get proper (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get proper (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.proper = true | opts.proper = true | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get improper (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get improper (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.proper = false | opts.proper = false | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get specific (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get specific (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.kind = NounKind.Specific | opts.kind = NounKind.Specific | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get nonspecific (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get nonspecific (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.kind = NounKind.Nonspecific | opts.kind = NounKind.Nonspecific | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get all (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get all (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.kind = NounKind.All | opts.kind = NounKind.All | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | } | ||||
| get uncountable (): Noun { | |||||
| const opts: WordOptions = Object.assign({}, this.options) | |||||
| get uncountable (): Word { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.count = false | opts.count = false | ||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| return this.configure(opts) | |||||
| } | |||||
| } | |||||
| export class RandomWord extends Word { | |||||
| private last: number | |||||
| constructor (public choices: Array<Word>, opt: WordOptions = emptyConfig) { | |||||
| super(opt) | |||||
| this.last = -1 | |||||
| } | |||||
| configure (opts: WordOptions): Word { | |||||
| return new RandomWord(this.choices, opts) | |||||
| } | |||||
| toString (): string { | |||||
| let choice | |||||
| do { | |||||
| choice = Math.floor(Math.random() * this.choices.length) | |||||
| } while (choice === this.last) | |||||
| this.last = choice | |||||
| return this.choices[choice].configure(this.opt).toString() | |||||
| } | |||||
| } | |||||
| export class Noun extends Word { | |||||
| constructor (private singularNoun: string, private pluralNoun: string|null = null, private options: WordOptions = emptyConfig) { | |||||
| super(options) | |||||
| } | } | ||||
| get isPlural (): boolean { | |||||
| return this.options.plural | |||||
| configure (opts: WordOptions): Word { | |||||
| return new Noun(this.singularNoun, this.pluralNoun, opts) | |||||
| } | } | ||||
| toString (): string { | toString (): string { | ||||
| @@ -208,6 +254,20 @@ export class ProperNoun extends Noun { | |||||
| } | } | ||||
| } | } | ||||
| export class Adjective extends Word { | |||||
| constructor (private adjective: string, opt: WordOptions = emptyConfig) { | |||||
| super(opt) | |||||
| } | |||||
| configure (opts: WordOptions): Word { | |||||
| return new Adjective(this.adjective, opts) | |||||
| } | |||||
| toString (): string { | |||||
| return this.adjective | |||||
| } | |||||
| } | |||||
| interface PronounDict { | interface PronounDict { | ||||
| subjective: string; | subjective: string; | ||||
| objective: string; | objective: string; | ||||