Przeglądaj źródła

Add non-vore containers

master
Fen Dweller 5 lat temu
rodzic
commit
587d3d2ecb
8 zmienionych plików z 165 dodań i 94 usunięć
  1. +1
    -1
      src/game/combat.ts
  2. +8
    -8
      src/game/combat/actions.ts
  3. +2
    -2
      src/game/creatures/cafat.ts
  4. +39
    -5
      src/game/creatures/withers.ts
  5. +16
    -10
      src/game/entity.ts
  6. +1
    -0
      src/game/language.ts
  7. +86
    -68
      src/game/vore.ts
  8. +12
    -0
      src/game/words.ts

+ 1
- 1
src/game/combat.ts Wyświetl plik

@@ -1,6 +1,6 @@
import { Creature, POV, Entity } from './entity'
import { POVPair, POVPairArgs, TextLike, DynText, LiveText } from './language'
import { Container } from './vore'
import { VoreContainer } from './vore'
import { LogEntry, LogLines, CompositeLog, FAElem, LogLine, FormatEntry, FormatOpt, PropElem } from './interface'
import { StatTest, StatVigorTest } from './combat/tests'



+ 8
- 8
src/game/combat/actions.ts Wyświetl plik

@@ -3,7 +3,7 @@ import { POVPairArgs, POVPair, DynText, LiveText, TextLike } from '../language'
import { Entity, POV, Creature } from '../entity'
import { Damage, DamageFormula, Stat, Vigor, TogetherAction, PairAction, SelfAction } from '../combat'
import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface'
import { Container } from '../vore'
import { VoreContainer, Container } from '../vore'
import { CapableCondition, DrainedVigorCondition } from './conditions'

export class AttackAction extends TogetherAction {
@@ -73,7 +73,7 @@ export class DevourAction extends TogetherAction {
}

constructor (protected container: Container) {
super(new DynText('Devour (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()])
super(new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()])
this.test = new StatVigorTest(Stat.Power)
}

@@ -132,7 +132,7 @@ export class StruggleAction extends PairAction {
protected failLines: POVPair<Entity, Entity> = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLine(`You fail to escape from ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} tries to escape from you, but fails`)],
[[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} unsuccessfully struggles within ${target.name}`)]
[[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} unsuccessfully struggles against ${target.name}`)]
])

allowed (user: Creature, target: Creature) {
@@ -176,7 +176,7 @@ export abstract class EatenAction extends PairAction {
}
}

constructor (public container: Container, name: TextLike, desc: string) {
constructor (public container: VoreContainer, name: TextLike, desc: string) {
super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()])
}
}
@@ -191,7 +191,7 @@ export class DigestAction extends SelfAction {
}
}

constructor (protected container: Container) {
constructor (protected container: VoreContainer) {
super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()])
}

@@ -231,7 +231,7 @@ export class TransferAction extends PairAction {
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.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.Third], (user, target, args) => new LogLine(`${user.name} squeezes ${target.name} from ${user.pronouns.possessive} ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)]
[[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name} squeezes ${target.name} from ${user.pronouns.possessive} ${args.from.name.all} to ${user.pronouns.possessive} ${args.to.name.all}`)]
])

allowed (user: Creature, target: Creature) {
@@ -242,8 +242,8 @@ export class TransferAction extends PairAction {
}
}

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

execute (user: Creature, target: Creature): LogEntry {


+ 2
- 2
src/game/creatures/cafat.ts Wyświetl plik

@@ -1,7 +1,7 @@
import { Creature, POV, Entity } from '../entity'
import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat'
import { ProperNoun, TheyPronouns, ImproperNoun, POVPair, FemalePronouns, POVPairArgs } from '../language'
import { VoreType, Stomach, InnerStomach, Container } from '../vore'
import { VoreType, Stomach, InnerStomach, VoreContainer, NormalContainer, Vore } from '../vore'
import { LogLine, LogLines, LogEntry, FAElem, CompositeLog, ImgElem } from '../interface'
import { AttackAction, EatenAction, TransferAction, FeedAction } from '../combat/actions'
import { InstantKill } from '../combat/effects'
@@ -66,7 +66,7 @@ class CrushAction extends EatenAction {
[[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} crushes ${target.name}; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `)]
])

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


+ 39
- 5
src/game/creatures/withers.ts Wyświetl plik

@@ -1,13 +1,43 @@
import { Creature, POV } from '../entity'
import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction } from '../combat'
import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs } from '../language'
import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs, Verb } from '../language'
import { LogLine, LogLines, LogEntry, Newline } from '../interface'
import { VoreType, Stomach, Container, Vore } from '../vore'
import { AttackAction, FeedAction } from '../combat/actions'
import { VoreType, Stomach, VoreContainer, Vore, NormalContainer } from '../vore'
import { AttackAction, FeedAction, TransferAction } from '../combat/actions'
import { TogetherCondition } from '../combat/conditions'
import { InstantKill } from '../combat/effects'
import * as Words from '../words'

class MawContainer extends NormalContainer {
consumeVerb = new Verb('grab')
releaseVerb = new Verb('release')
struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')

consumeLines = new POVPair<Vore, Vore>([
[[POV.First, POV.Third], (user, target) => new LogLine(`You snatch ${target.name} up in your jaws`)],
[[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} snatches you up in ${user.pronouns.possessive} maw`)],
[[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} snatches ${target.name} up in ${user.pronouns.possessive} maw`)]
])

releaseLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLine(`You let out ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} lets you out `)],
[[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} lets out ${target.name}`)]
])

struggleLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLine(`You claw your way free of ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} forces ${user.pronouns.possessive} way free!`)],
[[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from ${target.name}`)]
])

constructor (owner: Vore, stomach: VoreContainer) {
super(new ImproperNoun('maw'), owner, new Set([VoreType.Oral]), 50)

this.actions.push(new TransferAction(this, stomach))
}
}

const huge = new RandomWord([
new Adjective('massive'),
new Adjective('colossal'),
@@ -84,7 +114,7 @@ class DevourAllAction extends GroupAction {
return new LogLine('Eat all ', targets.length.toString(), ' of \'em!')
}

constructor (private container: Container) {
constructor (private container: VoreContainer) {
super('Devour All', 'GULP!', [
new TogetherCondition()
])
@@ -122,12 +152,16 @@ export class Withers extends Creature {
stomach.digestLines = new POVPair<Vore, Vore>([
[[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 squirms fade as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind}'s ${stomach.name}.`)]
[[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 ${stomach.name}.`)]
])

this.containers.push(stomach)
this.otherActions.push(new FeedAction(stomach))

this.groupActions.push(new DevourAllAction(stomach))

const grapple = new MawContainer(this, stomach)

this.otherContainers.push(grapple)
}
}

+ 16
- 10
src/game/entity.ts Wyświetl plik

@@ -1,7 +1,7 @@
import { DamageType, Damage, Combatant, Stats, Action, Vigor, VoreStats, VoreStat, Stat, Side, GroupAction } from './combat'
import { Noun, Pronoun, Adjective, ImproperNoun } from './language'
import { LogEntry, LogLine } from './interface'
import { Vore, Container, VoreType } from './vore'
import { Vore, VoreContainer, VoreType, Container } from './vore'

export enum POV {First, Third}

@@ -47,16 +47,17 @@ export class Creature extends Vore implements Combatant {

resistances: Map<DamageType, number> = new Map()
perspective: POV = POV.Third
containers: Array<Container> = []
actions: Array<Action> = [];
groupActions: Array<GroupAction> = [];
otherActions: Array<Action> = [];
containers: Array<VoreContainer> = []
otherContainers: Array<Container> = []
actions: Array<Action> = []
groupActions: Array<GroupAction> = []
otherActions: Array<Action> = []

get bulk (): number {
return this.voreStats.Mass + this.containers.reduce((total, conatiner) => { return total + conatiner.contents.reduce((total, prey) => total + prey.voreStats.Bulk, 0) }, 0)
}

containedIn: Container|null = null;
containedIn: VoreContainer|null = null;

constructor (public name: Noun, public kind: Noun, public pronouns: Pronoun, public stats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, mass: number) {
super()
@@ -67,7 +68,7 @@ export class Creature extends Vore implements Combatant {
get [VoreStat.Bulk] () {
console.log(containers)
return containers.reduce(
(total: number, container: Container) => {
(total: number, container: VoreContainer) => {
return total + container.contents.reduce(
(total: number, prey: Vore) => {
return total + prey.voreStats.Bulk
@@ -86,7 +87,7 @@ export class Creature extends Vore implements Combatant {
[VoreStat.Mass]: mass,
get [VoreStat.PreyCount] () {
return containers.reduce(
(total: number, container: Container) => {
(total: number, container: VoreContainer) => {
return total + container.contents.reduce(
(total: number, prey: Vore) => {
return total + 1 + prey.voreStats[VoreStat.PreyCount]
@@ -140,14 +141,19 @@ export class Creature extends Vore implements Combatant {
return "Broken"
}
if (this.containedIn !== null) {
return `Devoured by ${this.containedIn.owner.name}`
return `${this.containedIn.consumeVerb.past.capital} by ${this.containedIn.owner.name}`
}

return "Normal"
}

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

if (this.containedIn !== null) {
choices = choices.concat(this.containedIn.actions)


+ 1
- 0
src/game/language.ts Wyświetl plik

@@ -130,6 +130,7 @@ export class DynText {
}

toString (): string {
console.log(this.parts)
return (this.parts.map(part => part.toString())).join('')
}
}


+ 86
- 68
src/game/vore.ts Wyświetl plik

@@ -1,7 +1,7 @@
import { Entity, Mortal, POV, Creature } from './entity'
import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats } from './combat'
import { LogLines, LogEntry, CompositeLog, LogLine } from './interface'
import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo } from './language'
import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo, TextLike, Verb, Word } from './language'
import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions'

export enum VoreType {
@@ -29,7 +29,8 @@ export abstract class Vore implements Mortal {
abstract voreStats: VoreStats;
abstract containedIn: Container | null;
abstract predPrefs: Set<VoreType>;
abstract containers: Array<Container>;
abstract containers: Array<VoreContainer>;
abstract otherContainers: Array<Container>;
destroy (): LogEntry {
const lines = new POVSolo<Vore>([
[[POV.First], (target: Vore) => new LogLine('You die!')],
@@ -53,66 +54,101 @@ export interface Container extends Actionable {
owner: Vore;
voreTypes: Set<VoreType>;
contents: Array<Vore>;
digested: Array<Vore>;
capacity: number;
fullness: number;
canTake: (prey: Vore) => boolean;
consume: (prey: Vore) => LogEntry;
release: (prey: Vore) => LogEntry;
struggle: (prey: Vore) => LogEntry;
tick: (dt: number) => LogEntry;
describe: () => LogEntry;
digest: (prey: Vore) => LogEntry;
absorb: (prey: Vore) => LogEntry;
dispose: (preys: Vore[]) => LogEntry;
actions: Array<Action>;
consumeVerb: Verb;
releaseVerb: Verb;
struggleVerb: Verb;
}

abstract class NormalContainer implements Container {
contents: Array<Vore>
digested: Array<Vore>
export abstract class NormalContainer implements Container {
contents: Array<Vore> = []
actions: Array<Action> = []

abstract consumeLines: POVPair<Vore, Vore>
abstract releaseLines: POVPair<Vore, Vore>
abstract struggleLines: POVPair<Vore, Vore>
abstract tickLines: POVPairArgs<Vore, Vore, { damage: Damage }>
abstract digestLines: POVPair<Vore, Vore>
abstract absorbLines: POVPair<Vore, Vore>
abstract disposeLines: POVPair<Vore, Vore>
abstract consumeLines: POVPair<Vore, Vore>
abstract releaseLines: POVPair<Vore, Vore>
abstract struggleLines: POVPair<Vore, Vore>

get fullness (): number {
return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0)
}
abstract consumeVerb: Verb
abstract releaseVerb: Verb
abstract struggleVerb: Verb

canTake (prey: Vore): boolean {
const fits = this.capacity - this.fullness >= prey.voreStats.Bulk
get fullness (): number {
return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0)
}

const permitted = Array.from(this.voreTypes).every(voreType => {
return prey.preyPrefs.has(voreType)
})
canTake (prey: Vore): boolean {
const fits = this.capacity - this.fullness >= prey.voreStats.Bulk

return fits && permitted
}
const permitted = Array.from(this.voreTypes).every(voreType => {
return prey.preyPrefs.has(voreType)
})

consume (prey: Vore): LogEntry {
this.contents.push(prey)
prey.containedIn = this
return this.consumeLines.run(this.owner, prey)
}
return fits && permitted
}

release (prey: Vore): LogEntry {
prey.containedIn = this.owner.containedIn
this.contents = this.contents.filter(victim => victim !== prey)
consume (prey: Vore): LogEntry {
this.contents.push(prey)
prey.containedIn = this
return this.consumeLines.run(this.owner, prey)
}

if (this.owner.containedIn !== null) {
this.owner.containedIn.contents.push(prey)
}
return this.releaseLines.run(this.owner, prey)
}
release (prey: Vore): LogEntry {
prey.containedIn = this.owner.containedIn
this.contents = this.contents.filter(victim => victim !== prey)

struggle (prey: Vore): LogEntry {
return this.struggleLines.run(prey, this.owner)
if (this.owner.containedIn !== null) {
this.owner.containedIn.contents.push(prey)
}
return this.releaseLines.run(this.owner, prey)
}

struggle (prey: Vore): LogEntry {
return this.struggleLines.run(prey, this.owner)
}

describe (): LogEntry {
const lines: Array<string> = []

this.contents.forEach(prey => {
lines.push(prey.toString())
})

return new LogLine(...lines)
}

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

export interface VoreContainer extends Container {
digested: Array<Vore>;
tick: (dt: number) => LogEntry;
digest: (prey: Vore) => LogEntry;
absorb: (prey: Vore) => LogEntry;
dispose: (preys: Vore[]) => LogEntry;
}

export abstract class NormalVoreContainer extends NormalContainer implements VoreContainer {
digested: Array<Vore> = []

abstract tickLines: POVPairArgs<Vore, Vore, { damage: Damage }>
abstract digestLines: POVPair<Vore, Vore>
abstract absorbLines: POVPair<Vore, Vore>
abstract disposeLines: POVPair<Vore, Vore>

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> = []
@@ -140,16 +176,6 @@ abstract class NormalContainer implements Container {
return new LogLines(tickedEntries, new LogLines(...damageResults), digestedEntries)
}

describe (): LogEntry {
const lines: Array<string> = []

this.contents.forEach(prey => {
lines.push(prey.toString())
})

return new LogLine(...lines)
}

digest (prey: Vore): LogEntry {
return this.digestLines.run(this.owner, prey)
}
@@ -162,31 +188,23 @@ abstract class NormalContainer implements Container {
return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey)))
}

actions: Array<Action>

constructor (public name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) {
this.contents = []
this.digested = []

this.actions = []
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 DevourAction(this))
this.actions.push(new DigestAction(this))
this.actions.push(new ReleaseAction(this))
this.actions.push(new StruggleAction(this))
}
}

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

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

this.actions = []
@@ -196,7 +214,7 @@ abstract class InnerContainer extends NormalContainer {
}
}

export class Stomach extends NormalContainer {
export class Stomach extends NormalVoreContainer {
constructor (owner: Vore, capacity: number, damage: Damage) {
super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage)
}
@@ -245,7 +263,7 @@ export class Stomach extends NormalContainer {
}

export class InnerStomach extends InnerContainer {
constructor (owner: Vore, capacity: number, damage: Damage, escape: Container) {
constructor (owner: Vore, capacity: number, damage: Damage, escape: VoreContainer) {
super(new ImproperNoun('inner stomach', 'inner stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage, escape)
}

@@ -292,7 +310,7 @@ export class InnerStomach extends InnerContainer {
])
}

export class Bowels extends NormalContainer {
export class Bowels extends NormalVoreContainer {
constructor (owner: Vore, capacity: number, damage: Damage) {
super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage)
}


+ 12
- 0
src/game/words.ts Wyświetl plik

@@ -30,3 +30,15 @@ export const Digests = new RandomWord([
new Verb("melt"),
new Verb("dissolve", "dissolves", "dissolving", "dissolved")
])

export const Struggles = new RandomWord([
new Verb("squirm"),
new Verb("struggle", "struggles", "struggling", "struggled"),
new Verb("thrash", "thrashes")
])

export const Bulge = new RandomWord([
new ImproperNoun("bulge", "bulges"),
new ImproperNoun("outline", "outlines"),
new ImproperNoun("imprint", "imprints")
])

Ładowanie…
Anuluj
Zapisz