SimulationCraft
SimulationCraft is a tool to explore combat mechanics in the popular MMO RPG World of Warcraft (tm).
sc_warlock.hpp
1 #pragma once
2 #include "simulationcraft.hpp"
3 
4 #include "player/pet_spawner.hpp"
5 #include "sc_warlock_pets.hpp"
6 #include "class_modules/apl/warlock.hpp"
7 
8 namespace warlock
9 {
10 struct warlock_t;
11 
12 //Used for version checking in code (e.g. PTR vs Live)
13 enum version_check_e
14 {
15  VERSION_PTR,
16  VERSION_9_2_0,
17  VERSION_9_1_0,
18  VERSION_9_0_5,
19  VERSION_9_0_0,
20  VERSION_ANY
21 };
22 
23 template <typename Action, typename Actor, typename... Args>
24 action_t* get_action( util::string_view name, Actor* actor, Args&&... args )
25 {
26  action_t* a = actor->find_action( name );
27  if ( !a )
28  a = new Action( name, actor, std::forward<Args>( args )... );
29  assert( dynamic_cast<Action*>( a ) && a->name_str == name && a->background );
30  return a;
31 }
32 
34 {
35  // Cross-spec
36  propagate_const<dot_t*> dots_drain_life;
37  propagate_const<dot_t*> dots_drain_life_aoe; // SL - Soul Rot covenant effect
38  propagate_const<dot_t*> dots_scouring_tithe;
39  propagate_const<dot_t*> dots_impending_catastrophe;
40  propagate_const<dot_t*> dots_soul_rot;
41  propagate_const<dot_t*> dots_corruption;
42 
43  // Aff
44  propagate_const<dot_t*> dots_agony;
45  propagate_const<dot_t*> dots_seed_of_corruption;
46  propagate_const<dot_t*> dots_drain_soul;
47  propagate_const<dot_t*> dots_siphon_life;
48  propagate_const<dot_t*> dots_phantom_singularity;
49  propagate_const<dot_t*> dots_unstable_affliction;
50  propagate_const<dot_t*> dots_vile_taint;
51 
52  propagate_const<buff_t*> debuffs_haunt;
53  propagate_const<buff_t*> debuffs_shadow_embrace; //9.1 PTR - Same behavior as 9.0 but enabled by talent
54 
55  // Destro
56  propagate_const<dot_t*> dots_immolate;
57 
58  propagate_const<buff_t*> debuffs_shadowburn;
59  propagate_const<buff_t*> debuffs_eradication;
60  propagate_const<buff_t*> debuffs_roaring_blaze;
61  propagate_const<buff_t*> debuffs_havoc;
62 
63  // SL - Legendary
64  propagate_const<buff_t*> debuffs_odr;
65 
66  // SL - Conduit
67  propagate_const<buff_t*> debuffs_combusting_engine;
68 
69  // Demo
70  propagate_const<dot_t*> dots_doom;
71 
72  propagate_const<buff_t*> debuffs_from_the_shadows;
73 
74  double soc_threshold; //Aff - Seed of Corruption counts damage from cross-spec spells such as Drain Life
75 
77  warlock_td_t( player_t* target, warlock_t& p );
78 
79  void reset()
80  {
81  soc_threshold = 0;
82  }
83 
84  void target_demise();
85 
86  int count_affliction_dots();
87 };
88 
89 struct warlock_t : public player_t
90 {
91 public:
92  player_t* havoc_target;
93  player_t* ua_target; //Used for handling Unstable Affliction target swaps
94  std::vector<action_t*> havoc_spells; // Used for smarter target cache invalidation.
95  double agony_accumulator;
96  double corruption_accumulator;
97  std::vector<event_t*> wild_imp_spawns; // Used for tracking incoming imps from HoG
98 
99  unsigned active_pets;
100 
101  // Main pet held in active/last, guardians should be handled by pet spawners. TODO: Use spawner for Infernal/Darkglare?
102  struct pets_t
103  {
104  warlock_pet_t* active;
105  warlock_pet_t* last;
106  static const int INFERNAL_LIMIT = 1;
107  static const int DARKGLARE_LIMIT = 1;
108 
109  //TODO: Refactor infernal code including new talent Rain of Chaos
110  std::array<pets::destruction::infernal_t*, INFERNAL_LIMIT> infernals;
112  roc_infernals; // Infernal(s) summoned by Rain of Chaos
114  blasphemy; // T28 Destruction 4pc pet
115 
116  std::array<pets::affliction::darkglare_t*, DARKGLARE_LIMIT> darkglare;
117 
122 
125 
126  //Nether Portal demons - Check regularly for accuracy!
137 
138  pets_t( warlock_t* w );
139  } warlock_pet_list;
140 
141  std::vector<std::string> pet_name_list;
142 
143  //TODO: Refactor or remove this whole damn section
144  struct active_t
145  {
146  spell_t* rain_of_fire; //TODO: SL Beta - This is the definition for the ground aoe event, should we move this?
147  spell_t* bilescourge_bombers; //TODO: SL Beta - This is the definition for the ground aoe event, should we move this?
148  spell_t* summon_random_demon; //TODO: SL Beta - This is the definition for a helper action for Nether Portal, should we move this?
149  melee_attack_t* soul_strike; //TODO: SL Beta - This is currently unused, Felguard pets are using manual spellID. Fix or remove.
150  } active;
151 
152  // Talents
153  struct talents_t
154  {
155  // shared
156  // tier 30 - Not Implemented
157  const spell_data_t* demon_skin;
158  const spell_data_t* burning_rush;
159  const spell_data_t* dark_pact;
160 
161  // tier 40 - Not Implemented
162  const spell_data_t* darkfury;
163  const spell_data_t* mortal_coil;
164  const spell_data_t* howl_of_terror;
165 
166  // tier 45 (Aff/Destro)
167  const spell_data_t* grimoire_of_sacrifice;
168 
169  // tier 50
170  const spell_data_t* soul_conduit; //(t45 for demo)
171 
172  // AFF
173  // tier 15
174  const spell_data_t* nightfall; //TODO: RNG information is missing from spell data, and data also says buff can potentially stack to 2. Serious testing needed, especially with multiple corruptions out!
175  const spell_data_t* inevitable_demise;
176  const spell_data_t* drain_soul;
177 
178  // tier 25
179  const spell_data_t* writhe_in_agony;
180  const spell_data_t* absolute_corruption;
181  const spell_data_t* siphon_life;
182 
183  // tier 35
184  const spell_data_t* sow_the_seeds;
185  const spell_data_t* phantom_singularity; //TODO: Dot duration uses hardcoded tick count and should be pulled from spell data instead
186  const spell_data_t* vile_taint;
187 
188  // tier 45
189  const spell_data_t* shadow_embrace; //9.1 PTR - Replaces Dark Caller
190  const spell_data_t* dark_caller; //9.1 PTR - Removed as talent
191  const spell_data_t* haunt;
192  // grimoire of sacrifice
193 
194  // tier 50
195  // soul conduit
196  const spell_data_t* creeping_death;
197  const spell_data_t* dark_soul_misery;
198 
199  // DEMO
200  // tier 15
201  const spell_data_t* dreadlash;
202  const spell_data_t* bilescourge_bombers;
203  const spell_data_t* demonic_strength; //TODO: Investigate pet buff usage
204 
205  // tier 25
206  const spell_data_t* demonic_calling;
207  const spell_data_t* power_siphon;
208  const spell_data_t* doom; //TODO: Haste/refresh behavior needs checking still
209 
210  // tier 35
211  const spell_data_t* from_the_shadows;
212  const spell_data_t* soul_strike;
213  const spell_data_t* summon_vilefiend;
214 
215  // tier 45
216  // soul conduit
217  const spell_data_t* inner_demons;
218  const spell_data_t* grimoire_felguard; //TODO: Check summoning/buff durations and if permanent Felguard is affected by this ability
219 
220  // tier 50
221  const spell_data_t* sacrificed_souls; //TODO: Check what pets/guardians count for this talent. Also relevant for demonic consumption
222  const spell_data_t* demonic_consumption;
223  const spell_data_t* nether_portal;
224 
225  // DESTRO
226  // tier 15
227  const spell_data_t* flashover;
228  const spell_data_t* eradication;
229  const spell_data_t* soul_fire; //TODO: Confirm refresh/pandemic behavior matchup for immolates
230 
231  // tier 25
232  const spell_data_t* reverse_entropy; //Note: talent spell (not the buff spell) contains RPPM data
233  const spell_data_t* internal_combustion;
234  const spell_data_t* shadowburn;
235 
236  // tier 35
237  const spell_data_t* inferno; //TODO: Confirm interaction between Inferno and Rank 2 Rain of Fire, as well as if soul shard generation is per-target hit
238  const spell_data_t* fire_and_brimstone;
239  const spell_data_t* cataclysm;
240 
241  // tier 45
242  const spell_data_t* roaring_blaze; //TODO: Confirm interaction between roaring blaze and eradication
243  const spell_data_t* rain_of_chaos;
244  // grimoire of sacrifice
245 
246  // tier 50
247  // soul conduit
248  const spell_data_t* channel_demonfire; //TODO: Confirm aoe behavior on each tick is correct in sims
249  const spell_data_t* dark_soul_instability;
250  } talents;
251 
252  struct legendary_t
253  {
254  // Legendaries
255  // Cross-spec
256  item_runeforge_t claw_of_endereth;
257  item_runeforge_t relic_of_demonic_synergy; //TODO: Do pet and warlock procs share a single RPPM?
258  item_runeforge_t wilfreds_sigil_of_superior_summoning;
259  // Affliction
260  item_runeforge_t malefic_wrath;
261  item_runeforge_t perpetual_agony_of_azjaqir;
262  item_runeforge_t sacrolashs_dark_strike; //TODO: Check if slow effect (unimplemented atm) can proc anything important
263  item_runeforge_t wrath_of_consumption;
264  // Demonology
265  item_runeforge_t balespiders_burning_core;
266  item_runeforge_t forces_of_the_horned_nightmare;
267  item_runeforge_t grim_inquisitors_dread_calling;
268  item_runeforge_t implosive_potential;
269  // Destruction
270  item_runeforge_t cinders_of_the_azjaqir;
271  item_runeforge_t embers_of_the_diabolic_raiment;
272  item_runeforge_t madness_of_the_azjaqir;
273  item_runeforge_t odr_shawl_of_the_ymirjar;
274  // Covenant
275  item_runeforge_t languishing_soul_detritus;
276  item_runeforge_t shard_of_annihilation;
277  item_runeforge_t decaying_soul_satchel;
278  item_runeforge_t contained_perpetual_explosion;
279  } legendary;
280 
281  struct conduit_t
282  {
283  // Conduits
284  // Covenant Abilities
285  conduit_data_t catastrophic_origin; // Venthyr
286  conduit_data_t soul_eater; // Night Fae
287  conduit_data_t fatal_decimation; // Necrolord
288  conduit_data_t soul_tithe; // Kyrian
289  // Affliction
290  conduit_data_t cold_embrace; //9.1 PTR - Removed
291  conduit_data_t corrupting_leer;
292  conduit_data_t focused_malignancy;
293  conduit_data_t rolling_agony;
294  conduit_data_t withering_bolt; //9.1 PTR - New, replaces Cold Embrace
295  // Demonology
296  conduit_data_t borne_of_blood;
297  conduit_data_t carnivorous_stalkers;
298  conduit_data_t fel_commando;
299  conduit_data_t tyrants_soul;
300  // Destruction
301  conduit_data_t ashen_remains;
302  conduit_data_t combusting_engine;
303  conduit_data_t duplicitous_havoc;
304  conduit_data_t infernal_brand;
305  } conduit;
306 
307  struct covenant_t
308  {
309  // Covenant Abilities
310  const spell_data_t* decimating_bolt; // Necrolord
311  const spell_data_t* impending_catastrophe; // Venthyr
312  const spell_data_t* scouring_tithe; // Kyrian
313  const spell_data_t* soul_rot; // Night Fae
314  } covenant;
315 
316  // Mastery Spells
318  {
319  const spell_data_t* potent_afflictions;
320  const spell_data_t* master_demonologist;
321  const spell_data_t* chaotic_energies;
322  } mastery_spells;
323 
324  //TODO: Are there any other cooldown reducing/resetting mechanisms not currently in this struct?
325  // Cooldowns - Used for accessing cooldowns outside of their respective actions, such as reductions/resets
326  struct cooldowns_t
327  {
329  propagate_const<cooldown_t*> phantom_singularity;
331  propagate_const<cooldown_t*> demonic_tyrant;
332  propagate_const<cooldown_t*> scouring_tithe;
334  propagate_const<cooldown_t*> shadowburn;
335  } cooldowns;
336 
337  //TODO: this struct is supposedly for passives per the comment here, but that is potentially outdated. Consider refactoring and reorganizing ALL of this.
338  //TODO: Does find spec spell have rank support? If so, USE IT in assigning data to these
339  // Passives
340  struct specs_t
341  {
342  // All Specs
343  const spell_data_t* nethermancy; //The probably actual spell controlling armor type bonus. NOTE: Level req is missing, this matches in game behavior.
344  const spell_data_t* demonic_embrace; //Warlock stamina passive
345  //TODO: Corruption is now class-wide
346  //TODO: Ritual of Doom?
347 
348  // Affliction only
349  const spell_data_t* affliction; //Spec aura
350  const spell_data_t* agony; //This is the primary active ability
351  const spell_data_t* agony_2; //Rank 2 passive (increased stacks)
352  const spell_data_t* corruption_2; //Rank 2 passive (instant cast)
353  const spell_data_t* corruption_3; //Rank 3 passive (damage on cast component)
354  const spell_data_t* summon_darkglare; //This is the active summon ability
355  const spell_data_t* unstable_affliction; //This is the primary active ability
356  const spell_data_t* unstable_affliction_2; //Rank 2 passive (soul shard on death)
357  const spell_data_t* unstable_affliction_3; //Rank 3 passive (increased duration)
358  const spell_data_t* summon_darkglare_2; //9.1 PTR - Now a passive learned at level 58
359  const spell_data_t* deliberate_corruption; //9.2 PTR - Tier set causes instant corruption damage with Absolute Corruption talented
360 
361  // Demonology only
362  const spell_data_t* demonology; //Spec aura
363  const spell_data_t* call_dreadstalkers_2; //Rank 2 passive (reduced cast time, increased pet move speed)
364  const spell_data_t* demonic_core; //Spec passive for the ability. See also: buffs.demonic_core
365  const spell_data_t* fel_firebolt_2; //Rank 2 passive (reduced energy)
366  const spell_data_t* summon_demonic_tyrant_2; //Rank 2 passive (instant soul shard generation)
367  //TODO: Should Implosion be in this list? Currently in spells.implosion_aoe
368 
369  // Destruction only
370  const spell_data_t* destruction; //Spec aura
371  const spell_data_t* conflagrate; //TODO: This is the primary active ability, but is not currently being used. Fix this.
372  const spell_data_t* conflagrate_2; //Rank 2 passive (increased charges)
373  const spell_data_t* havoc; //This is the primary active ability
374  //TODO: debuffs_havoc is currently referencing the spellID directly for rank 2, fix or remove.
375  const spell_data_t* havoc_2; //Rank 2 passive (increased duration)
376  const spell_data_t* immolate; //TODO: this is supposed to be the primary active ability but is not being used at the moment - fix this
377  const spell_data_t* rain_of_fire_2; //Rank 2 passive (increased damage)
378  const spell_data_t* summon_infernal_2; //Rank 2 passive (impact damage)
379  } spec;
380 
381  // Buffs
382  struct buffs_t
383  {
384  propagate_const<buff_t*> demonic_power; //Buff from Summon Demonic Tyrant (increased demon damage + duration)
385  propagate_const<buff_t*> grimoire_of_sacrifice; //Buff which grants damage proc
386 
387  // Affliction Buffs
388  propagate_const<buff_t*> drain_life; //Dummy buff used internally for handling Inevitable Demise cases
389  propagate_const<buff_t*> nightfall;
390  propagate_const<buff_t*> inevitable_demise;
391  propagate_const<buff_t*> dark_soul_misery;
392  propagate_const<buff_t*> calamitous_crescendo;
393 
394  // Demonology Buffs
395  propagate_const<buff_t*> demonic_core;
396  propagate_const<buff_t*> power_siphon; //Hidden buff from Power Siphon that increases damage of successive Demonbolts
397  propagate_const<buff_t*> demonic_calling;
398  propagate_const<buff_t*> inner_demons;
399  propagate_const<buff_t*> nether_portal;
400  propagate_const<buff_t*> wild_imps; //Buff for tracking how many Wild Imps are currently out (does NOT include imps waiting to be spawned)
401  propagate_const<buff_t*> malicious_imps; // Buff for tracking T28 4pc pet
402  propagate_const<buff_t*> dreadstalkers; //Buff for tracking number of Dreadstalkers currently out
403  propagate_const<buff_t*> vilefiend; //Buff for tracking if Vilefiend is currently out
404  propagate_const<buff_t*> tyrant; //Buff for tracking if Demonic Tyrant is currently out
405  propagate_const<buff_t*> portal_summons; //TODO: Fix tracking with this or remove
406  propagate_const<buff_t*> grimoire_felguard; //Buff for tracking if GFG pet is currently out
407  propagate_const<buff_t*> prince_malchezaar; //Buff for tracking Malchezaar (who is currently disabled in sims)
408  propagate_const<buff_t*> eyes_of_guldan; //Buff for tracking if rare random summon is currently out
409 
410  // Destruction Buffs
411  propagate_const<buff_t*> backdraft; //Buff associated with Conflagrate
412  propagate_const<buff_t*> reverse_entropy;
413  propagate_const<buff_t*> rain_of_chaos;
414  propagate_const<buff_t*> dark_soul_instability;
415  propagate_const<buff_t*> impending_ruin;
416  propagate_const<buff_t*> ritual_of_ruin;
417  // Possible TODO: There is a new buff for Blasphemy when the pet is out, may be useful for simplifying mechanics/APL
418  // Requires manually adding spell ID to generator
419 
420  // Covenants
421  propagate_const<buff_t*> decimating_bolt;
422  propagate_const<buff_t*> tyrants_soul;
423  propagate_const<buff_t*> soul_tithe;
424  propagate_const<buff_t*> soul_rot; // Buff for determining if Drain Life is zero cost and aoe.
425 
426  // Legendaries
427  propagate_const<buff_t*> madness_of_the_azjaqir;
428  propagate_const<buff_t*> balespiders_burning_core;
429  propagate_const<buff_t*> malefic_wrath;
430  propagate_const<buff_t*> wrath_of_consumption;
431  propagate_const<buff_t*> implosive_potential;
432  propagate_const<buff_t*> implosive_potential_small;
433  propagate_const<buff_t*> dread_calling;
434  propagate_const<buff_t*> demonic_synergy;
435  propagate_const<buff_t*> languishing_soul_detritus; //TODO: Check what happens with Havoc and triggering both scenarios at once
436  propagate_const<buff_t*> shard_of_annihilation;
437  propagate_const<buff_t*> decaying_soul_satchel_haste; //These are one unified buff in-game but splitting them in simc to make it easier to apply stat pcts
438  propagate_const<buff_t*> decaying_soul_satchel_crit;
439  } buffs;
440 
441  //TODO: Determine if any gains are not currently being tracked
442  // Gains - Many of these are automatically handled for resource gains if get_gain( name ) is given the same name as the action source
443  struct gains_t
444  {
445  gain_t* soul_conduit;
446 
447  gain_t* agony;
448  gain_t* drain_soul;
449  gain_t* unstable_affliction_refund;
450 
451  gain_t* conflagrate;
452  gain_t* incinerate;
453  gain_t* incinerate_crits;
454  gain_t* incinerate_fnb;
455  gain_t* incinerate_fnb_crits;
456  gain_t* immolate;
457  gain_t* immolate_crits;
458  gain_t* soul_fire;
459  gain_t* infernal;
460  gain_t* shadowburn_refund;
461  gain_t* inferno;
462 
463  gain_t* miss_refund;
464 
465  gain_t* shadow_bolt;
466  gain_t* doom;
467  gain_t* summon_demonic_tyrant;
468 
469  // SL
470  gain_t* scouring_tithe;
471 
472  // T28
473  gain_t* return_soul; // Demonology 4pc
474  } gains;
475 
476  // Procs
477  struct procs_t
478  {
479  proc_t* soul_conduit;
480 
481  // aff
482  proc_t* nightfall;
483  proc_t* corrupting_leer;
484  proc_t* malefic_wrath;
485  proc_t* calamitous_crescendo;
486  std::array<proc_t*, 8> malefic_rapture; // This length should be at least equal to the maximum number of Affliction DoTs that can be active on a target.
487 
488  // demo
489  proc_t* demonic_calling;
490  proc_t* one_shard_hog;
491  proc_t* two_shard_hog;
492  proc_t* three_shard_hog;
493  proc_t* summon_random_demon;
494  proc_t* portal_summon;
495  proc_t* carnivorous_stalkers; // SL - Conduit
496  proc_t* horned_nightmare; // SL - Legendary
497  proc_t* malicious_imp; // T28 4pc
498 
499  // destro
500  proc_t* reverse_entropy;
501  proc_t* rain_of_chaos;
502  proc_t* ritual_of_ruin;
503  proc_t* avatar_of_destruction;
504  } procs;
505 
506  int initial_soul_shards;
507  std::string default_pet;
508  shuffled_rng_t* rain_of_chaos_rng;
509  const spell_data_t* version_9_2_0_data;
510 
511  warlock_t( sim_t* sim, util::string_view name, race_e r );
512 
513  // Character Definition
514  void init_spells() override;
515  void init_base_stats() override;
516  void init_scaling() override;
517  void create_buffs() override;
518  void init_gains() override;
519  void init_procs() override;
520  void init_rng() override;
521  void init_action_list() override;
522  void init_resources( bool force ) override;
523  void init_special_effects() override;
524  void reset() override;
525  void create_options() override;
526  int get_spawning_imp_count();
527  timespan_t time_to_imps( int count );
528  int imps_spawned_during( timespan_t period );
529  void darkglare_extension_helper( warlock_t* p, timespan_t darkglare_extension );
530  void malignancy_reduction_helper();
531  bool min_version_check( version_check_e version ) const;
532  action_t* create_action( util::string_view name, util::string_view options ) override;
533  pet_t* create_pet( util::string_view name, util::string_view type = {} ) override;
534  void create_pets() override;
535  std::string create_profile( save_e ) override;
536  void copy_from( player_t* source ) override;
537  resource_e primary_resource() const override
538  {
539  return RESOURCE_MANA;
540  }
541  role_e primary_role() const override
542  {
543  return ROLE_SPELL;
544  }
545  stat_e convert_hybrid_stat( stat_e s ) const override;
546  double matching_gear_multiplier( attribute_e attr ) const override;
547  double composite_player_multiplier( school_e school ) const override;
548  double composite_player_target_multiplier( player_t* target, school_e school ) const override;
549  double composite_player_pet_damage_multiplier( const action_state_t*, bool ) const override;
550  double composite_player_target_pet_damage_multiplier( player_t* target, bool guardian ) const override;
551  double composite_rating_multiplier( rating_e rating ) const override;
552  void invalidate_cache( cache_e ) override;
553  double composite_spell_crit_chance() const override;
554  double composite_spell_haste() const override;
555  double composite_melee_haste() const override;
556  double composite_melee_crit_chance() const override;
557  double composite_mastery() const override;
558  double resource_regen_per_second( resource_e ) const override;
559  double composite_attribute_multiplier( attribute_e attr ) const override;
560  void combat_begin() override;
561  void init_assessors() override;
562  std::unique_ptr<expr_t> create_expression( util::string_view name_str ) override;
563  std::string default_potion() const override { return warlock_apl::potion( this ); }
564  std::string default_flask() const override { return warlock_apl::flask( this ); }
565  std::string default_food() const override { return warlock_apl::food( this ); }
566  std::string default_rune() const override { return warlock_apl::rune( this ); }
567  std::string default_temporary_enchant() const override { return warlock_apl::temporary_enchant( this ); }
568  void apply_affecting_auras( action_t& action ) override;
569 
571 
572  const warlock_td_t* find_target_data( const player_t* target ) const override
573  {
574  return target_data[ target ];
575  }
576 
577  warlock_td_t* get_target_data( player_t* target ) const override
578  {
579  warlock_td_t*& td = target_data[ target ];
580  if ( !td )
581  {
582  td = new warlock_td_t( target, const_cast<warlock_t&>( *this ) );
583  }
584  return td;
585  }
586 
587  // sc_warlock
588  action_t* create_action_warlock( util::string_view, util::string_view );
589 
590  // sc_warlock_affliction
591  action_t* create_action_affliction( util::string_view, util::string_view );
592  void create_buffs_affliction();
593  void init_spells_affliction();
594  void init_gains_affliction();
595  void init_rng_affliction();
596  void init_procs_affliction();
597 
598  // sc_warlock_demonology
599  action_t* create_action_demonology( util::string_view, util::string_view );
600  void create_buffs_demonology();
601  void init_spells_demonology();
602  void init_gains_demonology();
603  void init_rng_demonology();
604  void init_procs_demonology();
605 
606  // sc_warlock_destruction
607  action_t* create_action_destruction( util::string_view, util::string_view );
608  void create_buffs_destruction();
609  void init_spells_destruction();
610  void init_gains_destruction();
611  void init_rng_destruction();
612  void init_procs_destruction();
613 
614  // sc_warlock_pets
615  pet_t* create_main_pet( util::string_view pet_name, util::string_view pet_type );
616  pet_t* create_demo_pet( util::string_view pet_name, util::string_view pet_type );
617  void create_all_pets();
618  std::unique_ptr<expr_t> create_pet_expression( util::string_view name_str );
619 };
620 
621 namespace actions
622 {
623 //Event for triggering delayed refunds from Soul Conduit
624 //Delay prevents instant reaction time issues for rng refunds
625 struct sc_event_t : public player_event_t
626 {
627  gain_t* shard_gain;
628  warlock_t* pl;
629  int shards_used;
630 
631  sc_event_t( warlock_t* p, int c )
632  : player_event_t( *p, 100_ms ),
633  shard_gain( p->gains.soul_conduit ),
634  pl( p ),
635  shards_used( c )
636  {
637  }
638 
639  virtual const char* name() const override
640  {
641  return "soul_conduit_event";
642  }
643 
644  virtual void execute() override
645  {
646  double soul_conduit_rng = pl->talents.soul_conduit->effectN( 1 ).percent();
647 
648  for ( int i = 0; i < shards_used; i++ )
649  {
650  if ( rng().roll( soul_conduit_rng ) )
651  {
652  pl->sim->print_log( "Soul Conduit proc occurred for Warlock {}, refunding 1.0 soul shards.", pl->name() );
653  pl->resource_gain( RESOURCE_SOUL_SHARD, 1.0, shard_gain );
654  pl->procs.soul_conduit->occur();
655  }
656  }
657  }
658 };
659 
660 struct warlock_heal_t : public heal_t
661 {
662  warlock_heal_t( util::string_view n, warlock_t* p, const uint32_t id ) : heal_t( n, p, p->find_spell( id ) )
663  {
664  target = p;
665  }
666 
667  warlock_t* p()
668  {
669  return static_cast<warlock_t*>( player );
670  }
671  const warlock_t* p() const
672  {
673  return static_cast<warlock_t*>( player );
674  }
675 };
676 
677 struct warlock_spell_t : public spell_t
678 {
679 public:
680  gain_t* gain;
681  bool can_havoc; //Needed in main module for cross-spec spells such as Covenants
682  bool affected_by_woc; // SL - Legendary (Wrath of Consumption) checker
683  bool affected_by_soul_tithe; // SL - Covenant (Kyrian) checker
684  //TODO: Refactor affected_by stuff to be more streamlined
685 
686  warlock_spell_t( warlock_t* p, util::string_view n ) : warlock_spell_t( n, p, p->find_class_spell( n ) )
687  {
688  }
689 
690  warlock_spell_t( warlock_t* p, util::string_view n, specialization_e s )
691  : warlock_spell_t( n, p, p->find_class_spell( n, s ) )
692  {
693  }
694 
695  warlock_spell_t( util::string_view token, warlock_t* p, const spell_data_t* s = spell_data_t::nil() )
696  : spell_t( token, p, s )
697  {
698  may_crit = true;
699  tick_may_crit = true;
700  weapon_multiplier = 0.0;
701  gain = player->get_gain( name_str );
702  can_havoc = false;
703 
704  //TOCHECK: Is there a way to link this to the buffs.x spell data so we don't have to remember this is hardcoded?
705  affected_by_woc = data().affected_by( p->find_spell( 337130 )->effectN( 1 ) );
706 
707  affected_by_soul_tithe = data().affected_by( p->find_spell( 340238 )->effectN( 1 ) );
708  }
709 
710  warlock_t* p()
711  {
712  return static_cast<warlock_t*>( player );
713  }
714  const warlock_t* p() const
715  {
716  return static_cast<warlock_t*>( player );
717  }
718 
719  warlock_td_t* td( player_t* t )
720  {
721  return p()->get_target_data( t );
722  }
723 
724  const warlock_td_t* td( player_t* t ) const
725  {
726  return p()->get_target_data( t );
727  }
728 
729  void reset() override
730  {
731  spell_t::reset();
732  }
733 
734  double cost() const override
735  {
736  double c = spell_t::cost();
737  return c;
738  }
739 
740  void consume_resource() override
741  {
742  spell_t::consume_resource();
743 
744  if ( resource_current == RESOURCE_SOUL_SHARD && p()->in_combat )
745  {
746  // lets try making all lock specs not react instantly to shard gen
747  if ( p()->talents.soul_conduit->ok() )
748  {
749  make_event<sc_event_t>( *p()->sim, p(), as<int>( last_resource_cost ) );
750  }
751 
752  if ( p()->legendary.wilfreds_sigil_of_superior_summoning->ok() )
753  {
754  switch ( p()->specialization() )
755  {
756  case WARLOCK_AFFLICTION:
757  p()->cooldowns.darkglare->adjust( -last_resource_cost * p()->legendary.wilfreds_sigil_of_superior_summoning->effectN( 1 ).time_value(), false );
758  break;
759  case WARLOCK_DEMONOLOGY:
760  p()->cooldowns.demonic_tyrant->adjust( -last_resource_cost * p()->legendary.wilfreds_sigil_of_superior_summoning->effectN( 2 ).time_value(), false );
761  break;
762  case WARLOCK_DESTRUCTION:
763  p()->cooldowns.infernal->adjust( -last_resource_cost * p()->legendary.wilfreds_sigil_of_superior_summoning->effectN( 3 ).time_value(), false );
764  break;
765  default:
766  break;
767  }
768  }
769  }
770  }
771 
772  void impact( action_state_t* s ) override
773  {
774  spell_t::impact( s );
775  }
776 
777  double composite_target_multiplier( player_t* t ) const override
778  {
779  double m = spell_t::composite_target_multiplier( t );
780  return m;
781  }
782 
783  double action_multiplier() const override
784  {
785  double pm = spell_t::action_multiplier();
786 
787  if ( p()->buffs.soul_tithe->check() && affected_by_soul_tithe )
788  pm *= 1.0 + p()->buffs.soul_tithe->check_stack_value();
789 
790  pm *= 1.0 + p()->buffs.demonic_synergy->check_stack_value();
791 
792  return pm;
793  }
794 
795  double composite_ta_multiplier( const action_state_t* s ) const override
796  {
797  double m = spell_t::composite_ta_multiplier( s );
798 
799  if ( p()->legendary.wrath_of_consumption.ok() && p()->buffs.wrath_of_consumption->check() && affected_by_woc )
800  m *= 1.0 + p()->buffs.wrath_of_consumption->check_stack_value();
801 
802  return m;
803  }
804 
805  void extend_dot( dot_t* dot, timespan_t extend_duration )
806  {
807  if ( dot->is_ticking() )
808  {
809  dot->adjust_duration( extend_duration, dot->current_action->dot_duration * 1.5 );
810  }
811  }
812 
813  //Destruction specific things for Havoc that unfortunately need to be in main module
814 
815  bool use_havoc() const
816  {
817  // Ensure we do not try to hit the same target twice.
818  return can_havoc && p()->havoc_target && p()->havoc_target != target;
819  }
820 
821  int n_targets() const override
822  {
823  if ( p()->specialization() == WARLOCK_DESTRUCTION && use_havoc() )
824  {
825  assert(spell_t::n_targets() == 0);
826  return 2;
827  }
828  else
829  return spell_t::n_targets();
830  }
831 
832  size_t available_targets(std::vector<player_t*>& tl) const override
833  {
834  spell_t::available_targets(tl);
835 
836  // Check target list size to prevent some silly scenarios where Havoc target
837  // is the only target in the list.
838  if ( p()->specialization() == WARLOCK_DESTRUCTION && tl.size() > 1 && use_havoc())
839  {
840  // We need to make sure that the Havoc target ends up second in the target list,
841  // so that Havoc spells can pick it up correctly.
842  auto it = range::find(tl, p()->havoc_target);
843  if (it != tl.end())
844  {
845  tl.erase(it);
846  tl.insert(tl.begin() + 1, p()->havoc_target);
847  }
848  }
849 
850  return tl.size();
851  }
852 
853  void init() override
854  {
855  spell_t::init();
856 
857  if ( p()->specialization() == WARLOCK_DESTRUCTION && can_havoc )
858  {
859  // SL - Conduit
860  base_aoe_multiplier *= p()->spec.havoc->effectN(1).percent() + p()->conduit.duplicitous_havoc.percent();
861  p()->havoc_spells.push_back(this);
862  }
863  }
864 
865  //End Destruction specific things
866 
867  std::unique_ptr<expr_t> create_expression( util::string_view name_str ) override
868  {
869  return spell_t::create_expression( name_str );
870  }
871 };
872 
874 {
876  : warlock_spell_t("grimoire_of_sacrifice_damage_proc", p, p->find_spell(196100))
877  {
878  background = true;
879  proc = true;
880  }
881 };
882 
884 {
885  warlock_t* owner;
886 
888  : dbc_proc_callback_t( p, e ), owner( p )
889  {
890  }
891 
892  void execute( action_t* /* a */, action_state_t* ) override
893  {
894  if ( owner->warlock_pet_list.active )
895  {
896  auto pet = owner->warlock_pet_list.active;
897  //Always set the pet's buff value using the owner's to ensure specialization value is correct
898  pet->buffs.demonic_synergy->trigger( 1, owner->buffs.demonic_synergy->default_value );
899  }
900  }
901 };
902 
904 
906 {
907  timespan_t summoning_duration;
908  std::string pet_name;
910 
911 private:
912  void _init_summon_pet_t()
913  {
914  util::tokenize( pet_name );
915  harmful = false;
916 
917  if ( data().ok() &&
918  std::find( p()->pet_name_list.begin(), p()->pet_name_list.end(), pet_name ) == p()->pet_name_list.end() )
919  {
920  p()->pet_name_list.push_back( pet_name );
921  }
922  }
923 
924 public:
925  summon_pet_t( util::string_view n, warlock_t* p, util::string_view sname = {} )
926  : warlock_spell_t( p, sname.empty() ? fmt::format( "Summon {}", n ) : sname ),
927  summoning_duration( timespan_t::zero() ),
928  pet_name( sname.empty() ? n : sname ),
929  pet( nullptr )
930  {
931  _init_summon_pet_t();
932  }
933 
934  summon_pet_t( util::string_view n, warlock_t* p, int id )
935  : warlock_spell_t( n, p, p->find_spell( id ) ),
936  summoning_duration( timespan_t::zero() ),
937  pet_name( n ),
938  pet( nullptr )
939  {
940  _init_summon_pet_t();
941  }
942 
943  summon_pet_t( util::string_view n, warlock_t* p, const spell_data_t* sd )
944  : warlock_spell_t( n, p, sd ), summoning_duration( timespan_t::zero() ), pet_name( n ), pet( nullptr )
945  {
946  _init_summon_pet_t();
947  }
948 
949  void init_finished() override
950  {
951  pet = debug_cast<warlock_pet_t*>( player->find_pet( pet_name ) );
952 
953  warlock_spell_t::init_finished();
954  }
955 
956  virtual void execute() override
957  {
958  pet->summon( summoning_duration );
959 
960  warlock_spell_t::execute();
961  }
962 
963  bool ready() override
964  {
965  if ( !pet )
966  {
967  return false;
968  }
969  return warlock_spell_t::ready();
970  }
971 };
972 
974 {
975  cooldown_t* instant_cooldown;
976 
977  summon_main_pet_t( util::string_view n, warlock_t* p, int id )
978  : summon_pet_t( n, p, id ), instant_cooldown( p->get_cooldown( "instant_summon_pet" ) )
979  {
980  instant_cooldown->duration = 60_s;
981  ignore_false_positive = true;
982  }
983 
984  summon_main_pet_t( util::string_view n, warlock_t* p )
985  : summon_pet_t( n, p ), instant_cooldown( p->get_cooldown( "instant_summon_pet" ) )
986  {
987  instant_cooldown->duration = 60_s;
988  ignore_false_positive = true;
989  }
990 
991  void schedule_execute( action_state_t* state = nullptr ) override
992  {
993  warlock_spell_t::schedule_execute( state );
994 
995  if ( p()->warlock_pet_list.active )
996  {
997  p()->warlock_pet_list.active->dismiss();
998  p()->warlock_pet_list.active = nullptr;
999  }
1000  }
1001 
1002  virtual bool ready() override
1003  {
1004  if ( p()->warlock_pet_list.active == pet )
1005  return false;
1006 
1007  return summon_pet_t::ready();
1008  }
1009 
1010  virtual void execute() override
1011  {
1012  summon_pet_t::execute();
1013 
1014  p()->warlock_pet_list.active = p()->warlock_pet_list.last = pet;
1015 
1016  if ( p()->buffs.grimoire_of_sacrifice->check() )
1017  p()->buffs.grimoire_of_sacrifice->expire();
1018  }
1019 };
1020 
1021 // Event for spawning wild imps for Demonology
1022 // Placed in warlock.cpp for expression purposes
1024 {
1025  timespan_t diff;
1026 
1027  imp_delay_event_t( warlock_t* p, double delay, double exp ) : player_event_t( *p, timespan_t::from_millis( delay ) )
1028  {
1029  diff = timespan_t::from_millis( exp - delay );
1030  }
1031 
1032  virtual const char* name() const override
1033  {
1034  return "imp_delay";
1035  }
1036 
1037  virtual void execute() override
1038  {
1039  warlock_t* p = static_cast<warlock_t*>( player() );
1040 
1041  p->warlock_pet_list.wild_imps.spawn();
1042 
1043  // Remove this event from the vector
1044  auto it = std::find( p->wild_imp_spawns.begin(), p->wild_imp_spawns.end(), this );
1045  if ( it != p->wild_imp_spawns.end() )
1046  p->wild_imp_spawns.erase( it );
1047  }
1048 
1049  // Used for APL expressions to estimate when imp is "supposed" to spawn
1050  timespan_t expected_time()
1051  {
1052  return std::max( 0_ms, this->remains() + diff );
1053  }
1054 };
1055 } // namespace actions
1056 
1057 namespace buffs
1058 {
1059 template <typename Base>
1060 struct warlock_buff_t : public Base
1061 {
1062 public:
1063  using base_t = warlock_buff_t;
1064  warlock_buff_t( warlock_td_t& p, util::string_view name, const spell_data_t* s = spell_data_t::nil(),
1065  const item_t* item = nullptr )
1066  : Base( p, name, s, item )
1067  {
1068  }
1069 
1070  warlock_buff_t( warlock_t& p, util::string_view name, const spell_data_t* s = spell_data_t::nil(),
1071  const item_t* item = nullptr )
1072  : Base( &p, name, s, item )
1073  {
1074  }
1075 
1076 protected:
1077  warlock_t* p()
1078  {
1079  return static_cast<warlock_t*>( Base::source );
1080  }
1081  const warlock_t* p() const
1082  {
1083  return static_cast<warlock_t*>( Base::source );
1084  }
1085 };
1086 } // namespace buffs
1087 
1088 
1089 } // namespace warlock
Definition: sc_warlock.hpp:883
Definition: sc_warlock.hpp:307
Definition: sc_warlock.hpp:340
Definition: sc_warlock.hpp:281
double composite_ta_multiplier(const action_state_t *s) const override
Normal ticking modifiers that are updated every tick.
Definition: sc_warlock.hpp:795
Definition: sc_demon_hunter.cpp:42
Definition: shuffled_rng.hpp:20
Definition: gain.hpp:17
Definition: sc_warlock.hpp:317
Definition: sc_warlock.hpp:1060
timespan_t dot_duration
Default full duration of dot.
Definition: action.hpp:302
Definition: attack.hpp:75
Definition: sc_warlock.hpp:477
Definition: cooldown.hpp:26
Definition: target_specific.hpp:20
void print_log(fmt::format_string< Args... > format, Args &&... args)
Convenient log function using python-like formatting.
Definition: sim.hpp:737
Definition: spell_data.hpp:398
Definition: sc_warlock.hpp:1023
Definition: sc_warlock.hpp:252
Definition: sc_warlock.hpp:382
Definition: sc_warlock.hpp:33
virtual double composite_ta_multiplier(const action_state_t *) const
Normal ticking modifiers that are updated every tick.
Definition: action.cpp:4409
Definition: action.hpp:47
Definition: unique_gear.cpp:62
Definition: sc_warlock.hpp:973
Definition: generic.hpp:567
Definition: action_state.hpp:20
Definition: runeforge_data.hpp:20
Definition: player_event.hpp:14
Definition: sc_warlock_pets.hpp:26
virtual bool ready() override
Is the ability ready based on spell characteristics.
Definition: sc_warlock.hpp:1002
Definition: covenant.cpp:108
Definition: sc_warlock.cpp:11
Definition: sc_shaman.cpp:2212
Definition: sc_warlock.hpp:625
Definition: proc.hpp:18
bool background
Enables/Disables direct execution of the ability in an action list.
Definition: action.hpp:131
Definition: sc_warlock.hpp:443
Definition: sc_warlock.hpp:905
virtual double cost() const
Resource cost of the action for current_resource()
Definition: action.cpp:1029
Definition: item.hpp:60
Class for representing InGame time.
Definition: timespan.hpp:37
Definition: player.hpp:109
void execute(action_t *, action_state_t *) override
Base rules for proc execution.
Definition: sc_warlock.hpp:892
Definition: sc_warlock.hpp:89
Definition: sc_warlock.hpp:677
Definition: pet.hpp:14
Definition: spell.hpp:11
Definition: dot.hpp:27
Definition: covenant.hpp:34
double cost() const override
Resource cost of the action for current_resource()
Definition: sc_warlock.hpp:734
Definition: sc_warlock.hpp:326
Definition: sc_warlock.hpp:144
Definition: residual_action.hpp:35
Definition: heal.hpp:12
Random number generation.
Definition: action.hpp:37
A wrapper object to enable dynamic pet spawns in simulationcraft.
Definition: pet_spawner.hpp:56
DBC-driven proc callback.
Definition: dbc_proc_callback.hpp:40
Definition: sc_demon_hunter.cpp:44
bool ready() override
Is the ability ready based on spell characteristics.
Definition: sc_warlock.hpp:963
Simulation engine.
Definition: sim.hpp:61
const spell_data_t * find_spell(util::string_view name, specialization_e s=SPEC_NONE) const
Tries to find spell data by name.
Definition: player.cpp:10165
Definition: actor_target_data.hpp:15
Definition: sc_warlock.hpp:660
Definition: sc_warlock.hpp:153
Definition: special_effect.hpp:39
Definition: sc_warlock.hpp:102