|
- import { DamageType, Damage, Stats, Vigor, VoreStats, VoreStat, Stat, Vigors, DamageInstance } from './combat'
- import { Noun, Pronoun, TextLike, POV, PronounAsNoun, FirstPersonPronouns, SecondPersonPronouns } from './language'
- import { LogEntry, LogLine } from './interface'
- import { Place, Nowhere } from './world'
-
- export abstract class Entity {
- get name (): Noun {
- if (this.perspective === POV.First) {
- return new PronounAsNoun(FirstPersonPronouns)
- } else if (this.perspective === POV.Second) {
- return new PronounAsNoun(SecondPersonPronouns)
- } else {
- return this.baseName
- }
- }
-
- get pronouns (): Pronoun {
- if (this.perspective === POV.First) {
- return FirstPersonPronouns
- } else if (this.perspective === POV.Second) {
- return SecondPersonPronouns
- } else {
- return this.basePronouns
- }
- }
-
- desc: TextLike = "It's a ting."
- perspective: POV = POV.Third
- title: TextLike = "Some thing."
- location: Place
-
- constructor (public baseName: Noun, public kind: Noun, public basePronouns: Pronoun) {
- this.location = Nowhere
- }
- }
-
- export type Resistances = {[key in DamageType]: number}
-
- export abstract class Mortal extends Entity {
- baseResistances: Resistances
-
- stats: Stats;
- vigors: {[key in Vigor]: number} = {
- [Vigor.Health]: 100,
- [Vigor.Stamina]: 100,
- [Vigor.Resolve]: 100
- }
-
- destroyed = false;
-
- constructor (name: Noun, kind: Noun, pronouns: Pronoun, public baseStats: Stats) {
- super(name, kind, pronouns)
- this.stats = Object.keys(Stat).reduce((base: any, key) => { base[key] = baseStats[key as Stat]; return base }, {})
- this.baseResistances = Object.keys(DamageType).reduce((resist: any, key) => { resist[key] = 1; return resist }, {})
- Object.entries(this.maxVigors).forEach(([key, val]) => {
- this.vigors[key as Vigor] = val
- })
- }
-
- resistanceTo (damageType: DamageType): number {
- return this.baseResistances[damageType]
- }
-
- get maxVigors (): Readonly<Vigors> {
- return {
- Health: this.stats.Toughness * 10 + this.stats.Power * 5,
- Resolve: this.stats.Willpower * 10 + this.stats.Charm * 5,
- Stamina: this.stats.Speed * 10 + this.stats.Power * 2.5 + this.stats.Charm * 2.5
- }
- }
-
- get disabled (): boolean {
- return Object.values(this.vigors).some(val => val <= 0)
- }
-
- effectiveDamage (damage: Damage): Damage {
- const newDamages: DamageInstance[] = []
- damage.damages.forEach(instance => {
- const factor = instance.type === DamageType.Heal ? -1 : 1
- const baseResistance: number = this.resistanceTo(instance.type)
- const resistance = baseResistance * factor
- newDamages.push({
- amount: instance.amount * resistance,
- target: instance.target,
- type: instance.type
- })
- })
-
- return new Damage(...newDamages)
- }
-
- takeDamage (damage: Damage): LogEntry {
- // first, we record health to decide if the entity just died
- const startHealth = this.vigors.Health
-
- damage = this.effectiveDamage(damage)
-
- damage.damages.forEach(instance => {
- if (instance.target in Vigor) {
- // just deal damage
- this.vigors[instance.target as Vigor] -= instance.amount
- } else if (instance.target in Stat) {
- // drain the stats, then deal damage to match
- const startVigors = this.maxVigors
- this.stats[instance.target as Stat] -= instance.amount
- const endVigors = this.maxVigors
-
- Object.keys(Vigor).map(vigor => {
- this.vigors[vigor as Vigor] -= startVigors[vigor as Vigor] - endVigors[vigor as Vigor]
- })
- }
- })
-
- Object.keys(Vigor).forEach(vigorStr => {
- const vigor = vigorStr as Vigor
- if (this.vigors[vigor] > this.maxVigors[vigor]) {
- this.vigors[vigor] = this.maxVigors[vigor]
- }
- })
-
- if (this.vigors.Health <= -this.maxVigors.Health) {
- this.destroyed = true
- }
-
- if (this.vigors.Health <= 0 && startHealth > 0) {
- return this.destroy()
- } else {
- return new LogLine()
- }
- }
-
- toString (): string {
- return this.name.toString()
- }
-
- abstract destroy (): LogEntry;
- }
|