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,904 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route pathfinding over the traced floorplan.
|
|
3
|
+
*
|
|
4
|
+
* W6 put every pin on its real world origin, which was the fix — but it left the gold
|
|
5
|
+
* route polyline drawn corner-to-corner between consecutive encounters. With real
|
|
6
|
+
* geometry, consecutive pulls are frequently across the dungeon from each other, so the
|
|
7
|
+
* "route" became long diagonals through solid rock. It looked worse than the pre-W6
|
|
8
|
+
* version precisely because the pins had become correct: the old polyline was tidy
|
|
9
|
+
* because `assignRoutePathT` smeared 1,845 packs along a hand-drawn path.
|
|
10
|
+
*
|
|
11
|
+
* This module walks the route through the floor instead. It rasterises the SAME polygons
|
|
12
|
+
* the map draws (`public/maps/floorplan/<mapId>-<slug>.json`, 0..1000 space) into a
|
|
13
|
+
* per-band occupancy grid and runs A* over it, so the line provably follows the floor the
|
|
14
|
+
* player is looking at — no second source, no new bake, nothing to keep in sync.
|
|
15
|
+
*
|
|
16
|
+
* BAND AWARENESS IS NOT OPTIONAL HERE. UBRS and Scholomance are ~37 %/39 % plan-view
|
|
17
|
+
* stacked (runsheet D1), so a plan-view-only search happily routes along an upper storey's
|
|
18
|
+
* corridor to reach a basement pull — which draws a line that *looks* right over drawn
|
|
19
|
+
* floor while describing a walk nobody can take. Nodes are (band, x, y); a band change is
|
|
20
|
+
* only legal where both bands are walkable at the same cell (a ramp or stairwell overlaps
|
|
21
|
+
* in plan) and costs extra.
|
|
22
|
+
*
|
|
23
|
+
* Holes: each traced loop is filled independently and OR'd, so a pillar's inner ring
|
|
24
|
+
* becomes walkable. That is deliberate — it is exactly what `scoreOnFloor` in
|
|
25
|
+
* bake-dungeon-floorplans.mjs does, so the nav mask and O1's mask agree.
|
|
26
|
+
*
|
|
27
|
+
* Pure module — no DOM, no I/O. The floorplan document is passed in (the UI owns the
|
|
28
|
+
* fetch), and the structural types are declared locally so `src/world/` keeps no edge
|
|
29
|
+
* into `src/ui/`.
|
|
30
|
+
*
|
|
31
|
+
* @see docs/archive/DUNGEON-MAP-RUNSHEET.md §3, decision D1
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type { MapPct } from './dungeonMapProjection.ts';
|
|
35
|
+
|
|
36
|
+
// Types (structural — traced floor loops / NavFloorDoc shape, no UI import)
|
|
37
|
+
|
|
38
|
+
export type NavFloorPath = {
|
|
39
|
+
/** Mean world-z of the loop. */
|
|
40
|
+
z?: number;
|
|
41
|
+
/** Band index from the bake. */
|
|
42
|
+
b?: number;
|
|
43
|
+
/** Polygon points in 0..1000 space. */
|
|
44
|
+
pts?: number[][];
|
|
45
|
+
/** SVG path `d` in 0..1000 space (parsed when `pts` is absent). */
|
|
46
|
+
d?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type NavFloorDoc = {
|
|
50
|
+
paths: NavFloorPath[];
|
|
51
|
+
nBands?: number;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type NavGrid = {
|
|
55
|
+
res: number;
|
|
56
|
+
nBands: number;
|
|
57
|
+
/** `band * res * res + y * res + x` → 1 when that band has floor there. */
|
|
58
|
+
cells: Uint8Array;
|
|
59
|
+
/** Union across bands (band-agnostic fallback + line-of-sight on flat maps). */
|
|
60
|
+
any: Uint8Array;
|
|
61
|
+
/** Mean world-z per band; NaN when the band traced nothing. */
|
|
62
|
+
bandZ: number[];
|
|
63
|
+
/**
|
|
64
|
+
* 1 where a walkable cell has a non-walkable 8-neighbour on its own band — a wall-adjacent
|
|
65
|
+
* cell. Adding a small cost for these makes the search prefer the MIDDLE of a corridor over
|
|
66
|
+
* scraping along its edge. It is not cosmetic: the drawn line's corners sit at cell
|
|
67
|
+
* positions, so an edge-hugging path puts corners on the floor boundary, where any
|
|
68
|
+
* independent mask disagrees about whether they are inside.
|
|
69
|
+
*/
|
|
70
|
+
nearWall: Uint8Array;
|
|
71
|
+
/**
|
|
72
|
+
* A finer mask of the same polygons, used ONLY for line-of-sight when smoothing.
|
|
73
|
+
*
|
|
74
|
+
* The search runs coarse on purpose (see NAV_RES: finer pinches corridors and strands
|
|
75
|
+
* legs), but a coarse mask is a GENEROUS mask, so a coarse-legal hop can clip a wall the
|
|
76
|
+
* drawn line then visibly crosses — and it can make A* detour around a corridor that is
|
|
77
|
+
* actually open. Validating the final hops against a finer mask fixes both, without
|
|
78
|
+
* giving up the coarse search's connectivity.
|
|
79
|
+
*/
|
|
80
|
+
fine: { res: number; nBands: number; cells: Uint8Array };
|
|
81
|
+
/** Reusable A* scratch (allocated once per grid, stamped per search). */
|
|
82
|
+
scratch: {
|
|
83
|
+
g: Float32Array;
|
|
84
|
+
parent: Int32Array;
|
|
85
|
+
gen: Int32Array;
|
|
86
|
+
seq: number;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/** One drawn segment of the route. `routed:false` means A* found no floor path. */
|
|
91
|
+
export type RouteLeg = {
|
|
92
|
+
points: MapPct[];
|
|
93
|
+
routed: boolean;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type NavWaypoint = {
|
|
97
|
+
pct: MapPct;
|
|
98
|
+
/** World z when the encounter carries one — picks the storey. */
|
|
99
|
+
z?: number;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Nav resolution: 1000/160 = 6.25 units per cell.
|
|
104
|
+
*
|
|
105
|
+
* MEASURED, not picked. `docs/dmapfid/route-on-floor.mjs` sweeps it, scoring against an
|
|
106
|
+
* independent mask at O1's res=256 (scoring on the nav grid itself rewards coarseness —
|
|
107
|
+
* a bigger cell touching any floor reads walkable, and the straight-line null rises with
|
|
108
|
+
* it, which is how a "better" number gets manufactured):
|
|
109
|
+
*
|
|
110
|
+
* res onFloor routed routedOnFloor (null = 0.7927 at every res)
|
|
111
|
+
* 128 0.9374 94.1 % 0.9681
|
|
112
|
+
* 160 0.9387 93.2 % 0.9759 ← here
|
|
113
|
+
* 192 0.9331 91.7 % 0.9830
|
|
114
|
+
* 256 0.9223 87.3 % 0.9912
|
|
115
|
+
*
|
|
116
|
+
* (Swept before NEAR_WALL_COST landed; that lifted the shipped row to 0.9446 / 93.4 % /
|
|
117
|
+
* 0.9850 without changing which resolution wins. Re-sweep with `--res N` if this changes.)
|
|
118
|
+
*
|
|
119
|
+
* Finer is worse on coverage, not better: the traced loops are already RDP-simplified at eps
|
|
120
|
+
* 1.2 px of the bake's 384 raster, so a finer nav grid pinches thin corridors into
|
|
121
|
+
* disconnected components and the leg falls back to a straight line. It buys a little
|
|
122
|
+
* `routedOnFloor` (the legs it still routes hug the floor tighter) at the cost of routing
|
|
123
|
+
* fewer of them, and a leg we decline to route is a leg the player gets no line for. 160
|
|
124
|
+
* is where the combined `onFloor` peaks.
|
|
125
|
+
*/
|
|
126
|
+
export const NAV_RES = 160;
|
|
127
|
+
|
|
128
|
+
// Cost of stepping between bands at an overlapping cell. Higher than a diagonal so the search prefers
|
|
129
|
+
// staying on one storey when a same-storey walk exists.
|
|
130
|
+
const BAND_STEP_COST = 6;
|
|
131
|
+
|
|
132
|
+
// Extra cost for stepping onto a wall-adjacent cell (see NavGrid.nearWall). Small enough that it never
|
|
133
|
+
// changes which corridor is chosen — only where inside it the line runs.
|
|
134
|
+
const NEAR_WALL_COST = 0.4;
|
|
135
|
+
|
|
136
|
+
/** Search abort. A 192² × 8 grid is 294,912 nodes; a real leg explores a few thousand. */
|
|
137
|
+
const MAX_EXPANDED = 120_000;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* How far (in cells) an endpoint may be snapped onto floor before the leg is declared
|
|
141
|
+
* UNROUTED. Kept tight on purpose, and it is a correctness knob rather than a cosmetic one:
|
|
142
|
+
* the drawn leg starts and ends at the real pin, so a generous snap produces a leg that is
|
|
143
|
+
* marked `routed` while its first and last segment run from an off-floor pin to wherever the
|
|
144
|
+
* search found floor. At radius 6 that stub dragged Zul'Farrak's routed legs to 0.71 on-floor
|
|
145
|
+
* while still calling them paths. See the sweep in docs/dmapfid/route-on-floor.json.
|
|
146
|
+
*/
|
|
147
|
+
const SNAP_RADIUS = 2;
|
|
148
|
+
|
|
149
|
+
const SQRT2 = Math.SQRT2;
|
|
150
|
+
|
|
151
|
+
// Rasterisation
|
|
152
|
+
|
|
153
|
+
function parsePathD(d: string): number[][] {
|
|
154
|
+
const nums = d
|
|
155
|
+
.replace(/[MLZmlz]/g, ' ')
|
|
156
|
+
.trim()
|
|
157
|
+
.split(/[\s,]+/)
|
|
158
|
+
.map(Number)
|
|
159
|
+
.filter(Number.isFinite);
|
|
160
|
+
const pts: number[][] = [];
|
|
161
|
+
for (let i = 0; i + 1 < nums.length; i += 2) pts.push([nums[i]!, nums[i + 1]!]);
|
|
162
|
+
return pts;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function polyOf(p: NavFloorPath): number[][] | null {
|
|
166
|
+
if (p.pts && p.pts.length >= 3) return p.pts;
|
|
167
|
+
if (p.d) {
|
|
168
|
+
const parsed = parsePathD(p.d);
|
|
169
|
+
return parsed.length >= 3 ? parsed : null;
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Even-odd scanline fill of one 0..1000 polygon into a res×res grid. Same algorithm as the bake's
|
|
175
|
+
// `scoreOnFloor.fillPoly`, so mask and oracle agree.
|
|
176
|
+
function fillPoly(grid: Uint8Array, res: number, poly: number[][]): void {
|
|
177
|
+
const n = poly.length;
|
|
178
|
+
if (n < 3) return;
|
|
179
|
+
const sx: number[] = new Array(n);
|
|
180
|
+
const sy: number[] = new Array(n);
|
|
181
|
+
let minY = res;
|
|
182
|
+
let maxY = 0;
|
|
183
|
+
for (let i = 0; i < n; i++) {
|
|
184
|
+
const x = idxOfUnit(poly[i]![0]!, res);
|
|
185
|
+
const y = idxOfUnit(poly[i]![1]!, res);
|
|
186
|
+
sx[i] = x;
|
|
187
|
+
sy[i] = y;
|
|
188
|
+
if (y < minY) minY = y;
|
|
189
|
+
if (y > maxY) maxY = y;
|
|
190
|
+
}
|
|
191
|
+
for (let y = minY; y <= maxY; y++) {
|
|
192
|
+
const xs: number[] = [];
|
|
193
|
+
for (let i = 0; i < n; i++) {
|
|
194
|
+
const j = (i + 1) % n;
|
|
195
|
+
const y1 = sy[i]!;
|
|
196
|
+
const y2 = sy[j]!;
|
|
197
|
+
if (y1 === y2) continue;
|
|
198
|
+
if ((y < y1 && y < y2) || (y >= y1 && y >= y2)) continue;
|
|
199
|
+
const t = (y - y1) / (y2 - y1);
|
|
200
|
+
xs.push(sx[i]! + t * (sx[j]! - sx[i]!));
|
|
201
|
+
}
|
|
202
|
+
xs.sort((a, b) => a - b);
|
|
203
|
+
const row = y * res;
|
|
204
|
+
for (let k = 0; k + 1 < xs.length; k += 2) {
|
|
205
|
+
const a = Math.max(0, Math.ceil(xs[k]!));
|
|
206
|
+
const b = Math.min(res - 1, Math.floor(xs[k + 1]!));
|
|
207
|
+
for (let x = a; x <= b; x++) grid[row + x] = 1;
|
|
208
|
+
}
|
|
209
|
+
// A polygon thinner than one scanline contributes no span pair above; stamp its
|
|
210
|
+
// vertices so a 1-cell corridor never vanishes from the nav mask entirely.
|
|
211
|
+
if (xs.length < 2) {
|
|
212
|
+
for (let i = 0; i < n; i++) if (sy[i] === y) grid[row + sx[i]!] = 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Per-band occupancy at one resolution. */
|
|
218
|
+
function rasterise(
|
|
219
|
+
paths: readonly NavFloorPath[],
|
|
220
|
+
nBands: number,
|
|
221
|
+
res: number,
|
|
222
|
+
): Uint8Array {
|
|
223
|
+
const plane = res * res;
|
|
224
|
+
const cells = new Uint8Array(plane * nBands);
|
|
225
|
+
for (const p of paths) {
|
|
226
|
+
const poly = polyOf(p);
|
|
227
|
+
if (!poly) continue;
|
|
228
|
+
const b = Number.isFinite(p.b) ? Math.max(0, Math.min(nBands - 1, p.b as number)) : 0;
|
|
229
|
+
fillPoly(cells.subarray(b * plane, (b + 1) * plane), res, poly);
|
|
230
|
+
}
|
|
231
|
+
return cells;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Line-of-sight resolution for hop validation — 2× the search grid. */
|
|
235
|
+
const FINE_RES_FACTOR = 2;
|
|
236
|
+
|
|
237
|
+
/** Rasterise a floorplan document into a per-band occupancy grid. */
|
|
238
|
+
export function buildNavGrid(doc: NavFloorDoc, res: number = NAV_RES): NavGrid {
|
|
239
|
+
const paths = doc.paths ?? [];
|
|
240
|
+
let maxBand = 0;
|
|
241
|
+
for (const p of paths) {
|
|
242
|
+
const b = Number.isFinite(p.b) ? (p.b as number) : 0;
|
|
243
|
+
if (b > maxBand) maxBand = b;
|
|
244
|
+
}
|
|
245
|
+
const nBands = Math.max(1, Math.min(64, maxBand + 1));
|
|
246
|
+
const plane = res * res;
|
|
247
|
+
const cells = rasterise(paths, nBands, res);
|
|
248
|
+
const any = new Uint8Array(plane);
|
|
249
|
+
const zSum = new Float64Array(nBands);
|
|
250
|
+
const zCount = new Int32Array(nBands);
|
|
251
|
+
|
|
252
|
+
for (const p of paths) {
|
|
253
|
+
const b = Number.isFinite(p.b) ? Math.max(0, Math.min(nBands - 1, p.b as number)) : 0;
|
|
254
|
+
if (Number.isFinite(p.z)) {
|
|
255
|
+
zSum[b]! += p.z as number;
|
|
256
|
+
zCount[b]! += 1;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
for (let b = 0; b < nBands; b++) {
|
|
260
|
+
const off = b * plane;
|
|
261
|
+
for (let i = 0; i < plane; i++) if (cells[off + i]) any[i] = 1;
|
|
262
|
+
}
|
|
263
|
+
const bandZ: number[] = [];
|
|
264
|
+
for (let b = 0; b < nBands; b++) {
|
|
265
|
+
bandZ.push(zCount[b] ? zSum[b]! / zCount[b]! : Number.NaN);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Wall adjacency, per band.
|
|
269
|
+
const nearWall = new Uint8Array(cells.length);
|
|
270
|
+
for (let b = 0; b < nBands; b++) {
|
|
271
|
+
const off = b * plane;
|
|
272
|
+
for (let y = 0; y < res; y++) {
|
|
273
|
+
for (let x = 0; x < res; x++) {
|
|
274
|
+
const i = off + y * res + x;
|
|
275
|
+
if (!cells[i]) continue;
|
|
276
|
+
let edge = 0;
|
|
277
|
+
for (let dy = -1; dy <= 1 && !edge; dy++) {
|
|
278
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
279
|
+
if (!dx && !dy) continue;
|
|
280
|
+
const nx = x + dx;
|
|
281
|
+
const ny = y + dy;
|
|
282
|
+
if (nx < 0 || ny < 0 || nx >= res || ny >= res || !cells[off + ny * res + nx]) {
|
|
283
|
+
edge = 1;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
nearWall[i] = edge;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const fineRes = res * FINE_RES_FACTOR;
|
|
294
|
+
return {
|
|
295
|
+
res,
|
|
296
|
+
nBands,
|
|
297
|
+
cells,
|
|
298
|
+
any,
|
|
299
|
+
bandZ,
|
|
300
|
+
nearWall,
|
|
301
|
+
fine: { res: fineRes, nBands, cells: rasterise(paths, nBands, fineRes) },
|
|
302
|
+
scratch: {
|
|
303
|
+
g: new Float32Array(plane * nBands),
|
|
304
|
+
parent: new Int32Array(plane * nBands),
|
|
305
|
+
gen: new Int32Array(plane * nBands),
|
|
306
|
+
seq: 0,
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Cell helpers
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* ONE lattice convention, and it is the bake's.
|
|
315
|
+
*
|
|
316
|
+
* `traceGrid` in bake-dungeon-floorplans.mjs emits 0..1000 from a res×res raster by dividing
|
|
317
|
+
* by `res - 1`, and `scoreOnFloor` inverts it with `round(u / 1000 * (res - 1))`. So a nav
|
|
318
|
+
* cell is a LATTICE POINT, not a box: index i sits at 1000·i/(res−1). Mixing that with a
|
|
319
|
+
* cell-box mapping (`floor(u / 1000 * res)`) shifts the mask against the points by up to a
|
|
320
|
+
* cell, which is how the synthetic corner-seam case leaked a diagonal between two rooms that
|
|
321
|
+
* only touch at a corner.
|
|
322
|
+
*/
|
|
323
|
+
function idxOfUnit(u: number, res: number): number {
|
|
324
|
+
return Math.max(0, Math.min(res - 1, Math.round((u / 1000) * (res - 1))));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Map% → nav lattice cell (clamped). */
|
|
328
|
+
export function cellOfPct(grid: NavGrid, p: MapPct): { x: number; y: number } {
|
|
329
|
+
return {
|
|
330
|
+
x: idxOfUnit(p.left * 10, grid.res),
|
|
331
|
+
y: idxOfUnit(p.top * 10, grid.res),
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** Nav lattice cell → map%. */
|
|
336
|
+
function pctOfCell(grid: NavGrid, x: number, y: number): MapPct {
|
|
337
|
+
const d = grid.res - 1 || 1;
|
|
338
|
+
return {
|
|
339
|
+
left: (x / d) * 100,
|
|
340
|
+
top: (y / d) * 100,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function walkable(grid: NavGrid, band: number, x: number, y: number): boolean {
|
|
345
|
+
if (x < 0 || y < 0 || x >= grid.res || y >= grid.res) return false;
|
|
346
|
+
return grid.cells[band * grid.res * grid.res + y * grid.res + x] === 1;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Band whose mean z is nearest the waypoint's world z. Falls back to the band that is actually walkable
|
|
350
|
+
// near the point, then to band 0.
|
|
351
|
+
function preferredBand(grid: NavGrid, wp: NavWaypoint): number {
|
|
352
|
+
if (grid.nBands === 1) return 0;
|
|
353
|
+
if (Number.isFinite(wp.z)) {
|
|
354
|
+
let best = -1;
|
|
355
|
+
let bestD = Infinity;
|
|
356
|
+
for (let b = 0; b < grid.nBands; b++) {
|
|
357
|
+
const bz = grid.bandZ[b]!;
|
|
358
|
+
if (!Number.isFinite(bz)) continue;
|
|
359
|
+
const d = Math.abs(bz - (wp.z as number));
|
|
360
|
+
if (d < bestD) {
|
|
361
|
+
bestD = d;
|
|
362
|
+
best = b;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (best >= 0) return best;
|
|
366
|
+
}
|
|
367
|
+
return 0;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Nearest walkable cell to `p`, searched outward by radius. Returns the preferred band
|
|
372
|
+
* when it has floor within `SNAP_RADIUS`, otherwise the closest cell on ANY band — a
|
|
373
|
+
* pack standing 2 cells off its own storey's traced edge (Deadmines' 0.897 coverage is
|
|
374
|
+
* exactly this) still gets routed rather than silently dropped.
|
|
375
|
+
*/
|
|
376
|
+
export function snapToFloor(
|
|
377
|
+
grid: NavGrid,
|
|
378
|
+
wp: NavWaypoint,
|
|
379
|
+
radius: number = SNAP_RADIUS,
|
|
380
|
+
): { band: number; x: number; y: number } | null {
|
|
381
|
+
const c = cellOfPct(grid, wp.pct);
|
|
382
|
+
const pref = preferredBand(grid, wp);
|
|
383
|
+
const bandOrder: number[] = [pref];
|
|
384
|
+
for (let b = 0; b < grid.nBands; b++) if (b !== pref) bandOrder.push(b);
|
|
385
|
+
|
|
386
|
+
for (let r = 0; r <= radius; r++) {
|
|
387
|
+
for (const band of bandOrder) {
|
|
388
|
+
// Ring scan at Chebyshev radius r.
|
|
389
|
+
for (let dy = -r; dy <= r; dy++) {
|
|
390
|
+
for (let dx = -r; dx <= r; dx++) {
|
|
391
|
+
if (Math.max(Math.abs(dx), Math.abs(dy)) !== r) continue;
|
|
392
|
+
if (walkable(grid, band, c.x + dx, c.y + dy)) {
|
|
393
|
+
return { band, x: c.x + dx, y: c.y + dy };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// A*
|
|
403
|
+
|
|
404
|
+
/** Binary min-heap over node ids keyed by f-score. */
|
|
405
|
+
class Heap {
|
|
406
|
+
private ids: number[] = [];
|
|
407
|
+
private fs: number[] = [];
|
|
408
|
+
|
|
409
|
+
get size(): number {
|
|
410
|
+
return this.ids.length;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
push(id: number, f: number): void {
|
|
414
|
+
this.ids.push(id);
|
|
415
|
+
this.fs.push(f);
|
|
416
|
+
let i = this.ids.length - 1;
|
|
417
|
+
while (i > 0) {
|
|
418
|
+
const p = (i - 1) >> 1;
|
|
419
|
+
if (this.fs[p]! <= this.fs[i]!) break;
|
|
420
|
+
this.swap(i, p);
|
|
421
|
+
i = p;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
pop(): number {
|
|
426
|
+
const top = this.ids[0]!;
|
|
427
|
+
const lastId = this.ids.pop()!;
|
|
428
|
+
const lastF = this.fs.pop()!;
|
|
429
|
+
if (this.ids.length) {
|
|
430
|
+
this.ids[0] = lastId;
|
|
431
|
+
this.fs[0] = lastF;
|
|
432
|
+
let i = 0;
|
|
433
|
+
for (;;) {
|
|
434
|
+
const l = i * 2 + 1;
|
|
435
|
+
const r = l + 1;
|
|
436
|
+
let m = i;
|
|
437
|
+
if (l < this.ids.length && this.fs[l]! < this.fs[m]!) m = l;
|
|
438
|
+
if (r < this.ids.length && this.fs[r]! < this.fs[m]!) m = r;
|
|
439
|
+
if (m === i) break;
|
|
440
|
+
this.swap(i, m);
|
|
441
|
+
i = m;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return top;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
private swap(a: number, b: number): void {
|
|
448
|
+
const ti = this.ids[a]!;
|
|
449
|
+
this.ids[a] = this.ids[b]!;
|
|
450
|
+
this.ids[b] = ti;
|
|
451
|
+
const tf = this.fs[a]!;
|
|
452
|
+
this.fs[a] = this.fs[b]!;
|
|
453
|
+
this.fs[b] = tf;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const DIRS: readonly (readonly [number, number, number])[] = [
|
|
458
|
+
[1, 0, 1],
|
|
459
|
+
[-1, 0, 1],
|
|
460
|
+
[0, 1, 1],
|
|
461
|
+
[0, -1, 1],
|
|
462
|
+
[1, 1, SQRT2],
|
|
463
|
+
[1, -1, SQRT2],
|
|
464
|
+
[-1, 1, SQRT2],
|
|
465
|
+
[-1, -1, SQRT2],
|
|
466
|
+
];
|
|
467
|
+
|
|
468
|
+
function octile(ax: number, ay: number, bx: number, by: number): number {
|
|
469
|
+
const dx = Math.abs(ax - bx);
|
|
470
|
+
const dy = Math.abs(ay - by);
|
|
471
|
+
return dx + dy + (SQRT2 - 2) * Math.min(dx, dy);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export type NavCell = { band: number; x: number; y: number };
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Single-source Dijkstra over the nav grid. Returns g-score (path cost) for every
|
|
478
|
+
* reachable walkable cell from `from`, or null when `from` is not walkable.
|
|
479
|
+
*
|
|
480
|
+
* Used by geometric route ordering to rank many candidate packs without running A*
|
|
481
|
+
* once per candidate (n×A* is too heavy at enter). Stops early once every `stopAt`
|
|
482
|
+
* cell id has been settled, when provided.
|
|
483
|
+
*/
|
|
484
|
+
export function dijkstraCosts(
|
|
485
|
+
grid: NavGrid,
|
|
486
|
+
from: NavCell,
|
|
487
|
+
stopAt?: ReadonlySet<number>,
|
|
488
|
+
): Float32Array | null {
|
|
489
|
+
const { res, nBands, cells, scratch, nearWall } = grid;
|
|
490
|
+
const plane = res * res;
|
|
491
|
+
const idOf = (b: number, x: number, y: number): number => b * plane + y * res + x;
|
|
492
|
+
const startId = idOf(from.band, from.x, from.y);
|
|
493
|
+
if (!cells[startId]) return null;
|
|
494
|
+
|
|
495
|
+
const gen = ++scratch.seq;
|
|
496
|
+
const { g, parent, gen: seen } = scratch;
|
|
497
|
+
// parent[] is reused as a "settled this generation" stamp (negated gen) so a
|
|
498
|
+
// lazy-heap re-pop of a stale entry does not re-expand or early-exit stopAt.
|
|
499
|
+
const open = new Heap();
|
|
500
|
+
g[startId] = 0;
|
|
501
|
+
parent[startId] = -1;
|
|
502
|
+
seen[startId] = gen;
|
|
503
|
+
open.push(startId, 0);
|
|
504
|
+
|
|
505
|
+
const pending = stopAt ? new Set(stopAt) : null;
|
|
506
|
+
if (pending) pending.delete(startId);
|
|
507
|
+
|
|
508
|
+
let expanded = 0;
|
|
509
|
+
while (open.size) {
|
|
510
|
+
const cur = open.pop();
|
|
511
|
+
// Already settled with best g — skip stale heap entries.
|
|
512
|
+
if (seen[cur] === gen && parent[cur] === -2) continue;
|
|
513
|
+
if (seen[cur] === gen) parent[cur] = -2; // mark settled
|
|
514
|
+
if (pending) {
|
|
515
|
+
pending.delete(cur);
|
|
516
|
+
if (pending.size === 0) break;
|
|
517
|
+
}
|
|
518
|
+
if (++expanded > MAX_EXPANDED) break;
|
|
519
|
+
const b = Math.floor(cur / plane);
|
|
520
|
+
const rem = cur - b * plane;
|
|
521
|
+
const y = Math.floor(rem / res);
|
|
522
|
+
const x = rem - y * res;
|
|
523
|
+
const gc = g[cur]!;
|
|
524
|
+
|
|
525
|
+
for (const [dx, dy, w] of DIRS) {
|
|
526
|
+
const nx = x + dx;
|
|
527
|
+
const ny = y + dy;
|
|
528
|
+
if (nx < 0 || ny < 0 || nx >= res || ny >= res) continue;
|
|
529
|
+
const nid = idOf(b, nx, ny);
|
|
530
|
+
if (!cells[nid]) continue;
|
|
531
|
+
if (dx !== 0 && dy !== 0) {
|
|
532
|
+
if (!cells[idOf(b, x + dx, y)] || !cells[idOf(b, x, y + dy)]) continue;
|
|
533
|
+
}
|
|
534
|
+
const ng = gc + w + (nearWall[nid] ? NEAR_WALL_COST : 0);
|
|
535
|
+
if (seen[nid] === gen && ng >= g[nid]!) continue;
|
|
536
|
+
// Do not reopen a settled node (uniform non-negative weights).
|
|
537
|
+
if (seen[nid] === gen && parent[nid] === -2) continue;
|
|
538
|
+
seen[nid] = gen;
|
|
539
|
+
g[nid] = ng;
|
|
540
|
+
parent[nid] = cur;
|
|
541
|
+
open.push(nid, ng);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (nBands > 1) {
|
|
545
|
+
for (let ob = 0; ob < nBands; ob++) {
|
|
546
|
+
if (ob === b) continue;
|
|
547
|
+
const nid = idOf(ob, x, y);
|
|
548
|
+
if (!cells[nid]) continue;
|
|
549
|
+
const ng = gc + BAND_STEP_COST;
|
|
550
|
+
if (seen[nid] === gen && ng >= g[nid]!) continue;
|
|
551
|
+
if (seen[nid] === gen && parent[nid] === -2) continue;
|
|
552
|
+
seen[nid] = gen;
|
|
553
|
+
g[nid] = ng;
|
|
554
|
+
parent[nid] = cur;
|
|
555
|
+
open.push(nid, ng);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Materialise costs: only cells visited this generation are finite.
|
|
561
|
+
const out = new Float32Array(plane * nBands);
|
|
562
|
+
out.fill(Number.POSITIVE_INFINITY);
|
|
563
|
+
for (let i = 0; i < out.length; i++) {
|
|
564
|
+
if (seen[i] === gen) out[i] = g[i]!;
|
|
565
|
+
}
|
|
566
|
+
return out;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Nav-graph path cost between two waypoints (cell units), or null when either end cannot snap to floor or
|
|
570
|
+
// the components are disconnected.
|
|
571
|
+
export function navPathCost(
|
|
572
|
+
grid: NavGrid,
|
|
573
|
+
a: NavWaypoint,
|
|
574
|
+
b: NavWaypoint,
|
|
575
|
+
): number | null {
|
|
576
|
+
const sa = snapToFloor(grid, a);
|
|
577
|
+
const sb = snapToFloor(grid, b);
|
|
578
|
+
if (!sa || !sb) return null;
|
|
579
|
+
if (sa.band === sb.band && sa.x === sb.x && sa.y === sb.y) return 0;
|
|
580
|
+
const costs = dijkstraCosts(
|
|
581
|
+
grid,
|
|
582
|
+
sa,
|
|
583
|
+
new Set([sb.band * grid.res * grid.res + sb.y * grid.res + sb.x]),
|
|
584
|
+
);
|
|
585
|
+
if (!costs) return null;
|
|
586
|
+
const goalId = sb.band * grid.res * grid.res + sb.y * grid.res + sb.x;
|
|
587
|
+
const c = costs[goalId]!;
|
|
588
|
+
return Number.isFinite(c) ? c : null;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// A* from `from` to `to` over (band, x, y). Returns the cell chain inclusive of both endpoints, or null
|
|
592
|
+
// when the two cells are in disconnected floor components.
|
|
593
|
+
export function findCellPath(grid: NavGrid, from: NavCell, to: NavCell): NavCell[] | null {
|
|
594
|
+
const { res, nBands, cells, scratch } = grid;
|
|
595
|
+
const plane = res * res;
|
|
596
|
+
const idOf = (b: number, x: number, y: number): number => b * plane + y * res + x;
|
|
597
|
+
const startId = idOf(from.band, from.x, from.y);
|
|
598
|
+
const goalId = idOf(to.band, to.x, to.y);
|
|
599
|
+
if (!cells[startId] || !cells[goalId]) return null;
|
|
600
|
+
if (startId === goalId) return [{ ...from }];
|
|
601
|
+
|
|
602
|
+
const gen = ++scratch.seq;
|
|
603
|
+
const { g, parent, gen: seen } = scratch;
|
|
604
|
+
const { nearWall } = grid;
|
|
605
|
+
const open = new Heap();
|
|
606
|
+
g[startId] = 0;
|
|
607
|
+
parent[startId] = -1;
|
|
608
|
+
seen[startId] = gen;
|
|
609
|
+
open.push(startId, octile(from.x, from.y, to.x, to.y));
|
|
610
|
+
|
|
611
|
+
let expanded = 0;
|
|
612
|
+
while (open.size) {
|
|
613
|
+
const cur = open.pop();
|
|
614
|
+
if (cur === goalId) break;
|
|
615
|
+
if (++expanded > MAX_EXPANDED) return null;
|
|
616
|
+
const b = Math.floor(cur / plane);
|
|
617
|
+
const rem = cur - b * plane;
|
|
618
|
+
const y = Math.floor(rem / res);
|
|
619
|
+
const x = rem - y * res;
|
|
620
|
+
const gc = g[cur]!;
|
|
621
|
+
|
|
622
|
+
for (const [dx, dy, w] of DIRS) {
|
|
623
|
+
const nx = x + dx;
|
|
624
|
+
const ny = y + dy;
|
|
625
|
+
if (nx < 0 || ny < 0 || nx >= res || ny >= res) continue;
|
|
626
|
+
const nid = idOf(b, nx, ny);
|
|
627
|
+
if (!cells[nid]) continue;
|
|
628
|
+
// No corner-cutting: a diagonal needs both orthogonal neighbours open, else the
|
|
629
|
+
// line is drawn slipping through the seam between two rooms.
|
|
630
|
+
if (dx !== 0 && dy !== 0) {
|
|
631
|
+
if (!cells[idOf(b, x + dx, y)] || !cells[idOf(b, x, y + dy)]) continue;
|
|
632
|
+
}
|
|
633
|
+
const ng = gc + w + (nearWall[nid] ? NEAR_WALL_COST : 0);
|
|
634
|
+
if (seen[nid] === gen && ng >= g[nid]!) continue;
|
|
635
|
+
seen[nid] = gen;
|
|
636
|
+
g[nid] = ng;
|
|
637
|
+
parent[nid] = cur;
|
|
638
|
+
open.push(nid, ng + octile(nx, ny, to.x, to.y));
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Storey change: only where the other band has floor at this very cell.
|
|
642
|
+
if (nBands > 1) {
|
|
643
|
+
for (let ob = 0; ob < nBands; ob++) {
|
|
644
|
+
if (ob === b) continue;
|
|
645
|
+
const nid = idOf(ob, x, y);
|
|
646
|
+
if (!cells[nid]) continue;
|
|
647
|
+
const ng = gc + BAND_STEP_COST;
|
|
648
|
+
if (seen[nid] === gen && ng >= g[nid]!) continue;
|
|
649
|
+
seen[nid] = gen;
|
|
650
|
+
g[nid] = ng;
|
|
651
|
+
parent[nid] = cur;
|
|
652
|
+
open.push(nid, ng + octile(x, y, to.x, to.y));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (seen[goalId] !== gen) return null;
|
|
658
|
+
const out: NavCell[] = [];
|
|
659
|
+
let cur = goalId;
|
|
660
|
+
while (cur !== -1) {
|
|
661
|
+
const b = Math.floor(cur / plane);
|
|
662
|
+
const rem = cur - b * plane;
|
|
663
|
+
const y = Math.floor(rem / res);
|
|
664
|
+
out.push({ band: b, x: rem - y * res, y });
|
|
665
|
+
cur = parent[cur]!;
|
|
666
|
+
}
|
|
667
|
+
out.reverse();
|
|
668
|
+
return out;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Straight walk from `a` to `b` stays on `band`, checked on the SEARCH grid.
|
|
673
|
+
*
|
|
674
|
+
* Sampled at half-cell steps rather than Bresenham-stepped: the seam case (a diagonal
|
|
675
|
+
* slipping between two rooms that touch at one corner) is what a naive Bresenham misses,
|
|
676
|
+
* and it is the failure that draws a line through a wall.
|
|
677
|
+
*/
|
|
678
|
+
export function lineOfSight(grid: NavGrid, band: number, a: NavCell, b: NavCell): boolean {
|
|
679
|
+
const dx = b.x - a.x;
|
|
680
|
+
const dy = b.y - a.y;
|
|
681
|
+
const n = Math.max(1, Math.ceil(Math.hypot(dx, dy) * 2));
|
|
682
|
+
for (let k = 0; k <= n; k++) {
|
|
683
|
+
const t = k / n;
|
|
684
|
+
if (!walkable(grid, band, Math.round(a.x + dx * t), Math.round(a.y + dy * t))) return false;
|
|
685
|
+
}
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/** The same test on the fine mask, in map% — what the DRAWN line is validated against. */
|
|
690
|
+
export function lineOfSightPct(grid: NavGrid, band: number, a: MapPct, b: MapPct): boolean {
|
|
691
|
+
const m = grid.fine;
|
|
692
|
+
if (band < 0 || band >= m.nBands) return false;
|
|
693
|
+
const off = band * m.res * m.res;
|
|
694
|
+
const ax = idxOfUnit(a.left * 10, m.res);
|
|
695
|
+
const ay = idxOfUnit(a.top * 10, m.res);
|
|
696
|
+
const bx = idxOfUnit(b.left * 10, m.res);
|
|
697
|
+
const by = idxOfUnit(b.top * 10, m.res);
|
|
698
|
+
const n = Math.max(1, Math.ceil(Math.hypot(bx - ax, by - ay) * 2));
|
|
699
|
+
for (let k = 0; k <= n; k++) {
|
|
700
|
+
const t = k / n;
|
|
701
|
+
const x = Math.round(ax + (bx - ax) * t);
|
|
702
|
+
const y = Math.round(ay + (by - ay) * t);
|
|
703
|
+
if (x < 0 || y < 0 || x >= m.res || y >= m.res) return false;
|
|
704
|
+
if (!m.cells[off + y * m.res + x]) return false;
|
|
705
|
+
}
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Aggro line-of-sight over the baked floorplan: same z-band and clear fine-mask walk.
|
|
711
|
+
*
|
|
712
|
+
* Classic aggro is radius **and** LoS — a mob through a wall or on another storey
|
|
713
|
+
* must not join. Uses the same rasterised polylines as route A* (no second geometry).
|
|
714
|
+
*
|
|
715
|
+
* Cite: cmangos-classic `UnitAI.cpp` `DetectOrAttack` ~530–536
|
|
716
|
+
* `GetAttackDistance` then `IsWithinLOSInMap(who, true)`;
|
|
717
|
+
* `CheckForHelp` ~518 `IsWithinDistInMap` + `IsWithinLOSInMap`.
|
|
718
|
+
*
|
|
719
|
+
* Cost: O(cell samples along the segment) on the fine mask (2×NAV_RES) — no per-path
|
|
720
|
+
* segment sweep. A dense Stratholme pull (~200 candidates) is a few thousand cell
|
|
721
|
+
* lookups; measured under 1 ms on a hot path in the population gate.
|
|
722
|
+
*/
|
|
723
|
+
export function aggroHasLineOfSight(
|
|
724
|
+
grid: NavGrid,
|
|
725
|
+
a: NavWaypoint,
|
|
726
|
+
b: NavWaypoint,
|
|
727
|
+
): boolean {
|
|
728
|
+
const sa = snapToFloor(grid, a);
|
|
729
|
+
const sb = snapToFloor(grid, b);
|
|
730
|
+
if (!sa || !sb) return false;
|
|
731
|
+
// Different storeys (no connection modelled as same-band LoS) — reject.
|
|
732
|
+
if (sa.band !== sb.band) return false;
|
|
733
|
+
return lineOfSightPct(grid, sa.band, a.pct, b.pct);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* String-pull: drop intermediate cells the line can see past. Turns the 8-connected
|
|
738
|
+
* staircase into the few real corners a player would walk. A band change always survives
|
|
739
|
+
* as a corner — that cell is the ramp.
|
|
740
|
+
*
|
|
741
|
+
* `los` defaults to the search grid; `legBetween` passes the fine-mask test instead so the
|
|
742
|
+
* hops that survive are legal at twice the search resolution.
|
|
743
|
+
*/
|
|
744
|
+
export function stringPull(
|
|
745
|
+
grid: NavGrid,
|
|
746
|
+
path: NavCell[],
|
|
747
|
+
los: (band: number, a: NavCell, b: NavCell) => boolean = (band, a, b) =>
|
|
748
|
+
lineOfSight(grid, band, a, b),
|
|
749
|
+
): NavCell[] {
|
|
750
|
+
if (path.length <= 2) return path.slice();
|
|
751
|
+
const out: NavCell[] = [path[0]!];
|
|
752
|
+
let i = 0;
|
|
753
|
+
while (i < path.length - 1) {
|
|
754
|
+
let best = i + 1;
|
|
755
|
+
for (let j = i + 2; j < path.length; j++) {
|
|
756
|
+
if (path[j]!.band !== path[i]!.band) break;
|
|
757
|
+
if (!los(path[i]!.band, path[i]!, path[j]!)) break;
|
|
758
|
+
best = j;
|
|
759
|
+
}
|
|
760
|
+
out.push(path[best]!);
|
|
761
|
+
i = best;
|
|
762
|
+
}
|
|
763
|
+
return out;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// Route legs
|
|
767
|
+
|
|
768
|
+
// One routed leg between two waypoints. Unrouted legs keep the two endpoints for measurement/caption but
|
|
769
|
+
// set `routed:false`. The map view must NOT draw them as a full chord through walls (see routeLegsSvg).
|
|
770
|
+
export function legBetween(grid: NavGrid, a: NavWaypoint, b: NavWaypoint): RouteLeg {
|
|
771
|
+
const sa = snapToFloor(grid, a);
|
|
772
|
+
const sb = snapToFloor(grid, b);
|
|
773
|
+
const unrouted: RouteLeg = { points: [a.pct, b.pct], routed: false };
|
|
774
|
+
if (!sa || !sb) return unrouted;
|
|
775
|
+
|
|
776
|
+
// Already walkable in a straight line at fine resolution? Then that IS the path, and A*
|
|
777
|
+
// must not be allowed to invent a detour around a corridor the coarse mask pinched shut.
|
|
778
|
+
if (sa.band === sb.band && lineOfSightPct(grid, sa.band, a.pct, b.pct)) {
|
|
779
|
+
return { points: [a.pct, b.pct], routed: true };
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const cells = findCellPath(grid, sa, sb);
|
|
783
|
+
if (!cells || cells.length < 2) return unrouted;
|
|
784
|
+
const pulled = stringPull(grid, cells, (band, p, q) =>
|
|
785
|
+
lineOfSightPct(grid, band, pctOfCell(grid, p.x, p.y), pctOfCell(grid, q.x, q.y)),
|
|
786
|
+
);
|
|
787
|
+
// Keep the real endpoints so the line still touches the pin, not the snapped cell.
|
|
788
|
+
const points: MapPct[] = [a.pct];
|
|
789
|
+
for (let i = 1; i < pulled.length - 1; i++) {
|
|
790
|
+
points.push(pctOfCell(grid, pulled[i]!.x, pulled[i]!.y));
|
|
791
|
+
}
|
|
792
|
+
points.push(b.pct);
|
|
793
|
+
return { points, routed: true };
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/** Instance-id → nav grid registry (primed when floorplan loads; pure, no I/O). */
|
|
797
|
+
const instanceNav = new Map<string, NavGrid>();
|
|
798
|
+
|
|
799
|
+
/** Map-id → nav grid (aggro LoS for spatial pulls when instance id is unknown). */
|
|
800
|
+
const mapNav = new Map<number, NavGrid>();
|
|
801
|
+
|
|
802
|
+
/** Register a nav grid for geometric route ordering at enter / reorder time. */
|
|
803
|
+
export function registerInstanceNav(instanceId: string, grid: NavGrid, mapId?: number): void {
|
|
804
|
+
instanceNav.set(instanceId, grid);
|
|
805
|
+
if (mapId != null) mapNav.set(mapId, grid);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/** Register a nav grid keyed by Classic map id (spatial pull LoS). */
|
|
809
|
+
export function registerMapNav(mapId: number, grid: NavGrid): void {
|
|
810
|
+
mapNav.set(mapId, grid);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/** Drop one or all registered instance nav grids (tests). */
|
|
814
|
+
export function clearInstanceNav(instanceId?: string): void {
|
|
815
|
+
if (instanceId == null) instanceNav.clear();
|
|
816
|
+
else instanceNav.delete(instanceId);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/** Drop one or all map-id nav grids (tests). */
|
|
820
|
+
export function clearMapNav(mapId?: number): void {
|
|
821
|
+
if (mapId == null) mapNav.clear();
|
|
822
|
+
else mapNav.delete(mapId);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/** Registered nav grid for an instance, if primed. */
|
|
826
|
+
export function instanceNavGrid(instanceId: string): NavGrid | null {
|
|
827
|
+
return instanceNav.get(instanceId) ?? null;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/** Registered nav grid for a Classic map id (aggro LoS). */
|
|
831
|
+
export function mapNavGrid(mapId: number): NavGrid | null {
|
|
832
|
+
return mapNav.get(mapId) ?? null;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Build the drawn route: one leg per consecutive waypoint pair (entrance first). Legs are cached per grid +
|
|
836
|
+
// endpoint cells, so a repaint costs nothing.
|
|
837
|
+
export function routeLegs(grid: NavGrid, waypoints: readonly NavWaypoint[]): RouteLeg[] {
|
|
838
|
+
const out: RouteLeg[] = [];
|
|
839
|
+
const cache = legCacheFor(grid);
|
|
840
|
+
for (let i = 0; i + 1 < waypoints.length; i++) {
|
|
841
|
+
const a = waypoints[i]!;
|
|
842
|
+
const b = waypoints[i + 1]!;
|
|
843
|
+
const ca = cellOfPct(grid, a.pct);
|
|
844
|
+
const cb = cellOfPct(grid, b.pct);
|
|
845
|
+
const key = `${ca.x},${ca.y},${a.z ?? ''}>${cb.x},${cb.y},${b.z ?? ''}`;
|
|
846
|
+
let leg = cache.get(key);
|
|
847
|
+
if (!leg) {
|
|
848
|
+
leg = legBetween(grid, a, b);
|
|
849
|
+
cache.set(key, leg);
|
|
850
|
+
}
|
|
851
|
+
out.push(leg);
|
|
852
|
+
}
|
|
853
|
+
return out;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
const legCaches = new WeakMap<NavGrid, Map<string, RouteLeg>>();
|
|
857
|
+
function legCacheFor(grid: NavGrid): Map<string, RouteLeg> {
|
|
858
|
+
let m = legCaches.get(grid);
|
|
859
|
+
if (!m) {
|
|
860
|
+
m = new Map();
|
|
861
|
+
legCaches.set(grid, m);
|
|
862
|
+
}
|
|
863
|
+
return m;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
const gridCaches = new WeakMap<NavFloorDoc, NavGrid>();
|
|
867
|
+
|
|
868
|
+
/** Memoised nav grid for a floorplan document (one rasterisation per document). */
|
|
869
|
+
export function navGridFor(doc: NavFloorDoc | null | undefined, res: number = NAV_RES): NavGrid | null {
|
|
870
|
+
if (!doc || !Array.isArray(doc.paths) || !doc.paths.length) return null;
|
|
871
|
+
const hit = gridCaches.get(doc);
|
|
872
|
+
if (hit && hit.res === res) return hit;
|
|
873
|
+
const grid = buildNavGrid(doc, res);
|
|
874
|
+
gridCaches.set(doc, grid);
|
|
875
|
+
return grid;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Fraction of a polyline's length that lies on floor — the oracle O13 scores.
|
|
880
|
+
* Samples every `stepPct` of map% along each segment (band-agnostic on purpose: the
|
|
881
|
+
* question this answers is "does the drawn line sit on drawn floor").
|
|
882
|
+
*/
|
|
883
|
+
export function polylineOnFloor(
|
|
884
|
+
grid: NavGrid,
|
|
885
|
+
points: readonly MapPct[],
|
|
886
|
+
stepPct = 0.25,
|
|
887
|
+
): { on: number; total: number } {
|
|
888
|
+
let on = 0;
|
|
889
|
+
let total = 0;
|
|
890
|
+
for (let i = 0; i + 1 < points.length; i++) {
|
|
891
|
+
const a = points[i]!;
|
|
892
|
+
const b = points[i + 1]!;
|
|
893
|
+
const dist = Math.hypot(b.left - a.left, b.top - a.top);
|
|
894
|
+
const n = Math.max(1, Math.ceil(dist / stepPct));
|
|
895
|
+
for (let k = 0; k <= n; k++) {
|
|
896
|
+
const t = k / n;
|
|
897
|
+
const p = { left: a.left + (b.left - a.left) * t, top: a.top + (b.top - a.top) * t };
|
|
898
|
+
const c = cellOfPct(grid, p);
|
|
899
|
+
total++;
|
|
900
|
+
if (grid.any[c.y * grid.res + c.x]) on++;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return { on, total };
|
|
904
|
+
}
|