mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 01:37:00 +00:00
Cmangos Cata commits applied
I thankee, cmangos :-) Commits: 13271d6 Commit Ported Core Pet DB cleanup and simplification 60d6e29 Commit Imported Core Utilize flags in PetAI (And uniform extra flags with the other cores) 06d30ce Commit Ported Core Make pet assist owner on summon if not a passive 2821da8 Commit Ported Core Fix Guardian reactions 4f88a9e Commit Ported Core Pet AI Fixup 67e0558 Commit Imported Core Fix pet unsummon on mount f50041f Commit Imported Core Fix player rooted after possesing an unit. df59a93 Commit Imported Core Syncing up pet work 056f4f5 Commit Imported Core Fix a couple of invalid name for spell attributes 6a58f1f Commit Imported Core only save correct auras on pet::SavePetToDB 34ab59b Commit Imported Core Hunter summon pet (call pet) checkcast fixup dfbb69c Commit Imported Core Handle owner entering combat properly 4b10eb4 Commit Imported Core Pet Aggro 1bdb7e3 Commit Ported Core Clean up pet stay functionality 1bdb7e3 Commit Ported Core Clean up pet stay functionality 9b7b50e Commit Imported Core UNIT_BYTE2_FLAG work 0777235 Commit Imported Core Implement displaying group leader indicators on players 5efab47 Commit Imported Core Health funnel fixes 60e6a84 Commit Ported Core Fix SMSG_QUESTGIVER_STATUS_MULTIPLE and GetDialogStatus 60e6a84 Commit Ported Core Fix SMSG_QUESTGIVER_STATUS_MULTIPLE and GetDialogStatus f8d3cbd Commit Imported Core Fix talent spell cannot stack 32ba32e Commit Imported Core Fix channeled spell distance check interval 47ec2fa Commit Imported Core Adding state to aura holder Now proc cannot remove an aura not finalized 34588dc Commit Ported Core Unbreak creature pets bd079a1 Commit Imported Core The (not so)Great Pet Rework
This commit is contained in:
parent
c4c83f5b58
commit
600205641d
20 changed files with 634 additions and 507 deletions
|
|
@ -52,10 +52,6 @@ Pet::Pet(PetType type) :
|
|||
|
||||
if (type == MINI_PET) // always passive
|
||||
charmInfo->SetReactState(REACT_PASSIVE);
|
||||
else if (type == PROTECTOR_PET) // always defensive
|
||||
charmInfo->SetReactState(REACT_DEFENSIVE);
|
||||
else if (type == GUARDIAN_PET) // always aggressive
|
||||
charmInfo->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
Pet::~Pet()
|
||||
|
|
@ -158,13 +154,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
|
|||
|
||||
uint32 pet_number = fields[0].GetUInt32();
|
||||
|
||||
if (current && owner->IsPetNeedBeTemporaryUnsummoned())
|
||||
{
|
||||
owner->SetTemporaryUnsummonedPetNumber(pet_number);
|
||||
delete result;
|
||||
return false;
|
||||
}
|
||||
|
||||
Map* map = owner->GetMap();
|
||||
|
||||
CreatureCreatePos pos(owner, owner->GetOrientation(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
|
|
@ -202,18 +191,13 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
|
|||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE | UNIT_BYTE2_FLAG_AURAS);
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
|
||||
switch (getPetType())
|
||||
if (getPetType() == HUNTER_PET)
|
||||
{
|
||||
case SUMMON_PET:
|
||||
petlevel = owner->getLevel();
|
||||
break;
|
||||
case HUNTER_PET:
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
|
||||
SetPowerType(POWER_FOCUS);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType());
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
|
||||
SetPowerType(POWER_FOCUS);
|
||||
}
|
||||
else if (getPetType() != SUMMON_PET)
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType());
|
||||
|
||||
if (owner->IsPvP())
|
||||
SetPvP(true);
|
||||
|
|
@ -282,21 +266,16 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
|
|||
CastOwnerTalentAuras();
|
||||
}
|
||||
|
||||
Powers powerType = GetPowerType();
|
||||
Powers powerType = GetPowerType();;
|
||||
|
||||
if (getPetType() == SUMMON_PET && !current) // all (?) summon pets come with full health when called, but not when they are current
|
||||
{
|
||||
SetHealth(GetMaxHealth());
|
||||
SetPower(powerType, GetMaxPower(powerType));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth);
|
||||
SetPower(powerType, savedpower > GetMaxPower(powerType) ? GetMaxPower(powerType) : savedpower);
|
||||
}
|
||||
SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth);
|
||||
SetPower(powerType, savedpower > GetMaxPower(powerType) ? GetMaxPower(powerType) : savedpower);
|
||||
|
||||
if (getPetType() == HUNTER_PET && savedhealth <= 0)
|
||||
SetDeathState(JUST_DIED);
|
||||
|
||||
AIM_Initialize();
|
||||
map->Add((Creature*)this);
|
||||
AIM_Initialize();
|
||||
|
||||
// Spells should be loaded after pet is added to map, because in CheckCast is check on it
|
||||
_LoadSpells();
|
||||
|
|
@ -363,7 +342,13 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
{
|
||||
// reagents must be returned before save call
|
||||
if (mode == PET_SAVE_REAGENTS)
|
||||
mode = PET_SAVE_NOT_IN_SLOT;
|
||||
{
|
||||
// Hunter Pets always save as current if dismissed or unsummoned due to range/etc.
|
||||
if (getPetType() == HUNTER_PET)
|
||||
mode = PET_SAVE_AS_CURRENT;
|
||||
else
|
||||
mode = PET_SAVE_NOT_IN_SLOT;
|
||||
}
|
||||
// not save pet as current if another pet temporary unsummoned
|
||||
else if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
|
||||
pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
|
||||
|
|
@ -430,7 +415,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
savePet.addUInt32(uint32(mode));
|
||||
savePet.addString(m_name);
|
||||
savePet.addUInt32(uint32(HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ? 0 : 1));
|
||||
savePet.addUInt32((curhealth < 1 ? 1 : curhealth));
|
||||
savePet.addUInt32(curhealth);
|
||||
savePet.addUInt32(curpower);
|
||||
|
||||
std::ostringstream ss;
|
||||
|
|
@ -441,7 +426,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
};
|
||||
savePet.addString(ss);
|
||||
|
||||
savePet.addUInt64(uint64(time(NULL)));
|
||||
savePet.addUInt64(uint64(time(nullptr)));
|
||||
savePet.addUInt32(uint32(m_resetTalentsCost));
|
||||
savePet.addUInt64(uint64(m_resetTalentsTime));
|
||||
savePet.addUInt32(GetUInt32Value(UNIT_CREATED_BY_SPELL));
|
||||
|
|
@ -774,18 +759,13 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
if (!Create(guid, pos, creature->GetCreatureInfo(), pet_number))
|
||||
return false;
|
||||
|
||||
CreatureInfo const* cinfo = GetCreatureInfo();
|
||||
if (!cinfo)
|
||||
CreatureInfo const* cInfo = GetCreatureInfo();
|
||||
if (!cInfo)
|
||||
{
|
||||
sLog.outError("CreateBaseAtCreature() failed, creatureInfo is missing!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cinfo->CreatureType == CREATURE_TYPE_CRITTER)
|
||||
{
|
||||
setPetType(MINI_PET);
|
||||
return true;
|
||||
}
|
||||
SetDisplayId(creature->GetDisplayId());
|
||||
SetNativeDisplayId(creature->GetNativeDisplayId());
|
||||
SetPowerType(POWER_FOCUS);
|
||||
|
|
@ -794,118 +774,141 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(creature->getLevel()));
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->Family))
|
||||
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->Family))
|
||||
SetName(cFamily->Name[sWorld.GetDefaultDbcLocale()]);
|
||||
else
|
||||
SetName(creature->GetNameForLocaleIdx(sObjectMgr.GetDBCLocaleIndex()));
|
||||
|
||||
if (cinfo->CreatureType == CREATURE_TYPE_BEAST)
|
||||
{
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_WARRIOR);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 2, GENDER_NONE);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 3, POWER_FOCUS);
|
||||
SetSheath(SHEATH_STATE_MELEE);
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
|
||||
}
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_WARRIOR);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 2, GENDER_NONE);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 3, POWER_FOCUS);
|
||||
SetSheath(SHEATH_STATE_MELEE);
|
||||
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE | UNIT_BYTE2_FLAG_AURAS);
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_RENAME);
|
||||
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
||||
void Pet::InitStatsForLevel(uint32 petlevel)
|
||||
{
|
||||
CreatureInfo const* cinfo = GetCreatureInfo();
|
||||
MANGOS_ASSERT(cinfo);
|
||||
|
||||
if (!owner)
|
||||
{
|
||||
owner = GetOwner();
|
||||
if (!owner)
|
||||
{
|
||||
sLog.outError("attempt to summon pet (Entry %u) without owner! Attempt terminated.", cinfo->Entry);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 creature_ID = (getPetType() == HUNTER_PET) ? 1 : cinfo->Entry;
|
||||
|
||||
switch (getPetType())
|
||||
{
|
||||
case SUMMON_PET:
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_MAGE);
|
||||
|
||||
// this enables popup window (pet dismiss, cancel)
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
break;
|
||||
case HUNTER_PET:
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_WARRIOR);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 2, GENDER_NONE);
|
||||
SetSheath(SHEATH_STATE_MELEE);
|
||||
|
||||
// this enables popup window (pet abandon, cancel)
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
break;
|
||||
case GUARDIAN_PET:
|
||||
case MINI_PET:
|
||||
case PROTECTOR_PET:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Unit* owner = GetOwner();
|
||||
CreatureInfo const* cInfo = GetCreatureInfo();
|
||||
MANGOS_ASSERT(cInfo);
|
||||
|
||||
SetLevel(petlevel);
|
||||
|
||||
SetMeleeDamageSchool(SpellSchools(cinfo->DamageSchool));
|
||||
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
||||
|
||||
SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
|
||||
SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
|
||||
SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME);
|
||||
|
||||
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0);
|
||||
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->Family);
|
||||
if (cFamily && cFamily->minScale > 0.0f && getPetType() == HUNTER_PET)
|
||||
{
|
||||
float Scale;
|
||||
if (getLevel() >= cFamily->maxScaleLevel)
|
||||
Scale = cFamily->maxScale;
|
||||
else if (getLevel() <= cFamily->minScaleLevel)
|
||||
Scale = cFamily->minScale;
|
||||
else
|
||||
Scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
|
||||
|
||||
SetObjectScale(Scale);
|
||||
UpdateModelData();
|
||||
}
|
||||
m_bonusdamage = 0;
|
||||
|
||||
int32 createResistance[MAX_SPELL_SCHOOL] = {0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
if (getPetType() != HUNTER_PET)
|
||||
if (getPetType() == HUNTER_PET)
|
||||
{
|
||||
createResistance[SPELL_SCHOOL_HOLY] = cinfo->ResistanceHoly;
|
||||
createResistance[SPELL_SCHOOL_FIRE] = cinfo->ResistanceFire;
|
||||
createResistance[SPELL_SCHOOL_NATURE] = cinfo->ResistanceNature;
|
||||
createResistance[SPELL_SCHOOL_FROST] = cinfo->ResistanceFrost;
|
||||
createResistance[SPELL_SCHOOL_SHADOW] = cinfo->ResistanceShadow;
|
||||
createResistance[SPELL_SCHOOL_ARCANE] = cinfo->ResistanceArcane;
|
||||
SetMeleeDamageSchool(SpellSchools(SPELL_SCHOOL_NORMAL));
|
||||
SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
|
||||
SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
|
||||
SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetMeleeDamageSchool(SpellSchools(cInfo->DamageSchool));
|
||||
SetAttackTime(BASE_ATTACK, cInfo->MeleeBaseAttackTime);
|
||||
SetAttackTime(OFF_ATTACK, cInfo->MeleeBaseAttackTime);
|
||||
SetAttackTime(RANGED_ATTACK, cInfo->RangedBaseAttackTime);
|
||||
|
||||
createResistance[SPELL_SCHOOL_HOLY] = cInfo->ResistanceHoly;
|
||||
createResistance[SPELL_SCHOOL_FIRE] = cInfo->ResistanceFire;
|
||||
createResistance[SPELL_SCHOOL_NATURE] = cInfo->ResistanceNature;
|
||||
createResistance[SPELL_SCHOOL_FROST] = cInfo->ResistanceFrost;
|
||||
createResistance[SPELL_SCHOOL_SHADOW] = cInfo->ResistanceShadow;
|
||||
createResistance[SPELL_SCHOOL_ARCANE] = cInfo->ResistanceArcane;
|
||||
}
|
||||
|
||||
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
|
||||
|
||||
float health, mana, armor, minDmg;
|
||||
|
||||
switch (getPetType())
|
||||
{
|
||||
case HUNTER_PET:
|
||||
{
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->Family);
|
||||
|
||||
if (cFamily && cFamily->minScale > 0.0f)
|
||||
{
|
||||
float scale;
|
||||
if (getLevel() >= cFamily->maxScaleLevel)
|
||||
scale = cFamily->maxScale;
|
||||
else if (getLevel() <= cFamily->minScaleLevel)
|
||||
scale = cFamily->minScale;
|
||||
else
|
||||
scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
|
||||
|
||||
SetObjectScale(scale);
|
||||
UpdateModelData();
|
||||
}
|
||||
|
||||
// Max level
|
||||
if (petlevel < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(petlevel));
|
||||
else
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
|
||||
}
|
||||
|
||||
// Info found in pet_levelstats
|
||||
if (PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(1, petlevel))
|
||||
{
|
||||
for (int i = STAT_STRENGTH; i < MAX_STATS;++i)
|
||||
SetCreateStat(Stats(i), float(pInfo->stats[i]));
|
||||
|
||||
health = pInfo->health;
|
||||
mana = 0;
|
||||
armor = pInfo->armor;
|
||||
|
||||
// First we divide attack time by standard attack time, and then multipy by level and damage mod.
|
||||
uint32 mDmg = (GetAttackTime(BASE_ATTACK) * petlevel) / 2000;
|
||||
|
||||
// Set damage
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(mDmg - mDmg / 4));
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((mDmg - mDmg / 4) * 1.5));
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outErrorDb("HUNTER PET levelstats missing in DB! 'Weakifying' pet");
|
||||
|
||||
for (int i = STAT_STRENGTH; i < MAX_STATS;++i)
|
||||
SetCreateStat(Stats(i), 1.0f);
|
||||
|
||||
health = 1;
|
||||
mana = 0;
|
||||
armor = 0;
|
||||
|
||||
// Set damage
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 1);
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SUMMON_PET:
|
||||
{
|
||||
if (owner->GetTypeId() == TYPEID_PLAYER)
|
||||
if (owner)
|
||||
{
|
||||
switch (owner->getClass())
|
||||
{
|
||||
case CLASS_WARLOCK:
|
||||
{
|
||||
|
||||
// the damage bonus used for pets is either fire or shadow damage, whatever is higher
|
||||
uint32 fire = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE);
|
||||
uint32 fire = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE);
|
||||
uint32 shadow = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW);
|
||||
uint32 val = (fire > shadow) ? fire : shadow;
|
||||
uint32 val = (fire > shadow) ? fire : shadow;
|
||||
|
||||
SetBonusDamage(int32(val * 0.15f));
|
||||
// bonusAP += val * 0.57;
|
||||
|
|
@ -924,109 +927,172 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
sLog.outError("Pet::InitStatsForLevel> No owner for creature pet %s !", GetGuidStr().c_str());
|
||||
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
|
||||
|
||||
// SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
|
||||
|
||||
PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
|
||||
if (pInfo) // exist in DB
|
||||
{
|
||||
SetCreateHealth(pInfo->health);
|
||||
SetCreateMana(pInfo->mana);
|
||||
|
||||
if (pInfo->armor > 0)
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
|
||||
|
||||
for (int stat = 0; stat < MAX_STATS; ++stat)
|
||||
{
|
||||
SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
|
||||
}
|
||||
}
|
||||
else // not exist in DB, use some default fake data
|
||||
{
|
||||
sLog.outErrorDb("Summoned pet (Entry: %u) not have pet stats data in DB", cinfo->Entry);
|
||||
|
||||
// remove elite bonuses included in DB values
|
||||
SetCreateHealth(uint32(((float(cinfo->MaxLevelHealth) / cinfo->MaxLevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
SetCreateMana(uint32(((float(cinfo->MaxLevelMana) / cinfo->MaxLevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
SetCreateStat(STAT_AGILITY, 22);
|
||||
SetCreateStat(STAT_STAMINA, 25);
|
||||
SetCreateStat(STAT_INTELLECT, 28);
|
||||
SetCreateStat(STAT_SPIRIT, 27);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HUNTER_PET:
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(petlevel));
|
||||
// these formula may not be correct; however, it is designed to be close to what it should be
|
||||
// this makes dps 0.5 of pets level
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
|
||||
// damage range is then petlevel / 2
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
|
||||
// damage is increased afterwards as strength and pet scaling modify attack power
|
||||
|
||||
// stored standard pet stats are entry 1 in pet_levelinfo
|
||||
PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
|
||||
if (pInfo) // exist in DB
|
||||
{
|
||||
SetCreateHealth(pInfo->health);
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
|
||||
// SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
|
||||
|
||||
for (int i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
{
|
||||
SetCreateStat(Stats(i), float(pInfo->stats[i]));
|
||||
}
|
||||
}
|
||||
else // not exist in DB, use some default fake data
|
||||
{
|
||||
sLog.outErrorDb("Hunter pet levelstats missing in DB");
|
||||
|
||||
// remove elite bonuses included in DB values
|
||||
SetCreateHealth(uint32(((float(cinfo->MaxLevelHealth) / cinfo->MaxLevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
SetCreateStat(STAT_AGILITY, 22);
|
||||
SetCreateStat(STAT_STAMINA, 25);
|
||||
SetCreateStat(STAT_INTELLECT, 28);
|
||||
SetCreateStat(STAT_SPIRIT, 27);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUARDIAN_PET:
|
||||
case PROTECTOR_PET:
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
|
||||
|
||||
SetCreateMana(28 + 10 * petlevel);
|
||||
SetCreateHealth(28 + 30 * petlevel);
|
||||
// Info found in pet_levelstats
|
||||
if (PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(cInfo->Entry, petlevel))
|
||||
{
|
||||
for (int i = STAT_STRENGTH; i < MAX_STATS;++i)
|
||||
SetCreateStat(Stats(i), float(pInfo->stats[i]));
|
||||
|
||||
health = pInfo->health;
|
||||
mana = pInfo->mana;
|
||||
armor = pInfo->armor;
|
||||
|
||||
// Info found in ClassLevelStats
|
||||
if (CreatureClassLvlStats const* cCLS = sObjectMgr.GetCreatureClassLvlStats(petlevel, cInfo->UnitClass, cInfo->Expansion))
|
||||
{
|
||||
minDmg = (cCLS->BaseDamage * cInfo->DamageVariance + (cCLS->BaseMeleeAttackPower / 14) * (cInfo->MeleeBaseAttackTime/1000)) * cInfo->DamageMultiplier;
|
||||
|
||||
// Apply custom damage setting (from config)
|
||||
minDmg *= _GetDamageMod(cInfo->Rank);
|
||||
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(minDmg));
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(minDmg * 1.5));
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outErrorDb("SUMMON_PET creature_template not finished (expansion field = -1) on creature %s! (entry: %u)", GetGuidStr().c_str(), cInfo->Entry);
|
||||
|
||||
float dMinLevel = cInfo->MinMeleeDmg / cInfo->MinLevel;
|
||||
float dMaxLevel = cInfo->MaxMeleeDmg / cInfo->MaxLevel;
|
||||
float mDmg = (dMaxLevel - ((dMaxLevel - dMinLevel) / 2)) * petlevel;
|
||||
|
||||
// Set damage
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(mDmg - mDmg / 4));
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((mDmg - mDmg / 4) * 1.5));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outErrorDb("SUMMON_PET levelstats missing in DB! 'Weakifying' pet and giving it mana to make it obvious");
|
||||
|
||||
for (int i = STAT_STRENGTH; i < MAX_STATS;++i)
|
||||
SetCreateStat(Stats(i), 1.0f);
|
||||
|
||||
health = 1;
|
||||
mana = 1;
|
||||
armor = 1;
|
||||
|
||||
// Set damage
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 1);
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 1);
|
||||
}
|
||||
|
||||
// FIXME: this is wrong formula, possible each guardian pet have own damage formula
|
||||
// these formula may not be correct; however, it is designed to be close to what it should be
|
||||
// this makes dps 0.5 of pets level
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
|
||||
// damage range is then petlevel / 2
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
|
||||
break;
|
||||
}
|
||||
case PROTECTOR_PET:
|
||||
case GUARDIAN_PET:
|
||||
{
|
||||
if (CreatureClassLvlStats const* cCLS = sObjectMgr.GetCreatureClassLvlStats(petlevel, cInfo->UnitClass, cInfo->Expansion))
|
||||
{
|
||||
health = cCLS->BaseHealth;
|
||||
mana = cCLS->BaseMana;
|
||||
armor = cCLS->BaseArmor;
|
||||
|
||||
// Melee
|
||||
minDmg = (cCLS->BaseDamage * cInfo->DamageVariance + (cCLS->BaseMeleeAttackPower / 14) * (cInfo->MeleeBaseAttackTime/1000)) * cInfo->DamageMultiplier;
|
||||
|
||||
// Get custom setting
|
||||
minDmg *= _GetDamageMod(cInfo->Rank);
|
||||
|
||||
// If the damage value is not passed on as float it will result in damage = 1; but only for guardian type pets, though...
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(minDmg));
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(minDmg * 1.5));
|
||||
|
||||
// Ranged
|
||||
minDmg = (cCLS->BaseDamage * cInfo->DamageVariance + (cCLS->BaseRangedAttackPower / 14) * (cInfo->RangedBaseAttackTime/1000)) * cInfo->DamageMultiplier;
|
||||
|
||||
// Get custom setting
|
||||
minDmg *= _GetDamageMod(cInfo->Rank);
|
||||
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, float(minDmg));
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, float(minDmg * 1.5));
|
||||
}
|
||||
else // TODO: Remove fallback to creature_template data when DB is ready
|
||||
{
|
||||
if (petlevel >= cInfo->MaxLevel)
|
||||
{
|
||||
health = cInfo->MaxLevelHealth;
|
||||
mana = cInfo->MaxLevelMana;
|
||||
}
|
||||
else if (petlevel <= cInfo->MinLevel)
|
||||
{
|
||||
health = cInfo->MinLevelHealth;
|
||||
mana = cInfo->MinLevelMana;
|
||||
}
|
||||
else
|
||||
{
|
||||
float hMinLevel = cInfo->MinLevelHealth / cInfo->MinLevel;
|
||||
float hMaxLevel = cInfo->MaxLevelHealth / cInfo->MaxLevel;
|
||||
float mMinLevel = cInfo->MinLevelMana / cInfo->MinLevel;
|
||||
float mMaxLevel = cInfo->MaxLevelMana / cInfo->MaxLevel;
|
||||
|
||||
health = (hMaxLevel - ((hMaxLevel - hMinLevel) / 2)) * petlevel;
|
||||
mana = (mMaxLevel - ((mMaxLevel - mMinLevel) / 2)) * petlevel;
|
||||
}
|
||||
|
||||
sLog.outErrorDb("Pet::InitStatsForLevel> Error trying to set stats for creature %s (entry: %u) using ClassLevelStats; not enough data to do it!", GetGuidStr().c_str(), cInfo->Entry);
|
||||
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(cInfo->MinMeleeDmg));
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(cInfo->MaxMeleeDmg));
|
||||
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, float(cInfo->MinRangedDmg));
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, float(cInfo->MaxRangedDmg));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("Pet have incorrect type (%u) for levelup.", getPetType());
|
||||
break;
|
||||
sLog.outError("Pet have incorrect type (%u) for level handling.", getPetType());
|
||||
}
|
||||
|
||||
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
|
||||
// Hunter's pets' should NOT use creature's original modifiers/multipliers
|
||||
if (getPetType() != HUNTER_PET)
|
||||
{
|
||||
health *= cInfo->HealthMultiplier;
|
||||
|
||||
if (mana > 0)
|
||||
mana *= cInfo->PowerMultiplier;
|
||||
|
||||
armor *= cInfo->ArmorMultiplier;
|
||||
}
|
||||
|
||||
// Apply custom health setting (from config)
|
||||
health *= _GetHealthMod(cInfo->Rank);
|
||||
|
||||
// Need to update stats before setting health and power or it will bug out in-game displaying it as the mob missing about 2/3
|
||||
UpdateAllStats();
|
||||
|
||||
SetHealth(GetMaxHealth());
|
||||
SetPower(GetPowerType(), GetMaxPower(GetPowerType()));
|
||||
// A pet cannot not have health
|
||||
if (health < 1)
|
||||
health = 1;
|
||||
|
||||
return true;
|
||||
// Set health
|
||||
SetCreateHealth(health);
|
||||
SetMaxHealth(health);
|
||||
SetHealth(health);
|
||||
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, health);
|
||||
|
||||
// Set mana
|
||||
SetCreateMana(mana);
|
||||
SetMaxPower(POWER_MANA, mana);
|
||||
SetPower(POWER_MANA, mana);
|
||||
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, mana);
|
||||
|
||||
// Remove rage bar from pets (By setting rage = 0, and ensuring it stays that way by setting max rage = 0 as well)
|
||||
SetMaxPower(POWER_RAGE, 0);
|
||||
SetPower(POWER_RAGE, 0);
|
||||
SetModifierValue(UNIT_MOD_RAGE, BASE_VALUE, 0);
|
||||
|
||||
// Set armor
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool Pet::HaveInDiet(ItemPrototype const* item) const
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue