import { StatTest, StatVigorTest } from './tests' import { DynText, LiveText, TextLike, Verb, PairLine, PairLineArgs } from '../language' import { Entity, Creature } from '../entity' import { Damage, DamageFormula, Stat, Vigor, Action } from '../combat' import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface' import { VoreContainer, Container } from '../vore' import { CapableCondition, UserDrainedVigorCondition, TogetherCondition, EnemyCondition, SoloCondition, PairCondition, ContainsCondition, ContainedByCondition } from './conditions' export class AttackAction extends Action { protected test: StatTest protected successLine: PairLineArgs = (user, target, args) => new LogLine( `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} for `, args.damage.renderShort() ) protected failLine: PairLine = (user, target) => new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('miss', 'misses'))} ${target.name.objective}` ) constructor (protected damage: DamageFormula, protected verb: Verb = new Verb('smack')) { super( verb.root.capital, 'Attack the enemy', [new CapableCondition(), new TogetherCondition(), new EnemyCondition()] ) 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.successLine(user, target, { damage: damage }) return new CompositeLog(ownResult, targetResult) } else { return this.failLine(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 Action { private test: StatVigorTest protected failLine: PairLineArgs = (user, target, args) => new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to ${args.container.consumeVerb} ${target.name.objective}.` ) 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(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'), new LiveText(container, x => `Try to ${x.consumeVerb} your foe`), [new CapableCondition(), new TogetherCondition()] ) 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.failLine(user, target, { container: this.container }) } } describe (user: Creature, target: Creature): LogEntry { return new LogLine(`Try to ${this.container.consumeVerb} your opponent, sending them to your ${this.container.name}. `, this.test.explain(user, target)) } } export class FeedAction extends Action { protected successLine: PairLine = (user, target) => new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('feed'))} ${user.pronouns.reflexive} to ${target.name}. ` ) protected failLine: PairLine = (user, target) => new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to feed ${user.pronouns.reflexive} 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.preyPrefs.has(pref)) const preyOk = Array.from(this.container.voreTypes).every(pref => target.predPrefs.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 UserDrainedVigorCondition(Vigor.Resolve), new TogetherCondition()] ) this.name += ` (${container.name})` } execute (user: Creature, target: Creature): LogEntry { return new LogLines(this.successLine(user, target), 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 Action { private test: StatVigorTest protected successLine: PairLineArgs = (prey, pred, args) => new LogLine( `${prey.name.capital} ${prey.name.conjugate(new Verb('escape'))} from ${pred.name.possessive} ${args.container.name}.` ) protected failLine: PairLineArgs = (prey, pred, args) => new LogLine( `${prey.name.capital} ${prey.name.conjugate(new Verb('fail'))} to escape from ${pred.name.possessive} ${args.container.name}.` ) constructor (public container: Container) { super( new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), 'Try to escape from your foe', [new CapableCondition(), new PairCondition(), new ContainedByCondition(container)] ) this.test = new StatVigorTest(Stat.Power) } execute (user: Creature, target: Creature): LogEntry { if (user.containedIn !== null) { if (this.test.test(user, target)) { return new LogLines(this.successLine(user, target, { container: this.container }), user.containedIn.release(user)) } else { return this.failLine(user, target, { container: this.container }) } } 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 Action { 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(), new PairCondition()] ) } } export class DigestAction extends Action { 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: VoreContainer) { super( new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition(), new SoloCondition()] ) } 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 Action { 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(), new PairCondition(), new ContainsCondition(container)] ) } 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 Action { verb: Verb = new Verb('send') line: PairLineArgs = (user, target, args) => new LogLine( `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} from ${user.pronouns.possessive} ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}` ) allowed (user: Creature, target: Creature) { if (target.containedIn === this.from && this.from.contents.includes(target)) { return super.allowed(user, target) } else { return false } } constructor (protected from: Container, protected to: Container, name = 'Transfer') { super( name, `${from.name.all.capital} to ${to.name.all}`, [new CapableCondition(), new PairCondition()] ) } execute (user: Creature, target: Creature): LogEntry { this.from.release(target) this.to.consume(target) return this.line(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}`) } }