/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "StdAfx.h"
void WorldSession::HandleRepopRequestOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Recvd CMSG_REPOP_REQUEST Message" );
GetPlayer()->RepopRequestedPlayer();
}
void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
{
if(!_player->IsInWorld()) return;
// uint8 slot = 0;
uint32 itemid = 0;
uint32 amt = 1;
uint8 lootSlot = 0;
uint8 error = 0;
SlotResult slotresult;
Item *add;
Loot *pLoot = NULL;
if(_player->isCasting())
_player->InterruptSpell();
GameObject * pGO = NULL;
Creature * pCreature = NULL;
if(UINT32_LOPART(GUID_HIPART(GetPlayer()->GetLootGUID())) == HIGHGUID_UNIT)
{
pCreature = _player->GetMapMgr()->GetCreature((uint32)GetPlayer()->GetLootGUID());
if (!pCreature)return;
pLoot=&pCreature->loot;
}
else if(UINT32_LOPART(GUID_HIPART(_player->GetLootGUID())) == HIGHGUID_GAMEOBJECT)
{
pGO = _player->GetMapMgr()->GetGameObject((uint32)GetPlayer()->GetLootGUID());
if(!pGO)return;
pLoot=&pGO->loot;
}else if( (UINT32_LOPART(GUID_HIPART(_player->GetLootGUID())) == HIGHGUID_ITEM) )
{
Item *pItem = _player->GetItemInterface()->GetItemByGUID(_player->GetLootGUID());
if(!pItem)
return;
pLoot = pItem->loot;
}
if(!pLoot) return;
recv_data >> lootSlot;
if (lootSlot >= pLoot->items.size())
{
sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %d)",
GetPlayer()->GetName(), lootSlot, pLoot->items.size());
return;
}
amt = pLoot->items.at(lootSlot).iItemsCount;
if (!amt)//Test for party loot
{
GetPlayer()->GetItemInterface()->BuildInventoryChangeError(NULL, NULL,INV_ERR_ALREADY_LOOTED);
return;
}
itemid = pLoot->items.at(lootSlot).item.itemid;
ItemPrototype* it = ItemPrototypeStorage.LookupEntry(itemid);
if((error = _player->GetItemInterface()->CanReceiveItem(it, 1)))
{
_player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, error);
return;
}
if(pGO)
CALL_GO_SCRIPT_EVENT(pGO, OnLootTaken)(_player, it);
else if(pCreature)
CALL_SCRIPT_EVENT(pCreature, OnLootTaken)(_player, it);
add = GetPlayer()->GetItemInterface()->FindItemLessMax(itemid, amt, false);
sHookInterface.OnLoot(_player, pCreature, 0, itemid);
if (!add)
{
slotresult = GetPlayer()->GetItemInterface()->FindFreeInventorySlot(it);
if(!slotresult.Result)
{
GetPlayer()->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_INVENTORY_FULL);
return;
}
sLog.outDebug("AutoLootItem MISC");
Item *item = objmgr.CreateItem( itemid, GetPlayer());
item->SetUInt32Value(ITEM_FIELD_STACK_COUNT,amt);
uint32 rndprop=pLoot->items.at(lootSlot).iRandomProperty;
if(rndprop)
item->SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID,rndprop);
item->ApplyRandomProperties();
GetPlayer()->GetItemInterface()->SafeAddItem(item,slotresult.ContainerSlot, slotresult.Slot);
sQuestMgr.OnPlayerItemPickup(GetPlayer(),item);
}
else
{
add->SetCount(add->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + amt);
add->m_isDirty = true;
sQuestMgr.OnPlayerItemPickup(GetPlayer(),add);
}
pLoot->items.at(lootSlot).iItemsCount=0;
// this gets sent to all looters
WorldPacket data(1);
data.SetOpcode(SMSG_LOOT_REMOVED);
data << lootSlot;
Player * plr;
for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); ++itr)
{
if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
plr->GetSession()->SendPacket(&data);
}
WorldPacket idata(45);
if(it->Class == ITEM_CLASS_QUEST)
{
uint32 pcount = _player->GetItemInterface()->GetItemCount(it->ItemId, true);
BuildItemPushResult(&idata, _player->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(lootSlot).iRandomProperty,0xFF,0,0xFFFFFFFF,pcount);
}
else BuildItemPushResult(&idata, _player->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(lootSlot).iRandomProperty);
if(_player->InGroup())
_player->GetGroup()->SendPacketToAll(&idata);
else
SendPacket(&idata);
/* any left yet? (for fishing bobbers) */
if(pGO && pGO->GetEntry() ==GO_FISHING_BOBBER)
{
int count=0;
for(vector<__LootItem>::iterator itr = pLoot->items.begin(); itr != pLoot->items.end(); ++itr)
count += (*itr).iItemsCount;
if(!count)
pGO->ExpireAndDelete();
}
}
void WorldSession::HandleLootMoneyOpcode( WorldPacket & recv_data )
{
if(!_player->IsInWorld()) return;
Loot * pLoot = NULL;
uint64 lootguid=GetPlayer()->GetLootGUID();
if(!lootguid)
return; // duno why this happens
if(_player->isCasting())
_player->InterruptSpell();
WorldPacket pkt;
Unit * pt = 0;
if(UINT32_LOPART(GUID_HIPART(lootguid)) == HIGHGUID_UNIT)
{
Creature* pCreature = _player->GetMapMgr()->GetCreature(lootguid);
if(!pCreature)return;
pLoot=&pCreature->loot;
pt = pCreature;
}
else if(UINT32_LOPART(GUID_HIPART(lootguid)) == HIGHGUID_GAMEOBJECT)
{
GameObject* pGO = _player->GetMapMgr()->GetGameObject(lootguid);
if(!pGO)return;
pLoot=&pGO->loot;
}
else if(UINT32_LOPART(GUID_HIPART(lootguid)) == HIGHGUID_CORPSE)
{
Corpse *pCorpse = objmgr.GetCorpse((uint32)lootguid);
if(!pCorpse)return;
pLoot=&pCorpse->loot;
}
else if(UINT32_LOPART(GUID_HIPART(lootguid)) == HIGHGUID_PLAYER)
{
Player * pPlayer = _player->GetMapMgr()->GetPlayer(lootguid);
if(!pPlayer) return;
pLoot = &pPlayer->loot;
pPlayer->bShouldHaveLootableOnCorpse = false;
pt = pPlayer;
}
else if( (UINT32_LOPART(GUID_HIPART(lootguid)) == HIGHGUID_ITEM) )
{
Item *pItem = _player->GetItemInterface()->GetItemByGUID(lootguid);
if(!pItem)
return;
pLoot = pItem->loot;
}
if (!pLoot)
{
//bitch about cheating maybe?
return;
}
uint32 money = pLoot->gold;
pLoot->gold=0;
WorldPacket data(1);
data.SetOpcode(SMSG_LOOT_CLEAR_MONEY);
// send to all looters
Player * plr;
for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); ++itr)
{
if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
plr->GetSession()->SendPacket(&data);
}
if(!_player->InGroup())
{
if(money)
{
GetPlayer()->ModUInt32Value( PLAYER_FIELD_COINAGE , money);
sHookInterface.OnLoot(_player, pt, money, 0);
}
}
else
{
//this code is wrong mustbe party not raid!
Group* party = _player->GetGroup();
if(party)
{
/*uint32 share = money/party->MemberCount();*/
vector targets;
targets.reserve(party->MemberCount());
GroupMembersSet::iterator itr;
SubGroup * sgrp;
party->getLock().Acquire();
for(uint32 i = 0; i < party->GetSubGroupCount(); i++)
{
sgrp = party->GetSubGroup(i);
for(itr = sgrp->GetGroupMembersBegin(); itr != sgrp->GetGroupMembersEnd(); ++itr)
{
if(itr->player && itr->player->GetZoneId() == _player->GetZoneId() && _player->GetInstanceID() == itr->player->GetInstanceID())
targets.push_back(itr->player);
}
}
party->getLock().Release();
if(!targets.size())
return;
uint32 share = money / targets.size();
pkt.SetOpcode(SMSG_LOOT_MONEY_NOTIFY);
pkt << share;
for(vector::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
(*itr)->ModUInt32Value(PLAYER_FIELD_COINAGE, share);
(*itr)->GetSession()->SendPacket(&pkt);
}
}
}
}
void WorldSession::HandleLootOpcode( WorldPacket & recv_data )
{
if(!_player->IsInWorld())
return;
uint64 guid;
recv_data >> guid;
if(_player->isCasting())
_player->InterruptSpell();
if(_player->InGroup() && !_player->m_bg)
{
Group * party = _player->GetGroup();
if(party)
{
if(party->GetMethod() == PARTY_LOOT_MASTER)
{
WorldPacket data(SMSG_LOOT_MASTER_LIST, 330); // wont be any larger
data << (uint8)party->MemberCount();
uint32 real_count = 0;
SubGroup *s;
GroupMembersSet::iterator itr;
party->Lock();
for(uint32 i = 0; i < party->GetSubGroupCount(); ++i)
{
s = party->GetSubGroup(i);
for(itr = s->GetGroupMembersBegin(); itr != s->GetGroupMembersEnd(); ++itr)
{
if(itr->player && _player->GetZoneId() == itr->player->GetZoneId())
{
data << itr->player->GetGUID();
++real_count;
}
}
}
party->Unlock();
*(uint8*)&data.contents()[0] = real_count;
party->SendPacketToAll(&data);
}
/* //this commented code is not used because it was never tested and finished !
else if(party->GetMethod() == PARTY_LOOT_RR)
{
Creature *target=GetPlayer()->GetMapMgr()->GetCreature(guid); //maybe we should extend this to other object types too
if(target)
{
if(target->TaggerGuid==GetPlayer()->GetGUID())
GetPlayer()->SendLoot(guid,1);
else return;
}
}*/
}
}
GetPlayer()->SendLoot(guid,1);
}
void WorldSession::HandleLootReleaseOpcode( WorldPacket & recv_data )
{
if(!_player->IsInWorld()) return;
uint64 guid;
recv_data >> guid;
WorldPacket data(SMSG_LOOT_RELEASE_RESPONSE, 9);
data << guid << uint8( 1 );
SendPacket( &data );
_player->SetLootGUID(0);
_player->RemoveFlag(UNIT_FIELD_FLAGS, U_FIELD_ANIMATION_LOOTING);
_player->m_currentLoot = 0;
if(UINT32_LOPART(GUID_HIPART(guid)) == HIGHGUID_UNIT)
{
Creature* pCreature = _player->GetMapMgr()->GetCreature(guid);
if(!pCreature)
return;
// remove from looter set
pCreature->loot.looters.erase(_player->GetGUID());
if(!pCreature->loot.gold)
{
for(std::vector<__LootItem>::iterator i=pCreature->loot.items.begin();i!=pCreature->loot.items.end();i++)
if(i->iItemsCount)
{
ItemPrototype *proto=ItemPrototypeStorage.LookupEntry(i->item.itemid);
if(proto->Class != 12)
return;
if(_player->HasQuestForItem(i->item.itemid))
return;
}
pCreature->BuildFieldUpdatePacket(_player, UNIT_DYNAMIC_FLAGS, 0);
if(!pCreature->Skinned)
{
if(lootmgr.IsSkinnable(pCreature->GetEntry()))
{
pCreature->BuildFieldUpdatePacket(_player, UNIT_FIELD_FLAGS, U_FIELD_FLAG_SKINNABLE);
}
}
}
}
else if(UINT32_LOPART(GUID_HIPART(guid)) == HIGHGUID_GAMEOBJECT)
{
GameObject* pGO = _player->GetMapMgr()->GetGameObject(guid);
if(!pGO)
return;
switch(pGO->GetUInt32Value(GAMEOBJECT_TYPE_ID))
{
case GAMEOBJECT_TYPE_FISHINGNODE:
{
pGO->loot.looters.erase(_player->GetGUID());
if(pGO->IsInWorld())
{
pGO->RemoveFromWorld();
}
delete pGO;
}break;
case GAMEOBJECT_TYPE_CHEST:
{
pGO->loot.looters.erase(_player->GetGUID());
//check for locktypes
Lock *pLock = sLockStore.LookupEntry(pGO->GetInfo()->SpellFocus);
if(pLock)
{
for(uint32 i=0; i < 5; i++)
{
if(pLock->locktype[i])
{
if(pLock->locktype[i] == 2) //locktype;
{
//herbalism and mining;
if(pLock->lockmisc[i] == LOCKTYPE_MINING || pLock->lockmisc[i] == LOCKTYPE_HERBALISM)
{
//we still have loot inside.
if(pGO->HasLoot())
{
pGO->SetUInt32Value(GAMEOBJECT_STATE, 1);
return;
}
if(pGO->CanMine())
{ pGO->loot.items.clear();
pGO->UseMine();
}
else
{
uint32 DespawnTime = 0;
if(sQuestMgr.GetGameObjectLootQuest(pGO->GetEntry()))
DespawnTime = 120000; // 5 min for quest GO,
else
{
DespawnTime = 900000; // 15 for else
}
pGO->Despawn(DespawnTime);
return;
}
}
else //other type of locks that i dont bother to split atm ;P
{
if(pGO->HasLoot())
{
pGO->SetUInt32Value(GAMEOBJECT_STATE, 1);
return;
}
uint32 DespawnTime = 0;
if(sQuestMgr.GetGameObjectLootQuest(pGO->GetEntry()))
DespawnTime = 120000; // 5 min for quest GO,
else
{
DespawnTime = 900000; // 15 for else
}
pGO->Despawn(DespawnTime);
return;
}
}
}
}
}
else
{
if(pGO->HasLoot())
{
pGO->SetUInt32Value(GAMEOBJECT_STATE, 1);
return;
}
uint32 DespawnTime = 0;
if(sQuestMgr.GetGameObjectLootQuest(pGO->GetEntry()))
DespawnTime = 120000; // 5 min for quest GO,
else
{
DespawnTime = 900000; // 15 for else
}
pGO->Despawn(DespawnTime);
}
}
default: break;
}
}
else if(UINT32_LOPART(GUID_HIPART(guid)) == HIGHGUID_CORPSE)
{
Corpse *pCorpse = objmgr.GetCorpse(guid);
if(pCorpse)
pCorpse->SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, 0);
}
else if(UINT32_LOPART(GUID_HIPART(guid)) == HIGHGUID_PLAYER)
{
Player *plr = objmgr.GetPlayer(guid);
if(plr)
{
plr->bShouldHaveLootableOnCorpse = false;
plr->RemoveFlag(UNIT_DYNAMIC_FLAGS, U_DYN_FLAG_LOOTABLE);
}
}
else if(UINT32_LOPART(GUID_HIPART(guid)))
{
// suicide!
_player->GetItemInterface()->SafeFullRemoveItemByGuid(guid);
}
}
void WorldSession::HandleWhoOpcode( WorldPacket & recv_data )
{
uint32 min_level;
uint32 max_level;
uint8 unk2;
uint32 unk3;
uint32 unk4;
uint32 zone_count;
uint32 * zones = 0;
uint32 name_count;
string * names = 0;
string chatname;
bool cname;
uint32 i;
recv_data >> min_level >> max_level;
recv_data >> chatname >> unk2 >> unk3 >> unk4;
recv_data >> zone_count;
if(zone_count > 0 && zone_count < 10)
{
zones = new uint32[zone_count];
for(i = 0; i < zone_count; ++i)
recv_data >> zones[i];
}
else
{
zone_count = 0;
}
recv_data >> name_count;
if(name_count > 0 && name_count < 10)
{
names = new string[name_count];
for(i = 0; i < name_count; ++i)
recv_data >> names[i];
}
else
{
name_count = 0;
}
if(chatname.length() > 0)
cname = true;
else
cname = false;
sLog.outDebug( "WORLD: Recvd CMSG_WHO Message with %u zones and %u names", zone_count, name_count );
bool gm = false;
uint32 team = _player->GetTeam();
if(HasGMPermissions())
gm = true;
uint32 sent_count = 0;
uint32 total_count = 0;
PlayerStorageMap::const_iterator itr,iend;
Player * plr;
uint32 lvl;
bool add;
WorldPacket data;
data.SetOpcode(SMSG_WHO);
data << uint64(0);
objmgr._playerslock.AcquireReadLock();
iend=objmgr._players.end();
itr=objmgr._players.begin();
while(itr !=iend && sent_count < 50)
{
plr = itr->second;
++itr;
if(!plr->GetSession() || !plr->IsInWorld())
continue;
if(!sWorld.show_gm_in_who_list && !HasGMPermissions())
{
if(plr->GetSession()->HasGMPermissions())
continue;
}
// Team check
if(!gm && plr->GetTeam() != team && !plr->GetSession()->HasGMPermissions())
continue;
++total_count;
// Add by default, if we don't have any checks
add = true;
// Chat name
if(cname && chatname != *plr->GetNameString())
continue;
// Level check
lvl = plr->m_uint32Values[UNIT_FIELD_LEVEL];
if(min_level && max_level)
{
// skip players outside of level range
if(lvl < min_level || lvl > max_level)
continue;
}
// Zone id compare
if(zone_count)
{
// people that fail the zone check don't get added
add = false;
for(i = 0; i < zone_count; ++i)
{
if(zones[i] == plr->GetZoneId())
{
add = true;
break;
}
}
}
// skip players that fail zone check
if(!add)
continue;
// name check
if(name_count)
{
// people that fail name check don't get added
add = false;
for(i = 0; i < name_count; ++i)
{
if(!strnicmp(names[i].c_str(), plr->GetName(), names[i].length()))
{
add = true;
break;
}
}
}
if(!add)
continue;
// if we're here, it means we've passed all testing
// so add the names :)
data << plr->GetName();
if(plr->myGuild)
data << plr->myGuild->GetGuildName();
else
data << uint8(0); // Guild name
data << plr->m_uint32Values[UNIT_FIELD_LEVEL];
data << uint32(plr->getClass());
data << uint32(plr->getRace());
data << uint32(plr->GetZoneId());
++sent_count;
}
objmgr._playerslock.ReleaseReadLock();
data.wpos(0);
data << sent_count;
data << sent_count;
SendPacket(&data);
// free up used memory
if(zones)
delete [] zones;
if(names)
delete [] names;
}
void WorldSession::HandleLogoutRequestOpcode( WorldPacket & recv_data )
{
WorldPacket data(SMSG_LOGOUT_RESPONSE, 9);
sLog.outDebug( "WORLD: Recvd CMSG_LOGOUT_REQUEST Message" );
Player *pPlayer = GetPlayer();
if(pPlayer)
{
if(pPlayer->m_isResting || // We are resting so log out instantly
pPlayer->GetTaxiState() || // or we are on a taxi
HasGMPermissions()) // or we are a gm
{
/* full remove from group */
if(_player->m_Group)
_player->m_Group->RemovePlayer(_player->m_playerInfo, _player, true);
LogoutPlayer(true);
return;
}
if(pPlayer->DuelingWith != NULL || pPlayer->isInCombat())
{
//can't quit still dueling or attacking
data << uint32(0x1); //Filler
data << uint8(0); //Logout accepted
SendPacket( &data );
return;
}
data << uint32(0); //Filler
data << uint8(0); //Logout accepted
SendPacket( &data );
//stop player from moving
pPlayer->SetMovement(MOVE_ROOT,1);
// Set the "player locked" flag, to prevent movement
pPlayer->SetFlag( UNIT_FIELD_FLAGS, U_FIELD_FLAG_LOCK_PLAYER );
//make player sit
pPlayer->SetStandState(STANDSTATE_SIT);
SetLogoutTimer(20000);
}
/*
> 0 = You can't Logout Now
*/
}
void WorldSession::HandlePlayerLogoutOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Recvd CMSG_PLAYER_LOGOUT Message" );
if(!_logoutTime && !HasGMPermissions())
{
// send "You do not have permission to use this"
SendNotification(NOTIFICATION_MESSAGE_NO_PERMISSION);
} else {
LogoutPlayer(true);
}
}
void WorldSession::HandleLogoutCancelOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Recvd CMSG_LOGOUT_CANCEL Message" );
Player *pPlayer = GetPlayer();
if(!pPlayer)
return;
//Cancel logout Timer
SetLogoutTimer(0);
//tell client about cancel
OutPacket(SMSG_LOGOUT_CANCEL_ACK);
//unroot player
pPlayer->SetMovement(MOVE_UNROOT,5);
// Remove the "player locked" flag, to allow movement
pPlayer->RemoveFlag( UNIT_FIELD_FLAGS, U_FIELD_FLAG_LOCK_PLAYER );
//make player stand
pPlayer->SetStandState(STANDSTATE_STAND);
sLog.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" );
}
void WorldSession::HandleZoneUpdateOpcode( WorldPacket & recv_data )
{
uint32 newZone;
WPAssert(GetPlayer());
recv_data >> newZone;
if (GetPlayer()->GetZoneId() == newZone)
return;
sWeatherMgr.SendWeather(GetPlayer());
_player->ZoneUpdate(newZone);
//clear buyback
_player->GetItemInterface()->EmptyBuyBack();
}
void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data )
{
uint64 guid ;
recv_data >> guid;
if( GetPlayer( ) != 0 ){
GetPlayer( )->SetTarget(guid);
}
if(guid == 0 && _player->getAttackTarget())
_player->setAttackTarget(0);
}
void WorldSession::HandleSetSelectionOpcode( WorldPacket & recv_data )
{
uint64 guid;
recv_data >> guid;
_player->SetSelection(guid);
if(_player->m_comboPoints)
_player->UpdateComboPoints();
_player->SetUInt64Value(UNIT_FIELD_TARGET, guid);
if(guid == 0 && _player->getAttackTarget())
_player->setAttackTarget(0);
}
void WorldSession::HandleStandStateChangeOpcode( WorldPacket & recv_data )
{
uint8 animstate;
recv_data >> animstate;
_player->SetStandState(animstate);
}
void WorldSession::HandleFriendListOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Received CMSG_FRIEND_LIST" );
sSocialMgr.SendFriendList( GetPlayer() );
sSocialMgr.SendIgnoreList( GetPlayer() );
}
void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Received CMSG_ADD_FRIEND" );
std::string friendName = "UNKNOWN";
recv_data >> friendName;
sSocialMgr.AddFriend( GetPlayer(), friendName );
}
void WorldSession::HandleDelFriendOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Received CMSG_DEL_FRIEND" );
uint64 FriendGuid;
recv_data >> FriendGuid;
sSocialMgr.DelFriend( GetPlayer(), FriendGuid );
}
void WorldSession::HandleAddIgnoreOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Received CMSG_ADD_IGNORE" );
std::string ignoreName = "UNKNOWN";
recv_data >> ignoreName;
sSocialMgr.AddIgnore( GetPlayer(), ignoreName );
}
void WorldSession::HandleDelIgnoreOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Received CMSG_DEL_IGNORE" );
uint64 IgnoreGuid;
recv_data >> IgnoreGuid;
sSocialMgr.DelIgnore( GetPlayer(), IgnoreGuid );
}
void WorldSession::HandleBugOpcode( WorldPacket & recv_data )
{
uint32 suggestion, contentlen;
std::string content;
uint32 typelen;
std::string type;
recv_data >> suggestion >> contentlen >> content >> typelen >> type;
if( suggestion == 0 )
sLog.outDebug( "WORLD: Received CMSG_BUG [Bug Report]" );
else
sLog.outDebug( "WORLD: Received CMSG_BUG [Suggestion]" );
sLog.outDebug( type.c_str( ) );
sLog.outDebug( content.c_str( ) );
}
void WorldSession::HandleCorpseReclaimOpcode(WorldPacket &recv_data)
{
if(_player->isAlive())
return;
sLog.outDetail("WORLD: Received CMSG_RECLAIM_CORPSE");
uint64 guid;
recv_data >> guid;
// Check that we're reviving from a corpse, and that corpse is associated with us.
Corpse * pCorpse = objmgr.GetCorpse(guid);
if(pCorpse == 0) return;
if(pCorpse == 0 ||
pCorpse->GetUInt64Value(CORPSE_FIELD_OWNER) != _player->GetGUID() &&
pCorpse->GetUInt32Value(CORPSE_FIELD_FLAGS) == 5)
{
WorldPacket data(SMSG_RESURRECT_FAILED, 4);
data << uint32(1); // this is a real guess!
SendPacket(&data);
return;
}
GetPlayer()->ResurrectPlayer();
GetPlayer()->SetUInt32Value(UNIT_FIELD_HEALTH, GetPlayer()->GetUInt32Value(UNIT_FIELD_MAXHEALTH)/2 );
}
void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data)
{
if(!_player->IsInWorld()) return;
sLog.outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE");
if(GetPlayer()->isAlive())
return;
uint64 guid;
uint8 status;
recv_data >> guid;
recv_data >> status;
// need to check guid
Player * pl = _player->GetMapMgr()->GetPlayer(guid);
if(!pl)
pl = objmgr.GetPlayer(guid);
if(pl == 0 || status != 1)
{
_player->m_resurrectHealth = 0;
_player->m_resurrectMana = 0;
return;
}
_player->ResurrectPlayer();
_player->SetMovement(MOVE_UNROOT, 1);
}
void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data)
{
sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA");
uint32 uiID;
recv_data >> uiID;
if(uiID > 8)
{
// Shit..
sLog.outString("WARNING: Accountdata > 8 (%d) was requested to be updated by %s of account %d!", uiID, GetPlayer()->GetName(), this->GetAccountId());
return;
}
uint32 uiDecompressedSize;
recv_data >> uiDecompressedSize;
uLongf uid = uiDecompressedSize;
// client wants to 'erase' current entries
if(uiDecompressedSize == 0)
{
SetAccountData(uiID, NULL, false,0);
return;
}
uint32 ReceivedPackedSize = recv_data.size() - 8;
char* data = new char[uiDecompressedSize+1];
memset(data,0,uiDecompressedSize+1); /* fix umr here */
if(uiDecompressedSize > ReceivedPackedSize) // if packed is compressed
{
int32 ZlibResult;
ZlibResult = uncompress((uint8*)data, &uid, recv_data.contents() + 8, ReceivedPackedSize);
switch (ZlibResult)
{
case Z_OK: //0 no error decompression is OK
SetAccountData(uiID, data, false,uiDecompressedSize);
sLog.outDetail("WORLD: Successfully decompressed account data %d for %s, and updated storage array.", uiID, GetPlayer()->GetName());
break;
case Z_ERRNO: //-1
case Z_STREAM_ERROR: //-2
case Z_DATA_ERROR: //-3
case Z_MEM_ERROR: //-4
case Z_BUF_ERROR: //-5
case Z_VERSION_ERROR: //-6
{
delete [] data;
sLog.outString("WORLD WARNING: Decompression of account data %d for %s FAILED.", uiID, GetPlayer()->GetName());
break;
}
default:
delete [] data;
sLog.outString("WORLD WARNING: Decompression gave a unknown error: %x, of account data %d for %s FAILED.", ZlibResult, uiID, GetPlayer()->GetName());
break;
}
}
else
{
memcpy(data,recv_data.contents() + 8,uiDecompressedSize);
SetAccountData(uiID, data, false,uiDecompressedSize);
}
}
void WorldSession::HandleRequestAccountData(WorldPacket& recv_data)
{
sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA");
uint32 id;
recv_data >> id;
if(id > 8)
{
// Shit..
sLog.outString("WARNING: Accountdata > 8 (%d) was requested by %s of account %d!", id, GetPlayer()->GetName(), this->GetAccountId());
return;
}
AccountDataEntry* res = GetAccountData(id);
WorldPacket data ;
data.SetOpcode(SMSG_UPDATE_ACCOUNT_DATA);
data << id;
// if red does not exists if ID == 7 and if there is no data send 0
if (!res || !res->data) // if error, send a NOTHING packet
{
data << (uint32)0;
}
else
{
data << res->sz;
uLongf destsize;
if(res->sz>200)
{
data.resize( res->sz+800 ); // give us plenty of room to work with..
if ( ( compress(const_cast(data.contents()) + (sizeof(uint32)*2), &destsize, (const uint8*)res->data, res->sz)) != Z_OK)
{
sLog.outError("Error while compressing ACCOUNT_DATA");
return;
}
data.resize(destsize+8);
}
else
data.append( res->data,res->sz);
}
SendPacket(&data);
}
void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data)
{
sLog.outDebug( "WORLD: Received CMSG_SET_ACTION_BUTTON" );
uint8 button, misc, type;
uint16 action;
recv_data >> button >> action >> misc >> type;
sLog.outDebug( "BUTTON: %u ACTION: %u TYPE: %u MISC: %u", button, action, type, misc );
if(action==0)
{
sLog.outDebug( "MISC: Remove action from button %u", button );
//remove the action button from the db
GetPlayer()->setAction(button, 0, 0, 0);
}
else
{
if(button >= 120)
return;
if(type == 64 || type == 65)
{
sLog.outDebug( "MISC: Added Macro %u into button %u", action, button );
GetPlayer()->setAction(button,action,misc,type);
}
else if(type == 128)
{
sLog.outDebug( "MISC: Added Item %u into button %u", action, button );
GetPlayer()->setAction(button,action,misc,type);
}
else if(type == 0)
{
sLog.outDebug( "MISC: Added Spell %u into button %u", action, button );
GetPlayer()->setAction(button,action,type,misc);
}
}
}
void WorldSession::HandleSetWatchedFactionIndexOpcode(WorldPacket &recvPacket)
{
uint32 factionid;
recvPacket >> factionid;
GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, factionid);
}
void WorldSession::HandleTogglePVPOpcode(WorldPacket& recv_data)
{
_player->PvPToggle();
}
void WorldSession::HandleAmmoSetOpcode(WorldPacket & recv_data)
{
uint32 ammoId;
recv_data >> ammoId;
ItemPrototype * xproto=ItemPrototypeStorage.LookupEntry(ammoId);
if(!xproto)
return;
if(xproto->Class != ITEM_CLASS_PROJECTILE || GetPlayer()->GetItemInterface()->GetItemCount(ammoId) == 0)
{
sCheatLog.writefromsession(GetPlayer()->GetSession(), "Definately cheating. tried to add %u as ammo.", ammoId);
GetPlayer()->GetSession()->Disconnect();
return;
}
_player->SetUInt32Value(PLAYER_AMMO_ID, ammoId);
_player->CalcDamage();
}
#define OPEN_CHEST 11437
void WorldSession::HandleGameObjectUse(WorldPacket & recv_data)
{
if(!_player->IsInWorld()) return;
uint64 guid;
recv_data >> guid;
SpellCastTargets targets;
Spell *spell = NULL;;
SpellEntry *spellInfo = NULL;;
sLog.outDebug("WORLD: CMSG_GAMEOBJ_USE: [GUID %d]", guid);
GameObject *obj = _player->GetMapMgr()->GetGameObject(guid);
if (!obj) return;
GameObjectInfo *goinfo= obj->GetInfo();
if (!goinfo) return;
Player *plyr = GetPlayer();
CALL_GO_SCRIPT_EVENT(obj, OnActivate)(_player);
ScriptSystem->OnGameObjectEvent(obj, _player, GAMEOBJECT_EVENT_ON_USE);
uint32 type = obj->GetUInt32Value(GAMEOBJECT_TYPE_ID);
switch (type)
{
case GAMEOBJECT_TYPE_CHAIR:
{
/// if players are mounted they are not able to sit on a chair
if( plyr->IsMounted() )
return;
WorldPacket data(MSG_MOVE_HEARTBEAT, 66);
data << plyr->GetNewGUID();
data << uint64(0);
data << obj->GetPositionX() << obj->GetPositionY() << obj->GetPositionZ() << obj->GetOrientation();
plyr->SendMessageToSet(&data, true);
plyr->SetStandState(STANDSTATE_SIT_MEDIUM_CHAIR);
}break;
case GAMEOBJECT_TYPE_CHEST://cast da spell
{
spellInfo = sSpellStore.LookupEntry( OPEN_CHEST );
spell = new Spell(plyr, spellInfo, true, NULL);
_player->m_currentSpell = spell;
targets.m_unitTarget = obj->GetGUID();
spell->prepare(&targets);
}break;
case GAMEOBJECT_TYPE_FISHINGNODE:
{
obj->UseFishingNode(plyr);
}break;
case GAMEOBJECT_TYPE_DOOR:
{
// door
if((obj->GetUInt32Value(GAMEOBJECT_STATE) == 1) && (obj->GetUInt32Value(GAMEOBJECT_FLAGS) == 33))
obj->EventCloseDoor();
else
{
obj->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
obj->SetUInt32Value(GAMEOBJECT_STATE, 0);
sEventMgr.AddEvent(obj,&GameObject::EventCloseDoor,EVENT_GAMEOBJECT_DOOR_CLOSE,20000,1,0);
}
}break;
case GAMEOBJECT_TYPE_FLAGSTAND:
{
// battleground/warsong gulch flag
if(plyr->m_bg)
plyr->m_bg->HookFlagStand(plyr, obj);
}break;
case GAMEOBJECT_TYPE_FLAGDROP:
{
// Dropped flag
if(plyr->m_bg)
plyr->m_bg->HookFlagDrop(plyr, obj);
}break;
case GAMEOBJECT_TYPE_QUESTGIVER:
{
// Questgiver
if(obj->HasQuests())
{
sQuestMgr.OnActivateQuestGiver(obj, plyr);
}
}break;
case GAMEOBJECT_TYPE_SPELLCASTER:
{
SpellEntry *info = sSpellStore.LookupEntry(goinfo->SpellFocus);
if(!info)
break;
Spell * spell = new Spell(plyr, info, false, NULL);
//spell->SpellByOther = true;
SpellCastTargets targets;
targets.m_unitTarget = plyr->GetGUID();
spell->prepare(&targets);
if(obj->charges>0 && !--obj->charges)
obj->ExpireAndDelete();
}break;
case GAMEOBJECT_TYPE_RITUAL:
{
// store the members in the ritual, cast sacrifice spell, and summon.
uint32 i = 0;
if(!obj->m_ritualmembers || !obj->m_ritualspell || !obj->m_ritualcaster /*|| !obj->m_ritualtarget*/)
return;
for(i=0;iSpellFocus;i++)
{
if(!obj->m_ritualmembers[i])
{
obj->m_ritualmembers[i] = plyr->GetGUIDLow();
plyr->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, obj->GetGUID());
plyr->SetUInt32Value(UNIT_CHANNEL_SPELL, obj->m_ritualspell);
break;
}else if(obj->m_ritualmembers[i] == plyr->GetGUIDLow())
{
// we're deselecting :(
obj->m_ritualmembers[i] = 0;
plyr->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
plyr->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
return;
}
}
if(i == goinfo->SpellFocus - 1)
{
obj->m_ritualspell = 0;
Player * plr;
for(i=0;iSpellFocus;i++)
{
plr = _player->GetMapMgr()->GetPlayer(obj->m_ritualmembers[i]);
if(plr)
{
plr->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
plr->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
}
SpellEntry *info = NULL;
if(goinfo->ID == 36727) // summon portal
{
if(!obj->m_ritualtarget)
return;
info = sSpellStore.LookupEntry(goinfo->sound1);
if(!info)
break;
Player * target = _player->GetMapMgr()->GetPlayer(obj->m_ritualtarget);
if(!target)
return;
spell = new Spell(obj,info,true,NULL);
SpellCastTargets targets;
targets.m_unitTarget = target->GetGUID();
spell->prepare(&targets);
}
else if(goinfo->ID == 177193) // doom portal
{
Player *psacrifice = NULL;
Spell * spell = NULL;
// kill the sacrifice player
psacrifice = _player->GetMapMgr()->GetPlayer(obj->m_ritualmembers[(int)(rand()%(goinfo->SpellFocus-1))]);
Player * pCaster = obj->GetMapMgr()->GetPlayer(obj->m_ritualcaster);
if(!psacrifice || !pCaster)
return;
info = sSpellStore.LookupEntry(goinfo->sound4);
if(!info)
break;
spell = new Spell(psacrifice, info, true, NULL);
targets.m_unitTarget = psacrifice->GetGUID();
spell->prepare(&targets);
// summons demon
info = sSpellStore.LookupEntry(goinfo->sound1);
spell = new Spell(pCaster, info, true, NULL);
SpellCastTargets targets;
targets.m_unitTarget = pCaster->GetGUID();
spell->prepare(&targets);
}
else if(goinfo->ID == 179944) // Summoning portal for meeting stones
{
Player * plr = _player->GetMapMgr()->GetPlayer(obj->m_ritualtarget);
if(!plr)
return;
Player * pleader = _player->GetMapMgr()->GetPlayer(obj->m_ritualcaster);
if(!pleader)
return;
info = sSpellStore.LookupEntry(goinfo->sound1);
Spell * spell = new Spell(pleader, info, true, 0);
SpellCastTargets targets(plr->GetGUID());
spell->prepare(&targets);
/* expire the gameobject */
obj->ExpireAndDelete();
}
}
}break;
case GAMEOBJECT_TYPE_GOOBER:
{
//Quest related mostly
}
case GAMEOBJECT_TYPE_CAMERA://eye of azora
{
/*WorldPacket pkt(SMSG_TRIGGER_CINEMATIC,4);
pkt << (uint32)1;//i ve found only on such item,id =1
SendPacket(&pkt);*/
/* these are usually scripted effects. but in the case of some, (e.g. orb of translocation) the spellid is located in unknown1 */
SpellEntry * sp = static_cast*>(SpellStore::getSingletonPtr())->LookupEntryForced(goinfo->Unknown1);
if(sp != NULL)
_player->CastSpell(_player,sp,true);
}break;
case GAMEOBJECT_TYPE_MEETINGSTONE: // Meeting Stone
{
/* Use selection */
Player * pPlayer = objmgr.GetPlayer(_player->GetSelection());
if(!pPlayer || _player->m_Group != pPlayer->m_Group || !_player->m_Group)
return;
GameObjectInfo * info = GameObjectNameStorage.LookupEntry(179944);
if(!info)
return;
/* Create the summoning portal */
GameObject * pGo = _player->GetMapMgr()->CreateGameObject();
pGo->CreateFromProto(179944, _player->GetMapId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), 0);
pGo->m_ritualcaster = _player->GetGUIDLow();
pGo->m_ritualtarget = pPlayer->GetGUIDLow();
pGo->m_ritualspell = 18540; // meh
pGo->PushToWorld(_player->GetMapMgr());
/* member one: the (w00t) caster */
pGo->m_ritualmembers[0] = _player->GetGUIDLow();
_player->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pGo->GetGUID());
_player->SetUInt32Value(UNIT_CHANNEL_SPELL, pGo->m_ritualspell);
/* expire after 2mins*/
sEventMgr.AddEvent(pGo, &GameObject::_Expire, EVENT_GAMEOBJECT_EXPIRE, 120000, 1,0);
}break;
}
}
void WorldSession::HandleTutorialFlag( WorldPacket & recv_data )
{
uint32 iFlag;
recv_data >> iFlag;
uint32 wInt = (iFlag / 32);
uint32 rInt = (iFlag % 32);
uint32 tutflag = GetPlayer()->GetTutorialInt( wInt );
tutflag |= (1 << rInt);
GetPlayer()->SetTutorialInt( wInt, tutflag );
sLog.outDebug("Received Tutorial Flag Set {%u}.", iFlag);
}
void WorldSession::HandleTutorialClear( WorldPacket & recv_data )
{
for ( uint32 iI = 0; iI < 8; iI++)
GetPlayer()->SetTutorialInt( iI, 0xFFFFFFFF );
}
void WorldSession::HandleTutorialReset( WorldPacket & recv_data )
{
for ( uint32 iI = 0; iI < 8; iI++)
GetPlayer()->SetTutorialInt( iI, 0x00000000 );
}
void WorldSession::HandleSetSheathedOpcode( WorldPacket & recv_data )
{
uint32 active;
recv_data >> active;
_player->SetByte(UNIT_FIELD_BYTES_2,0,active);
}
void WorldSession::HandlePlayedTimeOpcode( WorldPacket & recv_data )
{
uint32 playedt = (uint32)time(NULL) - _player->m_playedtime[2];
if(playedt)
{
_player->m_playedtime[0] += playedt;
_player->m_playedtime[1] += playedt;
_player->m_playedtime[2] += playedt;
}
WorldPacket data(SMSG_PLAYED_TIME, 8);
data << (uint32)_player->m_playedtime[1];
data << (uint32)_player->m_playedtime[0];
SendPacket(&data);
}
void WorldSession::HandleSetActionBarTogglesOpcode(WorldPacket &recvPacket)
{
uint8 cActionBarId;
recvPacket >> cActionBarId;
sLog.outDebug("Received CMSG_SET_ACTIONBAR_TOGGLES for actionbar id %d.", cActionBarId);
GetPlayer()->SetByte(PLAYER_FIELD_BYTES,2, cActionBarId);
}
// Handlers for acknowledgement opcodes (removes some 'unknown opcode' flood from the logs)
void WorldSession::HandleAcknowledgementOpcodes( WorldPacket & recv_data )
{
/* uint16 opcode = recv_data.GetOpcode();
std::stringstream ss;
ss << "Received ";
switch( opcode )
{
case CMSG_MOVE_FEATHER_FALL_ACK: ss << "Move_Feather_Fall"; break;
case CMSG_MOVE_WATER_WALK_ACK: ss << "Move_Water_Walk"; break;
case CMSG_MOVE_KNOCK_BACK_ACK: ss << "Move_Knock_Back"; break;
case CMSG_MOVE_HOVER_ACK: ss << "Move_Hover"; break;
case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: ss << "Force_Walk_Speed_Change"; break;
case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: ss << "Force_Swim_Speed_Change"; break;
case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: ss << "Force_Swim_Back_Speed_Change"; break;
case CMSG_FORCE_TURN_RATE_CHANGE_ACK: ss << "Force_Turn_Rate_Change"; break;
case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: ss << "Force_Run_Speed_Change"; break;
case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: ss << "Force_Run_Back_Speed_Change"; break;
case CMSG_FORCE_MOVE_ROOT_ACK: ss << "Force_Move_Root"; break;
case CMSG_FORCE_MOVE_UNROOT_ACK: ss << "Force_Move_Unroot"; break;
default: ss << "Unknown"; break;
}
ss << " Acknowledgement. PktSize: " << recv_data.size();
sLog.outDebug( ss.str().c_str() );*/
/*uint16 opcode = recv_data.GetOpcode();
if (opcode == CMSG_FORCE_RUN_SPEED_CHANGE_ACK)
{
uint64 GUID;
uint32 Flags, unk0, unk1, d_time;
float X, Y, Z, O, speed;
recv_data >> GUID;
recv_data >> unk0 >> Flags;
if (Flags & (0x2000 | 0x6000)) //0x2000 == jumping 0x6000 == Falling
{
uint32 unk2, unk3, unk4, unk5;
float OldSpeed;
recv_data >> d_time;
recv_data >> X >> Y >> Z >> O;
recv_data >> unk2 >> unk3; //no idea, maybe unk2 = flags2
recv_data >> unk4 >> unk5; //no idea
recv_data >> OldSpeed >> speed;
}
else //single check
{
recv_data >> d_time;
recv_data >> X >> Y >> Z >> O;
recv_data >> unk1 >> speed;
}
// if its not good kick player???
if (_player->GetPlayerSpeed() != speed)
{
sLog.outError("SpeedChange player:%s is NOT correct, its set to: %f he seems to be cheating",_player->GetName(), speed);
}
}*/
}
void WorldSession::HandleSelfResurrectOpcode(WorldPacket& recv_data)
{
uint32 self_res_spell = _player->GetUInt32Value(PLAYER_SELF_RES_SPELL);
if(self_res_spell)
{
SpellEntry * sp=sSpellStore.LookupEntry(self_res_spell);
Spell *s=new Spell(_player,sp,true,NULL);
SpellCastTargets tgt;
tgt.m_unitTarget=_player->GetGUID();
s->prepare(&tgt);
}
}
void WorldSession::HandleRandomRollOpcode(WorldPacket &recv_data)
{
uint32 min, max;
recv_data >> min >> max;
sLog.outDetail("WORLD: Received MSG_RANDOM_ROLL: %u-%u", min, max);
WorldPacket data(20);
data.SetOpcode(MSG_RANDOM_ROLL);
data << min << max;
uint32 roll;
// generate number
roll = min + int( ((max-min)+1) * rand() / (RAND_MAX + 1.0) );
// append to packet, and guid
data << roll << _player->GetGUID();
// send to set
if(_player->InGroup())
_player->GetGroup()->SendPacketToAll(&data);
else
GetPlayer()->SendMessageToSet(&data, true, true);
}
void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recv_data)
{
if(!_player->IsInWorld()) return;
// uint8 slot = 0;
uint32 itemid = 0;
uint32 amt = 1;
uint8 error = 0;
SlotResult slotresult;
Creature *pCreature = NULL;
Loot *pLoot = NULL;
/* struct:
{CLIENT} Packet: (0x02A3) CMSG_LOOT_MASTER_GIVE PacketSize = 17
|------------------------------------------------|----------------|
|00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF|
|------------------------------------------------|----------------|
|39 23 05 00 81 02 27 F0 01 7B FC 02 00 00 00 00 |9#....'..{......|
|00 |. |
-------------------------------------------------------------------
uint64 creatureguid
uint8 slotid
uint64 target_playerguid
*/
uint64 creatureguid, target_playerguid;
uint8 slotid;
recv_data >> creatureguid >> slotid >> target_playerguid;
Player *player = _player->GetMapMgr()->GetPlayer(target_playerguid);
if(!player)
return;
// cheaterz!
if(_player->GetLootGUID() != creatureguid)
return;
//now its time to give the loot to the target player
if(UINT32_LOPART(GUID_HIPART(GetPlayer()->GetLootGUID())) == HIGHGUID_UNIT)
{
pCreature = _player->GetMapMgr()->GetCreature((creatureguid));
if (!pCreature)return;
pLoot=&pCreature->loot;
}
if(!pLoot) return;
if (slotid >= pLoot->items.size())
{
sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %d)",
GetPlayer()->GetName(), slotid, pLoot->items.size());
return;
}
amt = pLoot->items.at(slotid).iItemsCount;
if (!amt)//Test for party loot
{
GetPlayer()->GetItemInterface()->BuildInventoryChangeError(NULL, NULL,INV_ERR_ALREADY_LOOTED);
return;
}
itemid = pLoot->items.at(slotid).item.itemid;
ItemPrototype* it = ItemPrototypeStorage.LookupEntry(itemid);
if((error = player->GetItemInterface()->CanReceiveItem(it, 1)))
{
_player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, error);
return;
}
if(pCreature)
CALL_SCRIPT_EVENT(pCreature, OnLootTaken)(player, it);
slotresult = player->GetItemInterface()->FindFreeInventorySlot(it);
if(!slotresult.Result)
{
GetPlayer()->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_INVENTORY_FULL);
return;
}
Item *item = objmgr.CreateItem( itemid, player);
item->SetUInt32Value(ITEM_FIELD_STACK_COUNT,amt);
uint32 rndprop=pLoot->items.at(slotid).iRandomProperty;
if(rndprop)
item->SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID,rndprop);
item->ApplyRandomProperties();
player->GetItemInterface()->SafeAddItem(item,slotresult.ContainerSlot, slotresult.Slot);
sQuestMgr.OnPlayerItemPickup(player,item);
pLoot->items.at(slotid).iItemsCount=0;
// this gets sent to all looters
WorldPacket data(1);
data.SetOpcode(SMSG_LOOT_REMOVED);
data << slotid;
Player * plr;
for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); ++itr)
{
if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
plr->GetSession()->SendPacket(&data);
}
WorldPacket idata(45);
if(it->Class == ITEM_CLASS_QUEST)
{
uint32 pcount = player->GetItemInterface()->GetItemCount(it->ItemId, true);
BuildItemPushResult(&idata, GetPlayer()->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(slotid).iRandomProperty,0xFF,0,0xFFFFFFFF,pcount);
}
else
{
BuildItemPushResult(&idata, player->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(slotid).iRandomProperty);
}
if(_player->InGroup())
_player->GetGroup()->SendPacketToAll(&idata);
else
SendPacket(&idata);
}
void WorldSession::HandleLootRollOpcode(WorldPacket& recv_data)
{
if(!_player->IsInWorld()) return;
/* struct:
{CLIENT} Packet: (0x02A0) CMSG_LOOT_ROLL PacketSize = 13
|------------------------------------------------|----------------|
|00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF|
|------------------------------------------------|----------------|
|11 4D 0B 00 BD 06 01 F0 00 00 00 00 02 |.M........... |
-------------------------------------------------------------------
uint64 creatureguid
uint21 slotid
uint8 choice
*/
uint64 creatureguid;
uint32 slotid;
uint8 choice;
recv_data >> creatureguid >> slotid >> choice;
Creature *pCreature = _player->GetMapMgr()->GetCreature(creatureguid);
if(!pCreature)
{
return;
}
LootRoll *li = NULL;
if(slotid >= pCreature->loot.items.size() || pCreature->loot.items.size()==0)
{
return;
} else {
li = pCreature->loot.items[slotid].roll;
}
if(!li)
return;
li->PlayerRolled(_player, choice);
}
void WorldSession::HandleOpenItemOpcode(WorldPacket &recv_data)
{
if(!_player->IsInWorld()) return;
CHECK_PACKET_SIZE(recv_data, 2);
int8 slot, containerslot;
recv_data >> containerslot >> slot;
Item *pItem = _player->GetItemInterface()->GetInventoryItem(containerslot, slot);
if(!pItem)
return;
Lock *lock = sLockStore.LookupEntry( pItem->GetProto()->LockId );
uint32 removeLockItems[5] = {0,0,0,0,0};
if(lock) // locked item
{
for(int i=0;i<5;i++)
{
if(lock->locktype[i] == 1 && lock->lockmisc[i] > 0)
{
int8 slot = _player->GetItemInterface()->GetInventorySlotById(lock->lockmisc[i]);
if(slot != ITEM_NO_SLOT_AVAILABLE && slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END)
{
removeLockItems[i] = lock->lockmisc[i];
}
else
{
_player->GetItemInterface()->BuildInventoryChangeError(pItem,NULL,INV_ERR_ITEM_LOCKED);
return;
}
}
else if(lock->locktype[i] == 2 && pItem->locked)
{
_player->GetItemInterface()->BuildInventoryChangeError(pItem,NULL,INV_ERR_ITEM_LOCKED);
return;
}
}
for(int i=0;i<5;i++)
if(removeLockItems[i])
_player->GetItemInterface()->RemoveItemAmt(removeLockItems[i],1);
}
// fill loot
_player->SetLootGUID(pItem->GetGUID());
if(!pItem->loot)
{
pItem->loot = new Loot;
lootmgr.FillItemLoot(pItem->loot, pItem->GetEntry());
}
_player->SendLoot(pItem->GetGUID(), 5);
}
void WorldSession::HandleCompleteCinematic(WorldPacket &recv_data)
{
// when a Cinematic is started the player is going to sit down, when its finished its standing up.
_player->SetStandState(STANDSTATE_STAND);
};
void WorldSession::HandleResetInstanceOpcode(WorldPacket& recv_data)
{
sInstanceSavingManager.ResetSavedInstancesForPlayer(_player);
}
void EncodeHex(const char* source, char* dest, uint32 size)
{
char temp[5];
for(uint32 i = 0; i < size; ++i)
{
snprintf(temp, 5, "%02X", source[i]);
strcat(dest, temp);
}
}
void DecodeHex(const char* source, char* dest, uint32 size)
{
char temp;
char* acc = const_cast(source);
for(uint32 i = 0; i < size; ++i)
{
sscanf("%02X", &temp);
acc = ((char*)&source[2]);
strcat(dest, &temp);
}
}
void WorldSession::HandleToggleCloakOpcode(WorldPacket &recv_data)
{
//////////////////////////
// PLAYER_FLAGS = 3104 / 0x00C20 / 0000000000000000000110000100000
// ^
// This bit, on = toggled OFF, off = toggled ON.. :S
//uint32 SetBit = 0 | (1 << 11);
if(_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_NOCLOAK))
_player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAG_NOCLOAK);
else
_player->SetFlag(PLAYER_FLAGS, PLAYER_FLAG_NOCLOAK);
}
void WorldSession::HandleToggleHelmOpcode(WorldPacket &recv_data)
{
//////////////////////////
// PLAYER_FLAGS = 3104 / 0x00C20 / 0000000000000000000110000100000
// ^
// This bit, on = toggled OFF, off = toggled ON.. :S
//uint32 SetBit = 0 | (1 << 10);
if(_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_NOHELM))
_player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAG_NOHELM);
else
_player->SetFlag(PLAYER_FLAGS, PLAYER_FLAG_NOHELM);
}
void WorldSession::HandleDungeonDifficultyOpcode(WorldPacket& recv_data)
{
uint32 data;
recv_data >> data;
_player->iInstanceType = data;
sInstanceSavingManager.ResetSavedInstancesForPlayer(_player);
}
void WorldSession::HandleSummonResponseOpcode(WorldPacket & recv_data)
{
if(!_player->m_summoner)
{
SendNotification(NOTIFICATION_MESSAGE_NO_PERMISSION);
return;
}
if(_player->isInCombat())
return;
_player->SafeTeleport(_player->m_summonMapId, _player->m_summonInstanceId,
_player->m_summonPos);
_player->m_summoner = _player->m_summonInstanceId = _player->m_summonMapId = 0;
}
void WorldSession::HandleDismountOpcode(WorldPacket& recv_data)
{
sLog.outDebug( "WORLD: Received CMSG_DISMOUNT" );
if( !_player->IsInWorld() || _player->GetTaxiState())
return;
if( _player->m_MountSpellId )
_player->RemoveAura( _player->m_MountSpellId );
}