Skip to content

Commit e8b4959

Browse files
Merge AzerothCore 3.3.5 to ElunaAzerothcore [skip ci]
2 parents fd8b549 + 0b30b3f commit e8b4959

9 files changed

Lines changed: 394 additions & 18 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- DB update 2026_05_09_00 -> 2026_05_14_00
2+
--
3+
-- RBAC permissions for `respawn creature guid`, `respawn gameobject guid`,
4+
-- `respawn creature entry`, and `respawn gameobject entry` commands (Console::Yes/No, security level 3 - GM)
5+
--
6+
DELETE FROM `rbac_permissions` WHERE `id` IN (916, 917, 918, 919);
7+
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
8+
(916, 'Command: respawn creature guid'),
9+
(917, 'Command: respawn gameobject guid'),
10+
(918, 'Command: respawn creature entry'),
11+
(919, 'Command: respawn gameobject entry');
12+
13+
DELETE FROM `rbac_linked_permissions` WHERE `linkedId` IN (916, 917, 918, 919);
14+
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES
15+
(197, 916),
16+
(197, 917),
17+
(197, 918),
18+
(197, 919);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
-- DB update 2026_05_10_01 -> 2026_05_14_00
2+
--
3+
-- Strings for `respawn creature guid` / `respawn gameobject guid` /
4+
-- `respawn creature entry` / `respawn gameobject entry` commands and updated `list respawns` command
5+
--
6+
DELETE FROM `acore_string` WHERE `entry` IN (35441, 35442, 35443, 35444, 35445, 35446, 35447, 35448, 35449, 35450, 35451, 35452);
7+
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
8+
(35441, 'No creature with spawn GUID {} found.', '스폰 GUID {}를 가진 생물을 찾을 수 없습니다.', 'Aucune créature avec le GUID d''apparition {} trouvée.', 'Keine Kreatur mit Spawn-GUID {} gefunden.', '未找到生成 GUID 为 {} 的生物。', '未找到生成 GUID 為 {} 的生物。', 'No se encontró ninguna criatura con el GUID de generación {}.', 'No se encontró ninguna criatura con el GUID de generación {}.', 'Существо с GUID спавна {} не найдено.'),
9+
(35442, 'Map {} is not currently loaded.', '맵 {}이(가) 현재 로드되어 있지 않습니다.', 'La carte {} n''est pas actuellement chargée.', 'Karte {} ist derzeit nicht geladen.', '地图 {} 当前未加载。', '地圖 {} 目前未載入。', 'El mapa {} no está cargado actualmente.', 'El mapa {} no está cargado actualmente.', 'Карта {} в данный момент не загружена.'),
10+
(35443, 'Creature (spawn GUID {}, entry {}) is already alive.', '생물 (스폰 GUID {}, 항목 {})이(가) 이미 살아 있습니다.', 'La créature (GUID d''apparition {}, entrée {}) est déjà en vie.', 'Kreatur (Spawn-GUID {}, Eintrag {}) ist bereits am Leben.', '生物(生成 GUID {},条目 {})已经存活。', '生物(生成 GUID {},條目 {})已經存活。', 'La criatura (GUID de generación {}, entrada {}) ya está viva.', 'La criatura (GUID de generación {}, entrada {}) ya está viva.', 'Существо (GUID спавна {}, запись {}) уже живо.'),
11+
(35444, 'Creature (spawn GUID {}, entry {}) queued for respawn.', '생물 (스폰 GUID {}, 항목 {})이(가) 리스폰 대기열에 추가되었습니다.', 'La créature (GUID d''apparition {}, entrée {}) est mise en file d''attente pour réapparition.', 'Kreatur (Spawn-GUID {}, Eintrag {}) für Respawn in Warteschlange.', '生物(生成 GUID {},条目 {})已加入重生队列。', '生物(生成 GUID {},條目 {})已加入重生佇列。', 'La criatura (GUID de generación {}, entrada {}) está en cola para reaparecer.', 'La criatura (GUID de generación {}, entrada {}) está en cola para reaparecer.', 'Существо (GUID спавна {}, запись {}) добавлено в очередь на респаун.'),
12+
(35445, 'Gameobject (spawn GUID {}, entry {}) is already active.', '게임오브젝트 (스폰 GUID {}, 항목 {})이(가) 이미 활성화되어 있습니다.', 'L''objet de jeu (GUID d''apparition {}, entrée {}) est déjà actif.', 'Spielobjekt (Spawn-GUID {}, Eintrag {}) ist bereits aktiv.', '游戏对象(生成 GUID {},条目 {})已经激活。', '遊戲物件(生成 GUID {},條目 {})已經激活。', 'El objeto de juego (GUID de generación {}, entrada {}) ya está activo.', 'El objeto de juego (GUID de generación {}, entrada {}) ya está activo.', 'Игровой объект (GUID спавна {}, запись {}) уже активен.'),
13+
(35446, 'Gameobject (spawn GUID {}, entry {}) queued for respawn.', '게임오브젝트 (스폰 GUID {}, 항목 {})이(가) 리스폰 대기열에 추가되었습니다.', 'L''objet de jeu (GUID d''apparition {}, entrée {}) est mis en file d''attente pour réapparition.', 'Spielobjekt (Spawn-GUID {}, Eintrag {}) für Respawn in Warteschlange.', '游戏对象(生成 GUID {},条目 {})已加入重生队列。', '遊戲物件(生成 GUID {},條目 {})已加入重生佇列。', 'El objeto de juego (GUID de generación {}, entrada {}) está en cola para reaparecer.', 'El objeto de juego (GUID de generación {}, entrada {}) está en cola para reaparecer.', 'Игровой объект (GUID спавна {}, запись {}) добавлен в очередь на респаун.'),
14+
(35447, 'A map ID is required when using this command from the console.', '콘솔에서 이 명령을 사용하려면 맵 ID가 필요합니다.', 'Un ID de carte est requis lors de l''utilisation de cette commande depuis la console.', 'Eine Karten-ID ist erforderlich, wenn dieser Befehl über die Konsole verwendet wird.', '从控制台使用此命令时需要提供地图 ID。', '從控制台使用此命令時需要提供地圖 ID。', 'Se requiere un ID de mapa al usar este comando desde la consola.', 'Se requiere un ID de mapa al usar este comando desde la consola.', 'При использовании этой команды из консоли требуется ID карты.'),
15+
(35448, 'No gameobject with spawn GUID {} found.', '스폰 GUID {}를 가진 게임오브젝트를 찾을 수 없습니다.', 'Aucun objet de jeu avec le GUID d''apparition {} trouvé.', 'Kein Spielobjekt mit Spawn-GUID {} gefunden.', '未找到生成 GUID 为 {} 的游戏对象。', '未找到生成 GUID 為 {} 的遊戲物件。', 'No se encontró ningún objeto de juego con el GUID de generación {}.', 'No se encontró ningún objeto de juego con el GUID de generación {}.', 'Игровой объект с GUID спавна {} не найден.'),
16+
(35449, 'No creature template with entry {} found.', '항목 {}을(를) 가진 생물 템플릿을 찾을 수 없습니다.', 'Aucun modèle de créature avec l''entrée {} trouvé.', 'Kein Kreaturvorlage mit Eintrag {} gefunden.', '未找到条目为 {} 的生物模板。', '未找到條目為 {} 的生物模板。', 'No se encontró ninguna plantilla de criatura con la entrada {}.', 'No se encontró ninguna plantilla de criatura con la entrada {}.', 'Шаблон существа с записью {} не найден.'),
17+
(35450, 'No gameobject template with entry {} found.', '항목 {}을(를) 가진 게임오브젝트 템플릿을 찾을 수 없습니다.', 'Aucun modèle d''objet de jeu avec l''entrée {} trouvé.', 'Kein Spielobjektvorlage mit Eintrag {} gefunden.', '未找到条目为 {} 的游戏对象模板。', '未找到條目為 {} 的遊戲物件模板。', 'No se encontró ninguna plantilla de objeto de juego con la entrada {}.', 'No se encontró ninguna plantilla de objeto de juego con la entrada {}.', 'Шаблон игрового объекта с записью {} не найден.'),
18+
(35451, 'Queued {} creature spawn(s) with entry {} for respawn on this map.', '이 맵에서 항목 {}을(를) 가진 생물 스폰 {}개가 리스폰 대기열에 추가되었습니다.', '{} apparition(s) de créature avec l''entrée {} mise(s) en file d''attente pour réapparition sur cette carte.', '{} Kreaturspawn(s) mit Eintrag {} für Respawn auf dieser Karte in Warteschlange.', '在此地图上,已将 {} 个条目为 {} 的生物生成加入重生队列。', '在此地圖上,已將 {} 個條目為 {} 的生物生成加入重生佇列。', 'Se pusieron en cola {} aparición(es) de criatura con entrada {} para reaparecer en este mapa.', 'Se pusieron en cola {} aparición(es) de criatura con entrada {} para reaparecer en este mapa.', 'В очередь на респаун на этой карте добавлено {} спавн(ов) существа с записью {}.'),
19+
(35452, 'Queued {} gameobject spawn(s) with entry {} for respawn on this map.', '이 맵에서 항목 {}을(를) 가진 게임오브젝트 스폰 {}개가 리스폰 대기열에 추가되었습니다.', '{} apparition(s) d''objet de jeu avec l''entrée {} mise(s) en file d''attente pour réapparition sur cette carte.', '{} Spielobjektspawn(s) mit Eintrag {} für Respawn auf dieser Karte in Warteschlange.', '在此地图上,已将 {} 个条目为 {} 的游戏对象生成加入重生队列。', '在此地圖上,已將 {} 個條目為 {} 的遊戲物件生成加入重生佇列。', 'Se pusieron en cola {} aparición(es) de objeto de juego con entrada {} para reaparecer en este mapa.', 'Se pusieron en cola {} aparición(es) de objeto de juego con entrada {} para reaparecer en este mapa.', 'В очередь на респаун на этой карте добавлено {} спавн(ов) игрового объекта с записью {}.');
20+
21+
--
22+
-- Update `list respawns` command help text
23+
--
24+
DELETE FROM `command` WHERE `name` = 'list respawns';
25+
INSERT INTO `command` (`name`, `security`, `help`) VALUES
26+
('list respawns', 2, 'Syntax: .list respawns [entryId]\r\nIn-game: shows all pending creature and gameobject respawns on the current map, filtered by entryId if provided.\r\nConsole: .list respawns #mapId [#instanceId [#entryId]] - specify map and optional instance ID and entry filter.');
27+
28+
--
29+
-- Register `respawn creature guid`, `respawn gameobject guid`,
30+
-- `respawn creature entry`, and `respawn gameobject entry` commands
31+
--
32+
DELETE FROM `command` WHERE `name` IN ('respawn id', 'respawn guid', 'respawn creature guid', 'respawn gameobject guid', 'respawn creature entry', 'respawn gameobject entry');
33+
INSERT INTO `command` (`name`, `security`, `help`) VALUES
34+
('respawn creature guid', 3, 'Syntax: .respawn creature guid #spawnGuid\r\nForces the creature with the given spawn GUID (database GUID) to respawn. Usable from console.'),
35+
('respawn gameobject guid', 3, 'Syntax: .respawn gameobject guid #spawnGuid\r\nForces the gameobject with the given spawn GUID (database GUID) to respawn. Usable from console.'),
36+
('respawn creature entry', 3, 'Syntax: .respawn creature entry #entry [#mapId [#instanceId]]\r\nIn-game: forces all creatures with the given #entry to respawn on the current map.\r\nConsole: specify #mapId (required) and optionally #instanceId. Pooled creatures are skipped in the queue phase to prevent duplicate spawns.'),
37+
('respawn gameobject entry', 3, 'Syntax: .respawn gameobject entry #entry [#mapId [#instanceId]]\r\nIn-game: forces all gameobjects with the given #entry to respawn on the current map.\r\nConsole: specify #mapId (required) and optionally #instanceId. Pooled gameobjects are skipped in the queue phase to prevent duplicate spawns.');

src/server/game/Accounts/RBAC.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,10 @@ enum RBACPermissions
677677
RBAC_PERM_COMMAND_BF_QUEUE = 913,
678678
RBAC_PERM_COMMAND_PET_LIST = 914,
679679
RBAC_PERM_COMMAND_PET_DELETE = 915,
680+
RBAC_PERM_COMMAND_RESPAWN_CREATURE_GUID = 916,
681+
RBAC_PERM_COMMAND_RESPAWN_GAMEOBJECT_GUID = 917,
682+
RBAC_PERM_COMMAND_RESPAWN_CREATURE_ENTRY = 918,
683+
RBAC_PERM_COMMAND_RESPAWN_GAMEOBJECT_ENTRY = 919,
680684
// custom permissions 1000+
681685
RBAC_PERM_MAX
682686
};

src/server/game/Maps/Map.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,12 +2744,18 @@ void Map::ProcessRespawns()
27442744

27452745
void Map::ProcessCreatureRespawn(ObjectGuid::LowType spawnId)
27462746
{
2747-
// Pool members are handled entirely by PoolMgr
2748-
if (uint32 poolId = sPoolMgr->IsPartOfAPool<Creature>(spawnId))
2747+
// Pool members in non-instanced maps are handled entirely by PoolMgr.
2748+
// In instanced maps the pool system operates globally and Spawn1Object is
2749+
// a no-op for instanceable maps, so fall through to the normal per-instance
2750+
// respawn logic instead.
2751+
if (!Instanceable())
27492752
{
2750-
sPoolMgr->UpdatePool<Creature>(poolId, spawnId);
2751-
RemoveCreatureRespawnTime(spawnId);
2752-
return;
2753+
if (uint32 poolId = sPoolMgr->IsPartOfAPool<Creature>(spawnId))
2754+
{
2755+
sPoolMgr->UpdatePool<Creature>(poolId, spawnId);
2756+
RemoveCreatureRespawnTime(spawnId);
2757+
return;
2758+
}
27532759
}
27542760

27552761
CreatureData const* data = sObjectMgr->GetCreatureData(spawnId);
@@ -2805,12 +2811,16 @@ void Map::ProcessCreatureRespawn(ObjectGuid::LowType spawnId)
28052811

28062812
void Map::ProcessGameObjectRespawn(ObjectGuid::LowType spawnId)
28072813
{
2808-
// Pool members are handled entirely by PoolMgr
2809-
if (uint32 poolId = sPoolMgr->IsPartOfAPool<GameObject>(spawnId))
2814+
// Same rationale as ProcessCreatureRespawn: pool management via PoolMgr is
2815+
// only meaningful for non-instanced maps where Spawn1Object actually spawns.
2816+
if (!Instanceable())
28102817
{
2811-
sPoolMgr->UpdatePool<GameObject>(poolId, spawnId);
2812-
RemoveGORespawnTime(spawnId);
2813-
return;
2818+
if (uint32 poolId = sPoolMgr->IsPartOfAPool<GameObject>(spawnId))
2819+
{
2820+
sPoolMgr->UpdatePool<GameObject>(poolId, spawnId);
2821+
RemoveGORespawnTime(spawnId);
2822+
return;
2823+
}
28142824
}
28152825

28162826
GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);

src/server/game/Miscellaneous/Language.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,25 @@ enum AcoreStrings
14891489
LANG_PET_DELETE_NOT_FOUND = 35438,
14901490
LANG_PET_DELETE_SUCCESS = 35439,
14911491

1492-
LANG_CHARACTER_DELETED_LIST_LIMIT = 35440
1492+
LANG_CHARACTER_DELETED_LIST_LIMIT = 35440,
1493+
1494+
// Respawn creature/gameobject by spawn GUID commands
1495+
LANG_RESPAWN_GUID_CREATURE_NOT_FOUND = 35441,
1496+
LANG_RESPAWN_GUID_MAP_NOT_LOADED = 35442,
1497+
LANG_RESPAWN_GUID_CREATURE_ALIVE = 35443,
1498+
LANG_RESPAWN_GUID_CREATURE_QUEUED = 35444,
1499+
LANG_RESPAWN_GUID_GAMEOBJECT_ACTIVE = 35445,
1500+
LANG_RESPAWN_GUID_GAMEOBJECT_QUEUED = 35446,
1501+
// 35447 is reserved for LANG_LIST_RESPAWNS_NO_MAP (list respawns command, defined at the end of this enum)
1502+
LANG_RESPAWN_GUID_GAMEOBJECT_NOT_FOUND = 35448,
1503+
1504+
// Respawn creature/gameobject by entry commands
1505+
LANG_RESPAWN_ENTRY_CREATURE_NOT_FOUND = 35449,
1506+
LANG_RESPAWN_ENTRY_GAMEOBJECT_NOT_FOUND = 35450,
1507+
LANG_RESPAWN_ENTRY_CREATURE_QUEUED = 35451,
1508+
LANG_RESPAWN_ENTRY_GAMEOBJECT_QUEUED = 35452,
1509+
1510+
// List respawns console support
1511+
LANG_LIST_RESPAWNS_NO_MAP = 35447
14931512
};
14941513
#endif

src/server/scripts/Commands/cs_list.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class list_commandscript : public CommandScript
5151
{ "item", HandleListItemCommand, rbac::RBAC_PERM_COMMAND_LIST_ITEM, Console::Yes },
5252
{ "object", HandleListObjectCommand, rbac::RBAC_PERM_COMMAND_LIST_OBJECT, Console::Yes },
5353
{ "auras", listAurasCommandTable },
54-
{ "respawns", HandleListRespawnsCommand, rbac::RBAC_PERM_COMMAND_LIST_CREATURE, Console::No },
54+
{ "respawns", HandleListRespawnsCommand, rbac::RBAC_PERM_COMMAND_LIST_RESPAWNS, Console::Yes },
5555
};
5656
static ChatCommandTable commandTable =
5757
{
@@ -521,21 +521,43 @@ class list_commandscript : public CommandScript
521521
return true;
522522
}
523523

524-
static bool HandleListRespawnsCommand(ChatHandler* handler)
524+
static bool HandleListRespawnsCommand(ChatHandler* handler, Optional<uint32> firstArg, Optional<uint32> secondArg, Optional<uint32> thirdArg)
525525
{
526-
Player* player = handler->GetSession()->GetPlayer();
527-
if (!player)
526+
Map* map = nullptr;
527+
Optional<uint32> entryFilter;
528+
529+
if (handler->GetSession())
530+
{
531+
// In-game: first arg = entryId (optional), use player's current map
532+
map = handler->GetSession()->GetPlayer()->GetMap();
533+
entryFilter = firstArg;
534+
}
535+
else
536+
{
537+
// Console: first arg = mapId (required), second = instanceId, third = entryId
538+
if (!firstArg)
539+
{
540+
handler->SendSysMessage(LANG_LIST_RESPAWNS_NO_MAP);
541+
return false;
542+
}
543+
map = sMapMgr->FindMap(*firstArg, secondArg.value_or(0));
544+
entryFilter = thirdArg;
545+
}
546+
547+
if (!map)
548+
{
549+
handler->PSendSysMessage(LANG_RESPAWN_GUID_MAP_NOT_LOADED, firstArg.value_or(0));
528550
return false;
551+
}
529552

530-
Map* map = player->GetMap();
531553
uint32 count = 0;
532554
time_t now = GameTime::GetGameTime().count();
533555

534556
handler->PSendSysMessage(LANG_LIST_RESPAWNS_CREATURE_HEADER, map->GetId(), map->GetInstanceId());
535557
for (auto const& pair : map->GetCreatureRespawnTimes())
536558
{
537559
CreatureData const* data = sObjectMgr->GetCreatureData(pair.first);
538-
if (!data)
560+
if (!data || (entryFilter && data->id1 != *entryFilter))
539561
continue;
540562

541563
CreatureTemplate const* cTemplate = sObjectMgr->GetCreatureTemplate(data->id1);
@@ -555,7 +577,7 @@ class list_commandscript : public CommandScript
555577
for (auto const& pair : map->GetGORespawnTimes())
556578
{
557579
GameObjectData const* data = sObjectMgr->GetGameObjectData(pair.first);
558-
if (!data)
580+
if (!data || (entryFilter && data->id != *entryFilter))
559581
continue;
560582

561583
GameObjectTemplate const* goTemplate = sObjectMgr->GetGameObjectTemplate(data->id);

0 commit comments

Comments
 (0)