Код:
Hunter Pet
// ==========================================================================
enum pet_type_t
{
PET_NONE=0,
PET_CARRION_BIRD,
PET_CAT,
PET_CORE_HOUND,
PET_DEVILSAUR,
PET_HYENA,
PET_MOTH,
PET_RAPTOR,
PET_SPIRIT_BEAST,
PET_TALLSTRIDER,
PET_WASP,
PET_WOLF,
PET_FEROCITY,
PET_BEAR,
PET_BOAR,
PET_CRAB,
PET_CROCOLISK,
PET_GORILLA,
PET_RHINO,
PET_SCORPID,
PET_TURTLE,
PET_WARP_STALKER,
PET_WORM,
PET_TENACITY,
PET_BAT,
PET_BIRD_OF_PREY,
PET_CHIMERA,
PET_DRAGONHAWK,
PET_NETHER_RAY,
PET_RAVAGER,
PET_SERPENT,
PET_SILITHID,
PET_SPIDER,
PET_SPOREBAT,
PET_WIND_SERPENT,
PET_CUNNING,
PET_MAX
};
struct hunter_pet_t : public pet_t
{
int pet_type;
// Buffs
buff_t* buffs_bestial_wrath;
buff_t* buffs_call_of_the_wild;
buff_t* buffs_culling_the_herd;
buff_t* buffs_frenzy;
buff_t* buffs_furious_howl;
buff_t* buffs_kill_command;
buff_t* buffs_monstrous_bite;
buff_t* buffs_owls_focus;
buff_t* buffs_rabid;
buff_t* buffs_rabid_power_stack;
buff_t* buffs_savage_rend;
buff_t* buffs_wolverine_bite;
buff_t* buffs_tier9_4pc;
// Gains
gain_t* gains_go_for_the_throat;
struct talents_t
{
int call_of_the_wild;
int cobra_reflexes;
int culling_the_herd;
int feeding_frenzy;
int rabid;
int roar_of_recovery;
int shark_attack;
int spiked_collar;
int spiders_bite;
int owls_focus;
int wild_hunt;
int wolverine_bite;
talents_t() { memset( ( void* ) this, 0x0, sizeof( talents_t ) ); }
};
talents_t talents;
hunter_pet_t( sim_t* sim, player_t* owner, const std::string& pet_name, int pt ) :
pet_t( sim, owner, pet_name ), pet_type( pt )
{
if ( ! supported( pet_type ) )
{
sim -> errorf( "Pet %s is not yet supported.\n", pet_name.c_str() );
sim -> cancel();
}
hunter_t* o = owner -> cast_hunter();
main_hand_weapon.type = WEAPON_BEAST;
main_hand_weapon.min_dmg = 51.0; // FIXME only level 80 value
main_hand_weapon.max_dmg = 78.0; // FIXME only level 80 value
main_hand_weapon.damage = ( main_hand_weapon.min_dmg + main_hand_weapon.max_dmg ) / 2; // FIXME only level 80 value
main_hand_weapon.swing_time = 2.0;
stamina_per_owner = 0.45;
health_per_stamina *= 1.05; // 3.1.0 change # Cunning, Ferocity and Tenacity pets now all have +5% damage, +5% armor and +5% health bonuses
if ( group() == PET_FEROCITY )
{
talents.call_of_the_wild = 1;
talents.cobra_reflexes = 2;
talents.culling_the_herd = 3;
talents.rabid = 1;
talents.spiders_bite = 3;
talents.spiked_collar = 3;
talents.shark_attack = ( o -> talents.beast_mastery ) ? 2 : 0;
talents.wild_hunt = ( o -> talents.beast_mastery ) ? 2 : 1;
}
else if ( group() == PET_CUNNING )
{
talents.cobra_reflexes = 2;
talents.culling_the_herd = 3;
talents.feeding_frenzy = 2;
talents.owls_focus = 2;
talents.roar_of_recovery = 1;
talents.spiked_collar = 3;
talents.wolverine_bite = 1;
talents.wild_hunt = ( o -> talents.beast_mastery ) ? 2 : 1;
}
else // TENACITY
{
assert( 0 );
}
init_actions();
}
static bool supported( int family )
{
switch ( family )
{
case PET_CAT:
case PET_DEVILSAUR:
case PET_RAPTOR:
case PET_WOLF:
case PET_WIND_SERPENT:
return true;
default:
return false;
}
}
virtual void reset()
{
pet_t::reset();
}
virtual int group()
{
if ( pet_type < PET_FEROCITY ) return PET_FEROCITY;
if ( pet_type < PET_TENACITY ) return PET_TENACITY;
if ( pet_type < PET_CUNNING ) return PET_CUNNING;
return PET_NONE;
}
virtual bool ooc_buffs() { return true; }
virtual void init_actions()
{
if ( group() == PET_FEROCITY )
{
if ( pet_type == PET_CAT )
{
action_list_str = "auto_attack";
if ( talents.call_of_the_wild ) action_list_str += "/call_of_the_wild";
if ( talents.rabid ) action_list_str += "/rabid";
action_list_str += "/rake/claw";
}
else if ( pet_type == PET_DEVILSAUR )
{
action_list_str = "auto_attack/monstrous_bite";
if ( talents.call_of_the_wild ) action_list_str += "/call_of_the_wild";
if ( talents.rabid ) action_list_str += "/rabid";
action_list_str += "/bite";
}
else if ( pet_type == PET_RAPTOR )
{
action_list_str = "auto_attack/savage_rend";
if ( talents.call_of_the_wild ) action_list_str += "/call_of_the_wild";
if ( talents.rabid ) action_list_str += "/rabid";
action_list_str += "/claw";
}
else if ( pet_type == PET_WOLF )
{
action_list_str = "auto_attack/furious_howl";
if ( talents.call_of_the_wild ) action_list_str += "/call_of_the_wild";
if ( talents.rabid ) action_list_str += "/rabid";
action_list_str += "/claw";
}
else assert( 0 );
}
else if ( group() == PET_CUNNING )
{
if ( pet_type == PET_WIND_SERPENT )
{
action_list_str = "auto_attack";
if ( talents.roar_of_recovery ) action_list_str += "/roar_of_recovery";
if ( talents.wolverine_bite ) action_list_str += "/wolverine_bite";
action_list_str += "/lightning_breath/bite";
}
else assert( 0 );
}
else // TENACITY
{
assert( 0 );
}
}
virtual void init_base()
{
pet_t::init_base();
hunter_t* o = owner -> cast_hunter();
attribute_base[ ATTR_STRENGTH ] = rating_t::interpolate( level, 0, 162, 331 );
attribute_base[ ATTR_AGILITY ] = rating_t::interpolate( level, 0, 54, 113 );
attribute_base[ ATTR_STAMINA ] = rating_t::interpolate( level, 0, 307, 361 ); // stamina is different for every pet type
attribute_base[ ATTR_INTELLECT ] = 100; // FIXME
attribute_base[ ATTR_SPIRIT ] = 100; // FIXME
base_attack_power = -20;
initial_attack_power_per_strength = 2.0;
initial_attack_crit_per_agility = rating_t::interpolate( level, 0.01/16.0, 0.01/30.0, 0.01/62.5 );
initial_attack_power_multiplier *= 1.0 + o -> talents.animal_handler * 0.05;
base_attack_crit = 0.032 + talents.spiders_bite * 0.03;
base_attack_crit += o -> talents.ferocity * 0.02;
resource_base[ RESOURCE_HEALTH ] = rating_t::interpolate( level, 0, 4253, 6373 );
resource_base[ RESOURCE_FOCUS ] = 100;
focus_regen_per_second = ( 24.5 / 4.0 );
focus_regen_per_second *= 1.0 + o -> talents.bestial_discipline * 0.50;
base_gcd = 1.20;
}
virtual void init_buffs()
{
pet_t::init_buffs();
hunter_pet_t* p = ( hunter_pet_t* ) this -> cast_pet();
hunter_t* o = p -> owner -> cast_hunter();
buffs_bestial_wrath = new buff_t( this, "bestial_wrath", 1, 10.0 );
buffs_call_of_the_wild = new buff_t( this, "call_of_the_wild", 1, 10.0 );
buffs_culling_the_herd = new buff_t( this, "culling_the_herd", 1, 10.0, 0.0, talents.culling_the_herd );
buffs_frenzy = new buff_t( this, "frenzy", 1, 8.0, 0.0, o -> talents.frenzy * 0.2 );
buffs_furious_howl = new buff_t( this, "furious_howl", 1, 20.0 );
buffs_kill_command = new buff_t( this, "kill_command", 3, 30.0 );
buffs_monstrous_bite = new buff_t( this, "monstrous_bite", 3, 12.0 );
buffs_owls_focus = new buff_t( this, "owls_focus", 1, 8.0, 0.0, talents.owls_focus * 0.15 );
buffs_rabid = new buff_t( this, "rabid", 1, 20.0 );
buffs_rabid_power_stack = new buff_t( this, "rabid_power_stack", 1, 0, 0.0, talents.rabid * 0.5 ); // FIXME: Probably a ppm, not flat chance
buffs_savage_rend = new buff_t( this, "savage_rend", 1, 30.0 );
buffs_wolverine_bite = new buff_t( this, "wolverine_bite", 1, 10.0, 0.0, talents.wolverine_bite );
buffs_tier9_4pc = new stat_buff_t( this, "tier9_4pc", STAT_ATTACK_POWER, 600, 1, 15.0, 45.0, ( o -> set_bonus.tier9_4pc_melee() ? 0.35 : 0 ) );
}
virtual void init_gains()
{
pet_t::init_gains();
gains_go_for_the_throat = get_gain( "go_for_the_throat" );
}
virtual void init_uptimes()
{
pet_t::init_uptimes();
}
virtual double composite_armor() SC_CONST
{
double a = player_t::composite_armor();
a *= 1.05; // 3.1 change: # Cunning, Ferocity and Tenacity pets now all have +5% damage, +5% armor and +5% health bonuses
return a;
}
virtual double composite_attack_power() SC_CONST
{
hunter_t* o = owner -> cast_hunter();
double ap = player_t::composite_attack_power();
ap += o -> stamina() * o -> talents.hunter_vs_wild * 0.1;
ap += o -> composite_attack_power() * 0.22 * ( 1 + talents.wild_hunt * 0.15 );
ap += buffs_furious_howl -> value();
return ap;
}
virtual double composite_attack_power_multiplier() SC_CONST
{
hunter_t* o = owner -> cast_hunter();
double mult = player_t::composite_attack_power_multiplier();
if ( o -> active_aspect == ASPECT_BEAST )
mult *= 1.10 + o -> glyphs.the_beast * 0.02;
if ( buffs_rabid -> up() )
mult *= 1.0 + buffs_rabid_power_stack -> stack() * 0.05;
if ( buffs_call_of_the_wild -> up() )
mult *= 1.1;
if ( o -> buffs_tier10_4pc -> up() )
mult *= 1.2;
return mult;
}
virtual double composite_spell_hit() SC_CONST
{
return composite_attack_hit() * 17.0 / 8.0;
}
virtual void summon( double duration=0 )
{
hunter_t* o = owner -> cast_hunter();
pet_t::summon( duration );
o -> active_pet = this;
}
virtual void interrupt()
{
pet_t::interrupt();
if ( main_hand_attack ) main_hand_attack -> cancel();
}
virtual int primary_resource() SC_CONST { return RESOURCE_FOCUS; }
virtual std::vector<option_t>& get_options()
{
if ( options.empty() )
{
pet_t::get_options();
option_t hunter_pet_options[] =
{
// Talents
{ "cobra_reflexes", OPT_INT, &( talents.cobra_reflexes ) },
{ "culling_the_herd", OPT_INT, &( talents.culling_the_herd ) },
{ "owls_focus", OPT_INT, &( talents.owls_focus ) },
{ "shark_attack", OPT_INT, &( talents.shark_attack ) },
{ "spiked_collar", OPT_INT, &( talents.spiked_collar ) },
{ "feeding_frenzy", OPT_INT, &( talents.feeding_frenzy ) },
{ "roar_of_recovery", OPT_INT, &( talents.roar_of_recovery ) },
{ "wild_hunt", OPT_INT, &( talents.wild_hunt ) },
{ "wolverine_bite", OPT_INT, &( talents.wolverine_bite ) },
{ "spiders_bite", OPT_INT, &( talents.spiders_bite ) },
{ "call_of_the_wild", OPT_INT, &( talents.call_of_the_wild ) },
{ "rabid", OPT_INT, &( talents.rabid ) },
{ NULL, OPT_UNKNOWN, NULL }
};
option_t::copy( options, hunter_pet_options );
}
return options;
}
virtual std::vector<talent_translation_t>& get_talent_list()
{
if(this->talent_list.empty())
{
talent_translation_t *translation_table;
if ( group() == PET_FEROCITY )
{
talent_translation_t group_table[] =
{
{ 1, 2, &( talents.cobra_reflexes ), 0, 0 },
{ 2, 0, NULL , 0, 0 },
{ 3, 0, NULL , 0, 0 }, // Empty talent, but need for compatibility with wowarmory.
{ 4, 0, NULL , 0, 0 },
{ 5, 0, NULL , 0, 0 },
{ 6, 0, NULL , 1, 0 },
{ 7, 0, NULL , 1, 0 },
{ 8, 3, &( talents.spiked_collar ), 1, 0 },
{ 9, 0, NULL , 1, 0 },
{ 10, 0, NULL , 1, 0 }, // Empty talent, but need for compatibility with wowarmory.
{ 11, 3, &( talents.culling_the_herd ), 2, 0 },
{ 12, 0, NULL , 2, 0 },
{ 13, 0, NULL , 2, 0 },
{ 14, 0, NULL , 3, 7 },
{ 15, 3, &( talents.spiders_bite ), 3, 0 },
{ 16, 0, NULL , 3, 0 },
{ 17, 1, &( talents.rabid ), 4, 0 },
{ 18, 0, NULL , 4, 14 },
{ 19, 1, &( talents.call_of_the_wild ), 4, 15 },
{ 20, 2, &( talents.shark_attack ), 5, 0 },
{ 21, 2, &( talents.wild_hunt ), 5, 19 },
{ 0, 0, NULL } /// must have talent with index 0 here
};
translation_table = group_table;
}
else if ( group() == PET_CUNNING )
{
talent_translation_t group_table[] =
{
{ 1, 2, &( talents.cobra_reflexes ), 0, 0 },
{ 2, 0, NULL , 0, 0 },
{ 3, 0, NULL , 0, 0 }, // Empty talent, but need for compatibility with wowarmory.
{ 4, 0, NULL , 0, 0 },
{ 5, 0, NULL , 0, 0 },
{ 6, 0, NULL , 1, 0 },
{ 7, 0, NULL , 0, 0 }, // Empty talent, but need for compatibility with wowarmory.
{ 8, 0, NULL , 1, 2 },
{ 9, 2, &( talents.owls_focus ), 1, 0 },
{ 10, 3, &( talents.spiked_collar ), 1, 0 },
{ 11, 3, &( talents.culling_the_herd ), 2, 0 },
{ 12, 0, NULL , 2, 0 },
{ 13, 0, NULL , 2, 0 },
{ 14, 0, NULL , 3, 0 },
{ 15, 0, NULL , 3, 0 },
{ 16, 2, &( talents.feeding_frenzy ), 3, 10 },
{ 17, 1, &( talents.wolverine_bite ), 4, 11 },
{ 18, 1, &( talents.roar_of_recovery ), 4, 0 },
{ 19, 0, NULL , 4, 0 },
{ 20, 0, NULL , 4, 0 },
{ 21, 2, &( talents.wild_hunt ), 5, 17 },
{ 22, 0, NULL , 5, 20 },
{ 0, 0, NULL } /// must have talent with index 0 here
};
translation_table = group_table;
}
else // TENACITY
{
return talent_list;
}
int count = 0;
for(int i=0; translation_table[i].index;i++)
{
if(translation_table[i].index > 0)
{
talent_list.push_back(translation_table[i]);
talent_list[count].tree = 0;
talent_list[count].index = count+1;
count++;
}
}
}
return talent_list;
}
virtual action_t* create_action( const std::string& name, const std::string& options_str );};
а) как видите базовое хп и тут указано 6373