azeroth-shell 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +26 -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 +126 -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,994 @@
|
|
|
1
|
+
// Combat weapon and defense skill state at CMaNGOS parity (Item.cpp GetSkill; Player.cpp
|
|
2
|
+
// LearnDefaultSkills, UpdateWeaponSkill; Skill* DBCs). Professions stay on Character.skills.
|
|
3
|
+
|
|
4
|
+
import type { ItemDef } from '../../data/schema.ts';
|
|
5
|
+
import { skillMaxForLevel } from '../../engine/combat/mitigation.ts';
|
|
6
|
+
import { detLog } from '../../engine/core/detMath.ts';
|
|
7
|
+
|
|
8
|
+
/** One skill's trained value + cap. Same shape as profession CharacterSkill. */
|
|
9
|
+
export interface CombatSkillProgress {
|
|
10
|
+
current: number;
|
|
11
|
+
max: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Sparse map: CMaNGOS skill id → progress. Only trained lines present. */
|
|
15
|
+
export type CombatSkillMap = Partial<Record<number, CombatSkillProgress>>;
|
|
16
|
+
|
|
17
|
+
/** Create-kit skill row (from playercreateinfo_skills, expanded per race/class). */
|
|
18
|
+
export interface CreateSkillRow {
|
|
19
|
+
skill: number;
|
|
20
|
+
step: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Optional DBC-backed meta (SkillLine / SkillTiers / SkillRaceClassInfo + spell↔skill links). Baked by
|
|
24
|
+
// enrich-combat-skills.mjs / extract.mjs; fixtures may omit (hardcoded fallbacks apply).
|
|
25
|
+
export interface CombatSkillMeta {
|
|
26
|
+
/** SkillLine.categoryId by skill id */
|
|
27
|
+
categories?: Record<number, number>;
|
|
28
|
+
/** SkillLine display name by skill id (for Character Skills UI) */
|
|
29
|
+
skillNames?: Record<number, string>;
|
|
30
|
+
/** SkillTiers.maxSkillValue[0..15] by skillTiersId */
|
|
31
|
+
tiers?: Record<number, number[]>;
|
|
32
|
+
/** SkillRaceClassInfo rows used for mono/rank create + SetSkillStep + train flags */
|
|
33
|
+
raceClass?: Array<{
|
|
34
|
+
skillId: number;
|
|
35
|
+
raceMask: number;
|
|
36
|
+
classMask: number;
|
|
37
|
+
flags: number;
|
|
38
|
+
skillTierId: number;
|
|
39
|
+
/** SkillRaceClassInfo.reqLevel (m_minLevel) — train gate when > 0 */
|
|
40
|
+
reqLevel?: number;
|
|
41
|
+
}>;
|
|
42
|
+
// Spell → skill for SkillLineAbility with learnOnGetSkill = ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
|
|
43
|
+
// (2). Cite: Player.cpp UpdateSpellTrainedSkills ~5722
|
|
44
|
+
spellGrants?: Record<number, number>;
|
|
45
|
+
// Spell → { skill, step } from SPELL_EFFECT_SKILL (118) / SKILL_STEP (44). Cite:
|
|
46
|
+
// SpellMgr::LoadSpellLearnSkills; SetSkillStep
|
|
47
|
+
spellLearnSkills?: Record<number, { skill: number; step: number }>;
|
|
48
|
+
// SkillLineAbility rows keyed by spell id (raceMask, classMask, skillId), read by
|
|
49
|
+
// IsSpellFitByClassAndRace for trainer lists and train gates. Cite: Player.cpp ~18369.
|
|
50
|
+
spellAbilities?: Record<number, Array<{ skillId: number; raceMask: number; classMask: number }>>;
|
|
51
|
+
// spell_learn_spell: learning `entry` auto-teaches the listed SpellIDs, e.g. Poisons 2842 →
|
|
52
|
+
// Instant Poison craft 8681. Cite: Player.cpp addSpell ~3412 SpellLearnSpellMapBounds.
|
|
53
|
+
spellLearnSpells?: Record<number, number[]>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** SharedDefines.h SKILL_POISONS / SKILL_LOCKPICKING — special-cased in UpdateSpellTrainedSkills. */
|
|
57
|
+
export const SKILL_POISONS = 40;
|
|
58
|
+
export const SKILL_LOCKPICKING = 633;
|
|
59
|
+
|
|
60
|
+
// ---- Skill ids (SharedDefines.h) used in combat / create kits --------------
|
|
61
|
+
|
|
62
|
+
export const COMBAT_SKILL = {
|
|
63
|
+
SWORDS: 43,
|
|
64
|
+
AXES: 44,
|
|
65
|
+
BOWS: 45,
|
|
66
|
+
GUNS: 46,
|
|
67
|
+
MACES: 54,
|
|
68
|
+
SWORDS_2H: 55,
|
|
69
|
+
DEFENSE: 95,
|
|
70
|
+
FERAL: 134,
|
|
71
|
+
STAVES: 136,
|
|
72
|
+
MACES_2H: 160,
|
|
73
|
+
UNARMED: 162,
|
|
74
|
+
AXES_2H: 172,
|
|
75
|
+
DAGGERS: 173,
|
|
76
|
+
THROWN: 176,
|
|
77
|
+
CROSSBOWS: 226,
|
|
78
|
+
WANDS: 228,
|
|
79
|
+
POLEARMS: 229,
|
|
80
|
+
/** Armor material skills — Item.cpp item_armor_skills */
|
|
81
|
+
PLATE: 293,
|
|
82
|
+
MAIL: 413,
|
|
83
|
+
LEATHER: 414,
|
|
84
|
+
CLOTH: 415,
|
|
85
|
+
SHIELD: 433,
|
|
86
|
+
FIST: 473,
|
|
87
|
+
} as const;
|
|
88
|
+
|
|
89
|
+
/** SharedDefines.h SkillCategory */
|
|
90
|
+
export const SKILL_CATEGORY = {
|
|
91
|
+
WEAPON: 6,
|
|
92
|
+
CLASS: 7,
|
|
93
|
+
ARMOR: 8,
|
|
94
|
+
SECONDARY: 9,
|
|
95
|
+
LANGUAGES: 10,
|
|
96
|
+
PROFESSION: 11,
|
|
97
|
+
GENERIC: 12,
|
|
98
|
+
} as const;
|
|
99
|
+
|
|
100
|
+
/** SkillRaceClassInfo flags — DBCEnums.h SkillRaceClassInfoFlags */
|
|
101
|
+
export const SKILL_FLAG_MAXIMIZED = 0x010;
|
|
102
|
+
/** SKILL_FLAG_NOT_TRAINABLE — cannot learn via trainer when race/class row matches */
|
|
103
|
+
export const SKILL_FLAG_NOT_TRAINABLE = 0x100;
|
|
104
|
+
|
|
105
|
+
/** SkillLineAbility learnOnGetSkill */
|
|
106
|
+
export const ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2;
|
|
107
|
+
|
|
108
|
+
export type SkillRangeType = 'language' | 'level' | 'mono' | 'rank' | 'none';
|
|
109
|
+
|
|
110
|
+
// Weapon subclass → skill id. Fist maps to UNARMED for the combat skill value while the equip
|
|
111
|
+
// gate uses FIST (skillIdForEquip). Cite: Item.cpp item_weapon_skills.
|
|
112
|
+
const WEAPON_SUBCLASS_SKILL: readonly number[] = [
|
|
113
|
+
COMBAT_SKILL.AXES, // 0
|
|
114
|
+
COMBAT_SKILL.AXES_2H, // 1
|
|
115
|
+
COMBAT_SKILL.BOWS, // 2
|
|
116
|
+
COMBAT_SKILL.GUNS, // 3
|
|
117
|
+
COMBAT_SKILL.MACES, // 4
|
|
118
|
+
COMBAT_SKILL.MACES_2H, // 5
|
|
119
|
+
COMBAT_SKILL.POLEARMS, // 6
|
|
120
|
+
COMBAT_SKILL.SWORDS, // 7
|
|
121
|
+
COMBAT_SKILL.SWORDS_2H, // 8
|
|
122
|
+
0, // 9 obsolete
|
|
123
|
+
COMBAT_SKILL.STAVES, // 10
|
|
124
|
+
0, // 11
|
|
125
|
+
0, // 12
|
|
126
|
+
COMBAT_SKILL.UNARMED, // 13 fist → unarmed for combat
|
|
127
|
+
0, // 14 misc
|
|
128
|
+
COMBAT_SKILL.DAGGERS, // 15
|
|
129
|
+
COMBAT_SKILL.THROWN, // 16
|
|
130
|
+
253, // 17 spear / assassination (SKILL_ASSASSINATION)
|
|
131
|
+
COMBAT_SKILL.CROSSBOWS, // 18
|
|
132
|
+
COMBAT_SKILL.WANDS, // 19
|
|
133
|
+
356, // 20 fishing pole (SKILL_FISHING) — excluded from weapon gain
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
/** Armor subclass → skill (Item.cpp item_armor_skills). Index = item_template.subclass. */
|
|
137
|
+
const ARMOR_SUBCLASS_SKILL: readonly number[] = [
|
|
138
|
+
0, // 0 misc
|
|
139
|
+
COMBAT_SKILL.CLOTH, // 1
|
|
140
|
+
COMBAT_SKILL.LEATHER, // 2
|
|
141
|
+
COMBAT_SKILL.MAIL, // 3
|
|
142
|
+
COMBAT_SKILL.PLATE, // 4
|
|
143
|
+
0, // 5 buckler (unused classic)
|
|
144
|
+
COMBAT_SKILL.SHIELD, // 6
|
|
145
|
+
0, 0, 0, // libram/idol/totem
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
/** typeName labels from extract.mjs → skill (fixtures / pre-subclass bakes). */
|
|
149
|
+
const TYPE_NAME_SKILL: Record<string, number> = {
|
|
150
|
+
Axe: COMBAT_SKILL.AXES,
|
|
151
|
+
'Two-Handed Axe': COMBAT_SKILL.AXES_2H,
|
|
152
|
+
Bow: COMBAT_SKILL.BOWS,
|
|
153
|
+
Gun: COMBAT_SKILL.GUNS,
|
|
154
|
+
Mace: COMBAT_SKILL.MACES,
|
|
155
|
+
'Two-Handed Mace': COMBAT_SKILL.MACES_2H,
|
|
156
|
+
Polearm: COMBAT_SKILL.POLEARMS,
|
|
157
|
+
Sword: COMBAT_SKILL.SWORDS,
|
|
158
|
+
'Two-Handed Sword': COMBAT_SKILL.SWORDS_2H,
|
|
159
|
+
Staff: COMBAT_SKILL.STAVES,
|
|
160
|
+
'Fist Weapon': COMBAT_SKILL.UNARMED,
|
|
161
|
+
Dagger: COMBAT_SKILL.DAGGERS,
|
|
162
|
+
Thrown: COMBAT_SKILL.THROWN,
|
|
163
|
+
Crossbow: COMBAT_SKILL.CROSSBOWS,
|
|
164
|
+
Wand: COMBAT_SKILL.WANDS,
|
|
165
|
+
'Fishing Pole': 356,
|
|
166
|
+
Cloth: COMBAT_SKILL.CLOTH,
|
|
167
|
+
Leather: COMBAT_SKILL.LEATHER,
|
|
168
|
+
Mail: COMBAT_SKILL.MAIL,
|
|
169
|
+
Plate: COMBAT_SKILL.PLATE,
|
|
170
|
+
Shield: COMBAT_SKILL.SHIELD,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Fallback LEVEL-range skills when SkillLine DBC meta is absent. Cite: GetSkillRangeType — WEAPON except
|
|
174
|
+
// fist; defense/unarmed; poisons/lockpicking LEVEL.
|
|
175
|
+
const LEVEL_RANGE_SKILLS = new Set<number>([
|
|
176
|
+
COMBAT_SKILL.SWORDS,
|
|
177
|
+
COMBAT_SKILL.AXES,
|
|
178
|
+
COMBAT_SKILL.BOWS,
|
|
179
|
+
COMBAT_SKILL.GUNS,
|
|
180
|
+
COMBAT_SKILL.MACES,
|
|
181
|
+
COMBAT_SKILL.SWORDS_2H,
|
|
182
|
+
COMBAT_SKILL.DEFENSE,
|
|
183
|
+
COMBAT_SKILL.FERAL,
|
|
184
|
+
COMBAT_SKILL.STAVES,
|
|
185
|
+
COMBAT_SKILL.MACES_2H,
|
|
186
|
+
COMBAT_SKILL.UNARMED,
|
|
187
|
+
COMBAT_SKILL.AXES_2H,
|
|
188
|
+
COMBAT_SKILL.DAGGERS,
|
|
189
|
+
COMBAT_SKILL.THROWN,
|
|
190
|
+
COMBAT_SKILL.CROSSBOWS,
|
|
191
|
+
COMBAT_SKILL.WANDS,
|
|
192
|
+
COMBAT_SKILL.POLEARMS,
|
|
193
|
+
253, // spear
|
|
194
|
+
]);
|
|
195
|
+
|
|
196
|
+
/** Language skill ids in create kits — grant 300/300, no combat use. */
|
|
197
|
+
const LANGUAGE_SKILLS = new Set<number>([
|
|
198
|
+
98, 109, 111, 113, 115, 137, 138, 139, 140, 141, 313, 315, 673,
|
|
199
|
+
]);
|
|
200
|
+
|
|
201
|
+
/** Fishing pole skill — UpdateWeaponSkill excludes fishing poles. */
|
|
202
|
+
const SKILL_FISHING = 356;
|
|
203
|
+
|
|
204
|
+
/** ITEM_SUBCLASS_WEAPON_FIST */
|
|
205
|
+
const WEAPON_SUBCLASS_FIST = 13;
|
|
206
|
+
|
|
207
|
+
// ---- Lookups ----------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
// Skill line for an item (weapon combat skill or armor material). 0 if none. Cite: Item.cpp GetSkill — fist
|
|
210
|
+
// weapons return UNARMED here.
|
|
211
|
+
export function skillIdForItem(item: ItemDef | undefined | null): number {
|
|
212
|
+
if (!item) return 0;
|
|
213
|
+
if (item.weaponSubclass != null && item.weaponSubclass >= 0) {
|
|
214
|
+
const id = WEAPON_SUBCLASS_SKILL[item.weaponSubclass] ?? 0;
|
|
215
|
+
return id | 0;
|
|
216
|
+
}
|
|
217
|
+
if (item.armorSubclass != null && item.armorSubclass >= 0) {
|
|
218
|
+
const id = ARMOR_SUBCLASS_SKILL[item.armorSubclass] ?? 0;
|
|
219
|
+
return id | 0;
|
|
220
|
+
}
|
|
221
|
+
if (item.typeName && TYPE_NAME_SKILL[item.typeName] != null) {
|
|
222
|
+
return TYPE_NAME_SKILL[item.typeName]!;
|
|
223
|
+
}
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Skill required to *equip* the item (CanUseItem proficiency gate). Fist weapons require SKILL_FIST_WEAPONS
|
|
228
|
+
// (473), not unarmed. Cite: Player.cpp CanUseItem ~9756–9762
|
|
229
|
+
export function skillIdForEquip(item: ItemDef | undefined | null): number {
|
|
230
|
+
if (!item) return 0;
|
|
231
|
+
if (item.weaponSubclass === WEAPON_SUBCLASS_FIST || item.typeName === 'Fist Weapon') {
|
|
232
|
+
return COMBAT_SKILL.FIST;
|
|
233
|
+
}
|
|
234
|
+
return skillIdForItem(item);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** GetSkillRangeType port. Cite: ObjectMgr.cpp GetSkillRangeType ~8569 */
|
|
238
|
+
export function skillRangeType(skillId: number, meta?: CombatSkillMeta | null, racial = false): SkillRangeType {
|
|
239
|
+
const id = skillId | 0;
|
|
240
|
+
if (!id) return 'none';
|
|
241
|
+
if (isLanguageSkill(id)) return 'language';
|
|
242
|
+
|
|
243
|
+
const cat = meta?.categories?.[id];
|
|
244
|
+
if (cat != null) {
|
|
245
|
+
switch (cat) {
|
|
246
|
+
case SKILL_CATEGORY.LANGUAGES:
|
|
247
|
+
return 'language';
|
|
248
|
+
case SKILL_CATEGORY.WEAPON:
|
|
249
|
+
// Fist is mono; all other weapons level-range.
|
|
250
|
+
return id === COMBAT_SKILL.FIST ? 'mono' : 'level';
|
|
251
|
+
case SKILL_CATEGORY.ARMOR:
|
|
252
|
+
case SKILL_CATEGORY.CLASS:
|
|
253
|
+
// Poisons (40) / lockpicking (633) are LEVEL; others MONO.
|
|
254
|
+
if (id === 40 || id === 633) return 'level';
|
|
255
|
+
return 'mono';
|
|
256
|
+
case SKILL_CATEGORY.SECONDARY:
|
|
257
|
+
case SKILL_CATEGORY.PROFESSION:
|
|
258
|
+
// Profession/riding → RANK (handled on Character.skills); other secondary → mono/none.
|
|
259
|
+
if (racial) return 'none';
|
|
260
|
+
return 'mono';
|
|
261
|
+
default:
|
|
262
|
+
return 'none';
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Fallback without DBC: hardcoded LEVEL set + known mono armor/fist.
|
|
267
|
+
if (LEVEL_RANGE_SKILLS.has(id)) return 'level';
|
|
268
|
+
if (
|
|
269
|
+
id === COMBAT_SKILL.FIST
|
|
270
|
+
|| id === COMBAT_SKILL.CLOTH
|
|
271
|
+
|| id === COMBAT_SKILL.LEATHER
|
|
272
|
+
|| id === COMBAT_SKILL.MAIL
|
|
273
|
+
|| id === COMBAT_SKILL.PLATE
|
|
274
|
+
|| id === COMBAT_SKILL.SHIELD
|
|
275
|
+
) {
|
|
276
|
+
return 'mono';
|
|
277
|
+
}
|
|
278
|
+
// Unknown create-kit lines (class skills, etc.) → mono proficiency presence.
|
|
279
|
+
return 'mono';
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function isLevelRangeCombatSkill(skillId: number, meta?: CombatSkillMeta | null): boolean {
|
|
283
|
+
return skillRangeType(skillId, meta) === 'level';
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export function isLanguageSkill(skillId: number): boolean {
|
|
287
|
+
return LANGUAGE_SKILLS.has(skillId | 0);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Race/class mask check for playercreateinfo_skills / SkillRaceClassInfo. mask 0 = all; else bit (1 << (id
|
|
291
|
+
// - 1)).
|
|
292
|
+
export function raceClassMaskMatches(mask: number, id: number): boolean {
|
|
293
|
+
if (!mask) return true;
|
|
294
|
+
if (id < 1) return false;
|
|
295
|
+
return (mask & (1 << (id - 1))) !== 0;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Player getRaceMask / getClassMask: `1 << (id - 1)`. */
|
|
299
|
+
export function unitRaceOrClassMask(id: number): number {
|
|
300
|
+
if (id < 1) return 0;
|
|
301
|
+
return 1 << (id - 1);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// True when SkillLineAbility has a nonzero classMask. No row / classMask 0 fail-opens in C++. Cite:
|
|
305
|
+
// Player.cpp:18369 IsSpellFitByClassAndRace.
|
|
306
|
+
export function spellHasClassRestrictingAbility(
|
|
307
|
+
spellId: number,
|
|
308
|
+
meta?: CombatSkillMeta | null,
|
|
309
|
+
): boolean {
|
|
310
|
+
const abilities = meta?.spellAbilities?.[spellId | 0];
|
|
311
|
+
if (!abilities?.length) return false;
|
|
312
|
+
return abilities.some((a) => (a.classMask | 0) !== 0);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Whether a spell can be trained for this race and class, a port of IsSpellFitByClassAndRace plus
|
|
316
|
+
// the SkillRaceClassInfo line gate — without which a Rogue learns Evocation from a Mage (KI-083).
|
|
317
|
+
export function isSpellFitByClassAndRace(
|
|
318
|
+
spellId: number,
|
|
319
|
+
race: number,
|
|
320
|
+
cls: number,
|
|
321
|
+
meta?: CombatSkillMeta | null,
|
|
322
|
+
level?: number,
|
|
323
|
+
): boolean {
|
|
324
|
+
const sid = spellId | 0;
|
|
325
|
+
if (!sid) return false;
|
|
326
|
+
const abilities = meta?.spellAbilities?.[sid];
|
|
327
|
+
// C++: bounds.first == bounds.second → true (no SLA restriction).
|
|
328
|
+
if (!abilities?.length) return true;
|
|
329
|
+
|
|
330
|
+
const raceMask = unitRaceOrClassMask(race);
|
|
331
|
+
const classMask = unitRaceOrClassMask(cls);
|
|
332
|
+
|
|
333
|
+
for (const ability of abilities) {
|
|
334
|
+
// skip wrong race skills
|
|
335
|
+
if (ability.raceMask && (ability.raceMask & raceMask) === 0) continue;
|
|
336
|
+
// skip wrong class skills
|
|
337
|
+
if (ability.classMask && (ability.classMask & classMask) === 0) continue;
|
|
338
|
+
|
|
339
|
+
const skillId = ability.skillId | 0;
|
|
340
|
+
// SLA classMask 0 = unrestricted on the class axis, but the skill line may still
|
|
341
|
+
// be class-restricted. Cite: SkillRaceClassInfo; KI-083 Evocation 12051 / skill 237.
|
|
342
|
+
if (!(ability.classMask | 0) && skillId && meta?.raceClass?.length) {
|
|
343
|
+
if (!raceClassCanLearnSkill(meta, skillId, race, cls, level)) continue;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Matching SLA — SkillRaceClassInfo may still block (NOT_TRAINABLE / reqLevel).
|
|
347
|
+
const rows = meta?.raceClass;
|
|
348
|
+
if (rows?.length && skillId) {
|
|
349
|
+
for (const skillRC of rows) {
|
|
350
|
+
if ((skillRC.skillId | 0) !== skillId) continue;
|
|
351
|
+
// C++ uses raw & (does not treat 0 as "all") on SkillRaceClassInfo masks.
|
|
352
|
+
if ((skillRC.raceMask & raceMask) === 0) continue;
|
|
353
|
+
if ((skillRC.classMask & classMask) === 0) continue;
|
|
354
|
+
if ((skillRC.flags & SKILL_FLAG_NOT_TRAINABLE) !== 0) return false;
|
|
355
|
+
const req = (skillRC.reqLevel ?? 0) | 0;
|
|
356
|
+
if (level != null && req > 0 && level < req) return false;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Can this race/class EVER learn `skillId`? Strict — unlike lookupRaceClass it does not fall back
|
|
365
|
+
// to other classes' rows. Fail-open when the meta predates the bake.
|
|
366
|
+
export function raceClassCanLearnSkill(
|
|
367
|
+
meta: CombatSkillMeta | undefined | null,
|
|
368
|
+
skillId: number,
|
|
369
|
+
race: number,
|
|
370
|
+
cls: number,
|
|
371
|
+
level?: number,
|
|
372
|
+
): boolean {
|
|
373
|
+
const rows = meta?.raceClass;
|
|
374
|
+
if (!rows?.length) return true;
|
|
375
|
+
const id = skillId | 0;
|
|
376
|
+
return rows.some((r) =>
|
|
377
|
+
(r.skillId | 0) === id
|
|
378
|
+
&& raceClassMaskMatches(r.raceMask | 0, race)
|
|
379
|
+
&& raceClassMaskMatches(r.classMask | 0, cls)
|
|
380
|
+
&& (level == null || ((r.reqLevel ?? 0) | 0) <= level));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function lookupRaceClass(
|
|
384
|
+
meta: CombatSkillMeta | undefined | null,
|
|
385
|
+
skillId: number,
|
|
386
|
+
race?: number,
|
|
387
|
+
cls?: number,
|
|
388
|
+
): CombatSkillMeta['raceClass'] extends (infer E)[] | undefined ? E | undefined : never {
|
|
389
|
+
const rows = meta?.raceClass;
|
|
390
|
+
if (!rows?.length) return undefined as never;
|
|
391
|
+
for (const row of rows) {
|
|
392
|
+
if ((row.skillId | 0) !== (skillId | 0)) continue;
|
|
393
|
+
if (race != null && !raceClassMaskMatches(row.raceMask | 0, race)) continue;
|
|
394
|
+
if (cls != null && !raceClassMaskMatches(row.classMask | 0, cls)) continue;
|
|
395
|
+
return row as never;
|
|
396
|
+
}
|
|
397
|
+
// Prefer a universal row if race/class not supplied.
|
|
398
|
+
return rows.find((r) => (r.skillId | 0) === (skillId | 0)) as never;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Initial progress for a create skill: LANGUAGE 300/300, LEVEL-range 1 of L×5, MONO/RANK the
|
|
402
|
+
// SkillTiers max at step, MAXIMIZED value = max. Cite: Player.cpp LearnDefaultSkills.
|
|
403
|
+
export function initialCreateSkillProgress(
|
|
404
|
+
skillId: number,
|
|
405
|
+
level: number,
|
|
406
|
+
step: number,
|
|
407
|
+
meta?: CombatSkillMeta | null,
|
|
408
|
+
race?: number,
|
|
409
|
+
cls?: number,
|
|
410
|
+
): CombatSkillProgress {
|
|
411
|
+
const range = skillRangeType(skillId, meta);
|
|
412
|
+
if (range === 'language') return { current: 300, max: 300 };
|
|
413
|
+
if (range === 'level') {
|
|
414
|
+
const max = skillMaxForLevel(level);
|
|
415
|
+
// Product cheat: Lockpicking sits at cap. The open gate reads this value, never a bypass.
|
|
416
|
+
return { current: skillId === SKILL_LOCKPICKING ? max : 1, max };
|
|
417
|
+
}
|
|
418
|
+
if (range === 'mono' || range === 'rank') {
|
|
419
|
+
const predefined = (step | 0) !== 0;
|
|
420
|
+
const stepN = predefined ? (step | 0) : 1;
|
|
421
|
+
const stepIndex = Math.max(0, stepN - 1);
|
|
422
|
+
const rc = lookupRaceClass(meta, skillId, race, cls);
|
|
423
|
+
if (rc?.skillTierId) {
|
|
424
|
+
const tierMax = meta?.tiers?.[rc.skillTierId]?.[stepIndex];
|
|
425
|
+
if (tierMax != null && tierMax > 0) {
|
|
426
|
+
const maxed = (rc.flags & SKILL_FLAG_MAXIMIZED) !== 0;
|
|
427
|
+
let value = 1;
|
|
428
|
+
if (maxed) value = tierMax;
|
|
429
|
+
else if (predefined) value = Math.max(1, (level - 1) * 5);
|
|
430
|
+
return { current: Math.min(value, tierMax), max: tierMax };
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (rc && (rc.flags & SKILL_FLAG_MAXIMIZED) !== 0) {
|
|
434
|
+
const max = skillMaxForLevel(level);
|
|
435
|
+
return { current: max, max };
|
|
436
|
+
}
|
|
437
|
+
// No tiers → proficiency 1/1 (classic mono default).
|
|
438
|
+
return { current: 1, max: 1 };
|
|
439
|
+
}
|
|
440
|
+
return { current: 1, max: 1 };
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/** Expand create-kit skill rows into a combat skill map for a new character. */
|
|
444
|
+
export function grantCreateCombatSkills(
|
|
445
|
+
rows: CreateSkillRow[],
|
|
446
|
+
level: number,
|
|
447
|
+
meta?: CombatSkillMeta | null,
|
|
448
|
+
race?: number,
|
|
449
|
+
cls?: number,
|
|
450
|
+
): CombatSkillMap {
|
|
451
|
+
const out: CombatSkillMap = {};
|
|
452
|
+
for (const row of rows) {
|
|
453
|
+
const id = row.skill | 0;
|
|
454
|
+
if (!id || out[id] || id === SKILL_POISONS) continue;
|
|
455
|
+
out[id] = initialCreateSkillProgress(id, level, row.step | 0, meta, race, cls);
|
|
456
|
+
}
|
|
457
|
+
// Defense + unarmed are universal in create kits (raceMask=0 classMask=0). Ensure present.
|
|
458
|
+
if (!out[COMBAT_SKILL.DEFENSE]) {
|
|
459
|
+
out[COMBAT_SKILL.DEFENSE] = initialCreateSkillProgress(COMBAT_SKILL.DEFENSE, level, 0, meta, race, cls);
|
|
460
|
+
}
|
|
461
|
+
if (!out[COMBAT_SKILL.UNARMED]) {
|
|
462
|
+
out[COMBAT_SKILL.UNARMED] = initialCreateSkillProgress(COMBAT_SKILL.UNARMED, level, 0, meta, race, cls);
|
|
463
|
+
}
|
|
464
|
+
return out;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// On level-up: raise max for SKILL_RANGE_LEVEL skills; keep current (unless already at old max). Cite:
|
|
468
|
+
// Player.cpp UpdateSkillsForLevel — non-maxed: val stays, max → new L×5; skip max==1 mono.
|
|
469
|
+
export function updateCombatSkillsForLevel(
|
|
470
|
+
map: CombatSkillMap | undefined,
|
|
471
|
+
level: number,
|
|
472
|
+
meta?: CombatSkillMeta | null,
|
|
473
|
+
): CombatSkillMap | undefined {
|
|
474
|
+
if (!map) return map;
|
|
475
|
+
const maxNew = skillMaxForLevel(level);
|
|
476
|
+
const out: CombatSkillMap = { ...map };
|
|
477
|
+
for (const key of Object.keys(out)) {
|
|
478
|
+
const id = Number(key);
|
|
479
|
+
const s = out[id];
|
|
480
|
+
if (!s) continue;
|
|
481
|
+
if (!isLevelRangeCombatSkill(id, meta)) continue;
|
|
482
|
+
if (s.max === 1) continue; // mono sentinel
|
|
483
|
+
const wasMaxed = s.current >= s.max || id === SKILL_LOCKPICKING;
|
|
484
|
+
out[id] = {
|
|
485
|
+
current: wasMaxed ? maxNew : Math.min(s.current, maxNew),
|
|
486
|
+
max: maxNew,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
return maxLockpickingSkill(out, level);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Armor proficiencies SkillRaceClassInfo unlocks at a level. Nothing else added them, so warriors
|
|
493
|
+
// never learned Plate Mail (293) and hunters never Mail (413), both reqLevel 40. Armor only.
|
|
494
|
+
export function grantLevelUnlockedArmorSkills(
|
|
495
|
+
map: CombatSkillMap | undefined,
|
|
496
|
+
level: number,
|
|
497
|
+
race: number,
|
|
498
|
+
cls: number,
|
|
499
|
+
meta?: CombatSkillMeta | null,
|
|
500
|
+
): CombatSkillMap | undefined {
|
|
501
|
+
if (map == null) return map;
|
|
502
|
+
const rows = meta?.raceClass;
|
|
503
|
+
if (!rows?.length) return map;
|
|
504
|
+
let out = map;
|
|
505
|
+
for (const row of rows) {
|
|
506
|
+
const id = row.skillId | 0;
|
|
507
|
+
if (!id || out[id]) continue;
|
|
508
|
+
if (!ARMOR_SUBCLASS_SKILL.includes(id)) continue;
|
|
509
|
+
const req = (row.reqLevel ?? 0) | 0;
|
|
510
|
+
if (req <= 0 || req > level) continue;
|
|
511
|
+
if (!raceClassMaskMatches(row.raceMask | 0, race)) continue;
|
|
512
|
+
if (!raceClassMaskMatches(row.classMask | 0, cls)) continue;
|
|
513
|
+
if (out === map) out = { ...map };
|
|
514
|
+
out[id] = initialCreateSkillProgress(id, level, 0, meta, race, cls);
|
|
515
|
+
}
|
|
516
|
+
return out;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Snap listed skill lines to L×5 (level-range only), for XP-leveled characters that never swung.
|
|
520
|
+
// An absent map stays undefined, meaning legacy fully trained. Cite: Unit.h GetSkillMaxForLevel.
|
|
521
|
+
export function raiseCombatSkillsToLevelCap(
|
|
522
|
+
map: CombatSkillMap | undefined,
|
|
523
|
+
level: number,
|
|
524
|
+
skillIds: readonly number[],
|
|
525
|
+
meta?: CombatSkillMeta | null,
|
|
526
|
+
): CombatSkillMap | undefined {
|
|
527
|
+
if (map == null) return map;
|
|
528
|
+
const max = skillMaxForLevel(level);
|
|
529
|
+
let out = map;
|
|
530
|
+
let changed = false;
|
|
531
|
+
for (const raw of skillIds) {
|
|
532
|
+
const id = raw | 0;
|
|
533
|
+
if (!id) continue;
|
|
534
|
+
const existing = out[id];
|
|
535
|
+
if (existing) {
|
|
536
|
+
if (existing.max === 1 && !isLevelRangeCombatSkill(id, meta)) continue;
|
|
537
|
+
if (existing.current === max && existing.max === max) continue;
|
|
538
|
+
if (!changed) {
|
|
539
|
+
out = { ...out };
|
|
540
|
+
changed = true;
|
|
541
|
+
}
|
|
542
|
+
out[id] = { current: max, max };
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (!isLevelRangeCombatSkill(id, meta)) continue;
|
|
546
|
+
if (!changed) {
|
|
547
|
+
out = { ...out };
|
|
548
|
+
changed = true;
|
|
549
|
+
}
|
|
550
|
+
out[id] = { current: max, max };
|
|
551
|
+
}
|
|
552
|
+
return out;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Pure skill value from the map. An absent map (legacy save) is fully trained L×5; a present map
|
|
556
|
+
// missing the skill is 0. Callers add bonuses. Cite: Player.h GetSkillValuePure.
|
|
557
|
+
export function combatSkillValue(
|
|
558
|
+
map: CombatSkillMap | undefined,
|
|
559
|
+
skillId: number,
|
|
560
|
+
level: number,
|
|
561
|
+
): number {
|
|
562
|
+
if (map == null) return skillMaxForLevel(level);
|
|
563
|
+
if (!skillId) return 0;
|
|
564
|
+
const s = map[skillId];
|
|
565
|
+
if (!s) return 0;
|
|
566
|
+
return s.current | 0;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// GetSkillValue = pure trained + skill bonuses (racial / talent / equip MOD_SKILL). Cite: Player.h
|
|
570
|
+
// GetSkillValue; Unit.cpp GetWeaponSkillValue / GetDefenseSkillValue
|
|
571
|
+
export function combatSkillValueWithBonus(
|
|
572
|
+
map: CombatSkillMap | undefined,
|
|
573
|
+
skillId: number,
|
|
574
|
+
level: number,
|
|
575
|
+
bonus = 0,
|
|
576
|
+
): number {
|
|
577
|
+
if (!skillId && map != null) return 0;
|
|
578
|
+
const pure = combatSkillValue(map, skillId || COMBAT_SKILL.UNARMED, level);
|
|
579
|
+
return Math.max(0, pure + (bonus | 0));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/** equipMods key for a skill line (`skill_43` = swords). Defense also uses Stat.defense. */
|
|
583
|
+
export function equipModKeyForSkill(skillId: number): string {
|
|
584
|
+
return `skill_${skillId | 0}`;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/** Parse equipMods `skill_<id>` → skill id, or 0. */
|
|
588
|
+
export function skillIdFromEquipModKey(mod: string): number {
|
|
589
|
+
if (!mod || !mod.startsWith('skill_')) return 0;
|
|
590
|
+
const n = Number(mod.slice(6));
|
|
591
|
+
return Number.isFinite(n) && n > 0 ? n | 0 : 0;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/** One build per (meta, level, race, cls). Both writers (tryCombatSkillGain,
|
|
595
|
+
* raiseCombatSkillsToLevelCap) are copy-on-write, so a shared map is safe. */
|
|
596
|
+
const maxedByMeta = new WeakMap<CombatSkillMeta, Map<string, CombatSkillMap>>();
|
|
597
|
+
const maxedNoMeta = new Map<string, CombatSkillMap>();
|
|
598
|
+
|
|
599
|
+
// Max out every weapon and defense skill this race/class can learn at `level`, so a companion's
|
|
600
|
+
// attack table matches a kept-up character. Cached: the raceClass scan cost 53 ms per body.
|
|
601
|
+
export function grantMaxedCombatSkillsForRaceClass(
|
|
602
|
+
level: number,
|
|
603
|
+
meta?: CombatSkillMeta | null,
|
|
604
|
+
race?: number,
|
|
605
|
+
cls?: number,
|
|
606
|
+
): CombatSkillMap {
|
|
607
|
+
const key = `${level}|${race ?? -1}|${cls ?? -1}`;
|
|
608
|
+
let byKey = maxedNoMeta;
|
|
609
|
+
if (meta) {
|
|
610
|
+
const hit = maxedByMeta.get(meta);
|
|
611
|
+
if (hit) byKey = hit;
|
|
612
|
+
else maxedByMeta.set(meta, (byKey = new Map()));
|
|
613
|
+
}
|
|
614
|
+
const cached = byKey.get(key);
|
|
615
|
+
if (cached) return cached;
|
|
616
|
+
const built = buildMaxedCombatSkillsForRaceClass(level, meta, race, cls);
|
|
617
|
+
byKey.set(key, built);
|
|
618
|
+
return built;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function buildMaxedCombatSkillsForRaceClass(
|
|
622
|
+
level: number,
|
|
623
|
+
meta?: CombatSkillMeta | null,
|
|
624
|
+
race?: number,
|
|
625
|
+
cls?: number,
|
|
626
|
+
): CombatSkillMap {
|
|
627
|
+
const max = skillMaxForLevel(level);
|
|
628
|
+
const out: CombatSkillMap = {};
|
|
629
|
+
const candidates = new Set<number>([
|
|
630
|
+
...Object.values(COMBAT_SKILL),
|
|
631
|
+
253, // spear / assassination subclass skill
|
|
632
|
+
]);
|
|
633
|
+
// Also pick up any SkillRaceClassInfo weapon/armor rows for this race/class.
|
|
634
|
+
for (const row of meta?.raceClass ?? []) {
|
|
635
|
+
const id = row.skillId | 0;
|
|
636
|
+
if (!id) continue;
|
|
637
|
+
if (race != null && !raceClassMaskMatches(row.raceMask | 0, race)) continue;
|
|
638
|
+
if (cls != null && !raceClassMaskMatches(row.classMask | 0, cls)) continue;
|
|
639
|
+
if (level != null && ((row.reqLevel ?? 0) | 0) > level) continue;
|
|
640
|
+
candidates.add(id);
|
|
641
|
+
}
|
|
642
|
+
for (const id of candidates) {
|
|
643
|
+
if (race != null && cls != null && !raceClassCanLearnSkill(meta, id, race, cls, level)) {
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
if (isLanguageSkill(id)) continue;
|
|
647
|
+
if (id === SKILL_POISONS) continue;
|
|
648
|
+
// Professions live on Character.skills, not combatSkills.
|
|
649
|
+
const cat = meta?.categories?.[id];
|
|
650
|
+
if (cat === SKILL_CATEGORY.PROFESSION || cat === SKILL_CATEGORY.SECONDARY) continue;
|
|
651
|
+
if (isLevelRangeCombatSkill(id, meta)) {
|
|
652
|
+
out[id] = { current: max, max };
|
|
653
|
+
} else {
|
|
654
|
+
// Armor / fist mono proficiency — presence gate, not L×5.
|
|
655
|
+
out[id] = { current: 1, max: 1 };
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
// Universal combat baselines.
|
|
659
|
+
out[COMBAT_SKILL.DEFENSE] = { current: max, max };
|
|
660
|
+
out[COMBAT_SKILL.UNARMED] = { current: max, max };
|
|
661
|
+
return out;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Equip proficiency gate: a legacy save with no combatSkills map allows, an item with no skill
|
|
665
|
+
// line allows, and a skill value of 0 is missing proficiency. Cite: Player.cpp CanUseItem ~9756.
|
|
666
|
+
export function hasRequiredEquipSkill(
|
|
667
|
+
map: CombatSkillMap | undefined,
|
|
668
|
+
item: ItemDef | undefined | null,
|
|
669
|
+
level: number,
|
|
670
|
+
): boolean {
|
|
671
|
+
if (map == null) return true;
|
|
672
|
+
const skillId = skillIdForEquip(item);
|
|
673
|
+
if (!skillId || skillId === SKILL_FISHING) return true;
|
|
674
|
+
return combatSkillValue(map, skillId, level) > 0;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Full equip proficiency: the trained skill when tracked AND the SkillRaceClassInfo race/class/
|
|
678
|
+
// level fit — the gate that blocks mail and plate before 40, and shields for hunters, even legacy.
|
|
679
|
+
export function canEquipItemProficiency(
|
|
680
|
+
char: { combatSkills?: CombatSkillMap; level: number; race: number; cls: number },
|
|
681
|
+
item: ItemDef | undefined | null,
|
|
682
|
+
meta?: CombatSkillMeta | null,
|
|
683
|
+
): boolean {
|
|
684
|
+
if (!hasRequiredEquipSkill(char.combatSkills, item, char.level)) return false;
|
|
685
|
+
const skillId = skillIdForEquip(item);
|
|
686
|
+
if (!skillId || skillId === SKILL_FISHING) return true;
|
|
687
|
+
return raceClassCanLearnSkill(meta, skillId, char.race, char.cls, char.level);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Effective weapon skill for an attack. Feral / no-weapon forms use max for level (GetWeaponSkillValue
|
|
691
|
+
// IsNoWeaponShapeShift branch). Unarmed when no weapon skill id.
|
|
692
|
+
export function effectiveWeaponSkillValue(
|
|
693
|
+
map: CombatSkillMap | undefined,
|
|
694
|
+
skillId: number,
|
|
695
|
+
level: number,
|
|
696
|
+
opts?: { noWeaponForm?: boolean },
|
|
697
|
+
): number {
|
|
698
|
+
if (opts?.noWeaponForm) return skillMaxForLevel(level);
|
|
699
|
+
const id = skillId || COMBAT_SKILL.UNARMED;
|
|
700
|
+
return combatSkillValue(map, id, level);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Effective defense skill (pure trained value; gear defense added by callers). Cite: GetDefenseSkillValue
|
|
704
|
+
// pure skill; gear is separate ITEM_MOD_DEFENSE.
|
|
705
|
+
export function effectiveDefenseSkillValue(
|
|
706
|
+
map: CombatSkillMap | undefined,
|
|
707
|
+
level: number,
|
|
708
|
+
): number {
|
|
709
|
+
return combatSkillValue(map, COMBAT_SKILL.DEFENSE, level);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/** SetSkillStep-style grant from a skill step (SkillTiers). Cite: Player.cpp SetSkillStep ~5486 */
|
|
713
|
+
export function setCombatSkillStep(
|
|
714
|
+
map: CombatSkillMap,
|
|
715
|
+
skillId: number,
|
|
716
|
+
step: number,
|
|
717
|
+
level: number,
|
|
718
|
+
meta?: CombatSkillMeta | null,
|
|
719
|
+
race?: number,
|
|
720
|
+
cls?: number,
|
|
721
|
+
): CombatSkillMap {
|
|
722
|
+
const id = skillId | 0;
|
|
723
|
+
if (!id) return map;
|
|
724
|
+
if (step <= 0) {
|
|
725
|
+
if (!map[id]) return map;
|
|
726
|
+
const next = { ...map };
|
|
727
|
+
delete next[id];
|
|
728
|
+
return next;
|
|
729
|
+
}
|
|
730
|
+
const stepIndex = Math.max(0, (step | 0) - 1);
|
|
731
|
+
const rc = lookupRaceClass(meta, id, race, cls);
|
|
732
|
+
let max = 0;
|
|
733
|
+
if (rc?.skillTierId) {
|
|
734
|
+
max = meta?.tiers?.[rc.skillTierId]?.[stepIndex] ?? 0;
|
|
735
|
+
}
|
|
736
|
+
if (!max) {
|
|
737
|
+
// No tiers: mono 1/1 or level-range L×5.
|
|
738
|
+
const range = skillRangeType(id, meta);
|
|
739
|
+
if (range === 'level') max = skillMaxForLevel(level);
|
|
740
|
+
else max = 1;
|
|
741
|
+
}
|
|
742
|
+
const maxed = rc != null && (rc.flags & SKILL_FLAG_MAXIMIZED) !== 0;
|
|
743
|
+
const prev = map[id]?.current ?? 0;
|
|
744
|
+
const value = Math.max(1, maxed ? max : (prev > 0 ? prev : 1));
|
|
745
|
+
return { ...map, [id]: { current: Math.min(value, max), max } };
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Grant a combat skill if missing (UpdateSpellTrainedSkills LEVEL/MONO branches). Does not overwrite an
|
|
749
|
+
// already-known skill. Cite: Player.cpp UpdateSpellTrainedSkills ~5727–5765
|
|
750
|
+
export function grantCombatSkillIfMissing(
|
|
751
|
+
map: CombatSkillMap,
|
|
752
|
+
skillId: number,
|
|
753
|
+
level: number,
|
|
754
|
+
meta?: CombatSkillMeta | null,
|
|
755
|
+
race?: number,
|
|
756
|
+
cls?: number,
|
|
757
|
+
): CombatSkillMap {
|
|
758
|
+
const id = skillId | 0;
|
|
759
|
+
if (!id || map[id]) return map;
|
|
760
|
+
const range = skillRangeType(id, meta);
|
|
761
|
+
if (range === 'language') {
|
|
762
|
+
return { ...map, [id]: { current: 300, max: 300 } };
|
|
763
|
+
}
|
|
764
|
+
if (range === 'level') {
|
|
765
|
+
const max = skillMaxForLevel(level);
|
|
766
|
+
return { ...map, [id]: { current: id === SKILL_LOCKPICKING ? max : 1, max } };
|
|
767
|
+
}
|
|
768
|
+
if (range === 'mono' || range === 'rank') {
|
|
769
|
+
const rc = lookupRaceClass(meta, id, race, cls);
|
|
770
|
+
if (rc && (rc.flags & SKILL_FLAG_MAXIMIZED) !== 0) {
|
|
771
|
+
const max = skillMaxForLevel(level);
|
|
772
|
+
return { ...map, [id]: { current: max, max } };
|
|
773
|
+
}
|
|
774
|
+
return { ...map, [id]: { current: 1, max: 1 } };
|
|
775
|
+
}
|
|
776
|
+
return map;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// When a spell is learned, grant its linked combat skills: SpellLearnSkill → SetSkillStep, SLA
|
|
780
|
+
// learnOnGetSkill, and the POISONS / LOCKPICKING special case. Cite: Player.cpp ~5690.
|
|
781
|
+
export function applySpellTrainedSkills(
|
|
782
|
+
map: CombatSkillMap | undefined,
|
|
783
|
+
spellId: number,
|
|
784
|
+
level: number,
|
|
785
|
+
meta?: CombatSkillMeta | null,
|
|
786
|
+
race?: number,
|
|
787
|
+
cls?: number,
|
|
788
|
+
): CombatSkillMap | undefined {
|
|
789
|
+
if (map == null) return map; // legacy: no skill tracking
|
|
790
|
+
const sid = spellId | 0;
|
|
791
|
+
if (!sid || !meta) {
|
|
792
|
+
// Even without full meta, allow hardcoded proficiency spell grants from spellGrants-only meta.
|
|
793
|
+
}
|
|
794
|
+
let out = map;
|
|
795
|
+
|
|
796
|
+
const learn = meta?.spellLearnSkills?.[sid];
|
|
797
|
+
if (learn?.skill) {
|
|
798
|
+
out = setCombatSkillStep(out, learn.skill, learn.step || 1, level, meta, race, cls);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
const grantSkill = meta?.spellGrants?.[sid];
|
|
802
|
+
if (grantSkill) {
|
|
803
|
+
out = grantCombatSkillIfMissing(out, grantSkill, level, meta, race, cls);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Lockpicking: learning any SLA-bound spell grants the class skill if missing.
|
|
807
|
+
// Poisons (40) is a secondary profession on Character.skills, not combatSkills.
|
|
808
|
+
const abilities = meta?.spellAbilities?.[sid];
|
|
809
|
+
if (abilities?.length) {
|
|
810
|
+
for (const ab of abilities) {
|
|
811
|
+
const skillId = ab.skillId | 0;
|
|
812
|
+
if (skillId !== SKILL_LOCKPICKING) continue;
|
|
813
|
+
if (race != null && ab.raceMask && !raceClassMaskMatches(ab.raceMask | 0, race)) continue;
|
|
814
|
+
if (cls != null && ab.classMask && !raceClassMaskMatches(ab.classMask | 0, cls)) continue;
|
|
815
|
+
out = grantCombatSkillIfMissing(out, skillId, level, meta, race, cls);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
return maxLockpickingSkill(out, level);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Dependent spell ids from `spell_learn_spell` when learning `spellId`. Cite: Player.cpp addSpell ~3412
|
|
823
|
+
// SpellLearnSpellMapBounds
|
|
824
|
+
export function spellLearnDependents(
|
|
825
|
+
spellId: number,
|
|
826
|
+
meta?: CombatSkillMeta | null,
|
|
827
|
+
): number[] {
|
|
828
|
+
const sid = spellId | 0;
|
|
829
|
+
if (!sid || !meta?.spellLearnSpells) return [];
|
|
830
|
+
const list = meta.spellLearnSpells[sid];
|
|
831
|
+
return list?.length ? [...list] : [];
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Re-apply UpdateSpellTrainedSkills for every known spell, fixing characters that learned a
|
|
835
|
+
// proficiency spell before the skill grant was wired. Idempotent for already-known skills.
|
|
836
|
+
export function syncCombatSkillsFromKnownSpells(
|
|
837
|
+
map: CombatSkillMap | undefined,
|
|
838
|
+
knownSpellIds: readonly number[],
|
|
839
|
+
level: number,
|
|
840
|
+
meta?: CombatSkillMeta | null,
|
|
841
|
+
race?: number,
|
|
842
|
+
cls?: number,
|
|
843
|
+
): CombatSkillMap | undefined {
|
|
844
|
+
if (map == null) return map;
|
|
845
|
+
let out = map;
|
|
846
|
+
for (const id of knownSpellIds) {
|
|
847
|
+
const next = applySpellTrainedSkills(out, id, level, meta, race, cls);
|
|
848
|
+
if (next) out = next;
|
|
849
|
+
}
|
|
850
|
+
return out;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Product cheat: a trained Lockpicking line sits at L×5. Callers that open locks read this
|
|
854
|
+
// value — they must not invent a skill the character does not have.
|
|
855
|
+
export function maxLockpickingSkill(
|
|
856
|
+
map: CombatSkillMap | undefined,
|
|
857
|
+
level: number,
|
|
858
|
+
): CombatSkillMap | undefined {
|
|
859
|
+
if (!map) return map;
|
|
860
|
+
const cur = map[SKILL_LOCKPICKING];
|
|
861
|
+
if (!cur || cur.current <= 0) return map;
|
|
862
|
+
const max = skillMaxForLevel(level);
|
|
863
|
+
if (cur.current === max && cur.max === max) return map;
|
|
864
|
+
return { ...map, [SKILL_LOCKPICKING]: { current: max, max } };
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/** Display name for a combat skill id (SkillLine.Name when baked). */
|
|
868
|
+
export function combatSkillDisplayName(skillId: number, meta?: CombatSkillMeta | null): string {
|
|
869
|
+
const id = skillId | 0;
|
|
870
|
+
return meta?.skillNames?.[id] || `Skill ${id}`;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// Spells learned when a skill reaches a value (LearnSkillRewardedSpells), from the reverse of
|
|
874
|
+
// spellGrants and still unknown. Grants at skill present; req_skill_value needs richer meta.
|
|
875
|
+
export function skillRewardedSpellIds(
|
|
876
|
+
skillId: number,
|
|
877
|
+
currVal: number,
|
|
878
|
+
meta?: CombatSkillMeta | null,
|
|
879
|
+
): number[] {
|
|
880
|
+
if (!meta?.spellGrants || currVal <= 0) return [];
|
|
881
|
+
const id = skillId | 0;
|
|
882
|
+
const out: number[] = [];
|
|
883
|
+
for (const [spellStr, sk] of Object.entries(meta.spellGrants)) {
|
|
884
|
+
if ((sk | 0) === id) out.push(Number(spellStr));
|
|
885
|
+
}
|
|
886
|
+
return out;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// Chance (0..1) to gain a skill point this swing. Cite: Player.cpp UpdateCombatSkills ~5241 (piecewise
|
|
890
|
+
// log/quadratic + intellect weapon bonus).
|
|
891
|
+
export function combatSkillGainChance(
|
|
892
|
+
skillCurrent: number,
|
|
893
|
+
skillMax: number,
|
|
894
|
+
level: number,
|
|
895
|
+
defence: boolean,
|
|
896
|
+
intellect: number,
|
|
897
|
+
): number {
|
|
898
|
+
const room = skillMax - skillCurrent;
|
|
899
|
+
if (skillMax <= 0 || level <= 0 || skillCurrent >= skillMax || room <= 0) return 0;
|
|
900
|
+
|
|
901
|
+
const skillGapLogGrowth = 0.22 * (1.0 + 12.0 / level);
|
|
902
|
+
const levelCapScale = 1;
|
|
903
|
+
let baseChance: number;
|
|
904
|
+
if (room >= 7) {
|
|
905
|
+
// detLog, not Math.log: this chance is compared against a seeded roll every swing, so an
|
|
906
|
+
// engine-dependent last bit flips a skill-up and desyncs the peers (W1b).
|
|
907
|
+
baseChance = (7.0 / skillMax) * levelCapScale
|
|
908
|
+
+ skillGapLogGrowth * detLog((room + 5.0) / 12.0);
|
|
909
|
+
} else {
|
|
910
|
+
baseChance = (room * room) / (7.0 * skillMax) * levelCapScale;
|
|
911
|
+
}
|
|
912
|
+
baseChance = Math.min(1, Math.max(0, baseChance));
|
|
913
|
+
|
|
914
|
+
let intellectBonus = 0;
|
|
915
|
+
if (!defence) {
|
|
916
|
+
const maxIntellectBonus = 0.1;
|
|
917
|
+
const intellectMax = level <= 60 ? 750 : level <= 70 ? 1500 : level <= 80 ? 3000 : 6000;
|
|
918
|
+
const levelBracket = level <= 60 ? 60 : level <= 70 ? 70 : level <= 80 ? 80 : 255;
|
|
919
|
+
intellectBonus = maxIntellectBonus
|
|
920
|
+
* (intellect / intellectMax)
|
|
921
|
+
* (levelBracket / level);
|
|
922
|
+
intellectBonus = Math.min(maxIntellectBonus, Math.max(0, intellectBonus));
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
return Math.min(1, Math.max(0, baseChance + intellectBonus));
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
export type SkillGainRoll = () => number; // 0..1 uniform
|
|
929
|
+
|
|
930
|
+
// Attempt one combat skill gain (weapon or defense). Returns updated map + whether a point was gained. Pure
|
|
931
|
+
// except for roll(). Cite: UpdateCombatSkills → UpdateWeaponSkill / UpdateDefense (+1 default gain).
|
|
932
|
+
export function tryCombatSkillGain(
|
|
933
|
+
map: CombatSkillMap,
|
|
934
|
+
skillId: number,
|
|
935
|
+
level: number,
|
|
936
|
+
opts: {
|
|
937
|
+
defence: boolean;
|
|
938
|
+
intellect: number;
|
|
939
|
+
/** CONFIG_UINT32_SKILL_GAIN_WEAPON / DEFENSE default 1 */
|
|
940
|
+
gainAmount?: number;
|
|
941
|
+
roll: SkillGainRoll;
|
|
942
|
+
},
|
|
943
|
+
): { map: CombatSkillMap; gained: boolean } {
|
|
944
|
+
const id = skillId | 0;
|
|
945
|
+
if (!id || id === SKILL_FISHING) return { map, gained: false };
|
|
946
|
+
const s = map[id];
|
|
947
|
+
if (!s || s.max <= 0 || s.current >= s.max) return { map, gained: false };
|
|
948
|
+
|
|
949
|
+
const chance = combatSkillGainChance(s.current, s.max, level, opts.defence, opts.intellect);
|
|
950
|
+
if (chance <= 0 || opts.roll() >= chance) return { map, gained: false };
|
|
951
|
+
|
|
952
|
+
const gain = Math.max(1, opts.gainAmount ?? 1);
|
|
953
|
+
const next = Math.min(s.max, s.current + gain);
|
|
954
|
+
return {
|
|
955
|
+
map: { ...map, [id]: { current: next, max: s.max } },
|
|
956
|
+
gained: next > s.current,
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Carry a fight's skill gains onto the sheet: current is the higher of the two, the sheet keeps its
|
|
961
|
+
// own max (a level-up raised it while the session held the old cap). Cite: Player.cpp UpdateSkillsForLevel.
|
|
962
|
+
export function mergeCombatSkillGains(
|
|
963
|
+
sheet: CombatSkillMap | undefined,
|
|
964
|
+
gained: CombatSkillMap | undefined,
|
|
965
|
+
): CombatSkillMap | undefined {
|
|
966
|
+
if (!gained) return sheet;
|
|
967
|
+
if (!sheet) return cloneCombatSkills(gained);
|
|
968
|
+
let out = sheet;
|
|
969
|
+
for (const [key, g] of Object.entries(gained)) {
|
|
970
|
+
const id = Number(key);
|
|
971
|
+
if (!g) continue;
|
|
972
|
+
const have = out[id];
|
|
973
|
+
if (!have) {
|
|
974
|
+
if (out === sheet) out = { ...sheet };
|
|
975
|
+
out[id] = { current: g.current, max: g.max };
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
const current = Math.min(have.max, Math.max(have.current, g.current));
|
|
979
|
+
if (current === have.current) continue;
|
|
980
|
+
if (out === sheet) out = { ...sheet };
|
|
981
|
+
out[id] = { current, max: have.max };
|
|
982
|
+
}
|
|
983
|
+
return out;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/** Clone a skill map (shallow values). */
|
|
987
|
+
export function cloneCombatSkills(map: CombatSkillMap | undefined): CombatSkillMap | undefined {
|
|
988
|
+
if (!map) return undefined;
|
|
989
|
+
const out: CombatSkillMap = {};
|
|
990
|
+
for (const [k, v] of Object.entries(map)) {
|
|
991
|
+
if (v) out[Number(k)] = { current: v.current, max: v.max };
|
|
992
|
+
}
|
|
993
|
+
return out;
|
|
994
|
+
}
|