| @@ -145,6 +145,10 @@ a { | |||||
| font-weight: bold; | font-weight: bold; | ||||
| } | } | ||||
| .damage-instance { | |||||
| white-space: nowrap; | |||||
| } | |||||
| #log > div { | #log > div { | ||||
| color: #888; | color: #888; | ||||
| padding-top: 8pt; | padding-top: 8pt; | ||||
| @@ -1,8 +1,50 @@ | |||||
| import { Creature, POV, Entity } from './entity' | import { Creature, POV, Entity } from './entity' | ||||
| import { POVPair, POVPairArgs } from './language' | import { POVPair, POVPairArgs } from './language' | ||||
| import { Container } from './vore' | import { Container } from './vore' | ||||
| import { LogEntry, LogLines, CompositeLog, FAElem, LogLine } from './interface' | |||||
| import { LogEntry, LogLines, CompositeLog, FAElem, LogLine, FormatEntry, FormatOpt } from './interface' | |||||
| export enum DamageType { | |||||
| Pierce = "Pierce", | |||||
| Slash = "Slash", | |||||
| Crush = "Crush", | |||||
| Acid = "Acid", | |||||
| Seduction = "Seduction", | |||||
| Dominance = "Dominance" | |||||
| } | |||||
| export interface DamageInstance { | |||||
| type: DamageType; | |||||
| amount: number; | |||||
| target: Vigor; | |||||
| } | |||||
| export enum Vigor { | |||||
| Health = "Health", | |||||
| Stamina = "Stamina", | |||||
| Willpower = "Willpower" | |||||
| } | |||||
| export const VigorIcons: {[key in Vigor]: string} = { | |||||
| [Vigor.Health]: "fas fa-heart", | |||||
| [Vigor.Stamina]: "fas fa-bolt", | |||||
| [Vigor.Willpower]: "fas fa-brain" | |||||
| } | |||||
| export type Vigors = {[key in Vigor]: number} | |||||
| export enum Stat { | |||||
| STR = 'Strength', | |||||
| DEX = 'Dexterity', | |||||
| CON = 'Constitution' | |||||
| } | |||||
| export type Stats = {[key in Stat]: number} | |||||
| export const StatIcons: {[key in Stat]: string} = { | |||||
| [Stat.STR]: 'fas fa-fist-raised', | |||||
| [Stat.DEX]: 'fas fa-feather', | |||||
| [Stat.CON]: 'fas fa-heartbeat' | |||||
| } | |||||
| export interface CombatTest { | export interface CombatTest { | ||||
| test: (user: Creature, target: Creature) => boolean; | test: (user: Creature, target: Creature) => boolean; | ||||
| odds: (user: Creature, target: Creature) => number; | odds: (user: Creature, target: Creature) => number; | ||||
| @@ -24,7 +66,7 @@ abstract class RandomTest implements CombatTest { | |||||
| abstract explain(user: Creature, target: Creature): LogEntry | abstract explain(user: Creature, target: Creature): LogEntry | ||||
| } | } | ||||
| export class StatTest extends RandomTest { | |||||
| export class StatVigorTest extends RandomTest { | |||||
| private f: (x: number) => number | private f: (x: number) => number | ||||
| constructor (public readonly stat: Stat, k = 0.1) { | constructor (public readonly stat: Stat, k = 0.1) { | ||||
| @@ -33,7 +75,27 @@ export class StatTest extends RandomTest { | |||||
| } | } | ||||
| odds (user: Creature, target: Creature): number { | odds (user: Creature, target: Creature): number { | ||||
| return this.f(user.stats[this.stat] - target.stats[this.stat]) | |||||
| let userPercent = 1 | |||||
| let targetPercent = 1 | |||||
| Object.keys(Vigor).forEach(key => { | |||||
| userPercent *= user.vigors[key as Vigor] / user.maxVigors[key as Vigor] | |||||
| targetPercent *= target.vigors[key as Vigor] / target.maxVigors[key as Vigor] | |||||
| userPercent = Math.max(0, userPercent) | |||||
| targetPercent = Math.max(0, targetPercent) | |||||
| }) | |||||
| if (userPercent === 0) { | |||||
| targetPercent *= 4 | |||||
| } | |||||
| if (targetPercent === 0) { | |||||
| userPercent *= 4 | |||||
| } | |||||
| console.log(userPercent, targetPercent, this.f(user.stats[this.stat] * userPercent - target.stats[this.stat] * targetPercent)) | |||||
| return this.f(user.stats[this.stat] * userPercent - target.stats[this.stat] * targetPercent) | |||||
| } | } | ||||
| explain (user: Creature, target: Creature): LogEntry { | explain (user: Creature, target: Creature): LogEntry { | ||||
| @@ -54,61 +116,48 @@ export class StatTest extends RandomTest { | |||||
| } | } | ||||
| } | } | ||||
| export class ChanceTest extends RandomTest { | |||||
| constructor (public readonly chance: number) { | |||||
| export class StatTest extends RandomTest { | |||||
| private f: (x: number) => number | |||||
| constructor (public readonly stat: Stat, k = 0.1) { | |||||
| super() | super() | ||||
| this.f = logistic(0, 1, k) | |||||
| } | } | ||||
| odds (user: Creature, target: Creature): number { | odds (user: Creature, target: Creature): number { | ||||
| return this.chance | |||||
| return this.f(user.stats[this.stat] - target.stats[this.stat]) | |||||
| } | } | ||||
| explain (user: Creature, target: Creature): LogEntry { | 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", | |||||
| Seduction = "Seduction", | |||||
| Dominance = "Dominance" | |||||
| } | |||||
| const delta: number = user.stats[this.stat] - target.stats[this.stat] | |||||
| let result: string | |||||
| export interface DamageInstance { | |||||
| type: DamageType; | |||||
| amount: number; | |||||
| target: Vigor; | |||||
| } | |||||
| 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.' | |||||
| } | |||||
| export enum Vigor { | |||||
| Health = "Health", | |||||
| Stamina = "Stamina", | |||||
| Willpower = "Willpower" | |||||
| } | |||||
| result += ' Your odds of success are ' + (100 * this.odds(user, target)) + '%' | |||||
| export const VigorIcons: {[key in Vigor]: string} = { | |||||
| [Vigor.Health]: "fas fa-heart", | |||||
| [Vigor.Stamina]: "fas fa-bolt", | |||||
| [Vigor.Willpower]: "fas fa-brain" | |||||
| return new LogLines(result) | |||||
| } | |||||
| } | } | ||||
| export type Vigors = {[key in Vigor]: number} | |||||
| export enum Stat { | |||||
| STR = 'Strength', | |||||
| DEX = 'Dexterity', | |||||
| CON = 'Constitution' | |||||
| } | |||||
| export class ChanceTest extends RandomTest { | |||||
| constructor (public readonly chance: number) { | |||||
| super() | |||||
| } | |||||
| export type Stats = {[key in Stat]: number} | |||||
| odds (user: Creature, target: Creature): number { | |||||
| return this.chance | |||||
| } | |||||
| export const StatIcons: {[key in Stat]: string} = { | |||||
| [Stat.STR]: 'fas fa-fist-raised', | |||||
| [Stat.DEX]: 'fas fa-feather', | |||||
| [Stat.CON]: 'fas fa-heartbeat' | |||||
| explain (user: Creature, target: Creature): LogEntry { | |||||
| return new LogLines('You have a flat ' + (100 * this.chance) + '% chance.') | |||||
| } | |||||
| } | } | ||||
| export class Damage { | export class Damage { | ||||
| @@ -149,7 +198,7 @@ export class Damage { | |||||
| totals[instance.target] += instance.amount | totals[instance.target] += instance.amount | ||||
| }) | }) | ||||
| return new LogLine(...Object.keys(Vigor).flatMap(key => totals[key as Vigor] === 0 ? [] : [totals[key as Vigor].toString(), new FAElem(VigorIcons[key as Vigor])])) | |||||
| return new FormatEntry(new LogLine(...Object.keys(Vigor).flatMap(key => totals[key as Vigor] === 0 ? [] : [totals[key as Vigor].toFixed(0).toString(), new FAElem(VigorIcons[key as Vigor])])), FormatOpt.DamageInst) | |||||
| } | } | ||||
| } | } | ||||
| @@ -276,7 +325,7 @@ export class AttackAction extends TogetherAction { | |||||
| } | } | ||||
| export class DevourAction extends TogetherAction { | export class DevourAction extends TogetherAction { | ||||
| private test: StatTest | |||||
| private test: StatVigorTest | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to make a meal out of ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to make a meal out of ${target.name}`)], | ||||
| @@ -299,7 +348,7 @@ export class DevourAction extends TogetherAction { | |||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super('Devour', 'Try to consume your foe', [new CapableCondition()]) | super('Devour', 'Try to consume your foe', [new CapableCondition()]) | ||||
| this.name += ` (${container.name})` | this.name += ` (${container.name})` | ||||
| this.test = new StatTest(Stat.STR) | |||||
| this.test = new StatVigorTest(Stat.STR) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -348,7 +397,7 @@ export class FeedAction extends TogetherAction { | |||||
| } | } | ||||
| export class StruggleAction extends PairAction { | export class StruggleAction extends PairAction { | ||||
| private test: StatTest | |||||
| private test: StatVigorTest | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to escape from ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to escape from ${target.name}`)], | ||||
| @@ -366,7 +415,7 @@ export class StruggleAction extends PairAction { | |||||
| constructor (public container: Container) { | constructor (public container: Container) { | ||||
| super('Struggle', 'Try to escape your predator', [new CapableCondition()]) | super('Struggle', 'Try to escape your predator', [new CapableCondition()]) | ||||
| this.test = new StatTest(Stat.STR) | |||||
| this.test = new StatVigorTest(Stat.STR) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -406,7 +455,7 @@ export class DigestAction extends SelfAction { | |||||
| export class ReleaseAction extends PairAction { | export class ReleaseAction extends PairAction { | ||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| if (target.containedIn === this.container) { | |||||
| if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) { | |||||
| return super.allowed(user, target) | return super.allowed(user, target) | ||||
| } else { | } else { | ||||
| return false | return false | ||||
| @@ -424,7 +473,11 @@ export class ReleaseAction extends PairAction { | |||||
| } | } | ||||
| export class TransferAction extends PairAction { | export class TransferAction extends PairAction { | ||||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | |||||
| protected lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | |||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | |||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${target.pronouns.possessive} ${args.to.name}`)], | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name} squeezes ${target.name} from ${user.pronouns.possessive} ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)] | |||||
| ]) | |||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| if (target.containedIn === this.from) { | if (target.containedIn === this.from) { | ||||
| @@ -441,6 +494,6 @@ export class TransferAction extends PairAction { | |||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| this.from.release(target) | this.from.release(target) | ||||
| this.to.consume(target) | this.to.consume(target) | ||||
| return this.lines.run(user, target) | |||||
| return this.lines.run(user, target, { from: this.from, to: this.to }) | |||||
| } | } | ||||
| } | } | ||||
| @@ -5,11 +5,11 @@ import { Stomach, Bowels, VoreType } from '../vore' | |||||
| export class Player extends Creature { | export class Player extends Creature { | ||||
| constructor () { | constructor () { | ||||
| 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) | |||||
| super(new ProperNoun('The Dude'), TheyPronouns, { [Stat.STR]: 20, [Stat.DEX]: 20, [Stat.CON]: 20 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 50) | |||||
| this.actions.push(new AttackAction(new Damage({ type: DamageType.Pierce, amount: 20, target: Vigor.Health }, { type: DamageType.Pierce, amount: 20, target: Vigor.Stamina }))) | this.actions.push(new AttackAction(new Damage({ type: DamageType.Pierce, amount: 20, target: Vigor.Health }, { type: DamageType.Pierce, amount: 20, target: Vigor.Stamina }))) | ||||
| const stomach = new Stomach(this, 100, new Damage({ amount: 100000000000, type: DamageType.Acid, target: Vigor.Health }, { amount: 10, type: DamageType.Crush, target: Vigor.Health })) | |||||
| const stomach = new Stomach(this, 100, new Damage({ amount: 20, type: DamageType.Acid, target: Vigor.Health }, { amount: 10, type: DamageType.Crush, target: Vigor.Health })) | |||||
| this.containers.push(stomach) | this.containers.push(stomach) | ||||
| const bowels = new Bowels(this, 100, new Damage({ amount: 20, type: DamageType.Crush, target: Vigor.Health })) | const bowels = new Bowels(this, 100, new Damage({ amount: 20, type: DamageType.Crush, target: Vigor.Health })) | ||||
| @@ -42,14 +42,23 @@ class HypnoAction extends AttackAction { | |||||
| export class Wolf extends Creature { | export class Wolf extends Creature { | ||||
| constructor () { | constructor () { | ||||
| super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 15, [Stat.DEX]: 15, [Stat.CON]: 25 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral]), 25) | |||||
| super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 15, [Stat.DEX]: 15, [Stat.CON]: 25 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 25) | |||||
| this.actions.push(new BiteAction()) | this.actions.push(new BiteAction()) | ||||
| this.actions.push(new HypnoAction()) | this.actions.push(new HypnoAction()) | ||||
| const stomach = new Stomach(this, 50, new Damage({ amount: 50, type: DamageType.Acid, target: Vigor.Health }, { amount: 500, type: DamageType.Crush, target: Vigor.Health })) | |||||
| const stomach = new Stomach(this, 50, new Damage( | |||||
| { amount: 20, type: DamageType.Acid, target: Vigor.Health }, | |||||
| { amount: 10, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 10, type: DamageType.Dominance, target: Vigor.Willpower } | |||||
| )) | |||||
| this.containers.push(stomach) | this.containers.push(stomach) | ||||
| const bowels = new Bowels(this, 50, new Damage({ amount: 50, type: DamageType.Acid, target: Vigor.Health }, { amount: 500, type: DamageType.Crush, target: Vigor.Health })) | |||||
| const bowels = new Bowels(this, 50, new Damage( | |||||
| { amount: 10, type: DamageType.Crush, target: Vigor.Health }, | |||||
| { amount: 25, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 25, type: DamageType.Dominance, target: Vigor.Willpower } | |||||
| )) | |||||
| this.containers.push(bowels) | this.containers.push(bowels) | ||||
| @@ -71,14 +71,23 @@ export class Creature implements Mortal, Pred, Prey, Combatant { | |||||
| } | } | ||||
| get status (): string { | get status (): string { | ||||
| if (this.vigors[Vigor.Health] < 0) { | |||||
| return "DEAD" | |||||
| if (this.vigors[Vigor.Health] <= -100) { | |||||
| return "Dead" | |||||
| } | } | ||||
| if (this.vigors[Vigor.Stamina] < 0) { | |||||
| if (this.vigors[Vigor.Stamina] <= -100) { | |||||
| return "Unconscious" | return "Unconscious" | ||||
| } | } | ||||
| if (this.vigors[Vigor.Willpower] < 0) { | |||||
| return "Too horny" | |||||
| if (this.vigors[Vigor.Willpower] <= -100) { | |||||
| return "Broken" | |||||
| } | |||||
| if (this.vigors[Vigor.Health] <= 0) { | |||||
| return "Unconscious" | |||||
| } | |||||
| if (this.vigors[Vigor.Stamina] <= 0) { | |||||
| return "Exhausted" | |||||
| } | |||||
| if (this.vigors[Vigor.Willpower] <= 0) { | |||||
| return "Overpowered" | |||||
| } | } | ||||
| if (this.containedIn !== null) { | if (this.containedIn !== null) { | ||||
| return "Devoured" | return "Devoured" | ||||
| @@ -19,11 +19,30 @@ export class LogLines implements LogEntry { | |||||
| } | } | ||||
| export enum FormatOpt { | export enum FormatOpt { | ||||
| Damage = "log-damage" | |||||
| Damage = "log-damage", | |||||
| DamageInst = "damage-instance" | |||||
| } | |||||
| export class FormatEntry implements LogEntry { | |||||
| constructor (private entry: LogEntry, private opt: FormatOpt) { | |||||
| } | |||||
| render (): HTMLElement[] { | |||||
| const span = document.createElement("span") | |||||
| this.entry.render().forEach(elem => { | |||||
| span.appendChild(elem) | |||||
| }) | |||||
| span.classList.add(this.opt) | |||||
| return [span] | |||||
| } | |||||
| } | } | ||||
| export class FormatText implements LogEntry { | export class FormatText implements LogEntry { | ||||
| constructor (private line: string, private opt: FormatOpt) { | |||||
| constructor (private opt: FormatOpt, private line: string) { | |||||
| } | } | ||||
| @@ -1,6 +1,6 @@ | |||||
| import { Entity, Mortal, POV } from './entity' | import { Entity, Mortal, POV } from './entity' | ||||
| import { Damage, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat' | import { Damage, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat' | ||||
| import { LogLines, LogEntry, CompositeLog } from './interface' | |||||
| import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | |||||
| import { POVSolo, POVPair, POVPairArgs } from './language' | import { POVSolo, POVPair, POVPairArgs } from './language' | ||||
| export enum VoreType { | export enum VoreType { | ||||
| @@ -46,7 +46,7 @@ abstract class NormalContainer implements Container { | |||||
| abstract consumeLines: POVPair<Pred, Prey> | abstract consumeLines: POVPair<Pred, Prey> | ||||
| abstract releaseLines: POVPair<Pred, Prey> | abstract releaseLines: POVPair<Pred, Prey> | ||||
| abstract struggleLines: POVPair<Prey, Pred> | abstract struggleLines: POVPair<Prey, Pred> | ||||
| abstract tickLines: POVSolo<Pred> | |||||
| abstract tickLines: POVPairArgs<Pred, Prey, { damage: Damage }> | |||||
| abstract digestLines: POVPair<Pred, Prey> | abstract digestLines: POVPair<Pred, Prey> | ||||
| abstract absorbLines: POVPair<Pred, Prey> | abstract absorbLines: POVPair<Pred, Prey> | ||||
| abstract disposeLines: POVPair<Pred, Prey> | abstract disposeLines: POVPair<Pred, Prey> | ||||
| @@ -85,9 +85,11 @@ abstract class NormalContainer implements Container { | |||||
| const digested: Array<Prey> = [] | const digested: Array<Prey> = [] | ||||
| const absorbed: Array<Prey> = [] | const absorbed: Array<Prey> = [] | ||||
| const scaled = this.damage.scale(dt / 60) | |||||
| this.contents.forEach(prey => { | this.contents.forEach(prey => { | ||||
| const start = prey.vigors[Vigor.Health] | const start = prey.vigors[Vigor.Health] | ||||
| prey.takeDamage(this.damage.scale(dt / 3600)) | |||||
| prey.takeDamage(scaled) | |||||
| const end = prey.vigors[Vigor.Health] | const end = prey.vigors[Vigor.Health] | ||||
| if (start > 0 && end <= 0) { | if (start > 0 && end <= 0) { | ||||
| @@ -99,6 +101,7 @@ abstract class NormalContainer implements Container { | |||||
| } | } | ||||
| }) | }) | ||||
| const tickedEntries = new CompositeLog(...this.contents.map(prey => this.tickLines.run(this.owner, prey, { damage: scaled }))) | |||||
| const digestedEntries = new CompositeLog(...digested.map(prey => this.digest(prey))) | const digestedEntries = new CompositeLog(...digested.map(prey => this.digest(prey))) | ||||
| const absorbedEntries = new CompositeLog(...absorbed.map(prey => this.absorb(prey))) | const absorbedEntries = new CompositeLog(...absorbed.map(prey => this.absorb(prey))) | ||||
| @@ -106,7 +109,7 @@ abstract class NormalContainer implements Container { | |||||
| return prey.vigors[Vigor.Health] > -100 | return prey.vigors[Vigor.Health] > -100 | ||||
| }) | }) | ||||
| return new CompositeLog(this.tickLines.run(this.owner), digestedEntries, absorbedEntries) | |||||
| return new CompositeLog(tickedEntries, digestedEntries, absorbedEntries) | |||||
| } | } | ||||
| describe (): LogEntry { | describe (): LogEntry { | ||||
| @@ -168,9 +171,10 @@ export class Stomach extends NormalContainer { | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the gut of ${target.name}`)] | [[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`)] | |||||
| tickLines = new POVPairArgs<Pred, Prey, { 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(`${target.name.capital} churns ${user.name} for `, args.damage.renderShort())] | |||||
| ]) | ]) | ||||
| digestLines = new POVPair([ | digestLines = new POVPair([ | ||||
| @@ -198,32 +202,33 @@ export class Bowels extends NormalContainer { | |||||
| } | } | ||||
| consumeLines = new POVPair([ | 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}`)] | |||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You force ${target.name} into your bowels`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} works you into ${user.pronouns.possessive} ass`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} anal-vores ${target.name.capital}`)] | |||||
| ]) | ]) | ||||
| releaseLines = new POVPair([ | 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}`)] | |||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You let out ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} lets you out `)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} lets out ${target.name.capital}`)] | |||||
| ]) | ]) | ||||
| struggleLines = new POVPair([ | struggleLines = new POVPair([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You claw your way out of ${target.name}`)], | [[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}`)] | |||||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} forces ${user.pronouns.possessive} way out your rump!`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the bowels 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`)] | |||||
| tickLines = new POVPairArgs<Pred, Prey, { 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([ | 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}`)] | |||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`Your bowels overwhelm ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s bowels finish you off`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name.capital}'s squirms fade, overwhelmed by the bowels of ${user.name}`)] | |||||
| ]) | ]) | ||||
| absorbLines = new POVPair([ | absorbLines = new POVPair([ | ||||