diff --git a/src/game/combat/actions.ts b/src/game/combat/actions.ts index 3bf3897..bdccd9c 100644 --- a/src/game/combat/actions.ts +++ b/src/game/combat/actions.ts @@ -310,3 +310,39 @@ export class TransferAction extends Action { return new LogLine(`Push ${target.baseName} from your ${this.from.name} to your ${this.to.name}`) } } + +export class WillingTransferAction extends Action { + giveIn: Verb = new Verb('give in', 'gives in', 'gave in', 'giving in') + allow: Verb = new Verb('allow') + verb: Verb = new Verb('send') + + constructor (protected from: Container, protected to: Container, name = 'Transfer') { + super( + name, + `${from.name.all.capital} to ${to.name.all}`, + [new CapableCondition(), new PairCondition()] + ) + } + + line: PairLineArgs = (user, target, args) => new LogLine( + `${user.name.capital} ${user.name.conjugate(this.giveIn)} and ${user.name.conjugate(this.allow)} ${target.name.objective} to send ${user.name.objective} from ${target.pronouns.possessive} ${args.from.name} to ${target.pronouns.possessive} ${args.to.name}` + ) + + allowed (user: Creature, target: Creature) { + if (user.containedIn === this.from && this.from.contents.includes(user)) { + return super.allowed(user, target) + } else { + return false + } + } + + execute (user: Creature, target: Creature): LogEntry { + this.from.release(user) + this.to.consume(user) + return this.line(user, target, { from: this.from, to: this.to }) + } + + describe (user: Creature, target: Creature): LogEntry { + return new LogLine(`Allow ${target.baseName} to pull ${user.pronouns.subjective} ${this.to.consumePreposition} ${target.pronouns.possessive} ${this.to.name}`) + } +} diff --git a/src/game/creatures.ts b/src/game/creatures.ts index 3f89d05..acf9e13 100644 --- a/src/game/creatures.ts +++ b/src/game/creatures.ts @@ -10,5 +10,6 @@ import { Goldeneye } from './creatures/goldeneye' import { Kuro } from './creatures/kuro' import { Geta } from './creatures/geta' import { Werewolf } from './creatures/werewolf' +import { Taluthus } from './creatures/taluthus' -export { Wolf, DireWolf, Player, Cafat, Human, Withers, Kenzie, Dragon, Shingo, Goldeneye, Kuro, Geta, Werewolf } +export { Wolf, DireWolf, Player, Cafat, Human, Withers, Kenzie, Dragon, Shingo, Goldeneye, Kuro, Geta, Werewolf, Taluthus } diff --git a/src/game/creatures/taluthus.ts b/src/game/creatures/taluthus.ts new file mode 100644 index 0000000..0289da7 --- /dev/null +++ b/src/game/creatures/taluthus.ts @@ -0,0 +1,100 @@ +import { Creature } from "../creature" +import { DamageType, Vigor, Side, StatDamageFormula, Stat } from '../combat' +import { MalePronouns, ProperNoun, Verb } from '../language' +import { Stomach, Bowels, Cock, Balls, anyVore, biconnectContainers, Tail } from '../vore' +import { AttackAction, TransferAction, FeedAction, WillingTransferAction } from '../combat/actions' +import { VoreAI } from '../ai' + +export class Taluthus extends Creature { + constructor () { + super( + new ProperNoun('Taluthus'), + new ProperNoun('Taluthus'), + MalePronouns, + { Toughness: 40, Power: 50, Reflexes: 40, Agility: 30, Willpower: 50, Charm: 60 }, + new Set(), + anyVore, + 100 + ) + this.actions.push( + new AttackAction( + new StatDamageFormula([ + { fraction: 1, stat: Stat.Power, target: Vigor.Health, type: DamageType.Pierce }, + { fraction: 0.5, stat: Stat.Power, target: Vigor.Health, type: DamageType.Crush } + ]), + new Verb("bite") + ) + ) + + this.ai = new VoreAI() + + this.side = Side.Monsters + + const stomach = new Stomach( + this, + 1, + new StatDamageFormula([ + { fraction: 1, stat: Stat.Toughness, target: Vigor.Health, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Health, type: DamageType.Crush }, + { fraction: 0.5, stat: Stat.Toughness, target: Vigor.Stamina, type: DamageType.Acid }, + { fraction: 0.5, stat: Stat.Power, target: Vigor.Stamina, type: DamageType.Crush }, + { fraction: 0.5, stat: Stat.Toughness, target: Vigor.Resolve, type: DamageType.Acid }, + { fraction: 0.5, stat: Stat.Power, target: Vigor.Resolve, type: DamageType.Crush } + ]) + ) + + this.containers.push(stomach) + + const tail = new Tail( + this, + 1.5, + new StatDamageFormula([ + { fraction: 0.05, stat: Stat.Toughness, target: Vigor.Health, type: DamageType.Acid }, + { fraction: 0.1, stat: Stat.Power, target: Vigor.Health, type: DamageType.Crush }, + { fraction: 0.5, stat: Stat.Toughness, target: Vigor.Stamina, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Stamina, type: DamageType.Crush }, + { fraction: 0.5, stat: Stat.Toughness, target: Vigor.Resolve, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Resolve, type: DamageType.Crush } + ]) + ) + + this.containers.push(tail) + + this.actions.push(new TransferAction(tail, stomach)) + this.otherActions.push(new WillingTransferAction(tail, stomach)) + + this.otherActions.push(new FeedAction(stomach)) + + const cock = new Cock( + this, + 1.5, + new StatDamageFormula([ + { fraction: 1, stat: Stat.Charm, target: Vigor.Health, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Health, type: DamageType.Crush }, + { fraction: 0.5, stat: Stat.Charm, target: Vigor.Stamina, type: DamageType.Acid }, + { fraction: 0.5, stat: Stat.Power, target: Vigor.Stamina, type: DamageType.Crush }, + { fraction: 1, stat: Stat.Charm, target: Vigor.Resolve, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Resolve, type: DamageType.Crush } + ]) + ) + + const balls = new Balls( + this, + 1.5, + new StatDamageFormula([ + { fraction: 1, stat: Stat.Toughness, target: Vigor.Health, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Health, type: DamageType.Crush }, + { fraction: 1, stat: Stat.Toughness, target: Vigor.Stamina, type: DamageType.Acid }, + { fraction: 1, stat: Stat.Power, target: Vigor.Stamina, type: DamageType.Crush }, + { fraction: 1.5, stat: Stat.Toughness, target: Vigor.Resolve, type: DamageType.Acid }, + { fraction: 1.5, stat: Stat.Power, target: Vigor.Resolve, type: DamageType.Crush } + ]), + cock + ) + + // this.containers.push(balls) + // this.containers.push(cock) + + biconnectContainers(cock, balls) + } +} diff --git a/src/game/maps/town.ts b/src/game/maps/town.ts index ff7945c..dd76d7f 100644 --- a/src/game/maps/town.ts +++ b/src/game/maps/town.ts @@ -192,6 +192,24 @@ export const Town = (): Place => { ) ) + woods.choices.push( + new Choice( + "Fight Taluthus", + "yolo", + (world, executor) => { + world.encounter = new Encounter( + { + name: "You punched Taluthus", + intro: () => new LogLine(`You punched Tal.`) + }, + [executor, new Creatures.Taluthus()] + ) + + return new LogLine(`FIGHT TIME`) + } + ) + ) + const bossEncounters = [ new Encounter( { name: "Withers & Kenzie", intro: () => nilLog }, diff --git a/src/game/vore.ts b/src/game/vore.ts index 601695b..c100b42 100644 --- a/src/game/vore.ts +++ b/src/game/vore.ts @@ -11,7 +11,8 @@ export enum VoreType { Cock = "Cock Vore", Unbirth = "Unbirthing", Breast = "Breast Vore", - Bladder = "Bladder vore" + Bladder = "Bladder Vore", + Tail = "Tail Vore" } export const anyVore = new Set([ @@ -20,7 +21,8 @@ export const anyVore = new Set([ VoreType.Cock, VoreType.Unbirth, VoreType.Breast, - VoreType.Bladder + VoreType.Bladder, + VoreType.Tail ]) export interface Container extends Actionable { @@ -40,8 +42,11 @@ export interface Container extends Actionable { struggle: (prey: Creature) => LogEntry; consumeVerb: Verb; + consumePreposition: Preposition; releaseVerb: Verb; + releasePreposition: Preposition; struggleVerb: Verb; + strugglePreposition: Preposition; consumeLine (user: Creature, target: Creature): LogEntry; @@ -209,8 +214,8 @@ export abstract class NormalVoreContainer extends NormalContainer implements Vor tickLine (user: Creature, target: Creature, args: { damage: Damage }): LogEntry { return new RandomEntry( new LogLine(`${user.name.capital} ${user.name.conjugate(Words.Churns)} ${target.name.objective} ${this.strugglePreposition} ${user.pronouns.possessive} ${this.name} for `, args.damage.renderShort(), `.`), - new LogLine(`${user.name.capital.possessive} ${this.name} ${this.name.conjugate(Words.Churns)}, stewing ${target.name.objective} for `, args.damage.renderShort(), `.`), - new LogLine(`${target.name.capital} ${target.name.conjugate(new Verb("thrash", "thrashes"))} ${this.strugglePreposition} ${user.name.possessive} ${Words.Slick} ${this.name} as it churns ${target.pronouns.objective} for `, args.damage.renderShort(), `.`) + new LogLine(`${user.name.capital.possessive} ${this.name} ${this.name.conjugate(Words.Churns)}, ${Words.Churns.present} ${target.name.objective} for `, args.damage.renderShort(), `.`), + new LogLine(`${target.name.capital} ${target.name.conjugate(new Verb("thrash", "thrashes"))} ${this.strugglePreposition} ${user.name.possessive} ${Words.Slick} ${this.name} as it ${Words.Churns.singular} ${target.pronouns.objective} for `, args.damage.renderShort(), `.`) ) } @@ -379,6 +384,20 @@ export class Bowels extends NormalVoreContainer { } } +export class Tail extends NormalVoreContainer { + fluidName = new Noun("chyme") + + constructor (owner: Creature, capacity: number, damage: DamageFormula) { + super(new ImproperNoun('tail', 'tails').all, owner, new Set([VoreType.Tail]), capacity, damage) + } + + tickLine (user: Creature, target: Creature, args: { damage: Damage }) { + return new RandomEntry( + new LogLine(`${user.name.capital} ${user.name.conjugate(Words.Clench)} ${target.name.objective} in ${user.pronouns.possessive} ${this.name} for `, args.damage.renderShort(), `.`) + ) + } +} + export class Cock extends NormalVoreContainer { fluidName = new Noun("cum") diff --git a/src/game/words.ts b/src/game/words.ts index 7ef7c61..08403c9 100644 --- a/src/game/words.ts +++ b/src/game/words.ts @@ -15,7 +15,8 @@ export const Slick = new RandomWord([ new Adjective('slick'), new Adjective('slippery'), new Adjective('slimy'), - new Adjective('glistening') + new Adjective('glistening'), + new Adjective('wet') ]) export const Swallow = new RandomWord([ @@ -28,30 +29,42 @@ export const Churns = new RandomWord([ new Verb("churn"), new Verb("sizzle", "sizzles", "sizzling", "sizzled"), new Verb("simmer"), - new Verb("stew") + new Verb("stew"), + new Verb("gurgle", "gurgles", "gurgling", "gurgled") ]) export const Dark = new RandomWord([ new Adjective("dark"), new Adjective("lightless"), - new Adjective("pitch-black") + new Adjective("pitch-black"), + new Adjective("black"), + new Adjective("tenebrous"), + new Adjective("unlit"), + new Adjective("dark-as-night") ]) export const Digest = new RandomWord([ new Verb("digest"), new Verb("melt down", "melts down", "melting down", "melted down"), - new Verb("dissolve", "dissolves", "dissolving", "dissolved") + new Verb("dissolve", "dissolves", "dissolving", "dissolved"), + new Verb("mulch", "mulches", "mulching", "mulched"), + new Verb("break down", "breaks down", "breaking down", "broken down") ]) export const Absorb = new RandomWord([ new Verb("absorb"), - new Verb("soak up", "soaks up", "soaking up", "soaked up") + new Verb("soak up", "soaks up", "soaking up", "soaked up"), + new Verb("erase", "erases", "erasing", "erased") ]) export const Struggle = new RandomWord([ new Verb("squirm"), new Verb("struggle", "struggles", "struggling", "struggled"), - new Verb("thrash", "thrashes") + new Verb("thrash", "thrashes"), + new Verb("writhe", "writhes", "writhing", "writhed"), + new Verb("flounder"), + new Verb("wriggle", "wriggles", "wriggling", "wriggled"), + new Verb("flail") ]) export const Bulge = new RandomWord([ @@ -69,6 +82,14 @@ export const Brutally = new RandomWord([ new Adjective('mercilessly') ]) +export const Fatal = new RandomWord([ + new Adjective("deadly"), + new Adjective("fatal"), + new Adjective("brutal"), + new Adjective("unsurvivable"), + new Adjective("death-sentence of a") +]) + export const Force = new RandomWord([ new Verb("force", "forces", "forcing", "forced"), new Verb("cram", "crams", "cramming", "crammed"), @@ -79,12 +100,15 @@ export const Clench = new RandomWord([ new Verb("clench", "clenches", "clenching", "clenched"), new Verb("smother", "smothers", "smothering", "smothered"), new Verb("squeeze", "squeezes", "squeezing", "squeezed"), - new Verb("bear down on", "bears down on", "bearing down on", "bore down on") + new Verb("bear down on", "bears down on", "bearing down on", "bore down on"), + new Verb("crush on", "crushes on", "crushing on", "crushed on") ]) export const Succumb = new RandomWord([ new Verb("succumb"), - new Verb("surrender") + new Verb("surrender"), + new Verb("give in to", "gives in to", "giving in to", "gave in to"), + new Verb("yield") ]) export const Flaunt = new RandomWord([