Feast 2.0!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

110 line
2.8 KiB

  1. import { DamageType, Damage, Combatant, Stats, Action, Vigor } from './combat'
  2. import { Noun, Pronoun } from './language'
  3. import { Pred, Prey, Container, VoreType } from './vore'
  4. export enum POV {First, Third}
  5. export interface Entity {
  6. name: Noun;
  7. pronouns: Pronoun;
  8. perspective: POV;
  9. }
  10. export interface Mortal extends Entity {
  11. vigors: {[key in Vigor]: number};
  12. maxVigors: {[key in Vigor]: number};
  13. disabled: boolean;
  14. resistances: Map<DamageType, number>;
  15. takeDamage: (damage: Damage) => void;
  16. stats: Stats;
  17. status: string;
  18. }
  19. export class Creature implements Mortal, Pred, Prey, Combatant {
  20. vigors = {
  21. [Vigor.Health]: 100,
  22. [Vigor.Stamina]: 100,
  23. [Vigor.Willpower]: 100
  24. }
  25. maxVigors = {
  26. [Vigor.Health]: 100,
  27. [Vigor.Stamina]: 100,
  28. [Vigor.Willpower]: 100
  29. }
  30. get disabled (): boolean {
  31. return Object.values(this.vigors).some(val => val <= 0)
  32. }
  33. resistances: Map<DamageType, number> = new Map()
  34. perspective: POV = POV.Third
  35. containers: Array<Container> = []
  36. actions: Array<Action> = [];
  37. otherActions: Array<Action> = [];
  38. private baseBulk: number;
  39. get bulk (): number {
  40. return this.baseBulk
  41. }
  42. containedIn: Container|null = null;
  43. constructor (public name: Noun, public pronouns: Pronoun, public stats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, bulk: number) {
  44. this.baseBulk = bulk
  45. }
  46. toString (): string {
  47. return this.name.toString()
  48. }
  49. takeDamage (damage: Damage): void {
  50. damage.damages.forEach(instance => {
  51. const resistance: number|undefined = this.resistances.get(instance.type)
  52. if (resistance !== undefined) {
  53. this.vigors[instance.target] -= instance.amount * resistance
  54. } else {
  55. this.vigors[instance.target] -= instance.amount
  56. }
  57. })
  58. }
  59. get status (): string {
  60. if (this.vigors[Vigor.Health] <= -100) {
  61. return "Dead"
  62. }
  63. if (this.vigors[Vigor.Stamina] <= -100) {
  64. return "Unconscious"
  65. }
  66. if (this.vigors[Vigor.Willpower] <= -100) {
  67. return "Broken"
  68. }
  69. if (this.vigors[Vigor.Health] <= 0) {
  70. return "Unconscious"
  71. }
  72. if (this.vigors[Vigor.Stamina] <= 0) {
  73. return "Exhausted"
  74. }
  75. if (this.vigors[Vigor.Willpower] <= 0) {
  76. return "Overpowered"
  77. }
  78. if (this.containedIn !== null) {
  79. return "Devoured"
  80. }
  81. return "Normal"
  82. }
  83. validActions (target: Creature): Array<Action> {
  84. let choices = this.actions.concat(this.containers.flatMap(container => container.actions)).concat(target.otherActions)
  85. if (this.containedIn !== null) {
  86. choices = choices.concat(this.containedIn.actions)
  87. }
  88. return choices.filter(action => {
  89. return action.allowed(this, target)
  90. })
  91. }
  92. }