Containers can now offer actions to their contents.vintage
| @@ -15,6 +15,7 @@ module.exports = { | |||
| 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', | |||
| 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', | |||
| 'no-useless-constructor': 'off', | |||
| '@typescript-eslint/no-unused-vars': 'off' | |||
| '@typescript-eslint/no-unused-vars': 'off', | |||
| 'quotes': 'off' | |||
| } | |||
| } | |||
| @@ -4,7 +4,8 @@ | |||
| <meta charset="utf-8"> | |||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
| <meta name="viewport" content="width=device-width,initial-scale=1.0"> | |||
| <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |||
| <link rel="icon" href="https://crux.sexy/images/feast.ico"> | |||
| <link rel="stylesheet" href="./reset.css"</link> | |||
| <title><%= htmlWebpackPlugin.options.title %></title> | |||
| </head> | |||
| <body> | |||
| @@ -0,0 +1,48 @@ | |||
| /* http://meyerweb.com/eric/tools/css/reset/ | |||
| v2.0 | 20110126 | |||
| License: none (public domain) | |||
| */ | |||
| html, body, div, span, applet, object, iframe, | |||
| h1, h2, h3, h4, h5, h6, p, blockquote, pre, | |||
| a, abbr, acronym, address, big, cite, code, | |||
| del, dfn, em, img, ins, kbd, q, s, samp, | |||
| small, strike, strong, sub, sup, tt, var, | |||
| b, u, i, center, | |||
| dl, dt, dd, ol, ul, li, | |||
| fieldset, form, label, legend, | |||
| table, caption, tbody, tfoot, thead, tr, th, td, | |||
| article, aside, canvas, details, embed, | |||
| figure, figcaption, footer, header, hgroup, | |||
| menu, nav, output, ruby, section, summary, | |||
| time, mark, audio, video { | |||
| margin: 0; | |||
| padding: 0; | |||
| border: 0; | |||
| font-size: 100%; | |||
| font: inherit; | |||
| vertical-align: baseline; | |||
| } | |||
| /* HTML5 display-role reset for older browsers */ | |||
| article, aside, details, figcaption, figure, | |||
| footer, header, hgroup, menu, nav, section { | |||
| display: block; | |||
| } | |||
| body { | |||
| line-height: 1; | |||
| } | |||
| ol, ul { | |||
| list-style: none; | |||
| } | |||
| blockquote, q { | |||
| quotes: none; | |||
| } | |||
| blockquote:before, blockquote:after, | |||
| q:before, q:after { | |||
| content: ''; | |||
| content: none; | |||
| } | |||
| table { | |||
| border-collapse: collapse; | |||
| border-spacing: 0; | |||
| } | |||
| @@ -1,9 +1,6 @@ | |||
| <template> | |||
| <div id="app"> | |||
| <div> | |||
| This is the (extremely early alpha of the) new Feast. If you're looking for the old version, <a href="https://classic.feast.crux.sexy">go here!</a> | |||
| </div> | |||
| <img alt="Feast logo" id="logo" src="./assets/feast.png"> | |||
| <Header version="pre-alpha" /> | |||
| <Combat :player="player" :enemy="enemy" /> | |||
| </div> | |||
| </template> | |||
| @@ -11,12 +8,13 @@ | |||
| <script lang="ts"> | |||
| import { Component, Vue } from 'vue-property-decorator' | |||
| import Combat from './components/Combat.vue' | |||
| import Header from './components/Header.vue' | |||
| import * as Creatures from '@/game/creatures' | |||
| import { Creature, POV } from '@/game/entity' | |||
| @Component({ | |||
| components: { | |||
| Combat | |||
| Combat, Header | |||
| } | |||
| }) | |||
| export default class App extends Vue { | |||
| @@ -28,6 +26,7 @@ export default class App extends Vue { | |||
| this.player.perspective = POV.First | |||
| this.enemy = new Creatures.Wolf() | |||
| console.log(this.player) | |||
| console.log(this.enemy) | |||
| } | |||
| } | |||
| </script> | |||
| @@ -35,6 +34,8 @@ export default class App extends Vue { | |||
| <style> | |||
| body, html { | |||
| background: #111; | |||
| width: 100vw; | |||
| height: 100vh; | |||
| } | |||
| #app { | |||
| @@ -44,9 +45,5 @@ body, html { | |||
| text-align: center; | |||
| color: #ddd; | |||
| background: #111; | |||
| margin-top: 60px; | |||
| } | |||
| #logo { | |||
| width: 30vw; | |||
| } | |||
| </style> | |||
| @@ -8,14 +8,14 @@ | |||
| <div class="horiz-display"> | |||
| <div> | |||
| <h2>Your moves</h2> | |||
| <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 @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> | |||
| <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>{{actionDescription}}</div> | |||
| </div> | |||
| <div> | |||
| <h2>Enemy moves</h2> | |||
| <button v-for="action in enemy.validActions(player)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, player))">{{action.name}}</button> | |||
| <button v-for="action in enemy.validActions(enemy)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, enemy))">{{action.name}}</button> | |||
| <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> | |||
| @@ -71,4 +71,8 @@ a { | |||
| display: flex; | |||
| justify-content: center; | |||
| } | |||
| .combat-button { | |||
| width: 100px; | |||
| height: 100px; | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,29 @@ | |||
| <template> | |||
| <div id="header"> | |||
| <div> | |||
| This is the (extremely early alpha of the) new Feast. If you're looking for the old version, <a href="https://classic.feast.crux.sexy">go here!</a> | |||
| </div> | |||
| <div>Version: {{version}}</div> | |||
| </div> | |||
| </template> | |||
| <script lang="ts"> | |||
| import { Component, Vue, Prop } from 'vue-property-decorator' | |||
| @Component({}) | |||
| export default class Header extends Vue { | |||
| @Prop() version!: string | |||
| } | |||
| </script> | |||
| <style scoped> | |||
| #header { | |||
| width: 100%; | |||
| background: #222; | |||
| top: 0%; | |||
| padding-top: 32pt; | |||
| padding-bottom: 32pt; | |||
| } | |||
| </style> | |||
| @@ -39,46 +39,42 @@ export enum Stat { | |||
| export type Stats = {[key in Stat]: number} | |||
| export enum State { | |||
| Normal = 'Normal', | |||
| Grappled = 'Grappled', | |||
| Grappling = 'Grappling', | |||
| Eaten = 'Eaten' | |||
| } | |||
| export interface Combatant { | |||
| actions: Array<Action>; | |||
| } | |||
| export abstract class Action { | |||
| allowed (user: Creature, target: Creature) { | |||
| return this.userStates.has(user.state) && this.targetStates.has(target.state) | |||
| } | |||
| abstract allowed (user: Creature, target: Creature): boolean | |||
| abstract execute(user: Creature, target: Creature): LogEntry | |||
| abstract execute(user: Creature, target: Creature): LogEntry | |||
| constructor (public name: string, public desc: string) { | |||
| constructor (public name: string, public desc: string, public userStates: Set<State>, public targetStates: Set<State>) { | |||
| } | |||
| } | |||
| toString (): string { | |||
| return this.name | |||
| } | |||
| } | |||
| toString (): string { | |||
| return this.name | |||
| } | |||
| export interface Actionable { | |||
| actions: Array<Action>; | |||
| } | |||
| abstract class SelfAction extends Action { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user === target) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| return user === target | |||
| } | |||
| } | |||
| abstract class PairAction extends Action { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user !== target) { | |||
| return user !== target | |||
| } | |||
| } | |||
| abstract class TogetherAction extends PairAction { | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user.containedIn === target.containedIn) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| @@ -86,7 +82,7 @@ abstract class PairAction extends Action { | |||
| } | |||
| } | |||
| export class AttackAction extends PairAction { | |||
| export class AttackAction extends TogetherAction { | |||
| protected lines: POVActionPicker = { | |||
| [POV.First]: { | |||
| [POV.First]: (user, target) => new LogLines('You bite...yourself?'), | |||
| @@ -99,7 +95,7 @@ export class AttackAction extends PairAction { | |||
| } | |||
| constructor (protected damage: Damage) { | |||
| super('Attack', 'Attack the enemy', new Set([State.Normal]), new Set([State.Normal])) | |||
| super('Attack', 'Attack the enemy') | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| @@ -108,7 +104,7 @@ export class AttackAction extends PairAction { | |||
| } | |||
| } | |||
| export class DevourAction extends PairAction { | |||
| export class DevourAction extends TogetherAction { | |||
| protected lines: POVActionPicker = { | |||
| [POV.First]: { | |||
| [POV.First]: (user, target) => new LogLines('You devour...yourself?'), | |||
| @@ -121,11 +117,11 @@ export class DevourAction extends PairAction { | |||
| } | |||
| constructor (protected container: Container) { | |||
| super('Devour', 'Try to consume your foe', new Set([State.Normal]), new Set([State.Normal])) | |||
| super('Devour', 'Try to consume your foe') | |||
| this.name += ` (${container.name})` | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| target.state = State.Eaten | |||
| return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), this.container.consume(target)) | |||
| } | |||
| } | |||
| @@ -142,48 +138,116 @@ export class StruggleAction extends PairAction { | |||
| } | |||
| } | |||
| constructor () { | |||
| super('Struggle', 'Try to escape your predator', new Set([State.Eaten]), new Set([State.Normal])) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user.containedIn === this.container) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (public container: Container) { | |||
| super('Struggle', 'Try to escape your predator') | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| if (user.containedIn) { | |||
| user.state = State.Normal | |||
| 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...") } | |||
| } | |||
| } | |||
| 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: 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.') | |||
| } | |||
| } | |||
| allowed (user: Creature, target: Creature) { | |||
| if (user.containers.some(container => { | |||
| return container.contents.length > 0 | |||
| })) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| allowed (user: Creature, target: Creature) { | |||
| if (this.container.owner === user && this.container.contents.length > 0) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super('Digest', 'Digest all of your current prey') | |||
| this.name += ` (${container.name})` | |||
| } | |||
| 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) | |||
| } | |||
| } | |||
| constructor () { | |||
| super('Digest', 'Digest all of your current prey', new Set([State.Normal]), new Set([State.Normal])) | |||
| 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}`) | |||
| } | |||
| } | |||
| 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) | |||
| allowed (user: Creature, target: Creature) { | |||
| if (target.containedIn === this.container) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected container: Container) { | |||
| super('Release', 'Release one of your prey') | |||
| this.name += ` (${container.name})` | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| const results = this.container.release(target) | |||
| return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), results) | |||
| } | |||
| } | |||
| 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}`) | |||
| } | |||
| } | |||
| allowed (user: Creature, target: Creature) { | |||
| if (target.containedIn === this.from) { | |||
| return super.allowed(user, target) | |||
| } else { | |||
| return false | |||
| } | |||
| } | |||
| constructor (protected from: Container, protected to: Container) { | |||
| super('Transfer', `Shove your prey from your ${from.name} to your ${to.name}`) | |||
| } | |||
| 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 { | |||
| @@ -1,7 +1,7 @@ | |||
| import { Creature, POV } from '../entity' | |||
| import { Stat, Damage, DamageType, AttackAction, DevourAction, StruggleAction, DigestAction } from '../combat' | |||
| import { Stat, Damage, DamageType, AttackAction, StruggleAction, TransferAction } from '../combat' | |||
| import { MalePronouns, ImproperNoun } from '../language' | |||
| import { VoreType, Stomach } from '../vore' | |||
| import { VoreType, Stomach, Bowels } from '../vore' | |||
| import { LogLines } from '../interface' | |||
| class BiteAction extends AttackAction { | |||
| @@ -21,8 +21,10 @@ export class Wolf extends Creature { | |||
| const stomach = new Stomach(this, 50, new Damage({ amount: 50, type: DamageType.Acid }, { amount: 500, type: DamageType.Crush })) | |||
| this.containers.push(stomach) | |||
| this.actions.push(new DevourAction(stomach)) | |||
| this.actions.push(new StruggleAction()) | |||
| this.actions.push(new DigestAction()) | |||
| const bowels = new Bowels(this, 50, new Damage({ amount: 50, type: DamageType.Acid }, { amount: 500, type: DamageType.Crush })) | |||
| this.containers.push(bowels) | |||
| this.actions.push(new TransferAction(bowels, stomach)) | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| import { DamageType, Damage, Combatant, Stats, State, Action } from './combat' | |||
| import { DamageType, Damage, Combatant, Stats, Action } from './combat' | |||
| import { Noun, Pronoun } from './language' | |||
| import { Pred, Prey, Container, VoreType } from './vore' | |||
| @@ -24,7 +24,6 @@ export class Creature implements Mortal, Pred, Prey, Combatant { | |||
| maxHealth = 100 | |||
| resistances: Map<DamageType, number> = new Map() | |||
| perspective: POV = POV.Third | |||
| state: State = State.Normal | |||
| containers: Array<Container> = [] | |||
| actions: Array<Action> = []; | |||
| private baseBulk: number; | |||
| @@ -55,7 +54,12 @@ export class Creature implements Mortal, Pred, Prey, Combatant { | |||
| } | |||
| validActions (target: Creature): Array<Action> { | |||
| return this.actions.filter(action => { | |||
| let choices = this.actions.concat(this.containers.flatMap(container => container.actions)) | |||
| if (this.containedIn !== null) { | |||
| choices = choices.concat(this.containedIn.actions) | |||
| } | |||
| return choices.filter(action => { | |||
| return action.allowed(this, target) | |||
| }) | |||
| } | |||
| @@ -1,7 +1,6 @@ | |||
| import { Entity, Mortal, POV } from './entity' | |||
| import { Damage } from './combat' | |||
| import { Damage, Actionable, Action, DevourAction, DigestAction, ReleaseAction, StruggleAction } from './combat' | |||
| import { LogLines, LogEntry, CompositeLog } from './interface' | |||
| import { ProperNoun } from './language' | |||
| export enum VoreType {Oral} | |||
| export interface Prey extends Mortal { | |||
| @@ -15,21 +14,23 @@ export interface Pred extends Entity { | |||
| containers: Array<Container>; | |||
| } | |||
| export interface Container { | |||
| name: string; | |||
| voreTypes: Set<VoreType>; | |||
| contents: Array<Prey>; | |||
| capacity: number; | |||
| fullness: number; | |||
| canTake: (prey: Prey) => boolean; | |||
| consume: (prey: Prey) => LogEntry; | |||
| release: (prey: Prey) => LogEntry; | |||
| struggle: (prey: Prey) => LogEntry; | |||
| tick: (dt: number) => LogEntry; | |||
| describe: () => LogEntry; | |||
| digest: (prey: Prey) => LogEntry; | |||
| absorb: (prey: Prey) => LogEntry; | |||
| dispose: (preys: Prey[]) => LogEntry; | |||
| export interface Container extends Actionable { | |||
| name: string; | |||
| owner: Pred; | |||
| voreTypes: Set<VoreType>; | |||
| contents: Array<Prey>; | |||
| capacity: number; | |||
| fullness: number; | |||
| canTake: (prey: Prey) => boolean; | |||
| consume: (prey: Prey) => LogEntry; | |||
| release: (prey: Prey) => LogEntry; | |||
| struggle: (prey: Prey) => LogEntry; | |||
| tick: (dt: number) => LogEntry; | |||
| describe: () => LogEntry; | |||
| digest: (prey: Prey) => LogEntry; | |||
| absorb: (prey: Prey) => LogEntry; | |||
| dispose: (preys: Prey[]) => LogEntry; | |||
| actions: Array<Action>; | |||
| } | |||
| abstract class NormalContainer implements Container { | |||
| @@ -112,14 +113,23 @@ abstract class NormalContainer implements Container { | |||
| return new LogLines('GLORP') | |||
| } | |||
| constructor (public name: string, protected owner: Pred, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | |||
| actions: Array<Action> | |||
| constructor (public name: string, public owner: Pred, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | |||
| this.contents = [] | |||
| this.actions = [] | |||
| } | |||
| } | |||
| 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 { | |||
| @@ -172,3 +182,64 @@ export class Stomach extends NormalContainer { | |||
| } | |||
| } | |||
| } | |||
| 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!') | |||
| } | |||
| } | |||
| 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!') | |||
| } | |||
| } | |||
| } | |||