fix(DB/SAI): Restore Timmy the Cruel (#27241)

This commit is contained in:
moostigre
2026-09-02 19:52:06 -03:00
committed by GitHub
parent 9eab2c5ec1
commit fc82095b02
3 changed files with 227 additions and 0 deletions
@@ -0,0 +1,68 @@
--
-- Timmy the Cruel
SET @CGUID := 247227;
SET @PATH := @CGUID * 10;
UPDATE `creature` SET `position_x` = 3624.6, `position_y` = -3188, `position_z` = 130.579, `orientation` = 2.99341, `MovementType` = 0, `VerifiedBuild` = 53622, `CreateObject` = 2 WHERE `guid` = @CGUID AND `id` = 10808;
DELETE FROM `creature_addon` WHERE `guid` = @CGUID;
INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
(@CGUID, 0, 0, 0, 1, 0, 3, '12787');
DELETE FROM `waypoint_data` WHERE `id` = @PATH;
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `velocity`, `delay`, `smoothTransition`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
(@PATH, 1, 3622.5618, -3187.6912, 130.70120, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 2, 3637.9067, -3196.1228, 128.94208, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 3, 3653.7864, -3202.9502, 127.63325, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 4, 3674.5347, -3204.5970, 126.66777, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 5, 3689.5625, -3191.0405, 127.16926, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 6, 3696.2886, -3171.0410, 127.19991, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 7, 3694.8628, -3156.6287, 127.44449, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 8, 3681.7678, -3154.1362, 127.26646, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 9, 3677.8403, -3162.5703, 126.69397, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 10, 3676.1355, -3175.5400, 126.43660, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 11, 3668.1090, -3185.7537, 126.311264, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 12, 3673.8386, -3194.0088, 126.40000, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 13, 3667.7388, -3203.3460, 126.56412, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 14, 3656.9858, -3204.5164, 127.65019, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 15, 3651.1753, -3196.8152, 127.30198, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 16, 3658.5908, -3188.9165, 126.71776, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 17, 3669.3274, -3183.5960, 126.359184, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 18, 3678.2393, -3171.0085, 126.507866, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 19, 3668.1770, -3166.6174, 126.90177, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 20, 3653.5696, -3174.7020, 127.15160, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 21, 3645.5012, -3185.9297, 127.69186, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 22, 3634.0906, -3178.5388, 129.00195, NULL, 0, 0, 0, 0, 0, 100, 0),
(@PATH, 23, 3623.9392, -3180.2332, 130.64621, NULL, 0, 0, 0, 0, 0, 100, 0);
DELETE FROM `creature_template_spell` WHERE `CreatureID` = 10808;
INSERT INTO `creature_template_spell` (`CreatureID`, `Index`, `Spell`) VALUES
(10808, 0, 12787),
(10808, 1, 17470),
(10808, 2, 8599);
DELETE FROM `smart_scripts` WHERE `entryorguid` = 10808 AND `source_type` = 0;
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`, `event_param6`, `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
(10808, 0, 0, 0, 0, 0, 100, 0, 10000, 15000, 10000, 15000, 0, 0, 11, 17470, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - In Combat - Cast Ravenous Claw'),
(10808, 0, 1, 0, 2, 0, 100, 1, 0, 50, 0, 0, 0, 0, 11, 8599, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Between 0-50% Health - Cast Enrage'),
(10808, 0, 2, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - On Aggro - Say Line 0'),
(10808, 0, 3, 4, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - On Respawn - Set Invisible'),
(10808, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - On Respawn - Set Immune to Players and NPCs'),
(10808, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - On Respawn - Set Event Phase 1'),
(10808, 0, 6, 0, 1, 1, 100, 1, 10000, 10000, 10000, 10000, 0, 0, 80, 1080800, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Out of Combat - Run Emerge Actionlist');
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND `SourceEntry` = 10808;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 7, 10808, 0, 1, 29, 1, 10418, 70, 0, 1, 0, 0, '', 'Timmy the Cruel - Activate if no living Crimson Guardsman is within 70 yards'),
(22, 7, 10808, 0, 1, 29, 1, 10419, 70, 0, 1, 0, 0, '', 'Timmy the Cruel - Activate if no living Crimson Conjuror is within 70 yards'),
(22, 7, 10808, 0, 1, 29, 1, 10420, 70, 0, 1, 0, 0, '', 'Timmy the Cruel - Activate if no living Crimson Initiate is within 70 yards'),
(22, 7, 10808, 0, 1, 29, 1, 10424, 70, 0, 1, 0, 0, '', 'Timmy the Cruel - Activate if no living Crimson Gallant is within 70 yards');
DELETE FROM `smart_scripts` WHERE `entryorguid` = 1080800 AND `source_type` = 9;
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`, `event_param6`, `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
(1080800, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 449, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Actionlist - Set Emerge Emote State'),
(1080800, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Actionlist - Set Visible'),
(1080800, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Actionlist - Remove Immunity to Players and NPCs'),
(1080800, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Actionlist - Set Event Phase 0'),
(1080800, 9, 4, 0, 0, 0, 100, 0, 3500, 3500, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Actionlist - Clear Emote State'),
(1080800, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 232, @PATH, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Timmy the Cruel - Actionlist - Start Repeating Path');
+1
View File
@@ -155,6 +155,7 @@ If the scenario should stay as a regression, **move** it into `suites/` next to
| protocol/teleport | cross-map; named; GoCreatureID | P1 | covered | — |
| guild/charter_bank | charter buy+turn-in | P2 | covered | — |
| instances/bind_reset | party tele; ritual summon | P2 | covered; post-reset summon `blocked-harness` (AcceptSummon after reset) | #10708 |
| instances/classic/stratholme | Timmy remains hidden while a relevant Square Scarlet lives, then emerges after the area is clear | P2 | covered (`TestAC_26363_TimmyEmergesAfterSquareCleared`) | #26363 |
| instances/ulduar | named tele; Freya wave interval | P2 | covered (`TestAC_27095_*`); Kologarn Charge `blocked-harness` (bridge Z after Charge) | #26266 #27095 |
---
@@ -0,0 +1,158 @@
//go:build e2e
package stratholme_test
import (
"testing"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
)
const (
npcTimmyTheCruel = uint32(10808)
npcCrimsonInitiate = uint32(10420)
stratholmeMap = uint32(329)
triggerRadius = float32(55)
activationCheckEvery = 10 * time.Second
)
var timmyActivationEntries = []uint32{10418, 10419, 10420, 10424}
func waitForTimmyActivationSet(t *testing.T, bot *e2eharness.ScenarioBot, timeout time.Duration) []uint64 {
t.Helper()
want := map[uint32]int{
10418: 8,
10419: 3,
10420: 2,
10424: 2,
}
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
timer := time.NewTimer(timeout)
defer timer.Stop()
var got map[uint32]int
for {
got = e2eharness.CountLivingByEntry(bot.World, triggerRadius, timmyActivationEntries...)
complete := true
for entry, count := range want {
if got[entry] != count {
complete = false
break
}
}
if complete {
return e2eharness.LivingByEntries(bot.World, triggerRadius, timmyActivationEntries...)
}
select {
case <-ticker.C:
case <-timer.C:
e2eharness.Preconditionf(t, "Timmy activation area did not load completely within %s: got=%v want=%v", timeout, got, want)
return nil
}
}
}
func assertTimmyAbsentWhileAlive(t *testing.T, bot *e2eharness.ScenarioBot, survivor uint64, window time.Duration) {
t.Helper()
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
timer := time.NewTimer(window)
defer timer.Stop()
for {
if health, _ := bot.UnitHP(survivor); health == 0 {
e2eharness.Preconditionf(t, "final relevant Scarlet 0x%X died before the gating oracle completed", survivor)
}
if timmy := bot.FindUnit(npcTimmyTheCruel, 100); timmy != 0 {
e2eharness.ConfirmedBugf(t, 26363, "Timmy emerged as 0x%X while relevant Scarlet 0x%X was still alive", timmy, survivor)
}
select {
case <-ticker.C:
case <-timer.C:
return
}
}
}
func waitForTimmy(t *testing.T, bot *e2eharness.ScenarioBot, timeout time.Duration) uint64 {
t.Helper()
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
timer := time.NewTimer(timeout)
defer timer.Stop()
for {
if timmy := bot.FindUnit(npcTimmyTheCruel, 100); timmy != 0 {
return timmy
}
select {
case <-ticker.C:
case <-timer.C:
e2eharness.ConfirmedBugf(t, 26363, "Timmy did not emerge within %s after the final Scarlet trigger died", timeout)
return 0
}
}
}
// Issue: https://github.com/azerothcore/azerothcore-wotlk/issues/26363
// Timmy must remain hidden while any relevant Scarlet in Crusaders' Square is
// alive, then emerge on the next SmartAI activation check.
func TestAC_26363_TimmyEmergesAfterSquareCleared(t *testing.T) {
meta.Begin(t, meta.TestMeta{
Tags: []string{"med", "instances", "issue", "serial"},
Runtime: "med",
Issue: 26363,
Category: "instances/classic/stratholme",
})
bot := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{
Prefix: "Timmy",
Level: 80,
})
// Center of the 15 relevant Scarlet spawns in Crusaders' Square. The 55-yard
// observation radius excludes other Scarlet spawns with the same entries.
bot.Teleport(t, 3660, -3180, 127, stratholmeMap)
triggers := waitForTimmyActivationSet(t, bot, 20*time.Second)
if len(triggers) != 15 {
e2eharness.Preconditionf(t, "loaded Timmy activation area has %d relevant Scarlets, want 15", len(triggers))
}
bot.CombatReady(t)
if timmy := bot.FindUnit(npcTimmyTheCruel, 100); timmy != 0 {
e2eharness.ConfirmedBugf(t, 26363, "Timmy was already present as 0x%X before the Scarlet activation area was cleared", timmy)
}
// The previous implementation omitted Crimson Initiates from its conditions.
// Leave one Initiate alive through a complete activation interval so the test
// deterministically guards that regression instead of choosing any survivor.
initiates := e2eharness.LivingByEntries(bot.World, triggerRadius, npcCrimsonInitiate)
if len(initiates) != 2 {
e2eharness.Preconditionf(t, "loaded Timmy activation area has %d Crimson Initiates, want 2", len(initiates))
}
survivor := initiates[0]
victims := make([]uint64, 0, len(triggers)-1)
for _, guid := range triggers {
if guid != survivor {
victims = append(victims, guid)
}
}
bot.DamageKill(t, victims, 10_000_000, 20*time.Second)
assertTimmyAbsentWhileAlive(t, bot, survivor, activationCheckEvery+2*time.Second)
bot.DamageKill(t, []uint64{survivor}, 10_000_000, 10*time.Second)
timmy := waitForTimmy(t, bot, 15*time.Second)
bot.AssertWorldAlive(t)
t.Logf("PASS AC#26363 Timmy emerged as 0x%X only after all 15 relevant Scarlets died", timmy)
}