void WorldSession::HandlePetAbandon(WorldPacket& recvData) { ObjectGuid guid; recvData.ReadBitSeq<7, 0, 6, 3, 1, 2, 4, 5>(guid); recvData.ReadByteSeq<7, 4, 3, 0, 2, 6, 5, 1>(guid); TC_LOG_INFO("network", "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); if (!_player->IsInWorld()) return; // pet/charmed Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (pet) { if (pet->isPet()) { _player->RemovePet(PET_REMOVE_ABANDON); if (GetPlayer()->getClass() == CLASS_HUNTER) SendPetList(0, PET_SLOT_ACTIVE_FIRST, PET_SLOT_ACTIVE_LAST); } else if (pet->GetGUID() == _player->GetCharmGUID()) { _player->StopCastingCharm(); } } }
void WorldSession::HandlePetAbandon( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8); uint64 guid; recv_data >> guid; //pet guid sLog.outDetail( "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid) ); // pet/charmed Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, guid); if(pet) { if(pet->isPet()) { if(pet->GetGUID() == _player->GetPetGUID()) { uint32 feelty = pet->GetPower(POWER_HAPPINESS); pet->SetPower(POWER_HAPPINESS ,(feelty-50000) > 0 ?(feelty-50000) : 0); } _player->RemovePet((Pet*)pet,PET_SAVE_AS_DELETED); } else if(pet->GetGUID() == _player->GetCharmGUID()) { _player->Uncharm(); } } }
void WorldSession::HandlePetAbandon(WorldPacket & recv_data) { uint64 guid; recv_data >> guid; //pet guid sLog->outDetail("HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); if (!_player->IsInWorld()) return; // pet/charmed Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (pet) { if (pet->isPet()) { if (pet->GetGUID() == _player->GetPetGUID()) { uint32 feelty = pet->GetPower(POWER_HAPPINESS); pet->SetPower(POWER_HAPPINESS , (feelty-50000) > 0 ?(feelty-50000) : 0); } _player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); } else if (pet->GetGUID() == _player->GetCharmGUID()) _player->StopCastingCharm(); } }
void WorldSession::SendPetNameQuery(uint64 petguid, uint32 petnumber) { Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); if (!pet) { 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 (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data << ((Pet*)pet)->GetDeclinedNames()->name[i]; } else data << uint8(0); _player->GetSession()->SendPacket(&data); }
//npc phasemask handling //change phasemask of creature or pet static bool HandleNpcSetPhaseCommand (ChatHandler* handler, const char* args) { if (!*args) return false; uint32 phasemask = (uint32) atoi((char*) args); if (phasemask == 0) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } Creature* pCreature = handler->getSelectedCreature(); if (!pCreature) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } pCreature->SetPhaseMask(phasemask, true); if (!pCreature->isPet()) pCreature->SaveToDB(); return true; }
void ObjectGridRespawnMover::Visit(CreatureMapType &m) { // creature in unloading grid can have respawn point in another grid // if it will be unloaded then it will not respawn in original grid until unload/load original grid // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) { Creature * c = iter->getSource(); ++iter; ASSERT(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); Cell const& cur_cell = c->GetCurrentCell(); float resp_x, resp_y, resp_z; c->GetRespawnCoord(resp_x, resp_y, resp_z); CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); Cell resp_cell(resp_val); if (cur_cell.DiffGrid(resp_cell)) { c->GetMap()->CreatureRespawnRelocation(c); // false result ignored: will be unload with other creatures at grid } } }
//npc deathstate handling static bool HandleNpcSetDeathStateCommand (ChatHandler* handler, const char* args) { if (!*args) return false; Creature* pCreature = handler->getSelectedCreature(); if (!pCreature || pCreature->isPet()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } if (strncmp(args, "on", 3) == 0) pCreature->SetDeadByDefault(true); else if (strncmp(args, "off", 4) == 0) pCreature->SetDeadByDefault(false); else { handler->SendSysMessage(LANG_USE_BOL); handler->SetSentErrorMessage(true); return false; } pCreature->SaveToDB(); pCreature->Respawn(); return true; }
static bool HandleRemoveDualSpecCommand(ChatHandler* handler, const char* args) { std::string name; Player *player; char *TargetName = strtok((char*)args, " "); if (!TargetName) { player = handler->getSelectedPlayer(); if (player) { name = player->GetName(); normalizePlayerName(name); } } else { name = TargetName; normalizePlayerName(name); player = sObjectAccessor->FindPlayerByName(name.c_str()); } if (!player) { // Try reset talents as Hunter Pet Creature* creature = handler->getSelectedCreature(); if (creature && creature->isPet()) { Unit *owner = creature->GetOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)creature)->IsPermanentPetFor(owner->ToPlayer())) { ((Pet *)creature)->resetTalents(true); owner->ToPlayer()->SendTalentsInfoData(true); ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS); return true; } } } else { player->ActivateSpec(1); player->resetTalents(true); player->SendTalentsInfoData(false); player->ActivateSpec(0); player->CastSpell(player, SPELL_DUAL_SPEC, true); ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS); Pet* pet = player->GetPet(); Pet::resetTalentsForAllPetsOf(player, pet); if (pet) player->SendTalentsInfoData(true); return true; } handler->SendSysMessage(LANG_NO_CHAR_SELECTED); return false; }
static bool HandleResetTalentsCommand(ChatHandler* handler, char const* args) { Player* target; uint64 targetGuid; std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) { // Try reset talents as Hunter Pet Creature* creature = handler->getSelectedCreature(); if (!*args && creature && creature->isPet()) { Unit* owner = creature->GetOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER && creature->ToPet()->IsPermanentPetFor(owner->ToPlayer())) { creature->ToPet()->resetTalents(); owner->ToPlayer()->SendTalentsInfoData(true); ChatHandler(owner->ToPlayer()->GetSession()).SendSysMessage(LANG_RESET_PET_TALENTS); if (!handler->GetSession() || handler->GetSession()->GetPlayer() != owner->ToPlayer()) handler->PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE, handler->GetNameLink(owner->ToPlayer()).c_str()); } return true; } handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); return false; } if (target) { target->ResetTalents(true); target->SendTalentsInfoData(false); ChatHandler(target->GetSession()).SendSysMessage(LANG_RESET_TALENTS); if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target) handler->PSendSysMessage(LANG_RESET_TALENTS_ONLINE, handler->GetNameLink(target).c_str()); Pet* pet = target->GetPet(); Pet::resetTalentsForAllPetsOf(target, pet); if (pet) target->SendTalentsInfoData(true); return true; } else if (targetGuid) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->setUInt16(0, uint16(AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS)); stmt->setUInt32(1, GUID_LOPART(targetGuid)); CharacterDatabase.Execute(stmt); std::string nameLink = handler->playerLink(targetName); handler->PSendSysMessage(LANG_RESET_TALENTS_OFFLINE, nameLink.c_str()); return true; } handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); return false; }
void WorldSession::SendPetNameQuery(uint32 petnumber, uint64 petguid) { Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); if (!pet) { WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE); data << uint64(petnumber); data.WriteBit(0); data.FlushBits(); _player->GetSession()->SendPacket(&data); return; } std::string name = pet->GetName(); WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE); data << uint64(petnumber); data.WriteBit(pet->isPet() ? 1 : 0); if (Pet* playerPet = pet->ToPet()) { DeclinedName const* declinedNames = playerPet->GetDeclinedNames(); if (declinedNames) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data.WriteBits(declinedNames->name[i].size(), 7); } else { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data.WriteBits(0, 7); } data.WriteBit(0); // Unk bit data.WriteBits(name.size(), 8); data.FlushBits(); if (declinedNames) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) data.WriteString(declinedNames->name[i]); } data << uint32(playerPet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); data.WriteString(name); } else { data.FlushBits(); } _player->GetSession()->SendPacket(&data); }
void ObjectGridEvacuator::Visit(CreatureMapType &m) { // creature in unloading grid can have respawn point in another grid // if it will be unloaded then it will not respawn in original grid until unload/load original grid // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) { Creature* c = iter->getSource(); ++iter; ASSERT(!c->isPet() && "ObjectGridRespawnMover must not be called for pets"); c->GetMap()->CreatureRespawnRelocation(c, true); } }
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff) { if (creature.hasUnitState(UNIT_STAT_NOT_MOVE)) { i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); return true; } i_nextMoveTime.Update(diff); if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); if (!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.addUnitState(UNIT_STAT_ROAMING_MOVE); CreatureTraveller traveller(creature); if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true)) { if (!IsActive(creature)) // force stop processing (movement can move out active zone with cleanup movegens list) return true; // not expire now, but already lost if (i_nextMoveTime.Passed()) { float x,y,z; if(i_destinationHolder.HasDestination()) i_destinationHolder.GetLocationNowNoMicroMovement(x,y,z); else creature.GetPosition(x,y,z); if (creature.canFly() && !(creature.canWalk() && creature.IsAtGroundLevel(x,y,z))) creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7); else creature.AddSplineFlag(SPLINEFLAG_WALKMODE); _setRandomLocation(creature); } else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f)) { creature.AddSplineFlag(SPLINEFLAG_WALKMODE); _setRandomLocation(creature); } } return true; }
void Unit::DoPetCastSpell(Player* owner, uint8 cast_count, SpellCastTargets targets, const SpellEntry* spellInfo) { // chained if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) if (Pet *chainedPet = GetPet()) if (((Creature*)this)->GetEntry() == chainedPet->GetEntry()) chainedPet->DoPetCastSpell(owner, cast_count, targets, spellInfo); if(GetTypeId() != TYPEID_UNIT) return; Creature* pet = dynamic_cast<Creature*>(this); uint32 spellid = spellInfo->Id; 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(pet->GetGUID()); } spell->prepare(&(spell->m_targets)); } else { pet->SendPetCastFail(spellid, result); if (!pet->HasSpellCooldown(spellid)) owner->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; } }
static bool HandleNpcDeleteCommand(ChatHandler* handler, const char* args) { Creature* unit = NULL; if (*args) { // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r char* cId = handler->extractKeyFromLink((char*) args, "Hcreature"); if (!cId) return false; uint32 lowguid = atoi(cId); if (!lowguid) return false; if (CreatureData const* cr_data = sObjectMgr->GetCreatureData(lowguid)) unit = handler->GetSession()->GetPlayer()->GetMap()->GetCreature( MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); } else unit = handler->getSelectedCreature(); if (!unit || unit->isPet() || unit->isTotem()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } QueryResult result; result = WorldDatabase.PQuery("SELECT * FROM creature_spawn WHERE guid='%u' AND account='%u'", unit->GetGUIDLow(), handler->GetSession()->GetAccountId()); if (!result) { handler->PSendSysMessage(LANG_CREATURE_ACCOUNT); handler->SetSentErrorMessage(true); return false; } // Delete the creature unit->CombatStop(); unit->DeleteFromDB(); unit->AddObjectToRemoveList(); handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); sLog->outSQLDev("DELETE FROM creature WHERE guid = %u;", unit->GetGUIDLow()); return true; }
void WorldSession::HandlePetAbandon(WorldPacket& recvData) { uint64 guid; recvData >> guid; //pet guid sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); if (!_player->IsInWorld()) return; // pet/charmed Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (pet) { if (pet->isPet()) _player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); else if (pet->GetGUID() == _player->GetCharmGUID()) _player->StopCastingCharm(); } }
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); }
bool ChatHandler::HandleDeleteCommand(const char* args) { Creature *unit = getSelectedCreature(); if(!unit || unit->isPet() || unit->isTotem()) { SendSysMessage(LANG_SELECT_CREATURE); return true; } unit->CombatStop(true); unit->DeleteFromDB(); unit->CleanupCrossRefsBeforeDelete(); ObjectAccessor::Instance().AddObjectToRemoveList(unit); SendSysMessage("Creature Removed"); return true; }
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff) { if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) { i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer creature.clearUnitState(UNIT_STAT_ROAMING); return true; } i_nextMoveTime.Update(diff); if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) creature.clearUnitState(UNIT_STAT_ROAMING); if(!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.addUnitState(UNIT_STAT_ROAMING); CreatureTraveller traveller(creature); if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) ) { if(i_nextMoveTime.Passed()) { if (creature.canFly()) creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY); else if(irand(0,RUNNING_CHANCE_RANDOMMV) > 0) creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); else // run with 1/RUNNING_CHANCE_RANDOMMV chance creature.RemoveMonsterMoveFlag(MONSTER_MOVE_WALK); _setRandomLocation(creature); } else if(creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(),PET_FOLLOW_DIST+2.5f)) { creature.AddMonsterMoveFlag(MONSTER_MOVE_WALK); _setRandomLocation(creature); } } return true; }
bool ChatHandler::HandleDebugThreatList(const char * /*args*/) { Creature* target = getSelectedCreature(); if(!target || target->isTotem() || target->isPet()) return false; std::list<HostilReference*>& tlist = target->getThreatManager().getThreatList(); std::list<HostilReference*>::iterator itr; uint32 cnt = 0; PSendSysMessage("Threat list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); for(itr = tlist.begin(); itr != tlist.end(); ++itr) { Unit* unit = (*itr)->getTarget(); if(!unit) continue; ++cnt; PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), (*itr)->getThreat()); } SendSysMessage("End of threat list."); return true; }
//change level of creature or pet static bool HandleNpcSetLevelCommand(ChatHandler* handler, const char* args) { if (!*args) return false; uint8 lvl = (uint8) atoi((char*)args); if (lvl < 1 || lvl > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } Creature* pCreature = handler->getSelectedCreature(); if (!pCreature) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } if (pCreature->isPet()) { if (((Pet*)pCreature)->getPetType() == HUNTER_PET) { pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr->GetXPForLevel(lvl)/4); pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); } ((Pet*)pCreature)->GivePetLevel(lvl); } else { pCreature->SetMaxHealth(100 + 30*lvl); pCreature->SetHealth(100 + 30*lvl); pCreature->SetLevel(lvl); pCreature->SaveToDB(); } return true; }
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff) { if (creature.hasUnitState(UNIT_STAT_NOT_MOVE & ~UNIT_STAT_ON_VEHICLE)) { i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);; return true; } i_nextMoveTime.Update(diff); if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); if (!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.addUnitState(UNIT_STAT_ROAMING_MOVE); CreatureTraveller traveller(creature); if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true)) { if (i_nextMoveTime.Passed()) { if (creature.canFly()) creature.AddSplineFlag(SPLINEFLAG_UNKNOWN7); else creature.AddSplineFlag(SPLINEFLAG_WALKMODE); _setRandomLocation(creature); } else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f)) { creature.AddSplineFlag(SPLINEFLAG_WALKMODE); _setRandomLocation(creature); } } return true; }
//set model of creature static bool HandleNpcSetModelCommand(ChatHandler* handler, const char* args) { if (!*args) return false; uint32 displayId = (uint32) atoi((char*) args); Creature *pCreature = handler->getSelectedCreature(); if (!pCreature || pCreature->isPet()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } pCreature->SetDisplayId(displayId); pCreature->SetNativeDisplayId(displayId); pCreature->SaveToDB(); return true; }
bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff) { if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) { i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer creature.clearUnitState(UNIT_STAT_ROAMING); return true; } i_nextMoveTime.Update(diff); if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) creature.clearUnitState(UNIT_STAT_ROAMING); if(!i_destinationHolder.HasArrived() && creature.IsStopped()) creature.addUnitState(UNIT_STAT_ROAMING); CreatureTraveller traveller(creature); if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) ) { if(i_nextMoveTime.Passed()) { if (creature.canFly()) creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2); else creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE); _setRandomLocation(creature); } else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f) { creature.SetUnitMovementFlags(MOVEMENTFLAG_NONE); _setRandomLocation(creature); } } return true; }
static bool HandleNpcDeleteCommand(ChatHandler* handler, const char* args) { Creature* unit = NULL; if (*args) { // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r char* cId = handler->extractKeyFromLink((char*)args,"Hcreature"); if (!cId) return false; uint32 lowguid = atoi(cId); if (!lowguid) return false; if (CreatureData const* cr_data = sObjectMgr->GetCreatureData(lowguid)) unit = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); } else unit = handler->getSelectedCreature(); if (!unit || unit->isPet() || unit->isTotem()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } // Delete the creature unit->CombatStop(); unit->DeleteFromDB(); unit->AddObjectToRemoveList(); handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); return true; }
void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber) { Creature* pet = _player->GetMap()->GetAnyTypeCreature(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)); 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); }
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->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()->AddToMap(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::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; } 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_STATE_FOLLOW); Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE); spell->_cast_count = castCount; // probably pending spell cast spell->m_targets = targets; // TODO: need to check victim? SpellCastResult result; if (caster->_movedPlayer) result = spell->CheckPetCast(caster->_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; } }
void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); CHECK_PACKET_SIZE(recvPacket,8+4); 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 .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if(!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i\n", 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 && ((Creature*)caster)->GetGlobalCooldown() > 0) { caster->SendPetCastFail(spellid, SPELL_FAILED_NOT_READY); return; } SpellCastTargets targets; if(!targets.read(&recvPacket,caster)) return; 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 = (Creature*)caster; 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(!((Player*)caster)->HasSpellCooldown(spellid)) caster->SendPetClearCooldown(spellid); } else { if(!((Creature*)caster)->HasSpellCooldown(spellid)) caster->SendPetClearCooldown(spellid); } 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; } // 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]); sLog.outDetail( "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::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); CHECK_PACKET_SIZE(recvPacket,8+1+4+1); 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; 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 .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } if (pet->GetGlobalCooldown() > 0) return; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if(!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i\n", spellid); return; } // do not cast not learned spells if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) return; SpellCastTargets targets; if(!targets.read(&recvPacket,pet)) return; pet->clearUnitState(UNIT_STAT_FOLLOW); Spell *spell = new Spell(pet, spellInfo, false); spell->m_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; int16 result = spell->PetCanCast(NULL); if(result == -1) { 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 { pet->SendPetCastFail(spellid, result); if(!pet->HasSpellCooldown(spellid)) pet->SendPetClearCooldown(spellid); spell->finish(false); delete spell; } }