import { Consequence, DamageFormula, Condition, StatusEffect, Damage, DamageType } from '@/game/combat' import { Creature } from '@/game/creature' import { LogEntry, LogLines, LogLine, nilLog } from '@/game/interface' import { Verb, PairLine } from '@/game/language' import { Container } from '@/game/vore' /** * Takes a function, and thus can do anything. */ export class ArbitraryConsequence extends Consequence { constructor ( public apply: (user: Creature, target: Creature) => LogEntry, public describe: (user: Creature, target: Creature) => LogEntry, conditions: Condition[] = [] ) { super(conditions) } } /** * Renders some text. */ export class LogConsequence extends Consequence { constructor (private line: PairLine, conditions: Condition[] = []) { super(conditions) } apply (user: Creature, target: Creature): LogEntry { return this.line(user, target) } describe (user: Creature, target: Creature): LogEntry { return nilLog } } /** * Deals damage. */ export class DamageConsequence extends Consequence { constructor (private damageFormula: DamageFormula, conditions: Condition[] = []) { super(conditions) } apply (user: Creature, target: Creature): LogEntry { const damage = this.damageFormula.calc(user, target) return new LogLines( new LogLine(`${target.name.capital} ${target.name.conjugate(new Verb('take'))} `, damage.renderShort(), ` damage!`), target.takeDamage(damage) ) } describe (user: Creature, target: Creature): LogEntry { return new LogLine( this.damageFormula.describe(user, target) ) } } /** * Same as [[DamageConsequence]], but it has healing text */ export class HealingConsequence extends Consequence { constructor (private damageFormula: DamageFormula, conditions: Condition[] = []) { super(conditions) } apply (user: Creature, target: Creature): LogEntry { const damage = this.damageFormula.calc(user, target) return new LogLines( new LogLine(`${target.name.capital} ${target.name.conjugate(new Verb('heal'))} `, damage.renderShort(), `!`), target.takeDamage(damage) ) } describe (user: Creature, target: Creature): LogEntry { return new LogLine( `Heals for `, this.damageFormula.describe(user, target) ) } } /** * Deals damage to the target and heals the user */ export class DrainConsequence extends Consequence { constructor (private damageFormula: DamageFormula, conditions: Condition[] = []) { super(conditions) } apply (user: Creature, target: Creature): LogEntry { const damage = this.damageFormula.calc(user, target) const heal = new Damage(...damage.damages.map(instance => ({ amount: instance.amount, type: DamageType.Heal, target: instance.target }))) console.log(heal) return new LogLines( new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb("drain"))} `, damage.renderShort(), ` from ${target.name.objective}.`), target.takeDamage(damage), user.takeDamage(heal) ) } describe (user: Creature, target: Creature): LogEntry { return new LogLine( this.damageFormula.describe(user, target) ) } } /** * Applies a status effect */ export class StatusConsequence extends Consequence { constructor (public statusMaker: (user: Creature, target: Creature) => StatusEffect, conditions: Condition[] = []) { super(conditions) } apply (user: Creature, target: Creature): LogEntry { return target.applyEffect(this.statusMaker(user, target)) } describe (user: Creature, target: Creature): LogEntry { return new LogLine( `Applies a `, this.statusMaker(user, target).name.toString(), ` effect.` ) } } /** * Consumes the target */ export class ConsumeConsequence extends Consequence { constructor (public container: Container, conditions: Condition[] = []) { super(conditions) } apply (user: Creature, target: Creature): LogEntry { return this.container.consume(target) } describe (user: Creature, target: Creature): LogEntry { return new LogLine( `${this.container.consumeVerb.singular.capital} ${target.name.objective}, sending ${target.pronouns.objective} ${this.container.consumePreposition} ${user.name.possessive} ${this.container.name}.` ) } }