diff --git a/.agents/docs/cpp-guidelines.md b/.agents/docs/cpp-guidelines.md index 5fa7be0a78..96505b0dbf 100644 --- a/.agents/docs/cpp-guidelines.md +++ b/.agents/docs/cpp-guidelines.md @@ -21,7 +21,7 @@ Hard rules (also enforced by CI with `-Werror`, plus `cppcheck`): - **Logging**: `LOG_INFO("category.sub", "msg with {}", arg)` (also `LOG_WARN`/`ERROR`/`DEBUG`/`TRACE`). Categories are hierarchical, dot-separated (`server.loading`, `entities.player`, `sql.dev`). No `printf`-style, no `sLog->`, no `TC_LOG_*`. Macro in `src/common/Logging/Log.h`. - **Random**: use helpers in `src/common/Utilities/Random.h` — `urand`, `irand`, `frand`, `rand32`, `rand_chance`, `roll_chance_f`, `roll_chance_i`. Not `std::rand` or ``. - **Strings**: `Acore::StringFormat(fmt, args...)` (`{}` placeholders) — `src/common/Utilities/StringFormat.h`. -- **Config**: `sConfigMgr->GetOption("Name", default)`. +- **Config**: `sConfigMgr->GetOption("Name", default)` — read once at startup/reload and cache the value; never call it in hot paths or per-call gating checks. - **Namespace**: project-wide `Acore::` (no `Trinity::` remnants — rename when porting from upstream forks). - **Long-lived references**: don't store a raw `Player*` / `Creature*` / `Unit*` past the current call/tick — the object can be removed (logout, despawn, instance unload) and the pointer dangles. Store the `ObjectGuid` and resolve at use time via `ObjectAccessor::FindPlayer(guid)`, `Map::GetCreature(guid)`, etc. - **DB queries**: use `PreparedStatement` (via `WorldDatabase` / `CharacterDatabase` / `LoginDatabase` and the prepared-statement enums), not raw query strings. Non-blocking reads go async: `_queryProcessor.AddCallback(db.AsyncQuery(stmt).WithPreparedCallback(...))` (or `WithCallback`). Multi-statement writes wrap in `SQLTransaction` + `Execute` / `AppendPreparedStatement`. diff --git a/.agents/docs/cpp-scripts.md b/.agents/docs/cpp-scripts.md index 3eb5ee0d87..c2aaa5ee7c 100644 --- a/.agents/docs/cpp-scripts.md +++ b/.agents/docs/cpp-scripts.md @@ -14,5 +14,9 @@ Then declare and call `AddSC_()` from the regional loader (`Spells/spells_ **Conventions:** - Script ids (action/event/data/phase) get named enum entries — never raw literals, even when the file already uses them: add the entry and convert that literal's every call site and handler in the same change. +- A `SpellScript`/`AuraScript` without a matching `spell_script_names` row is inert — ship the binding SQL update in the same change as the C++ registration. +- Never add `UNIT_FLAG*` / `UNIT_FLAG2*` / `UNIT_DYNFLAG*` values without sniff or upstream evidence; the same flag used in another script is not evidence. +- Trigger NPCs (`creature_template.flags_extra` 0x80) have no threat list — `SelectTarget` / `AddThreat` / `UpdateVictim` chains on them silently do nothing. A never-evading helper NPC left on a boss's threatened-by list also stalls the boss's evade/reset forever; make such helpers `IMMUNE_TO_NPC`. +- A spell id missing from Wowhead is inconclusive — check the world DB's `spell_dbc` table (server-side spells) before concluding a sniffed id doesn't exist. Custom (non-upstream) scripts go in `src/server/scripts/Custom/` (gitignored). diff --git a/.agents/docs/sql-guidelines.md b/.agents/docs/sql-guidelines.md index d40002c8ad..54c48e5269 100644 --- a/.agents/docs/sql-guidelines.md +++ b/.agents/docs/sql-guidelines.md @@ -8,6 +8,11 @@ Run the linter before claiming a change is done: `python apps/codestyle/codestyle-sql.py` (compares to origin/master). +## Data conventions + +- `smart_scripts` edits always rewrite the full block — `DELETE` + `INSERT` of every row for the `(entryorguid, source_type)` pair, with the `DELETE` matching both columns — never a partial `UPDATE`, not even for a comment-only fix. +- `creature_immunities`: negative ids are curated shared sets — reference them via `creature_template.CreatureImmunitiesId`, never edit them or allocate new ones. Positive ids are single-creature sets — reuse an existing set only on an exact match; to extend a creature's immunities, insert a superset under a new id and point the creature's `CreatureImmunitiesId` at it. + ## The three databases - `acore_auth` — accounts, realm list, IP/account bans, session keys. Shared across all realms.