From f8cbaf8d664d6a6e162e4b2e7c68ad8c9d34bb59 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Fri, 10 Jul 2020 22:11:26 -0400 Subject: [PATCH] Completely rewrite how text is generated --- src/App.vue | 3 +- src/components/Combat.vue | 26 ++- src/game/combat.ts | 344 ++++++++++++++++++----------------- src/game/creatures/player.ts | 12 +- src/game/creatures/wolf.ts | 6 +- src/game/interface.ts | 5 +- src/game/language.ts | 51 +++++- src/game/vore.ts | 226 +++++++++++------------ 8 files changed, 362 insertions(+), 311 deletions(-) diff --git a/src/App.vue b/src/App.vue index 5f0a152..85f145d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -22,8 +22,7 @@ export default class App extends Vue { enemy: Creature constructor () { super() - this.player = new Creatures.Wolf() - this.player.perspective = POV.First + this.player = new Creatures.Player() this.enemy = new Creatures.Wolf() console.log(this.player) console.log(this.enemy) diff --git a/src/components/Combat.vue b/src/components/Combat.vue index 1bcf39d..bb383ad 100644 --- a/src/components/Combat.vue +++ b/src/components/Combat.vue @@ -5,20 +5,24 @@ +

Your moves

- - +
+ + +
{{actionDescription}}

Enemy moves

- - +
+ +
-
+
@@ -71,8 +75,20 @@ a { display: flex; justify-content: center; } +.vert-display { + display: flex; + flex-direction: column; +} .combat-button { width: 100px; height: 100px; } + + diff --git a/src/game/combat.ts b/src/game/combat.ts index d8a05ee..f4aaf25 100644 --- a/src/game/combat.ts +++ b/src/game/combat.ts @@ -1,9 +1,78 @@ -import { Creature, POV } from './entity' -import { POVActionPicker } from './language' +import { Creature, POV, Entity } from './entity' +import { POVPair, POVPairArgs } from './language' import { Container } from './vore' import { LogEntry, LogLines, CompositeLog } from './interface' -export enum DamageType {Pierce, Slash, Crush, Acid} +export interface CombatTest { + test: (user: Creature, target: Creature) => boolean; + odds: (user: Creature, target: Creature) => number; + explain: (user: Creature, target: Creature) => LogEntry; +} + +function logistic (x0: number, L: number, k: number): (x: number) => number { + return (x: number) => { + return L / (1 + Math.exp(-k * (x - x0))) + } +} + +abstract class RandomTest implements CombatTest { + test (user: Creature, target: Creature): boolean { + return Math.random() < this.odds(user, target) + } + + abstract odds(user: Creature, target: Creature): number + abstract explain(user: Creature, target: Creature): LogEntry +} + +export class StatTest extends RandomTest { + private f: (x: number) => number + + constructor (public readonly stat: Stat, k = 0.1) { + super() + this.f = logistic(0, 1, k) + } + + odds (user: Creature, target: Creature): number { + return this.f(user.stats[this.stat] - target.stats[this.stat]) + } + + explain (user: Creature, target: Creature): LogEntry { + const delta: number = user.stats[this.stat] - target.stats[this.stat] + let result: string + + if (delta === 0) { + result = 'You and the target have the same ' + this.stat + '.' + } else if (delta < 0) { + result = 'You have ' + delta + ' less ' + this.stat + ' than your foe.' + } else { + result = 'You have ' + delta + ' more ' + this.stat + ' than you foe.' + } + + result += ' Your odds of success are ' + (100 * this.odds(user, target)) + '%' + + return new LogLines(result) + } +} + +export class ChanceTest extends RandomTest { + constructor (public readonly chance: number) { + super() + } + + odds (user: Creature, target: Creature): number { + return this.chance + } + + explain (user: Creature, target: Creature): LogEntry { + return new LogLines('You have a flat ' + (100 * this.chance) + '% chance.') + } +} + +export enum DamageType { + Pierce = "Pierce", + Slash = "Slash", + Crush = "Crush", + Acid = "Acid"} export interface DamageInstance { type: DamageType; @@ -11,24 +80,28 @@ export interface DamageInstance { } export class Damage { - readonly damages: DamageInstance[] + readonly damages: DamageInstance[] - constructor (...damages: DamageInstance[]) { - this.damages = damages - } + constructor (...damages: DamageInstance[]) { + this.damages = damages + } - scale (factor: number): Damage { - const results: Array = [] + scale (factor: number): Damage { + const results: Array = [] - this.damages.forEach(damage => { - results.push({ - type: damage.type, - amount: damage.amount * factor - }) + this.damages.forEach(damage => { + results.push({ + type: damage.type, + amount: damage.amount * factor }) + }) - return new Damage(...results) - } + return new Damage(...results) + } + + toString (): string { + return this.damages.map(damage => damage.amount + " " + damage.type).join("/") + } } export enum Stat { @@ -83,91 +156,108 @@ abstract class TogetherAction extends PairAction { } export class AttackAction extends TogetherAction { - protected lines: POVActionPicker = { - [POV.First]: { - [POV.First]: (user, target) => new LogLines('You bite...yourself?'), - [POV.Third]: (user, target) => new LogLines('You bite ' + target.name) - }, - [POV.Third]: { - [POV.First]: (user, target) => new LogLines(user.name.capital + ' bites you'), - [POV.Third]: (user, target) => new LogLines(user.name.capital + ' bites ' + target.name) - } - } - - constructor (protected damage: Damage) { - super('Attack', 'Attack the enemy') - } + private test: StatTest + + protected successLines: POVPairArgs = new POVPairArgs([ + [[POV.First, POV.Third], (user, target, args) => new LogLines(`You smack ${target.name} for ${args.damage} damage`)], + [[POV.Third, POV.First], (user, target, args) => new LogLines(`${user.name.capital} hits you for ${args.damage} damage`)], + [[POV.Third, POV.Third], (user, target, args) => new LogLines(`${user.name.capital} hits ${target.name.capital} for ${args.damage} damage`)] + ]) + + protected failLines: POVPair = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You try to smack ${target.name}, but you miss`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} misses you`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} misses ${target.name}`)] + ]) + + constructor (protected damage: Damage) { + super('Attack', 'Attack the enemy') + this.test = new StatTest(Stat.STR) + } - execute (user: Creature, target: Creature): LogEntry { + execute (user: Creature, target: Creature): LogEntry { + if (this.test.test(user, target)) { target.takeDamage(this.damage) - return this.lines[user.perspective][target.perspective](user, target) + return this.successLines.run(user, target, { damage: this.damage }) + } else { + return this.failLines.run(user, target) } + } } export class DevourAction extends TogetherAction { - protected lines: POVActionPicker = { - [POV.First]: { - [POV.First]: (user, target) => new LogLines('You devour...yourself?'), - [POV.Third]: (user, target) => new LogLines('You devour ' + target.name) - }, - [POV.Third]: { - [POV.First]: (user, target) => new LogLines(user.name.capital + ' devours you'), - [POV.Third]: (user, target) => new LogLines(user.name.capital + ' devours ' + target.name) - } - } + private test: StatTest - constructor (protected container: Container) { - super('Devour', 'Try to consume your foe') - this.name += ` (${container.name})` + protected failLines: POVPair = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to make a meal out of ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to devour you, but fails`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} unsuccessfully tries to swallow ${target.name}`)] + ]) + + allowed (user: Creature, target: Creature): boolean { + const owner = this.container.owner === user + const predOk = Array.from(this.container.voreTypes).every(pref => user.predPrefs.has(pref)) + const preyOk = Array.from(this.container.voreTypes).every(pref => target.preyPrefs.has(pref)) + + if (owner && predOk && preyOk) { + return super.allowed(user, target) + } else { + return false } + } - execute (user: Creature, target: Creature): LogEntry { - return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), this.container.consume(target)) + constructor (protected container: Container) { + super('Devour', 'Try to consume your foe') + this.name += ` (${container.name})` + this.test = new StatTest(Stat.STR) + } + + execute (user: Creature, target: Creature): LogEntry { + if (this.test.test(user, target)) { + return this.container.consume(target) + } else { + return this.failLines.run(user, target) } + } } export class StruggleAction extends PairAction { - protected lines: POVActionPicker = { - [POV.First]: { - [POV.First]: (user, target) => new LogLines('You escape from...yourself?'), - [POV.Third]: (user, target) => new LogLines('You escape from ' + target.name) - }, - [POV.Third]: { - [POV.First]: (user, target) => new LogLines(user.name.capital + ' escapes from you'), - [POV.Third]: (user, target) => new LogLines(user.name.capital + ' escapes from ' + target.name) - } - } + private test: StatTest - allowed (user: Creature, target: Creature) { - if (user.containedIn === this.container) { - return super.allowed(user, target) - } else { - return false - } - } + protected failLines: POVPair = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to make a meal out of ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to devour you, but fails`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} unsuccessfully tries to swallow ${target.name}`)] + ]) - constructor (public container: Container) { - super('Struggle', 'Try to escape your predator') + allowed (user: Creature, target: Creature) { + if (user.containedIn === this.container) { + return super.allowed(user, target) + } else { + return false } + } - execute (user: Creature, target: Creature): LogEntry { - if (user.containedIn) { - return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), user.containedIn.release(user)) - } else { return new LogLines("The prey wasn't actually eaten...") } + constructor (public container: Container) { + super('Struggle', 'Try to escape your predator') + this.test = new StatTest(Stat.STR) + } + + execute (user: Creature, target: Creature): LogEntry { + if (user.containedIn !== null) { + if (this.test.test(user, target)) { + return user.containedIn.release(user) + } else { + return this.failLines.run(user, target) + } + } else { + return new LogLines("Vore's bugged!") } + } } export class DigestAction extends SelfAction { - protected lines: POVActionPicker = { - [POV.First]: { - [POV.First]: (user, target) => new LogLines('You rub your stomach'), - [POV.Third]: (user, target) => new LogLines("You can't digest for other people...") - }, - [POV.Third]: { - [POV.First]: (user, target) => new LogLines("Other people can't digest for you..."), - [POV.Third]: (user, target) => new LogLines(user.name.capital + ' rubs ' + user.pronouns.possessive + ' gut.') - } - } + protected lines: POVPair = new POVPair([]) allowed (user: Creature, target: Creature) { if (this.container.owner === user && this.container.contents.length > 0) { @@ -184,22 +274,11 @@ export class DigestAction extends SelfAction { execute (user: Creature, target: Creature): LogEntry { const results = new CompositeLog(...user.containers.map(container => container.tick(60))) - return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), results) + return new CompositeLog(this.lines.run(user, target), results) } } export class ReleaseAction extends PairAction { - protected lines: POVActionPicker = { - [POV.First]: { - [POV.First]: (user, target) => new LogLines(`You can't release yourself`), - [POV.Third]: (user, target) => new LogLines(`You hork up ${target.name}}`) - }, - [POV.Third]: { - [POV.First]: (user, target) => new LogLines(`${user.name.capital} horks you up`), - [POV.Third]: (user, target) => new LogLines(`${user.name.capital} horks up ${target.name.capital}`) - } - } - allowed (user: Creature, target: Creature) { if (target.containedIn === this.container) { return super.allowed(user, target) @@ -214,22 +293,12 @@ export class ReleaseAction extends PairAction { } execute (user: Creature, target: Creature): LogEntry { - const results = this.container.release(target) - return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), results) + return this.container.release(target) } } export class TransferAction extends PairAction { - protected lines: POVActionPicker = { - [POV.First]: { - [POV.First]: (user, target) => new LogLines(), - [POV.Third]: (user, target) => new LogLines(`You push your prey from your ${this.from.name} to your ${this.to.name}`) - }, - [POV.Third]: { - [POV.First]: (user, target) => new LogLines(`You're shoved from ${user.name}'s ${this.from.name} to their ${this.to.name}`), - [POV.Third]: (user, target) => new LogLines(`${user.name.capital} pushes ${target.name} from their ${this.from.name} to their ${this.to.name}`) - } - } + protected lines: POVPair = new POVPair([]) allowed (user: Creature, target: Creature) { if (target.containedIn === this.from) { @@ -246,71 +315,6 @@ export class TransferAction extends PairAction { execute (user: Creature, target: Creature): LogEntry { this.from.release(target) this.to.consume(target) - return this.lines[user.perspective][target.perspective](user, target) - } -} - -export interface CombatTest { - test: (user: Creature, target: Creature) => boolean; - odds: (user: Creature, target: Creature) => number; - explain: (user: Creature, target: Creature) => LogEntry; -} - -function logistic (x0: number, L: number, k: number): (x: number) => number { - return (x: number) => { - return L / (1 + Math.exp(-k * (x - x0))) - } -} - -abstract class RandomTest implements CombatTest { - test (user: Creature, target: Creature): boolean { - return Math.random() < this.odds(user, target) - } - - abstract odds(user: Creature, target: Creature): number - abstract explain(user: Creature, target: Creature): LogEntry -} - -export class StatTest extends RandomTest { - private f: (x: number) => number - - constructor (public readonly stat: Stat, k = 0.1) { - super() - this.f = logistic(0, 1, k) - } - - odds (user: Creature, target: Creature): number { - return this.f(user.stats[this.stat] - target.stats[this.stat]) - } - - explain (user: Creature, target: Creature): LogEntry { - const delta: number = user.stats[this.stat] - target.stats[this.stat] - let result: string - - if (delta === 0) { - result = 'You and the target have the same ' + this.stat + '.' - } else if (delta < 0) { - result = 'You have ' + delta + ' less ' + this.stat + ' than your foe.' - } else { - result = 'You have ' + delta + ' more ' + this.stat + ' than you foe.' - } - - result += ' Your odds of success are ' + (100 * this.odds(user, target)) + '%' - - return new LogLines(result) - } -} - -export class ChanceTest extends RandomTest { - constructor (public readonly chance: number) { - super() - } - - odds (user: Creature, target: Creature): number { - return this.chance - } - - explain (user: Creature, target: Creature): LogEntry { - return new LogLines('You have a flat ' + (100 * this.chance) + '% chance.') + return this.lines.run(user, target) } } diff --git a/src/game/creatures/player.ts b/src/game/creatures/player.ts index 369ed11..90629a8 100644 --- a/src/game/creatures/player.ts +++ b/src/game/creatures/player.ts @@ -1,18 +1,20 @@ import { Creature, POV } from '../entity' import { ProperNoun, TheyPronouns } from '../language' -import { Stat, Damage, AttackAction, DevourAction, DamageType } from '../combat' -import { Stomach, VoreType } from '../vore' +import { Stat, Damage, AttackAction, DamageType } from '../combat' +import { Stomach, Bowels, VoreType } from '../vore' export class Player extends Creature { constructor () { - super(new ProperNoun('The Dude'), TheyPronouns, { [Stat.STR]: 20, [Stat.DEX]: 20, [Stat.CON]: 20 }, new Set([VoreType.Oral]), new Set([VoreType.Oral]), 50) + super(new ProperNoun('The Dude'), TheyPronouns, { [Stat.STR]: 20, [Stat.DEX]: 20, [Stat.CON]: 20 }, new Set([VoreType.Oral]), new Set([VoreType.Oral, VoreType.Anal]), 50) + this.actions.push(new AttackAction(new Damage({ type: DamageType.Pierce, amount: 20 }))) - const stomach = new Stomach(this, 100, new Damage({ amount: 10, type: DamageType.Acid }, { amount: 10, type: DamageType.Crush })) + const stomach = new Stomach(this, 100, new Damage({ amount: 100000000000, type: DamageType.Acid }, { amount: 10, type: DamageType.Crush })) this.containers.push(stomach) - this.actions.push(new DevourAction(stomach)) + const bowels = new Bowels(this, 100, new Damage({ amount: 20, type: DamageType.Crush })) + this.containers.push(bowels) this.perspective = POV.First } } diff --git a/src/game/creatures/wolf.ts b/src/game/creatures/wolf.ts index e94928d..8a49f97 100644 --- a/src/game/creatures/wolf.ts +++ b/src/game/creatures/wolf.ts @@ -2,20 +2,16 @@ import { Creature, POV } from '../entity' import { Stat, Damage, DamageType, AttackAction, StruggleAction, TransferAction } from '../combat' import { MalePronouns, ImproperNoun } from '../language' import { VoreType, Stomach, Bowels } from '../vore' -import { LogLines } from '../interface' class BiteAction extends AttackAction { constructor () { super(new Damage({ amount: 10, type: DamageType.Pierce })) - this.lines[POV.First][POV.Third] = (user, target) => new LogLines('You sink your fangs into ' + target.name) - this.lines[POV.Third][POV.First] = (user, target) => new LogLines(user.name.capital + ' bites you. This bite is easily the top 1% of bites produced by ' + user.name.plural.all + '.') - this.lines[POV.Third][POV.Third] = (user, target) => new LogLines(user.name.capital + ' chomps ' + target.name) } } export class Wolf extends Creature { constructor () { - super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 10, [Stat.DEX]: 10, [Stat.CON]: 10 }, new Set([VoreType.Oral]), new Set([VoreType.Oral]), 25) + super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 10, [Stat.DEX]: 10, [Stat.CON]: 10 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral]), 25) this.actions.push(new BiteAction()) const stomach = new Stomach(this, 50, new Damage({ amount: 50, type: DamageType.Acid }, { amount: 500, type: DamageType.Crush })) diff --git a/src/game/interface.ts b/src/game/interface.ts index c7acde8..1d9cfa6 100644 --- a/src/game/interface.ts +++ b/src/game/interface.ts @@ -35,9 +35,6 @@ export class CompositeLog implements LogEntry { export function log (entry: LogEntry): void { entry.render().forEach(elem => { - document.querySelector('#log')!.insertBefore(elem, document?.querySelector('#log > *')) + document.querySelector('#log')!.appendChild(elem) }) - - const entries: Array = Array.from(document.querySelectorAll('#log > *')) - entries.slice(5).forEach(element => element.remove()) } diff --git a/src/game/language.ts b/src/game/language.ts index a3f9af7..35bbf39 100644 --- a/src/game/language.ts +++ b/src/game/language.ts @@ -1,7 +1,52 @@ -import { Creature, POV } from './entity' -import { LogEntry } from './interface' +import { Entity, POV } from './entity' +import { LogEntry, LogLines } from './interface' -export type POVActionPicker = { [key in POV]: { [key in POV]: (user: Creature, target: Creature) => LogEntry } } +export class POVPair { + run (user: K, target: V): LogEntry { + const choice = this.options.find(element => element[0][0] === user.perspective && element[0][1] === target.perspective) + + if (choice === undefined) { + return new LogLines("Fen didn't write any text for this...") + } else { + return choice[1](user, target) + } + } + + constructor (private options: Array<[[POV, POV], (user: K, target: V) => LogEntry]>) { + + } +} + +export class POVPairArgs { + run (user: K, target: V, args: U): LogEntry { + const choice = this.options.find(element => element[0][0] === user.perspective && element[0][1] === target.perspective) + + if (choice === undefined) { + return new LogLines("Fen didn't write any text for this...") + } else { + return choice[1](user, target, args) + } + } + + constructor (private options: Array<[[POV, POV], (user: K, target: V, args: U) => LogEntry]>) { + + } +} +export class POVSolo { + run (user: K, args: any = {}): LogEntry { + const choice = this.options.find(element => element[0][0] === user.perspective) + + if (choice === undefined) { + return new LogLines("Fen didn't write any text for this...") + } else { + return choice[1](user, args) + } + } + + constructor (private options: Array<[[POV], (user: K, args: any) => LogEntry]>) { + + } +} enum NounKind { Specific, diff --git a/src/game/vore.ts b/src/game/vore.ts index 3aa34c3..1be3735 100644 --- a/src/game/vore.ts +++ b/src/game/vore.ts @@ -1,7 +1,14 @@ import { Entity, Mortal, POV } from './entity' import { Damage, Actionable, Action, DevourAction, DigestAction, ReleaseAction, StruggleAction } from './combat' import { LogLines, LogEntry, CompositeLog } from './interface' -export enum VoreType {Oral} +import { POVSolo, POVPair, POVPairArgs } from './language' + +export enum VoreType { + Oral = "Oral Vore", + Anal = "Anal Vore", + Cock = "Cock Vore", + Unbirth = "Unbirthing" +} export interface Prey extends Mortal { preyPrefs: Set; @@ -36,6 +43,14 @@ export interface Container extends Actionable { abstract class NormalContainer implements Container { contents: Array + abstract consumeLines: POVPair + abstract releaseLines: POVPair + abstract struggleLines: POVPair + abstract tickLines: POVSolo + abstract digestLines: POVPair + abstract absorbLines: POVPair + abstract disposeLines: POVPair + get fullness (): number { return Array.from(this.contents.values()).reduce((total: number, prey: Prey) => total + prey.bulk, 0) } @@ -53,17 +68,17 @@ abstract class NormalContainer implements Container { consume (prey: Prey): LogEntry { this.contents.push(prey) prey.containedIn = this - return new LogLines('MUNCH') + return this.consumeLines.run(this.owner, prey) } release (prey: Prey): LogEntry { prey.containedIn = null this.contents = this.contents.filter(victim => victim !== prey) - return new LogLines('ANTI-MUNCH') + return this.releaseLines.run(this.owner, prey) } struggle (prey: Prey): LogEntry { - return new LogLines('Slosh!') + return this.struggleLines.run(prey, this.owner) } tick (dt: number): LogEntry { @@ -88,7 +103,7 @@ abstract class NormalContainer implements Container { return prey.health > -100 }) - return new CompositeLog(digestedEntries, absorbedEntries) + return new CompositeLog(this.tickLines.run(this.owner), digestedEntries, absorbedEntries) } describe (): LogEntry { @@ -102,15 +117,15 @@ abstract class NormalContainer implements Container { } digest (prey: Prey): LogEntry { - return new LogLines('Glorp!') + return this.digestLines.run(this.owner, prey) } absorb (prey: Prey): LogEntry { - return new LogLines('Glorp...') + return this.absorbLines.run(this.owner, prey) } dispose (preys: Prey[]): LogEntry { - return new LogLines('GLORP') + return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey))) } actions: Array @@ -119,127 +134,104 @@ abstract class NormalContainer implements Container { this.contents = [] this.actions = [] + + this.actions.push(new DevourAction(this)) + this.actions.push(new DigestAction(this)) + this.actions.push(new ReleaseAction(this)) + this.actions.push(new StruggleAction(this)) } } export class Stomach extends NormalContainer { constructor (owner: Pred, capacity: number, damage: Damage) { super('Stomach', owner, new Set([VoreType.Oral]), capacity, damage) - - this.actions.push(new DevourAction(this)) - this.actions.push(new DigestAction(this)) - this.actions.push(new ReleaseAction(this)) - this.actions.push(new StruggleAction(this)) - } - - consume (prey: Prey): LogEntry { - super.consume(prey) - - const predPOV = this.owner.perspective - const preyPOV = prey.perspective - if (predPOV === POV.First && preyPOV === POV.Third) { - return new LogLines(prey.name.capital + ' slides down into your stomach') - } else if (predPOV === POV.Third && preyPOV === POV.First) { - return new LogLines(this.owner.name.capital + "'s guts swell as you slush down into " + this.owner.pronouns.possessive + ' stomach') - } else if (predPOV === POV.Third && preyPOV === POV.Third) { - return new LogLines(this.owner.name.capital + "'s belly fills with the struggling form of " + prey.name) - } else { - return new LogLines('FIX ME!') - } } - digest (prey: Prey): LogEntry { - super.digest(prey) - - const predPOV = this.owner.perspective - const preyPOV = prey.perspective - - if (predPOV === POV.First && preyPOV === POV.Third) { - return new LogLines('Your stomach finishes off ' + prey.name) - } else if (predPOV === POV.Third && preyPOV === POV.First) { - return new LogLines(this.owner.name.capital + ' digests you') - } else if (predPOV === POV.Third && preyPOV === POV.Third) { - return new LogLines(this.owner.name.capital + ' finishes digesting ' + prey.name) - } else { - return new LogLines('FIX ME!') - } - } - - absorb (prey: Prey): LogEntry { - super.absorb(prey) - - const predPOV = this.owner.perspective - const preyPOV = prey.perspective - - if (predPOV === POV.First && preyPOV === POV.Third) { - return new LogLines("Your stomach melts down what's left of " + prey.name) - } else if (predPOV === POV.Third && preyPOV === POV.First) { - return new LogLines(this.owner.name.capital + ' finishes absorbing you') - } else if (predPOV === POV.Third && preyPOV === POV.Third) { - return new LogLines(this.owner.name.capital + ' fully absorbs ' + prey.name) - } else { - return new LogLines('FIX ME!') - } - } + consumeLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You devour ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} munches you`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} munches ${target.name.capital}`)] + ]) + + releaseLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You hork up ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} horks you up`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} horks up ${target.name.capital}`)] + ]) + + struggleLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You claw your way out of ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} forces ${user.pronouns.possessive} way up your throat!`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the gut of ${target.name}`)] + ]) + + tickLines = new POVSolo([ + [[POV.First], (user) => new LogLines(`Your stomach gurgles and churns`)], + [[POV.Third], (user) => new LogLines(`${user.name.capital}'s gut snarls and gurgles`)] + ]) + + digestLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`Your stomach overwhelms ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s stomach finishes you off`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)] + ]) + + absorbLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] + ]) + + disposeLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] + ]) } export class Bowels extends NormalContainer { constructor (owner: Pred, capacity: number, damage: Damage) { - super('Bowels', owner, new Set([VoreType.Oral]), capacity, damage) - - this.actions.push(new DevourAction(this)) - this.actions.push(new DigestAction(this)) - this.actions.push(new ReleaseAction(this)) - this.actions.push(new StruggleAction(this)) - } - - consume (prey: Prey): LogEntry { - super.consume(prey) - - const predPOV = this.owner.perspective - const preyPOV = prey.perspective - if (predPOV === POV.First && preyPOV === POV.Third) { - return new LogLines(prey.name.capital + ' slides down into your bowels') - } else if (predPOV === POV.Third && preyPOV === POV.First) { - return new LogLines(this.owner.name.capital + "'s guts swell as you slush down into " + this.owner.pronouns.possessive + ' bowels') - } else if (predPOV === POV.Third && preyPOV === POV.Third) { - return new LogLines(this.owner.name.capital + "'s belly fills with the struggling form of " + prey.name) - } else { - return new LogLines('FIX ME!') - } + super('Bowels', owner, new Set([VoreType.Anal]), capacity, damage) } - digest (prey: Prey): LogEntry { - super.digest(prey) - - const predPOV = this.owner.perspective - const preyPOV = prey.perspective - - if (predPOV === POV.First && preyPOV === POV.Third) { - return new LogLines('Your bowels finishes off ' + prey.name) - } else if (predPOV === POV.Third && preyPOV === POV.First) { - return new LogLines(this.owner.name.capital + ' digests you') - } else if (predPOV === POV.Third && preyPOV === POV.Third) { - return new LogLines(this.owner.name.capital + ' finishes digesting ' + prey.name) - } else { - return new LogLines('FIX ME!') - } - } - - absorb (prey: Prey): LogEntry { - super.absorb(prey) - - const predPOV = this.owner.perspective - const preyPOV = prey.perspective - - if (predPOV === POV.First && preyPOV === POV.Third) { - return new LogLines("Your bowels melts down what's left of " + prey.name) - } else if (predPOV === POV.Third && preyPOV === POV.First) { - return new LogLines(this.owner.name.capital + ' finishes absorbing you') - } else if (predPOV === POV.Third && preyPOV === POV.Third) { - return new LogLines(this.owner.name.capital + ' fully absorbs ' + prey.name) - } else { - return new LogLines('FIX ME!') - } - } + consumeLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You devour ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} munches you`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} munches ${target.name.capital}`)] + ]) + + releaseLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You hork up ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} horks you up`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} horks up ${target.name.capital}`)] + ]) + + struggleLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`You claw your way out of ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} forces ${user.pronouns.possessive} way up your throat!`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the gut of ${target.name}`)] + ]) + + tickLines = new POVSolo([ + [[POV.First], (user) => new LogLines(`Your stomach gurgles and churns!`)], + [[POV.Third], (user) => new LogLines(`${user.name.capital}'s gut snarls and gurgles`)] + ]) + + digestLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`Your stomach overwhelms ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s stomach finishes you off`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)] + ]) + + absorbLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] + ]) + + disposeLines = new POVPair([ + [[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)], + [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)], + [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)] + ]) }