mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[8103] More wide use IsInWorld checks and delayed at teleport operations.
* IsInWorld used to prevent return unexpected not in world objects. * Delayed operations need to process its in world state. Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
parent
9f41772828
commit
9f938a9ed4
17 changed files with 220 additions and 40 deletions
|
|
@ -75,7 +75,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
|||
uint64 guid = MAKE_NEW_GUID(guidlo, 0, HIGHGUID_PLAYER);
|
||||
|
||||
// kick if player currently
|
||||
if(Player* p = ObjectAccessor::FindPlayer(guid))
|
||||
if(Player* p = ObjectAccessor::GetObjectInWorld(guid, (Player*)NULL))
|
||||
{
|
||||
WorldSession* s = p->GetSession();
|
||||
s->KickPlayer(); // mark session to remove at next session list update
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Language.h"
|
||||
#include "MapManager.h"
|
||||
|
||||
#include "Policies/SingletonImp.h"
|
||||
|
||||
|
|
@ -825,8 +826,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
|||
if(!miscvalue1)
|
||||
continue;
|
||||
|
||||
Map const* map = GetPlayer()->GetMap();
|
||||
if(!map->IsDungeon())
|
||||
Map const* map = GetPlayer()->IsInWorld() ? GetPlayer()->GetMap() : MapManager::Instance().FindMap(GetPlayer()->GetMapId(), GetPlayer()->GetInstanceId());
|
||||
if(!map || !map->IsDungeon())
|
||||
continue;
|
||||
|
||||
// search case
|
||||
|
|
|
|||
|
|
@ -70,7 +70,13 @@ void GameObject::CleanupsBeforeDelete()
|
|||
// Possible crash at access to deleted GO in Unit::m_gameobj
|
||||
if(uint64 owner_guid = GetOwnerGUID())
|
||||
{
|
||||
if(Unit* owner = ObjectAccessor::GetUnit(*this,owner_guid))
|
||||
Unit* owner = NULL;
|
||||
if(IS_PLAYER_GUID(owner_guid))
|
||||
owner = ObjectAccessor::GetObjectInWorld(owner_guid, (Player*)NULL);
|
||||
else
|
||||
owner = ObjectAccessor::GetUnit(*this,owner_guid);
|
||||
|
||||
if(owner)
|
||||
owner->RemoveGameObject(this,false);
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -963,7 +963,7 @@ void Group::SendUpdate()
|
|||
|
||||
void Group::UpdatePlayerOutOfRange(Player* pPlayer)
|
||||
{
|
||||
if(!pPlayer)
|
||||
if(!pPlayer || !pPlayer->IsInWorld())
|
||||
return;
|
||||
|
||||
Player *player;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ static void AttemptJoin(Player* _player)
|
|||
if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam())
|
||||
continue;
|
||||
|
||||
//skip players not in world
|
||||
if(!plr->IsInWorld())
|
||||
continue;
|
||||
|
||||
// skip not auto add, not group leader cases
|
||||
if(!plr->GetSession()->LookingForGroup_auto_add || plr->GetGroup() && plr->GetGroup()->GetLeaderGUID()!=plr->GetGUID())
|
||||
continue;
|
||||
|
|
@ -96,6 +100,9 @@ static void AttemptAddMore(Player* _player)
|
|||
if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam())
|
||||
continue;
|
||||
|
||||
if(!plr->IsInWorld())
|
||||
continue;
|
||||
|
||||
// skip not auto join or in group
|
||||
if(!plr->GetSession()->LookingForGroup_auto_join || plr->GetGroup() )
|
||||
continue;
|
||||
|
|
@ -309,6 +316,9 @@ void WorldSession::SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type)
|
|||
if(!plr || plr->GetTeam() != _player->GetTeam())
|
||||
continue;
|
||||
|
||||
if(!plr->IsInWorld())
|
||||
continue;
|
||||
|
||||
if(!plr->m_lookingForGroup.HaveInSlot(entry, type))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,10 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data )
|
|||
continue;
|
||||
}
|
||||
|
||||
//do not process players which are not in world
|
||||
if(!(itr->second->IsInWorld()))
|
||||
continue;
|
||||
|
||||
// check if target is globally visible for player
|
||||
if (!(itr->second->IsVisibleGloballyFor(_player)))
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,9 @@ void WorldSession::HandleMoveWorldportAckOpcode()
|
|||
|
||||
// resummon pet
|
||||
GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
|
||||
|
||||
//lets process all delayed operations on successful teleport
|
||||
GetPlayer()->ProcessDelayedOperations();
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
|
||||
|
|
@ -200,6 +203,9 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
|
|||
|
||||
// resummon pet
|
||||
GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
|
||||
|
||||
//lets process all delayed operations on successful teleport
|
||||
GetPlayer()->ProcessDelayedOperations();
|
||||
}
|
||||
|
||||
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
||||
|
|
@ -329,8 +335,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
}
|
||||
else // creature charmed
|
||||
{
|
||||
if(Map *map = mover->GetMap())
|
||||
map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
|
||||
if(mover->IsInWorld())
|
||||
mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
|
|||
uint64 npcGUID;
|
||||
recv_data >> npcGUID;
|
||||
|
||||
if(!GetPlayer()->isAlive())
|
||||
if(!GetPlayer()->IsInWorld() || !GetPlayer()->isAlive())
|
||||
return;
|
||||
|
||||
Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID,UNIT_NPC_FLAG_INNKEEPER);
|
||||
|
|
@ -435,7 +435,7 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
|
|||
void WorldSession::SendBindPoint(Creature *npc)
|
||||
{
|
||||
// prevent set homebind to instances in any case
|
||||
if(sMapStore.LookupEntry(GetPlayer()->GetMapId())->Instanceable())
|
||||
if(GetPlayer()->GetMap()->Instanceable())
|
||||
return;
|
||||
|
||||
uint32 bindspell = 3286;
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid)
|
|||
if(IS_VEHICLE_GUID(guid))
|
||||
return GetVehicle(guid);
|
||||
|
||||
return u.GetMap()->GetCreature(guid);
|
||||
return u.IsInWorld() ? u.GetMap()->GetCreature(guid) : NULL;
|
||||
}
|
||||
|
||||
Unit*
|
||||
|
|
@ -131,7 +131,11 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, u
|
|||
Player*
|
||||
ObjectAccessor::FindPlayer(uint64 guid)
|
||||
{
|
||||
return GetObjectInWorld(guid, (Player*)NULL);
|
||||
Player * plr = GetObjectInWorld(guid, (Player*)NULL);
|
||||
if(!plr || !plr->IsInWorld())
|
||||
return NULL;
|
||||
|
||||
return plr;
|
||||
}
|
||||
|
||||
Player*
|
||||
|
|
@ -141,7 +145,7 @@ ObjectAccessor::FindPlayerByName(const char *name)
|
|||
HashMapHolder<Player>::MapType& m = HashMapHolder<Player>::GetContainer();
|
||||
HashMapHolder<Player>::MapType::iterator iter = m.begin();
|
||||
for(; iter != m.end(); ++iter)
|
||||
if( ::strcmp(name, iter->second->GetName()) == 0 )
|
||||
if(iter->second->IsInWorld() && ( ::strcmp(name, iter->second->GetName()) == 0 ))
|
||||
return iter->second;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,10 +102,16 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
|
|||
return NULL;
|
||||
|
||||
if (IS_PLAYER_GUID(guid))
|
||||
return (Unit*)HashMapHolder<Player>::Find(guid);
|
||||
{
|
||||
Unit * u = (Unit*)HashMapHolder<Player>::Find(guid);
|
||||
if(!u || !u->IsInWorld())
|
||||
return NULL;
|
||||
|
||||
if (Unit* u = (Unit*)HashMapHolder<Pet>::Find(guid))
|
||||
return u;
|
||||
}
|
||||
|
||||
if (IS_PET_GUID(guid))
|
||||
return (Unit*)HashMapHolder<Pet>::Find(guid);
|
||||
|
||||
return (Unit*)HashMapHolder<Creature>::Find(guid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,6 +254,10 @@ template<class T>
|
|||
void
|
||||
ObjectGridUnloader::Visit(GridRefManager<T> &m)
|
||||
{
|
||||
// remove all cross-reference before deleting
|
||||
for(GridRefManager<T>::iterator iter=m.begin(); iter != m.end(); ++iter)
|
||||
iter->getSource()->CleanupsBeforeDelete();
|
||||
|
||||
while(!m.isEmpty())
|
||||
{
|
||||
T *obj = m.getFirst()->getSource();
|
||||
|
|
@ -267,25 +271,6 @@ ObjectGridUnloader::Visit(GridRefManager<T> &m)
|
|||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
ObjectGridUnloader::Visit(CreatureMapType &m)
|
||||
{
|
||||
// remove all cross-reference before deleting
|
||||
for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
|
||||
iter->getSource()->CleanupsBeforeDelete();
|
||||
|
||||
while(!m.isEmpty())
|
||||
{
|
||||
Creature *obj = m.getFirst()->getSource();
|
||||
// if option set then object already saved at this moment
|
||||
if(!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY))
|
||||
obj->SaveRespawnTime();
|
||||
///- object will get delinked from the manager when deleted
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ObjectGridStoper::Stop(GridType &grid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -463,6 +463,9 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data )
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -338,6 +338,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
|
|||
mSemaphoreTeleport_Near = false;
|
||||
mSemaphoreTeleport_Far = false;
|
||||
|
||||
m_DelayedOperations = 0;
|
||||
m_bCanDelayTeleport = false;
|
||||
m_bHasDelayedTeleport = false;
|
||||
m_teleport_options = 0;
|
||||
|
||||
pTrader = 0;
|
||||
ClearTrade();
|
||||
|
||||
|
|
@ -1064,7 +1069,10 @@ void Player::Update( uint32 p_time )
|
|||
m_nextMailDelivereTime = 0;
|
||||
}
|
||||
|
||||
//used to implement delayed far teleports
|
||||
SetCanDelayTeleport(true);
|
||||
Unit::Update( p_time );
|
||||
SetCanDelayTeleport(false);
|
||||
|
||||
// update player only attacks
|
||||
if(uint32 ranged_att = getAttackTimer(RANGED_ATTACK))
|
||||
|
|
@ -1326,8 +1334,12 @@ void Player::Update( uint32 p_time )
|
|||
if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
|
||||
{
|
||||
RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
|
||||
return;
|
||||
}
|
||||
|
||||
//we should execute delayed teleports only for alive(!) players
|
||||
//because we don't want player's ghost teleported from graveyard
|
||||
if(IsHasDelayedTeleport() && isAlive())
|
||||
TeleportTo(m_teleport_dest, m_teleport_options);
|
||||
}
|
||||
|
||||
void Player::setDeathState(DeathState s)
|
||||
|
|
@ -1611,6 +1623,21 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||
|
||||
if ((GetMapId() == mapid) && (!m_transport))
|
||||
{
|
||||
//lets reset far teleport flag if it wasn't reset during chained teleports
|
||||
SetSemaphoreTeleportFar(false);
|
||||
//setup delayed teleport flag
|
||||
SetDelayedTeleportFlag(IsCanDelayTeleport());
|
||||
//if teleport spell is casted in Unit::Update() func
|
||||
//then we need to delay it until update process will be finished
|
||||
if(IsHasDelayedTeleport())
|
||||
{
|
||||
SetSemaphoreTeleportNear(true);
|
||||
//lets save teleport destination for player
|
||||
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
m_teleport_options = options;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
|
||||
{
|
||||
//same map, only remove pet if out of range for new position
|
||||
|
|
@ -1652,6 +1679,21 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||
Map *map = MapManager::Instance().FindMap(mapid);
|
||||
if (!map || map->CanEnter(this))
|
||||
{
|
||||
//lets reset near teleport flag if it wasn't reset during chained teleports
|
||||
SetSemaphoreTeleportNear(false);
|
||||
//setup delayed teleport flag
|
||||
SetDelayedTeleportFlag(IsCanDelayTeleport());
|
||||
//if teleport spell is casted in Unit::Update() func
|
||||
//then we need to delay it until update process will be finished
|
||||
if(IsHasDelayedTeleport())
|
||||
{
|
||||
SetSemaphoreTeleportFar(true);
|
||||
//lets save teleport destination for player
|
||||
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
m_teleport_options = options;
|
||||
return true;
|
||||
}
|
||||
|
||||
SetSelection(0);
|
||||
|
||||
CombatStop();
|
||||
|
|
@ -1681,6 +1723,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||
if(IsNonMeleeSpellCasted(true))
|
||||
InterruptNonMeleeSpells(true);
|
||||
|
||||
//remove auras before removing from map...
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
|
||||
|
||||
if(!GetSession()->PlayerLogout())
|
||||
{
|
||||
// send transfer packets
|
||||
|
|
@ -1727,8 +1772,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||
// if the player is saved before worldportack (at logout for example)
|
||||
// this will be used instead of the current location in SaveToDB
|
||||
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
|
||||
|
||||
// move packet sent by client always after far teleport
|
||||
// code for finish transfer to new map called in WorldSession::HandleMoveWorldportAckOpcode at client packet
|
||||
SetSemaphoreTeleportFar(true);
|
||||
|
|
@ -1739,6 +1782,53 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||
return true;
|
||||
}
|
||||
|
||||
void Player::ProcessDelayedOperations()
|
||||
{
|
||||
if(m_DelayedOperations == 0)
|
||||
return;
|
||||
|
||||
if(m_DelayedOperations & DELAYED_RESURRECT_PLAYER)
|
||||
{
|
||||
ResurrectPlayer(0.0f, false);
|
||||
|
||||
if(GetMaxHealth() > m_resurrectHealth)
|
||||
SetHealth( m_resurrectHealth );
|
||||
else
|
||||
SetHealth( GetMaxHealth() );
|
||||
|
||||
if(GetMaxPower(POWER_MANA) > m_resurrectMana)
|
||||
SetPower(POWER_MANA, m_resurrectMana );
|
||||
else
|
||||
SetPower(POWER_MANA, GetMaxPower(POWER_MANA) );
|
||||
|
||||
SetPower(POWER_RAGE, 0 );
|
||||
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY) );
|
||||
|
||||
SpawnCorpseBones();
|
||||
}
|
||||
|
||||
if(m_DelayedOperations & DELAYED_SAVE_PLAYER)
|
||||
{
|
||||
SaveToDB();
|
||||
}
|
||||
|
||||
if(m_DelayedOperations & DELAYED_SPELL_CAST_DESERTER)
|
||||
{
|
||||
CastSpell(this, 26013, true); // Deserter
|
||||
}
|
||||
|
||||
//we have executed ALL delayed ops, so clear the flag
|
||||
m_DelayedOperations = 0;
|
||||
}
|
||||
|
||||
void Player::ScheduleDelayedOperation(uint32 operation)
|
||||
{
|
||||
if(operation >= DELAYED_END)
|
||||
return;
|
||||
|
||||
m_DelayedOperations |= operation;
|
||||
}
|
||||
|
||||
void Player::AddToWorld()
|
||||
{
|
||||
///- Do not add/remove the player from the object storage
|
||||
|
|
@ -12081,7 +12171,11 @@ Quest const * Player::GetNextQuest( uint64 guid, Quest const *pQuest )
|
|||
}
|
||||
else
|
||||
{
|
||||
GameObject *pGameObject = GetMap()->GetGameObject(guid);
|
||||
//we should obtain map pointer from GetMap() in 99% of cases. Special case
|
||||
//only for quests which cast teleport spells on player
|
||||
Map * _map = IsInWorld() ? GetMap() : MapManager::Instance().FindMap(GetMapId(), GetInstanceId());
|
||||
ASSERT(_map);
|
||||
GameObject *pGameObject = _map->GetGameObject(guid);
|
||||
if( pGameObject )
|
||||
{
|
||||
pObject = (Object*)pGameObject;
|
||||
|
|
@ -12415,6 +12509,10 @@ void Player::IncompleteQuest( uint32 quest_id )
|
|||
|
||||
void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver, bool announce )
|
||||
{
|
||||
//this THING should be here to protect code from quest, which cast on player far teleport as a reward
|
||||
//should work fine, cause far teleport will be executed in Player::Update()
|
||||
SetCanDelayTeleport(true);
|
||||
|
||||
uint32 quest_id = pQuest->GetQuestId();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i )
|
||||
|
|
@ -12607,6 +12705,9 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
|||
if( !HasAura(itr->second->spellId,0) )
|
||||
CastSpell(this,itr->second->spellId,true);
|
||||
}
|
||||
|
||||
//lets remove flag for delayed teleports
|
||||
SetCanDelayTeleport(false);
|
||||
}
|
||||
|
||||
void Player::FailQuest( uint32 quest_id )
|
||||
|
|
@ -15377,6 +15478,13 @@ void Player::SaveToDB()
|
|||
// delay auto save at any saves (manual, in code, or autosave)
|
||||
m_nextSave = sWorld.getConfig(CONFIG_INTERVAL_SAVE);
|
||||
|
||||
//lets allow only players in world to be saved
|
||||
if(IsBeingTeleportedFar())
|
||||
{
|
||||
ScheduleDelayedOperation(DELAYED_SAVE_PLAYER);
|
||||
return;
|
||||
}
|
||||
|
||||
// first save/honor gain after midnight will also update the player's honor fields
|
||||
UpdateHonorFields();
|
||||
|
||||
|
|
@ -17641,7 +17749,16 @@ void Player::LeaveBattleground(bool teleportToEntryPoint)
|
|||
if( bg->isBattleGround() && !isGameMaster() && sWorld.getConfig(CONFIG_BATTLEGROUND_CAST_DESERTER) )
|
||||
{
|
||||
if( bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN )
|
||||
{
|
||||
//lets check if player was teleported from BG and schedule delayed Deserter spell cast
|
||||
if(IsBeingTeleportedFar())
|
||||
{
|
||||
ScheduleDelayedOperation(DELAYED_SPELL_CAST_DESERTER);
|
||||
return;
|
||||
}
|
||||
|
||||
CastSpell(this, 26013, true); // Deserter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18868,6 +18985,14 @@ void Player::ResurectUsingRequestData()
|
|||
if(IS_PLAYER_GUID(m_resurrectGUID))
|
||||
TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation());
|
||||
|
||||
//we cannot resurrect player when we triggered far teleport
|
||||
//player will be resurrected upon teleportation
|
||||
if(IsBeingTeleportedFar())
|
||||
{
|
||||
ScheduleDelayedOperation(DELAYED_RESURRECT_PLAYER);
|
||||
return;
|
||||
}
|
||||
|
||||
ResurrectPlayer(0.0f,false);
|
||||
|
||||
if(GetMaxHealth() > m_resurrectHealth)
|
||||
|
|
|
|||
|
|
@ -858,6 +858,14 @@ enum PlayerLoginQueryIndex
|
|||
MAX_PLAYER_LOGIN_QUERY = 21
|
||||
};
|
||||
|
||||
enum PlayerDelayedOperations
|
||||
{
|
||||
DELAYED_SAVE_PLAYER = 1,
|
||||
DELAYED_RESURRECT_PLAYER = 2,
|
||||
DELAYED_SPELL_CAST_DESERTER = 4,
|
||||
DELAYED_END
|
||||
};
|
||||
|
||||
// Player summoning auto-decline time (in secs)
|
||||
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
|
||||
#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1)
|
||||
|
|
@ -1757,6 +1765,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; }
|
||||
void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; }
|
||||
void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; }
|
||||
void ProcessDelayedOperations();
|
||||
|
||||
void CheckExploreSystem(void);
|
||||
|
||||
|
|
@ -2397,6 +2406,13 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest);
|
||||
void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData );
|
||||
|
||||
bool IsCanDelayTeleport() const { return m_bCanDelayTeleport; }
|
||||
void SetCanDelayTeleport(bool setting) { m_bCanDelayTeleport = setting; }
|
||||
bool IsHasDelayedTeleport() const { return m_bHasDelayedTeleport; }
|
||||
void SetDelayedTeleportFlag(bool setting) { m_bHasDelayedTeleport = setting; }
|
||||
|
||||
void ScheduleDelayedOperation(uint32 operation);
|
||||
|
||||
GridReference<Player> m_gridRef;
|
||||
MapReference m_mapRef;
|
||||
|
||||
|
|
@ -2410,9 +2426,14 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
|
||||
// Current teleport data
|
||||
WorldLocation m_teleport_dest;
|
||||
uint32 m_teleport_options;
|
||||
bool mSemaphoreTeleport_Near;
|
||||
bool mSemaphoreTeleport_Far;
|
||||
|
||||
uint32 m_DelayedOperations;
|
||||
bool m_bCanDelayTeleport;
|
||||
bool m_bHasDelayedTeleport;
|
||||
|
||||
// Temporary removed pet cache
|
||||
uint32 m_temporaryUnsummonedPetNumber;
|
||||
uint32 m_oldpetspell;
|
||||
|
|
|
|||
|
|
@ -176,6 +176,9 @@ Unit::~Unit()
|
|||
|
||||
void Unit::Update( uint32 p_time )
|
||||
{
|
||||
if(!IsInWorld())
|
||||
return;
|
||||
|
||||
/*if(p_time > m_AurasCheck)
|
||||
{
|
||||
m_AurasCheck = 2000;
|
||||
|
|
@ -7248,7 +7251,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
|
|||
return false;
|
||||
|
||||
// dead units can neither attack nor be attacked
|
||||
if(!isAlive() || !victim->isAlive())
|
||||
if(!isAlive() || !victim->IsInWorld() || !victim->isAlive())
|
||||
return false;
|
||||
|
||||
// player cannot attack in mount state
|
||||
|
|
@ -8906,7 +8909,7 @@ bool Unit::isTargetableForAttack() const
|
|||
if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
|
||||
return false;
|
||||
|
||||
return isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;
|
||||
return IsInWorld() && isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;
|
||||
}
|
||||
|
||||
int32 Unit::ModifyHealth(int32 dVal)
|
||||
|
|
|
|||
|
|
@ -307,7 +307,13 @@ void WorldSession::LogoutPlayer(bool Save)
|
|||
|
||||
///- Teleport to home if the player is in an invalid instance
|
||||
if(!_player->m_InstanceValid && !_player->isGameMaster())
|
||||
{
|
||||
_player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation());
|
||||
//this is a bad place to call for far teleport because we need player to be in world for successful logout
|
||||
//maybe we should implement delayed far teleport logout?
|
||||
while(_player->IsBeingTeleportedFar())
|
||||
HandleMoveWorldportAckOpcode();
|
||||
}
|
||||
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8102"
|
||||
#define REVISION_NR "8103"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue