void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber) { Creature* pet = _player->GetMap()->GetAnyTypeCreature(petguid); if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) { WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+1+4+1)); data << uint32(petnumber); data << uint8(0); data << uint32(0); data << uint8(0); _player->GetSession()->SendPacket(&data); return; } std::string name = pet->GetName(); WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); data << uint32(petnumber); data << name.c_str(); data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); if( pet->IsPet() && ((Pet*)pet)->GetDeclinedNames() ) { data << uint8(1); for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data << ((Pet*)pet)->GetDeclinedNames()->name[i]; } else data << uint8(0); _player->GetSession()->SendPacket(&data); }
void WorldSession::SendPetNameQuery(ObjectGuid petguid, uint32 petnumber) { Creature* pet = _player->GetMap()->GetAnyTypeCreature(petguid); if (!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) return; char const* name = pet->GetName(); // creature pets have localization like other creatures if (!pet->GetOwnerGuid().IsPlayer()) { int loc_idx = GetSessionDbLocaleIndex(); sObjectMgr.GetCreatureLocaleStrings(pet->GetEntry(), loc_idx, &name); } WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4 + 4 + strlen(name) + 1)); data << uint32(petnumber); data << name; data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); if (pet->IsPet() && ((Pet*)pet)->GetDeclinedNames()) { data << uint8(1); for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data << ((Pet*)pet)->GetDeclinedNames()->name[i]; } else data << uint8(0); _player->GetSession()->SendPacket(&data); }
void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) { DETAIL_LOG("CMSG_PET_SPELL_AUTOCAST"); ObjectGuid guid; uint32 spellid; uint8 state; //1 for on, 0 for off recvPacket >> guid >> spellid >> state; Creature* pet = _player->GetMap()->GetAnyTypeCreature(guid); if (!pet || (guid != _player->GetPetGuid() && guid != _player->GetCharmGuid())) { sLog.outError("HandlePetSpellAutocastOpcode. %s isn't pet of %s .", guid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str()); return; } // do not add not learned spells/ passive spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) return; CharmInfo *charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: %s is considered pet-like but doesn't have a charminfo!", guid.GetString().c_str()); return; } if (pet->isCharmed()) //state can be used as boolean pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); else ((Pet*)pet)->ToggleAutocast(spellid, state); charmInfo->SetSpellAutocast(spellid,state); }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); ObjectGuid guid; uint32 spellid; uint8 cast_count; uint8 unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> unk_flags; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, unk_flags %u", guid.GetString().c_str(), cast_count, spellid, unk_flags); Creature* pet = GetPlayer()->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()->GetGuidStr().c_str()); return; } SpellCastTargets targets; recvPacket >> targets.ReadForCaster(pet); // some spell cast packet including more data (for projectiles?) if (unk_flags & 0x02) targets.ReadAdditionalData(recvPacket); 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; bool triggered = bool(pet->GetTriggeredByClientAura(spellid)); // do not cast not learned spells if ((!pet->HasSpell(spellid) && !triggered) || IsPassiveSpell(spellInfo)) return; if (pet->IsNonMeleeSpellCasted(false) && !triggered) pet->InterruptNonMeleeSpells(false); if (pet->IsPet() || pet->isCharmed()) GetPlayer()->CallForAllControlledUnits(DoPetCastWithHelper(GetPlayer(), cast_count, &targets, spellInfo ),CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_CHARM); }
void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber) { Creature* pet = _player->GetMap()->GetCreatureOrPet(petguid); if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) return; std::string name = pet->GetName(); WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); data << uint32(petnumber); data << name.c_str(); data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); _player->GetSession()->SendPacket(&data); }
void WorldSession::SendPetNameQuery(ObjectGuid petguid, uint32 petnumber) const { Creature* pet = _player->GetMap()->GetAnyTypeCreature(petguid); // When replying to a query, verify input against public field info only (where it comes from) if (!pet || !pet->GetCharmInfo() || (pet->GetUInt32Value(UNIT_FIELD_PETNUMBER) && pet->GetUInt32Value(UNIT_FIELD_PETNUMBER) != petnumber)) { WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4 + 1 + 4 + 1)); data << uint32(petnumber); data << uint8(0); data << uint32(0); data << uint8(0); _player->GetSession()->SendPacket(data); return; } char const* name = pet->GetName(); // creature pets have localization like other creatures if (!pet->GetOwnerGuid().IsPlayer()) { int loc_idx = GetSessionDbLocaleIndex(); sObjectMgr.GetCreatureLocaleStrings(pet->GetEntry(), loc_idx, &name); } WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4 + 4 + strlen(name) + 1)); data << uint32(petnumber); data << name; data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); _player->GetSession()->SendPacket(data); }
void CreatePet() { pet = master->GetBotsPet(60238); if(pet == NULL) return; pet->UpdateCharmAI(); pet->setFaction(m_creature->getFaction()); pet->SetReactState(REACT_DEFENSIVE); pet->GetMotionMaster()->MoveFollow(m_creature, PET_FOLLOW_DIST*urand(1, 2),PET_FOLLOW_ANGLE); CharmInfo *charmInfonewbot = pet->InitCharmInfo(); pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); pet->UpdateStats(STAT_STRENGTH); pet->UpdateStats(STAT_AGILITY); pet->SetLevel(master->getLevel()); float val2 = master->getLevel()*4.0f + pet->GetStat(STAT_STRENGTH)*2.0f; val2=100.0; uint32 attPowerMultiplier=1; pet->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, uint32(val2)); pet->UpdateAttackPowerAndDamage(); pet->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, uint32(val2 * attPowerMultiplier)); pet->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, uint32(val2 * attPowerMultiplier)*2+master->getLevel()); pet->UpdateDamagePhysical(BASE_ATTACK); }
void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) { TC_LOG_DEBUG("network.opcode", "WORLD: Received CMSG_PET_SPELL_AUTOCAST"); ObjectGuid guid; uint32 spellid; uint8 state; //1 for on, 0 for off recvPacket >> guid >> spellid >> state; if (!_player->GetGuardianPet() && !_player->GetCharm()) return; if (guid.IsPlayer()) return; Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) { TC_LOG_ERROR("entities.pet", "HandlePetSpellAutocastOpcode. %s isn't pet of player %s (%s).", guid.ToString().c_str(), GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str()); return; } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) { TC_LOG_ERROR("spells.pet", "WORLD: unknown PET spell id %u", spellid); return; } // do not add not learned spells/ passive spells if (!pet->HasSpell(spellid) || !spellInfo->IsAutocastable()) return; CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { TC_LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUID().GetCounter(), pet->GetTypeId()); return; } if (pet->IsPet()) ((Pet*)pet)->ToggleAutocast(spellInfo, state != 0); else pet->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, state != 0); charmInfo->SetSpellAutocast(spellInfo, state != 0); }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); ObjectGuid guid; uint32 spellid; uint8 cast_count; uint8 unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> unk_flags; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, unk_flags %u", guid.GetString().c_str(), cast_count, spellid, unk_flags); Creature* pet = GetPlayer()->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()->GetGuidStr().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 = new SpellCastTargets; recvPacket >> targets->ReadForCaster(pet); if (pet->IsPet() || pet->isCharmed()) GetPlayer()->CallForAllControlledUnits(DoPetCastWithHelper(GetPlayer(), cast_count, targets, spellInfo ),CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_CHARM); if (targets) delete targets; }
void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) { sLog.outDetail("CMSG_PET_SPELL_AUTOCAST"); uint64 guid; uint16 spellid; uint16 spellid2; //maybe second spell, automatically toggled off when first toggled on? uint8 state; //1 for on, 0 for off recvPacket >> guid >> spellid >> spellid2 >> state; if (!_player->GetGuardianPet() && !_player->GetCharm()) return; if (ObjectAccessor::FindPlayer(guid)) return; Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, guid); if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) { sLog.outError("HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); return; } // do not add not learned spells/ passive spells if (!pet->HasSpell(spellid) || !IsAutocastableSpell(spellid)) return; CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } if (pet->IsPet()) ((Pet*)pet)->ToggleAutocast(spellid, state); else pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); for (uint8 i = 0; i < 10; ++i) { if ((charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) && spellid == charmInfo->GetActionBarEntry(i)->SpellOrAction) charmInfo->GetActionBarEntry(i)->Type = state ? ACT_ENABLED : ACT_DISABLED; } }
void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint32 spellid; uint8 cast_count; uint8 unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> unk_flags; sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags); if (!_player->GetPet() && !_player->GetCharm()) return; Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid); if (!pet || (pet != _player->GetPet() && pet!= _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; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; SpellCastTargets targets; if (!targets.read(&recvPacket,pet)) return; pet->DoPetCastSpell(GetPlayer(), cast_count, targets, spellInfo ); }
void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) { sLog->outDetail("CMSG_PET_SPELL_AUTOCAST"); uint64 guid; uint32 spellid; uint8 state; //1 for on, 0 for off recvPacket >> guid >> spellid >> state; if (!_player->GetGuardianPet() && !_player->GetCharm()) return; if (ObjectAccessor::FindPlayer(guid)) return; Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) { sLog->outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); return; } // do not add not learned spells/ passive spells if (!pet->HasSpell(spellid) || IsAutocastableSpell(spellid)) return; CharmInfo *charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog->outError( "WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } if (pet->isPet()) ((Pet*) pet)->ToggleAutocast(spellid, state); else pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); charmInfo->SetSpellAutocast(spellid, state); }
void WorldSession::SendPetNameQuery(ObjectGuid petguid, uint32 petnumber) { Creature* pet = _player->GetMap()->GetAnyTypeCreature(petguid); if (!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) { return; } char const* name = pet->GetName(); // creature pets have localization like other creatures if (!pet->GetOwnerGuid().IsPlayer()) { int loc_idx = GetSessionDbLocaleIndex(); sObjectMgr.GetCreatureLocaleStrings(pet->GetEntry(), loc_idx, &name); } WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4 + 4 + strlen(name) + 1)); data << uint32(petnumber); data << name; data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); _player->GetSession()->SendPacket(&data); }
void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) { DETAIL_LOG("CMSG_PET_SPELL_AUTOCAST"); uint64 guid; uint32 spellid; uint8 state; //1 for on, 0 for off recvPacket >> guid >> spellid >> state; if(!_player->GetPet() && !_player->GetCharm()) return; Creature* pet = _player->GetMap()->GetAnyTypeCreature(guid); if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } // do not add not learned spells/ passive spells if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) return; CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } if(pet->isCharmed()) //state can be used as boolean pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); else ((Pet*)pet)->ToggleAutocast(spellid, state); charmInfo->SetSpellAutocast(spellid,state); }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); ObjectGuid guid; uint32 spellid; uint8 cast_count; uint8 unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> unk_flags; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, unk_flags %u", guid.GetString().c_str(), cast_count, spellid, unk_flags); 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()->GetGuidStr().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_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; SpellCastResult result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); if (pet->IsPet()) { // 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*)pet)->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::HandlePetSetAction( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+4+2+2); sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION\n" ); uint64 petguid; uint32 position; uint16 spell_id; uint16 act_state; uint8 count; recv_data >> petguid; // FIXME: charmed case //Pet* pet = ObjectAccessor::Instance().GetPet(petguid); if(ObjectAccessor::FindPlayer(petguid)) return; Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid); if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { sLog.outError( "HandlePetSetAction: Unknown pet or pet owner.\n" ); return; } CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetSetAction: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); return; } count = (recv_data.size() == 24) ? 2 : 1; for(uint8 i = 0; i < count; i++) { recv_data >> position; recv_data >> spell_id; recv_data >> act_state; sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) { if(pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, true); else ((Pet*)pet)->ToggleAutocast(spell_id, true); } //sign for no/turn off autocast else if(act_state == ACT_DISABLED && spell_id) { if(pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, false); else ((Pet*)pet)->ToggleAutocast(spell_id, false); } charmInfo->GetActionBarEntry(position)->Type = act_state; charmInfo->GetActionBarEntry(position)->SpellOrAction = spell_id; } } }
void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); recvPacket.hexlike(); recvPacket.print_storage(); //2 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 42 - 211 - 253 - 0 | - 0 | - 2 |- 96 - 0 - 0 - 0 | - 0 - 26 //- 164 - 59 - 196 - 174 - 98 - 131 | - 194 - 182 - 171 - 218| - 67 - 0 - 48 - 93| - 0 - 196 - 32 //- 177| - 242 - 193 - 22 - 110 - 224 - 67 - 203 - 166 | - 68 - 61 - 133 - 1| - 240 - 66 - 1 - 183 | //- 0 - 0 - 0 - 217| - 2 - 43 - 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 76 - 109 - 175 - 0 //- 238 - 115 - 58 - 196 - 20 - 110 - 121 - 194 - 187 - 107 - 217 - 67 - 32 - 44 - 27 - 62 - 217 //- 1 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 192 - 233 //- 172 - 62 - 4 - 0 - 0 - 0 - 7 - 230 - 0 - 0 - 0 - //5 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 85 - 211 - 253 - 0 | - 0 | - 2 | - 96 - 0 - 0 - 0 | - 0 - 69 - 60 - 61 //- 196 - 171 - 248 - 107| - 194 - 8 - 236 - 218 | - 67 - 0 - 177 - 11 | - 46 - 196 - 89 - 16 | - 14 - 195 //- 5 - 38 - 231 - 67 - 23 - 221 | - 110 - 62 - 15 - 3 | - 240 - 66 -| 1 - 183 | - 0 - 0 - 0 - 217 | - 5 - 43 //- 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 233 - 41 - 203 - 0 - 106 - 207 - 59 - 196 - 179 - 173 - 83 //- 194 - 8 - 108 - 217 - 67 - 127 - 153 - 170 - 64 - 217 - 4 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 //- 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 7 - 77 - 175 - 64 - 4 - 0 - 0 - 0 - 7 - 195 - 0 - 0 - 0 - uint64 guid; uint32 spellid; uint8 cast_count; uint8 unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> unk_flags; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags); if (!_player->GetPet() && !_player->GetCharm()) return; if (GUID_HIPART(guid) == HIGHGUID_PLAYER) return; Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); if (!pet || (pet != _player->GetPet() && pet!= _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; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; // Interrupt previous spell pet->InterruptNonMeleeSpells(true); SpellCastTargets targets; //float elevation, speed; //uint8 pos1, pos2; recvPacket >> targets.ReadForCaster(pet); //recvPacket >> elevation >> speed; //recvPacket >> pos1 >> pos2; //mask: 96, elevation: 0.167906, speed: 120.002441, pos1: 1, pos: 183 //sLog.outDebug("mask: %u, elevation: %f, speed: %f, pos1: %u, pos: %u", targets.m_targetMask, elevation, speed, pos1, pos2); sLog.outDebug("guid: %u, sX: %f, sY:%f, sZ: %f", targets.getUnitTargetGUID(),targets.m_src.x,targets.m_src.y,targets.m_src.z); sLog.outDebug("guid: %u, sX: %f, sY:%f, sZ: %f", targets.getUnitTargetGUID(),targets.m_dest.x,targets.m_dest.y,targets.m_dest.z); pet->DoPetCastSpell( GetPlayer(), cast_count, targets, spellInfo ); }
void WorldSession::SendPetNameQuery( ObjectGuid petguid, uint32 petnumber) { //Client asks for data before add to map (or we have wrong teleport sequence), so we cant use GetCreatureOrPetOrVehicle() Creature* pet = NULL; if(_player->IsBeingTeleported()) { Map *map = sMapMgr.FindMap(_player->GetTeleportDest().mapid); if(map) { if (petguid.IsPet()) pet = map->GetPet(petguid); else if(petguid.IsVehicle()) pet = (Creature*)map->GetVehicle(petguid); else pet = map->GetCreature(petguid); } } else pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); if (!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) { std::string name = "NoPetName"; WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); data << uint32(petnumber); data << name.c_str(); data << uint32(time(0)); data << uint8(0); _player->GetSession()->SendPacket(&data); // looking for errors /* if (!pet) sLog.outError("SendPetNameQuery:: Pet not found, not exist or not in world"); <------- else if (!pet->GetCharmInfo()) sLog.outError("SendPetNameQuery:: Pet CharmInfo() not found"); else if (pet->GetCharmInfo()->GetPetNumber() != petnumber) sLog.outError("SendPetNameQuery:: Pet number is not equal to requested petnumber"); */ return; } std::string name = pet->GetName(); WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); data << uint32(petnumber); data << name.c_str(); data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); if ( pet->isPet() && ((Pet*)pet)->GetDeclinedNames() ) { data << uint8(1); for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data << ((Pet*)pet)->GetDeclinedNames()->name[i]; } else data << uint8(0); _player->GetSession()->SendPacket(&data); }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); ObjectGuid guid; uint32 spellid; uint8 cast_count; uint8 cast_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> cast_flags; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, cast_flags %u", guid.GetString().c_str(), cast_count, spellid, cast_flags); 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(), _player->GetGuidStr().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; Aura* triggeredByAura = pet->GetTriggeredByClientAura(spellid); // do not cast not learned spells if ((!triggeredByAura && !pet->HasSpell(spellid)) || IsPassiveSpell(spellInfo)) return; SpellCastTargets targets; recvPacket >> targets.ReadForCaster(pet); targets.ReadAdditionalData(recvPacket, cast_flags); pet->clearUnitState(UNIT_STAT_MOVING); Spell* spell = new Spell(pet, spellInfo, triggeredByAura ? true : false, pet->GetObjectGuid(), triggeredByAura ? triggeredByAura->GetSpellProto() : nullptr); spell->m_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; SpellCastResult result = triggeredByAura ? SPELL_CAST_OK : spell->CheckPetCast(nullptr); if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); spell->SpellStart(&(spell->m_targets), triggeredByAura); } else { Unit* owner = pet->GetCharmerOrOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER && !triggeredByAura) Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true); if (!pet->HasSpellCooldown(spellid) && !triggeredByAura) GetPlayer()->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; } }
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()->GetGuidStr().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(nullptr); if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); if (pet->IsPet()) ((Pet*)pet)->CheckLearning(spellid); spell->SpellStart(&(spell->m_targets)); } else { Unit* owner = pet->GetCharmerOrOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true); if (!pet->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; } }
void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) { DETAIL_LOG( "HandlePetSetAction. CMSG_PET_SET_ACTION" ); uint64 petguid; uint8 count; recv_data >> petguid; // FIXME: charmed case //Pet* pet = ObjectAccessor::Instance().GetPet(petguid); if(ObjectAccessor::FindPlayer(petguid)) return; Creature* pet = _player->GetMap()->GetAnyTypeCreature(petguid); if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { sLog.outError( "HandlePetSetAction: Unknown pet or pet owner." ); return; } // pet can have action bar disabled if(pet->IsPet() && ((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) return; CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } count = (recv_data.size() == 24) ? 2 : 1; uint32 position[2]; uint32 data[2]; bool move_command = false; for(uint8 i = 0; i < count; ++i) { recv_data >> position[i]; recv_data >> data[i]; uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); //ignore invalid position if(position[i] >= MAX_UNIT_ACTION_BAR_INDEX) return; // in the normal case, command and reaction buttons can only be moved, not removed // at moving count ==2, at removing count == 1 // ignore attempt to remove command|reaction buttons (not possible at normal case) if (act_state == ACT_COMMAND || act_state == ACT_REACTION) { if (count == 1) return; move_command = true; } } // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) if (move_command) { uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); if(act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) { uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || act_state_0 != actionEntry_1->GetType()) return; } uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); if(act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) { uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || act_state_1 != actionEntry_0->GetType()) return; } } for(uint8 i = 0; i < count; ++i) { uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); DETAIL_LOG( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state)); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) { if(pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, true); else ((Pet*)pet)->ToggleAutocast(spell_id, true); } //sign for no/turn off autocast else if(act_state == ACT_DISABLED && spell_id) { if(pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, false); else ((Pet*)pet)->ToggleAutocast(spell_id, false); } charmInfo->SetActionBar(position[i],spell_id,ActiveStates(act_state)); } } }
void WorldSession::HandlePetSetAction(WorldPacket& recv_data) { DETAIL_LOG("HandlePetSetAction. CMSG_PET_SET_ACTION"); ObjectGuid petGuid; uint8 count; recv_data >> petGuid; Creature* pet = _player->GetMap()->GetAnyTypeCreature(petGuid); if (!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { sLog.outError("HandlePetSetAction: Unknown pet or pet owner."); return; } CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } // pet can have action bar disabled if (pet->IsPet() && charmInfo->HasState(CHARM_STATE_ACTION,ACTIONS_DISABLE)) return; // if pet is chained - used first pet action bar if (((Pet*)pet)->GetPetCounter()) return; count = (recv_data.size() == 24) ? 2 : 1; uint32 position[2]; uint32 data[2]; bool move_command = false; for (uint8 i = 0; i < count; ++i) { recv_data >> position[i]; recv_data >> data[i]; uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); // ignore invalid position if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX) return; // in the normal case, command and reaction buttons can only be moved, not removed // at moving count ==2, at removing count == 1 // ignore attempt to remove command|reaction buttons (not possible at normal case) if (act_state == ACT_COMMAND || act_state == ACT_REACTION) { if (count == 1) return; move_command = true; } } // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) if (move_command) { uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) { uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || act_state_0 != actionEntry_1->GetType()) return; } uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) { uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || act_state_1 != actionEntry_0->GetType()) return; } } for (uint8 i = 0; i < count; ++i) { uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); DETAIL_LOG("Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state)); // if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if ((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && ((Pet*)pet)->HasSpell(spell_id)) { // sign for autocast on/off if (act_state == ACT_ENABLED || act_state == ACT_DISABLED) { bool enabled = act_state == ACT_ENABLED; if (pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, enabled); else { GuidSet const& groupPets = _player->GetPets(); if (!groupPets.empty()) { for (GuidSet::const_iterator itr = groupPets.begin(); itr != groupPets.end(); ++itr) { if (Pet* pPet = GetPlayer()->GetMap()->GetPet(*itr)) { if (pPet->IsInWorld()) pPet->ToggleAutocast(spell_id, enabled); } } } } } charmInfo->SetActionBar(position[i], spell_id, ActiveStates(act_state)); } } }
void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); recvPacket.hexlike(); recvPacket.print_storage(); //2 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 42 - 211 - 253 - 0 | - 0 | - 2 |- 96 - 0 - 0 - 0 | - 0 - 26 //- 164 - 59 - 196 - 174 - 98 - 131 | - 194 - 182 - 171 - 218| - 67 - 0 - 48 - 93| - 0 - 196 - 32 //- 177| - 242 - 193 - 22 - 110 - 224 - 67 - 203 - 166 | - 68 - 61 - 133 - 1| - 240 - 66 - 1 - 183 | //- 0 - 0 - 0 - 217| - 2 - 43 - 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 76 - 109 - 175 - 0 //- 238 - 115 - 58 - 196 - 20 - 110 - 121 - 194 - 187 - 107 - 217 - 67 - 32 - 44 - 27 - 62 - 217 //- 1 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 192 - 233 //- 172 - 62 - 4 - 0 - 0 - 0 - 7 - 230 - 0 - 0 - 0 - //5 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 85 - 211 - 253 - 0 | - 0 | - 2 | - 96 - 0 - 0 - 0 | - 0 - 69 - 60 - 61 //- 196 - 171 - 248 - 107| - 194 - 8 - 236 - 218 | - 67 - 0 - 177 - 11 | - 46 - 196 - 89 - 16 | - 14 - 195 //- 5 - 38 - 231 - 67 - 23 - 221 | - 110 - 62 - 15 - 3 | - 240 - 66 -| 1 - 183 | - 0 - 0 - 0 - 217 | - 5 - 43 //- 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 233 - 41 - 203 - 0 - 106 - 207 - 59 - 196 - 179 - 173 - 83 //- 194 - 8 - 108 - 217 - 67 - 127 - 153 - 170 - 64 - 217 - 4 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 //- 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 7 - 77 - 175 - 64 - 4 - 0 - 0 - 0 - 7 - 195 - 0 - 0 - 0 - ObjectGuid guid; uint32 spellid; uint8 cast_count; uint8 unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> guid >> cast_count >> spellid >> unk_flags; DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, unk_flags %u", guid.GetString().c_str(), cast_count, spellid, unk_flags); if (guid.IsPlayer()) return; 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()->GetGuidStr().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_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; SpellCastResult result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); if (pet->IsPet()) { //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*)pet)->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::HandlePetSetAction( WorldPacket & recv_data ) { sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION" ); uint64 petguid; uint8 count; recv_data >> petguid; Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(petguid); if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { sLog.outError( "HandlePetSetAction: Unknown pet or pet owner." ); return; } CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } count = (recv_data.size() == 24) ? 2 : 1; for(uint8 i = 0; i < count; ++i) { uint32 position; uint32 data; recv_data >> position; recv_data >> data; uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data); uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data); sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position, spell_id, uint32(act_state)); //ignore invalid position if(position >= MAX_UNIT_ACTION_BAR_INDEX) return; //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) { if(pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, true); else ((Pet*)pet)->ToggleAutocast(spell_id, true); } //sign for no/turn off autocast else if(act_state == ACT_DISABLED && spell_id) { if(pet->isCharmed()) charmInfo->ToggleCreatureAutocast(spell_id, false); else ((Pet*)pet)->ToggleAutocast(spell_id, false); } charmInfo->SetActionBar(position,spell_id,ActiveStates(act_state)); } } }