aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
{
}