From eb1b7174433c90b5eb0420af0045b54fb788c678 Mon Sep 17 00:00:00 2001 From: Vincent Bolcioni Date: Sun, 15 Feb 2026 23:54:52 +0100 Subject: [PATCH] [Warlock] Fix Demonology/Destruction infinite loops + remove version guard Demonology - summon_vilefiend: - Talent spell 1251778 has 0s duration AND 0s cooldown in Midnight DBC - Spell 1251781 has the correct values (15s duration) - Added cooldown->duration = 45s (matches in-game, both DBC spells show 0) - Added set_default_duration for vilefiends pet spawner (was missing) - Fixed vilefiend buff duration to use spell 1251781 Destruction - dimensional_rift: - Spell data already has 3 charges / 45s recharge but the charge system was never initialized in the constructor - Added cooldown->charges = data().charges() Without these fixes both specs enter infinite event loops on the first cast of vilefiend/dimensional_rift. Tested: Affliction ~21k DPS, Demonology ~11k DPS, Destruction ~30k DPS (default profiles, load_default_gear=1, load_default_talents=1, 100 iter) --- engine/class_modules/warlock/sc_warlock.cpp | 12 ++---------- engine/class_modules/warlock/sc_warlock_actions.cpp | 13 +++++++++++-- engine/class_modules/warlock/sc_warlock_init.cpp | 6 +++++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/engine/class_modules/warlock/sc_warlock.cpp b/engine/class_modules/warlock/sc_warlock.cpp index 5523d5efcac..47a58dd2530 100644 --- a/engine/class_modules/warlock/sc_warlock.cpp +++ b/engine/class_modules/warlock/sc_warlock.cpp @@ -639,16 +639,8 @@ stat_e warlock_t::convert_hybrid_stat( stat_e s ) const bool warlock_t::validate_actor() { - // TODO: Remove this when Midnight is properly supported - if ( sim->dbc->wowv() < wowv_t( 13, 0, 0 ) ) - { - std::string patch = "Midnight prepatch"; - if ( sim->dbc->wowv() > wowv_t( 12, 0, 0 ) ) - patch = "Midnight"; - throw sc_unsupported_specialization( fmt::format( "Warlock sims are non functional for {}", patch ) ); - return false; - } - + // Warlock Midnight support: guard removed — all three specs now sim + // with vilefiend and dimensional_rift fixes below return true; } diff --git a/engine/class_modules/warlock/sc_warlock_actions.cpp b/engine/class_modules/warlock/sc_warlock_actions.cpp index 90b06eb6371..b7689bf0f17 100644 --- a/engine/class_modules/warlock/sc_warlock_actions.cpp +++ b/engine/class_modules/warlock/sc_warlock_actions.cpp @@ -3303,15 +3303,20 @@ using namespace helpers; { harmful = may_crit = false; + // The talent spell (1251778) has 0s cooldown in Midnight DBC data, + // but the actual in-game cooldown is 45s. Hardcode until DBC is fixed. + cooldown->duration = timespan_t::from_seconds( 45.0 ); + triggers.diabolic_ritual = p->hero.diabolic_ritual.ok(); } void execute() override { warlock_spell_t::execute(); - + p()->buffs.vilefiend->trigger( -1, 1.0 ); // Set value to 1.0 to allow Houndmasters Gambit talent to apply - p()->warlock_pet_list.vilefiends.spawn( p()->talents.summon_vilefiend->duration() ); + // Talent spell 1251778 has 0s duration — spell 1251781 has the correct 15s + p()->warlock_pet_list.vilefiends.spawn( p()->find_spell( 1251781 )->duration() ); } }; @@ -4181,6 +4186,10 @@ using namespace helpers; energize_type = action_energize::ON_CAST; energize_amount = p->talents.dimensional_rift->effectN( 2 ).base_value() / 10.0; + + // Spell data has 3 charges / 45s recharge but the charge system + // was never initialized, causing infinite-cast loops + cooldown->charges = as( data().charges() ); } void execute() override diff --git a/engine/class_modules/warlock/sc_warlock_init.cpp b/engine/class_modules/warlock/sc_warlock_init.cpp index 28940714bae..7f41753c5f7 100644 --- a/engine/class_modules/warlock/sc_warlock_init.cpp +++ b/engine/class_modules/warlock/sc_warlock_init.cpp @@ -376,6 +376,9 @@ namespace warlock warlock_pet_list.doomguards.set_default_duration( talents.doomguard->duration() ); warlock_pet_list.greater_dreadstalkers.set_default_duration( tier.greater_dreadstalker->duration() ); + + // Talent spell 1251778 has 0s duration — spell 1251781 has the correct 15s + warlock_pet_list.vilefiends.set_default_duration( find_spell( 1251781 )->duration() ); } void warlock_t::init_spells_destruction() @@ -773,8 +776,9 @@ namespace warlock buffs.dreadstalkers = make_buff( this, "dreadstalkers" )->set_max_stack( 8 ) ->set_duration( talents.call_dreadstalkers_2->duration() ); + // Talent spell 1251778 has 0s duration — spell 1251781 has the correct 15s buffs.vilefiend = make_buff( this, "vilefiend" )->set_max_stack( 2 ) - ->set_duration( talents.summon_vilefiend->duration() ); + ->set_duration( find_spell( 1251781 )->duration() ); buffs.tyrant = make_buff( this, "tyrant" )->set_max_stack( 1 ) ->set_duration( talents.summon_demonic_tyrant->duration() );