本文整理汇总了C++中ObjectGuid类的典型用法代码示例。如果您正苦于以下问题:C++ ObjectGuid类的具体用法?C++ ObjectGuid怎么用?C++ ObjectGuid使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了ObjectGuid类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: TC_LOG_INFO
void WorldSession::HandlePetSetAction(WorldPacket& recvData)
{
TC_LOG_INFO("network", "HandlePetSetAction. CMSG_PET_SET_ACTION");
ObjectGuid petguid;
uint8 count;
recvData >> petguid;
Unit* pet = ObjectAccessor::GetUnit(*_player, petguid);
if (!pet || pet != _player->GetFirstControlled())
{
TC_LOG_ERROR("network", "HandlePetSetAction: Unknown %s or owner (%s)", petguid.ToString().c_str(), _player->GetGUID().ToString().c_str());
return;
}
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
TC_LOG_ERROR("network", "WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
return;
}
count = (recvData.size() == 24) ? 2 : 1;
uint32 position[2];
uint32 data[2];
bool move_command = false;
for (uint8 i = 0; i < count; ++i)
{
recvData >> position[i];
recvData >> 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]);
TC_LOG_INFO("network", "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X",
_player->GetName().c_str(), 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)))
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id))
{
//sign for autocast
if (act_state == ACT_ENABLED)
{
if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->IsPet())
((Pet*)pet)->ToggleAutocast(spellInfo, true);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == pet->GetEntry())
(*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, true);
}
//.........这里部分代码省略.........
示例2: AddMember
bool ArenaTeam::AddMember(ObjectGuid playerGuid)
{
std::string playerName;
uint8 playerClass;
// Check if arena team is full (Can't have more than type * 2 players)
if (GetMembersSize() >= GetType() * 2)
return false;
// Get player name and class either from db or ObjectMgr
Player* player = ObjectAccessor::FindPlayer(playerGuid);
if (player)
{
playerClass = player->getClass();
playerName = player->GetName();
}
else
{
// 0 1
// SELECT name, class FROM characters WHERE guid = ?
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_CLASS);
stmt->setUInt32(0, playerGuid.GetCounter());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
return false;
playerName = (*result)[0].GetString();
playerClass = (*result)[1].GetUInt8();
}
// Check if player is already in a similar arena team
if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0)
{
TC_LOG_DEBUG("bg.arena", "Arena: %s %s already has an arena team of type %u", playerGuid.ToString().c_str(), playerName.c_str(), GetType());
return false;
}
// Set player's personal rating
uint32 personalRating = 0;
if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0)
personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING);
else if (GetRating() >= 1000)
personalRating = 1000;
// Try to get player's match maker rating from db and fall back to config setting if not found
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING);
stmt->setUInt32(0, playerGuid.GetCounter());
stmt->setUInt8(1, GetSlot());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
uint32 matchMakerRating;
if (result)
matchMakerRating = (*result)[0].GetUInt16();
else
matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING);
// Remove all player signatures from other petitions
// This will prevent player from joining too many arena teams and corrupt arena team data integrity
Player::RemovePetitionsAndSigns(playerGuid, GetType());
// Feed data to the struct
ArenaTeamMember newMember;
newMember.Name = playerName;
newMember.Guid = playerGuid;
newMember.Class = playerClass;
newMember.SeasonGames = 0;
newMember.WeekGames = 0;
newMember.SeasonWins = 0;
newMember.WeekWins = 0;
newMember.PersonalRating = personalRating;
newMember.MatchMakerRating = matchMakerRating;
Members.push_back(newMember);
// Save player's arena team membership to db
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER);
stmt->setUInt32(0, TeamId);
stmt->setUInt32(1, playerGuid.GetCounter());
CharacterDatabase.Execute(stmt);
// Inform player if online
if (player)
{
player->SetInArenaTeam(TeamId, GetSlot(), GetType());
player->SetArenaTeamIdInvited(0);
// Hide promote/remove buttons
if (CaptainGuid != playerGuid)
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
}
TC_LOG_DEBUG("bg.arena", "Player: %s [%s] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), playerGuid.ToString().c_str(), GetType(), GetId(), GetName().c_str());
return true;
}
示例3: DEBUG_LOG
void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recv_data)
{
ObjectGuid guid;
uint32 spellId = 0;
recv_data >> guid >> spellId;
DEBUG_LOG("WORLD: Received opcode CMSG_TRAINER_BUY_SPELL Trainer: %s, learn spell id is: %u", guid.GetString().c_str(), spellId);
Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER);
if (!unit)
{
DEBUG_LOG("WORLD: HandleTrainerBuySpellOpcode - %s not found or you can't interact with him.", guid.GetString().c_str());
return;
}
// remove fake death
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
{
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
}
if (!unit->IsTrainerOf(_player, true))
{
return;
}
// check present spell in trainer spell list
TrainerSpellData const* cSpells = unit->GetTrainerSpells();
TrainerSpellData const* tSpells = unit->GetTrainerTemplateSpells();
if (!cSpells && !tSpells)
{
return;
}
// Try find spell in npc_trainer
TrainerSpell const* trainer_spell = cSpells ? cSpells->Find(spellId) : NULL;
// Not found, try find in npc_trainer_template
if (!trainer_spell && tSpells)
{
trainer_spell = tSpells->Find(spellId);
}
// Not found anywhere, cheating?
if (!trainer_spell)
{
return;
}
// can't be learn, cheat? Or double learn with lags...
uint32 reqLevel = 0;
if (!_player->IsSpellFitByClassAndRace(trainer_spell->spell, &reqLevel))
{
return;
}
reqLevel = trainer_spell->isProvidedReqLevel ? trainer_spell->reqLevel : std::max(reqLevel, trainer_spell->reqLevel);
if (_player->GetTrainerSpellState(trainer_spell, reqLevel) != TRAINER_SPELL_GREEN)
{
return;
}
SpellEntry const* proto = sSpellStore.LookupEntry(trainer_spell->spell);
SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->EffectTriggerSpell[0]);
// apply reputation discount
uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit)));
// check money requirement
if (_player->GetMoney() < nSpellCost)
{
return;
}
_player->ModifyMoney(-int32(nSpellCost));
SendPlaySpellVisual(guid, 0xB3); // visual effect on trainer
WorldPacket data(SMSG_PLAY_SPELL_IMPACT, 8 + 4); // visual effect on player
data << _player->GetObjectGuid();
data << uint32(0x016A); // index from SpellVisualKit.dbc
SendPacket(&data);
// learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
//[-ZERO] _player->learnSpell(trainer_spell->spell, false);
data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << ObjectGuid(guid);
data << uint32(spellId); // should be same as in packet from client
SendPacket(&data);
Spell* spell;
if (proto->SpellVisual == 222)
{
spell = new Spell(_player, proto, false);
}
else
{
spell = new Spell(unit, proto, false);
//.........这里部分代码省略.........
示例4: DEBUG_LOG
void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
{
DEBUG_LOG("WORLD: CMSG_LOOT_MONEY");
Player *player = GetPlayer();
ObjectGuid guid = player->GetLootGuid();
if (!guid)
return;
Loot *pLoot = NULL;
Item* pItem = NULL;
switch(guid.GetHigh())
{
case HIGHGUID_GAMEOBJECT:
{
GameObject *pGameObject = GetPlayer()->GetMap()->GetGameObject(guid);
// not check distance for GO in case owned GO (fishing bobber case, for example)
if( pGameObject && (pGameObject->GetOwnerGuid() == _player->GetObjectGuid() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) )
pLoot = &pGameObject->loot;
break;
}
case HIGHGUID_CORPSE: // remove insignia ONLY in BG
{
Corpse *bones = _player->GetMap()->GetCorpse(guid);
if (bones && bones->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
pLoot = &bones->loot;
break;
}
case HIGHGUID_ITEM:
{
pItem = GetPlayer()->GetItemByGuid(guid);
if (!pItem || !pItem->HasGeneratedLoot())
return;
pLoot = &pItem->loot;
break;
}
case HIGHGUID_UNIT:
case HIGHGUID_VEHICLE:
{
Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid);
bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed);
if ( ok_loot && pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
pLoot = &pCreature->loot ;
break;
}
default:
return; // unlootable type
}
if (pLoot)
{
pLoot->NotifyMoneyRemoved();
if (!guid.IsItem() && player->GetGroup()) //item can be looted only single player
{
Group *group = player->GetGroup();
std::vector<Player*> playersNear;
for(GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* playerGroup = itr->getSource();
if(!playerGroup)
continue;
if (player->IsWithinDistInMap(playerGroup,sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE),false))
playersNear.push_back(playerGroup);
}
uint32 money_per_player = uint32((pLoot->gold)/(playersNear.size()));
for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i)
{
(*i)->ModifyMoney( money_per_player );
(*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player);
WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4+1);
data << uint32(money_per_player);
data << uint8(playersNear.size() > 1 ? 0 : 1);// 0 is "you share of loot..."
(*i)->GetSession()->SendPacket(&data);
}
}
else
{
player->ModifyMoney( pLoot->gold );
player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold);
WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4+1);
data << uint32(pLoot->gold);
data << uint8(1); // 1 is "you loot..."
player->GetSession()->SendPacket(&data);
}
//.........这里部分代码省略.........
示例5: TC_LOG_DEBUG
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_LOOT_ITEM");
Player* player = GetPlayer();
ObjectGuid lguid = player->GetLootGUID();
Loot* loot = NULL;
uint8 lootSlot = 0;
recvData >> lootSlot;
if (lguid.IsGameObject())
{
GameObject* go = player->GetMap()->GetGameObject(lguid);
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE)))
{
player->SendLootRelease(lguid);
return;
}
loot = &go->loot;
}
else if (lguid.IsItem())
{
Item* pItem = player->GetItemByGuid(lguid);
if (!pItem)
{
player->SendLootRelease(lguid);
return;
}
loot = &pItem->loot;
}
else if (lguid.IsCorpse())
{
Corpse* bones = ObjectAccessor::GetCorpse(*player, lguid);
if (!bones)
{
player->SendLootRelease(lguid);
return;
}
loot = &bones->loot;
}
else
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
{
player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
return;
}
loot = &creature->loot;
}
player->StoreLootItem(lootSlot, loot);
// If player is removing the last LootItem, delete the empty container.
if (loot->isLooted() && lguid.IsItem())
player->GetSession()->DoLootRelease(lguid);
}
示例6: DEBUG_LOG
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recv_data)
{
DEBUG_LOG("WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
uint32 time;
uint32 queueSlot;
uint32 unk; // unk
uint8 action; // enter battle 0x1, leave queue 0x0
ObjectGuid guid; // player guid
recv_data >> time >> queueSlot >> unk;
recv_data.ReadGuidMask<0, 1, 5, 6, 7, 4, 3, 2>(guid);
action = recv_data.ReadBit() ? 1 : 0;
recv_data.ReadGuidBytes<1, 3, 5, 7, 0, 2, 6, 4>(guid);
DEBUG_LOG("WORLD: Recvd CMSG_BATTLEFIELD_PORT Message, time %u queueSlot %u unk %u action %u guid %s",
time, queueSlot, unk, action, guid.GetString().c_str());
//if (type && !IsArenaTypeValid(ArenaType(type)))
//{
// sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), arena type wrong: %u.", _player->GetGUIDLow(), type);
// return;
//}
if (!_player->InBattleGroundQueue())
{
sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow());
return;
}
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(queueSlot);
if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
{
sLog.outError("BattlegroundHandler: invalid queueSlot (%u) received.", queueSlot);
return;
}
// get GroupQueueInfo from BattleGroundQueue
BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId];
// we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function
GroupQueueInfo ginfo;
if (!bgQueue.GetPlayerGroupInfoData(_player->GetObjectGuid(), &ginfo))
{
sLog.outError("BattlegroundHandler: itrplayerstatus not found.");
return;
}
// if action == 1, then instanceId is required
if (!ginfo.IsInvitedToBGInstanceGUID && action == 1)
{
sLog.outError("BattlegroundHandler: instance not found.");
return;
}
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
// ::BGTemplateId returns BATTLEGROUND_AA when it is arena queue.
// Do instance id search as there is no AA bg instances.
BattleGround* bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BATTLEGROUND_AA ? BATTLEGROUND_TYPE_NONE : bgTypeId);
// bg template might and must be used in case of leaving queue, when instance is not created yet
if (!bg && action == 0)
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if (!bg)
{
sLog.outError("BattlegroundHandler: bg_template not found for instance id %u type id %u.", ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
return;
}
// get real bg type
bgTypeId = bg->GetTypeID();
// expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
if (!bracketEntry)
return;
// some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
if (action == 1 && ginfo.arenaType == ARENA_TYPE_NONE)
{
// if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
if (!_player->CanJoinToBattleground())
{
// send bg command result to show nice message
WorldPacket data2;
sBattleGroundMgr.BuildBattleGroundStatusFailedPacket(&data2, bg, _player, queueSlot, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data2);
action = 0;
DEBUG_LOG("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
}
// if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
if (_player->getLevel() > bg->GetMaxLevel())
{
sLog.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
_player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
action = 0;
}
}
WorldPacket data;
switch (action)
{
//.........这里部分代码省略.........
示例7: DoLootRelease
void WorldSession::DoLootRelease(ObjectGuid lguid)
{
Player *player = GetPlayer();
Loot *loot;
player->SetLootGUID(0);
player->SendLootRelease(lguid);
player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING);
if (!player->IsInWorld())
return;
switch (lguid.GetHigh())
{
case HIGHGUID_GAMEOBJECT:
{
GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid);
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))
return;
loot = &go->loot;
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR)
{
// locked doors are opened with spelleffect openlock, prevent remove its as looted
go->UseDoorOrButton();
}
else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE)
{
// GO is mineral vein? so it is not removed after its looted
if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST)
{
uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens;
uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens;
// only vein pass this check
if (go_min != 0 && go_max > go_min)
{
float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT);
float min_amount = go_min*amount_rate;
float max_amount = go_max*amount_rate;
go->AddUse();
float uses = float(go->GetUseCount());
if (uses < max_amount)
{
if (uses >= min_amount)
{
float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT);
int32 ReqValue = 175;
LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId);
if (lockInfo)
ReqValue = lockInfo->Skill[0];
float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25);
double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses));
if (roll_chance_f(float(100.0f*chance+skill)))
{
go->SetLootState(GO_READY);
}
else // not have more uses
go->SetLootState(GO_JUST_DEACTIVATED);
}
else // 100% chance until min uses
go->SetLootState(GO_READY);
}
else // max uses already
go->SetLootState(GO_JUST_DEACTIVATED);
}
else // not vein
go->SetLootState(GO_JUST_DEACTIVATED);
}
else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE)
{ // The fishing hole used once more
go->AddUse(); // if the max usage is reached, will be despawned in next tick
if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens))
{
go->SetLootState(GO_JUST_DEACTIVATED);
}
else
go->SetLootState(GO_READY);
}
else // not chest (or vein/herb/etc)
go->SetLootState(GO_JUST_DEACTIVATED);
loot->clear();
}
else
// not fully looted object
go->SetLootState(GO_ACTIVATED);
break;
}
case HIGHGUID_CORPSE: // ONLY remove insignia at BG
{
Corpse *corpse = _player->GetMap()->GetCorpse(lguid);
if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE) )
//.........这里部分代码省略.........
示例8: HandleSendItemsCommand
// Send items by mail
static bool HandleSendItemsCommand(ChatHandler* handler, char const* args)
{
// format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
Player* receiver;
ObjectGuid receiverGuid;
std::string receiverName;
if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName))
return false;
char* tail1 = strtok(NULL, "");
if (!tail1)
return false;
char const* msgSubject = handler->extractQuotedArg(tail1);
if (!msgSubject)
return false;
char* tail2 = strtok(NULL, "");
if (!tail2)
return false;
char const* msgText = handler->extractQuotedArg(tail2);
if (!msgText)
return false;
// msgSubject, msgText isn't NUL after prev. check
std::string subject = msgSubject;
std::string text = msgText;
// extract items
typedef std::pair<uint32, uint32> ItemPair;
typedef std::list< ItemPair > ItemPairs;
ItemPairs items;
// get all tail string
char* tail = strtok(NULL, "");
// get from tail next item str
while (char* itemStr = strtok(tail, " "))
{
// and get new tail
tail = strtok(NULL, "");
// parse item str
char const* itemIdStr = strtok(itemStr, ":");
char const* itemCountStr = strtok(NULL, " ");
uint32 itemId = atoul(itemIdStr);
if (!itemId)
return false;
ItemTemplate const* item_proto = sObjectMgr->GetItemTemplate(itemId);
if (!item_proto)
{
handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId);
handler->SetSentErrorMessage(true);
return false;
}
uint32 itemCount = itemCountStr ? atoi(itemCountStr) : 1;
if (itemCount < 1 || (item_proto->GetMaxCount() > 0 && itemCount > uint32(item_proto->GetMaxCount())))
{
handler->PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, itemCount, itemId);
handler->SetSentErrorMessage(true);
return false;
}
while (itemCount > item_proto->GetMaxStackSize())
{
items.push_back(ItemPair(itemId, item_proto->GetMaxStackSize()));
itemCount -= item_proto->GetMaxStackSize();
}
items.push_back(ItemPair(itemId, itemCount));
if (items.size() > MAX_MAIL_ITEMS)
{
handler->PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS);
handler->SetSentErrorMessage(true);
return false;
}
}
// from console show nonexisting sender
MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : UI64LIT(0), MAIL_STATIONERY_GM);
// fill mail
MailDraft draft(subject, text);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr)
{
if (Item* item = Item::CreateItem(itr->first, itr->second, handler->GetSession() ? handler->GetSession()->GetPlayer() : 0))
{
item->SaveToDB(trans); // Save to prevent being lost at next mail load. If send fails, the item will be deleted.
draft.AddItem(item);
}
}
//.........这里部分代码省略.........
示例9: DEBUG_LOG
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
{
uint32 opcode = recv_data.GetOpcode();
DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
/* extract packet */
ObjectGuid guid;
MovementInfo movementInfo;
float newspeed;
recv_data >> guid.ReadAsPacked();
recv_data >> Unused<uint32>(); // counter or moveEvent
recv_data >> movementInfo;
recv_data >> newspeed;
// now can skip not our packet
if(_player->GetObjectGuid() != guid)
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
/*----------------*/
// client ACK send one packet for mounted/run case and need skip all except last from its
// in other cases anti-cheat check can be fail in false case
UnitMoveType move_type;
UnitMoveType force_move_type;
static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
switch(opcode)
{
case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break;
case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break;
case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break;
case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break;
case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break;
case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
default:
sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
return;
}
// skip all forced speed changes except last and unexpected
// in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both.
if(_player->m_forced_speed_changes[force_move_type] > 0)
{
--_player->m_forced_speed_changes[force_move_type];
if(_player->m_forced_speed_changes[force_move_type] > 0)
return;
}
if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f)
{
if(_player->GetSpeed(move_type) > newspeed) // must be greater - just correct
{
sLog.outError("%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value",
move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), newspeed);
_player->SetSpeedRate(move_type,_player->GetSpeedRate(move_type),true);
}
else // must be lesser - cheating
{
BASIC_LOG("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)",
_player->GetName(),_player->GetSession()->GetAccountId(),_player->GetSpeed(move_type), newspeed);
_player->GetSession()->KickPlayer();
}
}
}
示例10: TC_LOG_DEBUG
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL");
ObjectGuid guid;
uint8 castCount;
uint32 spellId;
uint8 castFlags;
recvPacket >> guid >> castCount >> spellId >> castFlags;
TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL, %s, castCount: %u, spellId %u, castFlags %u", guid.ToString().c_str(), 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()))
{
TC_LOG_ERROR("network", "HandlePetCastSpellOpcode: %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("network", "WORLD: unknown PET spell id %i", spellId);
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->m_cast_count = castCount; // probably pending spell cast
spell->m_targets = targets;
SpellCastResult result = spell->CheckPetCast(NULL);
if (result == SPELL_CAST_OK)
{
if (Creature* creature = caster->ToCreature())
{
creature->AddCreatureSpellCooldown(spellId);
if (Pet* pet = creature->ToPet())
{
// 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->getPetType() == SUMMON_PET && (urand(0, 100) < 10))
pet->SendPetTalk(PET_TALK_SPECIAL_SPELL);
else
pet->SendPetAIReaction(guid);
}
}
spell->prepare(&(spell->m_targets));
}
else
{
spell->SendPetCastResult(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;
}
}
示例11: DEBUG_LOG
// this void creates new auction and adds auction to some auctionhouse
void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
{
DEBUG_LOG("WORLD: HandleAuctionSellItem");
ObjectGuid auctioneerGuid;
ObjectGuid itemGuid;
uint32 etime, bid, buyout;
recv_data >> auctioneerGuid;
recv_data >> itemGuid;
recv_data >> bid;
recv_data >> buyout;
recv_data >> etime;
if (itemGuid.IsEmpty() || !bid || !etime)
return; // check for cheaters
Player *pl = GetPlayer();
AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid);
if (!auctionHouseEntry)
return;
// always return pointer
AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry);
// client send time in minutes, convert to common used sec time
etime *= MINUTE;
// client understand only 3 auction time
switch(etime)
{
case 1*MIN_AUCTION_TIME:
case 2*MIN_AUCTION_TIME:
case 4*MIN_AUCTION_TIME:
break;
default:
return;
}
// remove fake death
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
Item *it = pl->GetItemByGuid(itemGuid);
// do not allow to sell already auctioned items
if (sAuctionMgr.GetAItem(itemGuid.GetCounter()))
{
sLog.outError("AuctionError, %s is sending %s, but item is already in another auction", pl->GetGuidStr().c_str(), itemGuid.GetString().c_str());
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
return;
}
// prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to auction)
if(!it)
{
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND);
return;
}
if(!it->CanBeTraded())
{
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
return;
}
if ((it->GetProto()->Flags & ITEM_FLAG_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION))
{
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
return;
}
//we have to take deposit :
uint32 deposit = AuctionHouseMgr::GetAuctionDeposit( auctionHouseEntry, etime, it );
if ( pl->GetMoney() < deposit )
{
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY);
return;
}
if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
{
sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
GetPlayerName(), GetAccountId(), it->GetProto()->Name1, it->GetEntry(), it->GetCount());
}
pl->ModifyMoney( -int32(deposit) );
uint32 auction_time = uint32(etime * sWorld.getConfig(CONFIG_FLOAT_RATE_AUCTION_TIME));
AuctionEntry *AH = new AuctionEntry;
AH->Id = sObjectMgr.GenerateAuctionID();
AH->item_guidlow = itemGuid.GetCounter();
AH->item_template = it->GetEntry();
AH->owner = pl->GetGUIDLow();
AH->startbid = bid;
AH->bidder = 0;
AH->bid = 0;
AH->buyout = buyout;
AH->expire_time = time(NULL) + auction_time;
AH->deposit = deposit;
//.........这里部分代码省略.........
示例12: DEBUG_LOG
// this void creates new auction and adds auction to some auctionhouse
void WorldSession::HandleAuctionSellItem(WorldPacket& recv_data)
{
DEBUG_LOG("WORLD: HandleAuctionSellItem");
ObjectGuid auctioneerGuid;
ObjectGuid itemGuid;
uint32 etime, bid, buyout;
recv_data >> auctioneerGuid;
recv_data >> itemGuid;
recv_data >> bid;
recv_data >> buyout;
recv_data >> etime;
if (!bid || !etime)
return; // check for cheaters
Player* pl = GetPlayer();
AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid);
if (!auctionHouseEntry)
return;
// always return pointer
AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry);
// client send time in minutes, convert to common used sec time
etime *= MINUTE;
// client understand only 3 auction time
switch (etime)
{
case 1*MIN_AUCTION_TIME:
case 2*MIN_AUCTION_TIME:
case 4*MIN_AUCTION_TIME:
break;
default:
return;
}
// remove fake death
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
if (!itemGuid)
return;
Item* it = pl->GetItemByGuid(itemGuid);
// do not allow to sell already auctioned items
if (sAuctionMgr.GetAItem(itemGuid.GetCounter()))
{
sLog.outError("AuctionError, %s is sending %s, but item is already in another auction", pl->GetGuidStr().c_str(), itemGuid.GetString().c_str());
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND);
return;
}
// prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to auction)
if (!it)
{
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND);
return;
}
if (!it->CanBeTraded())
{
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_CANNOT_TRADE_THAT);
return;
}
if ((it->GetProto()->Flags & ITEM_FLAG_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION))
{
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_CANNOT_TRADE_THAT);
return;
}
// check money for deposit
uint32 deposit = AuctionHouseMgr::GetAuctionDeposit(auctionHouseEntry, etime, it);
if (pl->GetMoney() < deposit)
{
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_NOT_ENOUGH_MONEY);
return;
}
if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE))
{
sLog.outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
GetPlayerName(), GetAccountId(), it->GetProto()->Name1, it->GetEntry(), it->GetCount());
}
pl->ModifyMoney(-int32(deposit));
AuctionEntry* AH = auctionHouse->AddAuction(auctionHouseEntry, it, etime, bid, buyout, deposit, pl);
DETAIL_LOG("selling %s to auctioneer %s with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
itemGuid.GetString().c_str(), auctioneerGuid.GetString().c_str(), bid, buyout, etime, auctionHouseEntry->houseId);
SendAuctionCommandResult(AH, AUCTION_STARTED, AUCTION_OK);
}
示例13: GetPlayer
void WorldSession::DoLootRelease(ObjectGuid lguid)
{
Player *player = GetPlayer();
Loot *loot;
player->SetLootGUID(ObjectGuid::Empty);
player->SendLootRelease(lguid);
player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING);
if (!player->IsInWorld())
return;
if (lguid.IsGameObject())
{
GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid);
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE)))
return;
loot = &go->loot;
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR)
{
// locked doors are opened with spelleffect openlock, prevent remove its as looted
go->UseDoorOrButton();
}
else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE)
{
if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE)
{ // The fishing hole used once more
go->AddUse(); // if the max usage is reached, will be despawned in next tick
if (go->GetUseCount() >= go->GetGOValue()->FishingHole.MaxOpens)
go->SetLootState(GO_JUST_DEACTIVATED);
else
go->SetLootState(GO_READY);
}
else
go->SetLootState(GO_JUST_DEACTIVATED);
loot->clear();
}
else
{
// not fully looted object
go->SetLootState(GO_ACTIVATED, player);
// if the round robin player release, reset it.
if (player->GetGUID() == loot->roundRobinPlayer)
loot->roundRobinPlayer.Clear();
}
}
else if (lguid.IsCorpse()) // ONLY remove insignia at BG
{
Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid);
if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
return;
loot = &corpse->loot;
if (loot->isLooted())
{
loot->clear();
corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE);
}
}
else if (lguid.IsItem())
{
Item* pItem = player->GetItemByGuid(lguid);
if (!pItem)
return;
ItemTemplate const* proto = pItem->GetTemplate();
// destroy only 5 items from stack in case prospecting and milling
if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE))
{
pItem->m_lootGenerated = false;
pItem->loot.clear();
uint32 count = pItem->GetCount();
// >=5 checked in spell code, but will work for cheating cases also with removing from another stacks.
if (count > 5)
count = 5;
player->DestroyItemCount(pItem, count, true);
}
else
{
// Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item
if (pItem->loot.isLooted() || !(proto->Flags & ITEM_PROTO_FLAG_OPENABLE))
player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
}
return; // item can be looted only single player
}
else
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
//.........这里部分代码省略.........
示例14: UNIT_ACTION_BUTTON_ACTION
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))
//.........这里部分代码省略.........
示例15: DETAIL_LOG
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);
// 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;
}
}