|  | 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<Creature>, 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}.`
    )
  }
}
 |