azeroth-shell 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1163) hide show
  1. package/README.md +138 -2
  2. package/bin/azsh.mjs +19 -0
  3. package/docs/aifid/eventai-texts.json +4414 -0
  4. package/docs/dungeons/atlas/atlas-rows-dungeons.json +8989 -0
  5. package/docs/dungeons/survey/pack-id-migration.json +2418 -0
  6. package/package.json +26 -4
  7. package/src/autopilot/bossSkip.ts +26 -0
  8. package/src/autopilot/combatRotation.ts +824 -0
  9. package/src/autopilot/config.ts +533 -0
  10. package/src/autopilot/consumables.ts +58 -0
  11. package/src/autopilot/encounterStand.ts +121 -0
  12. package/src/autopilot/objectGatePlan.ts +53 -0
  13. package/src/autopilot/pathEngage.ts +229 -0
  14. package/src/autopilot/plan.ts +1643 -0
  15. package/src/autopilot/questPolicy.ts +274 -0
  16. package/src/autopilot/routeStep.ts +69 -0
  17. package/src/autopilot/sessionReport.ts +88 -0
  18. package/src/autopilot/topOffPower.ts +26 -0
  19. package/src/autopilot/view.ts +476 -0
  20. package/src/cli/bootCheck.mjs +34 -0
  21. package/src/cli/bootData.mjs +57 -0
  22. package/src/cli/combatLogFilter.ts +153 -0
  23. package/src/cli/combatLogFormat.ts +613 -0
  24. package/src/cli/fileRepository.mjs +105 -0
  25. package/src/cli/gzLoader.mjs +31 -0
  26. package/src/cli/liveGauntletEscort.ts +978 -0
  27. package/src/cli/liveStratUndead.ts +305 -0
  28. package/src/cli/macroHostCombat.ts +545 -0
  29. package/src/cli/macroHostWorld.ts +330 -0
  30. package/src/cli/prefs.mjs +31 -0
  31. package/src/cli/register.mjs +4 -0
  32. package/src/cli/repl.mjs +693 -0
  33. package/src/cli/rotationText.mjs +226 -0
  34. package/src/cli/squad.mjs +105 -0
  35. package/src/cli/term.mjs +126 -0
  36. package/src/cli/text.mjs +122 -0
  37. package/src/cli/tui.mjs +626 -0
  38. package/src/cli/tuiArena.mjs +109 -0
  39. package/src/cli/tuiAutopilotSettings.mjs +93 -0
  40. package/src/cli/tuiBags.mjs +180 -0
  41. package/src/cli/tuiBars.mjs +133 -0
  42. package/src/cli/tuiBg.mjs +243 -0
  43. package/src/cli/tuiBulk.mjs +162 -0
  44. package/src/cli/tuiCheck.mjs +1882 -0
  45. package/src/cli/tuiCity.mjs +396 -0
  46. package/src/cli/tuiCompanionKit.mjs +300 -0
  47. package/src/cli/tuiCompanions.mjs +471 -0
  48. package/src/cli/tuiDev.mjs +62 -0
  49. package/src/cli/tuiDungeon.mjs +606 -0
  50. package/src/cli/tuiEnchantTarget.mjs +120 -0
  51. package/src/cli/tuiFight.mjs +577 -0
  52. package/src/cli/tuiFightPanes.mjs +228 -0
  53. package/src/cli/tuiFloor.mjs +506 -0
  54. package/src/cli/tuiGear.mjs +158 -0
  55. package/src/cli/tuiHonor.mjs +74 -0
  56. package/src/cli/tuiLoot.mjs +97 -0
  57. package/src/cli/tuiMacros.mjs +144 -0
  58. package/src/cli/tuiOutfitter.mjs +115 -0
  59. package/src/cli/tuiPet.mjs +116 -0
  60. package/src/cli/tuiProfessions.mjs +800 -0
  61. package/src/cli/tuiRaid.mjs +127 -0
  62. package/src/cli/tuiRep.mjs +65 -0
  63. package/src/cli/tuiSaves.mjs +69 -0
  64. package/src/cli/tuiSearch.mjs +363 -0
  65. package/src/cli/tuiSettings.mjs +151 -0
  66. package/src/cli/tuiSimLab.mjs +80 -0
  67. package/src/cli/tuiTalents.mjs +60 -0
  68. package/src/cli/tuiViews.mjs +1178 -0
  69. package/src/cli/tuiWiki.mjs +181 -0
  70. package/src/cli/tuiWorld.mjs +361 -0
  71. package/src/cli/wikiIndex.ts +259 -0
  72. package/src/cli/wikiSources.ts +355 -0
  73. package/src/data/alteracValley.ts +176 -0
  74. package/src/data/appearanceOptions.ts +534 -0
  75. package/src/data/applyLootChanceSanity.ts +21 -0
  76. package/src/data/createFlavor.ts +96 -0
  77. package/src/data/customItems.ts +33 -0
  78. package/src/data/dataStore.ts +1904 -0
  79. package/src/data/dungeonGameObjects.ts +84 -0
  80. package/src/data/dungeonPlateCover.ts +66 -0
  81. package/src/data/dungeonSpawns.ts +294 -0
  82. package/src/data/dungeons/alterac-valley.ts +135 -0
  83. package/src/data/dungeons/apply-dungeon-rooms.ts +29 -0
  84. package/src/data/dungeons/apply-encounter-outdoors.ts +72 -0
  85. package/src/data/dungeons/apply-instance-geometry.ts +65 -0
  86. package/src/data/dungeons/apply-spawn-placement.ts +171 -0
  87. package/src/data/dungeons/blackfathom-deeps.ts +539 -0
  88. package/src/data/dungeons/blackrock-depths.ts +1410 -0
  89. package/src/data/dungeons/blackwing-lair.ts +129 -0
  90. package/src/data/dungeons/boss-eventai.ts +8 -0
  91. package/src/data/dungeons/deadmines.ts +410 -0
  92. package/src/data/dungeons/dire-maul-east.ts +980 -0
  93. package/src/data/dungeons/dire-maul-north.ts +661 -0
  94. package/src/data/dungeons/dire-maul-west.ts +785 -0
  95. package/src/data/dungeons/dungeon-rooms.json +5479 -0
  96. package/src/data/dungeons/encounter-outdoors.json +359 -0
  97. package/src/data/dungeons/eventai/blackfathom-deeps.ts +308 -0
  98. package/src/data/dungeons/eventai/blackrock-depths.ts +1257 -0
  99. package/src/data/dungeons/eventai/deadmines.ts +264 -0
  100. package/src/data/dungeons/eventai/dire-maul-east.ts +320 -0
  101. package/src/data/dungeons/eventai/gnomeregan.ts +213 -0
  102. package/src/data/dungeons/eventai/helpers.ts +79 -0
  103. package/src/data/dungeons/eventai/index.ts +133 -0
  104. package/src/data/dungeons/eventai/lbrs.ts +372 -0
  105. package/src/data/dungeons/eventai/maraudon.ts +323 -0
  106. package/src/data/dungeons/eventai/ragefire-chasm.ts +108 -0
  107. package/src/data/dungeons/eventai/razorfen-downs.ts +207 -0
  108. package/src/data/dungeons/eventai/razorfen-kraul.ts +326 -0
  109. package/src/data/dungeons/eventai/scholomance.ts +680 -0
  110. package/src/data/dungeons/eventai/shadowfang-keep.ts +230 -0
  111. package/src/data/dungeons/eventai/sm-cathedral.ts +75 -0
  112. package/src/data/dungeons/eventai/sm-graveyard.ts +150 -0
  113. package/src/data/dungeons/eventai/sm-library.ts +55 -0
  114. package/src/data/dungeons/eventai/stratholme-undead.ts +127 -0
  115. package/src/data/dungeons/eventai/sunken-temple.ts +582 -0
  116. package/src/data/dungeons/eventai/the-stockade.ts +228 -0
  117. package/src/data/dungeons/eventai/ubrs.ts +225 -0
  118. package/src/data/dungeons/eventai/uldaman.ts +355 -0
  119. package/src/data/dungeons/eventai/wailing-caverns.ts +396 -0
  120. package/src/data/dungeons/eventai/zul-farrak.ts +591 -0
  121. package/src/data/dungeons/gnomeregan.ts +909 -0
  122. package/src/data/dungeons/index.ts +126 -0
  123. package/src/data/dungeons/instance-geometry.json +5233 -0
  124. package/src/data/dungeons/key-sources.json +169 -0
  125. package/src/data/dungeons/lbrs.ts +996 -0
  126. package/src/data/dungeons/maraudon.ts +786 -0
  127. package/src/data/dungeons/molten-core.ts +194 -0
  128. package/src/data/dungeons/naxxramas.ts +173 -0
  129. package/src/data/dungeons/onyxias-lair.ts +71 -0
  130. package/src/data/dungeons/pack-from-clusters.ts +1256 -0
  131. package/src/data/dungeons/ragefire-chasm.ts +238 -0
  132. package/src/data/dungeons/razorfen-downs.ts +698 -0
  133. package/src/data/dungeons/razorfen-kraul.ts +766 -0
  134. package/src/data/dungeons/ruins-of-ahnqiraj.ts +121 -0
  135. package/src/data/dungeons/scholomance.ts +1076 -0
  136. package/src/data/dungeons/shadowfang-keep.ts +740 -0
  137. package/src/data/dungeons/sm-armory.ts +266 -0
  138. package/src/data/dungeons/sm-cathedral.ts +430 -0
  139. package/src/data/dungeons/sm-graveyard.ts +482 -0
  140. package/src/data/dungeons/sm-library.ts +337 -0
  141. package/src/data/dungeons/stratholme-live.ts +808 -0
  142. package/src/data/dungeons/stratholme-undead.ts +1164 -0
  143. package/src/data/dungeons/sunken-temple.ts +931 -0
  144. package/src/data/dungeons/temple-of-ahnqiraj.ts +119 -0
  145. package/src/data/dungeons/the-stockade.ts +282 -0
  146. package/src/data/dungeons/ubrs.ts +1286 -0
  147. package/src/data/dungeons/uldaman.ts +685 -0
  148. package/src/data/dungeons/wailing-caverns.ts +356 -0
  149. package/src/data/dungeons/zul-farrak.ts +686 -0
  150. package/src/data/dungeons/zul-gurub.ts +142 -0
  151. package/src/data/dungeons.ts +42 -0
  152. package/src/data/fixtures.ts +446 -0
  153. package/src/data/gameobject-data.json.gz +0 -0
  154. package/src/data/item-data.json.gz +0 -0
  155. package/src/data/loot-data.json.gz +0 -0
  156. package/src/data/maps/atlas-approach-maps.json +1425 -0
  157. package/src/data/maps/atlas-landmarks.json +1711 -0
  158. package/src/data/maps/dungeon-viewports.json +392 -0
  159. package/src/data/materializeModDamagePercentTaken.ts +70 -0
  160. package/src/data/materializeModHealthRegen.ts +89 -0
  161. package/src/data/materializeSpellReputation.ts +26 -0
  162. package/src/data/pageTexts.ts +19 -0
  163. package/src/data/profession-data.json.gz +0 -0
  164. package/src/data/raid-plans/blackfathom-deeps.json +86 -0
  165. package/src/data/raid-plans/blackrock-depths.json +419 -0
  166. package/src/data/raid-plans/blackwing-lair.json +328 -0
  167. package/src/data/raid-plans/deadmines.json +55 -0
  168. package/src/data/raid-plans/dire-maul-east.json +94 -0
  169. package/src/data/raid-plans/dire-maul-north.json +70 -0
  170. package/src/data/raid-plans/dire-maul-west.json +75 -0
  171. package/src/data/raid-plans/gnomeregan.json +131 -0
  172. package/src/data/raid-plans/lbrs.json +176 -0
  173. package/src/data/raid-plans/maraudon.json +102 -0
  174. package/src/data/raid-plans/molten-core.json +169 -0
  175. package/src/data/raid-plans/naxxramas.json +354 -0
  176. package/src/data/raid-plans/onyxias-lair.json +18 -0
  177. package/src/data/raid-plans/ragefire-chasm.json +30 -0
  178. package/src/data/raid-plans/razorfen-downs.json +75 -0
  179. package/src/data/raid-plans/razorfen-kraul.json +53 -0
  180. package/src/data/raid-plans/ruins-of-ahnqiraj.json +110 -0
  181. package/src/data/raid-plans/scholomance.json +170 -0
  182. package/src/data/raid-plans/shadowfang-keep.json +87 -0
  183. package/src/data/raid-plans/sm-armory.json +53 -0
  184. package/src/data/raid-plans/sm-cathedral.json +72 -0
  185. package/src/data/raid-plans/sm-graveyard.json +63 -0
  186. package/src/data/raid-plans/sm-library.json +23 -0
  187. package/src/data/raid-plans/stratholme-live.json +129 -0
  188. package/src/data/raid-plans/stratholme-undead.json +73 -0
  189. package/src/data/raid-plans/sunken-temple.json +159 -0
  190. package/src/data/raid-plans/temple-of-ahnqiraj.json +163 -0
  191. package/src/data/raid-plans/the-stockade.json +42 -0
  192. package/src/data/raid-plans/ubrs.json +53 -0
  193. package/src/data/raid-plans/uldaman.json +131 -0
  194. package/src/data/raid-plans/wailing-caverns.json +90 -0
  195. package/src/data/raid-plans/zul-farrak.json +156 -0
  196. package/src/data/raid-plans/zul-gurub.json +307 -0
  197. package/src/data/raidInstanceCreatures.mjs +473 -0
  198. package/src/data/rotations/index.ts +152 -0
  199. package/src/data/rotations/layout.mjs +72 -0
  200. package/src/data/rotations/pve/druid/balance.json +754 -0
  201. package/src/data/rotations/pve/druid/feral-tank.json +2448 -0
  202. package/src/data/rotations/pve/druid/feral.json +2660 -0
  203. package/src/data/rotations/pve/druid/restoration.json +424 -0
  204. package/src/data/rotations/pve/hunter/beast-mastery.json +1288 -0
  205. package/src/data/rotations/pve/hunter/marksmanship.json +1260 -0
  206. package/src/data/rotations/pve/hunter/survival.json +1373 -0
  207. package/src/data/rotations/pve/mage/arcane-leveling.json +1798 -0
  208. package/src/data/rotations/pve/mage/fire-leveling.json +2003 -0
  209. package/src/data/rotations/pve/mage/frost-leveling.json +1912 -0
  210. package/src/data/rotations/pve/paladin/holy.json +755 -0
  211. package/src/data/rotations/pve/paladin/protection.json +962 -0
  212. package/src/data/rotations/pve/paladin/retribution.json +924 -0
  213. package/src/data/rotations/pve/priest/discipline.json +772 -0
  214. package/src/data/rotations/pve/priest/holy.json +707 -0
  215. package/src/data/rotations/pve/priest/shadow.json +787 -0
  216. package/src/data/rotations/pve/rogue/assassination.json +2477 -0
  217. package/src/data/rotations/pve/rogue/combat.json +2483 -0
  218. package/src/data/rotations/pve/rogue/subtlety.json +2523 -0
  219. package/src/data/rotations/pve/shaman/elemental.json +1157 -0
  220. package/src/data/rotations/pve/shaman/enhancement.json +1085 -0
  221. package/src/data/rotations/pve/shaman/restoration.json +592 -0
  222. package/src/data/rotations/pve/warlock/affliction.json +1185 -0
  223. package/src/data/rotations/pve/warlock/demonology.json +1165 -0
  224. package/src/data/rotations/pve/warlock/destruction.json +1177 -0
  225. package/src/data/rotations/pve/warrior/arms.json +3020 -0
  226. package/src/data/rotations/pve/warrior/fury.json +2996 -0
  227. package/src/data/rotations/pve/warrior/protection.json +2509 -0
  228. package/src/data/rotations/pvp/druid/balance.json +593 -0
  229. package/src/data/rotations/pvp/druid/feral.json +3276 -0
  230. package/src/data/rotations/pvp/druid/restoration.json +662 -0
  231. package/src/data/rotations/pvp/hunter/beast-mastery.json +665 -0
  232. package/src/data/rotations/pvp/hunter/marksmanship.json +2406 -0
  233. package/src/data/rotations/pvp/hunter/survival.json +635 -0
  234. package/src/data/rotations/pvp/mage/arcane.json +574 -0
  235. package/src/data/rotations/pvp/mage/fire.json +570 -0
  236. package/src/data/rotations/pvp/mage/frost.json +4048 -0
  237. package/src/data/rotations/pvp/paladin/holy.json +1498 -0
  238. package/src/data/rotations/pvp/paladin/protection.json +567 -0
  239. package/src/data/rotations/pvp/paladin/retribution.json +1110 -0
  240. package/src/data/rotations/pvp/priest/discipline.json +1848 -0
  241. package/src/data/rotations/pvp/priest/holy.json +6340 -0
  242. package/src/data/rotations/pvp/priest/shadow.json +2329 -0
  243. package/src/data/rotations/pvp/rogue/assassination.json +1322 -0
  244. package/src/data/rotations/pvp/rogue/combat.json +5258 -0
  245. package/src/data/rotations/pvp/rogue/subtlety.json +586 -0
  246. package/src/data/rotations/pvp/shaman/elemental.json +1404 -0
  247. package/src/data/rotations/pvp/shaman/enhancement.json +1277 -0
  248. package/src/data/rotations/pvp/shaman/restoration.json +2490 -0
  249. package/src/data/rotations/pvp/warlock/affliction.json +1017 -0
  250. package/src/data/rotations/pvp/warlock/demonology.json +1503 -0
  251. package/src/data/rotations/pvp/warlock/destruction.json +638 -0
  252. package/src/data/rotations/pvp/warrior/arms.json +5665 -0
  253. package/src/data/rotations/pvp/warrior/fury.json +850 -0
  254. package/src/data/rotations/pvp/warrior/protection.json +777 -0
  255. package/src/data/schema/bundle.ts +511 -0
  256. package/src/data/schema/constants.ts +49 -0
  257. package/src/data/schema/creature.ts +454 -0
  258. package/src/data/schema/encounter.ts +155 -0
  259. package/src/data/schema/faction.ts +48 -0
  260. package/src/data/schema/item.ts +297 -0
  261. package/src/data/schema/itemEnchant.ts +105 -0
  262. package/src/data/schema/npc.ts +44 -0
  263. package/src/data/schema/primitives.ts +295 -0
  264. package/src/data/schema/profession.ts +226 -0
  265. package/src/data/schema/quest.ts +154 -0
  266. package/src/data/schema/spell.ts +1149 -0
  267. package/src/data/schema/talent.ts +74 -0
  268. package/src/data/schema/world.ts +124 -0
  269. package/src/data/schema.ts +19 -0
  270. package/src/data/skinNodeGapFill.ts +68 -0
  271. package/src/data/spell-data.json.gz +0 -0
  272. package/src/data/spell-script-targets.json +1 -0
  273. package/src/data/tables/ahItemValues.json.gz +0 -0
  274. package/src/data/tables/alteracValley.json.gz +0 -0
  275. package/src/data/tables/areatriggerTeleports.json.gz +0 -0
  276. package/src/data/tables/botNames.json.gz +0 -0
  277. package/src/data/tables/botPopulation.json.gz +0 -0
  278. package/src/data/tables/botSpecs.json.gz +0 -0
  279. package/src/data/tables/classLevelStats.json.gz +0 -0
  280. package/src/data/tables/combatConditions.json.gz +0 -0
  281. package/src/data/tables/combatSkillMeta.json.gz +0 -0
  282. package/src/data/tables/conditions.json.gz +0 -0
  283. package/src/data/tables/createInfo.json.gz +0 -0
  284. package/src/data/tables/creatureAggroGroups.json.gz +0 -0
  285. package/src/data/tables/creatureClassLevelStats.json.gz +0 -0
  286. package/src/data/tables/creaturePatrolPacks.json.gz +0 -0
  287. package/src/data/tables/creatureWeapons.json.gz +0 -0
  288. package/src/data/tables/creatures.json.gz +0 -0
  289. package/src/data/tables/dbScripts.json.gz +0 -0
  290. package/src/data/tables/dungeonAuthoredRoutes.json.gz +0 -0
  291. package/src/data/tables/dungeonCensus.json.gz +0 -0
  292. package/src/data/tables/dungeonGameObjects.json.gz +0 -0
  293. package/src/data/tables/dungeonPacks.json.gz +0 -0
  294. package/src/data/tables/dungeonPlateCover.json.gz +0 -0
  295. package/src/data/tables/dungeonSpawns.json.gz +0 -0
  296. package/src/data/tables/dungeonSurvey.json.gz +0 -0
  297. package/src/data/tables/durabilityCosts.json.gz +0 -0
  298. package/src/data/tables/durabilityQuality.json.gz +0 -0
  299. package/src/data/tables/enchantApplicators.json.gz +0 -0
  300. package/src/data/tables/entranceYards.json.gz +0 -0
  301. package/src/data/tables/explorationBasexp.json.gz +0 -0
  302. package/src/data/tables/factionTemplates.json.gz +0 -0
  303. package/src/data/tables/factions.json.gz +0 -0
  304. package/src/data/tables/gameEvents.json.gz +0 -0
  305. package/src/data/tables/gameObjects.json.gz +0 -0
  306. package/src/data/tables/gossipMenus.json.gz +0 -0
  307. package/src/data/tables/graveyards.json.gz +0 -0
  308. package/src/data/tables/instanceMaps.json.gz +0 -0
  309. package/src/data/tables/itemEnchantmentTemplates.json.gz +0 -0
  310. package/src/data/tables/itemEnchants.json.gz +0 -0
  311. package/src/data/tables/itemRandomProperties.json.gz +0 -0
  312. package/src/data/tables/itemSets.json.gz +0 -0
  313. package/src/data/tables/items.json.gz +0 -0
  314. package/src/data/tables/levelStats.json.gz +0 -0
  315. package/src/data/tables/locks.json.gz +0 -0
  316. package/src/data/tables/map-pin-overrides.json.gz +0 -0
  317. package/src/data/tables/nonCombatTrash.json.gz +0 -0
  318. package/src/data/tables/npcTexts.json.gz +0 -0
  319. package/src/data/tables/pageTexts.json.gz +0 -0
  320. package/src/data/tables/petAbilityTP.json.gz +0 -0
  321. package/src/data/tables/petGenericSpells.json.gz +0 -0
  322. package/src/data/tables/petLevelStats.json.gz +0 -0
  323. package/src/data/tables/playerbot-weightscales.json.gz +0 -0
  324. package/src/data/tables/pools.json.gz +0 -0
  325. package/src/data/tables/quests.json.gz +0 -0
  326. package/src/data/tables/races.json.gz +0 -0
  327. package/src/data/tables/reputationRanks.json.gz +0 -0
  328. package/src/data/tables/reputationRates.json.gz +0 -0
  329. package/src/data/tables/reputationSpillover.json.gz +0 -0
  330. package/src/data/tables/ridingSpells.json.gz +0 -0
  331. package/src/data/tables/scriptTexts.json.gz +0 -0
  332. package/src/data/tables/soundClipVolume.json.gz +0 -0
  333. package/src/data/tables/spellChain.json.gz +0 -0
  334. package/src/data/tables/spellTeleports.json.gz +0 -0
  335. package/src/data/tables/spells.json.gz +0 -0
  336. package/src/data/tables/talents.json.gz +0 -0
  337. package/src/data/tables/tavernTriggers.json.gz +0 -0
  338. package/src/data/tables/taxiNodes.json.gz +0 -0
  339. package/src/data/tables/taxiRoutes.json.gz +0 -0
  340. package/src/data/tables/trainers.json.gz +0 -0
  341. package/src/data/tables/transports.json.gz +0 -0
  342. package/src/data/tables/travelAnchors.json.gz +0 -0
  343. package/src/data/tables/travelEdges.json.gz +0 -0
  344. package/src/data/tables/unitConditions.json.gz +0 -0
  345. package/src/data/tables/vendors.json.gz +0 -0
  346. package/src/data/tables/weaponEnchantProcs.json.gz +0 -0
  347. package/src/data/tables/xp.json.gz +0 -0
  348. package/src/data/tables/zoneWeather.json.gz +0 -0
  349. package/src/data/tables/zones.json.gz +0 -0
  350. package/src/data/world-data.ts +56 -0
  351. package/src/data/zone-music-sets.json +2751 -0
  352. package/src/dev/etl/lib/loot-chance-sanity.mjs +180 -0
  353. package/src/domain/audioQuality.mjs +145 -0
  354. package/src/domain/bg/ab.ts +433 -0
  355. package/src/domain/bg/arenaComps.ts +644 -0
  356. package/src/domain/bg/arenaLab.ts +695 -0
  357. package/src/domain/bg/arenaPace.ts +31 -0
  358. package/src/domain/bg/arenaRating.ts +110 -0
  359. package/src/domain/bg/av.ts +758 -0
  360. package/src/domain/bg/avEnemyPush.ts +219 -0
  361. package/src/domain/bg/avField.ts +283 -0
  362. package/src/domain/bg/avInstanceNodes.ts +197 -0
  363. package/src/domain/bg/avInstanceScore.ts +123 -0
  364. package/src/domain/bg/avQuestItems.ts +55 -0
  365. package/src/domain/bg/avQuests.ts +210 -0
  366. package/src/domain/bg/avSession.ts +196 -0
  367. package/src/domain/bg/bgConsumes.ts +269 -0
  368. package/src/domain/bg/bgPrebuff.ts +153 -0
  369. package/src/domain/bg/bgRest.ts +91 -0
  370. package/src/domain/bg/bgRoster.ts +305 -0
  371. package/src/domain/bg/bgTier.ts +61 -0
  372. package/src/domain/bg/bgWorld.ts +862 -0
  373. package/src/domain/bg/match.ts +215 -0
  374. package/src/domain/bg/strategies.ts +552 -0
  375. package/src/domain/bg/types.ts +291 -0
  376. package/src/domain/bg/wsg.ts +264 -0
  377. package/src/domain/bots/actionProviderSpec.ts +38 -0
  378. package/src/domain/bots/autoConsumables.ts +285 -0
  379. package/src/domain/bots/betweenPullRest.ts +239 -0
  380. package/src/domain/bots/botGear.ts +248 -0
  381. package/src/domain/bots/botInventory.ts +486 -0
  382. package/src/domain/bots/botPet.ts +535 -0
  383. package/src/domain/bots/botPool.ts +291 -0
  384. package/src/domain/bots/botProfessions.ts +334 -0
  385. package/src/domain/bots/companionActionBar.ts +209 -0
  386. package/src/domain/bots/companionHireCost.ts +236 -0
  387. package/src/domain/bots/companionMissions.ts +582 -0
  388. package/src/domain/bots/companionPrep.ts +254 -0
  389. package/src/domain/bots/companionQuests.ts +270 -0
  390. package/src/domain/bots/companionRep.ts +75 -0
  391. package/src/domain/bots/companionRotation.ts +708 -0
  392. package/src/domain/bots/companionXp.ts +66 -0
  393. package/src/domain/bots/consumableShare.ts +811 -0
  394. package/src/domain/bots/dpsMate.ts +1072 -0
  395. package/src/domain/bots/groupCompReport.ts +132 -0
  396. package/src/domain/bots/healthstoneSupply.ts +198 -0
  397. package/src/domain/bots/outfitter.ts +1056 -0
  398. package/src/domain/bots/paladinPrePull.ts +231 -0
  399. package/src/domain/bots/partyRole.ts +40 -0
  400. package/src/domain/bots/playerbotEquipCache.ts +412 -0
  401. package/src/domain/bots/playerbotItemEligibility.ts +60 -0
  402. package/src/domain/bots/playerbotStatWeight.ts +853 -0
  403. package/src/domain/bots/playerbotUnavailableItems.ts +147 -0
  404. package/src/domain/bots/prePullBuffs.ts +219 -0
  405. package/src/domain/bots/prePullStealth.ts +82 -0
  406. package/src/domain/bots/runSupply.ts +251 -0
  407. package/src/domain/bots/runSupplyPrefs.ts +28 -0
  408. package/src/domain/bots/sendTradeGoods.ts +394 -0
  409. package/src/domain/bots/soulShardCap.ts +35 -0
  410. package/src/domain/bots/squad.ts +842 -0
  411. package/src/domain/bots/squadRun.ts +81 -0
  412. package/src/domain/character/actionbar.ts +346 -0
  413. package/src/domain/character/appearance.ts +165 -0
  414. package/src/domain/character/buildCombatant.ts +1726 -0
  415. package/src/domain/character/character.ts +356 -0
  416. package/src/domain/character/characterName.ts +43 -0
  417. package/src/domain/character/characterRatings.ts +424 -0
  418. package/src/domain/character/characterSpells.ts +282 -0
  419. package/src/domain/character/characterStats.ts +1559 -0
  420. package/src/domain/character/characterTalents.ts +398 -0
  421. package/src/domain/character/combatSkills.ts +994 -0
  422. package/src/domain/character/displayForm.ts +72 -0
  423. package/src/domain/character/formTalentAuras.ts +171 -0
  424. package/src/domain/character/forms.ts +499 -0
  425. package/src/domain/character/races.ts +40 -0
  426. package/src/domain/character/resurrectionSickness.ts +49 -0
  427. package/src/domain/character/spellbook.ts +169 -0
  428. package/src/domain/character/stanceBar.ts +354 -0
  429. package/src/domain/character/stancePrereq.ts +70 -0
  430. package/src/domain/character/talentBuilds.ts +63 -0
  431. package/src/domain/character/talentImport.ts +130 -0
  432. package/src/domain/character/talentLink.ts +123 -0
  433. package/src/domain/character/talents.ts +201 -0
  434. package/src/domain/core/conditionSnapshot.ts +92 -0
  435. package/src/domain/core/hover.ts +14 -0
  436. package/src/domain/core/ids.ts +58 -0
  437. package/src/domain/core/internalNameTags.ts +5 -0
  438. package/src/domain/core/runtimeDataPatches.ts +357 -0
  439. package/src/domain/creature/aiTargeting.ts +588 -0
  440. package/src/domain/creature/combatCondition.ts +157 -0
  441. package/src/domain/creature/creatureAggro.ts +804 -0
  442. package/src/domain/creature/creatureAi.ts +206 -0
  443. package/src/domain/creature/creatureAiConstants.ts +661 -0
  444. package/src/domain/creature/creatureCastList.ts +1007 -0
  445. package/src/domain/creature/creatureEventAi.ts +1409 -0
  446. package/src/domain/creature/creatureGroups.ts +144 -0
  447. package/src/domain/creature/creatureLinking.ts +333 -0
  448. package/src/domain/creature/creatureScaling.ts +320 -0
  449. package/src/domain/creature/creatureTrigger.ts +53 -0
  450. package/src/domain/creature/creatureWander.ts +74 -0
  451. package/src/domain/creature/eventAiTexts.ts +145 -0
  452. package/src/domain/creature/faction.ts +287 -0
  453. package/src/domain/creature/forcedReaction.ts +48 -0
  454. package/src/domain/creature/outdoorHuntable.ts +74 -0
  455. package/src/domain/creature/patrolPacks.ts +210 -0
  456. package/src/domain/creature/reputation.ts +967 -0
  457. package/src/domain/creature/unitFlags.ts +74 -0
  458. package/src/domain/creature/worldBosses.ts +393 -0
  459. package/src/domain/dungeonMusic.mjs +48 -0
  460. package/src/domain/economy/auction.ts +282 -0
  461. package/src/domain/economy/auctionBot.ts +1060 -0
  462. package/src/domain/economy/honorPrice.ts +100 -0
  463. package/src/domain/economy/mail.ts +958 -0
  464. package/src/domain/economy/money.ts +42 -0
  465. package/src/domain/economy/syntheticClassTrainers.ts +62 -0
  466. package/src/domain/economy/trading.ts +296 -0
  467. package/src/domain/economy/vendorSellAll.ts +252 -0
  468. package/src/domain/economy/vendorStock.ts +146 -0
  469. package/src/domain/items/ammo.ts +817 -0
  470. package/src/domain/items/bank.ts +162 -0
  471. package/src/domain/items/consumableFamily.ts +205 -0
  472. package/src/domain/items/craftUpgrades.ts +83 -0
  473. package/src/domain/items/createItem.ts +93 -0
  474. package/src/domain/items/durability.ts +581 -0
  475. package/src/domain/items/equipment.ts +441 -0
  476. package/src/domain/items/equipmentHelper.ts +767 -0
  477. package/src/domain/items/inventory.ts +561 -0
  478. package/src/domain/items/itemBonding.ts +93 -0
  479. package/src/domain/items/itemContainer.ts +245 -0
  480. package/src/domain/items/itemDisplayName.ts +33 -0
  481. package/src/domain/items/itemInstance.ts +181 -0
  482. package/src/domain/items/itemRandomEnchantOutcomes.ts +315 -0
  483. package/src/domain/items/itemRandomProps.ts +77 -0
  484. package/src/domain/items/itemRestrictions.ts +329 -0
  485. package/src/domain/items/itemTeaches.ts +82 -0
  486. package/src/domain/items/itemUseCooldown.ts +52 -0
  487. package/src/domain/items/itemUseTarget.ts +90 -0
  488. package/src/domain/items/junkCategories.ts +174 -0
  489. package/src/domain/items/junkFilter.ts +368 -0
  490. package/src/domain/items/keyring.ts +131 -0
  491. package/src/domain/items/loot.ts +221 -0
  492. package/src/domain/items/mounts.ts +190 -0
  493. package/src/domain/items/onUsePayload.ts +102 -0
  494. package/src/domain/items/pendingLoot.ts +107 -0
  495. package/src/domain/items/relic.ts +105 -0
  496. package/src/domain/items/rocketBoots.ts +36 -0
  497. package/src/domain/items/sortContainer.ts +139 -0
  498. package/src/domain/items/spareContainers.ts +71 -0
  499. package/src/domain/items/spellReagentIndex.ts +131 -0
  500. package/src/domain/items/staleConsumables.ts +66 -0
  501. package/src/domain/items/weaponSpender.ts +110 -0
  502. package/src/domain/listDungeonIds.mjs +28 -0
  503. package/src/domain/macro/compose.ts +239 -0
  504. package/src/domain/macro/conditions.ts +260 -0
  505. package/src/domain/macro/creatureTypes.ts +40 -0
  506. package/src/domain/macro/describe.ts +169 -0
  507. package/src/domain/macro/icon.ts +60 -0
  508. package/src/domain/macro/index.ts +20 -0
  509. package/src/domain/macro/normalize.ts +112 -0
  510. package/src/domain/macro/parse.ts +316 -0
  511. package/src/domain/macro/plan.ts +288 -0
  512. package/src/domain/macro/rotation.ts +590 -0
  513. package/src/domain/macro/rotationEnv.ts +173 -0
  514. package/src/domain/macro/slots.ts +101 -0
  515. package/src/domain/macro/snapshot.ts +114 -0
  516. package/src/domain/macro/templates.ts +446 -0
  517. package/src/domain/macro/types.ts +70 -0
  518. package/src/domain/macro/units.ts +93 -0
  519. package/src/domain/macro/weaponTypes.ts +83 -0
  520. package/src/domain/nav/cityTeleports.ts +10 -0
  521. package/src/domain/nav/mounting.ts +113 -0
  522. package/src/domain/nav/nav.ts +43 -0
  523. package/src/domain/nav/navCollision.ts +606 -0
  524. package/src/domain/nav/navOutdoors.ts +91 -0
  525. package/src/domain/nav/navRegistry.ts +179 -0
  526. package/src/domain/nav/navRoomGraph.ts +302 -0
  527. package/src/domain/nav/navTypes.ts +43 -0
  528. package/src/domain/nav/navmesh.ts +1715 -0
  529. package/src/domain/nav/speed.ts +200 -0
  530. package/src/domain/nav/storey.ts +10 -0
  531. package/src/domain/nav/travel.ts +725 -0
  532. package/src/domain/nav/travelTypes.ts +75 -0
  533. package/src/domain/pet/pet.ts +1150 -0
  534. package/src/domain/pet/petActionBar.ts +180 -0
  535. package/src/domain/pet/petSpellbook.ts +39 -0
  536. package/src/domain/pet/petStable.ts +81 -0
  537. package/src/domain/professions/autoDisenchant.ts +236 -0
  538. package/src/domain/professions/characterEnchants.ts +176 -0
  539. package/src/domain/professions/craftCooldown.ts +52 -0
  540. package/src/domain/professions/enchantApply.ts +62 -0
  541. package/src/domain/professions/enchantTargets.ts +114 -0
  542. package/src/domain/professions/enchanting.ts +236 -0
  543. package/src/domain/professions/gatherFilter.ts +149 -0
  544. package/src/domain/professions/gearEnchant.ts +137 -0
  545. package/src/domain/professions/heldTools.ts +29 -0
  546. package/src/domain/professions/learnAllRecipes.ts +146 -0
  547. package/src/domain/professions/miningHarvest.ts +69 -0
  548. package/src/domain/professions/partyDisenchant.ts +294 -0
  549. package/src/domain/professions/partyWork.ts +83 -0
  550. package/src/domain/professions/pickpocket.ts +172 -0
  551. package/src/domain/professions/poisons.ts +240 -0
  552. package/src/domain/professions/professions.ts +677 -0
  553. package/src/domain/professions/rareNodes.ts +45 -0
  554. package/src/domain/professions/skinLoot.ts +27 -0
  555. package/src/domain/professions/vendorReagents.ts +152 -0
  556. package/src/domain/professions/weaponImbueHand.ts +171 -0
  557. package/src/domain/questFarmFilter.mjs +42 -0
  558. package/src/domain/quests/doQuest.ts +1204 -0
  559. package/src/domain/quests/gossip.ts +308 -0
  560. package/src/domain/quests/gossipTalk.ts +298 -0
  561. package/src/domain/quests/interpreter/canComplete.ts +150 -0
  562. package/src/domain/quests/interpreter/claim.ts +137 -0
  563. package/src/domain/quests/interpreter/dbscript/handlers.ts +1371 -0
  564. package/src/domain/quests/interpreter/dbscript/handlersBatch.ts +1251 -0
  565. package/src/domain/quests/interpreter/dbscript/hooks.ts +331 -0
  566. package/src/domain/quests/interpreter/dbscript/index.ts +212 -0
  567. package/src/domain/quests/interpreter/dbscript/opcodes.ts +257 -0
  568. package/src/domain/quests/interpreter/dbscript/registry.ts +1194 -0
  569. package/src/domain/quests/interpreter/dbscript/registryAreatriggerScripts.ts +539 -0
  570. package/src/domain/quests/interpreter/dbscript/registryAshenvale.ts +553 -0
  571. package/src/domain/quests/interpreter/dbscript/registryAzshara.ts +272 -0
  572. package/src/domain/quests/interpreter/dbscript/registryDarkshore.ts +637 -0
  573. package/src/domain/quests/interpreter/dbscript/registryDesolace.ts +501 -0
  574. package/src/domain/quests/interpreter/dbscript/registryDustwallowMarsh.ts +735 -0
  575. package/src/domain/quests/interpreter/dbscript/registryFelwood.ts +493 -0
  576. package/src/domain/quests/interpreter/dbscript/registryFeralas.ts +485 -0
  577. package/src/domain/quests/interpreter/dbscript/registryGoScripts.ts +203 -0
  578. package/src/domain/quests/interpreter/dbscript/registryMoonglade.ts +288 -0
  579. package/src/domain/quests/interpreter/dbscript/registryNpcProfessions.ts +230 -0
  580. package/src/domain/quests/interpreter/dbscript/registryNpcsSpecial.ts +545 -0
  581. package/src/domain/quests/interpreter/dbscript/registryRazorfenDowns.ts +293 -0
  582. package/src/domain/quests/interpreter/dbscript/registryRazorfenKraul.ts +221 -0
  583. package/src/domain/quests/interpreter/dbscript/registryRedridge.ts +112 -0
  584. package/src/domain/quests/interpreter/dbscript/registrySearingGorge.ts +125 -0
  585. package/src/domain/quests/interpreter/dbscript/registrySiblings.ts +51 -0
  586. package/src/domain/quests/interpreter/dbscript/registrySilverpineForest.ts +172 -0
  587. package/src/domain/quests/interpreter/dbscript/registryStonetalonMountains.ts +180 -0
  588. package/src/domain/quests/interpreter/dbscript/registryStormwindCity.ts +369 -0
  589. package/src/domain/quests/interpreter/dbscript/registryStranglethornVale.ts +115 -0
  590. package/src/domain/quests/interpreter/dbscript/registryStratholme.ts +146 -0
  591. package/src/domain/quests/interpreter/dbscript/registrySunkenTemple.ts +149 -0
  592. package/src/domain/quests/interpreter/dbscript/registrySwampOfSorrows.ts +163 -0
  593. package/src/domain/quests/interpreter/dbscript/registryTanaris.ts +318 -0
  594. package/src/domain/quests/interpreter/dbscript/registryTeldrassil.ts +120 -0
  595. package/src/domain/quests/interpreter/dbscript/registryTheBarrens.ts +603 -0
  596. package/src/domain/quests/interpreter/dbscript/registryThousandNeedles.ts +499 -0
  597. package/src/domain/quests/interpreter/dbscript/registryTirisfalGlades.ts +222 -0
  598. package/src/domain/quests/interpreter/dbscript/registryUngoroCrater.ts +291 -0
  599. package/src/domain/quests/interpreter/dbscript/registryWarEffort.ts +773 -0
  600. package/src/domain/quests/interpreter/dbscript/registryWesternPlaguelands.ts +206 -0
  601. package/src/domain/quests/interpreter/dbscript/registryWestfall.ts +190 -0
  602. package/src/domain/quests/interpreter/dbscript/registryWetlands.ts +186 -0
  603. package/src/domain/quests/interpreter/dbscript/registryWinterspring.ts +235 -0
  604. package/src/domain/quests/interpreter/dbscript/types.ts +817 -0
  605. package/src/domain/quests/interpreter/dbscript/vm.ts +171 -0
  606. package/src/domain/quests/interpreter/diff.ts +349 -0
  607. package/src/domain/quests/interpreter/fixtures/oracle-questlog-qi2.json +2417 -0
  608. package/src/domain/quests/interpreter/flags.ts +101 -0
  609. package/src/domain/quests/interpreter/index.ts +113 -0
  610. package/src/domain/quests/interpreter/live.ts +178 -0
  611. package/src/domain/quests/interpreter/types.ts +81 -0
  612. package/src/domain/quests/interpreter/updaters.ts +412 -0
  613. package/src/domain/quests/questCorpseUse.ts +155 -0
  614. package/src/domain/quests/questDialog.ts +43 -0
  615. package/src/domain/quests/questFight.ts +34 -0
  616. package/src/domain/quests/questObjectiveLabel.ts +39 -0
  617. package/src/domain/quests/questRewardChoice.ts +85 -0
  618. package/src/domain/quests/questScriptCredit.ts +26 -0
  619. package/src/domain/quests/questScriptItemUse.ts +74 -0
  620. package/src/domain/quests/questTameRods.ts +79 -0
  621. package/src/domain/quests/questlog.ts +1545 -0
  622. package/src/domain/quests/talkDeliver.ts +170 -0
  623. package/src/domain/raid/globalActionBar.ts +195 -0
  624. package/src/domain/raid/instanceRoster.ts +194 -0
  625. package/src/domain/raid/partySummon.ts +198 -0
  626. package/src/domain/raid/partyVault.ts +320 -0
  627. package/src/domain/raid/raidBossAbilities.ts +268 -0
  628. package/src/domain/raid/raidComp.ts +335 -0
  629. package/src/domain/raid/raidCustomRows.ts +453 -0
  630. package/src/domain/raid/raidEncounterGear.ts +298 -0
  631. package/src/domain/raid/raidEncounterTactics.ts +412 -0
  632. package/src/domain/raid/raidPlan.ts +509 -0
  633. package/src/domain/raid/raidPlanEdits.ts +98 -0
  634. package/src/domain/raid/raidPlanPacks.ts +480 -0
  635. package/src/domain/raid/raidRecovery.ts +183 -0
  636. package/src/domain/raid/raidRosterTemplate.ts +138 -0
  637. package/src/domain/rotation/auraSide.ts +68 -0
  638. package/src/domain/rotation/build.ts +3031 -0
  639. package/src/domain/rotation/classes/druid.ts +58 -0
  640. package/src/domain/rotation/classes/hooks.ts +59 -0
  641. package/src/domain/rotation/classes/hunter.ts +156 -0
  642. package/src/domain/rotation/classes/index.ts +104 -0
  643. package/src/domain/rotation/classes/mage.ts +99 -0
  644. package/src/domain/rotation/classes/paladin.ts +296 -0
  645. package/src/domain/rotation/classes/priest.ts +94 -0
  646. package/src/domain/rotation/classes/pullOpener.ts +92 -0
  647. package/src/domain/rotation/classes/rogue.ts +69 -0
  648. package/src/domain/rotation/classes/shaman.ts +29 -0
  649. package/src/domain/rotation/classes/supportSpec.ts +94 -0
  650. package/src/domain/rotation/classes/warlock.ts +81 -0
  651. package/src/domain/rotation/classes/warrior.ts +402 -0
  652. package/src/domain/rotation/classify.ts +1381 -0
  653. package/src/domain/rotation/condMetricPicker.ts +379 -0
  654. package/src/domain/rotation/consumables.ts +242 -0
  655. package/src/domain/rotation/evaluate.ts +1115 -0
  656. package/src/domain/rotation/finisherLadder.ts +145 -0
  657. package/src/domain/rotation/invent.ts +938 -0
  658. package/src/domain/rotation/killOrder.ts +30 -0
  659. package/src/domain/rotation/openerForm.ts +22 -0
  660. package/src/domain/rotation/paladinBuffs.ts +568 -0
  661. package/src/domain/rotation/prebuff.ts +283 -0
  662. package/src/domain/rotation/raidRowTuning.ts +34 -0
  663. package/src/domain/rotation/rotation.ts +11 -0
  664. package/src/domain/rotation/rotationProfiles.ts +180 -0
  665. package/src/domain/rotation/rotationSuggestions.ts +851 -0
  666. package/src/domain/rotation/ruleAfterChain.ts +49 -0
  667. package/src/domain/rotation/spec.ts +70 -0
  668. package/src/domain/rotation/spellPicker.ts +140 -0
  669. package/src/domain/rotation/stand.ts +143 -0
  670. package/src/domain/rotation/types.ts +718 -0
  671. package/src/domain/run/battlegroundRun.ts +111 -0
  672. package/src/domain/run/canEnterContext.ts +32 -0
  673. package/src/domain/run/death.ts +561 -0
  674. package/src/domain/run/deathRecovery.ts +289 -0
  675. package/src/domain/run/duel.ts +141 -0
  676. package/src/domain/run/dungeonRun.ts +344 -0
  677. package/src/domain/run/floorRest.ts +159 -0
  678. package/src/domain/run/honor.ts +557 -0
  679. package/src/domain/run/honorWeek.ts +180 -0
  680. package/src/domain/run/whenMap.ts +977 -0
  681. package/src/domain/scriptdev/arathiHighlands.ts +445 -0
  682. package/src/domain/scriptdev/ashenvale.ts +635 -0
  683. package/src/domain/scriptdev/ashenvaleHelpers.ts +1215 -0
  684. package/src/domain/scriptdev/azshara.ts +892 -0
  685. package/src/domain/scriptdev/blackfathomDeeps.ts +212 -0
  686. package/src/domain/scriptdev/blackrockDepths.ts +1434 -0
  687. package/src/domain/scriptdev/blackrockSpire.ts +730 -0
  688. package/src/domain/scriptdev/blackwingLair.ts +521 -0
  689. package/src/domain/scriptdev/burningSteppes.ts +62 -0
  690. package/src/domain/scriptdev/classFilter.ts +43 -0
  691. package/src/domain/scriptdev/darkshore.ts +817 -0
  692. package/src/domain/scriptdev/darkshoreHelpers.ts +853 -0
  693. package/src/domain/scriptdev/deadmines.ts +331 -0
  694. package/src/domain/scriptdev/desolace.ts +1239 -0
  695. package/src/domain/scriptdev/direMaul.ts +859 -0
  696. package/src/domain/scriptdev/durotar.ts +532 -0
  697. package/src/domain/scriptdev/dustwallowMarsh.ts +758 -0
  698. package/src/domain/scriptdev/dustwallowMarshHelpers.ts +994 -0
  699. package/src/domain/scriptdev/easternPlaguelands.ts +21 -0
  700. package/src/domain/scriptdev/felwood.ts +1055 -0
  701. package/src/domain/scriptdev/feralas.ts +571 -0
  702. package/src/domain/scriptdev/feralasHelpers.ts +838 -0
  703. package/src/domain/scriptdev/gnomeregan.ts +466 -0
  704. package/src/domain/scriptdev/guards.ts +616 -0
  705. package/src/domain/scriptdev/hinterlands.ts +693 -0
  706. package/src/domain/scriptdev/host.ts +1134 -0
  707. package/src/domain/scriptdev/index.ts +123 -0
  708. package/src/domain/scriptdev/instanceRaids.ts +136 -0
  709. package/src/domain/scriptdev/itemScripts.ts +37 -0
  710. package/src/domain/scriptdev/lochModan.ts +283 -0
  711. package/src/domain/scriptdev/maraudon.ts +232 -0
  712. package/src/domain/scriptdev/moltenCore.ts +831 -0
  713. package/src/domain/scriptdev/moonglade.ts +659 -0
  714. package/src/domain/scriptdev/moongladeHelpers.ts +933 -0
  715. package/src/domain/scriptdev/naxxramas.ts +577 -0
  716. package/src/domain/scriptdev/naxxramasConstruct.ts +364 -0
  717. package/src/domain/scriptdev/naxxramasFrostwyrm.ts +378 -0
  718. package/src/domain/scriptdev/naxxramasMilitary.ts +276 -0
  719. package/src/domain/scriptdev/npcProfessions.ts +1025 -0
  720. package/src/domain/scriptdev/npcsSpecial.ts +1379 -0
  721. package/src/domain/scriptdev/onyxiasLair.ts +313 -0
  722. package/src/domain/scriptdev/orgrimmar.ts +147 -0
  723. package/src/domain/scriptdev/professionSpecConsumer.ts +481 -0
  724. package/src/domain/scriptdev/razorfenDowns.ts +468 -0
  725. package/src/domain/scriptdev/razorfenKraul.ts +410 -0
  726. package/src/domain/scriptdev/redridgeMountains.ts +163 -0
  727. package/src/domain/scriptdev/registry.ts +945 -0
  728. package/src/domain/scriptdev/ruinsOfAhnqiraj.ts +356 -0
  729. package/src/domain/scriptdev/scarletMonastery.ts +713 -0
  730. package/src/domain/scriptdev/scholomance.ts +682 -0
  731. package/src/domain/scriptdev/searingGorge.ts +295 -0
  732. package/src/domain/scriptdev/shadowfangKeep.ts +181 -0
  733. package/src/domain/scriptdev/silithus.ts +71 -0
  734. package/src/domain/scriptdev/silverpineForest.ts +662 -0
  735. package/src/domain/scriptdev/stonetalonMountains.ts +493 -0
  736. package/src/domain/scriptdev/stormwindCity.ts +1192 -0
  737. package/src/domain/scriptdev/stranglethornVale.ts +402 -0
  738. package/src/domain/scriptdev/stratholme.ts +650 -0
  739. package/src/domain/scriptdev/stratholmeScripts.ts +505 -0
  740. package/src/domain/scriptdev/sunkenTemple.ts +736 -0
  741. package/src/domain/scriptdev/swampOfSorrows.ts +22 -0
  742. package/src/domain/scriptdev/tanaris.ts +391 -0
  743. package/src/domain/scriptdev/tanarisHelpers.ts +661 -0
  744. package/src/domain/scriptdev/teldrassil.ts +143 -0
  745. package/src/domain/scriptdev/templeOfAhnqiraj.ts +1013 -0
  746. package/src/domain/scriptdev/theBarrens.ts +709 -0
  747. package/src/domain/scriptdev/theBarrensHelpers.ts +1026 -0
  748. package/src/domain/scriptdev/thousandNeedles.ts +426 -0
  749. package/src/domain/scriptdev/thousandNeedlesHelpers.ts +566 -0
  750. package/src/domain/scriptdev/tirisfalGlades.ts +533 -0
  751. package/src/domain/scriptdev/types.ts +1026 -0
  752. package/src/domain/scriptdev/uldaman.ts +437 -0
  753. package/src/domain/scriptdev/ungoroCrater.ts +549 -0
  754. package/src/domain/scriptdev/ungoroCraterHelpers.ts +1006 -0
  755. package/src/domain/scriptdev/wailingCaverns.ts +700 -0
  756. package/src/domain/scriptdev/warEffort.ts +371 -0
  757. package/src/domain/scriptdev/westernPlaguelands.ts +952 -0
  758. package/src/domain/scriptdev/westfall.ts +767 -0
  759. package/src/domain/scriptdev/wetlands.ts +660 -0
  760. package/src/domain/scriptdev/winterspring.ts +482 -0
  761. package/src/domain/scriptdev/winterspringHelpers.ts +801 -0
  762. package/src/domain/scriptdev/worldBosses.ts +605 -0
  763. package/src/domain/scriptdev/zulfarrak.ts +478 -0
  764. package/src/domain/scriptdev/zulgurub.ts +1152 -0
  765. package/src/domain/sim/dummySim.ts +408 -0
  766. package/src/domain/sim/targetDummy.ts +29 -0
  767. package/src/domain/social/guild.ts +148 -0
  768. package/src/domain/spells/areaAuraMembership.ts +93 -0
  769. package/src/domain/spells/breakableStunCc.ts +166 -0
  770. package/src/domain/spells/cancelAura.ts +80 -0
  771. package/src/domain/spells/diminishing.ts +167 -0
  772. package/src/domain/spells/dispel.ts +149 -0
  773. package/src/domain/spells/dispelMechanic.ts +105 -0
  774. package/src/domain/spells/equipSpells.ts +247 -0
  775. package/src/domain/spells/learnOnTargets.ts +260 -0
  776. package/src/domain/spells/mergeSchoolImmunityFromRaw.ts +66 -0
  777. package/src/domain/spells/resurrectSpell.ts +124 -0
  778. package/src/domain/spells/spellPushback.ts +39 -0
  779. package/src/domain/spells/spellReflect.ts +43 -0
  780. package/src/domain/spells/stealth.ts +183 -0
  781. package/src/domain/spells/totem.ts +394 -0
  782. package/src/domain/spells/worldCast.ts +187 -0
  783. package/src/domain/world/areaTriggerLocks.ts +177 -0
  784. package/src/domain/world/dungeonMusic.ts +108 -0
  785. package/src/domain/world/gameEvents.ts +119 -0
  786. package/src/domain/world/gameObjects.ts +1030 -0
  787. package/src/domain/world/goEventFire.ts +234 -0
  788. package/src/domain/world/goMoTransport.ts +74 -0
  789. package/src/domain/world/goTransport.ts +81 -0
  790. package/src/domain/world/hazards.ts +459 -0
  791. package/src/domain/world/openLock.ts +398 -0
  792. package/src/domain/world/pools.ts +470 -0
  793. package/src/domain/world/restArea.ts +37 -0
  794. package/src/domain/world/weather.ts +201 -0
  795. package/src/domain/zoneAmbience.mjs +87 -0
  796. package/src/domain/zoneMusic.mjs +62 -0
  797. package/src/domain/zoneMusicQueue.mjs +7 -0
  798. package/src/engine/combat/activeSeal.ts +39 -0
  799. package/src/engine/combat/aiTargetResolve.ts +64 -0
  800. package/src/engine/combat/aoeCast.ts +289 -0
  801. package/src/engine/combat/applyConsumeAura.ts +74 -0
  802. package/src/engine/combat/applyDemonicSacrifice.ts +70 -0
  803. package/src/engine/combat/applyDispelMechanic.ts +30 -0
  804. package/src/engine/combat/applyHealEffect.ts +301 -0
  805. package/src/engine/combat/applySchoolAbsorb.ts +114 -0
  806. package/src/engine/combat/applySpell.ts +3169 -0
  807. package/src/engine/combat/applySpellLate.ts +2026 -0
  808. package/src/engine/combat/applySpellLateBag.ts +144 -0
  809. package/src/engine/combat/areaAura.ts +283 -0
  810. package/src/engine/combat/attackTable.ts +508 -0
  811. package/src/engine/combat/battleRez.ts +87 -0
  812. package/src/engine/combat/castAction.ts +36 -0
  813. package/src/engine/combat/castTargetGates.ts +75 -0
  814. package/src/engine/combat/castableKit.ts +68 -0
  815. package/src/engine/combat/ccMirrorUpgrade.ts +39 -0
  816. package/src/engine/combat/chainFan.ts +210 -0
  817. package/src/engine/combat/channel.ts +423 -0
  818. package/src/engine/combat/chaseCloseness.ts +95 -0
  819. package/src/engine/combat/cmangosCastGates.ts +129 -0
  820. package/src/engine/combat/combatFlag.ts +77 -0
  821. package/src/engine/combat/combatGeometry.ts +1329 -0
  822. package/src/engine/combat/combustion.ts +68 -0
  823. package/src/engine/combat/context.ts +730 -0
  824. package/src/engine/combat/createSession.ts +1165 -0
  825. package/src/engine/combat/creatureLeash.ts +38 -0
  826. package/src/engine/combat/crowdControl.ts +1259 -0
  827. package/src/engine/combat/dispelDuty.ts +54 -0
  828. package/src/engine/combat/dispelReflect.ts +609 -0
  829. package/src/engine/combat/displaceFloor.ts +113 -0
  830. package/src/engine/combat/duelBounds.ts +47 -0
  831. package/src/engine/combat/equippedItemGate.ts +297 -0
  832. package/src/engine/combat/evadeLifecycle.ts +63 -0
  833. package/src/engine/combat/eventAi.ts +2220 -0
  834. package/src/engine/combat/facing.ts +74 -0
  835. package/src/engine/combat/fearFlee.ts +137 -0
  836. package/src/engine/combat/fighterFactory.ts +1144 -0
  837. package/src/engine/combat/forceDespawnAction.ts +51 -0
  838. package/src/engine/combat/formulas.ts +807 -0
  839. package/src/engine/combat/friendlyFan.ts +55 -0
  840. package/src/engine/combat/groundPoolTick.ts +210 -0
  841. package/src/engine/combat/hazards.ts +114 -0
  842. package/src/engine/combat/healTargets.ts +226 -0
  843. package/src/engine/combat/heartbeatResist.ts +49 -0
  844. package/src/engine/combat/hostileItemUse.ts +75 -0
  845. package/src/engine/combat/interruptAuras.ts +66 -0
  846. package/src/engine/combat/itemRescue.ts +49 -0
  847. package/src/engine/combat/itemUse.ts +260 -0
  848. package/src/engine/combat/kitById.ts +23 -0
  849. package/src/engine/combat/knockBack.ts +201 -0
  850. package/src/engine/combat/leap.ts +89 -0
  851. package/src/engine/combat/mitigation.ts +587 -0
  852. package/src/engine/combat/modTaunt.ts +43 -0
  853. package/src/engine/combat/motionClaim.ts +268 -0
  854. package/src/engine/combat/motionGate.ts +150 -0
  855. package/src/engine/combat/motionGenerator.ts +27 -0
  856. package/src/engine/combat/navSight.ts +138 -0
  857. package/src/engine/combat/perfSink.ts +28 -0
  858. package/src/engine/combat/periodicDue.ts +55 -0
  859. package/src/engine/combat/petAuras.ts +86 -0
  860. package/src/engine/combat/pickAction.ts +3449 -0
  861. package/src/engine/combat/powerForm.ts +735 -0
  862. package/src/engine/combat/powerPools.ts +49 -0
  863. package/src/engine/combat/predicates.ts +538 -0
  864. package/src/engine/combat/procsDamage.ts +1823 -0
  865. package/src/engine/combat/reactiveGates.ts +135 -0
  866. package/src/engine/combat/roles.ts +389 -0
  867. package/src/engine/combat/rotationSubject.ts +78 -0
  868. package/src/engine/combat/ruleAfter.ts +106 -0
  869. package/src/engine/combat/seedDisplayAuras.ts +203 -0
  870. package/src/engine/combat/seedOocEffects.ts +317 -0
  871. package/src/engine/combat/seedSchoolImmunities.ts +45 -0
  872. package/src/engine/combat/session-types.ts +458 -0
  873. package/src/engine/combat/sessionApi.ts +1785 -0
  874. package/src/engine/combat/sessionCharge.ts +124 -0
  875. package/src/engine/combat/sessionChase.ts +869 -0
  876. package/src/engine/combat/sessionDeaths.ts +469 -0
  877. package/src/engine/combat/sessionFocus.ts +506 -0
  878. package/src/engine/combat/sessionFollow.ts +167 -0
  879. package/src/engine/combat/sessionGeometry.ts +188 -0
  880. package/src/engine/combat/sessionHome.ts +75 -0
  881. package/src/engine/combat/sessionInject.ts +719 -0
  882. package/src/engine/combat/sessionMechanicMove.ts +555 -0
  883. package/src/engine/combat/sessionMotion.ts +1553 -0
  884. package/src/engine/combat/sessionMotionKit.ts +247 -0
  885. package/src/engine/combat/sessionMoveIntent.ts +49 -0
  886. package/src/engine/combat/sessionMoveOrder.ts +200 -0
  887. package/src/engine/combat/sessionPathTo.ts +657 -0
  888. package/src/engine/combat/sessionPools.ts +688 -0
  889. package/src/engine/combat/sessionSteer.ts +144 -0
  890. package/src/engine/combat/sessionStepBack.ts +151 -0
  891. package/src/engine/combat/sessionStepWrap.ts +116 -0
  892. package/src/engine/combat/sessionView.ts +442 -0
  893. package/src/engine/combat/simEffects.ts +32 -0
  894. package/src/engine/combat/simFacade.ts +620 -0
  895. package/src/engine/combat/simPump.ts +264 -0
  896. package/src/engine/combat/simSnapshot.ts +165 -0
  897. package/src/engine/combat/simThreadPool.ts +35 -0
  898. package/src/engine/combat/skeramImages.ts +57 -0
  899. package/src/engine/combat/slowUpdate.ts +178 -0
  900. package/src/engine/combat/snapToFloor.ts +42 -0
  901. package/src/engine/combat/speedAura.ts +29 -0
  902. package/src/engine/combat/spellReagents.ts +71 -0
  903. package/src/engine/combat/stealthDetect.ts +93 -0
  904. package/src/engine/combat/stepBackMotion.ts +171 -0
  905. package/src/engine/combat/stepSession.ts +3102 -0
  906. package/src/engine/combat/summonCast.ts +243 -0
  907. package/src/engine/combat/thaddiusPolarity.ts +97 -0
  908. package/src/engine/combat/threat.ts +388 -0
  909. package/src/engine/combat/threatOps.ts +272 -0
  910. package/src/engine/combat/tickWorkerBody.ts +211 -0
  911. package/src/engine/combat/totemAuras.ts +122 -0
  912. package/src/engine/combat/triggerPayload.ts +42 -0
  913. package/src/engine/combat/triggeredCompanion.ts +63 -0
  914. package/src/engine/combat/types.ts +1897 -0
  915. package/src/engine/combat/useObjectTrap.ts +140 -0
  916. package/src/engine/combat/walkSurface.ts +54 -0
  917. package/src/engine/combat/weapon.ts +1248 -0
  918. package/src/engine/combat/worldFrame.ts +43 -0
  919. package/src/engine/combat.solo-golden.json +2242 -0
  920. package/src/engine/combat.ts +84 -0
  921. package/src/engine/core/detMath.ts +289 -0
  922. package/src/engine/core/events.ts +357 -0
  923. package/src/engine/core/rng.ts +36 -0
  924. package/src/engine/game/actionBars.ts +124 -0
  925. package/src/engine/game/activateObjectFromSpell.ts +320 -0
  926. package/src/engine/game/applyActiveObjectFromDbScript.ts +98 -0
  927. package/src/engine/game/applyDeathAndSpellScripts.ts +268 -0
  928. package/src/engine/game/applyDoorFromDbScript.ts +388 -0
  929. package/src/engine/game/applyEscortFromDbScript.ts +290 -0
  930. package/src/engine/game/applyGoSpellcasterCast.ts +40 -0
  931. package/src/engine/game/applyHoverFromDbScript.ts +110 -0
  932. package/src/engine/game/applyOocResurrect.ts +71 -0
  933. package/src/engine/game/applySpellDurability.ts +115 -0
  934. package/src/engine/game/applyTailFromDbScript.ts +478 -0
  935. package/src/engine/game/applyTerminateFromDbScript.ts +95 -0
  936. package/src/engine/game/auctionMail.ts +269 -0
  937. package/src/engine/game/bagOverflow.ts +130 -0
  938. package/src/engine/game/bank.ts +110 -0
  939. package/src/engine/game/barAutofill.ts +26 -0
  940. package/src/engine/game/battleground.ts +369 -0
  941. package/src/engine/game/combatEnemySpec.ts +216 -0
  942. package/src/engine/game/combatObjectTraps.ts +167 -0
  943. package/src/engine/game/combatSeed.ts +320 -0
  944. package/src/engine/game/combatSession.ts +3241 -0
  945. package/src/engine/game/combatSessionClock.ts +62 -0
  946. package/src/engine/game/companionQuestActions.ts +242 -0
  947. package/src/engine/game/companionTraining.ts +40 -0
  948. package/src/engine/game/consumables.ts +624 -0
  949. package/src/engine/game/context.ts +53 -0
  950. package/src/engine/game/createHealthstone.ts +45 -0
  951. package/src/engine/game/deathFlow.ts +127 -0
  952. package/src/engine/game/devGrant.ts +117 -0
  953. package/src/engine/game/dynamicObject.ts +365 -0
  954. package/src/engine/game/enchantItem.ts +177 -0
  955. package/src/engine/game/equipmentHelper.ts +806 -0
  956. package/src/engine/game/factionState.ts +108 -0
  957. package/src/engine/game/garmentsOoc.ts +69 -0
  958. package/src/engine/game/globalActionBar.ts +179 -0
  959. package/src/engine/game/goInteractQuestCredit.ts +51 -0
  960. package/src/engine/game/goMoTransportUse.ts +61 -0
  961. package/src/engine/game/goTransportUse.ts +60 -0
  962. package/src/engine/game/healthstoneUpkeep.ts +59 -0
  963. package/src/engine/game/killSkin.ts +124 -0
  964. package/src/engine/game/learnFromItem.ts +118 -0
  965. package/src/engine/game/loadReconcile.ts +551 -0
  966. package/src/engine/game/loot.ts +294 -0
  967. package/src/engine/game/macros.ts +125 -0
  968. package/src/engine/game/mail.ts +293 -0
  969. package/src/engine/game/meetingStoneQueue.ts +75 -0
  970. package/src/engine/game/meetingStoneUse.ts +54 -0
  971. package/src/engine/game/newGameState.ts +363 -0
  972. package/src/engine/game/oocAuraInterrupt.ts +92 -0
  973. package/src/engine/game/oocCast.ts +241 -0
  974. package/src/engine/game/oocCastEffects.ts +803 -0
  975. package/src/engine/game/oocCastMethods.ts +1077 -0
  976. package/src/engine/game/openLockFromSpell.ts +174 -0
  977. package/src/engine/game/outdoorPvp.ts +187 -0
  978. package/src/engine/game/outfitter.ts +644 -0
  979. package/src/engine/game/paladinBoard.ts +393 -0
  980. package/src/engine/game/partyAuras.ts +121 -0
  981. package/src/engine/game/persistCombatAuras.ts +91 -0
  982. package/src/engine/game/pets.ts +459 -0
  983. package/src/engine/game/prePullHealthstones.ts +154 -0
  984. package/src/engine/game/professions.ts +2227 -0
  985. package/src/engine/game/pruneStaleRuntime.ts +39 -0
  986. package/src/engine/game/questFightCredit.ts +36 -0
  987. package/src/engine/game/questItemOnCorpse.ts +166 -0
  988. package/src/engine/game/questItemOnCreature.ts +103 -0
  989. package/src/engine/game/questLog.ts +879 -0
  990. package/src/engine/game/questSpellComplete.ts +21 -0
  991. package/src/engine/game/questTurnIn.ts +598 -0
  992. package/src/engine/game/raidParty.ts +32 -0
  993. package/src/engine/game/reagentBuyIn.ts +39 -0
  994. package/src/engine/game/regenRest.ts +186 -0
  995. package/src/engine/game/rotation.ts +425 -0
  996. package/src/engine/game/runFullDungeon.ts +611 -0
  997. package/src/engine/game/runSupply.ts +80 -0
  998. package/src/engine/game/sanitizeDriftedItems.ts +135 -0
  999. package/src/engine/game/scriptDevGoUse.ts +397 -0
  1000. package/src/engine/game/scriptDevInnkeeper.ts +150 -0
  1001. package/src/engine/game/scriptDevProfessionSpec.ts +99 -0
  1002. package/src/engine/game/sendEventFromSpell.ts +87 -0
  1003. package/src/engine/game/sortContainers.ts +85 -0
  1004. package/src/engine/game/spellReputation.ts +69 -0
  1005. package/src/engine/game/squad/squadDungeonSeating.ts +197 -0
  1006. package/src/engine/game/squadDungeon.ts +4222 -0
  1007. package/src/engine/game/squadQuestShare.ts +260 -0
  1008. package/src/engine/game/summonObjectSlot.ts +69 -0
  1009. package/src/engine/game/summonObjectWild.ts +73 -0
  1010. package/src/engine/game/summoningRitualUse.ts +141 -0
  1011. package/src/engine/game/talents.ts +356 -0
  1012. package/src/engine/game/tamingRodUse.ts +66 -0
  1013. package/src/engine/game/tempSpawnCreature.ts +136 -0
  1014. package/src/engine/game/tickDungeonPatrolScripts.ts +205 -0
  1015. package/src/engine/game/tickTimedQuests.ts +28 -0
  1016. package/src/engine/game/trade.ts +586 -0
  1017. package/src/engine/game/travel.ts +1155 -0
  1018. package/src/engine/game/types.ts +1855 -0
  1019. package/src/engine/game/vendorOffers.ts +244 -0
  1020. package/src/engine/game/weaponImbueItem.ts +281 -0
  1021. package/src/engine/game/worldSession.ts +183 -0
  1022. package/src/engine/game/worldState.ts +166 -0
  1023. package/src/engine/game.ts +968 -0
  1024. package/src/engine/spells/GAP.md +67 -0
  1025. package/src/engine/spells/absorbs.ts +376 -0
  1026. package/src/engine/spells/addTargetTrigger.ts +53 -0
  1027. package/src/engine/spells/auraPerSecondCost.ts +50 -0
  1028. package/src/engine/spells/auraStacking.ts +497 -0
  1029. package/src/engine/spells/cmangos-special-cases-combustion.ts +13 -0
  1030. package/src/engine/spells/cmangos-special-cases-s18.ts +445 -0
  1031. package/src/engine/spells/cmangos-special-cases-s19.ts +324 -0
  1032. package/src/engine/spells/cmangos-special-cases-s20.ts +385 -0
  1033. package/src/engine/spells/cmangos-special-cases-s21.ts +116 -0
  1034. package/src/engine/spells/cmangos-special-cases-s22.ts +24 -0
  1035. package/src/engine/spells/cmangos-special-cases-s23.ts +52 -0
  1036. package/src/engine/spells/cmangos-special-cases.ts +1570 -0
  1037. package/src/engine/spells/conditions.ts +718 -0
  1038. package/src/engine/spells/effects.ts +203 -0
  1039. package/src/engine/spells/fixtures/oracle-effects-lock9a.json +1 -0
  1040. package/src/engine/spells/immunity.ts +942 -0
  1041. package/src/engine/spells/intentEffects.ts +351 -0
  1042. package/src/engine/spells/interpreter/GAPS.md +21 -0
  1043. package/src/engine/spells/interpreter/amount.ts +109 -0
  1044. package/src/engine/spells/interpreter/class-scripts-kit.ts +478 -0
  1045. package/src/engine/spells/interpreter/diff.ts +246 -0
  1046. package/src/engine/spells/interpreter/duration.ts +90 -0
  1047. package/src/engine/spells/interpreter/form-attrs.json +1 -0
  1048. package/src/engine/spells/interpreter/form-attrs.ts +95 -0
  1049. package/src/engine/spells/interpreter/handlers/aura-remove.ts +113 -0
  1050. package/src/engine/spells/interpreter/handlers/auras-control.ts +1547 -0
  1051. package/src/engine/spells/interpreter/handlers/auras-core.ts +1583 -0
  1052. package/src/engine/spells/interpreter/handlers/auras-misc.ts +1774 -0
  1053. package/src/engine/spells/interpreter/handlers/effect-disenchant.ts +17 -0
  1054. package/src/engine/spells/interpreter/handlers/effect-skinning.ts +20 -0
  1055. package/src/engine/spells/interpreter/handlers/effects-action-utility.ts +1455 -0
  1056. package/src/engine/spells/interpreter/handlers/effects-core.ts +432 -0
  1057. package/src/engine/spells/interpreter/handlers/effects-remainder.ts +105 -0
  1058. package/src/engine/spells/interpreter/handlers/effects-summon-item.ts +687 -0
  1059. package/src/engine/spells/interpreter/handlers/mod-increase-energy-percent.ts +36 -0
  1060. package/src/engine/spells/interpreter/handlers/mod-increase-energy.ts +36 -0
  1061. package/src/engine/spells/interpreter/handlers/periodic-trigger-zero.ts +327 -0
  1062. package/src/engine/spells/interpreter/handlers/procs.ts +131 -0
  1063. package/src/engine/spells/interpreter/handlers/registry.ts +975 -0
  1064. package/src/engine/spells/interpreter/handlers/shared.ts +667 -0
  1065. package/src/engine/spells/interpreter/handlers.ts +9 -0
  1066. package/src/engine/spells/interpreter/hunter-kit.ts +202 -0
  1067. package/src/engine/spells/interpreter/index.ts +525 -0
  1068. package/src/engine/spells/interpreter/item-triggers.ts +1121 -0
  1069. package/src/engine/spells/interpreter/lift-consume-energy.ts +37 -0
  1070. package/src/engine/spells/interpreter/mage-portals.ts +37 -0
  1071. package/src/engine/spells/interpreter/materialize-charm.ts +88 -0
  1072. package/src/engine/spells/interpreter/materialize-dispel-mechanic.ts +25 -0
  1073. package/src/engine/spells/interpreter/materialize-rating-buffs.ts +81 -0
  1074. package/src/engine/spells/interpreter/materialize-speed.ts +109 -0
  1075. package/src/engine/spells/interpreter/materialize-spell-magnet.ts +22 -0
  1076. package/src/engine/spells/interpreter/opcodes.ts +789 -0
  1077. package/src/engine/spells/interpreter/paladin-kit.ts +95 -0
  1078. package/src/engine/spells/interpreter/paladin-seals.ts +499 -0
  1079. package/src/engine/spells/interpreter/priest-warlock-kit.ts +135 -0
  1080. package/src/engine/spells/interpreter/proc.ts +443 -0
  1081. package/src/engine/spells/interpreter/registry/helpers.ts +16 -0
  1082. package/src/engine/spells/interpreter/registry/index.ts +216 -0
  1083. package/src/engine/spells/interpreter/registry/packs/class-abilities.ts +304 -0
  1084. package/src/engine/spells/interpreter/registry/packs/dire-maul.ts +44 -0
  1085. package/src/engine/spells/interpreter/registry/packs/dummy-script-tail.ts +1065 -0
  1086. package/src/engine/spells/interpreter/registry/packs/ex-wave-m.ts +70 -0
  1087. package/src/engine/spells/interpreter/registry/packs/life-tap.ts +107 -0
  1088. package/src/engine/spells/interpreter/registry/packs/paladin.ts +246 -0
  1089. package/src/engine/spells/interpreter/registry/packs/raid-script-summons.ts +26 -0
  1090. package/src/engine/spells/interpreter/registry/packs/raid-threat-wipe.ts +22 -0
  1091. package/src/engine/spells/interpreter/registry/packs/shaman.ts +214 -0
  1092. package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-a.ts +269 -0
  1093. package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-b.ts +370 -0
  1094. package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-c.ts +172 -0
  1095. package/src/engine/spells/interpreter/registry/packs/si4-dummy-hunter.ts +60 -0
  1096. package/src/engine/spells/interpreter/registry/packs/si4-dummy-warrior.ts +31 -0
  1097. package/src/engine/spells/interpreter/registry/packs/si4-script-generic-a.ts +114 -0
  1098. package/src/engine/spells/interpreter/registry/packs/si4-script-generic-b.ts +249 -0
  1099. package/src/engine/spells/interpreter/registry/packs/si4-script-generic-c.ts +233 -0
  1100. package/src/engine/spells/interpreter/registry/types.ts +48 -0
  1101. package/src/engine/spells/interpreter/talent-scripted.ts +329 -0
  1102. package/src/engine/spells/interpreter/targeting.ts +90 -0
  1103. package/src/engine/spells/interpreter/types-intent.ts +1501 -0
  1104. package/src/engine/spells/interpreter/types.ts +419 -0
  1105. package/src/engine/spells/interpreter/warrior-druid-kit.ts +314 -0
  1106. package/src/engine/spells/interpreter/weapon-imbue-kit.ts +384 -0
  1107. package/src/engine/spells/interrupt.ts +217 -0
  1108. package/src/engine/spells/meleeAttackReset.ts +60 -0
  1109. package/src/engine/spells/oocTriggerSpell.ts +49 -0
  1110. package/src/engine/spells/overrideClassScripts.ts +319 -0
  1111. package/src/engine/spells/parryHaste.ts +20 -0
  1112. package/src/engine/spells/procs.ts +300 -0
  1113. package/src/engine/spells/recovery.ts +203 -0
  1114. package/src/engine/spells/scriptTargetDest.ts +76 -0
  1115. package/src/engine/spells/scriptTargets.ts +85 -0
  1116. package/src/engine/spells/singleTargetAura.ts +82 -0
  1117. package/src/engine/spells/specialCasePayloads.ts +57 -0
  1118. package/src/engine/spells/spellAttributes.ts +249 -0
  1119. package/src/engine/spells/spellBonus.ts +143 -0
  1120. package/src/engine/spells/spellModIntents.ts +419 -0
  1121. package/src/engine/spells/spellMods.ts +283 -0
  1122. package/src/engine/spells/spellRadius.ts +15 -0
  1123. package/src/engine/spells/trapObjects.ts +26 -0
  1124. package/src/json.d.ts +7 -0
  1125. package/src/persistence/memoryRepository.ts +23 -0
  1126. package/src/persistence/saveBackups.ts +162 -0
  1127. package/src/persistence/saveFile.ts +68 -0
  1128. package/src/persistence/saveRepository.ts +11 -0
  1129. package/src/persistence/saveShape.ts +668 -0
  1130. package/src/progression/leveling.ts +89 -0
  1131. package/src/progression/rest.ts +1434 -0
  1132. package/src/progression/training.ts +226 -0
  1133. package/src/progression/xpGain.ts +369 -0
  1134. package/src/quests/quests.ts +1580 -0
  1135. package/src/world/aoePull.ts +198 -0
  1136. package/src/world/areaTableDbc.ts +39 -0
  1137. package/src/world/areaTableMapIdPairs.ts +141 -0
  1138. package/src/world/bakeSlug.ts +43 -0
  1139. package/src/world/continuousDungeon.ts +1250 -0
  1140. package/src/world/dungeonBakeProjection.ts +190 -0
  1141. package/src/world/dungeonMapDensity.ts +342 -0
  1142. package/src/world/dungeonMapProjection.ts +135 -0
  1143. package/src/world/dungeonNav.ts +904 -0
  1144. package/src/world/dungeonNpcSim.ts +147 -0
  1145. package/src/world/dungeonObjectives.ts +234 -0
  1146. package/src/world/dungeonPreset.ts +35 -0
  1147. package/src/world/dungeonRoute.ts +311 -0
  1148. package/src/world/dungeonRouteGeometry.ts +732 -0
  1149. package/src/world/dungeonRouteOrder.ts +1037 -0
  1150. package/src/world/dungeonWingRooms.ts +426 -0
  1151. package/src/world/escort.ts +296 -0
  1152. package/src/world/goPoolRoll.ts +75 -0
  1153. package/src/world/instanceObjects.ts +785 -0
  1154. package/src/world/instances.ts +1572 -0
  1155. package/src/world/meetingStones.ts +56 -0
  1156. package/src/world/navmeshFloors.ts +145 -0
  1157. package/src/world/nearGrid.ts +167 -0
  1158. package/src/world/packBudget.ts +613 -0
  1159. package/src/world/rareRoll.ts +335 -0
  1160. package/src/world/routeAuthoring.ts +132 -0
  1161. package/src/world/routeEdit.ts +209 -0
  1162. package/src/world/world.ts +812 -0
  1163. package/src/world/zoneHazards.ts +47 -0
@@ -0,0 +1,1547 @@
1
+ /** SI2.5 / SI3 handlers — auras-control (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_TOTAL_STAT_PERCENTAGE,
11
+ } from '../opcodes.ts';
12
+ import type {
13
+ HandlerState,
14
+ } from './shared.ts';
15
+ import {
16
+ MOD_INCREASE_HEALTH_CUR_HP_IDS,
17
+ MOD_INCREASE_HEALTH_PRESERVE_PCT_IDS,
18
+ MOD_THREAT_LEVEL_SCALE,
19
+ BASE_ATTACK_TIME_MS,
20
+ CONTROL_CONSOLE_APPLY_SPELLS,
21
+ CONTROL_CONSOLE_REMOVE_CASTER_SPELLS,
22
+ CONTROL_CONSOLE_REMOVE_TARGET_SPELL,
23
+ CONTROL_CONSOLE_DESPAWN_MS,
24
+ CONTROL_CONSOLE_SPELL_ID,
25
+ MUTATE_BUG_SPELL_ID,
26
+ SHADE_OF_ARAN_DRINK_SPELL_ID,
27
+ FORM_CAT,
28
+ FORM_TREE,
29
+ FORM_TRAVEL,
30
+ FORM_AQUA,
31
+ FORM_BEAR,
32
+ FORM_GHOUL,
33
+ FORM_DIREBEAR,
34
+ FORM_CREATUREBEAR,
35
+ FORM_GHOSTWOLF,
36
+ FORM_BATTLESTANCE,
37
+ FORM_DEFENSIVESTANCE,
38
+ FORM_BERSERKERSTANCE,
39
+ FORM_MOONKIN,
40
+ FORM_SPIRITOFREDEMPTION,
41
+ POWER_MANA,
42
+ POWER_RAGE,
43
+ POWER_ENERGY,
44
+ TRANQUILIZING_POISON_IDS,
45
+ TRANQUILIZING_POISON_SLEEP,
46
+ SPIRIT_SHADE_VISUAL_ID,
47
+ TRACK_HUMANOIDS_SPELL,
48
+ FUROR_ENERGY_SPELL,
49
+ FUROR_RAGE_SPELL,
50
+ SCHOOLS,
51
+ schoolOf,
52
+ schoolFromSingleBitMask,
53
+ durationMsResolved,
54
+ withPpc,
55
+ trunc,
56
+ pushOrMergePolymorphIncapacitate,
57
+ } from './shared.ts';
58
+ // ── SPELL_AURA_MOD_SILENCE (27) ───────────────────────────────────────────── Cite:
59
+ // SpellAuras.cpp:2778–2804 HandleAuraModSilence Bake: cc silence. Cite: map-spell-effects.mjs:708–714.
60
+ export function handleModSilence(
61
+ state: HandlerState,
62
+ raw: RawSpellEffect,
63
+ _slot: number,
64
+ _effectType: number,
65
+ ): void {
66
+ // C++: if (!Real) return. Interpret is apply-time snapshot (Real=true). Cite: :2781–2783.
67
+ const dur = durationMsResolved(state);
68
+ // SetFlag UNIT_FLAG_SILENCED; remove only when no other MOD_SILENCE remains.
69
+ // Cite: :2789 apply; :2799–2802 remove.
70
+ state.effects.push({
71
+ kind: 'cc',
72
+ control: 'silence',
73
+ mechanic: 'silence',
74
+ durationMs: dur,
75
+ school: schoolOf(state.spell),
76
+ });
77
+ state.role = state.role || 'control';
78
+ // On apply: interrupt current spells with PreventionType == SILENCE.
79
+ // Cite: :2790–2794.
80
+ state.intents.push({ kind: 'mod_silence_interrupt' });
81
+ }
82
+
83
+ // ── SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN (87) ── a physical-only mask becomes physical_taken_pct;
84
+ // magic or multi-bit becomes damage_taken_pct with a schoolMask. Cite: Unit.cpp:7108, :7628.
85
+ export function handleModDamagePercentTaken(
86
+ state: HandlerState,
87
+ raw: RawSpellEffect,
88
+ _slot: number,
89
+ _effectType: number,
90
+ ): void {
91
+ const { min } = effectAmountRange(raw, state.ctx);
92
+ const dur = durationMsResolved(state);
93
+ const misc = raw.miscValue | 0;
94
+ // Physical-only (SPELL_SCHOOL_MASK_NORMAL=1): Barkskin-class. Cite: Unit.cpp:7628.
95
+ if (misc === 1) {
96
+ const tagged = withHostile(
97
+ { kind: 'buff' as const, mod: 'physical_taken_pct' as const, amount: min, durationMs: dur },
98
+ raw.targetA | 0,
99
+ min,
100
+ );
101
+ state.effects.push(tagged as SpellEffect);
102
+ } else {
103
+ // CoE misc 20 fire|frost +6; CoS 96 shadow|arcane; Stormstrike 8 nature +20.
104
+ // Cite: spell_template 1490/17862/17364 EffectMiscValue; Unit.cpp:7628; KI-767.
105
+ const tagged = withHostile(
106
+ {
107
+ kind: 'buff' as const,
108
+ mod: 'damage_taken_pct' as const,
109
+ amount: min,
110
+ durationMs: dur,
111
+ ...(misc ? { schoolMask: misc } : {}),
112
+ },
113
+ raw.targetA | 0,
114
+ min,
115
+ );
116
+ state.effects.push(tagged as SpellEffect);
117
+ }
118
+ state.role = state.role || 'buff';
119
+ }
120
+
121
+ // ── SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT (161) ── an always-on flat regen. The DBC amount is health
122
+ // per five seconds, so an amplitude of 0 becomes a 5000 ms tick. Cite: Player.cpp:2407-2412.
123
+ export function handleModHealthRegenInCombat(
124
+ state: HandlerState,
125
+ raw: RawSpellEffect,
126
+ _slot: number,
127
+ _effectType: number,
128
+ ): void {
129
+ const { min } = effectAmountRange(raw, state.ctx);
130
+ const dur = durationMsResolved(state);
131
+ // Amount is HP per 5 sec (Demon Skin "3 Health per 5 sec"); rate-match via tickMs 5000.
132
+ // Cite: Player.cpp:2407–2412; StatSystem.cpp:555 mp5/5; KI-575/576/685.
133
+ state.effects.push({
134
+ kind: 'restore_health',
135
+ amountPerTick: Math.max(1, min),
136
+ tickMs: (raw.amplitude | 0) || 5000,
137
+ durationMs: dur,
138
+ });
139
+ state.role = state.role || 'buff';
140
+ // Does NOT set outOfCombatOnly — applies in combat. Cite: map-spell-effects.mjs aura 161.
141
+ }
142
+
143
+ // ── SPELL_AURA_MOD_HEALING_PCT (118) ── emitted as healing_taken_pct, a percent rather than a flat
144
+ // amount. The C++ takes the largest negative and the largest positive separately. Cite: Unit.cpp:7239.
145
+ export function handleModHealingPct(
146
+ state: HandlerState,
147
+ raw: RawSpellEffect,
148
+ _slot: number,
149
+ _effectType: number,
150
+ ): void {
151
+ const { min } = effectAmountRange(raw, state.ctx);
152
+ const dur = durationMsResolved(state);
153
+ // Signed percent (Mortal Strike −50). Live sum matches physical_taken_pct; single-debuff
154
+ // MS/Wound is identical to C++ GetMaxNegativeAuraModifier. Cite: Unit.cpp:7239–7245.
155
+ const tagged = withHostile(
156
+ { kind: 'buff' as const, mod: 'healing_taken_pct' as const, amount: min, durationMs: dur },
157
+ raw.targetA | 0,
158
+ min,
159
+ );
160
+ state.effects.push(tagged as SpellEffect);
161
+ state.role = state.role || 'buff';
162
+ }
163
+
164
+ // ── SPELL_AURA_MOD_CONFUSE (5) ── Real applications only, baked as an incapacitate with the polymorph
165
+ // mechanic. Cite: SpellAuras.cpp:2354-2366 HandleModConfuse.
166
+ export function handleModConfuse(
167
+ state: HandlerState,
168
+ raw: RawSpellEffect,
169
+ _slot: number,
170
+ _effectType: number,
171
+ ): void {
172
+ // TARGET_UNIT_CASTER stays a row: applySpell's isSelfTargetedSpell gate keeps it off a foe and
173
+ // still lands the self-cast. Cite: roles.ts:27; applySpell.ts:1554; KI-1017.
174
+ const dur = durationMsResolved(state);
175
+ // Blind is disoriented and breaks on damage; Polymorph keeps polymorph. The default is polymorph so
176
+ // a confuse and a transform still merge on one diminishing-returns step.
177
+ const named = state.spell.mechanic;
178
+ const mechanic =
179
+ named === 'disoriented' || named === 'polymorph' || named === 'sleep' || named === 'shackle'
180
+ ? named
181
+ : 'polymorph';
182
+ pushOrMergePolymorphIncapacitate(state, {
183
+ kind: 'cc',
184
+ control: 'incapacitate',
185
+ mechanic,
186
+ durationMs: dur,
187
+ school: schoolOf(state.spell),
188
+ breakOnDamage: true,
189
+ });
190
+ // SetConfused + getHostileRefManager().HandleSuppressed — runtime only. Cite: :2363–2365.
191
+ }
192
+
193
+ // ── SPELL_AURA_MOD_CHARM (6) / AOE_CHARM (177) ── the same TakeCharmOf thrall; the advertised form is
194
+ // the single-target handler and the other the AoE one. Cite: SpellAuras.cpp:2282-2351.
195
+ function emitTakeCharmOf(state: HandlerState, advertised: boolean): void {
196
+ // Not charm yourself. Cite: HandleModCharm :2289–2291; HandleAoECharm :2338–2340.
197
+ if (state.ctx.unitTargetIsSelf === true) return;
198
+ // Missing caster → return. Cite: :2293–2295 / :2342–2344. Bake-thin has implicit caster.
199
+
200
+ const dur = durationMsResolved(state);
201
+ // TakeCharmOf thrall surface (faction flip + PetAI). Cite: Unit.cpp:11328; KI-896.
202
+ state.effects.push({
203
+ kind: 'cc',
204
+ control: 'charm',
205
+ mechanic: 'charm',
206
+ durationMs: dur,
207
+ school: schoolOf(state.spell),
208
+ });
209
+ state.role = state.role || 'control';
210
+
211
+ const intent: InterpretIntent = {
212
+ kind: 'mod_charm',
213
+ spellId: state.spell.id | 0,
214
+ durationMs: dur,
215
+ advertised,
216
+ };
217
+ // Player advertised charm is unique: BreakCharmOutgoing(true) then TakeCharmOf.
218
+ // AOE_CHARM is non-advertised — skip. Cite: :2304–2307 vs :2346–2348.
219
+ if (advertised && state.ctx.casterIsPlayer !== false) {
220
+ intent.breakOutgoing = true;
221
+ }
222
+ state.intents.push(intent);
223
+ }
224
+
225
+ export function handleModCharm(
226
+ state: HandlerState,
227
+ _raw: RawSpellEffect,
228
+ _slot: number,
229
+ _effectType: number,
230
+ ): void {
231
+ // C++: if (!Real) return. Cite: :2284–2285.
232
+ emitTakeCharmOf(state, true);
233
+ }
234
+
235
+ export function handleAoECharm(
236
+ state: HandlerState,
237
+ _raw: RawSpellEffect,
238
+ _slot: number,
239
+ _effectType: number,
240
+ ): void {
241
+ // C++: if (!Real) return. Cite: :2333–2334. TakeCharmOf(target, GetId(), false) — private set, co-exists
242
+ // with other charms. Cite: SpellAuras.cpp:2346–2348 (de8f729); Unit.cpp:11350 m_charmedUnitsPrivate.
243
+ emitTakeCharmOf(state, false);
244
+ }
245
+
246
+ // ── SPELL_AURA_DISPEL_IMMUNITY (41) ── unmapped in the bake, so the intent carries the dispel type.
247
+ // Cite: SpellAuras.cpp:3053-3059; Unit.cpp ApplySpellDispelImmunity :7697-7702.
248
+ export function handleDispelImmunity(
249
+ state: HandlerState,
250
+ raw: RawSpellEffect,
251
+ _slot: number,
252
+ _effectType: number,
253
+ ): void {
254
+ // C++: if (!Real) return. Cite: :3056–3057.
255
+ const dispelType = raw.miscValue | 0;
256
+ const dur = durationMsResolved(state);
257
+ // Emitted as an EFFECT, not only an intent: intents are dropped by the resolver, so an intent-only
258
+ // dispel immunity never reached combat and Stoneform's poison immunity was inert.
259
+ if (dispelType > 0) {
260
+ state.effects.push({
261
+ kind: 'dispel_immunity',
262
+ dispelType,
263
+ durationMs: dur,
264
+ positive: true,
265
+ });
266
+ state.role = state.role || 'buff';
267
+ }
268
+ const intent: InterpretIntent = {
269
+ kind: 'dispel_immunity',
270
+ dispelType,
271
+ durationMs: dur,
272
+ };
273
+ // apply + ATTR_EX IMMUNITY_PURGES_EFFECT → RemoveAurasWithDispelType. Cite: Unit.cpp:7701–7702.
274
+ if (state.ctx.immunityPurgesEffect === true) {
275
+ intent.purgeDispelType = true;
276
+ }
277
+ state.intents.push(intent);
278
+ }
279
+
280
+ // ── SPELL_AURA_PERIODIC_LEECH (53) ── baked as a plain dot with no heal transfer.
281
+ // Cite: SpellAuras.cpp:3247-3265 HandlePeriodicLeech; PeriodicTick :4592-4682.
282
+ export function handlePeriodicLeech(
283
+ state: HandlerState,
284
+ raw: RawSpellEffect,
285
+ _slot: number,
286
+ _effectType: number,
287
+ ): void {
288
+ // The bonus fold is cast-time and the bake keeps base points, so the dot shape matches the bake and
289
+ // combat materializes the transfer from the leech-heal intent.
290
+ const { min, pointsPerComboPoint } = effectAmountRange(raw, state.ctx);
291
+ const dur = durationMsResolved(state);
292
+ const tickMs = (raw.amplitude | 0) || 3000;
293
+ const clamped = Math.max(1, min);
294
+ state.effects.push(
295
+ withPpc(
296
+ {
297
+ kind: 'dot' as const,
298
+ school: schoolOf(state.spell),
299
+ min: clamped,
300
+ max: clamped,
301
+ durationMs: dur,
302
+ tickMs,
303
+ },
304
+ pointsPerComboPoint,
305
+ ) as SpellEffect,
306
+ );
307
+
308
+ // The tick also heals the beneficiary: the damage times the multiplier, defaulting to 1. The resolver
309
+ // stamps that multiple onto the matching dot. Cite: SpellAuras.cpp:4677-4682 (no heal threat).
310
+ const multRaw = Number(raw.multipleValue) || 0;
311
+ const multipleValue = multRaw > 0 ? multRaw : 1;
312
+ state.intents.push({ kind: 'periodic_leech_heal', multipleValue });
313
+ }
314
+
315
+ // ── SPELL_AURA_PERIODIC_HEALTH_FUNNEL (62) ── the victim is the CASTER and the beneficiary the aura
316
+ // target, the opposite of periodic leech. Cite: SpellAuras.cpp:3285-3304.
317
+ export function handlePeriodicHealthFunnel(
318
+ state: HandlerState,
319
+ raw: RawSpellEffect,
320
+ _slot: number,
321
+ _effectType: number,
322
+ ): void {
323
+ // m_isPeriodic = apply; amount gets SpellDamageBonusDone on apply. Cite: :3287–3303.
324
+ const { min, pointsPerComboPoint } = effectAmountRange(raw, state.ctx);
325
+ const dur = durationMsResolved(state);
326
+ const tickMs = (raw.amplitude | 0) || 3000;
327
+ const clamped = Math.max(1, min);
328
+ const multRaw = Number(raw.multipleValue) || 0;
329
+ const multipleValue = multRaw > 0 ? multRaw : 1;
330
+ state.effects.push(
331
+ withPpc(
332
+ {
333
+ kind: 'dot' as const,
334
+ school: schoolOf(state.spell),
335
+ min: clamped,
336
+ max: clamped,
337
+ durationMs: dur,
338
+ tickMs,
339
+ leechMultiple: multipleValue,
340
+ healthFunnel: true,
341
+ },
342
+ pointsPerComboPoint,
343
+ ) as SpellEffect,
344
+ );
345
+ state.intents.push({ kind: 'periodic_health_funnel', multipleValue });
346
+ }
347
+
348
+ // ── SPELL_AURA_RETAIN_COMBO_POINTS (148) ── apply is a no-op; expiring by time removes the amount from
349
+ // the combo target. Premeditation is 2 points over 10 s. Cite: SpellAuras.cpp:4436-4452.
350
+ export function handleRetainComboPoints(
351
+ state: HandlerState,
352
+ raw: RawSpellEffect,
353
+ _slot: number,
354
+ _effectType: number,
355
+ ): void {
356
+ // C++: if (!Real) return; player only. Cite: :4438–4443.
357
+ if (state.ctx.unitTargetIsPlayer === false) {
358
+ state.intents.push({ kind: 'skip_effect', reason: 'RETAIN_COMBO_POINTS non-player target' });
359
+ return;
360
+ }
361
+ const { min } = effectAmountRange(raw, state.ctx);
362
+ const dur = durationMsResolved(state);
363
+ const amount = Math.max(0, Math.trunc(min));
364
+ if (amount <= 0) return;
365
+ state.effects.push({ kind: 'retain_combo_points', amount, durationMs: dur });
366
+ state.intents.push({ kind: 'retain_combo_points', amount, durationMs: dur });
367
+ }
368
+
369
+ // ── SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS (131) ─────────────────────────
370
+ // Cite: SpellAuras.cpp:192; Unit.cpp:7471 GetTotalAuraModifierByMiscMask (creature type mask).
371
+ export function handleModRangedAttackPowerVersus(
372
+ state: HandlerState,
373
+ raw: RawSpellEffect,
374
+ _slot: number,
375
+ _effectType: number,
376
+ ): void {
377
+ const { min } = effectAmountRange(raw, state.ctx);
378
+ const dur = durationMsResolved(state);
379
+ const creatureTypeMask = raw.miscValue | 0;
380
+ state.intents.push({ kind: 'mod_ranged_attack_power_versus', creatureTypeMask, amount: min, durationMs: dur });
381
+ state.effects.push({
382
+ kind: 'buff', mod: 'ranged_attack_power_versus', amount: min, durationMs: dur, creatureTypeMask,
383
+ } as SpellEffect);
384
+ state.role = state.role || 'buff';
385
+ }
386
+
387
+ // ── SPELL_AURA_MOD_SHAPESHIFT (36) ── baked as a shapeshift effect carrying the form.
388
+ // Cite: SpellAuras.cpp:1709-1976 HandleAuraModShapeshift; HandleShapeshiftBoosts :4223-4344.
389
+ export function handleModShapeshift(
390
+ state: HandlerState,
391
+ raw: RawSpellEffect,
392
+ _slot: number,
393
+ _effectType: number,
394
+ ): void {
395
+ // C++: if (!Real) return. Cite: :1711–1712. Unknown SpellShapeshiftFormEntry → error log + return. SI5
396
+ // DBC gate. Cite: :1716–1720.
397
+ const form = raw.miscValue | 0;
398
+ state.effects.push({ kind: 'shapeshift', form });
399
+ state.role = state.role || 'form';
400
+
401
+ const intent: InterpretIntent = { kind: 'mod_shapeshift', form };
402
+
403
+ // Form → display / power. Cite: :1727–1800 switch (form).
404
+ switch (form) {
405
+ case FORM_CAT:
406
+ intent.displayIdAlliance = 892;
407
+ intent.displayIdHorde = 8571;
408
+ intent.powerType = POWER_ENERGY;
409
+ intent.boostSpellIds = [3025];
410
+ intent.hotWSpellId = 24900;
411
+ intent.removeRootAndSlow = true;
412
+ intent.removeWaterWalk = true;
413
+ intent.trackHumanoidsSpellId = TRACK_HUMANOIDS_SPELL;
414
+ intent.furorEnergySpellId = FUROR_ENERGY_SPELL;
415
+ break;
416
+ case FORM_TRAVEL:
417
+ intent.displayId = 632;
418
+ intent.boostSpellIds = [5419];
419
+ intent.removeRootAndSlow = true;
420
+ intent.removeWaterWalk = true;
421
+ break;
422
+ case FORM_AQUA:
423
+ intent.displayId = 2428;
424
+ intent.boostSpellIds = [5421];
425
+ intent.removeRootAndSlow = true;
426
+ intent.removeWaterWalk = true;
427
+ break;
428
+ case FORM_BEAR:
429
+ intent.displayIdAlliance = 2281;
430
+ intent.displayIdHorde = 2289;
431
+ intent.powerType = POWER_RAGE;
432
+ intent.boostSpellIds = [1178, 21178];
433
+ intent.hotWSpellId = 24899;
434
+ intent.removeRootAndSlow = true;
435
+ intent.removeWaterWalk = true;
436
+ intent.furorRageSpellId = FUROR_RAGE_SPELL;
437
+ break;
438
+ case FORM_GHOUL:
439
+ // Alliance-only display 10045; Horde leaves 0. Cite: :1749–1752.
440
+ intent.displayIdAlliance = 10045;
441
+ break;
442
+ case FORM_DIREBEAR:
443
+ intent.displayIdAlliance = 2281;
444
+ intent.displayIdHorde = 2289;
445
+ intent.powerType = POWER_RAGE;
446
+ intent.boostSpellIds = [9635, 21178];
447
+ intent.hotWSpellId = 24899;
448
+ intent.removeRootAndSlow = true;
449
+ intent.removeWaterWalk = true;
450
+ intent.furorRageSpellId = FUROR_RAGE_SPELL;
451
+ break;
452
+ case FORM_CREATUREBEAR:
453
+ intent.displayId = 902;
454
+ break;
455
+ case FORM_GHOSTWOLF:
456
+ intent.displayId = 4613;
457
+ intent.removeWaterWalk = true;
458
+ break;
459
+ case FORM_MOONKIN:
460
+ // Spirit Shade Visual 24809 → native display + early return if non-player caster.
461
+ // Cite: :1767–1774.
462
+ if ((state.spell.id | 0) === SPIRIT_SHADE_VISUAL_ID) {
463
+ intent.spiritShadeNativeDisplay = true;
464
+ } else {
465
+ intent.displayIdAlliance = 15374;
466
+ intent.displayIdHorde = 15375;
467
+ }
468
+ intent.boostSpellIds = [24905];
469
+ intent.removeRootAndSlow = true;
470
+ intent.removeWaterWalk = true;
471
+ break;
472
+ case FORM_TREE:
473
+ intent.displayId = 864;
474
+ intent.boostSpellIds = [5420];
475
+ intent.removeRootAndSlow = true;
476
+ intent.removeWaterWalk = true;
477
+ break;
478
+ case FORM_BATTLESTANCE:
479
+ intent.powerType = POWER_RAGE;
480
+ intent.boostSpellIds = [21156];
481
+ break;
482
+ case FORM_DEFENSIVESTANCE:
483
+ intent.powerType = POWER_RAGE;
484
+ intent.boostSpellIds = [7376];
485
+ break;
486
+ case FORM_BERSERKERSTANCE:
487
+ intent.powerType = POWER_RAGE;
488
+ intent.boostSpellIds = [7381];
489
+ break;
490
+ case FORM_SPIRITOFREDEMPTION:
491
+ intent.displayId = 16031;
492
+ // spellId2 second for remove order. Cite: :4271–4272.
493
+ intent.boostSpellIds = [27792, 27795];
494
+ break;
495
+ default:
496
+ // FORM_AMBIENT / SHADOW / STEALTH / CREATURECAT / etc. — no model/power switch.
497
+ // Cite: :1783–1786 / :4274–4283.
498
+ break;
499
+ }
500
+
501
+ // Apply removes the other form, sets the display and power, and runs the boosts; remove restores the
502
+ // display. Furor, Track Humanoids and Leader of the Pack are runtime, off the spellbook.
503
+ state.intents.push(intent);
504
+ }
505
+
506
+ // ── SPELL_AURA_MOD_INVISIBILITY (18) ─────────────────────────────────────── Cite:
507
+ // SpellAuras.cpp:2626–2675 HandleInvisibility Bake: unmapped. Intent carries type + strength.
508
+ export function handleModInvisibility(
509
+ state: HandlerState,
510
+ raw: RawSpellEffect,
511
+ _slot: number,
512
+ _effectType: number,
513
+ ): void {
514
+ const { min } = effectAmountRange(raw, state.ctx);
515
+ const dur = durationMsResolved(state);
516
+ // AddInvisibilityValue(misc, ±amount); mask when value>0. Cite: :2630–2633. Visibility / glow / interrupt
517
+ // flags are SI5 runtime. Cite: :2634–2674. Stealth/invis strength. Cite: SpellAuras.cpp:2626–2675.
518
+ state.effects.push({
519
+ kind: 'mod_invisibility',
520
+ invisibilityType: raw.miscValue | 0,
521
+ amount: min,
522
+ durationMs: dur,
523
+ } as never);
524
+ state.role = state.role || 'buff';
525
+ }
526
+
527
+ // ── SPELL_AURA_MOD_BLOCK_PERCENT (51) ── baked as a block buff.
528
+ // Cite: SpellAuras.cpp:3789-3800 HandleAuraModBlockPercent.
529
+ export function handleModBlockPercent(
530
+ state: HandlerState,
531
+ raw: RawSpellEffect,
532
+ _slot: number,
533
+ _effectType: number,
534
+ ): void {
535
+ const { min } = effectAmountRange(raw, state.ctx);
536
+ const dur = durationMsResolved(state);
537
+ // Engine BuffMod block (same surface as dodge/parry). Cite: fighterFactory applyBuffMod.
538
+ const tagged = withHostile(
539
+ { kind: 'buff' as const, mod: 'block' as const, amount: min, durationMs: dur },
540
+ raw.targetA | 0,
541
+ min,
542
+ );
543
+ state.effects.push(tagged as SpellEffect);
544
+ state.role = state.role || 'buff';
545
+ // Intent retained for non-player flat path / SI5 exclusivity notes.
546
+ const intent: InterpretIntent = {
547
+ kind: 'mod_block_percent',
548
+ amount: min,
549
+ durationMs: dur,
550
+ };
551
+ // Non-player: m_modBlockChance ±amount. Cite: :3793–3796.
552
+ // Player: UpdateBlockPercentage() recompute. Cite: :3799.
553
+ if (state.ctx.unitTargetIsPlayer === false) {
554
+ intent.nonPlayerFlat = true;
555
+ }
556
+ state.intents.push(intent);
557
+ }
558
+
559
+ // ── SPELL_AURA_PERIODIC_MANA_LEECH (64) ── baked as a negative power restore.
560
+ // Cite: SpellAuras.cpp:3268-3282 HandlePeriodicManaLeech; PeriodicTick :4740-4807.
561
+ export function handlePeriodicManaLeech(
562
+ state: HandlerState,
563
+ raw: RawSpellEffect,
564
+ _slot: number,
565
+ _effectType: number,
566
+ ): void {
567
+ // Handler arms m_isPeriodic; Tranquilizing Poison expire special on remove.
568
+ // Cite: :3270 / :3272–3281.
569
+ const { min } = effectAmountRange(raw, state.ctx);
570
+ const dur = durationMsResolved(state);
571
+ // Bake: amountPerTick = −max(1, |min|). Cite: map-spell-effects.mjs:825–827.
572
+ // The drained pool is EffectMiscValue, and a tick on any other pool is skipped. Cite: :4746-4753.
573
+ state.effects.push({
574
+ kind: 'restore_power',
575
+ amountPerTick: -Math.max(1, Math.abs(min)),
576
+ powerType: raw.miscValue | 0,
577
+ tickMs: (raw.amplitude | 0) || 1000,
578
+ durationMs: dur,
579
+ });
580
+
581
+ // Tick: drain target power, gain = drain * EffectMultipleValue.
582
+ // Cite: :4747–4806. Gain only when caster max power > 0.
583
+ const multRaw = Number(raw.multipleValue) || 0;
584
+ const intent: InterpretIntent = {
585
+ kind: 'periodic_mana_leech',
586
+ powerType: raw.miscValue | 0,
587
+ multipleValue: multRaw,
588
+ };
589
+ // Expire special. Cite: :3274–3280.
590
+ if (TRANQUILIZING_POISON_IDS.has(state.spell.id | 0)) {
591
+ intent.expireCastSpellId = TRANQUILIZING_POISON_SLEEP;
592
+ }
593
+ state.intents.push(intent);
594
+ }
595
+
596
+ // ── SPELL_AURA_MOD_STEALTH (16) ── baked as a stealth strength plus its break flags.
597
+ // Cite: SpellAuras.cpp:2563-2614 HandleModStealth.
598
+ export function handleModStealth(
599
+ state: HandlerState,
600
+ raw: RawSpellEffect,
601
+ _slot: number,
602
+ _effectType: number,
603
+ ): void {
604
+ const { min } = effectAmountRange(raw, state.ctx);
605
+ const dur = durationMsResolved(state);
606
+ // Add the stealth strength for the type; a Real apply also fires the stealth interrupt flags and the
607
+ // visibility change, and a remove restores it. Cite: SpellAuras.cpp:2566-2612.
608
+ const effect: SpellEffect = {
609
+ kind: 'stealth',
610
+ strength: Math.max(0, min),
611
+ durationMs: dur,
612
+ };
613
+ // The break flags come from the spell's own interrupt flags: the bake-time override is unset at
614
+ // runtime, so every live stealth aura fell back to the default and lost four of its bits.
615
+ const spellAif = ((state.spell as { auraInterruptFlags?: number }).auraInterruptFlags ?? 0) | 0;
616
+ const aif = ((state.ctx.auraInterruptFlags ?? 0) | 0) || spellAif;
617
+ if (aif) effect.breakFlags = aif;
618
+ state.effects.push(effect);
619
+ state.role = state.role || 'stealth';
620
+ }
621
+
622
+ // ── SPELL_AURA_MOD_CRIT_PERCENT (52) ── baked as a crit buff.
623
+ // Cite: SpellAuras.cpp:3815-3848 HandleAuraModCritPercent.
624
+ export function handleModCritPercent(
625
+ state: HandlerState,
626
+ raw: RawSpellEffect,
627
+ _slot: number,
628
+ _effectType: number,
629
+ ): void {
630
+ const { min } = effectAmountRange(raw, state.ctx);
631
+ const dur = durationMsResolved(state);
632
+ // Whole percentage points → BuffMod crit (equip Increased Critical / temporary crit auras).
633
+ // Cite: schema BuffMod crit; characterRatings critChance; fighterFactory applyBuffMod.
634
+ const tagged = withHostile(
635
+ { kind: 'buff' as const, mod: 'crit' as const, amount: min, durationMs: dur },
636
+ raw.targetA | 0,
637
+ min,
638
+ );
639
+ state.effects.push(tagged as SpellEffect);
640
+ state.role = state.role || 'buff';
641
+ const intent: InterpretIntent = {
642
+ kind: 'mod_crit_percent',
643
+ amount: min,
644
+ durationMs: dur,
645
+ };
646
+ // Non-player: all m_modCritChance ±amount. Cite: :3819–3823.
647
+ if (state.ctx.unitTargetIsPlayer === false) {
648
+ intent.nonPlayerFlat = true;
649
+ }
650
+ // A player Real apply is weapon-dependent: an equipped-item class of -1 lands flat on main, off and
651
+ // ranged crit, and anything else goes through the weapon-dependent mods. Cite: :3827-3847.
652
+ const eqClass = state.ctx.equippedItemClass;
653
+ if (eqClass !== undefined) {
654
+ intent.equippedItemClass = eqClass | 0;
655
+ }
656
+ state.intents.push(intent);
657
+ }
658
+
659
+ // ── SPELL_AURA_MOD_DODGE_PERCENT (49) ────────────────────────────────────── Cite:
660
+ // SpellAuras.cpp:3775–3787 HandleAuraModDodgePercent Bake: buff dodge. Cite: map-spell-effects.mjs:787–790.
661
+ export function handleModDodgePercent(
662
+ state: HandlerState,
663
+ raw: RawSpellEffect,
664
+ _slot: number,
665
+ _effectType: number,
666
+ ): void {
667
+ const { min } = effectAmountRange(raw, state.ctx);
668
+ const dur = durationMsResolved(state);
669
+ // Player: UpdateDodgePercentage(); NPC: m_modDodgeChance ±amount. Cite: :3778–3785. Bake surface is flat
670
+ // dodge BuffMod points. Cite: map-spell-effects.mjs:787–790.
671
+ const tagged = withHostile(
672
+ { kind: 'buff' as const, mod: 'dodge' 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
+ // ── SPELL_AURA_MOD_RESISTANCE_PCT (101) ── a physical mask becomes armor_pct, not flat armor.
681
+ // Cite: SpellAuras.cpp:3388-3408 HandleModResistancePercent.
682
+ export function handleModResistancePct(
683
+ state: HandlerState,
684
+ raw: RawSpellEffect,
685
+ _slot: number,
686
+ _effectType: number,
687
+ ): void {
688
+ const { min } = effectAmountRange(raw, state.ctx);
689
+ // C++: if (!m_modifier.m_amount) return. Cite: :3390–3391.
690
+ if (!min) return;
691
+ const dur = durationMsResolved(state);
692
+ // Per-school TOTAL_PCT for bits in misc mask. Cite: :3395–3407.
693
+ state.intents.push({
694
+ kind: 'mod_resistance_pct',
695
+ schoolMask: raw.miscValue | 0,
696
+ amount: min,
697
+ durationMs: dur,
698
+ });
699
+ }
700
+
701
+ // ── SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT (150) ── the percent path of the block-value handler,
702
+ // player-only. Cite: SpellAuras.cpp:4426-4433 HandleShieldBlockValue.
703
+ export function handleModShieldBlockValuePct(
704
+ state: HandlerState,
705
+ raw: RawSpellEffect,
706
+ _slot: number,
707
+ _effectType: number,
708
+ ): void {
709
+ // C++: non-player → no-op (only Player branch). Cite: :4432–4433.
710
+ if (state.ctx.unitTargetIsPlayer === false) return;
711
+
712
+ const { min } = effectAmountRange(raw, state.ctx);
713
+ const dur = durationMsResolved(state);
714
+ // HandleBaseModValue(SHIELD_BLOCK_VALUE, PCT_MOD, amount, apply). Cite: :4428–4433.
715
+ // Aura 150 → PCT_MOD. Cite: :4429–4430.
716
+ const tagged = withHostile(
717
+ { kind: 'buff' as const, mod: 'block_value_pct' as const, amount: min, durationMs: dur },
718
+ raw.targetA | 0,
719
+ min,
720
+ );
721
+ state.effects.push(tagged as SpellEffect);
722
+ state.role = state.role || 'buff';
723
+ state.intents.push({
724
+ kind: 'mod_shield_blockvalue_pct',
725
+ amount: min,
726
+ durationMs: dur,
727
+ });
728
+ }
729
+
730
+ // ── SPELL_AURA_MOD_ATTACKSPEED (9) ── baked as a haste buff, and the C++ applies it to the MAIN hand
731
+ // only, unlike melee haste 138. Cite: SpellAuras.cpp:3922-3927.
732
+ export function handleModAttackSpeed(
733
+ state: HandlerState,
734
+ raw: RawSpellEffect,
735
+ _slot: number,
736
+ _effectType: number,
737
+ ): void {
738
+ const { min } = effectAmountRange(raw, state.ctx);
739
+ const dur = durationMsResolved(state);
740
+ // ApplyAttackTimePercentMod(BASE_ATTACK, amount, apply). Cite: :3924–3926.
741
+ const tagged = withHostile(
742
+ { kind: 'buff' as const, mod: 'haste' as const, amount: min, durationMs: dur },
743
+ raw.targetA | 0,
744
+ min,
745
+ );
746
+ state.effects.push(tagged as SpellEffect);
747
+ state.role = state.role || 'buff';
748
+ }
749
+
750
+ // ── SPELL_AURA_MOD_INVISIBILITY_DETECTION (19) ── the play surface is an aura chip; the world
751
+ // invisibility simulation is residual. Cite: SpellAuras.cpp:2677-2717 HandleInvisibilityDetect.
752
+ export function handleModInvisibilityDetection(
753
+ state: HandlerState,
754
+ raw: RawSpellEffect,
755
+ _slot: number,
756
+ _effectType: number,
757
+ ): void {
758
+ const { min } = effectAmountRange(raw, state.ctx);
759
+ const dur = durationMsResolved(state);
760
+ // Set the detect mask and raise the value when higher; a remove takes the maximum among the
761
+ // remaining auras of the same type. Cite: SpellAuras.cpp:2687-2712.
762
+ state.intents.push({
763
+ kind: 'mod_invisibility_detection',
764
+ invisibilityType: raw.miscValue | 0,
765
+ amount: min,
766
+ durationMs: dur,
767
+ });
768
+ // Catalog / OOC: not a pure mana sink. Cite: schema mod_invisibility_detection.
769
+ if (!state.effects.some((e) => e.kind === 'mod_invisibility_detection')) {
770
+ state.effects.push({
771
+ kind: 'mod_invisibility_detection',
772
+ amount: min,
773
+ durationMs: dur < 0 ? 0 : dur,
774
+ });
775
+ }
776
+ state.role = state.role || 'buff';
777
+ }
778
+
779
+ // ── SPELL_AURA_MOD_PACIFY (25) ── baked as pacify: no melee or ranged, casts still allowed.
780
+ // Cite: SpellAuras.cpp:4382-4388 HandleAuraModPacify.
781
+ export function handleModPacify(
782
+ state: HandlerState,
783
+ raw: RawSpellEffect,
784
+ _slot: number,
785
+ _effectType: number,
786
+ ): void {
787
+ // SetFlag / RemoveFlag UNIT_FLAG_PACIFIED. Cite: :4384–4387.
788
+ const dur = durationMsResolved(state);
789
+ state.effects.push({
790
+ kind: 'pacify',
791
+ durationMs: dur || 1000,
792
+ });
793
+ state.role = state.role || 'buff';
794
+ }
795
+
796
+ // ── SPELL_AURA_TRACK_CREATURES (44) ── minimap tracking, so the bake is empty and the intent carries
797
+ // the creature-type bit. Cite: SpellAuras.cpp:2152-2161 HandleAuraTrackCreatures.
798
+ export function handleTrackCreatures(
799
+ state: HandlerState,
800
+ raw: RawSpellEffect,
801
+ _slot: number,
802
+ _effectType: number,
803
+ ): void {
804
+ // C++: non-player → return. Cite: :2154–2155.
805
+ if (state.ctx.unitTargetIsPlayer === false) return;
806
+
807
+ const creatureType = raw.miscValue | 0;
808
+ // Bit = 1 << (misc − 1). Cite: :2158–2160.
809
+ // misc ≤ 0 would shift into large values — still emit (C++ does the same).
810
+ const trackFlag = creatureType > 0 ? (1 << (creatureType - 1)) : 0;
811
+ const dur = durationMsResolved(state);
812
+ // Minimap tracking aura. Cite: SpellAuras.cpp:2152–2161.
813
+ state.effects.push({
814
+ kind: 'track_creatures',
815
+ creatureType,
816
+ trackFlag,
817
+ durationMs: dur,
818
+ } as never);
819
+ state.role = state.role || 'buff';
820
+ }
821
+
822
+ // ── SPELL_AURA_REFLECT_SPELLS_SCHOOL (74) ── one reflect effect per school bit.
823
+ // Cite: SpellAuras.cpp:135; Unit::GetReflectChance :3425-3431; enrich-dispel-reflect.mjs:74-91.
824
+ export function handleReflectSpellsSchool(
825
+ state: HandlerState,
826
+ raw: RawSpellEffect,
827
+ _slot: number,
828
+ _effectType: number,
829
+ ): void {
830
+ const { min } = effectAmountRange(raw, state.ctx);
831
+ // pct ≤ 0 → skip (Fire/Frost Ward carry aura 74 at 0%). Cite: enrich-dispel-reflect.mjs:81.
832
+ if (min <= 0) return;
833
+ const dur = durationMsResolved(state);
834
+ const mask = raw.miscValue | 0;
835
+ // GetTotalAuraModifierByMiscMask(SPELL_AURA_REFLECT_SPELLS_SCHOOL, schoolMask).
836
+ // Cite: Unit.cpp:3430. Multi-bit → one reflect effect per school (enricher).
837
+ const schools: School[] = [];
838
+ for (let i = 0; i < 7; i++) {
839
+ if ((mask & (1 << i)) !== 0) schools.push(SCHOOLS[i]!);
840
+ }
841
+ if (schools.length === 0) {
842
+ // mask 0 → all-school reflect. Cite: enrich-dispel-reflect.mjs:87.
843
+ state.effects.push({ kind: 'reflect', pct: min, durationMs: dur });
844
+ } else {
845
+ for (const school of schools) {
846
+ state.effects.push({ kind: 'reflect', pct: min, school, durationMs: dur });
847
+ }
848
+ }
849
+ state.role = state.role || 'buff';
850
+ }
851
+
852
+ // ── SPELL_AURA_CHANNEL_DEATH_ITEM (86) ── apply is a no-op; the work runs on a Real remove by death
853
+ // for a player caster. Cite: SpellAuras.cpp:2070-2123 HandleChannelDeathItem.
854
+ export function handleChannelDeathItem(
855
+ state: HandlerState,
856
+ raw: RawSpellEffect,
857
+ _slot: number,
858
+ _effectType: number,
859
+ ): void {
860
+ const { min } = effectAmountRange(raw, state.ctx);
861
+ // C++: amount ≤ 0 → return. Cite: :2077–2078.
862
+ if (min <= 0) {
863
+ state.effects.push({ kind: 'client_inform' });
864
+ return;
865
+ }
866
+ const itemType = (raw.itemType ?? 0) | 0;
867
+ // EffectItemType == 0 → return. Cite: :2081–2082.
868
+ // Bake rawEffects often omit itemType (column not extracted) → 0 → no intent.
869
+ if (!itemType) return;
870
+ // Drain Soul family: grant the item on a channel kill, with the Soul Shard specials only for 6265.
871
+ // Cite: SpellAuras.cpp:2070-2123.
872
+ state.effects.push({
873
+ kind: 'channel_death_item',
874
+ itemType,
875
+ count: min,
876
+ soulShard: itemType === 6265,
877
+ } as never);
878
+ state.role = state.role || 'dot';
879
+ }
880
+
881
+ // ── SPELL_AURA_MOD_HEALTH_REGEN_PERCENT (88) ── out-of-combat regen only.
882
+ // Cite: SpellAuras.cpp:149 HandleNoImmediateEffect; Player.cpp:2395-2398 RegenerateHealth.
883
+ export function handleModHealthRegenPercent(
884
+ state: HandlerState,
885
+ raw: RawSpellEffect,
886
+ _slot: number,
887
+ _effectType: number,
888
+ ): void {
889
+ const { min } = effectAmountRange(raw, state.ctx);
890
+ const dur = durationMsResolved(state);
891
+ // addvalue *= (100 + amount) / 100 while !IsInCombat(). Cite: Player.cpp:2395–2398.
892
+ // Permanent racials (Troll Regeneration) have DurationIndex → 0; do not invent 15s.
893
+ state.effects.push({
894
+ kind: 'mod_health_regen_percent',
895
+ amount: min,
896
+ durationMs: dur,
897
+ } as never);
898
+ state.role = state.role || 'buff';
899
+ }
900
+
901
+ // ── SPELL_AURA_MOD_TARGET_RESISTANCE (123) ─────────────────────────────────
902
+ // Cite: SpellAuras.cpp:184; Unit.cpp:3890–3894 (pen = −aura amount; DBC amount typically negative).
903
+ export function handleModTargetResistance(
904
+ state: HandlerState,
905
+ raw: RawSpellEffect,
906
+ _slot: number,
907
+ _effectType: number,
908
+ ): void {
909
+ const { min } = effectAmountRange(raw, state.ctx);
910
+ const dur = durationMsResolved(state);
911
+ const schoolMask = raw.miscValue | 0;
912
+ state.intents.push({ kind: 'mod_target_resistance', schoolMask, amount: min, durationMs: dur });
913
+ state.effects.push({
914
+ kind: 'buff', mod: 'target_resistance', amount: min, durationMs: dur, schoolMask,
915
+ } as SpellEffect);
916
+ state.role = state.role || 'buff';
917
+ }
918
+
919
+ // ── SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE (137) ── all_stats_pct when the misc value is -1, else the
920
+ // per-stat percent mod. Cite: SpellAuras.cpp:3537-3568 HandleModTotalPercentStat.
921
+ export function handleModTotalStatPercentage(
922
+ state: HandlerState,
923
+ raw: RawSpellEffect,
924
+ slot: number,
925
+ effectType: number,
926
+ ): void {
927
+ const misc = raw.miscValue | 0;
928
+ // C++: misc < −1 || > 4 → error return. Cite: :3539–3543.
929
+ if (misc < -1 || misc > 4) {
930
+ state.unhandled.push({
931
+ slot,
932
+ effect: effectType,
933
+ auraName: SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE,
934
+ reason: `MOD_TOTAL_STAT_PERCENTAGE miscValue ${misc} out of range [-1,4]`,
935
+ });
936
+ return;
937
+ }
938
+ const { min } = effectAmountRange(raw, state.ctx);
939
+ const dur = durationMsResolved(state);
940
+ // A misc value of -1 means all five stats. Always the percent name, never the flat one — see
941
+ // STAT_MOD_PCT. Cite: SpellAuras.cpp:3551-3558.
942
+ const mod: BuffMod = STAT_MOD_PCT[String(misc)] ?? 'all_stats_pct';
943
+ const tagged = withHostile(
944
+ { kind: 'buff' as const, mod, amount: min, durationMs: dur },
945
+ raw.targetA | 0,
946
+ min,
947
+ );
948
+ state.effects.push(tagged as SpellEffect);
949
+ state.role = state.role || 'buff';
950
+
951
+ // Stamina + SPELL_ATTR_IS_ABILITY: rescale current HP by max-HP ratio. Cite: :3561–3567. Gate:
952
+ // ctx.spellIsAbility === true (bake-thin omits). STAT_STAMINA = 2. Cite: SharedDefines Stats.
953
+ if (misc === 2 && state.ctx.spellIsAbility === true) {
954
+ state.intents.push({ kind: 'mod_total_stat_pct_stamina_hp_scale' });
955
+ }
956
+ }
957
+
958
+ // ── SPELL_AURA_MOD_SHIELD_BLOCKVALUE (158) ── the flat path of the block-value handler, player-only,
959
+ // baked as a block-value buff. Cite: SpellAuras.cpp:4426-4433 HandleShieldBlockValue.
960
+ export function handleModShieldBlockValue(
961
+ state: HandlerState,
962
+ raw: RawSpellEffect,
963
+ _slot: number,
964
+ _effectType: number,
965
+ ): void {
966
+ // C++: non-player → no-op (only Player branch). Cite: :4432–4433.
967
+ if (state.ctx.unitTargetIsPlayer === false) return;
968
+
969
+ const { min } = effectAmountRange(raw, state.ctx);
970
+ const dur = durationMsResolved(state);
971
+ // HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, amount, apply). Cite: :4428–4433.
972
+ // Aura 158 → FLAT_MOD (150 → PCT_MOD). Cite: :4429–4430.
973
+ const tagged = withHostile(
974
+ { kind: 'buff' as const, mod: 'block_value' as const, amount: min, durationMs: dur },
975
+ raw.targetA | 0,
976
+ min,
977
+ );
978
+ state.effects.push(tagged as SpellEffect);
979
+ state.role = state.role || 'buff';
980
+ state.intents.push({
981
+ kind: 'mod_shield_blockvalue',
982
+ amount: min,
983
+ durationMs: dur,
984
+ });
985
+ }
986
+
987
+ // ── SI3 aura batch 7 (this claim list) ─────────────────────────────────────
988
+
989
+ // ── SPELL_AURA_REFLECT_SPELLS (28) ── all schools, no mask, unlike 74.
990
+ // Cite: SpellAuras.cpp:89; Unit::GetReflectChance :3425-3431; enrich-dispel-reflect.mjs:82-83.
991
+ export function handleReflectSpells(
992
+ state: HandlerState,
993
+ raw: RawSpellEffect,
994
+ _slot: number,
995
+ _effectType: number,
996
+ ): void {
997
+ const { min } = effectAmountRange(raw, state.ctx);
998
+ // pct ≤ 0 → skip. Cite: enrich-dispel-reflect.mjs:81.
999
+ if (min <= 0) return;
1000
+ const dur = durationMsResolved(state);
1001
+ // No school field = all-school reflect. Cite: Unit.cpp:3428; enrich:83.
1002
+ state.effects.push({ kind: 'reflect', pct: min, durationMs: dur });
1003
+ state.role = state.role || 'buff';
1004
+ }
1005
+
1006
+ // ── SPELL_AURA_MOD_INCREASE_HEALTH (34) ── a FLAT max-health mod. Proxying it as stamina times ten
1007
+ // turned Anastari's +2000 into +20k. Cite: SpellAuras.cpp:3658-3716.
1008
+ export function handleModIncreaseHealth(
1009
+ state: HandlerState,
1010
+ raw: RawSpellEffect,
1011
+ _slot: number,
1012
+ _effectType: number,
1013
+ ): void {
1014
+ const { min } = effectAmountRange(raw, state.ctx);
1015
+ const dur = durationMsResolved(state);
1016
+ // A flat max-health amount, not stamina, which would multiply by the health-per-stamina factor.
1017
+ // Hostile is stamped for oracle parity with the enriched buffs.
1018
+ const tagged = withHostile(
1019
+ {
1020
+ kind: 'buff' as const,
1021
+ mod: 'max_health' as const,
1022
+ amount: Math.max(1, min),
1023
+ durationMs: dur,
1024
+ },
1025
+ raw.targetA | 0,
1026
+ min,
1027
+ );
1028
+ state.effects.push(tagged as SpellEffect);
1029
+ state.role = state.role || 'buff';
1030
+
1031
+ const id = state.spell.id | 0;
1032
+ // Id specials beyond generic TOTAL_VALUE. Cite: :3662–3708.
1033
+ if (MOD_INCREASE_HEALTH_CUR_HP_IDS.has(id)) {
1034
+ // Real-only current HP adjust. Cite: :3675–3695.
1035
+ state.intents.push({
1036
+ kind: 'mod_increase_health_special',
1037
+ currentHealthAdjust: true,
1038
+ });
1039
+ } else if (MOD_INCREASE_HEALTH_PRESERVE_PCT_IDS.has(id)) {
1040
+ // Real-only preserve %. Cite: :3700–3707.
1041
+ state.intents.push({
1042
+ kind: 'mod_increase_health_special',
1043
+ preserveHealthPercent: true,
1044
+ });
1045
+ }
1046
+ }
1047
+
1048
+ // ── SPELL_AURA_MOD_DISARM (67) ───────────────────────────────────────────── Cite:
1049
+ // SpellAuras.cpp:2426–2451 HandleAuraModDisarm Bake: cc disarm. Cite: map-spell-effects.mjs:837–842.
1050
+ export function handleModDisarm(
1051
+ state: HandlerState,
1052
+ raw: RawSpellEffect,
1053
+ _slot: number,
1054
+ _effectType: number,
1055
+ ): void {
1056
+ // C++: if (!Real) return. Cite: :2428–2429.
1057
+ // Remove: keep flag while any MOD_DISARM remains. Cite: :2433–2434 — SI5 runtime.
1058
+ const dur = durationMsResolved(state);
1059
+ // ApplyModFlag(UNIT_FLAG_DISARMED). Cite: :2436.
1060
+ state.effects.push({
1061
+ kind: 'cc',
1062
+ control: 'disarm',
1063
+ mechanic: 'disarm',
1064
+ durationMs: dur || 10_000,
1065
+ school: schoolOf(state.spell),
1066
+ });
1067
+ state.role = state.role || 'control';
1068
+
1069
+ // Feral / no-weapon shapeshift: skip attack-time path. Cite: :2438–2440.
1070
+ if (state.ctx.unitTargetNoWeaponShapeShift === true) return;
1071
+ // Player: SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME) on apply. Cite: :2442–2447.
1072
+ // Bake-thin omit unitTargetIsPlayer → player path (emit intent).
1073
+ if (state.ctx.unitTargetIsPlayer === false) {
1074
+ // Non-player still UpdateDamagePhysical(BASE_ATTACK). Cite: :2450 — SI5 runtime.
1075
+ return;
1076
+ }
1077
+ state.intents.push({
1078
+ kind: 'mod_disarm_attack_time',
1079
+ baseAttackTimeMs: BASE_ATTACK_TIME_MS,
1080
+ });
1081
+ }
1082
+
1083
+ // ── SPELL_AURA_MOD_THREAT (10) ── baked as a threat modifier buff by school mask.
1084
+ // Cite: SpellAuras.cpp:2806-2838 HandleModThreat.
1085
+ export function handleModThreat(
1086
+ state: HandlerState,
1087
+ raw: RawSpellEffect,
1088
+ _slot: number,
1089
+ _effectType: number,
1090
+ ): void {
1091
+ // C++: if (!Real) return; !IsAlive() return. Cite: :2808–2815.
1092
+ // Alive gate is SI5 runtime.
1093
+ let { min } = effectAmountRange(raw, state.ctx);
1094
+ const id = state.spell.id | 0;
1095
+ const levelMult = MOD_THREAT_LEVEL_SCALE[id];
1096
+ if (levelMult != null) {
1097
+ // level_diff = targetLevel − 60; amount += mult * level_diff when > 0.
1098
+ // Cite: :2821–2834. Gate: unitTargetLevel ?? casterLevel.
1099
+ const level = state.ctx.unitTargetLevel ?? state.ctx.casterLevel;
1100
+ if (level != null) {
1101
+ const levelDiff = level - 60;
1102
+ if (levelDiff > 0) min += levelMult * levelDiff;
1103
+ }
1104
+ }
1105
+ const dur = durationMsResolved(state);
1106
+ // A single-bit mask (Righteous Fury is holy) stamps the school so only that school is multiplied;
1107
+ // a multi-bit or all-schools mask (Salvation) stays global. Cite: SpellAuras.cpp:2836-2838.
1108
+ const school = schoolFromSingleBitMask(raw.miscValue | 0);
1109
+ const tagged = withHostile(
1110
+ {
1111
+ kind: 'buff' as const,
1112
+ mod: 'threat_mod' as const,
1113
+ amount: min,
1114
+ durationMs: dur,
1115
+ ...(school ? { school } : {}),
1116
+ },
1117
+ raw.targetA | 0,
1118
+ min,
1119
+ );
1120
+ state.effects.push(tagged as SpellEffect);
1121
+ state.role = state.role || 'buff';
1122
+ }
1123
+
1124
+ // ── SPELL_AURA_MOD_TAUNT (11) ── the taunted state while the aura holds, distinct from the taunt
1125
+ // EFFECT's threat equalize. Taunt and Growl carry both slots. Cite: SpellAuras.cpp:2860-2875.
1126
+ export function handleModTaunt(
1127
+ state: HandlerState,
1128
+ _raw: RawSpellEffect,
1129
+ _slot: number,
1130
+ _effectType: number,
1131
+ ): void {
1132
+ // C++: if (!Real) return. Cite: :2862–2864.
1133
+ // !IsAlive() || !CanHaveThreatList() → return. Cite: :2868–2869.
1134
+ if (state.ctx.canHaveThreatList === false) return;
1135
+ // Always emit: do NOT collapse this into the taunt effect's equalize row. The bake mapper emits
1136
+ // the same dual surface for a re-bake.
1137
+ const dur = durationMsResolved(state);
1138
+ state.effects.push({
1139
+ kind: 'mod_taunt',
1140
+ durationMs: dur < 0 ? 0 : dur,
1141
+ });
1142
+ state.role = state.role || 'control';
1143
+ }
1144
+
1145
+ // ── SPELL_AURA_MOD_STEALTH_DETECT (17) ── baked as a stealth-detect value.
1146
+ // Cite: SpellAuras.cpp:2616-2618 HandleModStealthDetect.
1147
+ export function handleModStealthDetect(
1148
+ state: HandlerState,
1149
+ raw: RawSpellEffect,
1150
+ _slot: number,
1151
+ _effectType: number,
1152
+ ): void {
1153
+ const { min } = effectAmountRange(raw, state.ctx);
1154
+ const dur = durationMsResolved(state);
1155
+ // AddStealthDetectionStrength(StealthType(misc), ±amount). Cite: :2618.
1156
+ state.effects.push({
1157
+ kind: 'stealth_detect',
1158
+ amount: Math.max(0, min),
1159
+ durationMs: dur < 0 ? 0 : dur,
1160
+ });
1161
+ }
1162
+
1163
+ // ── SPELL_AURA_MOD_HEALING (115) ── baked as a healing-taken buff, summed by school mask.
1164
+ // Cite: SpellAuras.cpp:176; Unit.cpp:7301-7309 SpellBaseHealingBonusTaken.
1165
+ export function handleModHealing(
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
+ // AdvertisedBenefit += amount when misc & schoolMask. Cite: Unit.cpp:7305–7307.
1174
+ // Bake folds school into flat healing_taken. Cite: map-spell-effects.mjs:939–944.
1175
+ const tagged = withHostile(
1176
+ { kind: 'buff' as const, mod: 'healing_taken' as const, amount: min, durationMs: dur },
1177
+ raw.targetA | 0,
1178
+ min,
1179
+ );
1180
+ state.effects.push(tagged as SpellEffect);
1181
+ state.role = state.role || 'buff';
1182
+ }
1183
+
1184
+ // ── SPELL_AURA_MOD_MECHANIC_RESISTANCE (117) ── a full-resist chance by mechanic, as Orc Hardiness
1185
+ // gives 25% against stun. Cite: SpellAuras.cpp:178; Unit.cpp:4015-4031 MagicSpellHitResult.
1186
+ export function handleModMechanicResistance(
1187
+ state: HandlerState,
1188
+ raw: RawSpellEffect,
1189
+ _slot: number,
1190
+ _effectType: number,
1191
+ ): void {
1192
+ const { min } = effectAmountRange(raw, state.ctx);
1193
+ const dur = durationMsResolved(state);
1194
+ const mechanic = raw.miscValue | 0;
1195
+ // GetTotalAuraModifierByMiscValue(MOD_MECHANIC_RESISTANCE, mechanic).
1196
+ // Cite: Unit.cpp:4016 (spell mechanic) / :4026 (effect mechanic max).
1197
+ state.effects.push({
1198
+ kind: 'mod_mechanic_resistance',
1199
+ mechanic,
1200
+ amount: min,
1201
+ durationMs: dur,
1202
+ } as never);
1203
+ state.role = state.role || 'buff';
1204
+ }
1205
+
1206
+ // ── SPELL_AURA_MOD_POSSESS (2) ── baked as an incapacitate with the charm mechanic.
1207
+ // Cite: SpellAuras.cpp:2188-2256 HandleModPossess.
1208
+ export function handleModPossess(
1209
+ state: HandlerState,
1210
+ raw: RawSpellEffect,
1211
+ _slot: number,
1212
+ _effectType: number,
1213
+ ): void {
1214
+ // C++: if (!Real) return. Cite: :2190–2191.
1215
+ // Not possess yourself. Cite: :2195–2197.
1216
+ if (state.ctx.unitTargetIsSelf === true) return;
1217
+ // Non-player caster → return. Cite: :2199–2201.
1218
+ // Bake-thin: omit casterIsPlayer → player path (emit).
1219
+ if (state.ctx.casterIsPlayer === false) return;
1220
+
1221
+ const dur = durationMsResolved(state);
1222
+ // TakePossessOf is the same thrall as TakeCharmOf, so the row is control:'charm' like every other
1223
+ // member of the family. Cite: SpellAuras.cpp:2219 TakePossessOf; map-spell-effects.mjs aura 2.
1224
+ state.effects.push({
1225
+ kind: 'cc',
1226
+ control: 'charm',
1227
+ mechanic: 'charm',
1228
+ durationMs: dur || 10_000,
1229
+ school: schoolOf(state.spell),
1230
+ });
1231
+ state.role = state.role || 'control';
1232
+
1233
+ // TakePossessOf + BreakCharmOutgoing for player casters.
1234
+ // Cite: :2219–2222. Client field update :2224–2233 is network-only.
1235
+ const intent: InterpretIntent = {
1236
+ kind: 'mod_possess',
1237
+ spellId: state.spell.id | 0,
1238
+ durationMs: dur || 10_000,
1239
+ breakOutgoing: true,
1240
+ };
1241
+
1242
+ // Spell 24937 Using Control Console apply/remove specials. Cite: :2207–2216 / :2238–2254.
1243
+ if ((state.spell.id | 0) === CONTROL_CONSOLE_SPELL_ID) {
1244
+ intent.controlConsoleApplySpells = CONTROL_CONSOLE_APPLY_SPELLS;
1245
+ intent.controlConsoleRemoveCasterSpells = CONTROL_CONSOLE_REMOVE_CASTER_SPELLS;
1246
+ intent.controlConsoleRemoveTargetSpell = CONTROL_CONSOLE_REMOVE_TARGET_SPELL;
1247
+ intent.controlConsoleDespawnMs = CONTROL_CONSOLE_DESPAWN_MS;
1248
+ }
1249
+ state.intents.push(intent);
1250
+ }
1251
+
1252
+ // ── SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT (133) ── baked as a max-health percent buff.
1253
+ // Cite: SpellAuras.cpp:3740-3756 HandleAuraModIncreaseHealthPercent.
1254
+ export function handleModIncreaseHealthPercent(
1255
+ state: HandlerState,
1256
+ raw: RawSpellEffect,
1257
+ _slot: number,
1258
+ _effectType: number,
1259
+ ): void {
1260
+ const { min } = effectAmountRange(raw, state.ctx);
1261
+ const dur = durationMsResolved(state);
1262
+ // HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, amount). Cite: :3745.
1263
+ const tagged = withHostile(
1264
+ {
1265
+ kind: 'buff' as const,
1266
+ mod: 'max_health_pct' as const,
1267
+ amount: min,
1268
+ durationMs: dur,
1269
+ },
1270
+ raw.targetA | 0,
1271
+ min,
1272
+ );
1273
+ state.effects.push(tagged as SpellEffect);
1274
+ state.role = state.role || 'buff';
1275
+
1276
+ // Mutate Bug 802: on apply ModifyHealth(+maxDelta). Cite: :3748–3753.
1277
+ if ((state.spell.id | 0) === MUTATE_BUG_SPELL_ID) {
1278
+ state.intents.push({
1279
+ kind: 'mod_increase_health_percent_special',
1280
+ mutateBugHealthGain: true,
1281
+ });
1282
+ }
1283
+ }
1284
+
1285
+ // ── SPELL_AURA_MOD_MANA_REGEN_INTERRUPT (134) ── the percent of spirit regen kept while casting.
1286
+ // Cite: SpellAuras.cpp:3803-3812; StatSystem.cpp:558-562 UpdateManaRegen.
1287
+ export function handleModManaRegenInterrupt(
1288
+ state: HandlerState,
1289
+ raw: RawSpellEffect,
1290
+ _slot: number,
1291
+ _effectType: number,
1292
+ ): void {
1293
+ // C++: if (!Real) return. Cite: :3805–3806.
1294
+ // Non-player → return. Cite: :3808–3809.
1295
+ if (state.ctx.unitTargetIsPlayer === false) return;
1296
+
1297
+ const { min } = effectAmountRange(raw, state.ctx);
1298
+ const dur = durationMsResolved(state);
1299
+ // Player::UpdateManaRegen folds GetTotalAuraModifier(134). Cite: StatSystem.cpp:558–562.
1300
+ state.effects.push({
1301
+ kind: 'buff',
1302
+ mod: 'mana_regen_interrupt',
1303
+ amount: min,
1304
+ durationMs: dur > 0 ? dur : 15_000,
1305
+ } as never);
1306
+ state.role = state.role || 'buff';
1307
+ }
1308
+
1309
+ // ── SPELL_AURA_MOD_STALKED (68) ──────────────────────────────────────────── Cite:
1310
+ // SpellAuras.cpp:3079–3086 HandleAuraModStalked Bake: unmapped. Cite: map-spell-effects.mjs:882–883.
1311
+ export function handleModStalked(
1312
+ state: HandlerState,
1313
+ _raw: RawSpellEffect,
1314
+ _slot: number,
1315
+ _effectType: number,
1316
+ ): void {
1317
+ // SetFlag / RemoveFlag UNIT_DYNFLAG_TRACK_UNIT. Cite: :3082–3085.
1318
+ // Used by Hunter's Mark, Mind Vision, Syndicate Tracker. Cite: :3081.
1319
+ const dur = durationMsResolved(state);
1320
+ state.effects.push({
1321
+ kind: 'mod_stalked',
1322
+ durationMs: dur,
1323
+ } as never);
1324
+ // Hostile mark/track — ACTIVE control so combat kit keeps Hunter's Mark class. Cite: roles.ts.
1325
+ state.role = state.role || 'control';
1326
+ }
1327
+
1328
+ // ── SPELL_AURA_MOD_TOTAL_THREAT (103) ── baked as a temporary flat threat reduction.
1329
+ // Cite: SpellAuras.cpp:2841-2858 HandleAuraModTotalThreat.
1330
+ export function handleModTotalThreat(
1331
+ state: HandlerState,
1332
+ raw: RawSpellEffect,
1333
+ _slot: number,
1334
+ _effectType: number,
1335
+ ): void {
1336
+ // C++: if (!Real) return. Cite: :2843–2844.
1337
+ // Target must be alive player. Cite: :2848–2849 — SI5 alive gate.
1338
+ if (state.ctx.unitTargetIsPlayer === false) return;
1339
+ // Caster must be alive. Cite: :2852–2854 — SI5 runtime.
1340
+
1341
+ const { min } = effectAmountRange(raw, state.ctx);
1342
+ const dur = durationMsResolved(state);
1343
+ // threatTemporaryFade(caster, amount, apply). Cite: :2857.
1344
+ // Flat signed amount (Fade r1 basePoints −56 → −55), not generation %.
1345
+ state.effects.push({
1346
+ kind: 'threat_temporary',
1347
+ amount: min,
1348
+ durationMs: dur,
1349
+ });
1350
+ state.role = state.role || 'buff';
1351
+ }
1352
+
1353
+ // ── SPELL_AURA_FEATHER_FALL (105) ────────────────────────────────────────── Cite:
1354
+ // SpellAuras.cpp:1670–1677 HandleAuraFeatherFall Bake: feather_fall. Cite: map-spell-effects.mjs:930–935.
1355
+ export function handleAuraFeatherFall(
1356
+ state: HandlerState,
1357
+ _raw: RawSpellEffect,
1358
+ _slot: number,
1359
+ _effectType: number,
1360
+ ): void {
1361
+ // C++: if (!Real) return. Cite: :1672–1673.
1362
+ // SetFeatherFall(apply). Cite: :1675; Unit.cpp:12386–12410 (movement flag / packet).
1363
+ const dur = durationMsResolved(state);
1364
+ state.effects.push({ kind: 'feather_fall', durationMs: dur });
1365
+ state.role = state.role || 'buff';
1366
+ }
1367
+
1368
+ // ── SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN (113) ── the ranged twin of the physical-taken aura.
1369
+ // Cite: SpellAuras.cpp:174; Unit.cpp:7615-7617 MeleeDamageBonusTaken.
1370
+ export function handleModRangedDamageTaken(
1371
+ state: HandlerState,
1372
+ raw: RawSpellEffect,
1373
+ _slot: number,
1374
+ _effectType: number,
1375
+ ): void {
1376
+ const { min } = effectAmountRange(raw, state.ctx);
1377
+ const dur = durationMsResolved(state);
1378
+ // This used to push ONLY an intent, which the resolver drops, so all three Windwall ranks baked an
1379
+ // empty effect list and the totem did nothing. Push the effect; the intent stays for its consumers.
1380
+ const tagged = withHostile(
1381
+ { kind: 'buff' as const, mod: 'ranged_taken' as const, amount: min, durationMs: dur },
1382
+ raw.targetA | 0,
1383
+ min,
1384
+ );
1385
+ state.effects.push(tagged as SpellEffect);
1386
+ state.role = state.role || 'buff';
1387
+ state.intents.push({
1388
+ kind: 'mod_ranged_damage_taken',
1389
+ amount: min,
1390
+ durationMs: dur,
1391
+ });
1392
+ }
1393
+
1394
+ // ── SPELL_AURA_MOD_RANGED_HASTE (140) ── baked as a haste buff, like 138 and 141.
1395
+ // Cite: SpellAuras.cpp:3938-3943 HandleAuraModRangedHaste.
1396
+ export function handleModRangedHaste(
1397
+ state: HandlerState,
1398
+ raw: RawSpellEffect,
1399
+ _slot: number,
1400
+ _effectType: number,
1401
+ ): void {
1402
+ const { min } = effectAmountRange(raw, state.ctx);
1403
+ const dur = durationMsResolved(state);
1404
+ // ApplyAttackTimePercentMod(RANGED_ATTACK, amount, apply). Cite: :3940–3942.
1405
+ const tagged = withHostile(
1406
+ { kind: 'buff' as const, mod: 'haste' as const, amount: min, durationMs: dur },
1407
+ raw.targetA | 0,
1408
+ min,
1409
+ );
1410
+ state.effects.push(tagged as SpellEffect);
1411
+ state.role = state.role || 'buff';
1412
+ }
1413
+
1414
+ // ── SPELL_AURA_OBS_MOD_HEALTH (20) ── a periodic heal of a PERCENT of max health.
1415
+ // Cite: SpellAuras.cpp:3590-3593; PeriodicTick :4687-4738.
1416
+ export function handleObsModHealth(
1417
+ state: HandlerState,
1418
+ raw: RawSpellEffect,
1419
+ _slot: number,
1420
+ _effectType: number,
1421
+ ): void {
1422
+ // Apply: m_isPeriodic = apply. Cite: :3590–3592.
1423
+ const { min } = effectAmountRange(raw, state.ctx);
1424
+ const dur = durationMsResolved(state);
1425
+ const tickMs = (raw.amplitude | 0) || 1000;
1426
+ // The amount IS the percentage, so it is emitted as a percent of max for the consumer to scale
1427
+ // against its own maximum. Emitting only the flat value made Harvest Fish heal 2 HP a second.
1428
+ let amountPerTick = Math.max(1, min);
1429
+ if (state.ctx.targetMaxHealth != null && min > 0) {
1430
+ amountPerTick = Math.max(1, trunc((state.ctx.targetMaxHealth * min) / 100));
1431
+ }
1432
+ state.effects.push({
1433
+ kind: 'restore_health',
1434
+ amountPerTick,
1435
+ tickMs,
1436
+ durationMs: dur,
1437
+ ...(min > 0 ? { pctOfMax: min } : {}),
1438
+ });
1439
+ }
1440
+
1441
+ // ── SPELL_AURA_OBS_MOD_MANA (21) ── a periodic restore of a PERCENT of max mana.
1442
+ // Cite: SpellAuras.cpp:3595-3609; PeriodicTick :4854-4890.
1443
+ export function handleObsModMana(
1444
+ state: HandlerState,
1445
+ raw: RawSpellEffect,
1446
+ _slot: number,
1447
+ _effectType: number,
1448
+ ): void {
1449
+ // Apply: periodictime default 1000; m_isPeriodic. Cite: :3597–3601.
1450
+ const { min } = effectAmountRange(raw, state.ctx);
1451
+ const dur = durationMsResolved(state);
1452
+ const tickMs = (raw.amplitude | 0) || 1000;
1453
+ // The amount IS the percentage, emitted as a percent of max so the consumer resolves it against its
1454
+ // own maximum. The flat per-tick value remains only as the legacy fallback.
1455
+ state.effects.push({
1456
+ kind: 'restore_power',
1457
+ amountPerTick: Math.max(1, min),
1458
+ // The C++ tick names POWER_MANA outright, never the miscValue. Cite: SpellAuras.cpp:4865,:4880.
1459
+ powerType: POWER_MANA,
1460
+ tickMs,
1461
+ durationMs: dur,
1462
+ ...(min > 0 ? { pctOfMax: min } : {}),
1463
+ });
1464
+
1465
+ // Spell 30024 Shade of Aran drink remove-by-default AI event. Cite: :3603–3609.
1466
+ if ((state.spell.id | 0) === SHADE_OF_ARAN_DRINK_SPELL_ID) {
1467
+ state.intents.push({
1468
+ kind: 'obs_mod_mana_remove_special',
1469
+ spellId: SHADE_OF_ARAN_DRINK_SPELL_ID,
1470
+ });
1471
+ }
1472
+ }
1473
+
1474
+ // ── SPELL_AURA_MOD_PARRY_PERCENT (47) ───────────────────────────────────── Cite: SpellAuras.cpp:3762–3773
1475
+ // HandleAuraModParryPercent Bake: buff parry. Cite: map-spell-effects.mjs:779–786.
1476
+ export function handleModParryPercent(
1477
+ state: HandlerState,
1478
+ raw: RawSpellEffect,
1479
+ _slot: number,
1480
+ _effectType: number,
1481
+ ): void {
1482
+ const { min } = effectAmountRange(raw, state.ctx);
1483
+ const dur = durationMsResolved(state);
1484
+ // Player: UpdateParryPercentage(); NPC: m_modParryChance ±amount. Cite: :3765–3772. Bake surface is flat
1485
+ // parry BuffMod points. Cite: map-spell-effects.mjs:782–785.
1486
+ const tagged = withHostile(
1487
+ { kind: 'buff' as const, mod: 'parry' as const, amount: min, durationMs: dur },
1488
+ raw.targetA | 0,
1489
+ min,
1490
+ );
1491
+ state.effects.push(tagged as SpellEffect);
1492
+ state.role = state.role || 'buff';
1493
+ }
1494
+
1495
+ // ── SPELL_AURA_MOD_SPELL_CRIT_CHANCE (57) ── baked as spell_crit, NOT the melee crit of aura 52:
1496
+ // routing it there gave Slip'kik's Savvy a melee buff. Cite: SpellAuras.cpp:3873-3889.
1497
+ export function handleModSpellCritChance(
1498
+ state: HandlerState,
1499
+ raw: RawSpellEffect,
1500
+ _slot: number,
1501
+ _effectType: number,
1502
+ ): void {
1503
+ // C++: if (!Real) return. Cite: :3875–3876. Interpret is apply-time (Real=true).
1504
+ const { min } = effectAmountRange(raw, state.ctx);
1505
+ const dur = durationMsResolved(state);
1506
+ // Spell crit % — combat buff. Cite: SpellAuras.cpp:3875–3888.
1507
+ state.effects.push({
1508
+ kind: 'buff',
1509
+ mod: 'spell_crit',
1510
+ amount: min,
1511
+ durationMs: dur,
1512
+ });
1513
+ state.role = state.role || 'buff';
1514
+ }
1515
+
1516
+ // ── SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE (179) ── added to crit taken for a magic-class hit, by
1517
+ // school mask (Winter's Chill is frost). Cite: SpellAuras.cpp:240; Unit.cpp:3516-3536.
1518
+ export function handleModAttackerSpellCritChance(
1519
+ state: HandlerState,
1520
+ raw: RawSpellEffect,
1521
+ _slot: number,
1522
+ _effectType: number,
1523
+ ): void {
1524
+ const { min } = effectAmountRange(raw, state.ctx);
1525
+ const dur = durationMsResolved(state);
1526
+ const schoolMask = raw.miscValue | 0;
1527
+ const tagged = withHostile(
1528
+ {
1529
+ kind: 'buff' as const,
1530
+ mod: 'attacker_spell_crit' as const,
1531
+ amount: min,
1532
+ durationMs: dur,
1533
+ schoolMask,
1534
+ },
1535
+ raw.targetA | 0,
1536
+ min,
1537
+ );
1538
+ state.effects.push(tagged as SpellEffect);
1539
+ // Hostile crit-taken debuff (Winter's Chill / Imp. Scorpid) — ACTIVE control kit role.
1540
+ state.role = state.role || 'control';
1541
+ state.intents.push({
1542
+ kind: 'mod_attacker_spell_crit_chance',
1543
+ amount: min,
1544
+ schoolMask,
1545
+ durationMs: dur,
1546
+ });
1547
+ }