Feast 2.0!
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 

122 řádky
3.2 KiB

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