|
- import { Entity, Mortal, POV, Creature } from './entity'
- import { Damage, DamageType, Stats, Actionable, Action, Vigor } from './combat'
- import { LogLines, LogEntry, CompositeLog, LogLine } from './interface'
- import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo } from './language'
- import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions'
-
- export enum VoreType {
- Oral = "Oral Vore",
- Anal = "Anal Vore",
- Cock = "Cock Vore",
- Unbirth = "Unbirthing"
- }
-
- export abstract class Vore implements Mortal {
- abstract name: Noun;
- abstract pronouns: Pronoun;
- abstract perspective: POV;
- abstract vigors: {[key in Vigor]: number};
- abstract maxVigors: {[key in Vigor]: number};
- abstract disabled: boolean;
- abstract resistances: Map<DamageType, number>;
- abstract takeDamage (damage: Damage): LogEntry;
- abstract stats: Stats;
- abstract status: string;
- abstract preyPrefs: Set<VoreType>;
- abstract bulk: number;
- abstract containedIn: Container | null;
- abstract predPrefs: Set<VoreType>;
- abstract containers: Array<Container>;
- destroy (): LogEntry {
- const lines = new POVSolo<Vore>([
- [[POV.First], (target: Vore) => new LogLine('You die!')],
- [[POV.Third], (target: Vore) => new LogLine(`${target.name.capital} dies!`)]
- ])
- this.containers.map(container => {
- container.contents.map(prey => {
- prey.containedIn = this.containedIn
- if (this.containedIn !== null) {
- this.containedIn.contents.push(prey)
- }
- })
- })
-
- return lines.run(this)
- }
- }
-
- export interface Container extends Actionable {
- name: Noun;
- owner: Vore;
- voreTypes: Set<VoreType>;
- contents: Array<Vore>;
- digested: Array<Vore>;
- capacity: number;
- fullness: number;
- canTake: (prey: Vore) => boolean;
- consume: (prey: Vore) => LogEntry;
- release: (prey: Vore) => LogEntry;
- struggle: (prey: Vore) => LogEntry;
- tick: (dt: number) => LogEntry;
- describe: () => LogEntry;
- digest: (prey: Vore) => LogEntry;
- absorb: (prey: Vore) => LogEntry;
- dispose: (preys: Vore[]) => LogEntry;
- actions: Array<Action>;
- }
-
- abstract class NormalContainer implements Container {
- contents: Array<Vore>
- digested: Array<Vore>
-
- abstract consumeLines: POVPair<Vore, Vore>
- abstract releaseLines: POVPair<Vore, Vore>
- abstract struggleLines: POVPair<Vore, Vore>
- abstract tickLines: POVPairArgs<Vore, Vore, { damage: Damage }>
- abstract digestLines: POVPair<Vore, Vore>
- abstract absorbLines: POVPair<Vore, Vore>
- abstract disposeLines: POVPair<Vore, Vore>
-
- get fullness (): number {
- return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.bulk, 0)
- }
-
- canTake (prey: Vore): boolean {
- const fits = this.capacity - this.fullness >= prey.bulk
-
- const permitted = Array.from(this.voreTypes).every(voreType => {
- return prey.preyPrefs.has(voreType)
- })
-
- return fits && permitted
- }
-
- consume (prey: Vore): LogEntry {
- this.contents.push(prey)
- prey.containedIn = this
- return this.consumeLines.run(this.owner, prey)
- }
-
- release (prey: Vore): LogEntry {
- prey.containedIn = this.owner.containedIn
- this.contents = this.contents.filter(victim => victim !== prey)
-
- if (this.owner.containedIn !== null) {
- this.owner.containedIn.contents.push(prey)
- }
- return this.releaseLines.run(this.owner, prey)
- }
-
- struggle (prey: Vore): LogEntry {
- return this.struggleLines.run(prey, this.owner)
- }
-
- tick (dt: number): LogEntry {
- const digested: Array<Vore> = []
-
- const scaled = this.damage.scale(dt / 60)
-
- const damageResults: Array<LogEntry> = []
- this.contents.forEach(prey => {
- damageResults.push(prey.takeDamage(scaled))
-
- if (prey.vigors[Vigor.Health] <= 0) {
- digested.push(prey)
- }
- })
-
- const tickedEntries = new LogLines(...this.contents.map(prey => this.tickLines.run(this.owner, prey, { damage: scaled })))
- const digestedEntries = new LogLines(...digested.map(prey => this.digest(prey)))
-
- this.contents = this.contents.filter(prey => {
- return prey.vigors[Vigor.Health] > 0
- })
-
- return new LogLines(tickedEntries, new LogLines(...damageResults), digestedEntries)
- }
-
- describe (): LogEntry {
- const lines: Array<string> = []
-
- this.contents.forEach(prey => {
- lines.push(prey.toString())
- })
-
- return new LogLine(...lines)
- }
-
- digest (prey: Vore): LogEntry {
- return this.digestLines.run(this.owner, prey)
- }
-
- absorb (prey: Vore): LogEntry {
- return this.absorbLines.run(this.owner, prey)
- }
-
- dispose (preys: Vore[]): LogEntry {
- return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey)))
- }
-
- actions: Array<Action>
-
- constructor (public name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) {
- this.contents = []
- this.digested = []
-
- this.actions = []
-
- this.name = name
-
- this.actions.push(new DevourAction(this))
- this.actions.push(new DigestAction(this))
- this.actions.push(new ReleaseAction(this))
- this.actions.push(new StruggleAction(this))
- }
- }
-
- abstract class InnerContainer extends NormalContainer {
- release (prey: Vore): LogEntry {
- prey.containedIn = this.escape
- this.contents = this.contents.filter(victim => victim !== prey)
- return this.releaseLines.run(this.owner, prey)
- }
-
- constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: Container) {
- super(name, owner, voreTypes, capacity, damage)
-
- this.actions = []
-
- this.actions.push(new DigestAction(this))
- this.actions.push(new StruggleAction(this))
- }
- }
-
- export class Stomach extends NormalContainer {
- constructor (owner: Vore, capacity: number, damage: Damage) {
- super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage)
- }
-
- consumeLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} munches ${target.name}`)]
- ])
-
- releaseLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} horks up ${target.name}`)]
- ])
-
- struggleLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} escapes from the gut of ${target.name}`)]
- ])
-
- tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([
- [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())],
- [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you 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([
- [[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.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)]
- ])
-
- absorbLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
- ])
-
- disposeLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
- ])
- }
-
- export class InnerStomach extends InnerContainer {
- constructor (owner: Vore, capacity: number, damage: Damage, escape: Container) {
- super(new ImproperNoun('inner stomach', 'inner stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage, escape)
- }
-
- consumeLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} munches ${target.name.capital}`)]
- ])
-
- releaseLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} horks up ${target.name.capital}`)]
- ])
-
- struggleLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} escapes from the gut of ${target.name}`)]
- ])
-
- tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([
- [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())],
- [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you 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([
- [[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.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)]
- ])
-
- absorbLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
- ])
-
- disposeLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
- ])
- }
-
- export class Bowels extends NormalContainer {
- constructor (owner: Vore, capacity: number, damage: Damage) {
- super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage)
- }
-
- consumeLines = new POVPair([
- [[POV.First, POV.Third], (user, target) => new LogLine(`You force ${target.name} into your bowels`)],
- [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} works you into ${user.pronouns.possessive} ass`)],
- [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} anal-vores ${target.name.capital}`)]
- ])
-
- releaseLines = new POVPair([
- [[POV.First, POV.Third], (user, target) => new LogLine(`You let out ${target.name}`)],
- [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} lets you out `)],
- [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} lets out ${target.name.capital}`)]
- ])
-
- struggleLines = new POVPair([
- [[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 out your rump!`)],
- [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from the bowels of ${target.name}`)]
- ])
-
- tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([
- [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your bowels gurgle ${target.name} for `, args.damage.renderShort())],
- [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s bowels churn you for `, args.damage.renderShort())],
- [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${target.name.capital} churns ${user.name} for `, args.damage.renderShort())]
- ])
-
- digestLines = new POVPair([
- [[POV.First, POV.Third], (user, target) => new LogLine(`Your bowels overwhelm ${target.name}`)],
- [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s bowels finish you off`)],
- [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the bowels of ${user.name}`)]
- ])
-
- absorbLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
- ])
-
- disposeLines = new POVPair([
- [[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.Third], (user, target) => new LogLine(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
- ])
- }
|