| @@ -127,6 +127,8 @@ export default class Statblock extends Vue { | |||||
| }) | }) | ||||
| }) | }) | ||||
| createSingleton(tippyInstances, { delay: 500 }) | createSingleton(tippyInstances, { delay: 500 }) | ||||
| this.statusChanged([]) | |||||
| } | } | ||||
| @Watch('subject.status') | @Watch('subject.status') | ||||
| @@ -373,4 +373,11 @@ export abstract class StatusEffect implements VisibleStatus { | |||||
| preDamage (creature: Creature, damage: Damage): Damage { | preDamage (creature: Creature, damage: Damage): Damage { | ||||
| return damage | return damage | ||||
| } | } | ||||
| preAttack (creature: Creature, attacker: Creature): { prevented: boolean; log: LogEntry } { | |||||
| return { | |||||
| prevented: false, | |||||
| log: nilLog | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -28,6 +28,11 @@ export class AttackAction extends Action { | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| const effectResults = target.effects.map(effect => effect.preAttack(target, user)) | |||||
| if (effectResults.some(result => result.prevented)) { | |||||
| return new LogLines(...effectResults.map(result => result.log)) | |||||
| } | |||||
| if (this.test.test(user, target)) { | if (this.test.test(user, target)) { | ||||
| const damage = this.damage.calc(user, target) | const damage = this.damage.calc(user, target) | ||||
| const targetResult = target.takeDamage(damage) | const targetResult = target.takeDamage(damage) | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { StatusEffect, Damage, DamageType } from '../combat' | |||||
| import { StatusEffect, Damage, DamageType, Action } from '../combat' | |||||
| import { DynText, LiveText, ToBe, Verb } from '../language' | import { DynText, LiveText, ToBe, Verb } from '../language' | ||||
| import { Creature } from '../entity' | import { Creature } from '../entity' | ||||
| import { LogLine, LogEntry, LogLines, FAElem } from '../interface' | |||||
| import { LogLine, LogEntry, LogLines, FAElem, nilLog } from '../interface' | |||||
| export class InstantKillEffect extends StatusEffect { | export class InstantKillEffect extends StatusEffect { | ||||
| constructor () { | constructor () { | ||||
| @@ -74,3 +74,24 @@ export class ShieldEffect extends StatusEffect { | |||||
| return damage.scale(this.amount) | return damage.scale(this.amount) | ||||
| } | } | ||||
| } | } | ||||
| 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 } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -2,10 +2,10 @@ import { Creature } from '../entity' | |||||
| import { ProperNoun, ImproperNoun, FemalePronouns, Verb } from '../language' | import { ProperNoun, ImproperNoun, FemalePronouns, Verb } from '../language' | ||||
| import { VoreType, Stomach } from '../vore' | import { VoreType, Stomach } from '../vore' | ||||
| import { Side, Damage, DamageType, Vigor, StatDamageFormula, Stat, VoreStat, DamageFormula } from '../combat' | import { Side, Damage, DamageType, Vigor, StatDamageFormula, Stat, VoreStat, DamageFormula } from '../combat' | ||||
| import { AttackAction } from '../combat/actions' | |||||
| import { AttackAction, DevourAction } from '../combat/actions' | |||||
| import { LogEntry, LogLines } from '../interface' | import { LogEntry, LogLines } from '../interface' | ||||
| import { StatTest } from '../combat/tests' | import { StatTest } from '../combat/tests' | ||||
| import { StunEffect } from '../combat/effects' | |||||
| import { StunEffect, PredatorCounterEffect } from '../combat/effects' | |||||
| class StompAttack extends AttackAction { | class StompAttack extends AttackAction { | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -52,6 +52,8 @@ export class Kenzie extends Creature { | |||||
| { amount: 100, type: DamageType.Dominance, target: Vigor.Resolve } | { amount: 100, type: DamageType.Dominance, target: Vigor.Resolve } | ||||
| )) | )) | ||||
| this.applyEffect(new PredatorCounterEffect(new DevourAction(stomach), 0.4)) | |||||
| this.containers.push(stomach) | this.containers.push(stomach) | ||||
| this.actions.push( | this.actions.push( | ||||
| @@ -3,9 +3,9 @@ import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, Co | |||||
| import { ImproperNoun, ProperNoun, FemalePronouns, RandomWord, Adjective, Verb, POV, PairLine } from '../language' | import { ImproperNoun, ProperNoun, FemalePronouns, RandomWord, Adjective, Verb, POV, PairLine } from '../language' | ||||
| import { LogLine, LogLines, LogEntry, Newline } from '../interface' | import { LogLine, LogLines, LogEntry, Newline } from '../interface' | ||||
| import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container, InnerStomach } from '../vore' | import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container, InnerStomach } from '../vore' | ||||
| import { AttackAction, FeedAction, TransferAction, EatenAction } from '../combat/actions' | |||||
| import { AttackAction, FeedAction, TransferAction, EatenAction, DevourAction } from '../combat/actions' | |||||
| import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions' | import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions' | ||||
| import { InstantKillEffect, ShieldEffect } from '../combat/effects' | |||||
| import { InstantKillEffect, ShieldEffect, PredatorCounterEffect } from '../combat/effects' | |||||
| import * as Words from '../words' | import * as Words from '../words' | ||||
| import { StatVigorTest } from '../combat/tests' | import { StatVigorTest } from '../combat/tests' | ||||