| @@ -16,6 +16,7 @@ module.exports = { | |||||
| 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', | ||||
| 'no-useless-constructor': 'off', | 'no-useless-constructor': 'off', | ||||
| '@typescript-eslint/no-unused-vars': 'off', | '@typescript-eslint/no-unused-vars': 'off', | ||||
| 'quotes': 'off' | |||||
| 'quotes': 'off', | |||||
| 'function-paren-newline': ['error', 'multiline-arguments'] | |||||
| } | } | ||||
| } | } | ||||
| @@ -73,7 +73,8 @@ export default class App extends Vue { | |||||
| this.left = fighter | this.left = fighter | ||||
| this.right = new Creatures.Withers() | this.right = new Creatures.Withers() | ||||
| this.combatants = [this.left, this.right, wizard, rogue, cleric] | |||||
| const kenzie = new Creatures.Kenzie() | |||||
| this.combatants = [this.left, this.right, wizard, rogue, cleric, kenzie] | |||||
| console.log(this.left) | console.log(this.left) | ||||
| console.log(this.right) | console.log(this.right) | ||||
| } | } | ||||
| @@ -1,10 +1,10 @@ | |||||
| <template> | <template> | ||||
| <div class="combat-layout"> | <div class="combat-layout"> | ||||
| <div @wheel="horizWheelLeft" class="stat-column" id="left-stats"> | <div @wheel="horizWheelLeft" class="stat-column" id="left-stats"> | ||||
| <Statblock v-on:click.native="left = combatant" class="left-stats" :data-active="combatant === left" v-for="combatant in combatants.filter(c => c.side == Side.Heroes && !c.digested)" v-bind:key="combatant.name" :subject="combatant" /> | |||||
| <Statblock v-on:click.native="left = combatant" class="left-stats" :data-active="combatant === left" v-for="(combatant, index) in combatants.filter(c => c.side == Side.Heroes && !c.digested)" v-bind:key="'left-stat-' + index" :subject="combatant" /> | |||||
| </div> | </div> | ||||
| <div @wheel="horizWheelRight" class="stat-column" id="right-stats"> | <div @wheel="horizWheelRight" class="stat-column" id="right-stats"> | ||||
| <Statblock v-on:click.native="right = combatant" class="right-stats" :data-active="combatant === right" v-for="combatant in combatants.filter(c => c.side == Side.Monsters && !c.digested)" v-bind:key="combatant.name" :subject="combatant" /> | |||||
| <Statblock v-on:click.native="right = combatant" class="right-stats" :data-active="combatant === right" v-for="(combatant, index) in combatants.filter(c => c.side == Side.Monsters && !c.digested)" v-bind:key="'right-stat-' + index" :subject="combatant" /> | |||||
| </div> | </div> | ||||
| <div id="log"> | <div id="log"> | ||||
| </div> | </div> | ||||
| @@ -18,7 +18,7 @@ | |||||
| <i class="action-label fas fa-user-friends" v-if="left.validActions(right).length > 0"></i> | <i class="action-label fas fa-user-friends" v-if="left.validActions(right).length > 0"></i> | ||||
| <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(right)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" /> | <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(right)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" /> | ||||
| <i class="action-label fas fa-user" v-if="left.validActions(left).length > 0"></i> | <i class="action-label fas fa-user" v-if="left.validActions(left).length > 0"></i> | ||||
| <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(left)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" /> | |||||
| <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(left)" :key="'left' + action.name" :action="action" :user="left" :target="left" :combatants="combatants" /> | |||||
| </div> | </div> | ||||
| <div>{{actionDescription}}</div> | <div>{{actionDescription}}</div> | ||||
| </div> | </div> | ||||
| @@ -32,7 +32,7 @@ | |||||
| <i class="action-label fas fa-user-friends" v-if="right.validActions(left).length > 0"></i> | <i class="action-label fas fa-user-friends" v-if="right.validActions(left).length > 0"></i> | ||||
| <ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(left)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" /> | <ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(left)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" /> | ||||
| <i class="action-label fas fa-user" v-if="right.validActions(right).length > 0"></i> | <i class="action-label fas fa-user" v-if="right.validActions(right).length > 0"></i> | ||||
| <ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(right)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" /> | |||||
| <ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(right)" :key="'right' + action.name" :action="action" :user="right" :target="right" :combatants="combatants" /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div id="action-desc"> | <div id="action-desc"> | ||||
| @@ -295,37 +295,7 @@ export interface Actionable { | |||||
| actions: Array<Action>; | actions: Array<Action>; | ||||
| } | } | ||||
| export abstract class SelfAction extends Action { | |||||
| allowed (user: Creature, target: Creature) { | |||||
| if (user === target) { | |||||
| return super.allowed(user, target) | |||||
| } else { | |||||
| return false | |||||
| } | |||||
| } | |||||
| } | |||||
| export abstract class PairAction extends Action { | |||||
| allowed (user: Creature, target: Creature) { | |||||
| if (user !== target) { | |||||
| return super.allowed(user, target) | |||||
| } else { | |||||
| return false | |||||
| } | |||||
| } | |||||
| } | |||||
| export abstract class TogetherAction extends PairAction { | |||||
| allowed (user: Creature, target: Creature) { | |||||
| if (user.containedIn === target.containedIn) { | |||||
| return super.allowed(user, target) | |||||
| } else { | |||||
| return false | |||||
| } | |||||
| } | |||||
| } | |||||
| export abstract class GroupAction extends PairAction { | |||||
| export abstract class GroupAction extends Action { | |||||
| allowedGroup (user: Creature, targets: Array<Creature>): Array<Creature> { | allowedGroup (user: Creature, targets: Array<Creature>): Array<Creature> { | ||||
| return targets.filter(target => this.allowed(user, target)) | return targets.filter(target => this.allowed(user, target)) | ||||
| } | } | ||||
| @@ -335,4 +305,8 @@ export abstract class GroupAction extends PairAction { | |||||
| } | } | ||||
| abstract describeGroup (user: Creature, targets: Array<Creature>): LogEntry | abstract describeGroup (user: Creature, targets: Array<Creature>): LogEntry | ||||
| constructor (name: TextLike, desc: TextLike, conditions: Array<Condition>) { | |||||
| super(name, desc, conditions) | |||||
| } | |||||
| } | } | ||||
| @@ -1,12 +1,12 @@ | |||||
| import { StatTest, StatVigorTest } from './tests' | import { StatTest, StatVigorTest } from './tests' | ||||
| import { POVPairArgs, POVPair, DynText, LiveText, TextLike } from '../language' | import { POVPairArgs, POVPair, DynText, LiveText, TextLike } from '../language' | ||||
| import { Entity, POV, Creature } from '../entity' | import { Entity, POV, Creature } from '../entity' | ||||
| import { Damage, DamageFormula, Stat, Vigor, TogetherAction, PairAction, SelfAction } from '../combat' | |||||
| import { Damage, DamageFormula, Stat, Vigor, Action } from '../combat' | |||||
| import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface' | import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface' | ||||
| import { VoreContainer, Container } from '../vore' | import { VoreContainer, Container } from '../vore' | ||||
| import { CapableCondition, DrainedVigorCondition } from './conditions' | |||||
| import { CapableCondition, DrainedVigorCondition, TogetherCondition, EnemyCondition, SoloCondition, PairCondition } from './conditions' | |||||
| export class AttackAction extends TogetherAction { | |||||
| export class AttackAction extends Action { | |||||
| protected test: StatTest | protected test: StatTest | ||||
| protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([ | protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([ | ||||
| @@ -31,7 +31,11 @@ export class AttackAction extends TogetherAction { | |||||
| ]) | ]) | ||||
| constructor (protected damage: DamageFormula) { | constructor (protected damage: DamageFormula) { | ||||
| super('Attack', 'Attack the enemy', [new CapableCondition()]) | |||||
| super( | |||||
| 'Attack', | |||||
| 'Attack the enemy', | |||||
| [new CapableCondition(), new TogetherCondition(), new EnemyCondition()] | |||||
| ) | |||||
| this.test = new StatTest(Stat.Power) | this.test = new StatTest(Stat.Power) | ||||
| } | } | ||||
| @@ -51,7 +55,7 @@ export class AttackAction extends TogetherAction { | |||||
| } | } | ||||
| } | } | ||||
| export class DevourAction extends TogetherAction { | |||||
| export class DevourAction extends Action { | |||||
| private test: StatVigorTest | private test: StatVigorTest | ||||
| protected failLines: POVPairArgs<Entity, Entity, { container: Container }> = new POVPairArgs([ | protected failLines: POVPairArgs<Entity, Entity, { container: Container }> = new POVPairArgs([ | ||||
| @@ -73,7 +77,11 @@ export class DevourAction extends TogetherAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super(new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'), new LiveText(container, x => `Try to ${x.consumeVerb} your foe`), [new CapableCondition()]) | |||||
| super( | |||||
| new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'), | |||||
| new LiveText(container, x => `Try to ${x.consumeVerb} your foe`), | |||||
| [new CapableCondition(), new TogetherCondition()] | |||||
| ) | |||||
| this.test = new StatVigorTest(Stat.Power) | this.test = new StatVigorTest(Stat.Power) | ||||
| } | } | ||||
| @@ -90,7 +98,7 @@ export class DevourAction extends TogetherAction { | |||||
| } | } | ||||
| } | } | ||||
| export class FeedAction extends TogetherAction { | |||||
| export class FeedAction extends Action { | |||||
| private test: StatTest | private test: StatTest | ||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| @@ -112,7 +120,11 @@ export class FeedAction extends TogetherAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Resolve)]) | |||||
| super( | |||||
| 'Feed', | |||||
| 'Feed yourself to your opponent', | |||||
| [new DrainedVigorCondition(Vigor.Resolve), new TogetherCondition()] | |||||
| ) | |||||
| this.name += ` (${container.name})` | this.name += ` (${container.name})` | ||||
| this.test = new StatTest(Stat.Power) | this.test = new StatTest(Stat.Power) | ||||
| } | } | ||||
| @@ -126,7 +138,7 @@ export class FeedAction extends TogetherAction { | |||||
| } | } | ||||
| } | } | ||||
| export class StruggleAction extends PairAction { | |||||
| export class StruggleAction extends Action { | |||||
| private test: StatVigorTest | private test: StatVigorTest | ||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| @@ -144,7 +156,11 @@ export class StruggleAction extends PairAction { | |||||
| } | } | ||||
| constructor (public container: Container) { | constructor (public container: Container) { | ||||
| super(new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), 'Try to escape from your foe', [new CapableCondition()]) | |||||
| super( | |||||
| new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), | |||||
| 'Try to escape from your foe', | |||||
| [new CapableCondition(), new PairCondition()] | |||||
| ) | |||||
| this.test = new StatVigorTest(Stat.Power) | this.test = new StatVigorTest(Stat.Power) | ||||
| } | } | ||||
| @@ -165,7 +181,7 @@ export class StruggleAction extends PairAction { | |||||
| } | } | ||||
| } | } | ||||
| export abstract class EatenAction extends PairAction { | |||||
| export abstract class EatenAction extends Action { | |||||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | protected lines: POVPair<Entity, Entity> = new POVPair([]) | ||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| @@ -177,10 +193,15 @@ export abstract class EatenAction extends PairAction { | |||||
| } | } | ||||
| constructor (public container: Container, name: TextLike, desc: string) { | constructor (public container: Container, name: TextLike, desc: string) { | ||||
| super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()]) | |||||
| super( | |||||
| new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), | |||||
| desc, | |||||
| [new CapableCondition(), new PairCondition()] | |||||
| ) | |||||
| } | } | ||||
| } | } | ||||
| export class DigestAction extends SelfAction { | |||||
| export class DigestAction extends Action { | |||||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | protected lines: POVPair<Entity, Entity> = new POVPair([]) | ||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| @@ -192,7 +213,11 @@ export class DigestAction extends SelfAction { | |||||
| } | } | ||||
| constructor (protected container: VoreContainer) { | constructor (protected container: VoreContainer) { | ||||
| super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()]) | |||||
| super( | |||||
| new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), | |||||
| 'Digest your prey', | |||||
| [new CapableCondition(), new SoloCondition()] | |||||
| ) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -205,7 +230,7 @@ export class DigestAction extends SelfAction { | |||||
| } | } | ||||
| } | } | ||||
| export class ReleaseAction extends PairAction { | |||||
| export class ReleaseAction extends Action { | |||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) { | if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) { | ||||
| return super.allowed(user, target) | return super.allowed(user, target) | ||||
| @@ -215,7 +240,11 @@ export class ReleaseAction extends PairAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super(new DynText('Release (', new LiveText(container, x => x.name.all), ')'), 'Release one of your prey', [new CapableCondition()]) | |||||
| super( | |||||
| new DynText('Release (', new LiveText(container, x => x.name.all), ')'), | |||||
| 'Release one of your prey', | |||||
| [new CapableCondition(), new PairCondition()] | |||||
| ) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -227,7 +256,7 @@ export class ReleaseAction extends PairAction { | |||||
| } | } | ||||
| } | } | ||||
| export class TransferAction extends PairAction { | |||||
| export class TransferAction extends Action { | |||||
| lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | ||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | ||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)], | [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)], | ||||
| @@ -243,7 +272,11 @@ export class TransferAction extends PairAction { | |||||
| } | } | ||||
| constructor (protected from: Container, protected to: Container, name = 'Transfer') { | constructor (protected from: Container, protected to: Container, name = 'Transfer') { | ||||
| super(name, `${from.name.all.capital} to ${to.name.all}`, [new CapableCondition()]) | |||||
| super( | |||||
| name, | |||||
| `${from.name.all.capital} to ${to.name.all}`, | |||||
| [new CapableCondition(), new PairCondition()] | |||||
| ) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -27,9 +27,21 @@ export class DrainedVigorCondition implements Condition { | |||||
| } | } | ||||
| } | } | ||||
| export class SoloCondition implements Condition { | |||||
| allowed (user: Creature, target: Creature): boolean { | |||||
| return user === target | |||||
| } | |||||
| } | |||||
| export class PairCondition implements Condition { | |||||
| allowed (user: Creature, target: Creature): boolean { | |||||
| return user !== target | |||||
| } | |||||
| } | |||||
| export class TogetherCondition implements Condition { | export class TogetherCondition implements Condition { | ||||
| allowed (user: Creature, target: Creature): boolean { | allowed (user: Creature, target: Creature): boolean { | ||||
| return user.containedIn === target.containedIn | |||||
| return user.containedIn === target.containedIn && user !== target | |||||
| } | } | ||||
| } | } | ||||
| @@ -42,3 +54,15 @@ export class ContainerCondition implements Condition { | |||||
| } | } | ||||
| } | } | ||||
| export class AllyCondition implements Condition { | |||||
| allowed (user: Creature, target: Creature): boolean { | |||||
| return user.side === target.side | |||||
| } | |||||
| } | |||||
| export class EnemyCondition implements Condition { | |||||
| allowed (user: Creature, target: Creature): boolean { | |||||
| return user.side !== target.side | |||||
| } | |||||
| } | |||||
| @@ -3,5 +3,6 @@ import { Player } from './creatures/player' | |||||
| import { Cafat } from './creatures/cafat' | import { Cafat } from './creatures/cafat' | ||||
| import { Human } from './creatures/human' | import { Human } from './creatures/human' | ||||
| import { Withers } from './creatures/withers' | import { Withers } from './creatures/withers' | ||||
| import { Kenzie } from './creatures/kenzie' | |||||
| export { Wolf, Player, Cafat, Human, Withers } | |||||
| export { Wolf, Player, Cafat, Human, Withers, Kenzie } | |||||
| @@ -0,0 +1,34 @@ | |||||
| import { Creature, POV } from '../entity' | |||||
| import { ProperNoun, ImproperNoun, FemalePronouns, POVPairArgs, POVPair } from '../language' | |||||
| import { VoreType, Stomach, Vore } from '../vore' | |||||
| import { Side, Damage, DamageType, Vigor, UniformRandomDamageFormula } from '../combat' | |||||
| import { LogLine } from '../interface' | |||||
| import { FeedAction, TransferAction } from '../combat/actions' | |||||
| import * as Words from '../words' | |||||
| export class Kenzie extends Creature { | |||||
| title = "Large Lycanroc" | |||||
| desc = "Will eat your party" | |||||
| constructor () { | |||||
| super( | |||||
| new ProperNoun('Kenzie'), | |||||
| new ImproperNoun('lycanroc', 'lycanrocs'), | |||||
| FemalePronouns, | |||||
| { Toughness: 60, Power: 70, Speed: 40, Willpower: 60, Charm: 120 }, | |||||
| new Set(), | |||||
| new Set([VoreType.Oral]), | |||||
| 1000 | |||||
| ) | |||||
| this.side = Side.Monsters | |||||
| const stomach = new Stomach(this, 50, new Damage( | |||||
| { amount: 100, type: DamageType.Acid, target: Vigor.Health }, | |||||
| { amount: 100, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 100, type: DamageType.Dominance, target: Vigor.Resolve } | |||||
| )) | |||||
| this.containers.push(stomach) | |||||
| } | |||||
| } | |||||
| @@ -1,10 +1,10 @@ | |||||
| import { Creature, POV } from '../entity' | import { Creature, POV } from '../entity' | ||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, Action, DamageFormula, UniformRandomDamageFormula, PairAction } from '../combat' | |||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, DamageFormula, UniformRandomDamageFormula, Action } from '../combat' | |||||
| import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs, Verb } from '../language' | import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs, Verb } from '../language' | ||||
| import { LogLine, LogLines, LogEntry, Newline } from '../interface' | import { LogLine, LogLines, LogEntry, Newline } from '../interface' | ||||
| import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container } from '../vore' | import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container } from '../vore' | ||||
| import { AttackAction, FeedAction, TransferAction, EatenAction } from '../combat/actions' | import { AttackAction, FeedAction, TransferAction, EatenAction } from '../combat/actions' | ||||
| import { TogetherCondition, ContainerCondition } from '../combat/conditions' | |||||
| import { TogetherCondition, ContainerCondition, EnemyCondition } from '../combat/conditions' | |||||
| import { InstantKill } from '../combat/effects' | import { InstantKill } from '../combat/effects' | ||||
| import * as Words from '../words' | import * as Words from '../words' | ||||
| import { StatVigorTest } from '../combat/tests' | import { StatVigorTest } from '../combat/tests' | ||||
| @@ -92,12 +92,14 @@ class BootContainer extends NormalContainer { | |||||
| constructor (owner: Vore) { | constructor (owner: Vore) { | ||||
| super(new ImproperNoun('boot'), owner, new Set(), 50) | super(new ImproperNoun('boot'), owner, new Set(), 50) | ||||
| const flex = new FlexToesAction(new UniformRandomDamageFormula(new Damage( | |||||
| { target: Vigor.Health, type: DamageType.Crush, amount: 50 }, | |||||
| { target: Vigor.Stamina, type: DamageType.Crush, amount: 50 }, | |||||
| { target: Vigor.Resolve, type: DamageType.Crush, amount: 50 } | |||||
| ), 0.5), | |||||
| this) | |||||
| const flex = new FlexToesAction( | |||||
| new UniformRandomDamageFormula(new Damage( | |||||
| { target: Vigor.Health, type: DamageType.Crush, amount: 50 }, | |||||
| { target: Vigor.Stamina, type: DamageType.Crush, amount: 50 }, | |||||
| { target: Vigor.Resolve, type: DamageType.Crush, amount: 50 } | |||||
| ), 0.5), | |||||
| this | |||||
| ) | |||||
| this.actions.push(flex) | this.actions.push(flex) | ||||
| } | } | ||||
| @@ -179,7 +181,8 @@ class StompAction extends GroupAction { | |||||
| constructor () { | constructor () { | ||||
| super('Stomp', 'STOMP!', [ | super('Stomp', 'STOMP!', [ | ||||
| new TogetherCondition() | |||||
| new TogetherCondition(), | |||||
| new EnemyCondition() | |||||
| ]) | ]) | ||||
| } | } | ||||
| } | } | ||||
| @@ -222,7 +225,8 @@ class DevourAllAction extends GroupAction { | |||||
| constructor (private container: VoreContainer) { | constructor (private container: VoreContainer) { | ||||
| super('Devour All', 'GULP!', [ | super('Devour All', 'GULP!', [ | ||||
| new TogetherCondition() | |||||
| new TogetherCondition(), | |||||
| new EnemyCondition() | |||||
| ]) | ]) | ||||
| this.test = new StatVigorTest(Stat.Power) | this.test = new StatVigorTest(Stat.Power) | ||||
| } | } | ||||
| @@ -240,7 +244,8 @@ export class Withers extends Creature { | |||||
| { Toughness: 60, Power: 70, Speed: 40, Willpower: 60, Charm: 120 }, | { Toughness: 60, Power: 70, Speed: 40, Willpower: 60, Charm: 120 }, | ||||
| new Set(), | new Set(), | ||||
| new Set([VoreType.Oral]), | new Set([VoreType.Oral]), | ||||
| 5000) | |||||
| 5000 | |||||
| ) | |||||
| this.actions.push(new BiteAction()) | this.actions.push(new BiteAction()) | ||||
| this.groupActions.push(new StompAction()) | this.groupActions.push(new StompAction()) | ||||
| @@ -274,11 +279,13 @@ export class Withers extends Creature { | |||||
| this.otherContainers.push(maw) | this.otherContainers.push(maw) | ||||
| this.actions.push(new ChewAction(new UniformRandomDamageFormula(new Damage( | |||||
| { target: Vigor.Health, type: DamageType.Crush, amount: 10000 } | |||||
| ), 0.5), | |||||
| maw, | |||||
| new TransferAction(maw, stomach))) | |||||
| this.actions.push(new ChewAction( | |||||
| new UniformRandomDamageFormula(new Damage( | |||||
| { target: Vigor.Health, type: DamageType.Crush, amount: 10000 } | |||||
| ), 0.5), | |||||
| maw, | |||||
| new TransferAction(maw, stomach) | |||||
| )) | |||||
| const boot = new BootContainer(this) | const boot = new BootContainer(this) | ||||
| this.otherContainers.push(boot) | this.otherContainers.push(boot) | ||||
| @@ -3,6 +3,7 @@ import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats } from | |||||
| import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | ||||
| import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo, TextLike, Verb, Word } from './language' | import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo, TextLike, Verb, Word } from './language' | ||||
| import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions' | import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions' | ||||
| import * as Words from './words' | |||||
| export enum VoreType { | export enum VoreType { | ||||
| Oral = "Oral Vore", | Oral = "Oral Vore", | ||||
| @@ -242,15 +243,15 @@ export class Stomach extends NormalVoreContainer { | |||||
| ]) | ]) | ||||
| tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([ | tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([ | ||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | |||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach ${Words.Churns.singular} you for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())] | |||||
| ]) | ]) | ||||
| digestLines = new POVPair<Vore, Vore>([ | digestLines = new POVPair<Vore, Vore>([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach overwhelms ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach finishes you off`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)] | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach ${Words.Digests.singular} ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach ${Words.Digests.singular} you`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s ${Words.Struggles.present} fades as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind.all}'s ${this.name}.`)] | |||||
| ]) | ]) | ||||
| absorbLines = new POVPair<Vore, Vore>([ | absorbLines = new POVPair<Vore, Vore>([ | ||||