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.
 
 
 
 
 

342 line
8.7 KiB

  1. import { Place, Choice, Direction, World } from '@/game/world'
  2. import { ProperNoun, ImproperNoun, MalePronouns, FemalePronouns, TheyPronouns } from '@/game/language'
  3. import { Encounter, Stat, Damage, DamageType, Vigor, Side } from '@/game/combat'
  4. import * as Items from '@/game/items'
  5. import { LogLine, nilLog, LogLines } from '@/game/interface'
  6. import { Creature } from '@/game/creature'
  7. import { DevourAction } from '@/game/combat/actions'
  8. import { InstantDigestionEffect, SurrenderEffect } from '@/game/combat/effects'
  9. import moment from 'moment'
  10. import { VoreAI } from '@/game/ai'
  11. import { DeliciousPerk } from '@/game/combat/perks'
  12. import Human from '../creatures/human'
  13. import Werewolf from '../creatures/monsters/werewolf'
  14. function makeParty (): Creature[] {
  15. const fighter = new Human(new ProperNoun("Redgar"), MalePronouns, {
  16. stats: {
  17. Toughness: 20,
  18. Power: 20,
  19. Reflexes: 15,
  20. Agility: 15,
  21. Willpower: 15,
  22. Charm: 10
  23. }
  24. })
  25. fighter.title = "Lv. 6 Fighter"
  26. fighter.equip(new Items.Sword(), Items.EquipmentSlot.MainHand)
  27. const rogue = new Human(new ProperNoun('Lidda'), FemalePronouns, {
  28. stats: {
  29. Toughness: 10,
  30. Power: 15,
  31. Reflexes: 20,
  32. Agility: 20,
  33. Willpower: 15,
  34. Charm: 20
  35. }
  36. })
  37. rogue.title = "Lv. 5 Rogue"
  38. rogue.equip(new Items.Dagger(), Items.EquipmentSlot.MainHand)
  39. const wizard = new Human(new ProperNoun('Mialee'), FemalePronouns, {
  40. stats: {
  41. Toughness: 10,
  42. Power: 10,
  43. Reflexes: 15,
  44. Agility: 15,
  45. Willpower: 20,
  46. Charm: 25
  47. }
  48. })
  49. wizard.title = "Lv. 6 Wizard"
  50. wizard.equip(new Items.Wand(), Items.EquipmentSlot.MainHand)
  51. const cleric = new Human(new ProperNoun('Jozan'), MalePronouns, {
  52. stats: {
  53. Toughness: 15,
  54. Power: 15,
  55. Reflexes: 10,
  56. Agility: 10,
  57. Willpower: 20,
  58. Charm: 15
  59. }
  60. })
  61. cleric.title = "Lv. 5 Cleric"
  62. cleric.equip(new Items.Mace(), Items.EquipmentSlot.MainHand)
  63. return [fighter, cleric, rogue, wizard]
  64. }
  65. export const Town = (): Place => {
  66. const home = new Place(
  67. new ProperNoun("Home"),
  68. "A very home-y place"
  69. )
  70. const debug = new Place(
  71. new ProperNoun("Debug Room"),
  72. "Where weird stuff happens"
  73. )
  74. const alley = new Place(
  75. new ImproperNoun('alley'),
  76. "A spooky alley"
  77. )
  78. const westRoad = new Place(
  79. new ImproperNoun('road'),
  80. "West of town"
  81. )
  82. const woods = new Place(
  83. new ImproperNoun('woods'),
  84. "Scary woods"
  85. )
  86. const bosses = new Place(
  87. new ProperNoun("BOSS ZONE"),
  88. "Extra scary"
  89. )
  90. const square = new Place(
  91. new ProperNoun("Central Square"),
  92. "The center of town"
  93. )
  94. home.choices.push(
  95. new Choice(
  96. "Nap",
  97. "Zzzzzz",
  98. (world) => {
  99. return new LogLines(
  100. `You lie down for a nice nap...`,
  101. world.advance(moment.duration(1, "hour"))
  102. )
  103. }
  104. )
  105. )
  106. home.choices.push(
  107. new Choice(
  108. "Heal",
  109. "Become not dead and/or eaten",
  110. (world, executor) => {
  111. Object.keys(Vigor).forEach(vigor => {
  112. executor.vigors[vigor as Vigor] = executor.maxVigors[vigor as Vigor]
  113. })
  114. if (executor.containedIn !== null) {
  115. executor.containedIn.release(executor)
  116. }
  117. executor.statusEffects.forEach(effect => {
  118. executor.removeEffect(effect)
  119. })
  120. executor.destroyed = false
  121. return new LogLine(`You're healthy again`)
  122. }
  123. )
  124. )
  125. home.choices.push(
  126. new Choice(
  127. "Grab potions",
  128. "Grab some potions",
  129. (world, executor) => {
  130. executor.items.push(new Items.HealthPotion())
  131. executor.items.push(new Items.AcidPotion())
  132. executor.items.push(new Items.ShrinkPotion())
  133. executor.items.push(new Items.StrengthPotion())
  134. return new LogLine("You grab some potions")
  135. }
  136. )
  137. )
  138. square.choices.push(
  139. new Choice(
  140. "Eat someone",
  141. "Slurp",
  142. (world, executor) => {
  143. const snack = new Human(new ProperNoun(["Snack", "Treat", "Tasty", "Dinner", "Appetizer"][Math.floor(Math.random() * 5)]), [MalePronouns, FemalePronouns, TheyPronouns][Math.floor(Math.random() * 3)])
  144. snack.applyEffect(new SurrenderEffect())
  145. const options = executor.validActions(snack).filter(action => action instanceof DevourAction)
  146. return options[Math.floor(options.length * Math.random())].execute(executor, snack)
  147. }
  148. )
  149. )
  150. square.choices.push(
  151. new Choice(
  152. "Fight someone",
  153. "Ow",
  154. (world) => {
  155. const enemy = new Human(new ProperNoun("Nerd"), TheyPronouns)
  156. enemy.side = Side.Monsters
  157. enemy.ai = new VoreAI(enemy)
  158. enemy.equip(new Items.Sword(), Items.EquipmentSlot.MainHand)
  159. enemy.addPerk(new DeliciousPerk())
  160. const encounter = new Encounter(
  161. {
  162. name: "Fight some tasty nerd",
  163. intro: () => new LogLine(`You find some nerd to fight.`)
  164. },
  165. [world.player, enemy].concat(world.party)
  166. )
  167. world.encounter = encounter
  168. return nilLog
  169. }
  170. )
  171. )
  172. square.choices.push(
  173. new Choice(
  174. "Recruit someone",
  175. "Not ow",
  176. (world) => {
  177. const ally = new Human(new ProperNoun("Ally"), TheyPronouns)
  178. ally.side = Side.Heroes
  179. ally.ai = new VoreAI(ally)
  180. ally.equip(new Items.Sword(), Items.EquipmentSlot.MainHand)
  181. world.party.push(ally)
  182. return new LogLine(`You recruit a nerd`)
  183. }
  184. )
  185. )
  186. square.choices.push(
  187. new Choice(
  188. "Buy a shiny rock",
  189. "This rock has no use.",
  190. (world, executor) => {
  191. if (executor.wallet.Gold >= 500) {
  192. executor.wallet.Gold -= 500
  193. executor.items.push(
  194. new Items.KeyItem(new ProperNoun("Shiny Rock"), "Very shiny")
  195. )
  196. return new LogLine(`You buy a shiny rock`)
  197. } else {
  198. return new LogLine(`Shiny rocks are 500 gold coins, loser!`)
  199. }
  200. }
  201. )
  202. )
  203. debug.choices.push(
  204. new Choice(
  205. "Cut stats",
  206. "Make your stats less good-er",
  207. (world, executor) => {
  208. Object.keys(Stat).forEach(stat => {
  209. executor.baseStats[stat as Stat] -= 5
  210. executor.takeDamage(new Damage(
  211. { amount: 5, target: (stat as Stat), type: DamageType.Pure }
  212. ))
  213. })
  214. return new LogLine(`You're weaker now`)
  215. }
  216. )
  217. )
  218. debug.choices.push(
  219. new Choice(
  220. "Boost stats",
  221. "Make your stats more good-er",
  222. (world, executor) => {
  223. Object.keys(Stat).forEach(stat => {
  224. executor.baseStats[stat as Stat] += 5
  225. executor.takeDamage(new Damage(
  226. { amount: 5, target: (stat as Stat), type: DamageType.Heal }
  227. ))
  228. })
  229. return new LogLine(`You're stronger now`)
  230. }
  231. )
  232. )
  233. debug.choices.push(
  234. new Choice(
  235. "Grow",
  236. "Make yourself larger",
  237. (world, executor) => {
  238. executor.voreStats.Mass *= 1.5
  239. return new LogLine(`You're larger now`)
  240. }
  241. )
  242. )
  243. debug.choices.push(
  244. new Choice(
  245. "Shrink",
  246. "Make yourself smaller",
  247. (world, executor) => {
  248. executor.voreStats.Mass /= 1.5
  249. return new LogLine(`You're smaller now`)
  250. }
  251. )
  252. )
  253. debug.choices.push(
  254. new Choice(
  255. "Instant Digestion",
  256. "Make your stomach REALLY powerful",
  257. (world, executor) => {
  258. executor.applyEffect(new InstantDigestionEffect())
  259. return new LogLine(`You're really gonna melt people now.`)
  260. }
  261. )
  262. )
  263. debug.choices.push(
  264. new Choice(
  265. "Set Name",
  266. "Set your name",
  267. (world, executor) => {
  268. const input = prompt("Enter a name")
  269. if (input !== null) {
  270. executor.baseName = new ProperNoun(input)
  271. return new LogLine(`Your new name is ${executor.baseName}.`)
  272. } else {
  273. return new LogLine(`nvm`)
  274. }
  275. }
  276. )
  277. )
  278. woods.choices.push(
  279. new Choice(
  280. "Fight a werewolf",
  281. "Go fight a werewolf",
  282. (world, executor) => {
  283. const enemy = new Werewolf()
  284. enemy.location = world.player.location
  285. const encounter = new Encounter(
  286. {
  287. name: "Fight some tasty nerd",
  288. intro: () => new LogLine(`A werewolf draws near!`)
  289. },
  290. [world.player, enemy].concat(world.party)
  291. )
  292. world.encounter = encounter
  293. return nilLog
  294. }
  295. )
  296. )
  297. debug.choices.push(
  298. new Choice(
  299. "Add money",
  300. "Get some money",
  301. (world, executor) => {
  302. executor.wallet.Gold += 1000
  303. return new LogLine(`$$$$$$$$$$$$$$$$$`)
  304. }
  305. )
  306. )
  307. home.biconnect(Direction.South, debug)
  308. debug.biconnect(Direction.South, bosses)
  309. home.biconnect(Direction.North, square)
  310. westRoad.biconnect(Direction.South, woods)
  311. square.biconnect(Direction.West, westRoad)
  312. return home
  313. }