From 13ccc36a908d1648b964c0dccff58886aa3301a0 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Sun, 2 Aug 2020 10:07:23 -0400 Subject: [PATCH] Change the shield effect to affect effective resistances (and renamede it) --- src/game/combat.ts | 8 +++++++ src/game/combat/effects.ts | 13 ++++++++---- src/game/creature.ts | 12 +++++++++-- src/game/creatures/goldeneye.ts | 1 + src/game/creatures/withers.ts | 6 +++--- src/game/entity.ts | 37 +++++++++++++++++++++++++-------- 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/game/combat.ts b/src/game/combat.ts index 9b1a908..c1e757a 100644 --- a/src/game/combat.ts +++ b/src/game/combat.ts @@ -1,6 +1,7 @@ import { Creature } from "./creature" import { TextLike, DynText, ToBe, LiveText, PairLineArgs, PairLine } from './language' import { LogEntry, LogLines, FAElem, LogLine, FormatEntry, FormatOpt, PropElem, nilLog } from './interface' +import { Resistances } from './entity' export enum DamageType { Pierce = "Pierce", @@ -458,6 +459,13 @@ export class Effective { log: nilLog } } + + /** + * Modifies the effective resistance to a certain damage type + */ + modResistance (type: DamageType, factor: number): number { + return factor + } } /** * A displayable status effect diff --git a/src/game/combat/effects.ts b/src/game/combat/effects.ts index 6d7094c..03e7a08 100644 --- a/src/game/combat/effects.ts +++ b/src/game/combat/effects.ts @@ -20,6 +20,7 @@ export class InstantKillEffect extends StatusEffect { ) } } + export class StunEffect extends StatusEffect { constructor (private duration: number) { super('Stun', 'Cannot act!', 'fas fa-sun') @@ -58,9 +59,9 @@ export class StunEffect extends StatusEffect { } } -export class ShieldEffect extends StatusEffect { +export class DamageTypeResistanceEffect extends StatusEffect { constructor (private damageTypes: DamageType[], private amount: number) { - super('Shield', 'Block a fraction of incoming damage', 'fas fa-shield-alt') + super('Resistance', 'Block ' + ((1 - amount) * 100).toFixed() + '% of these damage types: ' + damageTypes.join(", "), 'fas fa-shield-alt') } onApply (creature: Creature) { @@ -71,8 +72,12 @@ export class ShieldEffect extends StatusEffect { 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) + modResistance (type: DamageType, factor: number) { + if (this.damageTypes.includes(type)) { + return factor * (1 - this.amount) + } else { + return factor + } } } diff --git a/src/game/creature.ts b/src/game/creature.ts index ce71c3f..e928a38 100644 --- a/src/game/creature.ts +++ b/src/game/creature.ts @@ -1,4 +1,4 @@ -import { Damage, Combatant, Stats, Action, Vigor, Side, GroupAction, VisibleStatus, ImplicitStatus, StatusEffect } from './combat' +import { Damage, Combatant, Stats, Action, Vigor, Side, GroupAction, VisibleStatus, ImplicitStatus, StatusEffect, DamageType } from './combat' import { Noun, Pronoun } from './language' import { LogEntry, LogLines } from './interface' import { Vore, VoreContainer, VoreType } from './vore' @@ -32,9 +32,17 @@ export class Creature extends Vore implements Combatant { * Determines how much damage an attack would do */ effectiveDamage (damage: Damage): Damage { - return this.effects.reduce((modifiedDamage: Damage, effect: StatusEffect) => { + const preDamage = this.effects.reduce((modifiedDamage: Damage, effect: StatusEffect) => { return effect.preDamage(this, modifiedDamage) }, damage) + return super.effectiveDamage(preDamage) + } + + resistanceTo (damageType: DamageType) { + const base = super.resistanceTo(damageType) + + const modified = this.effects.reduce((resist, effect) => effect.modResistance(damageType, resist), base) + return modified } executeAction (action: Action, target: Creature): LogEntry { diff --git a/src/game/creatures/goldeneye.ts b/src/game/creatures/goldeneye.ts index 6ba56d6..0f2422b 100644 --- a/src/game/creatures/goldeneye.ts +++ b/src/game/creatures/goldeneye.ts @@ -151,6 +151,7 @@ export class Goldeneye extends Creature { ) ) + this.groupActions.push(new Flaunt(crop)) this.groupActions.push(new Flaunt(stomach)) this.groupActions.push(new Taunt()) diff --git a/src/game/creatures/withers.ts b/src/game/creatures/withers.ts index bdfaaf1..5dd3512 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 } from '../vore' import { AttackAction, FeedAction, TransferAction } from '../combat/actions' import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions' -import { InstantKillEffect, ShieldEffect } from '../combat/effects' +import { InstantKillEffect, ResistanceEffect } from '../combat/effects' import * as Words from '../words' import { StatVigorTest } from '../combat/tests' @@ -248,7 +248,7 @@ class StompAllyAction extends Action { return new LogLines( this.line(user, target), target.applyEffect(new InstantKillEffect()), - user.applyEffect(new ShieldEffect( + user.applyEffect(new ResistanceEffect( [DamageType.Crush, DamageType.Slash, DamageType.Pierce], 0.5 )), @@ -309,7 +309,7 @@ export class Withers extends Creature { new ProperNoun('Withers'), new ImproperNoun('hellhound', 'hellhounds'), FemalePronouns, - { Toughness: 40, Power: 50, Speed: 30, Willpower: 40, Charm: 70 }, + { Toughness: 40, Power: 10, Speed: 30, Willpower: 40, Charm: 70 }, new Set(), new Set([VoreType.Oral]), 5000 diff --git a/src/game/entity.ts b/src/game/entity.ts index 7e16e3b..dd35e69 100644 --- a/src/game/entity.ts +++ b/src/game/entity.ts @@ -1,4 +1,4 @@ -import { DamageType, Damage, Stats, Vigor, VoreStats, VoreStat, Stat, Vigors } from './combat' +import { DamageType, Damage, Stats, Vigor, VoreStats, VoreStat, Stat, Vigors, DamageInstance } from './combat' import { Noun, Pronoun, TextLike, POV, PronounAsNoun, FirstPersonPronouns, SecondPersonPronouns } from './language' import { LogEntry, LogLine } from './interface' import { Place, Nowhere } from './world' @@ -34,8 +34,11 @@ export abstract class Entity { } } +export type Resistances = {[key in DamageType]: number} + export abstract class Mortal extends Entity { - resistances: Map = new Map() + baseResistances: Resistances + stats: Stats; vigors: {[key in Vigor]: number} = { [Vigor.Health]: 100, @@ -46,11 +49,16 @@ export abstract class Mortal extends Entity { constructor (name: Noun, kind: Noun, pronouns: Pronoun, public baseStats: Stats) { super(name, kind, pronouns) this.stats = Object.keys(Stat).reduce((base: any, key) => { base[key] = baseStats[key as Stat]; return base }, {}) + this.baseResistances = Object.keys(DamageType).reduce((resist: any, key) => { resist[key] = 1; return resist }, {}) Object.entries(this.maxVigors).forEach(([key, val]) => { this.vigors[key as Vigor] = val }) } + resistanceTo (damageType: DamageType): number { + return this.baseResistances[damageType] + } + get maxVigors (): Readonly { return { Health: this.stats.Toughness * 10 + this.stats.Power * 5, @@ -63,6 +71,22 @@ export abstract class Mortal extends Entity { return Object.values(this.vigors).some(val => val <= 0) } + effectiveDamage (damage: Damage): Damage { + const newDamages: DamageInstance[] = [] + damage.damages.forEach(instance => { + const factor = instance.type === DamageType.Heal ? -1 : 1 + const baseResistance: number = this.resistanceTo(instance.type) + const resistance = baseResistance * factor + newDamages.push({ + amount: instance.amount * resistance, + target: instance.target, + type: instance.type + }) + }) + + return new Damage(...newDamages) + } + takeDamage (damage: Damage): LogEntry { // first, we record health to decide if the entity just died const startHealth = this.vigors.Health @@ -70,17 +94,13 @@ export abstract class Mortal extends Entity { 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) - const resistance = effectiveResistance === undefined ? factor : effectiveResistance * factor - if (instance.target in Vigor) { // just deal damage - this.vigors[instance.target as Vigor] -= instance.amount * resistance + this.vigors[instance.target as Vigor] -= instance.amount } else if (instance.target in Stat) { // drain the stats, then deal damage to match const startVigors = this.maxVigors - this.stats[instance.target as Stat] -= instance.amount * resistance + this.stats[instance.target as Stat] -= instance.amount const endVigors = this.maxVigors Object.keys(Vigor).map(vigor => { @@ -101,5 +121,4 @@ export abstract class Mortal extends Entity { } abstract destroy (): LogEntry; - abstract effectiveDamage (damage: Damage): Damage }