| @@ -0,0 +1 @@ | |||||
| *.webp filter=lfs diff=lfs merge=lfs -text | |||||
| oid sha256:1f33bba6327c0a75e40d3e67a1c757421acde2d826ce3de05f397ab4c80fd039 | |||||
| size 39712 |
| oid sha256:9af601f92ecf19fbef987599e4fbba7162be7fe24cc1fa809ca1d8dbb57091b8 | |||||
| size 43650 |
| oid sha256:e29868efd8a6fb854ab3a3c0381dcdd1f9677e7f446183e4f9b4360cc997bbca | |||||
| size 26554 |
| oid sha256:cc9e319a2319b4ae676650a4cec84ceb5a70a76ebe92c222f6d0722aff9a6214 | |||||
| size 29310 |
| @@ -11,6 +11,7 @@ import Combat from './components/Combat.vue' | |||||
| import Header from './components/Header.vue' | import Header from './components/Header.vue' | ||||
| import * as Creatures from '@/game/creatures' | import * as Creatures from '@/game/creatures' | ||||
| import { Creature, POV } from '@/game/entity' | import { Creature, POV } from '@/game/entity' | ||||
| import { ProperNoun } from '@/game/language' | |||||
| @Component({ | @Component({ | ||||
| components: { | components: { | ||||
| @@ -22,8 +23,9 @@ export default class App extends Vue { | |||||
| enemy: Creature | enemy: Creature | ||||
| constructor () { | constructor () { | ||||
| super() | super() | ||||
| this.player = new Creatures.Player() | |||||
| this.enemy = new Creatures.Wolf() | |||||
| this.player = new Creatures.Wolf() | |||||
| this.enemy = new Creatures.Cafat() | |||||
| this.player.perspective = POV.First | |||||
| console.log(this.player) | console.log(this.player) | ||||
| console.log(this.enemy) | console.log(this.enemy) | ||||
| } | } | ||||
| @@ -174,6 +174,10 @@ div.enemy-move { | |||||
| margin-right: 5%; | margin-right: 5%; | ||||
| } | } | ||||
| #log img { | |||||
| width: 75%; | |||||
| } | |||||
| #log > div.enemy-move:nth-last-child(7) { | #log > div.enemy-move:nth-last-child(7) { | ||||
| color: #988; | color: #988; | ||||
| } | } | ||||
| @@ -8,7 +8,7 @@ | |||||
| <br> | <br> | ||||
| <div class="stat-line" v-for="stat in Object.keys(subject.stats)" v-bind:key="stat"><i :class="statIcons[stat]" />: {{subject.stats[stat]}}</div> | <div class="stat-line" v-for="stat in Object.keys(subject.stats)" v-bind:key="stat"><i :class="statIcons[stat]" />: {{subject.stats[stat]}}</div> | ||||
| <div>Status: {{subject.status}}</div> | <div>Status: {{subject.status}}</div> | ||||
| <ContainerView v-for="container in subject.containers" :key="container.name" :container="container" /> | |||||
| <ContainerView v-for="container in subject.containers" :key="container.name.toString()" :container="container" /> | |||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -1,5 +1,5 @@ | |||||
| import { Creature, POV, Entity } from './entity' | import { Creature, POV, Entity } from './entity' | ||||
| import { POVPair, POVPairArgs } from './language' | |||||
| import { POVPair, POVPairArgs, TextLike, DynText, LiveText } from './language' | |||||
| import { Container } from './vore' | import { Container } from './vore' | ||||
| import { LogEntry, LogLines, CompositeLog, FAElem, LogLine, FormatEntry, FormatOpt } from './interface' | import { LogEntry, LogLines, CompositeLog, FAElem, LogLine, FormatEntry, FormatOpt } from './interface' | ||||
| @@ -213,12 +213,12 @@ export abstract class Action { | |||||
| abstract execute(user: Creature, target: Creature): LogEntry | abstract execute(user: Creature, target: Creature): LogEntry | ||||
| constructor (public name: string, public desc: string, private conditions: Array<Condition> = []) { | |||||
| constructor (public name: TextLike, public desc: string, private conditions: Array<Condition> = []) { | |||||
| } | } | ||||
| toString (): string { | toString (): string { | ||||
| return this.name | |||||
| return this.name.toString() | |||||
| } | } | ||||
| } | } | ||||
| @@ -306,7 +306,7 @@ export class AttackAction extends TogetherAction { | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | 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.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.First], (user, target) => new LogLines(`${user.name.capital} misses you`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} misses ${target.name}`)] | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} misses ${target.name}`)] | |||||
| ]) | ]) | ||||
| constructor (protected damage: Damage) { | constructor (protected damage: Damage) { | ||||
| @@ -330,7 +330,7 @@ export class DevourAction extends TogetherAction { | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | 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.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.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}`)] | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} unsuccessfully tries to swallow ${target.name}`)] | |||||
| ]) | ]) | ||||
| allowed (user: Creature, target: Creature): boolean { | allowed (user: Creature, target: Creature): boolean { | ||||
| @@ -346,8 +346,7 @@ export class DevourAction extends TogetherAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super('Devour', 'Try to consume your foe', [new CapableCondition()]) | |||||
| this.name += ` (${container.name})` | |||||
| super(new DynText('Devour (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()]) | |||||
| this.test = new StatVigorTest(Stat.STR) | this.test = new StatVigorTest(Stat.STR) | ||||
| } | } | ||||
| @@ -366,7 +365,7 @@ export class FeedAction extends TogetherAction { | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to feed yourself to ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to feed yourself to ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to feed ${user.pronouns.possessive} to you, but fails`)], | [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to feed ${user.pronouns.possessive} to you, but fails`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} unsuccessfully tries to feed ${user.pronouns.possessive} to ${target.name}`)] | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} unsuccessfully tries to feed ${user.pronouns.possessive} to ${target.name}`)] | |||||
| ]) | ]) | ||||
| allowed (user: Creature, target: Creature): boolean { | allowed (user: Creature, target: Creature): boolean { | ||||
| @@ -402,7 +401,7 @@ export class StruggleAction extends PairAction { | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to escape from ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLines(`You fail to escape from ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to escape from you, but fails`)], | [[POV.Third, POV.First], (user, target) => new LogLines(`${user.name.capital} tries to escape from you, but fails`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${target.name} unsuccessfully struggles within ${target.name}`)] | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} unsuccessfully struggles within ${target.name}`)] | |||||
| ]) | ]) | ||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| @@ -414,7 +413,7 @@ export class StruggleAction extends PairAction { | |||||
| } | } | ||||
| constructor (public container: Container) { | constructor (public container: Container) { | ||||
| super('Struggle', 'Try to escape your predator', [new CapableCondition()]) | |||||
| super(new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), 'Try to escape from your foe', [new CapableCondition()]) | |||||
| this.test = new StatVigorTest(Stat.STR) | this.test = new StatVigorTest(Stat.STR) | ||||
| } | } | ||||
| @@ -431,6 +430,21 @@ export class StruggleAction extends PairAction { | |||||
| } | } | ||||
| } | } | ||||
| export abstract class EatenAction extends PairAction { | |||||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | |||||
| 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), ')'), 'Do something to your prey!', [new CapableCondition()]) | |||||
| } | |||||
| } | |||||
| export class DigestAction extends SelfAction { | export class DigestAction extends SelfAction { | ||||
| protected lines: POVPair<Entity, Entity> = new POVPair([]) | protected lines: POVPair<Entity, Entity> = new POVPair([]) | ||||
| @@ -443,8 +457,7 @@ export class DigestAction extends SelfAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super('Digest', 'Digest all of your current prey', [new CapableCondition()]) | |||||
| this.name += ` (${container.name})` | |||||
| super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()]) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -463,8 +476,7 @@ export class ReleaseAction extends PairAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super('Release', 'Release one of your prey') | |||||
| this.name += ` (${container.name})` | |||||
| super(new DynText('Release (', new LiveText(container, x => x.name.all), ')'), 'Release one of your prey', [new CapableCondition()]) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -473,9 +485,9 @@ export class ReleaseAction extends PairAction { | |||||
| } | } | ||||
| export class TransferAction extends PairAction { | export class TransferAction extends PairAction { | ||||
| protected lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | |||||
| lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | |||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | ||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${target.pronouns.possessive} ${args.to.name}`)], | |||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)], | |||||
| [[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} to ${user.pronouns.possessive} ${args.to.name}`)] | ||||
| ]) | ]) | ||||
| @@ -1,4 +1,5 @@ | |||||
| import { Wolf } from './creatures/wolf' | import { Wolf } from './creatures/wolf' | ||||
| import { Player } from './creatures/player' | import { Player } from './creatures/player' | ||||
| import { Cafat } from './creatures/cafat' | |||||
| export { Wolf, Player } | |||||
| export { Wolf, Player, Cafat } | |||||
| @@ -0,0 +1,103 @@ | |||||
| import { Creature, POV, Entity } from '../entity' | |||||
| import { Stat, Damage, DamageType, TransferAction, Vigor, StatTest, FeedAction, DigestAction, EatenAction, AttackAction } from '../combat' | |||||
| import { ProperNoun, TheyPronouns, ImproperNoun, POVPair, FemalePronouns, POVPairArgs } from '../language' | |||||
| import { VoreType, Stomach, InnerStomach, Container } from '../vore' | |||||
| import { LogLine, LogLines, LogEntry, FAElem, CompositeLog, ImgElem } from '../interface' | |||||
| class BelchAction extends AttackAction { | |||||
| successLines = new POVPairArgs<Entity, Entity, { damage: Damage }>([ | |||||
| [[POV.First, POV.Third], (user, target, args) => new CompositeLog(new LogLine( | |||||
| `You belch on ${target.name} for `, | |||||
| args.damage.renderShort() | |||||
| ), new ImgElem('./media/cafat/images/belch.webp'))], | |||||
| [[POV.Third, POV.First], (user, target, args) => new CompositeLog(new LogLine( | |||||
| `${user.name.capital} belches on you for `, | |||||
| args.damage.renderShort() | |||||
| ), new ImgElem('./media/cafat/images/belch.webp'))], | |||||
| [[POV.Third, POV.Third], (user, target, args) => new CompositeLog(new LogLine( | |||||
| `${user.name.capital} belches on ${target.name} for `, | |||||
| args.damage.renderShort() | |||||
| ), new ImgElem('./media/cafat/images/belch.webp'))] | |||||
| ]) | |||||
| constructor (damage: Damage) { | |||||
| super(damage) | |||||
| this.name = 'Belch' | |||||
| } | |||||
| } | |||||
| class CrushAction extends EatenAction { | |||||
| lines: POVPair<Entity, Entity> = new POVPair([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You crush ${target.name} `, new FAElem('fas fa-skull'))], | |||||
| [[POV.Third, POV.First], (user, target) => new CompositeLog(new LogLine(`${user.name.capital} crushes you; ${user.pronouns.subjective} belches as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `, new FAElem('fas fa-skull')), new ImgElem('./media/cafat/images/crunch.webp'))], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} crushes ${target.name}; ${user.pronouns.subjective} belches as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `, new FAElem('fas fa-skull'))] | |||||
| ]) | |||||
| private damage: Damage = new Damage( | |||||
| { amount: 99, type: DamageType.Crush, target: Vigor.Health } | |||||
| ) | |||||
| constructor (container: Container) { | |||||
| super(container, "Crush", "Crush 'em!") | |||||
| } | |||||
| execute (user: Creature, target: Creature): LogEntry { | |||||
| target.takeDamage(this.damage) | |||||
| return this.lines.run(user, target) | |||||
| } | |||||
| } | |||||
| export class Cafat extends Creature { | |||||
| constructor () { | |||||
| super(new ProperNoun('Cafat'), [TheyPronouns, FemalePronouns][Math.floor(Math.random() * 2)], { [Stat.STR]: 30, [Stat.DEX]: 15, [Stat.CON]: 25 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 150) | |||||
| this.vigors.Health = 200 | |||||
| this.maxVigors.Health = 200 | |||||
| this.vigors.Stamina = 250 | |||||
| this.maxVigors.Stamina = 250 | |||||
| this.vigors.Willpower = 150 | |||||
| this.maxVigors.Willpower = 150 | |||||
| const stomach = new Stomach(this, 100, new Damage( | |||||
| { amount: 20, type: DamageType.Acid, target: Vigor.Health }, | |||||
| { amount: 10, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 10, type: DamageType.Dominance, target: Vigor.Willpower } | |||||
| )) | |||||
| stomach.name = new ImproperNoun("upper stomach", "upper stomachs").all | |||||
| this.containers.push(stomach) | |||||
| const lowerStomach = new InnerStomach(this, 100, new Damage( | |||||
| { amount: 40, type: DamageType.Acid, target: Vigor.Health }, | |||||
| { amount: 20, type: DamageType.Crush, target: Vigor.Stamina }, | |||||
| { amount: 20, type: DamageType.Dominance, target: Vigor.Willpower } | |||||
| ), stomach) | |||||
| lowerStomach.name = new ImproperNoun("lower stomach", "lower stomachs").all | |||||
| stomach.consumeLines = new POVPair([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLines(`You devour ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new CompositeLog(new LogLines(`${user.name.capital} devours you`), new ImgElem('./media/cafat/images/stomach.webp'))], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} munches ${target.name.capital}`)] | |||||
| ]) | |||||
| const crush = new CrushAction(lowerStomach) | |||||
| lowerStomach.actions.push(crush) | |||||
| this.containers.push(lowerStomach) | |||||
| const transfer = new TransferAction(stomach, lowerStomach) | |||||
| transfer.lines = 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 CompositeLog(new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`), new ImgElem('./media/cafat/images/lower-stomach.webp'))], | |||||
| [[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}`)] | |||||
| ]) | |||||
| this.actions.push(transfer) | |||||
| this.actions.push(new TransferAction(lowerStomach, stomach)) | |||||
| this.actions.push(new BelchAction(new Damage( | |||||
| { amount: 100, target: Vigor.Willpower, type: DamageType.Acid } | |||||
| ))) | |||||
| this.otherActions.push(new FeedAction(stomach)) | |||||
| } | |||||
| } | |||||
| @@ -1,16 +0,0 @@ | |||||
| import { Wolf } from './creatures/wolf' | |||||
| import { POV } from './entity' | |||||
| import { CompositeLog, LogLines, log } from './interface' | |||||
| const wolf = new Wolf() | |||||
| const player = new Wolf() | |||||
| player.perspective = POV.First | |||||
| log(new CompositeLog(...player.validActions(wolf).map(action => new LogLines(action.toString())))) | |||||
| log(new CompositeLog(...player.validActions(player).map(action => new LogLines(action.toString())))) | |||||
| log(player.actions[1].execute(player, wolf)) | |||||
| log(new CompositeLog(...player.validActions(wolf).map(action => new LogLines(action.toString())))) | |||||
| log(new CompositeLog(...player.validActions(player).map(action => new LogLines(action.toString())))) | |||||
| @@ -92,6 +92,18 @@ export class FAElem implements LogEntry { | |||||
| } | } | ||||
| } | } | ||||
| export class ImgElem implements LogEntry { | |||||
| constructor (private url: string) { | |||||
| } | |||||
| render (): HTMLElement[] { | |||||
| const img = document.createElement("img") | |||||
| img.src = this.url | |||||
| return [img] | |||||
| } | |||||
| } | |||||
| export class CompositeLog implements LogEntry { | export class CompositeLog implements LogEntry { | ||||
| entries: LogEntry[] | entries: LogEntry[] | ||||
| @@ -69,6 +69,29 @@ interface WordOptions { | |||||
| count: boolean; | count: boolean; | ||||
| } | } | ||||
| export type TextLike = { toString: () => string } | |||||
| // updates as needed | |||||
| export class LiveText<T> { | |||||
| toString (): string { | |||||
| return this.run(this.contents).toString() | |||||
| } | |||||
| constructor (private contents: T, private run: (thing: T) => TextLike) { | |||||
| } | |||||
| } | |||||
| export class DynText { | |||||
| private parts: Array<TextLike> | |||||
| constructor (...parts: TextLike[]) { | |||||
| this.parts = parts | |||||
| } | |||||
| toString (): string { | |||||
| return (this.parts.map(part => part.toString())).join('') | |||||
| } | |||||
| } | |||||
| export class Noun { | export class Noun { | ||||
| constructor (private singularNoun: string, private pluralNoun: string|null = null, private options: WordOptions = { plural: false, capital: false, proper: false, kind: NounKind.Specific, vowel: VowelSound.Default, count: true }) { | constructor (private singularNoun: string, private pluralNoun: string|null = null, private options: WordOptions = { plural: false, capital: false, proper: false, kind: NounKind.Specific, vowel: VowelSound.Default, count: true }) { | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { Entity, Mortal, POV } from './entity' | import { Entity, Mortal, POV } from './entity' | ||||
| import { Damage, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat' | import { Damage, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat' | ||||
| import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | ||||
| import { POVSolo, POVPair, POVPairArgs } from './language' | |||||
| import { Noun, POVPair, POVPairArgs, ImproperNoun } from './language' | |||||
| export enum VoreType { | export enum VoreType { | ||||
| Oral = "Oral Vore", | Oral = "Oral Vore", | ||||
| @@ -22,7 +22,7 @@ export interface Pred extends Entity { | |||||
| } | } | ||||
| export interface Container extends Actionable { | export interface Container extends Actionable { | ||||
| name: string; | |||||
| name: Noun; | |||||
| owner: Pred; | owner: Pred; | ||||
| voreTypes: Set<VoreType>; | voreTypes: Set<VoreType>; | ||||
| contents: Array<Prey>; | contents: Array<Prey>; | ||||
| @@ -136,11 +136,13 @@ abstract class NormalContainer implements Container { | |||||
| actions: Array<Action> | actions: Array<Action> | ||||
| constructor (public name: string, public owner: Pred, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | |||||
| constructor (public name: Noun, public owner: Pred, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | |||||
| this.contents = [] | this.contents = [] | ||||
| this.actions = [] | this.actions = [] | ||||
| this.name = name | |||||
| this.actions.push(new DevourAction(this)) | this.actions.push(new DevourAction(this)) | ||||
| this.actions.push(new DigestAction(this)) | this.actions.push(new DigestAction(this)) | ||||
| this.actions.push(new ReleaseAction(this)) | this.actions.push(new ReleaseAction(this)) | ||||
| @@ -148,9 +150,74 @@ abstract class NormalContainer implements Container { | |||||
| } | } | ||||
| } | } | ||||
| abstract class InnerContainer extends NormalContainer { | |||||
| release (prey: Prey): LogEntry { | |||||
| prey.containedIn = this.escape | |||||
| this.contents = this.contents.filter(victim => victim !== prey) | |||||
| return this.releaseLines.run(this.owner, prey) | |||||
| } | |||||
| constructor (name: Noun, owner: Pred, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: Container) { | |||||
| super(name, owner, voreTypes, capacity, damage) | |||||
| this.actions = [] | |||||
| this.actions.push(new DigestAction(this)) | |||||
| this.actions.push(new StruggleAction(this)) | |||||
| } | |||||
| } | |||||
| export class Stomach extends NormalContainer { | export class Stomach extends NormalContainer { | ||||
| constructor (owner: Pred, capacity: number, damage: Damage) { | constructor (owner: Pred, capacity: number, damage: Damage) { | ||||
| super('Stomach', owner, new Set([VoreType.Oral]), capacity, damage) | |||||
| super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage) | |||||
| } | |||||
| 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}`)] | |||||
| ]) | |||||
| 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}`)] | |||||
| ]) | |||||
| 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 POVPairArgs<Pred, Prey, { damage: Damage }>([ | |||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())], | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | |||||
| ]) | |||||
| 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 InnerStomach extends InnerContainer { | |||||
| constructor (owner: Pred, capacity: number, damage: Damage, escape: Container) { | |||||
| super(new ImproperNoun('inner stomach', 'inner stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage, escape) | |||||
| } | } | ||||
| consumeLines = new POVPair([ | consumeLines = new POVPair([ | ||||
| @@ -174,7 +241,7 @@ export class Stomach extends NormalContainer { | |||||
| tickLines = new POVPairArgs<Pred, Prey, { damage: Damage }>([ | tickLines = new POVPairArgs<Pred, Prey, { damage: Damage }>([ | ||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())], | [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())], | ||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())], | [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())], | ||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${target.name.capital} churns ${user.name} for `, args.damage.renderShort())] | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | |||||
| ]) | ]) | ||||
| digestLines = new POVPair([ | digestLines = new POVPair([ | ||||
| @@ -198,7 +265,7 @@ export class Stomach extends NormalContainer { | |||||
| export class Bowels extends NormalContainer { | export class Bowels extends NormalContainer { | ||||
| constructor (owner: Pred, capacity: number, damage: Damage) { | constructor (owner: Pred, capacity: number, damage: Damage) { | ||||
| super('Bowels', owner, new Set([VoreType.Anal]), capacity, damage) | |||||
| super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage) | |||||
| } | } | ||||
| consumeLines = new POVPair([ | consumeLines = new POVPair([ | ||||