|
- import { Creature } from "../creature"
- import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, DamageFormula, UniformRandomDamageFormula, Action, DamageInstance, StatDamageFormula, VoreStat } from '../combat'
- import { ImproperNoun, ProperNoun, FemalePronouns, RandomWord, Adjective, Verb, PairLine } from '../language'
- import { LogLine, LogLines, LogEntry, Newline } from '../interface'
- import { VoreType, Stomach, VoreContainer, NormalContainer, Container } from '../vore'
- import { AttackAction, FeedAction, TransferAction } from '../combat/actions'
- import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions'
- import { InstantKillEffect, DamageTypeResistanceEffect } from '../combat/effects'
- import * as Words from '../words'
- import { StatVigorTest } from '../combat/tests'
-
- class LevelDrain extends Action {
- constructor (private container: Container) {
- super(
- 'Level Drain',
- 'Drain energy from your prey',
- [
- new ContainsCondition(container),
- new CapableCondition()
- ]
- )
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- const damage: Damage = new Damage(...Object.keys(Stat).map(stat => {
- return {
- type: DamageType.Acid,
- target: stat as Stat,
- amount: target.baseStats[stat as Stat] / 5
- }
- }))
- const heal: Damage = new Damage(...Object.keys(Stat).map(stat => {
- return {
- type: DamageType.Heal,
- target: stat as Stat,
- amount: target.baseStats[stat as Stat] / 5
- }
- }))
-
- // TODO make this respect resistances
-
- user.takeDamage(heal)
- const targetResult = target.takeDamage(damage)
-
- return new LogLines(
- new LogLine(`${user.name.capital.possessive} ${this.container.name} drains power from ${target.name.objective}, siphoning `, damage.renderShort(), ` from ${target.pronouns.possessive} body!`),
- targetResult
- )
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Drain energy from ${target.name}`)
- }
- }
- class HypnotizeAction extends Action {
- constructor () {
- super(
- `Hypnotize`,
- `Change their mind!`,
- [
- new TogetherCondition(),
- new EnemyCondition(),
- new CapableCondition()
- ]
- )
- }
-
- line: PairLine<Creature> = (user, target) => new LogLine(
- `${user.name.capital.possessive} hypnotic gaze enthralls ${target.name}, putting ${target.pronouns.objective} under ${user.pronouns.possessive} control!`
- )
-
- execute (user: Creature, target: Creature): LogEntry {
- target.side = user.side
- return this.line(user, target)
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Force your target to fight by your side`)
- }
- }
- class MawContainer extends NormalContainer {
- consumeVerb = new Verb('grab', 'grabs', 'grabbing', 'grabbed')
- releaseVerb = new Verb('release')
- struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')
-
- constructor (owner: Creature, stomach: VoreContainer) {
- super(new ImproperNoun('maw'), owner, new Set([VoreType.Oral]), 0.05)
-
- const transfer = new TransferAction(this, stomach)
- transfer.verb = new Verb('gulp')
- this.actions.push(transfer)
- }
- }
-
- class FlexToesAction extends GroupAction {
- constructor (private damage: DamageFormula, container: Container) {
- super('Flex Toes', 'Flex your toes!', [
- new ContainsCondition(container),
- new PairCondition()
- ])
- }
-
- line = (user: Creature, target: Creature, args: { damage: Damage }) => new LogLine(`${user.name.capital.possessive} toes crush ${target.name.objective} for `, args.damage.renderShort(), ` damage!`)
-
- describeGroup (user: Creature, targets: Creature[]): LogEntry {
- return new LogLine(`Flex your toes. `, this.damage.explain(user))
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- const damage = this.damage.calc(user, target)
- return new LogLines(target.takeDamage(damage), this.line(user, target, { damage: damage }))
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Flex your toes! `, this.damage.describe(user, target))
- }
- }
-
- class BootContainer extends NormalContainer {
- consumeVerb = new Verb('trap', 'traps', 'trapped', 'trapping')
- releaseVerb = new Verb('dump')
- struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')
-
- constructor (owner: Creature) {
- super(new ImproperNoun('boot'), owner, new Set(), 0.05)
-
- const flex = new FlexToesAction(
- new UniformRandomDamageFormula(new Damage(
- { target: Stat.Toughness, type: DamageType.Crush, amount: 10 },
- { target: Stat.Power, type: DamageType.Crush, amount: 10 },
- { target: Stat.Speed, type: DamageType.Crush, amount: 10 },
- { target: Stat.Willpower, type: DamageType.Crush, amount: 30 },
- { target: Stat.Charm, type: DamageType.Crush, amount: 10 }
- ), 0.5),
- this
- )
-
- this.actions.push(flex)
- }
- }
-
- const huge = new RandomWord([
- new Adjective('massive'),
- new Adjective('colossal'),
- new Adjective('big ol\''),
- new Adjective('heavy'),
- new Adjective('crushing'),
- new Adjective('huge')
- ])
-
- class BiteAction extends AttackAction {
- constructor () {
- super(
- new ConstantDamageFormula(new Damage({ amount: 50, type: DamageType.Slash, target: Vigor.Health })),
- new Verb('bite', 'bites', 'biting', 'bit')
- )
- this.name = "Bite"
- }
- }
-
- class ChewAction extends GroupAction {
- constructor (private damage: DamageFormula, container: Container, private killAction: Action) {
- super('Chew', 'Give them the big chew', [
- new ContainsCondition(container)
- ])
- }
-
- line = (user: Creature, target: Creature, args: { damage: Damage }) => new LogLine(`${user.name.capital} chews on ${target.name.objective} for `, args.damage.renderShort(), `!`)
-
- describeGroup (user: Creature, targets: Creature[]): LogEntry {
- return new LogLine('Crunch \'em all. ', this.damage.explain(user))
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- const damage = this.damage.calc(user, target)
- const results: Array<LogEntry> = []
- results.push(this.line(user, target, { damage: damage }))
- results.push(new LogLine(' '))
- results.push(target.takeDamage(damage))
-
- if (target.vigors.Health <= 0) {
- if (this.killAction.allowed(user, target)) {
- results.push(new Newline())
- results.push(this.killAction.execute(user, target))
- }
- }
-
- return new LogLine(...results)
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine('Do the crunch')
- }
- }
-
- class StompAction extends GroupAction {
- constructor () {
- super('Stomp', 'STOMP!', [
- new TogetherCondition(),
- new EnemyCondition(),
- new CapableCondition()
- ])
- }
-
- line: PairLine<Creature> = (user, target) => new LogLine(
- `${user.name.capital} ${user.name.conjugate(new Verb('flatten'))} ${target.name.objective} under ${user.pronouns.possessive} ${huge} foot!`
- )
-
- execute (user: Creature, target: Creature): LogEntry {
- return new LogLines(this.line(user, target), target.applyEffect(new InstantKillEffect()))
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine('Stomp one sucker')
- }
-
- describeGroup (user: Creature, targets: Array<Creature>): LogEntry {
- return new LogLine('Stomp all ', targets.length.toString(), ' of \'em!')
- }
- }
-
- class StompAllyAction extends Action {
- constructor () {
- super('Stomp Ally', '-1 ally, +1 buff', [
- new TogetherCondition(),
- new AllyCondition(),
- new CapableCondition()
- ])
- }
-
- line: PairLine<Creature> = (user, target) => new LogLine(
- `${user.name.capital} ${user.name.conjugate(new Verb('flatten'))} ${target.name.objective} under ${user.pronouns.possessive} ${huge} boot!`
- )
-
- execute (user: Creature, target: Creature): LogEntry {
- const damages: Array<DamageInstance> = Object.keys(Stat).map(stat => ({
- target: stat as Stat,
- amount: target.stats[stat as Stat] / 3,
- type: DamageType.Heal
- }))
-
- const heal = new Damage(
- ...damages
- )
- user.takeDamage(heal)
- target.destroyed = true
-
- return new LogLines(
- this.line(user, target),
- target.applyEffect(new InstantKillEffect()),
- user.applyEffect(new DamageTypeResistanceEffect(
- [DamageType.Crush, DamageType.Slash, DamageType.Pierce],
- 0.5
- )),
- new LogLine(`${user.name.capital} absorbs ${target.pronouns.possessive} power, gaining `, heal.renderShort())
- )
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine('Crush an ally to absorb their power')
- }
- }
-
- class DevourAllAction extends GroupAction {
- constructor (private container: VoreContainer) {
- super('Devour All', 'GULP!', [
- new TogetherCondition(),
- new EnemyCondition(),
- new CapableCondition()
- ])
- }
-
- line = (user: Creature, target: Creature) => new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb('scoop'))} ${target.name} up!`)
-
- groupLine = (user: Creature, args: { count: number }) => new LogLine(`${Words.SwallowSound.allCaps}! All ${args.count} of ${user.pronouns.possessive} prey pour down ${user.name.possessive} ${Words.Slick} gullet as ${user.pronouns.subjective} ${user.name.conjugate(Words.Swallows)}; they're just ${user.kind.all} chow now`)
-
- execute (user: Creature, target: Creature): LogEntry {
- this.container.consume(target)
- return new LogLines(this.line(user, target))
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine('Stomp one sucker')
- }
-
- executeGroup (user: Creature, targets: Array<Creature>): LogEntry {
- return new LogLines(...targets.map(target => this.execute(user, target)).concat(
- [
- new Newline(),
- this.groupLine(user, { count: targets.length })
- ]
- ))
- }
-
- describeGroup (user: Creature, targets: Array<Creature>): LogEntry {
- return new LogLine('Eat all ', targets.length.toString(), ' of \'em!')
- }
- }
-
- export class Withers extends Creature {
- title = "Huge Hellhound"
- desc = "Will eat your party"
-
- constructor () {
- super(
- new ProperNoun('Withers'),
- new ImproperNoun('hellhound', 'hellhounds'),
- FemalePronouns,
- { Toughness: 40, Power: 50, Speed: 30, Willpower: 40, Charm: 70 },
- new Set(),
- new Set([VoreType.Oral]),
- 5000
- )
-
- this.actions.push(new BiteAction())
- this.groupActions.push(new StompAction())
-
- this.side = Side.Monsters
-
- const stomach = new Stomach(this, 0.1, new ConstantDamageFormula(new Damage(
- { amount: 300, type: DamageType.Acid, target: Vigor.Health },
- { amount: 200, type: DamageType.Crush, target: Vigor.Stamina },
- { amount: 200, type: DamageType.Dominance, target: Vigor.Resolve }
- )))
-
- this.containers.push(stomach)
- this.otherActions.push(new FeedAction(stomach))
-
- this.groupActions.push(new DevourAllAction(stomach))
-
- const maw = new MawContainer(this, stomach)
-
- this.otherContainers.push(maw)
-
- const transfer = new TransferAction(maw, stomach)
- transfer.verb = new Verb('gulp')
-
- this.actions.push(new ChewAction(
- new UniformRandomDamageFormula(new Damage(
- { target: Vigor.Health, type: DamageType.Crush, amount: 10000 }
- ), 0.5),
- maw,
- transfer
- ))
-
- const boot = new BootContainer(this)
- this.otherContainers.push(boot)
- this.actions.push(new StompAllyAction())
-
- this.actions.push(
- new AttackAction(
- new StatDamageFormula([
- { fraction: 0.5, stat: Stat.Toughness, target: Vigor.Health, type: DamageType.Crush },
- { fraction: 0.05, stat: VoreStat.Bulk, target: Vigor.Health, type: DamageType.Crush }
- ]),
- new Verb('stomp')
- )
- )
-
- this.actions.push(new HypnotizeAction())
- this.actions.push(new LevelDrain(stomach))
- }
- }
|