|
- import { TestCategory, CompositionTest, OpposedStatScorer } from '@/game/combat/tests'
- import { DynText, LiveText, TextLike, Verb, PairLine, PairLineArgs } from '@/game/language'
- import { Entity } from '@/game/entity'
- import { Creature } from "../creature"
- import { Damage, DamageFormula, Vigor, Action, Condition, CombatTest, CompositionAction } from '@/game/combat'
- import { LogLine, LogLines, LogEntry } from '@/game/interface'
- import { Connection, Container } from '@/game/vore'
- import { CapableCondition, UserDrainedVigorCondition, TogetherCondition, EnemyCondition, SoloCondition, PairCondition, ContainsCondition, ContainedByCondition, HasRoomCondition } from '@/game/combat/conditions'
- import { ConsumeConsequence } from '@/game/combat/consequences'
-
- /**
- * The PassAction has no effect.
- */
- export class PassAction extends Action {
- constructor () {
- super("Pass", "Do nothing", [new SoloCondition()])
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- return new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb('pass', 'passes'))}`)
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine("Do nothing.")
- }
- }
-
- /**
- * A generic action that causes damage.
- */
- export abstract class DamageAction extends Action {
- abstract successLine: PairLineArgs<Creature, { damage: Damage }>
-
- constructor (name: TextLike, desc: TextLike, protected damage: DamageFormula, tests: CombatTest[], conditions: Condition[] = []) {
- super(
- name,
- desc,
- [new CapableCondition(), new EnemyCondition()].concat(conditions),
- tests
- )
- }
-
- // TODO: remove me or replace the logic for damage prevention
-
- execute (user: Creature, target: Creature): LogEntry {
- const damage = this.damage.calc(user, target)
- const targetResult = target.takeDamage(damage)
- const ownResult = this.successLine(user, target, { damage: damage })
- return new LogLines(ownResult, targetResult)
- }
- }
-
- /**
- * Adds flavor text to [[DamageAction]]
- */
- export class AttackAction extends DamageAction {
- constructor (damage: DamageFormula, protected verb: Verb = new Verb('smack')) {
- super(
- verb.root.capital,
- 'Attack the enemy',
- damage,
- [
- new CompositionTest(
- [
- new OpposedStatScorer(
- {
- Power: 1
- },
- {
- Reflexes: 1
- }
- )
- ],
- (user, target) => new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb("swing"))} and ${user.name.conjugate(new Verb("miss", "misses"))} ${target.name.objective}.`),
- TestCategory.Attack,
- 0
- )
- ],
- [new TogetherCondition()]
- )
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Attack ${target.baseName}. `, this.damage.describe(user, target), super.describe(user, target))
- }
-
- successLine: PairLineArgs<Creature, { damage: Damage }> = (user, target, args) => new LogLine(
- `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} for `,
- target.effectiveDamage(args.damage).renderShort()
- )
- }
-
- /**
- * Devours the target.
- */
- export class DevourAction extends CompositionAction {
- constructor (protected container: Container) {
- super(
- new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'),
- new LiveText(container, x => `Try to ${x.consumeVerb} your foe`),
- {
- conditions: [new CapableCondition(), new TogetherCondition(), new HasRoomCondition(container)],
- tests: [
- new CompositionTest(
- [
- new OpposedStatScorer(
- { Power: 1, Charm: 1, Mass: 0.05 },
- { Toughness: 1, Willpower: 1, Bulk: 0.05 }
- )
- ],
- (user, target) => new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to ${container.consumeVerb} ${target.name.objective}.`),
- TestCategory.Vore,
- -5
- )],
- consequences: [
- new ConsumeConsequence(container)
- ]
- }
- )
- }
-
- 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
- }
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Try to ${this.container.consumeVerb} your opponent, sending them to your ${this.container.name}. `, super.describe(user, target))
- }
- }
-
- /**
- * Causes the user to be eaten by the target.
- */
- export class FeedAction extends Action {
- constructor (protected container: Container) {
- super(
- 'Feed',
- 'Feed yourself to your opponent',
- [new UserDrainedVigorCondition(Vigor.Resolve), new TogetherCondition()]
- )
- this.name += ` (${container.name})`
- }
-
- allowed (user: Creature, target: Creature): boolean {
- const owner = this.container.owner === target
- const predOk = Array.from(this.container.voreTypes).every(pref => user.preyPrefs.has(pref))
- const preyOk = Array.from(this.container.voreTypes).every(pref => target.predPrefs.has(pref))
-
- if (owner && predOk && preyOk) {
- return super.allowed(user, target)
- } else {
- return false
- }
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- return new LogLines(this.successLine(user, target), this.container.consume(user))
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Your willpower is drained, and you really feel like shoving yourself into ${target.name.possessive} ${this.container.name}...`)
- }
-
- protected successLine: PairLine<Entity> = (user, target) => new LogLine(
- `${user.name.capital} ${user.name.conjugate(new Verb('feed'))} ${user.pronouns.reflexive} to ${target.name}. `
- )
- }
-
- /**
- * Tries to escape from the target's container
- */
- export class StruggleAction extends Action {
- constructor (public container: Container) {
- super(
- new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'),
- 'Try to escape from your foe',
- [new CapableCondition(), new PairCondition(), new ContainedByCondition(container)],
- [
- new CompositionTest(
- [
- new OpposedStatScorer(
- { Power: 1, Agility: 1, Bulk: 0.05 },
- { Toughness: 1, Reflexes: 1, Mass: 0.05 }
- )
- ],
- (user, target) => new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to escape from ${target.name.possessive} ${container.name}.`),
- TestCategory.Vore,
- -5
- )
- ]
- )
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- if (user.containedIn !== null) {
- return new LogLines(this.successLine(user, target, { container: this.container }), user.containedIn.release(user))
- } else {
- return new LogLine("Vore's bugged!")
- }
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Try to escape from ${target.baseName.possessive} ${this.container.name}. `, super.describe(user, target))
- }
-
- protected successLine: PairLineArgs<Entity, { container: Container }> = (prey, pred, args) => new LogLine(
- `${prey.name.capital} ${prey.name.conjugate(new Verb('escape'))}!`
- )
- }
-
- /**
- * Tries to move between containers
- */
- export class StruggleMoveAction extends Action {
- constructor (public from: Container, public to: Container) {
- super(
- new DynText('Struggle (', new LiveText(from, x => x.name.all), ' to ', new LiveText(to, x => x.name.all), ')'),
- 'Try to escape from your foe',
- [new CapableCondition(), new PairCondition(), new ContainedByCondition(from)],
- [
- new CompositionTest(
- [
- new OpposedStatScorer(
- { Power: 1, Agility: 1, Bulk: 0.05 },
- { Toughness: 1, Reflexes: 1, Mass: 0.05 }
- )
- ],
- (user, target) => new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb('fail'))} to escape from ${target.name.possessive} ${from.name}.`),
- TestCategory.Vore,
- -5
- )
- ]
- )
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- if (user.containedIn !== null) {
- return new LogLines(this.successLine(user, target, { container: this.from }), user.containedIn.release(user))
- } else {
- return new LogLine("Vore's bugged!")
- }
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Try to escape from ${target.baseName.possessive} ${this.from.name}. `, super.describe(user, target))
- }
-
- protected successLine: PairLineArgs<Entity, { container: Container }> = (prey, pred, args) => new LogLine(
- `${prey.name.capital} ${prey.name.conjugate(new Verb('escape'))}!`
- )
- }
-
- export class RubAction extends Action {
- constructor (protected container: Container) {
- super(
- new DynText('Rub (', new LiveText(container, container => container.name.all), ')'),
- 'Digest your prey more quickly',
- [new CapableCondition(), new SoloCondition()]
- )
- }
-
- allowed (user: Creature, target: Creature) {
- if (this.container.owner === user && this.container.contents.length > 0) {
- return super.allowed(user, target)
- } else {
- return false
- }
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- const results = this.container.tick(60)
- return new LogLines(results)
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Digest everyone inside of your ${this.container.name}.`)
- }
- }
-
- export class ReleaseAction extends Action {
- constructor (protected container: Container) {
- super(
- new DynText('Release (', new LiveText(container, x => x.name.all), ')'),
- 'Release one of your prey',
- [new CapableCondition(), new PairCondition(), new ContainsCondition(container)]
- )
- }
-
- allowed (user: Creature, target: Creature) {
- if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) {
- return super.allowed(user, target)
- } else {
- return false
- }
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- return this.container.release(target)
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Release ${target.baseName} from your ${this.container.name}.`)
- }
- }
-
- export class TransferAction extends Action {
- verb: Verb = new Verb('send')
-
- constructor (public from: Container, public to: Connection, name = 'Transfer') {
- super(
- name,
- `${from.name.all.capital} to ${to.destination.name.all}`,
- [new CapableCondition(), new PairCondition()]
- )
- }
-
- line: PairLineArgs<Creature, { from: Container; to: Connection }> = (user, target, args) => new LogLine(
- `${user.name.capital} ${user.name.conjugate(this.verb)} ${target.name.objective} from ${user.pronouns.possessive} ${args.from.name} to ${user.pronouns.possessive} ${args.to.destination.name}`
- )
-
- allowed (user: Creature, target: Creature) {
- if (target.containedIn === this.from && this.from.contents.includes(target)) {
- return super.allowed(user, target)
- } else {
- return false
- }
- }
-
- execute (user: Creature, target: Creature): LogEntry {
- this.from.release(target)
- this.to.destination.consume(target)
- return this.line(user, target, { from: this.from, to: this.to })
- }
-
- describe (user: Creature, target: Creature): LogEntry {
- return new LogLine(`Push ${target.baseName} from your ${this.from.name} to your ${this.to.destination.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<Creature, { from: Container; to: Container }> = (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}`)
- }
- }
|