feat(Core/Maps): port spawn system/dynamic spawns from TrinityCore#25206
feat(Core/Maps): port spawn system/dynamic spawns from TrinityCore#25206Nyeriah wants to merge 2 commits intoazerothcore:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Ports TrinityCore’s spawn group system into AzerothCore to allow grouping spawns (creatures/gameobjects) with per-group activation and respawn behavior, including a non-compatibility respawn scheduler and admin/SAI controls.
Changes:
- Added spawn group template/member loading in
ObjectMgr, plus map-level spawn/despawn toggling and a periodicMap::ProcessRespawns()scheduler. - Added GM/admin commands for listing pending respawns, forcing respawns, reloading spawn group tables, and spawning/despawning groups.
- Added config toggles for forcing legacy respawn behavior and (documented) escort NPC dynamic respawn behavior, plus initial SQL tables.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/server/scripts/Commands/cs_reload.cpp | Adds .reload spawn_group command to hot-reload spawn group data |
| src/server/scripts/Commands/cs_npc.cpp | Adds .npc spawngroup / .npc despawngroup commands |
| src/server/scripts/Commands/cs_misc.cpp | Extends respawn-all logic to also clear non-compat pending respawns |
| src/server/scripts/Commands/cs_list.cpp | Adds .list respawns to show pending creature/GO respawn timers |
| src/server/scripts/Commands/cs_gobject.cpp | Adds .go spawngroup / .go despawngroup commands |
| src/server/game/World/WorldConfig.h | Adds new config keys for spawn/respawn behavior |
| src/server/game/World/WorldConfig.cpp | Registers new config values |
| src/server/game/World/World.cpp | Loads spawn group templates and members during server startup |
| src/server/game/Maps/SpawnData.h | Adds compatibility flag, per-spawn spawnId, and mapId changes for group templates |
| src/server/game/Maps/Map.h | Adds spawn group APIs, respawn processing, and respawn-time accessors |
| src/server/game/Maps/Map.cpp | Implements group activation, spawn/despawn, and periodic respawn processing |
| src/server/game/Grids/GridObjectLoader.cpp | Skips loading spawns whose spawn group is inactive |
| src/server/game/Globals/ObjectMgr.h | Adds spawn group load APIs and group-to-spawn lookup storage |
| src/server/game/Globals/ObjectMgr.cpp | Implements spawn group template/member DB loading and bookkeeping |
| src/server/game/Entities/GameObject/GameObject.h | Tracks per-GO compatibility mode flag |
| src/server/game/Entities/GameObject/GameObject.cpp | Sets GO compatibility mode from spawn group flags/config |
| src/server/game/Entities/Creature/Creature.h | Tracks per-creature compatibility mode flag |
| src/server/game/Entities/Creature/Creature.cpp | Changes corpse removal/respawn behavior for non-compat mode and sets compatibility mode on load |
| src/server/game/AI/SmartScripts/SmartScriptMgr.h | Adds params struct for spawn group SAI actions |
| src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | Enables SAI validation/param sizing for spawn group actions |
| src/server/game/AI/SmartScripts/SmartScript.cpp | Implements SAI actions to spawn/despawn spawn groups |
| src/server/game/AI/ScriptedAI/ScriptedEscortAI.h | Marks escort AI as escort NPC via new virtual |
| src/server/game/AI/CreatureAI.h | Adds virtual IsEscortNPC() hook |
| src/server/database/Database/Implementation/WorldDatabase.h | Adds prepared statement id for deleting spawn group members |
| src/server/database/Database/Implementation/WorldDatabase.cpp | Prepares DELETE FROM spawn_group ... statement |
| src/server/apps/worldserver/worldserver.conf.dist | Documents/configures new respawn toggles |
| data/sql/updates/pending_db_world/rev_spawn_group_tables.sql | Adds initial spawn_group_template and spawn_group tables with defaults |
Comments suppressed due to low confidence (1)
src/server/scripts/Commands/cs_misc.cpp:1
- PR description says
.respawn all'force-respawn everything on the map', but this implementation only clears respawn times for the player's current grid ID (and the phase-1 visit is limited to activation range). If the intended behavior is truly 'entire map', remove the grid filter and iterate all respawn times / loaded grids accordingly; otherwise, clarify the command behavior in the PR description/help text.
/*
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Would close this #23824 ? or TC implementation is not the same as cmangos? Currently this issue would be by this implemantion (not the pr itself) if the above is the same for TC and Cmangos |
No, completely different stuff |
|
Just gonna put a dump here, since you are porting the (now known to be wrong) TC spawn group system: This is leaked wowedit picture of spawn groups. (the name means a very specific thing on B end) Spawning or not spawning is governed by these: https://wowdev.wiki/DB/WorldStateExpression https://gist.github.com/killerwife/20a822b785944dcb10cffc4018b5f48d here is a list of "leaked" ones couple years back Relevant to the topic from https://wowdev.wiki/EnumeratedString: JoinSummonersSpawnGroup = 9, enum Unknown_867 => linkage is meant to be fully replaced by spawn group behaviour An event for spawn group exists for scripting: OnSpawnGroupDeath or something similar, essentially when last member dies it triggers (used all over vanilla and tbc for example) Use this information as you wish, not saying my implementation is strictly correct from official standpoint, but unlike TC one it does incorporate these leaks. |
|
Thanks for sharing! I don't plan to stray too far from the TC implementation but hopefully someone else can pick it up later |
| -- Insert default spawn groups | ||
| DELETE FROM `spawn_group_template` WHERE `groupId` IN (0, 1); | ||
| INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES | ||
| (0, 'Default Group', 0x01), -- SYSTEM (dynamic respawn by default) |
There was a problem hiding this comment.
Shouldn't this be numeric values 1 and 3 even if it's a flag?
…ty queue Port TrinityCore's spawn group system to AzerothCore, enabling dynamic respawn management for creatures and gameobjects. Adds pool-aware ProcessRespawns() that delegates pooled spawns to PoolMgr, a time-ordered priority queue (based on TC commit 59db2eee by r00ty-tc) for O(1) idle cost, .pool info/.pool lookup debug commands, spawn/despawn group commands, and .list respawns. Prevents .respawn all from creating duplicate pool spawns. Includes full localization for all 8 supported locales and SQL migrations. Co-Authored-By: Claude Opus 4.6 <[email protected]>

Changes Proposed:
This PR proposes changes to:
Ports TrinityCore's spawn group system to AzerothCore, enabling logical grouping of creature and gameobject spawns with per-group control over respawn behavior.
Key changes:
spawn_group_template(group definitions with flags) andspawn_group(creature/GO membership)Map::Update()— creatures are fully removed on death and recreated fresh by the scheduler when their timer expiresSPAWNGROUP_FLAG_COMPATIBILITY_MODE, preserving current behavior. ARespawn.ForceCompatibilityModeworldserver config allows forcing all spawns to use legacy behavior regardless of group flags.list respawn(show pending respawns on current map),.respawn all(force-respawn everything on the map),.npc spawngroup/.go spawngroup(show spawn group info)SMART_ACTION_SPAWN_SPAWNGROUPandSMART_ACTION_DESPAWN_SPAWNGROUPfor script-driven spawn group control.reload spawn_groupto hot-reload group dataAI-assisted Pull Requests
Important
While the use of AI tools when preparing pull requests is not prohibited, contributors must clearly disclose when such tools have been used and specify the model involved.
Issues Addressed:
SOURCE:
The changes have been validated through:
Based on TrinityCore commit 59db2eee by r00ty-tc, adapted for AzerothCore's codebase (different DB access patterns,
LoadCreatureFromDBsignatures, existing dynamic respawn system, config framework, etc.)Tests Performed:
This PR has been:
How to Test the Changes:
Respawn.ForceCompatibilityMode = 0inworldserver.confto enable the new system.list respawnto verify creatures appear in the pending respawn list with correct timers.respawn allto force immediate respawn of all pending creatures/GOs on the map.npc spawngroupand.go spawngroupshow correct group info for targeted spawnsRespawn.ForceCompatibilityMode = 1and verify legacy corpse-stays-on-map behavior is restoredKnown Issues and TODO List:
spawn_group_template,spawn_group) ship with only default groups — individual creature/GO assignments to custom groups need to be populated by future DB PRs🤖 Generated with Claude Code