@@ -916,6 +916,7 @@ class demon_hunter_t : public parse_player_effects_t
916916 const spell_data_t * thrill_of_the_fight_haste_buff;
917917 const spell_data_t * thrill_of_the_fight_damage_buff;
918918 double wounded_quarry_proc_rate;
919+ std::array<double , 3 > voidfall_proc_chances;
919920
920921 // Annihilator
921922 const spell_data_t * voidfall_meteor;
@@ -1215,6 +1216,15 @@ class demon_hunter_t : public parse_player_effects_t
12151216 double wounded_quarry_chance_vengeance = 0.30 ;
12161217 // Proc rate for Wounded Quarry for Havoc
12171218 double wounded_quarry_chance_havoc = 0.10 ;
1219+ // Voidfall proc rate per building stack count (WCL analysis, ~72k casts).
1220+ // Fits rate = base - k*sqrt(stacks) within 0.5pp, but no spell data
1221+ // parameterizes the decay, so these are likely server-side lookup tables.
1222+ double voidfall_proc_chance_0_stacks_vengeance = 0.385 ;
1223+ double voidfall_proc_chance_1_stacks_vengeance = 0.325 ;
1224+ double voidfall_proc_chance_2_stacks_vengeance = 0.30 ;
1225+ double voidfall_proc_chance_0_stacks_havoc = 0.41 ;
1226+ double voidfall_proc_chance_1_stacks_havoc = 0.34 ;
1227+ double voidfall_proc_chance_2_stacks_havoc = 0.325 ;
12181228 // How many seconds that Vengeful Retreat locks out Felblade
12191229 double felblade_lockout_from_vengeful_retreat = 0.6 ;
12201230 bool enable_dungeon_slice = false ;
@@ -2948,7 +2958,8 @@ struct voidfall_building_trigger_t : public BASE
29482958 if ( !BASE::p ()->talent .annihilator .voidfall ->ok () )
29492959 return ;
29502960
2951- if ( !BASE::rng ().roll ( BASE::p ()->talent .annihilator .voidfall ->effectN ( 3 ).percent () ) )
2961+ int stacks = std::min ( BASE::p ()->buff .voidfall_building ->check (), 2 );
2962+ if ( !BASE::rng ().roll ( BASE::p ()->hero_spec .voidfall_proc_chances [ stacks ] ) )
29522963 return ;
29532964
29542965 // can't gain building while spending is up
@@ -10113,6 +10124,12 @@ void demon_hunter_t::create_options()
1011310124 opt_float ( " soul_fragment_movement_consume_chance" , options.soul_fragment_movement_consume_chance , 0 , 1 ) );
1011410125 add_option ( opt_float ( " wounded_quarry_chance_vengeance" , options.wounded_quarry_chance_vengeance , 0 , 1 ) );
1011510126 add_option ( opt_float ( " wounded_quarry_chance_havoc" , options.wounded_quarry_chance_havoc , 0 , 1 ) );
10127+ add_option ( opt_float ( " voidfall_proc_chance_0_stacks_vengeance" , options.voidfall_proc_chance_0_stacks_vengeance , 0 , 1 ) );
10128+ add_option ( opt_float ( " voidfall_proc_chance_1_stacks_vengeance" , options.voidfall_proc_chance_1_stacks_vengeance , 0 , 1 ) );
10129+ add_option ( opt_float ( " voidfall_proc_chance_2_stacks_vengeance" , options.voidfall_proc_chance_2_stacks_vengeance , 0 , 1 ) );
10130+ add_option ( opt_float ( " voidfall_proc_chance_0_stacks_havoc" , options.voidfall_proc_chance_0_stacks_havoc , 0 , 1 ) );
10131+ add_option ( opt_float ( " voidfall_proc_chance_1_stacks_havoc" , options.voidfall_proc_chance_1_stacks_havoc , 0 , 1 ) );
10132+ add_option ( opt_float ( " voidfall_proc_chance_2_stacks_havoc" , options.voidfall_proc_chance_2_stacks_havoc , 0 , 1 ) );
1011610133 add_option (
1011710134 opt_float ( " felblade_lockout_from_vengeful_retreat" , options.felblade_lockout_from_vengeful_retreat , 0 , 1 ) );
1011810135 add_option ( opt_bool ( " enable_dungeon_slice" , options.enable_dungeon_slice ) );
@@ -10981,20 +10998,27 @@ void demon_hunter_t::init_spells()
1098110998 hero_spec.meteor_shower_driver = talent_spell_lookup ( talent.annihilator .dark_matter , 1264126 );
1098210999 hero_spec.meteor_shower_damage = hero_spec.meteor_shower_driver ->effectN ( 1 ).trigger ();
1098311000 hero_spec.world_killer = talent_spell_lookup ( talent.annihilator .world_killer , 1256618 );
11001+ hero_spec.voidfall_proc_chances = { options.voidfall_proc_chance_0_stacks_havoc ,
11002+ options.voidfall_proc_chance_1_stacks_havoc ,
11003+ options.voidfall_proc_chance_2_stacks_havoc };
1098411004 break ;
1098511005 case DEMON_HUNTER_VENGEANCE:
1098611006 hero_spec.voidfall_meteor = talent_spell_lookup ( talent.annihilator .voidfall , 1256303 );
1098711007 hero_spec.catastrophe_dot = talent_spell_lookup ( talent.annihilator .catastrophe , 1256667 );
1098811008 hero_spec.meteor_shower_driver = talent_spell_lookup ( talent.annihilator .dark_matter , 1264128 );
1098911009 hero_spec.meteor_shower_damage = hero_spec.meteor_shower_driver ->effectN ( 1 ).trigger ();
1099011010 hero_spec.world_killer = talent_spell_lookup ( talent.annihilator .world_killer , 1256616 );
11011+ hero_spec.voidfall_proc_chances = { options.voidfall_proc_chance_0_stacks_vengeance ,
11012+ options.voidfall_proc_chance_1_stacks_vengeance ,
11013+ options.voidfall_proc_chance_2_stacks_vengeance };
1099111014 break ;
1099211015 default :
1099311016 hero_spec.voidfall_meteor = spell_data_t::not_found ();
1099411017 hero_spec.catastrophe_dot = spell_data_t::not_found ();
1099511018 hero_spec.meteor_shower_driver = spell_data_t::not_found ();
1099611019 hero_spec.meteor_shower_damage = spell_data_t::not_found ();
1099711020 hero_spec.world_killer = spell_data_t::not_found ();
11021+ hero_spec.voidfall_proc_chances = { 0 , 0 , 0 };
1099811022 break ;
1099911023 }
1100011024
0 commit comments