// ==========================================================================
// Warlock Pet
// ==========================================================================
enum pet_type_t { PET_NONE=0, PET_FELGUARD, PET_FELHUNTER, PET_IMP,
PET_VOIDWALKER, PET_SUCCUBUS, PET_INFERNAL, PET_DOOMGUARD
};
struct warlock_pet_t : public pet_t
{
int pet_type;
double damage_modifier;
attack_t* melee;
warlock_pet_t( sim_t* sim, player_t* owner, const std::string& pet_name, int pt ) :
pet_t( sim, owner, pet_name ), pet_type( pt ),
damage_modifier( 1.0 ), melee( 0 )
{
}
virtual bool ooc_buffs() { return true; }
virtual void init_base()
{
pet_t::init_base();
warlock_t* o = owner -> cast_warlock();
attribute_base[ ATTR_STRENGTH ] = 314;
attribute_base[ ATTR_AGILITY ] = 90;
attribute_base[ ATTR_STAMINA ] = 328;
attribute_base[ ATTR_INTELLECT ] = 150;
attribute_base[ ATTR_SPIRIT ] = 209;
attribute_multiplier_initial[ ATTR_STAMINA ] *= 1.0 + ( o -> talents.fel_stamina * 0.03 +
o -> talents.fel_vitality * 0.05 );
attribute_multiplier_initial[ ATTR_INTELLECT ] *= 1.0 + ( o -> talents.fel_intellect * 0.03 +
o -> talents.fel_vitality * 0.05 );
base_attack_crit = 0.0328;
base_spell_crit = 0.0092;
initial_attack_power_per_strength = 2.0;
initial_attack_crit_per_agility = 0.01 / 52.0;
initial_spell_crit_per_intellect = owner -> initial_spell_crit_per_intellect;
health_per_stamina = 10;
mana_per_intellect = 10.8;
mp5_per_intellect = 2.0 / 3.0;
base_mp5 = -55;
}
virtual void schedule_ready( double delta_time=0,
bool waiting=false )
{
if ( melee && ! melee -> execute_event )
{
melee -> schedule_execute();
}
pet_t::schedule_ready( delta_time, waiting );
}
virtual void summon( double duration=0 )
{
warlock_t* o = owner -> cast_warlock();
pet_t::summon( duration );
o -> active_pet = this;
}
virtual void dismiss()
{
warlock_t* o = owner -> cast_warlock();
pet_t::dismiss();
o -> active_pet = 0;
}
virtual void interrupt()
{
pet_t::interrupt();
if ( melee ) melee -> cancel();
}
void adjust_base_modifiers( action_t* a )
{
warlock_t* o = owner -> cast_warlock();
// Orc Command Racial
if ( o -> race == RACE_ORC )
{
a -> base_multiplier *= 1.05;
}
if ( pet_type != PET_INFERNAL && pet_type != PET_DOOMGUARD )
{
a -> base_crit += o -> talents.demonic_tactics * 0.02;
a -> base_multiplier *= 1.0 + o -> talents.unholy_power * 0.04;
}
if ( pet_type == PET_FELGUARD )
{
a -> base_multiplier *= 1.0 + o -> talents.master_demonologist * 0.01;
}
else if ( pet_type == PET_IMP )
{
if ( a -> school == SCHOOL_FIRE )
{
a -> base_multiplier *= 1.0 + o -> talents.master_demonologist * 0.01;
a -> base_crit += o -> talents.master_demonologist * 0.01;
}
}
else if ( pet_type == PET_SUCCUBUS )
{
if ( a -> school == SCHOOL_SHADOW )
{
a -> base_multiplier *= 1.0 + o -> talents.master_demonologist * 0.01;
a -> base_crit += o -> talents.master_demonologist * 0.01;
}
}
if ( o -> set_bonus.tier9_2pc_caster() )
{
a -> base_crit += 0.10;
}
}
void adjust_player_modifiers( action_t* a )
{
warlock_t* o = owner -> cast_warlock();
if ( o -> talents.improved_demonic_tactics )
{
a -> player_crit += o -> composite_spell_crit() * o -> talents.improved_demonic_tactics * 0.10;
}
}
virtual double composite_attack_hit() SC_CONST
{
return owner -> composite_spell_hit();
}
virtual double composite_attack_expertise() SC_CONST
{
return owner -> composite_spell_hit() * 26.0 / 17.0;
}
virtual void register_callbacks();
virtual int primary_resource() SC_CONST { return RESOURCE_MANA; }
};
// ==========================================================================
// Warlock Pet Melee
// ==========================================================================
struct warlock_pet_melee_t : public attack_t
{
warlock_pet_melee_t( player_t* player, const char* name ) :
attack_t( name, player, RESOURCE_NONE, SCHOOL_PHYSICAL, TREE_NONE, false )
{
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
weapon = &( p -> main_hand_weapon );
base_execute_time = weapon -> swing_time;
base_dd_min = base_dd_max = 1;
may_crit = true;
background = true;
repeating = true;
p -> adjust_base_modifiers( this );
base_multiplier *= p -> damage_modifier;
}
virtual void player_buff()
{
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
attack_t::player_buff();
if ( o -> buffs_tier10_4pc_caster -> up() )
{
player_multiplier *= 1.10;
}
if ( p -> pet_type != PET_INFERNAL )
{
player_attack_power += 0.57 * o -> composite_spell_power( SCHOOL_MAX );
p -> adjust_player_modifiers( this );
}
}
};
// ==========================================================================
// Warlock Pet Attack
// ==========================================================================
struct warlock_pet_attack_t : public attack_t
{
warlock_pet_attack_t( const char* n, player_t* player, int r=RESOURCE_MANA, int s=SCHOOL_PHYSICAL ) :
attack_t( n, player, r, s, TREE_NONE, true )
{
special = true;
may_crit = true;
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
p -> adjust_base_modifiers( this );
}
virtual void execute()
{
attack_t::execute();
}
virtual void player_buff()
{
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
attack_t::player_buff();
player_attack_power += 0.57 * o -> composite_spell_power( SCHOOL_MAX );
if ( o -> buffs_tier10_4pc_caster -> up() )
{
player_multiplier *= 1.10;
}
p -> adjust_player_modifiers( this );
}
};
// ==========================================================================
// Warlock Pet Spell
// ==========================================================================
struct warlock_pet_spell_t : public spell_t
{
warlock_pet_spell_t( const char* n, player_t* player, int r=RESOURCE_MANA, int s=SCHOOL_SHADOW ) :
spell_t( n, player, r, s )
{
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
p -> adjust_base_modifiers( this );
}
virtual void player_buff()
{
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
spell_t::player_buff();
if ( o -> buffs_tier10_4pc_caster -> up() )
{
player_multiplier *= 1.10;
}
player_spell_power += 0.15 * o -> composite_spell_power( SCHOOL_MAX );
p -> adjust_player_modifiers( this );
}
};
// ==========================================================================
// Pet Imp
// ==========================================================================
struct imp_pet_t : public warlock_pet_t
{
struct fire_bolt_t : public warlock_pet_spell_t
{
fire_bolt_t( player_t* player ):
warlock_pet_spell_t( "fire_bolt", player, RESOURCE_MANA, SCHOOL_FIRE )
{
imp_pet_t* p = ( imp_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
static rank_t ranks[] =
{
{ 78, 8, 203, 227, 0, 180 },
{ 68, 8, 110, 124, 0, 145 },
{ 58, 7, 83, 93, 0, 115 },
{ 0, 0, 0, 0, 0, 0 }
};
init_rank( ranks, 47964 );
// improved_imp does not influence +SP from player
base_dd_min*=1.0 + o -> talents.improved_imp * 0.10;
base_dd_max*=1.0 + o -> talents.improved_imp * 0.10;
base_execute_time = 2.5;
direct_power_mod = ( base_execute_time / 3.5 ); // was 2.0/3.5
may_crit = true;
min_gcd = 1.0;
base_execute_time -= 0.25 * ( o -> talents.improved_fire_bolt + o -> talents.demonic_power );
base_multiplier *= 1.0 + ( o -> talents.empowered_imp * 0.10 + // o -> talents.improved_imp moved up
o -> glyphs.imp * 0.20 );
base_crit_bonus_multiplier *= 1.0 + o -> talents.ruin * 0.20;
}
virtual void execute();
virtual void player_buff()
{
warlock_t* o = player -> cast_pet() -> owner -> cast_warlock();
warlock_pet_spell_t::player_buff();
if ( o -> buffs_demonic_empowerment -> up() ) player_crit += 0.20;
}
};
imp_pet_t( sim_t* sim, player_t* owner ) :
warlock_pet_t( sim, owner, "imp", PET_IMP )
{
action_list_str = "fire_bolt";
}
virtual void init_base()
{
warlock_pet_t::init_base();
attribute_base[ ATTR_STRENGTH ] = 297;
attribute_base[ ATTR_AGILITY ] = 79;
attribute_base[ ATTR_STAMINA ] = 118;
attribute_base[ ATTR_INTELLECT ] = 369;
attribute_base[ ATTR_SPIRIT ] = 367;
resource_base[ RESOURCE_HEALTH ] = 4011;
resource_base[ RESOURCE_MANA ] = 1175;
health_per_stamina = 2;
mana_per_intellect = 4.8;
mp5_per_intellect = 5.0 / 6.0;
base_mp5 = -257;
}
virtual action_t* create_action( const std::string& name,
const std::string& options_str )
{
if ( name == "fire_bolt" ) return new fire_bolt_t( this );
return player_t::create_action( name, options_str );
}
};
// ==========================================================================
// Pet Felguard
// ==========================================================================
struct felguard_pet_t : public warlock_pet_t
{
struct cleave_t : public warlock_pet_attack_t
{
cleave_t( player_t* player ) :
warlock_pet_attack_t( "cleave", player, RESOURCE_MANA, SCHOOL_PHYSICAL )
{
felguard_pet_t* p = ( felguard_pet_t* ) player -> cast_pet();
static rank_t ranks[] =
{
{ 76, 4, 124, 124, 0, 0.1 },
{ 68, 3, 78, 78, 0, 0.1 },
{ 0, 0, 0, 0, 0, 0 }
};
init_rank( ranks, 47994 );
weapon = &( p -> main_hand_weapon );
cooldown -> duration = 6.0;
}
virtual void player_buff()
{
felguard_pet_t* p = ( felguard_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
warlock_pet_attack_t::player_buff();
player_attack_power *= 1.0 + o -> buffs_demonic_frenzy -> stack() * ( 0.05 + o -> talents.demonic_brutality * 0.01 );
if ( o -> glyphs.felguard ) player_attack_power *= 1.20;
}
};
struct melee_t : public warlock_pet_melee_t
{
melee_t( player_t* player ) :
warlock_pet_melee_t( player, "felguard_melee" )
{}
virtual double execute_time() SC_CONST
{
warlock_t* o = player -> cast_pet() -> owner -> cast_warlock();
double t = attack_t::execute_time();
if ( o -> buffs_demonic_empowerment -> up() ) t *= 1.0 / 1.20;
return t;
}
virtual void player_buff()
{
felguard_pet_t* p = ( felguard_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
warlock_pet_melee_t::player_buff();
player_attack_power *= 1.0 + o -> buffs_demonic_frenzy -> stack() * ( 0.05 + o -> talents.demonic_brutality * 0.01 );
if ( o -> glyphs.felguard ) player_attack_power *= 1.20;
}
virtual void assess_damage( double amount, int dmg_type )
{
warlock_t* o = player -> cast_pet() -> owner -> cast_warlock();
attack_t::assess_damage( amount, dmg_type );
o -> buffs_demonic_frenzy -> trigger();
}
};
felguard_pet_t( sim_t* sim, player_t* owner ) :
warlock_pet_t( sim, owner, "felguard", PET_FELGUARD )
{
main_hand_weapon.type = WEAPON_BEAST;
main_hand_weapon.min_dmg = 412.5;
main_hand_weapon.max_dmg = 412.5;
main_hand_weapon.damage = ( main_hand_weapon.min_dmg + main_hand_weapon.max_dmg ) / 2;
main_hand_weapon.swing_time = 2.0;
damage_modifier = 1.05;
action_list_str = "cleave/wait_until_ready";
}
virtual void init_base()
{
warlock_pet_t::init_base();
resource_base[ RESOURCE_HEALTH ] = 1627;
resource_base[ RESOURCE_MANA ] = 3331;
base_attack_power = -20;
melee = new melee_t( this );
}
virtual action_t* create_action( const std::string& name,
const std::string& options_str )
{
if ( name == "cleave" ) return new cleave_t( this );
return player_t::create_action( name, options_str );
}
};
// ==========================================================================
// Pet Felhunter
// ==========================================================================
struct felhunter_pet_t : public warlock_pet_t
{
// TODO: Need to add fel intelligence on the warlock while felhunter is out
// This is +48 int / + 64 spi at rank 5, plus 5%/10% if talented in the affliction tree
// These do NOT stack with Prayer of Spirit, or with Arcane Intellect/Arcane Brilliance
struct shadow_bite_t : public warlock_pet_attack_t
{
shadow_bite_t( player_t* player ) :
warlock_pet_attack_t( "shadow_bite", player, RESOURCE_MANA, SCHOOL_SHADOW )
{
felhunter_pet_t* p = ( felhunter_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
static rank_t ranks[] =
{
{ 74, 5, 118, 118, 0, 0.03 },
{ 66, 4, 101, 101, 0, 0.03 },
{ 0, 0, 0, 0, 0, 0 }
};
init_rank( ranks, 54053 );
base_spell_power_multiplier = 1.0;
base_attack_power_multiplier = 0.0;
direct_power_mod = ( 1.5 / 3.5 ); // Converting from Pet Attack Power into Pet Spell Power.
may_crit = true;
cooldown -> duration = 6.0;
cooldown -> duration -= 2.0 * o -> talents.improved_felhunter;
base_multiplier *= 1.0 + ( o -> talents.shadow_mastery * 0.03 );
base_crit_bonus = 0.5;
base_crit_bonus_multiplier = 2.0;
}
virtual void execute()
{
felhunter_pet_t* p = ( felhunter_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
warlock_pet_attack_t::execute();
if ( result_is_hit() && o -> talents.improved_felhunter )
{
double amount = p -> resource_max[ RESOURCE_MANA ] * o -> talents.improved_felhunter * 0.08;
p -> resource_gain( RESOURCE_MANA, amount );
}
}
virtual void player_buff()
{
felhunter_pet_t* p = ( felhunter_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
warlock_pet_attack_t::player_buff();
player_spell_power += 0.15 * player -> cast_pet() -> owner -> composite_spell_power( SCHOOL_MAX );
player_multiplier *= 1.0 + o -> active_dots() * 0.15;
}
};
felhunter_pet_t( sim_t* sim, player_t* owner ) :
warlock_pet_t( sim, owner, "felhunter", PET_FELHUNTER )
{
main_hand_weapon.type = WEAPON_BEAST;
main_hand_weapon.min_dmg = 309.6;
main_hand_weapon.max_dmg = 309.6;
main_hand_weapon.damage = ( main_hand_weapon.min_dmg + main_hand_weapon.max_dmg ) / 2;
main_hand_weapon.swing_time = 2.0;
// damage_modifier = 0.8;
action_list_str = "shadow_bite/wait_until_ready";
}
virtual void init_base()
{
warlock_pet_t::init_base();
base_attack_power = -20;
resource_base[ RESOURCE_HEALTH ] = 4788;
resource_base[ RESOURCE_MANA ] = 1559;
attribute_base[ ATTR_STRENGTH ] = 314;
attribute_base[ ATTR_AGILITY ] = 90;
attribute_base[ ATTR_STAMINA ] = 328;
attribute_base[ ATTR_INTELLECT ] = 150;
attribute_base[ ATTR_SPIRIT ] = 209;
base_attack_power = -20;
initial_attack_power_per_strength = 2.0;
health_per_stamina = 9.5;
mana_per_intellect = 11.55;
mp5_per_intellect = 8.0 / 324.0;
base_mp5 = 11.22;
base_attack_crit = 0.0327;
melee = new warlock_pet_melee_t( this, "felhunter_melee" );
}
virtual action_t* create_action( const std::string& name,
const std::string& options_str )
{
if ( name == "shadow_bite" ) return new shadow_bite_t( this );
return player_t::create_action( name, options_str );
}
};
// ==========================================================================
// Pet Succubus
// ==========================================================================
struct succubus_pet_t : public warlock_pet_t
{
struct lash_of_pain_t : public warlock_pet_spell_t
{
lash_of_pain_t( player_t* player ) :
warlock_pet_spell_t( "lash_of_pain", player, RESOURCE_MANA, SCHOOL_SHADOW )
{
static rank_t ranks[] =
{
{ 80, 9, 237, 237, 0, 250 },
{ 74, 8, 193, 193, 0, 220 },
{ 68, 7, 123, 123, 0, 190 },
{ 60, 6, 99, 99, 0, 160 },
{ 0, 0, 0, 0, 0, 0 }
};
init_rank( ranks, 47992 );
direct_power_mod = ( 1.5 / 3.5 );
may_crit = true;
succubus_pet_t* p = ( succubus_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
cooldown -> duration = 12.0;
cooldown -> duration -= 3.0 * ( o -> talents.improved_lash_of_pain + o -> talents.demonic_power );
}
};
succubus_pet_t( sim_t* sim, player_t* owner ) :
warlock_pet_t( sim, owner, "succubus", PET_SUCCUBUS )
{
main_hand_weapon.type = WEAPON_BEAST;
main_hand_weapon.min_dmg = 412.5;
main_hand_weapon.max_dmg = 412.5;
main_hand_weapon.damage = ( main_hand_weapon.min_dmg + main_hand_weapon.max_dmg ) / 2;
main_hand_weapon.swing_time = 2.0;
damage_modifier = 1.05;
action_list_str = "lash_of_pain/wait_until_ready";
}
virtual void init_base()
{
warlock_pet_t::init_base();
base_attack_power = -20;
resource_base[ RESOURCE_HEALTH ] = 1468;
resource_base[ RESOURCE_MANA ] = 1559;
melee = new warlock_pet_melee_t( this, "succubus_melee" );
}
virtual action_t* create_action( const std::string& name,
const std::string& options_str )
{
if ( name == "lash_of_pain" ) return new lash_of_pain_t( this );
return player_t::create_action( name, options_str );
}
};
// ==========================================================================
// Pet Infernal
// ==========================================================================
struct infernal_pet_t : public warlock_pet_t
{
struct infernal_immolation_t : public warlock_pet_spell_t
{
infernal_immolation_t( player_t* player ) :
warlock_pet_spell_t( "immolation", player, RESOURCE_NONE, SCHOOL_FIRE )
{
base_dd_min = base_dd_max = 40;
direct_power_mod = 0.2;
background = true;
repeating = true;
}
virtual double execute_time() SC_CONST
{
// immolation is an aura that ticks every 2 seconds
return 2.0;
}
virtual void player_buff()
{
// immolation uses the master's spell power, not the infernal's
warlock_pet_t* p = ( warlock_pet_t* ) player -> cast_pet();
warlock_t* o = p -> owner -> cast_warlock();
warlock_pet_spell_t::player_buff();
player_spell_power = o -> composite_spell_power( school );
}
};
infernal_immolation_t* immolation;
infernal_pet_t( sim_t* sim, player_t* owner ) :
warlock_pet_t( sim, owner, "infernal", PET_INFERNAL )
{
main_hand_weapon.type = WEAPON_BEAST;
main_hand_weapon.min_dmg = 412.5;
main_hand_weapon.max_dmg = 412.5;
main_hand_weapon.damage = ( main_hand_weapon.min_dmg + main_hand_weapon.max_dmg ) / 2;
main_hand_weapon.swing_time = 2.0;
damage_modifier = 3.20;
}
virtual void init_base()
{
warlock_pet_t::init_base();
attribute_base[ ATTR_STRENGTH ] = 331;
attribute_base[ ATTR_AGILITY ] = 113;
attribute_base[ ATTR_STAMINA ] = 361;
attribute_base[ ATTR_INTELLECT ] = 65;
attribute_base[ ATTR_SPIRIT ] = 109;
resource_base[ RESOURCE_HEALTH ] = 20300;
resource_base[ RESOURCE_MANA ] = 0;
base_attack_power = -20;
melee = new warlock_pet_melee_t( this, "infernal_melee" );
immolation = new infernal_immolation_t( this );
}
virtual void schedule_ready( double delta_time=0,
bool waiting=false )
{
melee -> schedule_execute();
immolation -> schedule_execute();
}
virtual double composite_attack_hit() SC_CONST { return 0; }
virtual double composite_spell_hit() SC_CONST { return 0; }
};
// ==========================================================================
// Pet Doomguard
// ==========================================================================
struct doomguard_pet_t : public warlock_pet_t
{
doomguard_pet_t( sim_t* sim, player_t* owner ) :
warlock_pet_t( sim, owner, "doomguard", PET_DOOMGUARD )
{
main_hand_weapon.type = WEAPON_BEAST;
main_hand_weapon.min_dmg = 412.5;
main_hand_weapon.max_dmg = 412.5;
main_hand_weapon.damage = ( main_hand_weapon.min_dmg + main_hand_weapon.max_dmg ) / 2;
main_hand_weapon.swing_time = 2.0;
damage_modifier = 1.98;
}
virtual void init_base()
{
warlock_pet_t::init_base();
resource_base[ RESOURCE_HEALTH ] = 18000;
resource_base[ RESOURCE_MANA ] = 3000;
base_attack_power = -20;
melee = new warlock_pet_melee_t( this, "doomguard_melee" );
}
virtual action_t* create_action( const std::string& name,
const std::string& options_str )
{
return player_t::create_action( name, options_str );
}
};