浏览代码

Completely rewrite how text is generated

master
Fen Dweller 5 年前
父节点
当前提交
f8cbaf8d66
共有 8 个文件被更改,包括 362 次插入311 次删除
  1. +1
    -2
      src/App.vue
  2. +21
    -5
      src/components/Combat.vue
  3. +174
    -170
      src/game/combat.ts
  4. +7
    -5
      src/game/creatures/player.ts
  5. +1
    -5
      src/game/creatures/wolf.ts
  6. +1
    -4
      src/game/interface.ts
  7. +48
    -3
      src/game/language.ts
  8. +109
    -117
      src/game/vore.ts

+ 1
- 2
src/App.vue 查看文件

@@ -22,8 +22,7 @@ export default class App extends Vue {
enemy: Creature
constructor () {
super()
this.player = new Creatures.Wolf()
this.player.perspective = POV.First
this.player = new Creatures.Player()
this.enemy = new Creatures.Wolf()
console.log(this.player)
console.log(this.enemy)


+ 21
- 5
src/components/Combat.vue 查看文件

@@ -5,20 +5,24 @@
<Statblock :subject="player" />
<Statblock :subject="enemy" />
</div>
<div id="log"></div>
<div class="horiz-display">
<div>
<h2>Your moves</h2>
<button class="combat-button" @mouseleave="actionDescription= ''" @mouseover="actionDescription = action.desc" v-for="action in player.validActions(enemy)" :key="'player-' + action.name" v-on:click="log(action.execute(player, enemy))">{{action.name}}</button>
<button class="combat-button" @mouseleave="actionDescription= ''" @mouseover="actionDescription = action.desc" v-for="action in player.validActions(player)" :key="'player-' + action.name" v-on:click="log(action.execute(player, player))">{{action.name}}</button>
<div class="vert-display">
<button class="combat-button" @mouseleave="actionDescription= ''" @mouseover="actionDescription = action.desc" v-for="action in player.validActions(enemy)" :key="'player-' + action.name" v-on:click="log(action.execute(player, enemy))">{{action.name}}</button>
<button class="combat-button" @mouseleave="actionDescription= ''" @mouseover="actionDescription = action.desc" v-for="action in player.validActions(player)" :key="'player-' + action.name" v-on:click="log(action.execute(player, player))">{{action.name}}</button>
</div>
<div>{{actionDescription}}</div>
</div>
<div>
<h2>Enemy moves</h2>
<button class="combat-button" v-for="action in enemy.validActions(player)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, player))">{{action.name}}</button>
<button class="combat-button" v-for="action in enemy.validActions(enemy)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, enemy))">{{action.name}}</button>
<div class="vert-display">
<button class="combat-button" v-for="action in enemy.validActions(player)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, player))">{{action.name}}</button>
<button class="combat-button" v-for="action in enemy.validActions(enemy)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, enemy))">{{action.name}}</button>
</div>
</div>
<div id="log"></div>
</div>
</div>
</template>

@@ -71,8 +75,20 @@ a {
display: flex;
justify-content: center;
}
.vert-display {
display: flex;
flex-direction: column;
}
.combat-button {
width: 100px;
height: 100px;
}
</style>

<style>

#log p:nth-last-child(1) {
padding-top: 16pt;
}

</style>

+ 174
- 170
src/game/combat.ts 查看文件

@@ -1,9 +1,78 @@
import { Creature, POV } from './entity'
import { POVActionPicker } from './language'
import { Creature, POV, Entity } from './entity'
import { POVPair, POVPairArgs } from './language'
import { Container } from './vore'
import { LogEntry, LogLines, CompositeLog } from './interface'

export enum DamageType {Pierce, Slash, Crush, Acid}
export interface CombatTest {
test: (user: Creature, target: Creature) => boolean;
odds: (user: Creature, target: Creature) => number;
explain: (user: Creature, target: Creature) => LogEntry;
}

function logistic (x0: number, L: number, k: number): (x: number) => number {
return (x: number) => {
return L / (1 + Math.exp(-k * (x - x0)))
}
}

abstract class RandomTest implements CombatTest {
test (user: Creature, target: Creature): boolean {
return Math.random() < this.odds(user, target)
}

abstract odds(user: Creature, target: Creature): number
abstract explain(user: Creature, target: Creature): LogEntry
}

export class StatTest extends RandomTest {
private f: (x: number) => number

constructor (public readonly stat: Stat, k = 0.1) {
super()
this.f = logistic(0, 1, k)
}

odds (user: Creature, target: Creature): number {
return this.f(user.stats[this.stat] - target.stats[this.stat])
}

explain (user: Creature, target: Creature): LogEntry {
const delta: number = user.stats[this.stat] - target.stats[this.stat]
let result: string

if (delta === 0) {
result = 'You and the target have the same ' + this.stat + '.'
} else if (delta < 0) {
result = 'You have ' + delta + ' less ' + this.stat + ' than your foe.'
} else {
result = 'You have ' + delta + ' more ' + this.stat + ' than you foe.'
}

result += ' Your odds of success are ' + (100 * this.odds(user, target)) + '%'

return new LogLines(result)
}
}

export class ChanceTest extends RandomTest {
constructor (public readonly chance: number) {
super()
}

odds (user: Creature, target: Creature): number {
return this.chance
}

explain (user: Creature, target: Creature): LogEntry {
return new LogLines('You have a flat ' + (100 * this.chance) + '% chance.')
}
}

export enum DamageType {
Pierce = "Pierce",
Slash = "Slash",
Crush = "Crush",
Acid = "Acid"}

export interface DamageInstance {
type: DamageType;
@@ -11,24 +80,28 @@ export interface DamageInstance {
}

export class Damage {
readonly damages: DamageInstance[]
readonly damages: DamageInstance[]

constructor (...damages: DamageInstance[]) {
this.damages = damages
}
constructor (...damages: DamageInstance[]) {
this.damages = damages
}

scale (factor: number): Damage {
const results: Array<DamageInstance> = []
scale (factor: number): Damage {
const results: Array<DamageInstance> = []

this.damages.forEach(damage => {
results.push({
type: damage.type,
amount: damage.amount * factor
})
this.damages.forEach(damage => {
results.push({
type: damage.type,
amount: damage.amount * factor
})
})

return new Damage(...results)
}
return new Damage(...results)
}

toString (): string {
return this.damages.map(damage => damage.amount + " " + damage.type).join("/")
}
}

export enum Stat {
@@ -83,91 +156,108 @@ abstract class TogetherAction extends PairAction {
}

export class AttackAction extends TogetherAction {
protected lines: POVActionPicker = {
[POV.First]: {
[POV.First]: (user, target) => new LogLines('You bite...yourself?'),
[POV.Third]: (user, target) => new LogLines('You bite ' + target.name)
},
[POV.Third]: {
[POV.First]: (user, target) => new LogLines(user.name.capital + ' bites you'),
[POV.Third]: (user, target) => new LogLines(user.name.capital + ' bites ' + target.name)
}
}

constructor (protected damage: Damage) {
super('Attack', 'Attack the enemy')
}
private test: StatTest

protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([
[[POV.First, POV.Third], (user, target, args) => new LogLines(`You smack ${target.name} for ${args.damage} damage`)],
[[POV.Third, POV.First], (user, target, args) => new LogLines(`${user.name.capital} hits you for ${args.damage} damage`)],
[[POV.Third, POV.Third], (user, target, args) => new LogLines(`${user.name.capital} hits ${target.name.capital} for ${args.damage} damage`)]
])

protected failLines: POVPair<Entity, Entity> = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You try to smack ${target.name}, but you miss`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} misses you`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} misses ${target.name}`)]
])

constructor (protected damage: Damage) {
super('Attack', 'Attack the enemy')
this.test = new StatTest(Stat.STR)
}

execute (user: Creature, target: Creature): LogEntry {
execute (user: Creature, target: Creature): LogEntry {
if (this.test.test(user, target)) {
target.takeDamage(this.damage)
return this.lines[user.perspective][target.perspective](user, target)
return this.successLines.run(user, target, { damage: this.damage })
} else {
return this.failLines.run(user, target)
}
}
}

export class DevourAction extends TogetherAction {
protected lines: POVActionPicker = {
[POV.First]: {
[POV.First]: (user, target) => new LogLines('You devour...yourself?'),
[POV.Third]: (user, target) => new LogLines('You devour ' + target.name)
},
[POV.Third]: {
[POV.First]: (user, target) => new LogLines(user.name.capital + ' devours you'),
[POV.Third]: (user, target) => new LogLines(user.name.capital + ' devours ' + target.name)
}
}
private test: StatTest

constructor (protected container: Container) {
super('Devour', 'Try to consume your foe')
this.name += ` (${container.name})`
protected failLines: POVPair<Entity, Entity> = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You fail to make a meal out of ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to devour you, but fails`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} unsuccessfully tries to swallow ${target.name}`)]
])

allowed (user: Creature, target: Creature): boolean {
const owner = this.container.owner === user
const predOk = Array.from(this.container.voreTypes).every(pref => user.predPrefs.has(pref))
const preyOk = Array.from(this.container.voreTypes).every(pref => target.preyPrefs.has(pref))

if (owner && predOk && preyOk) {
return super.allowed(user, target)
} else {
return false
}
}

execute (user: Creature, target: Creature): LogEntry {
return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), this.container.consume(target))
constructor (protected container: Container) {
super('Devour', 'Try to consume your foe')
this.name += ` (${container.name})`
this.test = new StatTest(Stat.STR)
}

execute (user: Creature, target: Creature): LogEntry {
if (this.test.test(user, target)) {
return this.container.consume(target)
} else {
return this.failLines.run(user, target)
}
}
}

export class StruggleAction extends PairAction {
protected lines: POVActionPicker = {
[POV.First]: {
[POV.First]: (user, target) => new LogLines('You escape from...yourself?'),
[POV.Third]: (user, target) => new LogLines('You escape from ' + target.name)
},
[POV.Third]: {
[POV.First]: (user, target) => new LogLines(user.name.capital + ' escapes from you'),
[POV.Third]: (user, target) => new LogLines(user.name.capital + ' escapes from ' + target.name)
}
}
private test: StatTest

allowed (user: Creature, target: Creature) {
if (user.containedIn === this.container) {
return super.allowed(user, target)
} else {
return false
}
}
protected failLines: POVPair<Entity, Entity> = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You fail to make a meal out of ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to devour you, but fails`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} unsuccessfully tries to swallow ${target.name}`)]
])

constructor (public container: Container) {
super('Struggle', 'Try to escape your predator')
allowed (user: Creature, target: Creature) {
if (user.containedIn === this.container) {
return super.allowed(user, target)
} else {
return false
}
}

execute (user: Creature, target: Creature): LogEntry {
if (user.containedIn) {
return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), user.containedIn.release(user))
} else { return new LogLines("The prey wasn't actually eaten...") }
constructor (public container: Container) {
super('Struggle', 'Try to escape your predator')
this.test = new StatTest(Stat.STR)
}

execute (user: Creature, target: Creature): LogEntry {
if (user.containedIn !== null) {
if (this.test.test(user, target)) {
return user.containedIn.release(user)
} else {
return this.failLines.run(user, target)
}
} else {
return new LogLines("Vore's bugged!")
}
}
}

export class DigestAction extends SelfAction {
protected lines: POVActionPicker = {
[POV.First]: {
[POV.First]: (user, target) => new LogLines('You rub your stomach'),
[POV.Third]: (user, target) => new LogLines("You can't digest for other people...")
},
[POV.Third]: {
[POV.First]: (user, target) => new LogLines("Other people can't digest for you..."),
[POV.Third]: (user, target) => new LogLines(user.name.capital + ' rubs ' + user.pronouns.possessive + ' gut.')
}
}
protected lines: POVPair<Entity, Entity> = new POVPair([])

allowed (user: Creature, target: Creature) {
if (this.container.owner === user && this.container.contents.length > 0) {
@@ -184,22 +274,11 @@ export class DigestAction extends SelfAction {

execute (user: Creature, target: Creature): LogEntry {
const results = new CompositeLog(...user.containers.map(container => container.tick(60)))
return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), results)
return new CompositeLog(this.lines.run(user, target), results)
}
}

export class ReleaseAction extends PairAction {
protected lines: POVActionPicker = {
[POV.First]: {
[POV.First]: (user, target) => new LogLines(`You can't release yourself`),
[POV.Third]: (user, target) => new LogLines(`You hork up ${target.name}}`)
},
[POV.Third]: {
[POV.First]: (user, target) => new LogLines(`${user.name.capital} horks you up`),
[POV.Third]: (user, target) => new LogLines(`${user.name.capital} horks up ${target.name.capital}`)
}
}

allowed (user: Creature, target: Creature) {
if (target.containedIn === this.container) {
return super.allowed(user, target)
@@ -214,22 +293,12 @@ export class ReleaseAction extends PairAction {
}

execute (user: Creature, target: Creature): LogEntry {
const results = this.container.release(target)
return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), results)
return this.container.release(target)
}
}

export class TransferAction extends PairAction {
protected lines: POVActionPicker = {
[POV.First]: {
[POV.First]: (user, target) => new LogLines(),
[POV.Third]: (user, target) => new LogLines(`You push your prey from your ${this.from.name} to your ${this.to.name}`)
},
[POV.Third]: {
[POV.First]: (user, target) => new LogLines(`You're shoved from ${user.name}'s ${this.from.name} to their ${this.to.name}`),
[POV.Third]: (user, target) => new LogLines(`${user.name.capital} pushes ${target.name} from their ${this.from.name} to their ${this.to.name}`)
}
}
protected lines: POVPair<Entity, Entity> = new POVPair([])

allowed (user: Creature, target: Creature) {
if (target.containedIn === this.from) {
@@ -246,71 +315,6 @@ export class TransferAction extends PairAction {
execute (user: Creature, target: Creature): LogEntry {
this.from.release(target)
this.to.consume(target)
return this.lines[user.perspective][target.perspective](user, target)
}
}

export interface CombatTest {
test: (user: Creature, target: Creature) => boolean;
odds: (user: Creature, target: Creature) => number;
explain: (user: Creature, target: Creature) => LogEntry;
}

function logistic (x0: number, L: number, k: number): (x: number) => number {
return (x: number) => {
return L / (1 + Math.exp(-k * (x - x0)))
}
}

abstract class RandomTest implements CombatTest {
test (user: Creature, target: Creature): boolean {
return Math.random() < this.odds(user, target)
}

abstract odds(user: Creature, target: Creature): number
abstract explain(user: Creature, target: Creature): LogEntry
}

export class StatTest extends RandomTest {
private f: (x: number) => number

constructor (public readonly stat: Stat, k = 0.1) {
super()
this.f = logistic(0, 1, k)
}

odds (user: Creature, target: Creature): number {
return this.f(user.stats[this.stat] - target.stats[this.stat])
}

explain (user: Creature, target: Creature): LogEntry {
const delta: number = user.stats[this.stat] - target.stats[this.stat]
let result: string

if (delta === 0) {
result = 'You and the target have the same ' + this.stat + '.'
} else if (delta < 0) {
result = 'You have ' + delta + ' less ' + this.stat + ' than your foe.'
} else {
result = 'You have ' + delta + ' more ' + this.stat + ' than you foe.'
}

result += ' Your odds of success are ' + (100 * this.odds(user, target)) + '%'

return new LogLines(result)
}
}

export class ChanceTest extends RandomTest {
constructor (public readonly chance: number) {
super()
}

odds (user: Creature, target: Creature): number {
return this.chance
}

explain (user: Creature, target: Creature): LogEntry {
return new LogLines('You have a flat ' + (100 * this.chance) + '% chance.')
return this.lines.run(user, target)
}
}

+ 7
- 5
src/game/creatures/player.ts 查看文件

@@ -1,18 +1,20 @@
import { Creature, POV } from '../entity'
import { ProperNoun, TheyPronouns } from '../language'
import { Stat, Damage, AttackAction, DevourAction, DamageType } from '../combat'
import { Stomach, VoreType } from '../vore'
import { Stat, Damage, AttackAction, DamageType } from '../combat'
import { Stomach, Bowels, VoreType } from '../vore'

export class Player extends Creature {
constructor () {
super(new ProperNoun('The Dude'), TheyPronouns, { [Stat.STR]: 20, [Stat.DEX]: 20, [Stat.CON]: 20 }, new Set([VoreType.Oral]), new Set([VoreType.Oral]), 50)
super(new ProperNoun('The Dude'), TheyPronouns, { [Stat.STR]: 20, [Stat.DEX]: 20, [Stat.CON]: 20 }, new Set([VoreType.Oral]), new Set([VoreType.Oral, VoreType.Anal]), 50)

this.actions.push(new AttackAction(new Damage({ type: DamageType.Pierce, amount: 20 })))

const stomach = new Stomach(this, 100, new Damage({ amount: 10, type: DamageType.Acid }, { amount: 10, type: DamageType.Crush }))
const stomach = new Stomach(this, 100, new Damage({ amount: 100000000000, type: DamageType.Acid }, { amount: 10, type: DamageType.Crush }))

this.containers.push(stomach)
this.actions.push(new DevourAction(stomach))
const bowels = new Bowels(this, 100, new Damage({ amount: 20, type: DamageType.Crush }))

this.containers.push(bowels)
this.perspective = POV.First
}
}

+ 1
- 5
src/game/creatures/wolf.ts 查看文件

@@ -2,20 +2,16 @@ import { Creature, POV } from '../entity'
import { Stat, Damage, DamageType, AttackAction, StruggleAction, TransferAction } from '../combat'
import { MalePronouns, ImproperNoun } from '../language'
import { VoreType, Stomach, Bowels } from '../vore'
import { LogLines } from '../interface'

class BiteAction extends AttackAction {
constructor () {
super(new Damage({ amount: 10, type: DamageType.Pierce }))
this.lines[POV.First][POV.Third] = (user, target) => new LogLines('You sink your fangs into ' + target.name)
this.lines[POV.Third][POV.First] = (user, target) => new LogLines(user.name.capital + ' bites you. This bite is easily the top 1% of bites produced by ' + user.name.plural.all + '.')
this.lines[POV.Third][POV.Third] = (user, target) => new LogLines(user.name.capital + ' chomps ' + target.name)
}
}

export class Wolf extends Creature {
constructor () {
super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 10, [Stat.DEX]: 10, [Stat.CON]: 10 }, new Set([VoreType.Oral]), new Set([VoreType.Oral]), 25)
super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 10, [Stat.DEX]: 10, [Stat.CON]: 10 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral]), 25)
this.actions.push(new BiteAction())

const stomach = new Stomach(this, 50, new Damage({ amount: 50, type: DamageType.Acid }, { amount: 500, type: DamageType.Crush }))


+ 1
- 4
src/game/interface.ts 查看文件

@@ -35,9 +35,6 @@ export class CompositeLog implements LogEntry {

export function log (entry: LogEntry): void {
entry.render().forEach(elem => {
document.querySelector('#log')!.insertBefore(elem, document?.querySelector('#log > *'))
document.querySelector('#log')!.appendChild(elem)
})

const entries: Array<HTMLElement> = Array.from(document.querySelectorAll('#log > *'))
entries.slice(5).forEach(element => element.remove())
}

+ 48
- 3
src/game/language.ts 查看文件

@@ -1,7 +1,52 @@
import { Creature, POV } from './entity'
import { LogEntry } from './interface'
import { Entity, POV } from './entity'
import { LogEntry, LogLines } from './interface'

export type POVActionPicker = { [key in POV]: { [key in POV]: (user: Creature, target: Creature) => LogEntry } }
export class POVPair<K extends Entity, V extends Entity> {
run (user: K, target: V): LogEntry {
const choice = this.options.find(element => element[0][0] === user.perspective && element[0][1] === target.perspective)

if (choice === undefined) {
return new LogLines("Fen didn't write any text for this...")
} else {
return choice[1](user, target)
}
}

constructor (private options: Array<[[POV, POV], (user: K, target: V) => LogEntry]>) {

}
}

export class POVPairArgs<K extends Entity, V extends Entity, U> {
run (user: K, target: V, args: U): LogEntry {
const choice = this.options.find(element => element[0][0] === user.perspective && element[0][1] === target.perspective)

if (choice === undefined) {
return new LogLines("Fen didn't write any text for this...")
} else {
return choice[1](user, target, args)
}
}

constructor (private options: Array<[[POV, POV], (user: K, target: V, args: U) => LogEntry]>) {

}
}
export class POVSolo<K extends Entity> {
run (user: K, args: any = {}): LogEntry {
const choice = this.options.find(element => element[0][0] === user.perspective)

if (choice === undefined) {
return new LogLines("Fen didn't write any text for this...")
} else {
return choice[1](user, args)
}
}

constructor (private options: Array<[[POV], (user: K, args: any) => LogEntry]>) {

}
}

enum NounKind {
Specific,


+ 109
- 117
src/game/vore.ts 查看文件

@@ -1,7 +1,14 @@
import { Entity, Mortal, POV } from './entity'
import { Damage, Actionable, Action, DevourAction, DigestAction, ReleaseAction, StruggleAction } from './combat'
import { LogLines, LogEntry, CompositeLog } from './interface'
export enum VoreType {Oral}
import { POVSolo, POVPair, POVPairArgs } from './language'

export enum VoreType {
Oral = "Oral Vore",
Anal = "Anal Vore",
Cock = "Cock Vore",
Unbirth = "Unbirthing"
}

export interface Prey extends Mortal {
preyPrefs: Set<VoreType>;
@@ -36,6 +43,14 @@ export interface Container extends Actionable {
abstract class NormalContainer implements Container {
contents: Array<Prey>

abstract consumeLines: POVPair<Pred, Prey>
abstract releaseLines: POVPair<Pred, Prey>
abstract struggleLines: POVPair<Prey, Pred>
abstract tickLines: POVSolo<Pred>
abstract digestLines: POVPair<Pred, Prey>
abstract absorbLines: POVPair<Pred, Prey>
abstract disposeLines: POVPair<Pred, Prey>

get fullness (): number {
return Array.from(this.contents.values()).reduce((total: number, prey: Prey) => total + prey.bulk, 0)
}
@@ -53,17 +68,17 @@ abstract class NormalContainer implements Container {
consume (prey: Prey): LogEntry {
this.contents.push(prey)
prey.containedIn = this
return new LogLines('MUNCH')
return this.consumeLines.run(this.owner, prey)
}

release (prey: Prey): LogEntry {
prey.containedIn = null
this.contents = this.contents.filter(victim => victim !== prey)
return new LogLines('ANTI-MUNCH')
return this.releaseLines.run(this.owner, prey)
}

struggle (prey: Prey): LogEntry {
return new LogLines('Slosh!')
return this.struggleLines.run(prey, this.owner)
}

tick (dt: number): LogEntry {
@@ -88,7 +103,7 @@ abstract class NormalContainer implements Container {
return prey.health > -100
})

return new CompositeLog(digestedEntries, absorbedEntries)
return new CompositeLog(this.tickLines.run(this.owner), digestedEntries, absorbedEntries)
}

describe (): LogEntry {
@@ -102,15 +117,15 @@ abstract class NormalContainer implements Container {
}

digest (prey: Prey): LogEntry {
return new LogLines('Glorp!')
return this.digestLines.run(this.owner, prey)
}

absorb (prey: Prey): LogEntry {
return new LogLines('Glorp...')
return this.absorbLines.run(this.owner, prey)
}

dispose (preys: Prey[]): LogEntry {
return new LogLines('GLORP')
return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey)))
}

actions: Array<Action>
@@ -119,127 +134,104 @@ abstract class NormalContainer implements Container {
this.contents = []

this.actions = []

this.actions.push(new DevourAction(this))
this.actions.push(new DigestAction(this))
this.actions.push(new ReleaseAction(this))
this.actions.push(new StruggleAction(this))
}
}

export class Stomach extends NormalContainer {
constructor (owner: Pred, capacity: number, damage: Damage) {
super('Stomach', owner, new Set([VoreType.Oral]), capacity, damage)

this.actions.push(new DevourAction(this))
this.actions.push(new DigestAction(this))
this.actions.push(new ReleaseAction(this))
this.actions.push(new StruggleAction(this))
}

consume (prey: Prey): LogEntry {
super.consume(prey)

const predPOV = this.owner.perspective
const preyPOV = prey.perspective
if (predPOV === POV.First && preyPOV === POV.Third) {
return new LogLines(prey.name.capital + ' slides down into your stomach')
} else if (predPOV === POV.Third && preyPOV === POV.First) {
return new LogLines(this.owner.name.capital + "'s guts swell as you slush down into " + this.owner.pronouns.possessive + ' stomach')
} else if (predPOV === POV.Third && preyPOV === POV.Third) {
return new LogLines(this.owner.name.capital + "'s belly fills with the struggling form of " + prey.name)
} else {
return new LogLines('FIX ME!')
}
}

digest (prey: Prey): LogEntry {
super.digest(prey)

const predPOV = this.owner.perspective
const preyPOV = prey.perspective

if (predPOV === POV.First && preyPOV === POV.Third) {
return new LogLines('Your stomach finishes off ' + prey.name)
} else if (predPOV === POV.Third && preyPOV === POV.First) {
return new LogLines(this.owner.name.capital + ' digests you')
} else if (predPOV === POV.Third && preyPOV === POV.Third) {
return new LogLines(this.owner.name.capital + ' finishes digesting ' + prey.name)
} else {
return new LogLines('FIX ME!')
}
}

absorb (prey: Prey): LogEntry {
super.absorb(prey)

const predPOV = this.owner.perspective
const preyPOV = prey.perspective

if (predPOV === POV.First && preyPOV === POV.Third) {
return new LogLines("Your stomach melts down what's left of " + prey.name)
} else if (predPOV === POV.Third && preyPOV === POV.First) {
return new LogLines(this.owner.name.capital + ' finishes absorbing you')
} else if (predPOV === POV.Third && preyPOV === POV.Third) {
return new LogLines(this.owner.name.capital + ' fully absorbs ' + prey.name)
} else {
return new LogLines('FIX ME!')
}
}
consumeLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You devour ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} munches you`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} munches ${target.name.capital}`)]
])

releaseLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You hork up ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} horks you up`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} horks up ${target.name.capital}`)]
])

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

tickLines = new POVSolo([
[[POV.First], (user) => new LogLines(`Your stomach gurgles and churns`)],
[[POV.Third], (user) => new LogLines(`${user.name.capital}'s gut snarls and gurgles`)]
])

digestLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`Your stomach overwhelms ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s stomach finishes you off`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)]
])

absorbLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
])

disposeLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
])
}

export class Bowels extends NormalContainer {
constructor (owner: Pred, capacity: number, damage: Damage) {
super('Bowels', owner, new Set([VoreType.Oral]), capacity, damage)

this.actions.push(new DevourAction(this))
this.actions.push(new DigestAction(this))
this.actions.push(new ReleaseAction(this))
this.actions.push(new StruggleAction(this))
}

consume (prey: Prey): LogEntry {
super.consume(prey)

const predPOV = this.owner.perspective
const preyPOV = prey.perspective
if (predPOV === POV.First && preyPOV === POV.Third) {
return new LogLines(prey.name.capital + ' slides down into your bowels')
} else if (predPOV === POV.Third && preyPOV === POV.First) {
return new LogLines(this.owner.name.capital + "'s guts swell as you slush down into " + this.owner.pronouns.possessive + ' bowels')
} else if (predPOV === POV.Third && preyPOV === POV.Third) {
return new LogLines(this.owner.name.capital + "'s belly fills with the struggling form of " + prey.name)
} else {
return new LogLines('FIX ME!')
}
super('Bowels', owner, new Set([VoreType.Anal]), capacity, damage)
}

digest (prey: Prey): LogEntry {
super.digest(prey)

const predPOV = this.owner.perspective
const preyPOV = prey.perspective

if (predPOV === POV.First && preyPOV === POV.Third) {
return new LogLines('Your bowels finishes off ' + prey.name)
} else if (predPOV === POV.Third && preyPOV === POV.First) {
return new LogLines(this.owner.name.capital + ' digests you')
} else if (predPOV === POV.Third && preyPOV === POV.Third) {
return new LogLines(this.owner.name.capital + ' finishes digesting ' + prey.name)
} else {
return new LogLines('FIX ME!')
}
}

absorb (prey: Prey): LogEntry {
super.absorb(prey)

const predPOV = this.owner.perspective
const preyPOV = prey.perspective

if (predPOV === POV.First && preyPOV === POV.Third) {
return new LogLines("Your bowels melts down what's left of " + prey.name)
} else if (predPOV === POV.Third && preyPOV === POV.First) {
return new LogLines(this.owner.name.capital + ' finishes absorbing you')
} else if (predPOV === POV.Third && preyPOV === POV.Third) {
return new LogLines(this.owner.name.capital + ' fully absorbs ' + prey.name)
} else {
return new LogLines('FIX ME!')
}
}
consumeLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You devour ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} munches you`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} munches ${target.name.capital}`)]
])

releaseLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You hork up ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} horks you up`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} horks up ${target.name.capital}`)]
])

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

tickLines = new POVSolo([
[[POV.First], (user) => new LogLines(`Your stomach gurgles and churns!`)],
[[POV.Third], (user) => new LogLines(`${user.name.capital}'s gut snarls and gurgles`)]
])

digestLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`Your stomach overwhelms ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s stomach finishes you off`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)]
])

absorbLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
])

disposeLines = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`Your guts completely absorb ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital}'s guts soak you up like water in a sponge`)],
[[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} finishes absorbing the remains of ${target.name}`)]
])
}

正在加载...
取消
保存