2012-01-14 15:34:41 +01:00
/*
* Copyright (C) 2005-2011 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 "MoveSplineInit.h"
#include "MoveSpline.h"
#include "MovementPacketBuilder.h"
#include "Unit.h"
2012-05-31 19:45:11 +02:00
#include "Transport.h"
#include "Vehicle.h"
2012-01-14 15:34:41 +01:00
namespace Movement
{
UnitMoveType SelectSpeedType ( uint32 moveFlags )
{
2012-03-15 13:14:42 +01:00
/*! Not sure about MOVEMENTFLAG_CAN_FLY here - do creatures that can fly
but are on ground right now also have it? If yes, this needs a more
dynamic check, such as is flying now
*/
if ( moveFlags & ( MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY ))
2012-01-14 15:34:41 +01:00
{
2012-03-15 13:14:42 +01:00
if ( moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/ )
2012-01-14 15:34:41 +01:00
return MOVE_FLIGHT_BACK ;
else
return MOVE_FLIGHT ;
}
else if ( moveFlags & MOVEMENTFLAG_SWIMMING )
{
if ( moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.swim >= speed_obj.swim_back*/ )
return MOVE_SWIM_BACK ;
else
return MOVE_SWIM ;
}
else if ( moveFlags & MOVEMENTFLAG_WALKING )
{
2012-03-15 13:14:42 +01:00
//if (speed_obj.run > speed_obj.walk)
2012-01-14 15:34:41 +01:00
return MOVE_WALK ;
}
else if ( moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.run >= speed_obj.run_back*/ )
return MOVE_RUN_BACK ;
return MOVE_RUN ;
}
void MoveSplineInit :: Launch ()
{
MoveSpline & move_spline = * unit . movespline ;
2012-05-31 19:45:11 +02:00
bool transport = false ;
Location real_position ( unit . GetPositionX (), unit . GetPositionY (), unit . GetPositionZMinusOffset (), unit . GetOrientation ());
2012-06-06 20:36:34 +02:00
// Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes
if ( unit . HasUnitMovementFlag ( MOVEMENTFLAG_ONTRANSPORT ) && unit . GetTransGUID ())
2012-05-31 19:45:11 +02:00
{
transport = true ;
real_position . x = unit . GetTransOffsetX ();
real_position . y = unit . GetTransOffsetY ();
real_position . z = unit . GetTransOffsetZ ();
real_position . orientation = unit . GetTransOffsetO ();
}
// there is a big chance that current position is unknown if current state is not finalized, need compute it
2012-01-14 15:34:41 +01:00
// this also allows calculate spline position and update map position in much greater intervals
2012-09-07 03:16:43 +02:00
// Don't compute for transport movement. The unit could be in a motion between two transports, thus having transport moveflag but is resulting in regular positions
else if ( ! move_spline . Finalized ())
2012-01-14 15:34:41 +01:00
real_position = move_spline . ComputePosition ();
2012-05-31 19:45:11 +02:00
// should i do the things that user should do? - no.
2012-01-14 15:34:41 +01:00
if ( args . path . empty ())
2012-05-31 19:45:11 +02:00
return ;
2012-01-14 15:34:41 +01:00
// corrent first vertex
args . path [ 0 ] = real_position ;
args . initialOrientation = real_position . orientation ;
uint32 moveFlags = unit . m_movementInfo . GetMovementFlags ();
if ( args . flags . walkmode )
moveFlags |= MOVEMENTFLAG_WALKING ;
else
moveFlags &= ~ MOVEMENTFLAG_WALKING ;
moveFlags |= ( MOVEMENTFLAG_SPLINE_ENABLED | MOVEMENTFLAG_FORWARD );
2012-05-31 19:45:11 +02:00
if ( ! args . HasVelocity )
2012-01-14 15:34:41 +01:00
args . velocity = unit . GetSpeed ( SelectSpeedType ( moveFlags ));
if ( ! args . Validate ())
return ;
if ( moveFlags & MOVEMENTFLAG_ROOT )
moveFlags &= ~ MOVEMENTFLAG_MASK_MOVING ;
unit . m_movementInfo . SetMovementFlags (( MovementFlags ) moveFlags );
move_spline . Initialize ( args );
2012-05-31 19:45:11 +02:00
WorldPacket data ( ! transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT , 64 );
2012-01-14 15:34:41 +01:00
data . append ( unit . GetPackGUID ());
2012-05-31 19:45:11 +02:00
if ( transport )
{
2012-06-06 20:36:34 +02:00
data . appendPackGUID ( unit . GetTransGUID ());
2012-05-31 19:45:11 +02:00
data << int8 ( unit . GetTransSeat ());
}
2012-01-14 15:34:41 +01:00
PacketBuilder :: WriteMonsterMove ( move_spline , data );
unit . SendMessageToSet ( & data , true );
}
MoveSplineInit :: MoveSplineInit ( Unit & m ) : unit ( m )
{
2012-06-06 20:36:34 +02:00
// Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes
args . TransformForTransport = unit . HasUnitMovementFlag ( MOVEMENTFLAG_ONTRANSPORT ) && unit . GetTransGUID ();
2012-01-14 15:34:41 +01:00
// mix existing state into new
args . flags . walkmode = unit . m_movementInfo . HasMovementFlag ( MOVEMENTFLAG_WALKING );
2012-03-12 00:45:58 +01:00
args . flags . flying = unit . m_movementInfo . HasMovementFlag (( MovementFlags )( MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY ));
2012-01-14 15:34:41 +01:00
}
void MoveSplineInit :: SetFacing ( const Unit * target )
{
args . flags . EnableFacingTarget ();
2012-06-07 23:20:57 +02:00
args . facing . target = target -> GetGUID ();
2012-01-14 15:34:41 +01:00
}
void MoveSplineInit :: SetFacing ( float angle )
{
2012-06-06 20:36:34 +02:00
if ( args . TransformForTransport )
2012-06-03 15:31:37 +02:00
{
if ( Unit * vehicle = unit . GetVehicleBase ())
angle -= vehicle -> GetOrientation ();
else if ( Transport * transport = unit . GetTransport ())
angle -= transport -> GetOrientation ();
}
2012-01-14 15:34:41 +01:00
args . facing . angle = G3D :: wrap ( angle , 0.f , ( float ) G3D :: twoPi ());
args . flags . EnableFacingAngle ();
}
2012-05-31 19:45:11 +02:00
void MoveSplineInit :: MoveTo ( Vector3 const & dest )
{
args . path_Idx_offset = 0 ;
args . path . resize ( 2 );
2012-06-06 20:36:34 +02:00
TransportPathTransform transform ( unit , args . TransformForTransport );
2012-05-31 19:45:11 +02:00
args . path [ 1 ] = transform ( dest );
}
Vector3 TransportPathTransform :: operator ()( Vector3 input )
{
2012-06-06 20:36:34 +02:00
if ( _transformForTransport )
2012-05-31 19:45:11 +02:00
{
if ( Unit * vehicle = _owner . GetVehicleBase ())
{
input . x -= vehicle -> GetPositionX ();
input . y -= vehicle -> GetPositionY ();
input . z -= vehicle -> GetPositionZMinusOffset ();
}
else if ( Transport * transport = _owner . GetTransport ())
{
float unused = 0.0f ;
transport -> CalculatePassengerOffset ( input . x , input . y , input . z , unused );
}
}
return input ;
}
2012-01-14 15:34:41 +01:00
}