2008-10-02 16:23:55 -05:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2009-02-04 12:04:12 +01:00
* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
2008-10-02 16:23:55 -05:00
*
* 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
2008-10-14 11:57:03 -05:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -05:00
* 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
2008-10-14 11:57:03 -05:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
#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 ;
// 2.3.2 - 0x58
2008-12-24 09:58:26 -06:00
m_updateFlag = ( UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION );
2008-10-02 16:23:55 -05:00
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 ;
}
2009-01-31 16:38:50 -06:00
bool Corpse :: Create ( uint32 guidlow , Player * owner )
2008-10-02 16:23:55 -05:00
{
SetInstanceId ( owner -> GetInstanceId ());
2009-01-31 16:38:50 -06:00
WorldObject :: _Create ( guidlow , HIGHGUID_CORPSE , owner -> GetMapId (), owner -> GetPhaseMask ());
2008-10-02 16:23:55 -05:00
2009-01-31 16:38:50 -06:00
Relocate ( owner -> GetPositionX (), owner -> GetPositionY (), owner -> GetPositionZ (), owner -> GetOrientation ());
2008-10-02 16:23:55 -05:00
if ( ! IsPositionValid ())
{
2009-03-21 14:28:02 -06:00
sLog . outError ( "Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)" ,
2009-01-31 16:38:50 -06:00
guidlow , owner -> GetName (), owner -> GetPositionX (), owner -> GetPositionY ());
2008-10-02 16:23:55 -05:00
return false ;
}
SetFloatValue ( OBJECT_FIELD_SCALE_X , 1 );
2009-01-31 16:38:50 -06:00
SetFloatValue ( CORPSE_FIELD_POS_X , GetPositionX () );
SetFloatValue ( CORPSE_FIELD_POS_Y , GetPositionY () );
SetFloatValue ( CORPSE_FIELD_POS_Z , GetPositionZ () );
SetFloatValue ( CORPSE_FIELD_FACING , GetOrientation () );
2008-10-02 16:23:55 -05:00
SetUInt64Value ( CORPSE_FIELD_OWNER , owner -> GetGUID () );
2008-10-14 11:57:03 -05:00
m_grid = Trinity :: ComputeGridPair ( GetPositionX (), GetPositionY ());
2008-10-02 16:23:55 -05:00
return true ;
}
void Corpse :: SaveToDB ()
{
2009-01-31 16:38:50 -06:00
// prevent DB data inconsistence problems and duplicates
2008-10-02 16:23:55 -05:00
CharacterDatabase . BeginTransaction ();
DeleteFromDB ();
std :: ostringstream ss ;
2009-01-31 16:38:50 -06:00
ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES ("
2009-02-27 12:26:40 -06:00
<< GetGUIDLow () << ", "
<< GUID_LOPART ( GetOwnerGUID ()) << ", "
<< GetPositionX () << ", "
<< GetPositionY () << ", "
<< GetPositionZ () << ", "
<< GetOrientation () << ", "
<< GetZoneId () << ", "
<< GetMapId () << ", '" ;
2008-10-02 16:23:55 -05:00
for ( uint16 i = 0 ; i < m_valuesCount ; i ++ )
ss << GetUInt32Value ( i ) << " " ;
2009-02-27 12:26:40 -06:00
ss << "',"
<< uint64 ( m_time ) << ", "
<< uint32 ( GetType ()) << ", "
<< int ( GetInstanceId ()) << ", "
<< uint16 ( GetPhaseMask ()) << ")" ; // prevent out of range error
2008-10-02 16:23:55 -05:00
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 , uint32 InstanceId )
{
bool external = ( result != NULL );
if ( ! external )
2009-01-31 16:38:50 -06:00
// 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 );
2008-10-02 16:23:55 -05:00
if ( ! result )
{
2009-03-21 14:28:02 -06:00
sLog . outError ( "Corpse (GUID: %u) not found in table `corpse`, can't load. " , guid );
2008-10-02 16:23:55 -05:00
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 )
{
2009-01-31 16:38:50 -06:00
// 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);
2008-10-02 16:23:55 -05:00
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 ();
if ( ! LoadValues ( fields [ 5 ]. GetString () ))
{
2009-03-21 14:28:02 -06:00
sLog . outError ( "Corpse #%d have broken data in `data` field. Can't be loaded." , guid );
2008-10-02 16:23:55 -05:00
return false ;
}
m_time = time_t ( fields [ 6 ]. GetUInt64 ());
m_type = CorpseType ( fields [ 7 ]. GetUInt32 ());
if ( m_type >= MAX_CORPSE_TYPE )
{
2009-03-21 14:28:02 -06:00
sLog . outError ( "Corpse (guidlow %d, owner %d) have wrong corpse type, not load." , GetGUIDLow (), GUID_LOPART ( GetOwnerGUID ()));
2008-10-02 16:23:55 -05:00
return false ;
}
uint32 instanceid = fields [ 8 ]. GetUInt32 ();
2009-01-31 16:38:50 -06:00
uint32 phaseMask = fields [ 9 ]. GetUInt32 ();
2008-10-02 16:23:55 -05:00
// overwrite possible wrong/corrupted guid
SetUInt64Value ( OBJECT_FIELD_GUID , MAKE_NEW_GUID ( guid , 0 , HIGHGUID_CORPSE ));
// place
SetInstanceId ( instanceid );
SetMapId ( mapid );
2009-01-31 16:38:50 -06:00
SetPhaseMask ( phaseMask , false );
2008-10-02 16:23:55 -05:00
Relocate ( positionX , positionY , positionZ , ort );
if ( ! IsPositionValid ())
{
2009-03-21 14:28:02 -06:00
sLog . outError ( "Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)" ,
2008-11-14 17:03:03 -06:00
GetGUIDLow (), GUID_LOPART ( GetOwnerGUID ()), GetPositionX (), GetPositionY ());
2008-10-02 16:23:55 -05:00
return false ;
}
2008-10-14 11:57:03 -05:00
m_grid = Trinity :: ComputeGridPair ( GetPositionX (), GetPositionY ());
2008-10-02 16:23:55 -05:00
return true ;
}
bool Corpse :: isVisibleForInState ( Player const * u , bool inVisibleList ) const
{
2009-03-10 15:26:17 -06:00
return IsInWorld () && u -> IsInWorld () && IsWithinDistInMap ( u -> m_seer , World :: GetMaxVisibleDistanceForObject () + ( inVisibleList ? World :: GetVisibleObjectGreyDistance () : 0.0f ), false );
2008-10-02 16:23:55 -05:00
}
2009-02-17 20:07:49 -06:00