Feast 2.0!
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

425 lines
10 KiB

  1. import { Place, Choice, Direction, World } from '../world'
  2. import { ProperNoun, ImproperNoun, MalePronouns, FemalePronouns, TheyPronouns } from '../language'
  3. import { Encounter, Stat, Damage, DamageType, Vigor, Side } from '../combat'
  4. import * as Creatures from '../creatures'
  5. import * as Items from '../items'
  6. import { LogLine, nilLog, LogLines } from '../interface'
  7. import { Creature } from '../creature'
  8. import { DevourAction } from '../combat/actions'
  9. import { SurrenderEffect } from '../combat/effects'
  10. import moment from 'moment'
  11. import { VoreAI } from '../ai'
  12. function makeParty (): Creature[] {
  13. const fighter = new Creatures.Human(new ProperNoun("Redgar"), MalePronouns, {
  14. stats: {
  15. Toughness: 20,
  16. Power: 20,
  17. Reflexes: 15,
  18. Agility: 15,
  19. Willpower: 15,
  20. Charm: 10
  21. }
  22. })
  23. fighter.title = "Lv. 6 Fighter"
  24. fighter.equip(new Items.Sword(), Items.EquipmentSlot.MainHand)
  25. const rogue = new Creatures.Human(new ProperNoun('Lidda'), FemalePronouns, {
  26. stats: {
  27. Toughness: 10,
  28. Power: 15,
  29. Reflexes: 20,
  30. Agility: 20,
  31. Willpower: 15,
  32. Charm: 20
  33. }
  34. })
  35. rogue.title = "Lv. 5 Rogue"
  36. rogue.equip(new Items.Dagger(), Items.EquipmentSlot.MainHand)
  37. const wizard = new Creatures.Human(new ProperNoun('Mialee'), FemalePronouns, {
  38. stats: {
  39. Toughness: 10,
  40. Power: 10,
  41. Reflexes: 15,
  42. Agility: 15,
  43. Willpower: 20,
  44. Charm: 25
  45. }
  46. })
  47. wizard.title = "Lv. 6 Wizard"
  48. wizard.equip(new Items.Wand(), Items.EquipmentSlot.MainHand)
  49. const cleric = new Creatures.Human(new ProperNoun('Jozan'), MalePronouns, {
  50. stats: {
  51. Toughness: 15,
  52. Power: 15,
  53. Reflexes: 10,
  54. Agility: 10,
  55. Willpower: 20,
  56. Charm: 15
  57. }
  58. })
  59. cleric.title = "Lv. 5 Cleric"
  60. cleric.equip(new Items.Mace(), Items.EquipmentSlot.MainHand)
  61. return [fighter, cleric, rogue, wizard]
  62. }
  63. export const Town = (): Place => {
  64. const home = new Place(
  65. new ProperNoun('Your home'),
  66. "A very home-y place"
  67. )
  68. const debug = new Place(
  69. new ProperNoun("Debug Room"),
  70. "Where weird stuff happens"
  71. )
  72. const westAve = new Place(
  73. new ImproperNoun('West Avenue'),
  74. "Streets of Sim City"
  75. )
  76. const northAve = new Place(
  77. new ImproperNoun('North Avenue'),
  78. "Streets of Sim City"
  79. )
  80. const eastAve = new Place(
  81. new ImproperNoun('East Avenue'),
  82. "Streets of Sim City"
  83. )
  84. const southAve = new Place(
  85. new ImproperNoun('South Avenue'),
  86. "Streets of Sim City"
  87. )
  88. const alley = new Place(
  89. new ImproperNoun('alley'),
  90. "A spooky alley"
  91. )
  92. const westRoad = new Place(
  93. new ImproperNoun('road'),
  94. "West of town"
  95. )
  96. const woods = new Place(
  97. new ImproperNoun('woods'),
  98. "Scary woods"
  99. )
  100. const bosses = new Place(
  101. new ProperNoun("BOSS ZONE"),
  102. "Extra scary"
  103. )
  104. const square = new Place(
  105. new ProperNoun("Central Square"),
  106. "The center of town"
  107. )
  108. woods.choices.push(
  109. new Choice(
  110. "Fight a wolf",
  111. "yolo",
  112. (world, executor) => {
  113. world.encounter = new Encounter(
  114. {
  115. name: "You punched a wolf",
  116. intro: (world: World) => new LogLine(`You punched a wolf. The wolf is angry.`)
  117. },
  118. [executor, new Creatures.Wolf()]
  119. )
  120. return new LogLine(`FIGHT TIME`)
  121. }
  122. )
  123. )
  124. woods.choices.push(
  125. new Choice(
  126. "Fight a werewolf",
  127. "yolo",
  128. (world, executor) => {
  129. world.encounter = new Encounter(
  130. {
  131. name: "You punched a werewolf",
  132. intro: (world: World) => new LogLine(`You punched a werewolf. The werewolf is angry.`)
  133. },
  134. [executor, new Creatures.Werewolf()]
  135. )
  136. return new LogLine(`FIGHT TIME`)
  137. }
  138. )
  139. )
  140. woods.choices.push(
  141. new Choice(
  142. "Fight a dragon",
  143. "yolo",
  144. (world, executor) => {
  145. world.encounter = new Encounter(
  146. {
  147. name: "You punched a dragon",
  148. intro: (world: World) => new LogLine(`You punched a dragon. The dragon is angry.`)
  149. },
  150. [executor, new Creatures.Dragon()]
  151. )
  152. return new LogLine(`FIGHT TIME`)
  153. }
  154. )
  155. )
  156. const bossEncounters = [
  157. new Encounter(
  158. { name: "Withers & Kenzie", intro: (world: World) => nilLog },
  159. makeParty().concat([new Creatures.Withers(), new Creatures.Kenzie()])
  160. ),
  161. new Encounter(
  162. { name: "Goldeneye", intro: (world: World) => nilLog },
  163. makeParty().concat([new Creatures.Goldeneye()])
  164. ),
  165. new Encounter(
  166. { name: "Large Wah", intro: (world: World) => nilLog },
  167. makeParty().concat([new Creatures.Shingo()])
  168. ),
  169. new Encounter(
  170. { name: "Cafat", intro: (world: World) => nilLog },
  171. makeParty().concat([new Creatures.Cafat()])
  172. )
  173. ]
  174. home.choices.push(
  175. new Choice(
  176. "Nap",
  177. "Zzzzzz",
  178. (world, executor) => {
  179. return new LogLines(
  180. `You lie down for a nice nap...`,
  181. world.advance(moment.duration(1, "hour"))
  182. )
  183. }
  184. )
  185. )
  186. home.choices.push(
  187. new Choice(
  188. "Heal",
  189. "Become not dead and/or eaten",
  190. (world, executor) => {
  191. Object.keys(Vigor).forEach(vigor => {
  192. executor.vigors[vigor as Vigor] = executor.maxVigors[vigor as Vigor]
  193. })
  194. if (executor.containedIn !== null) {
  195. executor.containedIn.release(executor)
  196. }
  197. executor.statusEffects.forEach(effect => {
  198. executor.removeEffect(effect)
  199. })
  200. return new LogLine(`You're healthy again`)
  201. }
  202. )
  203. )
  204. westAve.choices.push(
  205. new Choice(
  206. "Eat someone",
  207. "Slurp",
  208. (world, executor) => {
  209. const snack = new Creatures.Human(new ProperNoun(["Snack", "Treat", "Tasty", "Dinner", "Appetizer"][Math.floor(Math.random() * 5)]), TheyPronouns)
  210. snack.applyEffect(new SurrenderEffect())
  211. const options = executor.validActions(snack).filter(action => action instanceof DevourAction)
  212. return options[Math.floor(options.length * Math.random())].execute(executor, snack)
  213. }
  214. )
  215. )
  216. westAve.choices.push(
  217. new Choice(
  218. "Fight someone",
  219. "Ow",
  220. (world, executor) => {
  221. const enemy = new Creatures.Human(new ProperNoun("Nerd"), TheyPronouns)
  222. enemy.side = Side.Monsters
  223. enemy.ai = new VoreAI()
  224. const encounter = new Encounter(
  225. {
  226. name: "Fight some nerd",
  227. intro: world => new LogLine(`You find some nerd to fight.`)
  228. },
  229. [world.player, enemy]
  230. )
  231. world.encounter = encounter
  232. return nilLog
  233. }
  234. )
  235. )
  236. square.choices.push(
  237. new Choice(
  238. "Fight Geta",
  239. "yolo",
  240. (world, executor) => {
  241. world.encounter = new Encounter(
  242. {
  243. name: "You punched Geta",
  244. intro: (world: World) => new LogLine(`You punched Geta. Geta is angry.`)
  245. },
  246. [executor, new Creatures.Geta()]
  247. )
  248. return new LogLine(`FIGHT TIME`)
  249. }
  250. )
  251. )
  252. square.choices.push(
  253. new Choice(
  254. "Buy a shiny rock",
  255. "This rock has no use.",
  256. (world, executor) => {
  257. if (executor.wallet.Gold >= 500) {
  258. executor.wallet.Gold -= 500
  259. executor.items.push(
  260. new Items.KeyItem(new ProperNoun("Shiny Rock"), "Very shiny")
  261. )
  262. return new LogLine(`You buy a shiny rock`)
  263. } else {
  264. return new LogLine(`Shiny rocks are 500 gold coins, loser!`)
  265. }
  266. }
  267. )
  268. )
  269. alley.choices.push(
  270. new Choice(
  271. "Kuro",
  272. "Get eaten by a Luxray",
  273. (world, executor) => {
  274. const enemy = new Creatures.Kuro()
  275. enemy.ai = new VoreAI()
  276. const encounter = new Encounter(
  277. {
  278. name: "Luxray time",
  279. intro: world => new LogLine(`Luxray time!`)
  280. },
  281. [world.player, enemy]
  282. )
  283. world.encounter = encounter
  284. return nilLog
  285. }
  286. )
  287. )
  288. bossEncounters.forEach(encounter => {
  289. bosses.choices.push(
  290. new Choice(
  291. encounter.desc.name,
  292. "Boss fight!",
  293. (world, executor) => {
  294. world.encounter = encounter
  295. return nilLog
  296. }
  297. )
  298. )
  299. })
  300. debug.choices.push(
  301. new Choice(
  302. "Cut stats",
  303. "Make your stats less good-er",
  304. (world, executor) => {
  305. Object.keys(Stat).forEach(stat => {
  306. executor.baseStats[stat as Stat] -= 5
  307. executor.takeDamage(new Damage(
  308. { amount: 5, target: (stat as Stat), type: DamageType.Pure }
  309. ))
  310. })
  311. return new LogLine(`You're weaker now`)
  312. }
  313. )
  314. )
  315. debug.choices.push(
  316. new Choice(
  317. "Boost stats",
  318. "Make your stats more good-er",
  319. (world, executor) => {
  320. Object.keys(Stat).forEach(stat => {
  321. executor.baseStats[stat as Stat] += 5
  322. executor.takeDamage(new Damage(
  323. { amount: 5, target: (stat as Stat), type: DamageType.Heal }
  324. ))
  325. })
  326. return new LogLine(`You're stronger now`)
  327. }
  328. )
  329. )
  330. debug.choices.push(
  331. new Choice(
  332. "Grow",
  333. "Make yourself larger",
  334. (world, executor) => {
  335. executor.voreStats.Mass *= 1.5
  336. return new LogLine(`You're larger now`)
  337. }
  338. )
  339. )
  340. debug.choices.push(
  341. new Choice(
  342. "Shrink",
  343. "Make yourself smaller",
  344. (world, executor) => {
  345. executor.voreStats.Mass /= 1.5
  346. return new LogLine(`You're smaller now`)
  347. }
  348. )
  349. )
  350. debug.choices.push(
  351. new Choice(
  352. "Set Name",
  353. "Set your name",
  354. (world, executor) => {
  355. const input = prompt("Enter a name")
  356. if (input !== null) {
  357. executor.baseName = new ProperNoun(input)
  358. return new LogLine(`Your new name is ${executor.baseName}.`)
  359. } else {
  360. return new LogLine(`nvm`)
  361. }
  362. }
  363. )
  364. )
  365. debug.choices.push(
  366. new Choice(
  367. "Add money",
  368. "Get some money",
  369. (world, executor) => {
  370. executor.wallet.Gold += 1000
  371. return new LogLine(`$$$$$$$$$$$$$$$$$`)
  372. }
  373. )
  374. )
  375. home.biconnect(Direction.South, debug)
  376. home.biconnect(Direction.North, westAve)
  377. westAve.biconnect(Direction.West, westRoad)
  378. westAve.biconnect(Direction.North, alley)
  379. westRoad.biconnect(Direction.South, woods)
  380. westRoad.biconnect(Direction.North, bosses)
  381. square.biconnect(Direction.East, eastAve)
  382. square.biconnect(Direction.West, westAve)
  383. square.biconnect(Direction.North, northAve)
  384. square.biconnect(Direction.South, southAve)
  385. return home
  386. }