2010-10-07 15:35:36 +02:00
/*
2012-01-01 00:32:13 +01:00
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* 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, see <http://www.gnu.org/licenses/>.
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "MotionMaster.h"
#include "CreatureAISelector.h"
#include "Creature.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "ConfusedMovementGenerator.h"
#include "FleeingMovementGenerator.h"
#include "HomeMovementGenerator.h"
#include "IdleMovementGenerator.h"
#include "PointMovementGenerator.h"
#include "TargetedMovementGenerator.h"
#include "WaypointMovementGenerator.h"
2008-12-19 00:37:40 +02:00
#include "RandomMovementGenerator.h"
2012-01-14 15:34:41 +01:00
#include "MoveSpline.h"
#include "MoveSplineInit.h"
2008-10-11 14:16:25 -05:00
#include <cassert>
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
inline bool isStatic ( MovementGenerator * mv )
{
return ( mv == & si_idleMovement );
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: Initialize ()
2008-10-11 14:16:25 -05:00
{
// clear ALL movement generators (including default)
2010-04-07 19:13:19 +02:00
while ( ! empty ())
2008-10-11 14:16:25 -05:00
{
MovementGenerator * curr = top ();
pop ();
2010-04-07 19:14:10 +02:00
if ( curr ) DirectDelete ( curr );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-21 10:11:29 -06:00
InitDefault ();
}
2009-10-17 15:51:44 -07:00
2009-03-21 10:11:29 -06:00
// set new default movement generator
void MotionMaster :: InitDefault ()
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_UNIT )
2008-10-11 14:16:25 -05:00
{
2012-02-14 12:46:26 -05:00
MovementGenerator * movement = FactorySelector :: selectMovementGenerator ( _owner -> ToCreature ());
2009-03-21 10:11:29 -06:00
Mutate ( movement == NULL ? & si_idleMovement : movement , MOTION_SLOT_IDLE );
2008-10-11 14:16:25 -05:00
}
else
2009-03-04 10:16:15 -06:00
{
2009-03-21 10:11:29 -06:00
Mutate ( & si_idleMovement , MOTION_SLOT_IDLE );
2009-03-04 10:16:15 -06:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
MotionMaster ::~ MotionMaster ()
{
// clear ALL movement generators (including default)
2010-04-07 19:13:19 +02:00
while ( ! empty ())
2008-10-11 14:16:25 -05:00
{
MovementGenerator * curr = top ();
pop ();
2010-04-07 19:14:10 +02:00
if ( curr ) DirectDelete ( curr );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: UpdateMotion ( uint32 diff )
2008-10-11 14:16:25 -05:00
{
2012-02-14 12:46:26 -05:00
if ( ! _owner )
2011-08-01 13:44:54 +02:00
return ;
2012-02-14 12:46:26 -05:00
if ( _owner -> HasUnitState ( UNIT_STATE_ROOT | UNIT_STATE_STUNNED )) // what about UNIT_STATE_DISTRACTED? Why is this not included?
2008-10-11 14:16:25 -05:00
return ;
2011-08-01 13:44:54 +02:00
2010-07-30 20:04:28 +02:00
ASSERT ( ! empty ());
2011-08-01 13:44:54 +02:00
2012-02-14 12:46:26 -05:00
_cleanFlag |= MMCF_UPDATE ;
2012-08-25 22:57:55 -05:00
if ( ! top () -> Update ( _owner , diff ))
2009-02-08 22:56:57 -06:00
{
2012-02-14 12:46:26 -05:00
_cleanFlag &= ~ MMCF_UPDATE ;
2008-10-11 14:16:25 -05:00
MovementExpired ();
2009-02-08 22:56:57 -06:00
}
else
2012-02-14 12:46:26 -05:00
_cleanFlag &= ~ MMCF_UPDATE ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
if ( _expList )
2009-02-08 22:56:57 -06:00
{
2012-02-14 12:46:26 -05:00
for ( size_t i = 0 ; i < _expList -> size (); ++ i )
2009-02-08 22:56:57 -06:00
{
2012-02-14 12:46:26 -05:00
MovementGenerator * mg = ( * _expList )[ i ];
2009-02-08 22:56:57 -06:00
DirectDelete ( mg );
}
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
delete _expList ;
_expList = NULL ;
2009-10-17 15:51:44 -07:00
2009-11-19 20:03:35 -08:00
if ( empty ())
2009-02-08 22:56:57 -06:00
Initialize ();
2009-11-19 20:03:35 -08:00
else if ( needInitTop ())
2009-03-04 10:16:15 -06:00
InitTop ();
2012-02-14 12:46:26 -05:00
else if ( _cleanFlag & MMCF_RESET )
2012-08-25 22:57:55 -05:00
top () -> Reset ( _owner );
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
_cleanFlag &= ~ MMCF_RESET ;
2009-02-08 22:56:57 -06:00
}
2012-03-29 13:14:21 -04:00
// probably not the best place to pu this but im not really sure where else to put it.
_owner -> UpdateUnderwaterState ( _owner -> GetMap (), _owner -> GetPositionX (), _owner -> GetPositionY (), _owner -> GetPositionZ ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: DirectClean ( bool reset )
2008-10-11 14:16:25 -05:00
{
2009-11-19 20:03:35 -08:00
while ( size () > 1 )
2008-10-11 14:16:25 -05:00
{
MovementGenerator * curr = top ();
pop ();
2010-04-07 19:14:10 +02:00
if ( curr ) DirectDelete ( curr );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-19 20:03:35 -08:00
if ( needInitTop ())
2009-03-04 10:16:15 -06:00
InitTop ();
2009-11-19 20:03:35 -08:00
else if ( reset )
2012-08-25 22:57:55 -05:00
top () -> Reset ( _owner );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: DelayedClean ()
2008-12-19 00:37:40 +02:00
{
2009-11-19 20:03:35 -08:00
while ( size () > 1 )
2008-12-19 00:37:40 +02:00
{
2009-02-08 22:56:57 -06:00
MovementGenerator * curr = top ();
pop ();
2009-11-19 20:03:35 -08:00
if ( curr )
DelayedDelete ( curr );
2008-12-19 00:37:40 +02:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: DirectExpire ( bool reset )
2008-10-11 14:16:25 -05:00
{
2009-11-19 20:03:35 -08:00
if ( size () > 1 )
2009-03-04 10:16:15 -06:00
{
MovementGenerator * curr = top ();
pop ();
DirectDelete ( curr );
}
2009-10-17 15:51:44 -07:00
2009-11-19 20:03:35 -08:00
while ( ! top ())
2012-02-14 12:46:26 -05:00
-- _top ;
2009-10-17 15:51:44 -07:00
2009-11-19 20:03:35 -08:00
if ( empty ())
2008-10-11 14:16:25 -05:00
Initialize ();
2009-11-19 20:03:35 -08:00
else if ( needInitTop ())
2009-03-04 10:16:15 -06:00
InitTop ();
2009-11-19 20:03:35 -08:00
else if ( reset )
2012-08-25 22:57:55 -05:00
top () -> Reset ( _owner );
2009-02-08 22:56:57 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: DelayedExpire ()
2009-02-08 22:56:57 -06:00
{
2009-11-19 20:03:35 -08:00
if ( size () > 1 )
2009-03-04 10:16:15 -06:00
{
MovementGenerator * curr = top ();
pop ();
DelayedDelete ( curr );
}
2009-10-17 15:51:44 -07:00
2009-11-19 20:03:35 -08:00
while ( ! top ())
2012-02-14 12:46:26 -05:00
-- _top ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-01-13 16:43:49 +01:00
void MotionMaster :: MoveIdle ()
2008-10-11 14:16:25 -05:00
{
2012-01-13 16:43:49 +01:00
//! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active
if ( empty () || ! isStatic ( top ()))
Mutate ( & si_idleMovement , MOTION_SLOT_IDLE );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveRandom ( float spawndist )
2009-02-08 22:56:57 -06:00
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_UNIT )
2009-02-08 22:56:57 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (GUID: %u) start moving random" , _owner -> GetGUIDLow ());
2009-02-08 22:56:57 -06:00
Mutate ( new RandomMovementGenerator < Creature > ( spawndist ), MOTION_SLOT_IDLE );
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveTargetedHome ()
2008-10-11 14:16:25 -05:00
{
Clear ( false );
2009-10-17 15:51:44 -07:00
2012-08-25 22:57:55 -05:00
if ( _owner -> GetTypeId () == TYPEID_UNIT && ! _owner -> ToCreature () -> GetCharmerOrOwnerGUID ())
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) targeted home" , _owner -> GetEntry (), _owner -> GetGUIDLow ());
2009-03-21 10:11:29 -06:00
Mutate ( new HomeMovementGenerator < Creature > (), MOTION_SLOT_ACTIVE );
2008-10-11 14:16:25 -05:00
}
2012-08-25 22:57:55 -05:00
else if ( _owner -> GetTypeId () == TYPEID_UNIT && _owner -> ToCreature () -> GetCharmerOrOwnerGUID ())
2012-01-14 15:34:41 +01:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Pet or controlled creature (Entry: %u GUID: %u) targeting home" , _owner -> GetEntry (), _owner -> GetGUIDLow ());
2012-08-25 22:57:55 -05:00
Unit * target = _owner -> ToCreature () -> GetCharmerOrOwner ();
2012-01-14 15:34:41 +01:00
if ( target )
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Following %s (GUID: %u)" , target -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" , target -> GetTypeId () == TYPEID_PLAYER ? target -> GetGUIDLow () : (( Creature * ) target ) -> GetDBTableGUIDLow ());
2012-08-25 22:57:55 -05:00
Mutate ( new FollowMovementGenerator < Creature > ( target , PET_FOLLOW_DIST , PET_FOLLOW_ANGLE ), MOTION_SLOT_ACTIVE );
2012-01-14 15:34:41 +01:00
}
}
2008-10-11 14:16:25 -05:00
else
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_GENERAL , "Player (GUID: %u) attempt targeted home" , _owner -> GetGUIDLow ());
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveConfused ()
2008-10-11 14:16:25 -05:00
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) move confused" , _owner -> GetGUIDLow ());
2009-01-16 22:57:03 -06:00
Mutate ( new ConfusedMovementGenerator < Player > (), MOTION_SLOT_CONTROLLED );
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) move confused" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow ());
2009-01-16 22:57:03 -06:00
Mutate ( new ConfusedMovementGenerator < Creature > (), MOTION_SLOT_CONTROLLED );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveChase ( Unit * target , float dist , float angle )
2008-10-11 14:16:25 -05:00
{
// ignore movement request if target not exist
2012-02-14 12:46:26 -05:00
if ( ! target || target == _owner || _owner -> HasFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_DISABLE_MOVE ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
//_owner->ClearUnitState(UNIT_STATE_FOLLOW);
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) chase to %s (GUID: %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetGUIDLow (),
2009-10-18 18:38:46 -07:00
target -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" ,
2010-03-12 14:28:43 +01:00
target -> GetTypeId () == TYPEID_PLAYER ? target -> GetGUIDLow () : target -> ToCreature () -> GetDBTableGUIDLow ());
2012-08-25 22:57:55 -05:00
Mutate ( new ChaseMovementGenerator < Player > ( target , dist , angle ), MOTION_SLOT_ACTIVE );
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (),
2009-10-18 18:38:46 -07:00
target -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" ,
2010-03-07 18:30:53 +01:00
target -> GetTypeId () == TYPEID_PLAYER ? target -> GetGUIDLow () : target -> ToCreature () -> GetDBTableGUIDLow ());
2012-08-25 22:57:55 -05:00
Mutate ( new ChaseMovementGenerator < Creature > ( target , dist , angle ), MOTION_SLOT_ACTIVE );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveFollow ( Unit * target , float dist , float angle , MovementSlot slot )
2008-10-11 14:16:25 -05:00
{
// ignore movement request if target not exist
2012-02-14 12:46:26 -05:00
if ( ! target || target == _owner || _owner -> HasFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_DISABLE_MOVE ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
//_owner->AddUnitState(UNIT_STATE_FOLLOW);
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) follow to %s (GUID: %u)" , _owner -> GetGUIDLow (),
2009-10-18 18:38:46 -07:00
target -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" ,
2010-03-13 12:51:37 +01:00
target -> GetTypeId () == TYPEID_PLAYER ? target -> GetGUIDLow () : target -> ToCreature () -> GetDBTableGUIDLow ());
2012-08-25 22:57:55 -05:00
Mutate ( new FollowMovementGenerator < Player > ( target , dist , angle ), slot );
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (),
2009-10-18 18:38:46 -07:00
target -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" ,
2010-03-07 18:30:53 +01:00
target -> GetTypeId () == TYPEID_PLAYER ? target -> GetGUIDLow () : target -> ToCreature () -> GetDBTableGUIDLow ());
2012-08-25 22:57:55 -05:00
Mutate ( new FollowMovementGenerator < Creature > ( target , dist , angle ), slot );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2012-04-09 18:36:45 +02:00
void MotionMaster :: MovePoint ( uint32 id , float x , float y , float z , bool generatePath )
2008-10-11 14:16:25 -05:00
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)" , _owner -> GetGUIDLow (), id , x , y , z );
2012-04-09 18:36:45 +02:00
Mutate ( new PointMovementGenerator < Player > ( id , x , y , z , generatePath ), MOTION_SLOT_ACTIVE );
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (), id , x , y , z );
2012-04-09 18:36:45 +02:00
Mutate ( new PointMovementGenerator < Creature > ( id , x , y , z , generatePath ), MOTION_SLOT_ACTIVE );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2012-05-31 19:45:11 +02:00
void MotionMaster :: MoveLand ( uint32 id , Position const & pos )
2011-07-27 12:40:14 +02:00
{
float x , y , z ;
pos . GetPosition ( x , y , z );
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)" , _owner -> GetEntry (), id , x , y , z );
2011-07-27 12:40:14 +02:00
2012-08-25 22:57:55 -05:00
Movement :: MoveSplineInit init ( _owner );
2012-01-14 15:34:41 +01:00
init . MoveTo ( x , y , z );
init . SetAnimation ( Movement :: ToGround );
init . Launch ();
2012-01-18 16:26:45 +03:00
Mutate ( new EffectMovementGenerator ( id ), MOTION_SLOT_ACTIVE );
2011-07-27 12:40:14 +02:00
}
2012-05-31 19:45:11 +02:00
void MotionMaster :: MoveTakeoff ( uint32 id , Position const & pos )
2011-07-27 12:40:14 +02:00
{
float x , y , z ;
pos . GetPosition ( x , y , z );
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)" , _owner -> GetEntry (), id , x , y , z );
2011-07-27 12:40:14 +02:00
2012-08-25 22:57:55 -05:00
Movement :: MoveSplineInit init ( _owner );
2012-01-14 15:34:41 +01:00
init . MoveTo ( x , y , z );
init . SetAnimation ( Movement :: ToFly );
init . Launch ();
2012-01-18 16:26:45 +03:00
Mutate ( new EffectMovementGenerator ( id ), MOTION_SLOT_ACTIVE );
2011-07-27 12:40:14 +02:00
}
2009-04-11 22:41:15 -05:00
void MotionMaster :: MoveKnockbackFrom ( float srcX , float srcY , float speedXY , float speedZ )
2009-03-23 15:26:13 -06:00
{
//this function may make players fall below map
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2009-03-23 15:26:13 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-23 15:26:13 -06:00
float x , y , z ;
2012-01-14 15:34:41 +01:00
float moveTimeHalf = speedZ / Movement :: gravity ;
float dist = 2 * moveTimeHalf * speedXY ;
2012-07-28 17:07:05 +02:00
float max_height = - Movement :: computeFallElevation ( moveTimeHalf , false , - speedZ );
2012-01-14 15:34:41 +01:00
2012-02-14 12:46:26 -05:00
_owner -> GetNearPoint ( _owner , x , y , z , _owner -> GetObjectSize (), dist , _owner -> GetAngle ( srcX , srcY ) + M_PI );
2012-07-28 17:07:05 +02:00
2012-08-25 22:57:55 -05:00
Movement :: MoveSplineInit init ( _owner );
2012-09-03 20:30:30 +02:00
init . MoveTo ( x , y , z );
2012-07-28 17:07:05 +02:00
init . SetParabolic ( max_height , 0 );
init . SetOrientationFixed ( true );
init . SetVelocity ( speedXY );
init . Launch ();
Mutate ( new EffectMovementGenerator ( 0 ), MOTION_SLOT_CONTROLLED );
2009-03-23 15:26:13 -06:00
}
2009-10-17 15:51:44 -07:00
2009-04-11 22:41:15 -05:00
void MotionMaster :: MoveJumpTo ( float angle , float speedXY , float speedZ )
{
//this function may make players fall below map
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2009-04-11 22:41:15 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-11 22:41:15 -05:00
float x , y , z ;
2012-01-14 15:34:41 +01:00
float moveTimeHalf = speedZ / Movement :: gravity ;
float dist = 2 * moveTimeHalf * speedXY ;
2012-02-14 12:46:26 -05:00
_owner -> GetClosePoint ( x , y , z , _owner -> GetObjectSize (), dist , angle );
2009-04-11 22:41:15 -05:00
MoveJump ( x , y , z , speedXY , speedZ );
}
2009-10-17 15:51:44 -07:00
2012-01-14 15:34:41 +01:00
void MotionMaster :: MoveJump ( float x , float y , float z , float speedXY , float speedZ , uint32 id )
2009-03-23 15:26:13 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)" , _owner -> GetGUIDLow (), x , y , z );
2009-10-17 15:51:44 -07:00
2012-01-14 15:34:41 +01:00
float moveTimeHalf = speedZ / Movement :: gravity ;
float max_height = - Movement :: computeFallElevation ( moveTimeHalf , false , - speedZ );
2010-08-25 18:24:40 +03:00
2012-08-25 22:57:55 -05:00
Movement :: MoveSplineInit init ( _owner );
2012-08-25 14:32:52 -05:00
init . MoveTo ( x , y , z , false );
2012-01-14 15:34:41 +01:00
init . SetParabolic ( max_height , 0 );
init . SetVelocity ( speedXY );
init . Launch ();
2012-02-17 00:19:14 +03:00
Mutate ( new EffectMovementGenerator ( id ), MOTION_SLOT_CONTROLLED );
2012-01-14 15:34:41 +01:00
}
2012-01-15 15:26:00 +01:00
void MotionMaster :: MoveFall ( uint32 id /*=0*/ )
2012-01-14 15:34:41 +01:00
{
// use larger distance for vmap height search than in most other cases
2012-02-14 12:46:26 -05:00
float tz = _owner -> GetMap () -> GetHeight ( _owner -> GetPhaseMask (), _owner -> GetPositionX (), _owner -> GetPositionY (), _owner -> GetPositionZ (), true , MAX_FALL_DISTANCE );
2012-01-14 15:34:41 +01:00
if ( tz <= INVALID_HEIGHT )
2009-03-23 15:26:13 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "MotionMaster::MoveFall: unable retrive a proper height at map %u (x: %f, y: %f, z: %f)." ,
2012-02-14 12:46:26 -05:00
_owner -> GetMap () -> GetId (), _owner -> GetPositionX (), _owner -> GetPositionX (), _owner -> GetPositionZ ());
2012-01-14 15:34:41 +01:00
return ;
2009-03-23 15:26:13 -06:00
}
2009-10-17 15:51:44 -07:00
2012-01-14 15:34:41 +01:00
// Abort too if the ground is very near
2012-02-14 12:46:26 -05:00
if ( fabs ( _owner -> GetPositionZ () - tz ) < 0.1f )
2012-01-14 15:34:41 +01:00
return ;
2012-04-08 12:17:43 +02:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
{
_owner -> AddUnitMovementFlag ( MOVEMENTFLAG_FALLING );
_owner -> m_movementInfo . SetFallTime ( 0 );
}
2012-08-25 22:57:55 -05:00
Movement :: MoveSplineInit init ( _owner );
2012-09-03 20:34:07 +02:00
init . MoveTo ( _owner -> GetPositionX (), _owner -> GetPositionY (), tz , false );
2012-01-14 15:34:41 +01:00
init . SetFall ();
init . Launch ();
2012-01-15 15:26:00 +01:00
Mutate ( new EffectMovementGenerator ( id ), MOTION_SLOT_CONTROLLED );
2009-03-23 15:26:13 -06:00
}
2009-10-17 15:51:44 -07:00
2012-04-09 18:36:45 +02:00
void MotionMaster :: MoveCharge ( float x , float y , float z , float speed , uint32 id , bool generatePath )
2009-01-17 17:46:28 -06:00
{
2010-04-07 19:14:10 +02:00
if ( Impl [ MOTION_SLOT_CONTROLLED ] && Impl [ MOTION_SLOT_CONTROLLED ] -> GetMovementGeneratorType () != DISTRACT_MOTION_TYPE )
2009-01-17 17:46:28 -06:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2009-01-17 17:46:28 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) charge point (X: %f Y: %f Z: %f)" , _owner -> GetGUIDLow (), x , y , z );
2012-04-09 18:36:45 +02:00
Mutate ( new PointMovementGenerator < Player > ( id , x , y , z , generatePath , speed ), MOTION_SLOT_CONTROLLED );
2009-01-17 17:46:28 -06:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) charge point (X: %f Y: %f Z: %f)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (), x , y , z );
2012-04-09 18:36:45 +02:00
Mutate ( new PointMovementGenerator < Creature > ( id , x , y , z , generatePath , speed ), MOTION_SLOT_CONTROLLED );
2009-01-17 17:46:28 -06:00
}
}
2009-10-17 15:51:44 -07:00
2012-09-03 20:30:30 +02:00
void MotionMaster :: MoveCharge ( PathGenerator path , float speed , uint32 id )
{
2012-09-05 23:47:02 +02:00
Vector3 dest = path . GetActualEndPosition ();
2012-09-03 20:30:30 +02:00
MoveCharge ( dest . x , dest . y , dest . z );
Movement :: MoveSplineInit init ( _owner );
2012-09-05 23:47:02 +02:00
init . MovebyPath ( path . GetPath ());
2012-09-03 20:30:30 +02:00
init . SetVelocity ( speed );
init . Launch ();
}
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveSeekAssistance ( float x , float y , float z )
2009-05-21 10:48:00 -05:00
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2009-05-21 10:48:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_GENERAL , "Player (GUID: %u) attempt to seek assistance" , _owner -> GetGUIDLow ());
2009-05-21 10:48:00 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) seek assistance (X: %f Y: %f Z: %f)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (), x , y , z );
_owner -> AttackStop ();
_owner -> ToCreature () -> SetReactState ( REACT_PASSIVE );
2011-04-29 20:47:02 +02:00
Mutate ( new AssistanceMovementGenerator ( x , y , z ), MOTION_SLOT_ACTIVE );
2009-05-21 10:48:00 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveSeekAssistanceDistract ( uint32 time )
2009-05-21 10:48:00 -05:00
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2009-05-21 10:48:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_GENERAL , "Player (GUID: %u) attempt to call distract after assistance" , _owner -> GetGUIDLow ());
2009-05-21 10:48:00 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) is distracted after assistance call (Time: %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (), time );
2009-05-21 10:48:00 -05:00
Mutate ( new AssistanceDistractMovementGenerator ( time ), MOTION_SLOT_ACTIVE );
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveFleeing ( Unit * enemy , uint32 time )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! enemy )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
if ( _owner -> HasAuraType ( SPELL_AURA_PREVENTS_FLEEING ))
2009-01-17 00:00:48 -06:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) flee from %s (GUID: %u)" , _owner -> GetGUIDLow (),
2009-10-18 18:38:46 -07:00
enemy -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" ,
2010-04-07 22:59:46 +02:00
enemy -> GetTypeId () == TYPEID_PLAYER ? enemy -> GetGUIDLow () : enemy -> ToCreature () -> GetDBTableGUIDLow ());
2009-01-16 22:57:03 -06:00
Mutate ( new FleeingMovementGenerator < Player > ( enemy -> GetGUID ()), MOTION_SLOT_CONTROLLED );
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)%s" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (),
2009-10-18 18:38:46 -07:00
enemy -> GetTypeId () == TYPEID_PLAYER ? "player" : "creature" ,
2010-03-07 18:30:53 +01:00
enemy -> GetTypeId () == TYPEID_PLAYER ? enemy -> GetGUIDLow () : enemy -> ToCreature () -> GetDBTableGUIDLow (),
2009-05-21 10:48:00 -05:00
time ? " for a limited time" : "" );
if ( time )
Mutate ( new TimedFleeingMovementGenerator ( enemy -> GetGUID (), time ), MOTION_SLOT_CONTROLLED );
else
Mutate ( new FleeingMovementGenerator < Creature > ( enemy -> GetGUID ()), MOTION_SLOT_CONTROLLED );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveTaxiFlight ( uint32 path , uint32 pathnode )
2008-10-11 14:16:25 -05:00
{
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2010-06-23 00:57:16 +02:00
if ( path < sTaxiPathNodesByPath . size ())
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "%s taxi to (Path %u node %u)" , _owner -> GetName (), path , pathnode );
2011-04-29 20:47:02 +02:00
FlightPathMovementGenerator * mgen = new FlightPathMovementGenerator ( sTaxiPathNodesByPath [ path ], pathnode );
2010-06-23 00:57:16 +02:00
Mutate ( mgen , MOTION_SLOT_CONTROLLED );
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_GENERAL , "%s attempt taxi to (not existed Path %u node %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetName (), path , pathnode );
2010-06-23 00:57:16 +02:00
}
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (), path , pathnode );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:40:14 +02:00
void MotionMaster :: MoveDistract ( uint32 timer )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( Impl [ MOTION_SLOT_CONTROLLED ])
2009-01-17 00:00:48 -06:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
if ( _owner -> GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player (GUID: %u) distracted (timer: %u)" , _owner -> GetGUIDLow (), timer );
2008-10-11 14:16:25 -05:00
}
else
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Creature (Entry: %u GUID: %u) (timer: %u)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetEntry (), _owner -> GetGUIDLow (), timer );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
DistractMovementGenerator * mgen = new DistractMovementGenerator ( timer );
2009-01-16 22:57:03 -06:00
Mutate ( mgen , MOTION_SLOT_CONTROLLED );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-01-16 22:57:03 -06:00
void MotionMaster :: Mutate ( MovementGenerator * m , MovementSlot slot )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( MovementGenerator * curr = Impl [ slot ])
2009-01-16 22:57:03 -06:00
{
2009-05-21 15:17:51 -05:00
Impl [ slot ] = NULL ; // in case a new one is generated in this slot during directdelete
2012-02-14 12:46:26 -05:00
if ( _top == slot && ( _cleanFlag & MMCF_UPDATE ))
2009-02-08 22:56:57 -06:00
DelayedDelete ( curr );
else
DirectDelete ( curr );
2009-01-16 22:57:03 -06:00
}
2012-02-14 12:46:26 -05:00
else if ( _top < slot )
2009-01-16 22:57:03 -06:00
{
2012-02-14 12:46:26 -05:00
_top = slot ;
2009-01-16 22:57:03 -06:00
}
2009-10-17 15:51:44 -07:00
2010-09-15 15:38:46 +02:00
Impl [ slot ] = m ;
2012-02-14 12:46:26 -05:00
if ( _top > slot )
_needInit [ slot ] = true ;
2009-03-04 10:16:15 -06:00
else
{
2012-02-14 12:46:26 -05:00
_needInit [ slot ] = false ;
2012-08-25 22:57:55 -05:00
m -> Initialize ( _owner );
2009-03-04 10:16:15 -06:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-12-09 23:06:16 -06:00
void MotionMaster :: MovePath ( uint32 path_id , bool repeatable )
{
2010-04-07 19:14:10 +02:00
if ( ! path_id )
2009-02-09 08:16:34 -05:00
return ;
//We set waypoint movement as new default movement generator
// clear ALL movement generators (including default)
2010-04-07 19:13:19 +02:00
/*while (!empty())
2008-12-09 23:06:16 -06:00
{
MovementGenerator *curr = top();
2012-02-14 12:46:26 -05:00
curr->Finalize(*_owner);
2008-12-09 23:06:16 -06:00
pop();
2010-04-07 22:59:46 +02:00
if (!isStatic(curr))
2008-12-09 23:06:16 -06:00
delete curr;
2009-01-17 17:46:28 -06:00
}*/
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
//_owner->GetTypeId() == TYPEID_PLAYER ?
2009-02-09 08:16:34 -05:00
//Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)):
2012-01-14 15:34:41 +01:00
Mutate ( new WaypointMovementGenerator < Creature > ( path_id , repeatable ), MOTION_SLOT_IDLE );
2009-10-17 15:51:44 -07:00
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "%s (GUID: %u) start moving over path(Id:%u, repeatable: %s)" ,
2012-02-14 12:46:26 -05:00
_owner -> GetTypeId () == TYPEID_PLAYER ? "Player" : "Creature" ,
_owner -> GetGUIDLow (), path_id , repeatable ? "YES" : "NO" );
2008-12-09 23:06:16 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-29 17:14:47 -05:00
void MotionMaster :: MoveRotate ( uint32 time , RotateDirection direction )
{
2010-04-07 19:14:10 +02:00
if ( ! time )
2009-08-30 11:50:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-29 17:14:47 -05:00
Mutate ( new RotateMovementGenerator ( time , direction ), MOTION_SLOT_ACTIVE );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void MotionMaster :: propagateSpeedChange ()
{
2009-01-16 22:57:03 -06:00
/*Impl::container_type::iterator it = Impl::c.begin();
2009-10-17 16:20:24 -07:00
for (; it != end(); ++it)
2008-10-11 14:16:25 -05:00
{
(*it)->unitSpeedChanged();
2009-01-16 22:57:03 -06:00
}*/
2012-02-14 12:46:26 -05:00
for ( int i = 0 ; i <= _top ; ++ i )
2009-01-17 13:29:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ( Impl [ i ])
2009-01-17 13:29:26 -06:00
Impl [ i ] -> unitSpeedChanged ();
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
MovementGeneratorType MotionMaster :: GetCurrentMovementGeneratorType () const
{
2010-04-07 19:14:10 +02:00
if ( empty ())
2008-10-11 14:16:25 -05:00
return IDLE_MOTION_TYPE ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return top () -> GetMovementGeneratorType ();
}
2009-10-17 15:51:44 -07:00
2009-03-15 10:50:10 -06:00
MovementGeneratorType MotionMaster :: GetMotionSlotType ( int slot ) const
{
2010-04-07 19:14:10 +02:00
if ( ! Impl [ slot ])
2009-03-15 10:50:10 -06:00
return NULL_MOTION_TYPE ;
else
return Impl [ slot ] -> GetMovementGeneratorType ();
}
2009-10-17 15:51:44 -07:00
2009-03-04 10:16:15 -06:00
void MotionMaster :: InitTop ()
{
2012-08-25 22:57:55 -05:00
top () -> Initialize ( _owner );
2012-02-14 12:46:26 -05:00
_needInit [ _top ] = false ;
2009-03-04 10:16:15 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-08 22:56:57 -06:00
void MotionMaster :: DirectDelete ( _Ty curr )
{
2010-04-07 19:14:10 +02:00
if ( isStatic ( curr ))
2009-02-08 22:56:57 -06:00
return ;
2012-08-25 22:57:55 -05:00
curr -> Finalize ( _owner );
2009-02-08 22:56:57 -06:00
delete curr ;
}
2009-10-17 15:51:44 -07:00
2009-02-08 22:56:57 -06:00
void MotionMaster :: DelayedDelete ( _Ty curr )
{
2012-08-03 14:20:18 +02:00
sLog -> outFatal ( LOG_FILTER_GENERAL , "Unit (Entry %u) is trying to delete its updating MG (Type %u)!" , _owner -> GetEntry (), curr -> GetMovementGeneratorType ());
2010-04-07 19:14:10 +02:00
if ( isStatic ( curr ))
2009-02-08 22:56:57 -06:00
return ;
2012-02-14 12:46:26 -05:00
if ( ! _expList )
_expList = new ExpireList ();
_expList -> push_back ( curr );
2009-02-08 22:56:57 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool MotionMaster :: GetDestination ( float & x , float & y , float & z )
{
2012-02-14 12:46:26 -05:00
if ( _owner -> movespline -> Finalized ())
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 16:20:24 -07:00
2012-02-14 12:46:26 -05:00
const G3D :: Vector3 & dest = _owner -> movespline -> FinalDestination ();
2012-01-14 15:34:41 +01:00
x = dest . x ;
y = dest . y ;
z = dest . z ;
return true ;
2008-10-11 14:16:25 -05:00
}