f2952c905a
- SpellInfoCorrections: zero Reagent/ReagentCount on spells with non-zero SpellFamilyName so class abilities no longer require shards, candles, etc., while profession crafts (SpellFamilyName 0) keep mats. Matches the client Spell.dbc bake in patch-enUS-4.MPQ. - Paragon_SC: OnPlayerIsClass returns true for CLASS_CONTEXT_EQUIP_RELIC for paladin/druid/shaman/warlock/dk so Paragon can equip all relic types in the ranged slot. - CLIENT-PATCHES: document Spell.dbc reagent pass, rune script order, and stock ammo slot behavior in patch-enUS-5. Co-authored-by: Cursor <cursoragent@cursor.com>
256 lines
13 KiB
Markdown
256 lines
13 KiB
Markdown
# Fractured Client Patches
|
||
|
||
Binary client artifacts that pair with this server. They live on the
|
||
[Releases page](https://github.com/Dawnforger/Fractured/releases),
|
||
**not** in the tree, so the repo stays lean and binaries can be
|
||
re-downloaded without bloating `git clone`.
|
||
|
||
This file is the table of contents and install guide.
|
||
|
||
---
|
||
|
||
## What ships in a release
|
||
|
||
| 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-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-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. |
|
||
| `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
|
||
worldserver via `WHISPER` addon-channel messages with the `PARAA` prefix
|
||
(currency push, spell/talent snapshot, commit, combo points, rune
|
||
cooldowns, learn-toast silence window). Mismatched versions usually
|
||
manifest as the panel rendering blank or AE/TE reading 0/0.
|
||
|
||
---
|
||
|
||
## Install
|
||
|
||
You need a 3.3.5a (build 12340) WoW client. ChromieCraft's free 3.3.5a
|
||
download is the canonical clean source if you don't already have one.
|
||
|
||
1. Download every artifact from the latest release matching this server
|
||
build:
|
||
`https://github.com/Dawnforger/Fractured/releases/latest`
|
||
2. Replace `Wow.exe` at the root of your client install with the patched
|
||
one from the release. Keep a backup of the original if you want.
|
||
3. Drop `patch-enUS-4.MPQ`, `patch-enUS-5.MPQ`, `patch-enUS-6.MPQ` into
|
||
`Data/enUS/`. (For other locales, rename the suffix accordingly —
|
||
contents are locale-independent, only the filename ordering matters
|
||
to the loader.)
|
||
4. Edit `Data/enUS/realmlist.wtf` to point at your server, e.g.
|
||
`set realmlist your.host.tld`.
|
||
5. Launch `Wow.exe`. The login screen should reach the realm list. Make
|
||
a Paragon character (the new class entry on the create screen) and
|
||
press `N` in-world to open the Character Advancement panel.
|
||
|
||
If the panel opens empty / AE+TE read 0/0 / `N` opens the stock talent
|
||
pane: your client is loading an older `patch-enUS-6.MPQ`, or the
|
||
worldserver image is older than commit `4d2a80d` (the
|
||
`character_paragon_panel_spell_revoked` migration). Pull both ends to
|
||
the same release tag and rebuild the worldserver image.
|
||
|
||
If the **client** shows the Paragon class on the create screen but the
|
||
server replies **Character Creation Failed** (sometimes shown as
|
||
"Error creating character") when you pick it -- **or** the character
|
||
is created but spawns with no weapon / armor proficiencies (auto-attack
|
||
greys out, can't equip anything beyond a fist), or with the proficiency
|
||
**skills** but no **passive spells** like Block, Parry, Dual Wield --
|
||
the worldserver is missing one of four pieces of class-12 data. All
|
||
ship as SQL migrations under
|
||
`modules/mod-paragon/data/sql/db-world/updates/` and are auto-applied
|
||
by AzerothCore's DBUpdater on every `ac-db-import` run, but the SQL
|
||
files are baked into the dbimport Docker image at build time -- so a
|
||
stale image won't pick up new migrations. Fix:
|
||
|
||
```bash
|
||
git pull origin main
|
||
docker compose build ac-db-import ac-worldserver
|
||
docker compose up -d ac-db-import
|
||
docker compose restart ac-worldserver
|
||
```
|
||
|
||
Existing class-12 characters created before these migrations will
|
||
keep their broken state -- the cascade only fires inside
|
||
`Player::Create` and `Player::LearnDefaultSkill` at character spawn.
|
||
Delete the old Paragon and re-roll after the rebuild.
|
||
|
||
The four migrations:
|
||
|
||
- `2026_05_09_00.sql` -- DBC overlay rows for `chrclasses_dbc` and
|
||
`skillraceclassinfo_dbc`. Without this the server can't even
|
||
resolve class 12 in `sChrClassesStore`. See **Server-side Paragon
|
||
DBC overlay** below.
|
||
- `2026_05_10_00.sql` -- `playercreateinfo`, `playercreateinfo_action`,
|
||
and `player_class_stats` rows for class 12. Without this
|
||
`Player::Create` rejects every (race, class=12) pair as an
|
||
"invalid race/class pair" and the worldserver prints
|
||
`class-N Level-L does not have stats data!` integrity warnings on
|
||
load.
|
||
- `2026_05_10_01.sql` -- 20 `playercreateinfo_skills` rows
|
||
(`classMask = 2048` = class 12) granting every weapon /
|
||
armor proficiency at level 1. Without this a Paragon spawns with
|
||
only the universal `classMask = 0` skills (Defense, Unarmed,
|
||
Cloth, languages, Mounts) -- no Swords, no Mail, no Shield, etc.
|
||
- `2026_05_10_02.sql` -- 3,314 `skilllineability_dbc` rows opening
|
||
the class-12 bit on every SkillLineAbility row our patched
|
||
`SkillLineAbility.dbc` modified. AC reads these rows in
|
||
`Player::LearnDefaultSkill` to drive the `skill -> passive spell`
|
||
cascade. Without it the proficiency *skills* from `_01.sql` exist
|
||
but the *passive spells* (Block, Parry, Dual Wield, Defense,
|
||
weapon Shoot, racial Mace/Sword Specialization, etc.) never auto-
|
||
learn, so the spellbook past the racials looks empty.
|
||
|
||
After the rebuild + restart, `ac-worldserver` should log
|
||
`>> Loaded 72 Player Create Definitions` (was 62 pre-Paragon),
|
||
`>> Loaded 1391 Player Create Skills` (was 1371),
|
||
`>> Loaded 10219 SkillLineAbility MultiMap Data` (unchanged total --
|
||
the SQL overlay replaces existing rows by ID, doesn't add new ones),
|
||
and character creation succeeds for any DK-eligible race with a full
|
||
weapon / armor kit and the matching passive spells.
|
||
|
||
If the client **logs in** successfully but **disconnects immediately**
|
||
when entering the realm: the auth server is handing your client the
|
||
wrong world-server address. On a fresh local install the seed defaults
|
||
to `127.0.0.1` (commit landing this paragraph). If your DB was
|
||
imported from an older Fractured checkout, the seed may still point at
|
||
`hsrwow.net`, which sends the client to our production world server
|
||
instead of yours. Fix:
|
||
|
||
```bash
|
||
# Docker:
|
||
docker exec ac-database mysql -uroot -ppassword \
|
||
-e "UPDATE acore_auth.realmlist SET address='127.0.0.1' WHERE id=1;"
|
||
docker compose restart ac-authserver
|
||
```
|
||
|
||
Substitute your public hostname/IP for `127.0.0.1` if remote players
|
||
will be connecting. See `BUILD-NATIVE.md` -> *Production deployment
|
||
overrides* for the full list of values to set on a production box.
|
||
|
||
---
|
||
|
||
## Server-side Paragon DBC overlay (automatic)
|
||
|
||
The Fractured **client** learns about Paragon from `patch-enUS-4.MPQ`
|
||
(DBC + GlueXML). The **worldserver** never reads your MPQs — it reads
|
||
plain `.dbc` files under its `DataDir` (`.../data/dbc/` by default).
|
||
|
||
Stock Docker installs populate `data/dbc/` from a vanilla 3.3.5a
|
||
extract (`ac-client-data-init` in `docker-compose.yml`). That tree has
|
||
no `ChrClasses` row for id **12** and no class-12 bit on
|
||
`SkillRaceClassInfo` rows, which would normally trigger:
|
||
|
||
`Class (12) not found in DBC while creating new char ... wrong DBC files or cheater?`
|
||
|
||
…and reject the create with `CHAR_CREATE_FAILED`.
|
||
|
||
To remove that gap, the repo ships
|
||
`modules/mod-paragon/data/sql/db-world/updates/2026_05_09_00.sql`,
|
||
which `INSERT`s the Paragon class-12 deltas into:
|
||
|
||
- `chrclasses_dbc` — 1 row defining class 12 ("Paragon", power=Mana,
|
||
family=Warrior, expansion=2).
|
||
- `skillraceclassinfo_dbc` — 235 rows replacing stock entries with the
|
||
patched ClassMask (class-12 bit OR'd in) so every baseline skill is
|
||
available to Paragon characters.
|
||
|
||
`AzerothCore`'s DBC loader (`DBCStores.cpp::LoadDBC` -> `LoadFromDB`)
|
||
merges these rows on top of whatever `data/dbc/` contains at every
|
||
worldserver boot. The DBUpdater in `ac-db-import` (Docker) or the
|
||
worldserver itself (native) applies the migration automatically — so
|
||
the **only** steps a fresh contributor needs are `git clone` and
|
||
`docker compose up -d`.
|
||
|
||
### Regenerating the migration
|
||
|
||
The SQL is auto-generated from the patched DBCs that already live
|
||
inside `patch-enUS-4.MPQ`. The bake script lives outside this repo
|
||
(per the repo-tidy policy) at:
|
||
|
||
`fractured-tooling/from-workspace-root/_gen_paragon_dbc_overlay_sql.py`
|
||
|
||
Re-run it whenever you change the Paragon DBC bake — for example,
|
||
adding a new race to the Paragon class mask. It diffs the patched
|
||
DBCs against a stock 3.3.5a DBC extract and emits a fresh
|
||
`2026_05_09_00.sql` (or successor migration with a new timestamp if
|
||
deltas change). Workflow:
|
||
|
||
```powershell
|
||
# Extract the patched DBCs once:
|
||
.\tools\mpq\mpqcli.exe extract `
|
||
"ChromieCraft_3.3.5a\Data\enUS\patch-enUS-4.MPQ" `
|
||
-o "$env:TEMP\paragon-dbc-extract"
|
||
|
||
# Regenerate the SQL migration:
|
||
python fractured-tooling\from-workspace-root\_gen_paragon_dbc_overlay_sql.py
|
||
```
|
||
|
||
If the regenerated SQL has new content, commit it as a **new** dated
|
||
migration filename (e.g. `2026_06_01_00.sql`) — never edit a file that
|
||
has already been applied to live databases, AC's DBUpdater will detect
|
||
the hash change and re-run the SQL, which can be fine but is best
|
||
reserved for emergencies.
|
||
|
||
### Manual DBC overlay (rare, fallback)
|
||
|
||
If you ever need the patched DBCs *on disk* — e.g. for a tool that
|
||
reads `data/dbc/` directly outside the worldserver, or to verify a
|
||
client-vs-server DBC mismatch — extract `patch-enUS-4.MPQ` and copy
|
||
its `DBFilesClient/*.dbc` into `data/dbc/`:
|
||
|
||
**Docker:**
|
||
|
||
```powershell
|
||
docker run --rm `
|
||
-v ac-client-data:/data `
|
||
-v ${PWD}\paragon-dbc-extract:/patch:ro `
|
||
alpine sh -c "cp -f /patch/*.dbc /data/dbc/"
|
||
docker compose restart ac-worldserver
|
||
```
|
||
|
||
**Native:** copy into `<CMAKE_INSTALL_PREFIX>/data/dbc/` and restart.
|
||
|
||
This is **not required** for normal operation — the SQL migration
|
||
covers everything `mod-paragon` needs at runtime. Use the manual
|
||
overlay only when you're consciously bypassing the SQL merge layer.
|
||
|
||
---
|
||
|
||
## Building the patches yourself
|
||
|
||
The MPQs are reproducible from the dev tree (not in this repo —
|
||
`Classless Dev/Paragon Patch UI/` and
|
||
`Classless Dev/Paragon Advancement/` on the maintainer's workstation)
|
||
via two PowerShell scripts in `tools/`:
|
||
|
||
```
|
||
tools\build_paragon_ui_patch.ps1 -Deploy # -> patch-enUS-5.MPQ
|
||
tools\build_paragon_advancement_patch.ps1 -Deploy # -> patch-enUS-6.MPQ
|
||
```
|
||
|
||
`patch-enUS-4.MPQ` is the DBC + GlueXML bake; the bake scripts live with
|
||
the rest of the dev tooling and are not part of this repo by design
|
||
(see the repo-tidy policy in `README.txt` next to this file). Typical
|
||
order on a maintainer machine:
|
||
|
||
1. `fractured-tooling/from-workspace-root/_patch_spell_dbc_runes.py` — stage `Spell.dbc` with `RuneCostID` cleared.
|
||
2. `fractured-tooling/from-workspace-root/_patch_spell_dbc_reagents.py` — same staged `Spell.dbc`, clear class-spell reagents for client preflight.
|
||
3. `fractured-tooling/from-workspace-root/_make_paragon_dbc_patch.py` — rebuild `ChrClasses` / `CharBaseInfo` / game tables, then pack `patch-enUS-4.MPQ`.
|
||
|
||
The patched `Wow.exe` is a one-time hex-edit of the stock 3.3.5a
|
||
client. The diff is publicly documented in the WoW emulation community
|
||
under names like "MPQ signature patch" / "no-CD-signature patch".
|
||
|
||
---
|
||
|
||
## Versioning
|
||
|
||
Releases are tagged to match the state of `main` they were built from.
|
||
The release notes call out which server commit shipped alongside each
|
||
artifact set, so a contributor running `git checkout <tag>` on this
|
||
repo can pull the matching client bundle and have a guaranteed-aligned
|
||
end-to-end build.
|