void Player::UpdateAttackPowerAndDamage(bool ranged) { float val2 = 0.0f; float level = float(getLevel()); ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod_pos = UNIT_FIELD_ATTACK_POWER_MOD_POS; uint16 index_mod_neg = UNIT_FIELD_ATTACK_POWER_MOD_NEG; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility; if (unitMod == UNIT_MOD_ATTACK_POWER_RANGED) { index_mod_pos = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS; index_mod_neg = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG; val2 += GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_ATTACK_POWER); } } else { float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f); float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f); SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm()); // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ? if (form && form->flags1 & 0x20) { agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * 2.0f, 0.0f); strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * 2.0f, 0.0f); } val2 = strengthValue + agilityValue; } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod_pos = GetModifierValue(unitMod, TOTAL_VALUE); float attPowerMod_neg = 0.0f; // Check if we have to subcract or increase AP if (attPowerMod_pos < 0) { attPowerMod_pos = 0; attPowerMod_neg = -attPowerMod_pos; } if (ranged) { attPowerMod_pos = 0.0f; attPowerMod_neg = 0.0f; } // Check this base_attPower *= GetModifierValue(unitMod, TOTAL_PCT); //add dynamic flat mods if (!ranged) { AuraEffectList const& mAPbyArmor = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for (AuraEffectList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) { // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) int32 temp = int32(GetArmor() / (*iter)->GetAmount()); if (temp > 0) attPowerMod_pos += temp; else attPowerMod_neg -= temp; } } SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod_pos, (uint32) attPowerMod_pos); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field SetInt32Value(index_mod_neg, (uint32) attPowerMod_neg); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_NEG field Pet* pet = GetPet(); //update pet's AP Guardian* guardian = GetGuardianPet(); //automatically update weapon damage after attack power modification if (ranged) { UpdateDamagePhysical(RANGED_ATTACK); if (pet && pet->isHunterPet()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } else { UpdateDamagePhysical(BASE_ATTACK); if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet pet->UpdateAttackPowerAndDamage(); if (guardian && guardian->IsSpiritWolf()) // At melee attack power change for Shaman feral spirit guardian->UpdateAttackPowerAndDamage(); } }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask == GROUP_UPDATE_FLAG_NONE) return; if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); data->append(player->GetPackGUID()); *data << uint32(mask); if (mask & GROUP_UPDATE_FLAG_STATUS) { uint16 playerStatus = MEMBER_STATUS_ONLINE; if (player->IsPvP()) playerStatus |= MEMBER_STATUS_PVP; if (!player->IsAlive()) { if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) playerStatus |= MEMBER_STATUS_GHOST; else playerStatus |= MEMBER_STATUS_DEAD; } if (player->IsFFAPvP()) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) playerStatus |= MEMBER_STATUS_AFK; if (player->isDND()) playerStatus |= MEMBER_STATUS_DND; *data << uint16(playerStatus); } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << uint32(player->GetHealth()); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << uint32(player->GetMaxHealth()); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << uint8(powerType); if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << uint16(player->GetPower(powerType)); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << uint16(player->GetMaxPower(powerType)); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << uint16(player->getLevel()); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << uint16(player->GetZoneId()); if (mask & GROUP_UPDATE_FLAG_POSITION) { *data << uint16(player->GetPositionX()); *data << uint16(player->GetPositionY()); } if (mask & GROUP_UPDATE_FLAG_AURAS) { uint64 auramask = player->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const* aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } Pet* pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) { if (pet) *data << (uint64) pet->GetGUID(); else *data << (uint64) 0; } if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if (pet) *data << pet->GetName(); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if (pet) *data << uint16(pet->GetDisplayId()); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if (pet) *data << uint32(pet->GetHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if (pet) *data << uint32(pet->GetMaxHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if (pet) *data << uint8(pet->getPowerType()); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if (pet) *data << uint16(pet->GetPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if (pet) *data << uint16(pet->GetMaxPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { uint64 auramask = pet->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const* aurApp = pet->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(aurApp ? aurApp->GetFlags() : 0); } } } else *data << uint64(0); } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { if (Vehicle* veh = player->GetVehicle()) *data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); else *data << uint32(0); } }
void WorldSession::HandlePetRename(WorldPacket & recv_data) { sLog->outDetail("HandlePetRename. CMSG_PET_RENAME"); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petguid; recv_data >> name; recv_data >> isdeclined; Pet* pet = ObjectAccessor::FindPet(petguid); // check it! if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if (sObjectMgr->IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Unit* owner = pet->GetOwner(); if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.EscapeString(declinedname.name[i]); trans->PAppend("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); trans->PAppend("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u', '%u', '%s', '%s', '%s', '%s', '%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.EscapeString(name); trans->PAppend("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(trans); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped }
void WorldSession::HandlePetRename(WorldPacket & recv_data) { sLog.outDetail("HandlePetRename. CMSG_PET_RENAME"); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petguid; recv_data >> name; recv_data >> isdeclined; Pet* pet = ObjectAccessor::FindPet(petguid); // check it! if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType() != HUNTER_PET || pet->GetByteValue(UNIT_FIELD_BYTES_2, 2) != UNIT_RENAME_ALLOWED || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; if (!ObjectMgr::IsValidPetName(name)) { SendPetNameInvalid(PET_NAME_INVALID, name, NULL); return; } if (objmgr.IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Unit *owner = pet->GetOwner(); if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); if (isdeclined) { for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) recv_data >> declinedname.name[i]; std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } CharacterDatabase.BeginTransaction(); if (isdeclined) { for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.escape_string(name); CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); }
void Player::UpdateAttackPowerAndDamage(bool ranged ) { float val2 = 0.0f; float level = float(getLevel()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if(ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; switch(getClass()) { case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_WARRIOR:val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_DRUID: switch(m_form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: val2 = 0.0f; break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } } else { switch(getClass()) { case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_DRUID: { //Check if Predatory Strikes is skilled float mLevelMult = 0.0; switch(m_form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: case FORM_MOONKIN: { Unit::AuraEffectList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { // Predatory Strikes (effect 0) if ((*itr)->GetEffIndex()==0 && (*itr)->GetSpellProto()->SpellIconID == 1563) { mLevelMult = (*itr)->GetAmount() / 100.0f; break; } } break; } default: break; } switch(m_form) { case FORM_CAT: val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; case FORM_MOONKIN: val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; default: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; } break; } case CLASS_MAGE: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_PRIEST: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_WARLOCK: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; } } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods if( ranged ) { if ((getClassMask() & CLASSMASK_WAND_USERS)==0) { AuraEffectList const& mRAPbyStat = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 100.0f); } } else { AuraEffectList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 100.0f); AuraEffectList const& mAPbyArmor = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for (AuraEffectList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) attPowerMod += int32(GetArmor() / (*iter)->GetAmount()); } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field Pet *pet = GetPet(); //update pet's AP //automatically update weapon damage after attack power modification if(ranged) { UpdateDamagePhysical(RANGED_ATTACK); if(pet && pet->isHunterPet()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } else { UpdateDamagePhysical(BASE_ATTACK); if(CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if(getClass() == CLASS_SHAMAN) // mental quickness UpdateSpellDamageAndHealingBonus(); if(pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); *data << player->GetPackGUID(); *data << uint32(mask); if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player->IsPvP()) *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << uint16(MEMBER_STATUS_ONLINE); } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << uint32(player->GetHealth()); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << uint32(player->GetMaxHealth()); Powers powerType = player->GetPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << uint8(powerType); if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << uint16(player->GetPower(powerType)); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << uint16(player->GetMaxPower(powerType)); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << uint16(player->getLevel()); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << uint16(player->GetZoneId()); if (mask & GROUP_UPDATE_FLAG_UNK) *data << uint16(0); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()) << uint16(player->GetPositionZ()); if (mask & GROUP_UPDATE_FLAG_AURAS) { *data << uint8(0); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below const uint64& auramask = player->GetAuraUpdateMask(); *data << uint64(auramask); *data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { if (SpellAuraHolder* holder = player->GetVisibleAura(i)) { *data << uint32(holder->GetId()); *data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) *data << int32(aura->GetModifier()->m_amount); else *data << int32(0); } else { *data << uint32(0); *data << uint16(0); } } } } Pet* pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) *data << (pet ? pet->GetObjectGuid() : ObjectGuid()); if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if (pet) *data << pet->GetName(); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if (pet) *data << uint16(pet->GetDisplayId()); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if (pet) *data << uint32(pet->GetHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if (pet) *data << uint32(pet->GetMaxHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if (pet) *data << uint8(pet->GetPowerType()); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if (pet) *data << uint16(pet->GetPower(pet->GetPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if (pet) *data << uint16(pet->GetMaxPower(pet->GetPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { *data << uint8(0); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below const uint64& auramask = pet->GetAuraUpdateMask(); *data << uint64(auramask); *data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { if (SpellAuraHolder* holder = pet->GetVisibleAura(i)) { *data << uint32(holder->GetId()); *data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) *data << int32(aura->GetModifier()->m_amount); else *data << int32(0); } else { *data << uint32(0); *data << uint16(0); } } } } else { *data << uint8(0); *data << uint64(0); *data << uint32(0); } } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) *data << int32(0); if (mask & GROUP_UPDATE_FLAG_PHASE) { *data << uint32(8); *data << uint32(0); *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { if (player->GetTransportInfo()) *data << uint32(((Unit*)player->GetTransportInfo()->GetTransport())->GetVehicleInfo()->GetVehicleEntry()->m_seatID[player->GetTransportInfo()->GetTransportSeat()]); else *data << uint32(0); } }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); uint64 Guid; recv_data >> Guid; Player* player = HashMapHolder<Player>::Find(Guid); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(Guid); data << (uint32) GROUP_UPDATE_FLAG_STATUS; data << (uint16) MEMBER_STATUS_OFFLINE; SendPacket(&data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if (pet) mask1 = 0x7FFFFFFF; // for hunters and other classes with pets Powers powerType = player->getPowerType(); data << (uint32) mask1; // group update mask data << (uint16) MEMBER_STATUS_ONLINE; // member's online status data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER data << (uint16) player->getLevel(); // GROUP_UPDATE_FLAG_LEVEL data << (uint16) player->GetZoneId(); // GROUP_UPDATE_FLAG_ZONE data << (uint16) player->GetPositionX(); // GROUP_UPDATE_FLAG_POSITION data << (uint16) player->GetPositionY(); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << (uint64) auramask; // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication * aurApp = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << (uint32) aurApp->GetBase()->GetId(); data << (uint8) 1; } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->getPowerType(); data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << (uint64) petauramask; // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication * auraApp = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << (uint32) auraApp->GetBase()->GetId(); data << (uint8) 1; } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS } SendPacket(&data); }
// Split from the basic MakePet to allow backward compatiblity with existing code while also // making it possible for petpower to be retained without the focus item having to // stay equipped when the character zones. petpower of -1 means that the currently equipped petfocus // of a client is searched for and used instead. void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname, float in_size) { // Sanity and early out checking first. if(HasPet() || pettype == nullptr) return; int16 act_power = 0; // The actual pet power we'll use. if (petpower == -1) { if (this->IsClient()) { act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); act_power = CastToClient()->mod_pet_power(act_power, spell_id); } } else if (petpower > 0) act_power = petpower; // optional rule: classic style variance in pets. Achieve this by // adding a random 0-4 to pet power, since it only comes in increments // of five from focus effects. //lookup our pets table record for this type PetRecord record; if(!database.GetPoweredPetEntry(pettype, act_power, &record)) { Message(13, "Unable to find data for pet %s", pettype); LogFile->write(EQEMuLog::Error, "Unable to find data for pet %s, check pets table.", pettype); return; } //find the NPC data for the specified NPC type const NPCType *base = database.GetNPCType(record.npc_type); if(base == nullptr) { Message(13, "Unable to load NPC data for pet %s", pettype); LogFile->write(EQEMuLog::Error, "Unable to load NPC data for pet %s (NPC ID %d), check pets and npc_types tables.", pettype, record.npc_type); return; } //we copy the npc_type data because we need to edit it a bit NPCType *npc_type = new NPCType; memcpy(npc_type, base, sizeof(NPCType)); // If pet power is set to -1 in the DB, use stat scaling if (this->IsClient() && record.petpower == -1) { float scale_power = (float)act_power / 100.0f; if(scale_power > 0) { npc_type->max_hp *= (1 + scale_power); npc_type->cur_hp = npc_type->max_hp; npc_type->AC *= (1 + scale_power); npc_type->level += 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2))); npc_type->max_dmg = (npc_type->max_dmg * (1 + (scale_power / 2))); npc_type->size *= (1 + (scale_power / 2)); } record.petpower = act_power; } //Live AA - Elemental Durability int16 MaxHP = aabonuses.PetMaxHP + itembonuses.PetMaxHP + spellbonuses.PetMaxHP; if (MaxHP){ npc_type->max_hp += (npc_type->max_hp*MaxHP)/100; npc_type->cur_hp = npc_type->max_hp; } //TODO: think about regen (engaged vs. not engaged) // Pet naming: // 0 - `s pet // 1 - `s familiar // 2 - `s Warder // 3 - Random name if client, `s pet for others // 4 - Keep DB name if (petname != nullptr) { // Name was provided, use it. strn0cpy(npc_type->name, petname, 64); } else if (record.petnaming == 0) { strcpy(npc_type->name, this->GetCleanName()); npc_type->name[25] = '\0'; strcat(npc_type->name, "`s_pet"); } else if (record.petnaming == 1) { strcpy(npc_type->name, this->GetName()); npc_type->name[19] = '\0'; strcat(npc_type->name, "`s_familiar"); } else if (record.petnaming == 2) { strcpy(npc_type->name, this->GetName()); npc_type->name[21] = 0; strcat(npc_type->name, "`s_Warder"); } else if (record.petnaming == 4) { // Keep the DB name } else if (record.petnaming == 3 && IsClient()) { strcpy(npc_type->name, GetRandPetName()); } else { strcpy(npc_type->name, this->GetCleanName()); npc_type->name[25] = '\0'; strcat(npc_type->name, "`s_pet"); } //handle beastlord pet appearance if(record.petnaming == 2) { switch(GetBaseRace()) { case VAHSHIR: npc_type->race = TIGER; npc_type->size *= 0.8f; break; case TROLL: npc_type->race = ALLIGATOR; npc_type->size *= 2.5f; break; case OGRE: npc_type->race = BEAR; npc_type->texture = 3; npc_type->gender = 2; break; case BARBARIAN: npc_type->race = WOLF; npc_type->texture = 2; break; case IKSAR: npc_type->race = WOLF; npc_type->texture = 0; npc_type->gender = 1; npc_type->size *= 2.0f; npc_type->luclinface = 0; break; default: npc_type->race = WOLF; npc_type->texture = 0; } } // handle monster summoning pet appearance if(record.monsterflag) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; MYSQL_RES *result = nullptr; MYSQL_ROW row = nullptr; uint32 monsterid; // get a random npc id from the spawngroups assigned to this zone if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT npcID FROM (spawnentry INNER JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID) " "INNER JOIN npc_types ON npc_types.id = spawnentry.npcID " "WHERE spawn2.zone = '%s' AND npc_types.bodytype NOT IN (11, 33, 66, 67) " "AND npc_types.race NOT IN (0,1,2,3,4,5,6,7,8,9,10,11,12,44,55,67,71,72,73,77,78,81,90,92,93,94,106,112,114,127,128,130,139,141,183,236,237,238,239,254,266,329,330,378,379,380,381,382,383,404,522) " "ORDER BY RAND() LIMIT 1", zone->GetShortName()), errbuf, &result)) { row = mysql_fetch_row(result); if (row) monsterid = atoi(row[0]); else monsterid = 567; // since we don't have any monsters, just make it look like an earth pet for now } else { // if the database query failed LogFile->write(EQEMuLog::Error, "Error querying database for monster summoning pet in zone %s (%s)", zone->GetShortName(), errbuf); monsterid = 567; } // give the summoned pet the attributes of the monster we found const NPCType* monster = database.GetNPCType(monsterid); if(monster) { npc_type->race = monster->race; npc_type->size = monster->size; npc_type->texture = monster->texture; npc_type->gender = monster->gender; npc_type->luclinface = monster->luclinface; npc_type->helmtexture = monster->helmtexture; } else { LogFile->write(EQEMuLog::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid); } safe_delete_array(query); } //this takes ownership of the npc_type data Pet *npc = new Pet(npc_type, this, (PetType)record.petcontrol, spell_id, record.petpower); // Now that we have an actual object to interact with, load // the base items for the pet. These are always loaded // so that a rank 1 suspend minion does not kill things // like the special back items some focused pets may receive. uint32 petinv[MAX_WORN_INVENTORY]; memset(petinv, 0, sizeof(petinv)); const Item_Struct *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { for (int i=0; i<MAX_WORN_INVENTORY; i++) if (petinv[i]) { item = database.GetItem(petinv[i]); npc->AddLootDrop(item, &npc->itemlist, 0, 1, 127, true, true); } } // finally, override size if one was provided if (in_size > 0.0f) npc->size = in_size; entity_list.AddNPC(npc, true, true); SetPetID(npc->GetID()); // We need to handle PetType 5 (petHatelist), add the current target to the hatelist of the pet }
void PlayerbotHunterAI::DoNonCombatActions() { PlayerbotAI *ai = GetAI(); if (!ai) return; Player * m_bot = GetPlayerBot(); if (!m_bot) return; // reset ranged combat state if (!m_rangedCombat) m_rangedCombat = true; // buff group if (TRUESHOT_AURA > 0) (!m_bot->HasAura(TRUESHOT_AURA, EFFECT_INDEX_0) && ai->CastSpell (TRUESHOT_AURA, *m_bot)); // buff myself if (ASPECT_OF_THE_HAWK > 0) (!m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0) && ai->CastSpell (ASPECT_OF_THE_HAWK, *m_bot)); // mana check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); Item* pItem = ai->FindDrink(); Item* fItem = ai->FindBandage(); if (pItem != NULL && ai->GetManaPercent() < 30) { ai->TellMaster("I could use a drink."); ai->UseItem(pItem); return; } // hp check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); pItem = ai->FindFood(); if (pItem != NULL && ai->GetHealthPercent() < 30) { ai->TellMaster("I could use some food."); ai->UseItem(pItem); return; } else if (pItem == NULL && fItem != NULL && !m_bot->HasAura(RECENTLY_BANDAGED, EFFECT_INDEX_0) && ai->GetHealthPercent() < 70) { ai->TellMaster("I could use first aid."); ai->UseItem(fItem); return; } else if (pItem == NULL && fItem == NULL && m_bot->getRace() == RACE_DRAENEI && !m_bot->HasAura(GIFT_OF_THE_NAARU, EFFECT_INDEX_0) && ai->GetHealthPercent() < 70) { ai->TellMaster("I'm casting gift of the naaru."); ai->CastSpell(GIFT_OF_THE_NAARU, *m_bot); return; } // check for pet if (PET_SUMMON > 0 && !m_petSummonFailed && HasPet(m_bot)) { // we can summon pet, and no critical summon errors before Pet *pet = m_bot->GetPet(); if (!pet) { // summon pet if (PET_SUMMON > 0 && ai->CastSpell(PET_SUMMON, *m_bot)) ai->TellMaster("summoning pet."); else { m_petSummonFailed = true; ai->TellMaster("summon pet failed!"); } } else if (pet->getDeathState() != ALIVE) { // revive pet if (PET_REVIVE > 0 && ai->GetManaPercent() >= 80 && ai->CastSpell(PET_REVIVE, *m_bot)) ai->TellMaster("reviving pet."); } else if (((float) pet->GetHealth() / (float) pet->GetMaxHealth()) < 0.5f) { // heal pet when health lower 50% if (PET_MEND > 0 && !pet->getDeathState() != ALIVE && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && ai->GetManaPercent() >= 13 && ai->CastSpell(PET_MEND, *m_bot)) ai->TellMaster("healing pet."); } else if (pet->GetHappinessState() != HAPPY) // if pet is hungry { Unit *caster = (Unit *) m_bot; // list out items in main backpack for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; slot++) { Item* const pItem = m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); if (pItem) { const ItemPrototype* const pItemProto = pItem->GetProto(); if (!pItemProto) continue; if (pet->HaveInDiet(pItemProto)) // is pItem in pets diet { //sLog.outDebug("Food for pet: %s",pItemProto->Name1); caster->CastSpell(caster, 51284, true); // pet feed visual uint32 count = 1; // number of items used int32 benefit = pet->GetCurrentFoodBenefitLevel(pItemProto->ItemLevel); // nutritional value of food m_bot->DestroyItemCount(pItem, count, true); // remove item from inventory m_bot->CastCustomSpell(m_bot, PET_FEED, &benefit, NULL, NULL, true); // feed pet ai->TellMaster("feeding pet."); ai->SetIgnoreUpdateTime(10); return; } } } // list out items in other removable backpacks for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag) { const Bag* const pBag = (Bag *) m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, bag); if (pBag) for (uint8 slot = 0; slot < pBag->GetBagSize(); ++slot) { Item* const pItem = m_bot->GetItemByPos(bag, slot); if (pItem) { const ItemPrototype* const pItemProto = pItem->GetProto(); if (!pItemProto) continue; if (pet->HaveInDiet(pItemProto)) // is pItem in pets diet { //sLog.outDebug("Food for pet: %s",pItemProto->Name1); caster->CastSpell(caster, 51284, true); // pet feed visual uint32 count = 1; // number of items used int32 benefit = pet->GetCurrentFoodBenefitLevel(pItemProto->ItemLevel); // nutritional value of food m_bot->DestroyItemCount(pItem, count, true); // remove item from inventory m_bot->CastCustomSpell(m_bot, PET_FEED, &benefit, NULL, NULL, true); // feed pet ai->TellMaster("feeding pet."); ai->SetIgnoreUpdateTime(10); return; } } } } if (pet->HasAura(PET_MEND, EFFECT_INDEX_0) && !pet->HasAura(PET_FEED, EFFECT_INDEX_0)) ai->TellMaster("..no pet food!"); ai->SetIgnoreUpdateTime(7); } } } // end DoNonCombatActions
static bool HandleLearnAllMyPetTalentsCommand(ChatHandler* handler, const char* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); Pet* pet = player->GetPet(); if (!pet) { handler->SendSysMessage(LANG_NO_PET_FOUND); handler->SetSentErrorMessage(true); return false; } CreatureInfo const *ci = pet->GetCreatureInfo(); if (!ci) { handler->SendSysMessage(LANG_WRONG_PET_TYPE); handler->SetSentErrorMessage(true); return false; } CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); if (!pet_family) { handler->SendSysMessage(LANG_WRONG_PET_TYPE); handler->SetSentErrorMessage(true); return false; } if (pet_family->petTalentType < 0) // not hunter pet { handler->SendSysMessage(LANG_WRONG_PET_TYPE); handler->SetSentErrorMessage(true); return false; } for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); if (!talentTabInfo) continue; // prevent learn talent for different family (cheating) if (((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask) == 0) continue; // search highest talent rank uint32 spellid = 0; for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) { if (talentInfo->RankID[rank] != 0) { spellid = talentInfo->RankID[rank]; break; } } if (!spellid) // ??? none spells in talent continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer(),false)) continue; // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) pet->learnSpellHighRank(spellid); } pet->SetFreeTalentPoints(0); handler->SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); return true; }
bool ChatHandler::HandleCreatePetCommand(const char* /*args*/) { Player* player = m_session->GetPlayer(); Creature* creatureTarget = getSelectedCreature(); if (!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) { PSendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creatureTarget->GetEntry()); // Creatures with family 0 crashes the server if (cInfo->family == 0) { PSendSysMessage("This creature cannot be tamed. (family id: 0)."); SetSentErrorMessage(true); return false; } if (player->GetPetGUID()) { PSendSysMessage("You already have a pet"); SetSentErrorMessage(true); return false; } // Everything looks OK, create new pet Pet* pet = new Pet(player, HUNTER_PET); if (!pet) return false; if (!pet->CreateBaseAtCreature(creatureTarget)) { delete pet; PSendSysMessage("Error 1"); return false; } creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); if (!pet->InitStatsForLevel(creatureTarget->getLevel())) { sLog->outError("InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); PSendSysMessage("Error 2"); delete pet; return false; } // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()-1); pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); // this enables pet details window (Shift+P) pet->InitPetCreateSpells(); pet->SetFullHealth(); pet->GetMap()->Add(pet->ToCreature()); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()); player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); player->PetSpellInitialize(); return true; }
void WorldSession::HandleMoveWorldportAckOpcode() { // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if(!MapManager::IsValidMapCoord(loc.mapid,loc.x,loc.y,loc.z,loc.o)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if(GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleport(false); // relocate the player to the teleport destination GetPlayer()->SetMapId(loc.mapid); GetPlayer()->Relocate(loc.x, loc.y, loc.z, loc.o); // since the MapId is set before the GetInstance call, the InstanceId must be set to 0 // to let GetInstance() determine the proper InstanceId based on the player's binds GetPlayer()->SetInstanceId(0); // check this before Map::Add(player), because that will create the instance save! bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!GetPlayer()->GetMap()->Add(GetPlayer())) { sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o); // teleport the player home GetPlayer()->SetDontMove(false); if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) { // the player must always be able to teleport home sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d,%f,%f,%f,%f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); assert(false); } return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleGround()) { // cleanup seting if outdated if(!mEntry->IsBattleGroundOrArena()) { _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team _player->SetBGTeam(0); } // join to bg case else if(BattleGround *bg = _player->GetBattleGround()) { if(_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) { if(!_player->InBattleGround()) { // short preparations to continue flight GetPlayer()->SetDontMove(false); FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->m_taxi.ClearTaxiDestinations(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if( mEntry->IsDungeon() ) { GetPlayer()->ResurrectPlayer(0.5f); GetPlayer()->SpawnCorpseBones(); GetPlayer()->SaveToDB(); } } if(mEntry->IsRaid() && mInstance) { if(reset_notify) { uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance } } // mount allow check if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet if(GetPlayer()->m_temporaryUnsummonedPetNumber) { Pet* NewPet = new Pet; if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true)) delete NewPet; GetPlayer()->m_temporaryUnsummonedPetNumber = 0; } GetPlayer()->SetDontMove(false); }
bool PlayerbotPaladinAI::BuffPlayer(Player* target) { PlayerbotAI * ai = GetAI(); uint8 SPELL_BLESSING = 2; // See SpellSpecific enum in SpellMgr.h Pet * pet = target->GetPet(); bool petCanBeBlessed = false; if (pet) petCanBeBlessed = ai->CanReceiveSpecificSpell(SPELL_BLESSING, pet); if (!ai->CanReceiveSpecificSpell(SPELL_BLESSING, target) && !petCanBeBlessed) return false; switch (target->getClass()) { case CLASS_DRUID: case CLASS_SHAMAN: case CLASS_PALADIN: if (Bless(BLESSING_OF_MIGHT, target)) return true; if (Bless(BLESSING_OF_KINGS, target)) return true; if (Bless(BLESSING_OF_WISDOM, target)) return true; if (Bless(BLESSING_OF_SANCTUARY, target)) return true; else return false; case CLASS_DEATH_KNIGHT: case CLASS_HUNTER: if (petCanBeBlessed) if (Bless(BLESSING_OF_MIGHT, pet)) return true; if (Bless(BLESSING_OF_KINGS, pet)) return true; if (Bless(BLESSING_OF_SANCTUARY, pet)) return true; case CLASS_ROGUE: case CLASS_WARRIOR: if (Bless(BLESSING_OF_MIGHT, target)) return true; if (Bless(BLESSING_OF_KINGS, target)) return true; if (Bless(BLESSING_OF_SANCTUARY, target)) return true; else return false; case CLASS_WARLOCK: if (petCanBeBlessed) { if (pet->getPowerType() == POWER_MANA) { if (Bless(BLESSING_OF_WISDOM, pet)) return true; } else if (Bless(BLESSING_OF_MIGHT, pet)) return true; if (Bless(BLESSING_OF_KINGS, pet)) return true; if (Bless(BLESSING_OF_SANCTUARY, pet)) return true; } case CLASS_PRIEST: case CLASS_MAGE: if (Bless(BLESSING_OF_WISDOM, target)) return true; if (Bless(BLESSING_OF_KINGS, target)) return true; if (Bless(BLESSING_OF_SANCTUARY, target)) return true; else return false; } return false; }
void PlayerbotDeathKnightAI::DoNextCombatManeuver(Unit *pTarget) { PlayerbotAI* ai = GetAI(); if (!ai) return; switch (ai->GetScenarioType()) { case PlayerbotAI::SCENARIO_DUEL: ai->CastSpell(PLAGUE_STRIKE); return; } // ------- Non Duel combat ---------- //ai->SetMovementOrder( PlayerbotAI::MOVEMENT_FOLLOW, GetMaster() ); // dont want to melee mob // DK Attacks: Unholy, Frost & Blood // damage spells ai->SetInFront( pTarget );//<--- Player *m_bot = GetPlayerBot(); Unit* pVictim = pTarget->getVictim(); Pet *pet = m_bot->GetPet(); float dist = m_bot->GetDistance( pTarget ); std::ostringstream out; switch (SpellSequence) { case SPELL_DK_UNHOLY: if (UNHOLY_PRESENCE > 0) (!m_bot->HasAura(UNHOLY_PRESENCE, 0) && !m_bot->HasAura(BLOOD_PRESENCE, 0) && !m_bot->HasAura(FROST_PRESENCE, 0) && ai->CastSpell (UNHOLY_PRESENCE, *m_bot)); // check for BONE_SHIELD in combat if (BONE_SHIELD > 0) (!m_bot->HasAura(BONE_SHIELD, 0) && !m_bot->HasAura(ARMY_OF_THE_DEAD, 0) && ai->CastSpell (BONE_SHIELD, *m_bot)); if (ARMY_OF_THE_DEAD > 0 && ai->GetAttackerCount()>=5 && LastSpellUnholyDK < 1) { ai->CastSpell(ARMY_OF_THE_DEAD); out << " summoning Army of the Dead!"; if (ARMY_OF_THE_DEAD > 0 && m_bot->HasAura(ARMY_OF_THE_DEAD, 0)) ai->SetIgnoreUpdateTime(7); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (PLAGUE_STRIKE > 0 && !pTarget->HasAura(PLAGUE_STRIKE, 0) && LastSpellUnholyDK < 2) { ai->CastSpell(PLAGUE_STRIKE, *pTarget); out << " Plague Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_GRIP > 0 && !pTarget->HasAura(DEATH_GRIP, 0) && LastSpellUnholyDK < 3) { ai->CastSpell(DEATH_GRIP, *pTarget); out << " Death Grip"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_COIL > 0 && LastSpellUnholyDK < 4 && ai->GetRunicPower() >= 40) { ai->CastSpell(DEATH_COIL, *pTarget); out << " Death Coil"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_STRIKE > 0 && !pTarget->HasAura(DEATH_STRIKE, 0) && LastSpellUnholyDK < 5) { ai->CastSpell(DEATH_STRIKE, *pTarget); out << " Death Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (UNHOLY_BLIGHT > 0 && !pTarget->HasAura(UNHOLY_BLIGHT, 0) && LastSpellUnholyDK < 6) { ai->CastSpell(UNHOLY_BLIGHT); out << " Unholy Blight"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (SCOURGE_STRIKE > 0 && LastSpellUnholyDK < 7) { ai->CastSpell(SCOURGE_STRIKE, *pTarget); out << " Scourge Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_AND_DECAY > 0 && ai->GetAttackerCount()>=3 && dist <= ATTACK_DISTANCE && !pTarget->HasAura(DEATH_AND_DECAY, 0) && LastSpellUnholyDK < 8) { ai->CastSpell(DEATH_AND_DECAY); out << " Death and Decay"; ai->SetIgnoreUpdateTime(1); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (SUMMON_GARGOYLE > 0 && !m_bot->HasAura(ARMY_OF_THE_DEAD, 0) && !pTarget->HasAura(SUMMON_GARGOYLE, 0) && LastSpellUnholyDK < 9 && ai->GetRunicPower() >= 60) { ai->CastSpell(SUMMON_GARGOYLE, *pTarget); out << " summoning Gargoyle"; ai->SetIgnoreUpdateTime(2); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (CORPSE_EXPLOSION > 0 && dist <= ATTACK_DISTANCE && LastSpellUnholyDK < 10) { ai->CastSpell(CORPSE_EXPLOSION, *pTarget); out << " Corpse Explosion"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (ANTI_MAGIC_SHELL > 0 && pTarget->IsNonMeleeSpellCasted(true) && !m_bot->HasAura(ANTI_MAGIC_SHELL, 0) && LastSpellUnholyDK < 11 && ai->GetRunicPower() >= 20) { ai->CastSpell(ANTI_MAGIC_SHELL, *m_bot); out << " Anti-Magic Shell"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (ANTI_MAGIC_ZONE > 0 && pTarget->IsNonMeleeSpellCasted(true) && !m_bot->HasAura(ANTI_MAGIC_SHELL, 0) && LastSpellUnholyDK < 12) { ai->CastSpell(ANTI_MAGIC_ZONE, *m_bot); out << " Anti-Magic Zone"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if(( !pet ) && (RAISE_DEAD > 0 && !m_bot->HasAura(ARMY_OF_THE_DEAD, 0) && LastSpellUnholyDK < 13)) { ai->CastSpell(RAISE_DEAD); out << " summoning Ghoul"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if(( pet ) && (GHOUL_FRENZY > 0 && pVictim == pet && !pet->HasAura(GHOUL_FRENZY, 0) && LastSpellUnholyDK < 14)) { ai->CastSpell(GHOUL_FRENZY, *pet); out << " casting Ghoul Frenzy on pet"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (LastSpellUnholyDK > 15) { LastSpellUnholyDK = 0; SpellSequence = SPELL_DK_FROST; break; } LastSpellUnholyDK = 0; case SPELL_DK_FROST: if (FROST_PRESENCE > 0) (!m_bot->HasAura(FROST_PRESENCE, 0) && !m_bot->HasAura(BLOOD_PRESENCE, 0) && !m_bot->HasAura(UNHOLY_PRESENCE, 0) && ai->CastSpell (FROST_PRESENCE, *m_bot)); if (DEATHCHILL > 0) (!m_bot->HasAura(DEATHCHILL, 0) && !m_bot->HasAura(KILLING_MACHINE, 0) && ai->CastSpell (DEATHCHILL, *m_bot)); else if (KILLING_MACHINE > 0) (!m_bot->HasAura(KILLING_MACHINE, 0) && !m_bot->HasAura(DEATHCHILL, 0) && ai->CastSpell (KILLING_MACHINE, *m_bot)); if (ICY_TOUCH > 0 && !pTarget->HasAura(ICY_TOUCH, 0) && LastSpellFrostDK < 1) { ai->CastSpell(ICY_TOUCH, *pTarget); out << " Icy Touch"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (OBLITERATE > 0 && LastSpellFrostDK < 2) { ai->CastSpell(OBLITERATE, *pTarget); out << " Obliterate"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (FROST_STRIKE > 0 && LastSpellFrostDK < 3 && ai->GetRunicPower() >= 40) { ai->CastSpell(FROST_STRIKE, *pTarget); out << " Frost Strike"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (HOWLING_BLAST > 0 && ai->GetAttackerCount()>=3 && LastSpellFrostDK < 4) { ai->CastSpell(HOWLING_BLAST, *pTarget); out << " Howling Blast"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (CHAINS_OF_ICE > 0 && !pTarget->HasAura(CHAINS_OF_ICE, 0) && LastSpellFrostDK < 5) { ai->CastSpell(CHAINS_OF_ICE, *pTarget); out << " Chains of Ice"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (RUNE_STRIKE > 0 && LastSpellFrostDK < 6 && ai->GetRunicPower() >= 20) { ai->CastSpell(RUNE_STRIKE, *pTarget); out << " Rune Strike"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (ICY_CLUTCH > 0 && !pTarget->HasAura(ICY_CLUTCH, 0) && LastSpellFrostDK < 7) { ai->CastSpell(ICY_CLUTCH, *pTarget); out << " Icy Clutch"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (ICEBOUND_FORTITUDE > 0 && ai->GetHealthPercent() < 50 && pVictim == m_bot && !m_bot->HasAura(ICEBOUND_FORTITUDE, 0) && LastSpellFrostDK < 8 && ai->GetRunicPower() >= 20) { ai->CastSpell(ICEBOUND_FORTITUDE, *m_bot); out << " Icebound Fortitude"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (MIND_FREEZE > 0 && pTarget->IsNonMeleeSpellCasted(true) && dist <= ATTACK_DISTANCE && LastSpellFrostDK < 9 && ai->GetRunicPower() >= 20) { ai->CastSpell(MIND_FREEZE, *pTarget); out << " Mind Freeze"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (HUNGERING_COLD > 0 && ai->GetAttackerCount()>=3 && dist <= ATTACK_DISTANCE && LastSpellFrostDK < 10 && ai->GetRunicPower() >= 40) { ai->CastSpell(HUNGERING_COLD, *pTarget); out << " Hungering Cold"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (EMPOWER_WEAPON > 0 && ai->GetRunicPower() < 20 && LastSpellFrostDK < 11) { ai->CastSpell(EMPOWER_WEAPON, *m_bot); out << " Empower Rune Weapon"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (UNBREAKABLE_ARMOR > 0 && !m_bot->HasAura(UNBREAKABLE_ARMOR, 0) && ai->GetHealthPercent() < 70 && pVictim == m_bot && LastSpellFrostDK < 12) { ai->CastSpell(UNBREAKABLE_ARMOR, *m_bot); out << " Unbreakable Armor"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (LastSpellFrostDK > 13) { LastSpellFrostDK = 0; SpellSequence = SPELL_DK_BLOOD; break; } LastSpellFrostDK = 0; case SPELL_DK_BLOOD: if (BLOOD_PRESENCE > 0) (!m_bot->HasAura(BLOOD_PRESENCE, 0) && !m_bot->HasAura(UNHOLY_PRESENCE, 0) && !m_bot->HasAura(FROST_PRESENCE, 0) && ai->CastSpell (BLOOD_PRESENCE, *m_bot)); if (MARK_OF_BLOOD > 0 && !pTarget->HasAura(MARK_OF_BLOOD, 0) && LastSpellBloodDK < 1) { ai->CastSpell(MARK_OF_BLOOD, *pTarget); out << " Mark of Blood"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (BLOOD_STRIKE > 0 && LastSpellBloodDK < 2) { ai->CastSpell(BLOOD_STRIKE, *pTarget); out << " Blood Strike"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (PESTILENCE > 0 && dist <= ATTACK_DISTANCE && ai->GetAttackerCount()>=3 && LastSpellBloodDK < 3) { ai->CastSpell(PESTILENCE, *pTarget); out << " Pestilence"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (STRANGULATE > 0 && !pTarget->HasAura(STRANGULATE, 0) && LastSpellBloodDK < 4) { ai->CastSpell(STRANGULATE, *pTarget); out << " Strangulate"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (BLOOD_BOIL > 0 && ai->GetAttackerCount()>=5 && dist <= ATTACK_DISTANCE && LastSpellBloodDK < 5) { ai->CastSpell(BLOOD_BOIL, *pTarget); out << " Blood Boil"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (HEART_STRIKE > 0 && LastSpellBloodDK < 6) { ai->CastSpell(HEART_STRIKE, *pTarget); out << " Heart Strike"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (VAMPIRIC_BLOOD > 0 && ai->GetHealthPercent() < 70 && !m_bot->HasAura(VAMPIRIC_BLOOD, 0) && LastSpellBloodDK < 7) { ai->CastSpell(VAMPIRIC_BLOOD, *m_bot); out << " Vampiric Blood"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (RUNE_TAP > 0 && ai->GetHealthPercent() < 70 && !m_bot->HasAura(VAMPIRIC_BLOOD, 0) && LastSpellBloodDK < 8) { ai->CastSpell(RUNE_TAP, *m_bot); out << " Rune Tap"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (HYSTERIA > 0 && ai->GetHealthPercent() > 25 && !m_bot->HasAura(HYSTERIA, 0) && LastSpellBloodDK < 9) { ai->CastSpell(HYSTERIA, *m_bot); out << " Hysteria"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (DANCING_WEAPON > 0 && !m_bot->HasAura(DANCING_WEAPON, 0) && ai->GetRunicPower() >= 60 && LastSpellBloodDK < 10) { ai->CastSpell(DANCING_WEAPON, *pTarget); out << " summoning Dancing Rune Weapon"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (DARK_COMMAND > 0 && ai->GetHealthPercent() > 50 && pVictim != m_bot && !pTarget->HasAura(DARK_COMMAND, 0) && dist <= ATTACK_DISTANCE && LastSpellBloodDK < 11) { ai->CastSpell(DARK_COMMAND, *pTarget); out << " Dark Command"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if(( pet ) && (DEATH_PACT > 0 && ai->GetHealthPercent() < 50 && LastSpellBloodDK < 12 && ai->GetRunicPower() >= 40)) { ai->CastSpell(DEATH_PACT, *pet); out << " Death Pact (sacrifice pet)"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (LastSpellBloodDK > 13) { LastSpellBloodDK = 0; SpellSequence = SPELL_DK_UNHOLY; break; } else { LastSpellBloodDK = 0; SpellSequence = SPELL_DK_UNHOLY; } } if( ai->GetManager()->m_confDebugWhisper ) ai->TellMaster( out.str().c_str() ); } // end DoNextCombatManeuver
void PlayerbotWarlockAI::DoNonCombatActions() { PlayerbotAI *ai = GetAI(); if( !ai ) return; Player * m_bot = GetPlayerBot(); if (!m_bot) return; SpellSequence = SPELL_CURSES; Pet *pet = m_bot->GetPet(); // buff myself DEMON_SKIN, DEMON_ARMOR, FEL_ARMOR if (FEL_ARMOR > 0) (!m_bot->HasAura(FEL_ARMOR, EFFECT_INDEX_0) && ai->CastSpell(FEL_ARMOR, *m_bot)); else if (DEMON_ARMOR > 0) (!m_bot->HasAura(DEMON_ARMOR, EFFECT_INDEX_0) && !m_bot->HasAura(FEL_ARMOR, EFFECT_INDEX_0) && ai->CastSpell(DEMON_ARMOR, *m_bot)); else if (DEMON_SKIN > 0) (!m_bot->HasAura(DEMON_SKIN, EFFECT_INDEX_0) && !m_bot->HasAura(FEL_ARMOR, EFFECT_INDEX_0) && !m_bot->HasAura(DEMON_ARMOR, EFFECT_INDEX_0) && ai->CastSpell(DEMON_SKIN, *m_bot)); // buff myself & master DETECT_INVISIBILITY if (DETECT_INVISIBILITY > 0) (!m_bot->HasAura(DETECT_INVISIBILITY, EFFECT_INDEX_0) && ai->GetManaPercent() >= 2 && ai->CastSpell(DETECT_INVISIBILITY, *m_bot)); if (DETECT_INVISIBILITY > 0) (!GetMaster()->HasAura(DETECT_INVISIBILITY, EFFECT_INDEX_0) && ai->GetManaPercent() >= 2 && ai->CastSpell(DETECT_INVISIBILITY, *GetMaster())); // mana check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); Item* pItem = ai->FindDrink(); Item* fItem = ai->FindBandage(); if (pItem != NULL && ai->GetManaPercent() < 25) { ai->TellMaster("I could use a drink."); ai->UseItem(*pItem); ai->SetIgnoreUpdateTime(30); return; } else if(( pet ) && (pItem == NULL && DARK_PACT>0 && ai->GetManaPercent() <= 50 && pet->GetPower(POWER_MANA) > 0) ) { ai->CastSpell(DARK_PACT, *m_bot); //ai->TellMaster("casting dark pact."); return; } else if(( !pet ) && (pItem == NULL && LIFE_TAP>0 && ai->GetManaPercent() <= 50 && ai->GetHealthPercent() > 25) ) { ai->CastSpell(LIFE_TAP, *m_bot); //ai->TellMaster("casting life tap."); return; } // hp check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); pItem = ai->FindFood(); if (pItem != NULL && ai->GetHealthPercent() < 30) { ai->TellMaster("I could use some food."); ai->UseItem(*pItem); ai->SetIgnoreUpdateTime(30); return; } else if (pItem == NULL && fItem != NULL && !m_bot->HasAura(RECENTLY_BANDAGED, EFFECT_INDEX_0) && ai->GetHealthPercent() < 70) { ai->TellMaster("I could use first aid."); ai->UseItem(*fItem); ai->SetIgnoreUpdateTime(8); return; } else if(( pet ) && (pItem == NULL && fItem == NULL && CONSUME_SHADOWS>0 && !m_bot->HasAura(CONSUME_SHADOWS, EFFECT_INDEX_0) && ai->GetHealthPercent() < 75) ) { ai->CastSpell(CONSUME_SHADOWS, *m_bot); //ai->TellMaster("casting consume shadows."); return; } // check for demon if( SUMMON_FELGUARD>0 || SUMMON_FELHUNTER>0 || SUMMON_SUCCUBUS>0 || SUMMON_VOIDWALKER>0 || SUMMON_IMP>0 && !m_demonSummonFailed ) { if( !pet ) { // summon demon if( SUMMON_FELGUARD>0 && ai->CastSpell(SUMMON_FELGUARD,*m_bot) ) ai->TellMaster( "summoning felguard." ); else if( SUMMON_FELHUNTER>0 && ai->CastSpell(SUMMON_FELHUNTER,*m_bot) ) ai->TellMaster( "summoning felhunter." ); else if( SUMMON_SUCCUBUS>0 && ai->CastSpell(SUMMON_SUCCUBUS,*m_bot) ) ai->TellMaster( "summoning succubus." ); else if( SUMMON_VOIDWALKER>0 && ai->CastSpell(SUMMON_VOIDWALKER,*m_bot) ) ai->TellMaster( "summoning voidwalker." ); else if( SUMMON_IMP>0 && ai->GetManaPercent() >= 64 && ai->CastSpell(SUMMON_IMP,*m_bot) ) ai->TellMaster( "summoning imp." ); else { m_demonSummonFailed = true; //ai->TellMaster( "summon demon failed!" ); } } } // check for buffs with demon if(( pet ) && ( SOUL_LINK>0 && !m_bot->HasAura(SOUL_LINK, EFFECT_INDEX_0) && ai->GetManaPercent() >= 16 && ai->CastSpell(SOUL_LINK,*m_bot) )) { //ai->TellMaster( "casting soul link." ); return; } else if(( pet ) && ( BLOOD_PACT>0 && !m_bot->HasAura(BLOOD_PACT, EFFECT_INDEX_0) && ai->CastSpell(BLOOD_PACT,*m_bot) )) { //ai->TellMaster( "casting blood pact." ); return; } else if(( pet ) && ( FEL_INTELLIGENCE>0 && !m_bot->HasAura(FEL_INTELLIGENCE, EFFECT_INDEX_0) && ai->CastSpell(FEL_INTELLIGENCE,*m_bot) )) { //ai->TellMaster( "casting fel intelligence." ); return; } } // end DoNonCombatActions
void PlayerbotHunterAI::DoNextCombatManeuver(Unit *pTarget) { PlayerbotAI* ai = GetAI(); if (!ai) return; switch (ai->GetScenarioType()) { case PlayerbotAI::SCENARIO_DUEL: ai->CastSpell(RAPTOR_STRIKE); return; } // ------- Non Duel combat ---------- // Hunter ai->SetInFront(pTarget); Player *m_bot = GetPlayerBot(); Unit* pVictim = pTarget->getVictim(); // check for pet and heal if neccessary Pet *pet = m_bot->GetPet(); if ((pet) && (((float) pet->GetHealth() / (float) pet->GetMaxHealth()) < 0.5f) && (PET_MEND > 0 && !pet->getDeathState() != ALIVE && pVictim != m_bot && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && ai->GetManaPercent() >= 13 && ai->CastSpell(PET_MEND, *m_bot))) { ai->TellMaster("healing pet."); return; } else if ((pet) && (INTIMIDATION > 0 && pVictim == pet && !pet->HasAura(INTIMIDATION, EFFECT_INDEX_0) && ai->CastSpell(INTIMIDATION, *m_bot))) //ai->TellMaster( "casting intimidation." ); // if pet has aggro :) return; // racial traits if (m_bot->getRace() == RACE_ORC && !m_bot->HasAura(BLOOD_FURY, EFFECT_INDEX_0)) ai->CastSpell(BLOOD_FURY, *m_bot); //ai->TellMaster( "Blood Fury." ); else if (m_bot->getRace() == RACE_TROLL && !m_bot->HasAura(BERSERKING, EFFECT_INDEX_0)) ai->CastSpell(BERSERKING, *m_bot); //ai->TellMaster( "Berserking." ); // check if ranged combat is possible (set m_rangedCombat and switch auras float dist = m_bot->GetDistance(pTarget); if ((dist <= ATTACK_DISTANCE || !m_bot->GetUInt32Value(PLAYER_AMMO_ID)) && m_rangedCombat) { // switch to melee combat (target in melee range, out of ammo) m_rangedCombat = false; if (!m_bot->GetUInt32Value(PLAYER_AMMO_ID)) ai->TellMaster("Out of ammo!"); // become monkey (increases dodge chance)... (ASPECT_OF_THE_MONKEY > 0 && !m_bot->HasAura(ASPECT_OF_THE_MONKEY, EFFECT_INDEX_0) && ai->CastSpell(ASPECT_OF_THE_MONKEY, *m_bot)); } else if (dist > ATTACK_DISTANCE && !m_rangedCombat) { // switch to ranged combat m_rangedCombat = true; // increase ranged attack power... (ASPECT_OF_THE_HAWK > 0 && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0) && ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot)); } else if (m_rangedCombat && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0)) // check if we have hawk aspect in ranged combat (ASPECT_OF_THE_HAWK > 0 && ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot)); else if (!m_rangedCombat && !m_bot->HasAura(ASPECT_OF_THE_MONKEY, EFFECT_INDEX_0)) // check if we have monkey aspect in melee combat (ASPECT_OF_THE_MONKEY > 0 && ai->CastSpell(ASPECT_OF_THE_MONKEY, *m_bot)); // activate auto shot if (AUTO_SHOT > 0 && m_rangedCombat && !m_bot->FindCurrentSpellBySpellId(AUTO_SHOT)) ai->CastSpell(AUTO_SHOT, *pTarget); //ai->TellMaster( "started auto shot." ); else if (AUTO_SHOT > 0 && m_bot->FindCurrentSpellBySpellId(AUTO_SHOT)) m_bot->InterruptNonMeleeSpells(true, AUTO_SHOT); //ai->TellMaster( "stopped auto shot." ); // damage spells std::ostringstream out; if (m_rangedCombat) { out << "Case Ranged"; if (HUNTERS_MARK > 0 && ai->GetManaPercent() >= 3 && !pTarget->HasAura(HUNTERS_MARK, EFFECT_INDEX_0) && ai->CastSpell(HUNTERS_MARK, *pTarget)) out << " > Hunter's Mark"; else if (RAPID_FIRE > 0 && ai->GetManaPercent() >= 3 && !m_bot->HasAura(RAPID_FIRE, EFFECT_INDEX_0) && ai->CastSpell(RAPID_FIRE, *m_bot)) out << " > Rapid Fire"; else if (MULTI_SHOT > 0 && ai->GetManaPercent() >= 13 && ai->GetAttackerCount() >= 3 && ai->CastSpell(MULTI_SHOT, *pTarget)) out << " > Multi-Shot"; else if (ARCANE_SHOT > 0 && ai->GetManaPercent() >= 7 && ai->CastSpell(ARCANE_SHOT, *pTarget)) out << " > Arcane Shot"; else if (CONCUSSIVE_SHOT > 0 && ai->GetManaPercent() >= 6 && !pTarget->HasAura(CONCUSSIVE_SHOT, EFFECT_INDEX_0) && ai->CastSpell(CONCUSSIVE_SHOT, *pTarget)) out << " > Concussive Shot"; else if (EXPLOSIVE_SHOT > 0 && ai->GetManaPercent() >= 10 && !pTarget->HasAura(EXPLOSIVE_SHOT, EFFECT_INDEX_0) && ai->CastSpell(EXPLOSIVE_SHOT, *pTarget)) out << " > Explosive Shot"; else if (VIPER_STING > 0 && ai->GetManaPercent() >= 8 && pTarget->GetPower(POWER_MANA) > 0 && ai->GetManaPercent() < 70 && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && ai->CastSpell(VIPER_STING, *pTarget)) out << " > Viper Sting"; else if (SERPENT_STING > 0 && ai->GetManaPercent() >= 13 && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && ai->CastSpell(SERPENT_STING, *pTarget)) out << " > Serpent Sting"; else if (SCORPID_STING > 0 && ai->GetManaPercent() >= 11 && !pTarget->HasAura(WYVERN_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && ai->CastSpell(SCORPID_STING, *pTarget)) out << " > Scorpid Sting"; else if (CHIMERA_SHOT > 0 && ai->GetManaPercent() >= 12 && ai->CastSpell(CHIMERA_SHOT, *pTarget)) out << " > Chimera Shot"; else if (VOLLEY > 0 && ai->GetManaPercent() >= 24 && ai->GetAttackerCount() >= 3 && ai->CastSpell(VOLLEY, *pTarget)) out << " > Volley"; else if (BLACK_ARROW > 0 && ai->GetManaPercent() >= 6 && !pTarget->HasAura(BLACK_ARROW, EFFECT_INDEX_0) && ai->CastSpell(BLACK_ARROW, *pTarget)) out << " > Black Arrow"; else if (AIMED_SHOT > 0 && ai->GetManaPercent() >= 12 && ai->CastSpell(AIMED_SHOT, *pTarget)) out << " > Aimed Shot"; else if (STEADY_SHOT > 0 && ai->GetManaPercent() >= 5 && ai->CastSpell(STEADY_SHOT, *pTarget)) out << " > Steady Shot"; else if (KILL_SHOT > 0 && ai->GetManaPercent() >= 7 && pTarget->GetHealth() < pTarget->GetMaxHealth() * 0.2 && ai->CastSpell(KILL_SHOT, *pTarget)) out << " > Kill Shot!"; else out << " NONE!"; } else { out << "Case Melee"; if (RAPTOR_STRIKE > 0 && ai->GetManaPercent() >= 6 && ai->CastSpell(RAPTOR_STRIKE, *pTarget)) out << " > Raptor Strike"; else if (EXPLOSIVE_TRAP > 0 && ai->GetManaPercent() >= 27 && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && ai->CastSpell(EXPLOSIVE_TRAP, *pTarget)) out << " > Explosive Trap"; else if (WING_CLIP > 0 && ai->GetManaPercent() >= 6 && !pTarget->HasAura(WING_CLIP, EFFECT_INDEX_0) && ai->CastSpell(WING_CLIP, *pTarget)) out << " > Wing Clip"; else if (IMMOLATION_TRAP > 0 && ai->GetManaPercent() >= 13 && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && ai->CastSpell(IMMOLATION_TRAP, *pTarget)) out << " > Immolation Trap"; else if (MONGOOSE_BITE > 0 && ai->GetManaPercent() >= 4 && ai->CastSpell(MONGOOSE_BITE, *pTarget)) out << " > Mongoose Bite"; else if (FROST_TRAP > 0 && ai->GetManaPercent() >= 2 && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && ai->CastSpell(FROST_TRAP, *pTarget)) out << " > Frost Trap"; else if (ARCANE_TRAP > 0 && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && ai->CastSpell(ARCANE_TRAP, *pTarget)) out << " > Arcane Trap"; else if (DETERRENCE > 0 && pVictim == m_bot && m_bot->GetHealth() < m_bot->GetMaxHealth() * 0.5 && !m_bot->HasAura(DETERRENCE, EFFECT_INDEX_0) && ai->CastSpell(DETERRENCE, *m_bot)) out << " > Deterrence"; else if (m_bot->getRace() == RACE_TAUREN && !pTarget->HasAura(WAR_STOMP, EFFECT_INDEX_0) && ai->CastSpell(WAR_STOMP, *pTarget)) out << " > War Stomp"; else if (m_bot->getRace() == RACE_BLOODELF && !pTarget->HasAura(ARCANE_TORRENT, EFFECT_INDEX_0) && ai->CastSpell(ARCANE_TORRENT, *pTarget)) out << " > Arcane Torrent"; else if (m_bot->getRace() == RACE_DWARF && m_bot->HasAuraState(AURA_STATE_DEADLY_POISON) && ai->CastSpell(STONEFORM, *m_bot)) out << " > Stoneform"; else if (m_bot->getRace() == RACE_NIGHTELF && pVictim == m_bot && ai->GetHealthPercent() < 25 && !m_bot->HasAura(SHADOWMELD, EFFECT_INDEX_0) && ai->CastSpell(SHADOWMELD, *m_bot)) out << " > Shadowmeld"; else if (m_bot->getRace() == RACE_DRAENEI && ai->GetHealthPercent() < 25 && !m_bot->HasAura(GIFT_OF_THE_NAARU, EFFECT_INDEX_0) && ai->CastSpell(GIFT_OF_THE_NAARU, *m_bot)) out << " > Gift of the Naaru"; else if ((pet && !pet->getDeathState() != ALIVE) && (MISDIRECTION > 0 && pVictim == m_bot && !m_bot->HasAura(MISDIRECTION, EFFECT_INDEX_0) && ai->GetManaPercent() >= 9 && ai->CastSpell(MISDIRECTION, *pet))) out << " > Misdirection"; // give threat to pet /*else if( FREEZING_TRAP>0 && ai->GetManaPercent()>=5 && !pTarget->HasAura(FREEZING_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && ai->CastSpell(FREEZING_TRAP,*pTarget) ) out << " > Freezing Trap"; // this can trap your bots too else if( BEAR_TRAP>0 && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && ai->CastSpell(BEAR_TRAP,*pTarget) ) out << " > Bear Trap"; // this was just too annoying :) else if( DISENGAGE>0 && pVictim && ai->GetManaPercent()>=5 && ai->CastSpell(DISENGAGE,*pTarget) ) out << " > Disengage!"; // attempt to return to ranged combat*/ else out << " NONE!"; } if (ai->GetManager()->m_confDebugWhisper) ai->TellMaster(out.str().c_str()); } // end DoNextCombatManeuver
void PlayerbotWarlockAI::DoNextCombatManeuver(Unit *pTarget) { PlayerbotAI* ai = GetAI(); if (!ai) return; switch (ai->GetScenarioType()) { case PlayerbotAI::SCENARIO_DUEL: if (SHADOW_BOLT > 0) ai->CastSpell(SHADOW_BOLT); return; } // ------- Non Duel combat ---------- //ai->SetMovementOrder( PlayerbotAI::MOVEMENT_FOLLOW, GetMaster() ); // dont want to melee mob ai->SetInFront( pTarget ); Player *m_bot = GetPlayerBot(); Unit* pVictim = pTarget->getVictim(); Pet *pet = m_bot->GetPet(); // Damage Spells ai->SetInFront( pTarget ); switch (SpellSequence) { case SPELL_CURSES: if (CURSE_OF_AGONY > 0 && !pTarget->HasAura(CURSE_OF_AGONY, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && LastSpellCurse < 1 && ai->GetManaPercent() >= 14) { ai->CastSpell(CURSE_OF_AGONY, *pTarget); SpellSequence = SPELL_AFFLICTION; LastSpellCurse = LastSpellCurse +1; break; } else if (CURSE_OF_THE_ELEMENTS > 0 && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_AGONY, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_WEAKNESS, EFFECT_INDEX_0) && LastSpellCurse < 2 && ai->GetManaPercent() >= 10) { ai->CastSpell(CURSE_OF_THE_ELEMENTS, *pTarget); SpellSequence = SPELL_AFFLICTION; LastSpellCurse = LastSpellCurse +1; break; } else if (CURSE_OF_EXHAUSTION > 0 && !pTarget->HasAura(CURSE_OF_EXHAUSTION, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_WEAKNESS, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_AGONY, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS, EFFECT_INDEX_0) && LastSpellCurse < 3 && ai->GetManaPercent() >= 6) { ai->CastSpell(CURSE_OF_EXHAUSTION, *pTarget); SpellSequence = SPELL_AFFLICTION; LastSpellCurse = LastSpellCurse +1; break; } else if (CURSE_OF_WEAKNESS > 0 && !pTarget->HasAura(CURSE_OF_WEAKNESS, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_EXHAUSTION, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_AGONY, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS, EFFECT_INDEX_0) && LastSpellCurse < 4 && ai->GetManaPercent() >= 14) { ai->CastSpell(CURSE_OF_WEAKNESS, *pTarget); SpellSequence = SPELL_AFFLICTION; LastSpellCurse = LastSpellCurse +1; break; } else if (CURSE_OF_TONGUES > 0 && !pTarget->HasAura(CURSE_OF_TONGUES, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_WEAKNESS, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_EXHAUSTION, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_AGONY, EFFECT_INDEX_0) && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS, EFFECT_INDEX_0) && LastSpellCurse < 5 && ai->GetManaPercent() >= 4) { ai->CastSpell(CURSE_OF_TONGUES, *pTarget); SpellSequence = SPELL_AFFLICTION; LastSpellCurse = LastSpellCurse +1; break; } LastSpellCurse = 0; //SpellSequence = SPELL_AFFLICTION; //break; case SPELL_AFFLICTION: if (LIFE_TAP > 0 && LastSpellAffliction < 1 && ai->GetManaPercent() <= 50) { ai->CastSpell(LIFE_TAP, *m_bot); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (CORRUPTION > 0 && !pTarget->HasAura(CORRUPTION, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && !pTarget->HasAura(SEED_OF_CORRUPTION, EFFECT_INDEX_0) && LastSpellAffliction < 2 && ai->GetManaPercent() >= 19) { ai->CastSpell(CORRUPTION, *pTarget); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (DRAIN_SOUL > 0 && pTarget->GetHealth() < pTarget->GetMaxHealth()*0.40 && !pTarget->HasAura(DRAIN_SOUL, EFFECT_INDEX_0) && LastSpellAffliction < 3 && ai->GetManaPercent() >= 19) { ai->CastSpell(DRAIN_SOUL, *pTarget); ai->SetIgnoreUpdateTime(15); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (DRAIN_LIFE > 0 && LastSpellAffliction < 4 && !pTarget->HasAura(DRAIN_SOUL, EFFECT_INDEX_0) && !pTarget->HasAura(SEED_OF_CORRUPTION, EFFECT_INDEX_0) && !pTarget->HasAura(DRAIN_LIFE, EFFECT_INDEX_0) && !pTarget->HasAura(DRAIN_MANA, EFFECT_INDEX_0) && ai->GetHealthPercent() <= 70 && ai->GetManaPercent() >= 23) { ai->CastSpell(DRAIN_LIFE, *pTarget); ai->SetIgnoreUpdateTime(5); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (DRAIN_MANA > 0 && pTarget->GetPower(POWER_MANA) > 0 && !pTarget->HasAura(DRAIN_SOUL, EFFECT_INDEX_0) && !pTarget->HasAura(DRAIN_MANA, EFFECT_INDEX_0) && !pTarget->HasAura(SEED_OF_CORRUPTION, EFFECT_INDEX_0) && !pTarget->HasAura(DRAIN_LIFE, EFFECT_INDEX_0) && LastSpellAffliction < 5 && ai->GetManaPercent() < 70 && ai->GetManaPercent() >= 17) { ai->CastSpell(DRAIN_MANA, *pTarget); ai->SetIgnoreUpdateTime(5); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (UNSTABLE_AFFLICTION > 0 && LastSpellAffliction < 6 && !pTarget->HasAura(UNSTABLE_AFFLICTION, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && ai->GetManaPercent() >= 20) { ai->CastSpell(UNSTABLE_AFFLICTION, *pTarget); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (HAUNT > 0 && LastSpellAffliction < 7 && !pTarget->HasAura(HAUNT, EFFECT_INDEX_0) && ai->GetManaPercent() >= 12) { ai->CastSpell(HAUNT, *pTarget); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (ATROCITY > 0 && !pTarget->HasAura(ATROCITY, EFFECT_INDEX_0) && LastSpellAffliction < 8 && ai->GetManaPercent() >= 21) { ai->CastSpell(ATROCITY, *pTarget); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (SEED_OF_CORRUPTION > 0 && !pTarget->HasAura(SEED_OF_CORRUPTION, EFFECT_INDEX_0) && LastSpellAffliction < 9 && ai->GetManaPercent() >= 34) { ai->CastSpell(SEED_OF_CORRUPTION, *pTarget); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (HOWL_OF_TERROR > 0 && !pTarget->HasAura(HOWL_OF_TERROR, EFFECT_INDEX_0) && ai->GetAttackerCount()>3 && LastSpellAffliction < 10 && ai->GetManaPercent() >= 11) { ai->CastSpell(HOWL_OF_TERROR, *pTarget); ai->TellMaster("casting howl of terror!"); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if (FEAR > 0 && !pTarget->HasAura(FEAR, EFFECT_INDEX_0) && pVictim==m_bot && ai->GetAttackerCount()>=2 && LastSpellAffliction < 11 && ai->GetManaPercent() >= 12) { ai->CastSpell(FEAR, *pTarget); //ai->TellMaster("casting fear!"); ai->SetIgnoreUpdateTime(1.5); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } else if(( pet ) && (DARK_PACT > 0 && ai->GetManaPercent() <= 50 && LastSpellAffliction < 12 && pet->GetPower(POWER_MANA) > 0)) { ai->CastSpell(DARK_PACT, *m_bot); SpellSequence = SPELL_DESTRUCTION; LastSpellAffliction = LastSpellAffliction +1; break; } LastSpellAffliction = 0; //SpellSequence = SPELL_DESTRUCTION; //break; case SPELL_DESTRUCTION: if (SHADOWFURY > 0 && LastSpellDestruction < 1 && !pTarget->HasAura(SHADOWFURY, EFFECT_INDEX_0) && ai->GetManaPercent() >= 37) { ai->CastSpell(SHADOWFURY, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (SHADOW_BOLT > 0 && LastSpellDestruction < 2 && ai->GetManaPercent() >= 23) { ai->CastSpell(SHADOW_BOLT, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (RAIN_OF_FIRE > 0 && LastSpellDestruction < 3 && ai->GetAttackerCount()>=3 && ai->GetManaPercent() >= 77) { ai->CastSpell(RAIN_OF_FIRE, *pTarget); //ai->TellMaster("casting rain of fire!"); ai->SetIgnoreUpdateTime(8); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (SHADOWFLAME > 0 && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && LastSpellDestruction < 4 && ai->GetManaPercent() >= 25) { ai->CastSpell(SHADOWFLAME, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (IMMOLATE > 0 && !pTarget->HasAura(IMMOLATE, EFFECT_INDEX_0) && !pTarget->HasAura(SHADOWFLAME, EFFECT_INDEX_0) && LastSpellDestruction < 5 && ai->GetManaPercent() >= 23) { ai->CastSpell(IMMOLATE, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (CONFLAGRATE > 0 && LastSpellDestruction < 6 && ai->GetManaPercent() >= 16) { ai->CastSpell(CONFLAGRATE, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (INCINERATE > 0 && LastSpellDestruction < 7 && ai->GetManaPercent() >= 19) { ai->CastSpell(INCINERATE, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (SEARING_PAIN > 0 && LastSpellDestruction < 8 && ai->GetManaPercent() >= 11) { ai->CastSpell(SEARING_PAIN, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (SOUL_FIRE > 0 && LastSpellDestruction < 9 && ai->GetManaPercent() >= 13) { ai->CastSpell(SOUL_FIRE, *pTarget); ai->SetIgnoreUpdateTime(6); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (CHAOS_BOLT > 0 && LastSpellDestruction < 10 && ai->GetManaPercent() >= 9) { ai->CastSpell(CHAOS_BOLT, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (SHADOWBURN > 0 && LastSpellDestruction < 11 && pTarget->GetHealth() < pTarget->GetMaxHealth()*0.20 && !pTarget->HasAura(SHADOWBURN, EFFECT_INDEX_0) && ai->GetManaPercent() >= 27) { ai->CastSpell(SHADOWBURN, *pTarget); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else if (HELLFIRE > 0 && LastSpellDestruction < 12 && !m_bot->HasAura(HELLFIRE, EFFECT_INDEX_0) && ai->GetAttackerCount()>=5 && ai->GetHealthPercent() >= 10 && ai->GetManaPercent() >= 87) { ai->CastSpell(HELLFIRE); ai->TellMaster("casting hellfire!"); ai->SetIgnoreUpdateTime(15); SpellSequence = SPELL_CURSES; LastSpellDestruction = LastSpellDestruction + 1; break; } else { LastSpellDestruction = 0; SpellSequence = SPELL_CURSES; } } } // end DoNextCombatManeuver
void CreatePet(Player* player, Creature* creature, uint32 entry) { if (player->GetPet()) { player->GetSession()->SendNotification("You already have a pet!"); player->CLOSE_GOSSIP_MENU(); return; } Creature *creatureTarget = creature->SummonCreature(entry, player->GetPositionX(), player->GetPositionY() + 2, player->GetPositionZ(), player->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 500); if (!creatureTarget) return; Pet* pet = player->CreateTamedPetFrom(creatureTarget, 0); if (!pet) return; // kill original creature creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); pet->SetPower(POWER_HAPPINESS, 1048000); pet->SetTP(350); // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, player->getLevel() - 1); pet->GetMap()->Add(pet->ToCreature()); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, player->getLevel()); if (!pet->InitStatsForLevel(player->getLevel())) sLog->outError("Pet Create fail: No init stats for pet with entry %u", entry); pet->UpdateAllStats(); player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); player->PetSpellInitialize(); // make sure player has all training spells player->learnSpell(27348); // bite player->learnSpell(28343); // charge player->learnSpell(27347); // claw player->learnSpell(27346); // cower player->learnSpell(23112); // dash player->learnSpell(23150); // dive player->learnSpell(35324); // fire breath player->learnSpell(24599); // furious howl player->learnSpell(35308); // gore player->learnSpell(25017); // lightning breath player->learnSpell(35391); // poison spit player->learnSpell(24455); // prowl player->learnSpell(27361); // scorpid poison player->learnSpell(27349); // screech player->learnSpell(26065); // spell shield player->learnSpell(27366); // thunderstomp player->learnSpell(35348); // warp player->learnSpell(27350); // arcane res player->learnSpell(27353); // shadow res player->learnSpell(27351); // fire res player->learnSpell(27352); // frost res player->learnSpell(27354); // nature res player->learnSpell(27362); // natural armor player->learnSpell(27364); // great stamina player->learnSpell(35700); // avoidance player->learnSpell(25077); // cobra reflexes player->CLOSE_GOSSIP_MENU(); player->GetSession()->SendAreaTriggerMessage("Pet tamed successfully."); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player* player = ObjectAccessor::FindPlayer(guid, false); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3 + 4 + 2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_AURAS | GROUP_UPDATE_FLAG_PHASE; if (pet) mask1 = 0x7FEFFEFF; // full mask & ~(GROUP_UPDATE_FLAG_VEHICLE_SEAT | GROUP_UPDATE_FLAG_UNK) Powers powerType = player->GetPowerType(); data << uint32(mask1); // group update mask data << uint16(MEMBER_STATUS_ONLINE); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL // verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; uint16 iCoordZ = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); iCoordZ = player->GetPositionZ(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; iCoordZ = loc.coord_z; } else { // unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordZ); // GROUP_UPDATE_FLAG_POSITION data << uint8(1); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder, server sends 0xFFFFFFFFFFFFFFFF here, but with 1 above it seems no difference data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolder* holder = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) data << int32(aura->GetModifier()->m_amount); else data << int32(0); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->GetPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER data << uint8(1); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder, server sends 0xFFFFFFFFFFFFFFFF here, but with 1 above it seems no difference data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolder* holder = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) data << int32(aura->GetModifier()->m_amount); else data << int32(0); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint8(1); // GROUP_UPDATE_FLAG_PET_AURAS data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS data << uint32(0); // GROUP_UPDATE_FLAG_PET_AURAS } if (player->GetTransportInfo()) // GROUP_UPDATE_FLAG_VEHICLE_SEAT data << uint32(((Unit*)player->GetTransportInfo()->GetTransport())->GetVehicleInfo()->GetVehicleEntry()->m_seatID[player->GetTransportInfo()->GetTransportSeat()]); data << uint32(8); // GROUP_UPDATE_FLAG_PHASE data << uint32(0); // GROUP_UPDATE_FLAG_PHASE data << uint8(0); // GROUP_UPDATE_FLAG_PHASE SendPacket(&data); }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask == GROUP_UPDATE_FLAG_NONE) return; if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); data->append(player->GetPackGUID()); *data << (uint32) mask; if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player) { if (player->IsPvP()) *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << (uint16) MEMBER_STATUS_ONLINE; } else *data << (uint16) MEMBER_STATUS_OFFLINE; } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << (uint32) player->GetHealth(); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << (uint32) player->GetMaxHealth(); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << (uint8) powerType; if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << (uint16) player->GetPower(powerType); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << (uint16) player->GetMaxPower(powerType); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << (uint16) player->getLevel(); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << (uint16) player->GetZoneId(); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY(); if (mask & GROUP_UPDATE_FLAG_AURAS) { const uint64& auramask = player->GetAuraUpdateMaskForRaid(); *data << uint8(0); // if true client clears auras that are not covered by auramask // TODO: looks like now client requires all active auras to be in the beginning of the auramask // e.g. if you have holes in the aura mask the values after are ignored. *data << uint64(auramask); *data << uint32(64); // how many bits client reads from auramask for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const * aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } Pet *pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) { if (pet) *data << (uint64) pet->GetGUID(); else *data << (uint64) 0; } if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if (pet) *data << pet->GetName(); else *data << (uint8) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if (pet) *data << (uint16) pet->GetDisplayId(); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if (pet) *data << (uint32) pet->GetHealth(); else *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if (pet) *data << (uint32) pet->GetMaxHealth(); else *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if (pet) *data << (uint8) pet->getPowerType(); else *data << (uint8) 0; } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if (pet) *data << (uint16) pet->GetPower(pet->getPowerType()); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if (pet) *data << (uint16) pet->GetMaxPower(pet->getPowerType()); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { *data << uint8(0); // if true client clears auras that are not covered by auramask const uint64& auramask = pet->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); *data << uint32(64); // how many bits client reads from auramask for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const * aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } else *data << uint8(1) << (uint64) 0 << uint32(0); } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { if (player->GetVehicle()){ Vehicle* vv=player->GetVehicle(); *data << (uint32) vv->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]; } } if (mask & GROUP_UPDATE_FLAG_PHASE) // 4.0.6 unk { *data << (uint32) 0; *data << (uint32) 0; // string } }
void WorldSession::HandlePetAction(WorldPacket & recv_data) { uint64 guid1; uint16 spellid; uint16 flag; uint64 guid2; recv_data >> guid1; //pet guid recv_data >> spellid; recv_data >> flag; //delete = 0x0700 CastSpell = C100 recv_data >> guid2; //tag guid // used also for charmed creature Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2))); if (!pet) { sLog.outError("Pet %u not exist.", uint32(GUID_LOPART(guid1))); return; } if (pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) { sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName()); return; } if (!pet->isAlive()) return; if (pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) return; CharmInfo *charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } switch(flag) { case ACT_COMMAND: //0x0700 // Possessed or shared vision pets are only able to attack //if ((pet->isPossessed() || pet->HasAuraType(SPELL_AURA_BIND_SIGHT)) && spellid != COMMAND_ATTACK) // return; switch(spellid) { case COMMAND_STAY: //flat=1792 //STAY pet->AttackStop(); pet->InterruptNonMeleeSpells(false); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); charmInfo->SetIsCommandAttack(false); charmInfo->SetIsAtStay(true); charmInfo->SetIsFollowing(false); charmInfo->SetIsReturning(false); charmInfo->SaveStayPosition(); break; case COMMAND_FOLLOW: //spellid=1792 //FOLLOW pet->AttackStop(); pet->InterruptNonMeleeSpells(false); pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,pet->GetFollowAngle()); charmInfo->SetCommandState(COMMAND_FOLLOW); charmInfo->SetIsCommandAttack(false); charmInfo->SetIsAtStay(false); charmInfo->SetIsReturning(true); charmInfo->SetIsFollowing(false); break; case COMMAND_ATTACK: //spellid=1792 //ATTACK { // Can't attack if owner is pacified if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY)) { //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED); //TODO: Send proper error message to client return; } // only place where pet can be player Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); if (!TargetUnit) return; if (!pet->canAttack(TargetUnit)) return; // Not let attack through obstructions if (sWorld.getConfig(CONFIG_PET_LOS)) { if (!pet->IsWithinLOSInMap(TargetUnit)) return; } pet->clearUnitState(UNIT_STAT_FOLLOW); // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != TargetUnit || (pet->getVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) { if (pet->getVictim()) pet->AttackStop(); if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled) { charmInfo->SetIsCommandAttack(true); charmInfo->SetIsAtStay(false); charmInfo->SetIsFollowing(false); charmInfo->SetIsReturning(false); pet->ToCreature()->AI()->AttackStart(TargetUnit); //10% chance to play special pet attack talk, else growl if (pet->ToCreature()->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) pet->SendPetTalk((uint32)PET_TALK_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature pet->SendPetAIReaction(guid1); } } else // charmed player { if (pet->getVictim() && pet->getVictim() != TargetUnit) pet->AttackStop(); charmInfo->SetIsCommandAttack(true); charmInfo->SetIsAtStay(false); charmInfo->SetIsFollowing(false); charmInfo->SetIsReturning(false); pet->Attack(TargetUnit,true); pet->SendPetAIReaction(guid1); } } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) if (pet->ToCreature()->isPet()) { Pet* p = (Pet*)pet; if (p->getPetType() == HUNTER_PET) _player->RemovePet(p,PET_SAVE_AS_DELETED); else //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) p->setDeathState(CORPSE); } else // charmed or possessed _player->Uncharm(); break; default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid); } break; case ACT_REACTION: // 0x600 switch(spellid) { case REACT_PASSIVE: //passive pet->AttackStop(); case REACT_DEFENSIVE: //recovery case REACT_AGGRESSIVE: //activete if (pet->GetTypeId() == TYPEID_UNIT) pet->ToCreature()->SetReactState(ReactStates(spellid)); break; } break; case ACT_DISABLED: //0x8100 spell (disabled), ignore case ACT_CAST: //0x0100 case ACT_ENABLED: //0xc100 spell { Unit* unit_target = NULL; if (pet->ToCreature()->GetGlobalCooldown() > 0) return; if (guid2) unit_target = ObjectAccessor::GetUnit(*_player,guid2); // do not cast unknown spells SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } for (uint32 i = 0; i < 3;i++) { if (spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) return; } // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) return; // Clear the flags as if owner clicked 'attack'. AI will reset them // after AttackStart, even if spell failed if (pet->GetCharmInfo()) { pet->GetCharmInfo()->SetIsAtStay(false); pet->GetCharmInfo()->SetIsCommandAttack(true); pet->GetCharmInfo()->SetIsReturning(false); pet->GetCharmInfo()->SetIsFollowing(false); } Spell *spell = new Spell(pet, spellInfo, false); int16 result = spell->PetCanCast(unit_target); //auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed()) { pet->SetInFront(unit_target); if (unit_target->GetTypeId() == TYPEID_PLAYER) pet->SendUpdateToPlayer(unit_target->ToPlayer()); if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) pet->SendUpdateToPlayer(powner->ToPlayer()); result = -1; } if (result == -1) { pet->ToCreature()->AddCreatureSpellCooldown(spellid); if (pet->ToCreature()->isPet()) ((Pet*)pet)->CheckLearning(spellid); unit_target = spell->m_targets.getUnitTarget(); //10% chance to play special pet attack talk, else growl //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (pet->ToCreature()->isPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); } if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed()) { // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != unit_target) { if (pet->getVictim()) pet->AttackStop(); pet->GetMotionMaster()->Clear(); if (pet->ToCreature()->IsAIEnabled) pet->ToCreature()->AI()->AttackStart(unit_target); } } spell->prepare(&(spell->m_targets)); } else { if (pet->isPossessed()) { WorldPacket data(SMSG_CAST_FAILED, (4+1+1)); data << uint32(spellid) << uint8(2) << uint8(result); switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: data << uint32(spellInfo->RequiresSpellFocus); break; case SPELL_FAILED_REQUIRES_AREA: data << uint32(spellInfo->AreaId); break; } SendPacket(&data); } else pet->SendPetCastFail(spellid, result); if (!pet->ToCreature()->HasSpellCooldown(spellid)) pet->SendPetClearCooldown(spellid); spell->finish(false); delete spell; // reset specific flags in case of spell fail. AI will reset other flags if (pet->GetCharmInfo()) pet->GetCharmInfo()->SetIsCommandAttack(false); } break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid); } }
void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); ObjectGuid guid; uint32 spellid; recvPacket >> guid >> spellid; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, spellid %u", guid.GetString().c_str(), spellid); Creature* pet = _player->GetMap()->GetAnyTypeCreature(guid); if (!pet || (guid != _player->GetPetGuid() && guid != _player->GetCharmGuid())) { sLog.outError("HandlePetCastSpellOpcode: %s isn't pet of %s .", guid.GetString().c_str(), GetPlayer()->GetObjectGuid().GetString().c_str()); return; } SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; SpellCastTargets targets; recvPacket >> targets.ReadForCaster(pet); pet->clearUnitState(UNIT_STAT_MOVING); Spell *spell = new Spell(pet, spellInfo, false); spell->m_targets = targets; SpellCastResult result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); if (pet->IsPet()) { Pet* p = (Pet*)pet; p->CheckLearning(spellid); //10% chance to play special pet attack talk, else growl //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if(p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(); } spell->prepare(&(spell->m_targets)); } else { pet->SendPetCastFail(spellid, result); if (!pet->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; } }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint32 spellid; recvPacket >> guid >> spellid; // This opcode is also sent from charmed and possessed units (players and creatures) if (!_player->GetPet() && !_player->GetCharm()) return; Unit* caster = ObjectAccessor::GetUnit(*_player, guid); if (!caster || (caster != _player->GetPet() && caster != _player->GetCharm())) { sLog.outError("HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); return; } SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } // do not cast not learned spells if (!caster->HasSpell(spellid) || IsPassiveSpell(spellid)) return; if (spellInfo->StartRecoveryCategory > 0) //Check if spell is affected by GCD if (caster->GetTypeId() == TYPEID_UNIT && caster->ToCreature()->GetGlobalCooldown() > 0) { caster->SendPetCastFail(spellid, SPELL_FAILED_NOT_READY); return; } SpellCastTargets targets; recvPacket >> targets.ReadForCaster(caster); caster->clearUnitState(UNIT_STAT_FOLLOW); Spell *spell = new Spell(caster, spellInfo, spellid == 33395); // water elemental can cast freeze as triggered spell->m_targets = targets; int16 result = spell->PetCanCast(NULL); if (result == -1) { if (caster->GetTypeId() == TYPEID_UNIT) { Creature* pet = caster->ToCreature(); pet->AddCreatureSpellCooldown(spellid); if (pet->isPet()) { Pet* p = (Pet*)pet; p->CheckLearning(spellid); // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } } spell->prepare(&(spell->m_targets)); } else { caster->SendPetCastFail(spellid, result); if (caster->GetTypeId() == TYPEID_PLAYER) { if (!caster->ToPlayer()->HasSpellCooldown(spellid)) caster->SendPetClearCooldown(spellid); } else { if (!caster->ToCreature()->HasSpellCooldown(spellid)) caster->SendPetClearCooldown(spellid); } spell->finish(false); delete spell; } }
void WorldSession::HandlePetAction(WorldPacket& recv_data) { ObjectGuid petGuid; uint32 data; ObjectGuid targetGuid; recv_data >> petGuid; recv_data >> data; recv_data >> targetGuid; uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); // delete = 0x07 CastSpell = C1 DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str()); // used also for charmed creature/player Unit* pet = _player->GetMap()->GetUnit(petGuid); if (!pet) { sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str()); return; } if (GetPlayer()->GetObjectGuid() != pet->GetCharmerOrOwnerGuid()) { sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str()); return; } if (!pet->isAlive()) return; if (pet->GetTypeId() == TYPEID_PLAYER) { // controller player can only do melee attack if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) return; } else if (((Creature*)pet)->IsPet()) { // pet can have action bar disabled if (((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) return; } CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } switch (flag) { case ACT_COMMAND: // 0x07 switch (spellid) { case COMMAND_STAY: // flat=1792 // STAY pet->StopMoving(); pet->GetMotionMaster()->Clear(false); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); break; case COMMAND_FOLLOW: // spellid=1792 // FOLLOW pet->AttackStop(); pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); charmInfo->SetCommandState(COMMAND_FOLLOW); break; case COMMAND_ATTACK: // spellid=1792 // ATTACK { Unit* TargetUnit = _player->GetMap()->GetUnit(targetGuid); if (!TargetUnit) return; // not let attack friendly units. if (GetPlayer()->IsFriendlyTo(TargetUnit)) return; // Not let attack through obstructions if (!pet->IsWithinLOSInMap(TargetUnit)) return; // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != TargetUnit) { if (pet->getVictim()) pet->AttackStop(); if (pet->hasUnitState(UNIT_STAT_CONTROLLED)) { pet->Attack(TargetUnit, true); pet->SendPetAIReaction(); } else { pet->GetMotionMaster()->Clear(); if (((Creature*)pet)->AI()) ((Creature*)pet)->AI()->AttackStart(TargetUnit); // 10% chance to play special pet attack talk, else growl if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature pet->SendPetAIReaction(); } } } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) if (((Creature*)pet)->IsPet()) { Pet* p = (Pet*)pet; if (p->getPetType() == HUNTER_PET) p->Unsummon(PET_SAVE_AS_DELETED, _player); else // dismissing a summoned pet is like killing them (this prevents returning a soulshard...) p->SetDeathState(CORPSE); } else // charmed _player->Uncharm(); break; default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } break; case ACT_REACTION: // 0x6 switch (spellid) { case REACT_PASSIVE: // passive case REACT_DEFENSIVE: // recovery case REACT_AGGRESSIVE: // activete charmInfo->SetReactState(ReactStates(spellid)); break; } break; case ACT_DISABLED: // 0x81 spell (disabled), ignore case ACT_PASSIVE: // 0x01 case ACT_ENABLED: // 0xC1 spell { Unit* unit_target = nullptr; if (targetGuid) unit_target = _player->GetMap()->GetUnit(targetGuid); // do not cast unknown spells SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { if (spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) return; } // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; pet->clearUnitState(UNIT_STAT_MOVING); Spell* spell = new Spell(pet, spellInfo, false); SpellCastResult result = spell->CheckPetCast(unit_target); // auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { if (unit_target) { pet->SetInFront(unit_target); if (unit_target->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target); } else if (Unit* unit_target2 = spell->m_targets.getUnitTarget()) { pet->SetInFront(unit_target2); if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target2); } if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)powner); result = SPELL_CAST_OK; } if (result == SPELL_CAST_OK) { ((Creature*)pet)->AddCreatureSpellCooldown(spellid); if (((Creature*)pet)->IsPet()) ((Pet*)pet)->CheckLearning(spellid); unit_target = spell->m_targets.getUnitTarget(); // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (((Creature*)pet)->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else { pet->SendPetAIReaction(); } if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != unit_target) { if (pet->getVictim()) pet->AttackStop(); pet->GetMotionMaster()->Clear(); if (((Creature*)pet)->AI()) ((Creature*)pet)->AI()->AttackStart(unit_target); } } spell->prepare(&(spell->m_targets)); } else { if (pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); else { Unit* owner = pet->GetCharmerOrOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true); } if (!((Creature*)pet)->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; } break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } }
bool Player::UpdateStats(Stats stat) { if(stat > STAT_SPIRIT) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); SetStat(stat, int32(value)); if (stat == STAT_STAMINA || stat == STAT_INTELLECT || stat == STAT_STRENGTH) { Pet *pet = GetPet(); if(pet) pet->UpdateStats(stat); } switch(stat) { case STAT_STRENGTH: UpdateShieldBlockValue(); break; case STAT_AGILITY: UpdateArmor(); UpdateAllCritPercentages(); UpdateDodgePercentage(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); UpdateAllSpellCritChances(); UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently break; case STAT_SPIRIT: break; default: break; } if (stat == STAT_STRENGTH) { UpdateAttackPowerAndDamage(false); if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat)) UpdateAttackPowerAndDamage(true); } else if (stat == STAT_AGILITY) { UpdateAttackPowerAndDamage(false); UpdateAttackPowerAndDamage(true); } else { // Need update (exist AP from stat auras) if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT, stat)) UpdateAttackPowerAndDamage(false); if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat)) UpdateAttackPowerAndDamage(true); } UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat uint32 mask = 0; AuraEffectList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); for (AuraEffectList::const_iterator i = modRatingFromStat.begin(); i != modRatingFromStat.end(); ++i) if (Stats((*i)->GetMiscBValue()) == stat) mask |= (*i)->GetMiscValue(); if (mask) { for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) if (mask & (1 << rating)) ApplyRatingMod(CombatRating(rating), 0, true); } return true; }
void WorldSession::HandlePetRename(WorldPacket& recv_data) { DETAIL_LOG("HandlePetRename. CMSG_PET_RENAME"); ObjectGuid petGuid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petGuid; recv_data >> name; recv_data >> isdeclined; Pet* pet = _player->GetMap()->GetPet(petGuid); // check it! if (!pet || pet->getPetType() != HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGuid() != _player->GetObjectGuid() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, nullptr); return; } if (sObjectMgr.IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, nullptr); return; } pet->SetName(name); if (_player->GetGroup()) _player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } CharacterDatabase.BeginTransaction(); if (isdeclined) { for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.escape_string(name); CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(nullptr))); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); uint64 Guid; recvData >> Guid; Player* player = HashMapHolder<Player>::Find(Guid); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(Guid); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); Powers powerType = player->getPowerType(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS; if (powerType != POWER_MANA) updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE; if (pet) updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER; if (player->GetVehicle()) updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT; uint16 playerStatus = MEMBER_STATUS_ONLINE; if (player->IsPvP()) playerStatus |= MEMBER_STATUS_PVP; if (!player->IsAlive()) { if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) playerStatus |= MEMBER_STATUS_GHOST; else playerStatus |= MEMBER_STATUS_DEAD; } if (player->IsFFAPvP()) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) playerStatus |= MEMBER_STATUS_AFK; if (player->isDND()) playerStatus |= MEMBER_STATUS_DND; data << uint32(updateFlags); data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE) data << uint8(powerType); data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION uint64 auraMask = 0; size_t maskPos = data.wpos(); data << uint64(auraMask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = player->GetVisibleAura(i)) { auraMask |= uint64(1) << i; data << uint32(aurApp->GetBase()->GetId()); data << uint8(aurApp->GetFlags()); } } data.put<uint64>(maskPos, auraMask); // GROUP_UPDATE_FLAG_AURAS if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID) data << uint64(pet->GetGUID()); data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP) data << uint32(pet->GetHealth()); if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP) data << uint32(pet->GetMaxHealth()); if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE) data << (uint8)pet->getPowerType(); if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER) data << uint16(pet->GetPower(pet->getPowerType())); if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER) data << uint16(pet->GetMaxPower(pet->getPowerType())); uint64 petAuraMask = 0; maskPos = data.wpos(); data << uint64(petAuraMask); // placeholder if (pet) { for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = pet->GetVisibleAura(i)) { petAuraMask |= uint64(1) << i; data << uint32(aurApp->GetBase()->GetId()); data << uint8(aurApp->GetFlags()); } } } data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT) data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); SendPacket(&data); }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket *data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask == GROUP_UPDATE_FLAG_NONE) return; if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); data->append(player->GetPackGUID()); *data << (uint32) mask; if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player) { if (player->IsPvP()) *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << (uint16) MEMBER_STATUS_ONLINE; } else *data << (uint16) MEMBER_STATUS_OFFLINE; } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << (uint32) player->GetHealth(); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << (uint32) player->GetMaxHealth(); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << (uint8) powerType; if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << (uint16) player->GetPower(powerType); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << (uint16) player->GetMaxPower(powerType); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << (uint16) player->getLevel(); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << (uint16) player->GetZoneId(); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY(); if (mask & GROUP_UPDATE_FLAG_AURAS) { const uint64& auramask = player->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const* aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } Pet *pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) { if (pet) *data << (uint64) pet->GetGUID(); else *data << (uint64) 0; } if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if (pet) *data << pet->GetName(); else *data << (uint8) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if (pet) *data << (uint16) pet->GetDisplayId(); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if (pet) *data << (uint32) pet->GetHealth(); else *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if (pet) *data << (uint32) pet->GetMaxHealth(); else *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if (pet) *data << (uint8) pet->getPowerType(); else *data << (uint8) 0; } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if (pet) *data << (uint16) pet->GetPower(pet->getPowerType()); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if (pet) *data << (uint16) pet->GetMaxPower(pet->getPowerType()); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { if (player->GetVehicle()){ Vehicle* vv=player->GetVehicle(); *data << (uint32) vv->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]; } } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { const uint64& auramask = pet->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const* aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } else *data << (uint64) 0; } }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { sLog->outDetail("WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint8 castCount; uint32 spellId; uint8 castFlags; recvPacket >> guid >> castCount >> spellId >> castFlags; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_CAST_SPELL, guid: " UI64FMTD ", castCount: %u, spellId %u, castFlags %u", guid, castCount, spellId, castFlags); // This opcode is also sent from charmed and possessed units (players and creatures) if (!_player->GetGuardianPet() && !_player->GetCharm()) return; Unit* caster = ObjectAccessor::GetUnit(*_player, guid); if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) { sLog->outError("HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); return; } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { sLog->outError("WORLD: unknown PET spell id %i", spellId); return; } switch(spellId) { case 64077: { _player->CastSpell(caster, spellId, true); return; } } if (spellInfo->StartRecoveryCategory > 0) // Check if spell is affected by GCD if (caster->GetTypeId() == TYPEID_UNIT && caster->GetCharmInfo() && caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) { caster->SendPetCastFail(spellId, SPELL_FAILED_NOT_READY); return; } // do not cast not learned spells if (!caster->HasSpell(spellId) || spellInfo->IsPassive()) return; SpellCastTargets targets; targets.Read(recvPacket, caster); HandleClientCastFlags(recvPacket, castFlags, targets); caster->ClearUnitState(UNIT_STAT_FOLLOW); Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE); spell->m_cast_count = castCount; // probably pending spell cast spell->m_targets = targets; // TODO: need to check victim? SpellCastResult result; if (caster->m_movedPlayer) result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit()); else result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { if (caster->GetTypeId() == TYPEID_UNIT) { Creature* pet = caster->ToCreature(); pet->AddCreatureSpellCooldown(spellId); if (pet->isPet()) { Pet* p = (Pet*)pet; // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } } spell->prepare(&(spell->m_targets)); } else { caster->SendPetCastFail(spellId, result); if (caster->GetTypeId() == TYPEID_PLAYER) { if (!caster->ToPlayer()->HasSpellCooldown(spellId)) GetPlayer()->SendClearCooldown(spellId, caster); } else { if (!caster->ToCreature()->HasSpellCooldown(spellId)) GetPlayer()->SendClearCooldown(spellId, caster); } spell->finish(false); delete spell; } }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player* player = ObjectAccessor::FindPlayer(guid, false); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3 + 4 + 2); data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint8(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8); data << player->GetPackGUID(); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if (pet) mask1 = 0x7FFFFFFF; // for hunters and other classes with pets Powers powerType = player->getPowerType(); data << uint32(mask1); // group update mask data << uint8(MEMBER_STATUS_ONLINE); // member's online status data << uint16(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint16(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL // verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; } else { // unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION uint32 auramask = 0; size_t maskPos = data.wpos(); data << uint32(auramask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (uint32 aura = player->GetUInt32Value(UNIT_FIELD_AURA + i)) { auramask |= (uint32(1) << i); data << uint16(aura); } } data.put<uint32>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->getPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint16(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint16(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint32 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint32(petauramask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (uint32 petaura = pet->GetUInt32Value(UNIT_FIELD_AURA + i)) { petauramask |= (uint32(1) << i); data << uint16(petaura); } } data.put<uint32>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint32(0); // GROUP_UPDATE_FLAG_PET_AURAS } SendPacket(&data); }