Commit Graph

11 Commits

Author SHA1 Message Date
Docker Build 999f7e94bd Paragon: narrow weapon bypass; cascade talent ranks; Savage Defense
* Weapon-narrow: replace blanket EquippedItemSubClassMask bypass with an
  explicit allowlist (IsParagonWeaponSubclassWildcardSpell, currently
  Maelstrom Weapon 51528 only). Applied at all three gates: Player::
  HasItemFitToSpellRequirements, Player::CheckAttackFitToAuraRequirement,
  and Aura::IsProcTriggeredOnEvent. Maelstrom Weapon still procs from any
  weapon for Paragon, but Hack and Slash / Sword / Mace Specialization
  remain correctly weapon-gated.
* Talent ability-rank cascade: TeachLevelGatedAbilityChainNoPanel +
  CascadeRanksForTalentLearnSpellEffects walk the SPELL_EFFECT_LEARN_SPELL
  chain a talent rank grants and learn each rank up to the player's level.
  Wired into HandleCommit (on talent purchase) and OnPlayerLevelChanged
  (on level-up). Fixes Mangle (and any future LEARN_SPELL talent) being
  stuck at rank 1 because Player::learnSkillRewardedSpells is intentionally
  disabled for Paragon's class skill lines.
* Riding-skill gate for flight forms (IsParagonSpellAllowedByRidingSkill):
  Flight Form (33943) requires Expert Riding (34090); Swift Flight Form
  (40120) requires Artisan Riding (34091). Applied in PanelLearnSpellChain
  and TeachLevelGatedAbilityChainNoPanel so the cascade can't push past a
  rank the player isn't trained for. Also backticks `rank` in the level-up
  query (MySQL reserved word).
* Savage Defense (62600) on the panel: the SpellData bake's blanket
  SPELL_ATTR0_PASSIVE filter dropped Savage Defense even though Druid
  trainer 33 sells it at level 40. Bake (in fractured-tooling) now carves
  out a small PASSIVE_TRAINER_ALLOWLIST and the regenerated
  paragon_spell_ae_cost.sql + 2026_05_11_05.sql migration surface it on
  the Druid Feral spell tab.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 19:09:25 -04:00
Docker Build 7c57abd69f Paragon: weapon-class subclass bypass for proc talents (Maelstrom Weapon any weapon)
Cross-class wildcard now also relaxes the EquippedItemSubClassMask
gate on weapon-class proc talents so e.g. Maelstrom Weapon procs
from any weapon a Paragon has equipped, not just the talent's stock
melee subset (axe / mace / staff / fist / dagger / 2H sword/axe/mace).

Three independent gates run in the proc chain; all three needed the
bypass for the proc to actually fire:

- Player::HasItemFitToSpellRequirements -- talent-attach check at
  item-equip / login time. Without this the passive talent aura
  never even applies for a Paragon wielding a non-stock weapon.
- Player::CheckAttackFitToAuraRequirement -- per-swing match the
  proc engine uses to decide whether attackType + weapon is
  compatible with the aura's EquippedItemClass / SubClassMask.
- Aura::IsProcTriggeredOnEvent (SpellAuras.cpp) -- per-event proc
  evaluator that calls Item::IsFitToSpellRequirements again,
  independently of the previous two. Was the proc-killing gate
  before this commit: talent attached, swing matched, but this
  evaluator returned 0 charges for any weapon outside the stock
  subclass mask, so no stack was ever applied.

All three bypasses are gated on:
- IsParagonWildcardCaller(this) (player class 12 + config flag
  Paragon.WildcardFamilyMatching = 1).
- spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON. ARMOR-class
  gates (shield) are deliberately left alone -- shield-required
  talents (Shield Specialization, Shield Block, etc.) still need
  an actual shield equipped.

Each bypass also requires *some* weapon to be in the relevant slot
(MAINHAND / OFFHAND / RANGED). Unarmed Paragons do not auto-activate
every weapon-gated talent in the game.

Net effect for Paragon characters with Maelstrom Weapon talented:
proc fires from any melee weapon -- 1H sword / polearm / spear /
fist / dagger / staff / 2H weapons / axes / maces. Stock Shamans
and every other non-Paragon class are unchanged.

Caveat (not addressed by this commit): the talent's stock ProcFlags
(0xC00014) only fire on melee swings + melee abilities. Ranged
auto-attacks (bow / gun / crossbow / wand) fire
PROC_FLAG_DONE_RANGED_AUTO_ATTACK (0x40), which the proc engine
never matches against this talent, so the new weapon-subclass
bypass is moot for those weapons. Adding ranged-auto-attack support
would require a Paragon-only ProcFlags expansion at the proc
engine layer; deferred until requested.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 18:19:42 -04:00
Docker Build e649402163 Paragon: cross-class talents + Warrior stance bypass + Mirror Image spellbook draw
Server-side cross-class wildcard pass for several talents that were
previously locked to a single SpellFamilyName, plus a server+client
Warrior stance bypass and a Paragon-aware Mirror Image rebuild that
mimics the owner's spellbook instead of stock Frostbolt/Fire Blast.

Talent expansions (Paragon owners only; stock classes unchanged):
- Cold Snap (11958): resets cooldown of any Frost-school spell.
- Nature's Swiftness (17116, 16188) + Predator's Swiftness (69369):
  instant-cast on any Nature-school spell.
- Vampiric Embrace (15286): leech-heals from any single-target
  Shadow-school spell.
- Fingers of Frost (44543/44545) + Frostbite (11071/12496/12497):
  proc from any Frost-school chill effect (DK Howling Blast / Icy
  Touch / Chains of Ice, Hunter Frost Trap, Shaman Frost Shock,
  cross-class chill auras via SPELL_AURA_MOD_DECREASE_SPEED).
- Maelstrom Weapon (53817): now also affects Mage Fireball (133),
  Frostbolt (116), and Arcane Blast (30451) at every rank, both
  for cast-time/cost spellmod and for stack consumption.

Warrior stance bypass:
- SpellInfo::CheckShapeshift returns SPELL_CAST_OK whenever a
  Paragon caster hits any Stances!=0 spell (no SpellFamilyName
  gate). Stock classes still see the regular form rules.
- Client side: patch-enUS-4.MPQ now zeroes Stances on every
  SPELLFAMILY_WARRIOR Spell.dbc row (105 spells) so the engine's
  pre-cast "Must be in Battle/Defensive/Berserker Stance" check
  no longer eats CMSG_CAST_SPELL packets for Paragons. Server
  bypass enforces the actual decision; stock Warriors still
  error mid-cast if they actually click while out of stance.
- patch-enUS-5.MPQ Lua tooltip post-processor recolors and
  appends "(Paragon: bypassed)" to "Requires *Stance*" lines on
  Warrior abilities, plus Paragon notes on Maelstrom Weapon and
  Mirror Image tooltips. Action-bar UseAction wrapper routes
  stance-gated Warrior spell clicks through CastSpellByName so
  the stance-zero DBC + server bypass actually run.

Mirror Image:
- npc_pet_mage_mirror_image rebuilds its spell list from the
  Paragon owner's spellbook on InitializeAI AND JustEngagedWith
  (the second pass + events.Reset clears any stale events the
  CasterAI base scheduler may have queued from stock 59637 /
  59638 entries before the rebuild ran).
- Curated filter keeps single-target damaging spells (instant,
  cast-time, or channeled) with a base cooldown <=10s, with the
  "damaging" definition expanded to include
  SPELL_EFFECT_TRIGGER_MISSILE and
  SPELL_AURA_PERIODIC_TRIGGER_SPELL so Arcane Missiles
  qualifies. Rejects passives, AoE, melee/ranged weapon strikes,
  item/reagent/stance/equip-gated, and lower spell ranks.
- UpdateAI picks a random spell from the curated list per cast
  and reschedules the next pick by the actually-cast spell's
  cast/channel duration + 750ms breather, so a 5s Arcane
  Missiles channel waits its full duration before re-rolling
  rather than visually looping across four images.

Helpers:
- Unit::IsParagonWildcardCaller / Unit::ParagonFamilyMatches
  used by Spell.cpp, SpellInfo.cpp, Player.cpp,
  SpellAuraEffects.cpp, and the spell scripts.
- SpellInfo::CheckShapeshift signature gains an optional caster
  pointer; all call sites updated.

SQL migrations under modules/mod-paragon/data/sql/db-world/updates/:
- 2026_05_11_01.sql  Vampiric Embrace spell_proc relax + script
                     gate (CheckProc enforces stock for non-Paragon).
- 2026_05_11_02.sql  Maelstrom Weapon spell_proc relax (initial,
                     superseded by _04 below for stack-consumption fix).
- 2026_05_11_03.sql  Fingers of Frost / Frostbite spell_proc relax
                     and spell_script_names binding.
- 2026_05_11_04.sql  Maelstrom Weapon spell_proc fixup: restore
                     SpellPhaseMask=1 (CAST) and AttributesMask=8
                     (REQ_SPELLMOD); previous _02 set 8/0 which
                     silently dropped every proc event.

Diagnostics from this debugging session demoted from LOG_INFO to
LOG_DEBUG (silent at default info level) so production logs stay
quiet but the probes remain available for reproducing future
regressions: pet_mage.cpp MirrorImage probe/kept/rebuild/init/
engage/cast lines and SpellInfo.cpp CheckShapeshift bypass line.

CLIENT-PATCHES.md updated to document the new Warrior stance DBC
patcher (_patch_spell_dbc_stances.py), the spell-tooltip post-
processor and stance UseAction wrapper in patch-enUS-5.MPQ, and
the Mirror Image / Maelstrom Weapon Paragon notes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 14:54:05 -04:00
Docker Build a1c9172beb Paragon cross-class family wildcard + Predatory Strikes proc
- CONFIG_PARAGON_WILDCARD_FAMILY + Paragon.WildcardFamilyMatching (reloadable)
- SpellInfo::IsAffected / IsAffectedBySpellMod(listenerOwner) for Paragon proc/mod wildcard
- SpellMgr::CanSpellTriggerProcOnEvent(procOwner) + Aura::IsProcTriggeredOnEvent wiring
- Player::IsAffectedBySpellmod passes listener for SpellMod wildcard
- ParagonFamilyMatches helper + Nourish / Shred-Maul bleed gate usage in Unit.cpp
- Spell::prepare: Paragon consumes 69369 for Nature spells <10s base cast (non-channeled)
- spell_paragon_predatory_strikes + SQL 2026_05_11_00.sql (spell_proc + spell_script_names)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 01:25:18 -04:00
Docker Build 8ad6a2aca3 Paragon: cascade guard for class skill lines + panel catalog backfill
The skill-line cascade in Player::learnSkillRewardedSpells re-fires from
_LoadSkills (every login), UpdateSkillsForLevel (every level-up),
UpdateSkillPro (every weapon-skill tick on a training dummy), and
SetSkill (first time a class skill is granted). Each pass re-grants
every SkillLineAbility-tagged class ability on the matching skill line,
which leaks Blood Presence / Death Coil / Death Grip / etc. back into
the spellbook within seconds even after the player intentionally
refunded them via the Character Advancement panel.

Path B fix: a 5-line guard at the top of learnSkillRewardedSpells skips
the cascade for class-category skill lines on CLASS_PARAGON characters.
mod-paragon already calls Player::learnSpell directly for the abilities
the player actually purchased (and their attached passives), so the
panel becomes the sole authority over class abilities. Profession,
weapon, language, and racial cascades stay enabled so recipe auto-learn,
weapon proficiencies, and racial perks still work.

Side effect: passives that previously rode along on the cascade
(Forceful Deflection on Blood Strike, Runic Focus on Icy Touch) must be
force-attached the same way Blood Plague / Frost Fever already are.
Extend kAttached and kFixup in Paragon_Essence.cpp to do that; existing
characters self-heal on next login.

Backfill paragon_spell_ae_cost for 42 spells newly exposed by the panel
after the ClassMask=0 filter was removed from the client catalog
generator (Lava Burst, Hex, Evocation, Kill Shot, Path of Frost,
Horn of Winter, Rune Strike, Raise Ally, Dark Command, etc.). Migration
is INSERT IGNORE so any per-spell tuning on existing rows is preserved.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 23:53:13 -04:00
Docker Build 49cb354133 mod-paragon: ignore item AllowableClass for class 12 (gear + glyphs)
Paragon is a classless concept layered on top of WotLK class data: stock items and class glyphs gate equip / vendor visibility / loot rolls / AH 'usable' filter via ItemTemplate.AllowableClass, which never has the class-12 bit (0x800). Bypassing the gate at the five enforcement sites lets Paragon equip any class-restricted item -- including class glyphs, since EffectApplyGlyph itself has no class check beyond the item gate. Race / level / proficiency / skill / required-spell checks still apply, so Paragon can't skip baseline progression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-09 16:07:01 -04:00
Docker Build 8a0da95ed2 mod-paragon: bypass talent DependsOn check for Paragon class
Player::LearnTalent enforces the column-arrow prereq (talentInfo->DependsOn)
even when called with command=true, so Character Advancement's commit path
was silently dropping any talent whose Talent.dbc row points to an unrelated
sibling -- e.g. Deep Wounds (depends on Improved Heroic Strike), Bloody
Vengeance (depends on Dark Conviction), Expose Weakness (depends on Lethal
Shots). Players spent points in the panel, hit Learn All, and the talent
silently never reached addTalent / OnPlayerLearnTalents -- the snapshot came
back without it and the client repainted the points as "unspent."

The Character Advancement panel gates progression via AE/TE essence cost,
not via the spec-tree column arrows, so the DependsOn rule doesn't apply to
class 12. Skip it for Paragon, mirroring the existing class-mask bypass a
few lines above.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-09 15:16:30 -04:00
Docker Build 203356aca8 Paragon: AE/TE currency, Character Advancement commit/reset, panel SQL
- mod-paragon: Paragon_Essence addon channel (PARAA), commit queue, resets,
  spell chain learn with passive child tracking, silence-window hints for
  cascade learns, trainer exemptions for pet/portal trainers
- SQL: character_paragon_panel_* tables, paragon_spell_ae_cost world data
- Core: Player Paragon class talent learn hook; Trainer skip for Paragon
  where appropriate
- Ignore local build-worldserver.log

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-08 21:43:01 -04:00
Dawnforger 22e79a4f32 fix(core): DK ToT off-hand strikes and Titan Grip for classless
- Item: 2H weapon subclass/inventory masks for strike spells (ToT / dual 2H).
- Player: allow SPELL_EFFECT_TITAN_GRIP through skill validation; clear TG on
  talent/spec reset only for warriors.
- PlayerStorage: sync m_canTitanGrip from spellbook before inventory load.
- Spell: treat Thassarian off-hand strike spells as OFF_ATTACK when DBC omits
  SPELL_ATTR3_REQUIRES_OFF_HAND_WEAPON.
2026-05-07 23:40:40 -05:00
Docker Build 8e4c8f57e4 Fractured: Paragon core hooks, mod-paragon, mod-ale, Docker build cap
- Track mod-paragon and mod-ale (un-ignore modules in .gitignore).
- Ship docker-compose.override.yml with CMAKE_EXTRA_OPTIONS for LuaJIT (mod-ale).
- Dockerfile: CBUILD_PARALLEL default to limit OOM under Docker/WSL2.
- Core: CLASS_PARAGON sticky combo points (DetachComboTarget), selection rebind,
  Spell::CheckPower rune path for multi-resource Paragon.
- spell_dk_death_rune: IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY) for
  Blood of the North / Reaping / DRM on Paragon.
- Remove temporary Paragon CheckPower logging.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-08 00:03:09 -04:00
Docker Build 72dd540b67 Local snapshot for Docker build (includes mod-ale)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-06 21:18:20 -04:00