Skip to content

[Warlock] Adjust Hellcaller and Feast of Souls RNG#11520

Merged
nyterage merged 2 commits into
simulationcraft:midnightfrom
millanzarreta:wl-hellcaller-rng-adj
Jun 21, 2026
Merged

[Warlock] Adjust Hellcaller and Feast of Souls RNG#11520
nyterage merged 2 commits into
simulationcraft:midnightfrom
millanzarreta:wl-hellcaller-rng-adj

Conversation

@millanzarreta

@millanzarreta millanzarreta commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

This PR updates the Warlock module to adjust the values and behavior of several RNG systems, mainly Feast of Souls (on kills) for Affliction and the different Hellcaller procs for both Affliction and Destruction. These are described below, but here is a ZIP file containing all the analyses, sample files (parsed logs), figures, and summary:
HC_and_FoSAffKill_procs.zip

In addition to the RNG updates, we also checked how collapse works, as well as the different interactions between talents, stack gains, stack consumes (Blackened Soul damage events), Malevolence, and so on. The code has been updated with comments documenting most of these details.

One relevant finding about Hellcaller is that the number of pending collapse stacks does not necessarily have to match the number of Wither stacks. When a collapse starts on a target, it snapshots the number of Wither stacks on that target, and that becomes the number of stacks consumed by the collapse. However, any Wither stack gains that happen afterward while collapse is active do not refresh the number of pending collapse stacks. In practice, this means many collapses can end before all Wither stacks have been consumed.

However, if collapse conditions are met again while a collapse is already active, the number of stacks to be consumed by the active collapse is updated to the current number of Wither stacks.

In simc, this behavior has been replicated by giving stacks to the Blackened Soul dummy debuff used for collapse. These dummy stacks represent the active collapse snapshot/budget for that target. When collapse starts or is refreshed by collapse conditions being met again, the dummy stack count is synchronized to the current Wither stack count. Each Blackened Soul damage event then decrements both Wither and this dummy collapse counter until either Wither reaches 1 stack or the collapse counter is exhausted.

Feast of Souls (Affliction) (on kill)

Feast of Souls RNG proc with Quietus has not been retested here, but the previously analyzed average chance was ~4%-~5%, much lower than expected, possibly due to a bug.

It appears that the chance for Feast of Souls in Affliction is much higher when the proc comes from killing a target rather than from Quietus. Samples were collected to analyze the proc rate of Feast of Souls across ~3200 kills, resulting in a ~11.8% average chance. Therefore, in the absence of more samples to get higher precision, we assume an average chance of 12%.

The RNG type was also analyzed, and, as expected, it is accumulator PRD, the same as Feast of Souls with Quietus and the Demonology version.

We also confirmed that the accumulator PRD appears to be shared between kills and Quietus procs, so this is how it has been implemented in simc.

  • Histogram for the distance between procs:
fos_kills_unitdied_sample_gap_histogram

Bleakheart Tactics (Hellcaller)

Chance to gain an additional stack when Wither gains a stack from Blackened Soul. Malevolence stack gains do not benefit from Bleakheart Tactics. Wither stack gains from Mark of Perotharn do not benefit from Bleakheart Tactics.

After analyzing several samples, we obtained an average chance of 14.90% for Affliction and 14.95% for Destruction. The most likely real value used in-game is 15%, which is the value we set in simc.

The RNG type used is clearly accumulator PRD, and only a single global PRD accumulator is used, shared across all Wither targets.

  • Histogram for the distance between procs:

· Affliction:
aff_marchitar_bs_global_gap_hist_v2

· Destruction:
dest_BTBS_hist_global_corrected

  • ECDF distance between procs:

· Destruction:
dest_BTBS_ecdf_global_corrected

  • Hazard per attempt (probability of success on attempt n since the last attempt):

· Destruction:
dest_BTBS_hazard_global_corrected

  • Tail / survival of the distance between procs (log scale):
    · Destruction:
dest_BTBS_survival_global_corrected

Blackened Soul (Hellcaller)

Chance for a Wither to start collapse each time it gains a stack (on eligible Wither stack gain events). This proc cannot occur on a target while it already has an active collapse; it is only attempted when no collapse is active. Malevolence stack gains do not trigger the Blackened Soul collapse proc.

After analyzing several samples, we obtained an average chance of 23.18% for Affliction and 22.47% for Destruction. In the absence of higher precision, the most likely real value used in-game is 23%, which is the value we set in simc.

The RNG type used is Flat %, so there does not appear to be any BLP mechanism associated with this proc.

  • Histogram for the distance between procs:

· Affliction:
CPS_Aff_hist_global

· Destruction:
CPS_Destr_hist_global

  • ECDF distance between procs:

· Affliction:
CPS_Aff_ecdf_global

· Destruction:
CPS_Destr_ecdf_global

  • Hazard per attempt (probability of success on attempt n since the last attempt):

· Affliction:
CPS_Aff_hazard_global

· Destruction:
CPS_Destr_hazard_global

  • Tail / survival of the distance between procs (log scale):

· Affliction:
CPS_Aff_survival_global

· Destruction:
CPS_Destr_survival_global

Mark of Perotharn (Hellcaller)

Chance to gain a Wither stack on a Wither crit. Wither stack gains from Mark of Perotharn do not directly trigger collapse on that tick (although the collapse can be triggered on the next Wither tick if collapse conditions are met). Wither stack gains from Mark of Perotharn do not benefit from Bleakheart Tactics.

After analyzing several samples, we obtained an average chance of 15.23% for Affliction and 15.12% for Destruction. The most likely real value used in-game is 15%, which is the value we set in simc.

The RNG type used is clearly accumulator PRD, and only a single global PRD accumulator is used, shared across all Wither targets.

  • Histogram for the distance between procs:

· Affliction:
aff_MP_law2_mp_global_comparison_figures-1

· Destruction:
dest_MP_hist_global

  • ECDF distance between procs:

· Affliction:
aff_MP_law2_mp_global_comparison_figures-2

· Destruction:
dest_MP_ecdf_global

  • Hazard per attempt (probability of success on attempt n since the last attempt):

· Affliction:
aff_MP_law2_mp_global_comparison_figures-3

· Destruction:
dest_MP_hazard_global

  • Tail / survival of the distance between procs (log scale):

· Affliction:
aff_MP_law2_mp_global_comparison_figures-4

· Destruction:
dest_MP_survival_global

Seeds of Their Demise (Hellcaller)

Chance to gain Shard Instability (Affliction) / Flashpoint (Destruction) when Blackened Soul deals damage.

After analyzing multiple logs, both in Affliction and Destruction, using a variable number of targets (1T, 3T, 5T, and 9T), and varying the cadence of Wither stack gains and consumes, we confirmed that this RNG uses a Threshold accumulator, similar to the system used by Agony energize or Nightfall proc. This proc is somewhat more complex than those other procs because, in addition to scaling with the number of targets, it also scales with the number of Wither stacks. The accumulator increment appears to follow this formula: rng().range( inc_max * ( std::pow( wither_stacks_before, -2.0 / 3.0 ) * std::pow( active_withers, -3.0 / 4.0 ) ) ) with an initial base inc_max value of 0.240.

  • stacks_before is used because, based on the result analysis, the data strongly favors using the number of stacks Wither had before the Blackened Soul damage event consumes a stack.
  • roll_over=true: Although this parameter is difficult to distinguish in the samples, the result analysis favors roll_over=true over roll_over=false, and this also tends to match how Blizzard uses it in other similar threshold RNG procs.
  • Although this proc was previously believed to have an ICD of ~10s or ~15s, this is simply a result of how this threshold accumulator currently behaves and how it scales with targets. There is currently nothing that seems to indicate that it has a real ICD.
  • An attempt was made to analyze whether collapse windows have anything to do with this proc, whether the number of simultaneous collapses or the number of internal collapse stacks has any effect. The results seem to strongly favor that neither of them affects this proc, which appears to use the number of active Withers and the number of Wither stacks.
  • Only a single global Threshold accumulator is used, shared across all Wither targets.
  • Implemented as:
double base_inc_max = rng_settings.seeds_of_their_demise.setting_value; // = 0.240
progress_rng.seeds_of_their_demise = get_threshold_rng( "seeds_of_their_demise", base_inc_max,
	[ this ]( double increment_max, action_state_t* s ) {
		assert( hero.wither.ok() );
		assert( s );
		auto tdata = get_target_data( s->target );
		assert( tdata );
		dot_t* wither_dot = tdata->dots.wither;
		assert( wither_dot && wither_dot->is_ticking() );
		const double stacks_before = wither_dot->current_stack() + 1.0;
		unsigned active_withers = get_active_dots( wither_dot );
		assert( active_withers > 0 );
		const double weight = std::pow( stacks_before, -2.0 / 3.0 ) * std::pow( active_withers, -3.0 / 4.0 );
		return rng().range( increment_max * weight );
	}, true, true );
  • Histogram for the distance between procs across the different samples:
    • Affliction:

· 1T-v1 (aff):
aff-1t-vFast_event_gap_hist

· 1T-v2 (aff):
aff-1t-vSlow_event_gap_hist

· 3T-v1 (aff):
aff-3t-vFast_event_gap_hist

· 3T-v2 (aff):
aff-3t-vSlow_event_gap_hist

· 5T-v1 (aff):
aff-5t-vFast_event_gap_hist_bw10

· 5T-v2 (aff):
aff-5t-vSlow_event_gap_hist

· 9T-v1 (aff):
aff-9t-vFast_event_gap_hist_bw20

· 9T-v2 (aff):
aff-9t-vSlow_event_gap_hist_bw5

  • Destruction:

· 1T-v1 (dest):
destr-1t-vFast_event_gap_hist

· 1T-v2 (dest):
destr-1t-vSlow_event_gap_hist

· 3T-v1 (dest):
destr-3t-vFast_event_gap_hist

· 3T-v2 (dest):
destr-3t-vSlow_event_gap_hist

· 5T-v1 (dest):
destr-5t-vFast_event_gap_hist

· 5T-v2 (dest):
destr-5t-vSlow_event_gap_hist

@nyterage nyterage merged commit b802082 into simulationcraft:midnight Jun 21, 2026
81 of 90 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants