azeroth-shell 0.0.0-stage → 0.1.1

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 +35 -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 +144 -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,1774 @@
1
+ /** SI2.5 / SI3 handlers — auras-misc (split from handlers.ts, pure move). */
2
+
3
+ import type { BuffMod, RawSpellEffect, School, SpellEffect } from '../../../../data/schema.ts';
4
+ import { effectAmountRange } from '../amount.ts';
5
+ import type {
6
+ InterpretIntent,
7
+ } from '../types.ts';
8
+ import { STAT_MOD_PCT, withHostile } from '../targeting.ts';
9
+ import {
10
+ SPELL_AURA_MOD_INCREASE_SWIM_SPEED,
11
+ SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS,
12
+ SPELL_AURA_MOD_PERCENT_STAT,
13
+ SPELL_AURA_MOD_SPEED_ALWAYS,
14
+ SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED,
15
+ } from '../opcodes.ts';
16
+ import type {
17
+ HandlerState,
18
+ } from './shared.ts';
19
+ import {
20
+ SPELLFAMILY_MAGE,
21
+ MANA_SHIELD_FAMILY_FLAGS,
22
+ MANA_SHIELD_SPD_COEFF,
23
+ LEVEL_PENALTY_THRESHOLD,
24
+ LEVEL_PENALTY_PER_LEVEL,
25
+ REP_FRIENDLY,
26
+ schoolOf,
27
+ schoolFromSingleBitMask,
28
+ familyOf,
29
+ flagsOf,
30
+ durationMsResolved,
31
+ withPpc,
32
+ trunc,
33
+ SCHOOLS,
34
+ } from './shared.ts';
35
+ import {
36
+ OVERRIDE_SCRIPT_PROC_TRIGGERS,
37
+ OVERRIDE_SCRIPT_ROLLS_OWN_AMOUNT,
38
+ } from '../../overrideClassScripts.ts';
39
+ import { SPELL_AFFECT_MASK_ADD_TARGET_TRIGGER } from '../class-scripts-kit.ts';
40
+ // ── SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL (71) ────────────────────────── Cite: SpellAuras.cpp:3891–3911
41
+ // HandleModSpellCritChanceShool Bake empty (aura === 71 return). Cite: map-spell-effects.mjs:814.
42
+ export function handleModSpellCritChanceSchool(
43
+ state: HandlerState,
44
+ raw: RawSpellEffect,
45
+ _slot: number,
46
+ _effectType: number,
47
+ ): void {
48
+ // C++: if (!Real) return. Cite: :3893–3894.
49
+ const { min } = effectAmountRange(raw, state.ctx);
50
+ const dur = durationMsResolved(state);
51
+ const schoolMask = raw.miscValue | 0;
52
+ // Spell crit % buff — combat applies via spellCritChance. Cite: SpellAuras.cpp:3897–3909.
53
+ state.effects.push({
54
+ kind: 'buff',
55
+ mod: 'spell_crit',
56
+ amount: min,
57
+ durationMs: dur,
58
+ ...(schoolMask ? { schoolMask } : {}),
59
+ } as never);
60
+ state.role = state.role || 'buff';
61
+ }
62
+
63
+ // ── SPELL_AURA_MOD_LANGUAGE (75) ── unmapped in the bake. Hostility comes from targetA, since Curse of
64
+ // Tongues targets an enemy and is not a self buff. Cite: SpellAuras.cpp:136; ChatHandler.cpp:151-155.
65
+ export function handleModLanguage(
66
+ state: HandlerState,
67
+ raw: RawSpellEffect,
68
+ _slot: number,
69
+ _effectType: number,
70
+ ): void {
71
+ const dur = durationMsResolved(state);
72
+ // m_miscvalue = language id. Cite: ChatHandler.cpp:154–155.
73
+ state.effects.push(withHostile({
74
+ kind: 'mod_language',
75
+ languageId: raw.miscValue | 0,
76
+ durationMs: dur,
77
+ }, raw.targetA | 0, 0) as never);
78
+ state.role = state.role || 'buff';
79
+ }
80
+
81
+ // ── SPELL_AURA_WATER_BREATHING (82) ── the play surface is an aura chip plus a breathing effect, which
82
+ // suppresses the hazard when wired. Cite: SpellAuras.cpp:1688-1699 HandleWaterBreathing.
83
+ export function handleWaterBreathing(
84
+ state: HandlerState,
85
+ _raw: RawSpellEffect,
86
+ _slot: number,
87
+ _effectType: number,
88
+ ): void {
89
+ // C++: player only SetWaterBreathingIntervalMultiplier. Cite: :1692–1698.
90
+ // Non-player: no-op body. Cite: TYPEID_PLAYER gate :1692.
91
+ if (state.ctx.unitTargetIsPlayer === false) return;
92
+ // apply || HasAuraType(WATER_BREATHING) → multiplier 0. Cite: :1694–1695.
93
+ // Interpret apply snapshot always sets 0 (aura present).
94
+ const dur = durationMsResolved(state);
95
+ state.intents.push({
96
+ kind: 'water_breathing',
97
+ intervalMultiplier: 0,
98
+ durationMs: dur,
99
+ });
100
+ // Catalog / OOC: not a pure mana sink. Cite: schema water_breathing; KI inert castables.
101
+ if (!state.effects.some((e) => e.kind === 'water_breathing')) {
102
+ state.effects.push({ kind: 'water_breathing', durationMs: dur < 0 ? 0 : dur });
103
+ }
104
+ state.role = state.role || 'buff';
105
+ }
106
+
107
+ // ── SPELL_AURA_MOD_DETECT_RANGE (91) ── unmapped in the bake; the C++ adds it to the attack distance.
108
+ // Cite: SpellAuras.cpp:152; Unit.cpp:11772 GetAttackDistance.
109
+ export function handleModDetectRange(
110
+ state: HandlerState,
111
+ raw: RawSpellEffect,
112
+ _slot: number,
113
+ _effectType: number,
114
+ ): void {
115
+ const { min } = effectAmountRange(raw, state.ctx);
116
+ const dur = durationMsResolved(state);
117
+ // Amount is signed yards (Mind Soothe −10). Cite: Unit.cpp:11772.
118
+ state.intents.push({
119
+ kind: 'mod_detect_range',
120
+ amount: min,
121
+ durationMs: dur,
122
+ });
123
+ // Catalog / OOC / combat kit surface (Mind Soothe). Cite: schema mod_detect_range; KI-186.
124
+ state.effects.push({ kind: 'mod_detect_range', amount: min, durationMs: dur });
125
+ state.role = state.role || 'control';
126
+ }
127
+
128
+ // ── SPELL_AURA_MANA_SHIELD (97) ── baked as a mana shield, whose absorb is paid from mana at the
129
+ // effect's multiple value. Cite: SpellAuras.cpp:5063-5093; Unit.cpp:2457-2496.
130
+ export function handleManaShield(
131
+ state: HandlerState,
132
+ raw: RawSpellEffect,
133
+ _slot: number,
134
+ _effectType: number,
135
+ ): void {
136
+ // C++: if (!Real) return. Cite: :5065–5066.
137
+ const { min, max } = effectAmountRange(raw, state.ctx);
138
+ const dur = durationMsResolved(state);
139
+ // Pool from basepoints; clamp ≥ 1. Cite: map-spell-effects.mjs:972–975.
140
+ let poolMin = Math.max(1, min);
141
+ let poolMax = Math.max(1, max || min);
142
+ // manaMultiplier = EffectMultipleValue (Mana Shield ranks: 2). Cite: Unit.cpp:2473.
143
+ const manaMultiplier = Number(raw.multipleValue) || 0;
144
+
145
+ // At cast time a mage of the right family adds half its spell damage bonus. Gated on the caller
146
+ // supplying that bonus; nothing produces it today, as it would need the school.
147
+ if (state.ctx.spellBaseDamageBonusDone != null) {
148
+ if (
149
+ familyOf(state.spell) === SPELLFAMILY_MAGE
150
+ && (flagsOf(state.spell) & MANA_SHIELD_FAMILY_FLAGS) !== 0
151
+ ) {
152
+ const spellLevel = state.spell.spellLevel ?? state.spell.reqLevel ?? 0;
153
+ const levelPenalty =
154
+ spellLevel < LEVEL_PENALTY_THRESHOLD && spellLevel > 0
155
+ ? 1.0 - (LEVEL_PENALTY_THRESHOLD - spellLevel) * LEVEL_PENALTY_PER_LEVEL
156
+ : 1.0;
157
+ const bonus = trunc(
158
+ state.ctx.spellBaseDamageBonusDone * MANA_SHIELD_SPD_COEFF * levelPenalty,
159
+ );
160
+ if (bonus) {
161
+ poolMin += bonus;
162
+ poolMax += bonus;
163
+ state.intents.push({ kind: 'mana_shield_spd_bonus', bonusAmount: bonus });
164
+ }
165
+ }
166
+ }
167
+
168
+ state.effects.push({
169
+ kind: 'mana_shield',
170
+ schoolMask: raw.miscValue | 0,
171
+ min: poolMin,
172
+ max: poolMax,
173
+ manaMultiplier,
174
+ durationMs: dur,
175
+ });
176
+ state.role = state.role || 'buff';
177
+ }
178
+
179
+ // ── SPELL_AURA_OVERRIDE_CLASS_SCRIPTS (112) ── empty in the bake; the C++ registers the script id.
180
+ // Cite: SpellAuras.cpp:5096-5099; Unit.cpp:11980-11985 RegisterOverrideScriptAura.
181
+ export function handleOverrideClassScripts(
182
+ state: HandlerState,
183
+ raw: RawSpellEffect,
184
+ _slot: number,
185
+ _effectType: number,
186
+ ): void {
187
+ const { min } = effectAmountRange(raw, state.ctx);
188
+ const dur = durationMsResolved(state);
189
+ const scriptId = raw.miscValue | 0;
190
+ // RegisterOverrideScriptAura(this, m_modifier.m_miscvalue, apply). Cite: :5098.
191
+ state.intents.push({
192
+ kind: 'override_class_scripts',
193
+ scriptId,
194
+ amount: min,
195
+ durationMs: dur,
196
+ });
197
+ // A per-id switch: proc ids become proc triggers and two register on apply. The remaining ids are
198
+ // listed as not implemented rather than given an invented payload.
199
+ const triggerSpellId = OVERRIDE_SCRIPT_PROC_TRIGGERS[scriptId];
200
+ if (triggerSpellId != null) {
201
+ state.effects.push({
202
+ kind: 'proc_trigger_spell',
203
+ triggerSpellId,
204
+ durationMs: dur,
205
+ amount: min,
206
+ // Improved Mend Pet rolls the aura amount (15%/50%), not ProcChance 101.
207
+ // Dreamwalker 2pc (4533) requires roll_chance_i(50). Cite: UnitAuraProcHandler.cpp:1630.
208
+ ...(OVERRIDE_SCRIPT_ROLLS_OWN_AMOUNT.has(scriptId) && min > 0
209
+ ? { procChancePct: min }
210
+ : scriptId === 4533 ? { procChancePct: 50 } : {}),
211
+ });
212
+ state.role = state.role || 'buff';
213
+ }
214
+ }
215
+
216
+ // ── SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN (125) ── baked as physical_taken, the non-ranged flat.
217
+ // Cite: SpellAuras.cpp:186; Unit.cpp:7618 MeleeDamageBonusTaken.
218
+ export function handleModMeleeDamageTaken(
219
+ state: HandlerState,
220
+ raw: RawSpellEffect,
221
+ _slot: number,
222
+ _effectType: number,
223
+ ): void {
224
+ const { min } = effectAmountRange(raw, state.ctx);
225
+ const dur = durationMsResolved(state);
226
+ // GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN). Cite: Unit.cpp:7618.
227
+ // Bake collapses to physical_taken BuffMod. Cite: map-spell-effects.mjs:1060–1061.
228
+ const tagged = withHostile(
229
+ { kind: 'buff' as const, mod: 'physical_taken' as const, amount: min, durationMs: dur },
230
+ raw.targetA | 0,
231
+ min,
232
+ );
233
+ state.effects.push(tagged as SpellEffect);
234
+ state.role = state.role || 'buff';
235
+ }
236
+
237
+ // ── SPELL_AURA_FORCE_REACTION (139) ─────────────────────────────────────── Cite: SpellAuras.cpp:2034–2052
238
+ // HandleForceReaction Bake unmapped.
239
+ export function handleForceReaction(
240
+ state: HandlerState,
241
+ raw: RawSpellEffect,
242
+ _slot: number,
243
+ _effectType: number,
244
+ ): void {
245
+ // C++: non-player return. Cite: :2036–2037.
246
+ if (state.ctx.unitTargetIsPlayer === false) return;
247
+ // C++: if (!Real) return. Cite: :2039–2040.
248
+ const { min } = effectAmountRange(raw, state.ctx);
249
+ const dur = durationMsResolved(state);
250
+ const factionId = raw.miscValue | 0;
251
+ const reputationRank = min;
252
+ // ApplyForceReaction(faction_id, rank, apply) + SendForceReactions. Cite: :2046–2047.
253
+ state.effects.push({
254
+ kind: 'force_reaction',
255
+ factionId,
256
+ reputationRank,
257
+ durationMs: dur,
258
+ ...(reputationRank >= REP_FRIENDLY ? { stopAttackFaction: true } : {}),
259
+ });
260
+ state.role = state.role || 'buff';
261
+ }
262
+
263
+ // ── SPELL_AURA_EFFECT_IMMUNITY (37) ──────────────────────────────────────── Cite:
264
+ // SpellAuras.cpp:2962–2970 HandleAuraModEffectImmunity Bake empty.
265
+ export function handleEffectImmunity(
266
+ state: HandlerState,
267
+ raw: RawSpellEffect,
268
+ _slot: number,
269
+ _effectType: number,
270
+ ): void {
271
+ const effectId = raw.miscValue | 0;
272
+ const dur = durationMsResolved(state);
273
+ // Emitted as an EFFECT as well as an intent: the resolver drops intents, so intent-only left the
274
+ // WSG flag auras resolving to a send-event alone and the carrier's immunity did nothing.
275
+ if (effectId > 0) {
276
+ state.effects.push({
277
+ kind: 'effect_immunity',
278
+ effectId,
279
+ durationMs: dur,
280
+ positive: true,
281
+ });
282
+ }
283
+ const intent: InterpretIntent = {
284
+ kind: 'effect_immunity',
285
+ effectId,
286
+ durationMs: dur,
287
+ };
288
+ // apply + IsPositive → RemoveAurasWithInterruptFlags INVULNERABILITY. Cite: :2968–2969.
289
+ // Interpret is apply-time on a positive immunity aura → always purge flag.
290
+ intent.purgeInvulnerabilityBuffs = true;
291
+ state.intents.push(intent);
292
+ state.role = state.role || 'buff';
293
+ }
294
+
295
+ // ── SPELL_AURA_STATE_IMMUNITY (38) ───────────────────────────────────────── Cite:
296
+ // SpellAuras.cpp:2972–2989 HandleAuraModStateImmunity Bake empty.
297
+ export function handleStateImmunity(
298
+ state: HandlerState,
299
+ raw: RawSpellEffect,
300
+ _slot: number,
301
+ _effectType: number,
302
+ ): void {
303
+ const auraType = raw.miscValue | 0;
304
+ const dur = durationMsResolved(state);
305
+ // Emitted as an EFFECT as well as an intent: the resolver drops intents, so an intent-only state
306
+ // immunity never reaches combat — the same defect as the dispel immunity aura.
307
+ if (auraType > 0) {
308
+ state.effects.push({
309
+ kind: 'state_immunity',
310
+ stateAuraType: auraType,
311
+ durationMs: dur,
312
+ positive: true,
313
+ });
314
+ }
315
+ const intent: InterpretIntent = {
316
+ kind: 'state_immunity',
317
+ auraType,
318
+ durationMs: dur,
319
+ };
320
+ // apply + Real + ATTR_EX IMMUNITY_PURGES_EFFECT → remove auras of that AuraType.
321
+ // Cite: :2974–2987. Gate: ctx.immunityPurgesEffect.
322
+ if (state.ctx.immunityPurgesEffect === true) {
323
+ intent.purgeAuraType = true;
324
+ }
325
+ state.intents.push(intent);
326
+ state.role = state.role || 'buff';
327
+ }
328
+
329
+ // ── SPELL_AURA_DAMAGE_IMMUNITY (40) ── baked as a damage immunity.
330
+ // Cite: SpellAuras.cpp:3046-3051 HandleAuraModDmgImmunity.
331
+ export function handleDamageImmunity(
332
+ state: HandlerState,
333
+ raw: RawSpellEffect,
334
+ _slot: number,
335
+ _effectType: number,
336
+ ): void {
337
+ const schoolMask = raw.miscValue | 0;
338
+ const dur = durationMsResolved(state);
339
+ // ApplySpellImmune(IMMUNITY_DAMAGE, misc). Cite: :3048.
340
+ // Hostile-ref suppress is runtime. Cite: :3050.
341
+ state.effects.push({
342
+ kind: 'damage_immunity',
343
+ schoolMask,
344
+ durationMs: dur,
345
+ positive: true,
346
+ });
347
+ state.role = state.role || 'buff';
348
+ }
349
+
350
+ // ── SPELL_AURA_TRACK_RESOURCES (45) ──────────────────────────────────────── Cite:
351
+ // SpellAuras.cpp:2163–2171 HandleAuraTrackResources Bake empty (minimap tracking).
352
+ export function handleTrackResources(
353
+ state: HandlerState,
354
+ raw: RawSpellEffect,
355
+ _slot: number,
356
+ _effectType: number,
357
+ ): void {
358
+ // C++: non-player → return. Cite: :2165–2166.
359
+ if (state.ctx.unitTargetIsPlayer === false) return;
360
+
361
+ const resourceType = raw.miscValue | 0;
362
+ // Bit = 1 << (misc − 1). Cite: :2169–2170.
363
+ const trackFlag = resourceType > 0 ? (1 << (resourceType - 1)) : 0;
364
+ const dur = durationMsResolved(state);
365
+ state.intents.push({
366
+ kind: 'track_resources',
367
+ resourceType,
368
+ trackFlag,
369
+ durationMs: dur,
370
+ });
371
+ // Catalog / OOC: not a pure no-op. Cite: schema track_resources; KI-567 Find Treasure.
372
+ if (!state.effects.some((e) => e.kind === 'track_resources')) {
373
+ state.effects.push({
374
+ kind: 'track_resources',
375
+ resourceType,
376
+ trackFlag,
377
+ durationMs: dur < 0 ? 0 : dur,
378
+ });
379
+ }
380
+ state.role = state.role || 'buff';
381
+ }
382
+
383
+ // ── SPELL_AURA_MOD_INCREASE_SWIM_SPEED (58) ── baked as a signed speed percent on the swim rate.
384
+ // Cite: SpellAuras.cpp:2898-2905 HandleAuraModIncreaseSwimSpeed.
385
+ export function handleModIncreaseSwimSpeed(
386
+ state: HandlerState,
387
+ raw: RawSpellEffect,
388
+ _slot: number,
389
+ _effectType: number,
390
+ ): void {
391
+ // C++ requires Real. Cite: :2900–2902.
392
+ const { min } = effectAmountRange(raw, state.ctx);
393
+ const dur = durationMsResolved(state);
394
+ const tagged = withHostile(
395
+ {
396
+ kind: 'speed' as const,
397
+ aura: SPELL_AURA_MOD_INCREASE_SWIM_SPEED,
398
+ pct: min,
399
+ durationMs: dur,
400
+ },
401
+ raw.targetA | 0,
402
+ min,
403
+ );
404
+ state.effects.push(tagged as SpellEffect);
405
+ state.role = state.role || 'buff';
406
+ }
407
+
408
+ // ── SPELL_AURA_MOD_PACIFY_SILENCE (60) ── the bake carries the silence half only and omits the pacify.
409
+ // Cite: SpellAuras.cpp:4390-4394; HandleAuraModPacify :4382; HandleAuraModSilence :2778.
410
+ export function handleModPacifySilence(
411
+ state: HandlerState,
412
+ raw: RawSpellEffect,
413
+ _slot: number,
414
+ _effectType: number,
415
+ ): void {
416
+ const dur = durationMsResolved(state);
417
+ // Pacify: SetFlag UNIT_FLAG_PACIFIED. Cite: HandleAuraModPacify :4384–4387.
418
+ state.effects.push({
419
+ kind: 'pacify',
420
+ durationMs: dur || 1000,
421
+ });
422
+ // Silence: SetFlag UNIT_FLAG_SILENCED + interrupt PreventionType SILENCE. Cite: :2778–2794.
423
+ // C++ silence path requires Real — interpret is apply-time. Cite: :2781–2783.
424
+ state.effects.push({
425
+ kind: 'cc',
426
+ control: 'silence',
427
+ mechanic: 'silence',
428
+ durationMs: dur,
429
+ school: schoolOf(state.spell),
430
+ });
431
+ state.role = state.role || 'control';
432
+ state.intents.push({ kind: 'mod_silence_interrupt' });
433
+ }
434
+
435
+ // ── SPELL_AURA_PREVENTS_FLEEING (92) ── empty in the bake. Hostility comes from targetA, since Curse
436
+ // of Recklessness targets an enemy and is not a self-buff. Cite: SpellAuras.cpp:5047-5060.
437
+ export function handlePreventsFleeing(
438
+ state: HandlerState,
439
+ raw: RawSpellEffect,
440
+ _slot: number,
441
+ _effectType: number,
442
+ ): void {
443
+ // C++: if (!Real) return. Cite: :5049–5050. If fear auras present: apply → SetFleeing(false); remove →
444
+ // restore flee. Cite: :5052–5059. Fear presence is runtime unit state — emit intent.
445
+ const dur = durationMsResolved(state);
446
+ state.effects.push(withHostile({
447
+ kind: 'prevents_fleeing',
448
+ durationMs: dur,
449
+ }, raw.targetA | 0, 0) as never);
450
+ state.role = state.role || 'buff';
451
+ }
452
+
453
+ // ── SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS (127) ── the VICTIM's aura adds to the attacker's
454
+ // ranged attack power. Cite: SpellAuras.cpp:188; Unit.cpp:7470 MeleeDamageBonusDone.
455
+ export function handleRangedAttackPowerAttackerBonus(
456
+ state: HandlerState,
457
+ raw: RawSpellEffect,
458
+ _slot: number,
459
+ _effectType: number,
460
+ ): void {
461
+ const { min } = effectAmountRange(raw, state.ctx);
462
+ const dur = durationMsResolved(state);
463
+ // Victim aura: attackers gain RAP while debuff is up. Cite: Unit.cpp:7470.
464
+ const tagged = withHostile(
465
+ {
466
+ kind: 'buff' as const,
467
+ mod: 'attacker_attack_power' as const,
468
+ amount: min,
469
+ durationMs: dur,
470
+ },
471
+ raw.targetA | 0,
472
+ min,
473
+ );
474
+ state.effects.push(tagged as SpellEffect);
475
+ state.role = state.role || 'buff';
476
+ }
477
+
478
+ // ── SPELL_AURA_MOD_RANGED_AMMO_HASTE (141) ───────────────────────────────── Cite:
479
+ // SpellAuras.cpp:3945–3980 HandleRangedAmmoHaste Bake: haste buff. Cite: map-spell-effects.mjs:1065–1069.
480
+ export function handleRangedAmmoHaste(
481
+ state: HandlerState,
482
+ raw: RawSpellEffect,
483
+ _slot: number,
484
+ _effectType: number,
485
+ ): void {
486
+ // C++: non-player → return. Cite: :3947–3948.
487
+ if (state.ctx.unitTargetIsPlayer === false) return;
488
+
489
+ const { min } = effectAmountRange(raw, state.ctx);
490
+ const dur = durationMsResolved(state);
491
+
492
+ // EquippedItemClass != −1 requires fitted ranged weapon. Cite: :3957–3959.
493
+ // Gate: ctx.equippedItemClass set and no fit (ctx.rangedWeaponFitsSpell === false).
494
+ const equipClass = state.ctx.equippedItemClass;
495
+ if (
496
+ equipClass != null
497
+ && equipClass !== -1
498
+ && state.ctx.rangedWeaponFitsSpell === false
499
+ ) {
500
+ return;
501
+ }
502
+
503
+ // Highest-only stacking: only max positive amount applies. Cite: :3951–3954 / :3975–3980.
504
+ // Bake-thin always emits this aura's amount; intent documents highest-only policy.
505
+ state.intents.push({ kind: 'ranged_ammo_haste_highest', amount: min });
506
+
507
+ // ApplyAttackTimePercentMod(RANGED_ATTACK, amount). Cite: :3975–3978.
508
+ const tagged = withHostile(
509
+ { kind: 'buff' as const, mod: 'haste' as const, amount: min, durationMs: dur },
510
+ raw.targetA | 0,
511
+ min,
512
+ );
513
+ state.effects.push(tagged as SpellEffect);
514
+ state.role = state.role || 'buff';
515
+ }
516
+
517
+ // ── SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS (180) ── the misc value is a creature type MASK.
518
+ // Cite: SpellAuras.cpp:241; Unit.cpp:7055 SpellDamageBonusDone, :4538 GetCreatureTypeMask.
519
+ export function handleModFlatSpellDamageVersus(
520
+ state: HandlerState,
521
+ raw: RawSpellEffect,
522
+ _slot: number,
523
+ _effectType: number,
524
+ ): void {
525
+ const { min } = effectAmountRange(raw, state.ctx);
526
+ const dur = durationMsResolved(state);
527
+ const creatureTypeMask = raw.miscValue | 0;
528
+ state.intents.push({
529
+ kind: 'mod_flat_spell_damage_versus',
530
+ creatureTypeMask,
531
+ amount: min,
532
+ durationMs: dur,
533
+ });
534
+ state.effects.push({
535
+ kind: 'buff',
536
+ mod: 'spell_damage_versus',
537
+ amount: min,
538
+ durationMs: dur,
539
+ creatureTypeMask,
540
+ } as SpellEffect);
541
+ state.role = state.role || 'buff';
542
+ }
543
+
544
+ // ── SPELL_AURA_MOD_SPELL_HIT_CHANCE (55) ────────────────────────────────── Cite: SpellAuras.cpp:3868–3870
545
+ // HandleModSpellHitChance Bake empty (aura === 54 || 55 return). Cite: map-spell-effects.mjs:801–802.
546
+ export function handleModSpellHitChance(
547
+ state: HandlerState,
548
+ raw: RawSpellEffect,
549
+ _slot: number,
550
+ _effectType: number,
551
+ ): void {
552
+ const { min } = effectAmountRange(raw, state.ctx);
553
+ const dur = durationMsResolved(state);
554
+ // m_modSpellHitChance += ±amount. Cite: :3870.
555
+ // Player recompute: GetTotalAuraModifier(55). Cite: StatSystem.cpp:538.
556
+ state.intents.push({
557
+ kind: 'mod_spell_hit_chance',
558
+ amount: min,
559
+ durationMs: dur,
560
+ });
561
+ // Unread intent → Nature's Guidance and every Increased Spell Hit Chance item granted nothing.
562
+ if (min !== 0) {
563
+ state.effects.push({
564
+ kind: 'buff',
565
+ mod: 'spell_hit',
566
+ amount: min,
567
+ durationMs: dur,
568
+ hostile: min < 0,
569
+ });
570
+ state.role = state.role || 'buff';
571
+ }
572
+ }
573
+
574
+ // ── SPELL_AURA_PERIODIC_DAMAGE_PERCENT (89) ── the tick is a percent of the target's max health,
575
+ // baked as a flat dot from base points. Cite: SpellAuras.cpp:3242-3244; PeriodicTick :4506-4525.
576
+ export function handlePeriodicDamagePercent(
577
+ state: HandlerState,
578
+ raw: RawSpellEffect,
579
+ _slot: number,
580
+ _effectType: number,
581
+ ): void {
582
+ const { min, pointsPerComboPoint } = effectAmountRange(raw, state.ctx);
583
+ // The tick ignores a non-positive amount. Bake-thin keeps the flat value; with a target maximum
584
+ // supplied it is the full formula, that maximum times the amount over 100.
585
+ let amount = Math.max(1, min);
586
+ if (state.ctx.targetMaxHealth != null && min > 0) {
587
+ amount = Math.max(1, trunc((state.ctx.targetMaxHealth * min) / 100));
588
+ }
589
+ const tickMs = (raw.amplitude | 0) || 3000;
590
+ const dur = durationMsResolved(state);
591
+ // Bake fallback duration when unset. Cite: map-spell-effects.mjs:1100 dur || 12000.
592
+ const durationMs = dur > 0 ? dur : 12_000;
593
+ state.effects.push(
594
+ withPpc(
595
+ {
596
+ kind: 'dot',
597
+ school: schoolOf(state.spell),
598
+ min: amount,
599
+ max: amount,
600
+ durationMs,
601
+ tickMs,
602
+ },
603
+ pointsPerComboPoint,
604
+ ) as SpellEffect,
605
+ );
606
+ }
607
+
608
+ // ── SPELL_AURA_WATER_WALK (104) ─────────────────────────────────────────── Cite: SpellAuras.cpp:1661–1667
609
+ // HandleAuraWaterWalk Play surface: aura chip (no water-surface movement sim — feather_fall pattern).
610
+ export function handleAuraWaterWalk(
611
+ state: HandlerState,
612
+ _raw: RawSpellEffect,
613
+ _slot: number,
614
+ _effectType: number,
615
+ ): void {
616
+ // C++: if (!Real) return. Cite: :1663–1664.
617
+ // SetWaterWalk(apply). Cite: :1666; Unit.cpp:12486 SMSG_MOVE_WATER_WALK.
618
+ const dur = durationMsResolved(state);
619
+ state.intents.push({ kind: 'water_walk', durationMs: dur });
620
+ if (!state.effects.some((e) => e.kind === 'water_walk')) {
621
+ state.effects.push({ kind: 'water_walk', durationMs: dur < 0 ? 0 : dur });
622
+ }
623
+ state.role = state.role || 'buff';
624
+ }
625
+
626
+ // ── SPELL_AURA_ADD_TARGET_TRIGGER (109) ── the payload fires on the spell's victim.
627
+ // Cite: SpellAuras.cpp:170; Spell.cpp:7433-7468 ProcSpellAuraTriggers.
628
+ export function handleAddTargetTrigger(
629
+ state: HandlerState,
630
+ raw: RawSpellEffect,
631
+ _slot: number,
632
+ _effectType: number,
633
+ ): void {
634
+ const trig = raw.triggerSpell | 0;
635
+ if (!trig) return;
636
+ const { min } = effectAmountRange(raw, state.ctx);
637
+ const dur = durationMsResolved(state);
638
+ const id = state.spell.id | 0;
639
+ // procid = EffectTriggerSpell[eff]. Cite: Spell.cpp:7454. chance = CalculateSpellEffectValue (amount).
640
+ // Cite: :7457–7458. Mask = spell_affect row, else EffectItemType. Cite: SpellMgr.h:1950–1958.
641
+ const itemType = (raw.itemType ?? 0) | 0;
642
+ const affect = SPELL_AFFECT_MASK_ADD_TARGET_TRIGGER[id] ?? 0;
643
+ state.effects.push({
644
+ kind: 'add_target_trigger',
645
+ triggerSpellId: trig,
646
+ chancePct: min,
647
+ durationMs: dur,
648
+ familyName: (state.spell.spellFamilyName ?? 0) | 0,
649
+ familyFlags: itemType || affect,
650
+ });
651
+ state.role = state.role || 'buff';
652
+ }
653
+
654
+ // ── SPELL_AURA_MOD_POWER_REGEN_PERCENT (110) ── a percent of the spirit-based mana regen, not a flat
655
+ // mana per five. Cite: SpellAuras.cpp:3644-3655; StatSystem.cpp:551-552.
656
+ export function handleModPowerRegenPercent(
657
+ state: HandlerState,
658
+ raw: RawSpellEffect,
659
+ _slot: number,
660
+ _effectType: number,
661
+ ): void {
662
+ // C++: if (!Real) return; player only; POWER_MANA → UpdateManaRegen. Cite: :3646–3655.
663
+ if (state.ctx.unitTargetIsPlayer === false) return;
664
+
665
+ const { min } = effectAmountRange(raw, state.ctx);
666
+ const dur = durationMsResolved(state);
667
+ const powerType = raw.miscValue | 0;
668
+
669
+ // POWER_MANA = 0: catalog + combat buff. Cite: StatSystem.cpp:551–552.
670
+ if (powerType === 0) {
671
+ const tagged = withHostile(
672
+ { kind: 'buff' as const, mod: 'mana_regen_pct' as const, amount: min, durationMs: dur },
673
+ raw.targetA | 0,
674
+ min,
675
+ );
676
+ state.effects.push(tagged as SpellEffect);
677
+ state.role = state.role || 'buff';
678
+ }
679
+
680
+ // C++ use sites: mana spirit × multiplier; rage/energy (100+amount)/100.
681
+ // Cite: StatSystem.cpp:551–552; Player.cpp:2340–2353. POWER_MANA = 0.
682
+ const intent: InterpretIntent = {
683
+ kind: 'mod_power_regen_percent',
684
+ powerType,
685
+ amount: min,
686
+ durationMs: dur,
687
+ };
688
+ if (powerType === 0) intent.updateManaRegen = true;
689
+ state.intents.push(intent);
690
+ }
691
+
692
+ // ── SPELL_AURA_SAFE_FALL (144) ── an empty body in the C++; the modifier reduces the fall distance.
693
+ // Cite: SpellAuras.cpp:5649-5651; Player.cpp:19535-19537.
694
+ export function handleAuraSafeFall(
695
+ state: HandlerState,
696
+ raw: RawSpellEffect,
697
+ _slot: number,
698
+ _effectType: number,
699
+ ): void {
700
+ const { min } = effectAmountRange(raw, state.ctx);
701
+ const dur = durationMsResolved(state);
702
+ // damageperc = 0.018 * (z_diff - safe_fall) - 0.2426. Cite: Player.cpp:19537.
703
+ state.intents.push({
704
+ kind: 'safe_fall',
705
+ amount: min,
706
+ durationMs: dur,
707
+ });
708
+ // Catalog / OOC: not a pure no-op. Cite: schema safe_fall; KI-693.
709
+ if (!state.effects.some((e) => e.kind === 'safe_fall')) {
710
+ state.effects.push({ kind: 'safe_fall', amount: min, durationMs: dur < 0 ? 0 : dur });
711
+ }
712
+ state.role = state.role || 'buff';
713
+ }
714
+
715
+ // ── SPELL_AURA_MOD_STEALTH_LEVEL (154) ──────────────────────────────────── Cite: SpellAuras.cpp:2621–2623
716
+ // HandleModStealthLevel Bake: stealth_level. Cite: map-spell-effects.mjs:1077–1079.
717
+ export function handleModStealthLevel(
718
+ state: HandlerState,
719
+ raw: RawSpellEffect,
720
+ _slot: number,
721
+ _effectType: number,
722
+ ): void {
723
+ const { min } = effectAmountRange(raw, state.ctx);
724
+ // AddStealthStrength(StealthType(misc), ±amount). Cite: :2623.
725
+ // Bake: Math.max(0, min). Cite: map-spell-effects.mjs:1078.
726
+ state.effects.push({
727
+ kind: 'stealth_level',
728
+ amount: Math.max(0, min),
729
+ });
730
+ }
731
+
732
+ // ── SPELL_AURA_BIND_SIGHT (1) ───────────────────────────────────────────── Cite: SpellAuras.cpp:2126–2136
733
+ // HandleBindSight Bake empty. (Distinct from SPELL_EFFECT_BIND_SIGHT EffectNULL.)
734
+ export function handleAuraBindSight(
735
+ state: HandlerState,
736
+ _raw: RawSpellEffect,
737
+ _slot: number,
738
+ _effectType: number,
739
+ ): void {
740
+ // C++: caster must be player. Cite: :2128–2129.
741
+ if (state.ctx.casterIsPlayer === false) return;
742
+ // apply → camera.SetView(target); remove → ResetView. Cite: :2133–2136.
743
+ const dur = durationMsResolved(state);
744
+ state.intents.push({ kind: 'bind_sight', durationMs: dur });
745
+ // Player-visible channel chip (no multi-session camera). Cite: schema bind_sight; KI-187.
746
+ state.effects.push({ kind: 'bind_sight', durationMs: dur });
747
+ state.role = state.role || 'buff';
748
+ }
749
+
750
+ // ── SPELL_AURA_MOD_POWER_COST_SCHOOL (73) ───────────────────────────────── Cite: SpellAuras.cpp:4208–4216
751
+ // HandleModPowerCost Bake empty.
752
+ export function handleModPowerCost(
753
+ state: HandlerState,
754
+ raw: RawSpellEffect,
755
+ _slot: number,
756
+ _effectType: number,
757
+ ): void {
758
+ // C++: if (!Real) return. Cite: :4210–4211.
759
+ const { min } = effectAmountRange(raw, state.ctx);
760
+ const dur = durationMsResolved(state);
761
+ // Per school bit in misc: ApplyModInt32Value(POWER_COST_MODIFIER+i, amount).
762
+ // Cite: :4214–4216.
763
+ const schoolMask = raw.miscValue | 0;
764
+ state.intents.push({
765
+ kind: 'mod_power_cost_school',
766
+ schoolMask,
767
+ amount: min,
768
+ durationMs: dur,
769
+ });
770
+ // The intent had no consumer, so the Focus set bonuses and Burst of Knowledge / Insight
771
+ // changed no cast cost at all. `power_cost` is read in spellCost.
772
+ if (min !== 0) {
773
+ state.effects.push({
774
+ kind: 'buff',
775
+ mod: 'power_cost',
776
+ amount: min,
777
+ durationMs: dur,
778
+ hostile: min > 0,
779
+ ...schoolScope(schoolMask),
780
+ });
781
+ state.role = state.role || 'buff';
782
+ }
783
+ }
784
+
785
+ // A single-bit school mask narrows a cost buff to that school; a multi-bit or empty mask means every
786
+ // school, which is what applyBuffMod does with no school named. Cite: SpellAuras.cpp:4199-4216.
787
+ function schoolScope(schoolMask: number): { school?: School } {
788
+ const school = schoolFromSingleBitMask(schoolMask);
789
+ return school ? { school } : {};
790
+ }
791
+
792
+ // ── SPELL_AURA_FAR_SIGHT (76) ───────────────────────────────────────────── Cite: SpellAuras.cpp:2139–2149
793
+ // HandleFarSight Bake empty. Same camera body as BIND_SIGHT.
794
+ export function handleAuraFarSight(
795
+ state: HandlerState,
796
+ _raw: RawSpellEffect,
797
+ _slot: number,
798
+ _effectType: number,
799
+ ): void {
800
+ // C++: caster must be player. Cite: :2141–2142.
801
+ if (state.ctx.casterIsPlayer === false) return;
802
+ // apply → camera.SetView(target); remove → ResetView. Cite: :2146–2149.
803
+ const dur = durationMsResolved(state);
804
+ state.intents.push({ kind: 'far_sight', durationMs: dur });
805
+ }
806
+
807
+ // ── SPELL_AURA_SPLIT_DAMAGE_PCT (81) ── a percent of the remaining damage is redirected.
808
+ // Cite: SpellAuras.cpp:142; Unit.cpp:2539-2570 CalculateAbsorbAndResist.
809
+ export function handleSplitDamagePct(
810
+ state: HandlerState,
811
+ raw: RawSpellEffect,
812
+ _slot: number,
813
+ _effectType: number,
814
+ ): void {
815
+ const { min } = effectAmountRange(raw, state.ctx);
816
+ const dur = durationMsResolved(state);
817
+ // The split is the remaining damage times the amount over 100, gated on the school mask and on a
818
+ // living linked caster, which is a runtime check. Cite: Unit.cpp:2545-2553.
819
+ state.effects.push({
820
+ kind: 'split_damage',
821
+ pct: Math.max(1, min),
822
+ schoolMask: raw.miscValue | 0,
823
+ durationMs: dur,
824
+ });
825
+ state.role = state.role || 'buff';
826
+ }
827
+
828
+ // ── SPELL_AURA_MOD_UNATTACKABLE (93) ────────────────────────────────────── Cite: SpellAuras.cpp:4454–4459
829
+ // HandleModUnattackable Bake empty.
830
+ export function handleModUnattackable(
831
+ state: HandlerState,
832
+ _raw: RawSpellEffect,
833
+ _slot: number,
834
+ _effectType: number,
835
+ ): void {
836
+ // Real && Apply → CombatStop(). Cite: :4456–4457.
837
+ // ApplyModFlag(UNIT_FLAG_UNTARGETABLE, apply). Cite: :4459.
838
+ const dur = durationMsResolved(state);
839
+ state.intents.push({
840
+ kind: 'mod_unattackable',
841
+ durationMs: dur,
842
+ combatStopOnApply: true,
843
+ });
844
+ // Phase Shift (Imp): catalog surface so Grimoire teach is not a pure no-op. Cite: KI-490.
845
+ if (!state.effects.some((e) => e.kind === 'mod_unattackable')) {
846
+ state.effects.push({
847
+ kind: 'mod_unattackable',
848
+ durationMs: dur < 0 ? 0 : dur,
849
+ combatStopOnApply: true,
850
+ });
851
+ }
852
+ state.role = state.role || 'buff';
853
+ }
854
+
855
+ /** Enrage (5229) / Bloodrage (29131) SetInDummyCombatState. Cite: SpellAuras.cpp:5116–5119. */
856
+ export const INTERRUPT_REGEN_DUMMY_COMBAT_IDS = new Set([5229, 29131]);
857
+
858
+ // ── SPELL_AURA_INTERRUPT_REGEN (94) ───────────────────────────────────────
859
+ // Cite: SpellAuras.cpp:5111–5119 HandleInterruptRegen; Player.cpp:2303–2304 HasAuraType.
860
+ export function handleInterruptRegen(
861
+ state: HandlerState,
862
+ _raw: RawSpellEffect,
863
+ _slot: number,
864
+ _effectType: number,
865
+ ): void {
866
+ // C++: if (!Real) return. Cite: :5113–5114.
867
+ const dur = durationMsResolved(state);
868
+ const dummy = INTERRUPT_REGEN_DUMMY_COMBAT_IDS.has(state.spell.id | 0);
869
+ const intent: InterpretIntent = { kind: 'interrupt_regen', durationMs: dur };
870
+ if (dummy) intent.setInDummyCombatState = true;
871
+ state.intents.push(intent);
872
+ if (!state.effects.some((e) => e.kind === 'interrupt_regen')) {
873
+ state.effects.push({
874
+ kind: 'interrupt_regen',
875
+ durationMs: dur < 0 ? 0 : dur,
876
+ ...(dummy ? { setInDummyCombatState: true as const } : {}),
877
+ });
878
+ }
879
+ state.role = state.role || 'buff';
880
+ }
881
+
882
+ // ── SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT (126) ── emitted as physical_taken_pct, shared with aura 87.
883
+ // Cite: SpellAuras.cpp:187; Unit.cpp:7634 MeleeDamageBonusTaken.
884
+ export function handleModMeleeDamageTakenPct(
885
+ state: HandlerState,
886
+ raw: RawSpellEffect,
887
+ _slot: number,
888
+ _effectType: number,
889
+ ): void {
890
+ const { min } = effectAmountRange(raw, state.ctx);
891
+ const dur = durationMsResolved(state);
892
+ // GetTotalAuraMultiplier product of (100+amount)/100. Cite: Unit.cpp:7634.
893
+ // Surface: signed whole-percent on physical_taken_pct (Shadowform −20).
894
+ const tagged = withHostile(
895
+ { kind: 'buff' as const, mod: 'physical_taken_pct' as const, amount: min, durationMs: dur },
896
+ raw.targetA | 0,
897
+ min,
898
+ );
899
+ state.effects.push(tagged as SpellEffect);
900
+ state.role = state.role || 'buff';
901
+ }
902
+
903
+ // ── SPELL_AURA_MOD_SPEED_ALWAYS (129) ── the same body as aura 31, but it stacks as a product on the
904
+ // run rate whether mounted or not. Cite: SpellAuras.cpp:190; Unit.cpp UpdateSpeed.
905
+ export function handleModSpeedAlways(
906
+ state: HandlerState,
907
+ raw: RawSpellEffect,
908
+ _slot: number,
909
+ _effectType: number,
910
+ ): void {
911
+ // C++ requires Real. Cite: :2882–2884.
912
+ const { min } = effectAmountRange(raw, state.ctx);
913
+ const dur = durationMsResolved(state);
914
+ const tagged = withHostile(
915
+ {
916
+ kind: 'speed' as const,
917
+ aura: SPELL_AURA_MOD_SPEED_ALWAYS,
918
+ pct: min,
919
+ durationMs: dur,
920
+ },
921
+ raw.targetA | 0,
922
+ min,
923
+ );
924
+ state.effects.push(tagged as SpellEffect);
925
+ state.role = state.role || 'buff';
926
+ }
927
+
928
+ // ── SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED (191) ────────────────────────────
929
+ // Cite: SpellAuras.cpp:2920–2930 HandleAuraModUseNormalSpeed → UpdateSpeed RUN/SWIM.
930
+ export function handleAuraUseNormalMovementSpeed(
931
+ state: HandlerState,
932
+ raw: RawSpellEffect,
933
+ _slot: number,
934
+ _effectType: number,
935
+ ): void {
936
+ const { min } = effectAmountRange(raw, state.ctx);
937
+ const dur = durationMsResolved(state);
938
+ const tagged = withHostile(
939
+ {
940
+ kind: 'speed' as const,
941
+ aura: SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED,
942
+ pct: min,
943
+ durationMs: dur,
944
+ },
945
+ raw.targetA | 0,
946
+ min,
947
+ );
948
+ state.effects.push(tagged as SpellEffect);
949
+ state.role = state.role || 'buff';
950
+ }
951
+
952
+ // ── SPELL_AURA_RESIST_PUSHBACK (149) ── empty in the bake; the C++ applies it to cast and channel
953
+ // delay. Cite: SpellAuras.cpp:210; Spell.cpp:6817-6820 Delayed, :6849-6852 DelayedChannel.
954
+ export function handleResistPushback(
955
+ state: HandlerState,
956
+ raw: RawSpellEffect,
957
+ _slot: number,
958
+ _effectType: number,
959
+ ): void {
960
+ const { min } = effectAmountRange(raw, state.ctx);
961
+ const dur = durationMsResolved(state);
962
+ // resistChance starts 100; spellmod; then += GetTotalAuraModifier − 100.
963
+ // Cite: Spell.cpp:6817–6819. Presence of aura amount alone drives chance.
964
+ state.intents.push({
965
+ kind: 'resist_pushback',
966
+ amount: min,
967
+ durationMs: dur,
968
+ });
969
+ state.role = state.role || 'buff';
970
+ }
971
+
972
+ // ── SPELL_AURA_SPLIT_DAMAGE_FLAT (153) ── empty in the bake; a flat share is redirected.
973
+ // Cite: SpellAuras.cpp:214; Unit.cpp:2501-2537 CalculateAbsorbAndResist.
974
+ export function handleSplitDamageFlat(
975
+ state: HandlerState,
976
+ raw: RawSpellEffect,
977
+ _slot: number,
978
+ _effectType: number,
979
+ ): void {
980
+ const { min } = effectAmountRange(raw, state.ctx);
981
+ const dur = durationMsResolved(state);
982
+ // currentAbsorb = min(remaining, amount). Cite: Unit.cpp:2516–2519.
983
+ // School mask + alive linked caster gates. Cite: :2507–2513 — SI5 runtime.
984
+ state.intents.push({
985
+ kind: 'split_damage_flat',
986
+ amount: min,
987
+ schoolMask: raw.miscValue | 0,
988
+ durationMs: dur,
989
+ });
990
+ state.role = state.role || 'buff';
991
+ }
992
+
993
+ // ── SPELL_AURA_POWER_BURN_MANA (162) ── empty in the bake; the tick burns power and deals it back as
994
+ // damage. Cite: SpellAuras.cpp:3124-3126 HandleAuraPowerBurn; PeriodicTick :4892-4946.
995
+ export function handlePowerBurnMana(
996
+ state: HandlerState,
997
+ raw: RawSpellEffect,
998
+ _slot: number,
999
+ _effectType: number,
1000
+ ): void {
1001
+ // Handler body only arms m_isPeriodic. Cite: :3125–3126.
1002
+ const { min } = effectAmountRange(raw, state.ctx);
1003
+ const dur = durationMsResolved(state);
1004
+ // The burn is capped at the amount, the power type must match the target, and the damage dealt is
1005
+ // the burn times the effect's multiple value. Cite: SpellAuras.cpp:4902-4943.
1006
+ const multRaw = Number(raw.multipleValue);
1007
+ // C++ multiplies by EffectMultipleValue as-is (0 → 0 damage). Cite: :4922.
1008
+ const multiplier = Number.isFinite(multRaw) ? multRaw : 0;
1009
+ state.intents.push({
1010
+ kind: 'power_burn_mana',
1011
+ powerType: raw.miscValue | 0,
1012
+ amountPerTick: Math.max(0, min),
1013
+ tickMs: (raw.amplitude | 0) || 1000,
1014
+ multiplier,
1015
+ durationMs: dur,
1016
+ });
1017
+ // Periodic mana burn → school damage: ACTIVE dot role (not invalid 'damage'). Cite: roles.ts.
1018
+ state.role = state.role || 'dot';
1019
+ }
1020
+
1021
+ // ── SPELL_AURA_MOD_DAMAGE_DONE_VERSUS (168) ── empty in the bake; a multiplier by creature type mask.
1022
+ // Cite: SpellAuras.cpp:229; Unit.cpp:7058 SpellDamageBonusDone, :7503 MeleeDamageBonusDone.
1023
+ export function handleModDamageDoneVersus(
1024
+ state: HandlerState,
1025
+ raw: RawSpellEffect,
1026
+ _slot: number,
1027
+ _effectType: number,
1028
+ ): void {
1029
+ const { min } = effectAmountRange(raw, state.ctx);
1030
+ const dur = durationMsResolved(state);
1031
+ // An intent alone was dead: nothing read that kind, so all eight Echoes of Lordaeron ranks resolved
1032
+ // to zero effects. Emit the buff row combat actually consumes.
1033
+ const mask = raw.miscValue | 0;
1034
+ if (mask) {
1035
+ state.effects.push({
1036
+ kind: 'buff',
1037
+ mod: 'damage_done_versus_pct',
1038
+ amount: min,
1039
+ creatureTypeMask: mask,
1040
+ durationMs: dur,
1041
+ hostile: false,
1042
+ } as SpellEffect);
1043
+ }
1044
+ state.intents.push({
1045
+ kind: 'mod_damage_done_versus',
1046
+ creatureTypeMask: mask,
1047
+ amount: min,
1048
+ durationMs: dur,
1049
+ });
1050
+ state.role = state.role || 'buff';
1051
+ }
1052
+
1053
+ // Dead-talent gap: seven auras a shipped talent carries. Each is a no-immediate-effect or a stat
1054
+ // modifier in C++, so the ROW is the behaviour and an intent alone would be dead here.
1055
+
1056
+ // SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT (122) - Dual Wield Specialization. Cite: SpellAuras.cpp:4175-4184
1057
+ // HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT).
1058
+ export function handleModOffhandDamagePercent(
1059
+ state: HandlerState,
1060
+ raw: RawSpellEffect,
1061
+ _slot: number,
1062
+ _effectType: number,
1063
+ ): void {
1064
+ const { min } = effectAmountRange(raw, state.ctx);
1065
+ if (!min) return;
1066
+ state.effects.push({
1067
+ kind: 'buff',
1068
+ mod: 'offhand_damage_pct' as BuffMod,
1069
+ amount: min,
1070
+ durationMs: durationMsResolved(state),
1071
+ hostile: false,
1072
+ } as SpellEffect);
1073
+ state.role = state.role || 'buff';
1074
+ }
1075
+
1076
+ // SPELL_AURA_MOD_CRIT_PERCENT_VERSUS (169) - Monster / Humanoid Slaying crit multiplier. Cite:
1077
+ // Unit.cpp:3555-3563 GetCritMultiplier bonus += ...ByMiscMask(169, creatureTypeMask).
1078
+ export function handleModCritPercentVersus(
1079
+ state: HandlerState,
1080
+ raw: RawSpellEffect,
1081
+ _slot: number,
1082
+ _effectType: number,
1083
+ ): void {
1084
+ const mask = raw.miscValue | 0;
1085
+ const { min } = effectAmountRange(raw, state.ctx);
1086
+ if (!mask || !min) return;
1087
+ state.effects.push({
1088
+ kind: 'buff',
1089
+ mod: 'crit_damage_versus_pct' as BuffMod,
1090
+ amount: min,
1091
+ creatureTypeMask: mask,
1092
+ durationMs: durationMsResolved(state),
1093
+ hostile: false,
1094
+ } as SpellEffect);
1095
+ state.role = state.role || 'buff';
1096
+ }
1097
+
1098
+ // MOD_RESISTANCE_OF_STAT_PERCENT (182), Arcane Resilience's armor from intellect. The C++ supports the
1099
+ // physical school only and logs an error otherwise, so an unsupported mask emits nothing.
1100
+ export function handleModResistanceOfStatPercent(
1101
+ state: HandlerState,
1102
+ raw: RawSpellEffect,
1103
+ _slot: number,
1104
+ _effectType: number,
1105
+ ): void {
1106
+ const mask = raw.miscValue | 0;
1107
+ const { min } = effectAmountRange(raw, state.ctx);
1108
+ if (!min || !(mask & 1)) return;
1109
+ state.effects.push({
1110
+ kind: 'buff',
1111
+ mod: 'armor_from_intellect_pct' as BuffMod,
1112
+ amount: min,
1113
+ durationMs: durationMsResolved(state),
1114
+ hostile: false,
1115
+ } as SpellEffect);
1116
+ state.role = state.role || 'buff';
1117
+ }
1118
+
1119
+ /** Victim-side attacker-chance auras (185-188). The amount is signed and used as-is. */
1120
+ function attackerChanceAura(state: HandlerState, raw: RawSpellEffect, mod: BuffMod): void {
1121
+ const { min } = effectAmountRange(raw, state.ctx);
1122
+ if (!min) return;
1123
+ const mask = raw.miscValue | 0;
1124
+ state.effects.push({
1125
+ kind: 'buff',
1126
+ mod,
1127
+ amount: min,
1128
+ ...(mask ? { schoolMask: mask } : {}),
1129
+ durationMs: durationMsResolved(state),
1130
+ hostile: false,
1131
+ } as SpellEffect);
1132
+ state.role = state.role || 'buff';
1133
+ }
1134
+
1135
+ /** 185. Cite: Unit.cpp:3794 CalculateEffectiveMissChance victim modifier. */
1136
+ export function handleModAttackerRangedHitChance(
1137
+ state: HandlerState, raw: RawSpellEffect, _slot: number, _effectType: number,
1138
+ ): void {
1139
+ attackerChanceAura(state, raw, 'attacker_ranged_hit' as BuffMod);
1140
+ }
1141
+
1142
+ /** 186. Cite: Unit.cpp:3873-3874 MagicSpellHitResult victim modifier (school mask). */
1143
+ export function handleModAttackerSpellHitChance(
1144
+ state: HandlerState, raw: RawSpellEffect, _slot: number, _effectType: number,
1145
+ ): void {
1146
+ attackerChanceAura(state, raw, 'attacker_spell_hit' as BuffMod);
1147
+ }
1148
+
1149
+ /** 187. Cite: Unit.cpp:3523-3525 GetCritTakenChance MELEE. */
1150
+ export function handleModAttackerMeleeCritChance(
1151
+ state: HandlerState, raw: RawSpellEffect, _slot: number, _effectType: number,
1152
+ ): void {
1153
+ attackerChanceAura(state, raw, 'attacker_melee_crit' as BuffMod);
1154
+ }
1155
+
1156
+ /** 188. Cite: Unit.cpp:3526-3528 GetCritTakenChance RANGED. */
1157
+ export function handleModAttackerRangedCritChance(
1158
+ state: HandlerState, raw: RawSpellEffect, _slot: number, _effectType: number,
1159
+ ): void {
1160
+ attackerChanceAura(state, raw, 'attacker_ranged_crit' as BuffMod);
1161
+ }
1162
+
1163
+ // SPELL_AURA_MOD_DAMAGE_DONE_CREATURE (59): flat damage vs a creature-type mask.
1164
+ // Cite: Unit.cpp:7061 SpellDamageBonusDone; :7465 MeleeDamageBonusDone.
1165
+ export function handleModDamageDoneCreature(
1166
+ state: HandlerState,
1167
+ raw: RawSpellEffect,
1168
+ _slot: number,
1169
+ _effectType: number,
1170
+ ): void {
1171
+ const { min } = effectAmountRange(raw, state.ctx);
1172
+ const dur = durationMsResolved(state);
1173
+ const mask = raw.miscValue | 0;
1174
+ if (mask) {
1175
+ state.effects.push({
1176
+ kind: 'buff',
1177
+ mod: 'damage_done_creature',
1178
+ amount: min,
1179
+ creatureTypeMask: mask,
1180
+ durationMs: dur,
1181
+ hostile: false,
1182
+ } as SpellEffect);
1183
+ }
1184
+ state.intents.push({
1185
+ kind: 'mod_damage_done_creature',
1186
+ creatureTypeMask: mask,
1187
+ amount: min,
1188
+ durationMs: dur,
1189
+ });
1190
+ state.role = state.role || 'buff';
1191
+ }
1192
+
1193
+ // SPELL_AURA_MOD_INCREASE_ENERGY (35) → handlers/mod-increase-energy.ts (KI-907 peel).
1194
+
1195
+ // ── SI3 aura batch 13 (this claim list) ────────────────────────────────────
1196
+
1197
+ // ── SPELL_AURA_PERIODIC_MANA_FUNNEL (63) ── unused in the C++ and empty in the bake; the obsolete
1198
+ // Mana Funnel row still carries it. Cite: SpellAuras.h:279-282 HandleUnused.
1199
+ export function handlePeriodicManaFunnel(
1200
+ state: HandlerState,
1201
+ _raw: RawSpellEffect,
1202
+ _slot: number,
1203
+ _effectType: number,
1204
+ ): void {
1205
+ // C++ body empty: "NOT USED BY ANY SPELL OR USELESS". Cite: SpellAuras.h:279–282.
1206
+ state.intents.push({ kind: 'periodic_mana_funnel_unused' });
1207
+ }
1208
+
1209
+ // ── SPELL_AURA_FEIGN_DEATH (66) ─────────────────────────────────────────── Cite: SpellAuras.cpp:2382–2424
1210
+ // HandleFeignDeath; Unit.cpp:10083–10140 SetFeignDeath. Bake empty.
1211
+ export function handleFeignDeath(
1212
+ state: HandlerState,
1213
+ _raw: RawSpellEffect,
1214
+ _slot: number,
1215
+ _effectType: number,
1216
+ ): void {
1217
+ // C++: if (!Real) return. Cite: :2384–2385.
1218
+ // Remove while another FEIGN_DEATH remains → no-op. Cite: :2389–2391 — SI5 runtime.
1219
+ const dur = durationMsResolved(state);
1220
+ const intent: InterpretIntent = {
1221
+ kind: 'feign_death',
1222
+ durationMs: dur,
1223
+ };
1224
+ // For a player-controlled target, the highest miss chance among NPC attackers is rolled against, and
1225
+ // only a success interrupts the spells cast on them. Cite: SpellAuras.cpp:2390-2416.
1226
+ if (state.ctx.unitTargetPlayerControlled === true) {
1227
+ intent.playerControlledResistRoll = true;
1228
+ }
1229
+ state.intents.push(intent);
1230
+ // The hate wipe is what this aura DOES: it was gated on one spell id, so Torpor, Fake Death and
1231
+ // Play Dead emitted nothing. Wipe current hate, then generate none for the duration.
1232
+ state.effects.push(
1233
+ { kind: 'modify_threat_pct', pct: -100 },
1234
+ { kind: 'buff', mod: 'threat_mod', amount: -100, durationMs: dur, hostile: false },
1235
+ {
1236
+ kind: 'feign_death',
1237
+ durationMs: dur,
1238
+ ...(intent.playerControlledResistRoll ? { playerControlledResistRoll: true } : {}),
1239
+ },
1240
+ );
1241
+ state.role = state.role || 'buff';
1242
+ }
1243
+
1244
+ // ── SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT (72) ───────────────────────────── Cite: SpellAuras.cpp:4190–4204
1245
+ // HandleModPowerCostPCT Bake empty. Use site: Spell.cpp:6368 powerCost × (1 + POWER_COST_MULTIPLIER).
1246
+
1247
+ /** Expire-cast special on spell 30422 (not Classic 1.12 content). Cite: :4202–4204. */
1248
+ export const MOD_POWER_COST_PCT_EXPIRE_CAST: ReadonlyMap<number, number> = new Map([
1249
+ [30422, 38638],
1250
+ ]);
1251
+
1252
+ export function handleModPowerCostPct(
1253
+ state: HandlerState,
1254
+ raw: RawSpellEffect,
1255
+ _slot: number,
1256
+ _effectType: number,
1257
+ ): void {
1258
+ // C++: if (!Real) return. Cite: :4192–4193.
1259
+ const { min } = effectAmountRange(raw, state.ctx);
1260
+ const dur = durationMsResolved(state);
1261
+ // amount/100 written to UNIT_FIELD_POWER_COST_MULTIPLIER+school. Cite: :4197–4200.
1262
+ const intent: InterpretIntent = {
1263
+ kind: 'mod_power_cost_school_pct',
1264
+ schoolMask: raw.miscValue | 0,
1265
+ amount: min,
1266
+ durationMs: dur,
1267
+ };
1268
+ // Expire remove → CastSpell(38638) for id 30422. Cite: :4202–4204.
1269
+ const expireCast = MOD_POWER_COST_PCT_EXPIRE_CAST.get(state.spell.id | 0);
1270
+ if (expireCast != null) intent.expireCastSpellId = expireCast;
1271
+ state.intents.push(intent);
1272
+ // Unread intent → Lucifron's Curse charged normal mana. `power_cost_pct` is read in spellCost.
1273
+ if (min !== 0) {
1274
+ state.effects.push({
1275
+ kind: 'buff',
1276
+ mod: 'power_cost_pct',
1277
+ amount: min,
1278
+ durationMs: dur,
1279
+ hostile: min > 0,
1280
+ ...schoolScope(raw.miscValue | 0),
1281
+ });
1282
+ }
1283
+ state.role = state.role || 'buff';
1284
+ }
1285
+
1286
+ // ── SPELL_AURA_MOD_PERCENT_STAT (80) ── a BASE percent, unlike 137's total, so there is no stamina
1287
+ // health rescale. Cite: SpellAuras.cpp:3489-3505 HandleModPercentStat.
1288
+ export function handleModPercentStat(
1289
+ state: HandlerState,
1290
+ raw: RawSpellEffect,
1291
+ slot: number,
1292
+ effectType: number,
1293
+ ): void {
1294
+ const misc = raw.miscValue | 0;
1295
+ // C++: misc < −1 || > 4 → error return. Cite: :3491–3495.
1296
+ if (misc < -1 || misc > 4) {
1297
+ state.unhandled.push({
1298
+ slot,
1299
+ effect: effectType,
1300
+ auraName: SPELL_AURA_MOD_PERCENT_STAT,
1301
+ reason: `MOD_PERCENT_STAT miscValue ${misc} out of range [-1,4]`,
1302
+ });
1303
+ return;
1304
+ }
1305
+ // only players have base stats. Cite: :3498–3500.
1306
+ if (state.ctx.unitTargetIsPlayer === false) return;
1307
+
1308
+ const { min } = effectAmountRange(raw, state.ctx);
1309
+ const dur = durationMsResolved(state);
1310
+ // A misc value of -1 means all five stats. Always the percent name, never the flat one — see
1311
+ // STAT_MOD_PCT. Cite: SpellAuras.cpp:3501-3504.
1312
+ const mod: BuffMod = STAT_MOD_PCT[String(misc)] ?? 'all_stats_pct';
1313
+ const tagged = withHostile(
1314
+ { kind: 'buff' as const, mod, amount: min, durationMs: dur },
1315
+ raw.targetA | 0,
1316
+ min,
1317
+ );
1318
+ state.effects.push(tagged as SpellEffect);
1319
+ state.role = state.role || 'buff';
1320
+ }
1321
+
1322
+ // ── SPELL_AURA_GHOST (95) ───────────────────────────────────────────────── Cite: SpellAuras.cpp:4396–4420
1323
+ // HandleAuraGhost Bake empty.
1324
+ export function handleAuraGhost(
1325
+ state: HandlerState,
1326
+ _raw: RawSpellEffect,
1327
+ _slot: number,
1328
+ _effectType: number,
1329
+ ): void {
1330
+ // SetVisFlags(UNIT_VIS_FLAG_GHOST); player PLAYER_FLAGS_GHOST + water-walk.
1331
+ // Cite: :4401–4408 apply / :4411–4418 remove.
1332
+ const dur = durationMsResolved(state);
1333
+ state.intents.push({
1334
+ kind: 'ghost',
1335
+ durationMs: dur,
1336
+ setWaterWalkUnlessWaterWalkAura: true,
1337
+ });
1338
+ state.role = state.role || 'buff';
1339
+ }
1340
+
1341
+ // ── SPELL_AURA_SPELL_MAGNET (96) ── baked as a magnet, which redirects a harmful single-target spell.
1342
+ // Cite: SpellAuras.cpp:157; Unit.cpp:6894-6919 SelectMagnetTarget.
1343
+ export function handleSpellMagnet(
1344
+ state: HandlerState,
1345
+ _raw: RawSpellEffect,
1346
+ _slot: number,
1347
+ _effectType: number,
1348
+ ): void {
1349
+ const dur = durationMsResolved(state);
1350
+ // Magic/none DmgClass; skip ABILITY / NO_REDIRECTION / NO_IMMUNITIES. Alive magnet caster + CanAttack →
1351
+ // UseMagnet() + redirect target. Cite: Unit.cpp:6899–6916.
1352
+ state.intents.push({ kind: 'spell_magnet', durationMs: dur });
1353
+ state.role = state.role || 'buff';
1354
+ }
1355
+
1356
+ // ── SPELL_AURA_AURAS_VISIBLE (100) ──────────────────────────────────────── Cite: SpellAuras.cpp:3383–3385
1357
+ // HandleAurasVisible Bake empty.
1358
+ export function handleAurasVisible(
1359
+ state: HandlerState,
1360
+ _raw: RawSpellEffect,
1361
+ _slot: number,
1362
+ _effectType: number,
1363
+ ): void {
1364
+ // ApplyModFlag(UNIT_FLAG_AURAS_VISIBLE, apply). Cite: :3385.
1365
+ const dur = durationMsResolved(state);
1366
+ state.intents.push({ kind: 'auras_visible', durationMs: dur });
1367
+ // Detect Magic catalog / OOC aura surface. Cite: schema auras_visible; KI-124.
1368
+ state.effects.push({ kind: 'auras_visible', durationMs: dur });
1369
+ state.role = state.role || 'buff';
1370
+ }
1371
+
1372
+ // SPELL_AURA_HOVER (106). Cite: SpellAuras.cpp:1681–1688 HandleAuraHover; Unit.cpp:12428 SetHover.
1373
+ export function handleAuraHover(
1374
+ state: HandlerState,
1375
+ _raw: RawSpellEffect,
1376
+ _slot: number,
1377
+ _effectType: number,
1378
+ ): void {
1379
+ // C++: if (!Real) return; SetHover(apply). Cite: :1683–1687.
1380
+ const dur = durationMsResolved(state);
1381
+ state.intents.push({ kind: 'hover', durationMs: dur });
1382
+ if (!state.effects.some((e) => e.kind === 'hover')) {
1383
+ state.effects.push({ kind: 'hover', durationMs: dur < 0 ? 0 : dur });
1384
+ }
1385
+ state.role = state.role || 'buff';
1386
+ }
1387
+
1388
+ // ── SPELL_AURA_MOD_REGEN_DURING_COMBAT (116) ── health regen that keeps running in combat.
1389
+ // Cite: SpellAuras.cpp:177; Player.cpp:2297-2299 RegenerateAll, :2390-2400 RegenerateHealth.
1390
+ export function handleModRegenDuringCombat(
1391
+ state: HandlerState,
1392
+ raw: RawSpellEffect,
1393
+ _slot: number,
1394
+ _effectType: number,
1395
+ ): void {
1396
+ const { min } = effectAmountRange(raw, state.ctx);
1397
+ const dur = durationMsResolved(state);
1398
+ // In combat + HasAuraType(116) → spirit HP regen; ×= amount/100. Cite: :2399–2400.
1399
+ state.intents.push({
1400
+ kind: 'mod_regen_during_combat',
1401
+ amount: min,
1402
+ durationMs: dur,
1403
+ });
1404
+ // Catalog surface (fillEmptyEffectsFromRaw) needs effects[], not intents alone.
1405
+ state.effects.push({
1406
+ kind: 'mod_regen_during_combat',
1407
+ amount: min,
1408
+ durationMs: dur,
1409
+ } as never);
1410
+ state.role = state.role || 'buff';
1411
+ }
1412
+
1413
+ // ── SPELL_AURA_UNTRACKABLE (120) ────────────────────────────────────────── Cite: SpellAuras.cpp:4374–4379
1414
+ // HandleAuraUntrackable Bake empty.
1415
+ export function handleAuraUntrackable(
1416
+ state: HandlerState,
1417
+ _raw: RawSpellEffect,
1418
+ _slot: number,
1419
+ _effectType: number,
1420
+ ): void {
1421
+ // apply SetVisFlags(UNIT_VIS_FLAG_UNTRACKABLE); else RemoveVisFlags. Cite: :4376–4379.
1422
+ const dur = durationMsResolved(state);
1423
+ state.intents.push({ kind: 'untrackable', durationMs: dur });
1424
+ state.role = state.role || 'buff';
1425
+ }
1426
+
1427
+ // SharedDefines.h CREATURE_TYPE_BEAST = 1. Cite: SharedDefines.h:1141.
1428
+
1429
+ export const CREATURE_TYPE_BEAST = 1;
1430
+
1431
+ // ── SPELL_AURA_EMPATHY (121) ────────────────────────────────────────────── Cite: SpellAuras.cpp:4351–4371
1432
+ // HandleAuraEmpathy Bake empty. Beast Lore 1462.
1433
+ export function handleAuraEmpathy(
1434
+ state: HandlerState,
1435
+ _raw: RawSpellEffect,
1436
+ _slot: number,
1437
+ _effectType: number,
1438
+ ): void {
1439
+ // Player or (unit + CREATURE_TYPE_BEAST) → UNIT_DYNFLAG_SPECIALINFO. Cite: :4355–4357.
1440
+ // Bake-thin: omit gates → eligible (emit applySpecialInfo).
1441
+ let applySpecialInfo = true;
1442
+ if (state.ctx.unitTargetIsPlayer === false) {
1443
+ // Non-player: only beasts. Cite: :4356–4357.
1444
+ if (
1445
+ state.ctx.unitTargetCreatureType != null
1446
+ && state.ctx.unitTargetCreatureType !== CREATURE_TYPE_BEAST
1447
+ ) {
1448
+ applySpecialInfo = false;
1449
+ }
1450
+ }
1451
+ // apply + player caster → BuildValuesUpdateBlockForPlayerWithFlags. Cite: :4359–4369.
1452
+ // Bake-thin omit casterIsPlayer → player path.
1453
+ const sendSpecialInfoUpdate = state.ctx.casterIsPlayer !== false;
1454
+
1455
+ const dur = durationMsResolved(state);
1456
+ const intent: InterpretIntent = {
1457
+ kind: 'empathy',
1458
+ durationMs: dur,
1459
+ applySpecialInfo,
1460
+ };
1461
+ if (sendSpecialInfoUpdate) intent.sendSpecialInfoUpdate = true;
1462
+ state.intents.push(intent);
1463
+ state.role = state.role || 'buff';
1464
+ }
1465
+
1466
+ // ── SPELL_AURA_MOD_POSSESS_PET (128) ── Eyes of the Beast possesses your OWN pet's vision, not an
1467
+ // enemy: emitting a control effect put it in the combat kit and incapacitated the fight target.
1468
+ export function handleModPossessPet(
1469
+ state: HandlerState,
1470
+ raw: RawSpellEffect,
1471
+ _slot: number,
1472
+ _effectType: number,
1473
+ ): void {
1474
+ // C++: if (!Real) return. Cite: :2260–2261. Non-player caster → return. Cite: :2263–2264. Bake-thin: omit
1475
+ // casterIsPlayer → player path (emit).
1476
+ if (state.ctx.casterIsPlayer === false) return;
1477
+ // Target must be unit pet. Cite: :2266–2267.
1478
+ // Bake-thin: omit unitTargetIsPet → assume pet (emit).
1479
+ if (state.ctx.unitTargetIsPet === false) return;
1480
+
1481
+ const dur = durationMsResolved(state);
1482
+ // An intent plus a play-surface effect, the bind-sight pattern. No control kind, because this is
1483
+ // not enemy control. Cite: SpellAuras.cpp:2269-2278.
1484
+ const durationMs = dur || 10_000;
1485
+ state.intents.push({
1486
+ kind: 'mod_possess_pet',
1487
+ spellId: state.spell.id | 0,
1488
+ durationMs,
1489
+ breakOutgoing: true,
1490
+ });
1491
+ state.effects.push({
1492
+ kind: 'mod_possess_pet',
1493
+ spellId: state.spell.id | 0,
1494
+ durationMs,
1495
+ } as never);
1496
+ // Pet vision utility — never combat control (KI-097 residual).
1497
+ state.role = state.role || 'utility';
1498
+ }
1499
+
1500
+ // ── SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS (130) ── the mounted run rate, stacking as a product while
1501
+ // mounted. Cite: SpellAuras.cpp:2889-2895; Unit.cpp:8340.
1502
+ export function handleModMountedSpeedAlways(
1503
+ state: HandlerState,
1504
+ raw: RawSpellEffect,
1505
+ _slot: number,
1506
+ _effectType: number,
1507
+ ): void {
1508
+ // C++ requires Real. Cite: :2891–2893.
1509
+ const { min } = effectAmountRange(raw, state.ctx);
1510
+ const dur = durationMsResolved(state);
1511
+ const tagged = withHostile(
1512
+ {
1513
+ kind: 'speed' as const,
1514
+ aura: SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS,
1515
+ pct: min,
1516
+ durationMs: dur,
1517
+ },
1518
+ raw.targetA | 0,
1519
+ min,
1520
+ );
1521
+ state.effects.push(tagged as SpellEffect);
1522
+ state.role = state.role || 'buff';
1523
+ }
1524
+
1525
+ // ── SPELL_AURA_MOD_HEALING_DONE_PERCENT (136) ── baked as a healing-done percent.
1526
+ // Cite: SpellAuras.cpp:197; Unit.cpp:7200-7203 SpellHealingBonusDone.
1527
+ export function handleModHealingDonePercent(
1528
+ state: HandlerState,
1529
+ raw: RawSpellEffect,
1530
+ _slot: number,
1531
+ _effectType: number,
1532
+ ): void {
1533
+ const { min } = effectAmountRange(raw, state.ctx);
1534
+ const dur = durationMsResolved(state);
1535
+ // Whole percent from base points (Power Infusion +20). Cite: Unit.cpp:7202.
1536
+ const tagged = withHostile(
1537
+ { kind: 'buff' as const, mod: 'healing_done_pct' as const, amount: min, durationMs: dur },
1538
+ raw.targetA | 0,
1539
+ min,
1540
+ );
1541
+ state.effects.push(tagged as SpellEffect);
1542
+ state.role = state.role || 'buff';
1543
+ }
1544
+
1545
+ // ── SPELL_AURA_MOD_BASE_RESISTANCE_PCT (142) ── a physical mask becomes a base armor percent, never
1546
+ // flat armor. Cite: SpellAuras.cpp:3425-3437 HandleAuraModBaseResistancePercent.
1547
+ export function handleModBaseResistancePct(
1548
+ state: HandlerState,
1549
+ raw: RawSpellEffect,
1550
+ _slot: number,
1551
+ _effectType: number,
1552
+ ): void {
1553
+ const { min } = effectAmountRange(raw, state.ctx);
1554
+ // C++: if (!m_modifier.m_amount) return. Cite: :3427–3428.
1555
+ if (!min) return;
1556
+ const dur = durationMsResolved(state);
1557
+ const mask = raw.miscValue | 0;
1558
+ // Physical bit (SPELL_SCHOOL_MASK_NORMAL = 1) is base armor percent. Cite: :3432–3435.
1559
+ if ((mask & 1) !== 0) {
1560
+ const tagged = withHostile(
1561
+ { kind: 'buff' as const, mod: 'armor_base_pct' as const, amount: min, durationMs: dur },
1562
+ raw.targetA | 0,
1563
+ min,
1564
+ );
1565
+ state.effects.push(tagged as SpellEffect);
1566
+ }
1567
+ // Magic bits are the same BASE_PCT on that school's resistance — Ossirian's five Weaknesses
1568
+ // strip 100%. Cite: boss_ossirian.cpp:54-58; SpellAuras.cpp:3432-3435.
1569
+ for (let bit = 1; bit <= 6; bit++) {
1570
+ if ((mask & (1 << bit)) === 0) continue;
1571
+ state.effects.push(withHostile(
1572
+ { kind: 'resist' as const, school: SCHOOLS[bit]!, amount: 0, pct: min },
1573
+ raw.targetA | 0,
1574
+ min,
1575
+ ) as SpellEffect);
1576
+ }
1577
+ state.role = state.role || 'buff';
1578
+ }
1579
+
1580
+ // ── SPELL_AURA_TRACK_STEALTHED (151) ────────────────────────────────────── Cite: SpellAuras.cpp:2174–2179
1581
+ // HandleAuraTrackStealthed Bake empty. Track Hidden 19885.
1582
+ export function handleAuraTrackStealthed(
1583
+ state: HandlerState,
1584
+ _raw: RawSpellEffect,
1585
+ _slot: number,
1586
+ _effectType: number,
1587
+ ): void {
1588
+ // C++: non-player → return. Cite: :2176–2177.
1589
+ if (state.ctx.unitTargetIsPlayer === false) return;
1590
+ // ApplyModByteFlag PLAYER_FIELD_BYTES TRACK_STEALTHED. Cite: :2179.
1591
+ const dur = durationMsResolved(state);
1592
+ state.intents.push({ kind: 'track_stealthed', durationMs: dur });
1593
+ state.role = state.role || 'buff';
1594
+ }
1595
+
1596
+ // ── SPELL_AURA_MOD_WATER_BREATHING (155) ── distinct from aura 82, which is infinite. Empty in the
1597
+ // bake; the Undead racial carries it. Cite: SpellAuras.cpp:1701-1706 HandleModWaterBreathing.
1598
+ export function handleModWaterBreathing(
1599
+ state: HandlerState,
1600
+ raw: RawSpellEffect,
1601
+ _slot: number,
1602
+ _effectType: number,
1603
+ ): void {
1604
+ // C++: player only. Cite: :1705–1706.
1605
+ if (state.ctx.unitTargetIsPlayer === false) return;
1606
+
1607
+ const { min } = effectAmountRange(raw, state.ctx);
1608
+ const dur = durationMsResolved(state);
1609
+ // GetTotalAuraMultiplier: product of (100+amount)/100. Cite: Unit.cpp:4492–4500.
1610
+ // Single-aura contribution for this slot.
1611
+ const intervalMultiplier = (100 + min) / 100;
1612
+ state.intents.push({
1613
+ kind: 'mod_water_breathing',
1614
+ amount: min,
1615
+ intervalMultiplier,
1616
+ durationMs: dur,
1617
+ });
1618
+ // Undead racial Underwater Breathing 5227 — catalog surface. Cite: KI-686.
1619
+ if (!state.effects.some((e) => e.kind === 'mod_water_breathing' || e.kind === 'water_breathing')) {
1620
+ state.effects.push({
1621
+ kind: 'mod_water_breathing',
1622
+ amount: min,
1623
+ intervalMultiplier,
1624
+ durationMs: dur < 0 ? 0 : dur,
1625
+ });
1626
+ }
1627
+ state.role = state.role || 'buff';
1628
+ }
1629
+
1630
+ // ── SPELL_AURA_MOD_REPUTATION_GAIN (156) ── an effect row for the catalog and combat surface, plus an
1631
+ // intent for the reputation pipelines. Cite: SpellAuras.cpp:217; Player.cpp:6297-6302.
1632
+ export function handleModReputationGain(
1633
+ state: HandlerState,
1634
+ raw: RawSpellEffect,
1635
+ _slot: number,
1636
+ _effectType: number,
1637
+ ): void {
1638
+ const { min } = effectAmountRange(raw, state.ctx);
1639
+ const dur = durationMsResolved(state);
1640
+ // repMod = GetTotalAuraModifier(156); percent += rep > 0 ? repMod : -repMod.
1641
+ // Cite: Player.cpp:6297, :6302.
1642
+ state.intents.push({
1643
+ kind: 'mod_reputation_gain',
1644
+ amount: min,
1645
+ durationMs: dur,
1646
+ });
1647
+ // Catalog / fillEmptyEffectsFromRaw needs a SpellEffect row (intents alone leave effects[]).
1648
+ state.effects.push({
1649
+ kind: 'mod_reputation_gain',
1650
+ amount: min,
1651
+ durationMs: dur,
1652
+ } as never);
1653
+ state.role = state.role || 'buff';
1654
+ }
1655
+
1656
+ // ── SPELL_AURA_NO_PVP_CREDIT (159) ── empty in the bake; the honor reward returns false while it is
1657
+ // held, and Honorless Target is the only Classic consumer. Cite: Player.cpp:6626-6627.
1658
+ export function handleNoPvpCredit(
1659
+ state: HandlerState,
1660
+ _raw: RawSpellEffect,
1661
+ _slot: number,
1662
+ _effectType: number,
1663
+ ): void {
1664
+ const dur = durationMsResolved(state);
1665
+ // Victim carrying this aura grants no honor. Cite: Player.cpp:6626–6627.
1666
+ state.intents.push({ kind: 'no_pvp_credit', durationMs: dur });
1667
+ state.effects.push({ kind: 'no_pvp_credit', durationMs: dur });
1668
+ state.role = state.role || 'buff';
1669
+ }
1670
+
1671
+ // SPELL_AURA_MOD_AOE_AVOIDANCE (160). Miss chance += GetTotalAuraModifier vs area spells. Cite:
1672
+ // SpellAuras.cpp:221 HandleNoImmediateEffect; Unit.cpp:3713–3715.
1673
+ export function handleModAoEAvoidance(
1674
+ state: HandlerState,
1675
+ raw: RawSpellEffect,
1676
+ _slot: number,
1677
+ _effectType: number,
1678
+ ): void {
1679
+ const { min } = effectAmountRange(raw, state.ctx);
1680
+ const dur = durationMsResolved(state);
1681
+ state.effects.push({ kind: 'buff', mod: 'aoe_avoidance', amount: min, durationMs: dur });
1682
+ state.role = state.role || 'buff';
1683
+ }
1684
+
1685
+ // SPELL_AURA_MECHANIC_IMMUNITY_MASK (147). misc is a mechanic bitmask; IsImmuneToSpell reads it. Cite:
1686
+ // SpellAuras.cpp:2951–2959 HandleModMechanicImmunityMask.
1687
+ export function handleModMechanicImmunityMask(
1688
+ state: HandlerState,
1689
+ raw: RawSpellEffect,
1690
+ _slot: number,
1691
+ _effectType: number,
1692
+ ): void {
1693
+ const mask = raw.miscValue | 0;
1694
+ const dur = durationMsResolved(state);
1695
+ state.effects.push({
1696
+ kind: 'mechanic_immunity',
1697
+ mechanic: mask,
1698
+ durationMs: dur,
1699
+ positive: true,
1700
+ });
1701
+ state.role = state.role || 'buff';
1702
+
1703
+ // On apply + SPELL_ATTR_EX_IMMUNITY_PURGES_EFFECT → RemoveAurasAtMechanicImmunity.
1704
+ // Cite: SpellAuras.cpp:2955-2956. Bake-thin: attr unknown unless ctx.immunityPurgesEffect === true.
1705
+ if (state.ctx.immunityPurgesEffect === true && mask > 0) {
1706
+ state.intents.push({
1707
+ kind: 'mechanic_immunity_purge',
1708
+ mechanic: 0,
1709
+ mechanicMask: mask,
1710
+ });
1711
+ }
1712
+ }
1713
+
1714
+ // SPELL_AURA_MOD_FACTION_REPUTATION_GAIN (190). GetTotalAuraModifierByMiscValue(faction). Cite:
1715
+ // Player.cpp:6301.
1716
+ export function handleModFactionReputationGain(
1717
+ state: HandlerState,
1718
+ raw: RawSpellEffect,
1719
+ _slot: number,
1720
+ _effectType: number,
1721
+ ): void {
1722
+ const { min } = effectAmountRange(raw, state.ctx);
1723
+ const dur = durationMsResolved(state);
1724
+ const factionId = raw.miscValue | 0;
1725
+ state.effects.push({
1726
+ kind: 'mod_reputation_gain',
1727
+ amount: min,
1728
+ durationMs: dur,
1729
+ factionId,
1730
+ });
1731
+ state.role = state.role || 'buff';
1732
+ }
1733
+
1734
+ /** SPELL_AURA_MOD_BLOCK_SKILL (50) — HandleUnused obsolete. Cite: SpellAuras.cpp:111. */
1735
+ export function handleModBlockSkillUnused(
1736
+ state: HandlerState,
1737
+ _raw: RawSpellEffect,
1738
+ _slot: number,
1739
+ _effectType: number,
1740
+ ): void {
1741
+ state.effects.push({ kind: 'client_inform' });
1742
+ }
1743
+
1744
+ /** SPELL_AURA_CHARISMA (145) — HandleUnused obsolete. Cite: SpellAuras.cpp:206. */
1745
+ export function handleAuraCharismaUnused(
1746
+ state: HandlerState,
1747
+ _raw: RawSpellEffect,
1748
+ _slot: number,
1749
+ _effectType: number,
1750
+ ): void {
1751
+ state.effects.push({ kind: 'client_inform' });
1752
+ }
1753
+
1754
+ /** SPELL_AURA_164 — unused aura id. Cite: SpellAuraDefines.h:299. */
1755
+ export function handleAura164Unused(
1756
+ state: HandlerState,
1757
+ _raw: RawSpellEffect,
1758
+ _slot: number,
1759
+ _effectType: number,
1760
+ ): void {
1761
+ state.effects.push({ kind: 'client_inform' });
1762
+ }
1763
+
1764
+ // SPELL_AURA_DETECT_AMORE (170) — PLAYER_FIELD_BYTES2 client flag, no combat payload. Cite:
1765
+ // SpellAuras.cpp:2719–2725 HandleDetectAmore.
1766
+ export function handleDetectAmoreUnused(
1767
+ state: HandlerState,
1768
+ _raw: RawSpellEffect,
1769
+ _slot: number,
1770
+ _effectType: number,
1771
+ ): void {
1772
+ state.effects.push({ kind: 'client_inform' });
1773
+ }
1774
+