Просмотр исходного кода

Start enforcing member ordering

vintage
Fen Dweller 5 лет назад
Родитель
Сommit
aed2d3f501
6 измененных файлов: 229 добавлений и 227 удалений
  1. +2
    -1
      .eslintrc.js
  2. +20
    -20
      src/components/Combat.vue
  3. +77
    -77
      src/game/combat/actions.ts
  4. +19
    -19
      src/game/creatures/cafat.ts
  5. +40
    -43
      src/game/entity.ts
  6. +71
    -67
      src/game/vore.ts

+ 2
- 1
.eslintrc.js Просмотреть файл

@@ -17,6 +17,7 @@ module.exports = {
'no-useless-constructor': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'quotes': 'off',
'function-paren-newline': ['error', 'multiline-arguments']
'function-paren-newline': ['error', 'multiline-arguments'],
'@typescript-eslint/member-ordering': ['warn']
}
}

+ 20
- 20
src/components/Combat.vue Просмотреть файл

@@ -97,17 +97,17 @@ export default class Combat extends Vue {

actionDescription = ''

created () {
this.$data.left = this.encounter.combatants.filter(x => x.side === Side.Heroes)[0]
this.$data.right = this.encounter.combatants.filter(x => x.side === Side.Monsters)[0]
this.$data.combatants = this.encounter.combatants
}

mounted () {
const leftStats = this.$el.querySelector("#left-stats")
@Emit("described")
described (entry: LogEntry) {
const actionDesc = document.querySelector("#action-desc")

if (leftStats !== null) {
leftStats.scrollTo(leftStats.getBoundingClientRect().width * 2, 0)
if (actionDesc !== null) {
const holder = document.createElement("div")
entry.render().forEach(element => {
holder.appendChild(element)
})
actionDesc.innerHTML = ''
actionDesc.appendChild(holder)
}
}

@@ -176,17 +176,17 @@ export default class Combat extends Vue {
})
}

@Emit("described")
described (entry: LogEntry) {
const actionDesc = document.querySelector("#action-desc")
created () {
this.$data.left = this.encounter.combatants.filter(x => x.side === Side.Heroes)[0]
this.$data.right = this.encounter.combatants.filter(x => x.side === Side.Monsters)[0]
this.$data.combatants = this.encounter.combatants
}

if (actionDesc !== null) {
const holder = document.createElement("div")
entry.render().forEach(element => {
holder.appendChild(element)
})
actionDesc.innerHTML = ''
actionDesc.appendChild(holder)
mounted () {
const leftStats = this.$el.querySelector("#left-stats")

if (leftStats !== null) {
leftStats.scrollTo(leftStats.getBoundingClientRect().width * 2, 0)
}
}
}


+ 77
- 77
src/game/combat/actions.ts Просмотреть файл

@@ -7,6 +7,10 @@ import { VoreContainer, Container } from '../vore'
import { CapableCondition, UserDrainedVigorCondition, TogetherCondition, EnemyCondition, SoloCondition, PairCondition, ContainsCondition, ContainedByCondition } from './conditions'

export class PassAction extends Action {
constructor () {
super("Pass", "Do nothing", [new SoloCondition()])
}

execute (user: Creature, target: Creature): LogEntry {
return nilLog
}
@@ -14,24 +18,11 @@ export class PassAction extends Action {
describe (user: Creature, target: Creature): LogEntry {
return new LogLine("Do nothing.")
}

constructor () {
super("Pass", "Do nothing", [new SoloCondition()])
}
}

export class AttackAction extends Action {
protected test: StatTest

protected successLine: PairLineArgs<Creature, { damage: Damage }> = (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<Creature> = (user, target) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('miss', 'misses'))} ${target.name.objective}`
)

constructor (protected damage: DamageFormula, protected verb: Verb = new Verb('smack')) {
super(
verb.root.capital,
@@ -60,14 +51,28 @@ export class AttackAction extends Action {
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<Creature, { damage: Damage }> = (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<Creature> = (user, target) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('miss', 'misses'))} ${target.name.objective}`
)
}

export class DevourAction extends Action {
private test: StatVigorTest

protected failLine: PairLineArgs<Entity, { container: Container }> = (user, target, args) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to ${args.container.consumeVerb} ${target.name.objective}.`
)
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(), new TogetherCondition()]
)
this.test = new StatVigorTest(Stat.Power)
}

allowed (user: Creature, target: Creature): boolean {
const owner = this.container.owner === user
@@ -81,13 +86,8 @@ export class DevourAction extends Action {
}
}

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(), new TogetherCondition()]
)
this.test = new StatVigorTest(Stat.Power)
describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Try to ${this.container.consumeVerb} your opponent, sending them to your ${this.container.name}. `, this.test.explain(user, target))
}

execute (user: Creature, target: Creature): LogEntry {
@@ -98,19 +98,20 @@ export class DevourAction extends Action {
}
}

describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Try to ${this.container.consumeVerb} your opponent, sending them to your ${this.container.name}. `, this.test.explain(user, target))
}
protected failLine: PairLineArgs<Entity, { container: Container }> = (user, target, args) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to ${args.container.consumeVerb} ${target.name.objective}.`
)
}

export class FeedAction extends Action {
protected successLine: PairLine<Entity> = (user, target) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('feed'))} ${user.pronouns.reflexive} to ${target.name}. `
)

protected failLine: PairLine<Entity> = (user, target) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to feed ${user.pronouns.reflexive} to ${target.name}. `
)
constructor (protected container: Container) {
super(
'Feed',
'Feed yourself to your opponent',
[new UserDrainedVigorCondition(Vigor.Resolve), new TogetherCondition()]
)
this.name += ` (${container.name})`
}

allowed (user: Creature, target: Creature): boolean {
const owner = this.container.owner === target
@@ -124,15 +125,6 @@ export class FeedAction extends Action {
}
}

constructor (protected container: Container) {
super(
'Feed',
'Feed yourself to your opponent',
[new UserDrainedVigorCondition(Vigor.Resolve), new TogetherCondition()]
)
this.name += ` (${container.name})`
}

execute (user: Creature, target: Creature): LogEntry {
return new LogLines(this.successLine(user, target), this.container.consume(user))
}
@@ -140,18 +132,18 @@ export class FeedAction extends Action {
describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Your willpower is drained, and you really feel like shoving yourself into ${target.name}'s ${this.container.name}...`)
}
}

export class StruggleAction extends Action {
private test: StatVigorTest

protected successLine: PairLineArgs<Entity, { container: Container }> = (prey, pred, args) => new LogLine(
`${prey.name.capital} ${prey.name.conjugate(new Verb('escape'))} from ${pred.name.possessive} ${args.container.name}.`
protected successLine: PairLine<Entity> = (user, target) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('feed'))} ${user.pronouns.reflexive} to ${target.name}. `
)

protected failLine: PairLineArgs<Entity, { container: Container }> = (prey, pred, args) => new LogLine(
`${prey.name.capital} ${prey.name.conjugate(new Verb('fail'))} to escape from ${pred.name.possessive} ${args.container.name}.`
protected failLine: PairLine<Entity> = (user, target) => new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to feed ${user.pronouns.reflexive} to ${target.name}. `
)
}

export class StruggleAction extends Action {
private test: StatVigorTest

constructor (public container: Container) {
super(
@@ -177,17 +169,17 @@ export class StruggleAction extends Action {
describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Try to escape from ${target.name}'s ${this.container.name}. `, this.test.explain(user, target))
}

protected successLine: PairLineArgs<Entity, { container: Container }> = (prey, pred, args) => new LogLine(
`${prey.name.capital} ${prey.name.conjugate(new Verb('escape'))} from ${pred.name.possessive} ${args.container.name}.`
)

protected failLine: PairLineArgs<Entity, { container: Container }> = (prey, pred, args) => new LogLine(
`${prey.name.capital} ${prey.name.conjugate(new Verb('fail'))} to escape from ${pred.name.possessive} ${args.container.name}.`
)
}

export abstract class EatenAction extends Action {
allowed (user: Creature, target: Creature) {
if (target.containedIn === this.container) {
return super.allowed(user, target)
} else {
return false
}
}

constructor (public container: Container, name: TextLike, desc: string) {
super(
new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'),
@@ -195,17 +187,17 @@ export abstract class EatenAction extends Action {
[new CapableCondition(), new PairCondition()]
)
}
}

export class DigestAction extends Action {
allowed (user: Creature, target: Creature) {
if (this.container.owner === user && this.container.contents.length > 0) {
if (target.containedIn === this.container) {
return super.allowed(user, target)
} else {
return false
}
}
}

export class DigestAction extends Action {
constructor (protected container: VoreContainer) {
super(
new DynText('Digest (', new LiveText(container, container => container.name.all), ')'),
@@ -214,6 +206,14 @@ export class DigestAction extends Action {
)
}

allowed (user: Creature, target: Creature) {
if (this.container.owner === user && this.container.contents.length > 0) {
return super.allowed(user, target)
} else {
return false
}
}

execute (user: Creature, target: Creature): LogEntry {
const results = this.container.tick(60)
return new CompositeLog(results)
@@ -225,14 +225,6 @@ export class DigestAction extends Action {
}

export class ReleaseAction extends Action {
allowed (user: Creature, target: Creature) {
if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) {
return super.allowed(user, target)
} else {
return false
}
}

constructor (protected container: Container) {
super(
new DynText('Release (', new LiveText(container, x => x.name.all), ')'),
@@ -241,6 +233,14 @@ export class ReleaseAction extends Action {
)
}

allowed (user: Creature, target: Creature) {
if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) {
return super.allowed(user, target)
} else {
return false
}
}

execute (user: Creature, target: Creature): LogEntry {
return this.container.release(target)
}
@@ -253,6 +253,14 @@ export class ReleaseAction extends Action {
export class TransferAction extends Action {
verb: Verb = new Verb('send')

constructor (protected from: Container, protected to: Container, name = 'Transfer') {
super(
name,
`${from.name.all.capital} to ${to.name.all}`,
[new CapableCondition(), new PairCondition()]
)
}

line: PairLineArgs<Creature, { from: Container; to: Container }> = (user, target, args) => new LogLine(
`${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} from ${user.pronouns.possessive} ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`
)
@@ -265,14 +273,6 @@ export class TransferAction extends Action {
}
}

constructor (protected from: Container, protected to: Container, name = 'Transfer') {
super(
name,
`${from.name.all.capital} to ${to.name.all}`,
[new CapableCondition(), new PairCondition()]
)
}

execute (user: Creature, target: Creature): LogEntry {
this.from.release(target)
this.to.consume(target)


+ 19
- 19
src/game/creatures/cafat.ts Просмотреть файл

@@ -8,11 +8,6 @@ import { InstantKillEffect } from '../combat/effects'
import * as Words from '../words'

class BellyCrushAction extends AttackAction {
successLine: PairLineArgs<Creature, { damage: Damage }> = (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 `,
target.effectiveDamage(args.damage).renderShort()
), new ImgElem('./media/cafat/images/belly-crush.webp'))

constructor (_damage: Damage) {
super({
calc (user) { return _damage.scale(user.voreStats.Bulk / 25) },
@@ -26,9 +21,20 @@ class BellyCrushAction extends AttackAction {
describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Crush ${target.name} under your gut. `, this.damage.describe(user, target))
}

successLine: PairLineArgs<Creature, { damage: Damage }> = (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 `,
target.effectiveDamage(args.damage).renderShort()
), new ImgElem('./media/cafat/images/belly-crush.webp'))
}

class BelchAction extends AttackAction {
constructor (damage: Damage) {
super(new ConstantDamageFormula(damage))
this.name = 'Belch'
this.desc = 'Drain your foe\'s stats with a solid BELCH'
}

successLine: PairLineArgs<Creature, { damage: Damage }> = (user, target, args) => new LogLines(
new LogLine(
`${user.name.capital} ${user.name.conjugate(new Verb('belch', 'belches'))} on ${target.name.objective} for `,
@@ -36,32 +42,26 @@ class BelchAction extends AttackAction {
),
new ImgElem('./media/cafat/images/belch.webp')
)

constructor (damage: Damage) {
super(new ConstantDamageFormula(damage))
this.name = 'Belch'
this.desc = 'Drain your foe\'s stats with a solid BELCH'
}
}

class CrushAction extends EatenAction {
line: PairLineArgs<Creature, { container: VoreContainer }> = (user, target, args) => new LogLine(
`${user.name.capital.possessive} ${args.container.name} ${Words.Brutally} ${user.name.conjugate(new Verb('crush', 'crushes'))} ${target.name.objective}; ${user.pronouns.subjective} ${user.pronouns.conjugate(new Verb('belch', 'belches'))} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `,
new ImgElem('./media/cafat/images/crunch.webp')
)

constructor (private _container: VoreContainer) {
super(_container, "Crush", "Crush 'em!")
this.desc = "Crush somebody in your gut"
}

describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Crush ${target.name} in your ${this.container.name} for massive, unavoidable damage.`)
}

execute (user: Creature, target: Creature): LogEntry {
return new LogLines(this.line(user, target, { container: this._container }), target.applyEffect(new InstantKillEffect()))
}

describe (user: Creature, target: Creature): LogEntry {
return new LogLine(`Crush ${target.name} in your ${this.container.name} for massive, unavoidable damage.`)
}
line: PairLineArgs<Creature, { container: VoreContainer }> = (user, target, args) => new LogLine(
`${user.name.capital.possessive} ${args.container.name} ${Words.Brutally} ${user.name.conjugate(new Verb('crush', 'crushes'))} ${target.name.objective}; ${user.pronouns.subjective} ${user.pronouns.conjugate(new Verb('belch', 'belches'))} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `,
new ImgElem('./media/cafat/images/crunch.webp')
)
}

export class Cafat extends Creature {


+ 40
- 43
src/game/entity.ts Просмотреть файл

@@ -26,9 +26,9 @@ export abstract class Entity {
}
}

title: TextLike = "Some thing."
desc: TextLike = "It's a ting."
perspective: POV = POV.Third
title: TextLike = "Some thing."

constructor (public baseName: Noun, public kind: Noun, public basePronouns: Pronoun) {

@@ -36,17 +36,23 @@ export abstract class Entity {
}

export abstract class Mortal extends Entity {
abstract destroy (): LogEntry;
abstract effectiveDamage (damage: Damage): Damage
resistances: Map<DamageType, number> = new Map()
stats: Stats;

vigors: {[key in Vigor]: number} = {
[Vigor.Health]: 100,
[Vigor.Stamina]: 100,
[Vigor.Resolve]: 100
}

constructor (name: Noun, kind: Noun, pronouns: Pronoun, public baseStats: Stats) {
super(name, kind, pronouns)
Object.entries(this.maxVigors).forEach(([key, val]) => {
this.vigors[key as Vigor] = val
})

this.stats = Object.keys(Stat).reduce((base: any, key) => { base[key] = baseStats[key as Stat]; return base }, {})
}

get maxVigors (): Readonly<Vigors> {
return {
Health: this.stats.Toughness * 10 + this.stats.Power * 5,
@@ -96,33 +102,33 @@ export abstract class Mortal extends Entity {
return this.name.toString()
}

constructor (name: Noun, kind: Noun, pronouns: Pronoun, public baseStats: Stats) {
super(name, kind, pronouns)
Object.entries(this.maxVigors).forEach(([key, val]) => {
this.vigors[key as Vigor] = val
})

this.stats = Object.keys(Stat).reduce((base: any, key) => { base[key] = baseStats[key as Stat]; return base }, {})
}
abstract destroy (): LogEntry;
abstract effectiveDamage (damage: Damage): Damage
}

export class Creature extends Vore implements Combatant {
title = "Lv. 1 Creature"
actions: Array<Action> = []
containedIn: VoreContainer|null = null;
desc = "Some creature"
effects: Array<StatusEffect> = []
groupActions: Array<GroupAction> = []
items: Array<Item> = []
otherActions: Array<Action> = []
side: Side
title = "Lv. 1 Creature"

effects: Array<StatusEffect> = []
constructor (name: Noun, kind: Noun, pronouns: Pronoun, stats: Stats, preyPrefs: Set<VoreType>, predPrefs: Set<VoreType>, mass: number) {
super(name, kind, pronouns, stats, preyPrefs, predPrefs, mass)

this.actions.push(new PassAction())
this.side = Side.Heroes
}

applyEffect (effect: StatusEffect): LogEntry {
this.effects.push(effect)
return effect.onApply(this)
}

removeEffect (effect: StatusEffect): LogEntry {
this.effects = this.effects.filter(eff => eff !== effect)
return effect.onRemove(this)
}

/**
* Determines how much damage an attack would do
*/
@@ -132,6 +138,21 @@ export class Creature extends Vore implements Combatant {
}, damage)
}

executeAction (action: Action, target: Creature): LogEntry {
const effectResults = this.effects.map(effect => effect.preAction(this))
const blocking = effectResults.filter(result => result.prevented)
if (blocking.length > 0) {
return new LogLines(...blocking.map(result => result.log))
} else {
return action.execute(this, target)
}
}

removeEffect (effect: StatusEffect): LogEntry {
this.effects = this.effects.filter(eff => eff !== effect)
return effect.onRemove(this)
}

get status (): Array<VisibleStatus> {
const results: Array<VisibleStatus> = []

@@ -154,30 +175,6 @@ export class Creature extends Vore implements Combatant {
return results
}

executeAction (action: Action, target: Creature): LogEntry {
const effectResults = this.effects.map(effect => effect.preAction(this))
const blocking = effectResults.filter(result => result.prevented)
if (blocking.length > 0) {
return new LogLines(...blocking.map(result => result.log))
} else {
return action.execute(this, target)
}
}

actions: Array<Action> = []
groupActions: Array<GroupAction> = []
otherActions: Array<Action> = []
items: Array<Item> = []

containedIn: VoreContainer|null = null;

constructor (name: Noun, kind: Noun, pronouns: Pronoun, stats: Stats, preyPrefs: Set<VoreType>, predPrefs: Set<VoreType>, mass: number) {
super(name, kind, pronouns, stats, preyPrefs, predPrefs, mass)

this.actions.push(new PassAction())
this.side = Side.Heroes
}

validActions (target: Creature): Array<Action> {
let choices = this.actions.concat(
this.containers.flatMap(container => container.actions)


+ 71
- 67
src/game/vore.ts Просмотреть файл

@@ -13,46 +13,13 @@ export enum VoreType {
}

export abstract class Vore extends Mortal {
destroyed = false;
voreStats: VoreStats

containedIn: Container | null = null
containers: Array<VoreContainer> = []
otherContainers: Array<Container> = []

destroy (): LogEntry {
const line: SoloLine<Vore> = (victim) => new LogLine(
`${victim.name.capital} ${victim.name.conjugate(new Verb('die'))}`
)

const released: Array<Vore> = this.containers.flatMap(container => {
return container.contents.map(prey => {
prey.containedIn = this.containedIn
if (this.containedIn !== null) {
this.containedIn.contents.push(prey)
}
return prey
})
})

const names = released.reduce((list: Array<string>, prey: Vore) => list.concat([prey.name.toString()]), []).joinGeneral(", ", " and ").join("")
containedIn: Container | null = null
destroyed = false;

if (released.length > 0) {
if (this.containedIn === null) {
return new LogLines(
line(this),
new LogLine(names + ` spill out!`)
)
} else {
return new LogLines(
line(this),
new LogLine(names + ` spill out into ${this.containedIn.owner.name}'s ${this.containedIn.name}!`)
)
}
} else {
return line(this)
}
}
voreStats: VoreStats

constructor (name: Noun, kind: Noun, pronouns: Pronoun, baseStats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, public mass: number) {
super(name, kind, pronouns, baseStats)
@@ -94,20 +61,57 @@ export abstract class Vore extends Mortal {
}
}
}

destroy (): LogEntry {
const line: SoloLine<Vore> = (victim) => new LogLine(
`${victim.name.capital} ${victim.name.conjugate(new Verb('die'))}`
)

const released: Array<Vore> = this.containers.flatMap(container => {
return container.contents.map(prey => {
prey.containedIn = this.containedIn
if (this.containedIn !== null) {
this.containedIn.contents.push(prey)
}
return prey
})
})

const names = released.reduce((list: Array<string>, prey: Vore) => list.concat([prey.name.toString()]), []).joinGeneral(", ", " and ").join("")

if (released.length > 0) {
if (this.containedIn === null) {
return new LogLines(
line(this),
new LogLine(names + ` spill out!`)
)
} else {
return new LogLines(
line(this),
new LogLine(names + ` spill out into ${this.containedIn.owner.name}'s ${this.containedIn.name}!`)
)
}
} else {
return line(this)
}
}
}

export interface Container extends Actionable {
name: Noun;
owner: Vore;
voreTypes: Set<VoreType>;
contents: Array<Vore>;
capacity: number;
fullness: number;

contents: Array<Vore>;
describe: () => LogEntry;

canTake: (prey: Vore) => boolean;
consume: (prey: Vore) => LogEntry;
release: (prey: Vore) => LogEntry;
struggle: (prey: Vore) => LogEntry;
describe: () => LogEntry;

consumeVerb: Verb;
releaseVerb: Verb;
@@ -119,6 +123,17 @@ export abstract class NormalContainer implements Container {
contents: Array<Vore> = []
actions: Array<Action> = []

abstract consumeVerb: Verb
abstract releaseVerb: Verb
abstract struggleVerb: Verb

constructor (name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number) {
this.name = name.all
this.actions.push(new DevourAction(this))
this.actions.push(new ReleaseAction(this))
this.actions.push(new StruggleAction(this))
}

consumeLine: PairLineArgs<Vore, { container: Container }> = (user, target, args) => {
return new LogLine(`${user.name.capital} ${user.name.conjugate(this.consumeVerb)} ${target.name.objective} in ${user.pronouns.possessive} ${args.container.name}.`)
}
@@ -131,10 +146,6 @@ export abstract class NormalContainer implements Container {
return new LogLine(`${user.name.capital} ${user.name.conjugate(this.struggleVerb)} within ${target.name.possessive} ${args.container.name}.`)
}

abstract consumeVerb: Verb
abstract releaseVerb: Verb
abstract struggleVerb: Verb

get fullness (): number {
return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0)
}
@@ -181,13 +192,6 @@ export abstract class NormalContainer implements Container {

return new LogLine(...lines)
}

constructor (name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number) {
this.name = name.all
this.actions.push(new DevourAction(this))
this.actions.push(new ReleaseAction(this))
this.actions.push(new StruggleAction(this))
}
}

export interface VoreContainer extends Container {
@@ -197,8 +201,20 @@ export interface VoreContainer extends Container {
}

export abstract class NormalVoreContainer extends NormalContainer implements VoreContainer {
consumeVerb = new Verb('devour')
releaseVerb = new Verb('release', 'releases', 'releasing', 'released')
struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')

digested: Array<Vore> = []

constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, private damage: Damage) {
super(name, owner, voreTypes, capacity)

this.name = name

this.actions.push(new DigestAction(this))
}

consumeLine: PairLineArgs<Vore, { container: Container }> = (user, target, args) => {
return new LogLine(`${user.name.capital} ${user.name.conjugate(this.consumeVerb)} ${target.name.objective}, forcing ${target.pronouns.objective} into ${user.pronouns.possessive} ${args.container.name}.`)
}
@@ -211,10 +227,6 @@ export abstract class NormalVoreContainer extends NormalContainer implements Vor
return new LogLine(`${user.name.capital.possessive} ${args.container.name} finishes ${Words.Digests.present} ${target.name.objective} down, ${target.pronouns.possessive} ${Words.Struggles.singular} fading away.`)
}

consumeVerb = new Verb('devour')
releaseVerb = new Verb('release', 'releases', 'releasing', 'released')
struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')

tick (dt: number): LogEntry {
const justDigested: Array<Vore> = []

@@ -246,23 +258,9 @@ export abstract class NormalVoreContainer extends NormalContainer implements Vor
digest (preys: Vore[]): LogEntry {
return new LogLines(...preys.map(prey => this.digestLine(this.owner, prey, { container: this })))
}

constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, private damage: Damage) {
super(name, owner, voreTypes, capacity)

this.name = name

this.actions.push(new DigestAction(this))
}
}

abstract class InnerContainer extends NormalVoreContainer {
release (prey: Vore): LogEntry {
prey.containedIn = this.escape
this.contents = this.contents.filter(victim => victim !== prey)
return this.releaseLine(this.owner, prey, { container: this })
}

constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: VoreContainer) {
super(name, owner, voreTypes, capacity, damage)

@@ -271,6 +269,12 @@ abstract class InnerContainer extends NormalVoreContainer {
this.actions.push(new DigestAction(this))
this.actions.push(new StruggleAction(this))
}

release (prey: Vore): LogEntry {
prey.containedIn = this.escape
this.contents = this.contents.filter(victim => victim !== prey)
return this.releaseLine(this.owner, prey, { container: this })
}
}

export class Stomach extends NormalVoreContainer {


Загрузка…
Отмена
Сохранить