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,869 @@
1
+ // Gap-close and the ranged stand band, peeled from sessionMotion. A pure move: the same bodies, order
2
+ // and gate names as the tail of the chain. Extracted modules must not import combat.ts.
3
+ import { castableKitIds } from './castableKit.ts';
4
+
5
+ import { isEnemySide, isTotemSide } from '../core/events.ts';
6
+ import {
7
+ moveStepYd, MELEE_REACH_YD, MELEE_PARK_SLACK_YD, meleeParkYd, meleeContactYd,
8
+ combatReachSumYd,
9
+ combatDistanceYd, STOREY_DZ_YD,
10
+ planarRangeHonestYd,
11
+ coneArcsOfKit, coneArcOf, coneClearBandRad, coneCovers,
12
+ meleeSlotBandRad, meleeSlotOffsetRad, meleeSlotIsExposed,
13
+ MELEE_CONTACT_EPS_YD,
14
+ type ConeArc,
15
+ type CombatPosYd,
16
+ } from './combatGeometry.ts';
17
+ import { navSightClear } from './navSight.ts';
18
+ import { holdAnchorOf } from './sessionHome.ts';
19
+ import { DEFAULT_DETECTION_RANGE } from '../../domain/creature/creatureAi.ts';
20
+ import { getCreatureAttackDistance } from '../../domain/creature/creatureAggro.ts';
21
+ import { COMBAT_DROP_YD } from './creatureLeash.ts';
22
+ import { detAtan2, detCos, detHypot, detHypot3, detSin } from '../core/detMath.ts';
23
+ import {
24
+ chaseBackpedalDest,
25
+ chaseBackpedalReachYd,
26
+ chaseFanDest,
27
+ chaseFanEnabled,
28
+ CHASE_CLOSENESS_TIMER_MS,
29
+ CHASE_FANNING_RADIUS_YD,
30
+ fanDirectionSign,
31
+ frandFanAngle,
32
+ isChaseInsideModel,
33
+ type ChaseClosenessState,
34
+ } from './chaseCloseness.ts';
35
+ import { rangedAutoMinYards, spellTargetTypeAllowed } from './predicates.ts';
36
+ import { CREATURE_FAMILY_ASSISTANCE_RADIUS } from '../../domain/creature/creatureAiConstants.ts';
37
+ import type { MotionOwner } from './motionClaim.ts';
38
+ import type { MotionGenerator } from './motionGenerator.ts';
39
+ import type { MotionGateInfo, MotionGateName } from './motionGate.ts';
40
+ import type { CombatContext } from './context.ts';
41
+ import { ALLY_HEAL_THRESHOLD } from './types.ts';
42
+ import type { Fighter } from './types.ts';
43
+ import type { SpellDef } from '../../data/schema.ts';
44
+ import type { UnitNavPath, PathToOpts } from './sessionPathTo.ts';
45
+
46
+ /** ObjectDefines.h CONTACT_DISTANCE 1.f — stand 2 contact radii past rangeMin so the min gate does not thrash. */
47
+ const RANGED_MIN_CLEARANCE_YD = 2;
48
+ /** Stay this far inside an unpulled mob's detection so the step does not graze aggro. */
49
+ const UNPULLED_AGGRO_MARGIN_YD = 1.5;
50
+ // How far inside the bad arc a melee DPS must be before it starts a flank slide (~20 deg). A dead band, not
51
+ // a tolerance: the arc's own edge is what moves under it every tick.
52
+ const MELEE_SLOT_ENTRY_MARGIN_RAD = 0.35;
53
+ /** Shared empty arc list, so the no-cone tick allocates nothing. */
54
+ const EMPTY_ARCS: readonly ConeArc[] = [];
55
+ /** One cone spell's wedge. */
56
+ const arcOfConeSpell = (sp: SpellDef): ConeArc =>
57
+ ({ ...coneArcOf(sp.coneDeg), radiusYd: sp.radiusYd ?? Number.POSITIVE_INFINITY });
58
+ // Unreachable victim => EnterEvadeMode rather than holding the party in combat forever. Cite:
59
+ // Unit::SelectHostileTarget; CombatManager evade timer.
60
+ const UNREACHABLE_EVADE_MS = 5_000;
61
+ // A ceiling on walking a corridor that never closes. Corridor progress resets the shorter timer, which
62
+ // is right for rounding a wall, but a corridor can simply be wrong — one mob walked 86.8 yd away.
63
+ const UNREACHABLE_ROUTE_MS = 25_000;
64
+ /** Tolerance on the evade ring — smaller than any real gap, larger than any float drift. */
65
+ const EVADE_REACH_EPS_YD = MELEE_CONTACT_EPS_YD;
66
+
67
+ /** Closures the chase arm needs from installSessionMotion. */
68
+ export interface ChaseDeps {
69
+ ctx: CombatContext;
70
+ tickMs: number;
71
+ posOf: (side: string) => CombatPosYd | undefined;
72
+ setPos: (side: string, p: CombatPosYd) => void;
73
+ dead: (f: Fighter) => boolean;
74
+ foeOf: (f: Fighter) => Fighter | null;
75
+ hostileTargetOf: (f: Fighter) => Fighter | null;
76
+ enemyEngaged: (f: Fighter) => boolean;
77
+ fightersOrder: () => Fighter[];
78
+ gate: (side: string, name: MotionGateName, info?: MotionGateInfo) => void;
79
+ diag: (side: string, name: string) => void;
80
+ claimOwnerOf: (side: string) => MotionOwner | null;
81
+ takeMotion: (side: string, owner: MotionOwner, goal: CombatPosYd | null) => CombatPosYd | null;
82
+ navStepToward: (
83
+ side: string, from: CombatPosYd, to: CombatPosYd,
84
+ step: number, stopAtDist: number, searchCorridor?: boolean,
85
+ ) => CombatPosYd;
86
+ pathTo: (side: string, dest: CombatPosYd, opts?: PathToOpts) => boolean;
87
+ /** Walk the corridor this arm just issued — the claim is already held. */
88
+ advanceHeldOrder: (f: Fighter) => boolean;
89
+ dropStaleCorridor: (side: string) => void;
90
+ unitNavPaths: Map<string, UnitNavPath>;
91
+ /** The move-order stuck ladder's per-side row — this arm only ever clears it. */
92
+ stuckState: { delete: (side: string) => boolean };
93
+ noProgressStuck: (f: Fighter, aim: CombatPosYd) => boolean;
94
+ watchPartyStuck: (f: Fighter, from: CombatPosYd, to: CombatPosYd, aim: CombatPosYd) => void;
95
+ evadeUnreachable: (f: Fighter) => void;
96
+ runSpeedYdPerSec: (f: Fighter) => number;
97
+ longestOffenseRangeYd: (f: Fighter) => number;
98
+ shortOffenseList: (f: Fighter) => readonly SpellDef[];
99
+ onCooldown: (f: Fighter, s: SpellDef) => boolean;
100
+ canAfford: (f: Fighter, s: SpellDef) => boolean;
101
+ kitRangedAuto: (f: Fighter) => boolean;
102
+ wantsMeleeBand: (f: Fighter) => boolean;
103
+ pbaoeRadiusYd: (f: Fighter) => number;
104
+ isThreatVictimOf: (tgt: Fighter, f: Fighter) => boolean;
105
+ /** Melee flank slot latch — the slide that must finish rather than stop on the boundary. */
106
+ heldSlideDest: (
107
+ side: string, focus: string, focusAt: CombatPosYd, from: CombatPosYd, slackYd: number,
108
+ ) => CombatPosYd | null;
109
+ holdSlide: (side: string, focus: string, focusAt: CombatPosYd, dest: CombatPosYd) => void;
110
+ posSlideSettled: Map<string, number>;
111
+ focusIsStill: (side: string, at: CombatPosYd) => boolean;
112
+ meleePeersOf: (focus: string) => readonly string[];
113
+ }
114
+
115
+ // The floor of the claim order: gap-close into range, the melee flank slot, the ranged stand band and
116
+ // the hold-ground return that clamps them. It still takes its own home and flank claims for now.
117
+ export function createChaseArm(deps: ChaseDeps): {
118
+ chase: MotionGenerator;
119
+ clearChaseParkTimer: (side: string) => void;
120
+ markNoPath: (side: string) => void;
121
+ standsInLiveCone: (f: Fighter) => boolean;
122
+ } {
123
+ const {
124
+ ctx, tickMs, posOf, setPos, dead, foeOf, hostileTargetOf, enemyEngaged, fightersOrder,
125
+ gate, diag, claimOwnerOf, takeMotion, navStepToward, pathTo, advanceHeldOrder,
126
+ dropStaleCorridor, unitNavPaths, stuckState, noProgressStuck, watchPartyStuck,
127
+ evadeUnreachable, runSpeedYdPerSec, longestOffenseRangeYd,
128
+ shortOffenseList, onCooldown, canAfford, kitRangedAuto, wantsMeleeBand, pbaoeRadiusYd,
129
+ isThreatVictimOf, heldSlideDest, holdSlide, posSlideSettled, focusIsStill,
130
+ meleePeersOf,
131
+ } = deps;
132
+
133
+ // The cone a live aura FIRES on a timer: Frenzy 19451 triggers Lava Breath 19272 (cone 35 yd) with
134
+ // no cast bar, so a cast-bar read left the raid in it. Cite: boss_magmadar.cpp:34,56.
135
+ const auraTriggerId = new Map<number, number>();
136
+ // The kit is the second place to look — a creature spec carries both rows without a wired spellOf.
137
+ const spellFrom = (caster: Fighter, id: number): SpellDef | undefined => {
138
+ if (!id) return undefined;
139
+ return ctx.spellOf?.(id) ?? (caster.spec.spells ?? []).find((s) => (s.id | 0) === id);
140
+ };
141
+ const coneFiredByAura = (caster: Fighter, auraSpellId: number): SpellDef | null => {
142
+ let trig = auraTriggerId.get(auraSpellId);
143
+ if (trig === undefined) {
144
+ const holder = spellFrom(caster, auraSpellId);
145
+ if (!holder) return null;
146
+ trig = 0;
147
+ for (const e of holder.effects ?? []) {
148
+ const t = (e as { triggerSpellId?: number }).triggerSpellId | 0;
149
+ if (t) { trig = t; break; }
150
+ }
151
+ auraTriggerId.set(auraSpellId, trig);
152
+ }
153
+ const sp = spellFrom(caster, trig);
154
+ return sp?.aoeShape === 'cone' ? sp : null;
155
+ };
156
+
157
+ // Every wedge live on this unit: the one it is CASTING plus the ones its auras fire. A cone in the
158
+ // KIT is still not a hazard — that read repositioned the raid for a Cleave nobody cast.
159
+ const castConeArcs = (caster: Fighter): readonly ConeArc[] => {
160
+ const arcs: ConeArc[] = [];
161
+ const sp = caster.castingSpell;
162
+ if (sp?.aoeShape === 'cone') arcs.push(arcOfConeSpell(sp));
163
+ for (const e of ctx.effectsOn(caster.side)) {
164
+ if (e.broken || e.source !== caster.side || e.expiresAt <= ctx.t) continue;
165
+ const fired = coneFiredByAura(caster, e.spellId | 0);
166
+ if (fired) arcs.push(arcOfConeSpell(fired));
167
+ }
168
+ return arcs.length ? arcs : EMPTY_ARCS;
169
+ };
170
+
171
+ // State this generator OWNS rather than borrows. A movement generator keeps its own fields, which is
172
+ // the whole difference from one chain re-deriving per tick; these were lent from the session bag.
173
+ const chaseCloseness = new Map<string, ChaseClosenessState>();
174
+ const unreachableFrom = new Map<string, {
175
+ minDist: number; victimX: number; victimY: number; victimZ?: number; ms: number;
176
+ /** Corridor progress: waypoints left last tick, and how long this route has run. */
177
+ wpLeft?: number; routeMs?: number;
178
+ }>();
179
+
180
+ // Sides whose last corridor search came back with no path — both ends on the mesh and no walk between
181
+ // them. The core does not wait out a timer for that; the proxy exists because enemies rarely search.
182
+ const noPathSides = new Set<string>();
183
+
184
+ const isReachable = (f: Fighter): boolean =>
185
+ !noPathSides.has(f.side) && (unreachableFrom.get(f.side)?.ms ?? 0) < UNREACHABLE_EVADE_MS;
186
+
187
+ const advanceChase = (f: Fighter): void => {
188
+
189
+ // The bubble a friendly may fight inside. Walking home when it is outside one is the arm above this
190
+ // in the chain; what is left here is the clamp, so a step cannot carry it out of a bubble.
191
+ const hold = holdAnchorOf(ctx, f.side, posOf);
192
+
193
+ const tgt = isEnemySide(f.side) ? hostileTargetOf(f) : foeOf(f);
194
+ // The self-sentinel means no living hostiles, not a target. The cast path guards it and motion did
195
+ // not, so out of combat every friendly measured zero distance to ITSELF and kept walking.
196
+ if (!tgt || tgt === f || dead(tgt)) {
197
+ gate(f.side, tgt === f ? 'targetIsSelf' : 'noTarget');
198
+ return;
199
+ }
200
+ const from = posOf(f.side);
201
+ const to = posOf(tgt.side);
202
+ // Where this pair PARKS, and the ring it swings from. Two player-sized bodies park at 2.5 and swing
203
+ // to 5.55, while a boss pushes both out — which is why the C++ makes them functions of the pair.
204
+ const pairPark = meleeParkYd(f.spec.combatReachYd, tgt.spec.combatReachYd);
205
+ const pairContact = meleeContactYd(false, f.spec.combatReachYd, tgt.spec.combatReachYd);
206
+ if (!from || !to) { gate(f.side, 'noPose'); return; }
207
+ const dist = combatDistanceYd(from, to);
208
+ if (dist == null) { gate(f.side, 'noPose'); return; }
209
+ // Local acquisition is the radius a unit fights inside, and a target outside it is not one to walk
210
+ // to. An ENGAGED enemy is exempt: nothing caps pursuit, so a pulled mob must keep closing.
211
+ if (ctx.cfg.acquireRangeYd != null && dist > ctx.cfg.acquireRangeYd) {
212
+ if (!isEnemySide(f.side)) {
213
+ // A dz past one storey folds combat distance out of range (combatGeometry.ts:207), so
214
+ // "too far" and "wrong floor" reach this gate as the same number. Name them apart.
215
+ const dz = Number.isFinite(from.z) && Number.isFinite(to.z)
216
+ ? Math.abs((from.z as number) - (to.z as number))
217
+ : 0;
218
+ if (dz > STOREY_DZ_YD) {
219
+ gate(f.side, 'storeyMismatch', { dz, dist, acquire: ctx.cfg.acquireRangeYd });
220
+ } else {
221
+ gate(f.side, 'pastAcquire', { dist, acquire: ctx.cfg.acquireRangeYd });
222
+ }
223
+ return;
224
+ }
225
+ // Past 90 yd the leak drops even outside acquire range. Cite: CombatManager.cpp:41.
226
+ if (dist > COMBAT_DROP_YD) {
227
+ evadeUnreachable(f);
228
+ gate(f.side, 'combatDrop', { dist, acquire: COMBAT_DROP_YD });
229
+ return;
230
+ }
231
+ }
232
+
233
+ // Combat movement off: stand and fight, never close. Below the leash on purpose, since the flag
234
+ // stops the step and not the drop, and above the unreachable proxy, which would evade a stander.
235
+ if (isEnemySide(f.side) && ctx.enemyCastBySide.get(f.side)?.eventAi.combatMovement === false) {
236
+ gate(f.side, 'noCombatMovement');
237
+ return;
238
+ }
239
+
240
+ const speed = runSpeedYdPerSec(f);
241
+ // 100% snare / immobilised by aura stack — no motion
242
+ if (!(speed > 0)) { gate(f.side, 'speedZero'); return; }
243
+
244
+ // An enemy that cannot touch its victim and is not closing evades rather than holding the party in
245
+ // combat forever. Mob displacement is not progress, or a wall slide resets the timer forever.
246
+ if (isEnemySide(f.side)) {
247
+ // The GRADE is the full contact ring while the PARK is half of it, which is the split the C++
248
+ // makes — and it retires the knife edge where one ULP of step error triggered a full-HP evade.
249
+ const reach = Math.max(pairContact, longestOffenseRangeYd(f) + EVADE_REACH_EPS_YD);
250
+ const prev = unreachableFrom.get(f.side);
251
+ const victimMoved = !!prev && (
252
+ to.z != null && prev.victimZ != null
253
+ ? detHypot3(to.x - prev.victimX, to.y - prev.victimY, to.z - prev.victimZ) > 0.05
254
+ : detHypot(to.x - prev.victimX, to.y - prev.victimY) > 0.05
255
+ );
256
+ const closed = !!prev && dist < prev.minDist - 0.5;
257
+ // Walking a corridor IS reaching, even while the straight line grows. A route rounding a wall
258
+ // increases that distance for its first half. Waypoints, not yards: a count needs no anchor.
259
+ const liveCorridor = unitNavPaths.get(f.side);
260
+ const wpLeft = liveCorridor && liveCorridor.pts.length > 0
261
+ ? liveCorridor.pts.length
262
+ : undefined;
263
+ const routeMs = wpLeft != null ? (prev?.routeMs ?? 0) + tickMs : 0;
264
+ const onCorridor = wpLeft != null && prev?.wpLeft != null && wpLeft < prev.wpLeft
265
+ && routeMs < UNREACHABLE_ROUTE_MS;
266
+ if (dist <= reach || !prev || victimMoved || closed || onCorridor) {
267
+ unreachableFrom.set(f.side, {
268
+ minDist: dist,
269
+ victimX: to.x,
270
+ victimY: to.y,
271
+ ...(to.z != null ? { victimZ: to.z } : {}),
272
+ ms: 0,
273
+ ...(wpLeft != null ? { wpLeft } : {}),
274
+ // A route that actually closed starts its leash over; one that never does keeps
275
+ // accumulating, so a wrong corridor still ends.
276
+ routeMs: closed || dist <= reach || victimMoved ? 0 : routeMs,
277
+ });
278
+ f.targetUnreachableMs = 0;
279
+ // Reaching, closing or on a corridor: whatever the last search said is stale.
280
+ // Cite: `:291` m_reachable = true when the target has not moved and we are reachable.
281
+ noPathSides.delete(f.side);
282
+ } else {
283
+ prev.wpLeft = wpLeft;
284
+ prev.routeMs = routeMs;
285
+ prev.ms += tickMs;
286
+ // EVENT_T_TARGET_NOT_REACHABLE reads this at 1 s, so a script fires long before the
287
+ // 5 s evade this counter is really for. Cite: CreatureEventAI.cpp:545-547.
288
+ f.targetUnreachableMs = prev.ms;
289
+ // The generator answers; the AI decides. Same threshold, one owner for it.
290
+ if (!isReachable(f)) {
291
+ evadeUnreachable(f);
292
+ gate(f.side, 'unreachable', { ms: prev.ms, dist });
293
+ return;
294
+ }
295
+ }
296
+ }
297
+
298
+ // EVERY unit searches. Denying the enemy side was the "the boss will not follow us down" report,
299
+ // and the cost was measured: free to 24 chasing bodies, about +0.89 ms a tick at 40.
300
+ const searchCorridor = true;
301
+
302
+ // Step, unless hold-ground or the party leash would carry the unit out of position. Every step in
303
+ // this function goes through here, so the claim is taken in ONE place.
304
+ const stepTo = (aim: CombatPosYd, stopAt: number, owner: MotionOwner = 'chase'): void => {
305
+ const aimTo = takeMotion(f.side, owner, aim);
306
+ if (!aimTo) {
307
+ gate(f.side, 'claimHeldBy', {
308
+ dist,
309
+ owner: claimOwnerOf(f.side) ?? '',
310
+ });
311
+ return;
312
+ }
313
+ // Friendlies issue one dest and walk it. navStepToward at the live mob every
314
+ // tick is a second goal (goalKey churn + hop vs corridor) and is the swirl.
315
+ if (!isEnemySide(f.side)) {
316
+ const otherFloor = aimTo.z != null && from.z != null && Math.abs(aimTo.z - from.z) > 3;
317
+ if (!otherFloor && pathTo(f.side, aimTo, {
318
+ keepFocus: true,
319
+ claimed: true,
320
+ ...(stopAt > 0 ? { standShortYd: stopAt } : {}),
321
+ })) {
322
+ advanceHeldOrder(f);
323
+ gate(f.side, 'stepped', { dist });
324
+ return;
325
+ }
326
+ }
327
+ // dest-close is not a stall while a corridor is live — a corner walk grows
328
+ // Euclidean dest distance. The follower already skips dead waypoints.
329
+ const live = unitNavPaths.get(f.side);
330
+ if (!(live && live.pts.length > 0) && noProgressStuck(f, aimTo)) {
331
+ dropStaleCorridor(f.side);
332
+ stuckState.delete(f.side);
333
+ diag(f.side, 'stuckRepath');
334
+ }
335
+ const next = navStepToward(f.side, from, aimTo, moveStepYd(speed, tickMs), stopAt, searchCorridor);
336
+ if (hold) {
337
+ const dA = combatDistanceYd(next, hold.anchor);
338
+ // the player moves this piece
339
+ if (dA != null && dA > hold.holdYd) { gate(f.side, 'holdGround', { dist: dA }); return; }
340
+ }
341
+ setPos(f.side, next);
342
+ gate(f.side, 'stepped', { dist });
343
+ if (!isEnemySide(f.side)) {
344
+ watchPartyStuck(f, from, posOf(f.side) ?? next, aimTo);
345
+ }
346
+ };
347
+
348
+ // 'auto' closes to the stand yards and holds, since a perpetual walk back to the band is a kite
349
+ // whose heading flips with the mob. 'hold' never auto-moves, 'melee' always closes, enemies chase.
350
+ const policy = f.spec.movement ?? 'auto';
351
+ /** Gap-close reached its stand decision and did not step: which of the three reasons. */
352
+ const standGate = (): void => {
353
+ gate(f.side, policy === 'hold' ? 'policyHold'
354
+ : (f.spec.weapon?.dmgMax ?? 0) > 1 ? 'inRange' : 'noWeapon', { dist });
355
+ };
356
+
357
+ /** Floor passives sit with empty threat. Walking into GetAttackDistance chain-pulls. */
358
+ const fightersForPullCheck = fightersOrder();
359
+ const stepPullsUnpulled = (at: CombatPosYd): boolean => {
360
+ const myLevel = f.spec.level | 0;
361
+ for (const h of fightersForPullCheck) {
362
+ if (!isEnemySide(h.side) || dead(h) || enemyEngaged(h)) continue;
363
+ if (h.side === tgt.side) continue;
364
+ const hp = posOf(h.side);
365
+ if (!hp) continue;
366
+ // Inside CallAssistance of the target: same pack, CFH will join. A second pack is farther.
367
+ const fromTgt = combatDistanceYd(hp, to);
368
+ if (fromTgt != null && fromTgt <= CREATURE_FAMILY_ASSISTANCE_RADIUS) continue;
369
+ const d = combatDistanceYd(at, hp);
370
+ if (d == null) continue;
371
+ const det = getCreatureAttackDistance(h.spec.level | 0, myLevel, {
372
+ detectionRange: DEFAULT_DETECTION_RANGE,
373
+ detectRangeMod: h.detectRangeMod ?? 0,
374
+ });
375
+ if (d <= det + UNPULLED_AGGRO_MARGIN_YD) return true;
376
+ }
377
+ return false;
378
+ };
379
+
380
+ const holdExtra = (f.stepBackHoldUntil ?? 0) > ctx.t ? (f.stepBackHoldYd ?? 0) : 0;
381
+ const sightOk = !ctx.cfg.navLos || navSightClear(ctx.cfg, from, to);
382
+
383
+ // A healer needs sight of the BODY IT HEALS, not only of the mob. Cite: Spell.cpp:4742 CheckCast
384
+ // has no friendly exemption; TargetedMovementGenerator.cpp:625 repositions on lost sight.
385
+ const blockedHealAlly = (): CombatPosYd | null => {
386
+ if (isEnemySide(f.side) || f.spec.groupRole !== 'healer' || !ctx.cfg.navLos) return null;
387
+ // A held unit never auto-moves, sight or no sight — the same bar the branch below keeps.
388
+ if (policy === 'hold') return null;
389
+ let worst: Fighter | null = null;
390
+ let worstPct = ALLY_HEAL_THRESHOLD;
391
+ for (const u of ctx.friendlyPoolOf(f)) {
392
+ if (u === f || dead(u) || isTotemSide(u.side)) continue;
393
+ const pct = u.hp / Math.max(1, u.spec.maxHealth);
394
+ if (pct >= worstPct) continue;
395
+ worstPct = pct;
396
+ worst = u;
397
+ }
398
+ if (!worst) return null;
399
+ const at = posOf(worst.side);
400
+ // Same floor only: a storey away is the climbAim branch's job, not a sight walk.
401
+ if (!at || !planarRangeHonestYd(from, at)) return null;
402
+ return navSightClear(ctx.cfg, from, at) ? null : at;
403
+ };
404
+
405
+ // Where a melee DPS parks: out of the focus's front half and out of any wedge its kit sweeps, one
406
+ // slot per unit. Standing in front hands the focus parry and block, and each parry shortens its swing.
407
+ const meleeFlankSlot = (): CombatPosYd | null => {
408
+ if (isEnemySide(f.side)) return null;
409
+ // Only slide once in, or one step from, contact. Solving the slot from 30 yd out would path the
410
+ // whole walk-in around the mob and park the unit at range whenever the arc grazed a second pack.
411
+ if (dist > MELEE_REACH_YD + MELEE_PARK_SLACK_YD + MELEE_REACH_YD) return null;
412
+ // Same anchor `facingOf` uses, so the arc we dodge is the arc the attack table rolls.
413
+ const victim = foeOf(tgt);
414
+ if (!victim || victim === f || victim === tgt) return null;
415
+ const at = posOf(victim.side);
416
+ if (!at) return null;
417
+ // A slide already in flight owns the walk: finish it. Stopping at the boundary is the
418
+ // oscillation this latch exists for (see posSlideHold).
419
+ const held = heldSlideDest(f.side, tgt.side, to, from, MELEE_PARK_SLACK_YD);
420
+ if (held) { diag(f.side, 'flankHold'); return held; }
421
+ if ((posSlideSettled.get(f.side) ?? 0) > ctx.t) return null;
422
+ if (!focusIsStill(tgt.side, to)) return null;
423
+ const arcs = coneArcsOfKit(tgt.spec.spells, castableKitIds(tgt, ctx.spellOf));
424
+ // ENTRY, with a dead band: only a unit well inside the bad arc starts walking. Asking the bare
425
+ // boundary made every unit parked just outside slide again on the next facing change.
426
+ if (!meleeSlotIsExposed(to, at, from, arcs, MELEE_SLOT_ENTRY_MARGIN_RAD)) return null;
427
+ // Facing bearing, mob → its victim. Degenerate (victim standing on it): no bearing exists.
428
+ const fx = at.x - to.x;
429
+ const fy = at.y - to.y;
430
+ const fLen = detHypot(fx, fy);
431
+ if (fLen < 1e-6) return null;
432
+ const ux = fx / fLen;
433
+ const uy = fy / fLen;
434
+ // Rotate that bearing by the solved offset, toward whichever side we already stand on —
435
+ // the cross product's sign IS that side, so nobody crosses through the mob to flank.
436
+ const side = (ux * (from.y - to.y) - uy * (from.x - to.x)) < 0 ? -1 : 1;
437
+ // One slot per unit inside the clear band. Everyone solving the band's deepest point stacks the
438
+ // melee group on it, body separation pushes them off, and they walk it back forever.
439
+ const band = meleeSlotBandRad(arcs);
440
+ let theta = meleeSlotOffsetRad(arcs);
441
+ if (band && band.hi > band.lo) {
442
+ const peers = meleePeersOf(tgt.side);
443
+ let rank = 0;
444
+ let count = 0;
445
+ for (const s2 of peers) {
446
+ if (s2 === victim.side) continue;
447
+ const p2 = posOf(s2);
448
+ // Same cross-product test: a unit on the far side is packing the far arc, not ours.
449
+ if (p2 && ((ux * (p2.y - to.y) - uy * (p2.x - to.x)) < 0 ? -1 : 1) !== side) continue;
450
+ if (s2 === f.side) rank = count;
451
+ count += 1;
452
+ }
453
+ // Deepest slot first — the back of the arc is the best spot, so rank 0 takes it.
454
+ if (count > 1) theta = band.hi - ((band.hi - band.lo) * rank) / (count - 1);
455
+ }
456
+ const c = detCos(theta);
457
+ const sn = detSin(theta) * side;
458
+ const rx = ux * c - uy * sn;
459
+ const ry = ux * sn + uy * c;
460
+ // THE CHASE'S OWN DEST, FLOORED AT THE PACKING RADIUS. A slot is the chase point at a different
461
+ // bearing, but the bare park is too tight for N melee — and a flat floor clamped every big body.
462
+ const slotRadius = Math.max(MELEE_REACH_YD, pairPark);
463
+ const slot: CombatPosYd = {
464
+ x: to.x + rx * slotRadius,
465
+ y: to.y + ry * slotRadius,
466
+ ...(to.z != null ? { z: to.z } : {}),
467
+ };
468
+ holdSlide(f.side, tgt.side, to, slot);
469
+ diag(f.side, 'flankSolve');
470
+ return slot;
471
+ };
472
+
473
+ if (policy === 'melee' || wantsMeleeBand(f)) {
474
+ // Hold once in white range, otherwise close. Do not park outside a ranged kit's dead zone, which
475
+ // stranded packs. ARRIVAL is the full contact ring while the AIM is half of it.
476
+ const parkReach = Math.max(pairContact, holdExtra);
477
+
478
+ // Enemy vs friendly: closeness timer → backpedal inside model / fan when packed.
479
+ // Cite: TargetedMovementGenerator.cpp HandleFinalizedMovement + Backpedal + FanOut.
480
+ if (isEnemySide(f.side) && !isEnemySide(tgt.side)) {
481
+ let st = chaseCloseness.get(f.side);
482
+ if (st?.dest) {
483
+ const dDest = combatDistanceYd(from, st.dest);
484
+ if (dDest != null && dDest > 0.3) {
485
+ stepTo(st.dest, 0);
486
+ return;
487
+ }
488
+ st.dest = null;
489
+ st.remainingMs = CHASE_CLOSENESS_TIMER_MS;
490
+ st.expired = false;
491
+ }
492
+ if (dist <= parkReach && planarRangeHonestYd(from, to)) {
493
+ if (!st) {
494
+ st = { remainingMs: CHASE_CLOSENESS_TIMER_MS, expired: false, dest: null };
495
+ chaseCloseness.set(f.side, st);
496
+ } else if (!st.expired && st.remainingMs > 0) {
497
+ st.remainingMs -= tickMs;
498
+ if (st.remainingMs <= 0) {
499
+ st.remainingMs = 0;
500
+ st.expired = true;
501
+ }
502
+ }
503
+ if (st.expired) {
504
+ // Backpedal(): reset flags; inside model → step back, else FanOut.
505
+ st.expired = false;
506
+ st.remainingMs = CHASE_CLOSENESS_TIMER_MS;
507
+ // The NON-melee combined reach, so 3.0 for two player-sized bodies and the cap for a big
508
+ // one. It was a flat 5, which capped for everything. Cite: TargetedMovementGenerator.cpp:404.
509
+ const reach = chaseBackpedalReachYd(
510
+ combatReachSumYd(f.spec.combatReachYd, tgt.spec.combatReachYd),
511
+ );
512
+ const distSq = dist * dist;
513
+ if (isChaseInsideModel(distSq, reach)) {
514
+ const dest = chaseBackpedalDest(from, to, reach);
515
+ st.dest = dest;
516
+ st.remainingMs = 0;
517
+ stepTo(dest, 0);
518
+ return;
519
+ }
520
+ if (chaseFanEnabled(f.spec.staticFlags)) {
521
+ const fanR2 = CHASE_FANNING_RADIUS_YD * CHASE_FANNING_RADIUS_YD;
522
+ let collider = false;
523
+ for (const o of fightersOrder()) {
524
+ if (o.side === f.side || !isEnemySide(o.side) || dead(o)) continue;
525
+ if (!enemyEngaged(o)) continue;
526
+ const ov = hostileTargetOf(o);
527
+ if (!ov || ov.side !== tgt.side) continue;
528
+ const op = posOf(o.side);
529
+ if (!op) continue;
530
+ const odx = op.x - from.x;
531
+ const ody = op.y - from.y;
532
+ if (odx * odx + ody * ody > fanR2) continue;
533
+ if (chaseCloseness.get(o.side)?.dest) continue;
534
+ collider = true;
535
+ break;
536
+ }
537
+ if (collider) {
538
+ const sign = fanDirectionSign(ctx.rng);
539
+ const ang = frandFanAngle(ctx.rng);
540
+ // GetNearPoint at own + victim reach, same non-melee form as the backpedal.
541
+ // Cite: TargetedMovementGenerator.cpp:451,463.
542
+ const fanDist = combatReachSumYd(f.spec.combatReachYd, tgt.spec.combatReachYd);
543
+ let dest = chaseFanDest(from, to, fanDist, ang * sign);
544
+ st.dest = dest;
545
+ st.remainingMs = 0;
546
+ stepTo(dest, 0);
547
+ // Cite: TargetedMovementGenerator.cpp:461–470 second fan direction on fail.
548
+ const after = posOf(f.side) ?? from;
549
+ if (detHypot(after.x - from.x, after.y - from.y) <= 1e-6) {
550
+ dest = chaseFanDest(from, to, fanDist, ang * -sign);
551
+ st.dest = dest;
552
+ stepTo(dest, 0);
553
+ }
554
+ return;
555
+ }
556
+ }
557
+ }
558
+ standGate();
559
+ return;
560
+ }
561
+ chaseCloseness.delete(f.side);
562
+ }
563
+
564
+ // Flank slot first: in reach but standing in the front half (or a cone wedge) is not
565
+ // parked, and out of reach the walk-in goes round the arc rather than through it.
566
+ const slot = policy === 'hold' ? null : meleeFlankSlot();
567
+ const goal = slot ?? to;
568
+ const goalStop = slot ? 0 : Math.min(pairPark, parkReach);
569
+ const goalDist = slot ? combatDistanceYd(from, slot) : dist;
570
+ if (goalDist == null) { gate(f.side, 'noPose'); return; }
571
+ if (goalDist <= (slot ? MELEE_PARK_SLACK_YD : parkReach) && planarRangeHonestYd(from, to)) {
572
+ dropStaleCorridor(f.side);
573
+ gate(f.side, 'inRange', { dist: goalDist });
574
+ return;
575
+ }
576
+ // hold ground: never chase
577
+ if (policy === 'hold') { gate(f.side, 'policyHold', { dist: goalDist }); return; }
578
+ // Only on the WALK-IN: once the focus has a threat list the fight is open, and refusing every
579
+ // step that grazes a passive's GetAttackDistance strands the unit instead of saving a pull.
580
+ if (!isEnemySide(f.side) && goalDist > 1e-6 && !enemyEngaged(tgt)) {
581
+ const step = Math.min(moveStepYd(speed, tickMs), Math.max(0, goalDist - goalStop));
582
+ const aim: CombatPosYd = {
583
+ x: from.x + ((goal.x - from.x) / goalDist) * step,
584
+ y: from.y + ((goal.y - from.y) / goalDist) * step,
585
+ ...(from.z != null ? { z: from.z } : {}),
586
+ };
587
+ if (stepPullsUnpulled(aim)) { gate(f.side, 'wouldPull', { dist: goalDist }); return; }
588
+ }
589
+ if (slot) {
590
+ diag(f.side, 'flankStep');
591
+ // A slide is OPTIONAL motion: no corridor to the slot means stand and fight. The step fallback
592
+ // drops the corridor and repaths, which walks the unit off the boss for a 5 yd sidestep.
593
+
594
+ const tookSlot = takeMotion(f.side, 'flank', slot) != null;
595
+ if (tookSlot && pathTo(f.side, slot, { keepFocus: true, claimed: true })) {
596
+ advanceHeldOrder(f);
597
+ gate(f.side, 'stepped', { dist: goalDist });
598
+ } else {
599
+ gate(f.side, tookSlot ? 'noRoute' : 'claimHeldBy', {
600
+ dist: goalDist,
601
+ owner: claimOwnerOf(f.side) ?? '',
602
+ });
603
+ }
604
+ return;
605
+ }
606
+ diag(f.side, 'meleeChase');
607
+ stepTo(goal, goalStop);
608
+ return;
609
+ }
610
+
611
+ // Ranged standing in a breath — the breath being CAST, not one the kit merely owns. Treating the
612
+ // kit as a wedge was 1,257 of 1,819 added steps and moved nobody out of any damage actually dealt.
613
+ if (!isEnemySide(f.side) && policy !== 'hold') {
614
+ const arcs = castConeArcs(tgt);
615
+ if (arcs.length > 0) {
616
+ const victim = foeOf(tgt);
617
+ const at = victim && victim !== f && victim !== tgt ? posOf(victim.side) : undefined;
618
+ // Same latch as the melee slot: a rotation already in flight finishes, so the caster
619
+ // does not park on the wedge's edge and get swept back in by the next facing change.
620
+ const heldArc = at ? heldSlideDest(f.side, tgt.side, to, from, 1) : null;
621
+ if (heldArc && !stepPullsUnpulled(heldArc)) {
622
+ diag(f.side, 'coneHold');
623
+ stepTo(heldArc, 0, 'flank');
624
+ return;
625
+ }
626
+ if (at && (posSlideSettled.get(f.side) ?? 0) <= ctx.t
627
+ && arcs.some((a) => coneCovers(to, at, from, a))) {
628
+ const band = coneClearBandRad(arcs, dist);
629
+ // Null band: every bearing at this radius is swept, so stepping sideways buys nothing.
630
+ if (band) {
631
+ const fx = at.x - to.x;
632
+ const fy = at.y - to.y;
633
+ const fLen = detHypot(fx, fy);
634
+ if (fLen > 1e-6 && dist > 1e-6) {
635
+ const ux = fx / fLen;
636
+ const uy = fy / fLen;
637
+ // detAtan2, not Math.acos: every angle in this engine comes off the det table.
638
+ let delta = detAtan2(from.y - to.y, from.x - to.x) - detAtan2(fy, fx);
639
+ while (delta > Math.PI) delta -= Math.PI * 2;
640
+ while (delta <= -Math.PI) delta += Math.PI * 2;
641
+ const now = delta < 0 ? -delta : delta;
642
+ const theta = now < band.lo ? band.lo : band.hi;
643
+ const side = (ux * (from.y - to.y) - uy * (from.x - to.x)) < 0 ? -1 : 1;
644
+ const c = detCos(theta);
645
+ const sn = detSin(theta) * side;
646
+ const dest = {
647
+ x: to.x + (ux * c - uy * sn) * dist,
648
+ y: to.y + (ux * sn + uy * c) * dist,
649
+ ...(to.z != null ? { z: to.z } : {}),
650
+ };
651
+ if (!stepPullsUnpulled(dest)) {
652
+ diag(f.side, 'coneSolve');
653
+ holdSlide(f.side, tgt.side, to, dest);
654
+ stepTo(dest, 0, 'flank');
655
+ return;
656
+ }
657
+ }
658
+ }
659
+ }
660
+ }
661
+ }
662
+
663
+ const maxR = longestOffenseRangeYd(f);
664
+
665
+ // A stamped ranged stand IS the plan to fight from range, so it outranks pack-close. Walking a
666
+ // caster inside its own PBAoE radius also walks it into every melee swing on the pack.
667
+ const rangedStandPlan = (f.spec.standYards ?? 0) > MELEE_REACH_YD + 1;
668
+
669
+ // Pack-close is keyed on pack count, never inBlast (that oscillated on the blast edge).
670
+ const packCloseArmed = !isEnemySide(f.side)
671
+ && policy === 'auto'
672
+ && f.spec.packClose !== false
673
+ && !rangedStandPlan
674
+ && pbaoeRadiusYd(f) > 0
675
+ && (() => {
676
+ let n = 0;
677
+ for (const h of ctx.livingHostilesFor(f)) {
678
+ if (dead(h)) continue;
679
+ if (++n >= 2) return true;
680
+ }
681
+ return false;
682
+ })();
683
+
684
+ // The ranged dead zone: packed inside the minimum range, commit to white reach with a real main
685
+ // hand. The whole thrash band commits, not only under the minimum. With no weapon, stand.
686
+ const minR = rangedAutoMinYards(f);
687
+ const holdAt = minR > 0
688
+ ? Math.min(
689
+ minR + RANGED_MIN_CLEARANCE_YD,
690
+ maxR > minR ? maxR : minR + RANGED_MIN_CLEARANCE_YD,
691
+ )
692
+ : 0;
693
+ if (minR > 0) {
694
+ if (dist < holdAt) {
695
+ // Not the victim: walk OUT of the dead zone instead of committing to white reach. The commit is
696
+ // right for the unit the boss is chewing on and wrong for everyone else — it trades the kit.
697
+ const backOutTo = holdAt + RANGED_MIN_CLEARANCE_YD;
698
+ if (
699
+ !isEnemySide(f.side)
700
+ && policy === 'auto'
701
+ && kitRangedAuto(f)
702
+ && maxR >= backOutTo
703
+ && dist > 1e-6
704
+ && !isThreatVictimOf(tgt, f)
705
+ ) {
706
+ const aim = {
707
+ x: to.x + ((from.x - to.x) / dist) * backOutTo,
708
+ y: to.y + ((from.y - to.y) / dist) * backOutTo,
709
+ ...(to.z != null ? { z: to.z } : {}),
710
+ };
711
+ if (!stepPullsUnpulled(aim)) {
712
+ f.mode = 'ranged';
713
+ diag(f.side, 'deadZoneBackOut');
714
+ stepTo(aim, 0);
715
+ return;
716
+ }
717
+ }
718
+ if (!((f.spec.weapon?.dmgMax ?? 0) > 1)) { standGate(); return; }
719
+ f.mode = 'melee';
720
+ if (policy !== 'hold' && dist > pairContact) {
721
+ stepTo(to, pairPark);
722
+ } else {
723
+ standGate();
724
+ }
725
+ return;
726
+ }
727
+ }
728
+ // Outside hold band: re-arm bow/wand auto if the kit is ranged-auto (mode may have
729
+ // flipped to melee while packed inside rangeMin).
730
+ if (kitRangedAuto(f) && f.mode === 'melee') f.mode = 'ranged';
731
+
732
+ // A ranged kit holds at its stand yards for single-target bolts, unless a multi pack sits outside
733
+ // the PBAoE radius. A ground rain keeps the long stop, since its density is at the focus.
734
+ const standYd = f.spec.standYards;
735
+ let stopAt = standYd != null && standYd > 0 ? standYd : maxR;
736
+ // The creature's own ranged-mode park distance, where this derived one from kit reach. A minimum,
737
+ // not an assignment: the main-spell prevention is unported, so parking past reach buys silence.
738
+ if (stopAt > 0 && isEnemySide(f.side)) {
739
+ const ea = ctx.enemyCastBySide.get(f.side)?.eventAi;
740
+ if (ea?.rangedMode && ea.rangedChaseDistance > 0) stopAt = Math.min(stopAt, ea.rangedChaseDistance);
741
+ }
742
+ if (holdExtra > stopAt) stopAt = holdExtra;
743
+ if (packCloseArmed && maxR > 0) {
744
+ const pbaoeR = pbaoeRadiusYd(f);
745
+ let inBlast = 0;
746
+ for (const h of ctx.livingHostilesFor(f)) {
747
+ if (dead(h)) continue;
748
+ const hd = combatDistanceYd(from, posOf(h.side));
749
+ if (hd != null && hd <= pbaoeR && ++inBlast >= 2) break;
750
+ }
751
+ if (inBlast < 2) {
752
+ let closeTo = Math.min(maxR, Math.max(MELEE_REACH_YD, pbaoeR * 0.85));
753
+ // The ranged-auto dead zone: walking in below the back-out point thrashes against the back-out
754
+ // itself. Cite: PlayerbotHunterAI.cpp:252-274 — keep distance, do not commit to melee.
755
+ if (kitRangedAuto(f) && holdAt > 0) {
756
+ const floor = holdAt + RANGED_MIN_CLEARANCE_YD;
757
+ if (closeTo < floor) closeTo = Math.min(maxR, floor);
758
+ }
759
+ const aim = dist > 1e-6
760
+ ? {
761
+ x: to.x + ((from.x - to.x) / dist) * closeTo,
762
+ y: to.y + ((from.y - to.y) / dist) * closeTo,
763
+ ...(to.z != null ? { z: to.z } : {}),
764
+ }
765
+ : from;
766
+ if (!stepPullsUnpulled(aim)) stopAt = closeTo;
767
+ }
768
+ }
769
+ // No fireable ranged stop: close to Judgement/Holy Shock range, else melee with MH
770
+ // (KI-884 / KI-1046). Cite: Spell.cpp CheckTargetCreatureType.
771
+ if (!(maxR > 0)) {
772
+ let fireR = 0;
773
+ for (const s of shortOffenseList(f)) {
774
+ if (onCooldown(f, s) || !canAfford(f, s)) continue;
775
+ if (!spellTargetTypeAllowed(s, tgt.creatureType ?? 0)) continue;
776
+ const r = s.rangeMax ?? 0;
777
+ if (r > fireR) fireR = r;
778
+ }
779
+ if (fireR > 0) {
780
+ stopAt = stopAt > 0 ? Math.min(stopAt, fireR) : fireR;
781
+ } else {
782
+ // Healer off-aggro may keep a stamped stand for heals; solo MH must not freeze.
783
+ let healerHold = false;
784
+ if (!isEnemySide(f.side) && f.spec.groupRole === 'healer' && stopAt > MELEE_REACH_YD + 1) {
785
+ try {
786
+ // No threat manager reads as "hold", same as the throw this used to take.
787
+ const mgr = ctx.threatOf(tgt);
788
+ const v = mgr ? mgr.getCurrentVictimId() : null;
789
+ healerHold = mgr ? v != null && v !== f.side : true;
790
+ } catch { healerHold = true; }
791
+ }
792
+ if (!healerHold) {
793
+ if (policy !== 'hold' && (f.spec.weapon?.dmgMax ?? 0) > 1
794
+ && dist > pairContact) {
795
+ stepTo(to, pairPark);
796
+ } else {
797
+ standGate();
798
+ }
799
+ return;
800
+ }
801
+ }
802
+ }
803
+ if (dist <= stopAt && planarRangeHonestYd(from, to) && sightOk) {
804
+ // In range of the mob is not in sight of the wounded. Walk at the ally; the next tick's
805
+ // sight test ends the walk the moment the corner is rounded, as the mob branch below does.
806
+ const ally = blockedHealAlly();
807
+ if (ally) { stepTo(ally, 0); return; }
808
+ dropStaleCorridor(f.side);
809
+ gate(f.side, 'inRange', { dist });
810
+ return;
811
+ }
812
+ // hold ground: enemies come to you
813
+ if (policy === 'hold') { gate(f.side, 'policyHold', { dist }); return; }
814
+ if (planarRangeHonestYd(from, to)) {
815
+ // Same floor, no LOS (dungeon corner): walk at the body; the parked-dest cleanup
816
+ // above ends the walk at the first sighted in-range spot.
817
+ stepTo(to, sightOk ? stopAt : 0);
818
+ return;
819
+ }
820
+ // Other floor: walk to the firing position (stopAt short of the focus ON ITS floor).
821
+ // Aiming the body with stop 0 climbed the whole back line into the boss (ZG Venoxis).
822
+ const nearR = Math.min(stopAt, dist);
823
+ const climbAim: CombatPosYd = dist > 1e-6 && nearR > MELEE_REACH_YD + MELEE_PARK_SLACK_YD
824
+ ? {
825
+ x: to.x + ((from.x - to.x) / dist) * nearR,
826
+ y: to.y + ((from.y - to.y) / dist) * nearR,
827
+ ...(to.z != null ? { z: to.z } : {}),
828
+ }
829
+ : to;
830
+ stepTo(climbAim, 0);
831
+ };
832
+
833
+ // Chase is the last arm in the chain and the floor of the claim order, so it always handles the unit — a
834
+ // stand is its answer, not a fall-through. The boolean is the interface's.
835
+ return {
836
+ chase: {
837
+ owner: 'chase',
838
+ update: (f) => { advanceChase(f); return true; },
839
+ isReachable,
840
+ /** Finalize (`:39`) — off the stack for good, so nothing about this unit survives. */
841
+ finalize: (f) => {
842
+ unreachableFrom.delete(f.side);
843
+ chaseCloseness.delete(f.side);
844
+ noPathSides.delete(f.side);
845
+ },
846
+ },
847
+ // The search queue reporting an honest no-path for this side. Enemies only: a party member with no
848
+ // route walks the lead's corridor or stands, it does not leave combat.
849
+ markNoPath: (side: string) => { if (isEnemySide(side)) noPathSides.add(side); },
850
+ // A displacement moved the body, so the melee-park closeness timer is measuring from somewhere the
851
+ // unit no longer is. Side-keyed, because the displacement handlers have a side and not a Fighter.
852
+ clearChaseParkTimer: (side: string) => { chaseCloseness.delete(side); },
853
+ // Standing in a wedge that is live RIGHT NOW — the cone slide's own test, asked by the motion
854
+ // gate before it parks a caster in a breath, so the fact stays in one place.
855
+ standsInLiveCone: (f: Fighter): boolean => {
856
+ if (isEnemySide(f.side) || dead(f)) return false;
857
+ const tgt = foeOf(f);
858
+ if (!tgt || tgt === f || dead(tgt)) return false;
859
+ const arcs = castConeArcs(tgt);
860
+ if (arcs.length === 0) return false;
861
+ const from = posOf(f.side);
862
+ const to = posOf(tgt.side);
863
+ const victim = foeOf(tgt);
864
+ const at = victim && victim !== f && victim !== tgt ? posOf(victim.side) : undefined;
865
+ if (!from || !to || !at) return false;
866
+ return arcs.some((a) => coneCovers(to, at, from, a));
867
+ },
868
+ };
869
+ }