diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6d09301..3d4219d 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7143,6 +7143,16 @@ bool Player::CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEf if (spellInfo->EquippedItemClass == -1) return true; + // Fractured / Paragon: cross-class wildcard relaxes weapon-class subclass + // gates on per-swing proc matches. A Paragon's talent list spans every + // class so a stock weapon-subclass mask (e.g. Maelstrom Weapon's + // axe/mace/staff/fist/dagger restriction) excludes weapons the player + // can legitimately wield. Accept any equipped weapon in attackType slot + // when listener is a Paragon AND the spell gates on ITEM_CLASS_WEAPON; + // ITEM_CLASS_ARMOR (shield) gates still enforce the original mask. + if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && IsParagonWildcardCaller(this)) + return GetWeaponForAttack(attackType, true) != nullptr; + Item* item = GetWeaponForAttack(attackType, true); if (!item || !item->IsFitToSpellRequirements(spellInfo)) return false; @@ -12581,6 +12591,27 @@ bool Player::HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item cons if (spellInfo->EquippedItemClass < 0) return true; + // Fractured / Paragon: cross-class wildcard relaxes weapon-class subclass + // gates so passive talent auras (e.g. Maelstrom Weapon talents 51528-51532) + // attach for any equipped weapon, not just the talent's restrictive + // subclass mask. Mirrors CheckAttackFitToAuraRequirement so per-swing + // proc match agrees with talent-attach time. Still requires *some* weapon + // to be equipped (otherwise unarmed Paragons would auto-activate every + // weapon-gated talent in the game). ITEM_CLASS_ARMOR (shield) is left + // alone -- shield-gated talents still need an actual shield. + if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && IsParagonWildcardCaller(this)) + { + for (uint8 i = EQUIPMENT_SLOT_MAINHAND; i < EQUIPMENT_SLOT_TABARD; ++i) + if (Item const* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i)) + if (item != ignoreItem) + if (ItemTemplate const* proto = item->GetTemplate()) + if (proto->Class == ITEM_CLASS_WEAPON) + return true; + // No weapon equipped at all -- fall through to stock logic, which + // returns false for passive talent auras (correct: an unarmed + // Paragon shouldn't have weapon talents active). + } + // scan other equipped items for same requirements (mostly 2 daggers/etc) // for optimize check 2 used cases only switch (spellInfo->EquippedItemClass) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 5398ca5..97c8457 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2251,8 +2251,26 @@ uint8 Aura::GetProcEffectMask(AuraApplication* aurApp, ProcEventInfo& eventInfo, item = target->ToPlayer()->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); } - if (!item || item->IsBroken() || !item->IsFitToSpellRequirements(GetSpellInfo())) + if (!item || item->IsBroken()) return 0; + if (!item->IsFitToSpellRequirements(GetSpellInfo())) + { + // Fractured / Paragon: cross-class wildcard relaxes weapon- + // class subclass gates on per-event proc evaluation. This + // mirrors Player::CheckAttackFitToAuraRequirement and + // Player::HasItemFitToSpellRequirements -- without this + // third bypass, the talent attaches (HasItemFit lets it), + // the per-swing match accepts the weapon (CheckAttackFit + // lets it), but IsProcTriggeredOnEvent still kills the + // proc here for any weapon outside the talent's stock + // subclass mask (e.g. Maelstrom Weapon on a Paragon + // wielding a 1H sword or polearm). Restricted to + // ITEM_CLASS_WEAPON so shield-gated talents still need + // an actual shield. + if (!(GetSpellInfo()->EquippedItemClass == ITEM_CLASS_WEAPON + && IsParagonWildcardCaller(target))) + return 0; + } } }