Paragon: expand IsClass hooks and addon pet talent reset
Broaden OnPlayerIsClass for CLASS_CONTEXT_ABILITY, pet/charm/equip contexts; add PARAA C RESET PET TALENTS handler. Update CLIENT-PATCHES.md for patch-enUS-5/6 and PARAA. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,14 +14,16 @@ This file is the table of contents and install guide.
|
|||||||
| Artifact | Size | Purpose |
|
| Artifact | Size | Purpose |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `patch-enUS-4.MPQ` | ~5 MB | DBC + GlueXML bake. Adds `CLASS_PARAGON` (id 12), the character-create slot, glue strings, game-table DBCs, and a patched `Spell.dbc`: **(1)** `RuneCostID` zeroed on every rune-cost spell so non–Death Knight clients still send DK casts (rune costs are shown via `RuneFrame.lua`); **(2)** `Reagent[]` / `ReagentCount[]` zeroed on every spell whose `SpellFamilyName` is non-zero (all class abilities), while profession crafts (`SpellFamilyName == 0`) keep their materials. Both edits mirror server load-time corrections so client preflight and server validation stay aligned. Required for character creation as Paragon to even show up. |
|
| `patch-enUS-4.MPQ` | ~5 MB | DBC + GlueXML bake. Adds `CLASS_PARAGON` (id 12), the character-create slot, glue strings, game-table DBCs, and a patched `Spell.dbc`: **(1)** `RuneCostID` zeroed on every rune-cost spell so non–Death Knight clients still send DK casts (rune costs are shown via `RuneFrame.lua`); **(2)** `Reagent[]` / `ReagentCount[]` zeroed on every spell whose `SpellFamilyName` is non-zero (all class abilities), while profession crafts (`SpellFamilyName == 0`) keep their materials. Both edits mirror server load-time corrections so client preflight and server validation stay aligned. Required for character creation as Paragon to even show up. |
|
||||||
| `patch-enUS-5.MPQ` | ~50 KB | FrameXML overrides. Replaces stock `PlayerFrame.lua` / `RuneFrame.lua` / `ComboFrame.lua` / `UnitFrame.lua` / `SpellBookFrame.lua` + `SpellBookFrame.xml` with Paragon-aware versions: rune simulator, combo-point simulator, server-authoritative resource sync over the `PARAA` addon channel, action-button usability + click guards, an expanded spellbook (higher `MAX_SPELLS`, 24 skill-line tabs instead of stock 8) so all-class spells render, Paragon stat tooltips on the character sheet, and a tooltip post-processor that appends ", Paragon" to the "Classes:" line on class-restricted gear / glyphs (the server bypasses `AllowableClass` for class 12, but the engine paints the line red and omits Paragon — the Lua hook recolors it green and adds the name so the player can tell it's wearable). The paper-doll **ammo slot** follows stock visibility rules (shown for hunters / ranged weapons; hidden when `UnitHasRelicSlot` applies). |
|
| `patch-enUS-5.MPQ` | ~57 KB | FrameXML overrides. Replaces stock `PlayerFrame.lua` / `RuneFrame.lua` / `ComboFrame.lua` / `UnitFrame.lua` / `SpellBookFrame.lua` + `SpellBookFrame.xml` with Paragon-aware versions: rune simulator, combo-point simulator, server-authoritative resource sync over the `PARAA` addon channel, action-button usability + click guards, an expanded spellbook (higher `MAX_SPELLS`, 24 skill-line tabs instead of stock 8) so all-class spells render, Paragon stat tooltips on the character sheet (including filtering duplicate “attack power from strength” lines so the paper doll matches server AP), a tooltip post-processor that appends ", Paragon" to the "Classes:" line on class-restricted gear / glyphs (the server bypasses `AllowableClass` for class 12, but the engine paints the line red and omits Paragon — the Lua hook recolors it green and adds the name so the player can tell it's wearable), and **PetFrame** re-anchored so the **pet unit frame sits below the rune row** for Paragon (stock layout had runes overlapping the pet portrait). The paper-doll **ammo slot** follows stock visibility rules (shown for hunters / ranged weapons; hidden when `UnitHasRelicSlot` applies). |
|
||||||
| `patch-enUS-6.MPQ` | ~160 KB | The `ParagonAdvancement` addon. Replaces the talent pane (`N` key) for Paragon characters with the Character Advancement panel: per-class spell tabs, talent grid, Overview/Search tabs, AE/TE currency, commit / reset / preview, login-time toast suppression. |
|
| `patch-enUS-6.MPQ` | ~123 KB | The `ParagonAdvancement` addon. Replaces the talent pane (`N` key) for Paragon characters with the Character Advancement panel: per-class spell tabs, talent grid, Overview/Search tabs, AE/TE currency, commit / reset / preview, login-time toast suppression, a **PETS** tab with live hunter pet talent trees (preview learn, no TE/AE cost), a dedicated **Reset Pet Talents** control (server `PARAA` `C RESET PET TALENTS` — instant, no gold, no confirmation; requires matching worldserver), and bottom-row **Reset all Abilities / Reset Build / Reset all Talents** disabled while on the PETS tab so those paths cannot dismiss the pet or unlearn Tame Beast. |
|
||||||
| `Wow.exe` | ~7.5 MB | 3.3.5a (build 12340) client byte-patched to skip the MPQ signature check so custom `patch-enUS-N.MPQ` files load. Diff against stock is a few bytes; everything else is unchanged. |
|
| `Wow.exe` | ~7.5 MB | 3.3.5a (build 12340) client byte-patched to skip the MPQ signature check so custom `patch-enUS-N.MPQ` files load. Diff against stock is a few bytes; everything else is unchanged. |
|
||||||
|
|
||||||
Server and client work as a pair: the addon talks to `mod-paragon` on the
|
Server and client work as a pair: the addon talks to `mod-paragon` on the
|
||||||
worldserver via `WHISPER` addon-channel messages with the `PARAA` prefix
|
worldserver via `WHISPER` addon-channel messages with the `PARAA` prefix
|
||||||
(currency push, spell/talent snapshot, commit, combo points, rune
|
(currency push, spell/talent snapshot, commit, combo points, rune
|
||||||
cooldowns, learn-toast silence window). Mismatched versions usually
|
cooldowns, learn-toast silence window, and **`C RESET PET TALENTS`**
|
||||||
|
for hunter pet talent resets from the Character Advancement PETS tab).
|
||||||
|
Mismatched versions usually
|
||||||
manifest as the panel rendering blank or AE/TE reading 0/0.
|
manifest as the panel rendering blank or AE/TE reading 0/0.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
#include "CommandScript.h"
|
#include "CommandScript.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "Pet.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "RBAC.h"
|
#include "RBAC.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
@@ -1689,6 +1690,10 @@ public:
|
|||||||
// "Q SNAPSHOT" -- push R SPELLS and R TALENTS for Overview
|
// "Q SNAPSHOT" -- push R SPELLS and R TALENTS for Overview
|
||||||
// "C COMMIT s:... t:..." -- apply pending learns from the panel
|
// "C COMMIT s:... t:..." -- apply pending learns from the panel
|
||||||
// "C RESET ABILITIES" / "C RESET TALENTS" / "C RESET ALL" / "C RESET EVERYTHING"
|
// "C RESET ABILITIES" / "C RESET TALENTS" / "C RESET ALL" / "C RESET EVERYTHING"
|
||||||
|
// "C RESET PET TALENTS" -- free + instant pet talent reset (no popup,
|
||||||
|
// no gold). Routes to Player::ResetPetTalents
|
||||||
|
// which itself calls Pet::resetTalents and
|
||||||
|
// refreshes the talent points.
|
||||||
void OnPlayerBeforeSendChatMessage(Player* player, uint32& /*type*/, uint32& lang, std::string& msg) override
|
void OnPlayerBeforeSendChatMessage(Player* player, uint32& /*type*/, uint32& lang, std::string& msg) override
|
||||||
{
|
{
|
||||||
if (!player || player->getClass() != CLASS_PARAGON)
|
if (!player || player->getClass() != CLASS_PARAGON)
|
||||||
@@ -1765,6 +1770,29 @@ public:
|
|||||||
SendAddonMessage(player, "R ERR " + err);
|
SendAddonMessage(player, "R ERR " + err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (body == "C RESET PET TALENTS")
|
||||||
|
{
|
||||||
|
// Pet talent reset: deliberately bypasses the engine's
|
||||||
|
// gold-cost confirmation flow. Player::ResetPetTalents
|
||||||
|
// wraps Pet::resetTalents (which only refunds and unlearns;
|
||||||
|
// does NOT charge gold or dismiss the pet) and re-sends the
|
||||||
|
// talent UI to the client. Pre-conditions:
|
||||||
|
// - the player must own a HUNTER_PET (the only pet kind
|
||||||
|
// with a talent tree in 3.3.5)
|
||||||
|
// - the pet must have spent at least 1 talent point
|
||||||
|
// If either fails Player::ResetPetTalents returns silently;
|
||||||
|
// we ack with R OK so the client UI can refresh either way.
|
||||||
|
Pet* pet = player->GetPet();
|
||||||
|
if (!pet || pet->getPetType() != HUNTER_PET)
|
||||||
|
{
|
||||||
|
SendAddonMessage(player,
|
||||||
|
"R ERR No active hunter pet to reset.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player->ResetPetTalents();
|
||||||
|
SendAddonMessage(player, "R OK PET TALENTS RESET");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 /*talentRank*/, uint32 /*spellid*/) override
|
void OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 /*talentRank*/, uint32 /*spellid*/) override
|
||||||
|
|||||||
@@ -7,9 +7,12 @@
|
|||||||
|
|
||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "Creature.h"
|
||||||
|
#include "CreatureData.h"
|
||||||
#include "GameTime.h"
|
#include "GameTime.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "ObjectGuid.h"
|
#include "ObjectGuid.h"
|
||||||
|
#include "Pet.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
@@ -44,43 +47,142 @@ public:
|
|||||||
if (!player || player->getClass() != CLASS_PARAGON)
|
if (!player || player->getClass() != CLASS_PARAGON)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
// Death Knight rune / runic power ability stack (narrow on purpose).
|
// ============================================================
|
||||||
if (unitClass == CLASS_DEATH_KNIGHT && context == CLASS_CONTEXT_ABILITY)
|
// Ability stack -- claim ALL nine vanilla classes.
|
||||||
|
// ============================================================
|
||||||
|
// CLASS_CONTEXT_ABILITY is read by every class-specific spell
|
||||||
|
// gate in core / scripts: DK rune mechanics (Spell.cpp,
|
||||||
|
// SpellEffects.cpp, spell_dk.cpp, SpellAuraEffects.cpp),
|
||||||
|
// Warrior Titan's Grip / Bladestorm (Player.cpp 3783, 15432,
|
||||||
|
// PlayerUpdates.cpp 1547), Paladin Rebuke (Player.cpp 15441),
|
||||||
|
// Shaman dual-wield bookkeeping (Player.cpp 5028), Hunter pet
|
||||||
|
// / Hunter's Mark gates (spell_item.cpp 3718), Druid Insect
|
||||||
|
// Swarm / Wild Growth (SpellAuraEffects.cpp 2153, 2232),
|
||||||
|
// Priest Spirit of Redemption out-of-bounds check (Unit.cpp
|
||||||
|
// 14238), Rogue pickpocketing (LootHandler.cpp 86/165/385,
|
||||||
|
// Vehicle.cpp 80). Paragon learns abilities from every class
|
||||||
|
// through Character Advancement, so claiming all of them lets
|
||||||
|
// every gated spell script execute its class-specific branch
|
||||||
|
// for our players. The only downside is double-pathed scripts
|
||||||
|
// (e.g. a spell with both warrior and rogue branches) will
|
||||||
|
// pick whichever the script tests first -- acceptable.
|
||||||
|
if (context == CLASS_CONTEXT_ABILITY)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Warrior ability stack: enables warrior-spec ability gates anywhere
|
// ============================================================
|
||||||
// they're checked. None of the currently-traced sites in core/scripts
|
// Reactive melee states.
|
||||||
// gate on (CLASS_WARRIOR, CLASS_CONTEXT_ABILITY), so this is a safe
|
// ============================================================
|
||||||
// forward-compatible claim. Rage generation itself is gated on
|
// Warrior dodge -> AURA_STATE_DEFENSE (Overpower window).
|
||||||
// HasActivePowerType(POWER_RAGE) and is wired below.
|
// Hunter parry -> AURA_STATE_HUNTER_PARRY (Counterattack).
|
||||||
if (unitClass == CLASS_WARRIOR && context == CLASS_CONTEXT_ABILITY)
|
// We intentionally do NOT claim CLASS_ROGUE here:
|
||||||
return true;
|
// Unit::ProcDamageAndSpellFor (Unit.cpp 12824) skips the
|
||||||
|
// generic AURA_STATE_DEFENSE update on dodge for rogues so
|
||||||
// Reactive melee states: Overpower-on-dodge (warrior), Counterattack window (hunter).
|
// Riposte can take over. Claiming rogue would silently kill
|
||||||
// We intentionally do NOT claim CLASS_ROGUE here: that context skips the generic
|
// Overpower for Paragon, and Riposte already works for us via
|
||||||
// AURA_STATE_DEFENSE update on dodge (Riposte path) in Unit::ProcDamageAndSpellFor.
|
// the warrior-style state we already grant.
|
||||||
if (context == CLASS_CONTEXT_ABILITY_REACTIVE)
|
if (context == CLASS_CONTEXT_ABILITY_REACTIVE)
|
||||||
{
|
{
|
||||||
if (unitClass == CLASS_WARRIOR || unitClass == CLASS_HUNTER)
|
if (unitClass == CLASS_WARRIOR || unitClass == CLASS_HUNTER)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unified relic / ranged slot for class 12.
|
// ============================================================
|
||||||
// ----------------------------------------------------------------
|
// Pet ownership contexts.
|
||||||
// CLASS_CONTEXT_EQUIP_RELIC is read in exactly two places in core
|
// ============================================================
|
||||||
// (PlayerStorage.cpp): FindEquipSlot's INVTYPE_RELIC switch, which
|
// CLASS_CONTEXT_PET is read by Pet::AddToWorld, Pet::CreateBase
|
||||||
// routes Librams/Idols/Totems/Misc/Sigils into EQUIPMENT_SLOT_RANGED
|
// AtCreatureInfo, Pet::InitStatsForLevel (twice -- the
|
||||||
// for the matching class only, and CanEquipUniqueItem's per-subclass
|
// MAX_PET_TYPE bootstrap branch and the per-class attack-time
|
||||||
// proficiency gate. By claiming this context for paladin/druid/
|
// scaling), Pet::IsPermanentPetFor, Player::SummonPet,
|
||||||
// shaman/warlock/dk we let Paragon drop any of those relics into the
|
// Player::CanResummonPet, Spell::EffectTameCreature,
|
||||||
// ranged slot exactly the same way each native class does, with no
|
// SpellEffects.cpp (CreateTamedPet debug effects, Eyes of the
|
||||||
// core patch and no other side effects (the constant is not read
|
// Beast), spell_generic.cpp 1760 (charm-as-pet conversion),
|
||||||
// anywhere else in the codebase).
|
// and PlayerGossip.cpp's hunter stable check.
|
||||||
//
|
//
|
||||||
// Bows/guns/crossbows already equip via the regular
|
// The cleanest disambiguation is by the *active pet's* shape:
|
||||||
// INVTYPE_RANGED/RANGEDRIGHT routing -- weapon proficiencies for
|
// HUNTER_PET -> hunter (beast tame)
|
||||||
// class 12 are seeded by the Paragon proficiency SQL migrations, so
|
// SUMMON_PET + DEMON type -> warlock (Imp/VW/Succ/...)
|
||||||
// they pass the GetSkillValue check in CanEquipUniqueItem.
|
// SUMMON_PET + UNDEAD type -> DK ghoul / Army of Dead
|
||||||
|
// SUMMON_PET + ELEMENTAL type -> mage water / shaman fire
|
||||||
|
// For HUNTER specifically the no-pet case is also claimed so
|
||||||
|
// Tame Beast's EffectTameCreature gate passes during cast.
|
||||||
|
if (context == CLASS_CONTEXT_PET)
|
||||||
|
{
|
||||||
|
Pet const* activePet = const_cast<Player*>(player)->GetPet();
|
||||||
|
|
||||||
|
// Hunter beast: claim during taming OR when a HUNTER_PET is
|
||||||
|
// already active. This is what makes Tame Beast / Call Pet
|
||||||
|
// / pet stable / Counterattack pet aura feedback work.
|
||||||
|
if (unitClass == CLASS_HUNTER)
|
||||||
|
{
|
||||||
|
if (!activePet || activePet->getPetType() == HUNTER_PET)
|
||||||
|
return true;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other classes only claim when an active SUMMON_PET is
|
||||||
|
// present. We then disambiguate by the creature's type
|
||||||
|
// because warlock / DK / mage / shaman all use SUMMON_PET.
|
||||||
|
if (!activePet || activePet->getPetType() != SUMMON_PET)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
CreatureTemplate const* tmpl = activePet->GetCreatureTemplate();
|
||||||
|
if (!tmpl)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
switch (unitClass)
|
||||||
|
{
|
||||||
|
case CLASS_WARLOCK:
|
||||||
|
// Drives Master Demonologist / Demonic Knowledge /
|
||||||
|
// Demonic Pact propagation, last-pet-spell tracking
|
||||||
|
// (Pet.cpp 112), and IsPermanentPetFor (Pet.cpp
|
||||||
|
// 2288) so demon pets persist across logins.
|
||||||
|
if (tmpl->type == CREATURE_TYPE_DEMON)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case CLASS_DEATH_KNIGHT:
|
||||||
|
// Risen Ghoul + Army of the Dead. Player.cpp 14354
|
||||||
|
// and Pet.cpp 243 / 1046 / 2290 read this; without
|
||||||
|
// it the ghoul is invisible to the owner mid-load
|
||||||
|
// and ScriptedAI hooks on the ghoul mis-route.
|
||||||
|
if (tmpl->type == CREATURE_TYPE_UNDEAD)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case CLASS_MAGE:
|
||||||
|
// Glyph-of-Eternal-Water permanent Water Elemental
|
||||||
|
// (entry 510, 37994). Used by Pet.cpp 1047/2292.
|
||||||
|
if (tmpl->type == CREATURE_TYPE_ELEMENTAL)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case CLASS_SHAMAN:
|
||||||
|
// Fire Elemental / Earth Elemental. The base
|
||||||
|
// engine spawns these as creatures rather than
|
||||||
|
// proper Pet instances in most code paths, so the
|
||||||
|
// claim mostly matters for the Pet.cpp 1045 stat
|
||||||
|
// bootstrap when one is loaded as a SUMMON_PET.
|
||||||
|
if (tmpl->type == CREATURE_TYPE_ELEMENTAL)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warlock pet-charm context (Enslave Demon -- Unit.cpp 14828,
|
||||||
|
// 14894, 15025). Without this claim, charming a demon as a
|
||||||
|
// Paragon doesn't get the warlock-flavor charm semantics
|
||||||
|
// (faction-set-on-charm, action-bar layout, charm-break logic).
|
||||||
|
if (unitClass == CLASS_WARLOCK && context == CLASS_CONTEXT_PET_CHARM)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Equipment contexts.
|
||||||
|
// ============================================================
|
||||||
|
// CLASS_CONTEXT_EQUIP_RELIC: PlayerStorage.cpp 224-240 +
|
||||||
|
// 2475-2493. Routes Librams/Idols/Totems/Misc/Sigils into
|
||||||
|
// EQUIPMENT_SLOT_RANGED for the matching class. Claim every
|
||||||
|
// relic-bearing class so a Paragon can drop any of them into
|
||||||
|
// the ranged slot.
|
||||||
if (context == CLASS_CONTEXT_EQUIP_RELIC)
|
if (context == CLASS_CONTEXT_EQUIP_RELIC)
|
||||||
{
|
{
|
||||||
switch (unitClass)
|
switch (unitClass)
|
||||||
@@ -96,6 +198,67 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CLASS_CONTEXT_EQUIP_ARMOR_CLASS: PlayerStorage.cpp 2326,
|
||||||
|
// 2330, 2503-2523. At level 40 each class auto-learns its
|
||||||
|
// top armor proficiency. Paragon should pick up plate (via
|
||||||
|
// paladin/DK), shields (paladin/warrior/shaman), mail
|
||||||
|
// (hunter/shaman), and leather (rogue) so the level-40 train
|
||||||
|
// event grants Paragon full proficiency and we don't have to
|
||||||
|
// hand-curate it through the Paragon proficiency SQL.
|
||||||
|
if (context == CLASS_CONTEXT_EQUIP_ARMOR_CLASS)
|
||||||
|
{
|
||||||
|
switch (unitClass)
|
||||||
|
{
|
||||||
|
case CLASS_PALADIN:
|
||||||
|
case CLASS_WARRIOR:
|
||||||
|
case CLASS_DEATH_KNIGHT:
|
||||||
|
case CLASS_HUNTER:
|
||||||
|
case CLASS_SHAMAN:
|
||||||
|
case CLASS_DRUID:
|
||||||
|
case CLASS_ROGUE:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLASS_CONTEXT_EQUIP_SHIELDS: PlayerStorage.cpp 2467-2469.
|
||||||
|
// Lets a Paragon equip shields without a paladin/warrior/
|
||||||
|
// shaman skill gate.
|
||||||
|
if (context == CLASS_CONTEXT_EQUIP_SHIELDS)
|
||||||
|
{
|
||||||
|
switch (unitClass)
|
||||||
|
{
|
||||||
|
case CLASS_PALADIN:
|
||||||
|
case CLASS_WARRIOR:
|
||||||
|
case CLASS_SHAMAN:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLASS_CONTEXT_WEAPON_SWAP: PlayerStorage.cpp 1920, 2838 --
|
||||||
|
// rogue uses cooldown spell 6123 instead of 6119 on weapon
|
||||||
|
// swap (Quick Draw / Combat Potency interactions). Claim
|
||||||
|
// rogue so Paragon picks up the same cooldown spell.
|
||||||
|
if (context == CLASS_CONTEXT_WEAPON_SWAP && unitClass == CLASS_ROGUE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Contexts we DELIBERATELY DO NOT claim:
|
||||||
|
// ============================================================
|
||||||
|
// CLASS_CONTEXT_STATS -- Paragon has its own STR/AGI->AP and
|
||||||
|
// INT/SPI->SP curves wired in StatSystem.cpp's CLASS_PARAGON
|
||||||
|
// branch (level*2 + STR + AGI - 20 etc.). Claiming any
|
||||||
|
// vanilla class here would override our curves with theirs.
|
||||||
|
//
|
||||||
|
// CLASS_CONTEXT_INIT, _TELEPORT, _QUEST, _TAXI, _SKILL,
|
||||||
|
// _GRAVEYARD, _CLASS_TRAINER, _TALENT_POINT_CALC -- all
|
||||||
|
// used by DK Ebon Hold / druid Moonglade starting-zone
|
||||||
|
// scripts. Paragon doesn't go through those zones and we
|
||||||
|
// don't want our players bound to Acherus or trapped in
|
||||||
|
// the DK starting quest gates.
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user