diff --git a/src/game/combat/actions.ts b/src/game/combat/actions.ts index 59e6b66..67d8062 100644 --- a/src/game/combat/actions.ts +++ b/src/game/combat/actions.ts @@ -2,7 +2,7 @@ import { StatTest, StatVigorTest } from './tests' import { DynText, LiveText, TextLike, Verb, PairLine, PairLineArgs } from '../language' import { Entity } from '../entity' import { Creature } from "../creature" -import { Damage, DamageFormula, Stat, Vigor, Action } from '../combat' +import { Damage, DamageFormula, Stat, Vigor, Action, Condition } from '../combat' import { LogLine, LogLines, LogEntry, nilLog } from '../interface' import { VoreContainer, Container } from '../vore' import { CapableCondition, UserDrainedVigorCondition, TogetherCondition, EnemyCondition, SoloCondition, PairCondition, ContainsCondition, ContainedByCondition } from './conditions' @@ -21,14 +21,17 @@ export class PassAction extends Action { } } -export class AttackAction extends Action { +export abstract class DamageAction extends Action { protected test: StatTest - constructor (protected damage: DamageFormula, protected verb: Verb = new Verb('smack')) { + abstract successLine: PairLineArgs + abstract failLine: PairLine + + constructor (name: TextLike, desc: TextLike, protected damage: DamageFormula, conditions: Condition[] = []) { super( - verb.root.capital, - 'Attack the enemy', - [new CapableCondition(), new TogetherCondition(), new EnemyCondition()] + name, + desc, + [new CapableCondition(), new EnemyCondition()].concat(conditions) ) this.test = new StatTest(Stat.Power) } @@ -48,17 +51,23 @@ export class AttackAction extends Action { return this.failLine(user, target) } } +} + +export class AttackAction extends DamageAction { + constructor (damage: DamageFormula, protected verb: Verb = new Verb('smack')) { + super(verb.root.capital, 'Attack the enemy', damage, [new TogetherCondition()]) + } describe (user: Creature, target: Creature): LogEntry { return new LogLine(`Attack ${target.name}. `, this.damage.describe(user, target), '. ', this.test.explain(user, target)) } - protected successLine: PairLineArgs = (user, target, args) => new LogLine( + successLine: PairLineArgs = (user, target, args) => new LogLine( `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} for `, target.effectiveDamage(args.damage).renderShort() ) - protected failLine: PairLine = (user, target) => new LogLine( + failLine: PairLine = (user, target) => new LogLine( `${user.name.capital} ${user.name.conjugate(new Verb('miss', 'misses'))} ${target.name.objective}` ) } diff --git a/src/game/creatures/shingo.ts b/src/game/creatures/shingo.ts index 6db92bc..2e92ed1 100644 --- a/src/game/creatures/shingo.ts +++ b/src/game/creatures/shingo.ts @@ -1,64 +1,92 @@ import { Creature } from "../creature" import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, StatDamageFormula, Stat, Action, DamageFormula } from '../combat' -import { ImproperNoun, ProperNoun, FemalePronouns, MalePronouns, Verb, PairLineArgs, PairLine } from '../language' -import { VoreType, Stomach, Bowels, NormalContainer, InnerContainer, VoreContainer, Container } from '../vore' -import { AttackAction, TransferAction, FeedAction, StruggleAction } from '../combat/actions' +import { ImproperNoun, ProperNoun, FemalePronouns, MalePronouns, Verb, PairLineArgs, PairLine, TextLike } from '../language' +import { VoreType, Stomach, Bowels, NormalContainer, InnerContainer, VoreContainer, Container, Vore } from '../vore' +import { AttackAction, TransferAction, FeedAction, StruggleAction, DamageAction } from '../combat/actions' import { LogLine, LogEntry, LogLines } from '../interface' import { ContainsCondition, CapableCondition, EnemyCondition } from '../combat/conditions' import { StatTest } from '../combat/tests' -class Hand extends NormalContainer { - consumeVerb: Verb = new Verb('grab', 'grabs', 'grabbing', 'grabbed') - releaseVerb: Verb = new Verb('release', 'releases', 'releasing', 'released') - struggleVerb: Verb = new Verb('squirm', 'squirms', 'squirming', 'squirmed') - - constructor (owner: Creature) { - super(new ImproperNoun('hand', 'hands'), owner, new Set(), 100) - } -} - -export class ChewAction extends Action { +export class TrappedAction extends DamageAction { protected test: StatTest - constructor (protected damage: DamageFormula, protected verb: Verb = new Verb('smack'), container: Container) { + constructor (name: TextLike, desc: TextLike, protected verb: Verb, protected damage: DamageFormula, container: Container) { super( - verb.root.capital, - 'Chew your victim', + name, + desc, + damage, [new CapableCondition(), new ContainsCondition(container), new EnemyCondition()] ) this.test = new StatTest(Stat.Power) } - 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)) { - const damage = this.damage.calc(user, target) - const targetResult = target.takeDamage(damage) - const ownResult = this.successLine(user, target, { damage: damage }) - return new LogLines(ownResult, targetResult) - } else { - return this.failLine(user, target) - } - } - describe (user: Creature, target: Creature): LogEntry { - return new LogLine(`Attack ${target.name}. `, this.damage.describe(user, target), '. ', this.test.explain(user, target)) + return new LogLine(`Chew on ${target.name}. `, this.damage.describe(user, target), '. ', this.test.explain(user, target)) } - protected successLine: PairLineArgs = (user, target, args) => new LogLine( + successLine: PairLineArgs = (user, target, args) => new LogLine( `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} for `, target.effectiveDamage(args.damage).renderShort() ) - protected failLine: PairLine = (user, target) => new LogLine( - `${user.name.capital} ${user.name.conjugate(new Verb('miss', 'misses'))} ${target.name.objective}` + failLine: PairLine = (user, target) => new LogLine( + `${user.name.capital} can't quite get ${user.pronouns.possessive} teeth around ${target.name.objective}.` ) } +class Hand extends NormalContainer { + consumeVerb: Verb = new Verb('grab', 'grabs', 'grabbing', 'grabbed') + releaseVerb: Verb = new Verb('release', 'releases', 'releasing', 'released') + struggleVerb: Verb = new Verb('squirm', 'squirms', 'squirming', 'squirmed') + + constructor (owner: Creature) { + super(new ImproperNoun('hand', 'hands'), owner, new Set(), 100) + this.actions.push(new TrappedAction( + "Grip", + "Give your victim the squeeze", + new Verb( + 'squeeze' + ), + new ConstantDamageFormula( + new Damage( + { amount: 200, target: Vigor.Health, type: DamageType.Crush } + ) + ), + this + )) + } +} + +class Paw extends NormalContainer { + consumeVerb: Verb = new Verb('pin', 'pins', 'pinning', 'pinbed') + releaseVerb: Verb = new Verb('release', 'releases', 'releasing', 'released') + struggleVerb: Verb = new Verb('squirm', 'squirms', 'squirming', 'squirmed') + + constructor (owner: Creature) { + super(new ImproperNoun('paw', 'paws'), owner, new Set([VoreType.Oral]), 100) + + this.actions.push(new TrappedAction( + "Smother", + "Bury your victim under your ties", + new Verb( + 'smother' + ), + new ConstantDamageFormula( + new Damage( + { amount: 10, target: Stat.Toughness, type: DamageType.Crush }, + { amount: 10, target: Stat.Power, type: DamageType.Crush }, + { amount: 10, target: Stat.Speed, type: DamageType.Crush } + ) + ), + this + )) + } + + consumeLine: PairLineArgs = (user, target, args) => { + return new LogLine(`${user.name.capital} ${user.name.conjugate(this.consumeVerb)} ${target.name.objective} beneath ${user.pronouns.possessive} ${args.container.name}.`) + } +} + class Maw extends NormalContainer { consumeVerb: Verb = new Verb('grab', 'grabs', 'grabbing', 'grabbed') releaseVerb: Verb = new Verb('release', 'releases', 'releasing', 'released') @@ -69,13 +97,20 @@ class Maw extends NormalContainer { this.actions = [] this.actions.push(new StruggleAction(this)) - this.actions.push(new ChewAction( + this.actions.push(new TrappedAction( + "Chew", + "Chew on your victim", + new Verb( + 'bite down on', + 'bites down on', + 'biting down on', + 'bit down on' + ), new ConstantDamageFormula( new Damage( { amount: 200, target: Vigor.Health, type: DamageType.Crush } ) ), - new Verb('chew'), this )) } @@ -133,5 +168,7 @@ export class Shingo extends Creature { `${user.name.capital} ${user.name.conjugate(gulp.verb)} ${target.name.objective} down ${user.pronouns.possessive} tight, inescapable gullet, sending ${target.pronouns.objective} down to ${user.pronouns.possessive} ${args.to.name}` ) this.actions.push(gulp) + + this.otherContainers.push(new Paw(this)) } }