azeroth-shell 0.0.0-stage → 0.1.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 (1163) hide show
  1. package/README.md +138 -2
  2. package/bin/azsh.mjs +19 -0
  3. package/docs/aifid/eventai-texts.json +4414 -0
  4. package/docs/dungeons/atlas/atlas-rows-dungeons.json +8989 -0
  5. package/docs/dungeons/survey/pack-id-migration.json +2418 -0
  6. package/package.json +26 -4
  7. package/src/autopilot/bossSkip.ts +26 -0
  8. package/src/autopilot/combatRotation.ts +824 -0
  9. package/src/autopilot/config.ts +533 -0
  10. package/src/autopilot/consumables.ts +58 -0
  11. package/src/autopilot/encounterStand.ts +121 -0
  12. package/src/autopilot/objectGatePlan.ts +53 -0
  13. package/src/autopilot/pathEngage.ts +229 -0
  14. package/src/autopilot/plan.ts +1643 -0
  15. package/src/autopilot/questPolicy.ts +274 -0
  16. package/src/autopilot/routeStep.ts +69 -0
  17. package/src/autopilot/sessionReport.ts +88 -0
  18. package/src/autopilot/topOffPower.ts +26 -0
  19. package/src/autopilot/view.ts +476 -0
  20. package/src/cli/bootCheck.mjs +34 -0
  21. package/src/cli/bootData.mjs +57 -0
  22. package/src/cli/combatLogFilter.ts +153 -0
  23. package/src/cli/combatLogFormat.ts +613 -0
  24. package/src/cli/fileRepository.mjs +105 -0
  25. package/src/cli/gzLoader.mjs +31 -0
  26. package/src/cli/liveGauntletEscort.ts +978 -0
  27. package/src/cli/liveStratUndead.ts +305 -0
  28. package/src/cli/macroHostCombat.ts +545 -0
  29. package/src/cli/macroHostWorld.ts +330 -0
  30. package/src/cli/prefs.mjs +31 -0
  31. package/src/cli/register.mjs +4 -0
  32. package/src/cli/repl.mjs +693 -0
  33. package/src/cli/rotationText.mjs +226 -0
  34. package/src/cli/squad.mjs +105 -0
  35. package/src/cli/term.mjs +126 -0
  36. package/src/cli/text.mjs +122 -0
  37. package/src/cli/tui.mjs +626 -0
  38. package/src/cli/tuiArena.mjs +109 -0
  39. package/src/cli/tuiAutopilotSettings.mjs +93 -0
  40. package/src/cli/tuiBags.mjs +180 -0
  41. package/src/cli/tuiBars.mjs +133 -0
  42. package/src/cli/tuiBg.mjs +243 -0
  43. package/src/cli/tuiBulk.mjs +162 -0
  44. package/src/cli/tuiCheck.mjs +1882 -0
  45. package/src/cli/tuiCity.mjs +396 -0
  46. package/src/cli/tuiCompanionKit.mjs +300 -0
  47. package/src/cli/tuiCompanions.mjs +471 -0
  48. package/src/cli/tuiDev.mjs +62 -0
  49. package/src/cli/tuiDungeon.mjs +606 -0
  50. package/src/cli/tuiEnchantTarget.mjs +120 -0
  51. package/src/cli/tuiFight.mjs +577 -0
  52. package/src/cli/tuiFightPanes.mjs +228 -0
  53. package/src/cli/tuiFloor.mjs +506 -0
  54. package/src/cli/tuiGear.mjs +158 -0
  55. package/src/cli/tuiHonor.mjs +74 -0
  56. package/src/cli/tuiLoot.mjs +97 -0
  57. package/src/cli/tuiMacros.mjs +144 -0
  58. package/src/cli/tuiOutfitter.mjs +115 -0
  59. package/src/cli/tuiPet.mjs +116 -0
  60. package/src/cli/tuiProfessions.mjs +800 -0
  61. package/src/cli/tuiRaid.mjs +127 -0
  62. package/src/cli/tuiRep.mjs +65 -0
  63. package/src/cli/tuiSaves.mjs +69 -0
  64. package/src/cli/tuiSearch.mjs +363 -0
  65. package/src/cli/tuiSettings.mjs +151 -0
  66. package/src/cli/tuiSimLab.mjs +80 -0
  67. package/src/cli/tuiTalents.mjs +60 -0
  68. package/src/cli/tuiViews.mjs +1178 -0
  69. package/src/cli/tuiWiki.mjs +181 -0
  70. package/src/cli/tuiWorld.mjs +361 -0
  71. package/src/cli/wikiIndex.ts +259 -0
  72. package/src/cli/wikiSources.ts +355 -0
  73. package/src/data/alteracValley.ts +176 -0
  74. package/src/data/appearanceOptions.ts +534 -0
  75. package/src/data/applyLootChanceSanity.ts +21 -0
  76. package/src/data/createFlavor.ts +96 -0
  77. package/src/data/customItems.ts +33 -0
  78. package/src/data/dataStore.ts +1904 -0
  79. package/src/data/dungeonGameObjects.ts +84 -0
  80. package/src/data/dungeonPlateCover.ts +66 -0
  81. package/src/data/dungeonSpawns.ts +294 -0
  82. package/src/data/dungeons/alterac-valley.ts +135 -0
  83. package/src/data/dungeons/apply-dungeon-rooms.ts +29 -0
  84. package/src/data/dungeons/apply-encounter-outdoors.ts +72 -0
  85. package/src/data/dungeons/apply-instance-geometry.ts +65 -0
  86. package/src/data/dungeons/apply-spawn-placement.ts +171 -0
  87. package/src/data/dungeons/blackfathom-deeps.ts +539 -0
  88. package/src/data/dungeons/blackrock-depths.ts +1410 -0
  89. package/src/data/dungeons/blackwing-lair.ts +129 -0
  90. package/src/data/dungeons/boss-eventai.ts +8 -0
  91. package/src/data/dungeons/deadmines.ts +410 -0
  92. package/src/data/dungeons/dire-maul-east.ts +980 -0
  93. package/src/data/dungeons/dire-maul-north.ts +661 -0
  94. package/src/data/dungeons/dire-maul-west.ts +785 -0
  95. package/src/data/dungeons/dungeon-rooms.json +5479 -0
  96. package/src/data/dungeons/encounter-outdoors.json +359 -0
  97. package/src/data/dungeons/eventai/blackfathom-deeps.ts +308 -0
  98. package/src/data/dungeons/eventai/blackrock-depths.ts +1257 -0
  99. package/src/data/dungeons/eventai/deadmines.ts +264 -0
  100. package/src/data/dungeons/eventai/dire-maul-east.ts +320 -0
  101. package/src/data/dungeons/eventai/gnomeregan.ts +213 -0
  102. package/src/data/dungeons/eventai/helpers.ts +79 -0
  103. package/src/data/dungeons/eventai/index.ts +133 -0
  104. package/src/data/dungeons/eventai/lbrs.ts +372 -0
  105. package/src/data/dungeons/eventai/maraudon.ts +323 -0
  106. package/src/data/dungeons/eventai/ragefire-chasm.ts +108 -0
  107. package/src/data/dungeons/eventai/razorfen-downs.ts +207 -0
  108. package/src/data/dungeons/eventai/razorfen-kraul.ts +326 -0
  109. package/src/data/dungeons/eventai/scholomance.ts +680 -0
  110. package/src/data/dungeons/eventai/shadowfang-keep.ts +230 -0
  111. package/src/data/dungeons/eventai/sm-cathedral.ts +75 -0
  112. package/src/data/dungeons/eventai/sm-graveyard.ts +150 -0
  113. package/src/data/dungeons/eventai/sm-library.ts +55 -0
  114. package/src/data/dungeons/eventai/stratholme-undead.ts +127 -0
  115. package/src/data/dungeons/eventai/sunken-temple.ts +582 -0
  116. package/src/data/dungeons/eventai/the-stockade.ts +228 -0
  117. package/src/data/dungeons/eventai/ubrs.ts +225 -0
  118. package/src/data/dungeons/eventai/uldaman.ts +355 -0
  119. package/src/data/dungeons/eventai/wailing-caverns.ts +396 -0
  120. package/src/data/dungeons/eventai/zul-farrak.ts +591 -0
  121. package/src/data/dungeons/gnomeregan.ts +909 -0
  122. package/src/data/dungeons/index.ts +126 -0
  123. package/src/data/dungeons/instance-geometry.json +5233 -0
  124. package/src/data/dungeons/key-sources.json +169 -0
  125. package/src/data/dungeons/lbrs.ts +996 -0
  126. package/src/data/dungeons/maraudon.ts +786 -0
  127. package/src/data/dungeons/molten-core.ts +194 -0
  128. package/src/data/dungeons/naxxramas.ts +173 -0
  129. package/src/data/dungeons/onyxias-lair.ts +71 -0
  130. package/src/data/dungeons/pack-from-clusters.ts +1256 -0
  131. package/src/data/dungeons/ragefire-chasm.ts +238 -0
  132. package/src/data/dungeons/razorfen-downs.ts +698 -0
  133. package/src/data/dungeons/razorfen-kraul.ts +766 -0
  134. package/src/data/dungeons/ruins-of-ahnqiraj.ts +121 -0
  135. package/src/data/dungeons/scholomance.ts +1076 -0
  136. package/src/data/dungeons/shadowfang-keep.ts +740 -0
  137. package/src/data/dungeons/sm-armory.ts +266 -0
  138. package/src/data/dungeons/sm-cathedral.ts +430 -0
  139. package/src/data/dungeons/sm-graveyard.ts +482 -0
  140. package/src/data/dungeons/sm-library.ts +337 -0
  141. package/src/data/dungeons/stratholme-live.ts +808 -0
  142. package/src/data/dungeons/stratholme-undead.ts +1164 -0
  143. package/src/data/dungeons/sunken-temple.ts +931 -0
  144. package/src/data/dungeons/temple-of-ahnqiraj.ts +119 -0
  145. package/src/data/dungeons/the-stockade.ts +282 -0
  146. package/src/data/dungeons/ubrs.ts +1286 -0
  147. package/src/data/dungeons/uldaman.ts +685 -0
  148. package/src/data/dungeons/wailing-caverns.ts +356 -0
  149. package/src/data/dungeons/zul-farrak.ts +686 -0
  150. package/src/data/dungeons/zul-gurub.ts +142 -0
  151. package/src/data/dungeons.ts +42 -0
  152. package/src/data/fixtures.ts +446 -0
  153. package/src/data/gameobject-data.json.gz +0 -0
  154. package/src/data/item-data.json.gz +0 -0
  155. package/src/data/loot-data.json.gz +0 -0
  156. package/src/data/maps/atlas-approach-maps.json +1425 -0
  157. package/src/data/maps/atlas-landmarks.json +1711 -0
  158. package/src/data/maps/dungeon-viewports.json +392 -0
  159. package/src/data/materializeModDamagePercentTaken.ts +70 -0
  160. package/src/data/materializeModHealthRegen.ts +89 -0
  161. package/src/data/materializeSpellReputation.ts +26 -0
  162. package/src/data/pageTexts.ts +19 -0
  163. package/src/data/profession-data.json.gz +0 -0
  164. package/src/data/raid-plans/blackfathom-deeps.json +86 -0
  165. package/src/data/raid-plans/blackrock-depths.json +419 -0
  166. package/src/data/raid-plans/blackwing-lair.json +328 -0
  167. package/src/data/raid-plans/deadmines.json +55 -0
  168. package/src/data/raid-plans/dire-maul-east.json +94 -0
  169. package/src/data/raid-plans/dire-maul-north.json +70 -0
  170. package/src/data/raid-plans/dire-maul-west.json +75 -0
  171. package/src/data/raid-plans/gnomeregan.json +131 -0
  172. package/src/data/raid-plans/lbrs.json +176 -0
  173. package/src/data/raid-plans/maraudon.json +102 -0
  174. package/src/data/raid-plans/molten-core.json +169 -0
  175. package/src/data/raid-plans/naxxramas.json +354 -0
  176. package/src/data/raid-plans/onyxias-lair.json +18 -0
  177. package/src/data/raid-plans/ragefire-chasm.json +30 -0
  178. package/src/data/raid-plans/razorfen-downs.json +75 -0
  179. package/src/data/raid-plans/razorfen-kraul.json +53 -0
  180. package/src/data/raid-plans/ruins-of-ahnqiraj.json +110 -0
  181. package/src/data/raid-plans/scholomance.json +170 -0
  182. package/src/data/raid-plans/shadowfang-keep.json +87 -0
  183. package/src/data/raid-plans/sm-armory.json +53 -0
  184. package/src/data/raid-plans/sm-cathedral.json +72 -0
  185. package/src/data/raid-plans/sm-graveyard.json +63 -0
  186. package/src/data/raid-plans/sm-library.json +23 -0
  187. package/src/data/raid-plans/stratholme-live.json +129 -0
  188. package/src/data/raid-plans/stratholme-undead.json +73 -0
  189. package/src/data/raid-plans/sunken-temple.json +159 -0
  190. package/src/data/raid-plans/temple-of-ahnqiraj.json +163 -0
  191. package/src/data/raid-plans/the-stockade.json +42 -0
  192. package/src/data/raid-plans/ubrs.json +53 -0
  193. package/src/data/raid-plans/uldaman.json +131 -0
  194. package/src/data/raid-plans/wailing-caverns.json +90 -0
  195. package/src/data/raid-plans/zul-farrak.json +156 -0
  196. package/src/data/raid-plans/zul-gurub.json +307 -0
  197. package/src/data/raidInstanceCreatures.mjs +473 -0
  198. package/src/data/rotations/index.ts +152 -0
  199. package/src/data/rotations/layout.mjs +72 -0
  200. package/src/data/rotations/pve/druid/balance.json +754 -0
  201. package/src/data/rotations/pve/druid/feral-tank.json +2448 -0
  202. package/src/data/rotations/pve/druid/feral.json +2660 -0
  203. package/src/data/rotations/pve/druid/restoration.json +424 -0
  204. package/src/data/rotations/pve/hunter/beast-mastery.json +1288 -0
  205. package/src/data/rotations/pve/hunter/marksmanship.json +1260 -0
  206. package/src/data/rotations/pve/hunter/survival.json +1373 -0
  207. package/src/data/rotations/pve/mage/arcane-leveling.json +1798 -0
  208. package/src/data/rotations/pve/mage/fire-leveling.json +2003 -0
  209. package/src/data/rotations/pve/mage/frost-leveling.json +1912 -0
  210. package/src/data/rotations/pve/paladin/holy.json +755 -0
  211. package/src/data/rotations/pve/paladin/protection.json +962 -0
  212. package/src/data/rotations/pve/paladin/retribution.json +924 -0
  213. package/src/data/rotations/pve/priest/discipline.json +772 -0
  214. package/src/data/rotations/pve/priest/holy.json +707 -0
  215. package/src/data/rotations/pve/priest/shadow.json +787 -0
  216. package/src/data/rotations/pve/rogue/assassination.json +2477 -0
  217. package/src/data/rotations/pve/rogue/combat.json +2483 -0
  218. package/src/data/rotations/pve/rogue/subtlety.json +2523 -0
  219. package/src/data/rotations/pve/shaman/elemental.json +1157 -0
  220. package/src/data/rotations/pve/shaman/enhancement.json +1085 -0
  221. package/src/data/rotations/pve/shaman/restoration.json +592 -0
  222. package/src/data/rotations/pve/warlock/affliction.json +1185 -0
  223. package/src/data/rotations/pve/warlock/demonology.json +1165 -0
  224. package/src/data/rotations/pve/warlock/destruction.json +1177 -0
  225. package/src/data/rotations/pve/warrior/arms.json +3020 -0
  226. package/src/data/rotations/pve/warrior/fury.json +2996 -0
  227. package/src/data/rotations/pve/warrior/protection.json +2509 -0
  228. package/src/data/rotations/pvp/druid/balance.json +593 -0
  229. package/src/data/rotations/pvp/druid/feral.json +3276 -0
  230. package/src/data/rotations/pvp/druid/restoration.json +662 -0
  231. package/src/data/rotations/pvp/hunter/beast-mastery.json +665 -0
  232. package/src/data/rotations/pvp/hunter/marksmanship.json +2406 -0
  233. package/src/data/rotations/pvp/hunter/survival.json +635 -0
  234. package/src/data/rotations/pvp/mage/arcane.json +574 -0
  235. package/src/data/rotations/pvp/mage/fire.json +570 -0
  236. package/src/data/rotations/pvp/mage/frost.json +4048 -0
  237. package/src/data/rotations/pvp/paladin/holy.json +1498 -0
  238. package/src/data/rotations/pvp/paladin/protection.json +567 -0
  239. package/src/data/rotations/pvp/paladin/retribution.json +1110 -0
  240. package/src/data/rotations/pvp/priest/discipline.json +1848 -0
  241. package/src/data/rotations/pvp/priest/holy.json +6340 -0
  242. package/src/data/rotations/pvp/priest/shadow.json +2329 -0
  243. package/src/data/rotations/pvp/rogue/assassination.json +1322 -0
  244. package/src/data/rotations/pvp/rogue/combat.json +5258 -0
  245. package/src/data/rotations/pvp/rogue/subtlety.json +586 -0
  246. package/src/data/rotations/pvp/shaman/elemental.json +1404 -0
  247. package/src/data/rotations/pvp/shaman/enhancement.json +1277 -0
  248. package/src/data/rotations/pvp/shaman/restoration.json +2490 -0
  249. package/src/data/rotations/pvp/warlock/affliction.json +1017 -0
  250. package/src/data/rotations/pvp/warlock/demonology.json +1503 -0
  251. package/src/data/rotations/pvp/warlock/destruction.json +638 -0
  252. package/src/data/rotations/pvp/warrior/arms.json +5665 -0
  253. package/src/data/rotations/pvp/warrior/fury.json +850 -0
  254. package/src/data/rotations/pvp/warrior/protection.json +777 -0
  255. package/src/data/schema/bundle.ts +511 -0
  256. package/src/data/schema/constants.ts +49 -0
  257. package/src/data/schema/creature.ts +454 -0
  258. package/src/data/schema/encounter.ts +155 -0
  259. package/src/data/schema/faction.ts +48 -0
  260. package/src/data/schema/item.ts +297 -0
  261. package/src/data/schema/itemEnchant.ts +105 -0
  262. package/src/data/schema/npc.ts +44 -0
  263. package/src/data/schema/primitives.ts +295 -0
  264. package/src/data/schema/profession.ts +226 -0
  265. package/src/data/schema/quest.ts +154 -0
  266. package/src/data/schema/spell.ts +1149 -0
  267. package/src/data/schema/talent.ts +74 -0
  268. package/src/data/schema/world.ts +124 -0
  269. package/src/data/schema.ts +19 -0
  270. package/src/data/skinNodeGapFill.ts +68 -0
  271. package/src/data/spell-data.json.gz +0 -0
  272. package/src/data/spell-script-targets.json +1 -0
  273. package/src/data/tables/ahItemValues.json.gz +0 -0
  274. package/src/data/tables/alteracValley.json.gz +0 -0
  275. package/src/data/tables/areatriggerTeleports.json.gz +0 -0
  276. package/src/data/tables/botNames.json.gz +0 -0
  277. package/src/data/tables/botPopulation.json.gz +0 -0
  278. package/src/data/tables/botSpecs.json.gz +0 -0
  279. package/src/data/tables/classLevelStats.json.gz +0 -0
  280. package/src/data/tables/combatConditions.json.gz +0 -0
  281. package/src/data/tables/combatSkillMeta.json.gz +0 -0
  282. package/src/data/tables/conditions.json.gz +0 -0
  283. package/src/data/tables/createInfo.json.gz +0 -0
  284. package/src/data/tables/creatureAggroGroups.json.gz +0 -0
  285. package/src/data/tables/creatureClassLevelStats.json.gz +0 -0
  286. package/src/data/tables/creaturePatrolPacks.json.gz +0 -0
  287. package/src/data/tables/creatureWeapons.json.gz +0 -0
  288. package/src/data/tables/creatures.json.gz +0 -0
  289. package/src/data/tables/dbScripts.json.gz +0 -0
  290. package/src/data/tables/dungeonAuthoredRoutes.json.gz +0 -0
  291. package/src/data/tables/dungeonCensus.json.gz +0 -0
  292. package/src/data/tables/dungeonGameObjects.json.gz +0 -0
  293. package/src/data/tables/dungeonPacks.json.gz +0 -0
  294. package/src/data/tables/dungeonPlateCover.json.gz +0 -0
  295. package/src/data/tables/dungeonSpawns.json.gz +0 -0
  296. package/src/data/tables/dungeonSurvey.json.gz +0 -0
  297. package/src/data/tables/durabilityCosts.json.gz +0 -0
  298. package/src/data/tables/durabilityQuality.json.gz +0 -0
  299. package/src/data/tables/enchantApplicators.json.gz +0 -0
  300. package/src/data/tables/entranceYards.json.gz +0 -0
  301. package/src/data/tables/explorationBasexp.json.gz +0 -0
  302. package/src/data/tables/factionTemplates.json.gz +0 -0
  303. package/src/data/tables/factions.json.gz +0 -0
  304. package/src/data/tables/gameEvents.json.gz +0 -0
  305. package/src/data/tables/gameObjects.json.gz +0 -0
  306. package/src/data/tables/gossipMenus.json.gz +0 -0
  307. package/src/data/tables/graveyards.json.gz +0 -0
  308. package/src/data/tables/instanceMaps.json.gz +0 -0
  309. package/src/data/tables/itemEnchantmentTemplates.json.gz +0 -0
  310. package/src/data/tables/itemEnchants.json.gz +0 -0
  311. package/src/data/tables/itemRandomProperties.json.gz +0 -0
  312. package/src/data/tables/itemSets.json.gz +0 -0
  313. package/src/data/tables/items.json.gz +0 -0
  314. package/src/data/tables/levelStats.json.gz +0 -0
  315. package/src/data/tables/locks.json.gz +0 -0
  316. package/src/data/tables/map-pin-overrides.json.gz +0 -0
  317. package/src/data/tables/nonCombatTrash.json.gz +0 -0
  318. package/src/data/tables/npcTexts.json.gz +0 -0
  319. package/src/data/tables/pageTexts.json.gz +0 -0
  320. package/src/data/tables/petAbilityTP.json.gz +0 -0
  321. package/src/data/tables/petGenericSpells.json.gz +0 -0
  322. package/src/data/tables/petLevelStats.json.gz +0 -0
  323. package/src/data/tables/playerbot-weightscales.json.gz +0 -0
  324. package/src/data/tables/pools.json.gz +0 -0
  325. package/src/data/tables/quests.json.gz +0 -0
  326. package/src/data/tables/races.json.gz +0 -0
  327. package/src/data/tables/reputationRanks.json.gz +0 -0
  328. package/src/data/tables/reputationRates.json.gz +0 -0
  329. package/src/data/tables/reputationSpillover.json.gz +0 -0
  330. package/src/data/tables/ridingSpells.json.gz +0 -0
  331. package/src/data/tables/scriptTexts.json.gz +0 -0
  332. package/src/data/tables/soundClipVolume.json.gz +0 -0
  333. package/src/data/tables/spellChain.json.gz +0 -0
  334. package/src/data/tables/spellTeleports.json.gz +0 -0
  335. package/src/data/tables/spells.json.gz +0 -0
  336. package/src/data/tables/talents.json.gz +0 -0
  337. package/src/data/tables/tavernTriggers.json.gz +0 -0
  338. package/src/data/tables/taxiNodes.json.gz +0 -0
  339. package/src/data/tables/taxiRoutes.json.gz +0 -0
  340. package/src/data/tables/trainers.json.gz +0 -0
  341. package/src/data/tables/transports.json.gz +0 -0
  342. package/src/data/tables/travelAnchors.json.gz +0 -0
  343. package/src/data/tables/travelEdges.json.gz +0 -0
  344. package/src/data/tables/unitConditions.json.gz +0 -0
  345. package/src/data/tables/vendors.json.gz +0 -0
  346. package/src/data/tables/weaponEnchantProcs.json.gz +0 -0
  347. package/src/data/tables/xp.json.gz +0 -0
  348. package/src/data/tables/zoneWeather.json.gz +0 -0
  349. package/src/data/tables/zones.json.gz +0 -0
  350. package/src/data/world-data.ts +56 -0
  351. package/src/data/zone-music-sets.json +2751 -0
  352. package/src/dev/etl/lib/loot-chance-sanity.mjs +180 -0
  353. package/src/domain/audioQuality.mjs +145 -0
  354. package/src/domain/bg/ab.ts +433 -0
  355. package/src/domain/bg/arenaComps.ts +644 -0
  356. package/src/domain/bg/arenaLab.ts +695 -0
  357. package/src/domain/bg/arenaPace.ts +31 -0
  358. package/src/domain/bg/arenaRating.ts +110 -0
  359. package/src/domain/bg/av.ts +758 -0
  360. package/src/domain/bg/avEnemyPush.ts +219 -0
  361. package/src/domain/bg/avField.ts +283 -0
  362. package/src/domain/bg/avInstanceNodes.ts +197 -0
  363. package/src/domain/bg/avInstanceScore.ts +123 -0
  364. package/src/domain/bg/avQuestItems.ts +55 -0
  365. package/src/domain/bg/avQuests.ts +210 -0
  366. package/src/domain/bg/avSession.ts +196 -0
  367. package/src/domain/bg/bgConsumes.ts +269 -0
  368. package/src/domain/bg/bgPrebuff.ts +153 -0
  369. package/src/domain/bg/bgRest.ts +91 -0
  370. package/src/domain/bg/bgRoster.ts +305 -0
  371. package/src/domain/bg/bgTier.ts +61 -0
  372. package/src/domain/bg/bgWorld.ts +862 -0
  373. package/src/domain/bg/match.ts +215 -0
  374. package/src/domain/bg/strategies.ts +552 -0
  375. package/src/domain/bg/types.ts +291 -0
  376. package/src/domain/bg/wsg.ts +264 -0
  377. package/src/domain/bots/actionProviderSpec.ts +38 -0
  378. package/src/domain/bots/autoConsumables.ts +285 -0
  379. package/src/domain/bots/betweenPullRest.ts +239 -0
  380. package/src/domain/bots/botGear.ts +248 -0
  381. package/src/domain/bots/botInventory.ts +486 -0
  382. package/src/domain/bots/botPet.ts +535 -0
  383. package/src/domain/bots/botPool.ts +291 -0
  384. package/src/domain/bots/botProfessions.ts +334 -0
  385. package/src/domain/bots/companionActionBar.ts +209 -0
  386. package/src/domain/bots/companionHireCost.ts +236 -0
  387. package/src/domain/bots/companionMissions.ts +582 -0
  388. package/src/domain/bots/companionPrep.ts +254 -0
  389. package/src/domain/bots/companionQuests.ts +270 -0
  390. package/src/domain/bots/companionRep.ts +75 -0
  391. package/src/domain/bots/companionRotation.ts +708 -0
  392. package/src/domain/bots/companionXp.ts +66 -0
  393. package/src/domain/bots/consumableShare.ts +811 -0
  394. package/src/domain/bots/dpsMate.ts +1072 -0
  395. package/src/domain/bots/groupCompReport.ts +132 -0
  396. package/src/domain/bots/healthstoneSupply.ts +198 -0
  397. package/src/domain/bots/outfitter.ts +1056 -0
  398. package/src/domain/bots/paladinPrePull.ts +231 -0
  399. package/src/domain/bots/partyRole.ts +40 -0
  400. package/src/domain/bots/playerbotEquipCache.ts +412 -0
  401. package/src/domain/bots/playerbotItemEligibility.ts +60 -0
  402. package/src/domain/bots/playerbotStatWeight.ts +853 -0
  403. package/src/domain/bots/playerbotUnavailableItems.ts +147 -0
  404. package/src/domain/bots/prePullBuffs.ts +219 -0
  405. package/src/domain/bots/prePullStealth.ts +82 -0
  406. package/src/domain/bots/runSupply.ts +251 -0
  407. package/src/domain/bots/runSupplyPrefs.ts +28 -0
  408. package/src/domain/bots/sendTradeGoods.ts +394 -0
  409. package/src/domain/bots/soulShardCap.ts +35 -0
  410. package/src/domain/bots/squad.ts +842 -0
  411. package/src/domain/bots/squadRun.ts +81 -0
  412. package/src/domain/character/actionbar.ts +346 -0
  413. package/src/domain/character/appearance.ts +165 -0
  414. package/src/domain/character/buildCombatant.ts +1726 -0
  415. package/src/domain/character/character.ts +356 -0
  416. package/src/domain/character/characterName.ts +43 -0
  417. package/src/domain/character/characterRatings.ts +424 -0
  418. package/src/domain/character/characterSpells.ts +282 -0
  419. package/src/domain/character/characterStats.ts +1559 -0
  420. package/src/domain/character/characterTalents.ts +398 -0
  421. package/src/domain/character/combatSkills.ts +994 -0
  422. package/src/domain/character/displayForm.ts +72 -0
  423. package/src/domain/character/formTalentAuras.ts +171 -0
  424. package/src/domain/character/forms.ts +499 -0
  425. package/src/domain/character/races.ts +40 -0
  426. package/src/domain/character/resurrectionSickness.ts +49 -0
  427. package/src/domain/character/spellbook.ts +169 -0
  428. package/src/domain/character/stanceBar.ts +354 -0
  429. package/src/domain/character/stancePrereq.ts +70 -0
  430. package/src/domain/character/talentBuilds.ts +63 -0
  431. package/src/domain/character/talentImport.ts +130 -0
  432. package/src/domain/character/talentLink.ts +123 -0
  433. package/src/domain/character/talents.ts +201 -0
  434. package/src/domain/core/conditionSnapshot.ts +92 -0
  435. package/src/domain/core/hover.ts +14 -0
  436. package/src/domain/core/ids.ts +58 -0
  437. package/src/domain/core/internalNameTags.ts +5 -0
  438. package/src/domain/core/runtimeDataPatches.ts +357 -0
  439. package/src/domain/creature/aiTargeting.ts +588 -0
  440. package/src/domain/creature/combatCondition.ts +157 -0
  441. package/src/domain/creature/creatureAggro.ts +804 -0
  442. package/src/domain/creature/creatureAi.ts +206 -0
  443. package/src/domain/creature/creatureAiConstants.ts +661 -0
  444. package/src/domain/creature/creatureCastList.ts +1007 -0
  445. package/src/domain/creature/creatureEventAi.ts +1409 -0
  446. package/src/domain/creature/creatureGroups.ts +144 -0
  447. package/src/domain/creature/creatureLinking.ts +333 -0
  448. package/src/domain/creature/creatureScaling.ts +320 -0
  449. package/src/domain/creature/creatureTrigger.ts +53 -0
  450. package/src/domain/creature/creatureWander.ts +74 -0
  451. package/src/domain/creature/eventAiTexts.ts +145 -0
  452. package/src/domain/creature/faction.ts +287 -0
  453. package/src/domain/creature/forcedReaction.ts +48 -0
  454. package/src/domain/creature/outdoorHuntable.ts +74 -0
  455. package/src/domain/creature/patrolPacks.ts +210 -0
  456. package/src/domain/creature/reputation.ts +967 -0
  457. package/src/domain/creature/unitFlags.ts +74 -0
  458. package/src/domain/creature/worldBosses.ts +393 -0
  459. package/src/domain/dungeonMusic.mjs +48 -0
  460. package/src/domain/economy/auction.ts +282 -0
  461. package/src/domain/economy/auctionBot.ts +1060 -0
  462. package/src/domain/economy/honorPrice.ts +100 -0
  463. package/src/domain/economy/mail.ts +958 -0
  464. package/src/domain/economy/money.ts +42 -0
  465. package/src/domain/economy/syntheticClassTrainers.ts +62 -0
  466. package/src/domain/economy/trading.ts +296 -0
  467. package/src/domain/economy/vendorSellAll.ts +252 -0
  468. package/src/domain/economy/vendorStock.ts +146 -0
  469. package/src/domain/items/ammo.ts +817 -0
  470. package/src/domain/items/bank.ts +162 -0
  471. package/src/domain/items/consumableFamily.ts +205 -0
  472. package/src/domain/items/craftUpgrades.ts +83 -0
  473. package/src/domain/items/createItem.ts +93 -0
  474. package/src/domain/items/durability.ts +581 -0
  475. package/src/domain/items/equipment.ts +441 -0
  476. package/src/domain/items/equipmentHelper.ts +767 -0
  477. package/src/domain/items/inventory.ts +561 -0
  478. package/src/domain/items/itemBonding.ts +93 -0
  479. package/src/domain/items/itemContainer.ts +245 -0
  480. package/src/domain/items/itemDisplayName.ts +33 -0
  481. package/src/domain/items/itemInstance.ts +181 -0
  482. package/src/domain/items/itemRandomEnchantOutcomes.ts +315 -0
  483. package/src/domain/items/itemRandomProps.ts +77 -0
  484. package/src/domain/items/itemRestrictions.ts +329 -0
  485. package/src/domain/items/itemTeaches.ts +82 -0
  486. package/src/domain/items/itemUseCooldown.ts +52 -0
  487. package/src/domain/items/itemUseTarget.ts +90 -0
  488. package/src/domain/items/junkCategories.ts +174 -0
  489. package/src/domain/items/junkFilter.ts +368 -0
  490. package/src/domain/items/keyring.ts +131 -0
  491. package/src/domain/items/loot.ts +221 -0
  492. package/src/domain/items/mounts.ts +190 -0
  493. package/src/domain/items/onUsePayload.ts +102 -0
  494. package/src/domain/items/pendingLoot.ts +107 -0
  495. package/src/domain/items/relic.ts +105 -0
  496. package/src/domain/items/rocketBoots.ts +36 -0
  497. package/src/domain/items/sortContainer.ts +139 -0
  498. package/src/domain/items/spareContainers.ts +71 -0
  499. package/src/domain/items/spellReagentIndex.ts +131 -0
  500. package/src/domain/items/staleConsumables.ts +66 -0
  501. package/src/domain/items/weaponSpender.ts +110 -0
  502. package/src/domain/listDungeonIds.mjs +28 -0
  503. package/src/domain/macro/compose.ts +239 -0
  504. package/src/domain/macro/conditions.ts +260 -0
  505. package/src/domain/macro/creatureTypes.ts +40 -0
  506. package/src/domain/macro/describe.ts +169 -0
  507. package/src/domain/macro/icon.ts +60 -0
  508. package/src/domain/macro/index.ts +20 -0
  509. package/src/domain/macro/normalize.ts +112 -0
  510. package/src/domain/macro/parse.ts +316 -0
  511. package/src/domain/macro/plan.ts +288 -0
  512. package/src/domain/macro/rotation.ts +590 -0
  513. package/src/domain/macro/rotationEnv.ts +173 -0
  514. package/src/domain/macro/slots.ts +101 -0
  515. package/src/domain/macro/snapshot.ts +114 -0
  516. package/src/domain/macro/templates.ts +446 -0
  517. package/src/domain/macro/types.ts +70 -0
  518. package/src/domain/macro/units.ts +93 -0
  519. package/src/domain/macro/weaponTypes.ts +83 -0
  520. package/src/domain/nav/cityTeleports.ts +10 -0
  521. package/src/domain/nav/mounting.ts +113 -0
  522. package/src/domain/nav/nav.ts +43 -0
  523. package/src/domain/nav/navCollision.ts +606 -0
  524. package/src/domain/nav/navOutdoors.ts +91 -0
  525. package/src/domain/nav/navRegistry.ts +179 -0
  526. package/src/domain/nav/navRoomGraph.ts +302 -0
  527. package/src/domain/nav/navTypes.ts +43 -0
  528. package/src/domain/nav/navmesh.ts +1715 -0
  529. package/src/domain/nav/speed.ts +200 -0
  530. package/src/domain/nav/storey.ts +10 -0
  531. package/src/domain/nav/travel.ts +725 -0
  532. package/src/domain/nav/travelTypes.ts +75 -0
  533. package/src/domain/pet/pet.ts +1150 -0
  534. package/src/domain/pet/petActionBar.ts +180 -0
  535. package/src/domain/pet/petSpellbook.ts +39 -0
  536. package/src/domain/pet/petStable.ts +81 -0
  537. package/src/domain/professions/autoDisenchant.ts +236 -0
  538. package/src/domain/professions/characterEnchants.ts +176 -0
  539. package/src/domain/professions/craftCooldown.ts +52 -0
  540. package/src/domain/professions/enchantApply.ts +62 -0
  541. package/src/domain/professions/enchantTargets.ts +114 -0
  542. package/src/domain/professions/enchanting.ts +236 -0
  543. package/src/domain/professions/gatherFilter.ts +149 -0
  544. package/src/domain/professions/gearEnchant.ts +137 -0
  545. package/src/domain/professions/heldTools.ts +29 -0
  546. package/src/domain/professions/learnAllRecipes.ts +146 -0
  547. package/src/domain/professions/miningHarvest.ts +69 -0
  548. package/src/domain/professions/partyDisenchant.ts +294 -0
  549. package/src/domain/professions/partyWork.ts +83 -0
  550. package/src/domain/professions/pickpocket.ts +172 -0
  551. package/src/domain/professions/poisons.ts +240 -0
  552. package/src/domain/professions/professions.ts +677 -0
  553. package/src/domain/professions/rareNodes.ts +45 -0
  554. package/src/domain/professions/skinLoot.ts +27 -0
  555. package/src/domain/professions/vendorReagents.ts +152 -0
  556. package/src/domain/professions/weaponImbueHand.ts +171 -0
  557. package/src/domain/questFarmFilter.mjs +42 -0
  558. package/src/domain/quests/doQuest.ts +1204 -0
  559. package/src/domain/quests/gossip.ts +308 -0
  560. package/src/domain/quests/gossipTalk.ts +298 -0
  561. package/src/domain/quests/interpreter/canComplete.ts +150 -0
  562. package/src/domain/quests/interpreter/claim.ts +137 -0
  563. package/src/domain/quests/interpreter/dbscript/handlers.ts +1371 -0
  564. package/src/domain/quests/interpreter/dbscript/handlersBatch.ts +1251 -0
  565. package/src/domain/quests/interpreter/dbscript/hooks.ts +331 -0
  566. package/src/domain/quests/interpreter/dbscript/index.ts +212 -0
  567. package/src/domain/quests/interpreter/dbscript/opcodes.ts +257 -0
  568. package/src/domain/quests/interpreter/dbscript/registry.ts +1194 -0
  569. package/src/domain/quests/interpreter/dbscript/registryAreatriggerScripts.ts +539 -0
  570. package/src/domain/quests/interpreter/dbscript/registryAshenvale.ts +553 -0
  571. package/src/domain/quests/interpreter/dbscript/registryAzshara.ts +272 -0
  572. package/src/domain/quests/interpreter/dbscript/registryDarkshore.ts +637 -0
  573. package/src/domain/quests/interpreter/dbscript/registryDesolace.ts +501 -0
  574. package/src/domain/quests/interpreter/dbscript/registryDustwallowMarsh.ts +735 -0
  575. package/src/domain/quests/interpreter/dbscript/registryFelwood.ts +493 -0
  576. package/src/domain/quests/interpreter/dbscript/registryFeralas.ts +485 -0
  577. package/src/domain/quests/interpreter/dbscript/registryGoScripts.ts +203 -0
  578. package/src/domain/quests/interpreter/dbscript/registryMoonglade.ts +288 -0
  579. package/src/domain/quests/interpreter/dbscript/registryNpcProfessions.ts +230 -0
  580. package/src/domain/quests/interpreter/dbscript/registryNpcsSpecial.ts +545 -0
  581. package/src/domain/quests/interpreter/dbscript/registryRazorfenDowns.ts +293 -0
  582. package/src/domain/quests/interpreter/dbscript/registryRazorfenKraul.ts +221 -0
  583. package/src/domain/quests/interpreter/dbscript/registryRedridge.ts +112 -0
  584. package/src/domain/quests/interpreter/dbscript/registrySearingGorge.ts +125 -0
  585. package/src/domain/quests/interpreter/dbscript/registrySiblings.ts +51 -0
  586. package/src/domain/quests/interpreter/dbscript/registrySilverpineForest.ts +172 -0
  587. package/src/domain/quests/interpreter/dbscript/registryStonetalonMountains.ts +180 -0
  588. package/src/domain/quests/interpreter/dbscript/registryStormwindCity.ts +369 -0
  589. package/src/domain/quests/interpreter/dbscript/registryStranglethornVale.ts +115 -0
  590. package/src/domain/quests/interpreter/dbscript/registryStratholme.ts +146 -0
  591. package/src/domain/quests/interpreter/dbscript/registrySunkenTemple.ts +149 -0
  592. package/src/domain/quests/interpreter/dbscript/registrySwampOfSorrows.ts +163 -0
  593. package/src/domain/quests/interpreter/dbscript/registryTanaris.ts +318 -0
  594. package/src/domain/quests/interpreter/dbscript/registryTeldrassil.ts +120 -0
  595. package/src/domain/quests/interpreter/dbscript/registryTheBarrens.ts +603 -0
  596. package/src/domain/quests/interpreter/dbscript/registryThousandNeedles.ts +499 -0
  597. package/src/domain/quests/interpreter/dbscript/registryTirisfalGlades.ts +222 -0
  598. package/src/domain/quests/interpreter/dbscript/registryUngoroCrater.ts +291 -0
  599. package/src/domain/quests/interpreter/dbscript/registryWarEffort.ts +773 -0
  600. package/src/domain/quests/interpreter/dbscript/registryWesternPlaguelands.ts +206 -0
  601. package/src/domain/quests/interpreter/dbscript/registryWestfall.ts +190 -0
  602. package/src/domain/quests/interpreter/dbscript/registryWetlands.ts +186 -0
  603. package/src/domain/quests/interpreter/dbscript/registryWinterspring.ts +235 -0
  604. package/src/domain/quests/interpreter/dbscript/types.ts +817 -0
  605. package/src/domain/quests/interpreter/dbscript/vm.ts +171 -0
  606. package/src/domain/quests/interpreter/diff.ts +349 -0
  607. package/src/domain/quests/interpreter/fixtures/oracle-questlog-qi2.json +2417 -0
  608. package/src/domain/quests/interpreter/flags.ts +101 -0
  609. package/src/domain/quests/interpreter/index.ts +113 -0
  610. package/src/domain/quests/interpreter/live.ts +178 -0
  611. package/src/domain/quests/interpreter/types.ts +81 -0
  612. package/src/domain/quests/interpreter/updaters.ts +412 -0
  613. package/src/domain/quests/questCorpseUse.ts +155 -0
  614. package/src/domain/quests/questDialog.ts +43 -0
  615. package/src/domain/quests/questFight.ts +34 -0
  616. package/src/domain/quests/questObjectiveLabel.ts +39 -0
  617. package/src/domain/quests/questRewardChoice.ts +85 -0
  618. package/src/domain/quests/questScriptCredit.ts +26 -0
  619. package/src/domain/quests/questScriptItemUse.ts +74 -0
  620. package/src/domain/quests/questTameRods.ts +79 -0
  621. package/src/domain/quests/questlog.ts +1545 -0
  622. package/src/domain/quests/talkDeliver.ts +170 -0
  623. package/src/domain/raid/globalActionBar.ts +195 -0
  624. package/src/domain/raid/instanceRoster.ts +194 -0
  625. package/src/domain/raid/partySummon.ts +198 -0
  626. package/src/domain/raid/partyVault.ts +320 -0
  627. package/src/domain/raid/raidBossAbilities.ts +268 -0
  628. package/src/domain/raid/raidComp.ts +335 -0
  629. package/src/domain/raid/raidCustomRows.ts +453 -0
  630. package/src/domain/raid/raidEncounterGear.ts +298 -0
  631. package/src/domain/raid/raidEncounterTactics.ts +412 -0
  632. package/src/domain/raid/raidPlan.ts +509 -0
  633. package/src/domain/raid/raidPlanEdits.ts +98 -0
  634. package/src/domain/raid/raidPlanPacks.ts +480 -0
  635. package/src/domain/raid/raidRecovery.ts +183 -0
  636. package/src/domain/raid/raidRosterTemplate.ts +138 -0
  637. package/src/domain/rotation/auraSide.ts +68 -0
  638. package/src/domain/rotation/build.ts +3031 -0
  639. package/src/domain/rotation/classes/druid.ts +58 -0
  640. package/src/domain/rotation/classes/hooks.ts +59 -0
  641. package/src/domain/rotation/classes/hunter.ts +156 -0
  642. package/src/domain/rotation/classes/index.ts +104 -0
  643. package/src/domain/rotation/classes/mage.ts +99 -0
  644. package/src/domain/rotation/classes/paladin.ts +296 -0
  645. package/src/domain/rotation/classes/priest.ts +94 -0
  646. package/src/domain/rotation/classes/pullOpener.ts +92 -0
  647. package/src/domain/rotation/classes/rogue.ts +69 -0
  648. package/src/domain/rotation/classes/shaman.ts +29 -0
  649. package/src/domain/rotation/classes/supportSpec.ts +94 -0
  650. package/src/domain/rotation/classes/warlock.ts +81 -0
  651. package/src/domain/rotation/classes/warrior.ts +402 -0
  652. package/src/domain/rotation/classify.ts +1381 -0
  653. package/src/domain/rotation/condMetricPicker.ts +379 -0
  654. package/src/domain/rotation/consumables.ts +242 -0
  655. package/src/domain/rotation/evaluate.ts +1115 -0
  656. package/src/domain/rotation/finisherLadder.ts +145 -0
  657. package/src/domain/rotation/invent.ts +938 -0
  658. package/src/domain/rotation/killOrder.ts +30 -0
  659. package/src/domain/rotation/openerForm.ts +22 -0
  660. package/src/domain/rotation/paladinBuffs.ts +568 -0
  661. package/src/domain/rotation/prebuff.ts +283 -0
  662. package/src/domain/rotation/raidRowTuning.ts +34 -0
  663. package/src/domain/rotation/rotation.ts +11 -0
  664. package/src/domain/rotation/rotationProfiles.ts +180 -0
  665. package/src/domain/rotation/rotationSuggestions.ts +851 -0
  666. package/src/domain/rotation/ruleAfterChain.ts +49 -0
  667. package/src/domain/rotation/spec.ts +70 -0
  668. package/src/domain/rotation/spellPicker.ts +140 -0
  669. package/src/domain/rotation/stand.ts +143 -0
  670. package/src/domain/rotation/types.ts +718 -0
  671. package/src/domain/run/battlegroundRun.ts +111 -0
  672. package/src/domain/run/canEnterContext.ts +32 -0
  673. package/src/domain/run/death.ts +561 -0
  674. package/src/domain/run/deathRecovery.ts +289 -0
  675. package/src/domain/run/duel.ts +141 -0
  676. package/src/domain/run/dungeonRun.ts +344 -0
  677. package/src/domain/run/floorRest.ts +159 -0
  678. package/src/domain/run/honor.ts +557 -0
  679. package/src/domain/run/honorWeek.ts +180 -0
  680. package/src/domain/run/whenMap.ts +977 -0
  681. package/src/domain/scriptdev/arathiHighlands.ts +445 -0
  682. package/src/domain/scriptdev/ashenvale.ts +635 -0
  683. package/src/domain/scriptdev/ashenvaleHelpers.ts +1215 -0
  684. package/src/domain/scriptdev/azshara.ts +892 -0
  685. package/src/domain/scriptdev/blackfathomDeeps.ts +212 -0
  686. package/src/domain/scriptdev/blackrockDepths.ts +1434 -0
  687. package/src/domain/scriptdev/blackrockSpire.ts +730 -0
  688. package/src/domain/scriptdev/blackwingLair.ts +521 -0
  689. package/src/domain/scriptdev/burningSteppes.ts +62 -0
  690. package/src/domain/scriptdev/classFilter.ts +43 -0
  691. package/src/domain/scriptdev/darkshore.ts +817 -0
  692. package/src/domain/scriptdev/darkshoreHelpers.ts +853 -0
  693. package/src/domain/scriptdev/deadmines.ts +331 -0
  694. package/src/domain/scriptdev/desolace.ts +1239 -0
  695. package/src/domain/scriptdev/direMaul.ts +859 -0
  696. package/src/domain/scriptdev/durotar.ts +532 -0
  697. package/src/domain/scriptdev/dustwallowMarsh.ts +758 -0
  698. package/src/domain/scriptdev/dustwallowMarshHelpers.ts +994 -0
  699. package/src/domain/scriptdev/easternPlaguelands.ts +21 -0
  700. package/src/domain/scriptdev/felwood.ts +1055 -0
  701. package/src/domain/scriptdev/feralas.ts +571 -0
  702. package/src/domain/scriptdev/feralasHelpers.ts +838 -0
  703. package/src/domain/scriptdev/gnomeregan.ts +466 -0
  704. package/src/domain/scriptdev/guards.ts +616 -0
  705. package/src/domain/scriptdev/hinterlands.ts +693 -0
  706. package/src/domain/scriptdev/host.ts +1134 -0
  707. package/src/domain/scriptdev/index.ts +123 -0
  708. package/src/domain/scriptdev/instanceRaids.ts +136 -0
  709. package/src/domain/scriptdev/itemScripts.ts +37 -0
  710. package/src/domain/scriptdev/lochModan.ts +283 -0
  711. package/src/domain/scriptdev/maraudon.ts +232 -0
  712. package/src/domain/scriptdev/moltenCore.ts +831 -0
  713. package/src/domain/scriptdev/moonglade.ts +659 -0
  714. package/src/domain/scriptdev/moongladeHelpers.ts +933 -0
  715. package/src/domain/scriptdev/naxxramas.ts +577 -0
  716. package/src/domain/scriptdev/naxxramasConstruct.ts +364 -0
  717. package/src/domain/scriptdev/naxxramasFrostwyrm.ts +378 -0
  718. package/src/domain/scriptdev/naxxramasMilitary.ts +276 -0
  719. package/src/domain/scriptdev/npcProfessions.ts +1025 -0
  720. package/src/domain/scriptdev/npcsSpecial.ts +1379 -0
  721. package/src/domain/scriptdev/onyxiasLair.ts +313 -0
  722. package/src/domain/scriptdev/orgrimmar.ts +147 -0
  723. package/src/domain/scriptdev/professionSpecConsumer.ts +481 -0
  724. package/src/domain/scriptdev/razorfenDowns.ts +468 -0
  725. package/src/domain/scriptdev/razorfenKraul.ts +410 -0
  726. package/src/domain/scriptdev/redridgeMountains.ts +163 -0
  727. package/src/domain/scriptdev/registry.ts +945 -0
  728. package/src/domain/scriptdev/ruinsOfAhnqiraj.ts +356 -0
  729. package/src/domain/scriptdev/scarletMonastery.ts +713 -0
  730. package/src/domain/scriptdev/scholomance.ts +682 -0
  731. package/src/domain/scriptdev/searingGorge.ts +295 -0
  732. package/src/domain/scriptdev/shadowfangKeep.ts +181 -0
  733. package/src/domain/scriptdev/silithus.ts +71 -0
  734. package/src/domain/scriptdev/silverpineForest.ts +662 -0
  735. package/src/domain/scriptdev/stonetalonMountains.ts +493 -0
  736. package/src/domain/scriptdev/stormwindCity.ts +1192 -0
  737. package/src/domain/scriptdev/stranglethornVale.ts +402 -0
  738. package/src/domain/scriptdev/stratholme.ts +650 -0
  739. package/src/domain/scriptdev/stratholmeScripts.ts +505 -0
  740. package/src/domain/scriptdev/sunkenTemple.ts +736 -0
  741. package/src/domain/scriptdev/swampOfSorrows.ts +22 -0
  742. package/src/domain/scriptdev/tanaris.ts +391 -0
  743. package/src/domain/scriptdev/tanarisHelpers.ts +661 -0
  744. package/src/domain/scriptdev/teldrassil.ts +143 -0
  745. package/src/domain/scriptdev/templeOfAhnqiraj.ts +1013 -0
  746. package/src/domain/scriptdev/theBarrens.ts +709 -0
  747. package/src/domain/scriptdev/theBarrensHelpers.ts +1026 -0
  748. package/src/domain/scriptdev/thousandNeedles.ts +426 -0
  749. package/src/domain/scriptdev/thousandNeedlesHelpers.ts +566 -0
  750. package/src/domain/scriptdev/tirisfalGlades.ts +533 -0
  751. package/src/domain/scriptdev/types.ts +1026 -0
  752. package/src/domain/scriptdev/uldaman.ts +437 -0
  753. package/src/domain/scriptdev/ungoroCrater.ts +549 -0
  754. package/src/domain/scriptdev/ungoroCraterHelpers.ts +1006 -0
  755. package/src/domain/scriptdev/wailingCaverns.ts +700 -0
  756. package/src/domain/scriptdev/warEffort.ts +371 -0
  757. package/src/domain/scriptdev/westernPlaguelands.ts +952 -0
  758. package/src/domain/scriptdev/westfall.ts +767 -0
  759. package/src/domain/scriptdev/wetlands.ts +660 -0
  760. package/src/domain/scriptdev/winterspring.ts +482 -0
  761. package/src/domain/scriptdev/winterspringHelpers.ts +801 -0
  762. package/src/domain/scriptdev/worldBosses.ts +605 -0
  763. package/src/domain/scriptdev/zulfarrak.ts +478 -0
  764. package/src/domain/scriptdev/zulgurub.ts +1152 -0
  765. package/src/domain/sim/dummySim.ts +408 -0
  766. package/src/domain/sim/targetDummy.ts +29 -0
  767. package/src/domain/social/guild.ts +148 -0
  768. package/src/domain/spells/areaAuraMembership.ts +93 -0
  769. package/src/domain/spells/breakableStunCc.ts +166 -0
  770. package/src/domain/spells/cancelAura.ts +80 -0
  771. package/src/domain/spells/diminishing.ts +167 -0
  772. package/src/domain/spells/dispel.ts +149 -0
  773. package/src/domain/spells/dispelMechanic.ts +105 -0
  774. package/src/domain/spells/equipSpells.ts +247 -0
  775. package/src/domain/spells/learnOnTargets.ts +260 -0
  776. package/src/domain/spells/mergeSchoolImmunityFromRaw.ts +66 -0
  777. package/src/domain/spells/resurrectSpell.ts +124 -0
  778. package/src/domain/spells/spellPushback.ts +39 -0
  779. package/src/domain/spells/spellReflect.ts +43 -0
  780. package/src/domain/spells/stealth.ts +183 -0
  781. package/src/domain/spells/totem.ts +394 -0
  782. package/src/domain/spells/worldCast.ts +187 -0
  783. package/src/domain/world/areaTriggerLocks.ts +177 -0
  784. package/src/domain/world/dungeonMusic.ts +108 -0
  785. package/src/domain/world/gameEvents.ts +119 -0
  786. package/src/domain/world/gameObjects.ts +1030 -0
  787. package/src/domain/world/goEventFire.ts +234 -0
  788. package/src/domain/world/goMoTransport.ts +74 -0
  789. package/src/domain/world/goTransport.ts +81 -0
  790. package/src/domain/world/hazards.ts +459 -0
  791. package/src/domain/world/openLock.ts +398 -0
  792. package/src/domain/world/pools.ts +470 -0
  793. package/src/domain/world/restArea.ts +37 -0
  794. package/src/domain/world/weather.ts +201 -0
  795. package/src/domain/zoneAmbience.mjs +87 -0
  796. package/src/domain/zoneMusic.mjs +62 -0
  797. package/src/domain/zoneMusicQueue.mjs +7 -0
  798. package/src/engine/combat/activeSeal.ts +39 -0
  799. package/src/engine/combat/aiTargetResolve.ts +64 -0
  800. package/src/engine/combat/aoeCast.ts +289 -0
  801. package/src/engine/combat/applyConsumeAura.ts +74 -0
  802. package/src/engine/combat/applyDemonicSacrifice.ts +70 -0
  803. package/src/engine/combat/applyDispelMechanic.ts +30 -0
  804. package/src/engine/combat/applyHealEffect.ts +301 -0
  805. package/src/engine/combat/applySchoolAbsorb.ts +114 -0
  806. package/src/engine/combat/applySpell.ts +3169 -0
  807. package/src/engine/combat/applySpellLate.ts +2026 -0
  808. package/src/engine/combat/applySpellLateBag.ts +144 -0
  809. package/src/engine/combat/areaAura.ts +283 -0
  810. package/src/engine/combat/attackTable.ts +508 -0
  811. package/src/engine/combat/battleRez.ts +87 -0
  812. package/src/engine/combat/castAction.ts +36 -0
  813. package/src/engine/combat/castTargetGates.ts +75 -0
  814. package/src/engine/combat/castableKit.ts +68 -0
  815. package/src/engine/combat/ccMirrorUpgrade.ts +39 -0
  816. package/src/engine/combat/chainFan.ts +210 -0
  817. package/src/engine/combat/channel.ts +423 -0
  818. package/src/engine/combat/chaseCloseness.ts +95 -0
  819. package/src/engine/combat/cmangosCastGates.ts +129 -0
  820. package/src/engine/combat/combatFlag.ts +77 -0
  821. package/src/engine/combat/combatGeometry.ts +1329 -0
  822. package/src/engine/combat/combustion.ts +68 -0
  823. package/src/engine/combat/context.ts +730 -0
  824. package/src/engine/combat/createSession.ts +1165 -0
  825. package/src/engine/combat/creatureLeash.ts +38 -0
  826. package/src/engine/combat/crowdControl.ts +1259 -0
  827. package/src/engine/combat/dispelDuty.ts +54 -0
  828. package/src/engine/combat/dispelReflect.ts +609 -0
  829. package/src/engine/combat/displaceFloor.ts +113 -0
  830. package/src/engine/combat/duelBounds.ts +47 -0
  831. package/src/engine/combat/equippedItemGate.ts +297 -0
  832. package/src/engine/combat/evadeLifecycle.ts +63 -0
  833. package/src/engine/combat/eventAi.ts +2220 -0
  834. package/src/engine/combat/facing.ts +74 -0
  835. package/src/engine/combat/fearFlee.ts +137 -0
  836. package/src/engine/combat/fighterFactory.ts +1144 -0
  837. package/src/engine/combat/forceDespawnAction.ts +51 -0
  838. package/src/engine/combat/formulas.ts +807 -0
  839. package/src/engine/combat/friendlyFan.ts +55 -0
  840. package/src/engine/combat/groundPoolTick.ts +210 -0
  841. package/src/engine/combat/hazards.ts +114 -0
  842. package/src/engine/combat/healTargets.ts +226 -0
  843. package/src/engine/combat/heartbeatResist.ts +49 -0
  844. package/src/engine/combat/hostileItemUse.ts +75 -0
  845. package/src/engine/combat/interruptAuras.ts +66 -0
  846. package/src/engine/combat/itemRescue.ts +49 -0
  847. package/src/engine/combat/itemUse.ts +260 -0
  848. package/src/engine/combat/kitById.ts +23 -0
  849. package/src/engine/combat/knockBack.ts +201 -0
  850. package/src/engine/combat/leap.ts +89 -0
  851. package/src/engine/combat/mitigation.ts +587 -0
  852. package/src/engine/combat/modTaunt.ts +43 -0
  853. package/src/engine/combat/motionClaim.ts +268 -0
  854. package/src/engine/combat/motionGate.ts +150 -0
  855. package/src/engine/combat/motionGenerator.ts +27 -0
  856. package/src/engine/combat/navSight.ts +138 -0
  857. package/src/engine/combat/perfSink.ts +28 -0
  858. package/src/engine/combat/periodicDue.ts +55 -0
  859. package/src/engine/combat/petAuras.ts +86 -0
  860. package/src/engine/combat/pickAction.ts +3449 -0
  861. package/src/engine/combat/powerForm.ts +735 -0
  862. package/src/engine/combat/powerPools.ts +49 -0
  863. package/src/engine/combat/predicates.ts +538 -0
  864. package/src/engine/combat/procsDamage.ts +1823 -0
  865. package/src/engine/combat/reactiveGates.ts +135 -0
  866. package/src/engine/combat/roles.ts +389 -0
  867. package/src/engine/combat/rotationSubject.ts +78 -0
  868. package/src/engine/combat/ruleAfter.ts +106 -0
  869. package/src/engine/combat/seedDisplayAuras.ts +203 -0
  870. package/src/engine/combat/seedOocEffects.ts +317 -0
  871. package/src/engine/combat/seedSchoolImmunities.ts +45 -0
  872. package/src/engine/combat/session-types.ts +458 -0
  873. package/src/engine/combat/sessionApi.ts +1785 -0
  874. package/src/engine/combat/sessionCharge.ts +124 -0
  875. package/src/engine/combat/sessionChase.ts +869 -0
  876. package/src/engine/combat/sessionDeaths.ts +469 -0
  877. package/src/engine/combat/sessionFocus.ts +506 -0
  878. package/src/engine/combat/sessionFollow.ts +167 -0
  879. package/src/engine/combat/sessionGeometry.ts +188 -0
  880. package/src/engine/combat/sessionHome.ts +75 -0
  881. package/src/engine/combat/sessionInject.ts +719 -0
  882. package/src/engine/combat/sessionMechanicMove.ts +555 -0
  883. package/src/engine/combat/sessionMotion.ts +1553 -0
  884. package/src/engine/combat/sessionMotionKit.ts +247 -0
  885. package/src/engine/combat/sessionMoveIntent.ts +49 -0
  886. package/src/engine/combat/sessionMoveOrder.ts +200 -0
  887. package/src/engine/combat/sessionPathTo.ts +657 -0
  888. package/src/engine/combat/sessionPools.ts +688 -0
  889. package/src/engine/combat/sessionSteer.ts +144 -0
  890. package/src/engine/combat/sessionStepBack.ts +151 -0
  891. package/src/engine/combat/sessionStepWrap.ts +116 -0
  892. package/src/engine/combat/sessionView.ts +442 -0
  893. package/src/engine/combat/simEffects.ts +32 -0
  894. package/src/engine/combat/simFacade.ts +620 -0
  895. package/src/engine/combat/simPump.ts +264 -0
  896. package/src/engine/combat/simSnapshot.ts +165 -0
  897. package/src/engine/combat/simThreadPool.ts +35 -0
  898. package/src/engine/combat/skeramImages.ts +57 -0
  899. package/src/engine/combat/slowUpdate.ts +178 -0
  900. package/src/engine/combat/snapToFloor.ts +42 -0
  901. package/src/engine/combat/speedAura.ts +29 -0
  902. package/src/engine/combat/spellReagents.ts +71 -0
  903. package/src/engine/combat/stealthDetect.ts +93 -0
  904. package/src/engine/combat/stepBackMotion.ts +171 -0
  905. package/src/engine/combat/stepSession.ts +3102 -0
  906. package/src/engine/combat/summonCast.ts +243 -0
  907. package/src/engine/combat/thaddiusPolarity.ts +97 -0
  908. package/src/engine/combat/threat.ts +388 -0
  909. package/src/engine/combat/threatOps.ts +272 -0
  910. package/src/engine/combat/tickWorkerBody.ts +211 -0
  911. package/src/engine/combat/totemAuras.ts +122 -0
  912. package/src/engine/combat/triggerPayload.ts +42 -0
  913. package/src/engine/combat/triggeredCompanion.ts +63 -0
  914. package/src/engine/combat/types.ts +1897 -0
  915. package/src/engine/combat/useObjectTrap.ts +140 -0
  916. package/src/engine/combat/walkSurface.ts +54 -0
  917. package/src/engine/combat/weapon.ts +1248 -0
  918. package/src/engine/combat/worldFrame.ts +43 -0
  919. package/src/engine/combat.solo-golden.json +2242 -0
  920. package/src/engine/combat.ts +84 -0
  921. package/src/engine/core/detMath.ts +289 -0
  922. package/src/engine/core/events.ts +357 -0
  923. package/src/engine/core/rng.ts +36 -0
  924. package/src/engine/game/actionBars.ts +124 -0
  925. package/src/engine/game/activateObjectFromSpell.ts +320 -0
  926. package/src/engine/game/applyActiveObjectFromDbScript.ts +98 -0
  927. package/src/engine/game/applyDeathAndSpellScripts.ts +268 -0
  928. package/src/engine/game/applyDoorFromDbScript.ts +388 -0
  929. package/src/engine/game/applyEscortFromDbScript.ts +290 -0
  930. package/src/engine/game/applyGoSpellcasterCast.ts +40 -0
  931. package/src/engine/game/applyHoverFromDbScript.ts +110 -0
  932. package/src/engine/game/applyOocResurrect.ts +71 -0
  933. package/src/engine/game/applySpellDurability.ts +115 -0
  934. package/src/engine/game/applyTailFromDbScript.ts +478 -0
  935. package/src/engine/game/applyTerminateFromDbScript.ts +95 -0
  936. package/src/engine/game/auctionMail.ts +269 -0
  937. package/src/engine/game/bagOverflow.ts +130 -0
  938. package/src/engine/game/bank.ts +110 -0
  939. package/src/engine/game/barAutofill.ts +26 -0
  940. package/src/engine/game/battleground.ts +369 -0
  941. package/src/engine/game/combatEnemySpec.ts +216 -0
  942. package/src/engine/game/combatObjectTraps.ts +167 -0
  943. package/src/engine/game/combatSeed.ts +320 -0
  944. package/src/engine/game/combatSession.ts +3241 -0
  945. package/src/engine/game/combatSessionClock.ts +62 -0
  946. package/src/engine/game/companionQuestActions.ts +242 -0
  947. package/src/engine/game/companionTraining.ts +40 -0
  948. package/src/engine/game/consumables.ts +624 -0
  949. package/src/engine/game/context.ts +53 -0
  950. package/src/engine/game/createHealthstone.ts +45 -0
  951. package/src/engine/game/deathFlow.ts +127 -0
  952. package/src/engine/game/devGrant.ts +117 -0
  953. package/src/engine/game/dynamicObject.ts +365 -0
  954. package/src/engine/game/enchantItem.ts +177 -0
  955. package/src/engine/game/equipmentHelper.ts +806 -0
  956. package/src/engine/game/factionState.ts +108 -0
  957. package/src/engine/game/garmentsOoc.ts +69 -0
  958. package/src/engine/game/globalActionBar.ts +179 -0
  959. package/src/engine/game/goInteractQuestCredit.ts +51 -0
  960. package/src/engine/game/goMoTransportUse.ts +61 -0
  961. package/src/engine/game/goTransportUse.ts +60 -0
  962. package/src/engine/game/healthstoneUpkeep.ts +59 -0
  963. package/src/engine/game/killSkin.ts +124 -0
  964. package/src/engine/game/learnFromItem.ts +118 -0
  965. package/src/engine/game/loadReconcile.ts +551 -0
  966. package/src/engine/game/loot.ts +294 -0
  967. package/src/engine/game/macros.ts +125 -0
  968. package/src/engine/game/mail.ts +293 -0
  969. package/src/engine/game/meetingStoneQueue.ts +75 -0
  970. package/src/engine/game/meetingStoneUse.ts +54 -0
  971. package/src/engine/game/newGameState.ts +363 -0
  972. package/src/engine/game/oocAuraInterrupt.ts +92 -0
  973. package/src/engine/game/oocCast.ts +241 -0
  974. package/src/engine/game/oocCastEffects.ts +803 -0
  975. package/src/engine/game/oocCastMethods.ts +1077 -0
  976. package/src/engine/game/openLockFromSpell.ts +174 -0
  977. package/src/engine/game/outdoorPvp.ts +187 -0
  978. package/src/engine/game/outfitter.ts +644 -0
  979. package/src/engine/game/paladinBoard.ts +393 -0
  980. package/src/engine/game/partyAuras.ts +121 -0
  981. package/src/engine/game/persistCombatAuras.ts +91 -0
  982. package/src/engine/game/pets.ts +459 -0
  983. package/src/engine/game/prePullHealthstones.ts +154 -0
  984. package/src/engine/game/professions.ts +2227 -0
  985. package/src/engine/game/pruneStaleRuntime.ts +39 -0
  986. package/src/engine/game/questFightCredit.ts +36 -0
  987. package/src/engine/game/questItemOnCorpse.ts +166 -0
  988. package/src/engine/game/questItemOnCreature.ts +103 -0
  989. package/src/engine/game/questLog.ts +879 -0
  990. package/src/engine/game/questSpellComplete.ts +21 -0
  991. package/src/engine/game/questTurnIn.ts +598 -0
  992. package/src/engine/game/raidParty.ts +32 -0
  993. package/src/engine/game/reagentBuyIn.ts +39 -0
  994. package/src/engine/game/regenRest.ts +186 -0
  995. package/src/engine/game/rotation.ts +425 -0
  996. package/src/engine/game/runFullDungeon.ts +611 -0
  997. package/src/engine/game/runSupply.ts +80 -0
  998. package/src/engine/game/sanitizeDriftedItems.ts +135 -0
  999. package/src/engine/game/scriptDevGoUse.ts +397 -0
  1000. package/src/engine/game/scriptDevInnkeeper.ts +150 -0
  1001. package/src/engine/game/scriptDevProfessionSpec.ts +99 -0
  1002. package/src/engine/game/sendEventFromSpell.ts +87 -0
  1003. package/src/engine/game/sortContainers.ts +85 -0
  1004. package/src/engine/game/spellReputation.ts +69 -0
  1005. package/src/engine/game/squad/squadDungeonSeating.ts +197 -0
  1006. package/src/engine/game/squadDungeon.ts +4222 -0
  1007. package/src/engine/game/squadQuestShare.ts +260 -0
  1008. package/src/engine/game/summonObjectSlot.ts +69 -0
  1009. package/src/engine/game/summonObjectWild.ts +73 -0
  1010. package/src/engine/game/summoningRitualUse.ts +141 -0
  1011. package/src/engine/game/talents.ts +356 -0
  1012. package/src/engine/game/tamingRodUse.ts +66 -0
  1013. package/src/engine/game/tempSpawnCreature.ts +136 -0
  1014. package/src/engine/game/tickDungeonPatrolScripts.ts +205 -0
  1015. package/src/engine/game/tickTimedQuests.ts +28 -0
  1016. package/src/engine/game/trade.ts +586 -0
  1017. package/src/engine/game/travel.ts +1155 -0
  1018. package/src/engine/game/types.ts +1855 -0
  1019. package/src/engine/game/vendorOffers.ts +244 -0
  1020. package/src/engine/game/weaponImbueItem.ts +281 -0
  1021. package/src/engine/game/worldSession.ts +183 -0
  1022. package/src/engine/game/worldState.ts +166 -0
  1023. package/src/engine/game.ts +968 -0
  1024. package/src/engine/spells/GAP.md +67 -0
  1025. package/src/engine/spells/absorbs.ts +376 -0
  1026. package/src/engine/spells/addTargetTrigger.ts +53 -0
  1027. package/src/engine/spells/auraPerSecondCost.ts +50 -0
  1028. package/src/engine/spells/auraStacking.ts +497 -0
  1029. package/src/engine/spells/cmangos-special-cases-combustion.ts +13 -0
  1030. package/src/engine/spells/cmangos-special-cases-s18.ts +445 -0
  1031. package/src/engine/spells/cmangos-special-cases-s19.ts +324 -0
  1032. package/src/engine/spells/cmangos-special-cases-s20.ts +385 -0
  1033. package/src/engine/spells/cmangos-special-cases-s21.ts +116 -0
  1034. package/src/engine/spells/cmangos-special-cases-s22.ts +24 -0
  1035. package/src/engine/spells/cmangos-special-cases-s23.ts +52 -0
  1036. package/src/engine/spells/cmangos-special-cases.ts +1570 -0
  1037. package/src/engine/spells/conditions.ts +718 -0
  1038. package/src/engine/spells/effects.ts +203 -0
  1039. package/src/engine/spells/fixtures/oracle-effects-lock9a.json +1 -0
  1040. package/src/engine/spells/immunity.ts +942 -0
  1041. package/src/engine/spells/intentEffects.ts +351 -0
  1042. package/src/engine/spells/interpreter/GAPS.md +21 -0
  1043. package/src/engine/spells/interpreter/amount.ts +109 -0
  1044. package/src/engine/spells/interpreter/class-scripts-kit.ts +478 -0
  1045. package/src/engine/spells/interpreter/diff.ts +246 -0
  1046. package/src/engine/spells/interpreter/duration.ts +90 -0
  1047. package/src/engine/spells/interpreter/form-attrs.json +1 -0
  1048. package/src/engine/spells/interpreter/form-attrs.ts +95 -0
  1049. package/src/engine/spells/interpreter/handlers/aura-remove.ts +113 -0
  1050. package/src/engine/spells/interpreter/handlers/auras-control.ts +1547 -0
  1051. package/src/engine/spells/interpreter/handlers/auras-core.ts +1583 -0
  1052. package/src/engine/spells/interpreter/handlers/auras-misc.ts +1774 -0
  1053. package/src/engine/spells/interpreter/handlers/effect-disenchant.ts +17 -0
  1054. package/src/engine/spells/interpreter/handlers/effect-skinning.ts +20 -0
  1055. package/src/engine/spells/interpreter/handlers/effects-action-utility.ts +1455 -0
  1056. package/src/engine/spells/interpreter/handlers/effects-core.ts +432 -0
  1057. package/src/engine/spells/interpreter/handlers/effects-remainder.ts +105 -0
  1058. package/src/engine/spells/interpreter/handlers/effects-summon-item.ts +687 -0
  1059. package/src/engine/spells/interpreter/handlers/mod-increase-energy-percent.ts +36 -0
  1060. package/src/engine/spells/interpreter/handlers/mod-increase-energy.ts +36 -0
  1061. package/src/engine/spells/interpreter/handlers/periodic-trigger-zero.ts +327 -0
  1062. package/src/engine/spells/interpreter/handlers/procs.ts +131 -0
  1063. package/src/engine/spells/interpreter/handlers/registry.ts +975 -0
  1064. package/src/engine/spells/interpreter/handlers/shared.ts +667 -0
  1065. package/src/engine/spells/interpreter/handlers.ts +9 -0
  1066. package/src/engine/spells/interpreter/hunter-kit.ts +202 -0
  1067. package/src/engine/spells/interpreter/index.ts +525 -0
  1068. package/src/engine/spells/interpreter/item-triggers.ts +1121 -0
  1069. package/src/engine/spells/interpreter/lift-consume-energy.ts +37 -0
  1070. package/src/engine/spells/interpreter/mage-portals.ts +37 -0
  1071. package/src/engine/spells/interpreter/materialize-charm.ts +88 -0
  1072. package/src/engine/spells/interpreter/materialize-dispel-mechanic.ts +25 -0
  1073. package/src/engine/spells/interpreter/materialize-rating-buffs.ts +81 -0
  1074. package/src/engine/spells/interpreter/materialize-speed.ts +109 -0
  1075. package/src/engine/spells/interpreter/materialize-spell-magnet.ts +22 -0
  1076. package/src/engine/spells/interpreter/opcodes.ts +789 -0
  1077. package/src/engine/spells/interpreter/paladin-kit.ts +95 -0
  1078. package/src/engine/spells/interpreter/paladin-seals.ts +499 -0
  1079. package/src/engine/spells/interpreter/priest-warlock-kit.ts +135 -0
  1080. package/src/engine/spells/interpreter/proc.ts +443 -0
  1081. package/src/engine/spells/interpreter/registry/helpers.ts +16 -0
  1082. package/src/engine/spells/interpreter/registry/index.ts +216 -0
  1083. package/src/engine/spells/interpreter/registry/packs/class-abilities.ts +304 -0
  1084. package/src/engine/spells/interpreter/registry/packs/dire-maul.ts +44 -0
  1085. package/src/engine/spells/interpreter/registry/packs/dummy-script-tail.ts +1065 -0
  1086. package/src/engine/spells/interpreter/registry/packs/ex-wave-m.ts +70 -0
  1087. package/src/engine/spells/interpreter/registry/packs/life-tap.ts +107 -0
  1088. package/src/engine/spells/interpreter/registry/packs/paladin.ts +246 -0
  1089. package/src/engine/spells/interpreter/registry/packs/raid-script-summons.ts +26 -0
  1090. package/src/engine/spells/interpreter/registry/packs/raid-threat-wipe.ts +22 -0
  1091. package/src/engine/spells/interpreter/registry/packs/shaman.ts +214 -0
  1092. package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-a.ts +269 -0
  1093. package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-b.ts +370 -0
  1094. package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-c.ts +172 -0
  1095. package/src/engine/spells/interpreter/registry/packs/si4-dummy-hunter.ts +60 -0
  1096. package/src/engine/spells/interpreter/registry/packs/si4-dummy-warrior.ts +31 -0
  1097. package/src/engine/spells/interpreter/registry/packs/si4-script-generic-a.ts +114 -0
  1098. package/src/engine/spells/interpreter/registry/packs/si4-script-generic-b.ts +249 -0
  1099. package/src/engine/spells/interpreter/registry/packs/si4-script-generic-c.ts +233 -0
  1100. package/src/engine/spells/interpreter/registry/types.ts +48 -0
  1101. package/src/engine/spells/interpreter/talent-scripted.ts +329 -0
  1102. package/src/engine/spells/interpreter/targeting.ts +90 -0
  1103. package/src/engine/spells/interpreter/types-intent.ts +1501 -0
  1104. package/src/engine/spells/interpreter/types.ts +419 -0
  1105. package/src/engine/spells/interpreter/warrior-druid-kit.ts +314 -0
  1106. package/src/engine/spells/interpreter/weapon-imbue-kit.ts +384 -0
  1107. package/src/engine/spells/interrupt.ts +217 -0
  1108. package/src/engine/spells/meleeAttackReset.ts +60 -0
  1109. package/src/engine/spells/oocTriggerSpell.ts +49 -0
  1110. package/src/engine/spells/overrideClassScripts.ts +319 -0
  1111. package/src/engine/spells/parryHaste.ts +20 -0
  1112. package/src/engine/spells/procs.ts +300 -0
  1113. package/src/engine/spells/recovery.ts +203 -0
  1114. package/src/engine/spells/scriptTargetDest.ts +76 -0
  1115. package/src/engine/spells/scriptTargets.ts +85 -0
  1116. package/src/engine/spells/singleTargetAura.ts +82 -0
  1117. package/src/engine/spells/specialCasePayloads.ts +57 -0
  1118. package/src/engine/spells/spellAttributes.ts +249 -0
  1119. package/src/engine/spells/spellBonus.ts +143 -0
  1120. package/src/engine/spells/spellModIntents.ts +419 -0
  1121. package/src/engine/spells/spellMods.ts +283 -0
  1122. package/src/engine/spells/spellRadius.ts +15 -0
  1123. package/src/engine/spells/trapObjects.ts +26 -0
  1124. package/src/json.d.ts +7 -0
  1125. package/src/persistence/memoryRepository.ts +23 -0
  1126. package/src/persistence/saveBackups.ts +162 -0
  1127. package/src/persistence/saveFile.ts +68 -0
  1128. package/src/persistence/saveRepository.ts +11 -0
  1129. package/src/persistence/saveShape.ts +668 -0
  1130. package/src/progression/leveling.ts +89 -0
  1131. package/src/progression/rest.ts +1434 -0
  1132. package/src/progression/training.ts +226 -0
  1133. package/src/progression/xpGain.ts +369 -0
  1134. package/src/quests/quests.ts +1580 -0
  1135. package/src/world/aoePull.ts +198 -0
  1136. package/src/world/areaTableDbc.ts +39 -0
  1137. package/src/world/areaTableMapIdPairs.ts +141 -0
  1138. package/src/world/bakeSlug.ts +43 -0
  1139. package/src/world/continuousDungeon.ts +1250 -0
  1140. package/src/world/dungeonBakeProjection.ts +190 -0
  1141. package/src/world/dungeonMapDensity.ts +342 -0
  1142. package/src/world/dungeonMapProjection.ts +135 -0
  1143. package/src/world/dungeonNav.ts +904 -0
  1144. package/src/world/dungeonNpcSim.ts +147 -0
  1145. package/src/world/dungeonObjectives.ts +234 -0
  1146. package/src/world/dungeonPreset.ts +35 -0
  1147. package/src/world/dungeonRoute.ts +311 -0
  1148. package/src/world/dungeonRouteGeometry.ts +732 -0
  1149. package/src/world/dungeonRouteOrder.ts +1037 -0
  1150. package/src/world/dungeonWingRooms.ts +426 -0
  1151. package/src/world/escort.ts +296 -0
  1152. package/src/world/goPoolRoll.ts +75 -0
  1153. package/src/world/instanceObjects.ts +785 -0
  1154. package/src/world/instances.ts +1572 -0
  1155. package/src/world/meetingStones.ts +56 -0
  1156. package/src/world/navmeshFloors.ts +145 -0
  1157. package/src/world/nearGrid.ts +167 -0
  1158. package/src/world/packBudget.ts +613 -0
  1159. package/src/world/rareRoll.ts +335 -0
  1160. package/src/world/routeAuthoring.ts +132 -0
  1161. package/src/world/routeEdit.ts +209 -0
  1162. package/src/world/world.ts +812 -0
  1163. package/src/world/zoneHazards.ts +47 -0
@@ -0,0 +1,668 @@
1
+ // Versioned save shape + a defensive migrate(), so growing the schema never
2
+ // bricks an existing save (mirrors CarScene's Object.assign(fresh(), parsed)).
3
+
4
+ import type { GameState } from '../engine/game.ts';
5
+ import type { EquippedMap } from '../domain/character/character.ts';
6
+ import { removeItem } from '../domain/items/inventory.ts';
7
+ import { emptyAuctionHouse } from '../domain/economy/auction.ts';
8
+ import { migrateMailbox } from '../domain/economy/mail.ts';
9
+ import { normalizeBars } from '../domain/character/actionbar.ts';
10
+ import { normalizeGlobalBar } from '../domain/raid/globalActionBar.ts';
11
+ import { normalizeMacros } from '../domain/macro/normalize.ts';
12
+ import { normalizeProfiles } from '../domain/rotation/rotationProfiles.ts';
13
+ import { normalizePaladinAssignments } from '../domain/rotation/paladinBuffs.ts';
14
+ import { normalizeTalentBuilds } from '../domain/character/talentBuilds.ts';
15
+ import { normalizePrimaryPages, type PrimaryBarPages } from '../domain/character/stanceBar.ts';
16
+ import { normalizeAppearance, bodySlug, type Appearance } from '../domain/character/appearance.ts';
17
+ import { BATTLEGROUNDS } from '../domain/run/battlegroundRun.ts';
18
+ import packIdMigrationJson from '../../docs/dungeons/survey/pack-id-migration.json' with { type: 'json' };
19
+
20
+ // v32 full style unlock: 10 bodies had NO bald base, so hairStyle was LOCKED to index 0 (= their
21
+ // default hair/horn shape baked into the base). The new model puts None (bald/hornless) at index 0
22
+ // and the real styles at 1..K over a bald base — so a pre-v32 save's forced 0 must shift to the
23
+ // default style (index 1) to preserve the character's CURRENT look (nobody returns unexpectedly
24
+ // bald/hornless). Every other body's indices are already stable. Gated on incoming version so a
25
+ // v32+ player who deliberately picks None (0) keeps it. The set = bodies gen used to mark locked.
26
+ const V32_PREV_LOCKED = new Set([
27
+ 'nightelf-male', 'tauren-male',
28
+ 'human-female', 'orc-female', 'dwarf-female', 'nightelf-female',
29
+ 'undead-female', 'tauren-female', 'gnome-female', 'troll-female',
30
+ ]);
31
+ function appearanceForLoad(
32
+ raw: unknown, name: string, race: number, gender: 0 | 1, incomingVersion: number,
33
+ ): Appearance {
34
+ // v43 added a synthetic None at facialHair index 0 and shifted every stored index up one. v44
35
+ // took it back out — the client list decides whether a body can be beardless, and dwarf/human/
36
+ // troll-male/undead-male have no such choice — so a save written by v43 shifts back down. Saves
37
+ // at <=42 were never shifted on disk. Read before normalize, or clampAppearance has already
38
+ // pinned the index to the current range.
39
+ const fh = (raw as { facialHair?: unknown } | null)?.facialHair;
40
+ const shifted = incomingVersion === 43 && typeof fh === 'number' && fh > 0
41
+ ? { ...(raw as object), facialHair: fh - 1 }
42
+ : raw;
43
+ const look = normalizeAppearance(shifted, name, race, gender);
44
+ if (incomingVersion < 32 && look.hairStyle === 0) {
45
+ const slug = bodySlug(race, gender);
46
+ if (slug && V32_PREV_LOCKED.has(slug)) return { ...look, hairStyle: 1 };
47
+ }
48
+ return look;
49
+ }
50
+ import { CLASSIC_MAX_PLAYER_LEVEL } from '../progression/xpGain.ts';
51
+ import { normalizeAutoConsumables } from '../domain/bots/autoConsumables.ts';
52
+ import { newHonorState, rankForRp, type HonorState } from '../domain/run/honor.ts';
53
+ import { newHonorWeekLedger, type HonorWeekLedger } from '../domain/run/honorWeek.ts';
54
+
55
+ // Save versions v2–v44 are all ADDITIVE and OPTIONAL: a new field is absent in older saves and
56
+ // reads as the default documented on its own type, so load needs no field transform. That is why
57
+ // the whole persistence layer has exactly one version gate — `incoming === 43` below. The prior
58
+ // 118-line per-version log restated field optionality that the types already carry; git blame has it.
59
+ //
60
+ // The transforms that are NOT just "absent = default":
61
+ // v26 mid-run instance state on retired Jasperlode / 95xxxx Deadmines ids is cleared (migrate).
62
+ // v36 legacy `${map}-${index}` trash pack ids remapped via docs/dungeons/survey/pack-id-migration.json.
63
+ // v40 keys move out of bags into state.keyring (migrateKeysToKeyring). Cite: Player.h KEYRING_SLOT_*.
64
+ // v43/44 facialHair index 0: v43 made it a synthetic None and shifted real choices up one; v44
65
+ // reverts that — the client list owns whether a body can be beardless (no beardless dwarf, no
66
+ // tuskless troll) and index 0 is a real None only where the bake renders nothing.
67
+ // Cite: gen-appearance-options.mjs; docs/done/PAPERDOLL-REBAKE.md.
68
+ // v44+ `macros` (the MacroFrame's character tab) is additive and optional: absent reads as an
69
+ // empty list. Account-wide macros are deliberately NOT in the save — they are shared by
70
+ // every character, like the global junk filter (CreateGameOptions.accountMacros).
71
+ // v30 a pre-v30 save back-fills the deterministic-by-name look (deterministicAppearance) rather
72
+ // than a blank one, and stored indices clamp to the body's legal Choices.
73
+ // Cites with no other home: char.drunkValue Player.cpp SetDrunkValue / SPELL_EFFECT_INEBRIATE / KI-734;
74
+ // char.honor domain/run/honor.ts + Formulas.h.
75
+ /**
76
+ * A restorable BG run: it names an OBJECTIVE battleground and carries the team fields the mount
77
+ * reads. An arena bracket is not one - every bracket is a combat-surface session now.
78
+ */
79
+ function isObjectiveBattlegroundRun(raw: unknown): raw is NonNullable<GameState['battleground']> {
80
+ if (!raw || typeof raw !== 'object') return false;
81
+ const { bgId, team, teamSize } = raw as { bgId?: unknown; team?: unknown; teamSize?: unknown };
82
+ return Object.values(BATTLEGROUNDS).some((b) => b.id === bgId && b.mode === 'objective')
83
+ && (team === 'alliance' || team === 'horde')
84
+ && typeof teamSize === 'number' && Number.isFinite(teamSize);
85
+ }
86
+
87
+ export const SAVE_VERSION = 44 as const;
88
+
89
+ export interface Save {
90
+ version: number;
91
+ slot: string;
92
+ createdAt: number;
93
+ updatedAt: number;
94
+ /** The updatedAt of the copy this snapshot was built from. Wire-only: the server
95
+ * refuses the write when the stored row has moved (mail take, trade, another window). */
96
+ baseUpdatedAt?: number;
97
+ state: GameState;
98
+ }
99
+
100
+ export interface SaveMeta {
101
+ slot: string;
102
+ name: string;
103
+ level: number;
104
+ cls: number;
105
+ updatedAt: number;
106
+ }
107
+
108
+ /** Build a save envelope around a game state (timestamps injected by the caller). */
109
+ export function toSave(slot: string, state: GameState, now: number, createdAt?: number): Save {
110
+ return { version: SAVE_VERSION, slot, createdAt: createdAt ?? now, updatedAt: now, state };
111
+ }
112
+
113
+ /** Non-negative int field, or base default. */
114
+ function honorUInt(raw: unknown, fallback: number): number {
115
+ return typeof raw === 'number' && Number.isFinite(raw) ? Math.max(0, Math.trunc(raw)) : fallback;
116
+ }
117
+
118
+ // Arena Elo, keyed by bracket size. Only the four rated brackets survive, and only as finite
119
+ // numbers - a rating has no floor (arenaRating.ts) so a negative one is legal and is kept.
120
+ function normalizeArenaRating(raw: unknown): { arenaRating: Partial<Record<number, number>> } | null {
121
+ if (!raw || typeof raw !== 'object') return null;
122
+ const out: Partial<Record<number, number>> = {};
123
+ for (const b of [1, 2, 3, 5]) {
124
+ const v = (raw as Record<string, unknown>)[String(b)];
125
+ if (typeof v === 'number' && Number.isFinite(v)) out[b] = Math.round(v);
126
+ }
127
+ return Object.keys(out).length ? { arenaRating: out } : null;
128
+ }
129
+
130
+ // The weekly standing ledger. Rows are keyed by character name, so keys are arbitrary strings; only
131
+ // well-formed { cp, hk } pairs survive. Cite: domain/run/honorWeek.ts.
132
+ function normalizeHonorWeek(raw: unknown): HonorWeekLedger {
133
+ if (!raw || typeof raw !== 'object') return newHonorWeekLedger();
134
+ const r = raw as Record<string, unknown>;
135
+ const weekStart = typeof r.weekStart === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(r.weekStart)
136
+ ? r.weekStart
137
+ : '';
138
+ const rows: HonorWeekLedger['rows'] = {};
139
+ if (r.rows && typeof r.rows === 'object') {
140
+ for (const [key, v] of Object.entries(r.rows as Record<string, unknown>)) {
141
+ if (!key || !v || typeof v !== 'object') continue;
142
+ const row = v as Record<string, unknown>;
143
+ const cp = honorUInt(row.cp, 0);
144
+ const hk = honorUInt(row.hk, 0);
145
+ if (cp > 0 || hk > 0) rows[key] = { cp, hk };
146
+ }
147
+ }
148
+ return { weekStart, rows };
149
+ }
150
+
151
+ /** v41 honor ledger. Missing / corrupt → empty standing (same as newHonorState).
152
+ * Period fields (today/yesterday/…) are additive; pre-period saves default to 0. */
153
+ function normalizeHonorState(raw: unknown): HonorState | undefined {
154
+ if (!raw || typeof raw !== 'object') return undefined;
155
+ const r = raw as Record<string, unknown>;
156
+ const base = newHonorState();
157
+ // Signed and FRACTIONAL: `m_rank_points` is a float (Player.h:2344), and the weekly pass is
158
+ // the thing that produces a fraction — CalculateRpEarning interpolates. Truncating here cost a
159
+ // little rank progress on every save/load. Cite: Player.h:1783 SetRankPoints(float).
160
+ const rp = typeof r.rp === 'number' && Number.isFinite(r.rp) ? r.rp : base.rp;
161
+ const fromRp = rankForRp(rp)?.rank ?? 0;
162
+ const storedHighest = honorUInt(r.highestRank, base.highestRank);
163
+ return {
164
+ cp: honorUInt(r.cp, base.cp),
165
+ // Additive (v44): a pre-currency save opens with an empty purse and no lifetime total, which
166
+ // is exactly what "never earned an Honor Point" means. No SAVE_VERSION bump.
167
+ honorPoints: honorUInt(r.honorPoints, base.honorPoints),
168
+ lifetimeHonorPoints: honorUInt(r.lifetimeHonorPoints, base.lifetimeHonorPoints),
169
+ rp,
170
+ lifetimeKills: honorUInt(r.lifetimeKills, base.lifetimeKills),
171
+ dishonorableKills: honorUInt(r.dishonorableKills, base.dishonorableKills),
172
+ killsDate: typeof r.killsDate === 'string' ? r.killsDate : base.killsDate,
173
+ killsToday: r.killsToday && typeof r.killsToday === 'object'
174
+ ? Object.fromEntries(
175
+ Object.entries(r.killsToday as Record<string, unknown>)
176
+ .filter(([, n]) => typeof n === 'number' && n > 0)
177
+ .map(([k, n]) => [k, Math.trunc(n as number)]),
178
+ )
179
+ : base.killsToday,
180
+ todayHk: honorUInt(r.todayHk, base.todayHk),
181
+ todayDk: honorUInt(r.todayDk, base.todayDk),
182
+ todayHonor: honorUInt(r.todayHonor, base.todayHonor),
183
+ yesterdayHk: honorUInt(r.yesterdayHk, base.yesterdayHk),
184
+ yesterdayHonor: honorUInt(r.yesterdayHonor, base.yesterdayHonor),
185
+ thisWeekHk: honorUInt(r.thisWeekHk, base.thisWeekHk),
186
+ lastWeekHk: honorUInt(r.lastWeekHk, base.lastWeekHk),
187
+ lastWeekHonor: honorUInt(r.lastWeekHonor, base.lastWeekHonor),
188
+ lastWeekStanding: honorUInt(r.lastWeekStanding, base.lastWeekStanding),
189
+ // Pre-period saves lack highestRank — seed from current standing when higher.
190
+ highestRank: Math.max(storedHighest, fromRp),
191
+ };
192
+ }
193
+
194
+ // Legacy index-order packId → content-addressed packId (dmapfid W2 / D3 / O9). Source:
195
+ // docs/dungeons/survey/pack-id-migration.json (written by cluster-dungeon-packs.mjs).
196
+ const PACK_ID_MIGRATION: Map<string, string> = new Map(
197
+ Object.entries((packIdMigrationJson as { map?: Record<string, string> }).map ?? {}),
198
+ );
199
+ function packIdMigrationMap(): Map<string, string> {
200
+ return PACK_ID_MIGRATION;
201
+ }
202
+
203
+ // Remap one encounter id: exact packId hit, or `${prefix}-${legacyPackId}` when InstanceDefs used idPrefix.
204
+ // Unmapped / boss ids pass through.
205
+ export function remapPackEncounterId(id: string): string {
206
+ const map = packIdMigrationMap();
207
+ if (map.size === 0) return id;
208
+ const direct = map.get(id);
209
+ if (direct) return direct;
210
+ // prefix-legacyId form (rare): "foo-36-0" → "foo-36-abcd..."
211
+ for (const [legacy, next] of map) {
212
+ const needle = `-${legacy}`;
213
+ if (id.endsWith(needle)) {
214
+ return id.slice(0, id.length - legacy.length) + next;
215
+ }
216
+ }
217
+ return id;
218
+ }
219
+
220
+ /**
221
+ * v26 — retire Jasperlode + 95xxxx Deadmines placeholder run state.
222
+ * - `jasperlode` instance → clear (dungeon removed).
223
+ * - `deadmines` with old trash encounter ids `miners` / `foundry` → clear run
224
+ * (boss ids were reused on the golden graph; those two trash ids are unique to
225
+ * the placeholder sequence).
226
+ * v36 — remap legacy index-order pack ids in defeated / routeEncounterIds (D3).
227
+ */
228
+ function migrateInstanceRun(
229
+ raw: GameState['instance'] | null | undefined,
230
+ ): GameState['instance'] {
231
+ if (raw == null) return null;
232
+ if (typeof raw !== 'object') return null;
233
+ const dungeonId = (raw as { dungeonId?: unknown }).dungeonId;
234
+ if (dungeonId === 'jasperlode') return null;
235
+ const defeated = Array.isArray((raw as { defeated?: unknown }).defeated)
236
+ ? ((raw as { defeated: string[] }).defeated)
237
+ : [];
238
+ if (dungeonId === 'deadmines') {
239
+ const oldPlaceholder = defeated.some((id) => id === 'miners' || id === 'foundry');
240
+ if (oldPlaceholder) return null;
241
+ }
242
+ const run = { ...(raw as GameState['instance']) } as NonNullable<GameState['instance']>;
243
+ if (Array.isArray(run.defeated)) {
244
+ run.defeated = run.defeated.map(remapPackEncounterId);
245
+ }
246
+ if (Array.isArray(run.routeEncounterIds)) {
247
+ run.routeEncounterIds = run.routeEncounterIds.map(remapPackEncounterId);
248
+ }
249
+ return run;
250
+ }
251
+
252
+ /**
253
+ * Walked-out-of instances (5-man 30 min, raid until lockout). Optional — absent on
254
+ * any save written before the field existed, so no SAVE_VERSION bump. Each inner run goes
255
+ * through the same migration as a live one; an entry whose run migrates away is dropped.
256
+ */
257
+ function migrateInstanceSaves(raw: unknown): GameState['instanceSaves'] {
258
+ if (raw == null || typeof raw !== 'object') return {};
259
+ const out: NonNullable<GameState['instanceSaves']> = {};
260
+ for (const [id, v] of Object.entries(raw as Record<string, unknown>)) {
261
+ if (!v || typeof v !== 'object') continue;
262
+ const expiresAtMs = (v as { expiresAtMs?: unknown }).expiresAtMs;
263
+ if (typeof expiresAtMs !== 'number' || !Number.isFinite(expiresAtMs)) continue;
264
+ const run = migrateInstanceRun((v as { run?: unknown }).run as GameState['instance']);
265
+ if (!run || run.dungeonId !== id) continue;
266
+ out[id] = { run, expiresAtMs };
267
+ }
268
+ return out;
269
+ }
270
+
271
+ /** Drop lockout entries for retired dungeons (Jasperlode). */
272
+ function migrateLockouts(lockouts: GameState['lockouts']): GameState['lockouts'] {
273
+ if (!lockouts || typeof lockouts !== 'object') return {};
274
+ if (!('jasperlode' in lockouts)) return lockouts;
275
+ const next = { ...lockouts };
276
+ delete next.jasperlode;
277
+ return next;
278
+ }
279
+
280
+ /** Back-fill a stored auction house: default each listing's `highBidder` to null (pre-v6). */
281
+ function normalizeAuctionHouse(ah: GameState['auctionHouse'] | undefined): GameState['auctionHouse'] {
282
+ if (!ah || !Array.isArray(ah.auctions)) return emptyAuctionHouse();
283
+ return {
284
+ nextId: typeof ah.nextId === 'number' ? ah.nextId : 1,
285
+ auctions: ah.auctions.map((a) => ({ ...a, highBidder: a.highBidder ?? null })),
286
+ lastTickMs: typeof ah.lastTickMs === 'number' && Number.isFinite(ah.lastTickMs) ? ah.lastTickMs : 0,
287
+ };
288
+ }
289
+
290
+ /** Adopt untrusted JSON as an id→number map: integer-string keys, finite number values only. */
291
+ function numericMap(raw: unknown): Record<number, number> {
292
+ const out: Record<number, number> = {};
293
+ if (raw && typeof raw === 'object') {
294
+ for (const [k, v] of Object.entries(raw)) {
295
+ if (/^\d+$/.test(k) && typeof v === 'number' && Number.isFinite(v)) out[Number(k)] = v;
296
+ }
297
+ }
298
+ return out;
299
+ }
300
+
301
+ /** Coerce arbitrary stored JSON into a valid Save, back-filling anything missing. Returns null if unusable. */
302
+ export function migrate(raw: unknown): Save | null {
303
+ if (!raw || typeof raw !== 'object') return null;
304
+ const r = raw as Record<string, unknown>;
305
+ const stateRaw = (r.state ?? r) as Record<string, unknown>;
306
+ const charRaw = stateRaw?.char as Record<string, unknown> | undefined;
307
+ if (!charRaw || typeof charRaw.name !== 'string') return null;
308
+
309
+ // Equipment: v2 stores a slot map. An already-v2 save keeps its map; a v1 save is
310
+ // converted from its single `equippedMainhand` (and that copy is removed from the
311
+ // bags below, since v2 no longer keeps equipped items in the bags).
312
+ const hasMap = !!charRaw.equipped && typeof charRaw.equipped === 'object';
313
+ const legacyMain = typeof charRaw.equippedMainhand === 'number' ? charRaw.equippedMainhand : null;
314
+ const equipped: EquippedMap = hasMap
315
+ ? (charRaw.equipped as EquippedMap)
316
+ : legacyMain != null ? { mainhand: legacyMain } : {};
317
+
318
+ const char = {
319
+ ...(charRaw as unknown as GameState['char']),
320
+ activeBuffs: Array.isArray(charRaw.activeBuffs) ? (charRaw.activeBuffs as number[]) : [],
321
+ // v-next: activeAuras for timed buffs with correct DB durations.
322
+ // Old saves (only activeBuffs) are migrated to persistent auras (no expiry).
323
+ activeAuras: Array.isArray(charRaw.activeAuras)
324
+ ? (charRaw.activeAuras as GameState['char']['activeAuras'])
325
+ : (Array.isArray(charRaw.activeBuffs)
326
+ ? (charRaw.activeBuffs as number[]).map((id: number) => ({ spellId: id }))
327
+ : []),
328
+ equipped,
329
+ // v5 durability: a pre-v5 save has none, so all gear starts pristine (absent => full).
330
+ durability: charRaw.durability && typeof charRaw.durability === 'object' ? (charRaw.durability as GameState['char']['durability']) : {},
331
+ // v3 professions: a pre-v3 save has neither, so back-fill empty.
332
+ skills: charRaw.skills && typeof charRaw.skills === 'object' ? (charRaw.skills as GameState['char']['skills']) : {},
333
+ knownRecipes: Array.isArray(charRaw.knownRecipes) ? (charRaw.knownRecipes as number[]) : [],
334
+ // v9 enchanting: pre-v9 gear is un-enchanted and no formulas are known.
335
+ enchants: charRaw.enchants && typeof charRaw.enchants === 'object' ? (charRaw.enchants as GameState['char']['enchants']) : {},
336
+ knownEnchants: Array.isArray(charRaw.knownEnchants) ? (charRaw.knownEnchants as number[]) : [],
337
+ // Weapon imbues / poisons (TEMP_ENCHANTMENT_SLOT). Pre-imbue saves have none.
338
+ tempEnchants: charRaw.tempEnchants && typeof charRaw.tempEnchants === 'object'
339
+ ? (charRaw.tempEnchants as GameState['char']['tempEnchants'])
340
+ : {},
341
+ // v10 pet training: pre-v10 saves have unlocked no pet-ability ranks (pets know only rank 1).
342
+ petSpells: Array.isArray(charRaw.petSpells) ? (charRaw.petSpells as number[]) : [],
343
+ // v27 dismissed hunter pet: pre-v27 / no dismiss → absent. Round-trips via spread above;
344
+ // re-assert only when the raw shape actually carries a pet object.
345
+ storedPet: charRaw.storedPet && typeof charRaw.storedPet === 'object'
346
+ ? (charRaw.storedPet as GameState['char']['storedPet'])
347
+ : undefined,
348
+ // Hunter stable: absent → 0 slots / no occupants. Cite: Player.h m_stableSlots; Pet.h MAX_PET_STABLES=2.
349
+ stableSlots: (() => {
350
+ const n = charRaw.stableSlots;
351
+ if (typeof n !== 'number' || !Number.isFinite(n) || n <= 0) return undefined;
352
+ return Math.min(2, n | 0);
353
+ })(),
354
+ stablePets: Array.isArray(charRaw.stablePets)
355
+ ? (charRaw.stablePets as GameState['char']['stablePets'])
356
+ : undefined,
357
+ // v13 talents: pre-v13 saves (or fixtures) have no spent talent points.
358
+ talents: numericMap(charRaw.talents),
359
+ // v14 combat skills: pre-v14 saves omit the map → attack tables use L×5 defaults.
360
+ combatSkills: charRaw.combatSkills && typeof charRaw.combatSkills === 'object'
361
+ ? (charRaw.combatSkills as GameState['char']['combatSkills'])
362
+ : undefined,
363
+ // v16 reputation: pre-v16 saves have earned no rep → empty map (every faction at its base standing).
364
+ reputations: numericMap(charRaw.reputations),
365
+ // v35 reputation pane state: pre-v35 saves have toggled nothing → every faction reads its
366
+ // FactionDef default flags, and the XP bar shows XP.
367
+ factionFlags: numericMap(charRaw.factionFlags),
368
+ watchedFaction: typeof charRaw.watchedFaction === 'number' && charRaw.watchedFaction > 0
369
+ ? charRaw.watchedFaction
370
+ : undefined,
371
+ // v18 rested XP + exploration: pre-v18 saves start unrested / nothing discovered.
372
+ restedXp: typeof charRaw.restedXp === 'number' && charRaw.restedXp > 0 ? charRaw.restedXp : 0,
373
+ exploredZones: Array.isArray(charRaw.exploredZones) ? (charRaw.exploredZones as string[]) : [],
374
+ // v23 gender: pre-v23 saves are male (the only portrait art the UI used before).
375
+ gender: (charRaw.gender === 1 ? 1 : 0) as 0 | 1,
376
+ // v30 appearance (Wave R): a valid stored look is clamped to this body's Choices; a pre-v30
377
+ // save (no appearance) back-fills the deterministic-by-name look so it isn't a clone. v32 full
378
+ // style unlock: previously-locked bodies keep their default horns/hair (hairStyle 0 → 1).
379
+ appearance: appearanceForLoad(
380
+ charRaw.appearance,
381
+ charRaw.name,
382
+ typeof charRaw.race === 'number' ? charRaw.race : 1,
383
+ charRaw.gender === 1 ? 1 : 0,
384
+ typeof r.version === 'number' ? r.version : 0,
385
+ ),
386
+ // v22 riding / mount: pre-v22 → untrained and unmounted.
387
+ ridingSkill: typeof charRaw.ridingSkill === 'number' && charRaw.ridingSkill > 0
388
+ ? charRaw.ridingSkill
389
+ : 0,
390
+ mountedItem: typeof charRaw.mountedItem === 'number' ? charRaw.mountedItem : undefined,
391
+ // v24 travel (J3): pre-v24 → no journey / taxi nodes / hearth (fields stay absent).
392
+ journey: charRaw.journey && typeof charRaw.journey === 'object'
393
+ ? (charRaw.journey as GameState['char']['journey'])
394
+ : undefined,
395
+ discoveredTaxiNodes: Array.isArray(charRaw.discoveredTaxiNodes)
396
+ ? (charRaw.discoveredTaxiNodes as number[])
397
+ : undefined,
398
+ hearthBind: charRaw.hearthBind && typeof charRaw.hearthBind === 'object'
399
+ ? (charRaw.hearthBind as GameState['char']['hearthBind'])
400
+ : undefined,
401
+ hearthCooldownUntil: typeof charRaw.hearthCooldownUntil === 'number'
402
+ ? charRaw.hearthCooldownUntil
403
+ : undefined,
404
+ // Auto consumables (food/drink/buffs) — optional prefs; absent on older saves.
405
+ autoConsumables: normalizeAutoConsumables(charRaw.autoConsumables),
406
+ // v39 drunk: pre-v39 / sober → absent. Clamp 0..0xFFFF. Cite: Player m_drunk; KI-734.
407
+ drunkValue: typeof charRaw.drunkValue === 'number' && charRaw.drunkValue > 0
408
+ ? Math.min(0xFFFF, Math.trunc(charRaw.drunkValue))
409
+ : undefined,
410
+ // Player.cpp:5153 m_fishingSteps. Pre-field / 0 → absent (gainFishingSkill treats as 0).
411
+ fishingSteps: typeof charRaw.fishingSteps === 'number' && charRaw.fishingSteps > 0
412
+ ? Math.trunc(charRaw.fishingSteps)
413
+ : undefined,
414
+ // v41 honor: pre-v41 / missing → empty ledger. Round-trips a stored shape when present.
415
+ honor: normalizeHonorState(charRaw.honor),
416
+ // soul shards are item 6265 (mapped from DB on Drain Soul kills); old numeric field ignored
417
+ };
418
+ delete (char as { equippedMainhand?: unknown }).equippedMainhand;
419
+ if (char.autoConsumables == null) delete char.autoConsumables;
420
+
421
+ // Classic hard cap is 60. Pre-cap-fix saves (grantXp could walk the
422
+ // player_xp_for_level 60→61 row) stored level 61+; without classLevel stats past 60
423
+ // those chars brick on load (maxHealth falls back to baseHp 1). Clamp + clear XP.
424
+ if (typeof char.level !== 'number' || !Number.isFinite(char.level) || char.level < 1) {
425
+ char.level = 1;
426
+ } else if (char.level >= CLASSIC_MAX_PLAYER_LEVEL) {
427
+ char.level = CLASSIC_MAX_PLAYER_LEVEL;
428
+ char.xp = 0;
429
+ }
430
+
431
+ // v28 happiness rescale: the pet happiness bar went 0..100 → 0..1000 (vanilla raw ÷1000,
432
+ // so the combat log reads +35/bite, 350/course). Multiply a pre-v28 pet's stored happiness
433
+ // and any in-progress Feed Pet Effect (feedRemaining/feedPerSec are happiness/s) by 10 so
434
+ // old pets keep their exact mood. Idempotent via the version gate.
435
+ const rawVersion = typeof r.version === 'number' ? r.version : 0;
436
+ if (rawVersion < 28) {
437
+ const rescalePet = <T extends { happiness?: number; feedRemaining?: number; feedPerSec?: number }>(
438
+ p: T | undefined,
439
+ ): T | undefined => {
440
+ if (!p || typeof p !== 'object') return p;
441
+ const next = { ...p };
442
+ if (typeof next.happiness === 'number') next.happiness *= 10;
443
+ if (typeof next.feedRemaining === 'number') next.feedRemaining *= 10;
444
+ if (typeof next.feedPerSec === 'number') next.feedPerSec *= 10;
445
+ return next;
446
+ };
447
+ char.pet = rescalePet(char.pet);
448
+ char.storedPet = rescalePet(char.storedPet);
449
+ if (Array.isArray(char.stablePets)) {
450
+ char.stablePets = char.stablePets.map((p) => (p ? rescalePet(p) ?? p : p));
451
+ }
452
+ }
453
+
454
+ let inventory = (stateRaw.inventory as GameState['inventory']) ?? { stacks: [] };
455
+ if (legacyMain != null && !hasMap) inventory = removeItem(inventory, legacyMain, 1)[0];
456
+
457
+ // v40 keyring: back-fill empty when absent. createGame sweeps BagFamily KEYS from bags
458
+ // once DataStore is available (migrate has no item defs).
459
+ const keyringRaw = stateRaw.keyring as GameState['keyring'] | undefined;
460
+ const keyring: GameState['keyring'] = keyringRaw && Array.isArray(keyringRaw.stacks)
461
+ ? { stacks: keyringRaw.stacks.map((s) => ({ ...s })) }
462
+ : { stacks: [] };
463
+
464
+ const corpseRaw = stateRaw.corpse as GameState['corpse'] | undefined;
465
+ const state: GameState = {
466
+ char,
467
+ inventory,
468
+ keyring,
469
+ bank: (stateRaw.bank as GameState['bank']) ?? { stacks: [] },
470
+ // v11 bank bag slots: a pre-v11 save bought none, so the bank is the base grid.
471
+ bankBags: Array.isArray(stateRaw.bankBags) ? (stateRaw.bankBags as GameState['bankBags']) : [],
472
+ spellbook: (stateRaw.spellbook as GameState['spellbook']) ?? { known: [] },
473
+ // v7 action bars: normalize a stored layout, or hand a default bar to a pre-v7 save
474
+ // (game.ts autofills that empty bar from the character's abilities on load).
475
+ actionBars: normalizeBars(stateRaw.actionBars as GameState['actionBars'] | undefined),
476
+ globalActionBar: normalizeGlobalBar(stateRaw.globalActionBar),
477
+ // v38 primary bar pages: form-paged main-bar layouts (BonusActionBar). Pre-v38 → page "0"
478
+ // from actionBars[0]; other form pages empty until the player edits while shifted.
479
+ primaryBarPages: (() => {
480
+ const bars = normalizeBars(stateRaw.actionBars as GameState['actionBars'] | undefined);
481
+ return normalizePrimaryPages(
482
+ stateRaw.primaryBarPages as PrimaryBarPages | undefined,
483
+ bars[0],
484
+ );
485
+ })(),
486
+ // This character's macros. Untrusted like everything else here: normalizeMacros clamps the
487
+ // count/name/body/icon and re-issues bad ids, so a hand-edited save loads as a legal list.
488
+ macros: normalizeMacros(stateRaw.macros, 'character'),
489
+ questlog: (stateRaw.questlog as GameState['questlog']) ?? { quests: [] },
490
+ rngSeed: typeof stateRaw.rngSeed === 'number' ? stateRaw.rngSeed : 1,
491
+ fightCounter: typeof stateRaw.fightCounter === 'number' ? stateRaw.fightCounter : 0,
492
+ activity: Array.isArray(stateRaw.activity) ? (stateRaw.activity as string[]) : [],
493
+ corpse: corpseRaw ?? null,
494
+ // v8 gather-node depletion: a pre-v8 save has none, so back-fill empty (all pristine).
495
+ nodeState: stateRaw.nodeState && typeof stateRaw.nodeState === 'object' ? (stateRaw.nodeState as GameState['nodeState']) : {},
496
+ // Persisted spell/category cooldowns (wall-clock readyAt). Absent on pre-cooldown saves;
497
+ // back-fill empty (game.ts prunes anything already expired on load).
498
+ spellCooldowns: stateRaw.spellCooldowns && typeof stateRaw.spellCooldowns === 'object' ? (stateRaw.spellCooldowns as GameState['spellCooldowns']) : {},
499
+ categoryCooldowns: stateRaw.categoryCooldowns && typeof stateRaw.categoryCooldowns === 'object' ? (stateRaw.categoryCooldowns as GameState['categoryCooldowns']) : {},
500
+ // Phase 5 dungeon state: back-fill so a pre-instance save stays valid.
501
+ // v26: drop Jasperlode runs; reset Deadmines runs that still list old placeholder
502
+ // encounter ids (miners/foundry — unique to the 95xxxx graph).
503
+ instance: migrateInstanceRun(stateRaw.instance as GameState['instance'] | null | undefined),
504
+ instanceSaves: migrateInstanceSaves(stateRaw.instanceSaves),
505
+ lockouts: migrateLockouts(
506
+ stateRaw.lockouts && typeof stateRaw.lockouts === 'object'
507
+ ? (stateRaw.lockouts as GameState['lockouts'])
508
+ : {},
509
+ ),
510
+ // v4 auction house: a pre-v4 save has none, so back-fill an empty one. v6 added
511
+ // `highBidder` to each auction — a pre-v6 listing had no bids, so default it to null.
512
+ auctionHouse: normalizeAuctionHouse(stateRaw.auctionHouse as GameState['auctionHouse'] | undefined),
513
+ // v6 mailbox: Delivery[] overflow. Now MailMessage[]; wrap leftover Delivery rows.
514
+ mailbox: migrateMailbox(stateRaw.mailbox, typeof r.updatedAt === 'number' ? r.updatedAt : Date.now()),
515
+ // v37 loot container: a haul still held by a corpse / chest / node / opened item. Pre-v37
516
+ // saves have none. Rows carry their rolled ItemInstance, so a suffix survives the round-trip.
517
+ ...(stateRaw.pendingLoot && typeof stateRaw.pendingLoot === 'object'
518
+ ? { pendingLoot: stateRaw.pendingLoot as GameState['pendingLoot'] }
519
+ : {}),
520
+ // v18 limited vendor stock: pre-v18 saves have no trackers (all vendors fully stocked).
521
+ ...(stateRaw.vendorStock && typeof stateRaw.vendorStock === 'object'
522
+ ? { vendorStock: stateRaw.vendorStock as GameState['vendorStock'] }
523
+ : {}),
524
+ // The open honor week's standing rows. A missing / malformed ledger becomes an unstamped
525
+ // one, which runHonorMaintenance adopts as the current week rather than back-dating decay —
526
+ // so no SAVE_VERSION bump: an older save loses nothing and gets no phantom rank decay.
527
+ honorWeek: normalizeHonorWeek(stateRaw.honorWeek),
528
+ // The 1v1 gauntlet rung (P6.3). A missing or junk value reads as 0 rungs beaten, which is
529
+ // exactly what a pre-existing save means, so no SAVE_VERSION bump.
530
+ ...(typeof stateRaw.gauntletRung === 'number' && Number.isFinite(stateRaw.gauntletRung)
531
+ && stateRaw.gauntletRung > 0
532
+ ? { gauntletRung: Math.max(0, Math.trunc(stateRaw.gauntletRung)) }
533
+ : {}),
534
+ // Arena Elo per bracket. Absent reads as the 1500 start, which is what every pre-rating save
535
+ // means, so no SAVE_VERSION bump. Junk entries are dropped rather than carried.
536
+ ...(normalizeArenaRating(stateRaw.arenaRating) ?? {}),
537
+ // v19 dungeon squad: pre-v19 saves have recruited no companions.
538
+ ...(Array.isArray(stateRaw.squad) ? { squad: stateRaw.squad as GameState['squad'] } : {}),
539
+ // v21 bot roster: dismissed bots wait here with their gear/level/XP.
540
+ ...(stateRaw.botRoster && typeof stateRaw.botRoster === 'object'
541
+ ? { botRoster: stateRaw.botRoster as GameState['botRoster'] }
542
+ : {}),
543
+ // v42 dev raid roster is dropped on load: no app surface builds one, so a save never keeps it.
544
+ ...(typeof stateRaw.squadRole === 'string' ? { squadRole: stateRaw.squadRole as GameState['squadRole'] } : {}),
545
+ ...(typeof stateRaw.squadStrategy === 'string' ? { squadStrategy: stateRaw.squadStrategy as GameState['squadStrategy'] } : {}),
546
+ ...(stateRaw.companionEnergy && typeof stateRaw.companionEnergy === 'object'
547
+ ? { companionEnergy: stateRaw.companionEnergy as GameState['companionEnergy'] }
548
+ : {}),
549
+ ...(stateRaw.raidParty && typeof stateRaw.raidParty === 'object'
550
+ ? { raidParty: stateRaw.raidParty as GameState['raidParty'] }
551
+ : {}),
552
+ ...(stateRaw.instanceRoster && typeof stateRaw.instanceRoster === 'object'
553
+ ? { instanceRoster: stateRaw.instanceRoster as GameState['instanceRoster'] }
554
+ : {}),
555
+ ...(stateRaw.raidLineup && typeof stateRaw.raidLineup === 'object'
556
+ ? { raidLineup: stateRaw.raidLineup as GameState['raidLineup'] }
557
+ : {}),
558
+ ...(stateRaw.pickpocketRestock && typeof stateRaw.pickpocketRestock === 'object'
559
+ ? { pickpocketRestock: stateRaw.pickpocketRestock as GameState['pickpocketRestock'] }
560
+ : {}),
561
+ ...(stateRaw.worldStates && typeof stateRaw.worldStates === 'object'
562
+ ? { worldStates: stateRaw.worldStates as GameState['worldStates'] }
563
+ : {}),
564
+ // Optional GameState fields that must round-trip. Pre-feature saves omit them; normalize
565
+ // on read (game.equipmentHelperConfig / autopilotConfig / rotation()) supplies defaults.
566
+ // Dropping these on migrate was resetting Equipment Helper to "suggest" every load.
567
+ ...(stateRaw.rotation !== undefined ? { rotation: stateRaw.rotation as GameState['rotation'] } : {}),
568
+ ...(stateRaw.rotationSpec !== undefined ? { rotationSpec: stateRaw.rotationSpec as GameState['rotationSpec'] } : {}),
569
+ // Second rotation profile (a tank's / healer's DPS list) and which slot is in force.
570
+ // Both must be listed here or migrate drops them and every reload throws the edits away.
571
+ ...(stateRaw.rotationDps !== undefined ? { rotationDps: stateRaw.rotationDps as GameState['rotationDps'] } : {}),
572
+ ...(stateRaw.rotationProfile !== undefined
573
+ ? { rotationProfile: stateRaw.rotationProfile as GameState['rotationProfile'] }
574
+ : {}),
575
+ // Named rotation lists + which one is in force. How many you have and which you use is
576
+ // exactly what has to survive a reload, so both keys are passed through explicitly.
577
+ ...(stateRaw.rotationProfiles !== undefined
578
+ ? { rotationProfiles: normalizeProfiles(stateRaw.rotationProfiles) }
579
+ : {}),
580
+ ...(typeof stateRaw.activeRotationProfileId === 'string'
581
+ ? { activeRotationProfileId: stateRaw.activeRotationProfileId }
582
+ : {}),
583
+ // Named talent loadouts from the wiki calculator. Optional; pre-feature saves omit.
584
+ ...(stateRaw.talentBuilds !== undefined
585
+ ? { talentBuilds: normalizeTalentBuilds(stateRaw.talentBuilds) }
586
+ : {}),
587
+ ...(stateRaw.autopilot !== undefined ? { autopilot: stateRaw.autopilot as GameState['autopilot'] } : {}),
588
+ ...(stateRaw.equipmentHelper !== undefined
589
+ ? { equipmentHelper: stateRaw.equipmentHelper as GameState['equipmentHelper'] }
590
+ : {}),
591
+ ...(stateRaw.outfitter !== undefined
592
+ ? { outfitter: stateRaw.outfitter as GameState['outfitter'] }
593
+ : {}),
594
+ ...(stateRaw.autoDisenchant !== undefined
595
+ ? { autoDisenchant: stateRaw.autoDisenchant as GameState['autoDisenchant'] }
596
+ : {}),
597
+ // PallyPower board. Listed here or migrate drops it and every reload throws the grid away.
598
+ ...(stateRaw.paladinAssignments !== undefined
599
+ ? { paladinAssignments: normalizePaladinAssignments(stateRaw.paladinAssignments) }
600
+ : {}),
601
+ ...(stateRaw.junkFilter !== undefined
602
+ ? { junkFilter: stateRaw.junkFilter as GameState['junkFilter'] }
603
+ : {}),
604
+ ...(stateRaw.gatherFilter !== undefined
605
+ ? { gatherFilter: stateRaw.gatherFilter as GameState['gatherFilter'] }
606
+ : {}),
607
+ ...(stateRaw.lastCorpse !== undefined
608
+ ? { lastCorpse: stateRaw.lastCorpse as GameState['lastCorpse'] }
609
+ : {}),
610
+ // Talent respec ladder (CMaNGOS m_resetTalentsCost/Time). Must round-trip or the
611
+ // escalating cost silently resets to the 1g first-reset price on every reload.
612
+ ...(stateRaw.resetTalentsCost !== undefined
613
+ ? { resetTalentsCost: stateRaw.resetTalentsCost as GameState['resetTalentsCost'] }
614
+ : {}),
615
+ ...(stateRaw.resetTalentsTime !== undefined
616
+ ? { resetTalentsTime: stateRaw.resetTalentsTime as GameState['resetTalentsTime'] }
617
+ : {}),
618
+ // Wave DF: player death-flow (CORPSE/GHOST). Optional — pre-DF / repair-only saves omit.
619
+ ...(stateRaw.deathFlow && typeof stateRaw.deathFlow === 'object'
620
+ ? { deathFlow: stateRaw.deathFlow as GameState['deathFlow'] }
621
+ : {}),
622
+ // v24 J-wiring: GO restock/trap runtime + environmental hazard timers.
623
+ ...(stateRaw.goRuntime && typeof stateRaw.goRuntime === 'object'
624
+ ? { goRuntime: stateRaw.goRuntime as GameState['goRuntime'] }
625
+ : {}),
626
+ ...(stateRaw.hazards && typeof stateRaw.hazards === 'object'
627
+ ? { hazards: stateRaw.hazards as GameState['hazards'] }
628
+ : {}),
629
+ // The battleground you were in. Identity only — the match is rebuilt on mount. An ARENA row is
630
+ // dropped: 2026-09-01 moved every bracket to the combat surface, and a match there does not
631
+ // survive a reload any more than a duel does.
632
+ ...(isObjectiveBattlegroundRun(stateRaw.battleground)
633
+ ? { battleground: stateRaw.battleground }
634
+ : {}),
635
+ // SPELL_EFFECT_SUMMON_OBJECT_WILD session places (optional; pre-feature saves omit).
636
+ ...(Array.isArray(stateRaw.wildSummonedObjects)
637
+ ? { wildSummonedObjects: stateRaw.wildSummonedObjects as GameState['wildSummonedObjects'] }
638
+ : {}),
639
+ ...(Array.isArray(stateRaw.objectSlots)
640
+ ? { objectSlots: stateRaw.objectSlots as GameState['objectSlots'] }
641
+ : {}),
642
+ // enterInstance nowMs for runFullDungeon lockout (KI-1022). Mid-run reload must keep it
643
+ // or applyLockout falls through to `?? 0` and the raid save expires immediately.
644
+ ...(typeof stateRaw.instanceEnteredAtMs === 'number' && Number.isFinite(stateRaw.instanceEnteredAtMs)
645
+ ? { instanceEnteredAtMs: Math.max(0, Math.trunc(stateRaw.instanceEnteredAtMs)) }
646
+ : {}),
647
+ };
648
+ return {
649
+ version: SAVE_VERSION,
650
+ slot: typeof r.slot === 'string' ? r.slot : 'default',
651
+ createdAt: typeof r.createdAt === 'number' ? r.createdAt : 0,
652
+ updatedAt: typeof r.updatedAt === 'number' ? r.updatedAt : 0,
653
+ ...(typeof r.baseUpdatedAt === 'number' && Number.isFinite(r.baseUpdatedAt)
654
+ ? { baseUpdatedAt: r.baseUpdatedAt }
655
+ : {}),
656
+ state,
657
+ };
658
+ }
659
+
660
+ export function summarize(save: Save): SaveMeta {
661
+ return {
662
+ slot: save.slot,
663
+ name: save.state.char.name,
664
+ level: save.state.char.level,
665
+ cls: save.state.char.cls,
666
+ updatedAt: save.updatedAt,
667
+ };
668
+ }