SimulationCraft
SimulationCraft is a tool to explore combat mechanics in the popular MMO RPG World of Warcraft (tm).
sc_warlock_pets.hpp
1 // ==========================================================================
2 // Dedmonwakeen's Raid DPS/TPS Simulator.
3 // Send questions to [email protected]
4 // ==========================================================================
5 #ifndef SC_WARLOCK_PETS_HPP
6 #define SC_WARLOCK_PETS_HPP
7 
8 #include "simulationcraft.hpp"
9 
10 namespace warlock
11 {
12 // Forward declarations
13 struct warlock_t;
14 struct warlock_td_t;
15 struct warlock_pet_t;
16 
18 {
19  propagate_const<buff_t*> debuff_infernal_brand;
20  propagate_const<buff_t*> debuff_whiplash;
21 
24 };
25 
26 struct warlock_pet_t : public pet_t
27 {
28  action_t* special_action; // Used for pet interrupts (Axe Toss, Spell Lock)
29  melee_attack_t* melee_attack;
30  stats_t* summon_stats;
31 
32  struct buffs_t
33  {
34  propagate_const<buff_t*> embers; // Infernal Shard Generation
35  propagate_const<buff_t*> demonic_strength; // Talent that buffs Felguard
36  propagate_const<buff_t*> demonic_consumption; // Talent that buffs Demonic Tyrant
37  propagate_const<buff_t*> grimoire_of_service; // Buff used by Grimoire: Felguard talent
38  propagate_const<buff_t*> grim_inquisitors_dread_calling; // Buff used by SL Legendary
39  propagate_const<buff_t*> demonic_synergy; // Buff used by SL Legendary (Relic of Demonic Synergy)
40  } buffs;
41 
42  bool is_main_pet = false;
43 
44  warlock_pet_t( warlock_t*, util::string_view, pet_e, bool = false );
45  void init_base_stats() override;
46  void init_action_list() override;
47  void create_buffs() override;
48  void schedule_ready( timespan_t = 0_ms, bool = false ) override;
49  double composite_player_multiplier( school_e ) const override;
50  double composite_player_target_multiplier( player_t*, school_e ) const override;
51  void init_special_effects() override;
52 
54 
55  const warlock_pet_td_t* find_target_data( const player_t* target ) const override
56  {
57  return target_data[ target ];
58  }
59 
60  warlock_pet_td_t* get_target_data( player_t* target ) const override
61  {
62  warlock_pet_td_t*& td = target_data[ target ];
63  if ( !td )
64  {
65  td = new warlock_pet_td_t( target, const_cast<warlock_pet_t&>( *this ) );
66  }
67  return td;
68  }
69 
70  resource_e primary_resource() const override
71  {
72  return RESOURCE_ENERGY;
73  }
74 
75  warlock_t* o();
76  const warlock_t* o() const;
77 
78  virtual void arise() override
79  {
80  if ( melee_attack )
81  melee_attack->reset();
82  pet_t::arise();
83  }
84 
85  // Pet action to simulate travel time. Places actor at distance 1.0.
86  // "Executes" for a length of time it would take to travel from current distance to 1.0 at 33 yds/sec
87  struct travel_t : public action_t
88  {
89  double speed;
90  double melee_pos;
91 
92  travel_t( player_t* player ) : action_t( ACTION_OTHER, "travel", player )
93  {
94  trigger_gcd = 0_ms;
95  speed = 33.0;
96  melee_pos = 1.0;
97  }
98 
99  void execute() override
100  {
101  player->current.distance = melee_pos;
102  }
103 
104  timespan_t execute_time() const override
105  {
106  return timespan_t::from_seconds( ( player->current.distance - melee_pos ) / speed );
107  }
108 
109  bool ready() override
110  {
111  //For now, we assume the pet does not ever need to be anywhere except the main raid target
112  return ( player->current.distance > melee_pos );
113  }
114 
115  bool usable_moving() const override
116  {
117  return true;
118  }
119  };
120 
121  action_t* create_action( util::string_view name, util::string_view options_str ) override
122  {
123  if ( name == "travel" )
124  return new travel_t( this );
125 
126  return pet_t::create_action( name, options_str );
127  }
128 };
129 
130 namespace pets
131 {
141 {
142  warlock_simple_pet_t( warlock_t*, util::string_view, pet_e );
143  timespan_t available() const override;
144 
145 protected:
146  action_t* special_ability;
147 };
148 
149 // Template for common warlock pet action code.
150 template <class ACTION_BASE>
151 struct warlock_pet_action_t : public ACTION_BASE
152 {
153 private:
154  typedef ACTION_BASE ab; // action base, eg. spell_t
155 public:
157 
158  warlock_pet_action_t( util::string_view n, warlock_pet_t* p, const spell_data_t* s = spell_data_t::nil() )
159  : ab( n, p, s )
160  {
161  ab::may_crit = true;
162 
163  // If pets are not reported separately, create single stats_t objects for the various pet
164  // abilities.
165  if ( !ab::sim->report_pets_separately )
166  {
167  auto first_pet = p->owner->find_pet( p->name_str );
168  if ( first_pet && first_pet != p )
169  {
170  auto it = range::find( p->stats_list, ab::stats );
171  if ( it != p->stats_list.end() )
172  {
173  p->stats_list.erase( it );
174  delete ab::stats;
175  ab::stats = first_pet->get_stats( ab::name_str, this );
176  }
177  }
178  }
179  }
180 
181  warlock_pet_t* p()
182  {
183  return static_cast<warlock_pet_t*>( ab::player );
184  }
185 
186  const warlock_pet_t* p() const
187  {
188  return static_cast<warlock_pet_t*>( ab::player );
189  }
190 
191  virtual void execute()
192  {
193  ab::execute();
194 
195  // Some aoe pet abilities can actually reduce to 0 targets, so bail out early if we hit that situation
196  if ( ab::n_targets() != 0 && ab::target_list().size() == 0 )
197  {
198  return;
199  }
200  }
201 
202  warlock_td_t* owner_td( player_t* t )
203  {
204  return p()->o()->get_target_data( t );
205  }
206 
207  const warlock_td_t* owner_td( player_t* t ) const
208  {
209  return p()->o()->get_target_data( t );
210  }
211 
212  warlock_pet_td_t* pet_td( player_t* t )
213  {
214  return p()->get_target_data( t );
215  }
216 
217  const warlock_pet_td_t* pet_td( player_t* t ) const
218  {
219  return p()->get_target_data( t );
220  }
221 };
222 
223 // TODO: Switch to a general autoattack template if one is added
224 struct warlock_pet_melee_t : public warlock_pet_action_t<melee_attack_t>
225 {
226  bool first; // Needed for t=0 autoattack execution
228 
229  warlock_pet_melee_t( warlock_pet_t* p, double wm = 1.0, const char* name = "melee" )
230  : warlock_pet_action_t<melee_attack_t>( name, p, spell_data_t::nil() ), oh( nullptr )
231  {
232  school = SCHOOL_PHYSICAL;
233  weapon = &( p->main_hand_weapon );
234  weapon_multiplier = wm;
235  base_execute_time = weapon->swing_time;
236  may_crit = background = repeating = true;
237 
238  if ( p->dual_wield() )
239  {
240  oh = new warlock_pet_action_t<melee_attack_t>( "melee_oh", p, spell_data_t::nil() );
241  oh->school = SCHOOL_PHYSICAL;
242  oh->weapon = &( p->off_hand_weapon );
243  oh->weapon_multiplier = wm;
244  oh->base_execute_time = weapon->swing_time;
245  oh->may_crit = oh->background = true;
246  oh->base_multiplier = 0.5;
247  }
248  }
249 
250  void reset() override
251  {
252  warlock_pet_action_t::reset();
253 
254  first = true;
255  }
256 
257  timespan_t execute_time() const override
258  {
259  return first ? 0_ms : warlock_pet_action_t::execute_time();
260  }
261 
262  void execute() override
263  {
264  if ( first )
265  {
266  first = false;
267  }
268  if ( !player->executing && !player->channeling )
269  {
270  melee_attack_t::execute();
271  if ( oh )
272  {
273  oh->time_to_execute = time_to_execute;
274  oh->execute();
275  }
276  }
277  else
278  {
279  schedule_execute();
280  }
281  }
282 };
283 
284 struct warlock_pet_melee_attack_t : public warlock_pet_action_t<melee_attack_t>
285 {
286 private:
287  void _init_warlock_pet_melee_attack_t()
288  {
289  weapon = &( player->main_hand_weapon );
290  special = true;
291  }
292 
293 public:
294  warlock_pet_melee_attack_t( warlock_pet_t* p, util::string_view n ) : base_t( n, p, p->find_pet_spell( n ) )
295  {
296  _init_warlock_pet_melee_attack_t();
297  }
298 
299  warlock_pet_melee_attack_t( util::string_view token, warlock_pet_t* p, const spell_data_t* s = spell_data_t::nil() )
300  : base_t( token, p, s )
301  {
302  _init_warlock_pet_melee_attack_t();
303  }
304 };
305 
307 {
308 public:
309  warlock_pet_spell_t( warlock_pet_t* p, util::string_view n ) : base_t( n, p, p->find_pet_spell( n ) )
310  {
311  }
312 
313  warlock_pet_spell_t( util::string_view token, warlock_pet_t* p, const spell_data_t* s = spell_data_t::nil() )
314  : base_t( token, p, s )
315  {
316  }
317 };
318 
319 namespace base
320 {
322 {
323  felhunter_pet_t( warlock_t*, util::string_view );
324  void init_base_stats() override;
325  action_t* create_action( util::string_view, util::string_view ) override;
326 };
327 
328 struct imp_pet_t : public warlock_pet_t
329 {
330  double firebolt_cost;
331 
332  imp_pet_t( warlock_t*, util::string_view );
333  action_t* create_action( util::string_view, util::string_view ) override;
334  timespan_t available() const override;
335 };
336 
338 {
339  sayaad_pet_t( warlock_t*, util::string_view );
340  void init_base_stats() override;
341  action_t* create_action( util::string_view, util::string_view ) override;
342  double composite_player_target_multiplier( player_t*, school_e ) const override;
343 };
344 
346 {
347  voidwalker_pet_t( warlock_t*, util::string_view );
348  void init_base_stats() override;
349  action_t* create_action( util::string_view, util::string_view ) override;
350 };
351 
352 } // namespace base
353 
354 namespace demonology
355 {
357 {
358  action_t* soul_strike;
359  cooldown_t* felstorm_cd;
360  int demonic_strength_executes;
361 
362  // Energy thresholds to wake felguard up for something to do, minimum is the felstorm energy cost,
363  // and maximum is a predetermined empirical value from in game
364  double min_energy_threshold;
365  double max_energy_threshold;
366 
367  felguard_pet_t( warlock_t*, util::string_view );
368  void init_base_stats() override;
369  action_t* create_action( util::string_view, util::string_view ) override;
370  timespan_t available() const override;
371 
372  void queue_ds_felstorm();
373 };
374 
376 {
377  const spell_data_t* felstorm_spell;
378  cooldown_t* felstorm_cd;
379 
380  // Energy thresholds to wake felguard up for something to do, minimum is the felstorm energy cost,
381  // and maximum is a predetermined empirical value from in game
382  double min_energy_threshold;
383  double max_energy_threshold;
384 
386  void init_base_stats() override;
387  action_t* create_action( util::string_view, util::string_view ) override;
388  timespan_t available() const override;
389  void arise() override;
390 };
391 
393 {
394  action_t* firebolt;
395  bool power_siphon;
396  bool demonic_consumption;
397 
399  void init_base_stats() override;
400  void create_actions() override;
401  void schedule_ready( timespan_t, bool ) override;
402  void arise() override;
403  void demise() override;
404  void finish_moving() override;
405 
406 private:
407  void reschedule_firebolt();
408 };
409 
411 {
412  action_t* firebolt;
413  action_t* doombolt;
414  action_t* spite;
415  bool imploded;
416 
418  void init_base_stats() override;
419  void create_actions() override;
420  void schedule_ready( timespan_t, bool ) override;
421  void arise() override;
422  void demise() override;
423  void finish_moving() override;
424 
425 private:
426  void reschedule_firebolt();
427 };
428 
430 {
431  int dreadbite_executes;
432 
434  void init_base_stats() override;
435  void arise() override;
436  void demise() override;
437  timespan_t available() const override;
438  action_t* create_action( util::string_view, util::string_view ) override;
439 };
440 
442 {
443  int bile_spit_executes;
444 
446  void init_base_stats() override;
447  void arise() override;
448  action_t* create_action( util::string_view, util::string_view ) override;
449 };
450 
452 {
453  demonic_tyrant_t( warlock_t*, util::string_view = "demonic_tyrant" );
454  void demise() override;
455  action_t* create_action( util::string_view, util::string_view ) override;
456 };
457 
458 namespace random_demons
459 {
461 {
462  shivarra_t( warlock_t* );
463  void init_base_stats() override;
464  void arise() override;
465  action_t* create_action( util::string_view, util::string_view ) override;
466 };
467 
469 {
471  void init_base_stats() override;
472  void arise() override;
473  action_t* create_action( util::string_view, util::string_view ) override;
474 };
475 
477 {
479  action_t* create_action( util::string_view, util::string_view ) override;
480 };
481 
483 {
484  urzul_t( warlock_t* );
485  void init_base_stats() override;
486  void arise() override;
487  action_t* create_action( util::string_view, util::string_view ) override;
488 };
489 
491 {
493  void init_base_stats() override;
494  void arise() override;
495  action_t* create_action( util::string_view, util::string_view ) override;
496 };
497 
499 {
501  void init_base_stats() override;
502  void arise() override;
503  action_t* create_action( util::string_view, util::string_view ) override;
504 };
505 
507 {
509  void init_base_stats() override;
510  void arise() override;
511  action_t* create_action( util::string_view, util::string_view ) override;
512 };
513 
515 {
517  void init_base_stats() override;
518  void arise() override;
519  action_t* create_action( util::string_view, util::string_view ) override;
520 };
521 
523 {
525  void init_base_stats() override;
526  void arise() override;
527  void demise() override;
528  action_t* create_action( util::string_view, util::string_view ) override;
529 };
530 
532 {
534  void arise() override;
535  void demise() override;
536  void init_base_stats() override;
537  timespan_t available() const override;
538 };
539 } // namespace random_demons
540 } // namespace demonology
541 
542 namespace destruction
543 {
544 struct infernal_t : public warlock_pet_t
545 {
546  buff_t* immolation;
547 
548  infernal_t( warlock_t*, util::string_view = "infernal" );
549  void init_base_stats() override;
550  void create_buffs() override;
551  void arise() override;
552  void demise() override;
553 };
554 
555 struct blasphemy_t : public infernal_t
556 {
557  blasphemy_t( warlock_t*, util::string_view = "blasphemy" );
558  action_t* blasphemous_existence;
559  void init_base_stats() override;
560 };
561 } // namespace destruction
562 
563 namespace affliction
564 {
565 struct darkglare_t : public warlock_pet_t
566 {
567  darkglare_t( warlock_t*, util::string_view = "darkglare" );
568  action_t* create_action( util::string_view , util::string_view ) override;
569 };
570 } // namespace affliction
571 } // namespace pets
572 } // namespace warlock
573 
574 #endif /* SC_WARLOCK_PETS_HPP */
bool ready() override
Is the ability ready based on spell characteristics.
Definition: sc_warlock_pets.hpp:109
Definition: sc_warlock_pets.hpp:555
Definition: sc_demon_hunter.cpp:42
Definition: sc_death_knight.cpp:45
A simple warlock pet that has a potential melee attack, and a single on-cooldown special ability that...
Definition: sc_warlock_pets.hpp:140
Definition: sc_warlock_pets.hpp:321
Definition: attack.hpp:75
Definition: cooldown.hpp:26
Definition: sc_warlock_pets.hpp:482
Definition: sc_warlock_pets.hpp:87
Definition: sc_warlock_pets.hpp:306
Definition: sc_warlock_pets.hpp:565
Definition: sc_warlock_pets.hpp:392
Definition: target_specific.hpp:20
Definition: sc_warlock_pets.hpp:460
Definition: sc_warlock_pets.hpp:337
school_e school
What type of damage this spell does.
Definition: action.hpp:74
Definition: spell_data.hpp:398
Definition: sc_warlock_pets.hpp:151
Definition: sc_warlock_pets.hpp:356
Definition: sc_warlock.hpp:33
Definition: sc_warlock_pets.hpp:17
Definition: sc_warlock_pets.hpp:429
Definition: sc_warlock_pets.hpp:544
Definition: action.hpp:47
virtual void arise() override
Player arises from the dead.
Definition: sc_warlock_pets.hpp:78
Definition: generic.hpp:567
Definition: sc_warlock_pets.hpp:32
double base_multiplier
base damage multiplier (direct and tick damage)
Definition: action.hpp:329
Definition: sc_warlock_pets.hpp:26
virtual void arise()
Player arises from the dead.
Definition: player.cpp:5848
Definition: sc_warlock_pets.hpp:328
Definition: sc_warlock.cpp:11
Definition: sc_shaman.cpp:2212
Definition: sc_warlock_pets.hpp:441
Definition: sc_warlock_pets.hpp:451
bool background
Enables/Disables direct execution of the ability in an action list.
Definition: action.hpp:131
weapon_t * weapon
Weapon used for this ability. If set extra weapon damage is calculated.
Definition: action.hpp:63
double weapon_multiplier
Weapon damage for the ability.
Definition: action.hpp:340
Definition: sc_warlock_pets.hpp:375
Definition: sc_warlock_pets.hpp:224
Class for representing InGame time.
Definition: timespan.hpp:37
Definition: player.hpp:109
Definition: sc_warlock_pets.hpp:410
timespan_t time_to_execute
Last available, effectively used execute time.
Definition: action.hpp:429
Definition: sc_warlock.hpp:89
Definition: pet.hpp:14
timespan_t base_execute_time
Amount of time the ability uses to execute before modifiers.
Definition: action.hpp:296
Definition: buff.hpp:56
Definition: actor_target_data.hpp:15
Definition: stats.hpp:25
Definition: sc_warlock_pets.hpp:345
Definition: sc_warlock_pets.hpp:284