fix(Core/GameObject): trigger chest traps once per loot generation (#27381)

This commit is contained in:
moostigre
2026-09-24 11:05:42 -03:00
committed by GitHub
parent d9245b189d
commit 46cc4c62a6
7 changed files with 688 additions and 5 deletions
@@ -0,0 +1,8 @@
--
-- Shallow Grave
-- Entry 128403 summons through its WDB-linked trap; entry 128308 is the inert alternative.
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 128308) AND (`source_type` = 1);
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 128403) AND (`source_type` = 1);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(128308, 1, 0, 0, 64, 0, 100, 1, 0, 0, 0, 0, 0, 41, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shallow Grave - On Gossip Hello - Despawn after 5 minutes'),
(128403, 1, 0, 0, 64, 0, 100, 1, 0, 0, 0, 0, 0, 41, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shallow Grave - On Gossip Hello - Despawn after 5 minutes');
@@ -0,0 +1,25 @@
-- Zul'Farrak grave summons: use the Loot Normalization (#24398) world loot pools.
-- Gultask's WotLK Classic research (builds 49822, 52237 and 54261):
-- https://github.com/azerothcore/azerothcore-wotlk/pull/27381#issuecomment-5798468763
-- Keep Troll Sweat, cloth, food, ZF junk and quest drops unchanged.
-- Remove direct world drops supplied by the normalized references to avoid duplicate rolls.
DELETE FROM `creature_loot_template` WHERE `Entry` IN (7276, 7286) AND `Reference` = 0 AND `Item` IN
(1685,3395,3831,3832,3864,3868,3873,3874,3914,3928,4300,4353,4416,4417,4419,4421,4422,4424,
4637,4638,5974,6149,7084,7085,7086,7453,7909,7910,7975,7989,7990,7992,7993,8029,8386,8387,
8389,8390,9293,9295,9298,10300,10301,10302,10312,10315,10320,10603,10604,10606,11167,11202,
11204,11208,11225,12684,13068);
DELETE FROM `creature_loot_template` WHERE `Entry` IN (7276, 7286) AND `Reference` <> 0;
INSERT INTO `creature_loot_template`
(`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(7276, 1, 1000145, 0, 0, 1, 5, 1, 1, 'Zul''Farrak Dead Hero - World Loot Level 45'),
(7276, 2, 1000146, 0, 0, 1, 5, 1, 1, 'Zul''Farrak Dead Hero - World Loot Level 46'),
(7286, 1, 1000343, 0, 0, 1, 5, 1, 1, 'Zul''Farrak Zombie - World Loot Level 43'),
(7286, 2, 1000344, 0, 0, 1, 5, 1, 1, 'Zul''Farrak Zombie - World Loot Level 44'),
(7286, 209, 1209000, 0.5, 0, 1, 0, 1, 1, 'Zul''Farrak Zombie - Zul''Farrak BoEs');
-- Money research from the same sniffs:
-- https://github.com/azerothcore/azerothcore-wotlk/pull/27381#issuecomment-5798878487
-- Zombie bounds are inferred from comparable level 44 ZF elites; keep Dead Hero money unchanged.
UPDATE `creature_template` SET `mingold` = 186, `maxgold` = 1438 WHERE `entry` = 7286;
-- Observed grave money range, in copper. This addon table has no VerifiedBuild column.
UPDATE `gameobject_template_addon` SET `mingold` = 18, `maxgold` = 131 WHERE `entry` IN (128308, 128403);
@@ -0,0 +1,215 @@
-- Shallow Grave alternatives from Gultask's Classic sniff research:
-- https://github.com/azerothcore/azerothcore-wotlk/pull/27381#issuecomment-5803161498
-- Each location has an inert (128308) or trapped (128403) grave, never both.
-- The 75% active / 25% inert weighting is inferred, not an exact measured probability.
-- Preserve existing spawn GUIDs and the one-day respawn; add only the alternate at each location.
DELETE FROM `gameobject` WHERE `guid` BETWEEN 27097 AND 27139 AND `id` IN (128308, 128403);
DELETE FROM `gameobject` WHERE `guid` BETWEEN 43921 AND 43960 AND `id` IN (128308, 128403);
INSERT INTO `gameobject`
(`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) VALUES
(43921, 128308, 209, 1176, 1176, 1, 1, 1832.719, 1032.393, 9.452, 0.5759572982788086, 0, 0, 0.2840147018432617, 0.9588199257850647, 86400, 100, 1, 49822),
(27114, 128403, 209, 1176, 1176, 1, 1, 1832.719, 1032.393, 9.452, 0.5759572982788086, 0, 0, 0.2840147018432617, 0.9588199257850647, 86400, 100, 1, 42940),
(27116, 128308, 209, 1176, 1176, 1, 1, 1836.745, 1029.358, 9.624, 0.9424766302108765, 0, 0, 0.45398998260498047, 0.8910067677497864, 86400, 100, 1, 49345),
(43922, 128403, 209, 1176, 1176, 1, 1, 1836.745, 1029.358, 9.624, 0.9424766302108765, 0, 0, 0.45398998260498047, 0.8910067677497864, 86400, 100, 1, 42940),
(43923, 128308, 209, 1176, 1176, 1, 1, 1839.181, 1036.884, 9.352, 4.607671737670898, 0, 0, -0.7431440353393555, 0.6691314578056335, 86400, 100, 1, 49822),
(27120, 128403, 209, 1176, 1176, 1, 1, 1839.181, 1036.884, 9.352, 4.607671737670898, 0, 0, -0.7431440353393555, 0.6691314578056335, 86400, 100, 1, 42940),
(43924, 128308, 209, 1176, 1176, 1, 1, 1839.422, 1023.486, 9.563, 2.9844982624053955, 0, 0, 0.9969167709350586, 0.07846643030643463, 86400, 100, 1, 44400),
(27102, 128403, 209, 1176, 1176, 1, 1, 1839.422, 1023.486, 9.563, 2.9844982624053955, 0, 0, 0.9969167709350586, 0.07846643030643463, 86400, 100, 1, 42940),
(43925, 128308, 209, 1176, 1176, 1, 1, 1841.083, 1045.543, 9.216, 3.0543265342712402, 0, 0, 0.9990482330322266, 0.04361926019191742, 86400, 100, 1, 49345),
(27115, 128403, 209, 1176, 1176, 1, 1, 1841.083, 1045.543, 9.216, 3.0543265342712402, 0, 0, 0.9990482330322266, 0.04361926019191742, 86400, 100, 1, 42940),
(43926, 128308, 209, 1176, 1176, 1, 1, 1841.821, 1027.759, 9.151, 0.9599299430847168, 0, 0, 0.4617481231689453, 0.8870111107826233, 86400, 100, 1, 49822),
(27119, 128403, 209, 1176, 1176, 1, 1, 1841.821, 1027.759, 9.151, 0.9599299430847168, 0, 0, 0.4617481231689453, 0.8870111107826233, 86400, 100, 1, 42940),
(43927, 128308, 209, 1176, 1176, 1, 1, 1843.193, 1041.155, 8.877, 5.881760597229004, 0, 0, -0.19936752319335938, 0.9799247980117798, 86400, 100, 1, 49345),
(27118, 128403, 209, 1176, 1176, 1, 1, 1843.193, 1041.155, 8.877, 5.881760597229004, 0, 0, -0.19936752319335938, 0.9799247980117798, 86400, 100, 1, 42940),
(43928, 128308, 209, 1176, 1176, 1, 1, 1845.539, 1024.121, 9.08, 0.9773830771446228, 0, 0, 0.4694709777832031, 0.8829479217529297, 86400, 100, 1, 49822),
(27121, 128403, 209, 1176, 1176, 1, 1, 1845.539, 1024.121, 9.08, 0.9773830771446228, 0, 0, 0.4694709777832031, 0.8829479217529297, 86400, 100, 1, 42940),
(43929, 128308, 209, 1176, 1176, 1, 1, 1845.959, 1047.25, 8.877, 5.829400539398193, 0, 0, -0.22495079040527344, 0.9743701219558716, 86400, 100, 1, 44400),
(27133, 128403, 209, 1176, 1176, 1, 1, 1845.959, 1047.25, 8.877, 5.829400539398193, 0, 0, -0.22495079040527344, 0.9743701219558716, 86400, 100, 1, 42940),
(43930, 128308, 209, 1176, 1176, 1, 1, 1852.408, 1024.781, 8.877, 3.787367343902588, 0, 0, -0.9483232498168945, 0.31730589270591736, 86400, 100, 1, 49822),
(27117, 128403, 209, 1176, 1176, 1, 1, 1852.408, 1024.781, 8.877, 3.787367343902588, 0, 0, -0.9483232498168945, 0.31730589270591736, 86400, 100, 1, 42940),
(43931, 128308, 209, 1176, 1176, 1, 1, 1858.698, 1053.75, 8.877, 3.5430235862731934, 0, 0, -0.979924201965332, 0.1993703842163086, 86400, 100, 1, 44400),
(27134, 128403, 209, 1176, 1176, 1, 1, 1858.698, 1053.75, 8.877, 3.5430235862731934, 0, 0, -0.979924201965332, 0.1993703842163086, 86400, 100, 1, 42940),
(43932, 128308, 209, 1176, 1176, 1, 1, 1861.116, 1019.389, 8.877, 5.096362113952637, 0, 0, -0.5591926574707031, 0.8290377259254456, 86400, 100, 1, 49822),
(27103, 128403, 209, 1176, 1176, 1, 1, 1861.116, 1019.389, 8.877, 5.096362113952637, 0, 0, -0.5591926574707031, 0.8290377259254456, 86400, 100, 1, 42940),
(43933, 128308, 209, 1176, 1176, 1, 1, 1862.12, 1050.756, 9.057, 3.892086982727051, 0, 0, -0.9304170608520508, 0.3665024936199188, 86400, 100, 1, 42940),
(27135, 128403, 209, 1176, 1176, 1, 1, 1862.12, 1050.756, 9.057, 3.892086982727051, 0, 0, -0.9304170608520508, 0.3665024936199188, 86400, 100, 1, 44400),
(27122, 128308, 209, 1176, 1176, 1, 1, 1863.409, 1044.78, 8.877, 4.572763919830322, 0, 0, -0.7547092437744141, 0.6560594439506531, 86400, 100, 1, 42940),
(43934, 128403, 209, 1176, 1176, 1, 1, 1863.409, 1044.78, 8.877, 4.572763919830322, 0, 0, -0.7547092437744141, 0.6560594439506531, 86400, 100, 1, 49345),
(43935, 128308, 209, 1176, 1176, 1, 1, 1865.033, 1012.491, 8.877, 1.0471975803375244, 0, 0, 0.5, 0.8660253882408142, 86400, 100, 1, 52237),
(27105, 128403, 209, 1176, 1176, 1, 1, 1865.033, 1012.491, 8.877, 1.0471975803375244, 0, 0, 0.5, 0.8660253882408142, 86400, 100, 1, 42940),
(43936, 128308, 209, 1176, 1176, 1, 1, 1866.235, 1008.397, 8.877, 0.6632232069969177, 0, 0, 0.32556724548339844, 0.9455188512802124, 86400, 100, 1, 44400),
(27104, 128403, 209, 1176, 1176, 1, 1, 1866.235, 1008.397, 8.877, 0.6632232069969177, 0, 0, 0.32556724548339844, 0.9455188512802124, 86400, 100, 1, 42940),
(27136, 128308, 209, 1176, 1176, 1, 1, 1866.326, 1049.636, 9.015, 1.1170092821121216, 0, 0, 0.5299186706542969, 0.8480484485626221, 86400, 100, 1, 44400),
(43937, 128403, 209, 1176, 1176, 1, 1, 1866.326, 1049.636, 9.015, 1.1170092821121216, 0, 0, 0.5299186706542969, 0.8480484485626221, 86400, 100, 1, 42940),
(43938, 128308, 209, 1176, 1176, 1, 1, 1867.745, 1041.844, 8.877, 5.846853733062744, 0, 0, -0.21643924713134766, 0.976296067237854, 86400, 100, 1, 49822),
(27126, 128403, 209, 1176, 1176, 1, 1, 1867.745, 1041.844, 8.877, 5.846853733062744, 0, 0, -0.21643924713134766, 0.976296067237854, 86400, 100, 1, 42940),
(27127, 128308, 209, 1176, 1176, 1, 1, 1869.284, 1020.079, 8.877, 5.794494152069092, 0, 0, -0.24192142486572266, 0.9702958464622498, 86400, 100, 1, 49345),
(43939, 128403, 209, 1176, 1176, 1, 1, 1869.284, 1020.079, 8.877, 5.794494152069092, 0, 0, -0.24192142486572266, 0.9702958464622498, 86400, 100, 1, 42940),
(43940, 128308, 209, 1176, 1176, 1, 1, 1871.077, 1046.756, 9.034, 4.118979454040527, 0, 0, -0.8829469680786133, 0.4694727063179016, 86400, 100, 1, 52237),
(27138, 128403, 209, 1176, 1176, 1, 1, 1871.077, 1046.756, 9.034, 4.118979454040527, 0, 0, -0.8829469680786133, 0.4694727063179016, 86400, 100, 1, 42940),
(43941, 128308, 209, 1176, 1176, 1, 1, 1871.296, 1008.323, 8.877, 1.08210289478302, 0, 0, 0.5150375366210938, 0.8571676015853882, 86400, 100, 1, 54558),
(27113, 128403, 209, 1176, 1176, 1, 1, 1871.296, 1008.323, 8.877, 1.08210289478302, 0, 0, 0.5150375366210938, 0.8571676015853882, 86400, 100, 1, 42940),
(43942, 128308, 209, 1176, 1176, 1, 1, 1871.855, 994.256, 8.882, 0.5061445832252502, 0, 0, 0.2503795623779297, 0.9681477546691895, 86400, 100, 1, 49822),
(27111, 128403, 209, 1176, 1176, 1, 1, 1871.855, 994.256, 8.882, 0.5061445832252502, 0, 0, 0.2503795623779297, 0.9681477546691895, 86400, 100, 1, 42940),
(43943, 128308, 209, 1176, 1176, 1, 1, 1875.847, 1044.261, 9.078, 0.855210542678833, 0, 0, 0.41469287872314453, 0.909961462020874, 86400, 100, 1, 52237),
(27139, 128403, 209, 1176, 1176, 1, 1, 1875.847, 1044.261, 9.078, 0.855210542678833, 0, 0, 0.41469287872314453, 0.909961462020874, 86400, 100, 1, 42940),
(27101, 128308, 209, 1176, 1176, 1, 1, 1876.138, 976.482, 9.052, 1.0122894048690796, 0, 0, 0.48480892181396484, 0.8746200799942017, 86400, 100, 1, 52237),
(43944, 128403, 209, 1176, 1176, 1, 1, 1876.138, 976.482, 9.052, 1.0122894048690796, 0, 0, 0.48480892181396484, 0.8746200799942017, 86400, 100, 1, 42940),
(43945, 128308, 209, 1176, 1176, 1, 1, 1876.44, 972.207, 9.912, 2.8448827266693115, 0, 0, 0.9890155792236328, 0.14781136810779572, 86400, 100, 1, 42940),
(27099, 128403, 209, 1176, 1176, 1, 1, 1876.44, 972.207, 9.912, 2.8448827266693115, 0, 0, 0.9890155792236328, 0.14781136810779572, 86400, 100, 1, 49345),
(43946, 128308, 209, 1176, 1176, 1, 1, 1879.89, 974.651, 8.877, 1.0471975803375244, 0, 0, 0.5, 0.8660253882408142, 86400, 100, 1, 42940),
(27098, 128403, 209, 1176, 1176, 1, 1, 1879.89, 974.651, 8.877, 1.0471975803375244, 0, 0, 0.5, 0.8660253882408142, 86400, 100, 1, 49345),
(43947, 128308, 209, 1176, 1176, 1, 1, 1881.465, 1041.431, 8.877, 4.084071159362793, 0, 0, -0.8910064697265625, 0.453990638256073, 86400, 100, 1, 42940),
(27137, 128403, 209, 1176, 1176, 1, 1, 1881.465, 1041.431, 8.877, 4.084071159362793, 0, 0, -0.8910064697265625, 0.453990638256073, 86400, 100, 1, 44400),
(43948, 128308, 209, 1176, 1176, 1, 1, 1881.989, 1034.684, 8.877, 5.829400539398193, 0, 0, -0.22495079040527344, 0.9743701219558716, 86400, 100, 1, 54261),
(27131, 128403, 209, 1176, 1176, 1, 1, 1881.989, 1034.684, 8.877, 5.829400539398193, 0, 0, -0.22495079040527344, 0.9743701219558716, 86400, 100, 1, 42940),
(43949, 128308, 209, 1176, 1176, 1, 1, 1882.703, 971.825, 8.877, 0.9948371648788452, 0, 0, 0.4771585464477539, 0.8788172602653503, 86400, 100, 1, 44400),
(27100, 128403, 209, 1176, 1176, 1, 1, 1882.703, 971.825, 8.877, 0.9948371648788452, 0, 0, 0.4771585464477539, 0.8788172602653503, 86400, 100, 1, 42940),
(43950, 128308, 209, 1176, 1176, 1, 1, 1887.458, 967.143, 8.985, 5.969027042388916, 0, 0, -0.1564340591430664, 0.9876883625984192, 86400, 100, 1, 42940),
(27097, 128403, 209, 1176, 1176, 1, 1, 1887.458, 967.143, 8.985, 5.969027042388916, 0, 0, -0.1564340591430664, 0.9876883625984192, 86400, 100, 1, 49345),
(43951, 128308, 209, 1176, 1176, 1, 1, 1887.94, 1029.084, 9.148, 0.855210542678833, 0, 0, 0.41469287872314453, 0.909961462020874, 86400, 100, 1, 49822),
(27128, 128403, 209, 1176, 1176, 1, 1, 1887.94, 1029.084, 9.148, 0.855210542678833, 0, 0, 0.41469287872314453, 0.909961462020874, 86400, 100, 1, 42940),
(43952, 128308, 209, 1176, 1176, 1, 1, 1888.363, 1037.002, 8.921, 4.293513298034668, 0, 0, -0.8386697769165039, 0.5446402430534363, 86400, 100, 1, 42940),
(27130, 128403, 209, 1176, 1176, 1, 1, 1888.363, 1037.002, 8.921, 4.293513298034668, 0, 0, -0.8386697769165039, 0.5446402430534363, 86400, 100, 1, 44400),
(27110, 128308, 209, 1176, 1176, 1, 1, 1888.636, 977.75, 8.877, 3.7175536155700684, 0, 0, -0.9588193893432617, 0.2840164601802826, 86400, 100, 1, 49822),
(43953, 128403, 209, 1176, 1176, 1, 1, 1888.636, 977.75, 8.877, 3.7175536155700684, 0, 0, -0.9588193893432617, 0.2840164601802826, 86400, 100, 1, 42940),
(43954, 128308, 209, 1176, 1176, 1, 1, 1890.123, 989.759, 8.877, 2.7052552700042725, 0, 0, 0.9762954711914062, 0.2164420634508133, 86400, 100, 1, 49345),
(27106, 128403, 209, 1176, 1176, 1, 1, 1890.123, 989.759, 8.877, 2.7052552700042725, 0, 0, 0.9762954711914062, 0.2164420634508133, 86400, 100, 1, 42940),
(27112, 128308, 209, 1176, 1176, 1, 1, 1890.268, 970.862, 9.014, 2.565631866455078, 0, 0, 0.9588193893432617, 0.2840164601802826, 86400, 100, 1, 42940),
(43955, 128403, 209, 1176, 1176, 1, 1, 1890.268, 970.862, 9.014, 2.565631866455078, 0, 0, 0.9588193893432617, 0.2840164601802826, 86400, 100, 1, 44400),
(43956, 128308, 209, 1176, 1176, 1, 1, 1891.598, 1023.06, 9.371, 2.792518377304077, 0, 0, 0.984807014465332, 0.1736523061990738, 86400, 100, 1, 49822),
(27132, 128403, 209, 1176, 1176, 1, 1, 1891.598, 1023.06, 9.371, 2.792518377304077, 0, 0, 0.984807014465332, 0.1736523061990738, 86400, 100, 1, 42940),
(43957, 128308, 209, 1176, 1176, 1, 1, 1892.571, 1006.369, 9.068, 4.1538848876953125, 0, 0, -0.8746194839477539, 0.4848100543022156, 86400, 100, 1, 49345),
(27129, 128403, 209, 1176, 1176, 1, 1, 1892.571, 1006.369, 9.068, 4.1538848876953125, 0, 0, -0.8746194839477539, 0.4848100543022156, 86400, 100, 1, 42940),
(43958, 128308, 209, 1176, 1176, 1, 1, 1894.394, 977.006, 8.926, 6.003933906555176, 0, 0, -0.13917255401611328, 0.9902681708335876, 86400, 100, 1, 42940),
(27108, 128403, 209, 1176, 1176, 1, 1, 1894.394, 977.006, 8.926, 6.003933906555176, 0, 0, -0.13917255401611328, 0.9902681708335876, 86400, 100, 1, 44400),
(27107, 128308, 209, 1176, 1176, 1, 1, 1897.079, 980.836, 8.959, 3.298687219619751, 0, 0, -0.9969167709350586, 0.07846643030643463, 86400, 100, 1, 42940),
(43959, 128403, 209, 1176, 1176, 1, 1, 1897.079, 980.836, 8.959, 3.298687219619751, 0, 0, -0.9969167709350586, 0.07846643030643463, 86400, 100, 1, 49345),
(27109, 128308, 209, 1176, 1176, 1, 1, 1897.983, 985.276, 8.898, 2.757613182067871, 0, 0, 0.9816265106201172, 0.19081240892410278, 86400, 100, 1, 59415),
(43960, 128403, 209, 1176, 1176, 1, 1, 1897.983, 985.276, 8.898, 2.757613182067871, 0, 0, 0.9816265106201172, 0.19081240892410278, 86400, 100, 1, 42940);
DELETE FROM `pool_template` WHERE `entry` BETWEEN 1121 AND 1160;
INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES
(1121, 1, 'Zul''Farrak - Shallow Grave 1'),
(1122, 1, 'Zul''Farrak - Shallow Grave 2'),
(1123, 1, 'Zul''Farrak - Shallow Grave 3'),
(1124, 1, 'Zul''Farrak - Shallow Grave 4'),
(1125, 1, 'Zul''Farrak - Shallow Grave 5'),
(1126, 1, 'Zul''Farrak - Shallow Grave 6'),
(1127, 1, 'Zul''Farrak - Shallow Grave 7'),
(1128, 1, 'Zul''Farrak - Shallow Grave 8'),
(1129, 1, 'Zul''Farrak - Shallow Grave 9'),
(1130, 1, 'Zul''Farrak - Shallow Grave 10'),
(1131, 1, 'Zul''Farrak - Shallow Grave 11'),
(1132, 1, 'Zul''Farrak - Shallow Grave 12'),
(1133, 1, 'Zul''Farrak - Shallow Grave 13'),
(1134, 1, 'Zul''Farrak - Shallow Grave 14'),
(1135, 1, 'Zul''Farrak - Shallow Grave 15'),
(1136, 1, 'Zul''Farrak - Shallow Grave 16'),
(1137, 1, 'Zul''Farrak - Shallow Grave 17'),
(1138, 1, 'Zul''Farrak - Shallow Grave 18'),
(1139, 1, 'Zul''Farrak - Shallow Grave 19'),
(1140, 1, 'Zul''Farrak - Shallow Grave 20'),
(1141, 1, 'Zul''Farrak - Shallow Grave 21'),
(1142, 1, 'Zul''Farrak - Shallow Grave 22'),
(1143, 1, 'Zul''Farrak - Shallow Grave 23'),
(1144, 1, 'Zul''Farrak - Shallow Grave 24'),
(1145, 1, 'Zul''Farrak - Shallow Grave 25'),
(1146, 1, 'Zul''Farrak - Shallow Grave 26'),
(1147, 1, 'Zul''Farrak - Shallow Grave 27'),
(1148, 1, 'Zul''Farrak - Shallow Grave 28'),
(1149, 1, 'Zul''Farrak - Shallow Grave 29'),
(1150, 1, 'Zul''Farrak - Shallow Grave 30'),
(1151, 1, 'Zul''Farrak - Shallow Grave 31'),
(1152, 1, 'Zul''Farrak - Shallow Grave 32'),
(1153, 1, 'Zul''Farrak - Shallow Grave 33'),
(1154, 1, 'Zul''Farrak - Shallow Grave 34'),
(1155, 1, 'Zul''Farrak - Shallow Grave 35'),
(1156, 1, 'Zul''Farrak - Shallow Grave 36'),
(1157, 1, 'Zul''Farrak - Shallow Grave 37'),
(1158, 1, 'Zul''Farrak - Shallow Grave 38'),
(1159, 1, 'Zul''Farrak - Shallow Grave 39'),
(1160, 1, 'Zul''Farrak - Shallow Grave 40');
DELETE FROM `pool_gameobject` WHERE `pool_entry` BETWEEN 1121 AND 1160;
INSERT INTO `pool_gameobject` (`guid`, `pool_entry`, `chance`, `description`) VALUES
(43921, 1121, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27114, 1121, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27116, 1122, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43922, 1122, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43923, 1123, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27120, 1123, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43924, 1124, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27102, 1124, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43925, 1125, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27115, 1125, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43926, 1126, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27119, 1126, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43927, 1127, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27118, 1127, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43928, 1128, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27121, 1128, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43929, 1129, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27133, 1129, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43930, 1130, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27117, 1130, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43931, 1131, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27134, 1131, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43932, 1132, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27103, 1132, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43933, 1133, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27135, 1133, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27122, 1134, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43934, 1134, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43935, 1135, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27105, 1135, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43936, 1136, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27104, 1136, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27136, 1137, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43937, 1137, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43938, 1138, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27126, 1138, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27127, 1139, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43939, 1139, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43940, 1140, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27138, 1140, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43941, 1141, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27113, 1141, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43942, 1142, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27111, 1142, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43943, 1143, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27139, 1143, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27101, 1144, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43944, 1144, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43945, 1145, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27099, 1145, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43946, 1146, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27098, 1146, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43947, 1147, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27137, 1147, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43948, 1148, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27131, 1148, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43949, 1149, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27100, 1149, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43950, 1150, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27097, 1150, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43951, 1151, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27128, 1151, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43952, 1152, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27130, 1152, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27110, 1153, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43953, 1153, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43954, 1154, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27106, 1154, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27112, 1155, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43955, 1155, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43956, 1156, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27132, 1156, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43957, 1157, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27129, 1157, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(43958, 1158, 25, 'Zul''Farrak - Inert Shallow Grave'),
(27108, 1158, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27107, 1159, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43959, 1159, 75, 'Zul''Farrak - Trapped Shallow Grave'),
(27109, 1160, 25, 'Zul''Farrak - Inert Shallow Grave'),
(43960, 1160, 75, 'Zul''Farrak - Trapped Shallow Grave');
+18
View File
@@ -171,6 +171,24 @@ go test -tags=e2e ./local/... -count=1 -v -timeout 30m -parallel 1
---
### Chest regression checks (PR #27381)
`world/chests` covers Cat Figurine reopening, Ice Chest party rolls and reward attribution,
and both Shallow Grave variants: inert graves summon nothing; trapped graves do not summon
again on reopening. Grave checks include full bags, another looter, consuming all loot,
and replaying an opening request after despawn. Live execution is still pending.
```bash
go test -tags=e2e ./suites/world/chests -count=2 -v -p 1 -parallel 1 -timeout 20m
```
Use a disposable realm with the pending migrations applied. Tests create temporary fixtures
through cleanup-enabled spawn helpers, not the dungeon's real graves. They sample up to
48 fresh graves for item loot and a positive summon from the trapped variant; inability to
obtain that fixture fails as a precondition. Initial empty-loot coverage is not claimed:
the grave money range is now nonzero. Exact summon/drop probabilities and the dungeon's
pool selection are not asserted by these lifecycle tests.
## Parallelism and isolation
### Model
+417
View File
@@ -0,0 +1,417 @@
//go:build e2e
package chests_test
import (
"encoding/binary"
"fmt"
"reflect"
"testing"
"time"
"github.com/azerothcore/AzerothGhost/client"
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
_ "github.com/go-sql-driver/mysql"
)
// PR: https://github.com/azerothcore/azerothcore-wotlk/pull/27381
// Use fresh, cleaned-up spawns at an isolation pad, never the dungeon's real graves.
// These are chest lifecycle tests, not tests of Ahune or Zum'rah's encounter.
func chestBots(t *testing.T) (actor, mate, observer *e2eharness.ScenarioBot) {
t.Helper()
bots := e2eharness.NewScenario(t, e2eharness.ScenarioOpts{
Prefix: "Chests", Count: 3, Race: e2eharness.RaceHuman, Class: e2eharness.ClassWarrior, Level: 80,
})
actor, mate, observer = bots[0], bots[1], bots[2]
pad := e2eharness.PackagePad(t)
e2eharness.FormPartyAtPad(t, pad, actor, mate)
observer.TeleportPad(t, pad)
// The Ice Chest's bunny is an invisible trigger; a separate GM observes it.
// Neither looter gets GM-mode loot privileges.
observer.GM(t, ".gm on")
observer.FlushWorld(t)
actor.CombatReady(t)
mate.CombatReady(t)
return
}
func spawnChest(t *testing.T, observer, actor *e2eharness.ScenarioBot, entry uint32) uint64 {
t.Helper()
if observer.SpawnGameObject(t, entry) == 0 {
e2eharness.Preconditionf(t, "cannot resolve cleanup spawn ID for chest %d", entry)
}
return actor.WaitGameObject(t, entry, 10*time.Second)
}
type chestLoot struct {
gold uint32
items []client.LootItem
}
// v1.0.8 has no gameobject-target cast helper. Use its raw packet API, with the
// same CMSG_CAST_SPELL layout read by WorldSession::HandleCastSpellOpcode.
// CMSG_LOOT bypasses Spell::SendLoot; CMSG_GAMEOBJ_USE alone does not open a chest.
func castOpening(t *testing.T, bot *e2eharness.ScenarioBot, guid uint64, spell uint32) {
t.Helper()
payload := make([]byte, 11) // cast count, spell, cast flags, target flags, packed-GUID mask
binary.LittleEndian.PutUint32(payload[1:5], spell)
binary.LittleEndian.PutUint32(payload[6:10], 0x0800) // TARGET_FLAG_GAMEOBJECT
for i := uint(0); i < 8; i++ {
if b := byte(guid >> (8 * i)); b != 0 {
payload[10] |= 1 << i
payload = append(payload, b)
}
}
if err := bot.World.SendPacketRaw(client.CmsgCastSpell, payload); err != nil {
e2eharness.HarnessFailf(t, "Opening packet: %v", err)
}
}
func openChest(t *testing.T, bot *e2eharness.ScenarioBot, guid uint64, spell uint32) chestLoot {
t.Helper()
packets := make(chan []byte, 1)
cancel := bot.World.AddPacketHook(func(op uint16, data []byte) {
if op == client.SmsgLootResponse && len(data) >= 8 && binary.LittleEndian.Uint64(data) == guid {
select {
case packets <- append([]byte(nil), data...):
default:
}
}
})
defer cancel()
castOpening(t, bot, guid, spell)
select {
case data := <-packets:
if len(data) < 14 || len(data) < 14+22*int(data[13]) {
e2eharness.Assertf(t, "chest 0x%X rejected opening or returned malformed loot: %x", guid, data)
}
result := chestLoot{gold: binary.LittleEndian.Uint32(data[9:13])}
for i := 0; i < int(data[13]); i++ {
row := data[14+i*22:]
result.items = append(result.items, client.LootItem{
Index: row[0], ItemID: binary.LittleEndian.Uint32(row[1:5]), Quantity: binary.LittleEndian.Uint32(row[5:9]),
})
}
return result
case <-time.After(12 * time.Second):
e2eharness.Assertf(t, "chest 0x%X: no loot response to Opening spell %d", guid, spell)
return chestLoot{}
}
}
func closeChest(t *testing.T, bot *e2eharness.ScenarioBot, guid uint64) {
t.Helper()
ack := make(chan struct{}, 1)
cancel := bot.World.AddPacketHook(func(op uint16, data []byte) {
if op == client.SmsgLootReleaseResponse && len(data) >= 8 && binary.LittleEndian.Uint64(data) == guid {
select {
case ack <- struct{}{}:
default:
}
}
})
defer cancel()
bot.LootRelease(t, guid)
select {
case <-ack:
case <-time.After(5 * time.Second):
e2eharness.HarnessFailf(t, "no loot release acknowledgement for 0x%X", guid)
}
}
func waitChestGone(t *testing.T, bot *e2eharness.ScenarioBot, guid uint64) {
t.Helper()
deadline := time.Now().Add(5 * time.Second)
for bot.World.GetObject(guid) != nil {
if time.Now().After(deadline) {
e2eharness.Assertf(t, "consumed/deleted chest 0x%X remained visible", guid)
}
time.Sleep(25 * time.Millisecond)
}
}
// Count GUIDs, not surviving creatures: dying/despawning must not conceal a
// repeated summon. Only new units of the fixture's entries are cleaned up.
type summonObserver struct {
bot *e2eharness.ScenarioBot
entries map[uint32]bool
seen map[uint64]bool
owned map[uint64]bool
}
func observeSummons(t *testing.T, bot *e2eharness.ScenarioBot, entries ...uint32) *summonObserver {
t.Helper()
o := &summonObserver{bot: bot, entries: map[uint32]bool{}, seen: map[uint64]bool{}, owned: map[uint64]bool{}}
for _, entry := range entries {
o.entries[entry] = true
}
o.scan()
o.owned = map[uint64]bool{} // existing units are not ours
t.Cleanup(func() { o.clean(t) })
return o
}
func (o *summonObserver) scan() {
for _, unit := range o.bot.World.GetNearbyUnits(100) {
if o.entries[unit.Entry] && !o.seen[unit.GUID] {
o.seen[unit.GUID], o.owned[unit.GUID] = true, true
}
}
}
func (o *summonObserver) watch(duration time.Duration) {
deadline := time.Now().Add(duration)
for time.Now().Before(deadline) {
o.scan()
time.Sleep(25 * time.Millisecond)
}
o.scan()
}
func (o *summonObserver) clean(t *testing.T) {
t.Helper()
o.scan()
for guid := range o.owned {
if o.bot.World.GetObject(guid) != nil {
if err := o.bot.World.SetTarget(guid); err != nil {
e2eharness.HarnessFailf(t, "select fixture summon: %v", err)
}
o.bot.FlushWorld(t)
o.bot.GM(t, ".npc delete")
o.bot.FlushWorld(t)
}
delete(o.owned, guid)
}
}
func (o *summonObserver) unchanged(t *testing.T, baseline int) {
t.Helper()
// A bounded negative observation window also lets delayed object updates arrive.
o.watch(2 * time.Second)
if len(o.seen) != baseline {
e2eharness.Assertf(t, "reopening summoned new creatures: distinct GUIDs %d -> %d", baseline, len(o.seen))
}
}
func TestChests_CatFigurineReopen(t *testing.T) {
meta.Begin(t, meta.TestMeta{Tags: []string{"med", "loot", "serial"}, Runtime: "med", Category: "world/chests"})
actor, _, observer := chestBots(t)
o := observeSummons(t, observer, 3619)
guid := spawnChest(t, observer, actor, 13873)
before := len(o.seen)
first := openChest(t, actor, guid, 3365) // lock type 5, Opening
o.watch(2 * time.Second)
baseline := len(o.seen)
if baseline == before || len(first.items) != 1 || first.items[0].ItemID != 5329 {
e2eharness.Assertf(t, "Cat Figurine must summon Ghost Saber(s) and offer item 5329: summons=%d loot=%+v", baseline-before, first)
}
// Existing SAI also casts 5968; this test deliberately does not assert one saber.
closeChest(t, actor, guid)
o.clean(t)
for i := 0; i < 3; i++ {
got := openChest(t, actor, guid, 3365)
if !reflect.DeepEqual(got, first) {
e2eharness.Assertf(t, "unclaimed figurine loot changed on reopen: %+v -> %+v", first, got)
}
o.unchanged(t, baseline)
closeChest(t, actor, guid)
}
t.Log("PASS Cat Figurine summons on first opening; unclaimed loot survives without repeat summons")
}
func fillBackpack(t *testing.T, bot *e2eharness.ScenarioBot) {
t.Helper()
bot.Save(t)
var bags, used int
if err := bot.CharDB.QueryRow("SELECT COUNT(*) FROM character_inventory WHERE guid = ? AND bag = 0 AND slot BETWEEN 19 AND 22", bot.GUID).Scan(&bags); err != nil {
e2eharness.HarnessFailf(t, "bag query: %v", err)
}
if bags != 0 {
e2eharness.Preconditionf(t, "full-bag fixture expects a fresh character without equipped bags")
}
if err := bot.CharDB.QueryRow("SELECT COUNT(*) FROM character_inventory WHERE guid = ? AND bag = 0 AND slot BETWEEN 23 AND 38", bot.GUID).Scan(&used); err != nil {
e2eharness.HarnessFailf(t, "backpack query: %v", err)
}
if used < 16 {
if err := bot.World.SetTarget(0); err != nil {
e2eharness.HarnessFailf(t, "clear item-command target: %v", err)
}
bot.FlushWorld(t)
bot.GM(t, fmt.Sprintf(".additem 38 %d", 16-used)) // non-stackable Recruit's Shirt
bot.FlushWorld(t)
}
}
func assertBagFull(t *testing.T, bot *e2eharness.ScenarioBot, slot uint8) {
t.Helper()
ch := make(chan byte, 1)
cancel := bot.World.AddPacketHook(func(op uint16, data []byte) {
if op == 0x0112 && len(data) > 0 { // SMSG_INVENTORY_CHANGE_FAILURE
select {
case ch <- data[0]:
default:
}
}
})
defer cancel()
bot.LootTakeItem(t, slot)
select {
case reason := <-ch:
if reason != 50 { // EQUIP_ERR_INVENTORY_FULL
e2eharness.Preconditionf(t, "expected inventory-full error, got %d", reason)
}
case <-time.After(5 * time.Second):
e2eharness.Assertf(t, "taking grave loot with full bags did not return inventory-full error")
}
}
// Issues: https://github.com/azerothcore/azerothcore-wotlk/issues/24692
//
// https://github.com/azerothcore/azerothcore-wotlk/issues/12433
func TestAC_24692_ShallowGraveLifecycle(t *testing.T) {
meta.Begin(t, meta.TestMeta{Tags: []string{"med", "loot", "issue", "serial"}, Runtime: "med", Category: "world/chests", Issue: 24692})
for _, entry := range []uint32{128308, 128403} {
t.Run(fmt.Sprint(entry), func(t *testing.T) {
actor, mate, observer := chestBots(t)
actor.SetLootMethod(t, client.LootMethodFreeForAll, 0, e2eharness.LootThresholdUncommon)
actor.WaitLootMethod(t, client.LootMethodFreeForAll, 5*time.Second)
fillBackpack(t, actor)
o := observeSummons(t, observer, 7286, 7276)
covered := false
// Sample stock item loot and, for the trapped variant, a positive summon
// roll. Money is now always present; an initially empty grave is not a fixture.
for attempt := 0; attempt < 48 && !covered; attempt++ {
sid := observer.SpawnGameObject(t, entry)
if sid == 0 {
e2eharness.Preconditionf(t, "cannot resolve grave spawn for cleanup")
}
guid := actor.WaitGameObject(t, entry, 10*time.Second)
before := len(o.seen)
first := openChest(t, actor, guid, 6247) // lock type 10, Opening (no text)
o.watch(2 * time.Second)
baseline := len(o.seen)
if entry == 128308 && baseline != before {
e2eharness.ConfirmedBugf(t, 24692, "inert grave summoned %d creatures", baseline-before)
}
if len(first.items) == 0 || (entry == 128403 && baseline == before) {
closeChest(t, actor, guid)
o.clean(t)
observer.DespawnGameObjectSpawn(t, sid)
waitChestGone(t, actor, guid)
continue
}
assertBagFull(t, actor, first.items[0].Index)
closeChest(t, actor, guid)
o.clean(t)
for reopen := 0; reopen < 6; reopen++ {
looter := actor
if reopen%2 == 1 {
looter = mate
}
got := openChest(t, looter, guid, 6247)
if !reflect.DeepEqual(got, first) {
e2eharness.Assertf(t, "grave %d changed unclaimed loot: %+v -> %+v", entry, first, got)
}
closeChest(t, looter, guid)
o.unchanged(t, baseline)
}
// A different player can still collect everything left by full bags.
loot := openChest(t, mate, guid, 6247)
for _, item := range loot.items {
count := mate.InventoryCount(t, item.ItemID)
mate.LootTakeItem(t, item.Index)
mate.FlushWorld(t)
if got := mate.InventoryCount(t, item.ItemID); got != count+int(item.Quantity) {
e2eharness.Assertf(t, "grave %d item %d was not credited: %d -> %d", entry, item.ItemID, count, got)
}
}
if loot.gold != 0 {
if err := mate.World.SendPacketRaw(0x015E, nil); err != nil { // CMSG_LOOT_MONEY
e2eharness.HarnessFailf(t, "loot grave money: %v", err)
}
mate.FlushWorld(t)
}
closeChest(t, mate, guid)
waitChestGone(t, mate, guid)
// A stale opening request must not produce another wave after consumption.
castOpening(t, mate, guid, 6247)
mate.FlushWorld(t)
o.unchanged(t, baseline)
covered = true
observer.DespawnGameObjectSpawn(t, sid)
waitChestGone(t, actor, guid)
t.Logf("PASS grave %d initial summons=%d; six reopens and a consumed-GUID request added none", entry, baseline-before)
}
if !covered {
e2eharness.Preconditionf(t, "48 fresh graves did not produce an item-loot fixture with the required active/inert behavior")
}
})
}
}
func TestChests_IceChestGroupLoot(t *testing.T) {
meta.Begin(t, meta.TestMeta{Tags: []string{"med", "loot", "multi_bot", "serial"}, Runtime: "med", Category: "world/chests"})
actor, mate, observer := chestBots(t)
actor.SetLootMethod(t, client.LootMethodGroupLoot, 0, e2eharness.LootThresholdUncommon)
actor.WaitLootMethod(t, client.LootMethodGroupLoot, 5*time.Second)
o := observeSummons(t, observer, 26391)
guid := spawnChest(t, observer, actor, 187892)
waitActor, cancelActor := actor.ArmLootStartRoll()
defer cancelActor()
waitMate, cancelMate := mate.ArmLootStartRoll()
defer cancelMate()
before := len(o.seen)
loot := openChest(t, actor, guid, 6247)
var reward uint32
for _, item := range loot.items {
if item.ItemID >= 54801 && item.ItemID <= 54805 {
reward = item.ItemID
}
}
if reward == 0 {
e2eharness.Assertf(t, "Ice Chest did not offer one of its guaranteed cloaks: %+v", loot.items)
}
roll, ok := waitActor(reward, 10*time.Second)
if !ok {
e2eharness.Assertf(t, "Ice Chest did not start a group roll for its epic reward")
}
otherRoll, ok := waitMate(roll.ItemID, 10*time.Second)
if !ok || otherRoll.ItemGUID != roll.ItemGUID || otherRoll.ItemSlot != roll.ItemSlot {
e2eharness.Assertf(t, "party members did not receive the same Ice Chest roll")
}
o.watch(time.Second)
baseline := len(o.seen)
if baseline-before != 1 {
e2eharness.Assertf(t, "Ice Chest should summon its bunny on initial opening: got %d", baseline-before)
}
closeChest(t, actor, guid)
openChest(t, mate, guid, 6247)
closeChest(t, mate, guid)
openChest(t, actor, guid, 6247)
closeChest(t, actor, guid)
o.unchanged(t, baseline)
// The trap has a long stock cooldown; repeat-open observations here cannot
// prove the once-per-generation guard by themselves. The reward is the oracle.
count := actor.InventoryCount(t, roll.ItemID)
won, _, cancel := actor.ArmLootRollOutcome(roll.ItemID)
defer cancel()
mate.RollGreed(t, roll)
actor.RollNeed(t, roll)
select {
case result := <-won:
if result.WinnerGUID != actor.GUID {
e2eharness.Assertf(t, "Need did not beat Greed for Ice Chest item %d", roll.ItemID)
}
case <-time.After(10 * time.Second):
e2eharness.Assertf(t, "Ice Chest roll did not resolve after both votes")
}
deadline := time.Now().Add(5 * time.Second)
for actor.InventoryCount(t, roll.ItemID) != count+1 {
if time.Now().After(deadline) {
e2eharness.Assertf(t, "Ice Chest roll winner did not receive exactly one item %d", roll.ItemID)
}
time.Sleep(100 * time.Millisecond)
}
t.Logf("PASS Ice Chest first-open bunny, shared roll, second-player reopening and reward %d", roll.ItemID)
}
@@ -8100,6 +8100,11 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
}
go->SetLootState(GO_ACTIVATED, this);
// Trigger chest traps once per loot generation, including when the generated loot is empty.
if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST)
if (uint32 trapEntry = go->GetGOInfo()->chest.linkedTrapId)
go->TriggeringLinkedGameObject(trapEntry, this);
}
if (go->getLootState() == GO_ACTIVATED)
-5
View File
@@ -2184,11 +2184,6 @@ void Spell::SendLoot(ObjectGuid guid, LootType loottype)
gameObjTarget->TriggeringLinkedGameObject(trapEntry, unitCaster);
return;
case GAMEOBJECT_TYPE_CHEST:
// triggering linked GO
if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
gameObjTarget->TriggeringLinkedGameObject(trapEntry, unitCaster);
// Don't return, let loots been taken
default:
break;