azeroth-shell 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -2
- package/bin/azsh.mjs +19 -0
- package/docs/aifid/eventai-texts.json +4414 -0
- package/docs/dungeons/atlas/atlas-rows-dungeons.json +8989 -0
- package/docs/dungeons/survey/pack-id-migration.json +2418 -0
- package/package.json +35 -4
- package/src/autopilot/bossSkip.ts +26 -0
- package/src/autopilot/combatRotation.ts +824 -0
- package/src/autopilot/config.ts +533 -0
- package/src/autopilot/consumables.ts +58 -0
- package/src/autopilot/encounterStand.ts +121 -0
- package/src/autopilot/objectGatePlan.ts +53 -0
- package/src/autopilot/pathEngage.ts +229 -0
- package/src/autopilot/plan.ts +1643 -0
- package/src/autopilot/questPolicy.ts +274 -0
- package/src/autopilot/routeStep.ts +69 -0
- package/src/autopilot/sessionReport.ts +88 -0
- package/src/autopilot/topOffPower.ts +26 -0
- package/src/autopilot/view.ts +476 -0
- package/src/cli/bootCheck.mjs +34 -0
- package/src/cli/bootData.mjs +57 -0
- package/src/cli/combatLogFilter.ts +153 -0
- package/src/cli/combatLogFormat.ts +613 -0
- package/src/cli/fileRepository.mjs +105 -0
- package/src/cli/gzLoader.mjs +31 -0
- package/src/cli/liveGauntletEscort.ts +978 -0
- package/src/cli/liveStratUndead.ts +305 -0
- package/src/cli/macroHostCombat.ts +545 -0
- package/src/cli/macroHostWorld.ts +330 -0
- package/src/cli/prefs.mjs +31 -0
- package/src/cli/register.mjs +4 -0
- package/src/cli/repl.mjs +693 -0
- package/src/cli/rotationText.mjs +226 -0
- package/src/cli/squad.mjs +105 -0
- package/src/cli/term.mjs +144 -0
- package/src/cli/text.mjs +122 -0
- package/src/cli/tui.mjs +626 -0
- package/src/cli/tuiArena.mjs +109 -0
- package/src/cli/tuiAutopilotSettings.mjs +93 -0
- package/src/cli/tuiBags.mjs +180 -0
- package/src/cli/tuiBars.mjs +133 -0
- package/src/cli/tuiBg.mjs +243 -0
- package/src/cli/tuiBulk.mjs +162 -0
- package/src/cli/tuiCheck.mjs +1882 -0
- package/src/cli/tuiCity.mjs +396 -0
- package/src/cli/tuiCompanionKit.mjs +300 -0
- package/src/cli/tuiCompanions.mjs +471 -0
- package/src/cli/tuiDev.mjs +62 -0
- package/src/cli/tuiDungeon.mjs +606 -0
- package/src/cli/tuiEnchantTarget.mjs +120 -0
- package/src/cli/tuiFight.mjs +577 -0
- package/src/cli/tuiFightPanes.mjs +228 -0
- package/src/cli/tuiFloor.mjs +506 -0
- package/src/cli/tuiGear.mjs +158 -0
- package/src/cli/tuiHonor.mjs +74 -0
- package/src/cli/tuiLoot.mjs +97 -0
- package/src/cli/tuiMacros.mjs +144 -0
- package/src/cli/tuiOutfitter.mjs +115 -0
- package/src/cli/tuiPet.mjs +116 -0
- package/src/cli/tuiProfessions.mjs +800 -0
- package/src/cli/tuiRaid.mjs +127 -0
- package/src/cli/tuiRep.mjs +65 -0
- package/src/cli/tuiSaves.mjs +69 -0
- package/src/cli/tuiSearch.mjs +363 -0
- package/src/cli/tuiSettings.mjs +151 -0
- package/src/cli/tuiSimLab.mjs +80 -0
- package/src/cli/tuiTalents.mjs +60 -0
- package/src/cli/tuiViews.mjs +1178 -0
- package/src/cli/tuiWiki.mjs +181 -0
- package/src/cli/tuiWorld.mjs +361 -0
- package/src/cli/wikiIndex.ts +259 -0
- package/src/cli/wikiSources.ts +355 -0
- package/src/data/alteracValley.ts +176 -0
- package/src/data/appearanceOptions.ts +534 -0
- package/src/data/applyLootChanceSanity.ts +21 -0
- package/src/data/createFlavor.ts +96 -0
- package/src/data/customItems.ts +33 -0
- package/src/data/dataStore.ts +1904 -0
- package/src/data/dungeonGameObjects.ts +84 -0
- package/src/data/dungeonPlateCover.ts +66 -0
- package/src/data/dungeonSpawns.ts +294 -0
- package/src/data/dungeons/alterac-valley.ts +135 -0
- package/src/data/dungeons/apply-dungeon-rooms.ts +29 -0
- package/src/data/dungeons/apply-encounter-outdoors.ts +72 -0
- package/src/data/dungeons/apply-instance-geometry.ts +65 -0
- package/src/data/dungeons/apply-spawn-placement.ts +171 -0
- package/src/data/dungeons/blackfathom-deeps.ts +539 -0
- package/src/data/dungeons/blackrock-depths.ts +1410 -0
- package/src/data/dungeons/blackwing-lair.ts +129 -0
- package/src/data/dungeons/boss-eventai.ts +8 -0
- package/src/data/dungeons/deadmines.ts +410 -0
- package/src/data/dungeons/dire-maul-east.ts +980 -0
- package/src/data/dungeons/dire-maul-north.ts +661 -0
- package/src/data/dungeons/dire-maul-west.ts +785 -0
- package/src/data/dungeons/dungeon-rooms.json +5479 -0
- package/src/data/dungeons/encounter-outdoors.json +359 -0
- package/src/data/dungeons/eventai/blackfathom-deeps.ts +308 -0
- package/src/data/dungeons/eventai/blackrock-depths.ts +1257 -0
- package/src/data/dungeons/eventai/deadmines.ts +264 -0
- package/src/data/dungeons/eventai/dire-maul-east.ts +320 -0
- package/src/data/dungeons/eventai/gnomeregan.ts +213 -0
- package/src/data/dungeons/eventai/helpers.ts +79 -0
- package/src/data/dungeons/eventai/index.ts +133 -0
- package/src/data/dungeons/eventai/lbrs.ts +372 -0
- package/src/data/dungeons/eventai/maraudon.ts +323 -0
- package/src/data/dungeons/eventai/ragefire-chasm.ts +108 -0
- package/src/data/dungeons/eventai/razorfen-downs.ts +207 -0
- package/src/data/dungeons/eventai/razorfen-kraul.ts +326 -0
- package/src/data/dungeons/eventai/scholomance.ts +680 -0
- package/src/data/dungeons/eventai/shadowfang-keep.ts +230 -0
- package/src/data/dungeons/eventai/sm-cathedral.ts +75 -0
- package/src/data/dungeons/eventai/sm-graveyard.ts +150 -0
- package/src/data/dungeons/eventai/sm-library.ts +55 -0
- package/src/data/dungeons/eventai/stratholme-undead.ts +127 -0
- package/src/data/dungeons/eventai/sunken-temple.ts +582 -0
- package/src/data/dungeons/eventai/the-stockade.ts +228 -0
- package/src/data/dungeons/eventai/ubrs.ts +225 -0
- package/src/data/dungeons/eventai/uldaman.ts +355 -0
- package/src/data/dungeons/eventai/wailing-caverns.ts +396 -0
- package/src/data/dungeons/eventai/zul-farrak.ts +591 -0
- package/src/data/dungeons/gnomeregan.ts +909 -0
- package/src/data/dungeons/index.ts +126 -0
- package/src/data/dungeons/instance-geometry.json +5233 -0
- package/src/data/dungeons/key-sources.json +169 -0
- package/src/data/dungeons/lbrs.ts +996 -0
- package/src/data/dungeons/maraudon.ts +786 -0
- package/src/data/dungeons/molten-core.ts +194 -0
- package/src/data/dungeons/naxxramas.ts +173 -0
- package/src/data/dungeons/onyxias-lair.ts +71 -0
- package/src/data/dungeons/pack-from-clusters.ts +1256 -0
- package/src/data/dungeons/ragefire-chasm.ts +238 -0
- package/src/data/dungeons/razorfen-downs.ts +698 -0
- package/src/data/dungeons/razorfen-kraul.ts +766 -0
- package/src/data/dungeons/ruins-of-ahnqiraj.ts +121 -0
- package/src/data/dungeons/scholomance.ts +1076 -0
- package/src/data/dungeons/shadowfang-keep.ts +740 -0
- package/src/data/dungeons/sm-armory.ts +266 -0
- package/src/data/dungeons/sm-cathedral.ts +430 -0
- package/src/data/dungeons/sm-graveyard.ts +482 -0
- package/src/data/dungeons/sm-library.ts +337 -0
- package/src/data/dungeons/stratholme-live.ts +808 -0
- package/src/data/dungeons/stratholme-undead.ts +1164 -0
- package/src/data/dungeons/sunken-temple.ts +931 -0
- package/src/data/dungeons/temple-of-ahnqiraj.ts +119 -0
- package/src/data/dungeons/the-stockade.ts +282 -0
- package/src/data/dungeons/ubrs.ts +1286 -0
- package/src/data/dungeons/uldaman.ts +685 -0
- package/src/data/dungeons/wailing-caverns.ts +356 -0
- package/src/data/dungeons/zul-farrak.ts +686 -0
- package/src/data/dungeons/zul-gurub.ts +142 -0
- package/src/data/dungeons.ts +42 -0
- package/src/data/fixtures.ts +446 -0
- package/src/data/gameobject-data.json.gz +0 -0
- package/src/data/item-data.json.gz +0 -0
- package/src/data/loot-data.json.gz +0 -0
- package/src/data/maps/atlas-approach-maps.json +1425 -0
- package/src/data/maps/atlas-landmarks.json +1711 -0
- package/src/data/maps/dungeon-viewports.json +392 -0
- package/src/data/materializeModDamagePercentTaken.ts +70 -0
- package/src/data/materializeModHealthRegen.ts +89 -0
- package/src/data/materializeSpellReputation.ts +26 -0
- package/src/data/pageTexts.ts +19 -0
- package/src/data/profession-data.json.gz +0 -0
- package/src/data/raid-plans/blackfathom-deeps.json +86 -0
- package/src/data/raid-plans/blackrock-depths.json +419 -0
- package/src/data/raid-plans/blackwing-lair.json +328 -0
- package/src/data/raid-plans/deadmines.json +55 -0
- package/src/data/raid-plans/dire-maul-east.json +94 -0
- package/src/data/raid-plans/dire-maul-north.json +70 -0
- package/src/data/raid-plans/dire-maul-west.json +75 -0
- package/src/data/raid-plans/gnomeregan.json +131 -0
- package/src/data/raid-plans/lbrs.json +176 -0
- package/src/data/raid-plans/maraudon.json +102 -0
- package/src/data/raid-plans/molten-core.json +169 -0
- package/src/data/raid-plans/naxxramas.json +354 -0
- package/src/data/raid-plans/onyxias-lair.json +18 -0
- package/src/data/raid-plans/ragefire-chasm.json +30 -0
- package/src/data/raid-plans/razorfen-downs.json +75 -0
- package/src/data/raid-plans/razorfen-kraul.json +53 -0
- package/src/data/raid-plans/ruins-of-ahnqiraj.json +110 -0
- package/src/data/raid-plans/scholomance.json +170 -0
- package/src/data/raid-plans/shadowfang-keep.json +87 -0
- package/src/data/raid-plans/sm-armory.json +53 -0
- package/src/data/raid-plans/sm-cathedral.json +72 -0
- package/src/data/raid-plans/sm-graveyard.json +63 -0
- package/src/data/raid-plans/sm-library.json +23 -0
- package/src/data/raid-plans/stratholme-live.json +129 -0
- package/src/data/raid-plans/stratholme-undead.json +73 -0
- package/src/data/raid-plans/sunken-temple.json +159 -0
- package/src/data/raid-plans/temple-of-ahnqiraj.json +163 -0
- package/src/data/raid-plans/the-stockade.json +42 -0
- package/src/data/raid-plans/ubrs.json +53 -0
- package/src/data/raid-plans/uldaman.json +131 -0
- package/src/data/raid-plans/wailing-caverns.json +90 -0
- package/src/data/raid-plans/zul-farrak.json +156 -0
- package/src/data/raid-plans/zul-gurub.json +307 -0
- package/src/data/raidInstanceCreatures.mjs +473 -0
- package/src/data/rotations/index.ts +152 -0
- package/src/data/rotations/layout.mjs +72 -0
- package/src/data/rotations/pve/druid/balance.json +754 -0
- package/src/data/rotations/pve/druid/feral-tank.json +2448 -0
- package/src/data/rotations/pve/druid/feral.json +2660 -0
- package/src/data/rotations/pve/druid/restoration.json +424 -0
- package/src/data/rotations/pve/hunter/beast-mastery.json +1288 -0
- package/src/data/rotations/pve/hunter/marksmanship.json +1260 -0
- package/src/data/rotations/pve/hunter/survival.json +1373 -0
- package/src/data/rotations/pve/mage/arcane-leveling.json +1798 -0
- package/src/data/rotations/pve/mage/fire-leveling.json +2003 -0
- package/src/data/rotations/pve/mage/frost-leveling.json +1912 -0
- package/src/data/rotations/pve/paladin/holy.json +755 -0
- package/src/data/rotations/pve/paladin/protection.json +962 -0
- package/src/data/rotations/pve/paladin/retribution.json +924 -0
- package/src/data/rotations/pve/priest/discipline.json +772 -0
- package/src/data/rotations/pve/priest/holy.json +707 -0
- package/src/data/rotations/pve/priest/shadow.json +787 -0
- package/src/data/rotations/pve/rogue/assassination.json +2477 -0
- package/src/data/rotations/pve/rogue/combat.json +2483 -0
- package/src/data/rotations/pve/rogue/subtlety.json +2523 -0
- package/src/data/rotations/pve/shaman/elemental.json +1157 -0
- package/src/data/rotations/pve/shaman/enhancement.json +1085 -0
- package/src/data/rotations/pve/shaman/restoration.json +592 -0
- package/src/data/rotations/pve/warlock/affliction.json +1185 -0
- package/src/data/rotations/pve/warlock/demonology.json +1165 -0
- package/src/data/rotations/pve/warlock/destruction.json +1177 -0
- package/src/data/rotations/pve/warrior/arms.json +3020 -0
- package/src/data/rotations/pve/warrior/fury.json +2996 -0
- package/src/data/rotations/pve/warrior/protection.json +2509 -0
- package/src/data/rotations/pvp/druid/balance.json +593 -0
- package/src/data/rotations/pvp/druid/feral.json +3276 -0
- package/src/data/rotations/pvp/druid/restoration.json +662 -0
- package/src/data/rotations/pvp/hunter/beast-mastery.json +665 -0
- package/src/data/rotations/pvp/hunter/marksmanship.json +2406 -0
- package/src/data/rotations/pvp/hunter/survival.json +635 -0
- package/src/data/rotations/pvp/mage/arcane.json +574 -0
- package/src/data/rotations/pvp/mage/fire.json +570 -0
- package/src/data/rotations/pvp/mage/frost.json +4048 -0
- package/src/data/rotations/pvp/paladin/holy.json +1498 -0
- package/src/data/rotations/pvp/paladin/protection.json +567 -0
- package/src/data/rotations/pvp/paladin/retribution.json +1110 -0
- package/src/data/rotations/pvp/priest/discipline.json +1848 -0
- package/src/data/rotations/pvp/priest/holy.json +6340 -0
- package/src/data/rotations/pvp/priest/shadow.json +2329 -0
- package/src/data/rotations/pvp/rogue/assassination.json +1322 -0
- package/src/data/rotations/pvp/rogue/combat.json +5258 -0
- package/src/data/rotations/pvp/rogue/subtlety.json +586 -0
- package/src/data/rotations/pvp/shaman/elemental.json +1404 -0
- package/src/data/rotations/pvp/shaman/enhancement.json +1277 -0
- package/src/data/rotations/pvp/shaman/restoration.json +2490 -0
- package/src/data/rotations/pvp/warlock/affliction.json +1017 -0
- package/src/data/rotations/pvp/warlock/demonology.json +1503 -0
- package/src/data/rotations/pvp/warlock/destruction.json +638 -0
- package/src/data/rotations/pvp/warrior/arms.json +5665 -0
- package/src/data/rotations/pvp/warrior/fury.json +850 -0
- package/src/data/rotations/pvp/warrior/protection.json +777 -0
- package/src/data/schema/bundle.ts +511 -0
- package/src/data/schema/constants.ts +49 -0
- package/src/data/schema/creature.ts +454 -0
- package/src/data/schema/encounter.ts +155 -0
- package/src/data/schema/faction.ts +48 -0
- package/src/data/schema/item.ts +297 -0
- package/src/data/schema/itemEnchant.ts +105 -0
- package/src/data/schema/npc.ts +44 -0
- package/src/data/schema/primitives.ts +295 -0
- package/src/data/schema/profession.ts +226 -0
- package/src/data/schema/quest.ts +154 -0
- package/src/data/schema/spell.ts +1149 -0
- package/src/data/schema/talent.ts +74 -0
- package/src/data/schema/world.ts +124 -0
- package/src/data/schema.ts +19 -0
- package/src/data/skinNodeGapFill.ts +68 -0
- package/src/data/spell-data.json.gz +0 -0
- package/src/data/spell-script-targets.json +1 -0
- package/src/data/tables/ahItemValues.json.gz +0 -0
- package/src/data/tables/alteracValley.json.gz +0 -0
- package/src/data/tables/areatriggerTeleports.json.gz +0 -0
- package/src/data/tables/botNames.json.gz +0 -0
- package/src/data/tables/botPopulation.json.gz +0 -0
- package/src/data/tables/botSpecs.json.gz +0 -0
- package/src/data/tables/classLevelStats.json.gz +0 -0
- package/src/data/tables/combatConditions.json.gz +0 -0
- package/src/data/tables/combatSkillMeta.json.gz +0 -0
- package/src/data/tables/conditions.json.gz +0 -0
- package/src/data/tables/createInfo.json.gz +0 -0
- package/src/data/tables/creatureAggroGroups.json.gz +0 -0
- package/src/data/tables/creatureClassLevelStats.json.gz +0 -0
- package/src/data/tables/creaturePatrolPacks.json.gz +0 -0
- package/src/data/tables/creatureWeapons.json.gz +0 -0
- package/src/data/tables/creatures.json.gz +0 -0
- package/src/data/tables/dbScripts.json.gz +0 -0
- package/src/data/tables/dungeonAuthoredRoutes.json.gz +0 -0
- package/src/data/tables/dungeonCensus.json.gz +0 -0
- package/src/data/tables/dungeonGameObjects.json.gz +0 -0
- package/src/data/tables/dungeonPacks.json.gz +0 -0
- package/src/data/tables/dungeonPlateCover.json.gz +0 -0
- package/src/data/tables/dungeonSpawns.json.gz +0 -0
- package/src/data/tables/dungeonSurvey.json.gz +0 -0
- package/src/data/tables/durabilityCosts.json.gz +0 -0
- package/src/data/tables/durabilityQuality.json.gz +0 -0
- package/src/data/tables/enchantApplicators.json.gz +0 -0
- package/src/data/tables/entranceYards.json.gz +0 -0
- package/src/data/tables/explorationBasexp.json.gz +0 -0
- package/src/data/tables/factionTemplates.json.gz +0 -0
- package/src/data/tables/factions.json.gz +0 -0
- package/src/data/tables/gameEvents.json.gz +0 -0
- package/src/data/tables/gameObjects.json.gz +0 -0
- package/src/data/tables/gossipMenus.json.gz +0 -0
- package/src/data/tables/graveyards.json.gz +0 -0
- package/src/data/tables/instanceMaps.json.gz +0 -0
- package/src/data/tables/itemEnchantmentTemplates.json.gz +0 -0
- package/src/data/tables/itemEnchants.json.gz +0 -0
- package/src/data/tables/itemRandomProperties.json.gz +0 -0
- package/src/data/tables/itemSets.json.gz +0 -0
- package/src/data/tables/items.json.gz +0 -0
- package/src/data/tables/levelStats.json.gz +0 -0
- package/src/data/tables/locks.json.gz +0 -0
- package/src/data/tables/map-pin-overrides.json.gz +0 -0
- package/src/data/tables/nonCombatTrash.json.gz +0 -0
- package/src/data/tables/npcTexts.json.gz +0 -0
- package/src/data/tables/pageTexts.json.gz +0 -0
- package/src/data/tables/petAbilityTP.json.gz +0 -0
- package/src/data/tables/petGenericSpells.json.gz +0 -0
- package/src/data/tables/petLevelStats.json.gz +0 -0
- package/src/data/tables/playerbot-weightscales.json.gz +0 -0
- package/src/data/tables/pools.json.gz +0 -0
- package/src/data/tables/quests.json.gz +0 -0
- package/src/data/tables/races.json.gz +0 -0
- package/src/data/tables/reputationRanks.json.gz +0 -0
- package/src/data/tables/reputationRates.json.gz +0 -0
- package/src/data/tables/reputationSpillover.json.gz +0 -0
- package/src/data/tables/ridingSpells.json.gz +0 -0
- package/src/data/tables/scriptTexts.json.gz +0 -0
- package/src/data/tables/soundClipVolume.json.gz +0 -0
- package/src/data/tables/spellChain.json.gz +0 -0
- package/src/data/tables/spellTeleports.json.gz +0 -0
- package/src/data/tables/spells.json.gz +0 -0
- package/src/data/tables/talents.json.gz +0 -0
- package/src/data/tables/tavernTriggers.json.gz +0 -0
- package/src/data/tables/taxiNodes.json.gz +0 -0
- package/src/data/tables/taxiRoutes.json.gz +0 -0
- package/src/data/tables/trainers.json.gz +0 -0
- package/src/data/tables/transports.json.gz +0 -0
- package/src/data/tables/travelAnchors.json.gz +0 -0
- package/src/data/tables/travelEdges.json.gz +0 -0
- package/src/data/tables/unitConditions.json.gz +0 -0
- package/src/data/tables/vendors.json.gz +0 -0
- package/src/data/tables/weaponEnchantProcs.json.gz +0 -0
- package/src/data/tables/xp.json.gz +0 -0
- package/src/data/tables/zoneWeather.json.gz +0 -0
- package/src/data/tables/zones.json.gz +0 -0
- package/src/data/world-data.ts +56 -0
- package/src/data/zone-music-sets.json +2751 -0
- package/src/dev/etl/lib/loot-chance-sanity.mjs +180 -0
- package/src/domain/audioQuality.mjs +145 -0
- package/src/domain/bg/ab.ts +433 -0
- package/src/domain/bg/arenaComps.ts +644 -0
- package/src/domain/bg/arenaLab.ts +695 -0
- package/src/domain/bg/arenaPace.ts +31 -0
- package/src/domain/bg/arenaRating.ts +110 -0
- package/src/domain/bg/av.ts +758 -0
- package/src/domain/bg/avEnemyPush.ts +219 -0
- package/src/domain/bg/avField.ts +283 -0
- package/src/domain/bg/avInstanceNodes.ts +197 -0
- package/src/domain/bg/avInstanceScore.ts +123 -0
- package/src/domain/bg/avQuestItems.ts +55 -0
- package/src/domain/bg/avQuests.ts +210 -0
- package/src/domain/bg/avSession.ts +196 -0
- package/src/domain/bg/bgConsumes.ts +269 -0
- package/src/domain/bg/bgPrebuff.ts +153 -0
- package/src/domain/bg/bgRest.ts +91 -0
- package/src/domain/bg/bgRoster.ts +305 -0
- package/src/domain/bg/bgTier.ts +61 -0
- package/src/domain/bg/bgWorld.ts +862 -0
- package/src/domain/bg/match.ts +215 -0
- package/src/domain/bg/strategies.ts +552 -0
- package/src/domain/bg/types.ts +291 -0
- package/src/domain/bg/wsg.ts +264 -0
- package/src/domain/bots/actionProviderSpec.ts +38 -0
- package/src/domain/bots/autoConsumables.ts +285 -0
- package/src/domain/bots/betweenPullRest.ts +239 -0
- package/src/domain/bots/botGear.ts +248 -0
- package/src/domain/bots/botInventory.ts +486 -0
- package/src/domain/bots/botPet.ts +535 -0
- package/src/domain/bots/botPool.ts +291 -0
- package/src/domain/bots/botProfessions.ts +334 -0
- package/src/domain/bots/companionActionBar.ts +209 -0
- package/src/domain/bots/companionHireCost.ts +236 -0
- package/src/domain/bots/companionMissions.ts +582 -0
- package/src/domain/bots/companionPrep.ts +254 -0
- package/src/domain/bots/companionQuests.ts +270 -0
- package/src/domain/bots/companionRep.ts +75 -0
- package/src/domain/bots/companionRotation.ts +708 -0
- package/src/domain/bots/companionXp.ts +66 -0
- package/src/domain/bots/consumableShare.ts +811 -0
- package/src/domain/bots/dpsMate.ts +1072 -0
- package/src/domain/bots/groupCompReport.ts +132 -0
- package/src/domain/bots/healthstoneSupply.ts +198 -0
- package/src/domain/bots/outfitter.ts +1056 -0
- package/src/domain/bots/paladinPrePull.ts +231 -0
- package/src/domain/bots/partyRole.ts +40 -0
- package/src/domain/bots/playerbotEquipCache.ts +412 -0
- package/src/domain/bots/playerbotItemEligibility.ts +60 -0
- package/src/domain/bots/playerbotStatWeight.ts +853 -0
- package/src/domain/bots/playerbotUnavailableItems.ts +147 -0
- package/src/domain/bots/prePullBuffs.ts +219 -0
- package/src/domain/bots/prePullStealth.ts +82 -0
- package/src/domain/bots/runSupply.ts +251 -0
- package/src/domain/bots/runSupplyPrefs.ts +28 -0
- package/src/domain/bots/sendTradeGoods.ts +394 -0
- package/src/domain/bots/soulShardCap.ts +35 -0
- package/src/domain/bots/squad.ts +842 -0
- package/src/domain/bots/squadRun.ts +81 -0
- package/src/domain/character/actionbar.ts +346 -0
- package/src/domain/character/appearance.ts +165 -0
- package/src/domain/character/buildCombatant.ts +1726 -0
- package/src/domain/character/character.ts +356 -0
- package/src/domain/character/characterName.ts +43 -0
- package/src/domain/character/characterRatings.ts +424 -0
- package/src/domain/character/characterSpells.ts +282 -0
- package/src/domain/character/characterStats.ts +1559 -0
- package/src/domain/character/characterTalents.ts +398 -0
- package/src/domain/character/combatSkills.ts +994 -0
- package/src/domain/character/displayForm.ts +72 -0
- package/src/domain/character/formTalentAuras.ts +171 -0
- package/src/domain/character/forms.ts +499 -0
- package/src/domain/character/races.ts +40 -0
- package/src/domain/character/resurrectionSickness.ts +49 -0
- package/src/domain/character/spellbook.ts +169 -0
- package/src/domain/character/stanceBar.ts +354 -0
- package/src/domain/character/stancePrereq.ts +70 -0
- package/src/domain/character/talentBuilds.ts +63 -0
- package/src/domain/character/talentImport.ts +130 -0
- package/src/domain/character/talentLink.ts +123 -0
- package/src/domain/character/talents.ts +201 -0
- package/src/domain/core/conditionSnapshot.ts +92 -0
- package/src/domain/core/hover.ts +14 -0
- package/src/domain/core/ids.ts +58 -0
- package/src/domain/core/internalNameTags.ts +5 -0
- package/src/domain/core/runtimeDataPatches.ts +357 -0
- package/src/domain/creature/aiTargeting.ts +588 -0
- package/src/domain/creature/combatCondition.ts +157 -0
- package/src/domain/creature/creatureAggro.ts +804 -0
- package/src/domain/creature/creatureAi.ts +206 -0
- package/src/domain/creature/creatureAiConstants.ts +661 -0
- package/src/domain/creature/creatureCastList.ts +1007 -0
- package/src/domain/creature/creatureEventAi.ts +1409 -0
- package/src/domain/creature/creatureGroups.ts +144 -0
- package/src/domain/creature/creatureLinking.ts +333 -0
- package/src/domain/creature/creatureScaling.ts +320 -0
- package/src/domain/creature/creatureTrigger.ts +53 -0
- package/src/domain/creature/creatureWander.ts +74 -0
- package/src/domain/creature/eventAiTexts.ts +145 -0
- package/src/domain/creature/faction.ts +287 -0
- package/src/domain/creature/forcedReaction.ts +48 -0
- package/src/domain/creature/outdoorHuntable.ts +74 -0
- package/src/domain/creature/patrolPacks.ts +210 -0
- package/src/domain/creature/reputation.ts +967 -0
- package/src/domain/creature/unitFlags.ts +74 -0
- package/src/domain/creature/worldBosses.ts +393 -0
- package/src/domain/dungeonMusic.mjs +48 -0
- package/src/domain/economy/auction.ts +282 -0
- package/src/domain/economy/auctionBot.ts +1060 -0
- package/src/domain/economy/honorPrice.ts +100 -0
- package/src/domain/economy/mail.ts +958 -0
- package/src/domain/economy/money.ts +42 -0
- package/src/domain/economy/syntheticClassTrainers.ts +62 -0
- package/src/domain/economy/trading.ts +296 -0
- package/src/domain/economy/vendorSellAll.ts +252 -0
- package/src/domain/economy/vendorStock.ts +146 -0
- package/src/domain/items/ammo.ts +817 -0
- package/src/domain/items/bank.ts +162 -0
- package/src/domain/items/consumableFamily.ts +205 -0
- package/src/domain/items/craftUpgrades.ts +83 -0
- package/src/domain/items/createItem.ts +93 -0
- package/src/domain/items/durability.ts +581 -0
- package/src/domain/items/equipment.ts +441 -0
- package/src/domain/items/equipmentHelper.ts +767 -0
- package/src/domain/items/inventory.ts +561 -0
- package/src/domain/items/itemBonding.ts +93 -0
- package/src/domain/items/itemContainer.ts +245 -0
- package/src/domain/items/itemDisplayName.ts +33 -0
- package/src/domain/items/itemInstance.ts +181 -0
- package/src/domain/items/itemRandomEnchantOutcomes.ts +315 -0
- package/src/domain/items/itemRandomProps.ts +77 -0
- package/src/domain/items/itemRestrictions.ts +329 -0
- package/src/domain/items/itemTeaches.ts +82 -0
- package/src/domain/items/itemUseCooldown.ts +52 -0
- package/src/domain/items/itemUseTarget.ts +90 -0
- package/src/domain/items/junkCategories.ts +174 -0
- package/src/domain/items/junkFilter.ts +368 -0
- package/src/domain/items/keyring.ts +131 -0
- package/src/domain/items/loot.ts +221 -0
- package/src/domain/items/mounts.ts +190 -0
- package/src/domain/items/onUsePayload.ts +102 -0
- package/src/domain/items/pendingLoot.ts +107 -0
- package/src/domain/items/relic.ts +105 -0
- package/src/domain/items/rocketBoots.ts +36 -0
- package/src/domain/items/sortContainer.ts +139 -0
- package/src/domain/items/spareContainers.ts +71 -0
- package/src/domain/items/spellReagentIndex.ts +131 -0
- package/src/domain/items/staleConsumables.ts +66 -0
- package/src/domain/items/weaponSpender.ts +110 -0
- package/src/domain/listDungeonIds.mjs +28 -0
- package/src/domain/macro/compose.ts +239 -0
- package/src/domain/macro/conditions.ts +260 -0
- package/src/domain/macro/creatureTypes.ts +40 -0
- package/src/domain/macro/describe.ts +169 -0
- package/src/domain/macro/icon.ts +60 -0
- package/src/domain/macro/index.ts +20 -0
- package/src/domain/macro/normalize.ts +112 -0
- package/src/domain/macro/parse.ts +316 -0
- package/src/domain/macro/plan.ts +288 -0
- package/src/domain/macro/rotation.ts +590 -0
- package/src/domain/macro/rotationEnv.ts +173 -0
- package/src/domain/macro/slots.ts +101 -0
- package/src/domain/macro/snapshot.ts +114 -0
- package/src/domain/macro/templates.ts +446 -0
- package/src/domain/macro/types.ts +70 -0
- package/src/domain/macro/units.ts +93 -0
- package/src/domain/macro/weaponTypes.ts +83 -0
- package/src/domain/nav/cityTeleports.ts +10 -0
- package/src/domain/nav/mounting.ts +113 -0
- package/src/domain/nav/nav.ts +43 -0
- package/src/domain/nav/navCollision.ts +606 -0
- package/src/domain/nav/navOutdoors.ts +91 -0
- package/src/domain/nav/navRegistry.ts +179 -0
- package/src/domain/nav/navRoomGraph.ts +302 -0
- package/src/domain/nav/navTypes.ts +43 -0
- package/src/domain/nav/navmesh.ts +1715 -0
- package/src/domain/nav/speed.ts +200 -0
- package/src/domain/nav/storey.ts +10 -0
- package/src/domain/nav/travel.ts +725 -0
- package/src/domain/nav/travelTypes.ts +75 -0
- package/src/domain/pet/pet.ts +1150 -0
- package/src/domain/pet/petActionBar.ts +180 -0
- package/src/domain/pet/petSpellbook.ts +39 -0
- package/src/domain/pet/petStable.ts +81 -0
- package/src/domain/professions/autoDisenchant.ts +236 -0
- package/src/domain/professions/characterEnchants.ts +176 -0
- package/src/domain/professions/craftCooldown.ts +52 -0
- package/src/domain/professions/enchantApply.ts +62 -0
- package/src/domain/professions/enchantTargets.ts +114 -0
- package/src/domain/professions/enchanting.ts +236 -0
- package/src/domain/professions/gatherFilter.ts +149 -0
- package/src/domain/professions/gearEnchant.ts +137 -0
- package/src/domain/professions/heldTools.ts +29 -0
- package/src/domain/professions/learnAllRecipes.ts +146 -0
- package/src/domain/professions/miningHarvest.ts +69 -0
- package/src/domain/professions/partyDisenchant.ts +294 -0
- package/src/domain/professions/partyWork.ts +83 -0
- package/src/domain/professions/pickpocket.ts +172 -0
- package/src/domain/professions/poisons.ts +240 -0
- package/src/domain/professions/professions.ts +677 -0
- package/src/domain/professions/rareNodes.ts +45 -0
- package/src/domain/professions/skinLoot.ts +27 -0
- package/src/domain/professions/vendorReagents.ts +152 -0
- package/src/domain/professions/weaponImbueHand.ts +171 -0
- package/src/domain/questFarmFilter.mjs +42 -0
- package/src/domain/quests/doQuest.ts +1204 -0
- package/src/domain/quests/gossip.ts +308 -0
- package/src/domain/quests/gossipTalk.ts +298 -0
- package/src/domain/quests/interpreter/canComplete.ts +150 -0
- package/src/domain/quests/interpreter/claim.ts +137 -0
- package/src/domain/quests/interpreter/dbscript/handlers.ts +1371 -0
- package/src/domain/quests/interpreter/dbscript/handlersBatch.ts +1251 -0
- package/src/domain/quests/interpreter/dbscript/hooks.ts +331 -0
- package/src/domain/quests/interpreter/dbscript/index.ts +212 -0
- package/src/domain/quests/interpreter/dbscript/opcodes.ts +257 -0
- package/src/domain/quests/interpreter/dbscript/registry.ts +1194 -0
- package/src/domain/quests/interpreter/dbscript/registryAreatriggerScripts.ts +539 -0
- package/src/domain/quests/interpreter/dbscript/registryAshenvale.ts +553 -0
- package/src/domain/quests/interpreter/dbscript/registryAzshara.ts +272 -0
- package/src/domain/quests/interpreter/dbscript/registryDarkshore.ts +637 -0
- package/src/domain/quests/interpreter/dbscript/registryDesolace.ts +501 -0
- package/src/domain/quests/interpreter/dbscript/registryDustwallowMarsh.ts +735 -0
- package/src/domain/quests/interpreter/dbscript/registryFelwood.ts +493 -0
- package/src/domain/quests/interpreter/dbscript/registryFeralas.ts +485 -0
- package/src/domain/quests/interpreter/dbscript/registryGoScripts.ts +203 -0
- package/src/domain/quests/interpreter/dbscript/registryMoonglade.ts +288 -0
- package/src/domain/quests/interpreter/dbscript/registryNpcProfessions.ts +230 -0
- package/src/domain/quests/interpreter/dbscript/registryNpcsSpecial.ts +545 -0
- package/src/domain/quests/interpreter/dbscript/registryRazorfenDowns.ts +293 -0
- package/src/domain/quests/interpreter/dbscript/registryRazorfenKraul.ts +221 -0
- package/src/domain/quests/interpreter/dbscript/registryRedridge.ts +112 -0
- package/src/domain/quests/interpreter/dbscript/registrySearingGorge.ts +125 -0
- package/src/domain/quests/interpreter/dbscript/registrySiblings.ts +51 -0
- package/src/domain/quests/interpreter/dbscript/registrySilverpineForest.ts +172 -0
- package/src/domain/quests/interpreter/dbscript/registryStonetalonMountains.ts +180 -0
- package/src/domain/quests/interpreter/dbscript/registryStormwindCity.ts +369 -0
- package/src/domain/quests/interpreter/dbscript/registryStranglethornVale.ts +115 -0
- package/src/domain/quests/interpreter/dbscript/registryStratholme.ts +146 -0
- package/src/domain/quests/interpreter/dbscript/registrySunkenTemple.ts +149 -0
- package/src/domain/quests/interpreter/dbscript/registrySwampOfSorrows.ts +163 -0
- package/src/domain/quests/interpreter/dbscript/registryTanaris.ts +318 -0
- package/src/domain/quests/interpreter/dbscript/registryTeldrassil.ts +120 -0
- package/src/domain/quests/interpreter/dbscript/registryTheBarrens.ts +603 -0
- package/src/domain/quests/interpreter/dbscript/registryThousandNeedles.ts +499 -0
- package/src/domain/quests/interpreter/dbscript/registryTirisfalGlades.ts +222 -0
- package/src/domain/quests/interpreter/dbscript/registryUngoroCrater.ts +291 -0
- package/src/domain/quests/interpreter/dbscript/registryWarEffort.ts +773 -0
- package/src/domain/quests/interpreter/dbscript/registryWesternPlaguelands.ts +206 -0
- package/src/domain/quests/interpreter/dbscript/registryWestfall.ts +190 -0
- package/src/domain/quests/interpreter/dbscript/registryWetlands.ts +186 -0
- package/src/domain/quests/interpreter/dbscript/registryWinterspring.ts +235 -0
- package/src/domain/quests/interpreter/dbscript/types.ts +817 -0
- package/src/domain/quests/interpreter/dbscript/vm.ts +171 -0
- package/src/domain/quests/interpreter/diff.ts +349 -0
- package/src/domain/quests/interpreter/fixtures/oracle-questlog-qi2.json +2417 -0
- package/src/domain/quests/interpreter/flags.ts +101 -0
- package/src/domain/quests/interpreter/index.ts +113 -0
- package/src/domain/quests/interpreter/live.ts +178 -0
- package/src/domain/quests/interpreter/types.ts +81 -0
- package/src/domain/quests/interpreter/updaters.ts +412 -0
- package/src/domain/quests/questCorpseUse.ts +155 -0
- package/src/domain/quests/questDialog.ts +43 -0
- package/src/domain/quests/questFight.ts +34 -0
- package/src/domain/quests/questObjectiveLabel.ts +39 -0
- package/src/domain/quests/questRewardChoice.ts +85 -0
- package/src/domain/quests/questScriptCredit.ts +26 -0
- package/src/domain/quests/questScriptItemUse.ts +74 -0
- package/src/domain/quests/questTameRods.ts +79 -0
- package/src/domain/quests/questlog.ts +1545 -0
- package/src/domain/quests/talkDeliver.ts +170 -0
- package/src/domain/raid/globalActionBar.ts +195 -0
- package/src/domain/raid/instanceRoster.ts +194 -0
- package/src/domain/raid/partySummon.ts +198 -0
- package/src/domain/raid/partyVault.ts +320 -0
- package/src/domain/raid/raidBossAbilities.ts +268 -0
- package/src/domain/raid/raidComp.ts +335 -0
- package/src/domain/raid/raidCustomRows.ts +453 -0
- package/src/domain/raid/raidEncounterGear.ts +298 -0
- package/src/domain/raid/raidEncounterTactics.ts +412 -0
- package/src/domain/raid/raidPlan.ts +509 -0
- package/src/domain/raid/raidPlanEdits.ts +98 -0
- package/src/domain/raid/raidPlanPacks.ts +480 -0
- package/src/domain/raid/raidRecovery.ts +183 -0
- package/src/domain/raid/raidRosterTemplate.ts +138 -0
- package/src/domain/rotation/auraSide.ts +68 -0
- package/src/domain/rotation/build.ts +3031 -0
- package/src/domain/rotation/classes/druid.ts +58 -0
- package/src/domain/rotation/classes/hooks.ts +59 -0
- package/src/domain/rotation/classes/hunter.ts +156 -0
- package/src/domain/rotation/classes/index.ts +104 -0
- package/src/domain/rotation/classes/mage.ts +99 -0
- package/src/domain/rotation/classes/paladin.ts +296 -0
- package/src/domain/rotation/classes/priest.ts +94 -0
- package/src/domain/rotation/classes/pullOpener.ts +92 -0
- package/src/domain/rotation/classes/rogue.ts +69 -0
- package/src/domain/rotation/classes/shaman.ts +29 -0
- package/src/domain/rotation/classes/supportSpec.ts +94 -0
- package/src/domain/rotation/classes/warlock.ts +81 -0
- package/src/domain/rotation/classes/warrior.ts +402 -0
- package/src/domain/rotation/classify.ts +1381 -0
- package/src/domain/rotation/condMetricPicker.ts +379 -0
- package/src/domain/rotation/consumables.ts +242 -0
- package/src/domain/rotation/evaluate.ts +1115 -0
- package/src/domain/rotation/finisherLadder.ts +145 -0
- package/src/domain/rotation/invent.ts +938 -0
- package/src/domain/rotation/killOrder.ts +30 -0
- package/src/domain/rotation/openerForm.ts +22 -0
- package/src/domain/rotation/paladinBuffs.ts +568 -0
- package/src/domain/rotation/prebuff.ts +283 -0
- package/src/domain/rotation/raidRowTuning.ts +34 -0
- package/src/domain/rotation/rotation.ts +11 -0
- package/src/domain/rotation/rotationProfiles.ts +180 -0
- package/src/domain/rotation/rotationSuggestions.ts +851 -0
- package/src/domain/rotation/ruleAfterChain.ts +49 -0
- package/src/domain/rotation/spec.ts +70 -0
- package/src/domain/rotation/spellPicker.ts +140 -0
- package/src/domain/rotation/stand.ts +143 -0
- package/src/domain/rotation/types.ts +718 -0
- package/src/domain/run/battlegroundRun.ts +111 -0
- package/src/domain/run/canEnterContext.ts +32 -0
- package/src/domain/run/death.ts +561 -0
- package/src/domain/run/deathRecovery.ts +289 -0
- package/src/domain/run/duel.ts +141 -0
- package/src/domain/run/dungeonRun.ts +344 -0
- package/src/domain/run/floorRest.ts +159 -0
- package/src/domain/run/honor.ts +557 -0
- package/src/domain/run/honorWeek.ts +180 -0
- package/src/domain/run/whenMap.ts +977 -0
- package/src/domain/scriptdev/arathiHighlands.ts +445 -0
- package/src/domain/scriptdev/ashenvale.ts +635 -0
- package/src/domain/scriptdev/ashenvaleHelpers.ts +1215 -0
- package/src/domain/scriptdev/azshara.ts +892 -0
- package/src/domain/scriptdev/blackfathomDeeps.ts +212 -0
- package/src/domain/scriptdev/blackrockDepths.ts +1434 -0
- package/src/domain/scriptdev/blackrockSpire.ts +730 -0
- package/src/domain/scriptdev/blackwingLair.ts +521 -0
- package/src/domain/scriptdev/burningSteppes.ts +62 -0
- package/src/domain/scriptdev/classFilter.ts +43 -0
- package/src/domain/scriptdev/darkshore.ts +817 -0
- package/src/domain/scriptdev/darkshoreHelpers.ts +853 -0
- package/src/domain/scriptdev/deadmines.ts +331 -0
- package/src/domain/scriptdev/desolace.ts +1239 -0
- package/src/domain/scriptdev/direMaul.ts +859 -0
- package/src/domain/scriptdev/durotar.ts +532 -0
- package/src/domain/scriptdev/dustwallowMarsh.ts +758 -0
- package/src/domain/scriptdev/dustwallowMarshHelpers.ts +994 -0
- package/src/domain/scriptdev/easternPlaguelands.ts +21 -0
- package/src/domain/scriptdev/felwood.ts +1055 -0
- package/src/domain/scriptdev/feralas.ts +571 -0
- package/src/domain/scriptdev/feralasHelpers.ts +838 -0
- package/src/domain/scriptdev/gnomeregan.ts +466 -0
- package/src/domain/scriptdev/guards.ts +616 -0
- package/src/domain/scriptdev/hinterlands.ts +693 -0
- package/src/domain/scriptdev/host.ts +1134 -0
- package/src/domain/scriptdev/index.ts +123 -0
- package/src/domain/scriptdev/instanceRaids.ts +136 -0
- package/src/domain/scriptdev/itemScripts.ts +37 -0
- package/src/domain/scriptdev/lochModan.ts +283 -0
- package/src/domain/scriptdev/maraudon.ts +232 -0
- package/src/domain/scriptdev/moltenCore.ts +831 -0
- package/src/domain/scriptdev/moonglade.ts +659 -0
- package/src/domain/scriptdev/moongladeHelpers.ts +933 -0
- package/src/domain/scriptdev/naxxramas.ts +577 -0
- package/src/domain/scriptdev/naxxramasConstruct.ts +364 -0
- package/src/domain/scriptdev/naxxramasFrostwyrm.ts +378 -0
- package/src/domain/scriptdev/naxxramasMilitary.ts +276 -0
- package/src/domain/scriptdev/npcProfessions.ts +1025 -0
- package/src/domain/scriptdev/npcsSpecial.ts +1379 -0
- package/src/domain/scriptdev/onyxiasLair.ts +313 -0
- package/src/domain/scriptdev/orgrimmar.ts +147 -0
- package/src/domain/scriptdev/professionSpecConsumer.ts +481 -0
- package/src/domain/scriptdev/razorfenDowns.ts +468 -0
- package/src/domain/scriptdev/razorfenKraul.ts +410 -0
- package/src/domain/scriptdev/redridgeMountains.ts +163 -0
- package/src/domain/scriptdev/registry.ts +945 -0
- package/src/domain/scriptdev/ruinsOfAhnqiraj.ts +356 -0
- package/src/domain/scriptdev/scarletMonastery.ts +713 -0
- package/src/domain/scriptdev/scholomance.ts +682 -0
- package/src/domain/scriptdev/searingGorge.ts +295 -0
- package/src/domain/scriptdev/shadowfangKeep.ts +181 -0
- package/src/domain/scriptdev/silithus.ts +71 -0
- package/src/domain/scriptdev/silverpineForest.ts +662 -0
- package/src/domain/scriptdev/stonetalonMountains.ts +493 -0
- package/src/domain/scriptdev/stormwindCity.ts +1192 -0
- package/src/domain/scriptdev/stranglethornVale.ts +402 -0
- package/src/domain/scriptdev/stratholme.ts +650 -0
- package/src/domain/scriptdev/stratholmeScripts.ts +505 -0
- package/src/domain/scriptdev/sunkenTemple.ts +736 -0
- package/src/domain/scriptdev/swampOfSorrows.ts +22 -0
- package/src/domain/scriptdev/tanaris.ts +391 -0
- package/src/domain/scriptdev/tanarisHelpers.ts +661 -0
- package/src/domain/scriptdev/teldrassil.ts +143 -0
- package/src/domain/scriptdev/templeOfAhnqiraj.ts +1013 -0
- package/src/domain/scriptdev/theBarrens.ts +709 -0
- package/src/domain/scriptdev/theBarrensHelpers.ts +1026 -0
- package/src/domain/scriptdev/thousandNeedles.ts +426 -0
- package/src/domain/scriptdev/thousandNeedlesHelpers.ts +566 -0
- package/src/domain/scriptdev/tirisfalGlades.ts +533 -0
- package/src/domain/scriptdev/types.ts +1026 -0
- package/src/domain/scriptdev/uldaman.ts +437 -0
- package/src/domain/scriptdev/ungoroCrater.ts +549 -0
- package/src/domain/scriptdev/ungoroCraterHelpers.ts +1006 -0
- package/src/domain/scriptdev/wailingCaverns.ts +700 -0
- package/src/domain/scriptdev/warEffort.ts +371 -0
- package/src/domain/scriptdev/westernPlaguelands.ts +952 -0
- package/src/domain/scriptdev/westfall.ts +767 -0
- package/src/domain/scriptdev/wetlands.ts +660 -0
- package/src/domain/scriptdev/winterspring.ts +482 -0
- package/src/domain/scriptdev/winterspringHelpers.ts +801 -0
- package/src/domain/scriptdev/worldBosses.ts +605 -0
- package/src/domain/scriptdev/zulfarrak.ts +478 -0
- package/src/domain/scriptdev/zulgurub.ts +1152 -0
- package/src/domain/sim/dummySim.ts +408 -0
- package/src/domain/sim/targetDummy.ts +29 -0
- package/src/domain/social/guild.ts +148 -0
- package/src/domain/spells/areaAuraMembership.ts +93 -0
- package/src/domain/spells/breakableStunCc.ts +166 -0
- package/src/domain/spells/cancelAura.ts +80 -0
- package/src/domain/spells/diminishing.ts +167 -0
- package/src/domain/spells/dispel.ts +149 -0
- package/src/domain/spells/dispelMechanic.ts +105 -0
- package/src/domain/spells/equipSpells.ts +247 -0
- package/src/domain/spells/learnOnTargets.ts +260 -0
- package/src/domain/spells/mergeSchoolImmunityFromRaw.ts +66 -0
- package/src/domain/spells/resurrectSpell.ts +124 -0
- package/src/domain/spells/spellPushback.ts +39 -0
- package/src/domain/spells/spellReflect.ts +43 -0
- package/src/domain/spells/stealth.ts +183 -0
- package/src/domain/spells/totem.ts +394 -0
- package/src/domain/spells/worldCast.ts +187 -0
- package/src/domain/world/areaTriggerLocks.ts +177 -0
- package/src/domain/world/dungeonMusic.ts +108 -0
- package/src/domain/world/gameEvents.ts +119 -0
- package/src/domain/world/gameObjects.ts +1030 -0
- package/src/domain/world/goEventFire.ts +234 -0
- package/src/domain/world/goMoTransport.ts +74 -0
- package/src/domain/world/goTransport.ts +81 -0
- package/src/domain/world/hazards.ts +459 -0
- package/src/domain/world/openLock.ts +398 -0
- package/src/domain/world/pools.ts +470 -0
- package/src/domain/world/restArea.ts +37 -0
- package/src/domain/world/weather.ts +201 -0
- package/src/domain/zoneAmbience.mjs +87 -0
- package/src/domain/zoneMusic.mjs +62 -0
- package/src/domain/zoneMusicQueue.mjs +7 -0
- package/src/engine/combat/activeSeal.ts +39 -0
- package/src/engine/combat/aiTargetResolve.ts +64 -0
- package/src/engine/combat/aoeCast.ts +289 -0
- package/src/engine/combat/applyConsumeAura.ts +74 -0
- package/src/engine/combat/applyDemonicSacrifice.ts +70 -0
- package/src/engine/combat/applyDispelMechanic.ts +30 -0
- package/src/engine/combat/applyHealEffect.ts +301 -0
- package/src/engine/combat/applySchoolAbsorb.ts +114 -0
- package/src/engine/combat/applySpell.ts +3169 -0
- package/src/engine/combat/applySpellLate.ts +2026 -0
- package/src/engine/combat/applySpellLateBag.ts +144 -0
- package/src/engine/combat/areaAura.ts +283 -0
- package/src/engine/combat/attackTable.ts +508 -0
- package/src/engine/combat/battleRez.ts +87 -0
- package/src/engine/combat/castAction.ts +36 -0
- package/src/engine/combat/castTargetGates.ts +75 -0
- package/src/engine/combat/castableKit.ts +68 -0
- package/src/engine/combat/ccMirrorUpgrade.ts +39 -0
- package/src/engine/combat/chainFan.ts +210 -0
- package/src/engine/combat/channel.ts +423 -0
- package/src/engine/combat/chaseCloseness.ts +95 -0
- package/src/engine/combat/cmangosCastGates.ts +129 -0
- package/src/engine/combat/combatFlag.ts +77 -0
- package/src/engine/combat/combatGeometry.ts +1329 -0
- package/src/engine/combat/combustion.ts +68 -0
- package/src/engine/combat/context.ts +730 -0
- package/src/engine/combat/createSession.ts +1165 -0
- package/src/engine/combat/creatureLeash.ts +38 -0
- package/src/engine/combat/crowdControl.ts +1259 -0
- package/src/engine/combat/dispelDuty.ts +54 -0
- package/src/engine/combat/dispelReflect.ts +609 -0
- package/src/engine/combat/displaceFloor.ts +113 -0
- package/src/engine/combat/duelBounds.ts +47 -0
- package/src/engine/combat/equippedItemGate.ts +297 -0
- package/src/engine/combat/evadeLifecycle.ts +63 -0
- package/src/engine/combat/eventAi.ts +2220 -0
- package/src/engine/combat/facing.ts +74 -0
- package/src/engine/combat/fearFlee.ts +137 -0
- package/src/engine/combat/fighterFactory.ts +1144 -0
- package/src/engine/combat/forceDespawnAction.ts +51 -0
- package/src/engine/combat/formulas.ts +807 -0
- package/src/engine/combat/friendlyFan.ts +55 -0
- package/src/engine/combat/groundPoolTick.ts +210 -0
- package/src/engine/combat/hazards.ts +114 -0
- package/src/engine/combat/healTargets.ts +226 -0
- package/src/engine/combat/heartbeatResist.ts +49 -0
- package/src/engine/combat/hostileItemUse.ts +75 -0
- package/src/engine/combat/interruptAuras.ts +66 -0
- package/src/engine/combat/itemRescue.ts +49 -0
- package/src/engine/combat/itemUse.ts +260 -0
- package/src/engine/combat/kitById.ts +23 -0
- package/src/engine/combat/knockBack.ts +201 -0
- package/src/engine/combat/leap.ts +89 -0
- package/src/engine/combat/mitigation.ts +587 -0
- package/src/engine/combat/modTaunt.ts +43 -0
- package/src/engine/combat/motionClaim.ts +268 -0
- package/src/engine/combat/motionGate.ts +150 -0
- package/src/engine/combat/motionGenerator.ts +27 -0
- package/src/engine/combat/navSight.ts +138 -0
- package/src/engine/combat/perfSink.ts +28 -0
- package/src/engine/combat/periodicDue.ts +55 -0
- package/src/engine/combat/petAuras.ts +86 -0
- package/src/engine/combat/pickAction.ts +3449 -0
- package/src/engine/combat/powerForm.ts +735 -0
- package/src/engine/combat/powerPools.ts +49 -0
- package/src/engine/combat/predicates.ts +538 -0
- package/src/engine/combat/procsDamage.ts +1823 -0
- package/src/engine/combat/reactiveGates.ts +135 -0
- package/src/engine/combat/roles.ts +389 -0
- package/src/engine/combat/rotationSubject.ts +78 -0
- package/src/engine/combat/ruleAfter.ts +106 -0
- package/src/engine/combat/seedDisplayAuras.ts +203 -0
- package/src/engine/combat/seedOocEffects.ts +317 -0
- package/src/engine/combat/seedSchoolImmunities.ts +45 -0
- package/src/engine/combat/session-types.ts +458 -0
- package/src/engine/combat/sessionApi.ts +1785 -0
- package/src/engine/combat/sessionCharge.ts +124 -0
- package/src/engine/combat/sessionChase.ts +869 -0
- package/src/engine/combat/sessionDeaths.ts +469 -0
- package/src/engine/combat/sessionFocus.ts +506 -0
- package/src/engine/combat/sessionFollow.ts +167 -0
- package/src/engine/combat/sessionGeometry.ts +188 -0
- package/src/engine/combat/sessionHome.ts +75 -0
- package/src/engine/combat/sessionInject.ts +719 -0
- package/src/engine/combat/sessionMechanicMove.ts +555 -0
- package/src/engine/combat/sessionMotion.ts +1553 -0
- package/src/engine/combat/sessionMotionKit.ts +247 -0
- package/src/engine/combat/sessionMoveIntent.ts +49 -0
- package/src/engine/combat/sessionMoveOrder.ts +200 -0
- package/src/engine/combat/sessionPathTo.ts +657 -0
- package/src/engine/combat/sessionPools.ts +688 -0
- package/src/engine/combat/sessionSteer.ts +144 -0
- package/src/engine/combat/sessionStepBack.ts +151 -0
- package/src/engine/combat/sessionStepWrap.ts +116 -0
- package/src/engine/combat/sessionView.ts +442 -0
- package/src/engine/combat/simEffects.ts +32 -0
- package/src/engine/combat/simFacade.ts +620 -0
- package/src/engine/combat/simPump.ts +264 -0
- package/src/engine/combat/simSnapshot.ts +165 -0
- package/src/engine/combat/simThreadPool.ts +35 -0
- package/src/engine/combat/skeramImages.ts +57 -0
- package/src/engine/combat/slowUpdate.ts +178 -0
- package/src/engine/combat/snapToFloor.ts +42 -0
- package/src/engine/combat/speedAura.ts +29 -0
- package/src/engine/combat/spellReagents.ts +71 -0
- package/src/engine/combat/stealthDetect.ts +93 -0
- package/src/engine/combat/stepBackMotion.ts +171 -0
- package/src/engine/combat/stepSession.ts +3102 -0
- package/src/engine/combat/summonCast.ts +243 -0
- package/src/engine/combat/thaddiusPolarity.ts +97 -0
- package/src/engine/combat/threat.ts +388 -0
- package/src/engine/combat/threatOps.ts +272 -0
- package/src/engine/combat/tickWorkerBody.ts +211 -0
- package/src/engine/combat/totemAuras.ts +122 -0
- package/src/engine/combat/triggerPayload.ts +42 -0
- package/src/engine/combat/triggeredCompanion.ts +63 -0
- package/src/engine/combat/types.ts +1897 -0
- package/src/engine/combat/useObjectTrap.ts +140 -0
- package/src/engine/combat/walkSurface.ts +54 -0
- package/src/engine/combat/weapon.ts +1248 -0
- package/src/engine/combat/worldFrame.ts +43 -0
- package/src/engine/combat.solo-golden.json +2242 -0
- package/src/engine/combat.ts +84 -0
- package/src/engine/core/detMath.ts +289 -0
- package/src/engine/core/events.ts +357 -0
- package/src/engine/core/rng.ts +36 -0
- package/src/engine/game/actionBars.ts +124 -0
- package/src/engine/game/activateObjectFromSpell.ts +320 -0
- package/src/engine/game/applyActiveObjectFromDbScript.ts +98 -0
- package/src/engine/game/applyDeathAndSpellScripts.ts +268 -0
- package/src/engine/game/applyDoorFromDbScript.ts +388 -0
- package/src/engine/game/applyEscortFromDbScript.ts +290 -0
- package/src/engine/game/applyGoSpellcasterCast.ts +40 -0
- package/src/engine/game/applyHoverFromDbScript.ts +110 -0
- package/src/engine/game/applyOocResurrect.ts +71 -0
- package/src/engine/game/applySpellDurability.ts +115 -0
- package/src/engine/game/applyTailFromDbScript.ts +478 -0
- package/src/engine/game/applyTerminateFromDbScript.ts +95 -0
- package/src/engine/game/auctionMail.ts +269 -0
- package/src/engine/game/bagOverflow.ts +130 -0
- package/src/engine/game/bank.ts +110 -0
- package/src/engine/game/barAutofill.ts +26 -0
- package/src/engine/game/battleground.ts +369 -0
- package/src/engine/game/combatEnemySpec.ts +216 -0
- package/src/engine/game/combatObjectTraps.ts +167 -0
- package/src/engine/game/combatSeed.ts +320 -0
- package/src/engine/game/combatSession.ts +3241 -0
- package/src/engine/game/combatSessionClock.ts +62 -0
- package/src/engine/game/companionQuestActions.ts +242 -0
- package/src/engine/game/companionTraining.ts +40 -0
- package/src/engine/game/consumables.ts +624 -0
- package/src/engine/game/context.ts +53 -0
- package/src/engine/game/createHealthstone.ts +45 -0
- package/src/engine/game/deathFlow.ts +127 -0
- package/src/engine/game/devGrant.ts +117 -0
- package/src/engine/game/dynamicObject.ts +365 -0
- package/src/engine/game/enchantItem.ts +177 -0
- package/src/engine/game/equipmentHelper.ts +806 -0
- package/src/engine/game/factionState.ts +108 -0
- package/src/engine/game/garmentsOoc.ts +69 -0
- package/src/engine/game/globalActionBar.ts +179 -0
- package/src/engine/game/goInteractQuestCredit.ts +51 -0
- package/src/engine/game/goMoTransportUse.ts +61 -0
- package/src/engine/game/goTransportUse.ts +60 -0
- package/src/engine/game/healthstoneUpkeep.ts +59 -0
- package/src/engine/game/killSkin.ts +124 -0
- package/src/engine/game/learnFromItem.ts +118 -0
- package/src/engine/game/loadReconcile.ts +551 -0
- package/src/engine/game/loot.ts +294 -0
- package/src/engine/game/macros.ts +125 -0
- package/src/engine/game/mail.ts +293 -0
- package/src/engine/game/meetingStoneQueue.ts +75 -0
- package/src/engine/game/meetingStoneUse.ts +54 -0
- package/src/engine/game/newGameState.ts +363 -0
- package/src/engine/game/oocAuraInterrupt.ts +92 -0
- package/src/engine/game/oocCast.ts +241 -0
- package/src/engine/game/oocCastEffects.ts +803 -0
- package/src/engine/game/oocCastMethods.ts +1077 -0
- package/src/engine/game/openLockFromSpell.ts +174 -0
- package/src/engine/game/outdoorPvp.ts +187 -0
- package/src/engine/game/outfitter.ts +644 -0
- package/src/engine/game/paladinBoard.ts +393 -0
- package/src/engine/game/partyAuras.ts +121 -0
- package/src/engine/game/persistCombatAuras.ts +91 -0
- package/src/engine/game/pets.ts +459 -0
- package/src/engine/game/prePullHealthstones.ts +154 -0
- package/src/engine/game/professions.ts +2227 -0
- package/src/engine/game/pruneStaleRuntime.ts +39 -0
- package/src/engine/game/questFightCredit.ts +36 -0
- package/src/engine/game/questItemOnCorpse.ts +166 -0
- package/src/engine/game/questItemOnCreature.ts +103 -0
- package/src/engine/game/questLog.ts +879 -0
- package/src/engine/game/questSpellComplete.ts +21 -0
- package/src/engine/game/questTurnIn.ts +598 -0
- package/src/engine/game/raidParty.ts +32 -0
- package/src/engine/game/reagentBuyIn.ts +39 -0
- package/src/engine/game/regenRest.ts +186 -0
- package/src/engine/game/rotation.ts +425 -0
- package/src/engine/game/runFullDungeon.ts +611 -0
- package/src/engine/game/runSupply.ts +80 -0
- package/src/engine/game/sanitizeDriftedItems.ts +135 -0
- package/src/engine/game/scriptDevGoUse.ts +397 -0
- package/src/engine/game/scriptDevInnkeeper.ts +150 -0
- package/src/engine/game/scriptDevProfessionSpec.ts +99 -0
- package/src/engine/game/sendEventFromSpell.ts +87 -0
- package/src/engine/game/sortContainers.ts +85 -0
- package/src/engine/game/spellReputation.ts +69 -0
- package/src/engine/game/squad/squadDungeonSeating.ts +197 -0
- package/src/engine/game/squadDungeon.ts +4222 -0
- package/src/engine/game/squadQuestShare.ts +260 -0
- package/src/engine/game/summonObjectSlot.ts +69 -0
- package/src/engine/game/summonObjectWild.ts +73 -0
- package/src/engine/game/summoningRitualUse.ts +141 -0
- package/src/engine/game/talents.ts +356 -0
- package/src/engine/game/tamingRodUse.ts +66 -0
- package/src/engine/game/tempSpawnCreature.ts +136 -0
- package/src/engine/game/tickDungeonPatrolScripts.ts +205 -0
- package/src/engine/game/tickTimedQuests.ts +28 -0
- package/src/engine/game/trade.ts +586 -0
- package/src/engine/game/travel.ts +1155 -0
- package/src/engine/game/types.ts +1855 -0
- package/src/engine/game/vendorOffers.ts +244 -0
- package/src/engine/game/weaponImbueItem.ts +281 -0
- package/src/engine/game/worldSession.ts +183 -0
- package/src/engine/game/worldState.ts +166 -0
- package/src/engine/game.ts +968 -0
- package/src/engine/spells/GAP.md +67 -0
- package/src/engine/spells/absorbs.ts +376 -0
- package/src/engine/spells/addTargetTrigger.ts +53 -0
- package/src/engine/spells/auraPerSecondCost.ts +50 -0
- package/src/engine/spells/auraStacking.ts +497 -0
- package/src/engine/spells/cmangos-special-cases-combustion.ts +13 -0
- package/src/engine/spells/cmangos-special-cases-s18.ts +445 -0
- package/src/engine/spells/cmangos-special-cases-s19.ts +324 -0
- package/src/engine/spells/cmangos-special-cases-s20.ts +385 -0
- package/src/engine/spells/cmangos-special-cases-s21.ts +116 -0
- package/src/engine/spells/cmangos-special-cases-s22.ts +24 -0
- package/src/engine/spells/cmangos-special-cases-s23.ts +52 -0
- package/src/engine/spells/cmangos-special-cases.ts +1570 -0
- package/src/engine/spells/conditions.ts +718 -0
- package/src/engine/spells/effects.ts +203 -0
- package/src/engine/spells/fixtures/oracle-effects-lock9a.json +1 -0
- package/src/engine/spells/immunity.ts +942 -0
- package/src/engine/spells/intentEffects.ts +351 -0
- package/src/engine/spells/interpreter/GAPS.md +21 -0
- package/src/engine/spells/interpreter/amount.ts +109 -0
- package/src/engine/spells/interpreter/class-scripts-kit.ts +478 -0
- package/src/engine/spells/interpreter/diff.ts +246 -0
- package/src/engine/spells/interpreter/duration.ts +90 -0
- package/src/engine/spells/interpreter/form-attrs.json +1 -0
- package/src/engine/spells/interpreter/form-attrs.ts +95 -0
- package/src/engine/spells/interpreter/handlers/aura-remove.ts +113 -0
- package/src/engine/spells/interpreter/handlers/auras-control.ts +1547 -0
- package/src/engine/spells/interpreter/handlers/auras-core.ts +1583 -0
- package/src/engine/spells/interpreter/handlers/auras-misc.ts +1774 -0
- package/src/engine/spells/interpreter/handlers/effect-disenchant.ts +17 -0
- package/src/engine/spells/interpreter/handlers/effect-skinning.ts +20 -0
- package/src/engine/spells/interpreter/handlers/effects-action-utility.ts +1455 -0
- package/src/engine/spells/interpreter/handlers/effects-core.ts +432 -0
- package/src/engine/spells/interpreter/handlers/effects-remainder.ts +105 -0
- package/src/engine/spells/interpreter/handlers/effects-summon-item.ts +687 -0
- package/src/engine/spells/interpreter/handlers/mod-increase-energy-percent.ts +36 -0
- package/src/engine/spells/interpreter/handlers/mod-increase-energy.ts +36 -0
- package/src/engine/spells/interpreter/handlers/periodic-trigger-zero.ts +327 -0
- package/src/engine/spells/interpreter/handlers/procs.ts +131 -0
- package/src/engine/spells/interpreter/handlers/registry.ts +975 -0
- package/src/engine/spells/interpreter/handlers/shared.ts +667 -0
- package/src/engine/spells/interpreter/handlers.ts +9 -0
- package/src/engine/spells/interpreter/hunter-kit.ts +202 -0
- package/src/engine/spells/interpreter/index.ts +525 -0
- package/src/engine/spells/interpreter/item-triggers.ts +1121 -0
- package/src/engine/spells/interpreter/lift-consume-energy.ts +37 -0
- package/src/engine/spells/interpreter/mage-portals.ts +37 -0
- package/src/engine/spells/interpreter/materialize-charm.ts +88 -0
- package/src/engine/spells/interpreter/materialize-dispel-mechanic.ts +25 -0
- package/src/engine/spells/interpreter/materialize-rating-buffs.ts +81 -0
- package/src/engine/spells/interpreter/materialize-speed.ts +109 -0
- package/src/engine/spells/interpreter/materialize-spell-magnet.ts +22 -0
- package/src/engine/spells/interpreter/opcodes.ts +789 -0
- package/src/engine/spells/interpreter/paladin-kit.ts +95 -0
- package/src/engine/spells/interpreter/paladin-seals.ts +499 -0
- package/src/engine/spells/interpreter/priest-warlock-kit.ts +135 -0
- package/src/engine/spells/interpreter/proc.ts +443 -0
- package/src/engine/spells/interpreter/registry/helpers.ts +16 -0
- package/src/engine/spells/interpreter/registry/index.ts +216 -0
- package/src/engine/spells/interpreter/registry/packs/class-abilities.ts +304 -0
- package/src/engine/spells/interpreter/registry/packs/dire-maul.ts +44 -0
- package/src/engine/spells/interpreter/registry/packs/dummy-script-tail.ts +1065 -0
- package/src/engine/spells/interpreter/registry/packs/ex-wave-m.ts +70 -0
- package/src/engine/spells/interpreter/registry/packs/life-tap.ts +107 -0
- package/src/engine/spells/interpreter/registry/packs/paladin.ts +246 -0
- package/src/engine/spells/interpreter/registry/packs/raid-script-summons.ts +26 -0
- package/src/engine/spells/interpreter/registry/packs/raid-threat-wipe.ts +22 -0
- package/src/engine/spells/interpreter/registry/packs/shaman.ts +214 -0
- package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-a.ts +269 -0
- package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-b.ts +370 -0
- package/src/engine/spells/interpreter/registry/packs/si4-dummy-generic-c.ts +172 -0
- package/src/engine/spells/interpreter/registry/packs/si4-dummy-hunter.ts +60 -0
- package/src/engine/spells/interpreter/registry/packs/si4-dummy-warrior.ts +31 -0
- package/src/engine/spells/interpreter/registry/packs/si4-script-generic-a.ts +114 -0
- package/src/engine/spells/interpreter/registry/packs/si4-script-generic-b.ts +249 -0
- package/src/engine/spells/interpreter/registry/packs/si4-script-generic-c.ts +233 -0
- package/src/engine/spells/interpreter/registry/types.ts +48 -0
- package/src/engine/spells/interpreter/talent-scripted.ts +329 -0
- package/src/engine/spells/interpreter/targeting.ts +90 -0
- package/src/engine/spells/interpreter/types-intent.ts +1501 -0
- package/src/engine/spells/interpreter/types.ts +419 -0
- package/src/engine/spells/interpreter/warrior-druid-kit.ts +314 -0
- package/src/engine/spells/interpreter/weapon-imbue-kit.ts +384 -0
- package/src/engine/spells/interrupt.ts +217 -0
- package/src/engine/spells/meleeAttackReset.ts +60 -0
- package/src/engine/spells/oocTriggerSpell.ts +49 -0
- package/src/engine/spells/overrideClassScripts.ts +319 -0
- package/src/engine/spells/parryHaste.ts +20 -0
- package/src/engine/spells/procs.ts +300 -0
- package/src/engine/spells/recovery.ts +203 -0
- package/src/engine/spells/scriptTargetDest.ts +76 -0
- package/src/engine/spells/scriptTargets.ts +85 -0
- package/src/engine/spells/singleTargetAura.ts +82 -0
- package/src/engine/spells/specialCasePayloads.ts +57 -0
- package/src/engine/spells/spellAttributes.ts +249 -0
- package/src/engine/spells/spellBonus.ts +143 -0
- package/src/engine/spells/spellModIntents.ts +419 -0
- package/src/engine/spells/spellMods.ts +283 -0
- package/src/engine/spells/spellRadius.ts +15 -0
- package/src/engine/spells/trapObjects.ts +26 -0
- package/src/json.d.ts +7 -0
- package/src/persistence/memoryRepository.ts +23 -0
- package/src/persistence/saveBackups.ts +162 -0
- package/src/persistence/saveFile.ts +68 -0
- package/src/persistence/saveRepository.ts +11 -0
- package/src/persistence/saveShape.ts +668 -0
- package/src/progression/leveling.ts +89 -0
- package/src/progression/rest.ts +1434 -0
- package/src/progression/training.ts +226 -0
- package/src/progression/xpGain.ts +369 -0
- package/src/quests/quests.ts +1580 -0
- package/src/world/aoePull.ts +198 -0
- package/src/world/areaTableDbc.ts +39 -0
- package/src/world/areaTableMapIdPairs.ts +141 -0
- package/src/world/bakeSlug.ts +43 -0
- package/src/world/continuousDungeon.ts +1250 -0
- package/src/world/dungeonBakeProjection.ts +190 -0
- package/src/world/dungeonMapDensity.ts +342 -0
- package/src/world/dungeonMapProjection.ts +135 -0
- package/src/world/dungeonNav.ts +904 -0
- package/src/world/dungeonNpcSim.ts +147 -0
- package/src/world/dungeonObjectives.ts +234 -0
- package/src/world/dungeonPreset.ts +35 -0
- package/src/world/dungeonRoute.ts +311 -0
- package/src/world/dungeonRouteGeometry.ts +732 -0
- package/src/world/dungeonRouteOrder.ts +1037 -0
- package/src/world/dungeonWingRooms.ts +426 -0
- package/src/world/escort.ts +296 -0
- package/src/world/goPoolRoll.ts +75 -0
- package/src/world/instanceObjects.ts +785 -0
- package/src/world/instances.ts +1572 -0
- package/src/world/meetingStones.ts +56 -0
- package/src/world/navmeshFloors.ts +145 -0
- package/src/world/nearGrid.ts +167 -0
- package/src/world/packBudget.ts +613 -0
- package/src/world/rareRoll.ts +335 -0
- package/src/world/routeAuthoring.ts +132 -0
- package/src/world/routeEdit.ts +209 -0
- package/src/world/world.ts +812 -0
- 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
|
+
}
|