Selaa lähdekoodia

Add action conditions/feed actions

vintage
Fen Dweller 5 vuotta sitten
vanhempi
commit
1cde832996
4 muutettua tiedostoa jossa 136 lisäystä ja 18 poistoa
  1. +90
    -11
      src/game/combat.ts
  2. +38
    -4
      src/game/creatures/wolf.ts
  3. +7
    -2
      src/game/entity.ts
  4. +1
    -1
      src/game/vore.ts

+ 90
- 11
src/game/combat.ts Näytä tiedosto

@@ -72,7 +72,10 @@ export enum DamageType {
Pierce = "Pierce",
Slash = "Slash",
Crush = "Crush",
Acid = "Acid"}
Acid = "Acid",
Seduction = "Seduction",
Dominance = "Dominance"
}

export interface DamageInstance {
type: DamageType;
@@ -155,10 +158,13 @@ export interface Combatant {
}

export abstract class Action {
abstract allowed (user: Creature, target: Creature): boolean
allowed (user: Creature, target: Creature): boolean {
return this.conditions.every(cond => cond.allowed(user, target))
}

abstract execute(user: Creature, target: Creature): LogEntry

constructor (public name: string, public desc: string) {
constructor (public name: string, public desc: string, private conditions: Array<Condition> = []) {

}

@@ -167,19 +173,56 @@ export abstract class Action {
}
}

export interface Condition {
allowed: (user: Creature, target: Creature) => boolean;
}

class InverseCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return !this.condition.allowed(user, target)
}

constructor (private condition: Condition) {

}
}
class CapableCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return !user.disabled
}
}

class DrainedVigorCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return user.vigors[this.vigor] <= 0
}

constructor (private vigor: Vigor) {

}
}

export interface Actionable {
actions: Array<Action>;
}

abstract class SelfAction extends Action {
allowed (user: Creature, target: Creature) {
return user === target
if (user === target) {
return super.allowed(user, target)
} else {
return false
}
}
}

abstract class PairAction extends Action {
allowed (user: Creature, target: Creature) {
return user !== target
if (user !== target) {
return super.allowed(user, target)
} else {
return false
}
}
}

@@ -194,7 +237,7 @@ abstract class TogetherAction extends PairAction {
}

export class AttackAction extends TogetherAction {
private test: StatTest
protected test: StatTest

protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([
[[POV.First, POV.Third], (user, target, args) => new LogLine(
@@ -218,7 +261,7 @@ export class AttackAction extends TogetherAction {
])

constructor (protected damage: Damage) {
super('Attack', 'Attack the enemy')
super('Attack', 'Attack the enemy', [new CapableCondition()])
this.test = new StatTest(Stat.STR)
}

@@ -254,7 +297,7 @@ export class DevourAction extends TogetherAction {
}

constructor (protected container: Container) {
super('Devour', 'Try to consume your foe')
super('Devour', 'Try to consume your foe', [new CapableCondition()])
this.name += ` (${container.name})`
this.test = new StatTest(Stat.STR)
}
@@ -268,6 +311,42 @@ export class DevourAction extends TogetherAction {
}
}

export class FeedAction extends TogetherAction {
private test: StatTest

protected failLines: POVPair<Entity, Entity> = new POVPair([
[[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.Third], (user, target) => new LogLines(`${target.name} unsuccessfully tries to feed ${user.pronouns.possessive} to ${target.name}`)]
])

allowed (user: Creature, target: Creature): boolean {
const owner = this.container.owner === target
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
}
}

constructor (protected container: Container) {
super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Willpower)])
this.name += ` (${container.name})`
this.test = new StatTest(Stat.STR)
}

execute (user: Creature, target: Creature): LogEntry {
if (this.test.test(user, target)) {
return this.container.consume(user)
} else {
return this.failLines.run(user, target)
}
}
}

export class StruggleAction extends PairAction {
private test: StatTest

@@ -286,7 +365,7 @@ export class StruggleAction extends PairAction {
}

constructor (public container: Container) {
super('Struggle', 'Try to escape your predator')
super('Struggle', 'Try to escape your predator', [new CapableCondition()])
this.test = new StatTest(Stat.STR)
}

@@ -315,7 +394,7 @@ export class DigestAction extends SelfAction {
}

constructor (protected container: Container) {
super('Digest', 'Digest all of your current prey')
super('Digest', 'Digest all of your current prey', [new CapableCondition()])
this.name += ` (${container.name})`
}

@@ -356,7 +435,7 @@ export class TransferAction extends PairAction {
}

constructor (protected from: Container, protected to: Container) {
super('Transfer', `Shove your prey from your ${from.name} to your ${to.name}`)
super('Transfer', `Shove your prey from your ${from.name} to your ${to.name}`, [new CapableCondition()])
}

execute (user: Creature, target: Creature): LogEntry {


+ 38
- 4
src/game/creatures/wolf.ts Näytä tiedosto

@@ -1,18 +1,50 @@
import { Creature, POV } from '../entity'
import { Stat, Damage, DamageType, AttackAction, TransferAction, Vigor } from '../combat'
import { MalePronouns, ImproperNoun } from '../language'
import { Creature, POV, Entity } from '../entity'
import { Stat, Damage, DamageType, AttackAction, TransferAction, Vigor, StatTest, FeedAction } from '../combat'
import { MalePronouns, ImproperNoun, POVPair, POVPairArgs } from '../language'
import { LogLine, LogLines } from '../interface'
import { VoreType, Stomach, Bowels } from '../vore'

class BiteAction extends AttackAction {
constructor () {
super(new Damage({ amount: 10, type: DamageType.Slash, target: Vigor.Health }))
this.name = "Bite"
}
}

class HypnoAction extends AttackAction {
protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([
[[POV.First, POV.Third], (user, target, args) => new LogLine(
`You hypnotize ${target.name} for `,
args.damage.renderShort()
)],
[[POV.Third, POV.First], (user, target, args) => new LogLine(
`${user.name.capital} hypnotizes you for `,
args.damage.renderShort()
)],
[[POV.Third, POV.Third], (user, target, args) => new LogLine(
`${user.name.capital} hypnotizes ${target.name} for `,
args.damage.renderShort()
)]
])

protected failLines: POVPair<Entity, Entity> = new POVPair([
[[POV.First, POV.Third], (user, target) => new LogLines(`You try to hypnotize ${target.name}, but you miss`)],
[[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}`)]
])

constructor () {
super(new Damage({ amount: 30, type: DamageType.Dominance, target: Vigor.Willpower }))
this.test = new StatTest(Stat.CON)
this.name = "Hypnotize"
}
}

export class Wolf extends Creature {
constructor () {
super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 10, [Stat.DEX]: 10, [Stat.CON]: 10 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral]), 25)
super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 15, [Stat.DEX]: 15, [Stat.CON]: 25 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral]), 25)
this.actions.push(new BiteAction())
this.actions.push(new HypnoAction())

const stomach = new Stomach(this, 50, new Damage({ amount: 50, type: DamageType.Acid, target: Vigor.Health }, { amount: 500, type: DamageType.Crush, target: Vigor.Health }))

@@ -22,5 +54,7 @@ export class Wolf extends Creature {
this.containers.push(bowels)

this.actions.push(new TransferAction(bowels, stomach))

this.otherActions.push(new FeedAction(stomach))
}
}

+ 7
- 2
src/game/entity.ts Näytä tiedosto

@@ -14,7 +14,7 @@ export interface Entity {
export interface Mortal extends Entity {
vigors: {[key in Vigor]: number};
maxVigors: {[key in Vigor]: number};
disabled: boolean;
resistances: Map<DamageType, number>;
takeDamage: (damage: Damage) => void;
stats: Stats;
@@ -34,10 +34,15 @@ export class Creature implements Mortal, Pred, Prey, Combatant {
[Vigor.Willpower]: 100
}

get disabled (): boolean {
return Object.values(this.vigors).some(val => val <= 0)
}

resistances: Map<DamageType, number> = new Map()
perspective: POV = POV.Third
containers: Array<Container> = []
actions: Array<Action> = [];
otherActions: Array<Action> = [];
private baseBulk: number;

get bulk (): number {
@@ -83,7 +88,7 @@ export class Creature implements Mortal, Pred, Prey, Combatant {
}

validActions (target: Creature): Array<Action> {
let choices = this.actions.concat(this.containers.flatMap(container => container.actions))
let choices = this.actions.concat(this.containers.flatMap(container => container.actions)).concat(target.otherActions)

if (this.containedIn !== null) {
choices = choices.concat(this.containedIn.actions)


+ 1
- 1
src/game/vore.ts Näytä tiedosto

@@ -1,5 +1,5 @@
import { Entity, Mortal, POV } from './entity'
import { Damage, Actionable, Action, DevourAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat'
import { Damage, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat'
import { LogLines, LogEntry, CompositeLog } from './interface'
import { POVSolo, POVPair, POVPairArgs } from './language'



Loading…
Peruuta
Tallenna