@v12-engine/engine 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (951) hide show
  1. package/dist/abilities/amounts.d.ts +28 -0
  2. package/dist/abilities/amounts.js +74 -0
  3. package/dist/abilities/amounts.js.map +1 -0
  4. package/dist/abilities/buffs.d.ts +106 -6
  5. package/dist/abilities/buffs.js +443 -0
  6. package/dist/abilities/buffs.js.map +1 -0
  7. package/dist/abilities/castTold.d.ts +2 -0
  8. package/dist/abilities/castTold.js +66 -0
  9. package/dist/abilities/castTold.js.map +1 -0
  10. package/dist/abilities/chance.d.ts +38 -0
  11. package/dist/abilities/chance.js +77 -0
  12. package/dist/abilities/chance.js.map +1 -0
  13. package/dist/abilities/charges.d.ts +18 -0
  14. package/dist/abilities/charges.js +101 -0
  15. package/dist/abilities/charges.js.map +1 -0
  16. package/dist/abilities/control.d.ts +28 -0
  17. package/dist/abilities/control.js +113 -0
  18. package/dist/abilities/control.js.map +1 -0
  19. package/dist/abilities/dispel.js +51 -0
  20. package/dist/abilities/dispel.js.map +1 -0
  21. package/dist/abilities/effectFields.d.ts +1 -1
  22. package/dist/abilities/effectFields.js +676 -0
  23. package/dist/abilities/effectFields.js.map +1 -0
  24. package/dist/abilities/effectIndex.d.ts +27 -0
  25. package/dist/abilities/effectIndex.js +64 -0
  26. package/dist/abilities/effectIndex.js.map +1 -0
  27. package/dist/abilities/effects/buff.d.ts +9 -3
  28. package/dist/abilities/effects/buff.js +84 -0
  29. package/dist/abilities/effects/buff.js.map +1 -0
  30. package/dist/abilities/effects/conditions.d.ts +2 -0
  31. package/dist/abilities/effects/conditions.js +41 -0
  32. package/dist/abilities/effects/conditions.js.map +1 -0
  33. package/dist/abilities/effects/core.js +54 -0
  34. package/dist/abilities/effects/core.js.map +1 -0
  35. package/dist/abilities/effects/damage.d.ts +1 -1
  36. package/dist/abilities/effects/damage.js +43 -0
  37. package/dist/abilities/effects/damage.js.map +1 -0
  38. package/dist/abilities/effects/heal.d.ts +2 -2
  39. package/dist/abilities/effects/heal.js +51 -0
  40. package/dist/abilities/effects/heal.js.map +1 -0
  41. package/dist/abilities/effects/missile.d.ts +13 -1
  42. package/dist/abilities/effects/missile.js +104 -0
  43. package/dist/abilities/effects/missile.js.map +1 -0
  44. package/dist/abilities/effects/morph.d.ts +5 -0
  45. package/dist/abilities/effects/morph.js +43 -0
  46. package/dist/abilities/effects/morph.js.map +1 -0
  47. package/dist/abilities/effects/moves.d.ts +16 -4
  48. package/dist/abilities/effects/moves.js +212 -0
  49. package/dist/abilities/effects/moves.js.map +1 -0
  50. package/dist/abilities/effects/passives.d.ts +19 -9
  51. package/dist/abilities/effects/passives.js +131 -0
  52. package/dist/abilities/effects/passives.js.map +1 -0
  53. package/dist/abilities/effects/proxy.d.ts +5 -0
  54. package/dist/abilities/effects/proxy.js +60 -0
  55. package/dist/abilities/effects/proxy.js.map +1 -0
  56. package/dist/abilities/effects/sight.d.ts +2 -2
  57. package/dist/abilities/effects/sight.js +39 -0
  58. package/dist/abilities/effects/sight.js.map +1 -0
  59. package/dist/abilities/effects/spawn.d.ts +5 -2
  60. package/dist/abilities/effects/spawn.js +40 -0
  61. package/dist/abilities/effects/spawn.js.map +1 -0
  62. package/dist/abilities/effects/timed.d.ts +2 -2
  63. package/dist/abilities/effects/timed.js +96 -0
  64. package/dist/abilities/effects/timed.js.map +1 -0
  65. package/dist/abilities/effects/trade.d.ts +1 -1
  66. package/dist/abilities/effects/trade.js +25 -0
  67. package/dist/abilities/effects/trade.js.map +1 -0
  68. package/dist/abilities/effects.d.ts +97 -23
  69. package/dist/abilities/effects.js +860 -0
  70. package/dist/abilities/effects.js.map +1 -0
  71. package/dist/abilities/land.d.ts +38 -4
  72. package/dist/abilities/land.js +189 -0
  73. package/dist/abilities/land.js.map +1 -0
  74. package/dist/abilities/recast.d.ts +45 -0
  75. package/dist/abilities/recast.js +118 -0
  76. package/dist/abilities/recast.js.map +1 -0
  77. package/dist/abilities/scaled.js +40 -0
  78. package/dist/abilities/scaled.js.map +1 -0
  79. package/dist/abilities/screen.d.ts +6 -0
  80. package/dist/abilities/screen.js +83 -0
  81. package/dist/abilities/screen.js.map +1 -0
  82. package/dist/abilities/shapes.d.ts +66 -0
  83. package/dist/abilities/shapes.js +122 -0
  84. package/dist/abilities/shapes.js.map +1 -0
  85. package/dist/abilities/text.d.ts +14 -2
  86. package/dist/abilities/text.js +204 -0
  87. package/dist/abilities/text.js.map +1 -0
  88. package/dist/abilities/triggers.d.ts +98 -0
  89. package/dist/abilities/triggers.js +351 -0
  90. package/dist/abilities/triggers.js.map +1 -0
  91. package/dist/abilityChanges.d.ts +131 -0
  92. package/dist/abilityChanges.js +345 -0
  93. package/dist/abilityChanges.js.map +1 -0
  94. package/dist/ai/area.d.ts +4 -1
  95. package/dist/ai/brain.d.ts +4 -1
  96. package/dist/ai/brain.js +844 -0
  97. package/dist/ai/brain.js.map +1 -0
  98. package/dist/ai/budget.js +74 -0
  99. package/dist/ai/budget.js.map +1 -0
  100. package/dist/ai/checks.d.ts +9 -1
  101. package/dist/ai/checks.js +242 -0
  102. package/dist/ai/checks.js.map +1 -0
  103. package/dist/ai/computer.d.ts +11 -4
  104. package/dist/ai/computer.js +251 -0
  105. package/dist/ai/computer.js.map +1 -0
  106. package/dist/ai/defence.d.ts +4 -0
  107. package/dist/ai/defence.js +430 -0
  108. package/dist/ai/defence.js.map +1 -0
  109. package/dist/ai/define.d.ts +3 -2
  110. package/dist/ai/define.js +31 -0
  111. package/dist/ai/define.js.map +1 -0
  112. package/dist/ai/economy.d.ts +10 -7
  113. package/dist/ai/economy.js +780 -0
  114. package/dist/ai/economy.js.map +1 -0
  115. package/dist/ai/geometry.js +38 -0
  116. package/dist/ai/geometry.js.map +1 -0
  117. package/dist/ai/goals.d.ts +1 -0
  118. package/dist/ai/goals.js +560 -0
  119. package/dist/ai/goals.js.map +1 -0
  120. package/dist/ai/knowledge.d.ts +72 -7
  121. package/dist/ai/knowledge.js +804 -0
  122. package/dist/ai/knowledge.js.map +1 -0
  123. package/dist/ai/lanes.d.ts +10 -2
  124. package/dist/ai/lanes.js +715 -0
  125. package/dist/ai/lanes.js.map +1 -0
  126. package/dist/ai/melee/build.js +264 -0
  127. package/dist/ai/melee/build.js.map +1 -0
  128. package/dist/ai/melee/goals.d.ts +7 -0
  129. package/dist/ai/melee/goals.js +720 -0
  130. package/dist/ai/melee/goals.js.map +1 -0
  131. package/dist/ai/melee/heroes.js +68 -0
  132. package/dist/ai/melee/heroes.js.map +1 -0
  133. package/dist/ai/melee/index.d.ts +1 -1
  134. package/dist/ai/melee/index.js +51 -0
  135. package/dist/ai/melee/index.js.map +1 -0
  136. package/dist/ai/melee/production.js +29 -0
  137. package/dist/ai/melee/production.js.map +1 -0
  138. package/dist/ai/melee/surrender.js +64 -0
  139. package/dist/ai/melee/surrender.js.map +1 -0
  140. package/dist/ai/micro.d.ts +9 -0
  141. package/dist/ai/micro.js +1316 -0
  142. package/dist/ai/micro.js.map +1 -0
  143. package/dist/ai/mission.d.ts +9 -2
  144. package/dist/ai/mission.js +538 -0
  145. package/dist/ai/mission.js.map +1 -0
  146. package/dist/ai/missionRules.d.ts +1 -1
  147. package/dist/ai/missionRules.js +26 -0
  148. package/dist/ai/missionRules.js.map +1 -0
  149. package/dist/ai/module.d.ts +6 -2
  150. package/dist/ai/module.js +37 -0
  151. package/dist/ai/module.js.map +1 -0
  152. package/dist/ai/options.d.ts +3 -3
  153. package/dist/ai/plans/build.d.ts +20 -1
  154. package/dist/ai/plans/build.js +608 -0
  155. package/dist/ai/plans/build.js.map +1 -0
  156. package/dist/ai/plans/placement.d.ts +4 -1
  157. package/dist/ai/plans/placement.js +295 -0
  158. package/dist/ai/plans/placement.js.map +1 -0
  159. package/dist/ai/plans/plans.d.ts +9 -0
  160. package/dist/ai/plans/plans.js +110 -0
  161. package/dist/ai/plans/plans.js.map +1 -0
  162. package/dist/ai/plans/production.d.ts +14 -2
  163. package/dist/ai/plans/production.js +434 -0
  164. package/dist/ai/plans/production.js.map +1 -0
  165. package/dist/ai/plans/purse.d.ts +6 -3
  166. package/dist/ai/plans/purse.js +139 -0
  167. package/dist/ai/plans/purse.js.map +1 -0
  168. package/dist/ai/plans/tech.d.ts +6 -0
  169. package/dist/ai/plans/tech.js +122 -0
  170. package/dist/ai/plans/tech.js.map +1 -0
  171. package/dist/ai/profiles.d.ts +4 -4
  172. package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
  173. package/dist/ai/profiles.js.map +1 -0
  174. package/dist/ai/reach.js +54 -0
  175. package/dist/ai/reach.js.map +1 -0
  176. package/dist/ai/report.d.ts +8 -0
  177. package/dist/ai/report.js +87 -0
  178. package/dist/ai/report.js.map +1 -0
  179. package/dist/ai/roles.d.ts +4 -0
  180. package/dist/ai/roles.js +207 -0
  181. package/dist/ai/roles.js.map +1 -0
  182. package/dist/ai/rules.d.ts +8 -2
  183. package/dist/ai/rules.js +416 -0
  184. package/dist/ai/rules.js.map +1 -0
  185. package/dist/ai/scouting.d.ts +6 -0
  186. package/dist/ai/scouting.js +324 -0
  187. package/dist/ai/scouting.js.map +1 -0
  188. package/dist/ai/settings.js +99 -0
  189. package/dist/ai/settings.js.map +1 -0
  190. package/dist/ai/squads.d.ts +21 -2
  191. package/dist/ai/squads.js +916 -0
  192. package/dist/ai/squads.js.map +1 -0
  193. package/dist/ai/strength.js +320 -0
  194. package/dist/ai/strength.js.map +1 -0
  195. package/dist/ai/task.d.ts +3 -1
  196. package/dist/ai/task.js +17 -0
  197. package/dist/ai/task.js.map +1 -0
  198. package/dist/ai/tasks/attack.js +24 -0
  199. package/dist/ai/tasks/attack.js.map +1 -0
  200. package/dist/ai/tasks/capture.d.ts +3 -3
  201. package/dist/ai/tasks/capture.js +37 -0
  202. package/dist/ai/tasks/capture.js.map +1 -0
  203. package/dist/ai/tasks/creep.js +29 -0
  204. package/dist/ai/tasks/creep.js.map +1 -0
  205. package/dist/ai/tasks/defend.js +61 -0
  206. package/dist/ai/tasks/defend.js.map +1 -0
  207. package/dist/ai/tasks/drop.js +81 -0
  208. package/dist/ai/tasks/drop.js.map +1 -0
  209. package/dist/ai/tasks/escort.js +59 -0
  210. package/dist/ai/tasks/escort.js.map +1 -0
  211. package/dist/ai/tasks/gather.js +48 -0
  212. package/dist/ai/tasks/gather.js.map +1 -0
  213. package/dist/ai/tasks/harass.js +39 -0
  214. package/dist/ai/tasks/harass.js.map +1 -0
  215. package/dist/ai/tasks/hold.js +32 -0
  216. package/dist/ai/tasks/hold.js.map +1 -0
  217. package/dist/ai/tasks/index.js +34 -0
  218. package/dist/ai/tasks/index.js.map +1 -0
  219. package/dist/ai/tasks/move.js +26 -0
  220. package/dist/ai/tasks/move.js.map +1 -0
  221. package/dist/ai/tasks/patrol.js +59 -0
  222. package/dist/ai/tasks/patrol.js.map +1 -0
  223. package/dist/ai/tasks/retreat.js +28 -0
  224. package/dist/ai/tasks/retreat.js.map +1 -0
  225. package/dist/ai/tasks/scout.js +73 -0
  226. package/dist/ai/tasks/scout.js.map +1 -0
  227. package/dist/ai/tasks/shared.d.ts +1 -1
  228. package/dist/ai/tasks/shared.js +137 -0
  229. package/dist/ai/tasks/shared.js.map +1 -0
  230. package/dist/ai/team.d.ts +18 -1
  231. package/dist/ai/team.js +492 -0
  232. package/dist/ai/team.js.map +1 -0
  233. package/dist/ai/threat.d.ts +6 -0
  234. package/dist/ai/threat.js +206 -0
  235. package/dist/ai/threat.js.map +1 -0
  236. package/dist/ai/view.d.ts +21 -7
  237. package/dist/ai/view.js +677 -0
  238. package/dist/ai/view.js.map +1 -0
  239. package/dist/ai/waves.d.ts +6 -0
  240. package/dist/ai/waves.js +410 -0
  241. package/dist/ai/waves.js.map +1 -0
  242. package/dist/ai.js +54 -6239
  243. package/dist/aiTesting.d.ts +6 -3
  244. package/dist/aiTesting.js +229 -0
  245. package/dist/aiTesting.js.map +1 -0
  246. package/dist/areas.d.ts +4 -1
  247. package/dist/areas.js +295 -0
  248. package/dist/areas.js.map +1 -0
  249. package/dist/attacks.d.ts +3 -3
  250. package/dist/attacks.js +127 -0
  251. package/dist/attacks.js.map +1 -0
  252. package/dist/burning.d.ts +267 -0
  253. package/dist/burning.js +795 -0
  254. package/dist/burning.js.map +1 -0
  255. package/dist/bytes.js +21 -0
  256. package/dist/bytes.js.map +1 -0
  257. package/dist/callings.d.ts +71 -0
  258. package/dist/callings.js +157 -0
  259. package/dist/callings.js.map +1 -0
  260. package/dist/cameraOrders.d.ts +78 -0
  261. package/dist/cameraOrders.js +114 -0
  262. package/dist/cameraOrders.js.map +1 -0
  263. package/dist/camps.d.ts +70 -4
  264. package/dist/camps.js +501 -0
  265. package/dist/camps.js.map +1 -0
  266. package/dist/capture.d.ts +15 -3
  267. package/dist/capture.js +304 -0
  268. package/dist/capture.js.map +1 -0
  269. package/dist/cellLayers.d.ts +78 -13
  270. package/dist/cellLayers.js +275 -0
  271. package/dist/cellLayers.js.map +1 -0
  272. package/dist/cellPatches.d.ts +24 -0
  273. package/dist/cellPatches.js +73 -0
  274. package/dist/cellPatches.js.map +1 -0
  275. package/dist/cinematics.d.ts +10 -5
  276. package/dist/cinematics.js +161 -0
  277. package/dist/cinematics.js.map +1 -0
  278. package/dist/clock.d.ts +2 -2
  279. package/dist/clock.js +78 -0
  280. package/dist/clock.js.map +1 -0
  281. package/dist/commands.d.ts +36 -4
  282. package/dist/commands.js +636 -0
  283. package/dist/commands.js.map +1 -0
  284. package/dist/components.d.ts +31 -10
  285. package/dist/components.js +74 -0
  286. package/dist/components.js.map +1 -0
  287. package/dist/computers.d.ts +4 -4
  288. package/dist/computers.js +194 -0
  289. package/dist/computers.js.map +1 -0
  290. package/dist/concealment.d.ts +25 -2
  291. package/dist/concealment.js +409 -0
  292. package/dist/concealment.js.map +1 -0
  293. package/dist/coreComponents.js +130 -0
  294. package/dist/coreComponents.js.map +1 -0
  295. package/dist/createGame.d.ts +306 -0
  296. package/dist/createGame.js +405 -0
  297. package/dist/createGame.js.map +1 -0
  298. package/dist/dashing.d.ts +18 -2
  299. package/dist/dashing.js +41 -0
  300. package/dist/dashing.js.map +1 -0
  301. package/dist/debug.d.ts +8 -0
  302. package/dist/debug.js +5 -3
  303. package/dist/debug2.js +76 -0
  304. package/dist/debug2.js.map +1 -0
  305. package/dist/debugCommands.d.ts +6 -6
  306. package/dist/debugCommands.js +537 -0
  307. package/dist/debugCommands.js.map +1 -0
  308. package/dist/debugging.d.ts +1 -0
  309. package/dist/defaultSets.d.ts +183 -0
  310. package/dist/defaultSets.js +216 -0
  311. package/dist/defaultSets.js.map +1 -0
  312. package/dist/definitions.d.ts +6 -0
  313. package/dist/definitions.js +78 -0
  314. package/dist/definitions.js.map +1 -0
  315. package/dist/defs.d.ts +1895 -165
  316. package/dist/defs.js +380 -0
  317. package/dist/defs.js.map +1 -0
  318. package/dist/denying.d.ts +4 -4
  319. package/dist/denying.js +106 -0
  320. package/dist/denying.js.map +1 -0
  321. package/dist/destructibles.d.ts +2 -2
  322. package/dist/destructibles.js +36 -0
  323. package/dist/destructibles.js.map +1 -0
  324. package/dist/determinism.d.ts +4 -4
  325. package/dist/determinism.js +247 -0
  326. package/dist/determinism.js.map +1 -0
  327. package/dist/dialog.d.ts +17 -2
  328. package/dist/dialog.js +108 -0
  329. package/dist/dialog.js.map +1 -0
  330. package/dist/effectRefs.js +28 -0
  331. package/dist/effectRefs.js.map +1 -0
  332. package/dist/effects.d.ts +27 -11
  333. package/dist/effects.js +110 -0
  334. package/dist/effects.js.map +1 -0
  335. package/dist/endings.d.ts +1 -1
  336. package/dist/endings.js +78 -0
  337. package/dist/endings.js.map +1 -0
  338. package/dist/engagement.d.ts +40 -6
  339. package/dist/engagement.js +530 -0
  340. package/dist/engagement.js.map +1 -0
  341. package/dist/engineEvents.d.ts +72 -9
  342. package/dist/engineEvents.js +520 -0
  343. package/dist/engineEvents.js.map +1 -0
  344. package/dist/entity.d.ts +275 -26
  345. package/dist/entity.js +441 -0
  346. package/dist/entity.js.map +1 -0
  347. package/dist/entityIndex.d.ts +10 -3
  348. package/dist/entityIndex.js +149 -0
  349. package/dist/entityIndex.js.map +1 -0
  350. package/dist/errors.d.ts +6 -2
  351. package/dist/errors.js +59 -0
  352. package/dist/errors.js.map +1 -0
  353. package/dist/events.d.ts +11 -5
  354. package/dist/events.js +158 -0
  355. package/dist/events.js.map +1 -0
  356. package/dist/exactMath.js +273 -0
  357. package/dist/exactMath.js.map +1 -0
  358. package/dist/features.d.ts +1 -1
  359. package/dist/features.js +127 -0
  360. package/dist/features.js.map +1 -0
  361. package/dist/fields.d.ts +25 -5
  362. package/dist/fields.js +140 -0
  363. package/dist/fields.js.map +1 -0
  364. package/dist/fixture.d.ts +3 -3
  365. package/dist/fixture.js +512 -0
  366. package/dist/fixture.js.map +1 -0
  367. package/dist/fog.d.ts +26 -3
  368. package/dist/fog.js +333 -0
  369. package/dist/fog.js.map +1 -0
  370. package/dist/foliage.d.ts +476 -0
  371. package/dist/foliage.js +1478 -0
  372. package/dist/foliage.js.map +1 -0
  373. package/dist/foliageDebug.d.ts +57 -0
  374. package/dist/foliageDebug.js +172 -0
  375. package/dist/foliageDebug.js.map +1 -0
  376. package/dist/foliageRegrowth.d.ts +20 -0
  377. package/dist/foliageRegrowth.js +332 -0
  378. package/dist/foliageRegrowth.js.map +1 -0
  379. package/dist/formState.d.ts +67 -0
  380. package/dist/formState.js +65 -0
  381. package/dist/formState.js.map +1 -0
  382. package/dist/formation.d.ts +46 -8
  383. package/dist/formation.js +297 -0
  384. package/dist/formation.js.map +1 -0
  385. package/dist/forms.d.ts +58 -0
  386. package/dist/forms.js +146 -0
  387. package/dist/forms.js.map +1 -0
  388. package/dist/friendlyFire.d.ts +2 -2
  389. package/dist/friendlyFire.js +37 -0
  390. package/dist/friendlyFire.js.map +1 -0
  391. package/dist/game.d.ts +141 -48
  392. package/dist/game.js +834 -0
  393. package/dist/game.js.map +1 -0
  394. package/dist/gameData.d.ts +96 -22
  395. package/dist/gameData.js +1690 -0
  396. package/dist/gameData.js.map +1 -0
  397. package/dist/gameFiles.d.ts +3 -3
  398. package/dist/gameFiles.js +14 -0
  399. package/dist/gameFiles.js.map +1 -0
  400. package/dist/gates.js +92 -0
  401. package/dist/gates.js.map +1 -0
  402. package/dist/generate.d.ts +28 -1
  403. package/dist/generate.js +1062 -0
  404. package/dist/generate.js.map +1 -0
  405. package/dist/generateWorker.d.ts +7 -3
  406. package/dist/generateWorker.js +86 -0
  407. package/dist/generateWorker.js.map +1 -0
  408. package/dist/grid.d.ts +9 -0
  409. package/dist/grid.js +102 -0
  410. package/dist/grid.js.map +1 -0
  411. package/dist/ground.d.ts +17 -1
  412. package/dist/ground.js +375 -0
  413. package/dist/ground.js.map +1 -0
  414. package/dist/groundObjects.d.ts +70 -0
  415. package/dist/groundObjects.js +371 -0
  416. package/dist/groundObjects.js.map +1 -0
  417. package/dist/groundSpeed.d.ts +20 -3
  418. package/dist/groundSpeed.js +117 -0
  419. package/dist/groundSpeed.js.map +1 -0
  420. package/dist/hero.d.ts +126 -10
  421. package/dist/hero.js +432 -0
  422. package/dist/hero.js.map +1 -0
  423. package/dist/holds.d.ts +94 -0
  424. package/dist/holds.js +305 -0
  425. package/dist/holds.js.map +1 -0
  426. package/dist/home.d.ts +1 -1
  427. package/dist/home.js +30 -0
  428. package/dist/home.js.map +1 -0
  429. package/dist/hooks.d.ts +339 -57
  430. package/dist/hooks.js +105 -0
  431. package/dist/hooks.js.map +1 -0
  432. package/dist/hotReload.d.ts +6 -5
  433. package/dist/hotReload.js +145 -0
  434. package/dist/hotReload.js.map +1 -0
  435. package/dist/ids.d.ts +3 -3
  436. package/dist/ids.js +30 -0
  437. package/dist/ids.js.map +1 -0
  438. package/dist/idsFile.d.ts +36 -0
  439. package/dist/idsFile.js +134 -0
  440. package/dist/idsFile.js.map +1 -0
  441. package/dist/index.d.ts +105 -68
  442. package/dist/index.js +194 -4701
  443. package/dist/inspect.d.ts +29 -2
  444. package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
  445. package/dist/inspect.js.map +1 -0
  446. package/dist/inventory.d.ts +14 -1
  447. package/dist/inventory.js +84 -0
  448. package/dist/inventory.js.map +1 -0
  449. package/dist/items.d.ts +136 -8
  450. package/dist/items.js +585 -0
  451. package/dist/items.js.map +1 -0
  452. package/dist/lanes.d.ts +12 -3
  453. package/dist/lanes.js +496 -0
  454. package/dist/lanes.js.map +1 -0
  455. package/dist/life.d.ts +6 -2
  456. package/dist/life.js +287 -0
  457. package/dist/life.js.map +1 -0
  458. package/dist/log.d.ts +26 -3
  459. package/dist/log.js +192 -0
  460. package/dist/log.js.map +1 -0
  461. package/dist/manaBurn.d.ts +2 -2
  462. package/dist/manaBurn.js +75 -0
  463. package/dist/manaBurn.js.map +1 -0
  464. package/dist/map/file.d.ts +56 -3
  465. package/dist/map/file.js +264 -0
  466. package/dist/map/file.js.map +1 -0
  467. package/dist/map/images.js +61 -0
  468. package/dist/map/images.js.map +1 -0
  469. package/dist/map/look.d.ts +1 -1
  470. package/dist/map/look.js +30 -0
  471. package/dist/map/look.js.map +1 -0
  472. package/dist/map/pathProfile.js +183 -0
  473. package/dist/map/pathProfile.js.map +1 -0
  474. package/dist/map/resize.d.ts +4 -0
  475. package/dist/map/resize.js +136 -0
  476. package/dist/map/resize.js.map +1 -0
  477. package/dist/map/schema.js +257 -0
  478. package/dist/map/schema.js.map +1 -0
  479. package/dist/map/terrain.js +214 -0
  480. package/dist/map/terrain.js.map +1 -0
  481. package/dist/map/types.d.ts +92 -13
  482. package/dist/map/types.js +251 -0
  483. package/dist/map/types.js.map +1 -0
  484. package/dist/mapCheck/cells.js +94 -0
  485. package/dist/mapCheck/cells.js.map +1 -0
  486. package/dist/mapCheck/rules/foliage.d.ts +9 -0
  487. package/dist/mapCheck/rules/foliage.js +83 -0
  488. package/dist/mapCheck/rules/foliage.js.map +1 -0
  489. package/dist/mapCheck/rules/names.js +39 -0
  490. package/dist/mapCheck/rules/names.js.map +1 -0
  491. package/dist/mapCheck/rules/objects.d.ts +1 -1
  492. package/dist/mapCheck/rules/objects.js +56 -0
  493. package/dist/mapCheck/rules/objects.js.map +1 -0
  494. package/dist/mapCheck/rules/paths.js +32 -0
  495. package/dist/mapCheck/rules/paths.js.map +1 -0
  496. package/dist/mapCheck/rules/players.js +20 -0
  497. package/dist/mapCheck/rules/players.js.map +1 -0
  498. package/dist/mapCheck/rules/races.js +56 -0
  499. package/dist/mapCheck/rules/races.js.map +1 -0
  500. package/dist/mapCheck/rules/random.js +47 -0
  501. package/dist/mapCheck/rules/random.js.map +1 -0
  502. package/dist/mapCheck/rules/regions.js +30 -0
  503. package/dist/mapCheck/rules/regions.js.map +1 -0
  504. package/dist/mapCheck/rules/targets.js +31 -0
  505. package/dist/mapCheck/rules/targets.js.map +1 -0
  506. package/dist/mapCheck/rules/walking.js +45 -0
  507. package/dist/mapCheck/rules/walking.js.map +1 -0
  508. package/dist/mapCheck.d.ts +2 -2
  509. package/dist/mapCheck.js +63 -0
  510. package/dist/mapCheck.js.map +1 -0
  511. package/dist/mapFields.d.ts +25 -2
  512. package/dist/mapFields.js +134 -0
  513. package/dist/mapFields.js.map +1 -0
  514. package/dist/mapFile.js +176 -0
  515. package/dist/mapFile.js.map +1 -0
  516. package/dist/mapMeasure.d.ts +8 -0
  517. package/dist/mapMeasure.js +283 -0
  518. package/dist/mapMeasure.js.map +1 -0
  519. package/dist/mapMerge.d.ts +1 -0
  520. package/dist/mapMerge.js +172 -0
  521. package/dist/mapMerge.js.map +1 -0
  522. package/dist/mapObjectives.js +138 -0
  523. package/dist/mapObjectives.js.map +1 -0
  524. package/dist/mapObjects.js +80 -0
  525. package/dist/mapObjects.js.map +1 -0
  526. package/dist/math.d.ts +37 -7
  527. package/dist/math.js +155 -0
  528. package/dist/math.js.map +1 -0
  529. package/dist/messages.d.ts +71 -4
  530. package/dist/messages.js +29 -0
  531. package/dist/messages.js.map +1 -0
  532. package/dist/missionRules.d.ts +10 -2
  533. package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
  534. package/dist/missionRules.js.map +1 -0
  535. package/dist/mods.d.ts +39 -20
  536. package/dist/mods.js +271 -0
  537. package/dist/mods.js.map +1 -0
  538. package/dist/moves.d.ts +87 -0
  539. package/dist/moves.js +539 -0
  540. package/dist/moves.js.map +1 -0
  541. package/dist/names.d.ts +7 -0
  542. package/dist/names.js +122 -0
  543. package/dist/names.js.map +1 -0
  544. package/dist/navigation/agentParams.js +14 -0
  545. package/dist/navigation/agentParams.js.map +1 -0
  546. package/dist/navigation/air.d.ts +7 -3
  547. package/dist/navigation/air.js +401 -0
  548. package/dist/navigation/air.js.map +1 -0
  549. package/dist/navigation/builds.d.ts +34 -2
  550. package/dist/navigation/builds.js +287 -0
  551. package/dist/navigation/builds.js.map +1 -0
  552. package/dist/navigation/groundAreas.d.ts +59 -1
  553. package/dist/navigation/groundAreas.js +407 -0
  554. package/dist/navigation/groundAreas.js.map +1 -0
  555. package/dist/navigation/navigation.d.ts +98 -9
  556. package/dist/navigation/recast.d.ts +194 -18
  557. package/dist/navigation/recast.js +1379 -0
  558. package/dist/navigation/recast.js.map +1 -0
  559. package/dist/navigation/sidePaths.d.ts +8 -3
  560. package/dist/navigation/sidePaths.js +241 -0
  561. package/dist/navigation/sidePaths.js.map +1 -0
  562. package/dist/navigation/sized.js +243 -0
  563. package/dist/navigation/sized.js.map +1 -0
  564. package/dist/nearest.js +32 -0
  565. package/dist/nearest.js.map +1 -0
  566. package/dist/noise.js +59 -0
  567. package/dist/noise.js.map +1 -0
  568. package/dist/objectives.d.ts +12 -3
  569. package/dist/objectives.js +144 -0
  570. package/dist/objectives.js.map +1 -0
  571. package/dist/orders/basic.d.ts +5 -5
  572. package/dist/orders/basic.js +417 -0
  573. package/dist/orders/basic.js.map +1 -0
  574. package/dist/orders/build.js +278 -0
  575. package/dist/orders/build.js.map +1 -0
  576. package/dist/orders/cast.d.ts +13 -3
  577. package/dist/orders/cast.js +558 -0
  578. package/dist/orders/cast.js.map +1 -0
  579. package/dist/orders/facts.js +16 -0
  580. package/dist/orders/facts.js.map +1 -0
  581. package/dist/orders/harvest.d.ts +21 -5
  582. package/dist/orders/harvest.js +540 -0
  583. package/dist/orders/harvest.js.map +1 -0
  584. package/dist/orders/idle.d.ts +3 -1
  585. package/dist/orders/idle.js +234 -0
  586. package/dist/orders/idle.js.map +1 -0
  587. package/dist/orders/items.js +92 -0
  588. package/dist/orders/items.js.map +1 -0
  589. package/dist/orders/queue.js +108 -0
  590. package/dist/orders/queue.js.map +1 -0
  591. package/dist/orders/waiting.d.ts +39 -0
  592. package/dist/orders/waiting.js +149 -0
  593. package/dist/orders/waiting.js.map +1 -0
  594. package/dist/pack.schema.js +13 -0
  595. package/dist/pack.schema.js.map +1 -0
  596. package/dist/pack.schema.json +7622 -841
  597. package/dist/packs/director/index.d.ts +13 -5
  598. package/dist/packs/director/index.js +204 -0
  599. package/dist/packs/director/index.js.map +1 -0
  600. package/dist/packs/heroes/campaign.d.ts +3 -2
  601. package/dist/packs/heroes/campaign.js +241 -0
  602. package/dist/packs/heroes/campaign.js.map +1 -0
  603. package/dist/packs/heroes/carry.d.ts +6 -0
  604. package/dist/packs/heroes/carry.js +112 -0
  605. package/dist/packs/heroes/carry.js.map +1 -0
  606. package/dist/packs/heroes/commands.js +115 -0
  607. package/dist/packs/heroes/commands.js.map +1 -0
  608. package/dist/packs/heroes/fallen.d.ts +43 -0
  609. package/dist/packs/heroes/fallen.js +61 -0
  610. package/dist/packs/heroes/fallen.js.map +1 -0
  611. package/dist/packs/heroes/hire.js +60 -0
  612. package/dist/packs/heroes/hire.js.map +1 -0
  613. package/dist/packs/heroes/index.d.ts +7 -6
  614. package/dist/packs/heroes/index.js +130 -0
  615. package/dist/packs/heroes/index.js.map +1 -0
  616. package/dist/packs/heroes/loop.d.ts +95 -0
  617. package/dist/packs/heroes/loop.js +250 -0
  618. package/dist/packs/heroes/loop.js.map +1 -0
  619. package/dist/packs/heroes/making.d.ts +6 -3
  620. package/dist/packs/heroes/making.js +55 -0
  621. package/dist/packs/heroes/making.js.map +1 -0
  622. package/dist/packs/heroes/respawn.d.ts +3 -3
  623. package/dist/packs/heroes/respawn.js +87 -0
  624. package/dist/packs/heroes/respawn.js.map +1 -0
  625. package/dist/packs/heroes/sets.d.ts +32 -0
  626. package/dist/packs/heroes/sets.js +51 -0
  627. package/dist/packs/heroes/sets.js.map +1 -0
  628. package/dist/packs/heroes/spells.d.ts +16 -0
  629. package/dist/packs/heroes/spells.js +269 -0
  630. package/dist/packs/heroes/spells.js.map +1 -0
  631. package/dist/packs/items/defaults.d.ts +43 -0
  632. package/dist/packs/items/defaults.js +1504 -0
  633. package/dist/packs/items/defaults.js.map +1 -0
  634. package/dist/packs/items/index.d.ts +27 -0
  635. package/dist/packs/items/index.js +214 -0
  636. package/dist/packs/items/index.js.map +1 -0
  637. package/dist/packs/moba/index.d.ts +3 -3
  638. package/dist/packs/moba/index.js +174 -0
  639. package/dist/packs/moba/index.js.map +1 -0
  640. package/dist/packs/pack.d.ts +15 -15
  641. package/dist/packs/pack.js +14 -0
  642. package/dist/packs/pack.js.map +1 -0
  643. package/dist/packs.d.ts +15 -7
  644. package/dist/packs.js +222 -0
  645. package/dist/packs.js.map +1 -0
  646. package/dist/paths.d.ts +2 -0
  647. package/dist/paths.js +109 -0
  648. package/dist/paths.js.map +1 -0
  649. package/dist/plain.js +57 -0
  650. package/dist/plain.js.map +1 -0
  651. package/dist/player.d.ts +33 -10
  652. package/dist/player.js +159 -0
  653. package/dist/player.js.map +1 -0
  654. package/dist/portals.d.ts +1 -1
  655. package/dist/portals.js +194 -0
  656. package/dist/portals.js.map +1 -0
  657. package/dist/prefabs.d.ts +25 -2
  658. package/dist/prefabs.js +239 -0
  659. package/dist/prefabs.js.map +1 -0
  660. package/dist/presetBuildings.js +58 -0
  661. package/dist/presetBuildings.js.map +1 -0
  662. package/dist/presetFoliage.d.ts +27 -0
  663. package/dist/presetFoliage.js +98 -0
  664. package/dist/presetFoliage.js.map +1 -0
  665. package/dist/presetGround.js +65 -0
  666. package/dist/presetGround.js.map +1 -0
  667. package/dist/proxies.d.ts +12 -0
  668. package/dist/proxies.js +79 -0
  669. package/dist/proxies.js.map +1 -0
  670. package/dist/query.d.ts +56 -0
  671. package/dist/query.js +88 -0
  672. package/dist/query.js.map +1 -0
  673. package/dist/races.d.ts +15 -14
  674. package/dist/races.js +172 -0
  675. package/dist/races.js.map +1 -0
  676. package/dist/randomGroups.js +91 -0
  677. package/dist/randomGroups.js.map +1 -0
  678. package/dist/registry.d.ts +117 -53
  679. package/dist/registry.js +323 -0
  680. package/dist/registry.js.map +1 -0
  681. package/dist/remains.d.ts +11 -9
  682. package/dist/remains.js +188 -0
  683. package/dist/remains.js.map +1 -0
  684. package/dist/replication.d.ts +12 -7
  685. package/dist/replication.js +100 -0
  686. package/dist/replication.js.map +1 -0
  687. package/dist/rng.d.ts +2 -0
  688. package/dist/rng.js +40 -0
  689. package/dist/rng.js.map +1 -0
  690. package/dist/rules.d.ts +186 -99
  691. package/dist/rules.js +179 -0
  692. package/dist/rules.js.map +1 -0
  693. package/dist/rulesCheck.d.ts +5 -4
  694. package/dist/rulesCheck.js +693 -0
  695. package/dist/rulesCheck.js.map +1 -0
  696. package/dist/runes.d.ts +2 -2
  697. package/dist/runes.js +80 -0
  698. package/dist/runes.js.map +1 -0
  699. package/dist/save.d.ts +37 -12
  700. package/dist/save.js +532 -0
  701. package/dist/save.js.map +1 -0
  702. package/dist/scenario.d.ts +2 -2
  703. package/dist/scenario.js +99 -0
  704. package/dist/scenario.js.map +1 -0
  705. package/dist/scheduler.d.ts +3 -0
  706. package/dist/scheduler.js +156 -0
  707. package/dist/scheduler.js.map +1 -0
  708. package/dist/score.d.ts +19 -19
  709. package/dist/score.js +709 -0
  710. package/dist/score.js.map +1 -0
  711. package/dist/sequences.d.ts +10 -6
  712. package/dist/sequences.js +206 -0
  713. package/dist/sequences.js.map +1 -0
  714. package/dist/server/doorman.js +154 -0
  715. package/dist/server/doorman.js.map +1 -0
  716. package/dist/server/gameServer.d.ts +16 -1
  717. package/dist/server/gameServer.js +643 -0
  718. package/dist/server/gameServer.js.map +1 -0
  719. package/dist/server/index.d.ts +1 -1
  720. package/dist/server/lobby.js +199 -0
  721. package/dist/server/lobby.js.map +1 -0
  722. package/dist/server/log.js +18 -0
  723. package/dist/server/log.js.map +1 -0
  724. package/dist/server/match.js +267 -0
  725. package/dist/server/match.js.map +1 -0
  726. package/dist/server/mode.d.ts +18 -9
  727. package/dist/server/mode.js +220 -0
  728. package/dist/server/mode.js.map +1 -0
  729. package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
  730. package/dist/server/navigation-worker.js.map +1 -0
  731. package/dist/server/navigation.js +39 -0
  732. package/dist/server/navigation.js.map +1 -0
  733. package/dist/server/ops.d.ts +4 -0
  734. package/dist/server/ops.js +137 -0
  735. package/dist/server/ops.js.map +1 -0
  736. package/dist/server/packs.d.ts +3 -3
  737. package/dist/server/packs.js +32 -0
  738. package/dist/server/packs.js.map +1 -0
  739. package/dist/server/ratings.d.ts +5 -0
  740. package/dist/server/ratings.js +104 -0
  741. package/dist/server/ratings.js.map +1 -0
  742. package/dist/server/relay.d.ts +12 -2
  743. package/dist/server/relay.js +144 -0
  744. package/dist/server/relay.js.map +1 -0
  745. package/dist/server/rooms.d.ts +9 -2
  746. package/dist/server/rooms.js +442 -0
  747. package/dist/server/rooms.js.map +1 -0
  748. package/dist/server/seat.js +116 -0
  749. package/dist/server/seat.js.map +1 -0
  750. package/dist/server/seatSettings.d.ts +3 -3
  751. package/dist/server/seatSettings.js +63 -0
  752. package/dist/server/seatSettings.js.map +1 -0
  753. package/dist/server/secret.js +13 -0
  754. package/dist/server/secret.js.map +1 -0
  755. package/dist/server/start.d.ts +13 -6
  756. package/dist/server/start.js +76 -0
  757. package/dist/server/start.js.map +1 -0
  758. package/dist/server/websocket.d.ts +9 -1
  759. package/dist/server/websocket.js +306 -0
  760. package/dist/server/websocket.js.map +1 -0
  761. package/dist/server.js +15 -2861
  762. package/dist/session/can.js +26 -0
  763. package/dist/session/can.js.map +1 -0
  764. package/dist/session/commandReplay.d.ts +8 -2
  765. package/dist/session/commandReplay.js +293 -0
  766. package/dist/session/commandReplay.js.map +1 -0
  767. package/dist/session/debug.js +151 -0
  768. package/dist/session/debug.js.map +1 -0
  769. package/dist/session/delay.js +62 -0
  770. package/dist/session/delay.js.map +1 -0
  771. package/dist/session/delta.d.ts +14 -1
  772. package/dist/session/delta.js +407 -0
  773. package/dist/session/delta.js.map +1 -0
  774. package/dist/session/entityState.js +415 -0
  775. package/dist/session/entityState.js.map +1 -0
  776. package/dist/session/local.d.ts +47 -5
  777. package/dist/session/local.js +670 -0
  778. package/dist/session/local.js.map +1 -0
  779. package/dist/session/memory.d.ts +20 -2
  780. package/dist/session/memory.js +131 -0
  781. package/dist/session/memory.js.map +1 -0
  782. package/dist/session/protocol.d.ts +325 -31
  783. package/dist/session/protocol.js +55 -0
  784. package/dist/session/protocol.js.map +1 -0
  785. package/dist/session/remote.d.ts +74 -12
  786. package/dist/session/remote.js +1394 -0
  787. package/dist/session/remote.js.map +1 -0
  788. package/dist/session/replay.d.ts +11 -2
  789. package/dist/session/replay.js +160 -0
  790. package/dist/session/replay.js.map +1 -0
  791. package/dist/session/seed.js +12 -0
  792. package/dist/session/seed.js.map +1 -0
  793. package/dist/session/share.d.ts +5 -1
  794. package/dist/session/share.js +94 -0
  795. package/dist/session/share.js.map +1 -0
  796. package/dist/session/socket.d.ts +1 -1
  797. package/dist/session/socket.js +29 -0
  798. package/dist/session/socket.js.map +1 -0
  799. package/dist/session/wire.d.ts +5 -0
  800. package/dist/session/wire.js +84 -0
  801. package/dist/session/wire.js.map +1 -0
  802. package/dist/session/worker.d.ts +77 -12
  803. package/dist/session/worker.js +499 -0
  804. package/dist/session/worker.js.map +1 -0
  805. package/dist/shared.d.ts +31 -5
  806. package/dist/shared.js +166 -0
  807. package/dist/shared.js.map +1 -0
  808. package/dist/sides.d.ts +9 -3
  809. package/dist/sides.js +149 -0
  810. package/dist/sides.js.map +1 -0
  811. package/dist/sight.js +85 -0
  812. package/dist/sight.js.map +1 -0
  813. package/dist/simulate-worker.js +1 -1
  814. package/dist/simulate.d.ts +12 -8
  815. package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
  816. package/dist/simulate.js.map +1 -0
  817. package/dist/smart.js +77 -0
  818. package/dist/smart.js.map +1 -0
  819. package/dist/spatial.d.ts +32 -16
  820. package/dist/spatial.js +234 -0
  821. package/dist/spatial.js.map +1 -0
  822. package/dist/spawning.d.ts +1 -0
  823. package/dist/spawning.js +224 -0
  824. package/dist/spawning.js.map +1 -0
  825. package/dist/stances.d.ts +6 -3
  826. package/dist/stances.js +169 -0
  827. package/dist/stances.js.map +1 -0
  828. package/dist/start.d.ts +10 -10
  829. package/dist/start.js +75 -0
  830. package/dist/start.js.map +1 -0
  831. package/dist/stats.d.ts +42 -16
  832. package/dist/stats.js +290 -0
  833. package/dist/stats.js.map +1 -0
  834. package/dist/summoned.d.ts +52 -0
  835. package/dist/summoned.js +38 -0
  836. package/dist/summoned.js.map +1 -0
  837. package/dist/summons.d.ts +10 -13
  838. package/dist/summons.js +271 -0
  839. package/dist/summons.js.map +1 -0
  840. package/dist/systems/abilities.js +224 -0
  841. package/dist/systems/abilities.js.map +1 -0
  842. package/dist/systems/combat.d.ts +35 -1
  843. package/dist/systems/combat.js +677 -0
  844. package/dist/systems/combat.js.map +1 -0
  845. package/dist/systems/combatTold.d.ts +3 -1
  846. package/dist/systems/combatTold.js +85 -0
  847. package/dist/systems/combatTold.js.map +1 -0
  848. package/dist/systems/construction.js +80 -0
  849. package/dist/systems/construction.js.map +1 -0
  850. package/dist/systems/economy.d.ts +0 -6
  851. package/dist/systems/economy.js +128 -0
  852. package/dist/systems/economy.js.map +1 -0
  853. package/dist/systems/fog.d.ts +1 -1
  854. package/dist/systems/fog.js +120 -0
  855. package/dist/systems/fog.js.map +1 -0
  856. package/dist/systems/life.js +32 -0
  857. package/dist/systems/life.js.map +1 -0
  858. package/dist/systems/movement.d.ts +24 -12
  859. package/dist/systems/movement.js +1247 -0
  860. package/dist/systems/movement.js.map +1 -0
  861. package/dist/systems/orders.js +64 -0
  862. package/dist/systems/orders.js.map +1 -0
  863. package/dist/systems/production.js +322 -0
  864. package/dist/systems/production.js.map +1 -0
  865. package/dist/systems/productionQueue.js +120 -0
  866. package/dist/systems/productionQueue.js.map +1 -0
  867. package/dist/systems/victory.d.ts +1 -1
  868. package/dist/systems/victory.js +56 -0
  869. package/dist/systems/victory.js.map +1 -0
  870. package/dist/talk.d.ts +6 -6
  871. package/dist/talk.js +153 -0
  872. package/dist/talk.js.map +1 -0
  873. package/dist/targeting.d.ts +142 -0
  874. package/dist/targeting.js +49 -0
  875. package/dist/targeting.js.map +1 -0
  876. package/dist/tech.d.ts +20 -3
  877. package/dist/tech.js +239 -0
  878. package/dist/tech.js.map +1 -0
  879. package/dist/techTree.d.ts +7 -0
  880. package/dist/techTree.js +90 -0
  881. package/dist/techTree.js.map +1 -0
  882. package/dist/terrain.d.ts +59 -7
  883. package/dist/terrain.js +389 -0
  884. package/dist/terrain.js.map +1 -0
  885. package/dist/terrainSave.d.ts +6 -0
  886. package/dist/terrainSave.js +74 -0
  887. package/dist/terrainSave.js.map +1 -0
  888. package/dist/testing.d.ts +8 -7
  889. package/dist/testing.js +13 -739
  890. package/dist/testing.js.map +1 -1
  891. package/dist/tiles.d.ts +1 -1
  892. package/dist/tiles.js +43 -0
  893. package/dist/tiles.js.map +1 -0
  894. package/dist/timers.d.ts +29 -4
  895. package/dist/timers.js +242 -0
  896. package/dist/timers.js.map +1 -0
  897. package/dist/tomes.d.ts +4 -4
  898. package/dist/tomes.js +94 -0
  899. package/dist/tomes.js.map +1 -0
  900. package/dist/trade.js +103 -0
  901. package/dist/trade.js.map +1 -0
  902. package/dist/transport.d.ts +6 -1
  903. package/dist/transport.js +281 -0
  904. package/dist/transport.js.map +1 -0
  905. package/dist/tunables.d.ts +10 -3
  906. package/dist/tunables.js +56 -0
  907. package/dist/tunables.js.map +1 -0
  908. package/dist/unitResources.d.ts +67 -0
  909. package/dist/unitResources.js +266 -0
  910. package/dist/unitResources.js.map +1 -0
  911. package/dist/upkeep.d.ts +6 -1
  912. package/dist/upkeep.js +26 -0
  913. package/dist/upkeep.js.map +1 -0
  914. package/dist/veterancy.d.ts +8 -3
  915. package/dist/veterancy.js +131 -0
  916. package/dist/veterancy.js.map +1 -0
  917. package/dist/vision.d.ts +36 -0
  918. package/dist/vision.js +133 -0
  919. package/dist/vision.js.map +1 -0
  920. package/dist/walls.d.ts +1 -1
  921. package/dist/walls.js +278 -0
  922. package/dist/walls.js.map +1 -0
  923. package/dist/world.d.ts +606 -88
  924. package/dist/world.js +1263 -0
  925. package/dist/world.js.map +1 -0
  926. package/package.json +2 -2
  927. package/dist/ai.js.map +0 -1
  928. package/dist/attributes.d.ts +0 -66
  929. package/dist/brain-BvVdUhX8.js +0 -7659
  930. package/dist/brain-BvVdUhX8.js.map +0 -1
  931. package/dist/builds-C6LfgvEU.js +0 -460
  932. package/dist/builds-C6LfgvEU.js.map +0 -1
  933. package/dist/coreComponents-syuh2fPG.js +0 -5149
  934. package/dist/coreComponents-syuh2fPG.js.map +0 -1
  935. package/dist/debugCommands-CzjrSm66.js +0 -14739
  936. package/dist/debugCommands-CzjrSm66.js.map +0 -1
  937. package/dist/determinism-BCymQwiE.js +0 -518
  938. package/dist/determinism-BCymQwiE.js.map +0 -1
  939. package/dist/game-DiJEN-Ks.js +0 -5800
  940. package/dist/game-DiJEN-Ks.js.map +0 -1
  941. package/dist/index.js.map +0 -1
  942. package/dist/inspect-D9dWHmZ0.js.map +0 -1
  943. package/dist/local-Dkovq42k.js +0 -1379
  944. package/dist/local-Dkovq42k.js.map +0 -1
  945. package/dist/missionRules-C-bGxm0Q.js.map +0 -1
  946. package/dist/navigation-worker.js.map +0 -1
  947. package/dist/packs-g5thvmGn.js +0 -3199
  948. package/dist/packs-g5thvmGn.js.map +0 -1
  949. package/dist/profiles-B3NS9jwk.js.map +0 -1
  950. package/dist/server.js.map +0 -1
  951. package/dist/simulate-oXBiw1Ff.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../src/fixture.ts","../src/aiTesting.ts","../src/testing.ts"],"sourcesContent":["/**\n * The fixture game: the smallest game the engine's kit has a part for each of its roles in (a hall and its workers,\n * supply, a barracks of a fighter and an archer, a tower, an altar and a hero, a gold mine and trees, a creep, an\n * upgrade, abilities and items), for the engine's own tests and a game's. Its numbers are round (health 100 or 200,\n * damage 10, speed 4) so that what a test expects reads as what it means: a soldier hits an archer ten times\n */\nimport type { AbilityDef, BuffDef, ItemDef, UnitTypeDef, UpgradeDef } from './defs'\nimport type { GameModule } from './game'\nimport { createMap, type GameMap } from './map'\nimport { dist, type Vec2 } from './math'\nimport { withHeroes } from './packs/heroes'\nimport type { PlayerId } from './entity'\nimport type { World } from './world'\n\nconst worker: UnitTypeDef = {\n\tid: 'worker',\n\tname: 'Worker',\n\tkind: 'unit',\n\tradius: 0.4,\n\tstats: { health: 100, attackDamage: 5, attackSpeed: 1, attackRange: 0.5, moveSpeed: 4 },\n\tsight: 8,\n\tattacks: [{ damagePoint: 0.3, acquisitionRange: 0, targets: ['unit', 'building'] }],\n\tcost: { gold: 50 },\n\tsupply: 1,\n\tbuildTime: 10,\n\tharvester: { capacity: 10, gatherTime: 1 },\n\tbuilds: ['hall', 'supply', 'barracks', 'tower', 'altar']\n}\n\nconst soldier: UnitTypeDef = {\n\tid: 'soldier',\n\tname: 'Soldier',\n\tkind: 'unit',\n\tradius: 0.45,\n\tstats: { health: 200, attackDamage: 10, attackSpeed: 1, attackRange: 0.5, armor: 10, moveSpeed: 4 },\n\tsight: 10,\n\tattacks: [{ damagePoint: 0.3, acquisitionRange: 8 }],\n\tcost: { gold: 100 },\n\tsupply: 2,\n\tbuildTime: 10,\n\tabilities: ['guard']\n}\n\nconst archer: UnitTypeDef = {\n\tid: 'archer',\n\tname: 'Archer',\n\tkind: 'unit',\n\tradius: 0.45,\n\tstats: { health: 100, attackDamage: 10, attackSpeed: 1, attackRange: 6, moveSpeed: 4 },\n\tsight: 10,\n\tattacks: [{ damagePoint: 0.3, acquisitionRange: 8, projectileSpeed: 20, targets: ['ground', 'air'] }],\n\tcost: { gold: 100, lumber: 20 },\n\tsupply: 2,\n\tbuildTime: 10\n}\n\nconst hero: UnitTypeDef = {\n\tid: 'hero',\n\tname: 'Hero',\n\tkind: 'unit',\n\tradius: 0.5,\n\tstats: { health: 300, mana: 100, manaRegen: 1, attackDamage: 20, attackSpeed: 1, attackRange: 0.5, armor: 10, moveSpeed: 4 },\n\tsight: 12,\n\tattacks: [{ damagePoint: 0.3, acquisitionRange: 8 }],\n\thero: { growth: { stats: { health: 20, mana: 10, attackDamage: 2 } }, learns: ['heal', 'guard'] },\n\tinventory: 6,\n\tcost: { gold: 400, lumber: 100 },\n\tsupply: 5,\n\tbuildTime: 40\n}\n\nconst creep: UnitTypeDef = {\n\tid: 'creep',\n\tname: 'Creep',\n\tkind: 'unit',\n\tradius: 0.45,\n\tstats: { health: 200, attackDamage: 10, attackSpeed: 1, attackRange: 0.5, moveSpeed: 3 },\n\tsight: 8,\n\tattacks: [{ damagePoint: 0.3, acquisitionRange: 5 }],\n\tlevel: 1,\n\tbounty: [10, 10],\n\txp: 20\n}\n\nconst hall: UnitTypeDef = {\n\tid: 'hall',\n\tname: 'Hall',\n\tkind: 'building',\n\tradius: 2,\n\tfootprint: { w: 4, d: 4 },\n\tstats: { health: 1500, armor: 10 },\n\tsight: 12,\n\tcost: { gold: 400, lumber: 200 },\n\tbuildTime: 40,\n\tsupplyProvided: 10,\n\ttrains: ['worker'],\n\tdropOff: true,\n\tupgradesTo: 'keep'\n}\n\nconst keep: UnitTypeDef = {\n\t...hall,\n\tid: 'keep',\n\tname: 'Keep',\n\tstats: { health: 2000, armor: 10 },\n\tcost: { gold: 300, lumber: 200 },\n\tprovides: ['hall'],\n\tupgradesTo: undefined\n}\n\nconst supply: UnitTypeDef = {\n\tid: 'supply',\n\tname: 'Supply',\n\tkind: 'building',\n\tradius: 1,\n\tfootprint: { w: 2, d: 2 },\n\tstats: { health: 500, armor: 10 },\n\tsight: 6,\n\tcost: { gold: 50 },\n\tbuildTime: 10,\n\tsupplyProvided: 10\n}\n\nconst barracks: UnitTypeDef = {\n\tid: 'barracks',\n\tname: 'Barracks',\n\tkind: 'building',\n\tradius: 1.5,\n\tfootprint: { w: 3, d: 3 },\n\tstats: { health: 1000, armor: 10 },\n\tsight: 9,\n\tcost: { gold: 150, lumber: 50 },\n\tbuildTime: 20,\n\ttrains: ['soldier', 'archer'],\n\tresearches: ['armour']\n}\n\nconst tower: UnitTypeDef = {\n\tid: 'tower',\n\tname: 'Tower',\n\tkind: 'building',\n\tradius: 1,\n\tfootprint: { w: 2, d: 2 },\n\tstats: { health: 500, attackDamage: 20, attackSpeed: 1, attackRange: 8, armor: 10 },\n\tsight: 12,\n\tattacks: [{ damagePoint: 0.3, acquisitionRange: 8, projectileSpeed: 20, targets: ['ground', 'air'] }],\n\tcost: { gold: 100, lumber: 50 },\n\tbuildTime: 20,\n\trequires: ['barracks']\n}\n\nconst altar: UnitTypeDef = {\n\tid: 'altar',\n\tname: 'Altar',\n\tkind: 'building',\n\tradius: 1.5,\n\tfootprint: { w: 3, d: 3 },\n\tstats: { health: 1000, armor: 10 },\n\tsight: 9,\n\tcost: { gold: 200, lumber: 50 },\n\tbuildTime: 30,\n\ttrains: ['hero'],\n\trevives: true\n}\n\nconst mine: UnitTypeDef = {\n\tid: 'mine',\n\tname: 'Mine',\n\tkind: 'resource',\n\tradius: 2,\n\tfootprint: { w: 4, d: 4 },\n\tstats: { health: 1 },\n\tsight: 0,\n\tinvulnerable: true,\n\tresource: { kind: 'gold', amount: 10000, slots: 1, entered: true }\n}\n\nconst tree: UnitTypeDef = {\n\tid: 'tree',\n\tname: 'Tree',\n\tkind: 'resource',\n\tradius: 0.5,\n\tfootprint: { w: 1, d: 1 },\n\tstats: { health: 1 },\n\tsight: 0,\n\tinvulnerable: true,\n\tfellable: true,\n\tresource: { kind: 'lumber', amount: 50, slots: 1, gatherTime: 5 }\n}\n\nconst armour: UpgradeDef = {\n\tid: 'armour',\n\tname: 'Armour',\n\tdescription: '+10 armor for soldiers and archers',\n\tcost: { gold: 100, lumber: 50 },\n\tresearchTime: 20,\n\tmaxLevel: 2,\n\teffects: [{ units: ['soldier', 'archer'], stats: { armor: 10 } }]\n}\n\nconst guarded: BuffDef = { id: 'guarded', name: 'Guarded', description: '+20 armor', duration: 10, stats: { armor: 20 } }\n\nconst abilities: AbilityDef[] = [\n\t{\n\t\tid: 'heal',\n\t\tname: 'Heal',\n\t\tdescription: 'Heals a friendly unit for 100 or 200',\n\t\ttarget: 'unit',\n\t\ttargets: { allies: true, self: false },\n\t\tmanaCost: 10,\n\t\tcooldown: 5,\n\t\trange: 6,\n\t\teffects: [{ type: 'heal', amount: [100, 200] }]\n\t},\n\t{\n\t\tid: 'guard',\n\t\tname: 'Guard',\n\t\tdescription: '+20 armor for 10 seconds',\n\t\ttarget: 'none',\n\t\tcooldown: 10,\n\t\teffects: [{ type: 'buff', buff: 'guarded', on: 'caster' }]\n\t},\n\t{ id: 'drink', name: 'Drink', description: 'Heals 100', target: 'none', cooldown: 10, effects: [{ type: 'heal', amount: 100, on: 'caster' }] }\n]\n\nconst items: ItemDef[] = [\n\t{ id: 'sword', name: 'Sword', description: '+10 attack damage', tier: 'basic', cost: { gold: 100 }, bonus: { stats: { attackDamage: 10 } } },\n\t{ id: 'potion', name: 'Potion', description: 'Heals 100 when drunk', tier: 'consumable', cost: { gold: 50 }, charges: 1, ability: 'drink' }\n]\n\n/** A hall where a player starts, and five workers on the side of the closest mine */\nfunction startingBase(world: World, player: PlayerId, at: Vec2): void {\n\tconst base = world.spawn('hall', player, at)\n\tlet closest: Vec2 | undefined\n\tfor (const entity of world.entities.values()) {\n\t\tif (entity.def.resource?.kind !== 'gold' || dist(entity.pos, base.pos) > 20) continue\n\t\tif (!closest || dist(entity.pos, base.pos) < dist(closest, base.pos)) closest = entity.pos\n\t}\n\tconst towards = closest ? { x: Math.sign(closest.x - at.x), z: Math.sign(closest.z - at.z) } : { x: 1, z: 0 }\n\tfor (let i = 0; i < 5; i++)\n\t\tworld.spawn('worker', player, { x: at.x + towards.x * 4 + (i - 2) * towards.z, z: at.z + towards.z * 4 + (i - 2) * towards.x })\n}\n\n/**\n * The fixture game (see the top of this file): every role of the kit, with round numbers. Gold and lumber, 1000 of each\n * to start with; a hall and five workers at each start; heroes on (`withHeroes`); no fog explored at the start. A new\n * one each time, for a test to change\n *\n * @beta\n */\nexport function fixtureGame(): GameModule {\n\treturn {\n\t\tid: 'fixture',\n\t\tname: 'Fixture',\n\t\tversion: '1.0.0',\n\t\tunits: [worker, soldier, archer, hero, creep, hall, keep, supply, barracks, tower, altar, mine, tree].map((def) => structuredClone(def)),\n\t\tupgrades: [structuredClone(armour)],\n\t\tabilities: structuredClone(abilities),\n\t\tbuffs: [structuredClone(guarded)],\n\t\titems: structuredClone(items),\n\t\tresources: [\n\t\t\t{ id: 'gold', name: 'Gold', start: 1000 },\n\t\t\t{ id: 'lumber', name: 'Lumber', start: 1000 }\n\t\t],\n\t\tcurrency: 'gold',\n\t\tpacks: [withHeroes()],\n\t\tstart: { spawn: startingBase }\n\t}\n}\n\n/**\n * A map of the fixture game, 64 cells a side: two players, starting at opposite corners (12, 12 and 52, 52), a gold\n * mine and a row of trees by each start, and a camp of three creeps in the middle\n *\n * @beta\n */\nexport function fixtureMap(): GameMap {\n\tconst map = createMap({ name: 'Fixture', width: 64, depth: 64, game: 'fixture' })\n\tmap.players[0].start = { x: 12, z: 12 }\n\tmap.players[1].start = { x: 52, z: 52 }\n\tlet id = 1\n\tconst object = (type: string, x: number, z: number) => map.objects.push({ id: id++, type, owner: 0, x, z, facing: 0, scale: 1 })\n\tobject('mine', 12, 22)\n\tobject('mine', 52, 42)\n\tfor (let i = 0; i < 6; i++) {\n\t\tobject('tree', 22.5 + i, 4.5)\n\t\tobject('tree', 36.5 + i, 59.5)\n\t}\n\tmap.camps.push({ id: id++, x: 32, z: 32, units: ['creep', 'creep', 'creep'] })\n\treturn map\n}\n","/**\n * Testing a computer player (AI plan, E3): what a game's tests of its brains are written with, in\n * `@v12-engine/engine/testing` beside `testWorld` and `run`. A brain is tested as it plays, through the world it sits in:\n *\n * const world = await testWorld(myGame)\n * world.computers.seat(ENEMY, { enemyBases: [home], brain: myBrain })\n * const watch = watchComputer(world, ENEMY) // its invariants, every think\n * run(world, 120)\n * expectDecision(thinkOnce(world, ENEMY), 'ai.attack')\n * watch.assert() // no rule broken\n *\n * `thinkOnce` has a seated brain think now and gives its report; `expectDecision` says a goal runs, or why not in\n * words; `watchComputer` checks the invariants of `ai/checks.ts` after every think (a unit in one squad, gold spent\n * once, finite numbers, commands about what it sees, no churn, nothing stuck) and keeps what it decided; `fairPlay` is\n * the one about seeing; `recordDecisions` keeps every computer's decisions for a replay's side file; `checkComputerSave`\n * is the seventh invariant: a game saved and loaded decides the same from then on. These take the world, which a test\n * may: the brains under test never do.\n */\nimport { type AiCheckOptions, type AiViolation, checkBrain } from './ai/checks'\nimport { Brain } from './ai/brain'\nimport type { GoalReport } from './ai/goals'\nimport { type AiDecision, type AiReport, explainGoal } from './ai/report'\nimport type { PlayerId } from './entity'\nimport { type GameModule, loadWorld } from './game'\nimport { decodeSave, encodeSave, saveWorld } from './save'\nimport { LocalSession } from './session/local'\nimport type { PlayerCommand, Snapshot } from './session/protocol'\nimport type { World } from './world'\n\n/**\n * The brain that plays a player, where one is seated (`world.computers.seat`): none where nobody is, or where what is\n * seated is not a brain (`defineComputer`)\n *\n * @beta\n */\nexport function brainOf(world: World, player: PlayerId): Brain | undefined {\n\tconst computer = world.computers.get(player)?.computer\n\treturn computer instanceof Brain ? computer : undefined\n}\n\n/** The brain at a player, or an error that says what is seated there instead */\nfunction seated(world: World, player: PlayerId): Brain {\n\tconst brain = brainOf(world, player)\n\tif (brain) return brain\n\tconst system = world.computers.get(player)\n\tthrow new Error(\n\t\tsystem ? `The computer player at ${player} is not a brain (defineBrain): it has no report` : `No computer player is seated at ${player}`\n\t)\n}\n\n/**\n * Has the brain at a player think now, all of it (a think its budget slices over ticks is run to its end), over a new\n * picture of the game, and gives its report: what a test reads after setting a scene. Its commands land at the next\n * tick, as a think's do. A think the seat would have had is not skipped: this one is beside them\n *\n * @beta\n */\nexport function thinkOnce(world: World, player: PlayerId): AiReport {\n\tconst brain = seated(world, player)\n\tdo brain.think()\n\twhile (brain.busy)\n\treturn brain.report()\n}\n\n/**\n * Says that a goal runs, as of a report (`thinkOnce`, `Brain.report`): it is picked and holds what it claimed. Throws\n * where it does not, with its row in words (`Brain.explain`): what each consideration answered and what kept it out.\n * Gives the goal's row. With `picked: false`, says it does not run\n *\n * expectDecision(thinkOnce(world, ENEMY), 'ai.defend')\n *\n * @beta\n */\nexport function expectDecision(report: AiReport, goal: string, options: { picked?: boolean } = {}): GoalReport {\n\tconst wanted = options.picked ?? true\n\tconst row = report.goals.find((each) => each.id === goal)\n\tif (!row)\n\t\tthrow new Error(`The brain ${report.brain} has no goal \"${goal}\": its goals are ${report.goals.map((each) => each.id).join(', ') || 'none'}`)\n\tif (row.picked === wanted) return row\n\tconst seconds = (tick: number) => tick / report.tickRate\n\tthrow new Error(\n\t\t`Expected ${goal} ${wanted ? 'to run' : 'not to run'} at ${report.time.toFixed(1)} s, and it ${wanted ? 'does not' : 'does'}. ${explainGoal(row, seconds, report.time)}${\n\t\t\treport.goal && report.goal !== goal ? ` The best goal is ${report.goal}.` : ''\n\t\t}`\n\t)\n}\n\n/**\n * A computer player followed over a run (`watchComputer`): the rules it broke, what it decided and sent, and, where\n * asked, what an observer saw at each of its thinks\n *\n * @beta\n */\nexport interface ComputerWatch {\n\t/** The brain watched */\n\treadonly brain: Brain\n\t/** Every invariant it broke, in the order found (`ai/checks.ts`) */\n\treadonly violations: readonly AiViolation[]\n\t/** What it decided while watched, oldest first: every line, not only the last fifty its log keeps */\n\treadonly decisions: readonly AiDecision[]\n\t/** Its thinks while watched */\n\treadonly thinks: number\n\t/** Commands it sent while watched */\n\treadonly commands: number\n\t/** Throws, listing them, where it broke any rule */\n\tassert(): void\n\t/** Stops watching */\n\tstop(): void\n}\n\n/**\n * How a computer player is watched (`watchComputer`): which invariants and how long things may go on (`AiCheckOptions`),\n * and what to be shown at each think\n *\n * @beta\n */\nexport interface WatchOptions extends AiCheckOptions {\n\t/**\n\t * Shown, at the end of each of its thinks, the game as an observer sees it (everything, no fog) and the brain: for a\n\t * look at what it does (a test that writes frames, a page that draws them). An observer's seat is made only when given\n\t */\n\tobserve?: (snapshot: Snapshot, brain: Brain) => void\n\t/** Each command as it sends it */\n\tsent?: (command: PlayerCommand, brain: Brain) => void\n}\n\n/**\n * Follows the brain at a player from now on: after every think, the invariants of `ai/checks.ts` (a unit in one squad\n * and one hold, gold spent once, finite numbers, commands about what it sees, no order sent again to a unit still at\n * it, builders, tasks, holds and wants that end), with what it decided and sent. A broken rule is kept, not thrown,\n * unless `onViolation` throws: `assert` at the end says them all\n *\n * @beta\n */\nexport function watchComputer(world: World, player: PlayerId, options: WatchOptions = {}): ComputerWatch {\n\tconst brain = seated(world, player)\n\tconst violations: AiViolation[] = []\n\tconst decisions: AiDecision[] = []\n\tlet thinks = 0\n\tlet commands = 0\n\tconst { stop: unchecked } = checkBrain(brain, {\n\t\t...options,\n\t\tonViolation: (violation) => {\n\t\t\tviolations.push(violation)\n\t\t\toptions.onViolation?.(violation)\n\t\t}\n\t})\n\tconst observer = options.observe ? new LocalSession(world, player, { observer: true }) : undefined\n\tconst unwatched = brain.watch({\n\t\tsent: (command) => {\n\t\t\tcommands++\n\t\t\toptions.sent?.(command, brain)\n\t\t},\n\t\tdecided: (decision) => void decisions.push(decision),\n\t\tthought: () => {\n\t\t\tthinks++\n\t\t\tif (observer) options.observe!(observer.snapshot(), brain)\n\t\t}\n\t})\n\treturn {\n\t\tbrain,\n\t\tviolations,\n\t\tdecisions,\n\t\tget thinks() {\n\t\t\treturn thinks\n\t\t},\n\t\tget commands() {\n\t\t\treturn commands\n\t\t},\n\t\tassert() {\n\t\t\tif (!violations.length) return\n\t\t\tconst lines = violations.slice(0, 20).map((each) => ` ${each.invariant} at tick ${each.tick}: ${each.message}`)\n\t\t\tconst more = violations.length > 20 ? `\\n and ${violations.length - 20} more` : ''\n\t\t\tthrow new Error(\n\t\t\t\t`The computer player at ${player} broke ${violations.length} rule${violations.length === 1 ? '' : 's'}:\\n${lines.join('\\n')}${more}`\n\t\t\t)\n\t\t},\n\t\tstop() {\n\t\t\tunchecked()\n\t\t\tunwatched()\n\t\t\tobserver?.dispose()\n\t\t}\n\t}\n}\n\n/**\n * Whether a computer player played fair over a run (`fairPlay`): every command it sent named what its own snapshot\n * had, and how many the game refused\n *\n * @beta\n */\nexport interface FairPlay {\n\t/** Commands that named an entity it did not see, or a place off the map */\n\treadonly unfair: readonly AiViolation[]\n\t/** Commands the game refused while watched (a unit that could not do it, a place it could not build at) */\n\treadonly refused: number\n\t/** Throws where it sent any command about what it did not see */\n\tassert(): void\n\tstop(): void\n}\n\n/**\n * Follows the brain at a player from now on for fair play: that it never sends a command about an entity its snapshot\n * did not have (a fog leak: its seat's session would drop the command, so a game shows nothing; this says it), and\n * counts what the game refused\n *\n * @beta\n */\nexport function fairPlay(world: World, player: PlayerId): FairPlay {\n\tconst watch = watchComputer(world, player, { invariants: ['commands'] })\n\tconst brain = watch.brain\n\tconst refusedBefore = brain.stats.refused\n\treturn {\n\t\tget unfair() {\n\t\t\treturn watch.violations\n\t\t},\n\t\tget refused() {\n\t\t\treturn brain.stats.refused - refusedBefore\n\t\t},\n\t\tassert: () => watch.assert(),\n\t\tstop: () => watch.stop()\n\t}\n}\n\n/**\n * One thing a computer player decided, with whose: a line of a replay's side file (`recordDecisions`)\n *\n * @beta\n */\nexport interface RecordedDecision extends AiDecision {\n\tplayer: PlayerId\n\t/** The brain's id */\n\tbrain: string\n}\n\n/**\n * The decisions of every computer of a world, as they are made (`recordDecisions`): plain data, for a side file beside a\n * replay of commands, read back by whoever wonders why the computer did what the replay shows\n *\n * @beta\n */\nexport interface DecisionRecorder {\n\t/** Every decision so far, in the order made */\n\treadonly decisions: readonly RecordedDecision[]\n\tstop(): void\n}\n\n/** How many recorders were made: each one's system a name of its own */\nlet recorders = 0\n\n/**\n * Keeps the decisions of every brain seated at a world, from now on, those seated later included (looked for at each\n * tick, by a system of its own that keeps nothing in a save)\n *\n * @beta\n */\nexport function recordDecisions(world: World): DecisionRecorder {\n\tconst decisions: RecordedDecision[] = []\n\tconst watched = new Map<Brain, () => void>()\n\tconst look = () => {\n\t\tfor (const player of world.computers.list()) {\n\t\t\tconst brain = brainOf(world, player)\n\t\t\tif (!brain || watched.has(brain)) continue\n\t\t\twatched.set(brain, brain.watch({ decided: (decision) => void decisions.push({ ...decision, player: brain.playerId, brain: brain.def.id }) }))\n\t\t}\n\t}\n\tlook()\n\tconst name = `core.ai.recordDecisions.${++recorders}`\n\tworld.addSystem({ name, update: look })\n\treturn {\n\t\tdecisions,\n\t\tstop() {\n\t\t\tworld.removeSystem(name)\n\t\t\tfor (const unwatch of watched.values()) unwatch()\n\t\t\twatched.clear()\n\t\t}\n\t}\n}\n\n/**\n * Where a game saved and loaded first decided otherwise than the game it was saved from (`checkComputerSave`): the\n * decision each made at that place in their logs. `null` where they decided alike to the end\n *\n * @beta\n */\nexport interface DecisionsApart {\n\t/** How many decisions since the save they shared before this one */\n\tindex: number\n\t/** The game that went on from the save */\n\tsaved?: RecordedDecision\n\t/** The game loaded from it */\n\tloaded?: RecordedDecision\n}\n\n/**\n * The seventh invariant of a computer player: a game saved at tick `from` and loaded makes the same decisions from then\n * on as the game it was saved from, under the same commands. Makes the world with `make` (its computers seated, as a\n * game seats them), runs it to `from`, saves it as a file would keep it and loads that with `game`, then runs both to\n * `ticks` and compares what every computer decided. What lost rng, tasks or memory in a restore shows as\n *\n * expect(await checkComputerSave(() => duel(), { from: 600, ticks: 2400, game: melee })).toBeNull()\n *\n * @beta\n */\nexport async function checkComputerSave(\n\tmake: () => World | Promise<World>,\n\toptions: { from: number; ticks: number; game: GameModule }\n): Promise<DecisionsApart | null> {\n\tconst saved = await make()\n\tlet loaded: World | undefined\n\ttry {\n\t\twhile (saved.tick < options.from) saved.step()\n\t\tloaded = await loadWorld(decodeSave(encodeSave(saveWorld(saved))), { game: options.game })\n\t\tconst before = recordDecisions(saved)\n\t\tconst after = recordDecisions(loaded)\n\t\twhile (saved.tick < options.ticks) {\n\t\t\tsaved.step()\n\t\t\tloaded.step()\n\t\t}\n\t\tbefore.stop()\n\t\tafter.stop()\n\t\tconst a = before.decisions\n\t\tconst b = after.decisions\n\t\tfor (let i = 0; i < Math.max(a.length, b.length); i++)\n\t\t\tif (JSON.stringify(a[i]) !== JSON.stringify(b[i])) return { index: i, ...(a[i] && { saved: a[i] }), ...(b[i] && { loaded: b[i] }) }\n\t\treturn null\n\t} finally {\n\t\tsaved.dispose()\n\t\tloaded?.dispose()\n\t}\n}\n","/**\n * `@v12-engine/engine/testing`: what a game's tests are written with. A world runs in a test as it does in a page, with no\n * screen: these make one, step it and give its units orders, so that a test says what happens in the game and little\n * else.\n *\n * const world = await testWorld(myGame.rules)\n * const knight = world.spawn('knight', 1, { x: 10, z: 10 })\n * order(world, [knight], { type: 'move', point: { x: 30, z: 10 } })\n * run(world, 5, () => knight.pos.x > 29)\n */\nimport type { Entity } from './entity'\nimport { createWorld, type GameModule } from './game'\nimport type { PlayerInit } from './player'\nimport type { Logger } from './log'\nimport type { OrderInit } from './registry'\nimport { Terrain } from './terrain'\nimport type { World } from './world'\n\n/**\n * Flat ground, `size` cells a side: 48 when left out\n *\n * @beta\n */\nexport const flatTerrain = (size = 48): Terrain => new Terrain(size, size, new Float32Array((size + 1) * (size + 1)))\n\n/**\n * The players of a test world, when a test says none: a neutral one, and two who are enemies\n *\n * @beta\n */\nexport const TEST_PLAYERS: PlayerInit[] = [\n\t{ id: 0, name: 'Neutral', team: 0, color: [1, 1, 0], neutral: true },\n\t{ id: 1, name: 'Player', team: 1, color: [0, 0, 1] },\n\t{ id: 2, name: 'Enemy', team: 2, color: [1, 0, 0] }\n]\n\n/**\n * A small world of a game for a test: flat ground, a neutral player and two enemies (`TEST_PLAYERS`), the same every\n * time (seed 7). Each of them is the test's to say otherwise\n *\n * @beta\n */\nexport function testWorld(\n\tgame: GameModule,\n\toptions: { terrain?: Terrain; size?: number; players?: PlayerInit[]; seed?: number; log?: Logger } = {}\n): Promise<World> {\n\treturn createWorld({\n\t\tterrain: options.terrain ?? flatTerrain(options.size),\n\t\tgame,\n\t\tseed: options.seed ?? 7,\n\t\tplayers: options.players ?? TEST_PLAYERS.map((player) => ({ ...player })),\n\t\tlog: options.log\n\t})\n}\n\n/**\n * Steps the world for up to `seconds`, stopping early once `until` holds. Returns the time that went by in it\n *\n * @beta\n */\nexport function run(world: World, seconds: number, until?: () => boolean): number {\n\tconst ticks = Math.ceil(seconds * world.tickRate)\n\tfor (let i = 0; i < ticks; i++) {\n\t\tworld.step()\n\t\tif (until?.()) return (i + 1) / world.tickRate\n\t}\n\treturn seconds\n}\n\n/**\n * Gives units an order, as their owner would: taken up at the next tick. `queue` adds it after what they are doing\n *\n * @beta\n */\nexport const order = (world: World, entities: Entity[], init: OrderInit, queue = false): void =>\n\tworld.issue({ type: 'order', player: entities[0].owner, entities: entities.map((entity) => entity.id), order: init, queue })\n\n// the fixture game, every role of the kit with round numbers: see `fixture.ts`\nexport { fixtureGame, fixtureMap } from './fixture'\n// many games at once, for balance: see `simulate.ts`\nexport {\n\ttype BrainResults,\n\ttype ComputerMeasures,\n\tdefineSimulation,\n\tplayGame,\n\ttype Counted,\n\ttype SimulatedGame,\n\ttype SimulateOptions,\n\tsimulate,\n\ttype Simulation,\n\twinRates\n} from './simulate'\n// a computer player under test: see `aiTesting.ts`\nexport {\n\tbrainOf,\n\tcheckComputerSave,\n\ttype ComputerWatch,\n\ttype DecisionRecorder,\n\ttype DecisionsApart,\n\texpectDecision,\n\ttype FairPlay,\n\tfairPlay,\n\ttype RecordedDecision,\n\trecordDecisions,\n\tthinkOnce,\n\twatchComputer,\n\ttype WatchOptions\n} from './aiTesting'\n\nexport {\n\ttype Apart,\n\tcheckDeterminism,\n\ttype DeterminismOptions,\n\ttype DeterminismReport,\n\ttype Difference,\n\tfirstDifference,\n\tworldFingerprint,\n\tworldHash,\n\tworldState\n} from './determinism'\n"],"mappings":"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"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../src/testing.ts"],"sourcesContent":["/**\n * `@v12-engine/engine/testing`: what a game's tests are written with. A world runs in a test as it does in a page, with no\n * screen: these make one, step it and give its units orders, so that a test says what happens in the game and little\n * else.\n *\n * const world = await testWorld(myGame.rules)\n * const knight = world.spawn('knight', 1, { x: 10, z: 10 })\n * order(world, [knight], { type: 'move', point: { x: 30, z: 10 } })\n * run(world, 5, () => knight.pos.x > 29)\n */\nimport type { Entity } from './entity'\nimport { createWorld, type Rules } from './game'\nimport { type Game, rulesOf } from './createGame'\nimport type { PlayerInit } from './player'\nimport type { Logger } from './log'\nimport type { OrderInit } from './registry'\nimport { Terrain } from './terrain'\nimport type { World } from './world'\n\n/**\n * Flat ground, `size` cells a side: 48 when left out\n *\n * @beta\n */\nexport const flatTerrain = (size = 48): Terrain => new Terrain(size, size, new Float32Array((size + 1) * (size + 1)))\n\n/**\n * The players of a test world, when a test says none: a neutral one, and two who are enemies\n *\n * @beta\n */\nexport const TEST_PLAYERS: PlayerInit[] = [\n\t{ id: 0, name: 'Neutral', team: 0, color: [1, 1, 0], neutral: true },\n\t{ id: 1, name: 'Player', team: 1, color: [0, 0, 1] },\n\t{ id: 2, name: 'Enemy', team: 2, color: [1, 0, 0] }\n]\n\n/**\n * A small world of a game for a test (the game, `createGame`, or its module, `Rules`): flat ground, a neutral player and two enemies (`TEST_PLAYERS`), the same every\n * time (seed 7). Each of them is the test's to say otherwise\n *\n * @public\n */\nexport function testWorld(\n\tgame: Game<unknown> | Rules,\n\toptions: { terrain?: Terrain; size?: number; players?: PlayerInit[]; seed?: number; log?: Logger } = {}\n): Promise<World> {\n\treturn createWorld({\n\t\tterrain: options.terrain ?? flatTerrain(options.size),\n\t\trules: rulesOf(game),\n\t\tseed: options.seed ?? 7,\n\t\tplayers: options.players ?? TEST_PLAYERS.map((player) => ({ ...player })),\n\t\tlog: options.log\n\t})\n}\n\n/**\n * Steps the world for up to `seconds`, stopping early once `until` holds. Returns the time that went by in it\n *\n * @public\n */\nexport function run(world: World, seconds: number, until?: () => boolean): number {\n\tconst ticks = Math.ceil(seconds * world.tickRate)\n\tfor (let i = 0; i < ticks; i++) {\n\t\tworld.step()\n\t\tif (until?.()) return (i + 1) / world.tickRate\n\t}\n\treturn seconds\n}\n\n/**\n * Gives units an order, as their owner would: taken up at the next tick. `queue` adds it after what they are doing\n *\n * @public\n */\nexport const order = (world: World, entities: Entity[], init: OrderInit, queue = false): void =>\n\tworld.issue({ type: 'order', player: entities[0].owner, entities: entities.map((entity) => entity.id), order: init, queue })\n\n// the fixture game, every role of the kit with round numbers: see `fixture.ts`\nexport { fixtureGame, fixtureMap } from './fixture'\n// many games at once, for balance: see `simulate.ts`\nexport {\n\ttype BrainResults,\n\ttype ComputerMeasures,\n\tplayGame,\n\ttype Counted,\n\ttype SimulatedGame,\n\ttype SimulateOptions,\n\tsimulate,\n\ttype Simulation,\n\twinRates\n} from './simulate'\n// a computer player under test: see `aiTesting.ts`\nexport {\n\tbrainOf,\n\tcheckComputerSave,\n\ttype ComputerWatch,\n\ttype DecisionRecorder,\n\ttype DecisionsApart,\n\texpectDecision,\n\ttype FairPlay,\n\tfairPlay,\n\ttype RecordedDecision,\n\trecordDecisions,\n\tthinkOnce,\n\twatchComputer,\n\ttype WatchOptions\n} from './aiTesting'\n\nexport {\n\ttype Apart,\n\tcheckDeterminism,\n\ttype DeterminismOptions,\n\ttype DeterminismReport,\n\ttype Difference,\n\tfirstDifference,\n\tworldFingerprint,\n\tworldHash,\n\tworldState\n} from './determinism'\n"],"mappings":";;;;;;;;;;;;;AAwBA,IAAa,eAAe,OAAO,OAAgB,IAAI,QAAQ,MAAM,MAAM,IAAI,cAAc,OAAO,MAAM,OAAO,EAAE,CAAC;;;;;;AAOpH,IAAa,eAA6B;CACzC;EAAE,IAAI;EAAG,MAAM;EAAW,MAAM;EAAG,OAAO;GAAC;GAAG;GAAG;EAAC;EAAG,SAAS;CAAK;CACnE;EAAE,IAAI;EAAG,MAAM;EAAU,MAAM;EAAG,OAAO;GAAC;GAAG;GAAG;EAAC;CAAE;CACnD;EAAE,IAAI;EAAG,MAAM;EAAS,MAAM;EAAG,OAAO;GAAC;GAAG;GAAG;EAAC;CAAE;AACnD;;;;;;;AAQA,SAAgB,UACf,MACA,UAAqG,CAAC,GACrF;CACjB,OAAO,YAAY;EAClB,SAAS,QAAQ,WAAW,YAAY,QAAQ,IAAI;EACpD,OAAO,QAAQ,IAAI;EACnB,MAAM,QAAQ,QAAQ;EACtB,SAAS,QAAQ,WAAW,aAAa,KAAK,YAAY,EAAE,GAAG,OAAO,EAAE;EACxE,KAAK,QAAQ;CACd,CAAC;AACF;;;;;;AAOA,SAAgB,IAAI,OAAc,SAAiB,OAA+B;CACjF,MAAM,QAAQ,KAAK,KAAK,UAAU,MAAM,QAAQ;CAChD,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;EAC/B,MAAM,KAAK;EACX,IAAI,QAAQ,GAAG,QAAQ,IAAI,KAAK,MAAM;CACvC;CACA,OAAO;AACR;;;;;;AAOA,IAAa,SAAS,OAAc,UAAoB,MAAiB,QAAQ,UAChF,MAAM,MAAM;CAAE,MAAM;CAAS,QAAQ,SAAS,EAAE,CAAC;CAAO,UAAU,SAAS,KAAK,WAAW,OAAO,EAAE;CAAG,OAAO;CAAM;AAAM,CAAC"}
package/dist/tiles.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * What the ground of a map can be painted with, named by the game: grass, road, sand. A cell holds the index of its
3
3
  * paint: 0 for none, left to the slope and the height, and 1 and up for the game's tiles in the order it gives them
4
- * (`GameModule.tiles`). The rules read and paint by name (`registry.tile('road')`); what each looks like is the
4
+ * (`Rules.tiles`). The rules read and paint by name (`registry.tile('road')`); what each looks like is the
5
5
  * view's (`GameView.ground.tiles`).
6
6
  *
7
7
  * A map file says the name of each index it was painted with (`GameMap.tileset`), so that a map keeps its paint when
package/dist/tiles.js ADDED
@@ -0,0 +1,43 @@
1
+ //#region src/tiles.ts
2
+ /**
3
+ * Typed help for writing a tile
4
+ *
5
+ * @beta
6
+ */
7
+ var defineTile = (def) => def;
8
+ /**
9
+ * The most tiles a game can have: a cell holds its tile in a byte, and 0 is none
10
+ *
11
+ * @beta
12
+ */
13
+ var MAX_TILES = 255;
14
+ /**
15
+ * The tiles every map was painted with before maps said which: the client's list as it was then, by index. A map
16
+ * file of format 1 means these
17
+ *
18
+ * @internal
19
+ */
20
+ var LEGACY_TILESET = [
21
+ "grass",
22
+ "darkGrass",
23
+ "dirt",
24
+ "road",
25
+ "sand",
26
+ "rock",
27
+ "snow"
28
+ ];
29
+ /**
30
+ * The index of each tile of `from` in `to`, by name: what turns paint made with one list into paint of the other.
31
+ * A name `to` does not have is 0, no paint
32
+ *
33
+ * @internal
34
+ */
35
+ function tileRemap(from, to) {
36
+ const table = new Uint8Array(from.length + 1);
37
+ from.forEach((id, i) => table[i + 1] = to.indexOf(id) + 1);
38
+ return table;
39
+ }
40
+ //#endregion
41
+ export { LEGACY_TILESET, MAX_TILES, defineTile, tileRemap };
42
+
43
+ //# sourceMappingURL=tiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiles.js","names":[],"sources":["../src/tiles.ts"],"sourcesContent":["/**\n * What the ground of a map can be painted with, named by the game: grass, road, sand. A cell holds the index of its\n * paint: 0 for none, left to the slope and the height, and 1 and up for the game's tiles in the order it gives them\n * (`Rules.tiles`). The rules read and paint by name (`registry.tile('road')`); what each looks like is the\n * view's (`GameView.ground.tiles`).\n *\n * A map file says the name of each index it was painted with (`GameMap.tileset`), so that a map keeps its paint when\n * the game adds tiles or puts them in another order: it is brought in line with the game's list by name\n *\n * @beta\n */\nexport interface TileDef {\n\t/** Shared by every game, like other ids */\n\tid: string\n\t/** What the editor's palette calls it */\n\tname: string\n\t/**\n\t * How fast one on foot goes over it, as a multiplier of its speed: mud at 0.5, a road at 1.2. 1 when left out. What\n\t * flies or sails is not slowed; the game's own `moveSpeed` rule keeps the last word (`groundSpeedAt`)\n\t */\n\tspeed?: number\n}\n\n/**\n * Typed help for writing a tile\n *\n * @beta\n */\nexport const defineTile = (def: TileDef): TileDef => def\n\n/**\n * The most tiles a game can have: a cell holds its tile in a byte, and 0 is none\n *\n * @beta\n */\nexport const MAX_TILES = 255\n\n/**\n * The tiles every map was painted with before maps said which: the client's list as it was then, by index. A map\n * file of format 1 means these\n *\n * @internal\n */\nexport const LEGACY_TILESET: readonly string[] = ['grass', 'darkGrass', 'dirt', 'road', 'sand', 'rock', 'snow']\n\n/**\n * The index of each tile of `from` in `to`, by name: what turns paint made with one list into paint of the other.\n * A name `to` does not have is 0, no paint\n *\n * @internal\n */\nexport function tileRemap(from: readonly string[], to: readonly string[]): Uint8Array {\n\tconst table = new Uint8Array(from.length + 1)\n\tfrom.forEach((id, i) => (table[i + 1] = to.indexOf(id) + 1))\n\treturn table\n}\n"],"mappings":";;;;;;AA4BA,IAAa,cAAc,QAA0B;;;;;;AAOrD,IAAa,YAAY;;;;;;;AAQzB,IAAa,iBAAoC;CAAC;CAAS;CAAa;CAAQ;CAAQ;CAAQ;CAAQ;AAAM;;;;;;;AAQ9G,SAAgB,UAAU,MAAyB,IAAmC;CACrF,MAAM,QAAQ,IAAI,WAAW,KAAK,SAAS,CAAC;CAC5C,KAAK,SAAS,IAAI,MAAO,MAAM,IAAI,KAAK,GAAG,QAAQ,EAAE,IAAI,CAAE;CAC3D,OAAO;AACR"}
package/dist/timers.d.ts CHANGED
@@ -4,7 +4,7 @@ import type { System } from './registry';
4
4
  import type { World } from './world';
5
5
  /**
6
6
  * Something a game does after a while, or every so often: a wave coming, a spell wearing off, a line of dialog.
7
- * Made with `defineTimer` and given in `GameModule.timers`, the way listeners are, so that a loaded save finds the
7
+ * Made with `defineTimer` and given in `Rules.timers`, the way listeners are, so that a loaded save finds the
8
8
  * code by id: what is waiting in the world is data, which timer and with what, never a function
9
9
  *
10
10
  * @beta
@@ -12,14 +12,18 @@ import type { World } from './world';
12
12
  export interface TimerDef<T = any> {
13
13
  /** Shared by every game, like other ids: give it a prefix of the game's (`'td.waveComes'`) */
14
14
  readonly id: string;
15
+ /** What happens when the timer goes off: given the world, the data it was set with and which timer this is */
15
16
  run(world: World, data: T, timer: TimerInfo): void;
16
17
  }
17
18
  /**
18
- * Typed help: `defineTimer<{ wave: number }>('td.waveComes', (world, { wave }) => ...)`
19
+ * Typed help: `defineTimer<{ wave: number }>({ id: 'td.waveComes', run: (world, { wave }) => ... })`
19
20
  *
20
- * @beta
21
+ * @public
21
22
  */
22
- export declare function defineTimer<T = undefined>(id: string, run: (world: World, data: T, timer: TimerInfo) => void): TimerDef<T>;
23
+ export declare function defineTimer<T = undefined>(def: {
24
+ id: string;
25
+ run: (world: World, data: T, timer: TimerInfo) => void;
26
+ }): TimerDef<T>;
23
27
  /** A timer as it waits in the world. Plain data: it goes into a save */
24
28
  interface Waiting {
25
29
  /** Unique in the world, for `cancel` and `left` */
@@ -39,11 +43,17 @@ interface Waiting {
39
43
  * @beta
40
44
  */
41
45
  export interface WaitingTimer {
46
+ /** The waiting timer's id in the world, for `cancel` and `left` */
42
47
  id: number;
48
+ /** The id of the `TimerDef` it runs */
43
49
  timer: string;
50
+ /** What it was set with, handed to the timer's `run` */
44
51
  data: unknown;
52
+ /** Seconds until it next goes off */
45
53
  left: number;
54
+ /** Seconds between two times, for one that repeats */
46
55
  every?: number;
56
+ /** How many more times it goes off, for one that repeats a number of times */
47
57
  times?: number;
48
58
  }
49
59
  /**
@@ -65,6 +75,7 @@ export type EveryOptions<T> = {
65
75
  * @beta
66
76
  */
67
77
  export interface TimerInfo {
78
+ /** The id of the timer that went off, as `world.timers` gave it */
68
79
  id: number;
69
80
  /** How many more times it goes off after this one: 0 for the last, undefined for one that repeats forever */
70
81
  left?: number;
@@ -76,8 +87,11 @@ export interface TimerInfo {
76
87
  * @beta
77
88
  */
78
89
  export interface ShownTimer {
90
+ /** The timer's id in the world */
79
91
  id: number;
92
+ /** The words shown for it */
80
93
  label: Message;
94
+ /** The tick it goes off at, which the screen counts down to */
81
95
  at: number;
82
96
  }
83
97
  /** The timers each player is shown, by the id of each and its words: kept in the world, so that a save has them */
@@ -108,6 +122,9 @@ export declare const waitingTimers: (state: Record<string, unknown>) => string[]
108
122
  export declare class Timers {
109
123
  private readonly world;
110
124
  private readonly defs;
125
+ /** Those waiting as a binary heap, the first due on top (`heap`), and the list it was made of */
126
+ private due;
127
+ private heapOf;
111
128
  constructor(world: World, defs: readonly TimerDef[]);
112
129
  /** Goes off once, `seconds` from now. Returns its id, for `cancel` and `left` */
113
130
  after<T>(seconds: number, timer: TimerDef<T>, ...data: T extends undefined ? [] : [T]): number;
@@ -138,6 +155,14 @@ export declare class Timers {
138
155
  /** Sets off what is due. The `timers` system calls it at the start of every tick */
139
156
  update(): void;
140
157
  private add;
158
+ /**
159
+ * Those waiting as a heap, the first due on top: what `update` looks at, so that a tick with nothing due costs one
160
+ * look whatever waits. Worked out from the world's list, never saved, and made again when the list is another's (a
161
+ * loaded save, a state set whole)
162
+ */
163
+ private heap;
164
+ /** Takes the one at `index` out of the heap */
165
+ private take;
141
166
  private ticks;
142
167
  private state;
143
168
  }
package/dist/timers.js ADDED
@@ -0,0 +1,242 @@
1
+ import { defineComponent } from "./components.js";
2
+ import { toMessage } from "./messages.js";
3
+ import { assertPlainData } from "./debug2.js";
4
+ //#region src/timers.ts
5
+ /**
6
+ * Typed help: `defineTimer<{ wave: number }>({ id: 'td.waveComes', run: (world, { wave }) => ... })`
7
+ *
8
+ * @public
9
+ */
10
+ function defineTimer(def) {
11
+ return def;
12
+ }
13
+ /** The timers each player is shown, by the id of each and its words: kept in the world, so that a save has them */
14
+ var shownTimers = defineComponent({
15
+ id: "core.shownTimers",
16
+ default: () => ({})
17
+ });
18
+ /** The timers waiting in a world, kept in it so that a save has them */
19
+ var waiting = defineComponent({
20
+ id: "core.timers",
21
+ default: () => ({
22
+ next: 1,
23
+ list: []
24
+ })
25
+ });
26
+ /** The timers waiting in the state of a save, by the id of their definition: what a game must still have to load it */
27
+ var waitingTimers = (state) => (state[waiting.id]?.list ?? []).map((due) => due.timer);
28
+ /** Whether `a` goes off before `b`: the one due first, then the one set first */
29
+ var before = (a, b) => a.at < b.at || a.at === b.at && a.id < b.id;
30
+ /** Moves the one at `index` up the heap to where nothing above it goes off later */
31
+ function rise(heap, index) {
32
+ const entry = heap[index];
33
+ while (index > 0) {
34
+ const parent = index - 1 >> 1;
35
+ if (!before(entry, heap[parent])) break;
36
+ heap[index] = heap[parent];
37
+ index = parent;
38
+ }
39
+ heap[index] = entry;
40
+ }
41
+ /** Moves the one at `index` down the heap to where nothing below it goes off sooner */
42
+ function sink(heap, index) {
43
+ const entry = heap[index];
44
+ const size = heap.length;
45
+ for (;;) {
46
+ let child = 2 * index + 1;
47
+ if (child >= size) break;
48
+ if (child + 1 < size && before(heap[child + 1], heap[child])) child++;
49
+ if (!before(heap[child], entry)) break;
50
+ heap[index] = heap[child];
51
+ index = child;
52
+ }
53
+ heap[index] = entry;
54
+ }
55
+ /**
56
+ * The timers of a world. Time is counted in ticks, which every machine counts the same, never with the clock:
57
+ * a timer goes off at the start of the tick it is due, after the players' commands and before anything else, in the
58
+ * order they are due and then the order they were set
59
+ *
60
+ * @beta
61
+ */
62
+ var Timers = class {
63
+ world;
64
+ defs = /* @__PURE__ */ new Map();
65
+ /** Those waiting as a binary heap, the first due on top (`heap`), and the list it was made of */
66
+ due = [];
67
+ heapOf;
68
+ constructor(world, defs) {
69
+ this.world = world;
70
+ for (const def of defs) {
71
+ if (this.defs.has(def.id)) throw new Error(`Timer "${def.id}" is there twice`);
72
+ this.defs.set(def.id, def);
73
+ }
74
+ }
75
+ /** Goes off once, `seconds` from now. Returns its id, for `cancel` and `left` */
76
+ after(seconds, timer, ...data) {
77
+ return this.add(timer, data[0], this.ticks(seconds));
78
+ }
79
+ /**
80
+ * Goes off every `seconds`: the first time `seconds` from now, or after `first` seconds; `times` times, or until
81
+ * cancelled. Returns its id
82
+ */
83
+ every(seconds, timer, options) {
84
+ const every = Math.max(1, this.ticks(seconds));
85
+ if (options.times !== void 0 && options.times < 1) return 0;
86
+ return this.add(timer, options.data, options.first === void 0 ? every : this.ticks(options.first), every, options.times);
87
+ }
88
+ /** Stops a timer from going off again. Whether it was still waiting */
89
+ cancel(id) {
90
+ const state = this.state();
91
+ const index = state.list.findIndex((entry) => entry.id === id);
92
+ if (index < 0) return false;
93
+ const heap = this.heap(state);
94
+ const [gone] = state.list.splice(index, 1);
95
+ this.take(heap, heap.indexOf(gone));
96
+ return true;
97
+ }
98
+ /**
99
+ * Shows a player a timer (campaign plan CP5): its words and when it goes off, counted down on their screen (the HUD's
100
+ * timers) for as long as it waits. A timer that repeats is shown to each time it next goes off
101
+ */
102
+ show(player, id, options) {
103
+ const all = { ...this.world.state(shownTimers) };
104
+ all[player] = [...(all[player] ?? []).filter((shown) => shown.id !== id), {
105
+ id,
106
+ label: toMessage(options.label)
107
+ }];
108
+ this.world.setState(shownTimers, all);
109
+ }
110
+ /** Shows a player a timer no more */
111
+ hide(player, id) {
112
+ const all = { ...this.world.state(shownTimers) };
113
+ if (!all[player]) return;
114
+ all[player] = all[player].filter((shown) => shown.id !== id);
115
+ this.world.setState(shownTimers, all);
116
+ }
117
+ /** The timers a player is shown that still wait, with the tick each goes off at next */
118
+ shownTo(player) {
119
+ const shown = this.world.states.has(shownTimers) ? this.world.state(shownTimers)[player] : void 0;
120
+ if (!shown?.length) return [];
121
+ const { list } = this.state();
122
+ return shown.flatMap(({ id, label }) => {
123
+ const entry = list.find((candidate) => candidate.id === id);
124
+ return entry ? [{
125
+ id,
126
+ label,
127
+ at: entry.at
128
+ }] : [];
129
+ });
130
+ }
131
+ /** Seconds until the timer next goes off, or undefined when it is not waiting any more */
132
+ left(id) {
133
+ const entry = this.state().list.find((candidate) => candidate.id === id);
134
+ return entry && (entry.at - this.world.tick) / this.world.tickRate;
135
+ }
136
+ /** Whether the timer is still waiting */
137
+ has(id) {
138
+ return this.state().list.some((entry) => entry.id === id);
139
+ }
140
+ /** What is waiting, in the order it was set: a copy, for the debug tools */
141
+ list() {
142
+ const { tickRate, tick } = this.world;
143
+ return this.state().list.map((entry) => ({
144
+ id: entry.id,
145
+ timer: entry.timer,
146
+ data: structuredClone(entry.data),
147
+ left: (entry.at - tick) / tickRate,
148
+ every: entry.every === void 0 ? void 0 : entry.every / tickRate,
149
+ times: entry.times
150
+ }));
151
+ }
152
+ /** Sets off what is due. The `timers` system calls it at the start of every tick */
153
+ update() {
154
+ const state = this.state();
155
+ const now = this.world.tick;
156
+ for (;;) {
157
+ const heap = this.heap(state);
158
+ const due = heap[0];
159
+ if (!due || due.at > now) return;
160
+ const def = this.defs.get(due.timer);
161
+ if (!def) throw new Error(`Timer "${due.timer}" went off, and the game has no such timer: give it in Rules.timers`);
162
+ const last = due.times === 1 || due.every === void 0;
163
+ if (last) {
164
+ state.list.splice(state.list.indexOf(due), 1);
165
+ this.take(heap, 0);
166
+ } else {
167
+ due.at += due.every;
168
+ if (due.times !== void 0) due.times--;
169
+ sink(heap, 0);
170
+ }
171
+ if (this.world.disabled.has(`timer:${due.timer}`)) continue;
172
+ try {
173
+ def.run(this.world, due.data, {
174
+ id: due.id,
175
+ left: last ? 0 : due.times
176
+ });
177
+ } catch (error) {
178
+ this.world.caught(error, {
179
+ kind: "timer",
180
+ id: due.timer
181
+ });
182
+ }
183
+ }
184
+ }
185
+ add(timer, data, after, every, times) {
186
+ if (!this.defs.has(timer.id)) throw new Error(`Timer "${timer.id}" is not the game's: give it in Rules.timers, so that a save can find it`);
187
+ if (this.world.checks.events) assertPlainData(data, `Timer "${timer.id}"`);
188
+ const state = this.state();
189
+ const id = state.next++;
190
+ const entry = {
191
+ id,
192
+ timer: timer.id,
193
+ data,
194
+ at: this.world.tick + Math.max(1, after),
195
+ every,
196
+ times
197
+ };
198
+ const heap = this.heap(state);
199
+ state.list.push(entry);
200
+ heap.push(entry);
201
+ rise(heap, heap.length - 1);
202
+ return id;
203
+ }
204
+ /**
205
+ * Those waiting as a heap, the first due on top: what `update` looks at, so that a tick with nothing due costs one
206
+ * look whatever waits. Worked out from the world's list, never saved, and made again when the list is another's (a
207
+ * loaded save, a state set whole)
208
+ */
209
+ heap(state) {
210
+ if (this.heapOf !== state.list || this.due.length !== state.list.length) {
211
+ this.due = [...state.list].sort((a, b) => before(a, b) ? -1 : 1);
212
+ this.heapOf = state.list;
213
+ }
214
+ return this.due;
215
+ }
216
+ /** Takes the one at `index` out of the heap */
217
+ take(heap, index) {
218
+ const moved = heap.pop();
219
+ if (index >= heap.length) return;
220
+ heap[index] = moved;
221
+ rise(heap, index);
222
+ sink(heap, index);
223
+ }
224
+ ticks(seconds) {
225
+ return Math.round(seconds * this.world.tickRate);
226
+ }
227
+ state() {
228
+ return this.world.state(waiting);
229
+ }
230
+ };
231
+ /** Sets off the timers that are due, at the start of the tick, after the players' commands */
232
+ var timerSystem = {
233
+ name: "timers",
234
+ phase: "commands",
235
+ update(world) {
236
+ world.timers.update();
237
+ }
238
+ };
239
+ //#endregion
240
+ export { Timers, defineTimer, shownTimers, timerSystem, waiting, waitingTimers };
241
+
242
+ //# sourceMappingURL=timers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timers.js","names":[],"sources":["../src/timers.ts"],"sourcesContent":["import { defineComponent } from './components'\nimport { assertPlainData } from './debug'\nimport type { PlayerId } from './entity'\nimport { type Message, type MessageRef, toMessage } from './messages'\nimport type { System } from './registry'\nimport type { World } from './world'\n\n/**\n * Something a game does after a while, or every so often: a wave coming, a spell wearing off, a line of dialog.\n * Made with `defineTimer` and given in `Rules.timers`, the way listeners are, so that a loaded save finds the\n * code by id: what is waiting in the world is data, which timer and with what, never a function\n *\n * @beta\n */\nexport interface TimerDef<T = any> {\n\t/** Shared by every game, like other ids: give it a prefix of the game's (`'td.waveComes'`) */\n\treadonly id: string\n\t/** What happens when the timer goes off: given the world, the data it was set with and which timer this is */\n\trun(world: World, data: T, timer: TimerInfo): void\n}\n\n/**\n * Typed help: `defineTimer<{ wave: number }>({ id: 'td.waveComes', run: (world, { wave }) => ... })`\n *\n * @public\n */\nexport function defineTimer<T = undefined>(def: { id: string; run: (world: World, data: T, timer: TimerInfo) => void }): TimerDef<T> {\n\treturn def\n}\n\n/** A timer as it waits in the world. Plain data: it goes into a save */\ninterface Waiting {\n\t/** Unique in the world, for `cancel` and `left` */\n\tid: number\n\ttimer: string\n\tdata: unknown\n\t/** The tick it goes off at */\n\tat: number\n\t/** Ticks between two times, for one that repeats */\n\tevery?: number\n\t/** How many times it still goes off, for one that repeats a number of times. Forever when left out */\n\ttimes?: number\n}\n\n/**\n * A timer as the debug tools show it: seconds until it goes off, and between two times\n *\n * @beta\n */\nexport interface WaitingTimer {\n\t/** The waiting timer's id in the world, for `cancel` and `left` */\n\tid: number\n\t/** The id of the `TimerDef` it runs */\n\ttimer: string\n\t/** What it was set with, handed to the timer's `run` */\n\tdata: unknown\n\t/** Seconds until it next goes off */\n\tleft: number\n\t/** Seconds between two times, for one that repeats */\n\tevery?: number\n\t/** How many more times it goes off, for one that repeats a number of times */\n\ttimes?: number\n}\n\n/**\n * How a timer repeats, and what it is given, for one whose handler takes something\n *\n * @beta\n */\nexport type EveryOptions<T> = { times?: number; first?: number } & (T extends undefined ? { data?: undefined } : { data: T })\n\n/**\n * What a timer's handler is told about the time it went off\n *\n * @beta\n */\nexport interface TimerInfo {\n\t/** The id of the timer that went off, as `world.timers` gave it */\n\tid: number\n\t/** How many more times it goes off after this one: 0 for the last, undefined for one that repeats forever */\n\tleft?: number\n}\n\n/**\n * A timer the rules show a player (`world.timers.show`): its words, and the tick it goes off at, for the screen to count\n * down to\n *\n * @beta\n */\nexport interface ShownTimer {\n\t/** The timer's id in the world */\n\tid: number\n\t/** The words shown for it */\n\tlabel: Message\n\t/** The tick it goes off at, which the screen counts down to */\n\tat: number\n}\n\n/** The timers each player is shown, by the id of each and its words: kept in the world, so that a save has them */\nexport const shownTimers = defineComponent<Record<number, { id: number; label: Message }[]>>({ id: 'core.shownTimers', default: () => ({}) })\n\n/** The timers waiting in a world, kept in it so that a save has them */\nexport const waiting = defineComponent<{ next: number; list: Waiting[] }>({ id: 'core.timers', default: () => ({ next: 1, list: [] }) })\n\n/** The timers waiting in the state of a save, by the id of their definition: what a game must still have to load it */\nexport const waitingTimers = (state: Record<string, unknown>): string[] =>\n\t((state[waiting.id] as { list?: Waiting[] } | undefined)?.list ?? []).map((due) => due.timer)\n\n/** Whether `a` goes off before `b`: the one due first, then the one set first */\nconst before = (a: Waiting, b: Waiting): boolean => a.at < b.at || (a.at === b.at && a.id < b.id)\n\n/** Moves the one at `index` up the heap to where nothing above it goes off later */\nfunction rise(heap: Waiting[], index: number): void {\n\tconst entry = heap[index]\n\twhile (index > 0) {\n\t\tconst parent = (index - 1) >> 1\n\t\tif (!before(entry, heap[parent])) break\n\t\theap[index] = heap[parent]\n\t\tindex = parent\n\t}\n\theap[index] = entry\n}\n\n/** Moves the one at `index` down the heap to where nothing below it goes off sooner */\nfunction sink(heap: Waiting[], index: number): void {\n\tconst entry = heap[index]\n\tconst size = heap.length\n\tfor (;;) {\n\t\tlet child = 2 * index + 1\n\t\tif (child >= size) break\n\t\tif (child + 1 < size && before(heap[child + 1], heap[child])) child++\n\t\tif (!before(heap[child], entry)) break\n\t\theap[index] = heap[child]\n\t\tindex = child\n\t}\n\theap[index] = entry\n}\n\n/**\n * The timers of a world. Time is counted in ticks, which every machine counts the same, never with the clock:\n * a timer goes off at the start of the tick it is due, after the players' commands and before anything else, in the\n * order they are due and then the order they were set\n *\n * @beta\n */\nexport class Timers {\n\tprivate readonly defs = new Map<string, TimerDef>()\n\t/** Those waiting as a binary heap, the first due on top (`heap`), and the list it was made of */\n\tprivate due: Waiting[] = []\n\tprivate heapOf: Waiting[] | undefined\n\n\tconstructor(\n\t\tprivate readonly world: World,\n\t\tdefs: readonly TimerDef[]\n\t) {\n\t\tfor (const def of defs) {\n\t\t\tif (this.defs.has(def.id)) throw new Error(`Timer \"${def.id}\" is there twice`)\n\t\t\tthis.defs.set(def.id, def)\n\t\t}\n\t}\n\n\t/** Goes off once, `seconds` from now. Returns its id, for `cancel` and `left` */\n\tafter<T>(seconds: number, timer: TimerDef<T>, ...data: T extends undefined ? [] : [T]): number {\n\t\treturn this.add(timer, data[0], this.ticks(seconds))\n\t}\n\n\t/**\n\t * Goes off every `seconds`: the first time `seconds` from now, or after `first` seconds; `times` times, or until\n\t * cancelled. Returns its id\n\t */\n\tevery<T>(seconds: number, timer: TimerDef<T>, options: EveryOptions<T>): number {\n\t\tconst every = Math.max(1, this.ticks(seconds))\n\t\tif (options.times !== undefined && options.times < 1) return 0\n\t\treturn this.add(timer, options.data, options.first === undefined ? every : this.ticks(options.first), every, options.times)\n\t}\n\n\t/** Stops a timer from going off again. Whether it was still waiting */\n\tcancel(id: number): boolean {\n\t\tconst state = this.state()\n\t\tconst index = state.list.findIndex((entry) => entry.id === id)\n\t\tif (index < 0) return false\n\t\tconst heap = this.heap(state)\n\t\tconst [gone] = state.list.splice(index, 1)\n\t\tthis.take(heap, heap.indexOf(gone))\n\t\treturn true\n\t}\n\n\t/**\n\t * Shows a player a timer (campaign plan CP5): its words and when it goes off, counted down on their screen (the HUD's\n\t * timers) for as long as it waits. A timer that repeats is shown to each time it next goes off\n\t */\n\tshow(player: PlayerId, id: number, options: { label: MessageRef }): void {\n\t\tconst all = { ...this.world.state(shownTimers) }\n\t\tall[player] = [...(all[player] ?? []).filter((shown) => shown.id !== id), { id, label: toMessage(options.label) }]\n\t\tthis.world.setState(shownTimers, all)\n\t}\n\n\t/** Shows a player a timer no more */\n\thide(player: PlayerId, id: number): void {\n\t\tconst all = { ...this.world.state(shownTimers) }\n\t\tif (!all[player]) return\n\t\tall[player] = all[player].filter((shown) => shown.id !== id)\n\t\tthis.world.setState(shownTimers, all)\n\t}\n\n\t/** The timers a player is shown that still wait, with the tick each goes off at next */\n\tshownTo(player: PlayerId): ShownTimer[] {\n\t\tconst shown = this.world.states.has(shownTimers) ? this.world.state(shownTimers)[player] : undefined\n\t\tif (!shown?.length) return []\n\t\tconst { list } = this.state()\n\t\treturn shown.flatMap(({ id, label }) => {\n\t\t\tconst entry = list.find((candidate) => candidate.id === id)\n\t\t\treturn entry ? [{ id, label, at: entry.at }] : []\n\t\t})\n\t}\n\n\t/** Seconds until the timer next goes off, or undefined when it is not waiting any more */\n\tleft(id: number): number | undefined {\n\t\tconst entry = this.state().list.find((candidate) => candidate.id === id)\n\t\treturn entry && (entry.at - this.world.tick) / this.world.tickRate\n\t}\n\n\t/** Whether the timer is still waiting */\n\thas(id: number): boolean {\n\t\treturn this.state().list.some((entry) => entry.id === id)\n\t}\n\n\t/** What is waiting, in the order it was set: a copy, for the debug tools */\n\tlist(): WaitingTimer[] {\n\t\tconst { tickRate, tick } = this.world\n\t\treturn this.state().list.map((entry) => ({\n\t\t\tid: entry.id,\n\t\t\ttimer: entry.timer,\n\t\t\tdata: structuredClone(entry.data),\n\t\t\tleft: (entry.at - tick) / tickRate,\n\t\t\tevery: entry.every === undefined ? undefined : entry.every / tickRate,\n\t\t\ttimes: entry.times\n\t\t}))\n\t}\n\n\t/** Sets off what is due. The `timers` system calls it at the start of every tick */\n\tupdate(): void {\n\t\tconst state = this.state()\n\t\tconst now = this.world.tick\n\t\t// one at a time, the first due of those waiting each time: a timer that goes off may set or cancel others\n\t\tfor (;;) {\n\t\t\tconst heap = this.heap(state)\n\t\t\tconst due = heap[0]\n\t\t\tif (!due || due.at > now) return\n\t\t\tconst def = this.defs.get(due.timer)\n\t\t\tif (!def) throw new Error(`Timer \"${due.timer}\" went off, and the game has no such timer: give it in Rules.timers`)\n\t\t\tconst last = due.times === 1 || due.every === undefined\n\t\t\tif (last) {\n\t\t\t\tstate.list.splice(state.list.indexOf(due), 1)\n\t\t\t\tthis.take(heap, 0)\n\t\t\t} else {\n\t\t\t\tdue.at += due.every!\n\t\t\t\tif (due.times !== undefined) due.times--\n\t\t\t\tsink(heap, 0)\n\t\t\t}\n\t\t\t// one switched off for having thrown (`World.caught`) no longer goes off: what was set is let go\n\t\t\tif (this.world.disabled.has(`timer:${due.timer}`)) continue\n\t\t\ttry {\n\t\t\t\tdef.run(this.world, due.data, { id: due.id, left: last ? 0 : due.times })\n\t\t\t} catch (error) {\n\t\t\t\tthis.world.caught(error, { kind: 'timer', id: due.timer })\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate add(timer: TimerDef, data: unknown, after: number, every?: number, times?: number): number {\n\t\tif (!this.defs.has(timer.id)) throw new Error(`Timer \"${timer.id}\" is not the game's: give it in Rules.timers, so that a save can find it`)\n\t\tif (this.world.checks.events) assertPlainData(data, `Timer \"${timer.id}\"`)\n\t\tconst state = this.state()\n\t\tconst id = state.next++\n\t\t// due at the start of a later tick: never the one that is going on\n\t\tconst entry: Waiting = { id, timer: timer.id, data, at: this.world.tick + Math.max(1, after), every, times }\n\t\tconst heap = this.heap(state)\n\t\tstate.list.push(entry)\n\t\theap.push(entry)\n\t\trise(heap, heap.length - 1)\n\t\treturn id\n\t}\n\n\t/**\n\t * Those waiting as a heap, the first due on top: what `update` looks at, so that a tick with nothing due costs one\n\t * look whatever waits. Worked out from the world's list, never saved, and made again when the list is another's (a\n\t * loaded save, a state set whole)\n\t */\n\tprivate heap(state: { list: Waiting[] }): Waiting[] {\n\t\tif (this.heapOf !== state.list || this.due.length !== state.list.length) {\n\t\t\t// sorted is a heap already\n\t\t\tthis.due = [...state.list].sort((a, b) => (before(a, b) ? -1 : 1))\n\t\t\tthis.heapOf = state.list\n\t\t}\n\t\treturn this.due\n\t}\n\n\t/** Takes the one at `index` out of the heap */\n\tprivate take(heap: Waiting[], index: number): void {\n\t\tconst moved = heap.pop()!\n\t\tif (index >= heap.length) return\n\t\theap[index] = moved\n\t\trise(heap, index)\n\t\tsink(heap, index)\n\t}\n\n\tprivate ticks(seconds: number): number {\n\t\treturn Math.round(seconds * this.world.tickRate)\n\t}\n\n\tprivate state() {\n\t\treturn this.world.state(waiting)\n\t}\n}\n\n/** Sets off the timers that are due, at the start of the tick, after the players' commands */\nexport const timerSystem: System = {\n\tname: 'timers',\n\tphase: 'commands',\n\tupdate(world) {\n\t\tworld.timers.update()\n\t}\n}\n"],"mappings":"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"}
package/dist/tomes.d.ts CHANGED
@@ -31,18 +31,18 @@ export declare const gainedStats: import("./components").Component<GainedStats,
31
31
  /**
32
32
  * Gives a unit stats for good, as a tome does: added to what it gained before, kept with it in a save, its health and
33
33
  * mana raised with them. For the tomes pack's `tome` effect and a game's own rules (a shrine that makes a unit
34
- * stronger); it works in a game with the tomes pack (`withTomes`), which adds what was gained to the stats
34
+ * stronger); it works in a game with the tomes pack (`tomesPack`), which adds what was gained to the stats
35
35
  *
36
36
  * @beta
37
37
  */
38
38
  export declare function gainStats(world: World, entity: Entity, change: StatChange): void;
39
39
  /**
40
40
  * Tomes, as in classic RTS games: the `tome` effect (`EffectTypes.tome`) gives what it reaches stats for good (`gain`: a
41
- * point of strength with the attributes pack), a hero experience (`xp`) and levels (`levels`). A tome is an item whose
41
+ * point of a stat of the game's own), a hero experience (`xp`) and levels (`levels`). A tome is an item whose
42
42
  * ability has the effect, with a charge, used from the inventory, or as it is picked up with the runes pack
43
- * (`withRunes`). What a unit gained is kept with it and in a save (`gainedStats`), and a game gives it from its own
43
+ * (`runesPack`). What a unit gained is kept with it and in a save (`gainedStats`), and a game gives it from its own
44
44
  * rules with `gainStats`
45
45
  *
46
46
  * @beta
47
47
  */
48
- export declare function withTomes(): GamePack;
48
+ export declare function tomesPack(): GamePack;
package/dist/tomes.js ADDED
@@ -0,0 +1,94 @@
1
+ import { defineComponent } from "./components.js";
2
+ import { invalidateStats, refreshVitals } from "./stats.js";
3
+ import { grantXp, heroOf, maxLevelOf } from "./hero.js";
4
+ import { defineEffect, effectTargets } from "./abilities/effects.js";
5
+ //#region src/tomes.ts
6
+ /**
7
+ * The tomes pack's id
8
+ *
9
+ * @beta
10
+ */
11
+ var TOMES = "core.tomes";
12
+ /**
13
+ * What a unit gained for good from tomes or the game's own rules (`gainStats`): saved with it
14
+ *
15
+ * @beta
16
+ */
17
+ var gainedStats = defineComponent({ id: "core.gainedStats" });
18
+ /**
19
+ * Gives a unit stats for good, as a tome does: added to what it gained before, kept with it in a save, its health and
20
+ * mana raised with them. For the tomes pack's `tome` effect and a game's own rules (a shrine that makes a unit
21
+ * stronger); it works in a game with the tomes pack (`tomesPack`), which adds what was gained to the stats
22
+ *
23
+ * @beta
24
+ */
25
+ function gainStats(world, entity, change) {
26
+ const had = entity.get(gainedStats);
27
+ const next = {
28
+ stats: { ...had?.stats },
29
+ percent: { ...had?.percent },
30
+ times: (had?.times ?? 0) + 1
31
+ };
32
+ for (const key in change.stats) next.stats[key] = (next.stats[key] ?? 0) + change.stats[key];
33
+ for (const key in change.percent) next.percent[key] = (next.percent[key] ?? 0) + change.percent[key];
34
+ entity.set(gainedStats, next);
35
+ invalidateStats(world, entity);
36
+ refreshVitals(world, entity);
37
+ }
38
+ /** A tome read: what it gives for good, the experience and the levels it gives a hero */
39
+ var tomeEffect = defineEffect({
40
+ type: "tome",
41
+ run: (context, effect) => {
42
+ const { world } = context;
43
+ for (const entity of effectTargets(context, effect, "allies")) {
44
+ if (effect.gain) gainStats(world, entity, effect.gain);
45
+ if (effect.xp) grantXp(world, entity, effect.xp);
46
+ for (let i = 0; i < (effect.levels ?? 0); i++) {
47
+ const hero = heroOf(entity);
48
+ if (!hero || hero.level >= maxLevelOf(world, entity)) break;
49
+ grantXp(world, entity, world.settings.heroes.xpForLevel(hero.level + 1) - hero.xp);
50
+ }
51
+ }
52
+ },
53
+ fields: [{
54
+ path: "xp",
55
+ kind: "integer",
56
+ min: 0,
57
+ hint: "Experience a hero gains"
58
+ }, {
59
+ path: "levels",
60
+ kind: "integer",
61
+ min: 0,
62
+ hint: "Levels a hero gains"
63
+ }]
64
+ });
65
+ /** What was gained, added to the stats: worked out again each time something is gained */
66
+ var gained = {
67
+ id: "tomes",
68
+ stamp: (entity) => entity.get(gainedStats)?.times ?? 0,
69
+ add(_world, entity, sum) {
70
+ const had = entity.get(gainedStats);
71
+ if (had) sum.add(had);
72
+ }
73
+ };
74
+ /**
75
+ * Tomes, as in classic RTS games: the `tome` effect (`EffectTypes.tome`) gives what it reaches stats for good (`gain`: a
76
+ * point of a stat of the game's own), a hero experience (`xp`) and levels (`levels`). A tome is an item whose
77
+ * ability has the effect, with a charge, used from the inventory, or as it is picked up with the runes pack
78
+ * (`runesPack`). What a unit gained is kept with it and in a save (`gainedStats`), and a game gives it from its own
79
+ * rules with `gainStats`
80
+ *
81
+ * @beta
82
+ */
83
+ function tomesPack() {
84
+ return {
85
+ id: TOMES,
86
+ components: [gainedStats],
87
+ effects: [tomeEffect],
88
+ statFields: [gained]
89
+ };
90
+ }
91
+ //#endregion
92
+ export { TOMES, gainStats, gainedStats, tomesPack };
93
+
94
+ //# sourceMappingURL=tomes.js.map