| @@ -1,8 +1,8 @@ | |||||
| import { Creature, POV } from '../entity' | import { Creature, POV } from '../entity' | ||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction } from '../combat' | import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction } from '../combat' | ||||
| import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective } from '../language' | |||||
| import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs } from '../language' | |||||
| import { LogLine, LogLines, LogEntry } from '../interface' | import { LogLine, LogLines, LogEntry } from '../interface' | ||||
| import { VoreType, Stomach, Container } from '../vore' | |||||
| import { VoreType, Stomach, Container, Vore } from '../vore' | |||||
| import { AttackAction, FeedAction } from '../combat/actions' | import { AttackAction, FeedAction } from '../combat/actions' | ||||
| import { TogetherCondition } from '../combat/conditions' | import { TogetherCondition } from '../combat/conditions' | ||||
| import { InstantKill } from '../combat/effects' | import { InstantKill } from '../combat/effects' | ||||
| @@ -68,7 +68,7 @@ class DevourAllAction extends GroupAction { | |||||
| executeGroup (user: Creature, targets: Array<Creature>): LogEntry { | executeGroup (user: Creature, targets: Array<Creature>): LogEntry { | ||||
| return new LogLines(...targets.map(target => this.execute(user, target)).concat( | return new LogLines(...targets.map(target => this.execute(user, target)).concat( | ||||
| [new LogLine(`${Words.SwallowSound.allCaps}! All ${targets.length} of them pour down ${user.name}'s ${Words.Slick} gullet; they're just ${user.kind.all} chow now`)] | |||||
| [new LogLine(`${Words.SwallowSound.allCaps}! All ${targets.length} of them pour down ${user.name}'s ${Words.Slick} gullet as ${user.pronouns.possessive} ${Words.Swallows.singular}; they're just ${user.kind.all} chow now`)] | |||||
| )) | )) | ||||
| } | } | ||||
| @@ -100,11 +100,23 @@ export class Withers extends Creature { | |||||
| this.side = Side.Monsters | this.side = Side.Monsters | ||||
| const stomach = new Stomach(this, 50, new Damage( | const stomach = new Stomach(this, 50, new Damage( | ||||
| { amount: 30, type: DamageType.Acid, target: Vigor.Health }, | |||||
| { amount: 20, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 20, type: DamageType.Dominance, target: Vigor.Resolve } | |||||
| { amount: 300, type: DamageType.Acid, target: Vigor.Health }, | |||||
| { amount: 200, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 200, type: DamageType.Dominance, target: Vigor.Resolve } | |||||
| )) | )) | ||||
| stomach.tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([ | |||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach ${Words.Churns.singular} you for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())] | |||||
| ]) | |||||
| stomach.digestLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach ${Words.Digests.singular} ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach ${Words.Digests.singular} you`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind}'s ${stomach.name}.`)] | |||||
| ]) | |||||
| this.containers.push(stomach) | this.containers.push(stomach) | ||||
| this.otherActions.push(new FeedAction(stomach)) | this.otherActions.push(new FeedAction(stomach)) | ||||
| @@ -60,6 +60,14 @@ enum VowelSound { | |||||
| NonVowel | NonVowel | ||||
| } | } | ||||
| enum VerbKind { | |||||
| Root, | |||||
| Singular, | |||||
| Present, | |||||
| Past, | |||||
| PastParticiple | |||||
| } | |||||
| export interface Pluralizable { | export interface Pluralizable { | ||||
| isPlural: boolean; | isPlural: boolean; | ||||
| } | } | ||||
| @@ -69,7 +77,8 @@ interface WordOptions { | |||||
| capital: boolean; | capital: boolean; | ||||
| allCaps: boolean; | allCaps: boolean; | ||||
| proper: boolean; | proper: boolean; | ||||
| kind: NounKind; | |||||
| nounKind: NounKind; | |||||
| verbKind: VerbKind; | |||||
| vowel: VowelSound; | vowel: VowelSound; | ||||
| count: boolean; | count: boolean; | ||||
| } | } | ||||
| @@ -78,7 +87,8 @@ const emptyConfig: WordOptions = { | |||||
| allCaps: false, | allCaps: false, | ||||
| capital: false, | capital: false, | ||||
| count: false, | count: false, | ||||
| kind: NounKind.Specific, | |||||
| nounKind: NounKind.Specific, | |||||
| verbKind: VerbKind.Root, | |||||
| plural: false, | plural: false, | ||||
| proper: false, | proper: false, | ||||
| vowel: VowelSound.Default | vowel: VowelSound.Default | ||||
| @@ -151,19 +161,19 @@ export abstract class Word { | |||||
| get specific (): this { | get specific (): this { | ||||
| const opts: WordOptions = Object.assign({}, this.opt) | const opts: WordOptions = Object.assign({}, this.opt) | ||||
| opts.kind = NounKind.Specific | |||||
| opts.nounKind = NounKind.Specific | |||||
| return this.configure(opts) as this | return this.configure(opts) as this | ||||
| } | } | ||||
| get nonspecific (): this { | get nonspecific (): this { | ||||
| const opts: WordOptions = Object.assign({}, this.opt) | const opts: WordOptions = Object.assign({}, this.opt) | ||||
| opts.kind = NounKind.Nonspecific | |||||
| opts.nounKind = NounKind.Nonspecific | |||||
| return this.configure(opts) as this | return this.configure(opts) as this | ||||
| } | } | ||||
| get all (): this { | get all (): this { | ||||
| const opts: WordOptions = Object.assign({}, this.opt) | const opts: WordOptions = Object.assign({}, this.opt) | ||||
| opts.kind = NounKind.All | |||||
| opts.nounKind = NounKind.All | |||||
| return this.configure(opts) as this | return this.configure(opts) as this | ||||
| } | } | ||||
| @@ -172,6 +182,36 @@ export abstract class Word { | |||||
| opts.count = false | opts.count = false | ||||
| return this.configure(opts) as this | return this.configure(opts) as this | ||||
| } | } | ||||
| get root (): this { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.verbKind = VerbKind.Root | |||||
| return this.configure(opts) as this | |||||
| } | |||||
| get singular (): this { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.verbKind = VerbKind.Singular | |||||
| return this.configure(opts) as this | |||||
| } | |||||
| get present (): this { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.verbKind = VerbKind.Present | |||||
| return this.configure(opts) as this | |||||
| } | |||||
| get past (): this { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.verbKind = VerbKind.Past | |||||
| return this.configure(opts) as this | |||||
| } | |||||
| get pastParticiple (): this { | |||||
| const opts: WordOptions = Object.assign({}, this.opt) | |||||
| opts.verbKind = VerbKind.PastParticiple | |||||
| return this.configure(opts) as this | |||||
| } | |||||
| } | } | ||||
| export class RandomWord extends Word { | export class RandomWord extends Word { | ||||
| @@ -220,7 +260,7 @@ export class Noun extends Word { | |||||
| } | } | ||||
| if (!this.options.proper) { | if (!this.options.proper) { | ||||
| if (this.options.kind === NounKind.Nonspecific && this.options.count) { | |||||
| if (this.options.nounKind === NounKind.Nonspecific && this.options.count) { | |||||
| if (this.options.plural) { | if (this.options.plural) { | ||||
| result = 'some ' + result | result = 'some ' + result | ||||
| } else { | } else { | ||||
| @@ -236,7 +276,7 @@ export class Noun extends Word { | |||||
| result = 'a ' + result | result = 'a ' + result | ||||
| } | } | ||||
| } | } | ||||
| } else if (this.options.kind === NounKind.Specific) { | |||||
| } else if (this.options.nounKind === NounKind.Specific) { | |||||
| result = 'the ' + result | result = 'the ' + result | ||||
| } | } | ||||
| } | } | ||||
| @@ -253,13 +293,13 @@ export class Noun extends Word { | |||||
| export class ImproperNoun extends Noun { | export class ImproperNoun extends Noun { | ||||
| constructor (singularNoun: string, pluralNoun: string = singularNoun) { | constructor (singularNoun: string, pluralNoun: string = singularNoun) { | ||||
| super(singularNoun, pluralNoun, { plural: false, allCaps: false, capital: false, proper: false, kind: NounKind.Specific, vowel: VowelSound.Default, count: true }) | |||||
| super(singularNoun, pluralNoun, { plural: false, allCaps: false, capital: false, proper: false, nounKind: NounKind.Specific, verbKind: VerbKind.Root, vowel: VowelSound.Default, count: true }) | |||||
| } | } | ||||
| } | } | ||||
| export class ProperNoun extends Noun { | export class ProperNoun extends Noun { | ||||
| constructor (singularNoun: string) { | constructor (singularNoun: string) { | ||||
| super(singularNoun, null, { plural: false, allCaps: false, capital: false, proper: true, kind: NounKind.Specific, vowel: VowelSound.Default, count: true }) | |||||
| super(singularNoun, null, { plural: false, allCaps: false, capital: false, proper: true, nounKind: NounKind.Specific, verbKind: VerbKind.Root, vowel: VowelSound.Default, count: true }) | |||||
| } | } | ||||
| } | } | ||||
| @@ -272,11 +312,49 @@ export class Adjective extends Word { | |||||
| return new Adjective(this.adjective, opts) | return new Adjective(this.adjective, opts) | ||||
| } | } | ||||
| // TODO caps et al. | |||||
| toString (): string { | toString (): string { | ||||
| return this.adjective | return this.adjective | ||||
| } | } | ||||
| } | } | ||||
| export class Verb extends Word { | |||||
| configure (opts: WordOptions): Word { | |||||
| return new Verb( | |||||
| this._root, | |||||
| this._singular, | |||||
| this._present, | |||||
| this._past, | |||||
| this._pastParticiple, | |||||
| opts | |||||
| ) | |||||
| } | |||||
| toString (): string { | |||||
| let choice: string | |||||
| switch (this.opt.verbKind) { | |||||
| case VerbKind.Root: choice = this._root; break | |||||
| case VerbKind.Singular: choice = this._singular; break | |||||
| case VerbKind.Present: choice = this._present; break | |||||
| case VerbKind.Past: choice = this._past; break | |||||
| case VerbKind.PastParticiple: choice = this._pastParticiple; break | |||||
| } | |||||
| if (this.opt.allCaps) { | |||||
| choice = choice.toUpperCase() | |||||
| } else if (this.opt.capital) { | |||||
| choice = choice.slice(0, 1).toUpperCase() + choice.slice(1) | |||||
| } | |||||
| return choice | |||||
| } | |||||
| constructor (private _root: string, private _singular: string = _root + "s", private _present: string = _root + "ing", private _past: string = _root + "ed", private _pastParticiple: string = _past, public opt: WordOptions = emptyConfig) { | |||||
| super(opt) | |||||
| } | |||||
| } | |||||
| interface PronounDict { | interface PronounDict { | ||||
| subjective: string; | subjective: string; | ||||
| objective: string; | objective: string; | ||||
| @@ -201,19 +201,19 @@ export class Stomach extends NormalContainer { | |||||
| super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage) | super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage) | ||||
| } | } | ||||
| consumeLines = new POVPair([ | |||||
| consumeLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You devour ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`You devour ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} munches you`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} munches you`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} munches ${target.name}`)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} munches ${target.name}`)] | ||||
| ]) | ]) | ||||
| releaseLines = new POVPair([ | |||||
| releaseLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You hork up ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`You hork up ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} horks you up`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} horks you up`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} horks up ${target.name}`)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} horks up ${target.name}`)] | ||||
| ]) | ]) | ||||
| struggleLines = new POVPair([ | |||||
| struggleLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You claw your way out of ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`You claw your way out of ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} forces ${user.pronouns.possessive} way up your throat!`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} forces ${user.pronouns.possessive} way up your throat!`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from the gut of ${target.name}`)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from the gut of ${target.name}`)] | ||||
| @@ -225,19 +225,19 @@ export class Stomach extends NormalContainer { | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | ||||
| ]) | ]) | ||||
| digestLines = new POVPair([ | |||||
| digestLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach overwhelms ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach overwhelms ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach finishes you off`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach finishes you off`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)] | ||||
| ]) | ]) | ||||
| absorbLines = new POVPair([ | |||||
| absorbLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your guts completely absorb ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`Your guts completely absorb ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s guts soak you up like water in a sponge`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s guts soak you up like water in a sponge`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] | ||||
| ]) | ]) | ||||
| disposeLines = new POVPair([ | |||||
| disposeLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your guts completely absorb ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`Your guts completely absorb ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s guts soak you up like water in a sponge`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s guts soak you up like water in a sponge`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { RandomWord, ImproperNoun, Adjective } from './language' | |||||
| import { RandomWord, ImproperNoun, Adjective, Verb } from './language' | |||||
| export const SwallowSound = new RandomWord([ | export const SwallowSound = new RandomWord([ | ||||
| new ImproperNoun('gulp'), | new ImproperNoun('gulp'), | ||||
| @@ -12,3 +12,21 @@ export const Slick = new RandomWord([ | |||||
| new Adjective('slimy'), | new Adjective('slimy'), | ||||
| new Adjective('glistening') | new Adjective('glistening') | ||||
| ]) | ]) | ||||
| export const Swallows = new RandomWord([ | |||||
| new Verb("swallow"), | |||||
| new Verb("gulp") | |||||
| ]) | |||||
| export const Churns = new RandomWord([ | |||||
| new Verb("churn"), | |||||
| new Verb("sizzle", "sizzles", "sizzling", "sizzled"), | |||||
| new Verb("simmer"), | |||||
| new Verb("stew") | |||||
| ]) | |||||
| export const Digests = new RandomWord([ | |||||
| new Verb("digest"), | |||||
| new Verb("melt"), | |||||
| new Verb("dissolve", "dissolves", "dissolving", "dissolved") | |||||
| ]) | |||||