fix: allow explicit WoW Warrior off-hand swings

This commit is contained in:
warren authored and Codex (Root combat coordinator) committed 2026-10-15 09:26:01 -04:00
1 parent 9be6f54c52
commit 2f8cb8a510
2 files changed
+141 -6

No files matched your search

+32 -2
View File
@@ -462,6 +462,7 @@ import { inventoryItemUsableForCategory, normalizeInventory, type InventoryItem
import {
PLAYER_EQUIPMENT_OWNER_ID,
activeEquipmentStatsForClass,
classCanEquipItem,
equipInventoryItem,
normalizeEquipment,
unequipInventorySlot,
@@ -2416,6 +2417,33 @@ function playerEquippedMeleeWeapon(
return item?.weaponType ? item.stats.meleeWeapon : null;
}
function playerHasExplicitWoWWarriorDualWield(
state: Pick<CombatState, "classId" | "level" | "statRuleset" | "equipment" | "inventory">,
): boolean {
if (state.classId !== "warrior" || state.level < 20
|| normalizeCharacterStatRuleset(state.statRuleset, state.classId) !== "wow") return false;
const itemForSlot = (slot: "main-hand" | "off-hand"): InventoryItem | null => {
const assignedId = state.equipment[PLAYER_EQUIPMENT_OWNER_ID]?.[slot];
return assignedId ? state.inventory.find((item) => item.instanceId === assignedId) ?? null : null;
};
const mainHand = itemForSlot("main-hand");
const offHand = itemForSlot("off-hand");
const isClassLegalMeleeWeapon = (item: InventoryItem | null, allowedSlots: readonly string[]): boolean => Boolean(
item
&& allowedSlots.includes(item.inventorySlot)
&& item.armorType !== "shield"
&& item.weaponType
&& item.stats.meleeWeapon
&& classCanEquipItem(state.classId, item, { level: state.level })
);
// WoW Warrior spell 674 is learned at level 20. Only actual, legal one-hand
// assignments count; generated heirloom stats never grant a second swing.
return isClassLegalMeleeWeapon(mainHand, ["one-hand", "main-hand"])
&& isClassLegalMeleeWeapon(offHand, ["one-hand", "off-hand"]);
}
function playerEquippedRangedWeapon(
state: Pick<CombatState,
"classId" | "secondaryClassId" | "specializationId" | "gearRole" | "level" | "equipment" | "inventory"
@@ -24448,13 +24476,15 @@ export const useCombatStore = create<CombatState>((set, get) => ({
const nativeUnarmed = mainHandDisarmed && normalizeCharacterStatRuleset(state.statRuleset, state.classId) === "rom"
? nativeDisarmedMainHandAutoAttackProfile(deriveCharacterStats(state.classId, state.level, state.gearStats,
state.raceId, {}, state.secondaryClassId, state.gender, state.statRuleset).romNative) : undefined;
const explicitWarriorDualWield = playerHasExplicitWoWWarriorDualWield(state);
const offHandWeapon = state.classId === "rogue" || state.classId === "rom-rogue"
|| state.classId === "shaman" || state.classId === "death-knight"
|| state.classId === "shaman" || state.classId === "death-knight" || explicitWarriorDualWield
? playerEquippedMeleeWeapon(state, "off-hand")
: null;
const supportsPlayerOffhandSwings = state.classId === "rogue" || state.classId === "rom-rogue"
|| state.classId === "shaman"
|| (state.classId === "death-knight" && Boolean(offHandWeapon));
|| (state.classId === "death-knight" && Boolean(offHandWeapon))
|| explicitWarriorDualWield;
const mainHandWeapon = supportsPlayerOffhandSwings
? playerEquippedMeleeWeapon(state, "main-hand")
: null;