mirror of
https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk.git
synced 2026-10-10 07:06:38 +08:00
fix(Scripts/Ulduar): stop Freya's Ward adds despawning on the spell timer (#27651)
This commit is contained in:
+1
-1
@@ -164,7 +164,7 @@ go test -tags=e2e ./local/... -count=1 -v -timeout 30m -parallel 1
|
||||
| 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; a Laughing Skull's Lunatic Gaze stops at the brain room's geometry instead of draining sanity through it; Elder Brightleaf's Unstable Sun Beams despawn on their own timer instead of outliving him, one lands under the player rather than all on the elder, and a wave stays capped however many players stand in range; Psychosis and Malady of the Mind stop picking a player once they are at 40 Sanity or less; Algalon holds still for 3s once his Big Bang cast lands instead of resuming melee and Quantum Strike on the next tick | P2 | covered (`TestAC_27095_*`, `TestAC_27602_*`, `TestAC_27590_*`, `TestAC_27539_*`, `TestUlduar_BrightleafSunBeams*`); Kologarn Charge `blocked-harness` (bridge Z after Charge) | #26266 #27095 #27539 #27590 #27602 |
|
||||
| instances/ulduar | named tele; Freya wave interval; a Laughing Skull's Lunatic Gaze stops at the brain room's geometry instead of draining sanity through it; Elder Brightleaf's Unstable Sun Beams despawn on their own timer instead of outliving him, one lands under the player rather than all on the elder, and a wave stays capped however many players stand in range; Psychosis and Malady of the Mind stop picking a player once they are at 40 Sanity or less; Algalon holds still for 3s once his Big Bang cast lands instead of resuming melee and Quantum Strike on the next tick; a Writhing Lasher stays up past 62947's own 10s summon duration, because the despawn type its AI sets in `IsSummonedBy` is no longer overwritten on the way out of the summon call | P2 | covered (`TestAC_27095_*`, `TestAC_27602_*`, `TestAC_27590_*`, `TestAC_27539_*`, `TestUlduar_BrightleafSunBeams*`, `TestUlduar_FreyaWardLasherOutlivesSummonDuration`); Kologarn Charge `blocked-harness` (bridge Z after Charge) | #26266 #27095 #27539 #27590 #27602 |
|
||||
| world/gameevents | Call to Arms banners at the Dalaran portals belong to the side they stand on, and the already-correct Warsong set is unchanged. **Wants an exclusive realm**: starting a holiday re-anchors its schedule in the running worldserver until restart; holidays already running are left alone | P2 | covered (`TestAC_24380_*`); Shattrath's 23 positions `gap` | #24380 |
|
||||
|
||||
---
|
||||
|
||||
@@ -1050,3 +1050,89 @@ func TestAC_27539_AlgalonBigBangStasis(t *testing.T) {
|
||||
|
||||
t.Logf("PASS Big Bang stasis: no damage for %s after the cast, then Algalon resumed", stasisWindow)
|
||||
}
|
||||
|
||||
// Freya's Ward summons its adds with 62947, whose own summon duration is 10s, and
|
||||
// npc_freya_ward_summon raises them to TEMPSUMMON_MANUAL_DESPAWN so they stay until the encounter
|
||||
// clears them. Spell::EffectSummonType re-applies that duration once the summon call returns, which
|
||||
// is after IsSummonedBy has run, so an override applied from inside that hook is discarded and the
|
||||
// lashers vanish 10s in while the raid is still fighting them.
|
||||
// The IsSummonedBy override arrived with https://github.com/azerothcore/azerothcore-wotlk/pull/27567
|
||||
func TestUlduar_FreyaWardLasherOutlivesSummonDuration(t *testing.T) {
|
||||
meta.Begin(t, meta.TestMeta{
|
||||
Tags: []string{"med", "instances"},
|
||||
Runtime: "med",
|
||||
Category: "instances/northrend/ulduar",
|
||||
})
|
||||
|
||||
const (
|
||||
npcFreyaWardReticle = uint32(33366)
|
||||
npcFreyaWard = uint32(33367)
|
||||
npcWrithingLasher = uint32(33387)
|
||||
npcWardOfLife = uint32(34275)
|
||||
|
||||
addSearchRange = float32(100)
|
||||
|
||||
// npc_freya_ward resets its cast timer to 25s and casts at 29s, so the first lasher lands
|
||||
// ~4s after the ward spawns. One extra 29s cycle covers a ward that missed that window.
|
||||
firstLasherWindow = 40 * time.Second
|
||||
|
||||
// 62947 carries SpellDuration 1 (10s). A lasher still in the cache this long after it
|
||||
// appeared is not running on the spell's own timer. Do not shorten it below 10s: that is
|
||||
// the despawn this guards, and a shorter window would pass on an unfixed core.
|
||||
outliveWindow = 25 * time.Second
|
||||
)
|
||||
|
||||
bot := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{
|
||||
Prefix: "FWard", Race: e2eharness.RaceHuman, Level: 80,
|
||||
})
|
||||
|
||||
// Stay GM through the raid enter, and use the brain room floor: it is empty, so nothing else
|
||||
// pulls the bot while the lasher is being timed.
|
||||
bot.Teleport(t, 1930.0, -120.0, 240.07, e2eharness.MapUlduar)
|
||||
if _, _, _, m := bot.Pos(); m != e2eharness.MapUlduar {
|
||||
e2eharness.Preconditionf(t, "not in Ulduar after brain room tele map=%d", m)
|
||||
}
|
||||
|
||||
// The ward only casts while a reticle is within 60y of it, so the reticle goes down first.
|
||||
reticle := bot.Spawn(t, npcFreyaWardReticle, 30*time.Second)
|
||||
ward := bot.Spawn(t, npcFreyaWard, 30*time.Second)
|
||||
|
||||
// Drops GM so the lasher's DoZoneInCombat can pick the bot up the way it picks up a raid, and
|
||||
// turns on god mode, which is what keeps the bot standing there for the whole window.
|
||||
bot.CombatReady(t)
|
||||
|
||||
lasher := bot.WaitUnit(t, npcWrithingLasher, firstLasherWindow)
|
||||
if lasher == 0 {
|
||||
e2eharness.Preconditionf(t, "Freya's Ward 0x%X never summoned a Writhing Lasher next to reticle 0x%X", ward, reticle)
|
||||
}
|
||||
appeared := time.Now()
|
||||
t.Logf("Writhing Lasher 0x%X summoned by ward 0x%X", lasher, ward)
|
||||
|
||||
// Pin the GUID: the ward keeps summoning every 29s, so "some lasher is in the cache" would
|
||||
// still be true on an unfixed core and would hide the despawn.
|
||||
deadline := appeared.Add(outliveWindow)
|
||||
for time.Now().Before(deadline) {
|
||||
if bot.World.GetObject(lasher) == nil {
|
||||
e2eharness.Assertf(t, "Writhing Lasher 0x%X left the world %s after it was summoned — IsSummonedBy set TEMPSUMMON_MANUAL_DESPAWN but 62947's own 10s duration was restored over it",
|
||||
lasher, time.Since(appeared).Round(time.Millisecond))
|
||||
}
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
|
||||
hp, maxHP := bot.UnitHP(lasher)
|
||||
if hp == 0 {
|
||||
e2eharness.Preconditionf(t, "Writhing Lasher 0x%X is a corpse (%d/%d) — something killed it, so its lifetime proves nothing", lasher, hp, maxHP)
|
||||
}
|
||||
t.Logf("PASS Writhing Lasher 0x%X still up %s after summon (hp=%d/%d)", lasher, outliveWindow, hp, maxHP)
|
||||
|
||||
// A MANUAL_DESPAWN summon has nothing of its own to remove it, and deleting the ward does not
|
||||
// take its adds with it, so they have to be killed here. The ward dies first: while it lives it
|
||||
// summons another pair every 29s, and a sweep taken before that would race the next cycle.
|
||||
bot.DamageKill(t, []uint64{ward}, 10_000_000, 30*time.Second)
|
||||
var adds []uint64
|
||||
for _, add := range bot.UnitsByEntry(addSearchRange, npcWrithingLasher, npcWardOfLife) {
|
||||
adds = append(adds, add.GUID)
|
||||
}
|
||||
bot.DamageKill(t, adds, 10_000_000, 30*time.Second)
|
||||
bot.AssertWorldAlive(t)
|
||||
}
|
||||
|
||||
@@ -939,7 +939,14 @@ struct npc_freya_ward_summon : public ScriptedAI
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
me->ToTempSummon()->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN);
|
||||
// Deferred a tick on purpose: Spell::EffectSummonType re-applies the summon spell's own
|
||||
// duration (10s for the lashers, 3s for the wards) once the summon call returns, which
|
||||
// would overwrite anything this hook sets.
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
me->ToTempSummon()->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN);
|
||||
}, 1ms);
|
||||
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user