import { StatusEffect, Damage, DamageType, Action, Condition, Vigor, Stat } from '../combat' import { DynText, LiveText, ToBe, Verb } from '../language' import { Creature } from "../creature" import { LogLine, LogEntry, LogLines, FAElem, nilLog } from '../interface' import { VoreContainer } from '../vore' import * as Words from '../words' export class InstantKillEffect extends StatusEffect { constructor () { super('Instant Kill', 'Instant kill!', 'fas fa-skull') } onApply (creature: Creature) { creature.vigors.Health = 0 creature.removeEffect(this) return new LogLines( new LogLine( `${creature.name.capital} ${creature.name.conjugate(new ToBe())} killed instantly! `, new FAElem('fas fa-skull') ), creature.takeDamage(new Damage()) ) } } export class StunEffect extends StatusEffect { constructor (private duration: number) { super('Stun', 'Cannot act!', 'fas fa-sun') this.desc = new DynText('Stunned for your next ', new LiveText(this, x => x.duration), ' actions!') } get topLeft () { return this.duration.toString() } onApply (creature: Creature) { return new LogLine(`${creature.name.capital} ${creature.name.conjugate(new ToBe())} is stunned!`) } onRemove (creature: Creature) { return new LogLine(`${creature.name.capital} ${creature.name.conjugate(new ToBe())} no longer stunned.`) } preTurn (creature: Creature): { prevented: boolean; log: LogEntry } { if (--this.duration <= 0) { return { prevented: true, log: new LogLines( `${creature.name.capital} ${creature.name.conjugate(new ToBe())} stunned! ${creature.pronouns.capital.subjective} can't move.`, creature.removeEffect(this) ) } } else { return { prevented: true, log: new LogLines( `${creature.name.capital} ${creature.name.conjugate(new ToBe())} stunned! ${creature.pronouns.capital.subjective} can't move!` ) } } } } export class DamageTypeResistanceEffect extends StatusEffect { constructor (private damageTypes: DamageType[], private amount: number) { super('Resistance', 'Block ' + ((1 - amount) * 100).toFixed() + '% of these damage types: ' + damageTypes.join(", "), 'fas fa-shield-alt') } onApply (creature: Creature) { return new LogLine(`${creature.name.capital} ${creature.name.conjugate(new Verb('gain'))} a shield!`) } onRemove (creature: Creature) { return new LogLine(`${creature.name.capital} ${creature.name.conjugate(new Verb('lose'))} ${creature.pronouns.possessive} shield!`) } modResistance (type: DamageType, factor: number) { if (this.damageTypes.includes(type)) { return factor * this.amount } else { return factor } } } export class PredatorCounterEffect extends StatusEffect { constructor (private devour: Action, private chance: number) { super('Predatory Counter', 'Eat them back', 'fas fa-redo') this.desc = new DynText(new LiveText(this, x => (x.chance * 100).toFixed(0)), '% chance to devour your attackers') } preAttack (creature: Creature, attacker: Creature) { if (this.devour.allowed(creature, attacker) && Math.random() < this.chance) { return { prevented: true, log: new LogLines( `${creature.name.capital} ${creature.name.conjugate(new Verb('surprise'))} ${attacker.name.objective} and ${creature.name.conjugate(new Verb('try', 'tries'))} to devour ${attacker.pronouns.objective}!`, this.devour.execute(creature, attacker) ) } } else { return { prevented: false, log: nilLog } } } } export class UntouchableEffect extends StatusEffect { constructor () { super('Untouchable', 'Cannot be attacked', 'fas fa-times') } preAttack (creature: Creature, attacker: Creature) { return { prevented: true, log: new LogLine(`${creature.name.capital} cannot be attacked.`) } } } export class DazzlingEffect extends StatusEffect { constructor (private conditions: Condition[]) { super('Dazzling', 'Stuns enemies who try to affect this creature', 'fas fa-spinner') } preReceiveAction (creature: Creature, attacker: Creature) { if (this.conditions.every(cond => cond.allowed(creature, attacker))) { attacker.applyEffect(new StunEffect(1)) return { prevented: true, log: new LogLine(`${attacker.name.capital} can't act against ${creature.name.objective}!`) } } else { return { prevented: false, log: nilLog } } } } export class SurrenderEffect extends StatusEffect { constructor () { super('Surrendered', 'This creature has given up, and will fail most tests', 'fas fa-flag') } onApply (creature: Creature): LogEntry { creature.takeDamage( new Damage( { amount: creature.vigors.Resolve, target: Vigor.Resolve, type: DamageType.Pure } ) ) return new LogLine( `${creature.name.capital} ${creature.name.conjugate(new Verb('surrender'))}!` ) } failTest (creature: Creature, opponent: Creature): { failed: boolean; log: LogEntry } { return { failed: true, log: nilLog } } } export class SizeEffect extends StatusEffect { constructor (private change: number) { super('Size-Shifted', 'This creature has changed in size', 'fas fa-ruler') } onApply (creature: Creature): LogLine { return new LogLine(`Smol`) } scale (scale: number): number { return scale * this.change } } export class DigestionPowerEffect extends StatusEffect { constructor (private factor: number) { super('Acid-fueled', 'This creature is digesting faster than nomral', 'fas fa-flask') } onApply (creature: Creature): LogLine { const voreContainer: VoreContainer|undefined = creature.containers.find(c => c.digest !== null) if (voreContainer !== undefined) { return new LogLine(`${creature.name.capital.possessive}'s ${voreContainer.name} ${Words.Churns} and ${voreContainer.sound}`) } else { return new LogLine(`${creature.name.capital} can't digest people...`) } } modDigestionDamage (predator: Creature, prey: Creature, container: VoreContainer, damage: Damage): Damage { return damage.scale(this.factor) } } export class StatEffect extends StatusEffect { constructor (private stat: Stat, private amount: number, private factor: number) { super('Stat boosted', 'This creature has modified stats', 'fas fa-user-plus') } modStat (creature: Creature, stat: Stat, current: number): number { if (stat === this.stat) { return current * this.factor + this.amount } else { return current } } } export class InstantDigestionEffect extends StatusEffect { constructor () { super("Instant digestion", "This creature will melt people instantly", "fas fa-skull") } postConsume (predator: Creature, prey: Creature, container: VoreContainer) { prey.applyEffect(new InstantKillEffect()) predator.voreStats.Mass += prey.voreStats.Mass prey.voreStats.Mass = 0 return new LogLines( `${prey.name.capital} ${prey.name.conjugate(new ToBe())} instantly digested! `, new FAElem('fas fa-skull'), container.tick(0, [prey]) ) } }