aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMachiavelli <machiavelli.trinity@gmail.com>2012-01-14 15:34:41 +0100
committerMachiavelli <machiavelli.trinity@gmail.com>2012-01-14 15:36:07 +0100
commitdbbac0bdaae4b6d8a0125999962c4a686092bd80 (patch)
tree8962da6db594ae27fc5ac5e6a930b6292a997ea6
parent798677ca54553a9da688deef7b7c33ccbc17b801 (diff)
Core/Movement: 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: * Added linear, catmullrom and bezier3 splines which based on client's algorthims. They can be reused for proper transport position interpolation. * Precission increased. There are no more position desync issues since client's position calculation formulas used. * Now possible to move by paths with multiple points, send whole path to client. -- Original author of research and implementation: SilverIce. Massive kudos. Original port for Trinity (ref #4629) Chaplain and Venugh With the following incremental fixes during my review: - Restore flightmaster end grid pre-loading - Fix uninitialized Creature::m_path_id - Add missing trinity_string entries for .movegens command - Fix a bug in WaypointMovementGenerator that would trigger unexpected pausing at waypoints for various amounts of time Known issues: - Errors like WaypointMovementGenerator::LoadPath creature XXX (Entry: YYYYY GUID: ZZZZZZ) doesn't have waypoint path id: 0. This is caused by bad DB data. This commit didn't "break" it. Do not forget to re-run CMake before compiling.
-rw-r--r--sql/updates/world/2011_01_14_03_world_trinity_string.sql6
-rwxr-xr-xsrc/server/game/AI/CoreAI/GuardAI.cpp4
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp9
-rwxr-xr-xsrc/server/game/AI/EventAI/CreatureEventAI.cpp5
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp3
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp6
-rw-r--r--src/server/game/CMakeLists.txt2
-rwxr-xr-xsrc/server/game/Chat/Commands/Level3.cpp61
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp72
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h4
-rwxr-xr-xsrc/server/game/Entities/Creature/CreatureGroups.cpp4
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp2
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp139
-rwxr-xr-xsrc/server/game/Entities/Object/Object.h3
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp38
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h1
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp252
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h126
-rwxr-xr-xsrc/server/game/Maps/Map.cpp18
-rwxr-xr-xsrc/server/game/Maps/Map.h2
-rwxr-xr-xsrc/server/game/Maps/MapManager.cpp1
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h12
-rwxr-xr-xsrc/server/game/Movement/DestinationHolder.cpp20
-rwxr-xr-xsrc/server/game/Movement/DestinationHolder.h65
-rwxr-xr-xsrc/server/game/Movement/DestinationHolderImp.h215
-rwxr-xr-xsrc/server/game/Movement/MotionMaster.cpp160
-rwxr-xr-xsrc/server/game/Movement/MotionMaster.h15
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.cpp1
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp124
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h13
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp123
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h7
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp57
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/HomeMovementGenerator.h12
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp104
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.h30
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp188
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/RandomMovementGenerator.h12
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp357
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h92
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp416
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h90
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp316
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.h127
-rw-r--r--src/server/game/Movement/Spline/MoveSplineFlag.h143
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.cpp119
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.h170
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInitArgs.h67
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.cpp188
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.h37
-rw-r--r--src/server/game/Movement/Spline/MovementTypedefs.h81
-rw-r--r--src/server/game/Movement/Spline/MovementUtil.cpp208
-rw-r--r--src/server/game/Movement/Spline/Spline.cpp307
-rw-r--r--src/server/game/Movement/Spline/Spline.h212
-rw-r--r--src/server/game/Movement/Spline/SplineImpl.h97
-rwxr-xr-xsrc/server/game/Movement/Traveller.h152
-rwxr-xr-xsrc/server/game/Scripting/MapScripts.cpp10
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/TaxiHandler.cpp1
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp6
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp17
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp5
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/undercity.cpp4
-rwxr-xr-xsrc/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp6
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp2
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp20
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp2
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp27
-rw-r--r--src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp2
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_illidan.cpp2
-rw-r--r--src/server/scripts/Outland/GruulsLair/boss_gruul.cpp2
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp4
-rw-r--r--src/server/scripts/World/guards.cpp2
-rwxr-xr-xsrc/server/shared/Utilities/Timer.h2
84 files changed, 3325 insertions, 1912 deletions
diff --git a/sql/updates/world/2011_01_14_03_world_trinity_string.sql b/sql/updates/world/2011_01_14_03_world_trinity_string.sql
new file mode 100644
index 00000000000..7dab007f774
--- /dev/null
+++ b/sql/updates/world/2011_01_14_03_world_trinity_string.sql
@@ -0,0 +1,6 @@
+DELETE FROM `trinity_string` WHERE `entry` IN(1139,1140,1141,1142);
+INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES
+(1139,' Follow player %s (lowguid %u)'),
+(1140,' Follow creature %s (lowguid %u)'),
+(1141,' Follow <NULL>'),
+(1142,' Effect movement');
diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp
index 54061274408..b78fec7c142 100755
--- a/src/server/game/AI/CoreAI/GuardAI.cpp
+++ b/src/server/game/AI/CoreAI/GuardAI.cpp
@@ -115,8 +115,8 @@ void GuardAI::EnterEvadeMode()
me->CombatStop(true);
i_state = STATE_NORMAL;
- // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ // Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveTargetedHome();
}
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 60151e4865a..015e20415b1 100755
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -417,10 +417,9 @@ void PetAI::MovementInform(uint32 moveType, uint32 data)
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
}
+ break;
}
- break;
-
- case TARGETED_MOTION_TYPE:
+ case FOLLOW_MOTION_TYPE:
{
// If data is owner's GUIDLow then we've reached follow point,
// otherwise we're probably chasing a creature
@@ -430,11 +429,9 @@ void PetAI::MovementInform(uint32 moveType, uint32 data)
me->GetCharmInfo()->SetIsReturning(false);
me->GetCharmInfo()->SetIsFollowing(true);
me->GetCharmInfo()->SetIsCommandAttack(false);
- me->AddUnitState(UNIT_STAT_FOLLOW);
}
+ break;
}
- break;
-
default:
break;
}
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp
index c7590ebb512..c507262bd3f 100755
--- a/src/server/game/AI/EventAI/CreatureEventAI.cpp
+++ b/src/server/game/AI/EventAI/CreatureEventAI.cpp
@@ -475,7 +475,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
//Melee current victim if flag not set
if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM))
{
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
{
m_AttackDistance = 0.0f;
m_AttackAngle = 0.0f;
@@ -483,7 +483,6 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle);
}
}
-
}
else
{
@@ -595,7 +594,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
me->ClearUnitState(UNIT_STAT_MELEE_ATTACKING);
me->SendMeleeAttackStop(victim);
}
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveIdle();
}
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index e3518cb6921..1b6fde6d132 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -298,7 +298,8 @@ void ScriptedAI::DoModifyThreatPercent(Unit* unit, int32 pct)
void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time)
{
me->Relocate(x, y, z);
- me->SendMonsterMove(x, y, z, time);
+ float speed = me->GetDistance(x, y, z) / ((float)time * 0.001f);
+ me->MonsterMoveWithSpeed(x, y, z, speed);
}
void ScriptedAI::DoTeleportTo(const float position[4])
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index 1e0b212dd45..53747d0c799 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -167,7 +167,7 @@ void FollowerAI::EnterEvadeMode()
{
sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI left combat, returning to CombatStartPosition.");
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
{
float fPosX, fPosY, fPosZ;
me->GetPosition(fPosX, fPosY, fPosZ);
@@ -176,7 +176,7 @@ void FollowerAI::EnterEvadeMode()
}
else
{
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveTargetedHome();
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 9cea61c0d2b..4328eafc962 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1273,11 +1273,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
ObjectList* targets = GetTargets(e, unit);
if (e.GetTargetType() == SMART_TARGET_SELF)
- me->SetFacing(me->GetHomePosition().GetOrientation(), NULL);
+ me->SetFacingTo(me->GetHomePosition().GetOrientation());
else if (e.GetTargetType() == SMART_TARGET_POSITION)
- me->SetFacing(e.target.o, NULL);
+ me->SetFacingTo(e.target.o);
else if (targets && !targets->empty())
- me->SetFacing(0, (*targets->begin()));
+ me->SetFacingToObject(*targets->begin());
delete targets;
break;
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 117a8f680ee..658e9a15cc8 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -102,6 +102,7 @@ set(game_STAT_SRCS
include_directories(
${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/mersennetwister
${CMAKE_SOURCE_DIR}/dep/SFMT
${CMAKE_SOURCE_DIR}/dep/zlib
@@ -170,6 +171,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Maps
${CMAKE_CURRENT_SOURCE_DIR}/Miscellaneous
${CMAKE_CURRENT_SOURCE_DIR}/Movement
+ ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Spline
${CMAKE_CURRENT_SOURCE_DIR}/Movement/MovementGenerators
${CMAKE_CURRENT_SOURCE_DIR}/Movement/Waypoints
${CMAKE_CURRENT_SOURCE_DIR}/OutdoorPvP
diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp
index d23a429471f..cb3eb825354 100755
--- a/src/server/game/Chat/Commands/Level3.cpp
+++ b/src/server/game/Chat/Commands/Level3.cpp
@@ -3692,6 +3692,9 @@ bool ChatHandler::HandleMovegensCommand(const char* /*args*/)
PSendSysMessage(LANG_MOVEGENS_LIST, (unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), unit->GetGUIDLow());
MotionMaster* mm = unit->GetMotionMaster();
+ float x,y,z;
+ mm->GetDestination(x,y,z);
+
for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i)
{
MovementGenerator* mg = mm->GetMotionSlot(i);
@@ -3707,48 +3710,55 @@ bool ChatHandler::HandleMovegensCommand(const char* /*args*/)
case WAYPOINT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_WAYPOINT); break;
case ANIMAL_RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); break;
case CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break;
- case TARGETED_MOTION_TYPE:
+ case CHASE_MOTION_TYPE:
{
+ Unit* target = NULL;
if (unit->GetTypeId() == TYPEID_PLAYER)
- {
- TargetedMovementGenerator<Player> const* mgen = static_cast<TargetedMovementGenerator<Player> const*>(mg);
- Unit* target = mgen->GetTarget();
- if (target)
- PSendSysMessage(LANG_MOVEGENS_TARGETED_PLAYER, target->GetName(), target->GetGUIDLow());
- else
- SendSysMessage(LANG_MOVEGENS_TARGETED_NULL);
- }
+ target = static_cast<ChaseMovementGenerator<Player> const*>(mg)->GetTarget();
else
- {
- TargetedMovementGenerator<Creature> const* mgen = static_cast<TargetedMovementGenerator<Creature> const*>(mg);
- Unit* target = mgen->GetTarget();
- if (target)
- PSendSysMessage(LANG_MOVEGENS_TARGETED_CREATURE, target->GetName(), target->GetGUIDLow());
- else
- SendSysMessage(LANG_MOVEGENS_TARGETED_NULL);
- }
+ target = static_cast<ChaseMovementGenerator<Creature> const*>(mg)->GetTarget();
+
+ if (!target)
+ SendSysMessage(LANG_MOVEGENS_CHASE_NULL);
+ else if (target->GetTypeId() == TYPEID_PLAYER)
+ PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, target->GetName(), target->GetGUIDLow());
+ else
+ PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName(), target->GetGUIDLow());
break;
}
+ case FOLLOW_MOTION_TYPE:
+ {
+ Unit* target = NULL;
+ if (unit->GetTypeId() == TYPEID_PLAYER)
+ target = static_cast<FollowMovementGenerator<Player> const*>(mg)->GetTarget();
+ else
+ target = static_cast<FollowMovementGenerator<Creature> const*>(mg)->GetTarget();
+
+ if (!target)
+ SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL);
+ else if (target->GetTypeId() == TYPEID_PLAYER)
+ PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, target->GetName(), target->GetGUIDLow());
+ else
+ PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName(), target->GetGUIDLow());
+ break;
+ }
case HOME_MOTION_TYPE:
+ {
if (unit->GetTypeId() == TYPEID_UNIT)
- {
- float x, y, z;
- mg->GetDestination(x, y, z);
PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE, x, y, z);
- }
else
SendSysMessage(LANG_MOVEGENS_HOME_PLAYER);
break;
+ }
case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break;
case POINT_MOTION_TYPE:
{
- float x, y, z;
- mg->GetDestination(x, y, z);
PSendSysMessage(LANG_MOVEGENS_POINT, x, y, z);
break;
}
case FLEEING_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FEAR); break;
case DISTRACT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_DISTRACT); break;
+ case EFFECT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_EFFECT); break;
default:
PSendSysMessage(LANG_MOVEGENS_UNKNOWN, mg->GetMovementGeneratorType());
break;
@@ -4040,19 +4050,14 @@ bool ChatHandler::HandleComeToMeCommand(const char *args)
if (!newFlagStr)
return false;
- uint32 newFlags = (uint32)strtoul(newFlagStr, NULL, 0);
-
Creature* caster = getSelectedCreature();
if (!caster)
{
- m_session->GetPlayer()->SetUnitMovementFlags(newFlags);
SendSysMessage(LANG_SELECT_CREATURE);
SetSentErrorMessage(true);
return false;
}
- caster->SetUnitMovementFlags(newFlags);
-
Player* player = m_session->GetPlayer();
caster->GetMotionMaster()->MovePoint(0, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index ff627f78ea0..23865dd9e41 100755
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -48,6 +48,8 @@
#include "Vehicle.h"
#include "SpellAuraEffects.h"
#include "Group.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
// apply implementation of the singletons
TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
@@ -143,7 +145,7 @@ m_PlayerDamageReq(0), m_lootMoney(0), m_lootRecipient(0), m_lootRecipientGroup(0
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
-m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL)
+m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL), m_path_id(0)
{
m_regenTimer = CREATURE_REGEN_INTERVAL;
m_valuesCount = UNIT_END;
@@ -332,6 +334,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data
SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate
SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale);
+ SetLevitate(canFly());
// checked at loading
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
@@ -435,6 +438,17 @@ void Creature::Update(uint32 diff)
m_vehicleKit->Reset();
}
+ if (IsInWater())
+ {
+ if (canSwim())
+ AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
+ }
+ else
+ {
+ if (canWalk())
+ RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
+ }
+
switch (m_deathState)
{
case JUST_ALIVED:
@@ -472,9 +486,7 @@ void Creature::Update(uint32 diff)
}
case CORPSE:
{
- m_Events.Update(diff);
- _UpdateSpells(diff);
-
+ Unit::Update(diff);
// deathstate changed on spells update, prevent problems
if (m_deathState != CORPSE)
break;
@@ -565,9 +577,6 @@ void Creature::Update(uint32 diff)
m_regenTimer = CREATURE_REGEN_INTERVAL;
break;
}
- case DEAD_FALLING:
- GetMotionMaster()->UpdateMotion(diff);
- break;
default:
break;
}
@@ -945,7 +954,8 @@ void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint3
m_startMove = getMSTime();
m_moveTime = time;*/
- SendMonsterMove(x, y, z, time);
+ float speed = GetDistance(x, y, z) / ((float)time * 0.001f);
+ MonsterMoveWithSpeed(x, y, z, speed);
}
Player* Creature::GetLootRecipient() const
@@ -1507,8 +1517,8 @@ void Creature::setDeathState(DeathState s)
if (m_formation && m_formation->getLeader() == this)
m_formation->FormationReset(true);
- if ((canFly() || IsFlying()) && FallGround())
- return;
+ if ((canFly() || IsFlying()))
+ i_motionMaster.MoveFall();
Unit::setDeathState(CORPSE);
}
@@ -1520,7 +1530,7 @@ void Creature::setDeathState(DeathState s)
SetLootRecipient(NULL);
ResetPlayerDamageReq();
CreatureTemplate const* cinfo = GetCreatureInfo();
- AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ SetWalk(true);
if (GetCreatureInfo()->InhabitType & INHABIT_AIR)
AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING);
if (GetCreatureInfo()->InhabitType & INHABIT_WATER)
@@ -1536,24 +1546,6 @@ void Creature::setDeathState(DeathState s)
}
}
-bool Creature::FallGround()
-{
- // Let's abort after we called this function one time
- if (getDeathState() == DEAD_FALLING)
- return false;
-
- float x, y, z;
- GetPosition(x, y, z);
- // use larger distance for vmap height search than in most other cases
- float ground_Z = GetMap()->GetHeight(x, y, z, true, MAX_FALL_DISTANCE);
- if (fabs(ground_Z - z) < 0.1f)
- return false;
-
- GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND);
- Unit::setDeathState(DEAD_FALLING);
- return true;
-}
-
void Creature::Respawn(bool force)
{
DestroyForNearbyPlayers();
@@ -2415,3 +2407,25 @@ bool Creature::IsDungeonBoss() const
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry());
return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS);
}
+
+void Creature::SetWalk(bool enable)
+{
+ if (enable)
+ AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
+ data.append(GetPackGUID());
+ SendMessageToSet(&data, true);
+}
+
+void Creature::SetLevitate(bool enable)
+{
+ if (enable)
+ AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
+ data.append(GetPackGUID());
+ SendMessageToSet(&data, true);
+}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index adad02653bf..05339f1da53 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -520,6 +520,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
CreatureAI* AI() const { return (CreatureAI*)i_AI; }
+ void SetWalk(bool enable);
+ void SetLevitate(bool enable);
+
uint32 GetShieldBlockValue() const //dunno mob block value
{
return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20));
@@ -573,7 +576,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
const char* GetNameForLocaleIdx(LocaleConstant locale_idx) const;
void setDeathState(DeathState s); // override virtual Unit::setDeathState
- bool FallGround();
bool LoadFromDB(uint32 guid, Map* map) { return LoadCreatureFromDB(guid, map, false); }
bool LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap = true);
diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp
index abf82dc5919..f440fd497fc 100755
--- a/src/server/game/Entities/Creature/CreatureGroups.cpp
+++ b/src/server/game/Entities/Creature/CreatureGroups.cpp
@@ -212,10 +212,12 @@ void CreatureGroup::FormationReset(bool dismiss)
void CreatureGroup::LeaderMoveTo(float x, float y, float z)
{
+ //! To do: This should probably get its own movement generator or use WaypointMovementGenerator.
+ //! If the leader's path is known, member's path can be plotted as well using formation offsets.
if (!m_leader)
return;
- float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
+ float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
{
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 22f001d0224..fd094938da8 100755
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1869,4 +1869,4 @@ void GameObject::SetLootState(LootState s)
{
m_lootState = s;
AI()->OnStateChanged(s);
-} \ No newline at end of file
+}
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 3cd02d05a90..5c034f1a42a 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -45,6 +45,7 @@
#include "TemporarySummon.h"
#include "Totem.h"
#include "OutdoorPvPMgr.h"
+#include "MovementPacketBuilder.h"
uint32 GuidHigh2TypeId(uint32 guid_hi)
{
@@ -312,78 +313,17 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const
*data << ((Unit*)this)->GetSpeed(MOVE_WALK);
*data << ((Unit*)this)->GetSpeed(MOVE_RUN);
- *data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK);
- *data << ((Unit*)this)->GetSpeed(MOVE_SWIM);
*data << ((Unit*)this)->GetSpeed(MOVE_RUN_BACK);
+ *data << ((Unit*)this)->GetSpeed(MOVE_SWIM);
+ *data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK);
*data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT);
*data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT_BACK);
*data << ((Unit*)this)->GetSpeed(MOVE_TURN_RATE);
*data << ((Unit*)this)->GetSpeed(MOVE_PITCH_RATE);
- const Player* player = ToPlayer();
-
// 0x08000000
- if (player && player->isInFlight())
- {
- uint32 flags3 = SPLINEFLAG_GLIDE;
-
- *data << uint32(flags3); // splines flag?
-
- if (flags3 & 0x20000) // may be orientation
- {
- *data << (float)0;
- }
- else
- {
- if (flags3 & 0x8000) // probably x, y, z coords there
- {
- *data << (float)0;
- *data << (float)0;
- *data << (float)0;
- }
-
- if (flags3 & 0x10000) // probably guid there
- {
- *data << uint64(0);
- }
- }
-
- FlightPathMovementGenerator *fmg =
- (FlightPathMovementGenerator*)(player->GetMotionMaster()->top());
- 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); // ticks count?
-
- *data << float(0); // added in 3.1
- *data << float(0); // added in 3.1
- *data << float(0); // added in 3.1
-
- *data << uint32(0); // 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); // added in 3.0.8
-
- *data << float(path[poscount-1].x);
- *data << float(path[poscount-1].y);
- *data << float(path[poscount-1].z);
- }
+ if (((Unit*)this)->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED)
+ Movement::PacketBuilder::WriteCreate(*((Unit*)this)->movespline, *data);
}
else
{
@@ -487,7 +427,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const
// 0x200
if (flags & UPDATEFLAG_ROTATION)
{
- *data << uint64(((GameObject*)this)->GetRotation());
+ *data << int64(((GameObject*)this)->GetRotation());
}
}
@@ -1595,6 +1535,70 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface
}
+void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
+{
+ switch (GetTypeId())
+ {
+ case TYPEID_UNIT:
+ {
+ // non fly unit don't must be in air
+ // non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast
+ if (!((Creature const*)this)->canFly())
+ {
+ bool canSwim = ((Creature const*)this)->canSwim();
+ float ground_z = z;
+ float max_z = canSwim
+ ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK))
+ : ((ground_z = GetBaseMap()->GetHeight(x, y, z, true)));
+ if (max_z > INVALID_HEIGHT)
+ {
+ if (z > max_z)
+ z = max_z;
+ else if (z < ground_z)
+ z = ground_z;
+ }
+ }
+ else
+ {
+ float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
+ if (z < ground_z)
+ z = ground_z;
+ }
+ break;
+ }
+ case TYPEID_PLAYER:
+ {
+ // for server controlled moves playr work same as creature (but it can always swim)
+ if (!((Player const*)this)->canFly())
+ {
+ float ground_z = z;
+ float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK));
+ if (max_z > INVALID_HEIGHT)
+ {
+ if (z > max_z)
+ z = max_z;
+ else if (z < ground_z)
+ z = ground_z;
+ }
+ }
+ else
+ {
+ float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
+ if (z < ground_z)
+ z = ground_z;
+ }
+ break;
+ }
+ default:
+ {
+ float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
+ if(ground_z > INVALID_HEIGHT)
+ z = ground_z;
+ break;
+ }
+ }
+}
+
bool Position::IsPositionValid() const
{
return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation);
@@ -2033,7 +2037,8 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const
void WorldObject::SendMessageToSet(WorldPacket* data, bool self)
{
- SendMessageToSetInRange(data, GetVisibilityRange(), self);
+ if (IsInWorld())
+ SendMessageToSetInRange(data, GetVisibilityRange(), self);
}
void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*self*/)
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 3f78ec662e8..4cc298e4349 100755
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -497,7 +497,9 @@ struct MovementInfo
}
uint32 GetMovementFlags() { return flags; }
+ void SetMovementFlags(uint32 flag) { flags = flag; }
void AddMovementFlag(uint32 flag) { flags |= flag; }
+ void RemoveMovementFlag(uint32 flag) { flags &= ~flag; }
bool HasMovementFlag(uint32 flag) const { return flags & flag; }
uint16 GetExtraMovementFlags() { return flags2; }
@@ -615,6 +617,7 @@ class WorldObject : public Object, public WorldLocation
return (m_valuesCount > UNIT_FIELD_COMBATREACH) ? m_floatValues[UNIT_FIELD_COMBATREACH] : DEFAULT_WORLD_OBJECT_SIZE;
}
void UpdateGroundPositionZ(float x, float y, float &z) const;
+ void UpdateAllowedPositionZ(float x, float y, float &z) const;
void GetRandomPoint(const Position &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const;
void GetRandomPoint(const Position &srcPos, float distance, Position &pos) const
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7f7facfaff1..46f903ee71a 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2101,6 +2101,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// reset movement flags at teleport, because player will continue move with these flags after teleport
SetUnitMovementFlags(0);
+ DisableSpline();
if (m_transport)
{
@@ -5148,43 +5149,10 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
}
}
-/**
- * FallMode = 0 implies that the player is dying, or already dead, and the proper death state will be set.
- * = 1 simply causes the player to plummet towards the ground, and not suffer any damage.
- * = 2 causes the player to plummet towards the ground, and causes falling damage, regardless
- * of any auras that might of prevented fall damage.
- */
-bool Player::FallGround(uint8 FallMode)
-{
- // Let's abort after we called this function one time
- if (getDeathState() == DEAD_FALLING && FallMode == 0)
- return false;
-
- float x, y, z;
- GetPosition(x, y, z);
- float ground_Z = GetMap()->GetHeight(x, y, z);
- float z_diff = 0.0f;
- if ((z_diff = fabs(ground_Z - z)) < 0.1f)
- return false;
-
- GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND);
-
- // Below formula for falling damage is from Player::HandleFall
- if (FallMode == 2 && z_diff >= 14.57f)
- {
- uint32 damage = std::min(GetMaxHealth(), (uint32)((0.018f * z_diff - 0.2426f) * GetMaxHealth() * sWorld->getRate(RATE_DAMAGE_FALL)));
- if (damage)
- EnvironmentalDamage(DAMAGE_FALL, damage);
- }
- else if (FallMode == 0)
- Unit::setDeathState(DEAD_FALLING);
- return true;
-}
-
void Player::KillPlayer()
{
if (IsFlying() && !GetTransport())
- FallGround();
+ i_motionMaster.MoveFall();
SetMovement(MOVE_ROOT);
@@ -21474,8 +21442,6 @@ void Player::SendInitialVisiblePackets(Unit* target)
SendAurasForTarget(target);
if (target->isAlive())
{
- if (target->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE)
- target->SendMonsterMoveWithSpeedToCurrentDestination(this);
if (target->HasUnitState(UNIT_STAT_MELEE_ATTACKING) && target->getVictim())
target->SendMeleeAttackStart(target->getVictim());
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 21c87a993dc..aa1d4e8185e 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1964,7 +1964,6 @@ class Player : public Unit, public GridObject<Player>
Corpse* GetCorpse() const;
void SpawnCorpseBones();
void CreateCorpse();
- bool FallGround(uint8 FallMode = 0);
void KillPlayer();
uint32 GetResurrectionSpellId();
void ResurrectPlayer(float restore_percent, bool applySickness = false);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 2d6e8f1b724..63aa7771063 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -45,16 +45,16 @@
#include "InstanceSaveMgr.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
-#include "Path.h"
#include "CreatureGroups.h"
#include "PetAI.h"
#include "PassiveAI.h"
-#include "Traveller.h"
#include "TemporarySummon.h"
#include "Vehicle.h"
#include "Transport.h"
#include "InstanceScript.h"
#include "SpellInfo.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
#include <math.h>
@@ -62,9 +62,9 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
{
2.5f, // MOVE_WALK
7.0f, // MOVE_RUN
- 2.5f, // MOVE_RUN_BACK
+ 4.5f, // MOVE_RUN_BACK
4.722222f, // MOVE_SWIM
- 4.5f, // MOVE_SWIM_BACK
+ 2.5f, // MOVE_SWIM_BACK
3.141594f, // MOVE_TURN_RATE
7.0f, // MOVE_FLIGHT
4.5f, // MOVE_FLIGHT_BACK
@@ -73,9 +73,9 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
float playerBaseMoveSpeed[MAX_MOVE_TYPE] = {
2.5f, // MOVE_WALK
7.0f, // MOVE_RUN
- 2.5f, // MOVE_RUN_BACK
+ 4.5f, // MOVE_RUN_BACK
4.722222f, // MOVE_SWIM
- 4.5f, // MOVE_SWIM_BACK
+ 2.5f, // MOVE_SWIM_BACK
3.141594f, // MOVE_TURN_RATE
7.0f, // MOVE_FLIGHT
4.5f, // MOVE_FLIGHT_BACK
@@ -148,7 +148,7 @@ Unit::Unit(bool isWorldObject): WorldObject(isWorldObject),
m_movedPlayer(NULL), m_lastSanctuaryTime(0), IsAIEnabled(false), NeedChangeAI(false),
m_ControlledByPlayer(false), i_AI(NULL), i_disabledAI(NULL), m_procDeep(0),
m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), m_vehicle(NULL),
-m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this)
+m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this), movespline(new Movement::MoveSpline())
{
#ifdef _MSC_VER
#pragma warning(default:4355)
@@ -280,6 +280,7 @@ Unit::~Unit()
delete m_charmInfo;
delete m_vehicleKit;
+ delete movespline;
ASSERT(!m_duringRemoveFromWorld);
ASSERT(!m_attacking);
@@ -346,6 +347,7 @@ void Unit::Update(uint32 p_time)
ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, HealthAbovePct(75));
}
+ UpdateSplineMovement(p_time);
i_motionMaster.UpdateMotion(p_time);
}
@@ -357,151 +359,46 @@ bool Unit::haveOffhandWeapon() const
return m_canDualWield;
}
-void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player)
+void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed)
{
- float x, y, z;
- if (GetMotionMaster()->GetDestination(x, y, z))
- SendMonsterMoveWithSpeed(x, y, z, 0, player);
-}
-
-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.GetTotalTrevelTimeTo(x, y, z);
- }
- else
- {
- Traveller<Creature> traveller(*ToCreature());
- transitTime = traveller.GetTotalTrevelTimeTo(x, y, z);
- }
- }
- //float orientation = (float)atan2((double)dy, (double)dx);
- SendMonsterMove(x, y, z, transitTime, player);
+ Movement::MoveSplineInit init(*this);
+ init.MoveTo(x,y,z);
+ init.SetVelocity(speed);
+ init.Launch();
}
-void Unit::SetFacing(float ori, WorldObject* obj)
+void Unit::UpdateSplineMovement(uint32 t_diff)
{
- SetOrientation(obj ? GetAngle(obj) : ori);
-
- WorldPacket data(SMSG_MONSTER_MOVE, (1+12+4+1+(obj ? 8 : 4)+4+4+4+12+GetPackGUID().size()));
- data.append(GetPackGUID());
- data << uint8(0); // unk
- data << GetPositionX() << GetPositionY() << GetPositionZ();
- data << getMSTime();
- if (obj)
- {
- data << uint8(SPLINETYPE_FACING_TARGET);
- data << uint64(obj->GetGUID());
- }
- else
- {
- data << uint8(SPLINETYPE_FACING_ANGLE);
- data << ori;
- }
- data << uint32(SPLINEFLAG_NONE);
- data << uint32(0); // move time 0
- data << uint32(1); // one point
- data << GetPositionX() << GetPositionY() << GetPositionZ();
- SendMessageToSet(&data, true);
-}
-
-void Unit::SendMonsterStop(bool on_death)
-{
- WorldPacket data(SMSG_MONSTER_MOVE, (17 + GetPackGUID().size()));
- data.append(GetPackGUID());
- data << uint8(0); // new in 3.1
- data << GetPositionX() << GetPositionY() << GetPositionZ();
- data << getMSTime();
-
- if (on_death == true)
- {
- data << uint8(0);
- data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKING);
- data << uint32(0); // Time in between points
- data << uint32(1); // 1 single waypoint
- data << GetPositionX() << GetPositionY() << GetPositionZ();
- }
- else
- data << uint8(1);
-
- SendMessageToSet(&data, true);
-
- ClearUnitState(UNIT_STAT_MOVE);
-}
-
-void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player)
-{
- WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size());
- data.append(GetPackGUID());
-
- data << uint8(0); // new in 3.1
- data << GetPositionX() << GetPositionY() << GetPositionZ();
- data << getMSTime();
-
- data << uint8(0);
- data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKING);
- data << Time; // Time in between points
- data << uint32(1); // 1 single waypoint
- data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
-
- if (player)
- player->GetSession()->SendPacket(&data);
- else
- SendMessageToSet(&data, true);
-
- AddUnitState(UNIT_STAT_MOVE);
-}
+ enum{
+ POSITION_UPDATE_DELAY = 400,
+ };
-void Unit::SendMonsterMove(MonsterMoveData const& moveData, Player* player)
-{
- WorldPacket data(SMSG_MONSTER_MOVE, GetPackGUID().size() + 1 + 12 + 4 + 1 + 4 + 8 + 4 + 4 + 12);
- data.append(GetPackGUID());
+ if (movespline->Finalized())
+ return;
- data << uint8(0); // new in 3.1
- data << GetPositionX() << GetPositionY() << GetPositionZ();
- data << getMSTime();
+ movespline->updateState(t_diff);
+ bool arrived = movespline->Finalized();
- data << uint8(0);
- data << moveData.SplineFlag;
+ if (arrived)
+ DisableSpline();
- if (moveData.SplineFlag & SPLINEFLAG_ANIMATIONTIER)
+ m_movesplineTimer.Update(t_diff);
+ if (m_movesplineTimer.Passed() || arrived)
{
- data << uint8(moveData.AnimationState);
- data << uint32(0);
- }
+ m_movesplineTimer.Reset(POSITION_UPDATE_DELAY);
+ Movement::Location loc = movespline->ComputePosition();
- data << moveData.Time;
-
- if (moveData.SplineFlag & SPLINEFLAG_TRAJECTORY)
- {
- data << moveData.SpeedZ;
- data << uint32(0); // walk time after jump
+ if (GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->UpdatePosition(loc.x,loc.y,loc.z,loc.orientation);
+ else
+ GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation);
}
-
- data << uint32(1); // waypoint count
- data << moveData.DestLocation.GetPositionX();
- data << moveData.DestLocation.GetPositionY();
- data << moveData.DestLocation.GetPositionZ();
-
- if (player)
- player->GetSession()->SendPacket(&data);
- else
- SendMessageToSet(&data, true);
}
-void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player* player)
+void Unit::DisableSpline()
{
- MonsterMoveData data;
- data.DestLocation.Relocate(NewPosX, NewPosY, NewPosZ);
- data.SplineFlag = MoveFlags;
- data.Time = time;
- data.SpeedZ = speedZ;
-
- SendMonsterMove(data, player);
+ m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD));
+ movespline->_Interrupt();
}
void Unit::SendMonsterMoveExitVehicle(Position const* newPos)
@@ -3106,17 +3003,6 @@ bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
return IsWithinDistInMap(target, distance) && !HasInArc(2 * M_PI - arc, target);
}
-void Unit::SetFacingToObject(WorldObject* pObject)
-{
- // update orientation at server
- SetOrientation(GetAngle(pObject));
-
- // and client
- WorldPacket data;
- BuildHeartBeatMsg(&data);
- SendMessageToSet(&data, false);
-}
-
bool Unit::isInAccessiblePlaceFor(Creature const* c) const
{
if (IsInWater())
@@ -12744,7 +12630,7 @@ void Unit::setDeathState(DeathState s)
ClearDiminishings();
GetMotionMaster()->Clear(false);
GetMotionMaster()->MoveIdle();
- SendMonsterStop(true);
+ StopMoving();
// without this when removing IncreaseMaxHealth aura player may stuck with 1 hp
// do not why since in IncreaseMaxHealth currenthealth is checked
SetHealth(0);
@@ -13565,7 +13451,7 @@ void Unit::SetHealth(uint32 val)
{
if (getDeathState() == JUST_DIED)
val = 0;
- else if (GetTypeId() == TYPEID_PLAYER && (getDeathState() == DEAD || getDeathState() == DEAD_FALLING))
+ else if (GetTypeId() == TYPEID_PLAYER && getDeathState() == DEAD)
val = 1;
else
{
@@ -14682,22 +14568,20 @@ void Unit::StopMoving()
{
ClearUnitState(UNIT_STAT_MOVING);
- // send explicit stop packet
- // rely on vmaps here because for example stormwind is in air
- //float z = sMapMgr->GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true);
- //if (fabs(GetPositionZ() - z) < 2.0f)
- // Relocate(GetPositionX(), GetPositionY(), z);
- //Relocate(GetPositionX(), GetPositionY(), GetPositionZ());
+ // not need send any packets if not in world
+ if (!IsInWorld())
+ return;
- if (!(GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT))
- SendMonsterStop();
+ Movement::MoveSplineInit init(*this);
+ init.SetFacing(GetOrientation());
+ init.Launch();
}
void Unit::SendMovementFlagUpdate()
{
WorldPacket data;
BuildHeartBeatMsg(&data);
- SendMessageToSet(&data, false);
+ SendMessageToSet(&data, true);
}
bool Unit::IsSitState() const
@@ -17097,7 +16981,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
WorldPacket data2;
BuildHeartBeatMsg(&data2);
- SendMessageToSet(&data2, false);
+ SendMessageToSet(&data2, true);
if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
if (((Minion*)vehicle->GetBase())->GetOwner() == this)
@@ -17116,25 +17000,6 @@ void Unit::_ExitVehicle(Position const* exitPosition)
void Unit::BuildMovementPacket(ByteBuffer *data) const
{
- switch (GetTypeId())
- {
- case TYPEID_UNIT:
- if (canFly())
- const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- break;
- case TYPEID_PLAYER:
- // remove unknown, unused etc flags for now
- const_cast<Unit*>(this)->RemoveUnitMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED);
- if (isInFlight())
- {
- WPAssert(const_cast<Unit*>(this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
- const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE_ENABLED);
- }
- break;
- default:
- break;
- }
-
*data << uint32(GetUnitMovementFlags()); // movement flags
*data << uint16(m_movementInfo.flags2); // 2.3.0
*data << uint32(getMSTime()); // time
@@ -17198,13 +17063,13 @@ void Unit::SetFlying(bool apply)
void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/)
{
+ DisableSpline();
if (GetTypeId() == TYPEID_PLAYER)
ToPlayer()->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0));
else
{
- // FIXME: this interrupts spell visual
- DestroyForNearbyPlayers();
UpdatePosition(x, y, z, orientation, true);
+ SendMovementFlagUpdate();
}
}
@@ -17486,3 +17351,26 @@ bool CharmInfo::IsReturning()
{
return m_isReturning;
}
+
+void Unit::SetInFront(Unit const* target)
+{
+ if (!HasUnitState(UNIT_STAT_CANNOT_TURN))
+ SetOrientation(GetAngle(target));
+}
+
+void Unit::SetFacingTo(float ori)
+{
+ Movement::MoveSplineInit init(*this);
+ init.SetFacing(ori);
+ init.Launch();
+}
+
+void Unit::SetFacingToObject(WorldObject* pObject)
+{
+ // never face when already moving
+ if (!IsStopped())
+ return;
+
+ // TODO: figure out under what conditions creature will move towards object instead of facing it where it currently is.
+ SetFacingTo(GetAngle(pObject));
+}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 5a6b34bc380..b64a2e210bc 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -465,7 +465,6 @@ enum DeathState
CORPSE = 2,
DEAD = 3,
JUST_ALIVED = 4,
- DEAD_FALLING= 5
};
enum UnitState
@@ -493,13 +492,22 @@ enum UnitState
UNIT_STAT_MOVE = 0x00100000,
UNIT_STAT_ROTATING = 0x00200000,
UNIT_STAT_EVADE = 0x00400000,
+ UNIT_STAT_ROAMING_MOVE = 0x00800000,
+ UNIT_STAT_CONFUSED_MOVE = 0x01000000,
+ UNIT_STAT_FLEEING_MOVE = 0x02000000,
+ UNIT_STAT_CHASE_MOVE = 0x04000000,
+ UNIT_STAT_FOLLOW_MOVE = 0x08000000,
UNIT_STAT_UNATTACKABLE = (UNIT_STAT_IN_FLIGHT | UNIT_STAT_ONVEHICLE),
- UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE),
+ //UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE),
+ // for real move using movegen check and stop (except unstoppable flight)
+ UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CONFUSED_MOVE | UNIT_STAT_FLEEING_MOVE| UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE ,
UNIT_STAT_CONTROLLED = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING),
UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONTROLLED | UNIT_STAT_JUMPING | UNIT_STAT_CHARGING),
UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_EVADE),
UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING),
UNIT_STAT_CANNOT_TURN = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_ROTATING),
+ // stay by different reasons
+ UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_DISTRACTED,
UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
};
@@ -719,59 +727,18 @@ enum MovementFlags2
MOVEMENTFLAG2_UNK15 = 0x00004000,
MOVEMENTFLAG2_UNK16 = 0x00008000,
};
+
enum SplineFlags
{
- SPLINEFLAG_NONE = 0x00000000,
- SPLINEFLAG_FORWARD = 0x00000001,
- SPLINEFLAG_BACKWARD = 0x00000002,
- SPLINEFLAG_STRAFE_LEFT = 0x00000004,
- SPLINEFLAG_STRAFE_RIGHT = 0x00000008,
- SPLINEFLAG_LEFT = 0x00000010,
- SPLINEFLAG_RIGHT = 0x00000020,
- SPLINEFLAG_PITCH_UP = 0x00000040,
- SPLINEFLAG_PITCH_DOWN = 0x00000080,
- SPLINEFLAG_DONE = 0x00000100,
- SPLINEFLAG_FALLING = 0x00000200,
- SPLINEFLAG_NO_SPLINE = 0x00000400,
- SPLINEFLAG_TRAJECTORY = 0x00000800,
- SPLINEFLAG_WALKING = 0x00001000,
- SPLINEFLAG_FLYING = 0x00002000,
- SPLINEFLAG_KNOCKBACK = 0x00004000,
- SPLINEFLAG_FINAL_POINT = 0x00008000,
- SPLINEFLAG_FINAL_TARGET = 0x00010000,
- SPLINEFLAG_FINAL_FACING = 0x00020000,
- SPLINEFLAG_CATMULL_ROM = 0x00040000,
- SPLINEFLAG_UNKNOWN20 = 0x00080000,
- SPLINEFLAG_UNKNOWN21 = 0x00100000,
- SPLINEFLAG_ANIMATIONTIER = 0x00200000,
- SPLINEFLAG_UNKNOWN23 = 0x00400000,
- SPLINEFLAG_TRANSPORT = 0x00800000,
- SPLINEFLAG_EXIT_VEHICLE = 0x01000000,
- SPLINEFLAG_UNKNOWN26 = 0x02000000,
- SPLINEFLAG_UNKNOWN27 = 0x04000000,
- SPLINEFLAG_UNKNOWN28 = 0x08000000,
- SPLINEFLAG_UNKNOWN29 = 0x10000000,
- SPLINEFLAG_ANIMATION = 0x20000000,
- SPLINEFLAG_UNKNOWN31 = 0x40000000,
- SPLINEFLAG_UNKNOWN32 = 0x80000000,
-
- SPLINEFLAG_GLIDE = SPLINEFLAG_WALKING | SPLINEFLAG_FLYING,
-};
-
-enum SplineMode
-{
- SPLINEMODE_LINEAR = 0,
- SPLINEMODE_CATMULL_ROM = 1,
- SPLINEMODE_BEZIER3 = 2
+ SPLINEFLAG_WALKMODE = 0x00001000,
+ SPLINEFLAG_FLYING = 0x00002000,
+ SPLINEFLAG_TRANSPORT = 0x00800000,
+ SPLINEFLAG_EXIT_VEHICLE = 0x01000000,
};
enum SplineType
{
- SPLINETYPE_NORMAL = 0,
- SPLINETYPE_STOP = 1,
- SPLINETYPE_FACING_SPOT = 2,
- SPLINETYPE_FACING_TARGET = 3,
- SPLINETYPE_FACING_ANGLE = 4
+ SPLINETYPE_FACING_ANGLE = 4,
};
enum UnitTypeMask
@@ -789,6 +756,10 @@ enum UnitTypeMask
UNIT_MASK_ACCESSORY = 0x00000200,
};
+namespace Movement{
+ class MoveSpline;
+}
+
enum DiminishingLevels
{
DIMINISHING_LEVEL_1 = 0,
@@ -1628,20 +1599,18 @@ class Unit : public WorldObject
void JumpTo(float speedXY, float speedZ, bool forward = true);
void JumpTo(WorldObject* obj, float speedZ);
- void SetFacing(float ori, WorldObject* obj = NULL);
- void SendMonsterStop(bool on_death = false);
- void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL);
- void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player* player = NULL);
- void SendMonsterMove(MonsterMoveData const& moveData, Player* receiver = NULL);
+ void MonsterMoveWithSpeed(float x, float y, float z, float speed);
+ //void SetFacing(float ori, WorldObject* obj = NULL);
void SendMonsterMoveExitVehicle(Position const* newPos);
//void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
void SendMonsterMoveTransport(Unit* vehicleOwner);
- void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
- void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
void SendMovementFlagUpdate();
+ bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_LEVITATING);}
+ bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);}
- template<typename PathElem, typename PathNode>
- void SendMonsterMoveByPath(Path<PathElem, PathNode> const& path, uint32 start, uint32 end);
+ void SetInFront(Unit const* target);
+ void SetFacingTo(float ori);
+ void SetFacingToObject(WorldObject* pObject);
void SendChangeCurrentVictimOpcode(HostileReference* pHostileReference);
void SendClearThreatListOpcode();
@@ -1951,13 +1920,7 @@ class Unit : public WorldObject
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const;
- void SetInFront(Unit const* target)
- {
- if (!HasUnitState(UNIT_STAT_CANNOT_TURN))
- SetOrientation(GetAngle(target));
- }
bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const;
- void SetFacingToObject(WorldObject* pObject);
// Visibility system
bool IsVisible() const { return (m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM) > SEC_PLAYER) ? false : true; }
@@ -2232,6 +2195,9 @@ class Unit : public WorldObject
SetUInt64Value(UNIT_FIELD_TARGET, 0);
}
+ // Movement info
+ Movement::MoveSpline * movespline;
+
protected:
explicit Unit (bool isWorldObject);
@@ -2303,6 +2269,8 @@ class Unit : public WorldObject
bool IsAlwaysVisibleFor(WorldObject const* seer) const;
bool IsAlwaysDetectableFor(WorldObject const* seer) const;
+
+ void DisableSpline();
private:
bool IsTriggeredAtSpellProcEvent(Unit* pVictim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent);
bool HandleDummyAuraProc(Unit* pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
@@ -2316,6 +2284,8 @@ class Unit : public WorldObject
bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura);
bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura);
+ void UpdateSplineMovement(uint32 t_diff);
+
// player or player's pet
float GetCombatRatingReduction(CombatRating cr) const;
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
@@ -2330,6 +2300,7 @@ class Unit : public WorldObject
uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer;
uint32 m_lastManaUse; // msecs
+ TimeTrackerSmall m_movesplineTimer;
Diminishing m_Diminishing;
// Manage all Units that are threatened by us
@@ -2382,31 +2353,4 @@ namespace Trinity
const bool m_ascending;
};
}
-
-template<typename Elem, typename Node>
-inline void Unit::SendMonsterMoveByPath(Path<Elem, Node> const& path, uint32 start, uint32 end)
-{
- 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.append(GetPackGUID());
- data << uint8(0);
- data << GetPositionX();
- data << GetPositionY();
- data << GetPositionZ();
- data << uint32(getMSTime());
- data << uint8(0);
- data << uint32(((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) || isInFlight()) ? (SPLINEFLAG_FLYING|SPLINEFLAG_WALKING) : SPLINEFLAG_WALKING);
- 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
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index b2f8e5608a7..df5ec540427 100755
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1539,6 +1539,24 @@ inline GridMap* Map::GetGrid(float x, float y)
return GridMaps[gx][gy];
}
+float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool swim /*= false*/) const
+{
+ if (const_cast<Map*>(this)->GetGrid(x, y))
+ {
+ // we need ground level (including grid height version) for proper return water level in point
+ float ground_z = GetHeight(x, y, z, true, 50.0f);
+ if (ground)
+ *ground = ground_z;
+
+ LiquidData liquid_status;
+
+ ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
+ return res ? ( swim ? liquid_status.level - 2.0f : liquid_status.level) : ground_z;
+ }
+
+ return VMAP_INVALID_HEIGHT_VALUE;
+}
+
float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const
{
// find raw .map surface under Z coordinates
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 9f6b936541e..f3b45bd8f37 100755
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -424,6 +424,8 @@ class Map : public GridRefManager<NGridType>
InstanceMap* ToInstanceMap(){ if (IsDungeon()) return reinterpret_cast<InstanceMap*>(this); else return NULL; }
const InstanceMap* ToInstanceMap() const { if (IsDungeon()) return (const InstanceMap*)((InstanceMap*)this); else return NULL; }
+ float GetWaterOrGroundLevel(float x, float y, float z, float* ground = NULL, bool swim = false) const;
+
private:
void LoadMapAndVMap(int gx, int gy);
void LoadVMap(int gx, int gy);
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index afb5aa5660f..0fb28008c1e 100755
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -25,7 +25,6 @@
#include "GridDefines.h"
#include "MapInstanced.h"
#include "InstanceScript.h"
-#include "DestinationHolderImp.h"
#include "Config.h"
#include "World.h"
#include "CellImpl.h"
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 66610adc1f0..e751dbf92fe 100755
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -492,9 +492,9 @@ enum TrinityStrings
LANG_MOVEGENS_WAYPOINT = 529,
LANG_MOVEGENS_ANIMAL_RANDOM = 530,
LANG_MOVEGENS_CONFUSED = 531,
- LANG_MOVEGENS_TARGETED_PLAYER = 532,
- LANG_MOVEGENS_TARGETED_CREATURE = 533,
- LANG_MOVEGENS_TARGETED_NULL = 534,
+ LANG_MOVEGENS_CHASE_PLAYER = 532,
+ LANG_MOVEGENS_CHASE_CREATURE = 533,
+ LANG_MOVEGENS_CHASE_NULL = 534,
LANG_MOVEGENS_HOME_CREATURE = 535,
LANG_MOVEGENS_HOME_PLAYER = 536,
LANG_MOVEGENS_FLIGHT = 537,
@@ -807,7 +807,11 @@ enum TrinityStrings
LANG_CHAR_NOT_BANNED = 1136,
LANG_DEV_ON = 1137,
LANG_DEV_OFF = 1138,
- // Room for more level 3 1139-1199 not used
+ LANG_MOVEGENS_FOLLOW_PLAYER = 1139,
+ LANG_MOVEGENS_FOLLOW_CREATURE = 1140,
+ LANG_MOVEGENS_FOLLOW_NULL = 1141,
+ LANG_MOVEGENS_EFFECT = 1142,
+ // Room for more level 3 1143-1199 not used
// Debug commands
LANG_CINEMATIC_NOT_EXIST = 1200,
diff --git a/src/server/game/Movement/DestinationHolder.cpp b/src/server/game/Movement/DestinationHolder.cpp
deleted file mode 100755
index 4b763112968..00000000000
--- a/src/server/game/Movement/DestinationHolder.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "DestinationHolder.h"
-
diff --git a/src/server/game/Movement/DestinationHolder.h b/src/server/game/Movement/DestinationHolder.h
deleted file mode 100755
index 5ae4ee88ce3..00000000000
--- a/src/server/game/Movement/DestinationHolder.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_DESTINATION_HOLDER_H
-#define TRINITY_DESTINATION_HOLDER_H
-
-#include "Define.h"
-#include "Timer.h"
-
-class WorldObject;
-class Map;
-
-#define TRAVELLER_UPDATE_INTERVAL 300
-
-template<typename TRAVELLER>
-class DestinationHolder
-{
- TimeTrackerSmall 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; }
- void ResetTravelTime() { i_totalTravelTime = 0; }
- 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 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
-
diff --git a/src/server/game/Movement/DestinationHolderImp.h b/src/server/game/Movement/DestinationHolderImp.h
deleted file mode 100755
index 4d6e6f0c741..00000000000
--- a/src/server/game/Movement/DestinationHolderImp.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_DESTINATIONHOLDERIMP_H
-#define TRINITY_DESTINATIONHOLDERIMP_H
-
-#include "MapManager.h"
-#include "DestinationHolder.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.GetTotalTrevelTimeTo(i_destX, i_destY, i_destZ);
- i_timeElapsed = 0;
- if (sendMove)
- traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime);
- return i_totalTravelTime;
-}
-
-template<typename TRAVELLER>
-bool
-DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool micro_movement)
-{
- i_timeElapsed += diff;
-
- // Update every TRAVELLER_UPDATE_INTERVAL
- i_tracker.Update(diff);
- if (!i_tracker.Passed())
- return false;
- else
- ResetUpdate();
-
- if (!i_destSet) return true;
-
- float x, y, z;
- if (!micro_movement)
- GetLocationNowNoMicroMovement(x, y, z);
- else
- {
- if (!traveller.GetTraveller().HasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT))
- return true;
-
- if (traveller.GetTraveller().HasUnitState(UNIT_STAT_IN_FLIGHT))
- GetLocationNow(traveller.GetTraveller().GetBaseMap(), x, y, z, true); // Should reposition Object with right Coord, so I can bypass some Grid Relocation
- else
- GetLocationNow(traveller.GetTraveller().GetBaseMap(), x, y, z, false);
-
- // 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;
- }
-
- 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;
-}
-
-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->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 = (float)(i_fromX + ((i_destX - i_fromX) * percent_passed));
- y = (float)(i_fromY + ((i_destY - i_fromY) * percent_passed));
- z = (float)(i_fromZ + ((i_destZ - i_fromZ) * percent_passed));
- }
-}
-
-#endif
-
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 6660da146f0..2656d882009 100755
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -19,7 +19,6 @@
#include "MotionMaster.h"
#include "CreatureAISelector.h"
#include "Creature.h"
-#include "Traveller.h"
#include "ConfusedMovementGenerator.h"
#include "FleeingMovementGenerator.h"
@@ -29,7 +28,8 @@
#include "TargetedMovementGenerator.h"
#include "WaypointMovementGenerator.h"
#include "RandomMovementGenerator.h"
-
+#include "MoveSpline.h"
+#include "MoveSplineInit.h"
#include <cassert>
inline bool isStatic(MovementGenerator *mv)
@@ -193,16 +193,23 @@ void MotionMaster::MoveRandom(float spawndist)
void MotionMaster::MoveTargetedHome()
{
- //if (i_owner->HasUnitState(UNIT_STAT_FLEEING))
- // return;
-
Clear(false);
- if (i_owner->GetTypeId() == TYPEID_UNIT)
+ if (i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID())
{
sLog->outStaticDebug("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow());
Mutate(new HomeMovementGenerator<Creature>(), MOTION_SLOT_ACTIVE);
}
+ else if (i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID())
+ {
+ sLog->outStaticDebug("Pet or controlled creature (Entry: %u GUID: %u) targeting home", i_owner->GetEntry(), i_owner->GetGUIDLow() );
+ Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner();
+ if (target)
+ {
+ sLog->outStaticDebug("Following %s (GUID: %u)", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
+ Mutate(new FollowMovementGenerator<Creature>(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE);
+ }
+ }
else
{
sLog->outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow());
@@ -230,14 +237,14 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle)
if (!target || target == i_owner || i_owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
return;
- i_owner->ClearUnitState(UNIT_STAT_FOLLOW);
+ //i_owner->ClearUnitState(UNIT_STAT_FOLLOW);
if (i_owner->GetTypeId() == TYPEID_PLAYER)
{
sLog->outStaticDebug("Player (GUID: %u) chase to %s (GUID: %u)",
i_owner->GetGUIDLow(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
- Mutate(new TargetedMovementGenerator<Player>(*target, dist, angle), MOTION_SLOT_ACTIVE);
+ Mutate(new ChaseMovementGenerator<Player>(*target,dist,angle), MOTION_SLOT_ACTIVE);
}
else
{
@@ -245,7 +252,7 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle)
i_owner->GetEntry(), i_owner->GetGUIDLow(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
- Mutate(new TargetedMovementGenerator<Creature>(*target, dist, angle), MOTION_SLOT_ACTIVE);
+ Mutate(new ChaseMovementGenerator<Creature>(*target,dist,angle), MOTION_SLOT_ACTIVE);
}
}
@@ -255,13 +262,13 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo
if (!target || target == i_owner || i_owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
return;
- i_owner->AddUnitState(UNIT_STAT_FOLLOW);
+ //i_owner->AddUnitState(UNIT_STAT_FOLLOW);
if (i_owner->GetTypeId() == TYPEID_PLAYER)
{
sLog->outStaticDebug("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
- Mutate(new TargetedMovementGenerator<Player>(*target, dist, angle), slot);
+ Mutate(new FollowMovementGenerator<Player>(*target,dist,angle), slot);
}
else
{
@@ -269,7 +276,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo
i_owner->GetEntry(), i_owner->GetGUIDLow(),
target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow());
- Mutate(new TargetedMovementGenerator<Creature>(*target, dist, angle), slot);
+ Mutate(new FollowMovementGenerator<Creature>(*target,dist,angle), slot);
}
}
@@ -290,54 +297,32 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z)
void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed)
{
- if (i_owner->GetTypeId() != TYPEID_UNIT)
- return;
-
- uint32 moveFlag = SPLINEFLAG_FLYING | SPLINEFLAG_ANIMATIONTIER;
- uint32 moveTime = uint32(i_owner->GetExactDist(&pos) / speed) * IN_MILLISECONDS;
-
- // CHARGING state makes the unit use m_TempSpeed and JUMPING prevents sending movement packet in PointMovementGenerator
- i_owner->AddUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING);
- i_owner->m_TempSpeed = speed;
-
float x, y, z;
pos.GetPosition(x, y, z);
- sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), id, x, y, z);
- Mutate(new PointMovementGenerator<Creature>(id, x, y, z), MOTION_SLOT_ACTIVE);
- MonsterMoveData data;
- data.DestLocation.Relocate(pos);
- data.SplineFlag = moveFlag;
- data.Time = moveTime;
- data.AnimationState = ANIMATION_ON_GROUND;
+ sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), id, x, y, z);
- i_owner->SendMonsterMove(data);
+ Movement::MoveSplineInit init(*i_owner);
+ init.MoveTo(x,y,z);
+ init.SetVelocity(speed);
+ init.SetAnimation(Movement::ToGround);
+ init.Launch();
+ Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
}
void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed)
{
- if (i_owner->GetTypeId() != TYPEID_UNIT)
- return;
-
- uint32 moveFlag = SPLINEFLAG_FLYING | SPLINEFLAG_ANIMATIONTIER;
- uint32 moveTime = uint32(i_owner->GetExactDist(&pos) / speed) * IN_MILLISECONDS;
-
- // CHARGING state makes the unit use m_TempSpeed and JUMPING prevents sending movement packet in PointMovementGenerator
- i_owner->AddUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING);
- i_owner->m_TempSpeed = speed;
-
float x, y, z;
pos.GetPosition(x, y, z);
- sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), id, x, y, z);
- Mutate(new PointMovementGenerator<Creature>(id, x, y, z), MOTION_SLOT_ACTIVE);
- MonsterMoveData data;
- data.DestLocation.Relocate(pos);
- data.SplineFlag = moveFlag;
- data.Time = moveTime;
- data.AnimationState = ANIMATION_FLYING;
+ sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), id, x, y, z);
- i_owner->SendMonsterMove(data);
+ Movement::MoveSplineInit init(*i_owner);
+ init.MoveTo(x,y,z);
+ init.SetVelocity(speed);
+ init.SetAnimation(Movement::ToFly);
+ init.Launch();
+ Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
}
void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ)
@@ -347,7 +332,9 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
return;
float x, y, z;
- float dist = speedXY * speedZ * 0.1f;
+ float moveTimeHalf = speedZ / Movement::gravity;
+ float dist = 2 * moveTimeHalf * speedXY;
+
i_owner->GetNearPoint(i_owner, x, y, z, i_owner->GetObjectSize(), dist, i_owner->GetAngle(srcX, srcY) + M_PI);
MoveJump(x, y, z, speedXY, speedZ);
}
@@ -359,35 +346,48 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
return;
float x, y, z;
- float dist = speedXY * speedZ * 0.1f;
+
+ float moveTimeHalf = speedZ / Movement::gravity;
+ float dist = 2 * moveTimeHalf * speedXY;
i_owner->GetClosePoint(x, y, z, i_owner->GetObjectSize(), dist, angle);
MoveJump(x, y, z, speedXY, speedZ);
}
-void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ)
+void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id)
{
- uint32 moveFlag = SPLINEFLAG_TRAJECTORY | SPLINEFLAG_WALKING;
- uint32 time = uint32(speedZ * 100);
+ sLog->outStaticDebug("Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), x, y, z);
- // Instantly interrupt non melee spells being casted
- if (i_owner->IsNonMeleeSpellCasted(true))
- i_owner->InterruptNonMeleeSpells(true);
+ float moveTimeHalf = speedZ / Movement::gravity;
+ float max_height = -Movement::computeFallElevation(moveTimeHalf,false,-speedZ);
- i_owner->AddUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING);
- i_owner->m_TempSpeed = speedXY;
- if (i_owner->GetTypeId() == TYPEID_PLAYER)
- {
- sLog->outStaticDebug("Player (GUID: %u) jump to point (X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), x, y, z);
- Mutate(new PointMovementGenerator<Player>(0, x, y, z), MOTION_SLOT_CONTROLLED);
- }
- else
+ Movement::MoveSplineInit init(*i_owner);
+ init.MoveTo(x,y,z);
+ init.SetParabolic(max_height,0);
+ init.SetVelocity(speedXY);
+ init.Launch();
+ Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
+}
+
+void MotionMaster::MoveFall()
+{
+ // use larger distance for vmap height search than in most other cases
+ float tz = i_owner->GetMap()->GetHeight(i_owner->GetPositionX(), i_owner->GetPositionY(), i_owner->GetPositionZ(), true, MAX_FALL_DISTANCE);
+ if (tz <= INVALID_HEIGHT)
{
- sLog->outStaticDebug("Creature (Entry: %u GUID: %u) jump to point (X: %f Y: %f Z: %f)",
- i_owner->GetEntry(), i_owner->GetGUIDLow(), x, y, z);
- Mutate(new PointMovementGenerator<Creature>(0, x, y, z), MOTION_SLOT_CONTROLLED);
+ sLog->outStaticDebug("MotionMaster::MoveFall: unable retrive a proper height at map %u (x: %f, y: %f, z: %f).",
+ i_owner->GetMap()->GetId(), i_owner->GetPositionX(), i_owner->GetPositionX(), i_owner->GetPositionZ());
+ return;
}
- i_owner->SendMonsterMove(x, y, z, moveFlag, time, speedZ);
+ // Abort too if the ground is very near
+ if (fabs(i_owner->GetPositionZ() - tz) < 0.1f)
+ return;
+
+ Movement::MoveSplineInit init(*i_owner);
+ init.MoveTo(i_owner->GetPositionX(),i_owner->GetPositionY(),tz);
+ init.SetFall();
+ init.Launch();
+ Mutate(new EffectMovementGenerator(0), MOTION_SLOT_CONTROLLED);
}
void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id)
@@ -395,29 +395,19 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id)
if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE)
return;
- i_owner->AddUnitState(UNIT_STAT_CHARGING);
- i_owner->m_TempSpeed = speed;
if (i_owner->GetTypeId() == TYPEID_PLAYER)
{
sLog->outStaticDebug("Player (GUID: %u) charge point (X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), x, y, z);
- Mutate(new PointMovementGenerator<Player>(id, x, y, z), MOTION_SLOT_CONTROLLED);
+ Mutate(new PointMovementGenerator<Player>(id, x, y, z, speed), MOTION_SLOT_CONTROLLED);
}
else
{
sLog->outStaticDebug("Creature (Entry: %u GUID: %u) charge point (X: %f Y: %f Z: %f)",
i_owner->GetEntry(), i_owner->GetGUIDLow(), x, y, z);
- Mutate(new PointMovementGenerator<Creature>(id, x, y, z), MOTION_SLOT_CONTROLLED);
+ Mutate(new PointMovementGenerator<Creature>(id, x, y, z, speed), MOTION_SLOT_CONTROLLED);
}
}
-void MotionMaster::MoveFall(float z, uint32 id)
-{
- i_owner->SetFlying(false);
- i_owner->SendMovementFlagUpdate();
- //AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
- MoveCharge(i_owner->GetPositionX(), i_owner->GetPositionY(), z, SPEED_CHARGE, id);
-}
-
void MotionMaster::MoveSeekAssistance(float x, float y, float z)
{
if (i_owner->GetTypeId() == TYPEID_PLAYER)
@@ -561,7 +551,7 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable)
//i_owner->GetTypeId() == TYPEID_PLAYER ?
//Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)):
- Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
+ Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
sLog->outStaticDebug("%s (GUID: %u) start moving over path(Id:%u, repeatable: %s)",
i_owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
@@ -632,8 +622,12 @@ void MotionMaster::DelayedDelete(_Ty curr)
bool MotionMaster::GetDestination(float &x, float &y, float &z)
{
- if (empty())
+ if (i_owner->movespline->Finalized())
return false;
- return top()->GetDestination(x, y, z);
+ const G3D::Vector3& dest = i_owner->movespline->FinalDestination();
+ x = dest.x;
+ y = dest.y;
+ z = dest.z;
+ return true;
}
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index a972c3b06ce..00f1701e591 100755
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -39,7 +39,7 @@ enum MovementGeneratorType
MAX_DB_MOTION_TYPE = 3, // *** this and below motion types can't be set in DB.
ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h
CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h
- TARGETED_MOTION_TYPE = 5, // TargetedMovementGenerator.h
+ CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h
HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h
FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h
POINT_MOTION_TYPE = 8, // PointMovementGenerator.h
@@ -48,8 +48,10 @@ enum MovementGeneratorType
ASSISTANCE_MOTION_TYPE= 11, // PointMovementGenerator.h (first part of flee for assistance)
ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance)
TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance)
- ROTATE_MOTION_TYPE = 14,
- NULL_MOTION_TYPE = 15,
+ FOLLOW_MOTION_TYPE = 14,
+ ROTATE_MOTION_TYPE = 15,
+ EFFECT_MOTION_TYPE = 16,
+ NULL_MOTION_TYPE = 17,
};
enum MovementSlot
@@ -86,7 +88,6 @@ class MotionMaster //: private std::stack<MovementGenerator *>
typedef std::vector<_Ty> ExpireList;
int i_top;
- bool empty() const { return (i_top < 0); }
void pop() { Impl[i_top] = NULL; --i_top; }
void push(_Ty _Val) { ++i_top; Impl[i_top] = _Val; }
@@ -107,6 +108,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void Initialize();
void InitDefault();
+ bool empty() const { return (i_top < 0); }
int size() const { return i_top + 1; }
_Ty top() const { return Impl[i_top]; }
_Ty GetMotionSlot(int slot) const { return Impl[slot]; }
@@ -158,10 +160,11 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void MoveTakeoff(uint32 id, Position const& pos, float speed);
void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE);
- void MoveFall(float z, uint32 id = 0);
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
void MoveJumpTo(float angle, float speedXY, float speedZ);
- void MoveJump(float x, float y, float z, float speedXY, float speedZ);
+ void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = 0);
+ void MoveFall();
+
void MoveSeekAssistance(float x, float y, float z);
void MoveSeekAssistanceDistract(uint32 timer);
void MoveTaxiFlight(uint32 path, uint32 pathnode);
diff --git a/src/server/game/Movement/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp
index 103b8876959..73921ea86ff 100755
--- a/src/server/game/Movement/MovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerator.cpp
@@ -21,4 +21,3 @@
MovementGenerator::~MovementGenerator()
{
}
-
diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h
index 06450d938ae..dd9ba32f337 100755
--- a/src/server/game/Movement/MovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerator.h
@@ -43,8 +43,6 @@ class MovementGenerator
virtual MovementGeneratorType GetMovementGeneratorType() = 0;
virtual void unitSpeedChanged() { }
-
- virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; }
};
template<class T, class D>
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
index bf5c8bafc49..ac09f2d403a 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
@@ -18,10 +18,10 @@
#include "Creature.h"
#include "MapManager.h"
-#include "Opcodes.h"
#include "ConfusedMovementGenerator.h"
-#include "DestinationHolderImp.h"
#include "VMapFactory.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
#ifdef MAP_BASED_RAND_GEN
#define rand_norm() unit.rand_norm()
@@ -31,8 +31,8 @@
template<class T>
void ConfusedMovementGenerator<T>::Initialize(T &unit)
{
- float const wanderDistance = 4;
- float x, y, z;
+ const float wander_distance=4;
+ float x,y,z;
x = unit.GetPositionX();
y = unit.GetPositionY();
z = unit.GetPositionZ();
@@ -44,52 +44,33 @@ void ConfusedMovementGenerator<T>::Initialize(T &unit)
bool is_water_ok, is_land_ok;
_InitSpecific(unit, is_water_ok, is_land_ok);
- for (uint8 idx = 0; idx <= MAX_CONF_WAYPOINTS; ++idx)
+ for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS + 1; ++idx)
{
- float wanderX = x + wanderDistance * (float)rand_norm() - wanderDistance/2;
- float wanderY = y + wanderDistance * (float)rand_norm() - wanderDistance/2;
- Trinity::NormalizeMapCoord(wanderX);
- Trinity::NormalizeMapCoord(wanderY);
+ const float wanderX=wander_distance*(float)rand_norm() - wander_distance/2;
+ const float wanderY=wander_distance*(float)rand_norm() - wander_distance/2;
- float new_z = map->GetHeight(wanderX, wanderY, z, true);
- if (new_z > INVALID_HEIGHT && unit.IsWithinLOS(wanderX, wanderY, new_z))
- {
- // Don't move in water if we're not already in
- // Don't move on land if we're not already on it either
- bool is_water_now = map->IsInWater(x, y, z);
- bool is_water_next = map->IsInWater(wanderX, wanderY, new_z);
- if ((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok))
- {
- i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; // Back to previous location
- i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
- i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z;
- continue;
- }
-
- // Taken from FleeingMovementGenerator
- if (!(new_z - z) || wanderDistance / fabs(new_z - z) > 1.0f)
- {
- i_waypoints[idx][0] = wanderX;
- i_waypoints[idx][1] = wanderY;
- i_waypoints[idx][2] = new_z;
- continue;
- }
- }
- else // Back to previous location
+ i_waypoints[idx][0] = x + wanderX;
+ i_waypoints[idx][1] = y + wanderY;
+
+ // prevent invalid coordinates generation
+ Trinity::NormalizeMapCoord(i_waypoints[idx][0]);
+ Trinity::NormalizeMapCoord(i_waypoints[idx][1]);
+
+ bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z);
+ // if generated wrong path just ignore
+ if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
{
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
- i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z;
- continue;
}
+
+ unit.UpdateAllowedPositionZ(i_waypoints[idx][0], i_waypoints[idx][1], z);
+ i_waypoints[idx][2] = z;
}
- unit.SetTarget(0);
- unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
- unit.CastStop();
unit.StopMoving();
- unit.AddUnitMovementFlag(MOVEMENTFLAG_WALKING); // Should actually be splineflag
- unit.AddUnitState(UNIT_STAT_CONFUSED);
+ unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
+ unit.AddUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
}
template<>
@@ -111,69 +92,70 @@ void ConfusedMovementGenerator<T>::Reset(T &unit)
{
i_nextMove = 1;
i_nextMoveTime.Reset(0);
- i_destinationHolder.ResetUpdate();
unit.StopMoving();
+ unit.AddUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
}
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;
-
if (unit.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
return true;
if (i_nextMoveTime.Passed())
{
// currently moving, update location
- Traveller<T> traveller(unit);
- if (i_destinationHolder.UpdateTraveller(traveller, diff))
+ unit.AddUnitState(UNIT_STAT_CONFUSED_MOVE);
+
+ if (unit.movespline->Finalized())
{
- if (i_destinationHolder.HasArrived())
- {
- // arrived, stop and wait a bit
- unit.ClearUnitState(UNIT_STAT_MOVE);
-
- i_nextMove = urand(1, MAX_CONF_WAYPOINTS);
- i_nextMoveTime.Reset(urand(100, 1000));
- }
+ 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
{
// waiting for next move
i_nextMoveTime.Update(diff);
- if (i_nextMoveTime.Passed())
+ if(i_nextMoveTime.Passed() )
{
// start moving
- ASSERT(i_nextMove <= MAX_CONF_WAYPOINTS);
- const float x = i_waypoints[i_nextMove][0];
- const float y = i_waypoints[i_nextMove][1];
- const float z = i_waypoints[i_nextMove][2];
- Traveller<T> traveller(unit);
- i_destinationHolder.SetDestination(traveller, x, y, z);
+ unit.AddUnitState(UNIT_STAT_CONFUSED_MOVE);
+
+ ASSERT( i_nextMove <= MAX_CONF_WAYPOINTS );
+ float x = i_waypoints[i_nextMove][0];
+ float y = i_waypoints[i_nextMove][1];
+ float z = i_waypoints[i_nextMove][2];
+ Movement::MoveSplineInit init(unit);
+ init.MoveTo(x, y, z);
+ init.SetWalk(true);
+ init.Launch();
}
}
+
return true;
}
-template<class T>
-void ConfusedMovementGenerator<T>::Finalize(T &unit)
+template<>
+void ConfusedMovementGenerator<Player>::Finalize(Player &unit)
{
unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
- unit.ClearUnitState(UNIT_STAT_CONFUSED);
+ unit.ClearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
+}
- if (unit.GetTypeId() == TYPEID_UNIT && unit.getVictim())
+template<>
+void ConfusedMovementGenerator<Creature>::Finalize(Creature &unit)
+{
+ unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
+ unit.ClearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
+ if (unit.getVictim())
unit.SetTarget(unit.getVictim()->GetGUID());
}
template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
template void ConfusedMovementGenerator<Creature>::Initialize(Creature &creature);
-template void ConfusedMovementGenerator<Player>::Finalize(Player &player);
-template void ConfusedMovementGenerator<Creature>::Finalize(Creature &creature);
template void ConfusedMovementGenerator<Player>::Reset(Player &player);
template void ConfusedMovementGenerator<Creature>::Reset(Creature &creature);
-template bool ConfusedMovementGenerator<Player>::Update(Player &player, const uint32 diff);
-template bool ConfusedMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff);
+template bool ConfusedMovementGenerator<Player>::Update(Player &player, const uint32 &diff);
+template bool ConfusedMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff);
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
index d3981ee2dcf..b9f96bb785d 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
@@ -20,8 +20,7 @@
#define TRINITY_CONFUSEDGENERATOR_H
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
-#include "Traveller.h"
+#include "Timer.h"
#define MAX_CONF_WAYPOINTS 24
@@ -35,21 +34,13 @@ class ConfusedMovementGenerator
void Initialize(T &);
void Finalize(T &);
void Reset(T &);
- bool Update(T &, const uint32);
-
- bool GetDestination(float &x, float &y, float &z) const
- {
- if (i_destinationHolder.HasArrived()) return false;
- i_destinationHolder.GetDestination(x, y, z);
- return true;
- }
+ bool Update(T &, const uint32 &);
MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
private:
void _InitSpecific(T &, bool &, bool &);
TimeTracker i_nextMoveTime;
float i_waypoints[MAX_CONF_WAYPOINTS+1][3];
- DestinationHolder< Traveller<T> > i_destinationHolder;
uint32 i_nextMove;
};
#endif
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index d2b3fcee384..458e6f9a62c 100755
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -20,8 +20,9 @@
#include "CreatureAI.h"
#include "MapManager.h"
#include "FleeingMovementGenerator.h"
-#include "DestinationHolderImp.h"
#include "ObjectAccessor.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
#define MIN_QUIET_DISTANCE 28.0f
#define MAX_QUIET_DISTANCE 43.0f
@@ -43,25 +44,12 @@ FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
if (!_getPoint(owner, x, y, z))
return;
- owner.AddUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
- Traveller<T> traveller(owner);
- i_destinationHolder.SetDestination(traveller, x, y, z);
-}
-
-template<>
-bool FleeingMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
-{
- if (i_destinationHolder.HasArrived())
- return false;
+ owner.AddUnitState(UNIT_STAT_FLEEING_MOVE);
- i_destinationHolder.GetDestination(x, y, z);
- return true;
-}
-
-template<>
-bool FleeingMovementGenerator<Player>::GetDestination(float & /*x*/, float & /*y*/, float & /*z*/) const
-{
- return false;
+ Movement::MoveSplineInit init(owner);
+ init.MoveTo(x,y,z);
+ init.SetWalk(false);
+ init.Launch();
}
template<class T>
@@ -75,10 +63,10 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
y = owner.GetPositionY();
z = owner.GetPositionZ();
- float temp_x, temp_y, angle = 0;
+ float temp_x, temp_y, angle;
const Map* _map = owner.GetBaseMap();
//primitive path-finding
- for (uint8 i = 0; i < 18; ++i)
+ for(uint8 i = 0; i < 18; ++i)
{
if (i_only_forward && i > 2)
break;
@@ -143,11 +131,11 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
distance /= 4;
break;
case 15:
- angle = i_cur_angle + static_cast<float>(M_PI*3/4);
+ angle = i_cur_angle + static_cast<float>(3*M_PI/4);
distance /= 2;
break;
case 16:
- angle = i_cur_angle - static_cast<float>(M_PI*3/4);
+ angle = i_cur_angle - static_cast<float>(3*M_PI/4);
distance /= 2;
break;
case 17:
@@ -161,9 +149,9 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
Trinity::NormalizeMapCoord(temp_y);
if (owner.IsWithinLOS(temp_x, temp_y, z))
{
- bool is_water_now = _map->IsInWater(x, y, z);
+ bool is_water_now = _map->IsInWater(x,y,z);
- if (is_water_now && _map->IsInWater(temp_x, temp_y, z))
+ if (is_water_now && _map->IsInWater(temp_x,temp_y,z))
{
x = temp_x;
y = temp_y;
@@ -181,8 +169,8 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
if (!(new_z - z) || distance / fabs(new_z - z) > 1.0f)
{
- float new_z_left = _map->GetHeight(temp_x + (float)(cos(angle+M_PI/2)), temp_y + (float)(sin(angle+M_PI/2)), z, true);
- float new_z_right = _map->GetHeight(temp_x + (float)(cos(angle-M_PI/2)), temp_y + (float)(sin(angle-M_PI/2)), z, true);
+ float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle+static_cast<float>(M_PI/2)),z,true);
+ float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle-static_cast<float>(M_PI/2)),z,true);
if (fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f)
{
x = temp_x;
@@ -194,7 +182,7 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
}
}
i_to_distance_from_caster = 0.0f;
- i_nextCheckTime.Reset(urand(500, 1000));
+ i_nextCheckTime.Reset( urand(500,1000) );
return false;
}
@@ -213,12 +201,12 @@ FleeingMovementGenerator<T>::_setMoveData(T &owner)
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
// if we reach bigger distance
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
- (i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE))
+ (i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE) )
// if we leave 'quiet zone'
{
// we are very far or too close, stopping
i_to_distance_from_caster = 0.0f;
- i_nextCheckTime.Reset(urand(500, 1000));
+ i_nextCheckTime.Reset( urand(500,1000) );
return false;
}
else
@@ -232,9 +220,7 @@ FleeingMovementGenerator<T>::_setMoveData(T &owner)
float cur_dist;
float angle_to_caster;
- Unit* fright = ObjectAccessor::GetUnit(owner, i_frightGUID);
-
- if (fright)
+ if (Unit* fright = ObjectAccessor::GetUnit(owner, i_frightGUID))
{
cur_dist = fright->GetDistance(&owner);
if (cur_dist < cur_dist_xyz)
@@ -284,7 +270,7 @@ FleeingMovementGenerator<T>::_setMoveData(T &owner)
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
}
- int8 sign = rand_norm() > 0.5f ? 1 : -1;
+ int8 sign = (float)rand_norm() > 0.5f ? 1 : -1;
i_cur_angle = sign*angle + angle_to_caster;
// current distance
@@ -300,14 +286,12 @@ FleeingMovementGenerator<T>::Initialize(T &owner)
if (!&owner)
return;
- _Init(owner);
- owner.CastStop();
- owner.AddUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
owner.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
- owner.SetTarget(0);
- owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ owner.AddUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE);
- if (Unit* fright = ObjectAccessor::GetUnit(owner, i_frightGUID))
+ _Init(owner);
+
+ if (Unit *fright = ObjectAccessor::GetUnit(owner, i_frightGUID))
{
i_caster_x = fright->GetPositionX();
i_caster_y = fright->GetPositionY();
@@ -334,6 +318,7 @@ FleeingMovementGenerator<Creature>::_Init(Creature &owner)
if (!&owner)
return;
+ //owner.SetTargetGuid(ObjectGuid());
is_water_ok = owner.canSwim();
is_land_ok = owner.canWalk();
}
@@ -346,51 +331,44 @@ FleeingMovementGenerator<Player>::_Init(Player &)
is_land_ok = true;
}
-template<class T>
-void
-FleeingMovementGenerator<T>::Finalize(T &owner)
+template<>
+void FleeingMovementGenerator<Player>::Finalize(Player &owner)
+{
+ owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
+ owner.ClearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE);
+}
+
+template<>
+void FleeingMovementGenerator<Creature>::Finalize(Creature &owner)
{
owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
- owner.ClearUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
- if (owner.GetTypeId() == TYPEID_UNIT && owner.getVictim())
+ owner.ClearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE);
+ if (owner.getVictim())
owner.SetTarget(owner.getVictim()->GetGUID());
}
template<class T>
-void
-FleeingMovementGenerator<T>::Reset(T &owner)
+void FleeingMovementGenerator<T>::Reset(T &owner)
{
Initialize(owner);
}
template<class T>
bool
-FleeingMovementGenerator<T>::Update(T &owner, const uint32 time_diff)
+FleeingMovementGenerator<T>::Update(T &owner, const uint32 &time_diff)
{
if (!&owner || !owner.isAlive())
return false;
if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
+ {
+ owner.ClearUnitState(UNIT_STAT_FLEEING_MOVE);
return true;
-
- Traveller<T> traveller(owner);
+ }
i_nextCheckTime.Update(time_diff);
-
- if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || !i_destinationHolder.HasDestination())
- {
+ if (i_nextCheckTime.Passed() && owner.movespline->Finalized())
_setTargetLocation(owner);
- return true;
- }
- if (i_destinationHolder.UpdateTraveller(traveller, time_diff))
- {
- i_destinationHolder.ResetUpdate(50);
- if (i_nextCheckTime.Passed() && i_destinationHolder.HasArrived())
- {
- _setTargetLocation(owner);
- return true;
- }
- }
return true;
}
@@ -402,17 +380,15 @@ template bool FleeingMovementGenerator<Player>::_getPoint(Player &, float &, flo
template bool FleeingMovementGenerator<Creature>::_getPoint(Creature &, float &, float &, float &);
template void FleeingMovementGenerator<Player>::_setTargetLocation(Player &);
template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature &);
-template void FleeingMovementGenerator<Player>::Finalize(Player &);
-template void FleeingMovementGenerator<Creature>::Finalize(Creature &);
template void FleeingMovementGenerator<Player>::Reset(Player &);
template void FleeingMovementGenerator<Creature>::Reset(Creature &);
-template bool FleeingMovementGenerator<Player>::Update(Player &, const uint32);
-template bool FleeingMovementGenerator<Creature>::Update(Creature &, const uint32);
+template bool FleeingMovementGenerator<Player>::Update(Player &, const uint32 &);
+template bool FleeingMovementGenerator<Creature>::Update(Creature &, const uint32 &);
void TimedFleeingMovementGenerator::Finalize(Unit &owner)
{
owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
- owner.ClearUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING);
+ owner.ClearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE);
if (Unit* victim = owner.getVictim())
{
if (owner.isAlive())
@@ -429,13 +405,20 @@ bool TimedFleeingMovementGenerator::Update(Unit & owner, const uint32 time_diff)
return false;
if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
+ {
+ owner.ClearUnitState(UNIT_STAT_FLEEING_MOVE);
return true;
+ }
+
+ i_totalFleeTime.Update(time_diff);
+ if (i_totalFleeTime.Passed())
+ return false;
i_totalFleeTime.Update(time_diff);
if (i_totalFleeTime.Passed())
return false;
- // This calls grant-parent Update method hiden by FleeingMovementGenerator::Update(Creature &, const uint32) version
+ // This calls grant-parent Update method hiden by FleeingMovementGenerator::Update(Creature &, const uint32 &) version
// This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly
return MovementGeneratorMedium< Creature, FleeingMovementGenerator<Creature> >::Update(owner, time_diff);
}
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
index 4d4631fe932..750db52bb5a 100755
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
@@ -20,8 +20,6 @@
#define TRINITY_FLEEINGMOVEMENTGENERATOR_H
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
-#include "Traveller.h"
template<class T>
class FleeingMovementGenerator
@@ -33,8 +31,7 @@ class FleeingMovementGenerator
void Initialize(T &);
void Finalize(T &);
void Reset(T &);
- bool Update(T &, const uint32);
- bool GetDestination(float &x, float &y, float &z) const;
+ bool Update(T &, const uint32 &);
MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
@@ -56,8 +53,6 @@ class FleeingMovementGenerator
float i_cur_angle;
uint64 i_frightGUID;
TimeTracker i_nextCheckTime;
-
- DestinationHolder< Traveller<T> > i_destinationHolder;
};
class TimedFleeingMovementGenerator
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index 16153dd6ccb..84997d6d1ae 100755
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -19,22 +19,16 @@
#include "HomeMovementGenerator.h"
#include "Creature.h"
#include "CreatureAI.h"
-#include "Traveller.h"
-#include "DestinationHolderImp.h"
#include "WorldPacket.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
void HomeMovementGenerator<Creature>::Initialize(Creature & owner)
{
- owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
owner.AddUnitState(UNIT_STAT_EVADE);
_setTargetLocation(owner);
}
-void HomeMovementGenerator<Creature>::Finalize(Creature & owner)
-{
- owner.ClearUnitState(UNIT_STAT_EVADE);
-}
-
void HomeMovementGenerator<Creature>::Reset(Creature &)
{
}
@@ -47,42 +41,35 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
return;
- float x, y, z;
- owner.GetHomePosition(x, y, z, ori);
+ Movement::MoveSplineInit init(owner);
+ float x, y, z, o;
+ // 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))
+ //{
+ owner.GetHomePosition(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(uint32(UNIT_STAT_ALL_STATE & ~UNIT_STAT_EVADE));
+ arrived = false;
+ owner.ClearUnitState(UNIT_STAT_ALL_STATE & ~UNIT_STAT_EVADE);
}
bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32 time_diff)
{
- CreatureTraveller traveller(owner);
- i_destinationHolder.UpdateTraveller(traveller, time_diff);
+ arrived = owner.movespline->Finalized();
+ return !arrived;
+}
- if (time_diff > i_travel_timer)
+void HomeMovementGenerator<Creature>::Finalize(Creature& owner)
+{
+ if (arrived)
{
- owner.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
-
- // restore orientation of not moving creature at returning to home
- if (owner.GetDefaultMovementType() == IDLE_MOTION_TYPE)
- {
- //sLog->outDebug("Entering HomeMovement::GetDestination(z, y, z)");
- owner.SetOrientation(ori);
- WorldPacket packet;
- owner.BuildHeartBeatMsg(&packet);
- owner.SendMessageToSet(&packet, false);
- }
-
owner.ClearUnitState(UNIT_STAT_EVADE);
+ owner.SetWalk(true);
owner.LoadCreaturesAddon(true);
owner.AI()->JustReachedHome();
- return false;
}
-
- i_travel_timer -= time_diff;
-
- return true;
}
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
index ba34899dee5..c724edc91ff 100755
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
@@ -20,8 +20,6 @@
#define TRINITY_HOMEMOVEMENTGENERATOR_H
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
-#include "Traveller.h"
class Creature;
@@ -34,24 +32,18 @@ class HomeMovementGenerator<Creature>
{
public:
- HomeMovementGenerator() {}
+ HomeMovementGenerator() : arrived(false) {}
~HomeMovementGenerator() {}
void Initialize(Creature &);
void Finalize(Creature &);
void Reset(Creature &);
bool Update(Creature &, const uint32);
- void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; }
MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; }
- bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x, y, z); return true; }
-
private:
void _setTargetLocation(Creature &);
- DestinationHolder< Traveller<Creature> > i_destinationHolder;
-
- float ori;
- uint32 i_travel_timer;
+ bool arrived;
};
#endif
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
index af2207ae141..505615c07b8 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -20,84 +20,83 @@
#include "Errors.h"
#include "Creature.h"
#include "CreatureAI.h"
-#include "DestinationHolderImp.h"
#include "World.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
//----- Point Movement Generator
template<class T>
void PointMovementGenerator<T>::Initialize(T &unit)
{
- unit.StopMoving();
- Traveller<T> traveller(unit);
- // OLD: knockback effect has UNIT_STAT_JUMPING set, so if here we disable sentmonstermove there will be creature position sync problem between client and server
- // NEW: reactivated this check - UNIT_STAT_JUMPING is only used in MoveJump, which sends its own packet
- i_destinationHolder.SetDestination(traveller, i_x, i_y, i_z, /*true*/ !unit.HasUnitState(UNIT_STAT_JUMPING));
+ if (!unit.IsStopped())
+ unit.StopMoving();
+
+ unit.AddUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
+ Movement::MoveSplineInit init(unit);
+ init.MoveTo(i_x, i_y, i_z);
+ if (speed > 0.0f)
+ init.SetVelocity(speed);
+ init.Launch();
}
template<class T>
-bool PointMovementGenerator<T>::Update(T &unit, const uint32 diff)
+bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
if (!&unit)
return false;
- if (unit.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
+ if(unit.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED))
{
- if (unit.HasUnitState(UNIT_STAT_CHARGING))
- return false;
- else
- return true;
+ unit.ClearUnitState(UNIT_STAT_ROAMING_MOVE);
+ return true;
}
- Traveller<T> traveller(unit);
-
- i_destinationHolder.UpdateTraveller(traveller, diff);
-
- if (i_destinationHolder.HasArrived())
- {
- unit.ClearUnitState(UNIT_STAT_MOVE);
- arrived = true;
- return false;
- }
- else if (!unit.HasUnitState(UNIT_STAT_MOVE) && !unit.HasUnitState(UNIT_STAT_JUMPING))
- {
- i_destinationHolder.StartTravel(traveller);
- }
-
- return true;
+ unit.AddUnitState(UNIT_STAT_ROAMING_MOVE);
+ return !unit.movespline->Finalized();
}
template<class T>
void PointMovementGenerator<T>:: Finalize(T &unit)
{
- if (unit.HasUnitState(UNIT_STAT_CHARGING))
- unit.ClearUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING);
- if (arrived) // without this crash!
+ unit.ClearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
+
+ if (unit.movespline->Finalized())
MovementInform(unit);
}
template<class T>
+void PointMovementGenerator<T>::Reset(T &unit)
+{
+ if (!unit.IsStopped())
+ unit.StopMoving();
+
+ unit.AddUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
+}
+
+template<class T>
void PointMovementGenerator<T>::MovementInform(T & /*unit*/)
{
}
template <> void PointMovementGenerator<Creature>::MovementInform(Creature &unit)
{
- if (id == EVENT_FALL_GROUND)
- {
- unit.setDeathState(JUST_DIED);
- unit.SetFlying(true);
- }
- unit.AI()->MovementInform(POINT_MOTION_TYPE, id);
+ //if (id == EVENT_FALL_GROUND)
+ //{
+ // unit.setDeathState(JUST_DIED);
+ // unit.SetFlying(true);
+ //}
+ if (unit.AI())
+ unit.AI()->MovementInform(POINT_MOTION_TYPE, id);
}
template void PointMovementGenerator<Player>::Initialize(Player&);
-template bool PointMovementGenerator<Player>::Update(Player &, const uint32 diff);
-template void PointMovementGenerator<Player>::MovementInform(Player&);
-template void PointMovementGenerator<Player>::Finalize(Player&);
-
template void PointMovementGenerator<Creature>::Initialize(Creature&);
-template bool PointMovementGenerator<Creature>::Update(Creature&, const uint32 diff);
+template void PointMovementGenerator<Player>::Finalize(Player&);
template void PointMovementGenerator<Creature>::Finalize(Creature&);
+template void PointMovementGenerator<Player>::Reset(Player&);
+template void PointMovementGenerator<Creature>::Reset(Creature&);
+template bool PointMovementGenerator<Player>::Update(Player &, const uint32 &);
+template bool PointMovementGenerator<Creature>::Update(Creature&, const uint32 &);
void AssistanceMovementGenerator::Finalize(Unit &unit)
{
@@ -107,3 +106,24 @@ void AssistanceMovementGenerator::Finalize(Unit &unit)
unit.GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY));
}
+bool EffectMovementGenerator::Update(Unit &unit, const uint32)
+{
+ return !unit.movespline->Finalized();
+}
+
+void EffectMovementGenerator::Finalize(Unit &unit)
+{
+ if (unit.GetTypeId() != TYPEID_UNIT)
+ return;
+
+ if (((Creature&)unit).AI() && unit.movespline->Finalized())
+ ((Creature&)unit).AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id);
+ // Need restore previous movement since we have no proper states system
+ //if (unit.isAlive() && !unit.HasUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_FLEEING))
+ //{
+ // if (Unit * victim = unit.getVictim())
+ // unit.GetMotionMaster()->MoveChase(victim);
+ // else
+ // unit.GetMotionMaster()->Initialize();
+ //}
+}
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
index 2504f1a38e3..e47f3d93450 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
@@ -20,8 +20,6 @@
#define TRINITY_POINTMOVEMENTGENERATOR_H
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
-#include "Traveller.h"
#include "FollowerReference.h"
template<class T>
@@ -29,13 +27,13 @@ class PointMovementGenerator
: public MovementGeneratorMedium< T, PointMovementGenerator<T> >
{
public:
- PointMovementGenerator(uint32 _id, float _x, float _y, float _z) : id(_id),
- i_x(_x), i_y(_y), i_z(_z), i_nextMoveTime(0), arrived(false) {}
+ PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f) : id(_id),
+ i_x(_x), i_y(_y), i_z(_z), speed(_speed) {}
void Initialize(T &);
- void Finalize(T &unit);
- void Reset(T &unit){unit.StopMoving();}
- bool Update(T &, const uint32 diff);
+ void Finalize(T &);
+ void Reset(T &);
+ bool Update(T &, const uint32 &);
void MovementInform(T &);
@@ -45,9 +43,7 @@ class PointMovementGenerator
private:
uint32 id;
float i_x, i_y, i_z;
- TimeTracker i_nextMoveTime;
- DestinationHolder< Traveller<T> > i_destinationHolder;
- bool arrived;
+ float speed;
};
class AssistanceMovementGenerator
@@ -61,5 +57,19 @@ class AssistanceMovementGenerator
void Finalize(Unit &);
};
+// Does almost nothing - just doesn't allows previous movegen interrupt current effect.
+class EffectMovementGenerator : public MovementGenerator
+{
+ public:
+ explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {}
+ void Initialize(Unit &) {}
+ void Finalize(Unit &unit);
+ void Reset(Unit &) {}
+ bool Update(Unit &u, const uint32);
+ MovementGeneratorType GetMovementGeneratorType() { return EFFECT_MOTION_TYPE; }
+ private:
+ uint32 m_Id;
+};
+
#endif
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index 981ec031cf9..0205b734058 100755
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -19,123 +19,103 @@
#include "Creature.h"
#include "MapManager.h"
#include "RandomMovementGenerator.h"
-#include "Traveller.h"
#include "ObjectAccessor.h"
-#include "DestinationHolderImp.h"
#include "Map.h"
#include "Util.h"
#include "CreatureGroups.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV"
-template<>
-bool
-RandomMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
-{
- if (i_destinationHolder.HasArrived())
- return false;
-
- i_destinationHolder.GetDestination(x, y, z);
- return true;
-}
-
#ifdef MAP_BASED_RAND_GEN
#define rand_norm() creature.rand_norm()
#endif
template<>
-void
-RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
+void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
- float X, Y, Z, nx, ny, nz, ori, dist;
-
- creature.GetHomePosition(X, Y, Z, ori);
-
+ float respX, respY, respZ, respO, currZ, destX, destY, destZ, travelDistZ;
+ creature.GetHomePosition(respX, respY, respZ, respO);
+ currZ = creature.GetPositionZ();
Map const* map = creature.GetBaseMap();
// For 2D/3D system selection
- //bool is_land_ok = creature.canWalk();
- //bool is_water_ok = creature.canSwim();
- bool is_air_ok = creature.canFly();
+ //bool is_land_ok = creature.CanWalk(); // not used?
+ //bool is_water_ok = creature.CanSwim(); // not used?
+ bool is_air_ok = creature.canFly();
- for (uint32 i = 0; ; ++i)
- {
- const float angle = (float)rand_norm()*static_cast<float>(M_PI*2);
- const float range = (float)rand_norm()*wander_distance;
- const float distanceX = range * cos(angle);
- const float distanceY = range * sin(angle);
+ const float angle = float(rand_norm()) * static_cast<float>(M_PI*2.0f);
+ const float range = float(rand_norm()) * wander_distance;
+ const float distanceX = range * cos(angle);
+ const float distanceY = range * sin(angle);
- nx = X + distanceX;
- ny = Y + distanceY;
+ destX = respX + distanceX;
+ destY = respY + distanceY;
- // prevent invalid coordinates generation
- Trinity::NormalizeMapCoord(nx);
- Trinity::NormalizeMapCoord(ny);
+ // prevent invalid coordinates generation
+ Trinity::NormalizeMapCoord(destX);
+ Trinity::NormalizeMapCoord(destY);
- dist = (nx - X)*(nx - X) + (ny - Y)*(ny - Y);
+ travelDistZ = distanceX*distanceX + distanceY*distanceY;
- if (i == 5)
- {
- nz = Z;
- break;
- }
+ if (is_air_ok) // 3D system above ground and above water (flying mode)
+ {
+ // Limit height change
+ const float distanceZ = float(rand_norm()) * sqrtf(travelDistZ)/2.0f;
+ destZ = respZ + distanceZ;
+ float levelZ = map->GetWaterOrGroundLevel(destX, destY, destZ-2.0f);
+
+ // Problem here, we must fly above the ground and water, not under. Let's try on next tick
+ if (levelZ >= destZ)
+ return;
+ }
+ //else if (is_water_ok) // 3D system under water and above ground (swimming mode)
+ else // 2D only
+ {
+ // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
+ travelDistZ = travelDistZ >= 100.0f ? 10.0f : sqrtf(travelDistZ);
- if (is_air_ok) // 3D system above ground and above water (flying mode)
- {
- const float distanceZ = (float)(rand_norm()) * sqrtf(dist)/2; // Limit height change
- nz = Z + distanceZ;
- float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
- float wz = map->GetWaterLevel(nx, ny);
- if (tz >= nz || wz >= nz)
- continue; // Problem here, we must fly above the ground and water, not under. Let's try on next tick
- }
- //else if (is_water_ok) // 3D system under water and above ground (swimming mode)
- else // 2D only
+ // The fastest way to get an accurate result 90% of the time.
+ // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
+ destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, false);
+
+ if (fabs(destZ - respZ) > travelDistZ) // Map check
{
- dist = dist >= 100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
+ // Vmap Horizontal or above
+ destZ = map->GetHeight(destX, destY, respZ - 2.0f, true);
- // The fastest way to get an accurate result 90% of the time.
- // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
- nz = map->GetHeight(nx, ny, Z+dist-2.0f, false); // Map check
- if (fabs(nz-Z)>dist)
+ if (fabs(destZ - respZ) > travelDistZ)
{
- nz = map->GetHeight(nx, ny, Z-2.0f, true); // Vmap Horizontal or above
- if (fabs(nz-Z)>dist)
- {
- nz = map->GetHeight(nx, ny, Z+dist-2.0f, true); // Vmap Higher
- if (fabs(nz-Z)>dist)
- continue; // let's forget this bad coords where a z cannot be find and retry at next tick
- }
+ // Vmap Higher
+ destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, true);
+
+ // let's forget this bad coords where a z cannot be find and retry at next tick
+ if (fabs(destZ - respZ) > travelDistZ)
+ return;
}
}
- break;
}
- Traveller<Creature> traveller(creature);
- creature.SetOrientation(creature.GetAngle(nx, ny));
- i_destinationHolder.SetDestination(traveller, nx, ny, nz);
- creature.AddUnitState(UNIT_STAT_ROAMING);
if (is_air_ok)
- {
- i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
- }
- //else if (is_water_ok) // Swimming mode to be done with more than this check
+ i_nextMoveTime.Reset(0);
else
- {
- i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(), 5000+i_destinationHolder.GetTotalTravelTime()));
- creature.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
- }
+ i_nextMoveTime.Reset(urand(500, 10000));
+
+ creature.AddUnitState(UNIT_STAT_ROAMING_MOVE);
+
+ Movement::MoveSplineInit init(creature);
+ init.MoveTo(destX, destY, destZ);
+ init.SetWalk(true);
+ init.Launch();
//Call for creature group update
if (creature.GetFormation() && creature.GetFormation()->getLeader() == &creature)
- {
- creature.GetFormation()->LeaderMoveTo(nx, ny, nz);
- }
+ creature.GetFormation()->LeaderMoveTo(destX, destY, destZ);
}
template<>
-void
-RandomMovementGenerator<Creature>::Initialize(Creature &creature)
+void RandomMovementGenerator<Creature>::Initialize(Creature &creature)
{
if (!creature.isAlive())
return;
@@ -143,8 +123,7 @@ RandomMovementGenerator<Creature>::Initialize(Creature &creature)
if (!wander_distance)
wander_distance = creature.GetRespawnRadius();
- if (irand(0, RUNNING_CHANCE_RANDOMMV) > 0)
- creature.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ creature.AddUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
_setRandomLocation(creature);
}
@@ -156,8 +135,11 @@ RandomMovementGenerator<Creature>::Reset(Creature &creature)
}
template<>
-void
-RandomMovementGenerator<Creature>::Finalize(Creature & /*creature*/){}
+void RandomMovementGenerator<Creature>::Finalize(Creature &creature)
+{
+ creature.ClearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
+ creature.SetWalk(false);
+}
template<>
bool
@@ -165,35 +147,29 @@ RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff)
{
if (creature.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
{
- i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer
- creature.ClearUnitState(UNIT_STAT_ROAMING);
+ i_nextMoveTime.Reset(0); // Expire the timer
+ creature.ClearUnitState(UNIT_STAT_ROAMING_MOVE);
return true;
}
- i_nextMoveTime.Update(diff);
-
- if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
- creature.ClearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_MOVE);
-
- if (!i_destinationHolder.HasArrived() && creature.IsStopped())
- creature.AddUnitState(UNIT_STAT_ROAMING);
-
- CreatureTraveller traveller(creature);
-
- if (i_destinationHolder.UpdateTraveller(traveller, diff, true))
+ if (creature.movespline->Finalized())
{
+ i_nextMoveTime.Update(diff);
if (i_nextMoveTime.Passed())
- {
- if (irand(0, RUNNING_CHANCE_RANDOMMV) > 0)
- creature.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
_setRandomLocation(creature);
- }
- else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f))
- {
- creature.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
- _setRandomLocation(creature);
- }
}
return true;
}
+template<>
+bool RandomMovementGenerator<Creature>::GetResetPosition(Creature &creature, float& x, float& y, float& z)
+{
+ float radius;
+ creature.GetRespawnPosition(x, y, z, NULL, &radius);
+
+ // use current if in range
+ if (creature.IsWithinDist2d(x,y,radius))
+ creature.GetPosition(x,y,z);
+
+ return true;
+}
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
index 816e325f3b1..67161b6fc29 100755
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
@@ -20,15 +20,12 @@
#define TRINITY_RANDOMMOTIONGENERATOR_H
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
-#include "Traveller.h"
template<class T>
class RandomMovementGenerator
: public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
{
public:
- // Wander dist is related on db spawn dist. So what if we wanna set eandom movement on summoned creature?!
RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) {}
void _setRandomLocation(T &);
@@ -36,18 +33,13 @@ class RandomMovementGenerator
void Finalize(T &);
void Reset(T &);
bool Update(T &, const uint32);
- bool GetDestination(float &x, float &y, float &z) const;
- void UpdateMapPosition(uint32 mapid, float &x, float &y, float &z)
- {
- i_destinationHolder.GetLocationNow(mapid, x, y, z);
- }
+ bool GetResetPosition(T&, float& x, float& y, float& z);
MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; }
private:
TimeTrackerSmall i_nextMoveTime;
- DestinationHolder< Traveller<T> > i_destinationHolder;
- float wander_distance;
uint32 i_nextMove;
+ float wander_distance;
};
#endif
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index e0ca5231000..bded2fd512c 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -21,106 +21,42 @@
#include "Errors.h"
#include "Creature.h"
#include "CreatureAI.h"
-#include "DestinationHolderImp.h"
#include "World.h"
-
-#define SMALL_ALPHA 0.05f
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
#include <cmath>
-/*
-struct StackCleaner
-{
- Creature &i_creature;
- StackCleaner(Creature &creature) : i_creature(creature) {}
- void Done(void) { i_creature.StopMoving(); }
- ~StackCleaner()
- {
- i_creature->Clear();
- }
-};
-*/
-template<class T>
-TargetedMovementGenerator<T>::TargetedMovementGenerator(Unit &target, float offset, float angle)
-: TargetedMovementGeneratorBase(target)
-, i_offset(offset), i_angle(angle), i_recalculateTravel(false)
-{
- target.GetPosition(i_targetX, i_targetY, i_targetZ);
-}
-
-template<class T>
-bool
-TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
+template<class T, typename D>
+void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
{
if (!i_target.isValid() || !i_target->IsInWorld())
- return false;
+ return;
- if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
- return false;
+ if (owner.HasUnitState(UNIT_STAT_NOT_MOVE))
+ return;
float x, y, z;
- Traveller<T> traveller(owner);
- if (i_destinationHolder.HasDestination())
+
+ if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
{
- if (i_destinationHolder.HasArrived())
- {
- // prevent redundant micro-movement
- if (!i_offset)
- {
- if (i_target->IsWithinMeleeRange(&owner))
- return false;
- }
- else if (!i_angle && !owner.HasUnitState(UNIT_STAT_FOLLOW))
- {
- if (i_target->IsWithinDistInMap(&owner, i_offset))
- return false;
- }
- else
- {
- if (i_target->IsWithinDistInMap(&owner, i_offset + 1.0f))
- return false;
- }
- }
- else
- {
- bool stop = false;
- if (!i_offset)
- {
- if (i_target->IsWithinMeleeRange(&owner, 0))
- stop = true;
- }
- else if (!i_angle && !owner.HasUnitState(UNIT_STAT_FOLLOW))
- {
- if (i_target->IsWithinDist(&owner, i_offset * 0.8f))
- stop = true;
- }
-
- if (stop)
- {
- owner.GetPosition(x, y, z);
- i_destinationHolder.SetDestination(traveller, x, y, z);
- i_destinationHolder.StartTravel(traveller, false);
- owner.StopMoving();
- return false;
- }
- }
+ if (!owner.movespline->Finalized())
+ return;
- if (i_target->GetExactDistSq(i_targetX, i_targetY, i_targetZ) < 0.01f)
- return false;
+ owner.GetPosition(x, y, z);
}
-
- if (!i_offset)
+ else if (!i_offset)
{
+ if (i_target->IsWithinMeleeRange(&owner))
+ return;
+
// to nearest random contact position
i_target->GetRandomContactPoint(&owner, x, y, z, 0, MELEE_RANGE - 0.5f);
}
- else if (!i_angle && !owner.HasUnitState(UNIT_STAT_FOLLOW))
- {
- // caster chase
- i_target->GetContactPoint(&owner, x, y, z, i_offset * urand(80, 95) * 0.01f);
- }
else
{
+ if (i_target->IsWithinDistInMap(&owner, i_offset + 1.0f))
+ return;
// to at i_offset distance from target and i_angle from target facing
i_target->GetClosePoint(x, y, z, owner.GetObjectSize(), i_offset, i_angle);
}
@@ -137,55 +73,65 @@ TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
ralf
//We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
- float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
- if (i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x, y, z) < bothObjectSize)
+ float bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE;
+ if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
return;
*/
- i_destinationHolder.SetDestination(traveller, x, y, z);
- owner.AddUnitState(UNIT_STAT_CHASE);
- i_destinationHolder.StartTravel(traveller);
- return true;
+
+
+ D::_addUnitStateMove(owner);
+ i_targetReached = false;
+ i_recalculateTravel = false;
+
+ Movement::MoveSplineInit init(owner);
+ init.MoveTo(x,y,z);
+ init.SetWalk(((D*)this)->EnableWalking());
+ init.Launch();
}
-template<class T>
-void
-TargetedMovementGenerator<T>::Initialize(T &owner)
+template<>
+void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::UpdateFinalDistance(float /*fDistance*/)
{
- if (owner.isInCombat())
- owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ // nothing to do for Player
+}
- _setTargetLocation(owner);
+template<>
+void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::UpdateFinalDistance(float /*fDistance*/)
+{
+ // nothing to do for Player
}
-template<class T>
-void
-TargetedMovementGenerator<T>::Finalize(T &owner)
+template<>
+void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::UpdateFinalDistance(float fDistance)
{
- owner.ClearUnitState(UNIT_STAT_CHASE);
+ i_offset = fDistance;
+ i_recalculateTravel = true;
}
-template<class T>
-void
-TargetedMovementGenerator<T>::Reset(T &owner)
+template<>
+void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::UpdateFinalDistance(float fDistance)
{
- Initialize(owner);
+ i_offset = fDistance;
+ i_recalculateTravel = true;
}
-template<class T>
-bool
-TargetedMovementGenerator<T>::Update(T &owner, const uint32 time_diff)
+template<class T, typename D>
+bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_diff)
{
if (!i_target.isValid() || !i_target->IsInWorld())
return false;
- if (!&owner || !owner.isAlive())
+ if (!owner.isAlive())
return true;
- if (owner.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED))
+ if (owner.HasUnitState(UNIT_STAT_NOT_MOVE))
+ {
+ D::_clearUnitStateMove(owner);
return true;
+ }
// prevent movement while casting spells with cast time or channel time
- if (owner.HasUnitState(UNIT_STAT_CASTING))
+ if (owner.IsNonMeleeSpellCasted(false, false, true))
{
if (!owner.IsStopped())
owner.StopMoving();
@@ -193,85 +139,170 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 time_diff)
}
// prevent crash after creature killed pet
- if (!owner.HasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
+ if (static_cast<D*>(this)->_lostTarget(owner))
+ {
+ D::_clearUnitStateMove(owner);
return true;
+ }
- Traveller<T> traveller(owner);
-
- if (!i_destinationHolder.HasDestination())
- _setTargetLocation(owner);
- else if (owner.IsStopped() && !i_destinationHolder.HasArrived())
+ i_recheckDistance.Update(time_diff);
+ if (i_recheckDistance.Passed())
{
- owner.AddUnitState(UNIT_STAT_CHASE);
- i_destinationHolder.StartTravel(traveller);
- return true;
+ i_recheckDistance.Reset(50);
+ //More distance let have better performance, less distance let have more sensitive reaction at target move.
+ float allowed_dist = i_target->GetObjectSize() + owner.GetObjectSize() + MELEE_RANGE - 0.5f;
+ 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);
}
- if (i_destinationHolder.UpdateTraveller(traveller, time_diff))
+ if (owner.movespline->Finalized())
{
- // put targeted movement generators on a higher priority
- //if (owner.GetObjectSize())
- //i_destinationHolder.ResetUpdate(50);
+ static_cast<D*>(this)->MovementInform(owner);
+ if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget()))
+ owner.SetInFront(i_target.getTarget());
- // target moved
- if (i_targetX != i_target->GetPositionX() || i_targetY != i_target->GetPositionY()
- || i_targetZ != i_target->GetPositionZ())
+ if (!i_targetReached)
{
- if (_setTargetLocation(owner) || !owner.HasUnitState(UNIT_STAT_FOLLOW))
- owner.SetInFront(i_target.getTarget());
- i_target->GetPosition(i_targetX, i_targetY, i_targetZ);
+ i_targetReached = true;
+ static_cast<D*>(this)->_reachTarget(owner);
}
+ }
+ else
+ {
+ if (i_recalculateTravel)
+ _setTargetLocation(owner);
+ }
+ return true;
+}
- if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
- {
- i_recalculateTravel = false;
- //Angle update will take place into owner.StopMoving()
- owner.SetInFront(i_target.getTarget());
+//-----------------------------------------------//
+template<class T>
+void ChaseMovementGenerator<T>::_reachTarget(T &owner)
+{
+ if (owner.IsWithinMeleeRange(this->i_target.getTarget()))
+ owner.Attack(this->i_target.getTarget(),true);
+}
- owner.StopMoving();
- if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.HasUnitState(UNIT_STAT_FOLLOW))
- owner.Attack(i_target.getTarget(), true);
- }
- }
+template<>
+void ChaseMovementGenerator<Player>::Initialize(Player &owner)
+{
+ owner.AddUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
+ _setTargetLocation(owner);
+}
- // Implemented for PetAI to handle resetting flags when pet owner reached
- if (i_destinationHolder.HasArrived())
- MovementInform(owner);
+template<>
+void ChaseMovementGenerator<Creature>::Initialize(Creature &owner)
+{
+ owner.SetWalk(false);
+ owner.AddUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
+ _setTargetLocation(owner);
+}
- return true;
+template<class T>
+void ChaseMovementGenerator<T>::Finalize(T &owner)
+{
+ owner.ClearUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
}
template<class T>
-Unit*
-TargetedMovementGenerator<T>::GetTarget() const
+void ChaseMovementGenerator<T>::Reset(T &owner)
+{
+ Initialize(owner);
+}
+
+//-----------------------------------------------//
+template<>
+bool FollowMovementGenerator<Creature>::EnableWalking() const
+{
+ return i_target.isValid() && i_target->IsWalking();
+}
+
+template<>
+bool FollowMovementGenerator<Player>::EnableWalking() const
{
- return i_target.getTarget();
+ return false;
+}
+
+template<>
+void FollowMovementGenerator<Player>::_updateSpeed(Player &/*u*/)
+{
+ // nothing to do for Player
+}
+
+template<>
+void FollowMovementGenerator<Creature>::_updateSpeed(Creature &u)
+{
+ // pet only sync speed with owner
+ if (!((Creature&)u).isPet() || !i_target.isValid() || i_target->GetGUID() != u.GetOwnerGUID())
+ return;
+
+ u.UpdateSpeed(MOVE_RUN,true);
+ u.UpdateSpeed(MOVE_WALK,true);
+ u.UpdateSpeed(MOVE_SWIM,true);
+}
+
+template<>
+void FollowMovementGenerator<Player>::Initialize(Player &owner)
+{
+ owner.AddUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
+ _updateSpeed(owner);
+ _setTargetLocation(owner);
+}
+
+template<>
+void FollowMovementGenerator<Creature>::Initialize(Creature &owner)
+{
+ owner.AddUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
+ _updateSpeed(owner);
+ _setTargetLocation(owner);
}
template<class T>
-void TargetedMovementGenerator<T>::MovementInform(T & /*unit*/)
+void FollowMovementGenerator<T>::Finalize(T &owner)
{
+ owner.ClearUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
+ _updateSpeed(owner);
}
-template <> void TargetedMovementGenerator<Creature>::MovementInform(Creature &unit)
+template<class T>
+void FollowMovementGenerator<T>::Reset(T &owner)
+{
+ Initialize(owner);
+}
+
+template<class T>
+void FollowMovementGenerator<T>::MovementInform(T & /*unit*/)
{
- // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
- unit.AI()->MovementInform(TARGETED_MOTION_TYPE, i_target.getTarget()->GetGUIDLow());
}
-template void TargetedMovementGenerator<Player>::MovementInform(Player&); // Not implemented for players
-template TargetedMovementGenerator<Player>::TargetedMovementGenerator(Unit &target, float offset, float angle);
-template TargetedMovementGenerator<Creature>::TargetedMovementGenerator(Unit &target, float offset, float angle);
-template bool TargetedMovementGenerator<Player>::_setTargetLocation(Player &);
-template bool TargetedMovementGenerator<Creature>::_setTargetLocation(Creature &);
-template void TargetedMovementGenerator<Player>::Initialize(Player &);
-template void TargetedMovementGenerator<Creature>::Initialize(Creature &);
-template void TargetedMovementGenerator<Player>::Finalize(Player &);
-template void TargetedMovementGenerator<Creature>::Finalize(Creature &);
-template void TargetedMovementGenerator<Player>::Reset(Player &);
-template void TargetedMovementGenerator<Creature>::Reset(Creature &);
-template bool TargetedMovementGenerator<Player>::Update(Player &, const uint32);
-template bool TargetedMovementGenerator<Creature>::Update(Creature &, const uint32);
-template Unit* TargetedMovementGenerator<Player>::GetTarget() const;
-template Unit* TargetedMovementGenerator<Creature>::GetTarget() const;
+template<>
+void FollowMovementGenerator<Creature>::MovementInform(Creature &unit)
+{
+ // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
+ if (unit.AI())
+ unit.AI()->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUIDLow());
+}
+//-----------------------------------------------//
+template void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::_setTargetLocation(Player &);
+template void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::_setTargetLocation(Player &);
+template void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature &);
+template void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::_setTargetLocation(Creature &);
+template bool TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::Update(Player &, const uint32 &);
+template bool TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::Update(Player &, const uint32 &);
+template bool TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::Update(Creature &, const uint32 &);
+template bool TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::Update(Creature &, const uint32 &);
+
+template void ChaseMovementGenerator<Player>::_reachTarget(Player &);
+template void ChaseMovementGenerator<Creature>::_reachTarget(Creature &);
+template void ChaseMovementGenerator<Player>::Finalize(Player &);
+template void ChaseMovementGenerator<Creature>::Finalize(Creature &);
+template void ChaseMovementGenerator<Player>::Reset(Player &);
+template void ChaseMovementGenerator<Creature>::Reset(Creature &);
+
+template void FollowMovementGenerator<Player>::Finalize(Player &);
+template void FollowMovementGenerator<Creature>::Finalize(Creature &);
+template void FollowMovementGenerator<Player>::Reset(Player &);
+template void FollowMovementGenerator<Creature>::Reset(Creature &);
+template void FollowMovementGenerator<Player>::MovementInform(Player &unit);
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
index edb4fca8fce..785d12ba6d2 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
@@ -20,9 +20,8 @@
#define TRINITY_TARGETEDMOVEMENTGENERATOR_H
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
-#include "Traveller.h"
#include "FollowerReference.h"
+#include "Timer.h"
class TargetedMovementGeneratorBase
{
@@ -33,41 +32,84 @@ class TargetedMovementGeneratorBase
FollowerReference i_target;
};
+template<class T, typename D>
+class TargetedMovementGeneratorMedium
+: public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
+{
+ protected:
+ TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) :
+ TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle),
+ i_recalculateTravel(false), i_targetReached(false), i_recheckDistance(0)
+ {
+ }
+ ~TargetedMovementGeneratorMedium() {}
+
+ public:
+ bool Update(T &, const uint32 &);
+ Unit* GetTarget() const { return i_target.getTarget(); }
+
+ void unitSpeedChanged() { i_recalculateTravel=true; }
+ void UpdateFinalDistance(float fDistance);
+
+ protected:
+ void _setTargetLocation(T &);
+
+ TimeTrackerSmall i_recheckDistance;
+ float i_offset;
+ float i_angle;
+ bool i_recalculateTravel : 1;
+ bool i_targetReached : 1;
+};
+
template<class T>
-class TargetedMovementGenerator
-: public MovementGeneratorMedium< T, TargetedMovementGenerator<T> >, public TargetedMovementGeneratorBase
+class ChaseMovementGenerator : public TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >
{
public:
- TargetedMovementGenerator(Unit &target, float offset = 0, float angle = 0);
- ~TargetedMovementGenerator() {}
+ ChaseMovementGenerator(Unit &target)
+ : TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target) {}
+ ChaseMovementGenerator(Unit &target, float offset, float angle)
+ : TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target, offset, angle) {}
+ ~ChaseMovementGenerator() {}
+
+ MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; }
void Initialize(T &);
void Finalize(T &);
void Reset(T &);
- bool Update(T &, const uint32);
- MovementGeneratorType GetMovementGeneratorType() { return TARGETED_MOTION_TYPE; }
-
- void MovementInform(T &);
+ void MovementInform(T &){}
- Unit* GetTarget() const;
+ static void _clearUnitStateMove(T &u) { u.ClearUnitState(UNIT_STAT_CHASE_MOVE); }
+ static void _addUnitStateMove(T &u) { u.AddUnitState(UNIT_STAT_CHASE_MOVE); }
+ bool EnableWalking() const { return false;}
+ bool _lostTarget(T &u) const { return u.getVictim() != this->GetTarget(); }
+ void _reachTarget(T &);
+};
- bool GetDestination(float &x, float &y, float &z) const
- {
- if (i_destinationHolder.HasArrived() || !i_destinationHolder.HasDestination()) return false;
- i_destinationHolder.GetDestination(x, y, z);
- return true;
- }
+template<class T>
+class FollowMovementGenerator : public TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >
+{
+ public:
+ FollowMovementGenerator(Unit &target)
+ : TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target){}
+ FollowMovementGenerator(Unit &target, float offset, float angle)
+ : TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target, offset, angle) {}
+ ~FollowMovementGenerator() {}
- void unitSpeedChanged() { i_recalculateTravel=true; }
- private:
+ MovementGeneratorType GetMovementGeneratorType() { return FOLLOW_MOTION_TYPE; }
- bool _setTargetLocation(T &);
+ void Initialize(T &);
+ void Finalize(T &);
+ void Reset(T &);
+ void MovementInform(T &);
- float i_offset;
- float i_angle;
- DestinationHolder< Traveller<T> > i_destinationHolder;
- bool i_recalculateTravel;
- float i_targetX, i_targetY, i_targetZ;
+ static void _clearUnitStateMove(T &u) { u.ClearUnitState(UNIT_STAT_FOLLOW_MOVE); }
+ static void _addUnitStateMove(T &u) { u.AddUnitState(UNIT_STAT_FOLLOW_MOVE); }
+ bool EnableWalking() const;
+ bool _lostTarget(T &) const { return false; }
+ void _reachTarget(T &) {}
+ private:
+ void _updateSpeed(T &u);
};
+
#endif
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index f88ed249aca..ea858eaba84 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -17,222 +17,165 @@
*/
//Basic headers
#include "WaypointMovementGenerator.h"
-#include "DestinationHolderImp.h"
//Extended headers
#include "ObjectMgr.h"
#include "World.h"
-#include "MapManager.h" // for flightmaster grid preloading
+//Flightmaster grid preloading
+#include "MapManager.h"
//Creature-specific headers
#include "Creature.h"
#include "CreatureAI.h"
#include "CreatureGroups.h"
//Player-specific
#include "Player.h"
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
-template<class T>
-void
-WaypointMovementGenerator<T>::Initialize(T & /*u*/){}
-
-template<>
-void
-WaypointMovementGenerator<Creature>::Finalize(Creature & /*u*/){}
+void WaypointMovementGenerator<Creature>::LoadPath(Creature &creature)
+{
+ if (!path_id)
+ path_id = creature.GetWaypointPath();
-template<>
-void
-WaypointMovementGenerator<Player>::Finalize(Player & /*u*/){}
+ i_path = sWaypointMgr->GetPath(path_id);
-template<class T>
-void
-WaypointMovementGenerator<T>::MovementInform(T & /*unit*/){}
+ if (!i_path)
+ {
+ // No movement found for entry
+ sLog->outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path id: %u", creature.GetName(), creature.GetEntry(), creature.GetGUIDLow(), path_id);
+ return;
+ }
-template<>
-void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
-{
- unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
+ StartMoveNow(creature);
}
-template<>
-bool WaypointMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
+void WaypointMovementGenerator<Creature>::Initialize(Creature &creature)
{
- if (i_destinationHolder.HasArrived())
- return false;
-
- i_destinationHolder.GetDestination(x, y, z);
- return true;
+ LoadPath(creature);
+ creature.AddUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
}
-template<>
-bool WaypointMovementGenerator<Player>::GetDestination(float & /*x*/, float & /*y*/, float & /*z*/) const
+void WaypointMovementGenerator<Creature>::Finalize(Creature &creature)
{
- return false;
+ creature.ClearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
+ creature.SetWalk(false);
}
-template<>
-void WaypointMovementGenerator<Creature>::Reset(Creature & /*unit*/)
+void WaypointMovementGenerator<Creature>::Reset(Creature &creature)
{
- StopedByPlayer = true;
- i_nextMoveTime.Reset(0);
+ creature.AddUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE);
+ StartMoveNow(creature);
}
-template<>
-void WaypointMovementGenerator<Player>::Reset(Player & /*unit*/){}
-
-template<>
-void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node)
+void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
{
- node.run ? unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING):
- unit.AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ if (!i_path || i_path->empty())
+ return;
+ if (m_isArrivalDone)
+ return;
- unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
- unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
+ creature.ClearUnitState(UNIT_STAT_ROAMING_MOVE);
+ m_isArrivalDone = true;
- // TODO: make this part of waypoint node, so that creature can walk when desired?
- if (unit.canFly())
- unit.SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
+ if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
+ {
+ sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for %u.", i_path->at(i_currentNode)->event_id, i_currentNode, creature.GetGUID());
+ creature.GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, &creature, NULL/*, false*/);
+ }
- unit.AddUnitState(UNIT_STAT_ROAMING);
+ // Inform script
+ MovementInform(creature);
+ Stop(i_path->at(i_currentNode)->delay);
}
-template<>
-void
-WaypointMovementGenerator<Creature>::Initialize(Creature &u)
+bool WaypointMovementGenerator<Creature>::StartMove(Creature &creature)
{
- u.StopMoving();
- //i_currentNode = -1; // uint32, become 0 in the first update
- //i_nextMoveTime.Reset(0);
- StopedByPlayer = false;
- if (!path_id)
- path_id = u.GetWaypointPath();
- waypoints = sWaypointMgr->GetPath(path_id);
- i_currentNode = 0;
- if (waypoints && waypoints->size())
+ if (!i_path || i_path->empty())
+ return false;
+ if (Stopped())
+ return true;
+
+ const WaypointData *node = i_path->at(i_currentNode);
+
+ if (m_isArrivalDone)
{
- node = waypoints->front();
- Traveller<Creature> traveller(u);
- InitTraveller(u, *node);
- i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
- i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
-
- //Call for creature group update
- if (u.GetFormation() && u.GetFormation()->getLeader() == &u)
- u.GetFormation()->LeaderMoveTo(node->x, node->y, node->z);
+ if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint
+ {
+ creature.SetHomePosition(node->x, node->y, node->z, creature.GetOrientation());
+ creature.GetMotionMaster()->Initialize();
+ return false;
+ }
+
+ i_currentNode = (i_currentNode+1) % i_path->size();
}
- else
- node = NULL;
-}
-template<>
-void WaypointMovementGenerator<Player>::InitTraveller(Player & /*unit*/, const WaypointData & /*node*/){}
+ m_isArrivalDone = false;
-template<class T>
-bool
-WaypointMovementGenerator<T>::Update(T & /*unit*/, const uint32 /*diff*/)
-{
- return false;
-}
+ creature.AddUnitState(UNIT_STAT_ROAMING_MOVE);
+
+ Movement::MoveSplineInit init(creature);
+ init.MoveTo(node->x, node->y, node->z);
-template<>
-bool
-WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 diff)
-{
- if (!&unit)
- return true;
+ if (node->orientation != 100 && node->delay != 0)
+ init.SetFacing(node->orientation);
- if (!path_id)
- return false;
+ init.SetWalk(!node->run);
+ init.Launch();
+
+ //Call for creature group update
+ if (creature.GetFormation() && creature.GetFormation()->getLeader() == &creature)
+ creature.GetFormation()->LeaderMoveTo(node->x, node->y, node->z);
+
+ return true;
+}
+bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
+{
// Waypoint movement can be switched on/off
// This is quite handy for escort quests and other stuff
- if (unit.HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
+ if (creature.HasUnitState(UNIT_STAT_NOT_MOVE))
+ {
+ creature.ClearUnitState(UNIT_STAT_ROAMING_MOVE);
return true;
-
- // Clear the generator if the path doesn't exist
- if (!waypoints || !waypoints->size())
+ }
+ // prevent a crash at empty waypoint path.
+ if (!i_path || i_path->empty())
return false;
- Traveller<Creature> traveller(unit);
-
- i_nextMoveTime.Update(diff);
- i_destinationHolder.UpdateTraveller(traveller, diff, true);
-
- if (i_nextMoveTime.GetExpiry() < TIMEDIFF_NEXT_WP)
+ if (Stopped())
{
- if (unit.IsStopped())
- {
- if (StopedByPlayer)
- {
- ASSERT(node);
- InitTraveller(unit, *node);
- i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
- i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
- StopedByPlayer = false;
- return true;
- }
-
- if (i_currentNode == waypoints->size() - 1) // If that's our last waypoint
- {
- if (repeating) // If the movement is repeating
- i_currentNode = 0; // Start moving all over again
- else
- {
- unit.SetHomePosition(node->x, node->y, node->z, unit.GetOrientation());
- unit.GetMotionMaster()->Initialize();
- return false; // Clear the waypoint movement
- }
- }
- else
- ++i_currentNode;
-
- node = waypoints->at(i_currentNode);
- InitTraveller(unit, *node);
- i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z);
- i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
-
- //Call for creature group update
- if (unit.GetFormation() && unit.GetFormation()->getLeader() == &unit)
- unit.GetFormation()->LeaderMoveTo(node->x, node->y, node->z);
- }
- else
- {
- //Determine waittime
- if (node->delay)
- i_nextMoveTime.Reset(node->delay);
-
- //note: disable "start" for mtmap
- if (node->event_id && urand(0, 99) < node->event_chance)
- unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/);
-
- i_destinationHolder.ResetTravelTime();
- MovementInform(unit);
- unit.UpdateWaypointID(i_currentNode);
- unit.ClearUnitState(UNIT_STAT_ROAMING);
- if (node->orientation)
- {
- unit.Relocate(node->x, node->y, node->z, node->orientation);
- unit.SetFacing(node->orientation, NULL);
- }
- else
- unit.Relocate(node->x, node->y, node->z);
- }
+ if (CanMove(diff))
+ return StartMove(creature);
}
- else
+ else
{
- if (unit.IsStopped() && !i_destinationHolder.HasArrived())
+ if (creature.IsStopped())
+ Stop(STOP_TIME_FOR_PLAYER);
+ else if (creature.movespline->Finalized())
{
- if (!StopedByPlayer)
- {
- i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
- i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
- StopedByPlayer = true;
- }
- }
+ OnArrived(creature);
+ return StartMove(creature);
+ }
}
+ return true;
+ }
+
+void WaypointMovementGenerator<Creature>::MovementInform(Creature &creature)
+{
+ if (creature.AI())
+ creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
+}
+
+bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z)
+{
+ // prevent a crash at empty waypoint path.
+ if (!i_path || i_path->empty())
+ return false;
+
+ const WaypointData* node = i_path->at(i_currentNode);
+ x = node->x; y = node->y; z = node->z;
return true;
}
-template void WaypointMovementGenerator<Player>::Initialize(Player &);
-template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32);
-template void WaypointMovementGenerator<Player>::MovementInform(Player &);
//----------------------------------------------------//
@@ -253,71 +196,72 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
void FlightPathMovementGenerator::Initialize(Player &player)
{
- player.getHostileRefManager().setOnlineOfflineState(false);
- player.AddUnitState(UNIT_STAT_IN_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);
- // For preloading end grid
+ Reset(player);
InitEndGridInfo();
- player.SendMonsterMoveByPath(GetPath(), GetCurrentNode(), GetPathAtMapEnd());
}
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)
player.ClearUnitState(UNIT_STAT_IN_FLIGHT);
- float x = 0;
- float y = 0;
- float z = 0;
- i_destinationHolder.GetLocationNow(player.GetBaseMap(), x, y, z);
- player.UpdatePosition(x, y, z, player.GetOrientation());
+ player.Dismount();
+ player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
+ if(player.m_taxi.empty())
+ {
+ player.getHostileRefManager().setOnlineOfflineState(true);
+ if(player.pvpInfo.inHostileArea)
+ player.CastSpell(&player, 2479, true);
+
+ // update z position to ground and orientation for landing point
+ // this prevent cheating with landing point at lags
+ // when client side flight end early in comparison server side
+ player.StopMoving();
+ }
+}
+
+#define PLAYER_FLIGHT_SPEED 32.0f
+
+void FlightPathMovementGenerator::Reset(Player & player)
+{
+ player.getHostileRefManager().setOnlineOfflineState(false);
+ player.AddUnitState(UNIT_STAT_IN_FLIGHT);
+ player.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
+
+ 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)
{
- if (MovementInProgress())
+ uint32 pointId = (uint32)player.movespline->currentPathIdx();
+ if (pointId > i_currentNode)
{
- Traveller<Player> traveller(player);
- if (i_destinationHolder.UpdateTraveller(traveller, diff))
+ bool departureEvent = true;
+ do
{
- 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);
-
- sLog->outStaticDebug("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);
- }
-
- // check if it's time to preload the flightmaster grid at path end
- if (i_currentNode == m_preloadTargetNode)
- PreloadEndGrid();
-
- return true;
- }
- //else HasArrived()
- }
- else
- return true;
+ DoEventIfAny(player, (*i_path)[i_currentNode], departureEvent);
+ if (pointId == i_currentNode)
+ break;
+ if (i_currentNode == _preloadTargetNode)
+ PreloadEndGrid();
+ i_currentNode += (uint32)departureEvent;
+ departureEvent = !departureEvent;
}
- else
- return true;
+ while (true);
}
- // we have arrived at the end of the path
- return false;
+ return i_currentNode < (i_path->size()-1);
}
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
@@ -336,42 +280,48 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
}
}
+void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure)
+{
+ if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID)
+ {
+ sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player.GetName());
+ player.GetMap()->ScriptsStart(sEventScripts, eventid, &player, &player);
+ }
+}
+
+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;
+}
+
void FlightPathMovementGenerator::InitEndGridInfo()
{
- // Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will
- // be reinitialized for each flightmaster at the end of each spline (or stop) in the flight.
-
- uint32 nodeCount = (*i_path).size(); // Get the number of nodes in the path.
- m_endMapId = (*i_path)[nodeCount -1].mapid; // Get the map ID from the last node
- m_preloadTargetNode = nodeCount - 3; // 2 nodes before the final node, we pre-load the grid
- m_endGridX = (*i_path)[nodeCount -1].x; // Get the X position from the last node
- m_endGridY = (*i_path)[nodeCount -1].y; // Get the Y position from the last node
+ /*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will
+ be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */
+ uint32 nodeCount = (*i_path).size(); //! Number of nodes in path.
+ _endMapId = (*i_path)[nodeCount - 1].mapid; //! MapId of last node
+ _preloadTargetNode = nodeCount - 3;
+ _endGridX = (*i_path)[nodeCount - 1].x;
+ _endGridY = (*i_path)[nodeCount - 1].y;
}
void FlightPathMovementGenerator::PreloadEndGrid()
{
// used to preload the final grid where the flightmaster is
- Map* endMap = sMapMgr->FindBaseNonInstanceMap(m_endMapId);
+ Map* endMap = sMapMgr->FindBaseNonInstanceMap(_endMapId);
// Load the grid
if (endMap)
{
- sLog->outDetail("Preloading flightmaster at grid (%f, %f) for map %u", m_endGridX, m_endGridY, m_endMapId);
- endMap->LoadGrid(m_endGridX, m_endGridY);
+ sLog->outDetail("Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path->size()-1));
+ endMap->LoadGrid(_endGridX, _endGridY);
}
else
sLog->outDetail("Unable to determine map to preload flightmaster grid");
}
-void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure)
-{
- if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID)
- {
- sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player.GetName());
- player.GetMap()->ScriptsStart(sEventScripts, eventid, &player, &player);
- }
-}
-
//
// Unique1's ASTAR Pathfinding Code... For future use & reference...
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index 230630936ff..aa6d327db3b 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -26,10 +26,8 @@
*/
#include "MovementGenerator.h"
-#include "DestinationHolder.h"
#include "WaypointManager.h"
#include "Path.h"
-#include "Traveller.h"
#include "Player.h"
@@ -44,49 +42,68 @@ template<class T, class P>
class PathMovementBase
{
public:
- PathMovementBase() : i_currentNode(0) {}
+ PathMovementBase() : i_currentNode(0), i_path(NULL) {}
virtual ~PathMovementBase() {};
- bool MovementInProgress(void) const { return i_currentNode < i_path->size(); }
-
+ // template pattern, not defined .. override required
void LoadPath(T &);
- void ReloadPath(T &);
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:
- uint32 i_currentNode;
- DestinationHolder< Traveller<T> > i_destinationHolder;
P i_path;
+ uint32 i_currentNode;
};
template<class T>
+class WaypointMovementGenerator;
-class WaypointMovementGenerator
- : public MovementGeneratorMedium< T, WaypointMovementGenerator<T> >, public PathMovementBase<T, WaypointPath const*>
+template<>
+class WaypointMovementGenerator<Creature>
+: public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
+public PathMovementBase<Creature, WaypointPath const*>
{
public:
- WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) :
- node(NULL), path_id(_path_id), i_nextMoveTime(0), repeating(_repeating), StopedByPlayer(false) {}
-
- void Initialize(T &);
- void Finalize(T &);
- void MovementInform(T &);
- void InitTraveller(T &, const WaypointData &);
- void GeneratePathId(T &);
- void Reset(T &unit);
- bool Update(T &, const uint32);
- bool GetDestination(float &x, float &y, float &z) const;
+ WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) : i_nextMoveTime(0), path_id(_path_id), m_isArrivalDone(false), repeating(_repeating) {}
+ ~WaypointMovementGenerator() { i_path = NULL; }
+ void Initialize(Creature &);
+ void Finalize(Creature &);
+ void Reset(Creature &);
+ bool Update(Creature &, const uint32 &diff);
+
+ void MovementInform(Creature &);
+
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
+ // now path movement implmementation
+ void LoadPath(Creature &c);
+
+ bool GetResetPosition(Creature&, float& x, float& y, float& z);
+
private:
- WaypointData* node;
- uint32 path_id;
+
+ void Stop(int32 time) { i_nextMoveTime.Reset(time);}
+
+ bool Stopped() { return !i_nextMoveTime.Passed();}
+
+ bool CanMove(int32 diff)
+ {
+ i_nextMoveTime.Update(diff);
+ return i_nextMoveTime.Passed();
+ }
+
+ void OnArrived(Creature&);
+ bool StartMove(Creature&);
+
+ void StartMoveNow(Creature& creature)
+ {
+ i_nextMoveTime.Reset(0);
+ StartMove(creature);
+ }
+
TimeTrackerSmall i_nextMoveTime;
- WaypointPath const* waypoints;
- bool repeating, StopedByPlayer;
+ bool m_isArrivalDone;
+ uint32 path_id;
+ bool repeating;
};
/** FlightPathMovementGenerator generates movement of the player for the paths
@@ -103,7 +120,7 @@ public PathMovementBase<Player, TaxiPathNodeList const*>
i_currentNode = startNode;
}
void Initialize(Player &);
- void Reset(Player & /*u*/){};
+ void Reset(Player &);
void Finalize(Player &);
bool Update(Player &, const uint32);
MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; }
@@ -115,17 +132,16 @@ public PathMovementBase<Player, TaxiPathNodeList const*>
void SkipCurrentNode() { ++i_currentNode; }
void DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure);
- bool GetDestination(float& x, float& y, float& z) const { return PathMovementBase<Player, TaxiPathNodeList const*>::GetDestination(x, y, z); }
+ bool GetResetPosition(Player&, float& x, float& y, float& z);
- void PreloadEndGrid();
void InitEndGridInfo();
+ void PreloadEndGrid();
+
private:
- // storage for preloading the flightmaster grid at end
- // before reaching final waypoint
- uint32 m_endMapId;
- uint32 m_preloadTargetNode;
- float m_endGridX;
- float m_endGridY;
+ float _endGridX; //! X coord of last node location
+ float _endGridY; //! Y coord of last node location
+ uint32 _endMapId; //! map Id of last node location
+ uint32 _preloadTargetNode; //! node index where preloading starts
};
#endif
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
new file mode 100644
index 00000000000..4eaa6b57b36
--- /dev/null
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -0,0 +1,316 @@
+/*
+ * 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
+{
+ 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;
+ c.orientation = initialOrientation;
+ 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
+ {
+ if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed|MoveSplineFlag::Falling))
+ {
+ Vector3 hermite;
+ spline.evaluate_derivative(point_Idx,u,hermite);
+ c.orientation = atan2(hermite.y, hermite.x);
+ }
+
+ if (splineflags.orientationInversed)
+ 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;
+ initialOrientation = args.initialOrientation;
+
+ 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), initialOrientation(0.f)
+{
+ 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());
+ 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;
+}
+}
diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h
new file mode 100644
index 00000000000..4b8dbcc8ee3
--- /dev/null
+++ b/src/server/game/Movement/Spline/MoveSpline.h
@@ -0,0 +1,127 @@
+/*
+ * 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 TRINITYSERVER_MOVEPLINE_H
+#define TRINITYSERVER_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;
+ float initialOrientation;
+ 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();
+ void _Interrupt() { splineflags.done = true;}
+
+ #pragma endregion
+ public:
+
+ void Initialize(const MoveSplineInitArgs&);
+ bool Initialized() const { return !spline.empty();}
+
+ explicit MoveSpline();
+
+ template<class UpdateHandler>
+ void updateState(int32 difftime, UpdateHandler& handler)
+ {
+ ASSERT(Initialized());
+ do
+ handler(_updateState(difftime));
+ while(difftime > 0);
+ }
+
+ void updateState(int32 difftime)
+ {
+ 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 // TRINITYSERVER_MOVEPLINE_H
diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h
new file mode 100644
index 00000000000..de91f63c30a
--- /dev/null
+++ b/src/server/game/Movement/Spline/MoveSplineFlag.h
@@ -0,0 +1,143 @@
+/*
+ * 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 TRINITYSERVER_MOVESPLINEFLAG_H
+#define TRINITYSERVER_MOVESPLINEFLAG_H
+#include "MovementTypedefs.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
+ OrientationFixed = 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,
+ OrientationInversed = 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;}
+ bool hasFlag(uint32 f) const { return (raw() & f) != 0;}
+ 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) | Animation|anim;}
+ void EnableParabolic() { raw() = raw() & ~(Mask_Animations|Falling|Animation) | Parabolic;}
+ void EnableFalling() { raw() = raw() & ~(Mask_Animations|Parabolic|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 orientationFixed : 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 orientationInversed : 1;
+ bool unknown10 : 1;
+ bool unknown11 : 1;
+ bool unknown12 : 1;
+ bool unknown13 : 1;
+ };
+#if defined( __GNUC__ )
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+}
+
+#endif // TRINITYSERVER_MOVESPLINEFLAG_H
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp
new file mode 100644
index 00000000000..885ade57653
--- /dev/null
+++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "MoveSplineInit.h"
+#include "MoveSpline.h"
+#include "MovementPacketBuilder.h"
+#include "Unit.h"
+
+namespace Movement
+{
+ UnitMoveType SelectSpeedType(uint32 moveFlags)
+ {
+ if (moveFlags & MOVEMENTFLAG_FLYING)
+ {
+ if ( moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/ )
+ return MOVE_FLIGHT_BACK;
+ else
+ return MOVE_FLIGHT;
+ }
+ else if (moveFlags & MOVEMENTFLAG_SWIMMING)
+ {
+ if (moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.swim >= speed_obj.swim_back*/)
+ return MOVE_SWIM_BACK;
+ else
+ return MOVE_SWIM;
+ }
+ else if (moveFlags & MOVEMENTFLAG_WALKING)
+ {
+ //if ( speed_obj.run > speed_obj.walk )
+ return MOVE_WALK;
+ }
+ else if (moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.run >= speed_obj.run_back*/)
+ return MOVE_RUN_BACK;
+
+ return MOVE_RUN;
+ }
+
+ void MoveSplineInit::Launch()
+ {
+ MoveSpline& move_spline = *unit.movespline;
+
+ Location real_position(unit.GetPositionX(),unit.GetPositionY(),unit.GetPositionZ(),unit.GetOrientation());
+ // 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;
+ args.initialOrientation = real_position.orientation;
+
+ uint32 moveFlags = unit.m_movementInfo.GetMovementFlags();
+ if (args.flags.walkmode)
+ moveFlags |= MOVEMENTFLAG_WALKING;
+ else
+ moveFlags &= ~MOVEMENTFLAG_WALKING;
+
+ moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD);
+
+ if (args.velocity == 0.f)
+ args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags));
+
+ if (!args.Validate())
+ return;
+
+ if (moveFlags & MOVEMENTFLAG_ROOT)
+ moveFlags &= ~MOVEMENTFLAG_MASK_MOVING;
+
+ unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags);
+ move_spline.Initialize(args);
+
+ WorldPacket data(SMSG_MONSTER_MOVE, 64);
+ data.append(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(MOVEMENTFLAG_WALKING);
+ args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_FLYING|MOVEMENTFLAG_LEVITATING));
+ }
+
+ void MoveSplineInit::SetFacing(const Unit * target)
+ {
+ args.flags.EnableFacingTarget();
+ target->GetUInt64Value(OBJECT_FIELD_GUID);
+ //args.facing.target = target->GetObjectGuid().GetRawValue();
+ args.facing.target = target->GetUInt64Value(OBJECT_FIELD_GUID);
+ }
+
+ void MoveSplineInit::SetFacing(float angle)
+ {
+ args.facing.angle = G3D::wrap(angle, 0.f, (float)G3D::twoPi());
+ args.flags.EnableFacingAngle();
+ }
+}
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h
new file mode 100644
index 00000000000..7ef6cd7a120
--- /dev/null
+++ b/src/server/game/Movement/Spline/MoveSplineInit.h
@@ -0,0 +1,170 @@
+/*
+ * 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 TRINITYSERVER_MOVESPLINEINIT_H
+#define TRINITYSERVER_MOVESPLINEINIT_H
+
+#include "MoveSplineInitArgs.h"
+
+class Unit;
+
+namespace Movement
+{
+ enum AnimType
+ {
+ ToGround = 0, // 460 = ToGround, index of AnimationData.dbc
+ FlyToFly = 1, // 461 = FlyToFly?
+ ToFly = 2, // 458 = ToFly
+ FlyToGround = 3, // 463 = FlyToGround
+ };
+
+ /* Initializes and launches spline movement
+ */
+ class 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);
+ /* Plays animation after movement done
+ * can't be combined with parabolic movement
+ */
+ void SetAnimation(AnimType anim);
+
+ /* 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();
+ /* Inverses unit model orientation. Disabled by default
+ */
+ void SetOrientationInversed();
+ /* Fixes unit's model rotation. Disabled by default
+ */
+ void SetOrientationFixed(bool enable);
+
+ /* 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 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::SetOrientationInversed() { args.flags.orientationInversed = true;}
+ inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;}
+
+ 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)
+ {
+ args.time_perc = time_shift;
+ args.parabolic_amplitude = amplitude;
+ args.flags.EnableParabolic();
+ }
+
+ inline void MoveSplineInit::SetAnimation(AnimType anim)
+ {
+ args.time_perc = 0.f;
+ args.flags.EnableAnimation((uint8)anim);
+ }
+
+ 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 // TRINITYSERVER_MOVESPLINEINIT_H
diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h
new file mode 100644
index 00000000000..26fbbdd0fcc
--- /dev/null
+++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h
@@ -0,0 +1,67 @@
+/*
+ * 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 TRINITYSERVER_MOVESPLINEINIT_ARGS_H
+#define TRINITYSERVER_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), initialOrientation(0.f)
+ {
+ path.reserve(path_capacity);
+ }
+
+ PointsArray path;
+ FacingInfo facing;
+ MoveSplineFlag flags;
+ int32 path_Idx_offset;
+ float velocity;
+ float parabolic_amplitude;
+ float time_perc;
+ uint32 splineId;
+ float initialOrientation;
+
+ /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
+ bool Validate() const;
+ private:
+ bool _checkPathBounds() const;
+ };
+}
+
+#endif // TRINITYSERVER_MOVESPLINEINIT_ARGS_H
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
new file mode 100644
index 00000000000..73fdbf4c2f6
--- /dev/null
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
@@ -0,0 +1,188 @@
+/*
+ * 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 "MovementPacketBuilder.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; added in 3.1
+ data << float(1.f); // splineInfo.duration_mod_next; added in 3.1
+
+ data << move_spline.vertical_acceleration; // added in 3.1
+ data << move_spline.effect_start_time; // added in 3.1
+
+ uint32 nodes = move_spline.getPath().size();
+ data << nodes;
+ data.append<Vector3>(&move_spline.getPath()[0], nodes);
+ data << uint8(move_spline.spline.mode()); // added in 3.1
+ data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination());
+ }
+ }
+}
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.h b/src/server/game/Movement/Spline/MovementPacketBuilder.h
new file mode 100644
index 00000000000..92a414e9b3b
--- /dev/null
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.h
@@ -0,0 +1,37 @@
+/*
+ * 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 TRINITYSERVER_PACKET_BUILDER_H
+#define TRINITYSERVER_PACKET_BUILDER_H
+
+class ByteBuffer;
+class WorldPacket;
+
+namespace Movement
+{
+ class MoveSpline;
+ 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 // TRINITYSERVER_PACKET_BUILDER_H
diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h
new file mode 100644
index 00000000000..01c8a5b7e7b
--- /dev/null
+++ b/src/server/game/Movement/Spline/MovementTypedefs.h
@@ -0,0 +1,81 @@
+/*
+ * 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 TRINITYSERVER_TYPEDEFS_H
+#define TRINITYSERVER_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;
+
+ extern double gravity;
+ extern float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity);
+}
+
+#endif // TRINITYSERVER_TYPEDEFS_H
diff --git a/src/server/game/Movement/Spline/MovementUtil.cpp b/src/server/game/Movement/Spline/MovementUtil.cpp
new file mode 100644
index 00000000000..f0ed01c4676
--- /dev/null
+++ b/src/server/game/Movement/Spline/MovementUtil.cpp
@@ -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(AnimBit1 ),// 0x00000001,
+ STR(AnimBit2 ),// 0x00000002,
+ STR(AnimBit3 ),// 0x00000004,
+ STR(AnimBit4 ),// 0x00000008,
+ STR(AnimBit5 ),// 0x00000010,
+ STR(AnimBit6 ),// 0x00000020,
+ STR(AnimBit7 ),// 0x00000040,
+ STR(AnimBit8 ),// 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(OrientationInversed ),// 0x08000000, // Appears With Runmode 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;
+ }
+}
diff --git a/src/server/game/Movement/Spline/Spline.cpp b/src/server/game/Movement/Spline/Spline.cpp
new file mode 100644
index 00000000000..14c1bd0c117
--- /dev/null
+++ b/src/server/game/Movement/Spline/Spline.cpp
@@ -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
+{
+ 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
+{
+ 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;
+ 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
+{
+ ASSERT(index >= index_lo && index < index_hi);
+ result = points[index+1] - points[index];
+}
+
+void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const
+{
+ 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;
+ ASSERT(index >= index_lo && index < index_hi);
+ C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result);
+}
+
+float SplineBase::SegLengthLinear(index_type index) const
+{
+ ASSERT(index >= index_lo && index < index_hi);
+ return (points[index] - points[index+1]).length();
+}
+
+float SplineBase::SegLengthCatmullRom( index_type index ) const
+{
+ 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;
+ 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)
+{
+ 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();
+}
+
+}
diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h
new file mode 100644
index 00000000000..28876b220d4
--- /dev/null
+++ b/src/server/game/Movement/Spline/Spline.h
@@ -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 TRINITYSERVER_SPLINE_H
+#define TRINITYSERVER_SPLINE_H
+
+#include "MovementTypedefs.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 { 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;
+
+ 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 "SplineImpl.h"
+
+#endif // TRINITYSERVER_SPLINE_H
diff --git a/src/server/game/Movement/Spline/SplineImpl.h b/src/server/game/Movement/Spline/SplineImpl.h
new file mode 100644
index 00000000000..eded2d8c903
--- /dev/null
+++ b/src/server/game/Movement/Spline/SplineImpl.h
@@ -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
+{
+ ASSERT(t >= 0.f && t <= 1.f);
+ length_type length_ = t * length();
+ index = computeIndexInBounds(length_);
+ 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
+{
+ 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();
+}
+
+}
diff --git a/src/server/game/Movement/Traveller.h b/src/server/game/Movement/Traveller.h
deleted file mode 100755
index 641278ee37a..00000000000
--- a/src/server/game/Movement/Traveller.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_TRAVELLER_H
-#define TRINITY_TRAVELLER_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 Traveller
-{
- T &i_traveller;
- Traveller(T &t) : i_traveller(t) {}
- Traveller(const Traveller &obj) : i_traveller(obj) {}
- Traveller& operator=(const Traveller &obj)
- {
- this.i_traveller = obj.i_traveller;
- 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) { ASSERT(false); return 0.0f; }
- float GetMoveDestinationTo(float x, float y, float z);
- uint32 GetTotalTrevelTimeTo(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) {}
-};
-
-template<class T>
-inline uint32 Traveller<T>::GetTotalTrevelTimeTo(float x, float y, float z)
-{
- float dist = GetMoveDestinationTo(x, y, z);
- float speed = Speed();
- if (speed < 0.0f)
- return 0xfffffffe; // almost infinity-unit should stop
- else
- 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.HasUnitState(UNIT_STAT_CHARGING))
- return i_traveller.m_TempSpeed;
- else if (i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_WALKING))
- return i_traveller.GetSpeed(MOVE_WALK);
- else if (i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_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.UpdatePosition(x, y, z, orientation);
-}
-
-template<>
-inline float Traveller<Creature>::GetMoveDestinationTo(float x, float y, float z)
-{
- float dx = x - GetPositionX();
- float dy = y - GetPositionY();
- float dz = z - GetPositionZ();
-
- //if (i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_FLYING))
- 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.AI_SendMoveToPacket(x, y, z, t, i_traveller.GetUnitMovementFlags(), 0);
- i_traveller.SendMonsterMove(x, y, z, t);
-}
-
-// specialization for players
-template<>
-inline float Traveller<Player>::Speed()
-{
- if (i_traveller.HasUnitState(UNIT_STAT_CHARGING))
- return i_traveller.m_TempSpeed;
- else if (i_traveller.isInFlight())
- return PLAYER_FLIGHT_SPEED;
- else
- return i_traveller.GetSpeed(i_traveller.m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING) ? 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.isInFlight())
- 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.UpdatePosition(x, y, z, orientation);
-}
-
-template<>
-inline void Traveller<Player>::MoveTo(float x, float y, float z, uint32 t)
-{
- //Only send MOVEMENTFLAG_WALKING, client has strange issues with other move flags
- i_traveller.SendMonsterMove(x, y, z, t);
-}
-
-typedef Traveller<Creature> CreatureTraveller;
-typedef Traveller<Player> PlayerTraveller;
-#endif
-
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index 71195538256..7757e1a1a35 100755
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -475,8 +475,14 @@ void Map::ScriptsProcess()
// Source or target must be Creature.
if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
{
- cSource->SendMonsterMoveWithSpeed(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, step.script->MoveTo.TravelTime);
- cSource->GetMap()->CreatureRelocation(cSource, step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, 0);
+ Unit * unit = (Unit*)cSource;
+ if (step.script->MoveTo.TravelTime != 0)
+ {
+ float speed = unit->GetDistance(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ) / ((float)step.script->MoveTo.TravelTime * 0.001f);
+ unit->MonsterMoveWithSpeed(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, speed);
+ }
+ else
+ unit->NearTeleportTo(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, unit->GetOrientation());
}
break;
diff --git a/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp b/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp
index 81481bdef31..3533b153bd8 100755
--- a/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp
@@ -27,7 +27,6 @@
#include "UpdateMask.h"
#include "Path.h"
#include "WaypointMovementGenerator.h"
-#include "DestinationHolderImp.h"
void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket & recv_data)
{
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 1d3c657f50a..535253f4e13 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4761,11 +4761,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
break;
case 46361: // Reinforced Net
if (caster)
- {
- float currentGroundLevel = target->GetBaseMap()->GetHeight(target->GetPositionX(), target->GetPositionY(), MAX_HEIGHT);
- if (target->GetPositionZ() > currentGroundLevel)
- target->GetMotionMaster()->MoveFall(currentGroundLevel);
- }
+ target->GetMotionMaster()->MoveFall();
break;
case 46699: // Requires No Ammo
if (target->GetTypeId() == TYPEID_PLAYER)
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 2c33488f76c..eaf5f4e1d31 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3363,22 +3363,11 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
if (unitTarget->HasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING))
return;
- float angle = unitTarget->GetAngle(m_targets.GetDst());
+ unitTarget->SetFacingTo(unitTarget->GetAngle(m_targets.GetDst()));
+ unitTarget->ClearUnitState(UNIT_STAT_MOVING);
- if (unitTarget->GetTypeId() == TYPEID_PLAYER)
- {
- // For players just turn them
- unitTarget->ToPlayer()->UpdatePosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
- unitTarget->ToPlayer()->SendTeleportAckPacket();
- }
- else
- {
- // Set creature Distracted, Stop it, And turn it
- unitTarget->SetOrientation(angle);
- unitTarget->StopMoving();
+ if (unitTarget->GetTypeId() == TYPEID_UNIT)
unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
- unitTarget->SendMovementFlagUpdate();
- }
}
void Spell::EffectPickPocket(SpellEffIndex /*effIndex*/)
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 54dac404f03..1b6a6c6fdcf 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -1036,15 +1036,14 @@ public:
}
if (/*creature->GetMotionMaster()->empty() ||*/
- creature->GetMotionMaster()->GetCurrentMovementGeneratorType () != TARGETED_MOTION_TYPE)
+ creature->GetMotionMaster()->GetCurrentMovementGeneratorType () != FOLLOW_MOTION_TYPE)
{
handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName());
handler->SetSentErrorMessage(true);
return false;
}
- TargetedMovementGenerator<Creature> const* mgen
- = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
+ FollowMovementGenerator<Creature> const* mgen = static_cast<FollowMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
if (mgen->GetTarget() != player)
{
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index 999f3fda2e4..a7d1c3ad8ba 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -1009,7 +1009,7 @@ public:
me->SetInFront(car);
me->SendMovementFlagUpdate();
car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ() + 1);
- car->SendMonsterStop();
+ car->StopMoving();
car->RemoveAura(SPELL_CART_DRAG);
}
me->MonsterSay(SAY_SCARLET_MINER2, LANG_UNIVERSAL, 0);
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
index d04d7af5c80..eee6b08d834 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
@@ -325,7 +325,7 @@ class boss_akilzon : public CreatureScript
if (target)
{
target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
- target->SendMonsterMove(x, y, me->GetPositionZ()+15, 0);
+ target->MonsterMoveWithSpeed(x, y, me->GetPositionZ()+15, 0);
}
Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000);
if (Cloud)
diff --git a/src/server/scripts/EasternKingdoms/undercity.cpp b/src/server/scripts/EasternKingdoms/undercity.cpp
index f1c0fba2e29..fe9c40e6dbd 100644
--- a/src/server/scripts/EasternKingdoms/undercity.cpp
+++ b/src/server/scripts/EasternKingdoms/undercity.cpp
@@ -109,7 +109,7 @@ public:
{
if (Creature* target = Unit::GetCreature(*summoned, targetGUID))
{
- target->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), me->GetPositionZ()+15.0f, 0);
+ target->MonsterMoveWithSpeed(target->GetPositionX(), target->GetPositionY(), me->GetPositionZ()+15.0f, 0);
target->SetPosition(target->GetPositionX(), target->GetPositionY(), me->GetPositionZ()+15.0f, 0.0f);
summoned->CastSpell(target, SPELL_RIBBON_OF_SOULS, false);
}
@@ -186,7 +186,7 @@ public:
if (EventMove_Timer <= diff)
{
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- me->SendMonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, 5000);
+ me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, me->GetDistance(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW) / (5000 * 0.001f));
me->SetPosition(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, me->GetOrientation());
EventMove = false;
} else EventMove_Timer -= diff;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
index bc6145252d2..8e34a318d6c 100755
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -592,11 +592,8 @@ public:
me->GetMotionMaster()->MoveIdle();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
//At hit the ground
- me->GetPosition(x, y, z);
- z = me->GetMap()->GetHeight(x, y, z, true, 50);
me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH);
- me->GetMotionMaster()->MoveFall(z, 0);
- //me->FallGround(); //need correct vmap use (i believe it isn't working properly right now)
+ me->GetMotionMaster()->MoveFall();
}
}
}
@@ -610,7 +607,6 @@ public:
case 0:
me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE);
me->SetDisplayId(11686);
- me->Relocate(x, y, z, me->GetOrientation());
DoCast(SPELL_PERMAFROST_VISUAL);
DoCast(SPELL_PERMAFROST);
me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f);
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
index bc06a92ef07..d444160b8f2 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
@@ -201,7 +201,7 @@ class mob_corrupted_soul_fragment : public CreatureScript
void MovementInform(uint32 type, uint32 id)
{
- if (type != TARGETED_MOTION_TYPE)
+ if (type != CHASE_MOTION_TYPE)
return;
if (instance)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index 3b15bba5c5d..94a3da2672b 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -1159,7 +1159,7 @@ class npc_ball_of_flame : public CreatureScript
void MovementInform(uint32 type, uint32 id)
{
- if (type == TARGETED_MOTION_TYPE && id == GUID_LOPART(_chaseGUID) && _chaseGUID)
+ if (type == CHASE_MOTION_TYPE && id == GUID_LOPART(_chaseGUID) && _chaseGUID)
{
me->RemoveAurasDueToSpell(SPELL_BALL_OF_FLAMES_PERIODIC);
DoCast(me, SPELL_FLAMES);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
index 8396b6e6c85..31b3786a360 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
@@ -608,7 +608,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->SendMovementFlagUpdate();
me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f);
- me->SendMonsterMove(me->GetPositionX(), me->GetPositionY(), 539.2917f, SPLINEFLAG_FALLING, 0, 0.0f);
+ me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f);
for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
(*itr)->AI()->DoAction(ACTION_DESPAWN);
break;
@@ -815,7 +815,7 @@ class npc_muradin_bronzebeard_icc : public CreatureScript
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->SendMovementFlagUpdate();
me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f);
- me->SendMonsterMove(me->GetPositionX(), me->GetPositionY(), 539.2917f, SPLINEFLAG_FALLING, 0, 0.0f);
+ me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f);
for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
(*itr)->AI()->DoAction(ACTION_DESPAWN);
break;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index f2657e5b2ef..5029dbcceee 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -508,7 +508,7 @@ class boss_the_lich_king : public CreatureScript
if (fabs(ground_Z - z) < 0.1f)
return;
- me->GetMotionMaster()->MoveFall(ground_Z);
+ me->GetMotionMaster()->MoveFall();
}
void EnterCombat(Unit* target)
@@ -801,7 +801,7 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_INTRO_TALK_1, 9000, 0, PHASE_INTRO);
break;
case POINT_CENTER_1:
- me->SetFacing(0.0f);
+ me->SetFacingTo(0.0f);
Talk(SAY_LK_REMORSELESS_WINTER);
SendMusicToPlayers(MUSIC_SPECIAL);
me->SetReactState(REACT_PASSIVE);
@@ -818,7 +818,7 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_SOUL_REAPER, 94000, 0, PHASE_TWO);
break;
case POINT_CENTER_2:
- me->SetFacing(0.0f);
+ me->SetFacingTo(0.0f);
Talk(SAY_LK_REMORSELESS_WINTER);
SendMusicToPlayers(MUSIC_SPECIAL);
me->SetReactState(REACT_PASSIVE);
@@ -1047,14 +1047,14 @@ class boss_the_lich_king : public CreatureScript
break;
case EVENT_OUTRO_TALK_3:
if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
- me->SetFacing(0.0f, tirion);
+ me->SetFacingToObject(tirion);
Talk(SAY_LK_OUTRO_3);
break;
case EVENT_OUTRO_MOVE_CENTER:
me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_1, CenterPosition);
break;
case EVENT_OUTRO_TALK_4:
- me->SetFacing(0.01745329f);
+ me->SetFacingTo(0.01745329f);
Talk(SAY_LK_OUTRO_4);
break;
case EVENT_OUTRO_RAISE_DEAD:
@@ -1070,7 +1070,7 @@ class boss_the_lich_king : public CreatureScript
case EVENT_OUTRO_TALK_6:
Talk(SAY_LK_OUTRO_6);
if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
- tirion->SetFacing(0.0f, me);
+ tirion->SetFacingToObject(me);
me->ClearUnitState(UNIT_STAT_CASTING);
DoCastAOE(SPELL_SUMMON_BROKEN_FROSTMOURNE_3);
SetEquipmentSlots(false, EQUIP_UNEQUIP);
@@ -1222,7 +1222,7 @@ class npc_tirion_fordring_tft : public CreatureScript
void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
{
if (spell->Id == SPELL_ICE_LOCK)
- me->SetFacing(3.085098f);
+ me->SetFacingTo(3.085098f);
else if (spell->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
SetEquipmentSlots(true); // remove glow on ashbringer
}
@@ -1285,7 +1285,7 @@ class npc_tirion_fordring_tft : public CreatureScript
SetEquipmentSlots(false, EQUIP_ASHBRINGER_GLOWING);
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
{
- me->SetFacing(0.0f, lichKing);
+ me->SetFacingToObject(lichKing);
lichKing->AI()->DoAction(ACTION_PLAY_MUSIC);
}
break;
@@ -1621,7 +1621,7 @@ class npc_strangulate_vehicle : public CreatureScript
void IsSummonedBy(Unit* summoner)
{
- me->SetFacing(0.0f, summoner);
+ me->SetFacingToObject(summoner);
DoCast(summoner, SPELL_HARVEST_SOUL_VEHICLE);
_events.Reset();
_events.ScheduleEvent(EVENT_MOVE_TO_LICH_KING, 2000);
@@ -1789,7 +1789,7 @@ class npc_terenas_menethil : public CreatureScript
_events.Reset();
_events.SetPhase(PHASE_OUTRO);
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
- me->SetFacing(0.0f, lichKing);
+ me->SetFacingToObject(lichKing);
_events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_1, 2000, 0, PHASE_OUTRO);
_events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_2, 14000, 0, PHASE_OUTRO);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
index ab3046806db..6bd8f3cba7d 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
@@ -1264,7 +1264,7 @@ struct npc_argent_captainAI : public ScriptedAI
void EnterEvadeMode()
{
// not yet following
- if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != TARGETED_MOTION_TYPE || IsUndead)
+ if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != CHASE_MOTION_TYPE || IsUndead)
{
ScriptedAI::EnterEvadeMode();
return;
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 8e995a9b260..052fa3ba4a5 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -838,7 +838,7 @@ public:
return;
}
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f);
}
}
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
index 194c2a36862..1fc724c8b6c 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
@@ -243,7 +243,7 @@ public:
{
if (m_uiPause_Timer <= uiDiff)
{
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
if (me->getVictim())
me->GetMotionMaster()->MoveChase(me->getVictim());
@@ -421,7 +421,7 @@ public:
// me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //Set in DB
if (me->IsNonMeleeSpellCasted(false))
me->InterruptNonMeleeSpells(false);
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
m_bIsFrozen = true;
}
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
index 4ee71367b55..d1aba800094 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
@@ -174,7 +174,7 @@ public:
bIsSlam = false;
//and correct movement, if not already
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
{
if (me->getVictim())
me->GetMotionMaster()->MoveChase(me->getVictim());
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
index 68435fffb1b..2c7532fcf70 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
@@ -634,7 +634,7 @@ class boss_stormcaller_brundir : public CreatureScript
// Prevent to have Brundir somewhere in the air when he die in Air phase
if (me->GetPositionZ() > FLOOR_Z)
- me->GetMotionMaster()->MoveFall(FLOOR_Z);
+ me->GetMotionMaster()->MoveFall();
}
void KilledUnit(Unit* /*who*/)
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
index 1bedd7e19e9..d5cd79b25f1 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
@@ -288,7 +288,7 @@ public:
me->Dismount();
if (Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILLISECONDS))
{
- pGrauf->GetMotionMaster()->MoveFall(0);
+ pGrauf->GetMotionMaster()->MoveFall();
pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH);
}
me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f);
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
index 9cab1de197c..436336ec5b8 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
@@ -249,22 +249,16 @@ public:
if (Phase == SACRIFICING)
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
- me->GetPosition(x, y, z);
- z = me->GetMap()->GetHeight(x, y, z, true, 50);
+ damage = 0;
+ Phase = SVALADEAD;
+ me->InterruptNonMeleeSpells(true);
+ me->RemoveAllAuras();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetHealth(1);
- if (me->GetPositionZ() > z)
- {
- damage = 0;
- Phase = SVALADEAD;
- me->InterruptNonMeleeSpells(true);
- me->RemoveAllAuras();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetHealth(1);
-
- SetCombatMovement(false);
- me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH);
- me->GetMotionMaster()->MoveFall(z, 1);
- }
+ SetCombatMovement(false);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH);
+ me->GetMotionMaster()->MoveFall();
}
}
@@ -274,10 +268,7 @@ public:
return;
if (pointId == 1)
- {
- me->Relocate(x, y, z, me->GetOrientation());
me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- }
}
void JustDied(Unit* killer)
diff --git a/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp
index 81211b6e3d9..aa63f1adf18 100644
--- a/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp
@@ -187,7 +187,7 @@ public:
//expire movement, will prevent from running right back to victim after cast
//(but should MoveChase be used again at a certain time or should he not move?)
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
DoCast(me, SPELL_BLINK);
diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
index b23b7bcd1ac..c17b6d5baf3 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
@@ -1982,7 +1982,7 @@ void boss_illidan_stormrage::boss_illidan_stormrageAI::HandleTalkSequence()
Akama->GetMotionMaster()->Clear(false);
// Akama->GetMotionMaster()->MoveIdle();
Akama->SetPosition(x, y, z, 0.0f);
- Akama->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_NONE, 0); // Illidan must not die until Akama arrives.
+ Akama->MonsterMoveWithSpeed(x, y, z, 0); // Illidan must not die until Akama arrives.
Akama->GetMotionMaster()->MoveChase(me);
}
diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp
index 33196b1213a..b7604c41794 100644
--- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp
+++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp
@@ -151,7 +151,7 @@ public:
m_bPerformingGroundSlam = false;
//and correct movement, if not already
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
{
if (me->getVictim())
me->GetMotionMaster()->MoveChase(me->getVictim());
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
index 974d81ef914..a45576f8884 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
@@ -820,7 +820,7 @@ class boss_kaelthas : public CreatureScript
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0);
- me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0);
+ me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 1);
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_FULLPOWER);
@@ -887,7 +887,7 @@ class boss_kaelthas : public CreatureScript
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0);
- me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0);
+ me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0);
// 1) Kael'thas will portal the whole raid right into his body
for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i)
diff --git a/src/server/scripts/World/guards.cpp b/src/server/scripts/World/guards.cpp
index d562542a7d7..9bc511931b9 100644
--- a/src/server/scripts/World/guards.cpp
+++ b/src/server/scripts/World/guards.cpp
@@ -179,7 +179,7 @@ public:
globalCooldown = GENERIC_CREATURE_COOLDOWN;
} //If no spells available and we arn't moving run to target
- else if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ else if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
{
//Cancel our current spell and then mutate new movement generator
me->InterruptNonMeleeSpells(false);
diff --git a/src/server/shared/Utilities/Timer.h b/src/server/shared/Utilities/Timer.h
index 4dae8ac30d2..4d3f02f6688 100755
--- a/src/server/shared/Utilities/Timer.h
+++ b/src/server/shared/Utilities/Timer.h
@@ -133,7 +133,7 @@ struct TimeTrackerSmall
{
public:
- TimeTrackerSmall(uint32 expiry)
+ TimeTrackerSmall(uint32 expiry = 0)
: i_expiryTime(expiry)
{
}