mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 10:37:03 +00:00
[11720] Implement spline movement subsystem
Spline movement controls movements of server-side controlled units (monster movement, taxi movement, etc). Proper implementation of effects such as charge, jump, cyclic movement will rely on it. However, need improve our states system before. Technical changes: 1. Added linear, catmullrom and bezier3 splines which based on client's algorthims. They can be reused for proper transport position interpolation. 2. Precission increased. There are no more position desync issues since client's position calculation formulas used. 3. Now possible to move by paths with multiple points, send whole path to client.
This commit is contained in:
parent
e302fce513
commit
9d566398ad
52 changed files with 2471 additions and 1203 deletions
|
|
@ -41,7 +41,7 @@ source_group("World/Handlers"
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group("Motion generators"
|
source_group("Motion generators"
|
||||||
REGULAR_EXPRESSION Movement|Holder|Motion|Traveller
|
REGULAR_EXPRESSION Generator|MotionMaster
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group("Server"
|
source_group("Server"
|
||||||
|
|
@ -64,6 +64,13 @@ source_group("References"
|
||||||
REGULAR_EXPRESSION Reference|RefManager|ThreatManager
|
REGULAR_EXPRESSION Reference|RefManager|ThreatManager
|
||||||
)
|
)
|
||||||
|
|
||||||
|
source_group("Movement"
|
||||||
|
REGULAR_EXPRESSION spline|Spline|packet_builder
|
||||||
|
FILES
|
||||||
|
movement/typedefs.h
|
||||||
|
movement/util.cpp
|
||||||
|
)
|
||||||
|
|
||||||
if(PCH)
|
if(PCH)
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "MapManager.h"
|
#include "MapManager.h"
|
||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
#include "DestinationHolderImp.h"
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void
|
void
|
||||||
|
|
@ -71,8 +72,6 @@ template<>
|
||||||
void
|
void
|
||||||
ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
|
ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
|
||||||
{
|
{
|
||||||
creature.RemoveSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
is_water_ok = creature.CanSwim();
|
is_water_ok = creature.CanSwim();
|
||||||
is_land_ok = creature.CanWalk();
|
is_land_ok = creature.CanWalk();
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +96,6 @@ void ConfusedMovementGenerator<T>::Reset(T &unit)
|
||||||
{
|
{
|
||||||
i_nextMove = 1;
|
i_nextMove = 1;
|
||||||
i_nextMoveTime.Reset(0);
|
i_nextMoveTime.Reset(0);
|
||||||
i_destinationHolder.ResetUpdate();
|
|
||||||
unit.StopMoving();
|
unit.StopMoving();
|
||||||
unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
|
unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
|
||||||
}
|
}
|
||||||
|
|
@ -105,9 +103,6 @@ void ConfusedMovementGenerator<T>::Reset(T &unit)
|
||||||
template<class T>
|
template<class T>
|
||||||
bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||||
{
|
{
|
||||||
if(!&unit)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// ignore in case other no reaction state
|
// ignore in case other no reaction state
|
||||||
if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED))
|
if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED))
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -116,36 +111,30 @@ bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||||
{
|
{
|
||||||
// currently moving, update location
|
// currently moving, update location
|
||||||
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
|
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
|
||||||
Traveller<T> traveller(unit);
|
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, diff, false))
|
if (unit.movespline->Finalized())
|
||||||
{
|
{
|
||||||
if (!IsActive(unit)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
|
||||||
return true; // not expire now, but already lost
|
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
|
||||||
|
|
||||||
if (i_destinationHolder.HasArrived())
|
|
||||||
{
|
|
||||||
// arrived, stop and wait a bit
|
|
||||||
unit.StopMoving();
|
|
||||||
|
|
||||||
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
|
|
||||||
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// waiting for next move
|
// waiting for next move
|
||||||
i_nextMoveTime.Update(diff);
|
i_nextMoveTime.Update(diff);
|
||||||
if( i_nextMoveTime.Passed() )
|
if(i_nextMoveTime.Passed() )
|
||||||
{
|
{
|
||||||
// start moving
|
// start moving
|
||||||
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
|
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
|
||||||
|
|
||||||
MANGOS_ASSERT( i_nextMove <= MAX_CONF_WAYPOINTS );
|
MANGOS_ASSERT( i_nextMove <= MAX_CONF_WAYPOINTS );
|
||||||
const float x = i_waypoints[i_nextMove][0];
|
float x = i_waypoints[i_nextMove][0];
|
||||||
const float y = i_waypoints[i_nextMove][1];
|
float y = i_waypoints[i_nextMove][1];
|
||||||
const float z = i_waypoints[i_nextMove][2];
|
float z = i_waypoints[i_nextMove][2];
|
||||||
Traveller<T> traveller(unit);
|
Movement::MoveSplineInit init(unit);
|
||||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
init.MoveTo(x, y, z);
|
||||||
|
init.SetWalk(true);
|
||||||
|
init.Launch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -161,7 +150,6 @@ template<>
|
||||||
void ConfusedMovementGenerator<Creature>::Finalize(Creature &unit)
|
void ConfusedMovementGenerator<Creature>::Finalize(Creature &unit)
|
||||||
{
|
{
|
||||||
unit.clearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
|
unit.clearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
|
||||||
unit.AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
|
template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
#define MANGOS_CONFUSEDMOVEMENTGENERATOR_H
|
#define MANGOS_CONFUSEDMOVEMENTGENERATOR_H
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
|
|
||||||
#define MAX_CONF_WAYPOINTS 24
|
#define MAX_CONF_WAYPOINTS 24
|
||||||
|
|
||||||
|
|
@ -43,7 +41,6 @@ class MANGOS_DLL_SPEC ConfusedMovementGenerator
|
||||||
void _InitSpecific(T &, bool &, bool &);
|
void _InitSpecific(T &, bool &, bool &);
|
||||||
TimeTracker i_nextMoveTime;
|
TimeTracker i_nextMoveTime;
|
||||||
float i_waypoints[MAX_CONF_WAYPOINTS+1][3];
|
float i_waypoints[MAX_CONF_WAYPOINTS+1][3];
|
||||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
|
||||||
uint32 i_nextMove;
|
uint32 i_nextMove;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@
|
||||||
#include "GridNotifiers.h"
|
#include "GridNotifiers.h"
|
||||||
#include "GridNotifiersImpl.h"
|
#include "GridNotifiersImpl.h"
|
||||||
#include "CellImpl.h"
|
#include "CellImpl.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
// apply implementation of the singletons
|
// apply implementation of the singletons
|
||||||
#include "Policies/SingletonImp.h"
|
#include "Policies/SingletonImp.h"
|
||||||
|
|
@ -163,7 +165,7 @@ m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
|
||||||
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
|
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
|
||||||
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
|
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
|
||||||
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_temporaryFactionFlags(TEMPFACTION_NONE),
|
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_temporaryFactionFlags(TEMPFACTION_NONE),
|
||||||
m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)
|
m_creatureInfo(NULL)
|
||||||
{
|
{
|
||||||
m_regenTimer = 200;
|
m_regenTimer = 200;
|
||||||
m_valuesCount = UNIT_END;
|
m_valuesCount = UNIT_END;
|
||||||
|
|
@ -173,8 +175,6 @@ m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)
|
||||||
|
|
||||||
m_CreatureSpellCooldowns.clear();
|
m_CreatureSpellCooldowns.clear();
|
||||||
m_CreatureCategoryCooldowns.clear();
|
m_CreatureCategoryCooldowns.clear();
|
||||||
|
|
||||||
m_splineFlags = SPLINEFLAG_WALKMODE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Creature::~Creature()
|
Creature::~Creature()
|
||||||
|
|
@ -322,6 +322,8 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
|
||||||
UpdateSpeed(MOVE_WALK, false);
|
UpdateSpeed(MOVE_WALK, false);
|
||||||
UpdateSpeed(MOVE_RUN, false);
|
UpdateSpeed(MOVE_RUN, false);
|
||||||
|
|
||||||
|
SetLevitate(CanFly());
|
||||||
|
|
||||||
// checked at loading
|
// checked at loading
|
||||||
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
|
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
|
||||||
|
|
||||||
|
|
@ -1484,8 +1486,6 @@ void Creature::SetDeathState(DeathState s)
|
||||||
SetHealth(GetMaxHealth());
|
SetHealth(GetMaxHealth());
|
||||||
SetLootRecipient(NULL);
|
SetLootRecipient(NULL);
|
||||||
|
|
||||||
AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
if (GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_RESPAWN)
|
if (GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_RESPAWN)
|
||||||
ClearTemporaryFaction();
|
ClearTemporaryFaction();
|
||||||
|
|
||||||
|
|
@ -1530,25 +1530,19 @@ bool Creature::FallGround()
|
||||||
|
|
||||||
Unit::SetDeathState(CORPSE_FALLING);
|
Unit::SetDeathState(CORPSE_FALLING);
|
||||||
|
|
||||||
float dz = tz - GetPositionZ();
|
|
||||||
float distance = sqrt(dz*dz);
|
|
||||||
|
|
||||||
// default run speed * 2 explicit, not verified though but result looks proper
|
|
||||||
double speed = baseMoveSpeed[MOVE_RUN] * 2;
|
|
||||||
|
|
||||||
speed *= 0.001; // to milliseconds
|
|
||||||
|
|
||||||
uint32 travelTime = uint32(distance/speed);
|
|
||||||
|
|
||||||
DEBUG_LOG("FallGround: traveltime: %u, distance: %f, speed: %f, from %f to %f", travelTime, distance, speed, GetPositionZ(), tz);
|
|
||||||
|
|
||||||
// For creatures that are moving towards target and dies, the visual effect is not nice.
|
// For creatures that are moving towards target and dies, the visual effect is not nice.
|
||||||
// It is possibly caused by a xyz mismatch in DestinationHolder's GetLocationNow and the location
|
// It is possibly caused by a xyz mismatch in DestinationHolder's GetLocationNow and the location
|
||||||
// of the mob in client. For mob that are already reached target or dies while not moving
|
// of the mob in client. For mob that are already reached target or dies while not moving
|
||||||
// the visual appear to be fairly close to the expected.
|
// the visual appear to be fairly close to the expected.
|
||||||
|
|
||||||
|
Movement::MoveSplineInit init(*this);
|
||||||
|
init.MoveTo(GetPositionX(),GetPositionY(),tz);
|
||||||
|
init.SetFall();
|
||||||
|
init.Launch();
|
||||||
|
|
||||||
|
// hacky solution: by some reason died creatures not updated, that's why need finalize movement state
|
||||||
GetMap()->CreatureRelocation(this, GetPositionX(), GetPositionY(), tz, GetOrientation());
|
GetMap()->CreatureRelocation(this, GetPositionX(), GetPositionY(), tz, GetOrientation());
|
||||||
SendMonsterMove(GetPositionX(), GetPositionY(), tz, SPLINETYPE_NORMAL, SPLINEFLAG_FALLING, travelTime);
|
movespline->_Finalize();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1955,8 +1949,8 @@ bool Creature::LoadCreatureAddon(bool reload)
|
||||||
if (cainfo->emote != 0)
|
if (cainfo->emote != 0)
|
||||||
SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote);
|
SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote);
|
||||||
|
|
||||||
if (cainfo->splineFlags != 0)
|
if (cainfo->splineFlags & SPLINEFLAG_FLYING)
|
||||||
SetSplineFlags(SplineFlags(cainfo->splineFlags));
|
SetLevitate(true);
|
||||||
|
|
||||||
if(cainfo->auras)
|
if(cainfo->auras)
|
||||||
{
|
{
|
||||||
|
|
@ -2387,13 +2381,6 @@ void Creature::SetActiveObjectState( bool on )
|
||||||
map->Add(this);
|
map->Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::SendMonsterMoveWithSpeedToCurrentDestination(Player* player)
|
|
||||||
{
|
|
||||||
float x, y, z;
|
|
||||||
if (!IsStopped() && GetMotionMaster()->GetDestination(x, y, z))
|
|
||||||
SendMonsterMoveWithSpeed(x, y, z, 0, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl)
|
void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl)
|
||||||
{
|
{
|
||||||
uint32 next_resurrect = 0;
|
uint32 next_resurrect = 0;
|
||||||
|
|
@ -2490,3 +2477,26 @@ bool Creature::HasStaticDBSpawnData() const
|
||||||
{
|
{
|
||||||
return sObjectMgr.GetCreatureData(GetGUIDLow()) != NULL;
|
return sObjectMgr.GetCreatureData(GetGUIDLow()) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Creature::SetWalk(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
m_movementInfo.AddMovementFlag(MOVEFLAG_WALK_MODE);
|
||||||
|
else
|
||||||
|
m_movementInfo.RemoveMovementFlag(MOVEFLAG_WALK_MODE);
|
||||||
|
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
|
||||||
|
data << GetPackGUID();
|
||||||
|
SendMessageToSet(&data, true);
|
||||||
|
UpdateWalkMode(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Creature::SetLevitate(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
m_movementInfo.AddMovementFlag(MOVEFLAG_LEVITATING);
|
||||||
|
else
|
||||||
|
m_movementInfo.RemoveMovementFlag(MOVEFLAG_LEVITATING);
|
||||||
|
WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
|
||||||
|
data << GetPackGUID();
|
||||||
|
SendMessageToSet(&data, true);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -516,31 +516,10 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
||||||
|
|
||||||
CreatureAI* AI() { return i_AI; }
|
CreatureAI* AI() { return i_AI; }
|
||||||
|
|
||||||
void AddSplineFlag(SplineFlags f)
|
void SetWalk(bool enable);
|
||||||
{
|
void SetLevitate(bool enable);
|
||||||
bool need_walk_sync = (f & SPLINEFLAG_WALKMODE) != (m_splineFlags & SPLINEFLAG_WALKMODE);
|
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING);}
|
||||||
m_splineFlags = SplineFlags(m_splineFlags | f);
|
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);}
|
||||||
if (need_walk_sync)
|
|
||||||
UpdateWalkMode(this, false);
|
|
||||||
}
|
|
||||||
void RemoveSplineFlag(SplineFlags f)
|
|
||||||
{
|
|
||||||
bool need_walk_sync = (f & SPLINEFLAG_WALKMODE) != (m_splineFlags & SPLINEFLAG_WALKMODE);
|
|
||||||
m_splineFlags = SplineFlags(m_splineFlags & ~f);
|
|
||||||
if (need_walk_sync)
|
|
||||||
UpdateWalkMode(this, false);
|
|
||||||
}
|
|
||||||
bool HasSplineFlag(SplineFlags f) const { return m_splineFlags & f; }
|
|
||||||
SplineFlags GetSplineFlags() const { return m_splineFlags; }
|
|
||||||
void SetSplineFlags(SplineFlags f)
|
|
||||||
{
|
|
||||||
bool need_walk_sync = (f & SPLINEFLAG_WALKMODE) != (m_splineFlags & SPLINEFLAG_WALKMODE);
|
|
||||||
m_splineFlags = f; // need set before
|
|
||||||
if (need_walk_sync)
|
|
||||||
UpdateWalkMode(this, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
|
|
||||||
|
|
||||||
uint32 GetShieldBlockValue() const // dunno mob block value
|
uint32 GetShieldBlockValue() const // dunno mob block value
|
||||||
{
|
{
|
||||||
|
|
@ -762,7 +741,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
||||||
private:
|
private:
|
||||||
GridReference<Creature> m_gridRef;
|
GridReference<Creature> m_gridRef;
|
||||||
CreatureInfo const* m_creatureInfo; // in difficulty mode > 0 can different from ObjMgr::GetCreatureTemplate(GetEntry())
|
CreatureInfo const* m_creatureInfo; // in difficulty mode > 0 can different from ObjMgr::GetCreatureTemplate(GetEntry())
|
||||||
SplineFlags m_splineFlags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AssistDelayEvent : public BasicEvent
|
class AssistDelayEvent : public BasicEvent
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MANGOS_DESTINATION_HOLDER_H
|
|
||||||
#define MANGOS_DESTINATION_HOLDER_H
|
|
||||||
|
|
||||||
#include "Platform/Define.h"
|
|
||||||
#include "Timer.h"
|
|
||||||
|
|
||||||
class WorldObject;
|
|
||||||
class Map;
|
|
||||||
|
|
||||||
#define TRAVELLER_UPDATE_INTERVAL 300
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
class MANGOS_DLL_DECL DestinationHolder
|
|
||||||
{
|
|
||||||
ShortTimeTracker i_tracker;
|
|
||||||
uint32 i_totalTravelTime;
|
|
||||||
uint32 i_timeElapsed;
|
|
||||||
bool i_destSet;
|
|
||||||
float i_fromX, i_fromY, i_fromZ;
|
|
||||||
float i_destX, i_destY, i_destZ;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DestinationHolder() : i_tracker(TRAVELLER_UPDATE_INTERVAL), i_totalTravelTime(0), i_timeElapsed(0),
|
|
||||||
i_destSet(false), i_fromX(0), i_fromY(0), i_fromZ(0), i_destX(0), i_destY(0), i_destZ(0) {}
|
|
||||||
|
|
||||||
uint32 SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove = true);
|
|
||||||
void GetDestination(float &x, float &y, float &z) const { x = i_destX; y = i_destY; z = i_destZ; }
|
|
||||||
bool UpdateExpired(void) const { return i_tracker.Passed(); }
|
|
||||||
void ResetUpdate(uint32 t = TRAVELLER_UPDATE_INTERVAL) { i_tracker.Reset(t); }
|
|
||||||
uint32 GetTotalTravelTime(void) const { return i_totalTravelTime; }
|
|
||||||
void IncreaseTravelTime(uint32 increment) { i_totalTravelTime += increment; }
|
|
||||||
bool HasDestination(void) const { return i_destSet; }
|
|
||||||
float GetDestinationDiff(float x, float y, float z) const;
|
|
||||||
bool HasArrived(void) const { return (i_totalTravelTime == 0 || i_timeElapsed >= i_totalTravelTime); }
|
|
||||||
bool UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update=false, bool micro_movement=false);
|
|
||||||
uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true);
|
|
||||||
void GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D = false) const;
|
|
||||||
void GetLocationNowNoMicroMovement(float &x, float &y, float &z) const; // For use without micro movement
|
|
||||||
float GetDistance3dFromDestSq(const WorldObject &obj) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y);
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MANGOS_DESTINATIONHOLDERIMP_H
|
|
||||||
#define MANGOS_DESTINATIONHOLDERIMP_H
|
|
||||||
|
|
||||||
#include "MapManager.h"
|
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Unit.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
void
|
|
||||||
DestinationHolder<TRAVELLER>::_findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y)
|
|
||||||
{
|
|
||||||
/* given the point (x1, y1) and (x2, y2).. need to find the point (x,y) on the same line
|
|
||||||
* such that the distance from (x, y) to (x2, y2) is offset.
|
|
||||||
* Let the distance of p1 to p2 = d.. then the ratio of offset/d = (x2-x)/(x2-x1)
|
|
||||||
* hence x = x2 - (offset/d)*(x2-x1)
|
|
||||||
* like wise offset/d = (y2-y)/(y2-y1);
|
|
||||||
*/
|
|
||||||
if( offset == 0 )
|
|
||||||
{
|
|
||||||
x = x2;
|
|
||||||
y = y2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double x_diff = double(x2 - x1);
|
|
||||||
double y_diff = double(y2 - y1);
|
|
||||||
double distance_d = (double)((x_diff*x_diff) + (y_diff * y_diff));
|
|
||||||
if(distance_d == 0)
|
|
||||||
{
|
|
||||||
x = x2;
|
|
||||||
y = y2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
distance_d = ::sqrt(distance_d); // starting distance
|
|
||||||
double distance_ratio = (double)(distance_d - offset)/(double)distance_d;
|
|
||||||
// line above has revised formula which is more correct, I think
|
|
||||||
x = (float)(x1 + (distance_ratio*x_diff));
|
|
||||||
y = (float)(y1 + (distance_ratio*y_diff));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
uint32
|
|
||||||
DestinationHolder<TRAVELLER>::SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove)
|
|
||||||
{
|
|
||||||
i_destSet = true;
|
|
||||||
i_destX = dest_x;
|
|
||||||
i_destY = dest_y;
|
|
||||||
i_destZ = dest_z;
|
|
||||||
|
|
||||||
return StartTravel(traveller, sendMove);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
uint32
|
|
||||||
DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove)
|
|
||||||
{
|
|
||||||
if(!i_destSet) return 0;
|
|
||||||
|
|
||||||
i_fromX = traveller.GetPositionX();
|
|
||||||
i_fromY = traveller.GetPositionY();
|
|
||||||
i_fromZ = traveller.GetPositionZ();
|
|
||||||
|
|
||||||
i_totalTravelTime = traveller.GetTotalTravelTimeTo(i_destX,i_destY,i_destZ);
|
|
||||||
i_timeElapsed = 0;
|
|
||||||
if(sendMove)
|
|
||||||
{
|
|
||||||
if (i_totalTravelTime)
|
|
||||||
traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime);
|
|
||||||
else
|
|
||||||
traveller.Stop();
|
|
||||||
}
|
|
||||||
return i_totalTravelTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
bool
|
|
||||||
DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update, bool micro_movement)
|
|
||||||
{
|
|
||||||
if (!micro_movement)
|
|
||||||
{
|
|
||||||
i_tracker.Update(diff);
|
|
||||||
i_timeElapsed += diff;
|
|
||||||
if (i_tracker.Passed() || force_update)
|
|
||||||
{
|
|
||||||
ResetUpdate();
|
|
||||||
if (!i_destSet)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
float x,y,z;
|
|
||||||
GetLocationNowNoMicroMovement(x, y, z);
|
|
||||||
|
|
||||||
if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
|
|
||||||
{
|
|
||||||
float ori = traveller.GetTraveller().GetAngle(x, y);
|
|
||||||
traveller.Relocation(x, y, z, ori);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
i_tracker.Update(diff);
|
|
||||||
i_timeElapsed += diff;
|
|
||||||
if (i_tracker.Passed() || force_update)
|
|
||||||
{
|
|
||||||
ResetUpdate();
|
|
||||||
if (!i_destSet) return true;
|
|
||||||
|
|
||||||
if (!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_TAXI_FLIGHT))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
float x,y,z;
|
|
||||||
if (traveller.GetTraveller().hasUnitState(UNIT_STAT_TAXI_FLIGHT))
|
|
||||||
GetLocationNow(traveller.GetTraveller().GetMap() ,x, y, z, true); // Should reposition Object with right Coord, so I can bypass some Grid Relocation
|
|
||||||
else
|
|
||||||
GetLocationNow(traveller.GetTraveller().GetMap(), x, y, z, false);
|
|
||||||
|
|
||||||
if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
|
|
||||||
{
|
|
||||||
float ori = traveller.GetTraveller().GetAngle(x, y);
|
|
||||||
traveller.Relocation(x, y, z, ori);
|
|
||||||
}
|
|
||||||
// Change movement computation to micro movement based on last tick coords, this makes system work
|
|
||||||
// even on multiple floors zones without hugh vmaps usage ;)
|
|
||||||
|
|
||||||
// Take care of underrun of uint32
|
|
||||||
if (i_totalTravelTime >= i_timeElapsed)
|
|
||||||
i_totalTravelTime -= i_timeElapsed; // Consider only the remaining part
|
|
||||||
else
|
|
||||||
i_totalTravelTime = 0;
|
|
||||||
|
|
||||||
i_timeElapsed = 0;
|
|
||||||
i_fromX = x; // and change origine
|
|
||||||
i_fromY = y; // then I take into account only micro movement
|
|
||||||
i_fromZ = z;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
void
|
|
||||||
DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D) const
|
|
||||||
{
|
|
||||||
if (HasArrived())
|
|
||||||
{
|
|
||||||
x = i_destX;
|
|
||||||
y = i_destY;
|
|
||||||
z = i_destZ;
|
|
||||||
}
|
|
||||||
else if (HasDestination())
|
|
||||||
{
|
|
||||||
double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime;
|
|
||||||
const float distanceX = float((i_destX - i_fromX) * percent_passed);
|
|
||||||
const float distanceY = float((i_destY - i_fromY) * percent_passed);
|
|
||||||
const float distanceZ = float((i_destZ - i_fromZ) * percent_passed);
|
|
||||||
x = i_fromX + distanceX;
|
|
||||||
y = i_fromY + distanceY;
|
|
||||||
float z2 = i_fromZ + distanceZ;
|
|
||||||
// All that is not finished but previous code neither... Traveller need be able to swim.
|
|
||||||
if (is3D)
|
|
||||||
z = z2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//That part is good for mob Walking on the floor. But the floor is not always what we thought.
|
|
||||||
z = map->GetTerrain()->GetHeight(x,y,i_fromZ,false); // Disable cave check
|
|
||||||
const float groundDist = sqrt(distanceX*distanceX + distanceY*distanceY);
|
|
||||||
const float zDist = fabs(i_fromZ - z) + 0.000001f;
|
|
||||||
const float slope = groundDist / zDist;
|
|
||||||
if(slope < 1.0f) // This prevents the ground returned by GetHeight to be used when in cave
|
|
||||||
z = z2; // a climb or jump of more than 45 is denied
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
float
|
|
||||||
DestinationHolder<TRAVELLER>::GetDistance3dFromDestSq(const WorldObject &obj) const
|
|
||||||
{
|
|
||||||
float x,y,z;
|
|
||||||
obj.GetPosition(x,y,z);
|
|
||||||
return (i_destX-x)*(i_destX-x)+(i_destY-y)*(i_destY-y)+(i_destZ-z)*(i_destZ-z);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
float
|
|
||||||
DestinationHolder<TRAVELLER>::GetDestinationDiff(float x, float y, float z) const
|
|
||||||
{
|
|
||||||
return sqrt(((x-i_destX)*(x-i_destX)) + ((y-i_destY)*(y-i_destY)) + ((z-i_destZ)*(z-i_destZ)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TRAVELLER>
|
|
||||||
void
|
|
||||||
DestinationHolder<TRAVELLER>::GetLocationNowNoMicroMovement(float &x, float &y, float &z) const
|
|
||||||
{
|
|
||||||
if (HasArrived())
|
|
||||||
{
|
|
||||||
x = i_destX;
|
|
||||||
y = i_destY;
|
|
||||||
z = i_destZ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime;
|
|
||||||
x = i_fromX + float((i_destX - i_fromX) * percent_passed);
|
|
||||||
y = i_fromY + float((i_destY - i_fromY) * percent_passed);
|
|
||||||
z = i_fromZ + float((i_destZ - i_fromZ) * percent_passed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -20,8 +20,9 @@
|
||||||
#include "CreatureAI.h"
|
#include "CreatureAI.h"
|
||||||
#include "MapManager.h"
|
#include "MapManager.h"
|
||||||
#include "FleeingMovementGenerator.h"
|
#include "FleeingMovementGenerator.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "ObjectAccessor.h"
|
#include "ObjectAccessor.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
#define MIN_QUIET_DISTANCE 28.0f
|
#define MIN_QUIET_DISTANCE 28.0f
|
||||||
#define MAX_QUIET_DISTANCE 43.0f
|
#define MAX_QUIET_DISTANCE 43.0f
|
||||||
|
|
@ -45,8 +46,11 @@ FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
owner.addUnitState(UNIT_STAT_FLEEING_MOVE);
|
owner.addUnitState(UNIT_STAT_FLEEING_MOVE);
|
||||||
Traveller<T> traveller(owner);
|
|
||||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
Movement::MoveSplineInit init(owner);
|
||||||
|
init.MoveTo(x,y,z);
|
||||||
|
init.SetWalk(false);
|
||||||
|
init.Launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -308,7 +312,6 @@ template<>
|
||||||
void
|
void
|
||||||
FleeingMovementGenerator<Creature>::_Init(Creature &owner)
|
FleeingMovementGenerator<Creature>::_Init(Creature &owner)
|
||||||
{
|
{
|
||||||
owner.RemoveSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
owner.SetTargetGuid(ObjectGuid());
|
owner.SetTargetGuid(ObjectGuid());
|
||||||
is_water_ok = owner.CanSwim();
|
is_water_ok = owner.CanSwim();
|
||||||
is_land_ok = owner.CanWalk();
|
is_land_ok = owner.CanWalk();
|
||||||
|
|
@ -331,7 +334,6 @@ void FleeingMovementGenerator<Player>::Finalize(Player &owner)
|
||||||
template<>
|
template<>
|
||||||
void FleeingMovementGenerator<Creature>::Finalize(Creature &owner)
|
void FleeingMovementGenerator<Creature>::Finalize(Creature &owner)
|
||||||
{
|
{
|
||||||
owner.AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
owner.clearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE);
|
owner.clearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -361,28 +363,10 @@ bool FleeingMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Traveller<T> traveller(owner);
|
|
||||||
|
|
||||||
i_nextCheckTime.Update(time_diff);
|
i_nextCheckTime.Update(time_diff);
|
||||||
|
if (i_nextCheckTime.Passed() && owner.movespline->Finalized())
|
||||||
if( (owner.IsStopped() && !i_destinationHolder.HasArrived()) || !i_destinationHolder.HasDestination() )
|
|
||||||
{
|
|
||||||
_setTargetLocation(owner);
|
_setTargetLocation(owner);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
|
|
||||||
{
|
|
||||||
if (!IsActive(owner)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
|
||||||
return true; // not expire now, but already lost
|
|
||||||
|
|
||||||
i_destinationHolder.ResetUpdate(50);
|
|
||||||
if(i_nextCheckTime.Passed() && i_destinationHolder.HasArrived())
|
|
||||||
{
|
|
||||||
_setTargetLocation(owner);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
#define MANGOS_FLEEINGMOVEMENTGENERATOR_H
|
#define MANGOS_FLEEINGMOVEMENTGENERATOR_H
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
#include "ObjectGuid.h"
|
#include "ObjectGuid.h"
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -57,8 +55,6 @@ class MANGOS_DLL_SPEC FleeingMovementGenerator
|
||||||
float i_cur_angle;
|
float i_cur_angle;
|
||||||
ObjectGuid i_frightGuid;
|
ObjectGuid i_frightGuid;
|
||||||
TimeTracker i_nextCheckTime;
|
TimeTracker i_nextCheckTime;
|
||||||
|
|
||||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MANGOS_DLL_SPEC TimedFleeingMovementGenerator
|
class MANGOS_DLL_SPEC TimedFleeingMovementGenerator
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,6 @@ VisibleNotifier::Notify()
|
||||||
// target aura duration for caster show only if target exist at caster client
|
// target aura duration for caster show only if target exist at caster client
|
||||||
if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
|
if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
|
||||||
player.SendAurasForTarget((Unit*)(*vItr));
|
player.SendAurasForTarget((Unit*)(*vItr));
|
||||||
|
|
||||||
// non finished movements show to player
|
|
||||||
if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
|
|
||||||
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&player);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,13 @@
|
||||||
#include "HomeMovementGenerator.h"
|
#include "HomeMovementGenerator.h"
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "CreatureAI.h"
|
#include "CreatureAI.h"
|
||||||
#include "Traveller.h"
|
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
void HomeMovementGenerator<Creature>::Initialize(Creature & owner)
|
void HomeMovementGenerator<Creature>::Initialize(Creature & owner)
|
||||||
{
|
{
|
||||||
owner.RemoveSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
_setTargetLocation(owner);
|
_setTargetLocation(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,56 +38,30 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
|
||||||
if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
|
if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float x, y, z;
|
Movement::MoveSplineInit init(owner);
|
||||||
|
float x, y, z, o;
|
||||||
// at apply we can select more nice return points base at current movegen
|
// at apply we can select more nice return points base at current movegen
|
||||||
if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z))
|
if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z))
|
||||||
owner.GetRespawnCoord(x, y, z);
|
{
|
||||||
|
owner.GetRespawnCoord(x, y, z, &o);
|
||||||
|
init.SetFacing(o);
|
||||||
|
}
|
||||||
|
init.MoveTo(x,y,z);
|
||||||
|
init.SetWalk(false);
|
||||||
|
init.Launch();
|
||||||
|
|
||||||
CreatureTraveller traveller(owner);
|
|
||||||
|
|
||||||
uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
|
|
||||||
modifyTravelTime(travel_time);
|
|
||||||
owner.clearUnitState(UNIT_STAT_ALL_STATE);
|
owner.clearUnitState(UNIT_STAT_ALL_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
|
bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
|
||||||
{
|
{
|
||||||
CreatureTraveller traveller( owner);
|
return !owner.movespline->Finalized();
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
|
|
||||||
{
|
|
||||||
if (!IsActive(owner)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
|
||||||
return true; // not expire now, but already lost
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time_diff >= i_travel_timer)
|
|
||||||
{
|
|
||||||
i_travel_timer = 0; // Used as check in Finalize
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_travel_timer -= time_diff;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HomeMovementGenerator<Creature>::Finalize(Creature& owner)
|
void HomeMovementGenerator<Creature>::Finalize(Creature& owner)
|
||||||
{
|
{
|
||||||
if (i_travel_timer == 0)
|
if (i_travel_timer == 0)
|
||||||
{
|
{
|
||||||
owner.AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
// restore orientation of not moving creature at returning to home
|
|
||||||
if (owner.GetDefaultMovementType() == IDLE_MOTION_TYPE)
|
|
||||||
{
|
|
||||||
// such a mob might need very exact spawning point, hence relocate to spawn-position
|
|
||||||
if (CreatureData const* data = sObjectMgr.GetCreatureData(owner.GetGUIDLow()))
|
|
||||||
{
|
|
||||||
owner.Relocate(data->posX, data->posY, data->posZ, data->orientation);
|
|
||||||
owner.SendHeartBeat(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owner.GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_REACH_HOME)
|
if (owner.GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_REACH_HOME)
|
||||||
owner.ClearTemporaryFaction();
|
owner.ClearTemporaryFaction();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
#define MANGOS_HOMEMOVEMENTGENERATOR_H
|
#define MANGOS_HOMEMOVEMENTGENERATOR_H
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
|
|
||||||
class Creature;
|
class Creature;
|
||||||
|
|
||||||
|
|
@ -45,11 +43,8 @@ class MANGOS_DLL_SPEC HomeMovementGenerator<Creature>
|
||||||
void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; }
|
void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; }
|
||||||
MovementGeneratorType GetMovementGeneratorType() const { return HOME_MOTION_TYPE; }
|
MovementGeneratorType GetMovementGeneratorType() const { return HOME_MOTION_TYPE; }
|
||||||
|
|
||||||
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
|
||||||
private:
|
private:
|
||||||
void _setTargetLocation(Creature &);
|
void _setTargetLocation(Creature &);
|
||||||
DestinationHolder< Traveller<Creature> > i_destinationHolder;
|
|
||||||
|
|
||||||
uint32 i_travel_timer;
|
uint32 i_travel_timer;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -6015,6 +6015,8 @@ bool ChatHandler::HandleMovegensCommand(char* /*args*/)
|
||||||
PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature" ),unit->GetGUIDLow());
|
PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature" ),unit->GetGUIDLow());
|
||||||
|
|
||||||
MotionMaster* mm = unit->GetMotionMaster();
|
MotionMaster* mm = unit->GetMotionMaster();
|
||||||
|
float x,y,z;
|
||||||
|
mm->GetDestination(x,y,z);
|
||||||
for(MotionMaster::const_iterator itr = mm->begin(); itr != mm->end(); ++itr)
|
for(MotionMaster::const_iterator itr = mm->begin(); itr != mm->end(); ++itr)
|
||||||
{
|
{
|
||||||
switch((*itr)->GetMovementGeneratorType())
|
switch((*itr)->GetMovementGeneratorType())
|
||||||
|
|
@ -6058,8 +6060,6 @@ bool ChatHandler::HandleMovegensCommand(char* /*args*/)
|
||||||
case HOME_MOTION_TYPE:
|
case HOME_MOTION_TYPE:
|
||||||
if(unit->GetTypeId()==TYPEID_UNIT)
|
if(unit->GetTypeId()==TYPEID_UNIT)
|
||||||
{
|
{
|
||||||
float x,y,z;
|
|
||||||
(*itr)->GetDestination(x,y,z);
|
|
||||||
PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE,x,y,z);
|
PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE,x,y,z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -6068,8 +6068,6 @@ bool ChatHandler::HandleMovegensCommand(char* /*args*/)
|
||||||
case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break;
|
case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break;
|
||||||
case POINT_MOTION_TYPE:
|
case POINT_MOTION_TYPE:
|
||||||
{
|
{
|
||||||
float x,y,z;
|
|
||||||
(*itr)->GetDestination(x,y,z);
|
|
||||||
PSendSysMessage(LANG_MOVEGENS_POINT,x,y,z);
|
PSendSysMessage(LANG_MOVEGENS_POINT,x,y,z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -6289,12 +6287,6 @@ bool ChatHandler::HandleComeToMeCommand(char *args)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 newFlags;
|
|
||||||
if (!ExtractUInt32(&args, newFlags))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
caster->SetSplineFlags(SplineFlags(newFlags));
|
|
||||||
|
|
||||||
Player* pl = m_session->GetPlayer();
|
Player* pl = m_session->GetPlayer();
|
||||||
|
|
||||||
caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ());
|
caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ());
|
||||||
|
|
|
||||||
|
|
@ -1924,6 +1924,7 @@ void Map::ScriptsProcess()
|
||||||
source->SetUInt32Value(step.script->setField.fieldId, step.script->setField.fieldValue);
|
source->SetUInt32Value(step.script->setField.fieldId, step.script->setField.fieldValue);
|
||||||
break;
|
break;
|
||||||
case SCRIPT_COMMAND_MOVE_TO:
|
case SCRIPT_COMMAND_MOVE_TO:
|
||||||
|
{
|
||||||
if (!source)
|
if (!source)
|
||||||
{
|
{
|
||||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO (script id %u) call for NULL creature.", step.script->id);
|
sLog.outError("SCRIPT_COMMAND_MOVE_TO (script id %u) call for NULL creature.", step.script->id);
|
||||||
|
|
@ -1936,8 +1937,16 @@ void Map::ScriptsProcess()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
((Unit*)source)->MonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->moveTo.travelTime);
|
Unit * unit = (Unit*)source;
|
||||||
|
if (step.script->moveTo.travelTime != 0)
|
||||||
|
{
|
||||||
|
float speed = unit->GetDistance(step.script->x, step.script->y, step.script->z) / ((float)step.script->moveTo.travelTime * 0.001f);
|
||||||
|
unit->MonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, speed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
unit->NearTeleportTo(step.script->x, step.script->y, step.script->z, unit->GetOrientation());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SCRIPT_COMMAND_FLAG_SET:
|
case SCRIPT_COMMAND_FLAG_SET:
|
||||||
if (!source)
|
if (!source)
|
||||||
{
|
{
|
||||||
|
|
@ -2791,10 +2800,7 @@ void Map::ScriptsProcess()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step.script->run.run)
|
pOwner->SetWalk(!step.script->run.run);
|
||||||
pOwner->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
else
|
|
||||||
pOwner->AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "GridDefines.h"
|
#include "GridDefines.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "CellImpl.h"
|
#include "CellImpl.h"
|
||||||
#include "Corpse.h"
|
#include "Corpse.h"
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@
|
||||||
#include "MotionMaster.h"
|
#include "MotionMaster.h"
|
||||||
#include "CreatureAISelector.h"
|
#include "CreatureAISelector.h"
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "Traveller.h"
|
|
||||||
|
|
||||||
#include "ConfusedMovementGenerator.h"
|
#include "ConfusedMovementGenerator.h"
|
||||||
#include "FleeingMovementGenerator.h"
|
#include "FleeingMovementGenerator.h"
|
||||||
#include "HomeMovementGenerator.h"
|
#include "HomeMovementGenerator.h"
|
||||||
|
|
@ -29,6 +27,7 @@
|
||||||
#include "TargetedMovementGenerator.h"
|
#include "TargetedMovementGenerator.h"
|
||||||
#include "WaypointMovementGenerator.h"
|
#include "WaypointMovementGenerator.h"
|
||||||
#include "RandomMovementGenerator.h"
|
#include "RandomMovementGenerator.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
@ -448,10 +447,14 @@ MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
|
||||||
|
|
||||||
bool MotionMaster::GetDestination(float &x, float &y, float &z)
|
bool MotionMaster::GetDestination(float &x, float &y, float &z)
|
||||||
{
|
{
|
||||||
if (empty())
|
if (m_owner->movespline->Finalized())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return top()->GetDestination(x,y,z);
|
const G3D::Vector3& dest = m_owner->movespline->FinalDestination();
|
||||||
|
x = dest.x;
|
||||||
|
y = dest.y;
|
||||||
|
z = dest.z;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionMaster::UpdateFinalDistanceToTarget(float fDistance)
|
void MotionMaster::UpdateFinalDistanceToTarget(float fDistance)
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,6 @@ class MANGOS_DLL_SPEC MovementGenerator
|
||||||
|
|
||||||
virtual void UpdateFinalDistance(float /*fDistance*/) { }
|
virtual void UpdateFinalDistance(float /*fDistance*/) { }
|
||||||
|
|
||||||
virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; }
|
|
||||||
|
|
||||||
// used by Evade code for select point to evade with expected restart default movement
|
// used by Evade code for select point to evade with expected restart default movement
|
||||||
virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; }
|
virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,9 @@
|
||||||
#include "CellImpl.h"
|
#include "CellImpl.h"
|
||||||
#include "GridNotifiers.h"
|
#include "GridNotifiers.h"
|
||||||
#include "GridNotifiersImpl.h"
|
#include "GridNotifiersImpl.h"
|
||||||
|
|
||||||
#include "ObjectPosSelector.h"
|
#include "ObjectPosSelector.h"
|
||||||
|
|
||||||
#include "TemporarySummon.h"
|
#include "TemporarySummon.h"
|
||||||
|
#include "movement/packet_builder.h"
|
||||||
|
|
||||||
Object::Object( )
|
Object::Object( )
|
||||||
{
|
{
|
||||||
|
|
@ -256,57 +255,13 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
|
||||||
{
|
{
|
||||||
Unit *unit = ((Unit*)this);
|
Unit *unit = ((Unit*)this);
|
||||||
|
|
||||||
switch(GetTypeId())
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
case TYPEID_UNIT:
|
Player *player = ((Player*)unit);
|
||||||
{
|
if(player->GetTransport())
|
||||||
unit->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
|
player->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
|
||||||
|
else
|
||||||
// disabled, makes them run-in-same-place before movement generator updated once.
|
player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
|
||||||
/*if (((Creature*)unit)->hasUnitState(UNIT_STAT_MOVING))
|
|
||||||
unit->m_movementInfo.SetMovementFlags(MOVEFLAG_FORWARD);*/
|
|
||||||
|
|
||||||
if (((Creature*)unit)->CanFly())
|
|
||||||
{
|
|
||||||
// (ok) most seem to have this
|
|
||||||
unit->m_movementInfo.AddMovementFlag(MOVEFLAG_LEVITATING);
|
|
||||||
|
|
||||||
/*if (!((Creature*)unit)->hasUnitState(UNIT_STAT_MOVING))
|
|
||||||
{
|
|
||||||
// (ok) possibly some "hover" mode
|
|
||||||
unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ROOT);
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
{
|
|
||||||
if (((Creature*)unit)->IsMounted())
|
|
||||||
{
|
|
||||||
// seems to be often when mounted
|
|
||||||
unit->m_movementInfo.AddMovementFlag(MOVEFLAG_FLYING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TYPEID_PLAYER:
|
|
||||||
{
|
|
||||||
Player *player = ((Player*)unit);
|
|
||||||
|
|
||||||
if(player->GetTransport())
|
|
||||||
player->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
|
|
||||||
else
|
|
||||||
player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
|
|
||||||
|
|
||||||
// remove unknown, unused etc flags for now
|
|
||||||
player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_SPLINE_ENABLED);
|
|
||||||
|
|
||||||
if(player->IsTaxiFlying())
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
|
|
||||||
player->m_movementInfo.AddMovementFlag(MOVEFLAG_FORWARD);
|
|
||||||
player->m_movementInfo.AddMovementFlag(MOVEFLAG_SPLINE_ENABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update movement info time
|
// Update movement info time
|
||||||
|
|
@ -326,86 +281,8 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
|
||||||
*data << float(unit->GetSpeed(MOVE_PITCH_RATE));
|
*data << float(unit->GetSpeed(MOVE_PITCH_RATE));
|
||||||
|
|
||||||
// 0x08000000
|
// 0x08000000
|
||||||
if(unit->m_movementInfo.GetMovementFlags() & MOVEFLAG_SPLINE_ENABLED)
|
if (unit->m_movementInfo.GetMovementFlags() & MOVEFLAG_SPLINE_ENABLED)
|
||||||
{
|
Movement::PacketBuilder::WriteCreate(*unit->movespline, *data);
|
||||||
if(GetTypeId() != TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
DEBUG_LOG("_BuildMovementUpdate: MOVEFLAG_SPLINE_ENABLED for non-player");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player *player = ((Player*)unit);
|
|
||||||
|
|
||||||
if(!player->IsTaxiFlying())
|
|
||||||
{
|
|
||||||
DEBUG_LOG("_BuildMovementUpdate: MOVEFLAG_SPLINE_ENABLED but not in flight");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MANGOS_ASSERT(player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
|
|
||||||
|
|
||||||
FlightPathMovementGenerator *fmg = (FlightPathMovementGenerator*)(player->GetMotionMaster()->top());
|
|
||||||
|
|
||||||
uint32 flags3 = SPLINEFLAG_WALKMODE | SPLINEFLAG_FLYING;
|
|
||||||
|
|
||||||
*data << uint32(flags3); // splines flag?
|
|
||||||
|
|
||||||
if(flags3 & SPLINEFLAG_FINALFACING) // may be orientation
|
|
||||||
{
|
|
||||||
*data << float(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(flags3 & SPLINEFLAG_FINALTARGET) // probably guid there
|
|
||||||
{
|
|
||||||
*data << uint64(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(flags3 & SPLINEFLAG_FINALPOINT) // probably x,y,z coords there
|
|
||||||
{
|
|
||||||
*data << float(0);
|
|
||||||
*data << float(0);
|
|
||||||
*data << float(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TaxiPathNodeList const& path = fmg->GetPath();
|
|
||||||
|
|
||||||
float x, y, z;
|
|
||||||
player->GetPosition(x, y, z);
|
|
||||||
|
|
||||||
uint32 inflighttime = uint32(path.GetPassedLength(fmg->GetCurrentNode(), x, y, z) * 32);
|
|
||||||
uint32 traveltime = uint32(path.GetTotalLength() * 32);
|
|
||||||
|
|
||||||
*data << uint32(inflighttime); // passed move time?
|
|
||||||
*data << uint32(traveltime); // full move time?
|
|
||||||
*data << uint32(0); // sequenceId
|
|
||||||
|
|
||||||
*data << float(0); // added in 3.1
|
|
||||||
*data << float(0); // added in 3.1
|
|
||||||
|
|
||||||
// data as in SMSG_MONSTER_MOVE with flag SPLINEFLAG_TRAJECTORY
|
|
||||||
*data << float(0); // parabolic speed, added in 3.1
|
|
||||||
*data << uint32(0); // parabolic time, added in 3.1
|
|
||||||
|
|
||||||
uint32 poscount = uint32(path.size());
|
|
||||||
*data << uint32(poscount); // points count
|
|
||||||
|
|
||||||
for(uint32 i = 0; i < poscount; ++i)
|
|
||||||
{
|
|
||||||
*data << float(path[i].x);
|
|
||||||
*data << float(path[i].y);
|
|
||||||
*data << float(path[i].z);
|
|
||||||
}
|
|
||||||
|
|
||||||
*data << uint8(0); // splineMode
|
|
||||||
|
|
||||||
*data << float(path[poscount-1].x);
|
|
||||||
*data << float(path[poscount-1].y);
|
|
||||||
*data << float(path[poscount-1].z);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20034,9 +20034,6 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe
|
||||||
// send data at target visibility change (adding to client)
|
// send data at target visibility change (adding to client)
|
||||||
if(target!=this && target->isType(TYPEMASK_UNIT))
|
if(target!=this && target->isType(TYPEMASK_UNIT))
|
||||||
SendAurasForTarget((Unit*)target);
|
SendAurasForTarget((Unit*)target);
|
||||||
|
|
||||||
if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isAlive())
|
|
||||||
((Creature*)target)->SendMonsterMoveWithSpeedToCurrentDestination(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "CreatureAI.h"
|
#include "CreatureAI.h"
|
||||||
#include "TemporarySummon.h"
|
#include "TemporarySummon.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
//----- Point Movement Generator
|
//----- Point Movement Generator
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -32,12 +33,9 @@ void PointMovementGenerator<T>::Initialize(T &unit)
|
||||||
unit.StopMoving();
|
unit.StopMoving();
|
||||||
|
|
||||||
unit.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
unit.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
|
Movement::MoveSplineInit init(unit);
|
||||||
Traveller<T> traveller(unit);
|
init.MoveTo(i_x, i_y, i_z);
|
||||||
i_destinationHolder.SetDestination(traveller, i_x, i_y, i_z);
|
init.Launch();
|
||||||
|
|
||||||
if (unit.GetTypeId() == TYPEID_UNIT && ((Creature*)&unit)->CanFly())
|
|
||||||
((Creature&)unit).AddSplineFlag(SPLINEFLAG_FLYING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -45,7 +43,7 @@ void PointMovementGenerator<T>::Finalize(T &unit)
|
||||||
{
|
{
|
||||||
unit.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
unit.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
|
|
||||||
if (i_destinationHolder.HasArrived())
|
if (unit.movespline->Finalized())
|
||||||
MovementInform(unit);
|
MovementInform(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,18 +75,7 @@ bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
unit.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
unit.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||||
|
return !unit.movespline->Finalized();
|
||||||
Traveller<T> traveller(unit);
|
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, diff, false))
|
|
||||||
{
|
|
||||||
if (!IsActive(unit)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
|
||||||
return true; // not expire now, but already lost
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i_destinationHolder.HasArrived())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
#define MANGOS_POINTMOVEMENTGENERATOR_H
|
#define MANGOS_POINTMOVEMENTGENERATOR_H
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
#include "FollowerReference.h"
|
#include "FollowerReference.h"
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -47,7 +45,6 @@ class MANGOS_DLL_SPEC PointMovementGenerator
|
||||||
uint32 id;
|
uint32 id;
|
||||||
float i_x,i_y,i_z;
|
float i_x,i_y,i_z;
|
||||||
TimeTracker i_nextMoveTime;
|
TimeTracker i_nextMoveTime;
|
||||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MANGOS_DLL_SPEC AssistanceMovementGenerator
|
class MANGOS_DLL_SPEC AssistanceMovementGenerator
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "MapManager.h"
|
#include "MapManager.h"
|
||||||
#include "RandomMovementGenerator.h"
|
#include "RandomMovementGenerator.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void
|
void
|
||||||
|
|
@ -91,15 +92,17 @@ RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
creature.AddSplineFlag(is_air_ok ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKMODE);
|
if (is_air_ok)
|
||||||
Traveller<Creature> traveller(creature);
|
i_nextMoveTime.Reset(0);
|
||||||
i_destinationHolder.SetDestination(traveller, destX, destY, destZ);
|
else
|
||||||
|
i_nextMoveTime.Reset(urand(500, 10000));
|
||||||
|
|
||||||
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||||
|
|
||||||
if (is_air_ok)
|
Movement::MoveSplineInit init(creature);
|
||||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
init.MoveTo(destX, destY, destZ);
|
||||||
else
|
init.SetWalk(true);
|
||||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime() + urand(500, 10000));
|
init.Launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
@ -108,11 +111,6 @@ void RandomMovementGenerator<Creature>::Initialize(Creature &creature)
|
||||||
if (!creature.isAlive())
|
if (!creature.isAlive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (creature.CanFly())
|
|
||||||
creature.AddSplineFlag(SPLINEFLAG_FLYING);
|
|
||||||
else
|
|
||||||
creature.AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
_setRandomLocation(creature);
|
_setRandomLocation(creature);
|
||||||
}
|
}
|
||||||
|
|
@ -127,12 +125,14 @@ template<>
|
||||||
void RandomMovementGenerator<Creature>::Interrupt(Creature &creature)
|
void RandomMovementGenerator<Creature>::Interrupt(Creature &creature)
|
||||||
{
|
{
|
||||||
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
|
creature.SetWalk(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void RandomMovementGenerator<Creature>::Finalize(Creature &creature)
|
void RandomMovementGenerator<Creature>::Finalize(Creature &creature)
|
||||||
{
|
{
|
||||||
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
|
creature.SetWalk(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
@ -145,17 +145,12 @@ bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureTraveller traveller(creature);
|
if (creature.movespline->Finalized())
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true))
|
|
||||||
{
|
{
|
||||||
if (!IsActive(creature)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
i_nextMoveTime.Update(diff);
|
||||||
return true; // not expire now, but already lost
|
if (i_nextMoveTime.Passed())
|
||||||
|
_setRandomLocation(creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
i_nextMoveTime.Update(diff);
|
|
||||||
if (i_nextMoveTime.Passed())
|
|
||||||
_setRandomLocation(creature);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
#define MANGOS_RANDOMMOTIONGENERATOR_H
|
#define MANGOS_RANDOMMOTIONGENERATOR_H
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class MANGOS_DLL_SPEC RandomMovementGenerator
|
class MANGOS_DLL_SPEC RandomMovementGenerator
|
||||||
|
|
@ -36,17 +34,11 @@ class MANGOS_DLL_SPEC RandomMovementGenerator
|
||||||
void Interrupt(T &);
|
void Interrupt(T &);
|
||||||
void Reset(T &);
|
void Reset(T &);
|
||||||
bool Update(T &, const uint32 &);
|
bool Update(T &, const uint32 &);
|
||||||
void UpdateMapPosition(uint32 mapid, float &x ,float &y, float &z)
|
|
||||||
{
|
|
||||||
i_destinationHolder.GetLocationNow(mapid, x,y,z);
|
|
||||||
}
|
|
||||||
MovementGeneratorType GetMovementGeneratorType() const { return RANDOM_MOTION_TYPE; }
|
MovementGeneratorType GetMovementGeneratorType() const { return RANDOM_MOTION_TYPE; }
|
||||||
|
|
||||||
bool GetResetPosition(T&, float& x, float& y, float& z);
|
bool GetResetPosition(T&, float& x, float& y, float& z);
|
||||||
private:
|
private:
|
||||||
ShortTimeTracker i_nextMoveTime;
|
ShortTimeTracker i_nextMoveTime;
|
||||||
|
|
||||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
|
||||||
uint32 i_nextMove;
|
uint32 i_nextMove;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4056,7 +4056,6 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||||
pet->AddSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2069,7 +2069,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx)
|
||||||
if (unitTarget->hasUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE))
|
if (unitTarget->hasUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE))
|
||||||
unitTarget->GetMotionMaster()->MovementExpired();
|
unitTarget->GetMotionMaster()->MovementExpired();
|
||||||
|
|
||||||
unitTarget->MonsterMove(pTargetDummy->GetPositionX(), pTargetDummy->GetPositionY(), pTargetDummy->GetPositionZ(), IN_MILLISECONDS);
|
unitTarget->MonsterMoveWithSpeed(pTargetDummy->GetPositionX(), pTargetDummy->GetPositionY(), pTargetDummy->GetPositionZ(), 24.f);
|
||||||
|
|
||||||
// Add state to temporarily prevent follow
|
// Add state to temporarily prevent follow
|
||||||
unitTarget->addUnitState(UNIT_STAT_ROOT);
|
unitTarget->addUnitState(UNIT_STAT_ROOT);
|
||||||
|
|
@ -2356,7 +2356,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx)
|
||||||
}
|
}
|
||||||
case 64385: // Spinning (from Unusual Compass)
|
case 64385: // Spinning (from Unusual Compass)
|
||||||
{
|
{
|
||||||
m_caster->SetFacingTo(frand(0, M_PI_F*2), true);
|
m_caster->SetFacingTo(frand(0, M_PI_F*2));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 64981: // Summon Random Vanquished Tentacle
|
case 64981: // Summon Random Vanquished Tentacle
|
||||||
|
|
@ -4921,11 +4921,8 @@ void Spell::EffectDistract(SpellEffectIndex /*eff_idx*/)
|
||||||
if (unitTarget->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
|
if (unitTarget->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
|
unitTarget->SetFacingTo(unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY));
|
||||||
|
|
||||||
unitTarget->clearUnitState(UNIT_STAT_MOVING);
|
unitTarget->clearUnitState(UNIT_STAT_MOVING);
|
||||||
unitTarget->SetOrientation(angle);
|
|
||||||
unitTarget->SendMonsterMove(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), SPLINETYPE_FACINGANGLE, SPLINEFLAG_WALKMODE, 0, NULL, angle);
|
|
||||||
|
|
||||||
if (unitTarget->GetTypeId() == TYPEID_UNIT)
|
if (unitTarget->GetTypeId() == TYPEID_UNIT)
|
||||||
unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
|
unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
|
||||||
|
|
@ -8428,7 +8425,7 @@ void Spell::EffectCharge(SpellEffectIndex /*eff_idx*/)
|
||||||
((Creature *)unitTarget)->StopMoving();
|
((Creature *)unitTarget)->StopMoving();
|
||||||
|
|
||||||
// Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
|
// Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
|
||||||
m_caster->MonsterMove(x, y, z, 1);
|
m_caster->MonsterMoveWithSpeed(x, y, z, 24.f);
|
||||||
|
|
||||||
// not all charge effects used in negative spells
|
// not all charge effects used in negative spells
|
||||||
if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
|
if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
|
||||||
|
|
@ -8453,7 +8450,7 @@ void Spell::EffectCharge2(SpellEffectIndex /*eff_idx*/)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
|
// Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
|
||||||
m_caster->MonsterMove(x, y, z, 1);
|
m_caster->MonsterMoveWithSpeed(x, y, z, 24.f);
|
||||||
|
|
||||||
// not all charge effects used in negative spells
|
// not all charge effects used in negative spells
|
||||||
if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
|
if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,9 @@
|
||||||
#include "TargetedMovementGenerator.h"
|
#include "TargetedMovementGenerator.h"
|
||||||
#include "Errors.h"
|
#include "Errors.h"
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
#define SMALL_ALPHA 0.05f
|
#define SMALL_ALPHA 0.05f
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
|
||||||
// prevent redundant micro-movement for pets, other followers.
|
// prevent redundant micro-movement for pets, other followers.
|
||||||
if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
|
if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
|
||||||
{
|
{
|
||||||
if (i_destinationHolder.HasDestination())
|
if (!owner.movespline->Finalized())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
owner.GetPosition(x, y, z);
|
owner.GetPosition(x, y, z);
|
||||||
|
|
@ -74,14 +75,15 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
|
||||||
if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
|
if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
|
||||||
return;
|
return;
|
||||||
*/
|
*/
|
||||||
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly())
|
|
||||||
((Creature&)owner).AddSplineFlag(SPLINEFLAG_FLYING);
|
|
||||||
|
|
||||||
|
|
||||||
|
D::_addUnitStateMove(owner);
|
||||||
i_targetReached = false;
|
i_targetReached = false;
|
||||||
i_recalculateTravel = false;
|
i_recalculateTravel = false;
|
||||||
D::_addUnitStateMove(owner);
|
|
||||||
Traveller<T> traveller(owner);
|
Movement::MoveSplineInit init(owner);
|
||||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
init.MoveTo(x,y,z);
|
||||||
|
init.Launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
@ -140,21 +142,19 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Traveller<T> traveller(owner);
|
i_recheckDistance.Update(time_diff);
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
|
if (i_recheckDistance.Passed())
|
||||||
{
|
{
|
||||||
if (!IsActive(owner)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
i_destinationHolder.ResetUpdate(50);
|
|
||||||
//More distance let have better performance, less distance let have more sensitive reaction at target move.
|
//More distance let have better performance, less distance let have more sensitive reaction at target move.
|
||||||
float dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius()
|
float allowed_dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius()
|
||||||
+ sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
|
+ sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
|
||||||
if (i_destinationHolder.GetDistance3dFromDestSq(*i_target.getTarget()) > dist * dist)
|
float dist = (owner.movespline->FinalDestination() -
|
||||||
|
G3D::Vector3(i_target->GetPositionX(),i_target->GetPositionY(),i_target->GetPositionZ())).squaredLength();
|
||||||
|
if (dist >= allowed_dist * allowed_dist)
|
||||||
_setTargetLocation(owner);
|
_setTargetLocation(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i_destinationHolder.HasArrived())
|
if (owner.movespline->Finalized())
|
||||||
{
|
{
|
||||||
if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget()))
|
if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget()))
|
||||||
owner.SetInFront(i_target.getTarget());
|
owner.SetInFront(i_target.getTarget());
|
||||||
|
|
@ -191,12 +191,8 @@ void ChaseMovementGenerator<Player>::Initialize(Player &owner)
|
||||||
template<>
|
template<>
|
||||||
void ChaseMovementGenerator<Creature>::Initialize(Creature &owner)
|
void ChaseMovementGenerator<Creature>::Initialize(Creature &owner)
|
||||||
{
|
{
|
||||||
|
owner.SetWalk(false);
|
||||||
owner.addUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
|
owner.addUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
|
||||||
owner.RemoveSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
if (((Creature*)&owner)->CanFly())
|
|
||||||
owner.AddSplineFlag(SPLINEFLAG_FLYING);
|
|
||||||
|
|
||||||
_setTargetLocation(owner);
|
_setTargetLocation(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,10 +260,6 @@ void FollowMovementGenerator<Creature>::Initialize(Creature &owner)
|
||||||
owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
|
owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
|
||||||
_updateWalkMode(owner);
|
_updateWalkMode(owner);
|
||||||
_updateSpeed(owner);
|
_updateSpeed(owner);
|
||||||
|
|
||||||
if (((Creature*)&owner)->CanFly())
|
|
||||||
owner.AddSplineFlag(SPLINEFLAG_FLYING);
|
|
||||||
|
|
||||||
_setTargetLocation(owner);
|
_setTargetLocation(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
#define MANGOS_TARGETEDMOVEMENTGENERATOR_H
|
#define MANGOS_TARGETEDMOVEMENTGENERATOR_H
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
#include "FollowerReference.h"
|
#include "FollowerReference.h"
|
||||||
|
|
||||||
class MANGOS_DLL_SPEC TargetedMovementGeneratorBase
|
class MANGOS_DLL_SPEC TargetedMovementGeneratorBase
|
||||||
|
|
@ -38,12 +36,11 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium
|
||||||
: public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
|
: public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
TargetedMovementGeneratorMedium(Unit &target, float offset = 0.f, float angle = 0.f) :
|
TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) :
|
||||||
TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle),
|
TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle),
|
||||||
i_recalculateTravel(false), i_targetReached(false)
|
i_recalculateTravel(false), i_targetReached(false), i_recheckDistance(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~TargetedMovementGeneratorMedium() {}
|
~TargetedMovementGeneratorMedium() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -51,22 +48,15 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium
|
||||||
|
|
||||||
Unit* GetTarget() const { return i_target.getTarget(); }
|
Unit* GetTarget() const { return i_target.getTarget(); }
|
||||||
|
|
||||||
bool GetDestination(float &x, float &y, float &z) const
|
|
||||||
{
|
|
||||||
if(!i_destinationHolder.HasDestination()) return false;
|
|
||||||
i_destinationHolder.GetDestination(x,y,z);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unitSpeedChanged() { i_recalculateTravel=true; }
|
void unitSpeedChanged() { i_recalculateTravel=true; }
|
||||||
void UpdateFinalDistance(float fDistance);
|
void UpdateFinalDistance(float fDistance);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _setTargetLocation(T &);
|
void _setTargetLocation(T &);
|
||||||
|
|
||||||
|
ShortTimeTracker i_recheckDistance;
|
||||||
float i_offset;
|
float i_offset;
|
||||||
float i_angle;
|
float i_angle;
|
||||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
|
||||||
bool i_recalculateTravel : 1;
|
bool i_recalculateTravel : 1;
|
||||||
bool i_targetReached : 1;
|
bool i_targetReached : 1;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
#include "UpdateMask.h"
|
#include "UpdateMask.h"
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
#include "WaypointMovementGenerator.h"
|
#include "WaypointMovementGenerator.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
|
|
||||||
void WorldSession::HandleTaxiNodeStatusQueryOpcode( WorldPacket & recv_data )
|
void WorldSession::HandleTaxiNodeStatusQueryOpcode( WorldPacket & recv_data )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,163 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MANGOS_TRAVELLER_H
|
|
||||||
#define MANGOS_TRAVELLER_H
|
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Creature.h"
|
|
||||||
#include "Player.h"
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
/** Traveller is a wrapper for units (creatures or players) that
|
|
||||||
* travel from point A to point B using the destination holder.
|
|
||||||
*/
|
|
||||||
#define PLAYER_FLIGHT_SPEED 32.0f
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct MANGOS_DLL_DECL Traveller
|
|
||||||
{
|
|
||||||
T &i_traveller;
|
|
||||||
Traveller(T &t) : i_traveller(t) {}
|
|
||||||
Traveller(const Traveller &obj) : i_traveller(obj) {}
|
|
||||||
Traveller& operator=(const Traveller &obj)
|
|
||||||
{
|
|
||||||
~Traveller();
|
|
||||||
new (this) Traveller(obj);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T&(void) { return i_traveller; }
|
|
||||||
operator const T&(void) { return i_traveller; }
|
|
||||||
float GetPositionX() const { return i_traveller.GetPositionX(); }
|
|
||||||
float GetPositionY() const { return i_traveller.GetPositionY(); }
|
|
||||||
float GetPositionZ() const { return i_traveller.GetPositionZ(); }
|
|
||||||
T& GetTraveller(void) { return i_traveller; }
|
|
||||||
|
|
||||||
float Speed(void) { MANGOS_ASSERT(false); return 0.0f; }
|
|
||||||
float GetMoveDestinationTo(float x, float y, float z);
|
|
||||||
uint32 GetTotalTravelTimeTo(float x, float y, float z);
|
|
||||||
|
|
||||||
void Relocation(float x, float y, float z, float orientation) {}
|
|
||||||
void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); }
|
|
||||||
void MoveTo(float x, float y, float z, uint32 t) {}
|
|
||||||
void Stop() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline uint32 Traveller<T>::GetTotalTravelTimeTo(float x, float y, float z)
|
|
||||||
{
|
|
||||||
float dist = GetMoveDestinationTo(x,y,z);
|
|
||||||
double speed = Speed();
|
|
||||||
|
|
||||||
speed *= 0.001f; // speed is in seconds so convert from second to millisecond
|
|
||||||
return static_cast<uint32>(dist/speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// specialization for creatures
|
|
||||||
template<>
|
|
||||||
inline float Traveller<Creature>::Speed()
|
|
||||||
{
|
|
||||||
if(i_traveller.HasSplineFlag(SPLINEFLAG_WALKMODE))
|
|
||||||
return i_traveller.GetSpeed(MOVE_WALK);
|
|
||||||
else if(i_traveller.HasSplineFlag(SPLINEFLAG_FLYING))
|
|
||||||
return i_traveller.GetSpeed(MOVE_FLIGHT);
|
|
||||||
else
|
|
||||||
return i_traveller.GetSpeed(MOVE_RUN);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Traveller<Creature>::Relocation(float x, float y, float z, float orientation)
|
|
||||||
{
|
|
||||||
i_traveller.GetMap()->CreatureRelocation(&i_traveller, x, y, z, orientation);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline float Traveller<Creature>::GetMoveDestinationTo(float x, float y, float z)
|
|
||||||
{
|
|
||||||
float dx = x - GetPositionX();
|
|
||||||
float dy = y - GetPositionY();
|
|
||||||
|
|
||||||
if (i_traveller.CanFly())
|
|
||||||
{
|
|
||||||
float dz = z - GetPositionZ();
|
|
||||||
return sqrt((dx*dx) + (dy*dy) + (dz*dz));
|
|
||||||
}
|
|
||||||
else //Walking on the ground
|
|
||||||
return sqrt((dx*dx) + (dy*dy));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Traveller<Creature>::MoveTo(float x, float y, float z, uint32 t)
|
|
||||||
{
|
|
||||||
i_traveller.SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, i_traveller.GetSplineFlags(), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Traveller<Creature>::Stop()
|
|
||||||
{
|
|
||||||
i_traveller.SendMonsterMove(i_traveller.GetPositionX(), i_traveller.GetPositionY(), i_traveller.GetPositionZ(), SPLINETYPE_STOP, i_traveller.GetSplineFlags(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// specialization for players
|
|
||||||
template<>
|
|
||||||
inline float Traveller<Player>::Speed()
|
|
||||||
{
|
|
||||||
if (i_traveller.IsTaxiFlying())
|
|
||||||
return PLAYER_FLIGHT_SPEED;
|
|
||||||
else
|
|
||||||
return i_traveller.GetSpeed(i_traveller.m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline float Traveller<Player>::GetMoveDestinationTo(float x, float y, float z)
|
|
||||||
{
|
|
||||||
float dx = x - GetPositionX();
|
|
||||||
float dy = y - GetPositionY();
|
|
||||||
float dz = z - GetPositionZ();
|
|
||||||
|
|
||||||
if (i_traveller.IsTaxiFlying())
|
|
||||||
return sqrt((dx*dx) + (dy*dy) + (dz*dz));
|
|
||||||
else //Walking on the ground
|
|
||||||
return sqrt((dx*dx) + (dy*dy));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Traveller<Player>::Relocation(float x, float y, float z, float orientation)
|
|
||||||
{
|
|
||||||
i_traveller.SetPosition(x, y, z, orientation);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Traveller<Player>::MoveTo(float x, float y, float z, uint32 t)
|
|
||||||
{
|
|
||||||
//Only send SPLINEFLAG_WALKMODE, client has strange issues with other move flags
|
|
||||||
i_traveller.SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Traveller<Player>::Stop()
|
|
||||||
{
|
|
||||||
//Only send SPLINEFLAG_WALKMODE, client has strange issues with other move flags
|
|
||||||
i_traveller.SendMonsterMove(i_traveller.GetPositionX(), i_traveller.GetPositionY(), i_traveller.GetPositionZ(), SPLINETYPE_STOP, SPLINEFLAG_WALKMODE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef Traveller<Creature> CreatureTraveller;
|
|
||||||
typedef Traveller<Player> PlayerTraveller;
|
|
||||||
#endif
|
|
||||||
|
|
@ -45,10 +45,10 @@
|
||||||
#include "MapPersistentStateMgr.h"
|
#include "MapPersistentStateMgr.h"
|
||||||
#include "GridNotifiersImpl.h"
|
#include "GridNotifiersImpl.h"
|
||||||
#include "CellImpl.h"
|
#include "CellImpl.h"
|
||||||
#include "Path.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
#include "VMapFactory.h"
|
#include "VMapFactory.h"
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
@ -184,7 +184,8 @@ void GlobalCooldownMgr::CancelGlobalCooldown(SpellEntry const* spellInfo)
|
||||||
Unit::Unit() :
|
Unit::Unit() :
|
||||||
i_motionMaster(this), m_ThreatManager(this), m_HostileRefManager(this),
|
i_motionMaster(this), m_ThreatManager(this), m_HostileRefManager(this),
|
||||||
m_charmInfo(NULL),
|
m_charmInfo(NULL),
|
||||||
m_vehicleInfo(NULL)
|
m_vehicleInfo(NULL),
|
||||||
|
movespline(new Movement::MoveSpline())
|
||||||
{
|
{
|
||||||
m_objectType |= TYPEMASK_UNIT;
|
m_objectType |= TYPEMASK_UNIT;
|
||||||
m_objectTypeId = TYPEID_UNIT;
|
m_objectTypeId = TYPEID_UNIT;
|
||||||
|
|
@ -279,6 +280,7 @@ Unit::~Unit()
|
||||||
|
|
||||||
delete m_charmInfo;
|
delete m_charmInfo;
|
||||||
delete m_vehicleInfo;
|
delete m_vehicleInfo;
|
||||||
|
delete movespline;
|
||||||
|
|
||||||
// those should be already removed at "RemoveFromWorld()" call
|
// those should be already removed at "RemoveFromWorld()" call
|
||||||
MANGOS_ASSERT(m_gameObj.size() == 0);
|
MANGOS_ASSERT(m_gameObj.size() == 0);
|
||||||
|
|
@ -345,7 +347,7 @@ void Unit::Update( uint32 update_diff, uint32 p_time )
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f);
|
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f);
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f);
|
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f);
|
||||||
ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f);
|
ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f);
|
||||||
|
UpdateSplineMovement(p_time);
|
||||||
i_motionMaster.UpdateMotion(p_time);
|
i_motionMaster.UpdateMotion(p_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,83 +362,13 @@ bool Unit::haveOffhandWeapon() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, SplineType type, SplineFlags flags, uint32 Time, Player* player, ...)
|
void Unit::SendHeartBeat()
|
||||||
{
|
|
||||||
va_list vargs;
|
|
||||||
va_start(vargs,player);
|
|
||||||
|
|
||||||
float moveTime = (float)Time;
|
|
||||||
|
|
||||||
WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) );
|
|
||||||
data << GetPackGUID();
|
|
||||||
data << uint8(0); // new in 3.1 bool, used to toggle MOVEFLAG2_UNK4 = 0x0040 on client side
|
|
||||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
|
||||||
data << uint32(WorldTimer::getMSTime());
|
|
||||||
|
|
||||||
data << uint8(type); // unknown
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case SPLINETYPE_NORMAL: // normal packet
|
|
||||||
break;
|
|
||||||
case SPLINETYPE_STOP: // stop packet (raw pos?)
|
|
||||||
va_end(vargs);
|
|
||||||
SendMessageToSet( &data, true );
|
|
||||||
return;
|
|
||||||
case SPLINETYPE_FACINGSPOT: // facing spot, not used currently
|
|
||||||
{
|
|
||||||
data << float(va_arg(vargs,double));
|
|
||||||
data << float(va_arg(vargs,double));
|
|
||||||
data << float(va_arg(vargs,double));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SPLINETYPE_FACINGTARGET:
|
|
||||||
data << uint64(va_arg(vargs,uint64)); // ObjectGuid in fact
|
|
||||||
break;
|
|
||||||
case SPLINETYPE_FACINGANGLE:
|
|
||||||
data << float(va_arg(vargs,double)); // facing angle
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
data << uint32(flags); // splineflags
|
|
||||||
data << uint32(moveTime); // Time in between points
|
|
||||||
data << uint32(1); // 1 single waypoint
|
|
||||||
data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
|
|
||||||
|
|
||||||
va_end(vargs);
|
|
||||||
|
|
||||||
if(player)
|
|
||||||
player->GetSession()->SendPacket(&data);
|
|
||||||
else
|
|
||||||
SendMessageToSet( &data, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime, Player* player)
|
|
||||||
{
|
|
||||||
if (!transitTime)
|
|
||||||
{
|
|
||||||
if(GetTypeId()==TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
Traveller<Player> traveller(*(Player*)this);
|
|
||||||
transitTime = traveller.GetTotalTravelTimeTo(x, y, z);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Traveller<Creature> traveller(*(Creature*)this);
|
|
||||||
transitTime = traveller.GetTotalTravelTimeTo(x, y, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//float orientation = (float)atan2((double)dy, (double)dx);
|
|
||||||
SplineFlags flags = GetTypeId() == TYPEID_PLAYER ? SPLINEFLAG_WALKMODE : ((Creature*)this)->GetSplineFlags();
|
|
||||||
SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, flags, transitTime, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unit::SendHeartBeat(bool toSelf)
|
|
||||||
{
|
{
|
||||||
m_movementInfo.UpdateTime(WorldTimer::getMSTime());
|
m_movementInfo.UpdateTime(WorldTimer::getMSTime());
|
||||||
WorldPacket data(MSG_MOVE_HEARTBEAT, 64);
|
WorldPacket data(MSG_MOVE_HEARTBEAT, 64);
|
||||||
data << GetPackGUID();
|
data << GetPackGUID();
|
||||||
data << m_movementInfo;
|
data << m_movementInfo;
|
||||||
SendMessageToSet(&data, toSelf);
|
SendMessageToSet(&data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::resetAttackTimer(WeaponAttackType type)
|
void Unit::resetAttackTimer(WeaponAttackType type)
|
||||||
|
|
@ -3740,29 +3672,21 @@ void Unit::SetInFront(Unit const* target)
|
||||||
SetOrientation(GetAngle(target));
|
SetOrientation(GetAngle(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::SetFacingTo(float ori, bool bToSelf /*= false*/)
|
void Unit::SetFacingTo(float ori)
|
||||||
{
|
{
|
||||||
// update orientation at server
|
Movement::MoveSplineInit init(*this);
|
||||||
SetOrientation(ori);
|
init.SetFacing(ori);
|
||||||
|
init.Launch();
|
||||||
// and client
|
|
||||||
SendHeartBeat(bToSelf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider move this to Creature:: since only creature appear to be able to use this
|
|
||||||
void Unit::SetFacingToObject(WorldObject* pObject)
|
void Unit::SetFacingToObject(WorldObject* pObject)
|
||||||
{
|
{
|
||||||
if (GetTypeId() != TYPEID_UNIT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// never face when already moving
|
// never face when already moving
|
||||||
if (!IsStopped())
|
if (!IsStopped())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: figure out under what conditions creature will move towards object instead of facing it where it currently is.
|
// TODO: figure out under what conditions creature will move towards object instead of facing it where it currently is.
|
||||||
|
SetFacingTo(GetAngle(pObject));
|
||||||
SetOrientation(GetAngle(pObject));
|
|
||||||
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_FACINGTARGET, ((Creature*)this)->GetSplineFlags(), 0, NULL, pObject->GetObjectGuid().GetRawValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Unit::isInAccessablePlaceFor(Creature const* c) const
|
bool Unit::isInAccessablePlaceFor(Creature const* c) const
|
||||||
|
|
@ -8211,19 +8135,17 @@ void Unit::UpdateWalkMode(Unit* source, bool self)
|
||||||
CallForAllControlledUnits(UpdateWalkModeHelper(source), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_CHARM|CONTROLLED_MINIPET);
|
CallForAllControlledUnits(UpdateWalkModeHelper(source), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_CHARM|CONTROLLED_MINIPET);
|
||||||
else if (self)
|
else if (self)
|
||||||
{
|
{
|
||||||
bool on = source->GetTypeId() == TYPEID_PLAYER
|
bool on = source->m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);
|
||||||
? ((Player*)source)->HasMovementFlag(MOVEFLAG_WALK_MODE)
|
|
||||||
: ((Creature*)source)->HasSplineFlag(SPLINEFLAG_WALKMODE);
|
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
{
|
{
|
||||||
if (((Creature*)this)->IsPet() && hasUnitState(UNIT_STAT_FOLLOW))
|
if (((Creature*)this)->IsPet() && hasUnitState(UNIT_STAT_FOLLOW))
|
||||||
((Creature*)this)->AddSplineFlag(SPLINEFLAG_WALKMODE);
|
((Creature*)this)->SetWalk(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (((Creature*)this)->IsPet())
|
if (((Creature*)this)->IsPet())
|
||||||
((Creature*)this)->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
|
((Creature*)this)->SetWalk(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -8469,20 +8391,7 @@ void Unit::SetDeathState(DeathState s)
|
||||||
RemoveMiniPet();
|
RemoveMiniPet();
|
||||||
UnsummonAllTotems();
|
UnsummonAllTotems();
|
||||||
|
|
||||||
// after removing a Fearaura (in RemoveAllAurasOnDeath)
|
StopMoving();
|
||||||
// Unit::SetFeared is called and makes that creatures attack player again
|
|
||||||
if (GetTypeId() == TYPEID_UNIT)
|
|
||||||
{
|
|
||||||
clearUnitState(UNIT_STAT_MOVING);
|
|
||||||
|
|
||||||
GetMap()->CreatureRelocation((Creature*)this, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
|
||||||
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!IsStopped())
|
|
||||||
StopMoving();
|
|
||||||
}
|
|
||||||
|
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
|
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
|
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
|
||||||
|
|
@ -9981,12 +9890,9 @@ void Unit::StopMoving()
|
||||||
if (!IsInWorld())
|
if (!IsInWorld())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// send explicit stop packet
|
Movement::MoveSplineInit init(*this);
|
||||||
// player expected for correct work SPLINEFLAG_WALKMODE
|
init.SetFacing(GetOrientation());
|
||||||
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_STOP, GetTypeId() == TYPEID_PLAYER ? SPLINEFLAG_WALKMODE : SPLINEFLAG_NONE, 0);
|
init.Launch();
|
||||||
|
|
||||||
// update position and orientation for near players
|
|
||||||
SendHeartBeat(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::SetFeared(bool apply, ObjectGuid casterGuid, uint32 spellID, uint32 time)
|
void Unit::SetFeared(bool apply, ObjectGuid casterGuid, uint32 spellID, uint32 time)
|
||||||
|
|
@ -10529,7 +10435,7 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca
|
||||||
|
|
||||||
GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
|
GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
|
||||||
|
|
||||||
SendHeartBeat(false);
|
SendHeartBeat();
|
||||||
|
|
||||||
// finished relocation, movegen can different from top before creature relocation,
|
// finished relocation, movegen can different from top before creature relocation,
|
||||||
// but apply Reset expected to be safe in any case
|
// but apply Reset expected to be safe in any case
|
||||||
|
|
@ -10539,49 +10445,12 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::MonsterMove(float x, float y, float z, uint32 transitTime)
|
void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed)
|
||||||
{
|
{
|
||||||
SplineFlags flags = GetTypeId() == TYPEID_PLAYER ? SPLINEFLAG_WALKMODE : ((Creature*)this)->GetSplineFlags();
|
Movement::MoveSplineInit init(*this);
|
||||||
SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, flags, transitTime);
|
init.MoveTo(x,y,z);
|
||||||
|
init.SetVelocity(speed);
|
||||||
if (GetTypeId() != TYPEID_PLAYER)
|
init.Launch();
|
||||||
{
|
|
||||||
Creature* c = (Creature*)this;
|
|
||||||
// Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly
|
|
||||||
if (!c->GetMotionMaster()->empty())
|
|
||||||
if (MovementGenerator *movgen = c->GetMotionMaster()->top())
|
|
||||||
movgen->Interrupt(*c);
|
|
||||||
|
|
||||||
GetMap()->CreatureRelocation((Creature*)this, x, y, z, 0.0f);
|
|
||||||
|
|
||||||
// finished relocation, movegen can different from top before creature relocation,
|
|
||||||
// but apply Reset expected to be safe in any case
|
|
||||||
if (!c->GetMotionMaster()->empty())
|
|
||||||
if (MovementGenerator *movgen = c->GetMotionMaster()->top())
|
|
||||||
movgen->Reset(*c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unit::MonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime)
|
|
||||||
{
|
|
||||||
SendMonsterMoveWithSpeed(x, y, z, transitTime );
|
|
||||||
|
|
||||||
if (GetTypeId() != TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
Creature* c = (Creature*)this;
|
|
||||||
// Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly
|
|
||||||
if (!c->GetMotionMaster()->empty())
|
|
||||||
if (MovementGenerator *movgen = c->GetMotionMaster()->top())
|
|
||||||
movgen->Interrupt(*c);
|
|
||||||
|
|
||||||
GetMap()->CreatureRelocation((Creature*)this, x, y, z, 0.0f);
|
|
||||||
|
|
||||||
// finished relocation, movegen can different from top before creature relocation,
|
|
||||||
// but apply Reset expected to be safe in any case
|
|
||||||
if (!c->GetMotionMaster()->empty())
|
|
||||||
if (MovementGenerator *movgen = c->GetMotionMaster()->top())
|
|
||||||
movgen->Reset(*c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SetPvPHelper
|
struct SetPvPHelper
|
||||||
|
|
@ -10955,3 +10824,31 @@ void Unit::SetVehicleId(uint32 entry)
|
||||||
SendMessageToSet(&data, true);
|
SendMessageToSet(&data, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::UpdateSplineMovement(uint32 t_diff)
|
||||||
|
{
|
||||||
|
enum{
|
||||||
|
POSITION_UPDATE_DELAY = 400,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (movespline->Finalized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
movespline->updateState(t_diff);
|
||||||
|
bool arrived = movespline->Finalized();
|
||||||
|
|
||||||
|
if (arrived)
|
||||||
|
m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEFLAG_SPLINE_ENABLED|MOVEFLAG_FORWARD));
|
||||||
|
|
||||||
|
m_movesplineTimer.Update(t_diff);
|
||||||
|
if (m_movesplineTimer.Passed() || arrived)
|
||||||
|
{
|
||||||
|
m_movesplineTimer.Reset(POSITION_UPDATE_DELAY);
|
||||||
|
Movement::Location loc = movespline->ComputePosition();
|
||||||
|
|
||||||
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
|
((Player*)this)->SetPosition(loc.x,loc.y,loc.z,loc.orientation);
|
||||||
|
else
|
||||||
|
GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -803,6 +803,10 @@ inline ByteBuffer& operator>> (ByteBuffer& buf, MovementInfo& mi)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Movement{
|
||||||
|
class MoveSpline;
|
||||||
|
}
|
||||||
|
|
||||||
enum DiminishingLevels
|
enum DiminishingLevels
|
||||||
{
|
{
|
||||||
DIMINISHING_LEVEL_1 = 0,
|
DIMINISHING_LEVEL_1 = 0,
|
||||||
|
|
@ -1459,25 +1463,20 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
|
void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
|
||||||
|
|
||||||
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false);
|
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false);
|
||||||
|
void MonsterMoveWithSpeed(float x, float y, float z, float speed);
|
||||||
void MonsterMove(float x, float y, float z, uint32 transitTime);
|
|
||||||
void MonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0);
|
|
||||||
|
|
||||||
// recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens
|
// recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens
|
||||||
// if used additional args in ... part then floats must explicitly casted to double
|
// if used additional args in ... part then floats must explicitly casted to double
|
||||||
void SendMonsterMove(float x, float y, float z, SplineType type, SplineFlags flags, uint32 Time, Player* player = NULL, ...);
|
void SendHeartBeat();
|
||||||
void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
|
|
||||||
|
|
||||||
template<typename PathElem, typename PathNode>
|
void SetInFront(Unit const* target);
|
||||||
void SendMonsterMoveByPath(Path<PathElem,PathNode> const& path, uint32 start, uint32 end, SplineFlags flags);
|
void SetFacingTo(float ori);
|
||||||
|
void SetFacingToObject(WorldObject* pObject);
|
||||||
|
|
||||||
void SendHighestThreatUpdate(HostileReference* pHostileReference);
|
void SendHighestThreatUpdate(HostileReference* pHostileReference);
|
||||||
void SendThreatClear();
|
void SendThreatClear();
|
||||||
void SendThreatRemove(HostileReference* pHostileReference);
|
void SendThreatRemove(HostileReference* pHostileReference);
|
||||||
void SendThreatUpdate();
|
void SendThreatUpdate();
|
||||||
|
|
||||||
void SendHeartBeat(bool toSelf);
|
|
||||||
|
|
||||||
virtual void MoveOutOfRange(Player &) { };
|
virtual void MoveOutOfRange(Player &) { };
|
||||||
|
|
||||||
bool isAlive() const { return (m_deathState == ALIVE); };
|
bool isAlive() const { return (m_deathState == ALIVE); };
|
||||||
|
|
@ -1699,10 +1698,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const;
|
float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const;
|
||||||
void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
|
void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
|
||||||
|
|
||||||
void SetInFront(Unit const* target);
|
|
||||||
void SetFacingTo(float ori, bool bToSelf = false);
|
|
||||||
void SetFacingToObject(WorldObject* pObject);
|
|
||||||
|
|
||||||
// Visibility system
|
// Visibility system
|
||||||
UnitVisibility GetVisibility() const { return m_Visibility; }
|
UnitVisibility GetVisibility() const { return m_Visibility; }
|
||||||
void SetVisibility(UnitVisibility x);
|
void SetVisibility(UnitVisibility x);
|
||||||
|
|
@ -1954,6 +1949,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
|
|
||||||
// Movement info
|
// Movement info
|
||||||
MovementInfo m_movementInfo;
|
MovementInfo m_movementInfo;
|
||||||
|
Movement::MoveSpline * movespline;
|
||||||
|
|
||||||
void ScheduleAINotify(uint32 delay);
|
void ScheduleAINotify(uint32 delay);
|
||||||
bool IsAINotifyScheduled() const { return m_AINotifyScheduled;}
|
bool IsAINotifyScheduled() const { return m_AINotifyScheduled;}
|
||||||
|
|
@ -2012,6 +2008,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
VehicleInfo* m_vehicleInfo;
|
VehicleInfo* m_vehicleInfo;
|
||||||
private:
|
private:
|
||||||
void CleanupDeletedAuras();
|
void CleanupDeletedAuras();
|
||||||
|
void UpdateSplineMovement(uint32 t_diff);
|
||||||
|
|
||||||
// player or player's pet
|
// player or player's pet
|
||||||
float GetCombatRatingReduction(CombatRating cr) const;
|
float GetCombatRatingReduction(CombatRating cr) const;
|
||||||
|
|
@ -2029,6 +2026,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
UnitVisibility m_Visibility;
|
UnitVisibility m_Visibility;
|
||||||
Position m_last_notified_position;
|
Position m_last_notified_position;
|
||||||
bool m_AINotifyScheduled;
|
bool m_AINotifyScheduled;
|
||||||
|
ShortTimeTracker m_movesplineTimer;
|
||||||
|
|
||||||
Diminishing m_Diminishing;
|
Diminishing m_Diminishing;
|
||||||
// Manage all Units threatening us
|
// Manage all Units threatening us
|
||||||
|
|
@ -2130,33 +2128,4 @@ bool Unit::CheckAllControlledUnits(Func const& func, uint32 controlledMask) cons
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Elem, typename Node>
|
|
||||||
inline void Unit::SendMonsterMoveByPath(Path<Elem,Node> const& path, uint32 start, uint32 end, SplineFlags flags)
|
|
||||||
{
|
|
||||||
uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32);
|
|
||||||
|
|
||||||
uint32 pathSize = end - start;
|
|
||||||
|
|
||||||
WorldPacket data( SMSG_MONSTER_MOVE, (GetPackGUID().size()+1+4+4+4+4+1+4+4+4+pathSize*4*3) );
|
|
||||||
data << GetPackGUID();
|
|
||||||
data << uint8(0);
|
|
||||||
data << GetPositionX();
|
|
||||||
data << GetPositionY();
|
|
||||||
data << GetPositionZ();
|
|
||||||
data << uint32(WorldTimer::getMSTime());
|
|
||||||
data << uint8(SPLINETYPE_NORMAL);
|
|
||||||
data << uint32(flags);
|
|
||||||
data << uint32(traveltime);
|
|
||||||
data << uint32(pathSize);
|
|
||||||
|
|
||||||
for(uint32 i = start; i < end; ++i)
|
|
||||||
{
|
|
||||||
data << float(path[i].x);
|
|
||||||
data << float(path[i].y);
|
|
||||||
data << float(path[i].z);
|
|
||||||
}
|
|
||||||
|
|
||||||
SendMessageToSet(&data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,12 @@ alter table creature_movement add `wpguid` int(11) default '0';
|
||||||
#include "WaypointMovementGenerator.h"
|
#include "WaypointMovementGenerator.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "CreatureAI.h"
|
#include "CreatureAI.h"
|
||||||
#include "WaypointManager.h"
|
#include "WaypointManager.h"
|
||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
#include "movement/MoveSpline.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
@ -87,11 +88,13 @@ void WaypointMovementGenerator<Creature>::Initialize(Creature &creature)
|
||||||
void WaypointMovementGenerator<Creature>::Finalize(Creature &creature)
|
void WaypointMovementGenerator<Creature>::Finalize(Creature &creature)
|
||||||
{
|
{
|
||||||
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
|
creature.SetWalk(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointMovementGenerator<Creature>::Interrupt(Creature &creature)
|
void WaypointMovementGenerator<Creature>::Interrupt(Creature &creature)
|
||||||
{
|
{
|
||||||
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
|
||||||
|
creature.SetWalk(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointMovementGenerator<Creature>::Reset(Creature &creature)
|
void WaypointMovementGenerator<Creature>::Reset(Creature &creature)
|
||||||
|
|
@ -111,11 +114,6 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
|
||||||
creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
|
creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||||
m_isArrivalDone = true;
|
m_isArrivalDone = true;
|
||||||
|
|
||||||
if (i_path->at(i_currentNode).orientation != 100)
|
|
||||||
{
|
|
||||||
creature.SetFacingTo(i_path->at(i_currentNode).orientation);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i_path->at(i_currentNode).script_id)
|
if (i_path->at(i_currentNode).script_id)
|
||||||
{
|
{
|
||||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetGuidStr().c_str());
|
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetGuidStr().c_str());
|
||||||
|
|
@ -179,13 +177,16 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature &creature)
|
||||||
|
|
||||||
m_isArrivalDone = false;
|
m_isArrivalDone = false;
|
||||||
|
|
||||||
if (creature.CanFly())
|
|
||||||
creature.AddSplineFlag(SPLINEFLAG_FLYING);
|
|
||||||
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||||
|
|
||||||
const WaypointNode &node = i_path->at(i_currentNode);
|
const WaypointNode &node = i_path->at(i_currentNode);
|
||||||
CreatureTraveller traveller(creature);
|
Movement::MoveSplineInit init(creature);
|
||||||
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
init.MoveTo(node.x, node.y, node.z);
|
||||||
|
|
||||||
|
if (node.orientation != 100 && node.delay != 0)
|
||||||
|
init.SetFacing(node.orientation);
|
||||||
|
init.SetWalk(!creature.IsLevitating());
|
||||||
|
init.Launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
|
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
|
||||||
|
|
@ -212,14 +213,9 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CreatureTraveller traveller(creature);
|
|
||||||
if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true) && !IsActive(creature))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (creature.IsStopped())
|
if (creature.IsStopped())
|
||||||
Stop(STOP_TIME_FOR_PLAYER);
|
Stop(STOP_TIME_FOR_PLAYER);
|
||||||
|
else if (creature.movespline->Finalized())
|
||||||
if (i_destinationHolder.HasArrived())
|
|
||||||
{
|
{
|
||||||
OnArrived(creature);
|
OnArrived(creature);
|
||||||
StartMove(creature);
|
StartMove(creature);
|
||||||
|
|
@ -236,7 +232,13 @@ void WaypointMovementGenerator<Creature>::MovementInform(Creature &creature)
|
||||||
|
|
||||||
bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z)
|
bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z)
|
||||||
{
|
{
|
||||||
return PathMovementBase<Creature, WaypointPath const*>::GetPosition(x,y,z);
|
// prevent a crash at empty waypoint path.
|
||||||
|
if (!i_path || i_path->empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const WaypointNode& node = i_path->at(i_currentNode);
|
||||||
|
x = node.x; y = node.y; z = node.z;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------//
|
//----------------------------------------------------//
|
||||||
|
|
@ -266,10 +268,6 @@ void FlightPathMovementGenerator::Finalize(Player & player)
|
||||||
// remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack)
|
// remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack)
|
||||||
player.clearUnitState(UNIT_STAT_TAXI_FLIGHT);
|
player.clearUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||||
|
|
||||||
float x, y, z;
|
|
||||||
i_destinationHolder.GetLocationNow(player.GetMap(), x, y, z);
|
|
||||||
player.SetPosition(x, y, z, player.GetOrientation());
|
|
||||||
|
|
||||||
player.Unmount();
|
player.Unmount();
|
||||||
player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||||
|
|
||||||
|
|
@ -291,57 +289,39 @@ void FlightPathMovementGenerator::Interrupt(Player & player)
|
||||||
player.clearUnitState(UNIT_STAT_TAXI_FLIGHT);
|
player.clearUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PLAYER_FLIGHT_SPEED 32.0f
|
||||||
|
|
||||||
void FlightPathMovementGenerator::Reset(Player & player)
|
void FlightPathMovementGenerator::Reset(Player & player)
|
||||||
{
|
{
|
||||||
player.getHostileRefManager().setOnlineOfflineState(false);
|
player.getHostileRefManager().setOnlineOfflineState(false);
|
||||||
player.addUnitState(UNIT_STAT_TAXI_FLIGHT);
|
player.addUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||||
player.SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
player.SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||||
Traveller<Player> traveller(player);
|
|
||||||
// do not send movement, it was sent already
|
|
||||||
i_destinationHolder.SetDestination(traveller, (*i_path)[i_currentNode].x, (*i_path)[i_currentNode].y, (*i_path)[i_currentNode].z, false);
|
|
||||||
|
|
||||||
player.SendMonsterMoveByPath(GetPath(),GetCurrentNode(),GetPathAtMapEnd(), SplineFlags(SPLINEFLAG_WALKMODE|SPLINEFLAG_FLYING));
|
Movement::MoveSplineInit init(player);
|
||||||
|
uint32 end = GetPathAtMapEnd();
|
||||||
|
for (uint32 i = GetCurrentNode(); i != end; ++i)
|
||||||
|
{
|
||||||
|
G3D::Vector3 vertice((*i_path)[i].x,(*i_path)[i].y,(*i_path)[i].z);
|
||||||
|
init.Path().push_back(vertice);
|
||||||
|
}
|
||||||
|
init.SetFirstPointId(GetCurrentNode());
|
||||||
|
init.SetFly();
|
||||||
|
init.SetVelocity(PLAYER_FLIGHT_SPEED);
|
||||||
|
init.Launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlightPathMovementGenerator::Update(Player &player, const uint32 &diff)
|
bool FlightPathMovementGenerator::Update(Player &player, const uint32 &diff)
|
||||||
{
|
{
|
||||||
if (MovementInProgress())
|
int32 pointId = player.movespline->currentPathIdx();
|
||||||
|
// currentPathIdx returns lastIdx + 1 at arrive
|
||||||
|
while (i_currentNode < pointId)
|
||||||
{
|
{
|
||||||
Traveller<Player> traveller(player);
|
DoEventIfAny(player,(*i_path)[i_currentNode],true);
|
||||||
if( i_destinationHolder.UpdateTraveller(traveller, diff, false) )
|
DoEventIfAny(player,(*i_path)[i_currentNode],false);
|
||||||
{
|
++i_currentNode;
|
||||||
if (!IsActive(player)) // force stop processing (movement can move out active zone with cleanup movegens list)
|
|
||||||
return true; // not expire now, but already lost
|
|
||||||
|
|
||||||
i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE);
|
|
||||||
if (i_destinationHolder.HasArrived())
|
|
||||||
{
|
|
||||||
DoEventIfAny(player,(*i_path)[i_currentNode],false);
|
|
||||||
|
|
||||||
uint32 curMap = (*i_path)[i_currentNode].mapid;
|
|
||||||
++i_currentNode;
|
|
||||||
if (MovementInProgress())
|
|
||||||
{
|
|
||||||
DoEventIfAny(player,(*i_path)[i_currentNode],true);
|
|
||||||
|
|
||||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "loading node %u for player %s", i_currentNode, player.GetName());
|
|
||||||
if ((*i_path)[i_currentNode].mapid == curMap)
|
|
||||||
{
|
|
||||||
// do not send movement, it was sent already
|
|
||||||
i_destinationHolder.SetDestination(traveller, (*i_path)[i_currentNode].x, (*i_path)[i_currentNode].y, (*i_path)[i_currentNode].z, false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have arrived at the end of the path
|
return MovementInProgress();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
||||||
|
|
@ -372,6 +352,13 @@ void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z)
|
||||||
|
{
|
||||||
|
const TaxiPathNodeEntry& node = (*i_path)[i_currentNode];
|
||||||
|
x = node.x; y = node.y; z = node.z;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Unique1's ASTAR Pathfinding Code... For future use & reference...
|
// Unique1's ASTAR Pathfinding Code... For future use & reference...
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "DestinationHolder.h"
|
|
||||||
#include "WaypointManager.h"
|
#include "WaypointManager.h"
|
||||||
#include "Path.h"
|
|
||||||
#include "Traveller.h"
|
|
||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
@ -46,18 +43,15 @@ class MANGOS_DLL_SPEC PathMovementBase
|
||||||
PathMovementBase() : i_currentNode(0) {}
|
PathMovementBase() : i_currentNode(0) {}
|
||||||
virtual ~PathMovementBase() {};
|
virtual ~PathMovementBase() {};
|
||||||
|
|
||||||
bool MovementInProgress(void) const { return i_currentNode < i_path->size(); }
|
bool MovementInProgress(void) const { return (i_currentNode+1) < i_path->size(); }
|
||||||
|
|
||||||
// template pattern, not defined .. override required
|
// template pattern, not defined .. override required
|
||||||
void LoadPath(T &);
|
void LoadPath(T &);
|
||||||
uint32 GetCurrentNode() const { return i_currentNode; }
|
uint32 GetCurrentNode() const { return i_currentNode; }
|
||||||
|
|
||||||
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
|
||||||
bool GetPosition(float& x, float& y, float& z) const { i_destinationHolder.GetLocationNowNoMicroMovement(x,y,z); return true; }
|
|
||||||
protected:
|
protected:
|
||||||
uint32 i_currentNode;
|
|
||||||
DestinationHolder< Traveller<T> > i_destinationHolder;
|
|
||||||
P i_path;
|
P i_path;
|
||||||
|
uint32 i_currentNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** WaypointMovementGenerator loads a series of way points
|
/** WaypointMovementGenerator loads a series of way points
|
||||||
|
|
@ -89,9 +83,6 @@ public PathMovementBase<Creature, WaypointPath const*>
|
||||||
// now path movement implmementation
|
// now path movement implmementation
|
||||||
void LoadPath(Creature &c);
|
void LoadPath(Creature &c);
|
||||||
|
|
||||||
// allow use for overwrite empty implementation
|
|
||||||
bool GetDestination(float& x, float& y, float& z) const { return PathMovementBase<Creature, WaypointPath const*>::GetDestination(x,y,z); }
|
|
||||||
|
|
||||||
bool GetResetPosition(Creature&, float& x, float& y, float& z);
|
bool GetResetPosition(Creature&, float& x, float& y, float& z);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -145,8 +136,6 @@ public PathMovementBase<Player,TaxiPathNodeList const*>
|
||||||
void SetCurrentNodeAfterTeleport();
|
void SetCurrentNodeAfterTeleport();
|
||||||
void SkipCurrentNode() { ++i_currentNode; }
|
void SkipCurrentNode() { ++i_currentNode; }
|
||||||
void DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure);
|
void DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure);
|
||||||
|
bool GetResetPosition(Player&, float& x, float& y, float& z);
|
||||||
// allow use for overwrite empty implementation
|
|
||||||
bool GetDestination(float& x, float& y, float& z) const { return PathMovementBase<Player,TaxiPathNodeList const*>::GetDestination(x,y,z); }
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
311
src/game/movement/MoveSpline.cpp
Normal file
311
src/game/movement/MoveSpline.cpp
Normal file
|
|
@ -0,0 +1,311 @@
|
||||||
|
/*
|
||||||
|
* 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 "MoveSpline.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
namespace Movement{
|
||||||
|
|
||||||
|
extern float computeFallTime(float path_length, bool isSafeFall);
|
||||||
|
extern float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy);
|
||||||
|
extern float computeFallElevation(float time_passed);
|
||||||
|
|
||||||
|
Location MoveSpline::ComputePosition() const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(Initialized());
|
||||||
|
|
||||||
|
float u = 1.f;
|
||||||
|
int32 seg_time = spline.length(point_Idx,point_Idx+1);
|
||||||
|
if (seg_time > 0)
|
||||||
|
u = (time_passed - spline.length(point_Idx)) / (float)seg_time;
|
||||||
|
Location c;
|
||||||
|
spline.evaluate_percent(point_Idx, u, c);
|
||||||
|
|
||||||
|
if (splineflags.animation)
|
||||||
|
;// MoveSplineFlag::Animation disables falling or parabolic movement
|
||||||
|
else if (splineflags.parabolic)
|
||||||
|
computeParabolicElevation(c.z);
|
||||||
|
else if (splineflags.falling)
|
||||||
|
computeFallElevation(c.z);
|
||||||
|
|
||||||
|
if (splineflags.done && splineflags.isFacing())
|
||||||
|
{
|
||||||
|
if (splineflags.final_angle)
|
||||||
|
c.orientation = facing.angle;
|
||||||
|
else if (splineflags.final_point)
|
||||||
|
c.orientation = atan2(facing.f.y-c.y, facing.f.x-c.x);
|
||||||
|
//nothing to do for MoveSplineFlag::Final_Target flag
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector3 hermite;
|
||||||
|
spline.evaluate_derivative(point_Idx,u,hermite);
|
||||||
|
c.orientation = atan2(hermite.y, hermite.x);
|
||||||
|
|
||||||
|
if (splineflags.backward)
|
||||||
|
c.orientation = -c.orientation;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSpline::computeParabolicElevation(float& el) const
|
||||||
|
{
|
||||||
|
if (time_passed > effect_start_time)
|
||||||
|
{
|
||||||
|
float t_passedf = MSToSec(time_passed - effect_start_time);
|
||||||
|
float t_durationf = MSToSec(Duration() - effect_start_time); //client use not modified duration here
|
||||||
|
|
||||||
|
// -a*x*x + bx + c:
|
||||||
|
//(dur * v3->z_acceleration * dt)/2 - (v3->z_acceleration * dt * dt)/2 + Z;
|
||||||
|
el += (t_durationf - t_passedf) * 0.5f * vertical_acceleration * t_passedf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSpline::computeFallElevation(float& el) const
|
||||||
|
{
|
||||||
|
float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed));
|
||||||
|
float final_z = FinalDestination().z;
|
||||||
|
if (z_now < final_z)
|
||||||
|
el = final_z;
|
||||||
|
else
|
||||||
|
el = z_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32 computeDuration(float length, float velocity)
|
||||||
|
{
|
||||||
|
return SecToMS(length / velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FallInitializer
|
||||||
|
{
|
||||||
|
FallInitializer(float _start_elevation) : start_elevation(_start_elevation) {}
|
||||||
|
float start_elevation;
|
||||||
|
inline int32 operator()(Spline<int32>& s, int32 i)
|
||||||
|
{
|
||||||
|
return Movement::computeFallTime(start_elevation - s.getPoint(i+1).z,false) * 1000.f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum{
|
||||||
|
minimal_duration = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonInitializer
|
||||||
|
{
|
||||||
|
CommonInitializer(float _velocity) : velocityInv(1000.f/_velocity), time(minimal_duration) {}
|
||||||
|
float velocityInv;
|
||||||
|
int32 time;
|
||||||
|
inline int32 operator()(Spline<int32>& s, int32 i)
|
||||||
|
{
|
||||||
|
time += (s.SegLength(i) * velocityInv);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void MoveSpline::init_spline(const MoveSplineInitArgs& args)
|
||||||
|
{
|
||||||
|
const SplineBase::EvaluationMode modes[2] = {SplineBase::ModeLinear,SplineBase::ModeCatmullrom};
|
||||||
|
if (args.flags.cyclic)
|
||||||
|
{
|
||||||
|
uint32 cyclic_point = 0;
|
||||||
|
// MoveSplineFlag::Enter_Cycle support dropped
|
||||||
|
//if (splineflags & SPLINEFLAG_ENTER_CYCLE)
|
||||||
|
//cyclic_point = 1; // shouldn't be modified, came from client
|
||||||
|
spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init spline timestamps
|
||||||
|
if (splineflags.falling)
|
||||||
|
{
|
||||||
|
FallInitializer init(spline.getPoint(spline.first()).z);
|
||||||
|
spline.initLengths(init);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CommonInitializer init(args.velocity);
|
||||||
|
spline.initLengths(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: what to do in such cases? problem is in input data (all points are at same coords)
|
||||||
|
if (spline.length() < minimal_duration)
|
||||||
|
{
|
||||||
|
sLog.outError("MoveSpline::init_spline: zero length spline, wrong input data?");
|
||||||
|
spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
|
||||||
|
}
|
||||||
|
point_Idx = spline.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSpline::Initialize(const MoveSplineInitArgs& args)
|
||||||
|
{
|
||||||
|
splineflags = args.flags;
|
||||||
|
facing = args.facing;
|
||||||
|
m_Id = args.splineId;
|
||||||
|
point_Idx_offset = args.path_Idx_offset;
|
||||||
|
|
||||||
|
time_passed = 0;
|
||||||
|
vertical_acceleration = 0.f;
|
||||||
|
effect_start_time = 0;
|
||||||
|
|
||||||
|
init_spline(args);
|
||||||
|
|
||||||
|
// init parabolic / animation
|
||||||
|
// spline initialized, duration known and i able to compute parabolic acceleration
|
||||||
|
if (args.flags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation))
|
||||||
|
{
|
||||||
|
effect_start_time = Duration() * args.time_perc;
|
||||||
|
if (args.flags.parabolic && effect_start_time < Duration())
|
||||||
|
{
|
||||||
|
float f_duration = MSToSec(Duration() - effect_start_time);
|
||||||
|
vertical_acceleration = args.parabolic_amplitude * 8.f / (f_duration * f_duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveSpline::MoveSpline() : m_Id(0), time_passed(0),
|
||||||
|
vertical_acceleration(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0)
|
||||||
|
{
|
||||||
|
splineflags.done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ============================================================================================
|
||||||
|
|
||||||
|
bool MoveSplineInitArgs::Validate() const
|
||||||
|
{
|
||||||
|
#define CHECK(exp) \
|
||||||
|
if (!(exp))\
|
||||||
|
{\
|
||||||
|
sLog.outError("MoveSplineInitArgs::Validate: expression '%s' failed", #exp);\
|
||||||
|
return false;\
|
||||||
|
}
|
||||||
|
CHECK(path.size() > 1);
|
||||||
|
CHECK(velocity > 0.f);
|
||||||
|
CHECK(time_perc >= 0.f && time_perc <= 1.f);
|
||||||
|
//CHECK(_checkPathBounds());
|
||||||
|
return true;
|
||||||
|
#undef CHECK
|
||||||
|
}
|
||||||
|
|
||||||
|
// MONSTER_MOVE packet format limitation for not CatmullRom movement:
|
||||||
|
// each vertex offset packed into 11 bytes
|
||||||
|
bool MoveSplineInitArgs::_checkPathBounds() const
|
||||||
|
{
|
||||||
|
if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2)
|
||||||
|
{
|
||||||
|
enum{
|
||||||
|
MAX_OFFSET = (1 << 11) / 2,
|
||||||
|
};
|
||||||
|
Vector3 middle = (path.front()+path.back()) / 2;
|
||||||
|
Vector3 offset;
|
||||||
|
for (uint32 i = 1; i < path.size()-1; ++i)
|
||||||
|
{
|
||||||
|
offset = path[i] - middle;
|
||||||
|
if (fabs(offset.x) >= MAX_OFFSET || fabs(offset.y) >= MAX_OFFSET || fabs(offset.z) >= MAX_OFFSET)
|
||||||
|
{
|
||||||
|
sLog.outError("MoveSplineInitArgs::_checkPathBounds check failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ============================================================================================
|
||||||
|
|
||||||
|
MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff)
|
||||||
|
{
|
||||||
|
if (Finalized())
|
||||||
|
{
|
||||||
|
ms_time_diff = 0;
|
||||||
|
return Result_Arrived;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateResult result = Result_None;
|
||||||
|
|
||||||
|
int32 minimal_diff = std::min(ms_time_diff, segment_time_elapsed());
|
||||||
|
MANGOS_ASSERT(minimal_diff >= 0);
|
||||||
|
time_passed += minimal_diff;
|
||||||
|
ms_time_diff -= minimal_diff;
|
||||||
|
|
||||||
|
if (time_passed >= next_timestamp())
|
||||||
|
{
|
||||||
|
++point_Idx;
|
||||||
|
if (point_Idx < spline.last())
|
||||||
|
{
|
||||||
|
result = Result_NextSegment;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (spline.isCyclic())
|
||||||
|
{
|
||||||
|
point_Idx = spline.first();
|
||||||
|
time_passed = time_passed % Duration();
|
||||||
|
result = Result_NextSegment;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_Finalize();
|
||||||
|
ms_time_diff = 0;
|
||||||
|
result = Result_Arrived;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MoveSpline::ToString() const
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
str << "MoveSpline" << std::endl;
|
||||||
|
str << "spline Id: " << GetId() << std::endl;
|
||||||
|
str << "flags: " << splineflags.ToString() << std::endl;
|
||||||
|
if (splineflags.final_angle)
|
||||||
|
str << "facing angle: " << facing.angle;
|
||||||
|
else if (splineflags.final_target)
|
||||||
|
str << "facing target: " << facing.target;
|
||||||
|
else if(splineflags.final_point)
|
||||||
|
str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z;
|
||||||
|
str << std::endl;
|
||||||
|
str << "time passed: " << time_passed << std::endl;
|
||||||
|
str << "total time: " << Duration() << std::endl;
|
||||||
|
str << "spline point Id: " << point_Idx << std::endl;
|
||||||
|
str << "path point Id: " << currentPathIdx() << std::endl;
|
||||||
|
str << spline.ToString();
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSpline::_Finalize()
|
||||||
|
{
|
||||||
|
splineflags.done = true;
|
||||||
|
point_Idx = spline.last() - 1;
|
||||||
|
time_passed = Duration();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MoveSpline::currentPathIdx() const
|
||||||
|
{
|
||||||
|
int32 point = point_Idx_offset + point_Idx - spline.first() + (int)Finalized();
|
||||||
|
if (isCyclic())
|
||||||
|
point = point % (spline.last()-spline.first());
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
}
|
||||||
125
src/game/movement/MoveSpline.h
Normal file
125
src/game/movement/MoveSpline.h
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_MOVEPLINE_H
|
||||||
|
#define MANGOSSERVER_MOVEPLINE_H
|
||||||
|
|
||||||
|
#include "spline.h"
|
||||||
|
#include "MoveSplineInitArgs.h"
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
struct Location : public Vector3
|
||||||
|
{
|
||||||
|
Location() : orientation(0) {}
|
||||||
|
Location(float x, float y, float z, float o) : Vector3(x,y,z), orientation(o) {}
|
||||||
|
Location(const Vector3& v) : Vector3(v), orientation(0) {}
|
||||||
|
Location(const Vector3& v, float o) : Vector3(v), orientation(o) {}
|
||||||
|
|
||||||
|
float orientation;
|
||||||
|
};
|
||||||
|
|
||||||
|
// MoveSpline represents smooth catmullrom or linear curve and point that moves belong it
|
||||||
|
// curve can be cyclic - in this case movement will be cyclic
|
||||||
|
// point can have vertical acceleration motion componemt(used in fall, parabolic movement)
|
||||||
|
class MoveSpline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Spline<int32> MySpline;
|
||||||
|
enum UpdateResult{
|
||||||
|
Result_None = 0x01,
|
||||||
|
Result_Arrived = 0x02,
|
||||||
|
Result_NextCycle = 0x04,
|
||||||
|
Result_NextSegment = 0x08,
|
||||||
|
};
|
||||||
|
#pragma region fields
|
||||||
|
friend class PacketBuilder;
|
||||||
|
protected:
|
||||||
|
MySpline spline;
|
||||||
|
|
||||||
|
FacingInfo facing;
|
||||||
|
|
||||||
|
uint32 m_Id;
|
||||||
|
|
||||||
|
MoveSplineFlag splineflags;
|
||||||
|
|
||||||
|
int32 time_passed;
|
||||||
|
// currently duration mods are unused, but its _currently_
|
||||||
|
//float duration_mod;
|
||||||
|
//float duration_mod_next;
|
||||||
|
float vertical_acceleration;
|
||||||
|
int32 effect_start_time;
|
||||||
|
int32 point_Idx;
|
||||||
|
int32 point_Idx_offset;
|
||||||
|
|
||||||
|
void init_spline(const MoveSplineInitArgs& args);
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const MySpline::ControlArray& getPath() const { return spline.getPoints();}
|
||||||
|
void computeParabolicElevation(float& el) const;
|
||||||
|
void computeFallElevation(float& el) const;
|
||||||
|
|
||||||
|
UpdateResult _updateState(int32& ms_time_diff);
|
||||||
|
int32 next_timestamp() const { return spline.length(point_Idx+1);}
|
||||||
|
int32 segment_time_elapsed() const { return next_timestamp()-time_passed;}
|
||||||
|
int32 Duration() const { return spline.length();}
|
||||||
|
int32 timeElapsed() const { return Duration() - time_passed;}
|
||||||
|
int32 timePassed() const { return time_passed;}
|
||||||
|
|
||||||
|
public:
|
||||||
|
const MySpline& _Spline() const { return spline;}
|
||||||
|
int32 _currentSplineIdx() const { return point_Idx;}
|
||||||
|
void _Finalize();
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
public:
|
||||||
|
|
||||||
|
void Initialize(const MoveSplineInitArgs&);
|
||||||
|
bool Initialized() const { return !spline.empty();}
|
||||||
|
|
||||||
|
explicit MoveSpline();
|
||||||
|
|
||||||
|
template<class UpdateHandler>
|
||||||
|
void updateState(int32 difftime, UpdateHandler& handler)
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(Initialized());
|
||||||
|
do
|
||||||
|
handler(_updateState(difftime));
|
||||||
|
while(difftime > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateState(int32 difftime)
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(Initialized());
|
||||||
|
do _updateState(difftime);
|
||||||
|
while(difftime > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Location ComputePosition() const;
|
||||||
|
|
||||||
|
uint32 GetId() const { return m_Id;}
|
||||||
|
bool Finalized() const { return splineflags.done; }
|
||||||
|
bool isCyclic() const { return splineflags.cyclic;}
|
||||||
|
const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3();}
|
||||||
|
const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3();}
|
||||||
|
int32 currentPathIdx() const;
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // MANGOSSERVER_MOVEPLINE_H
|
||||||
142
src/game/movement/MoveSplineFlag.h
Normal file
142
src/game/movement/MoveSplineFlag.h
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_MOVESPLINEFLAG_H
|
||||||
|
#define MANGOSSERVER_MOVESPLINEFLAG_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
#if defined( __GNUC__ )
|
||||||
|
#pragma pack(1)
|
||||||
|
#else
|
||||||
|
#pragma pack(push,1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class MoveSplineFlag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum eFlags{
|
||||||
|
None = 0x00000000,
|
||||||
|
// x00-xFF(first byte) used as animation Ids storage in pair with Animation flag
|
||||||
|
Done = 0x00000100,
|
||||||
|
Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
|
||||||
|
No_Spline = 0x00000400,
|
||||||
|
Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
|
||||||
|
Walkmode = 0x00001000,
|
||||||
|
Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
|
||||||
|
Knockback = 0x00004000, // Model orientation fixed
|
||||||
|
Final_Point = 0x00008000,
|
||||||
|
Final_Target = 0x00010000,
|
||||||
|
Final_Angle = 0x00020000,
|
||||||
|
Catmullrom = 0x00040000, // Used Catmullrom interpolation mode
|
||||||
|
Cyclic = 0x00080000, // Movement by cycled spline
|
||||||
|
Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
|
||||||
|
Animation = 0x00200000, // Plays animation after some time passed
|
||||||
|
Frozen = 0x00400000, // Will never arrive
|
||||||
|
Unknown5 = 0x00800000,
|
||||||
|
Unknown6 = 0x01000000,
|
||||||
|
Unknown7 = 0x02000000,
|
||||||
|
Unknown8 = 0x04000000,
|
||||||
|
Backward = 0x08000000,
|
||||||
|
Unknown10 = 0x10000000,
|
||||||
|
Unknown11 = 0x20000000,
|
||||||
|
Unknown12 = 0x40000000,
|
||||||
|
Unknown13 = 0x80000000,
|
||||||
|
|
||||||
|
// Masks
|
||||||
|
Mask_Final_Facing = Final_Point | Final_Target | Final_Angle,
|
||||||
|
// animation ids stored here, see AnimType enum, used with Animation flag
|
||||||
|
Mask_Animations = 0xFF,
|
||||||
|
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
|
||||||
|
Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done,
|
||||||
|
// CatmullRom interpolation mode used
|
||||||
|
Mask_CatmullRom = Flying | Catmullrom,
|
||||||
|
// Unused, not suported flags
|
||||||
|
Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown5|Unknown6|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint32& raw() { return (uint32&)*this;}
|
||||||
|
inline const uint32& raw() const { return (const uint32&)*this;}
|
||||||
|
|
||||||
|
MoveSplineFlag() { raw() = 0; }
|
||||||
|
MoveSplineFlag(uint32 f) { raw() = f; }
|
||||||
|
MoveSplineFlag(const MoveSplineFlag& f) { raw() = f.raw(); }
|
||||||
|
|
||||||
|
// Constant interface
|
||||||
|
|
||||||
|
bool isSmooth() const { return raw() & Mask_CatmullRom;}
|
||||||
|
bool isLinear() const { return !isSmooth();}
|
||||||
|
bool isFacing() const { return raw() & Mask_Final_Facing;}
|
||||||
|
|
||||||
|
uint8 getAnimationId() const { return animId;}
|
||||||
|
bool hasAllFlags(uint32 f) const { return (raw() & f) == f;}
|
||||||
|
uint32 operator & (uint32 f) const { return (raw() & f);}
|
||||||
|
uint32 operator | (uint32 f) const { return (raw() | f);}
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
// Not constant interface
|
||||||
|
|
||||||
|
void operator &= (uint32 f) { raw() &= f;}
|
||||||
|
void operator |= (uint32 f) { raw() |= f;}
|
||||||
|
|
||||||
|
void EnableAnimation(uint8 anim) { raw() = raw() & ~(Mask_Animations|Falling|Parabolic|Knockback) | Animation|anim;}
|
||||||
|
void EnableParabolic() { raw() = raw() & ~(Mask_Animations|Falling|Animation) | Parabolic;}
|
||||||
|
void EnableFalling() { raw() = raw() & ~(Mask_Animations|Parabolic|Knockback|Animation) | Falling;}
|
||||||
|
void EnableFlying() { raw() = raw() & ~Catmullrom | Flying; }
|
||||||
|
void EnableCatmullRom() { raw() = raw() & ~Flying | Catmullrom; }
|
||||||
|
void EnableFacingPoint() { raw() = raw() & ~Mask_Final_Facing | Final_Point;}
|
||||||
|
void EnableFacingAngle() { raw() = raw() & ~Mask_Final_Facing | Final_Angle;}
|
||||||
|
void EnableFacingTarget() { raw() = raw() & ~Mask_Final_Facing | Final_Target;}
|
||||||
|
|
||||||
|
uint8 animId : 8;
|
||||||
|
bool done : 1;
|
||||||
|
bool falling : 1;
|
||||||
|
bool no_spline : 1;
|
||||||
|
bool parabolic : 1;
|
||||||
|
bool walkmode : 1;
|
||||||
|
bool flying : 1;
|
||||||
|
bool knockback : 1;
|
||||||
|
bool final_point : 1;
|
||||||
|
bool final_target : 1;
|
||||||
|
bool final_angle : 1;
|
||||||
|
bool catmullrom : 1;
|
||||||
|
bool cyclic : 1;
|
||||||
|
bool enter_cycle : 1;
|
||||||
|
bool animation : 1;
|
||||||
|
bool frozen : 1;
|
||||||
|
bool unknown5 : 1;
|
||||||
|
bool unknown6 : 1;
|
||||||
|
bool unknown7 : 1;
|
||||||
|
bool unknown8 : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
bool unknown10 : 1;
|
||||||
|
bool unknown11 : 1;
|
||||||
|
bool unknown12 : 1;
|
||||||
|
bool unknown13 : 1;
|
||||||
|
};
|
||||||
|
#if defined( __GNUC__ )
|
||||||
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MANGOSSERVER_MOVESPLINEFLAG_H
|
||||||
106
src/game/movement/MoveSplineInit.cpp
Normal file
106
src/game/movement/MoveSplineInit.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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 "packet_builder.h"
|
||||||
|
#include "../Unit.h"
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
UnitMoveType SelectSpeedType(uint32 moveFlags)
|
||||||
|
{
|
||||||
|
if (moveFlags & MOVEFLAG_FLYING)
|
||||||
|
{
|
||||||
|
if ( moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/ )
|
||||||
|
return MOVE_FLIGHT_BACK;
|
||||||
|
else
|
||||||
|
return MOVE_FLIGHT;
|
||||||
|
}
|
||||||
|
else if (moveFlags & MOVEFLAG_SWIMMING)
|
||||||
|
{
|
||||||
|
if (moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.swim >= speed_obj.swim_back*/)
|
||||||
|
return MOVE_SWIM_BACK;
|
||||||
|
else
|
||||||
|
return MOVE_SWIM;
|
||||||
|
}
|
||||||
|
else if (moveFlags & MOVEFLAG_WALK_MODE)
|
||||||
|
{
|
||||||
|
//if ( speed_obj.run > speed_obj.walk )
|
||||||
|
return MOVE_WALK;
|
||||||
|
}
|
||||||
|
else if (moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.run >= speed_obj.run_back*/)
|
||||||
|
return MOVE_RUN_BACK;
|
||||||
|
|
||||||
|
return MOVE_RUN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSplineInit::Launch()
|
||||||
|
{
|
||||||
|
MoveSpline& move_spline = *unit.movespline;
|
||||||
|
|
||||||
|
Vector3 real_position(unit.GetPositionX(),unit.GetPositionY(),unit.GetPositionZ());
|
||||||
|
// there is a big chane that current position is unknown if current state is not finalized, need compute it
|
||||||
|
// this also allows calculate spline position and update map position in much greater intervals
|
||||||
|
if (!move_spline.Finalized())
|
||||||
|
real_position = move_spline.ComputePosition();
|
||||||
|
|
||||||
|
if (args.path.empty())
|
||||||
|
{
|
||||||
|
// should i do the things that user should do?
|
||||||
|
MoveTo(real_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// corrent first vertex
|
||||||
|
args.path[0] = real_position;
|
||||||
|
uint32 moveFlags = unit.m_movementInfo.GetMovementFlags();
|
||||||
|
if (args.flags.walkmode)
|
||||||
|
moveFlags |= MOVEFLAG_WALK_MODE;
|
||||||
|
else
|
||||||
|
moveFlags &= ~MOVEFLAG_WALK_MODE;
|
||||||
|
|
||||||
|
moveFlags |= (MOVEFLAG_SPLINE_ENABLED|MOVEFLAG_FORWARD);
|
||||||
|
|
||||||
|
if (args.velocity == 0.f)
|
||||||
|
args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags));
|
||||||
|
|
||||||
|
if (!args.Validate())
|
||||||
|
return;
|
||||||
|
|
||||||
|
unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags);
|
||||||
|
move_spline.Initialize(args);
|
||||||
|
|
||||||
|
WorldPacket data(SMSG_MONSTER_MOVE, 64);
|
||||||
|
data << unit.GetPackGUID();
|
||||||
|
PacketBuilder::WriteMonsterMove(move_spline, data);
|
||||||
|
unit.SendMessageToSet(&data,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveSplineInit::MoveSplineInit(Unit& m) : unit(m)
|
||||||
|
{
|
||||||
|
// mix existing state into new
|
||||||
|
args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);
|
||||||
|
args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING|MOVEFLAG_LEVITATING));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSplineInit::SetFacing(const Unit * target)
|
||||||
|
{
|
||||||
|
args.flags.EnableFacingTarget();
|
||||||
|
args.facing.target = target->GetObjectGuid().GetRawValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
164
src/game/movement/MoveSplineInit.h
Normal file
164
src/game/movement/MoveSplineInit.h
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_MOVESPLINEINIT_H
|
||||||
|
#define MANGOSSERVER_MOVESPLINEINIT_H
|
||||||
|
|
||||||
|
#include "MoveSplineInitArgs.h"
|
||||||
|
|
||||||
|
class Unit;
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
/* Initializes and launches spline movement
|
||||||
|
*/
|
||||||
|
class MANGOS_DLL_SPEC MoveSplineInit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit MoveSplineInit(Unit& m);
|
||||||
|
|
||||||
|
/* Final pass of initialization that launches spline movement.
|
||||||
|
*/
|
||||||
|
void Launch();
|
||||||
|
|
||||||
|
/* Adds movement by parabolic trajectory
|
||||||
|
* @param amplitude - the maximum height of parabola, value could be negative and positive
|
||||||
|
* @param start_time - delay between movement starting time and beginning to move by parabolic trajectory
|
||||||
|
* can't be combined with final animation
|
||||||
|
*/
|
||||||
|
void SetParabolic(float amplitude, float start_time, bool is_knockback = false);
|
||||||
|
|
||||||
|
/* Adds final facing animation
|
||||||
|
* sets unit's facing to specified point/angle after all path done
|
||||||
|
* you can have only one final facing: previous will be overriden
|
||||||
|
*/
|
||||||
|
void SetFacing(float angle);
|
||||||
|
void SetFacing(Vector3 const& point);
|
||||||
|
void SetFacing(const Unit * target);
|
||||||
|
|
||||||
|
/* Initializes movement by path
|
||||||
|
* @param path - array of points, shouldn't be empty
|
||||||
|
* @param pointId - Id of fisrt point of the path. Example: when third path point will be done it will notify that pointId + 3 done
|
||||||
|
*/
|
||||||
|
void MovebyPath(const PointsArray& path, int32 pointId = 0);
|
||||||
|
|
||||||
|
/* Initializes simple A to B mition, A is current unit's position, B is destination
|
||||||
|
*/
|
||||||
|
void MoveTo(const Vector3& destination);
|
||||||
|
void MoveTo(float x, float y, float z);
|
||||||
|
|
||||||
|
/* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done
|
||||||
|
* Needed for waypoint movement where path splitten into parts
|
||||||
|
*/
|
||||||
|
void SetFirstPointId(int32 pointId) { args.path_Idx_offset = pointId; }
|
||||||
|
|
||||||
|
/* Enables CatmullRom spline interpolation mode(makes path smooth)
|
||||||
|
* if not enabled linear spline mode will be choosen. Disabled by default
|
||||||
|
*/
|
||||||
|
void SetSmooth();
|
||||||
|
/* Enables CatmullRom spline interpolation mode, enables flying animation. Disabled by default
|
||||||
|
*/
|
||||||
|
void SetFly();
|
||||||
|
/* Enables walk mode. Disabled by default
|
||||||
|
*/
|
||||||
|
void SetWalk(bool enable);
|
||||||
|
/* Makes movement cyclic. Disabled by default
|
||||||
|
*/
|
||||||
|
void SetCyclic();
|
||||||
|
/* Enables falling mode. Disabled by default
|
||||||
|
*/
|
||||||
|
void SetFall();
|
||||||
|
/* Disabled by default
|
||||||
|
*/
|
||||||
|
void SetBackward();
|
||||||
|
|
||||||
|
/* Sets the velocity (in case you want to have custom movement velocity)
|
||||||
|
* if no set, speed will be selected based on unit's speeds and current movement mode
|
||||||
|
* Has no effect if falling mode enabled
|
||||||
|
* velocity shouldn't be negative
|
||||||
|
*/
|
||||||
|
void SetVelocity(float velocity);
|
||||||
|
|
||||||
|
PointsArray& Path() { return args.path; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
MoveSplineInitArgs args;
|
||||||
|
Unit& unit;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void MoveJumpInit(Unit& st, const Vector3& dest, float velocity, float parabolic_heigth = 0.5f)
|
||||||
|
{
|
||||||
|
MoveSplineInit init(st);
|
||||||
|
init.MoveTo(dest);
|
||||||
|
init.SetParabolic(parabolic_heigth,0,false);
|
||||||
|
init.SetVelocity(velocity);
|
||||||
|
init.Launch();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::SetFly() { args.flags.EnableFlying();}
|
||||||
|
inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable;}
|
||||||
|
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();}
|
||||||
|
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;}
|
||||||
|
inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();}
|
||||||
|
inline void MoveSplineInit::SetVelocity(float vel){ args.velocity = vel;}
|
||||||
|
inline void MoveSplineInit::SetBackward() { args.flags.backward = true;}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset)
|
||||||
|
{
|
||||||
|
args.path_Idx_offset = path_offset;
|
||||||
|
args.path.assign(controls.begin(),controls.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::MoveTo(float x, float y, float z)
|
||||||
|
{
|
||||||
|
Vector3 v(x,y,z);
|
||||||
|
MoveTo(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::MoveTo(const Vector3& dest)
|
||||||
|
{
|
||||||
|
args.path_Idx_offset = 0;
|
||||||
|
args.path.resize(2);
|
||||||
|
args.path[1] = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift, bool is_knockback)
|
||||||
|
{
|
||||||
|
args.time_perc = time_shift;
|
||||||
|
args.parabolic_amplitude = amplitude;
|
||||||
|
args.flags.EnableParabolic();
|
||||||
|
args.flags.knockback = is_knockback;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::SetFacing(float o)
|
||||||
|
{
|
||||||
|
args.facing.angle = G3D::wrap(o, 0.f, (float)G3D::twoPi());
|
||||||
|
args.flags.EnableFacingAngle();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MoveSplineInit::SetFacing(Vector3 const& spot)
|
||||||
|
{
|
||||||
|
args.facing.f.x = spot.x;
|
||||||
|
args.facing.f.y = spot.y;
|
||||||
|
args.facing.f.z = spot.z;
|
||||||
|
args.flags.EnableFacingPoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // MANGOSSERVER_MOVESPLINEINIT_H
|
||||||
66
src/game/movement/MoveSplineInitArgs.h
Normal file
66
src/game/movement/MoveSplineInitArgs.h
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_MOVESPLINEINIT_ARGS_H
|
||||||
|
#define MANGOSSERVER_MOVESPLINEINIT_ARGS_H
|
||||||
|
|
||||||
|
#include "MoveSplineFlag.h"
|
||||||
|
#include <G3D/Vector3.h>
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
typedef std::vector<Vector3> PointsArray;
|
||||||
|
|
||||||
|
union FacingInfo
|
||||||
|
{
|
||||||
|
struct{
|
||||||
|
float x,y,z;
|
||||||
|
}f;
|
||||||
|
uint64 target;
|
||||||
|
float angle;
|
||||||
|
|
||||||
|
FacingInfo(float o) : angle(o) {}
|
||||||
|
FacingInfo(uint64 t) : target(t) {}
|
||||||
|
FacingInfo() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MoveSplineInitArgs
|
||||||
|
{
|
||||||
|
MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0),
|
||||||
|
velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0)
|
||||||
|
{
|
||||||
|
path.reserve(path_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointsArray path;
|
||||||
|
FacingInfo facing;
|
||||||
|
MoveSplineFlag flags;
|
||||||
|
int32 path_Idx_offset;
|
||||||
|
float velocity;
|
||||||
|
float parabolic_amplitude;
|
||||||
|
float time_perc;
|
||||||
|
uint32 splineId;
|
||||||
|
|
||||||
|
/** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
|
||||||
|
bool Validate() const;
|
||||||
|
private:
|
||||||
|
bool _checkPathBounds() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MANGOSSERVER_MOVESPLINEINIT_ARGS_H
|
||||||
189
src/game/movement/packet_builder.cpp
Normal file
189
src/game/movement/packet_builder.cpp
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* 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 "packet_builder.h"
|
||||||
|
#include "MoveSpline.h"
|
||||||
|
#include "WorldPacket.h"
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
inline void operator << (ByteBuffer& b, const Vector3& v)
|
||||||
|
{
|
||||||
|
b << v.x << v.y << v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void operator >> (ByteBuffer& b, Vector3& v)
|
||||||
|
{
|
||||||
|
b >> v.x >> v.y >> v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MonsterMoveType
|
||||||
|
{
|
||||||
|
MonsterMoveNormal = 0,
|
||||||
|
MonsterMoveStop = 1,
|
||||||
|
MonsterMoveFacingSpot = 2,
|
||||||
|
MonsterMoveFacingTarget = 3,
|
||||||
|
MonsterMoveFacingAngle = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data)
|
||||||
|
{
|
||||||
|
MoveSplineFlag splineflags = move_spline.splineflags;
|
||||||
|
|
||||||
|
/*if (mov.IsBoarded())
|
||||||
|
{
|
||||||
|
data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
|
||||||
|
data << mov.GetTransport()->Owner.GetPackGUID();
|
||||||
|
data << int8(mov.m_unused.transport_seat);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
data << uint8(0);
|
||||||
|
data << move_spline.spline.getPoint(move_spline.spline.first());
|
||||||
|
data << move_spline.GetId();
|
||||||
|
|
||||||
|
switch(splineflags & MoveSplineFlag::Mask_Final_Facing)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
data << uint8(MonsterMoveNormal);
|
||||||
|
break;
|
||||||
|
case MoveSplineFlag::Final_Target:
|
||||||
|
data << uint8(MonsterMoveFacingTarget);
|
||||||
|
data << move_spline.facing.target;
|
||||||
|
break;
|
||||||
|
case MoveSplineFlag::Final_Angle:
|
||||||
|
data << uint8(MonsterMoveFacingAngle);
|
||||||
|
data << move_spline.facing.angle;
|
||||||
|
break;
|
||||||
|
case MoveSplineFlag::Final_Point:
|
||||||
|
data << uint8(MonsterMoveFacingSpot);
|
||||||
|
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
|
||||||
|
splineflags.enter_cycle = move_spline.isCyclic();
|
||||||
|
data << uint32(splineflags & ~MoveSplineFlag::Mask_No_Monster_Move);
|
||||||
|
|
||||||
|
if (splineflags.animation)
|
||||||
|
{
|
||||||
|
data << splineflags.getAnimationId();
|
||||||
|
data << move_spline.effect_start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
data << move_spline.Duration();
|
||||||
|
|
||||||
|
if (splineflags.parabolic)
|
||||||
|
{
|
||||||
|
data << move_spline.vertical_acceleration;
|
||||||
|
data << move_spline.effect_start_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
|
||||||
|
{
|
||||||
|
uint32 last_idx = spline.getPointCount() - 3;
|
||||||
|
const Vector3 * real_path = &spline.getPoint(1);
|
||||||
|
|
||||||
|
data << last_idx;
|
||||||
|
data << real_path[last_idx]; // destination
|
||||||
|
if (last_idx > 1)
|
||||||
|
{
|
||||||
|
Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f;
|
||||||
|
Vector3 offset;
|
||||||
|
// first and last points already appended
|
||||||
|
for(uint32 i = 1; i < last_idx; ++i)
|
||||||
|
{
|
||||||
|
offset = middle - real_path[i];
|
||||||
|
data.appendPackXYZ(offset.x, offset.y, offset.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCatmullRomPath(const Spline<int32>& spline, ByteBuffer& data)
|
||||||
|
{
|
||||||
|
uint32 count = spline.getPointCount() - 3;
|
||||||
|
data << count;
|
||||||
|
data.append<Vector3>(&spline.getPoint(2), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data)
|
||||||
|
{
|
||||||
|
uint32 count = spline.getPointCount() - 3;
|
||||||
|
data << uint32(count + 1);
|
||||||
|
data << spline.getPoint(1); // fake point, client will erase it from the spline after first cycle done
|
||||||
|
data.append<Vector3>(&spline.getPoint(1), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, WorldPacket& data)
|
||||||
|
{
|
||||||
|
WriteCommonMonsterMovePart(move_spline, data);
|
||||||
|
|
||||||
|
const Spline<int32>& spline = move_spline.spline;
|
||||||
|
MoveSplineFlag splineflags = move_spline.splineflags;
|
||||||
|
if (splineflags & MoveSplineFlag::Mask_CatmullRom)
|
||||||
|
{
|
||||||
|
if (splineflags.cyclic)
|
||||||
|
WriteCatmullRomCyclicPath(spline, data);
|
||||||
|
else
|
||||||
|
WriteCatmullRomPath(spline, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WriteLinearPath(spline, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketBuilder::WriteCreate(const MoveSpline& move_spline, ByteBuffer& data)
|
||||||
|
{
|
||||||
|
//WriteClientStatus(mov,data);
|
||||||
|
//data.append<float>(&mov.m_float_values[SpeedWalk], SpeedMaxCount);
|
||||||
|
//if (mov.SplineEnabled())
|
||||||
|
{
|
||||||
|
MoveSplineFlag splineFlags = move_spline.splineflags;
|
||||||
|
|
||||||
|
data << splineFlags.raw();
|
||||||
|
|
||||||
|
if (splineFlags.final_angle)
|
||||||
|
{
|
||||||
|
data << move_spline.facing.angle;
|
||||||
|
}
|
||||||
|
else if (splineFlags.final_target)
|
||||||
|
{
|
||||||
|
data << move_spline.facing.target;
|
||||||
|
}
|
||||||
|
else if(splineFlags.final_point)
|
||||||
|
{
|
||||||
|
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
data << move_spline.timePassed();
|
||||||
|
data << move_spline.Duration();
|
||||||
|
data << move_spline.GetId();
|
||||||
|
|
||||||
|
data << float(1.f);//splineInfo.duration_mod;
|
||||||
|
data << float(1.f);//splineInfo.duration_mod_next;
|
||||||
|
|
||||||
|
data << move_spline.vertical_acceleration;
|
||||||
|
data << move_spline.effect_start_time;
|
||||||
|
|
||||||
|
uint32 nodes = move_spline.getPath().size();
|
||||||
|
data << nodes;
|
||||||
|
data.append<Vector3>(&move_spline.getPath()[0], nodes);
|
||||||
|
data << uint8(move_spline.spline.mode());
|
||||||
|
data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,5 +15,22 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_PACKET_BUILDER_H
|
||||||
|
#define MANGOSSERVER_PACKET_BUILDER_H
|
||||||
|
|
||||||
#include "DestinationHolder.h"
|
class ByteBuffer;
|
||||||
|
class WorldPacket;
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
class PacketBuilder
|
||||||
|
{
|
||||||
|
static void WriteCommonMonsterMovePart(const MoveSpline& mov, WorldPacket& data);
|
||||||
|
public:
|
||||||
|
|
||||||
|
static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data);
|
||||||
|
static void WriteCreate(const MoveSpline& mov, ByteBuffer& data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // MANGOSSERVER_PACKET_BUILDER_H
|
||||||
307
src/game/movement/spline.cpp
Normal file
307
src/game/movement/spline.cpp
Normal file
|
|
@ -0,0 +1,307 @@
|
||||||
|
/*
|
||||||
|
* 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 "spline.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <G3D/Matrix4.h>
|
||||||
|
|
||||||
|
namespace Movement{
|
||||||
|
|
||||||
|
SplineBase::EvaluationMethtod SplineBase::evaluators[SplineBase::ModesEnd] =
|
||||||
|
{
|
||||||
|
&SplineBase::EvaluateLinear,
|
||||||
|
&SplineBase::EvaluateCatmullRom,
|
||||||
|
&SplineBase::EvaluateBezier3,
|
||||||
|
(EvaluationMethtod)&SplineBase::UninitializedSpline,
|
||||||
|
};
|
||||||
|
|
||||||
|
SplineBase::EvaluationMethtod SplineBase::derivative_evaluators[SplineBase::ModesEnd] =
|
||||||
|
{
|
||||||
|
&SplineBase::EvaluateDerivativeLinear,
|
||||||
|
&SplineBase::EvaluateDerivativeCatmullRom,
|
||||||
|
&SplineBase::EvaluateDerivativeBezier3,
|
||||||
|
(EvaluationMethtod)&SplineBase::UninitializedSpline,
|
||||||
|
};
|
||||||
|
|
||||||
|
SplineBase::SegLenghtMethtod SplineBase::seglengths[SplineBase::ModesEnd] =
|
||||||
|
{
|
||||||
|
&SplineBase::SegLengthLinear,
|
||||||
|
&SplineBase::SegLengthCatmullRom,
|
||||||
|
&SplineBase::SegLengthBezier3,
|
||||||
|
(SegLenghtMethtod)&SplineBase::UninitializedSpline,
|
||||||
|
};
|
||||||
|
|
||||||
|
SplineBase::InitMethtod SplineBase::initializers[SplineBase::ModesEnd] =
|
||||||
|
{
|
||||||
|
//&SplineBase::InitLinear,
|
||||||
|
&SplineBase::InitCatmullRom, // we should use catmullrom initializer even for linear mode! (client's internal structure limitation)
|
||||||
|
&SplineBase::InitCatmullRom,
|
||||||
|
&SplineBase::InitBezier3,
|
||||||
|
(InitMethtod)&SplineBase::UninitializedSpline,
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////
|
||||||
|
#pragma region evaluation methtods
|
||||||
|
|
||||||
|
using G3D::Matrix4;
|
||||||
|
static const Matrix4 s_catmullRomCoeffs(
|
||||||
|
-0.5f, 1.5f,-1.5f, 0.5f,
|
||||||
|
1.f, -2.5f, 2.f, -0.5f,
|
||||||
|
-0.5f, 0.f, 0.5f, 0.f,
|
||||||
|
0.f, 1.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
static const Matrix4 s_Bezier3Coeffs(
|
||||||
|
-1.f, 3.f, -3.f, 1.f,
|
||||||
|
3.f, -6.f, 3.f, 0.f,
|
||||||
|
-3.f, 3.f, 0.f, 0.f,
|
||||||
|
1.f, 0.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
/* classic view:
|
||||||
|
inline void C_Evaluate(const Vector3 *vertice, float t, const float (&matrix)[4][4], Vector3 &position)
|
||||||
|
{
|
||||||
|
Vector3 tvec(t*t*t, t*t, t);
|
||||||
|
int i = 0;
|
||||||
|
double c;
|
||||||
|
double x = 0, y = 0, z = 0;
|
||||||
|
while ( i < 4 )
|
||||||
|
{
|
||||||
|
c = matrix[0][i]*tvec.x + matrix[1][i]*tvec.y + matrix[2][i]*tvec.z + matrix[3][i];
|
||||||
|
|
||||||
|
x += c * vertice->x;
|
||||||
|
y += c * vertice->y;
|
||||||
|
z += c * vertice->z;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
++vertice;
|
||||||
|
}
|
||||||
|
|
||||||
|
position.x = x;
|
||||||
|
position.y = y;
|
||||||
|
position.z = z;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
inline void C_Evaluate(const Vector3 *vertice, float t, const Matrix4& matr, Vector3 &result)
|
||||||
|
{
|
||||||
|
Vector4 tvec(t*t*t, t*t, t, 1.f);
|
||||||
|
Vector4 weights(tvec * matr);
|
||||||
|
|
||||||
|
result = vertice[0] * weights[0] + vertice[1] * weights[1]
|
||||||
|
+ vertice[2] * weights[2] + vertice[3] * weights[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void C_Evaluate_Derivative(const Vector3 *vertice, float t, const Matrix4& matr, Vector3 &result)
|
||||||
|
{
|
||||||
|
Vector4 tvec(3.f*t*t, 2.f*t, 1.f, 0.f);
|
||||||
|
Vector4 weights(tvec * matr);
|
||||||
|
|
||||||
|
result = vertice[0] * weights[0] + vertice[1] * weights[1]
|
||||||
|
+ vertice[2] * weights[2] + vertice[3] * weights[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateLinear(index_type index, float u, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
result = points[index] + (points[index+1] - points[index]) * u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateCatmullRom( index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate(&points[index - 1], t, s_catmullRomCoeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateBezier3(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
index *= 3u;
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate(&points[index], t, s_Bezier3Coeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateDerivativeLinear(index_type index, float, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
result = points[index+1] - points[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate_Derivative(&points[index - 1], t, s_catmullRomCoeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateDerivativeBezier3(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
index *= 3u;
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
float SplineBase::SegLengthLinear(index_type index) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
return (points[index] - points[index+1]).length();
|
||||||
|
}
|
||||||
|
|
||||||
|
float SplineBase::SegLengthCatmullRom( index_type index ) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
|
||||||
|
Vector3 curPos, nextPos;
|
||||||
|
const Vector3 * p = &points[index - 1];
|
||||||
|
curPos = nextPos = p[1];
|
||||||
|
|
||||||
|
index_type i = 1;
|
||||||
|
double length = 0;
|
||||||
|
while (i <= STEPS_PER_SEGMENT)
|
||||||
|
{
|
||||||
|
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_catmullRomCoeffs, nextPos);
|
||||||
|
length += (nextPos - curPos).length();
|
||||||
|
curPos = nextPos;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SplineBase::SegLengthBezier3(index_type index) const
|
||||||
|
{
|
||||||
|
index *= 3u;
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
|
||||||
|
Vector3 curPos, nextPos;
|
||||||
|
const Vector3 * p = &points[index];
|
||||||
|
|
||||||
|
C_Evaluate(p, 0.f, s_Bezier3Coeffs, nextPos);
|
||||||
|
curPos = nextPos;
|
||||||
|
|
||||||
|
index_type i = 1;
|
||||||
|
double length = 0;
|
||||||
|
while (i <= STEPS_PER_SEGMENT)
|
||||||
|
{
|
||||||
|
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_Bezier3Coeffs, nextPos);
|
||||||
|
length += (nextPos - curPos).length();
|
||||||
|
curPos = nextPos;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
void SplineBase::init_spline(const Vector3 * controls, index_type count, EvaluationMode m)
|
||||||
|
{
|
||||||
|
m_mode = m;
|
||||||
|
cyclic = false;
|
||||||
|
|
||||||
|
(this->*initializers[m_mode])(controls, count, cyclic, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point)
|
||||||
|
{
|
||||||
|
m_mode = m;
|
||||||
|
cyclic = true;
|
||||||
|
|
||||||
|
(this->*initializers[m_mode])(controls, count, cyclic, cyclic_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(count >= 2);
|
||||||
|
const int real_size = count + 1;
|
||||||
|
|
||||||
|
points.resize(real_size);
|
||||||
|
|
||||||
|
memcpy(&points[0],controls, sizeof(Vector3) * count);
|
||||||
|
|
||||||
|
// first and last two indexes are space for special 'virtual points'
|
||||||
|
// these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
|
||||||
|
if (cyclic)
|
||||||
|
points[count] = controls[cyclic_point];
|
||||||
|
else
|
||||||
|
points[count] = controls[count-1];
|
||||||
|
|
||||||
|
index_lo = 0;
|
||||||
|
index_hi = cyclic ? count : (count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
|
||||||
|
{
|
||||||
|
const int real_size = count + (cyclic ? (1+2) : (1+1));
|
||||||
|
|
||||||
|
points.resize(real_size);
|
||||||
|
|
||||||
|
int lo_index = 1;
|
||||||
|
int high_index = lo_index + count - 1;
|
||||||
|
|
||||||
|
memcpy(&points[lo_index],controls, sizeof(Vector3) * count);
|
||||||
|
|
||||||
|
// first and last two indexes are space for special 'virtual points'
|
||||||
|
// these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
|
||||||
|
if (cyclic)
|
||||||
|
{
|
||||||
|
if (cyclic_point == 0)
|
||||||
|
points[0] = controls[count-1];
|
||||||
|
else
|
||||||
|
points[0] = controls[0].lerp(controls[1], -1);
|
||||||
|
|
||||||
|
points[high_index+1] = controls[cyclic_point];
|
||||||
|
points[high_index+2] = controls[cyclic_point+1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points[0] = controls[0].lerp(controls[1], -1);
|
||||||
|
points[high_index+1] = controls[count-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
index_lo = lo_index;
|
||||||
|
index_hi = high_index + (cyclic ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/)
|
||||||
|
{
|
||||||
|
index_type c = count / 3u * 3u;
|
||||||
|
index_type t = c / 3u;
|
||||||
|
|
||||||
|
points.resize(c);
|
||||||
|
memcpy(&points[0],controls, sizeof(Vector3) * c);
|
||||||
|
|
||||||
|
index_lo = 0;
|
||||||
|
index_hi = t-1;
|
||||||
|
//mov_assert(points.size() % 3 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::clear()
|
||||||
|
{
|
||||||
|
index_lo = 0;
|
||||||
|
index_hi = 0;
|
||||||
|
points.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SplineBase::ToString() const
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
const char * mode_str[ModesEnd] = {"Linear", "CatmullRom", "Bezier3", "Uninitialized"};
|
||||||
|
|
||||||
|
index_type count = this->points.size();
|
||||||
|
str << "mode: " << mode_str[mode()] << std::endl;
|
||||||
|
str << "points count: " << count << std::endl;
|
||||||
|
for (index_type i = 0; i < count; ++i)
|
||||||
|
str << "point " << i << " : " << points[i].toString() << std::endl;
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
212
src/game/movement/spline.h
Normal file
212
src/game/movement/spline.h
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_SPLINE_H
|
||||||
|
#define MANGOSSERVER_SPLINE_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
#include <G3D/Vector3.h>
|
||||||
|
|
||||||
|
namespace Movement {
|
||||||
|
|
||||||
|
class SplineBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int index_type;
|
||||||
|
typedef std::vector<Vector3> ControlArray;
|
||||||
|
|
||||||
|
enum EvaluationMode
|
||||||
|
{
|
||||||
|
ModeLinear,
|
||||||
|
ModeCatmullrom,
|
||||||
|
ModeBezier3_Unused,
|
||||||
|
UninitializedMode,
|
||||||
|
ModesEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma region fields
|
||||||
|
protected:
|
||||||
|
ControlArray points;
|
||||||
|
|
||||||
|
index_type index_lo;
|
||||||
|
index_type index_hi;
|
||||||
|
|
||||||
|
uint8 m_mode;
|
||||||
|
bool cyclic;
|
||||||
|
|
||||||
|
enum{
|
||||||
|
// could be modified, affects segment length evaluation precision
|
||||||
|
// lesser value saves more performance in cost of lover precision
|
||||||
|
// minimal value is 1
|
||||||
|
// client's value is 20, blizzs use 2-3 steps to compute length
|
||||||
|
STEPS_PER_SEGMENT = 3,
|
||||||
|
};
|
||||||
|
static_assert(STEPS_PER_SEGMENT > 0, "shouldn't be lesser than 1");
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void EvaluateLinear(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateCatmullRom(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateBezier3(index_type, float, Vector3&) const;
|
||||||
|
typedef void (SplineBase::*EvaluationMethtod)(index_type,float,Vector3&) const;
|
||||||
|
static EvaluationMethtod evaluators[ModesEnd];
|
||||||
|
|
||||||
|
void EvaluateDerivativeLinear(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateDerivativeCatmullRom(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateDerivativeBezier3(index_type, float, Vector3&) const;
|
||||||
|
static EvaluationMethtod derivative_evaluators[ModesEnd];
|
||||||
|
|
||||||
|
float SegLengthLinear(index_type) const;
|
||||||
|
float SegLengthCatmullRom(index_type) const;
|
||||||
|
float SegLengthBezier3(index_type) const;
|
||||||
|
typedef float (SplineBase::*SegLenghtMethtod)(index_type) const;
|
||||||
|
static SegLenghtMethtod seglengths[ModesEnd];
|
||||||
|
|
||||||
|
void InitLinear(const Vector3*, index_type, bool, index_type);
|
||||||
|
void InitCatmullRom(const Vector3*, index_type, bool, index_type);
|
||||||
|
void InitBezier3(const Vector3*, index_type, bool, index_type);
|
||||||
|
typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, bool, index_type);
|
||||||
|
static InitMethtod initializers[ModesEnd];
|
||||||
|
|
||||||
|
void UninitializedSpline() const { MANGOS_ASSERT(false);}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SplineBase() : m_mode(UninitializedMode), index_lo(0), index_hi(0), cyclic(false) {}
|
||||||
|
|
||||||
|
/** Caclulates the position for given segment Idx, and percent of segment length t
|
||||||
|
@param t - percent of segment length, assumes that t in range [0, 1]
|
||||||
|
@param Idx - spline segment index, should be in range [first, last)
|
||||||
|
*/
|
||||||
|
void evaluate_percent(index_type Idx, float u, Vector3& c) const {(this->*evaluators[m_mode])(Idx,u,c);}
|
||||||
|
|
||||||
|
/** Caclulates derivation in index Idx, and percent of segment length t
|
||||||
|
@param Idx - spline segment index, should be in range [first, last)
|
||||||
|
@param t - percent of spline segment length, assumes that t in range [0, 1]
|
||||||
|
*/
|
||||||
|
void evaluate_derivative(index_type Idx, float u, Vector3& hermite) const {(this->*derivative_evaluators[m_mode])(Idx,u,hermite);}
|
||||||
|
|
||||||
|
/** Bounds for spline indexes. All indexes should be in range [first, last). */
|
||||||
|
index_type first() const { return index_lo;}
|
||||||
|
index_type last() const { return index_hi;}
|
||||||
|
|
||||||
|
bool empty() const { return index_lo == index_hi;}
|
||||||
|
EvaluationMode mode() const { return (EvaluationMode)m_mode;}
|
||||||
|
bool isCyclic() const { return cyclic;}
|
||||||
|
|
||||||
|
const ControlArray& getPoints() const { return points;}
|
||||||
|
index_type getPointCount() const { return points.size();}
|
||||||
|
const Vector3& getPoint(index_type i) const { return points[i];}
|
||||||
|
|
||||||
|
/** Initializes spline. Don't call other methods while spline not initialized. */
|
||||||
|
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m);
|
||||||
|
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point);
|
||||||
|
|
||||||
|
/** As i can see there are a lot of ways how spline can be initialized
|
||||||
|
would be no harm to have some custom initializers. */
|
||||||
|
template<class Init> inline void init_spline(Init& initializer)
|
||||||
|
{
|
||||||
|
initializer(m_mode,cyclic,points,index_lo,index_hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/** Calculates distance between [i; i+1] points, assumes that index i is in bounds. */
|
||||||
|
float SegLength(index_type i) const { return (this->*seglengths[m_mode])(i);}
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename length_type>
|
||||||
|
class Spline : public SplineBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef length_type LengthType;
|
||||||
|
typedef std::vector<length_type> LengthArray;
|
||||||
|
#pragma region fields
|
||||||
|
protected:
|
||||||
|
|
||||||
|
LengthArray lengths;
|
||||||
|
|
||||||
|
index_type computeIndexInBounds(length_type length) const;
|
||||||
|
#pragma endregion
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Spline(){}
|
||||||
|
|
||||||
|
/** Calculates the position for given t
|
||||||
|
@param t - percent of spline's length, assumes that t in range [0, 1]. */
|
||||||
|
void evaluate_percent(float t, Vector3 & c) const;
|
||||||
|
|
||||||
|
/** Calculates derivation for given t
|
||||||
|
@param t - percent of spline's length, assumes that t in range [0, 1]. */
|
||||||
|
void evaluate_derivative(float t, Vector3& hermite) const;
|
||||||
|
|
||||||
|
/** Calculates the position for given segment Idx, and percent of segment length t
|
||||||
|
@param t = partial_segment_length / whole_segment_length
|
||||||
|
@param Idx - spline segment index, should be in range [first, last). */
|
||||||
|
void evaluate_percent(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_percent(Idx,u,c);}
|
||||||
|
|
||||||
|
/** Caclulates derivation for index Idx, and percent of segment length t
|
||||||
|
@param Idx - spline segment index, should be in range [first, last)
|
||||||
|
@param t - percent of spline segment length, assumes that t in range [0, 1]. */
|
||||||
|
void evaluate_derivative(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_derivative(Idx,u,c);}
|
||||||
|
|
||||||
|
// Assumes that t in range [0, 1]
|
||||||
|
index_type computeIndexInBounds(float t) const;
|
||||||
|
void computeIndex(float t, index_type& out_idx, float& out_u) const;
|
||||||
|
|
||||||
|
/** Initializes spline. Don't call other methods while spline not initialized. */
|
||||||
|
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m) { SplineBase::init_spline(controls,count,m);}
|
||||||
|
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point) { SplineBase::init_cyclic_spline(controls,count,m,cyclic_point);}
|
||||||
|
|
||||||
|
/** Initializes lengths with SplineBase::SegLength method. */
|
||||||
|
void initLengths();
|
||||||
|
|
||||||
|
/** Initializes lengths in some custom way
|
||||||
|
Note that value returned by cacher must be greater or equal to previous value. */
|
||||||
|
template<class T> inline void initLengths(T& cacher)
|
||||||
|
{
|
||||||
|
index_type i = index_lo;
|
||||||
|
lengths.resize(index_hi+1);
|
||||||
|
length_type prev_length = 0, new_length = 0;
|
||||||
|
while(i < index_hi)
|
||||||
|
{
|
||||||
|
new_length = cacher(*this, i);
|
||||||
|
lengths[++i] = new_length;
|
||||||
|
|
||||||
|
MANGOS_ASSERT(prev_length <= new_length);
|
||||||
|
prev_length = new_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns length of the whole spline. */
|
||||||
|
length_type length() const { return lengths[index_hi];}
|
||||||
|
/** Returns length between given nodes. */
|
||||||
|
length_type length(index_type first, index_type last) const { return lengths[last]-lengths[first];}
|
||||||
|
length_type length(index_type Idx) const { return lengths[Idx];}
|
||||||
|
|
||||||
|
void set_length(index_type i, length_type length) { lengths[i] = length;}
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spline.impl.h"
|
||||||
|
|
||||||
|
#endif // MANGOSSERVER_SPLINE_H
|
||||||
97
src/game/movement/spline.impl.h
Normal file
97
src/game/movement/spline.impl.h
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
template<typename length_type> void Spline<length_type>::evaluate_percent( float t, Vector3 & c ) const
|
||||||
|
{
|
||||||
|
index_type Index;
|
||||||
|
float u;
|
||||||
|
computeIndex(t, Index, u);
|
||||||
|
evaluate_percent(Index, u, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::evaluate_derivative(float t, Vector3& hermite) const
|
||||||
|
{
|
||||||
|
index_type Index;
|
||||||
|
float u;
|
||||||
|
computeIndex(t, Index, u);
|
||||||
|
evaluate_derivative(Index, u, hermite);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds(length_type length_) const
|
||||||
|
{
|
||||||
|
// Temporary disabled: causes infinite loop with t = 1.f
|
||||||
|
/*
|
||||||
|
index_type hi = index_hi;
|
||||||
|
index_type lo = index_lo;
|
||||||
|
|
||||||
|
index_type i = lo + (float)(hi - lo) * t;
|
||||||
|
|
||||||
|
while ((lengths[i] > length) || (lengths[i + 1] <= length))
|
||||||
|
{
|
||||||
|
if (lengths[i] > length)
|
||||||
|
hi = i - 1; // too big
|
||||||
|
else if (lengths[i + 1] <= length)
|
||||||
|
lo = i + 1; // too small
|
||||||
|
|
||||||
|
i = (hi + lo) / 2;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
index_type i = index_lo;
|
||||||
|
index_type N = index_hi;
|
||||||
|
while (i+1 < N && lengths[i+1] < length_)
|
||||||
|
++i;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::computeIndex(float t, index_type& index, float& u) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(t >= 0.f && t <= 1.f);
|
||||||
|
length_type length_ = t * length();
|
||||||
|
index = computeIndexInBounds(length_);
|
||||||
|
MANGOS_ASSERT(index < index_hi);
|
||||||
|
u = (length_ - length(index)) / (float)length(index, index+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds( float t ) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(t >= 0.f && t <= 1.f);
|
||||||
|
return computeIndexInBounds(t * length());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::initLengths()
|
||||||
|
{
|
||||||
|
index_type i = index_lo;
|
||||||
|
length_type length = 0;
|
||||||
|
lengths.resize(index_hi+1);
|
||||||
|
while(i < index_hi )
|
||||||
|
{
|
||||||
|
length += SegLength(i);
|
||||||
|
lengths[++i] = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::clear()
|
||||||
|
{
|
||||||
|
SplineBase::clear();
|
||||||
|
lengths.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
78
src/game/movement/typedefs.h
Normal file
78
src/game/movement/typedefs.h
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANGOSSERVER_TYPEDEFS_H
|
||||||
|
#define MANGOSSERVER_TYPEDEFS_H
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
namespace G3D
|
||||||
|
{
|
||||||
|
class Vector2;
|
||||||
|
class Vector3;
|
||||||
|
class Vector4;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
using G3D::Vector2;
|
||||||
|
using G3D::Vector3;
|
||||||
|
using G3D::Vector4;
|
||||||
|
|
||||||
|
inline uint32 SecToMS(float sec)
|
||||||
|
{
|
||||||
|
return static_cast<uint32>(sec * 1000.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float MSToSec(uint32 ms)
|
||||||
|
{
|
||||||
|
return ms / 1000.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef static_assert
|
||||||
|
#define CONCAT(x, y) CONCAT1 (x, y)
|
||||||
|
#define CONCAT1(x, y) x##y
|
||||||
|
#define static_assert(expr, msg) typedef char CONCAT(static_assert_failed_at_line_, __LINE__) [(expr) ? 1 : -1]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class T, T limit>
|
||||||
|
class counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
counter() { init();}
|
||||||
|
|
||||||
|
void Increase()
|
||||||
|
{
|
||||||
|
if (m_counter == limit)
|
||||||
|
init();
|
||||||
|
else
|
||||||
|
++m_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
T NewId() { Increase(); return m_counter;}
|
||||||
|
T getCurrent() const { return m_counter;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init() { m_counter = 0; }
|
||||||
|
T m_counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef counter<uint32, 0xFFFFFFFF> UInt32Counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MANGOSSERVER_TYPEDEFS_H
|
||||||
208
src/game/movement/util.cpp
Normal file
208
src/game/movement/util.cpp
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* 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 "MoveSplineFlag.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Movement
|
||||||
|
{
|
||||||
|
double gravity = 19.29110527038574;
|
||||||
|
|
||||||
|
/// Velocity bounds that makes fall speed limited
|
||||||
|
float terminalVelocity = 60.148003f;
|
||||||
|
float terminalSavefallVelocity = 7.f;
|
||||||
|
|
||||||
|
const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.f * gravity);
|
||||||
|
const float terminal_savefall_length = (terminalSavefallVelocity * terminalSavefallVelocity) / (2.f * gravity);
|
||||||
|
const float terminalFallTime = float(terminalVelocity/gravity); // the time that needed to reach terminalVelocity
|
||||||
|
|
||||||
|
float computeFallTime(float path_length, bool isSafeFall)
|
||||||
|
{
|
||||||
|
if (path_length < 0.f)
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
float time;
|
||||||
|
if ( isSafeFall )
|
||||||
|
{
|
||||||
|
if (path_length >= terminal_savefall_length)
|
||||||
|
time = (path_length - terminal_savefall_length)/terminalSavefallVelocity + terminalSavefallVelocity/gravity;
|
||||||
|
else
|
||||||
|
time = sqrtf(2.f * path_length/gravity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (path_length >= terminal_length)
|
||||||
|
time = (path_length - terminal_length)/terminalVelocity + terminalFallTime;
|
||||||
|
else
|
||||||
|
time = sqrtf(2.f * path_length/gravity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity)
|
||||||
|
{
|
||||||
|
float termVel;
|
||||||
|
float result;
|
||||||
|
|
||||||
|
if ( isSafeFall )
|
||||||
|
termVel = terminalSavefallVelocity;
|
||||||
|
else
|
||||||
|
termVel = terminalVelocity;
|
||||||
|
|
||||||
|
if ( start_velocity > termVel )
|
||||||
|
start_velocity = termVel;
|
||||||
|
|
||||||
|
float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity
|
||||||
|
|
||||||
|
if ( t_passed > terminal_time )
|
||||||
|
{
|
||||||
|
result = terminalVelocity*(t_passed - terminal_time) +
|
||||||
|
start_velocity*terminal_time + gravity*terminal_time*terminal_time*0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = t_passed * (start_velocity + t_passed * gravity * 0.5f);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float computeFallElevation(float t_passed)
|
||||||
|
{
|
||||||
|
float result;
|
||||||
|
|
||||||
|
if (t_passed > terminalFallTime)
|
||||||
|
{
|
||||||
|
//result = terminalVelocity * (t_passed - terminal_time) + gravity*terminal_time*terminal_time*0.5f;
|
||||||
|
// simplified view:
|
||||||
|
result = terminalVelocity * (t_passed - terminalFallTime) + terminal_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = t_passed * t_passed * gravity * 0.5f;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STR(x) #x
|
||||||
|
|
||||||
|
const char * g_MovementFlag_names[]=
|
||||||
|
{
|
||||||
|
STR(Forward ),// 0x00000001,
|
||||||
|
STR(Backward ),// 0x00000002,
|
||||||
|
STR(Strafe_Left ),// 0x00000004,
|
||||||
|
STR(Strafe_Right ),// 0x00000008,
|
||||||
|
STR(Turn_Left ),// 0x00000010,
|
||||||
|
STR(Turn_Right ),// 0x00000020,
|
||||||
|
STR(Pitch_Up ),// 0x00000040,
|
||||||
|
STR(Pitch_Down ),// 0x00000080,
|
||||||
|
|
||||||
|
STR(Walk ),// 0x00000100, // Walking
|
||||||
|
STR(Ontransport ),// 0x00000200,
|
||||||
|
STR(Levitation ),// 0x00000400,
|
||||||
|
STR(Root ),// 0x00000800,
|
||||||
|
STR(Falling ),// 0x00001000,
|
||||||
|
STR(Fallingfar ),// 0x00002000,
|
||||||
|
STR(Pendingstop ),// 0x00004000,
|
||||||
|
STR(PendingSTRafestop ),// 0x00008000,
|
||||||
|
STR(Pendingforward ),// 0x00010000,
|
||||||
|
STR(Pendingbackward ),// 0x00020000,
|
||||||
|
STR(PendingSTRafeleft ),// 0x00040000,
|
||||||
|
STR(PendingSTRaferight ),// 0x00080000,
|
||||||
|
STR(Pendingroot ),// 0x00100000,
|
||||||
|
STR(Swimming ),// 0x00200000, // Appears With Fly Flag Also
|
||||||
|
STR(Ascending ),// 0x00400000, // Swim Up Also
|
||||||
|
STR(Descending ),// 0x00800000, // Swim Down Also
|
||||||
|
STR(Can_Fly ),// 0x01000000, // Can Fly In 3.3?
|
||||||
|
STR(Flying ),// 0x02000000, // Actual Flying Mode
|
||||||
|
STR(Spline_Elevation ),// 0x04000000, // Used For Flight Paths
|
||||||
|
STR(Spline_Enabled ),// 0x08000000, // Used For Flight Paths
|
||||||
|
STR(Waterwalking ),// 0x10000000, // Prevent Unit From Falling Through Water
|
||||||
|
STR(Safe_Fall ),// 0x20000000, // Active Rogue Safe Fall Spell (Passive)
|
||||||
|
STR(Hover ),// 0x40000000
|
||||||
|
STR(Unknown13 ),// 0x80000000
|
||||||
|
STR(Unk1 ),
|
||||||
|
STR(Unk2 ),
|
||||||
|
STR(Unk3 ),
|
||||||
|
STR(Fullspeedturning ),
|
||||||
|
STR(Fullspeedpitching ),
|
||||||
|
STR(Allow_Pitching ),
|
||||||
|
STR(Unk4 ),
|
||||||
|
STR(Unk5 ),
|
||||||
|
STR(Unk6 ),
|
||||||
|
STR(Unk7 ),
|
||||||
|
STR(Interp_Move ),
|
||||||
|
STR(Interp_Turning ),
|
||||||
|
STR(Interp_Pitching ),
|
||||||
|
STR(Unk8 ),
|
||||||
|
STR(Unk9 ),
|
||||||
|
STR(Unk10 ),
|
||||||
|
};
|
||||||
|
|
||||||
|
const char * g_SplineFlag_names[32]=
|
||||||
|
{
|
||||||
|
STR(Forward ),// 0x00000001,
|
||||||
|
STR(Backward ),// 0x00000002,
|
||||||
|
STR(Strafe_Left ),// 0x00000004,
|
||||||
|
STR(Strafe_Right ),// 0x00000008,
|
||||||
|
STR(Left ),// 0x00000010,
|
||||||
|
STR(Right ),// 0x00000020,
|
||||||
|
STR(Pitch_Up ),// 0x00000040,
|
||||||
|
STR(Pitch_Down ),// 0x00000080,
|
||||||
|
STR(Done ),// 0x00000100,
|
||||||
|
STR(Falling ),// 0x00000200, // Not Compartible With Trajectory Movement
|
||||||
|
STR(No_Spline ),// 0x00000400,
|
||||||
|
STR(Trajectory ),// 0x00000800, // Not Compartible With Fall Movement
|
||||||
|
STR(Walkmode ),// 0x00001000,
|
||||||
|
STR(Flying ),// 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
|
||||||
|
STR(Knockback ),// 0x00004000, // Model Orientation Fixed
|
||||||
|
STR(Final_Point ),// 0x00008000,
|
||||||
|
STR(Final_Target ),// 0x00010000,
|
||||||
|
STR(Final_Angle ),// 0x00020000,
|
||||||
|
STR(Catmullrom ),// 0x00040000, // Used Catmullrom Interpolation Mode
|
||||||
|
STR(Cyclic ),// 0x00080000, // Movement By Cycled Spline
|
||||||
|
STR(Enter_Cycle ),// 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet
|
||||||
|
STR(Animation ),// 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
|
||||||
|
STR(Unknown4 ),// 0x00400000, // Disables Movement By Path
|
||||||
|
STR(Unknown5 ),// 0x00800000,
|
||||||
|
STR(Unknown6 ),// 0x01000000,
|
||||||
|
STR(Unknown7 ),// 0x02000000,
|
||||||
|
STR(Unknown8 ),// 0x04000000,
|
||||||
|
STR(Backward ),// 0x08000000, // Appears With Walkmode Flag, Nodes ),// 1, Handles Orientation
|
||||||
|
STR(Unknown10 ),// 0x10000000,
|
||||||
|
STR(Unknown11 ),// 0x20000000,
|
||||||
|
STR(Unknown12 ),// 0x40000000,
|
||||||
|
STR(Unknown13 ),// 0x80000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Flags, int N>
|
||||||
|
void print_flags(Flags t, const char* (&names)[N], std::string& str)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
if ((t & (Flags)(1 << i)) && names[i] != NULL)
|
||||||
|
str.append(" ").append(names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MoveSplineFlag::ToString() const
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
print_flags(raw(),g_SplineFlag_names,str);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -132,7 +132,7 @@ struct TimeTracker
|
||||||
struct ShortTimeTracker
|
struct ShortTimeTracker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShortTimeTracker(int32 expiry) : i_expiryTime(expiry) {}
|
ShortTimeTracker(int32 expiry = 0) : i_expiryTime(expiry) {}
|
||||||
void Update(int32 diff) { i_expiryTime -= diff; }
|
void Update(int32 diff) { i_expiryTime -= diff; }
|
||||||
bool Passed() const { return (i_expiryTime <= 0); }
|
bool Passed() const { return (i_expiryTime <= 0); }
|
||||||
void Reset(int32 interval) { i_expiryTime = interval; }
|
void Reset(int32 interval) { i_expiryTime = interval; }
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "11718"
|
#define REVISION_NR "11720"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
|
|
@ -399,7 +399,6 @@
|
||||||
<ClCompile Include="..\..\src\game\CreatureEventAIMgr.cpp" />
|
<ClCompile Include="..\..\src\game\CreatureEventAIMgr.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\DBCStores.cpp" />
|
<ClCompile Include="..\..\src\game\DBCStores.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\debugcmds.cpp" />
|
<ClCompile Include="..\..\src\game\debugcmds.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\DestinationHolder.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\game\DuelHandler.cpp" />
|
<ClCompile Include="..\..\src\game\DuelHandler.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\DynamicObject.cpp" />
|
<ClCompile Include="..\..\src\game\DynamicObject.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\FleeingMovementGenerator.cpp" />
|
<ClCompile Include="..\..\src\game\FleeingMovementGenerator.cpp" />
|
||||||
|
|
@ -443,6 +442,11 @@
|
||||||
<ClCompile Include="..\..\src\game\MotionMaster.cpp" />
|
<ClCompile Include="..\..\src\game\MotionMaster.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\MovementGenerator.cpp" />
|
<ClCompile Include="..\..\src\game\MovementGenerator.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\MovementHandler.cpp" />
|
<ClCompile Include="..\..\src\game\MovementHandler.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\game\movement\MoveSpline.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\game\movement\MoveSplineInit.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\game\movement\packet_builder.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\game\movement\spline.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\game\movement\util.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\NPCHandler.cpp" />
|
<ClCompile Include="..\..\src\game\NPCHandler.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\NullCreatureAI.cpp" />
|
<ClCompile Include="..\..\src\game\NullCreatureAI.cpp" />
|
||||||
<ClCompile Include="..\..\src\game\Object.cpp" />
|
<ClCompile Include="..\..\src\game\Object.cpp" />
|
||||||
|
|
@ -559,8 +563,6 @@
|
||||||
<ClInclude Include="..\..\src\game\DBCfmt.h" />
|
<ClInclude Include="..\..\src\game\DBCfmt.h" />
|
||||||
<ClInclude Include="..\..\src\game\DBCStores.h" />
|
<ClInclude Include="..\..\src\game\DBCStores.h" />
|
||||||
<ClInclude Include="..\..\src\game\DBCStructure.h" />
|
<ClInclude Include="..\..\src\game\DBCStructure.h" />
|
||||||
<ClInclude Include="..\..\src\game\DestinationHolder.h" />
|
|
||||||
<ClInclude Include="..\..\src\game\DestinationHolderImp.h" />
|
|
||||||
<ClInclude Include="..\..\src\game\DynamicObject.h" />
|
<ClInclude Include="..\..\src\game\DynamicObject.h" />
|
||||||
<ClInclude Include="..\..\src\game\FleeingMovementGenerator.h" />
|
<ClInclude Include="..\..\src\game\FleeingMovementGenerator.h" />
|
||||||
<ClInclude Include="..\..\src\game\FollowerReference.h" />
|
<ClInclude Include="..\..\src\game\FollowerReference.h" />
|
||||||
|
|
@ -599,6 +601,14 @@
|
||||||
<ClInclude Include="..\..\src\game\MassMailMgr.h" />
|
<ClInclude Include="..\..\src\game\MassMailMgr.h" />
|
||||||
<ClInclude Include="..\..\src\game\MotionMaster.h" />
|
<ClInclude Include="..\..\src\game\MotionMaster.h" />
|
||||||
<ClInclude Include="..\..\src\game\MovementGenerator.h" />
|
<ClInclude Include="..\..\src\game\MovementGenerator.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSpline.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSplineFlag.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSplineInit.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSplineInitArgs.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\packet_builder.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\spline.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\spline.impl.h" />
|
||||||
|
<ClInclude Include="..\..\src\game\movement\typedefs.h" />
|
||||||
<ClInclude Include="..\..\src\game\NPCHandler.h" />
|
<ClInclude Include="..\..\src\game\NPCHandler.h" />
|
||||||
<ClInclude Include="..\..\src\game\NullCreatureAI.h" />
|
<ClInclude Include="..\..\src\game\NullCreatureAI.h" />
|
||||||
<ClInclude Include="..\..\src\game\Object.h" />
|
<ClInclude Include="..\..\src\game\Object.h" />
|
||||||
|
|
@ -636,7 +646,6 @@
|
||||||
<ClInclude Include="..\..\src\game\Totem.h" />
|
<ClInclude Include="..\..\src\game\Totem.h" />
|
||||||
<ClInclude Include="..\..\src\game\TotemAI.h" />
|
<ClInclude Include="..\..\src\game\TotemAI.h" />
|
||||||
<ClInclude Include="..\..\src\game\Transports.h" />
|
<ClInclude Include="..\..\src\game\Transports.h" />
|
||||||
<ClInclude Include="..\..\src\game\Traveller.h" />
|
|
||||||
<ClInclude Include="..\..\src\game\Unit.h" />
|
<ClInclude Include="..\..\src\game\Unit.h" />
|
||||||
<ClInclude Include="..\..\src\game\UnitEvents.h" />
|
<ClInclude Include="..\..\src\game\UnitEvents.h" />
|
||||||
<ClInclude Include="..\..\src\game\UpdateData.h" />
|
<ClInclude Include="..\..\src\game\UpdateData.h" />
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@
|
||||||
<Filter Include="vmaps">
|
<Filter Include="vmaps">
|
||||||
<UniqueIdentifier>{948284d3-9d89-4609-8cdd-28a213edb53e}</UniqueIdentifier>
|
<UniqueIdentifier>{948284d3-9d89-4609-8cdd-28a213edb53e}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Movement">
|
||||||
|
<UniqueIdentifier>{0ac140f9-89c1-4830-b673-514c5e8b4d37}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\game\AccountMgr.cpp">
|
<ClCompile Include="..\..\src\game\AccountMgr.cpp">
|
||||||
|
|
@ -255,9 +258,6 @@
|
||||||
<ClCompile Include="..\..\src\game\ConfusedMovementGenerator.cpp">
|
<ClCompile Include="..\..\src\game\ConfusedMovementGenerator.cpp">
|
||||||
<Filter>Motion generators</Filter>
|
<Filter>Motion generators</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\game\DestinationHolder.cpp">
|
|
||||||
<Filter>Motion generators</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\src\game\FleeingMovementGenerator.cpp">
|
<ClCompile Include="..\..\src\game\FleeingMovementGenerator.cpp">
|
||||||
<Filter>Motion generators</Filter>
|
<Filter>Motion generators</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -481,6 +481,21 @@
|
||||||
<ClCompile Include="..\..\src\game\vmap\WorldModel.cpp">
|
<ClCompile Include="..\..\src\game\vmap\WorldModel.cpp">
|
||||||
<Filter>vmaps</Filter>
|
<Filter>vmaps</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\game\movement\MoveSplineInit.cpp">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\game\movement\packet_builder.cpp">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\game\movement\spline.cpp">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\game\movement\util.cpp">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\game\movement\MoveSpline.cpp">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\game\AccountMgr.h">
|
<ClInclude Include="..\..\src\game\AccountMgr.h">
|
||||||
|
|
@ -645,12 +660,6 @@
|
||||||
<ClInclude Include="..\..\src\game\ConfusedMovementGenerator.h">
|
<ClInclude Include="..\..\src\game\ConfusedMovementGenerator.h">
|
||||||
<Filter>Motion generators</Filter>
|
<Filter>Motion generators</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\game\DestinationHolder.h">
|
|
||||||
<Filter>Motion generators</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\game\DestinationHolderImp.h">
|
|
||||||
<Filter>Motion generators</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\game\FleeingMovementGenerator.h">
|
<ClInclude Include="..\..\src\game\FleeingMovementGenerator.h">
|
||||||
<Filter>Motion generators</Filter>
|
<Filter>Motion generators</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -675,9 +684,6 @@
|
||||||
<ClInclude Include="..\..\src\game\TargetedMovementGenerator.h">
|
<ClInclude Include="..\..\src\game\TargetedMovementGenerator.h">
|
||||||
<Filter>Motion generators</Filter>
|
<Filter>Motion generators</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\game\Traveller.h">
|
|
||||||
<Filter>Motion generators</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\game\WaypointMovementGenerator.h">
|
<ClInclude Include="..\..\src\game\WaypointMovementGenerator.h">
|
||||||
<Filter>Motion generators</Filter>
|
<Filter>Motion generators</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -910,5 +916,29 @@
|
||||||
<ClInclude Include="..\..\src\game\vmap\WorldModel.h">
|
<ClInclude Include="..\..\src\game\vmap\WorldModel.h">
|
||||||
<Filter>vmaps</Filter>
|
<Filter>vmaps</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSpline.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSplineFlag.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSplineInit.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\MoveSplineInitArgs.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\packet_builder.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\spline.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\spline.impl.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\game\movement\typedefs.h">
|
||||||
|
<Filter>Movement</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1053,18 +1053,6 @@
|
||||||
RelativePath="..\..\src\game\ConfusedMovementGenerator.h"
|
RelativePath="..\..\src\game\ConfusedMovementGenerator.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\DestinationHolder.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\DestinationHolder.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\DestinationHolderImp.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
||||||
>
|
>
|
||||||
|
|
@ -1129,10 +1117,6 @@
|
||||||
RelativePath="..\..\src\game\TargetedMovementGenerator.h"
|
RelativePath="..\..\src\game\TargetedMovementGenerator.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\Traveller.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\WaypointMovementGenerator.cpp"
|
RelativePath="..\..\src\game\WaypointMovementGenerator.cpp"
|
||||||
>
|
>
|
||||||
|
|
@ -1717,6 +1701,62 @@
|
||||||
RelativePath="..\..\src\game\vmap\WorldModel.h"
|
RelativePath="..\..\src\game\vmap\WorldModel.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Movement"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSpline.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSpline.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineFlag.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineInit.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineInit.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineInitArgs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\packet_builder.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\packet_builder.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\spline.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\spline.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\spline.impl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\typedefs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\movement\util.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\pchdef.cpp"
|
RelativePath="..\..\src\game\pchdef.cpp"
|
||||||
|
|
|
||||||
|
|
@ -1046,18 +1046,6 @@
|
||||||
RelativePath="..\..\src\game\ConfusedMovementGenerator.h"
|
RelativePath="..\..\src\game\ConfusedMovementGenerator.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\DestinationHolder.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\DestinationHolder.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\DestinationHolderImp.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
||||||
>
|
>
|
||||||
|
|
@ -1122,10 +1110,6 @@
|
||||||
RelativePath="..\..\src\game\TargetedMovementGenerator.h"
|
RelativePath="..\..\src\game\TargetedMovementGenerator.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\game\Traveller.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\WaypointMovementGenerator.cpp"
|
RelativePath="..\..\src\game\WaypointMovementGenerator.cpp"
|
||||||
>
|
>
|
||||||
|
|
@ -1719,6 +1703,62 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Movement"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSpline.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSpline.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineFlag.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineInit.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineInit.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\MoveSplineInitArgs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\packet_builder.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\packet_builder.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\spline.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\spline.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\spline.impl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\Movement\typedefs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\movement\util.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\pchdef.cpp"
|
RelativePath="..\..\src\game\pchdef.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue