From 28d940e65523e44ecd8ad75cc76107edd4e40e45 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Mon, 27 Jul 2020 14:39:11 -0400 Subject: [PATCH] Show damage after reductions/amplifications; add a shield effect --- src/game/combat.ts | 6 ++++++ src/game/combat/actions.ts | 2 +- src/game/combat/effects.ts | 22 ++++++++++++++++++++-- src/game/creatures/cafat.ts | 4 ++-- src/game/creatures/withers.ts | 8 +++++++- src/game/entity.ts | 11 +++++++++++ src/game/vore.ts | 3 ++- 7 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/game/combat.ts b/src/game/combat.ts index cc8aad6..bf68424 100644 --- a/src/game/combat.ts +++ b/src/game/combat.ts @@ -360,11 +360,17 @@ export abstract class StatusEffect implements VisibleStatus { get bottomRight () { return '' } onApply (creature: Creature): LogEntry { return nilLog } + onRemove (creature: Creature): LogEntry { return nilLog } + preAction (creature: Creature): { prevented: boolean; log: LogEntry } { return { prevented: false, log: nilLog } } + + preDamage (creature: Creature, damage: Damage): Damage { + return damage + } } diff --git a/src/game/combat/actions.ts b/src/game/combat/actions.ts index 6de85da..1fb1b73 100644 --- a/src/game/combat/actions.ts +++ b/src/game/combat/actions.ts @@ -11,7 +11,7 @@ export class AttackAction extends Action { protected successLine: PairLineArgs = (user, target, args) => new LogLine( `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} for `, - args.damage.renderShort() + target.effectiveDamage(args.damage).renderShort() ) protected failLine: PairLine = (user, target) => new LogLine( diff --git a/src/game/combat/effects.ts b/src/game/combat/effects.ts index b29541d..3a2a957 100644 --- a/src/game/combat/effects.ts +++ b/src/game/combat/effects.ts @@ -1,5 +1,5 @@ -import { StatusEffect, Damage } from '../combat' -import { DynText, LiveText, ToBe } from '../language' +import { StatusEffect, Damage, DamageType } from '../combat' +import { DynText, LiveText, ToBe, Verb } from '../language' import { Creature } from '../entity' import { LogLine, LogEntry, LogLines, FAElem } from '../interface' @@ -56,3 +56,21 @@ export class StunEffect extends StatusEffect { } } } + +export class ShieldEffect extends StatusEffect { + constructor (private damageTypes: DamageType[], private amount: number) { + super('Shield', 'Block a fraction of incoming damage', '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!`) + } + + preDamage (creature: Creature, damage: Damage) { + return damage.scale(this.amount) + } +} diff --git a/src/game/creatures/cafat.ts b/src/game/creatures/cafat.ts index 7f3626d..c265bc9 100644 --- a/src/game/creatures/cafat.ts +++ b/src/game/creatures/cafat.ts @@ -10,7 +10,7 @@ import * as Words from '../words' class BellyCrushAction extends AttackAction { successLine: PairLineArgs = (user, target, args) => new LogLines(new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('crush', 'crushes'))} on ${target.name.objective} with ${user.pronouns.possessive} belly for `, - args.damage.renderShort() + target.effectiveDamage(args.damage).renderShort() ), new ImgElem('./media/cafat/images/belly-crush.webp')) constructor (_damage: Damage) { @@ -32,7 +32,7 @@ class BelchAction extends AttackAction { successLine: PairLineArgs = (user, target, args) => new LogLines( new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('belch', 'belches'))} on ${target.name.objective} for `, - args.damage.renderShort() + target.effectiveDamage(args.damage).renderShort() ), new ImgElem('./media/cafat/images/belch.webp') ) diff --git a/src/game/creatures/withers.ts b/src/game/creatures/withers.ts index a5a3f68..ee24bc0 100644 --- a/src/game/creatures/withers.ts +++ b/src/game/creatures/withers.ts @@ -5,7 +5,7 @@ import { LogLine, LogLines, LogEntry, Newline } from '../interface' import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container, InnerStomach } from '../vore' import { AttackAction, FeedAction, TransferAction, EatenAction } from '../combat/actions' import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions' -import { InstantKillEffect } from '../combat/effects' +import { InstantKillEffect, ShieldEffect } from '../combat/effects' import * as Words from '../words' import { StatVigorTest } from '../combat/tests' @@ -26,6 +26,8 @@ class LevelDrain extends Action { } })) + // TODO make this respect resistances + user.takeDamage(heal) const targetResult = target.takeDamage(damage) @@ -238,6 +240,10 @@ class StompAllyAction extends Action { return new LogLines( this.line(user, target), target.applyEffect(new InstantKillEffect()), + user.applyEffect(new ShieldEffect( + [DamageType.Crush, DamageType.Slash, DamageType.Pierce], + 0.5 + )), new LogLine(`${user.name.capital} absorbs ${target.pronouns.possessive} power, gaining `, heal.renderShort()) ) } diff --git a/src/game/entity.ts b/src/game/entity.ts index a215508..7a00841 100644 --- a/src/game/entity.ts +++ b/src/game/entity.ts @@ -139,10 +139,21 @@ export class Creature extends Vore implements Combatant { return this.name.toString() } + /** + * Determines how much damage an attack would do + */ + effectiveDamage (damage: Damage): Damage { + return this.effects.reduce((modifiedDamage: Damage, effect: StatusEffect) => { + return effect.preDamage(this, modifiedDamage) + }, damage) + } + takeDamage (damage: Damage): LogEntry { // first, we record health to decide if the entity just died const startHealth = this.vigors.Health + damage = this.effectiveDamage(damage) + damage.damages.forEach(instance => { const factor = instance.type === DamageType.Heal ? -1 : 1 const effectiveResistance: number|undefined = this.resistances.get(instance.type) diff --git a/src/game/vore.ts b/src/game/vore.ts index 753c91a..1f1b007 100644 --- a/src/game/vore.ts +++ b/src/game/vore.ts @@ -44,6 +44,7 @@ export abstract class Vore implements Mortal { abstract maxVigors: {[key in Vigor]: number}; abstract disabled: boolean; abstract resistances: Map; + abstract effectiveDamage (damage: Damage): Damage; abstract takeDamage (damage: Damage): LogEntry; abstract stats: Stats; abstract baseStats: Stats; @@ -287,7 +288,7 @@ export class Stomach extends NormalVoreContainer { this.owner.takeDamage(heal) return new LogLines( super.digest(preys), - new LogLine(`${this.owner.name.capital} heals for `, heal.renderShort()) + new LogLine(`${this.owner.name.capital} heals for `, this.owner.effectiveDamage(heal).renderShort()) ) } }