| @@ -71,6 +71,12 @@ export interface CombatTest { | |||
| explain: (user: Creature, target: Creature) => LogEntry; | |||
| } | |||
| export interface Effect { | |||
| name: string; | |||
| desc: string; | |||
| apply: (target: Creature) => LogEntry; | |||
| } | |||
| export class Damage { | |||
| readonly damages: DamageInstance[] | |||
| @@ -172,36 +178,11 @@ export interface Condition { | |||
| allowed: (user: Creature, target: Creature) => boolean; | |||
| } | |||
| class InverseCondition implements Condition { | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| return !this.condition.allowed(user, target) | |||
| } | |||
| constructor (private condition: Condition) { | |||
| } | |||
| } | |||
| class CapableCondition implements Condition { | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| return !user.disabled | |||
| } | |||
| } | |||
| class DrainedVigorCondition implements Condition { | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| return user.vigors[this.vigor] <= 0 | |||
| } | |||
| constructor (private vigor: Vigor) { | |||
| } | |||
| } | |||
| export interface Actionable { | |||
| actions: Array<Action>; | |||
| } | |||
| abstract class SelfAction extends Action { | |||
| export abstract class SelfAction extends Action { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user === target) { | |||
| return super.allowed(user, target) | |||
| @@ -211,7 +192,7 @@ abstract class SelfAction extends Action { | |||
| } | |||
| } | |||
| abstract class PairAction extends Action { | |||
| export abstract class PairAction extends Action { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user !== target) { | |||
| return super.allowed(user, target) | |||
| @@ -221,7 +202,7 @@ abstract class PairAction extends Action { | |||
| } | |||
| } | |||
| abstract class TogetherAction extends PairAction { | |||
| export abstract class TogetherAction extends PairAction { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user.containedIn === target.containedIn) { | |||
| return super.allowed(user, target) | |||
| @@ -230,254 +211,3 @@ abstract class TogetherAction extends PairAction { | |||
| } | |||
| } | |||
| } | |||
| export class AttackAction extends TogetherAction { | |||
| protected test: StatTest | |||
| protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([ | |||
| [[POV.First, POV.Third], (user, target, args) => new LogLine( | |||
| `You smack ${target.name} for `, | |||
| args.damage.renderShort() | |||
| )], | |||
| [[POV.Third, POV.First], (user, target, args) => new LogLine( | |||
| `${user.name.capital} smacks you for `, | |||
| args.damage.renderShort() | |||
| )], | |||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine( | |||
| `${user.name.capital} smacks ${target.name} for `, | |||
| args.damage.renderShort() | |||
| )] | |||
| ]) | |||
| protected failLines: POVPair<Entity, Entity> = 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(`${user.name.capital} misses ${target.name}`)] | |||
| ]) | |||
| constructor (protected damage: DamageFormula) { | |||
| super('Attack', 'Attack the enemy', [new CapableCondition()]) | |||
| this.test = new StatTest(Stat.Power) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| if (this.test.test(user, target)) { | |||
| const damage = this.damage.calc(user, target) | |||
| const targetResult = target.takeDamage(damage) | |||
| const ownResult = this.successLines.run(user, target, { damage: damage }) | |||
| return new CompositeLog(ownResult, targetResult) | |||
| } else { | |||
| return this.failLines.run(user, target) | |||
| } | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Attack ${target.name}. `, this.damage.describe(user, target), '. ', this.test.explain(user, target)) | |||
| } | |||
| } | |||
| export class DevourAction extends TogetherAction { | |||
| private test: StatVigorTest | |||
| 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.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to devour you, but fails`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} 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 | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super(new DynText('Devour (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()]) | |||
| this.test = new StatVigorTest(Stat.Power) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| if (this.test.test(user, target)) { | |||
| return this.container.consume(target) | |||
| } else { | |||
| return this.failLines.run(user, target) | |||
| } | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Try to consume your opponent, sending them to your ${this.container.name}. `, this.test.explain(user, target)) | |||
| } | |||
| } | |||
| export class FeedAction extends TogetherAction { | |||
| private test: StatTest | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to feed yourself to ${target.name}`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to feed ${user.pronouns.possessive} to you, but fails`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} unsuccessfully tries to feed ${user.pronouns.possessive} to ${target.name}`)] | |||
| ]) | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| const owner = this.container.owner === target | |||
| 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 | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Resolve)]) | |||
| this.name += ` (${container.name})` | |||
| this.test = new StatTest(Stat.Power) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| return this.container.consume(user) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Your willpower is drained, and you really feel like shoving yourself into ${target.name}'s ${this.container.name}...`) | |||
| } | |||
| } | |||
| export class StruggleAction extends PairAction { | |||
| private test: StatVigorTest | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to escape from ${target.name}`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to escape from you, but fails`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} unsuccessfully struggles within ${target.name}`)] | |||
| ]) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user.containedIn === this.container && this.container.owner === target) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (public container: Container) { | |||
| super(new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), 'Try to escape from your foe', [new CapableCondition()]) | |||
| this.test = new StatVigorTest(Stat.Power) | |||
| } | |||
| 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!") | |||
| } | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Try to escape from ${target.name}'s ${this.container.name}. `, this.test.explain(user, target)) | |||
| } | |||
| } | |||
| export abstract class EatenAction extends PairAction { | |||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (target.containedIn === this.container) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (public container: Container, name: TextLike, desc: string) { | |||
| super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()]) | |||
| } | |||
| } | |||
| export class DigestAction extends SelfAction { | |||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (this.container.owner === user && this.container.contents.length > 0) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()]) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| const results = this.container.tick(60) | |||
| return new CompositeLog(results) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Digest everyone inside of your ${this.container.name}.`) | |||
| } | |||
| } | |||
| export class ReleaseAction extends PairAction { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super(new DynText('Release (', new LiveText(container, x => x.name.all), ')'), 'Release one of your prey', [new CapableCondition()]) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| return this.container.release(target) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Release ${target.name} from your ${this.container.name}.`) | |||
| } | |||
| } | |||
| export class TransferAction extends PairAction { | |||
| 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 ${user.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) { | |||
| if (target.containedIn === this.from) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected from: Container, protected to: Container) { | |||
| super('Transfer', `Move from your ${from.name} to your ${to.name}`, [new CapableCondition()]) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| this.from.release(target) | |||
| this.to.consume(target) | |||
| return this.lines.run(user, target, { from: this.from, to: this.to }) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Push ${target.name} from your ${this.from.name} to your ${this.to.name}`) | |||
| } | |||
| } | |||
| @@ -0,0 +1,258 @@ | |||
| import { StatTest, StatVigorTest } from './tests' | |||
| import { POVPairArgs, POVPair, DynText, LiveText, TextLike } from '../language' | |||
| import { Entity, POV, Creature } from '../entity' | |||
| import { Damage, DamageFormula, Stat, Vigor, TogetherAction, PairAction, SelfAction } from '../combat' | |||
| import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface' | |||
| import { Container } from '../vore' | |||
| import { CapableCondition, DrainedVigorCondition } from './conditions' | |||
| export class AttackAction extends TogetherAction { | |||
| protected test: StatTest | |||
| protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([ | |||
| [[POV.First, POV.Third], (user, target, args) => new LogLine( | |||
| `You smack ${target.name} for `, | |||
| args.damage.renderShort() | |||
| )], | |||
| [[POV.Third, POV.First], (user, target, args) => new LogLine( | |||
| `${user.name.capital} smacks you for `, | |||
| args.damage.renderShort() | |||
| )], | |||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine( | |||
| `${user.name.capital} smacks ${target.name} for `, | |||
| args.damage.renderShort() | |||
| )] | |||
| ]) | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You try to smack ${target.name}, but you miss`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} misses you`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} misses ${target.name}`)] | |||
| ]) | |||
| constructor (protected damage: DamageFormula) { | |||
| super('Attack', 'Attack the enemy', [new CapableCondition()]) | |||
| this.test = new StatTest(Stat.Power) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| if (this.test.test(user, target)) { | |||
| const damage = this.damage.calc(user, target) | |||
| const targetResult = target.takeDamage(damage) | |||
| const ownResult = this.successLines.run(user, target, { damage: damage }) | |||
| return new CompositeLog(ownResult, targetResult) | |||
| } else { | |||
| return this.failLines.run(user, target) | |||
| } | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Attack ${target.name}. `, this.damage.describe(user, target), '. ', this.test.explain(user, target)) | |||
| } | |||
| } | |||
| export class DevourAction extends TogetherAction { | |||
| private test: StatVigorTest | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You fail to make a meal out of ${target.name}`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} tries to devour you, but fails`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} 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 | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super(new DynText('Devour (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()]) | |||
| this.test = new StatVigorTest(Stat.Power) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| if (this.test.test(user, target)) { | |||
| return this.container.consume(target) | |||
| } else { | |||
| return this.failLines.run(user, target) | |||
| } | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Try to consume your opponent, sending them to your ${this.container.name}. `, this.test.explain(user, target)) | |||
| } | |||
| } | |||
| export class FeedAction extends TogetherAction { | |||
| private test: StatTest | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You fail to feed yourself to ${target.name}`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} tries to feed ${user.pronouns.possessive} to you, but fails`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} unsuccessfully tries to feed ${user.pronouns.possessive} to ${target.name}`)] | |||
| ]) | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| const owner = this.container.owner === target | |||
| 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 | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Resolve)]) | |||
| this.name += ` (${container.name})` | |||
| this.test = new StatTest(Stat.Power) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| return this.container.consume(user) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Your willpower is drained, and you really feel like shoving yourself into ${target.name}'s ${this.container.name}...`) | |||
| } | |||
| } | |||
| export class StruggleAction extends PairAction { | |||
| private test: StatVigorTest | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You fail to escape from ${target.name}`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} tries to escape from you, but fails`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} unsuccessfully struggles within ${target.name}`)] | |||
| ]) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user.containedIn === this.container && this.container.owner === target) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (public container: Container) { | |||
| super(new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), 'Try to escape from your foe', [new CapableCondition()]) | |||
| this.test = new StatVigorTest(Stat.Power) | |||
| } | |||
| 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 LogLine("Vore's bugged!") | |||
| } | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Try to escape from ${target.name}'s ${this.container.name}. `, this.test.explain(user, target)) | |||
| } | |||
| } | |||
| export abstract class EatenAction extends PairAction { | |||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (target.containedIn === this.container) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (public container: Container, name: TextLike, desc: string) { | |||
| super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()]) | |||
| } | |||
| } | |||
| export class DigestAction extends SelfAction { | |||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (this.container.owner === user && this.container.contents.length > 0) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()]) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| const results = this.container.tick(60) | |||
| return new CompositeLog(results) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Digest everyone inside of your ${this.container.name}.`) | |||
| } | |||
| } | |||
| export class ReleaseAction extends PairAction { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super(new DynText('Release (', new LiveText(container, x => x.name.all), ')'), 'Release one of your prey', [new CapableCondition()]) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| return this.container.release(target) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Release ${target.name} from your ${this.container.name}.`) | |||
| } | |||
| } | |||
| export class TransferAction extends PairAction { | |||
| 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 ${user.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) { | |||
| if (target.containedIn === this.from) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected from: Container, protected to: Container) { | |||
| super('Transfer', `Move from your ${from.name} to your ${to.name}`, [new CapableCondition()]) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| this.from.release(target) | |||
| this.to.consume(target) | |||
| return this.lines.run(user, target, { from: this.from, to: this.to }) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return new LogLine(`Push ${target.name} from your ${this.from.name} to your ${this.to.name}`) | |||
| } | |||
| } | |||
| @@ -0,0 +1,27 @@ | |||
| import { Condition, Vigor } from "../combat" | |||
| import { Creature } from "../entity" | |||
| export class InverseCondition implements Condition { | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| return !this.condition.allowed(user, target) | |||
| } | |||
| constructor (private condition: Condition) { | |||
| } | |||
| } | |||
| export class CapableCondition implements Condition { | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| return !user.disabled | |||
| } | |||
| } | |||
| export class DrainedVigorCondition implements Condition { | |||
| allowed (user: Creature, target: Creature): boolean { | |||
| return user.vigors[this.vigor] <= 0 | |||
| } | |||
| constructor (private vigor: Vigor) { | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| import { Creature, POV } from '../entity' | |||
| import { LogEntry, LogLine, FAElem } from '../interface' | |||
| import { Effect } from '../combat' | |||
| import { POVSolo } from '../language' | |||
| export class InstantKill implements Effect { | |||
| lines = new POVSolo<Creature>([ | |||
| [[POV.First], (target: Creature) => new LogLine(`You're killed instantly! `, new FAElem('fas fa-skull'))], | |||
| [[POV.Third], (target: Creature) => new LogLine(`${target.name.capital} is killed instantly! `, new FAElem('fas fa-skull'))] | |||
| ]) | |||
| name = "Instant Kill" | |||
| desc = "Instantly kills its victim" | |||
| apply (target: Creature): LogEntry { | |||
| target.vigors.Health = Math.min(0, target.vigors.Health) | |||
| return this.lines.run(target) | |||
| } | |||
| } | |||
| @@ -128,6 +128,6 @@ export class ChanceTest extends RandomTest { | |||
| } | |||
| explain (user: Creature, target: Creature): LogEntry { | |||
| return new LogLines('You have a flat ' + (100 * this.chance) + '% chance.') | |||
| return new LogLine('You have a flat ' + (100 * this.chance) + '% chance.') | |||
| } | |||
| } | |||
| @@ -1,8 +1,10 @@ | |||
| import { Creature, POV, Entity } from '../entity' | |||
| import { Stat, Damage, DamageType, TransferAction, Vigor, FeedAction, EatenAction, AttackAction, ConstantDamageFormula } from '../combat' | |||
| import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat' | |||
| import { ProperNoun, TheyPronouns, ImproperNoun, POVPair, FemalePronouns, POVPairArgs } from '../language' | |||
| import { VoreType, Stomach, InnerStomach, Container } from '../vore' | |||
| import { LogLine, LogLines, LogEntry, FAElem, CompositeLog, ImgElem } from '../interface' | |||
| import { AttackAction, EatenAction, TransferAction, FeedAction } from '../combat/actions' | |||
| import { InstantKill } from '../combat/effects' | |||
| class BellyCrushAction extends AttackAction { | |||
| successLines = new POVPairArgs<Entity, Entity, { damage: Damage }>([ | |||
| @@ -56,25 +58,21 @@ class BelchAction extends AttackAction { | |||
| this.desc = 'Drain your foe\'s willpower with a solid BELCH' | |||
| } | |||
| } | |||
| class CrushAction extends EatenAction { | |||
| lines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You crush ${target.name} `, new FAElem('fas fa-skull'))], | |||
| [[POV.Third, POV.First], (user) => new CompositeLog(new LogLine(`${user.name.capital} crushes you; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `, new FAElem('fas fa-skull')), new ImgElem('./media/cafat/images/crunch.webp'))], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} crushes ${target.name}; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `, new FAElem('fas fa-skull'))] | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You crush ${target.name} `)], | |||
| [[POV.Third, POV.First], (user) => new CompositeLog(new LogLine(`${user.name.capital} crushes you; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `), new ImgElem('./media/cafat/images/crunch.webp'))], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} crushes ${target.name}; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `)] | |||
| ]) | |||
| private damage: Damage = new Damage( | |||
| { amount: 99, type: DamageType.Crush, target: Vigor.Health } | |||
| ) | |||
| constructor (container: Container) { | |||
| super(container, "Crush", "Crush 'em!") | |||
| this.desc = "Crush somebody in your gut" | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| target.takeDamage(this.damage) | |||
| return this.lines.run(user, target) | |||
| return new LogLines(this.lines.run(user, target), new InstantKill().apply(target)) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| @@ -118,9 +116,9 @@ export class Cafat extends Creature { | |||
| lowerStomach.name = new ImproperNoun("lower stomach", "lower stomachs").all | |||
| stomach.consumeLines = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You devour ${target.name}`)], | |||
| [[POV.Third, POV.First], (user) => new CompositeLog(new LogLines(`${user.name.capital} devours you`), new ImgElem('./media/cafat/images/stomach.webp'))], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} munches ${target.name.capital}`)] | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You devour ${target.name}`)], | |||
| [[POV.Third, POV.First], (user) => new CompositeLog(new LogLine(`${user.name.capital} devours you`), new ImgElem('./media/cafat/images/stomach.webp'))], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} munches ${target.name.capital}`)] | |||
| ]) | |||
| const crush = new CrushAction(lowerStomach) | |||
| @@ -1,7 +1,8 @@ | |||
| import { Creature, POV } from '../entity' | |||
| import { ProperNoun, TheyPronouns } from '../language' | |||
| import { Stat, Damage, AttackAction, DamageType, Vigor, ConstantDamageFormula } from '../combat' | |||
| import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat' | |||
| import { Stomach, Bowels, VoreType } from '../vore' | |||
| import { AttackAction } from '../combat/actions' | |||
| export class Player extends Creature { | |||
| constructor () { | |||
| @@ -1,9 +1,10 @@ | |||
| import { Creature, POV, Entity } from '../entity' | |||
| import { Stat, Damage, DamageType, AttackAction, TransferAction, Vigor, FeedAction, ConstantDamageFormula } from '../combat' | |||
| import { Stat, Damage, DamageType, ConstantDamageFormula, Vigor } from '../combat' | |||
| import { MalePronouns, ImproperNoun, POVPair, POVPairArgs } from '../language' | |||
| import { LogLine, LogLines } from '../interface' | |||
| import { VoreType, Stomach, Bowels } from '../vore' | |||
| import { StatTest } from '../combat/tests' | |||
| import { AttackAction, TransferAction, FeedAction } from '../combat/actions' | |||
| class BiteAction extends AttackAction { | |||
| constructor () { | |||
| @@ -29,9 +30,9 @@ class HypnoAction extends AttackAction { | |||
| ]) | |||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | |||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You try to hypnotize ${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}`)] | |||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You try to hypnotize ${target.name}, but you miss`)], | |||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} misses you`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name} misses ${target.name}`)] | |||
| ]) | |||
| constructor () { | |||
| @@ -5,18 +5,28 @@ export interface LogEntry { | |||
| } | |||
| export class LogLines implements LogEntry { | |||
| lines: string[] | |||
| private parts: Array<string|LogEntry> | |||
| constructor (...lines: string[]) { | |||
| this.lines = lines | |||
| constructor (...parts: Array<string|LogEntry>) { | |||
| this.parts = parts | |||
| } | |||
| render (): HTMLElement[] { | |||
| return this.lines.map(line => { | |||
| const div = document.createElement("div") | |||
| div.innerText = line | |||
| return div | |||
| const div = document.createElement("div") | |||
| this.parts.forEach(part => { | |||
| if (typeof part === "string") { | |||
| const partDiv = document.createElement("span") | |||
| partDiv.innerText = part | |||
| div.appendChild(partDiv) | |||
| } else { | |||
| (part as LogEntry).render().forEach(logPart => { | |||
| div.appendChild(logPart) | |||
| }) | |||
| } | |||
| }) | |||
| return [div] | |||
| } | |||
| } | |||
| @@ -114,8 +124,11 @@ export class PropElem implements LogEntry { | |||
| const span = document.createElement("span") | |||
| span.classList.add("stat-entry") | |||
| span.dataset.tooltip = this.prop | |||
| if (this.prop in Stat) { | |||
| span.dataset.tooltip = this.prop | |||
| } else if (this.prop in Vigor) { | |||
| span.dataset.tooltip = this.prop | |||
| } | |||
| if (this.prop in Stat) { | |||
| span.dataset.tooltipFull = StatDescs[this.prop as Stat] | |||
| } else if (this.prop in Vigor) { | |||
| @@ -1,12 +1,12 @@ | |||
| import { Entity, POV } from './entity' | |||
| import { LogEntry, LogLines } from './interface' | |||
| import { LogEntry, LogLines, LogLine } from './interface' | |||
| export class POVPair<K extends Entity, V extends Entity> { | |||
| 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...") | |||
| return new LogLine("Fen didn't write any text for this...") | |||
| } else { | |||
| return choice[1](user, target) | |||
| } | |||
| @@ -22,7 +22,7 @@ export class POVPairArgs<K extends Entity, V extends Entity, U> { | |||
| 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...") | |||
| return new LogLine("Fen didn't write any text for this...") | |||
| } else { | |||
| return choice[1](user, target, args) | |||
| } | |||
| @@ -37,7 +37,7 @@ export class POVSolo<K extends Entity> { | |||
| 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...") | |||
| return new LogLine("Fen didn't write any text for this...") | |||
| } else { | |||
| return choice[1](user, args) | |||
| } | |||
| @@ -1,7 +1,8 @@ | |||
| import { Entity, Mortal, POV, Creature } from './entity' | |||
| import { Damage, DamageType, Stats, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat' | |||
| import { Damage, DamageType, Stats, Actionable, Action, Vigor } from './combat' | |||
| import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | |||
| import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun } from './language' | |||
| import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions' | |||
| export enum VoreType { | |||
| Oral = "Oral Vore", | |||
| @@ -142,7 +143,7 @@ abstract class NormalContainer implements Container { | |||
| lines.push(prey.toString()) | |||
| }) | |||
| return new LogLines(...lines) | |||
| return new LogLine(...lines) | |||
| } | |||
| digest (prey: Vore): LogEntry { | |||
| @@ -196,21 +197,21 @@ export class Stomach extends NormalContainer { | |||
| } | |||
| 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}`)] | |||
| [[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 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}`)] | |||
| [[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 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.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 }>([ | |||
| @@ -220,21 +221,21 @@ export class Stomach extends NormalContainer { | |||
| ]) | |||
| 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 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 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}`)] | |||
| [[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 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}`)] | |||
| [[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}`)] | |||
| ]) | |||
| } | |||
| @@ -244,21 +245,21 @@ export class InnerStomach extends InnerContainer { | |||
| } | |||
| 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 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 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 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 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.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 }>([ | |||
| @@ -268,21 +269,21 @@ export class InnerStomach extends InnerContainer { | |||
| ]) | |||
| 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 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 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}`)] | |||
| [[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 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}`)] | |||
| [[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}`)] | |||
| ]) | |||
| } | |||
| @@ -292,21 +293,21 @@ export class Bowels extends NormalContainer { | |||
| } | |||
| consumeLines = new POVPair([ | |||
| [[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}`)] | |||
| [[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 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}`)] | |||
| [[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 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 out your rump!`)], | |||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the bowels 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 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 }>([ | |||
| @@ -316,20 +317,20 @@ export class Bowels extends NormalContainer { | |||
| ]) | |||
| digestLines = new POVPair([ | |||
| [[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}`)] | |||
| [[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 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}`)] | |||
| [[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 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}`)] | |||
| [[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}`)] | |||
| ]) | |||
| } | |||