2008-10-02 16:23:55 -05:00
/*
2008-10-23 03:29:52 -05:00
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
2008-10-14 11:57:03 -05:00
*
2008-10-23 03:29:52 -05:00
* Copyright (C) 2008 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-11-15 11:56:59 -06: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-11-15 11:56:59 -06: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 "GameObject.h"
#include "UpdateMask.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectAccessor.h"
#include "Database/DatabaseEnv.h"
#include "SpellAuras.h"
#include "MapManager.h"
#include "GridNotifiers.h"
#include "CellImpl.h"
#include "GridNotifiersImpl.h"
DynamicObject :: DynamicObject () : WorldObject ()
{
m_objectType |= TYPEMASK_DYNAMICOBJECT ;
m_objectTypeId = TYPEID_DYNAMICOBJECT ;
// 2.3.2 - 0x58
m_updateFlag = ( UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION );
m_valuesCount = DYNAMICOBJECT_END ;
}
void DynamicObject :: AddToWorld ()
{
///- Register the dynamicObject for guid lookup
if ( ! IsInWorld ()) ObjectAccessor :: Instance (). AddObject ( this );
2008-10-27 08:41:55 -05:00
WorldObject :: AddToWorld ();
2008-10-02 16:23:55 -05:00
}
void DynamicObject :: RemoveFromWorld ()
{
///- Remove the dynamicObject from the accessor
if ( IsInWorld ()) ObjectAccessor :: Instance (). RemoveObject ( this );
2008-10-27 08:41:55 -05:00
WorldObject :: RemoveFromWorld ();
2008-10-02 16:23:55 -05:00
}
bool DynamicObject :: Create ( uint32 guidlow , Unit * caster , uint32 spellId , uint32 effIndex , float x , float y , float z , int32 duration , float radius )
{
SetInstanceId ( caster -> GetInstanceId ());
WorldObject :: _Create ( guidlow , HIGHGUID_DYNAMICOBJECT , caster -> GetMapId ());
Relocate ( x , y , z , 0 );
if ( ! IsPositionValid ())
{
sLog . outError ( "ERROR: DynamicObject (spell %u eff %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)" , spellId , effIndex , GetPositionX (), GetPositionY ());
return false ;
}
2008-11-15 11:56:59 -06:00
SetEntry ( spellId );
2008-10-02 16:23:55 -05:00
SetFloatValue ( OBJECT_FIELD_SCALE_X , 1 );
SetUInt64Value ( DYNAMICOBJECT_CASTER , caster -> GetGUID () );
SetUInt32Value ( DYNAMICOBJECT_BYTES , 0x00000001 );
SetUInt32Value ( DYNAMICOBJECT_SPELLID , spellId );
SetFloatValue ( DYNAMICOBJECT_RADIUS , radius );
SetFloatValue ( DYNAMICOBJECT_POS_X , x );
SetFloatValue ( DYNAMICOBJECT_POS_Y , y );
SetFloatValue ( DYNAMICOBJECT_POS_Z , z );
SetUInt32Value ( DYNAMICOBJECT_CASTTIME , getMSTime () ); // new 2.4.0
m_aliveDuration = duration ;
m_radius = radius ;
m_effIndex = effIndex ;
m_spellId = spellId ;
m_casterGuid = caster -> GetGUID ();
return true ;
}
Unit * DynamicObject :: GetCaster () const
{
// can be not found in some cases
return ObjectAccessor :: GetUnit ( * this , m_casterGuid );
}
void DynamicObject :: Update ( uint32 p_time )
{
// caster can be not in world at time dynamic object update, but dynamic object not yet deleted in Unit destructor
Unit * caster = GetCaster ();
if ( ! caster )
{
Delete ();
return ;
}
bool deleteThis = false ;
if ( m_aliveDuration > int32 ( p_time ))
m_aliveDuration -= p_time ;
else
deleteThis = true ;
// TODO: make a timer and update this in larger intervals
2008-10-14 11:57:03 -05:00
CellPair p ( Trinity :: ComputeCellPair ( GetPositionX (), GetPositionY ()));
2008-10-02 16:23:55 -05:00
Cell cell ( p );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2008-10-14 11:57:03 -05:00
Trinity :: DynamicObjectUpdater notifier ( * this , caster );
2008-10-02 16:23:55 -05:00
2008-10-14 11:57:03 -05:00
TypeContainerVisitor < Trinity :: DynamicObjectUpdater , WorldTypeMapContainer > world_object_notifier ( notifier );
TypeContainerVisitor < Trinity :: DynamicObjectUpdater , GridTypeMapContainer > grid_object_notifier ( notifier );
2008-10-02 16:23:55 -05:00
CellLock < GridReadGuard > cell_lock ( cell , p );
cell_lock -> Visit ( cell_lock , world_object_notifier , * MapManager :: Instance (). GetMap ( GetMapId (), this ));
cell_lock -> Visit ( cell_lock , grid_object_notifier , * MapManager :: Instance (). GetMap ( GetMapId (), this ));
if ( deleteThis )
{
caster -> RemoveDynObjectWithGUID ( GetGUID ());
Delete ();
}
}
void DynamicObject :: Delete ()
{
2008-11-14 20:40:35 -06:00
// Make sure the object is back to grid container for removal as farsight targets
2008-11-15 13:34:59 -06:00
// are switched to world container on creation and they are also set to active
if ( isActive ())
{
2008-11-25 21:25:52 -06:00
Map * map = GetMap ();
if ( ! map )
{
sLog . outError ( "DynamicObject (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u)." , GetTypeId (), GetEntry (), GetGUIDLow (), GetMapId ());
return ;
}
map -> SwitchGridContainers ( this , false );
2008-11-15 13:34:59 -06:00
setActive ( false );
}
2008-10-02 16:23:55 -05:00
SendObjectDeSpawnAnim ( GetGUID ());
AddObjectToRemoveList ();
}
void DynamicObject :: Delay ( int32 delaytime )
{
m_aliveDuration -= delaytime ;
for ( AffectedSet :: iterator iunit = m_affected . begin (); iunit != m_affected . end (); ++ iunit )
if ( * iunit )
( * iunit ) -> DelayAura ( m_spellId , m_effIndex , delaytime );
}
bool DynamicObject :: isVisibleForInState ( Player const * u , bool inVisibleList ) const
{
2008-11-15 11:56:59 -06:00
return IsInWorld () && u -> IsInWorld ()
&& ( IsWithinDistInMap ( u , World :: GetMaxVisibleDistanceForObject () + ( inVisibleList ? World :: GetVisibleObjectGreyDistance () : 0.0f ))
|| GetCasterGUID () == u -> GetGUID ());
2008-10-02 16:23:55 -05:00
}