server/src/game/Corpse.cpp
Ambal 58209ee79a [8182] Store and use Map* pointer in WorldObject instead map ids for speedup
Also some code logic cleanups.
Changes let make more cleanups in base map access and other places,
but this chnages not inlcuded in patch.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
2009-07-15 02:13:52 +04:00

233 lines
7.1 KiB
C++

/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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 2 of the License, or
* (at your option) 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
#include "Corpse.h"
#include "Player.h"
#include "UpdateMask.h"
#include "ObjectAccessor.h"
#include "Database/DatabaseEnv.h"
#include "Opcodes.h"
#include "GossipDef.h"
#include "World.h"
Corpse::Corpse(CorpseType type) : WorldObject()
{
m_objectType |= TYPEMASK_CORPSE;
m_objectTypeId = TYPEID_CORPSE;
m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION);
m_valuesCount = CORPSE_END;
m_type = type;
m_time = time(NULL);
lootForBody = false;
}
Corpse::~Corpse()
{
}
void Corpse::AddToWorld()
{
///- Register the corpse for guid lookup
if(!IsInWorld())
ObjectAccessor::Instance().AddObject(this);
Object::AddToWorld();
}
void Corpse::RemoveFromWorld()
{
///- Remove the corpse from the accessor
if(IsInWorld())
ObjectAccessor::Instance().RemoveObject(this);
Object::RemoveFromWorld();
}
bool Corpse::Create( uint32 guidlow )
{
Object::_Create(guidlow, 0, HIGHGUID_CORPSE);
return true;
}
bool Corpse::Create( uint32 guidlow, Player *owner)
{
ASSERT(owner);
WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask());
Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
//we need to assign owner's map for corpse
//in other way we will get a crash in Corpse::SaveToDB()
SetMap(owner->GetMap());
if(!IsPositionValid())
{
sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
guidlow, owner->GetName(), owner->GetPositionX(), owner->GetPositionY());
return false;
}
SetFloatValue( OBJECT_FIELD_SCALE_X, 1 );
SetUInt64Value( CORPSE_FIELD_OWNER, owner->GetGUID() );
m_grid = MaNGOS::ComputeGridPair(GetPositionX(), GetPositionY());
return true;
}
void Corpse::SaveToDB()
{
// prevent DB data inconsistence problems and duplicates
CharacterDatabase.BeginTransaction();
DeleteFromDB();
std::ostringstream ss;
ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES ("
<< GetGUIDLow() << ", "
<< GUID_LOPART(GetOwnerGUID()) << ", "
<< GetPositionX() << ", "
<< GetPositionY() << ", "
<< GetPositionZ() << ", "
<< GetOrientation() << ", "
<< GetZoneId() << ", "
<< GetMapId() << ", '";
for(uint16 i = 0; i < m_valuesCount; ++i )
ss << GetUInt32Value(i) << " ";
ss << "',"
<< uint64(m_time) <<", "
<< uint32(GetType()) << ", "
<< int(GetInstanceId()) << ", "
<< uint16(GetPhaseMask()) << ")"; // prevent out of range error
CharacterDatabase.Execute( ss.str().c_str() );
CharacterDatabase.CommitTransaction();
}
void Corpse::DeleteBonesFromWorld()
{
assert(GetType() == CORPSE_BONES);
Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetGUID());
if (!corpse)
{
sLog.outError("Bones %u not found in world.", GetGUIDLow());
return;
}
AddObjectToRemoveList();
}
void Corpse::DeleteFromDB()
{
if(GetType() == CORPSE_BONES)
// only specific bones
CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%d'", GetGUIDLow());
else
// all corpses (not bones)
CharacterDatabase.PExecute("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID()));
}
bool Corpse::LoadFromDB(uint32 guid, QueryResult *result)
{
bool external = (result != NULL);
if (!external)
// 0 1 2 3 4 5 6 7 8 9
result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid);
if( !result )
{
sLog.outError("Corpse (GUID: %u) not found in table `corpse`, can't load. ",guid);
return false;
}
Field *fields = result->Fetch();
if(!LoadFromDB(guid, fields))
{
if (!external)
delete result;
return false;
}
if (!external)
delete result;
return true;
}
bool Corpse::LoadFromDB(uint32 guid, Field *fields)
{
// 0 1 2 3 4 5 6 7 8 9
//result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid);
float positionX = fields[0].GetFloat();
float positionY = fields[1].GetFloat();
float positionZ = fields[2].GetFloat();
float ort = fields[3].GetFloat();
uint32 mapid = fields[4].GetUInt32();
Object::_Create(guid, 0, HIGHGUID_CORPSE);
if(!LoadValues( fields[5].GetString() ))
{
sLog.outError("Corpse #%d have broken data in `data` field. Can't be loaded.",guid);
return false;
}
m_time = time_t(fields[6].GetUInt64());
m_type = CorpseType(fields[7].GetUInt32());
if(m_type >= MAX_CORPSE_TYPE)
{
sLog.outError("Corpse (guidlow %d, owner %d) have wrong corpse type, not load.",GetGUIDLow(),GUID_LOPART(GetOwnerGUID()));
return false;
}
uint32 instanceid = fields[8].GetUInt32();
uint32 phaseMask = fields[9].GetUInt32();
// overwrite possible wrong/corrupted guid
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE));
// place
SetLocationInstanceId(instanceid);
SetLocationMapId(mapid);
SetPhaseMask(phaseMask, false);
Relocate(positionX, positionY, positionZ, ort);
if(!IsPositionValid())
{
sLog.outError("Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
GetGUIDLow(), GUID_LOPART(GetOwnerGUID()), GetPositionX(), GetPositionY());
return false;
}
m_grid = MaNGOS::ComputeGridPair(GetPositionX(), GetPositionY());
return true;
}
bool Corpse::isVisibleForInState(Player const* u, bool inVisibleList) const
{
return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
}