Stock 3.3.5 hardcodes per-class stat -> AP/SP formulas in
Player::UpdateAttackPowerAndDamage and Unit::SpellBase{Damage,Healing}BonusDone,
so class 12 fell into the default branches and ended up with 0 AP and 0 SP
regardless of STR / AGI / INT / SPI. The character sheet, combat log, and
ability damage all reflected this, and Mental Quickness-style AP->SP plumbing
silently no-oped on Paragon characters.
Add Paragon-specific branches in core (no PlayerScript hooks - those caused
SIGSEGVs when the new mid-list enum entry shifted later hook ordinals and
broke vtable dispatch):
- StatSystem.cpp: melee and ranged AP = level*2 + STR + AGI - 20, mirroring
the formula the UI patch already advertises in tooltips.
- Unit.cpp: intrinsic SP = level*2 + INT + SPI - 20 (clamped >=0),
added symmetrically to SpellBaseDamageBonusDone and
SpellBaseHealingBonusDone so the single advertised Spell Power value the
character sheet renders matches what spells actually use in combat.
Drop the now-unused UnitDefines.h include in Paragon_SC.cpp - it was only
needed by the AP PlayerScript hook that was rolled back in favor of the
core change.
Co-authored-by: Cursor <cursoragent@cursor.com>
mod-paragon
Server-side support module for the custom CLASS_PARAGON (id 12).
What it does today
Hooks Player::IsClass / Player::HasActivePowerType so Paragon
inherits Death Knight ability mechanics where it matters:
- Rune system:
InitRunes, rune cooldown tick, runic power regen,Spell::CheckRuneCost/Spell::TakeRunePower,SMSG_RESYNC_RUNEScast flags, combat exit grace reset. - DK ability scripts:
spell_dk_*,MUST_BE_DEATH_KNIGHTcast result, DK aura effects.
It is intentionally narrow: the hook only fires for
(realClass == PARAGON, queriedClass == DEATH_KNIGHT, context == CLASS_CONTEXT_ABILITY).
Other DK-flavored contexts (Ebon Hold teleport gating, heroic start
level, DK-only taxi mount, talent point math on Ebon Hold, etc.) keep
their normal behavior for Paragon.
HasActivePowerType additionally claims POWER_RUNIC_POWER and
POWER_RUNE for Paragon, which keeps the rune pool sized correctly
in Player::InitStatsForLevel even if Paragon's primary power type is
later switched away from runic power.
Building
Auto-detected by modules/CMakeLists.txt (GetModuleSourceList globs
every subdirectory). No additional CMake plumbing is needed; rebuild
the worldserver image and the loader symbol Addmod_paragonScripts
gets linked into the static modules target.
SQL layout
SQL files live under data/sql/db-world/base/ and
data/sql/db-characters/base/ — the standard AzerothCore module path
that the built-in DBUpdater scans (see
src/server/database/Updater/UpdateFetcher.cpp). Files placed there
are applied automatically by worldserver / dbimport on startup and
recorded by hash in the updates table of the target database, so
re-runs are idempotent. Any new SQL added under those directories will
be picked up on the next container/server start without manual import.