Created
January 22, 2011 20:06
-
-
Save vermie/791419 to your computer and use it in GitHub Desktop.
ChargeMovementGenerator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/game/ChargeMovementGenerator.cpp b/src/game/ChargeMovementGenerator.cpp | |
new file mode 100644 | |
index 0000000..73838f2 | |
--- /dev/null | |
+++ b/src/game/ChargeMovementGenerator.cpp | |
@@ -0,0 +1,126 @@ | |
+ | |
+#include "ChargeMovementGenerator.h" | |
+ | |
+template<class T, class U> | |
+ChargeMovementGeneratorMedium<T, U>::ChargeMovementGeneratorMedium(Unit* target, const uint32 triggeredSpellId) | |
+ : PathMovementBase(), m_target(target), m_triggeredSpellId(triggeredSpellId) | |
+{ | |
+} | |
+ | |
+template<class T, class U> | |
+bool ChargeMovementGeneratorMedium<T, U>::Update(T &owner, const uint32 &diff) | |
+{ | |
+ if (!&owner) | |
+ return true; | |
+ | |
+ // if the unit can't move, stop charge | |
+ if (owner.hasUnitState(UNIT_STAT_NOT_MOVE)) | |
+ return true; | |
+ | |
+ // if there is no path, stop charge | |
+ if (i_path.empty()) | |
+ return true; | |
+ | |
+ Traveller<T> traveller(owner); | |
+ traveller.SetCustomSpeed(CHARGE_SPEED); | |
+ | |
+ if (i_destinationHolder.UpdateTraveller(traveller, diff, false, false)) | |
+ if (!IsActive(owner)) | |
+ return true; | |
+ | |
+ if (i_destinationHolder.HasArrived()) | |
+ { | |
+ ++i_currentNode; | |
+ | |
+ // if we are at the last node, stop charge | |
+ if (i_currentNode >= i_path.size()) | |
+ return true; | |
+ | |
+ MoveToNextNode(traveller); | |
+ } | |
+ | |
+ return false; | |
+} | |
+ | |
+template<class T, class U> | |
+void ChargeMovementGeneratorMedium<T, U>::MoveToNextNode(Traveller<T> &traveller) | |
+{ | |
+ PathNode &node = i_path[i_currentNode]; | |
+ i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z, false); | |
+} | |
+ | |
+template<class T, class U> | |
+void ChargeMovementGeneratorMedium<T, U>::LoadPath(T &owner) | |
+{ | |
+ // set the destination | |
+ float x, y, z; | |
+ m_target->GetContactPoint(&owner, x, y, z); | |
+ | |
+ // get the path to the destination | |
+ PathInfo path(&owner, x, y, z); | |
+ i_path = path.getFullPath(); | |
+ | |
+ // start movement | |
+ Traveller<T> traveller(owner); | |
+ traveller.SetCustomSpeed(CHARGE_SPEED); | |
+ MoveToNextNode(traveller); | |
+ | |
+ // send path to client | |
+ uint32 transitTime = uint32(i_path.GetTotalLength() / (CHARGE_SPEED / IN_MILLISECONDS)); | |
+ owner.MonsterMoveByPath(i_path, 1, i_path.size(), transitTime); | |
+} | |
+ | |
+template<class T, class U> | |
+void ChargeMovementGeneratorMedium<T, U>::Initialize(T &owner) | |
+{ | |
+ owner.addUnitState(UNIT_STAT_CHARGE|UNIT_STAT_CHARGE_MOVE); | |
+ | |
+ LoadPath(owner); | |
+ | |
+ // TODO: disable player bar? | |
+} | |
+ | |
+template<class T, class U> | |
+void ChargeMovementGeneratorMedium<T, U>::Finalize(T &owner) | |
+{ | |
+ owner.clearUnitState(UNIT_STAT_CHARGE|UNIT_STAT_CHARGE_MOVE); | |
+ | |
+ if (i_currentNode >= i_path.size() && m_target) | |
+ { | |
+ // we are at the destination, turn to target and cast spell | |
+ owner.SetInFront(m_target); | |
+ | |
+ if (m_triggeredSpellId) | |
+ owner.CastSpell(m_target, m_triggeredSpellId, true); | |
+ } | |
+} | |
+ | |
+template<class T, class U> | |
+void ChargeMovementGeneratorMedium<T, U>::Interrupt(T &owner) | |
+{ | |
+ owner.clearUnitState(UNIT_STAT_CHARGE|UNIT_STAT_CHARGE_MOVE); | |
+} | |
+ | |
+template<class T, class U> | |
+void ChargeMovementGeneratorMedium<T, U>::Reset(T &owner) | |
+{ | |
+ Initialize(owner); | |
+} | |
+ | |
+template ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::ChargeMovementGeneratorMedium(Unit*, const uint32); | |
+template void ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::Finalize(Player &); | |
+template void ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::Initialize(Player &); | |
+template void ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::Interrupt(Player &); | |
+template void ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::LoadPath(Player &); | |
+template void ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::MoveToNextNode(PlayerTraveller &); | |
+template void ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::Reset(Player &); | |
+template bool ChargeMovementGeneratorMedium<Player, ChargeMovementGenerator<Player> >::Update(Player &, const uint32 &); | |
+ | |
+template ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::ChargeMovementGeneratorMedium(Unit*, const uint32); | |
+template void ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::Finalize(Creature &); | |
+template void ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::Initialize(Creature &); | |
+template void ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::Interrupt(Creature &); | |
+template void ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::LoadPath(Creature &); | |
+template void ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::MoveToNextNode(CreatureTraveller &); | |
+template void ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::Reset(Creature &); | |
+template bool ChargeMovementGeneratorMedium<Creature, ChargeMovementGenerator<Creature> >::Update(Creature &, const uint32 &); | |
diff --git a/src/game/ChargeMovementGenerator.h b/src/game/ChargeMovementGenerator.h | |
new file mode 100644 | |
index 0000000..cde32d9 | |
--- /dev/null | |
+++ b/src/game/ChargeMovementGenerator.h | |
@@ -0,0 +1,42 @@ | |
+ | |
+#ifndef MANGOS_CHARGEMOVEMENTGENERATOR_H | |
+#define MANGOS_CHARGEMOVEMENTGENERATOR_H | |
+ | |
+#include "WaypointMovementGenerator.h" | |
+#include "PathFinder.h" | |
+ | |
+// TODO: figure out nice speed for charge | |
+#define CHARGE_SPEED 25.0f | |
+ | |
+template<class T, class U> | |
+class ChargeMovementGeneratorMedium : public MovementGeneratorMedium<T, U>, public PathMovementBase<T, PointPath> | |
+{ | |
+public: | |
+ ChargeMovementGeneratorMedium(Unit* target, const uint32 triggeredSpellId); | |
+ | |
+ void Initialize(T &u); | |
+ void Interrupt(T &); | |
+ void Finalize(T &); | |
+ void Reset(T &u); | |
+ bool Update(T &u, const uint32 &diff); | |
+ | |
+ void LoadPath(T &u); | |
+ | |
+ MovementGeneratorType GetMovementGeneratorType() const { return CHARGE_MOTION_TYPE; } | |
+ | |
+private: | |
+ Unit* m_target; | |
+ const uint32 m_triggeredSpellId; | |
+ | |
+ void MoveToNextNode(Traveller<T> &traveller); | |
+}; | |
+ | |
+template<class T> | |
+class ChargeMovementGenerator : public ChargeMovementGeneratorMedium<T, ChargeMovementGenerator<T> > | |
+{ | |
+public: | |
+ ChargeMovementGenerator(Unit* target, const uint32 triggeredSpellId) | |
+ : ChargeMovementGeneratorMedium<T, ChargeMovementGenerator<T> >(target, triggeredSpellId) {} | |
+}; | |
+ | |
+#endif | |
\ No newline at end of file | |
diff --git a/src/game/Makefile.am b/src/game/Makefile.am | |
index 316711a..6b7062a 100644 | |
--- a/src/game/Makefile.am | |
+++ b/src/game/Makefile.am | |
@@ -89,6 +89,8 @@ libmangosgame_a_SOURCES = \ | |
CharacterDatabaseCleaner.cpp \ | |
CharacterDatabaseCleaner.h \ | |
CharacterHandler.cpp \ | |
+ ChargeMovementHandler.cpp \ | |
+ ChargeMovementHandler.h \ | |
Chat.cpp \ | |
Chat.h \ | |
ChatHandler.cpp \ | |
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp | |
index 0f74601..087e7bb 100644 | |
--- a/src/game/MotionMaster.cpp | |
+++ b/src/game/MotionMaster.cpp | |
@@ -27,6 +27,7 @@ | |
#include "IdleMovementGenerator.h" | |
#include "PointMovementGenerator.h" | |
#include "TargetedMovementGenerator.h" | |
+#include "ChargeMovementGenerator.h" | |
#include "WaypointMovementGenerator.h" | |
#include "RandomMovementGenerator.h" | |
@@ -66,7 +67,13 @@ MotionMaster::~MotionMaster() | |
void MotionMaster::UpdateMotion(uint32 diff) | |
{ | |
if (m_owner->hasUnitState(UNIT_STAT_CAN_NOT_MOVE)) | |
+ { | |
+ // cancel charge if owner is not dead | |
+ if (!m_owner->hasUnitState(UNIT_STAT_DIED) && top()->GetMovementGeneratorType() == CHARGE_MOTION_TYPE) | |
+ DirectExpire(true); | |
+ | |
return; | |
+ } | |
MANGOS_ASSERT( !empty() ); | |
m_cleanFlag |= MMCF_UPDATE; | |
@@ -403,6 +410,17 @@ void MotionMaster::MoveDistract(uint32 timer) | |
Mutate(mgen); | |
} | |
+void MotionMaster::MoveCharge(Unit* target, uint32 triggeredSpellId/* = 0*/) | |
+{ | |
+ if (!target) | |
+ return; | |
+ | |
+ if (m_owner->GetTypeId() == TYPEID_PLAYER) | |
+ Mutate(new ChargeMovementGenerator<Player>(target, triggeredSpellId)); | |
+ else | |
+ Mutate(new ChargeMovementGenerator<Creature>(target, triggeredSpellId)); | |
+} | |
+ | |
void MotionMaster::Mutate(MovementGenerator *m) | |
{ | |
if (!empty()) | |
diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h | |
index ec23db1..c17d9df 100644 | |
--- a/src/game/MotionMaster.h | |
+++ b/src/game/MotionMaster.h | |
@@ -48,6 +48,7 @@ enum MovementGeneratorType | |
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) | |
FOLLOW_MOTION_TYPE = 14, // TargetedMovementGenerator.h | |
+ CHARGE_MOTION_TYPE = 15, // ChargeMovementGenerator.h (handles SpellEffect charge) | |
}; | |
enum MMCleanFlag | |
@@ -107,6 +108,7 @@ class MANGOS_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *> | |
void MoveWaypoint(); | |
void MoveTaxiFlight(uint32 path, uint32 pathnode); | |
void MoveDistract(uint32 timeLimit); | |
+ void MoveCharge(Unit* target, uint32 triggeredSpellId = 0); | |
MovementGeneratorType GetCurrentMovementGeneratorType() const; | |
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp | |
index 8263fb3..96faf2b 100644 | |
--- a/src/game/SpellEffects.cpp | |
+++ b/src/game/SpellEffects.cpp | |
@@ -7598,15 +7598,7 @@ void Spell::EffectCharge(SpellEffectIndex /*eff_idx*/) | |
if (!unitTarget) | |
return; | |
- //TODO: research more ContactPoint/attack distance. | |
- //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result. | |
- float x, y, z; | |
- unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f); | |
- | |
- if (unitTarget->GetTypeId() != TYPEID_PLAYER) | |
- ((Creature *)unitTarget)->StopMoving(); | |
- | |
- m_caster->MonsterMoveByPath(x, y, z, 25, false); | |
+ m_caster->GetMotionMaster()->MoveCharge(unitTarget); | |
// not all charge effects used in negative spells | |
if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id)) | |
diff --git a/src/game/Traveller.h b/src/game/Traveller.h | |
index 2101527..566c1a5 100644 | |
--- a/src/game/Traveller.h | |
+++ b/src/game/Traveller.h | |
@@ -32,9 +32,8 @@ | |
template<class T> | |
struct MANGOS_DLL_DECL Traveller | |
{ | |
- T &i_traveller; | |
- Traveller(T &t) : i_traveller(t) {} | |
- Traveller(const Traveller &obj) : i_traveller(obj) {} | |
+ Traveller(T &t) : i_traveller(t), m_usingCustomSpeed(false) {} | |
+ Traveller(const Traveller &obj) : i_traveller(obj), m_usingCustomSpeed(false) {} | |
Traveller& operator=(const Traveller &obj) | |
{ | |
~Traveller(); | |
@@ -50,6 +49,7 @@ struct MANGOS_DLL_DECL Traveller | |
T& GetTraveller(void) { return i_traveller; } | |
float Speed(void) { MANGOS_ASSERT(false); return 0.0f; } | |
+ void SetCustomSpeed(float newSpeed) { m_usingCustomSpeed = true; m_speed = newSpeed; } | |
float GetMoveDestinationTo(float x, float y, float z); | |
uint32 GetTotalTravelTimeTo(float x, float y, float z); | |
@@ -57,6 +57,11 @@ struct MANGOS_DLL_DECL Traveller | |
void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); } | |
void MoveTo(float x, float y, float z, uint32 t) {} | |
void Stop() {} | |
+ | |
+private: | |
+ T &i_traveller; | |
+ float m_speed; | |
+ bool m_usingCustomSpeed; | |
}; | |
template<class T> | |
@@ -73,7 +78,9 @@ inline uint32 Traveller<T>::GetTotalTravelTimeTo(float x, float y, float z) | |
template<> | |
inline float Traveller<Creature>::Speed() | |
{ | |
- if(i_traveller.HasSplineFlag(SPLINEFLAG_WALKMODE)) | |
+ if (m_usingCustomSpeed) | |
+ return m_speed; | |
+ else if(i_traveller.HasSplineFlag(SPLINEFLAG_WALKMODE)) | |
return i_traveller.GetSpeed(MOVE_WALK); | |
else if(i_traveller.HasSplineFlag(SPLINEFLAG_UNKNOWN7)) | |
return i_traveller.GetSpeed(MOVE_FLIGHT); | |
@@ -121,6 +128,8 @@ inline float Traveller<Player>::Speed() | |
{ | |
if (i_traveller.IsTaxiFlying()) | |
return PLAYER_FLIGHT_SPEED; | |
+ else if (m_usingCustomSpeed) | |
+ return m_speed; | |
else | |
return i_traveller.GetSpeed(i_traveller.m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE) ? MOVE_WALK : MOVE_RUN); | |
} | |
diff --git a/src/game/Unit.h b/src/game/Unit.h | |
index f362608..7c8af1a 100644 | |
--- a/src/game/Unit.h | |
+++ b/src/game/Unit.h | |
@@ -440,8 +440,10 @@ enum UnitState | |
UNIT_STAT_FOLLOW_MOVE = 0x00010000, | |
UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack | |
UNIT_STAT_FLEEING_MOVE = 0x00040000, | |
+ UNIT_STAT_CHARGE = 0x00080000, // ChargeMovementGenerator active | |
+ UNIT_STAT_CHARGE_MOVE = 0x00100000, | |
- UNIT_STAT_IGNORE_PATHFINDING = 0x00080000, // do not use pathfinding in any MovementGenerator | |
+ UNIT_STAT_IGNORE_PATHFINDING = 0x00200000, // do not use pathfinding in any MovementGenerator | |
// masks (only for check) | |
@@ -455,11 +457,11 @@ enum UnitState | |
// stay or scripted movement for effect( = in player case you can't move by client command) | |
UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | | |
UNIT_STAT_TAXI_FLIGHT | | |
- UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, | |
+ UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_CHARGE, | |
// not react at move in sight or other | |
UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED | | |
- UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, | |
+ UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_CHARGE, | |
// AI disabled by some reason | |
UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED, | |
@@ -470,7 +472,7 @@ enum UnitState | |
// masks (for check or reset) | |
// for real move using movegen check and stop (except unstoppable flight) | |
- UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE | UNIT_STAT_FLEEING_MOVE, | |
+ UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE | UNIT_STAT_FLEEING_MOVE | UNIT_STAT_CHARGE_MOVE, | |
UNIT_STAT_ALL_STATE = 0xFFFFFFFF | |
}; | |
diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp | |
index 107600a..4fd3933 100644 | |
--- a/src/game/WaypointMovementGenerator.cpp | |
+++ b/src/game/WaypointMovementGenerator.cpp | |
@@ -302,7 +302,7 @@ bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, | |
void WaypointMovementGenerator<Creature>::MoveToNextNode(CreatureTraveller &traveller) | |
{ | |
- Creature* owner = &(traveller.i_traveller); | |
+ Creature* owner = &(traveller.GetTraveller()); | |
const WaypointNode &node = i_path->at(i_currentNode); | |
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z, false); | |
diff --git a/win/VC100/game.vcxproj b/win/VC100/game.vcxproj | |
index 956f5d9..9157443 100644 | |
--- a/win/VC100/game.vcxproj | |
+++ b/win/VC100/game.vcxproj | |
@@ -386,6 +386,7 @@ | |
<ClCompile Include="..\..\src\game\ChannelMgr.cpp" /> | |
<ClCompile Include="..\..\src\game\CharacterDatabaseCleaner.cpp" /> | |
<ClCompile Include="..\..\src\game\CharacterHandler.cpp" /> | |
+ <ClCompile Include="..\..\src\game\ChargeMovementGenerator.cpp" /> | |
<ClCompile Include="..\..\src\game\Chat.cpp" /> | |
<ClCompile Include="..\..\src\game\ChatHandler.cpp" /> | |
<ClCompile Include="..\..\src\game\CombatHandler.cpp" /> | |
@@ -545,6 +546,7 @@ | |
<ClInclude Include="..\..\src\game\Channel.h" /> | |
<ClInclude Include="..\..\src\game\ChannelMgr.h" /> | |
<ClInclude Include="..\..\src\game\CharacterDatabaseCleaner.h" /> | |
+ <ClInclude Include="..\..\src\game\ChargeMovementGenerator.h" /> | |
<ClInclude Include="..\..\src\game\Chat.h" /> | |
<ClInclude Include="..\..\src\game\ConfusedMovementGenerator.h" /> | |
<ClInclude Include="..\..\src\game\Corpse.h" /> | |
diff --git a/win/VC100/game.vcxproj.filters b/win/VC100/game.vcxproj.filters | |
index d805b10..7c8603f 100644 | |
--- a/win/VC100/game.vcxproj.filters | |
+++ b/win/VC100/game.vcxproj.filters | |
@@ -481,6 +481,9 @@ | |
<ClCompile Include="..\..\src\game\vmap\WorldModel.cpp"> | |
<Filter>vmaps</Filter> | |
</ClCompile> | |
+ <ClCompile Include="..\..\src\game\ChargeMovementGenerator.cpp"> | |
+ <Filter>Motion generators</Filter> | |
+ </ClCompile> | |
</ItemGroup> | |
<ItemGroup> | |
<ClInclude Include="..\..\src\game\AccountMgr.h"> | |
@@ -916,5 +919,8 @@ | |
<ClInclude Include="..\..\src\game\vmap\WorldModel.h"> | |
<Filter>vmaps</Filter> | |
</ClInclude> | |
+ <ClInclude Include="..\..\src\game\ChargeMovementGenerator.h"> | |
+ <Filter>Motion generators</Filter> | |
+ </ClInclude> | |
</ItemGroup> | |
</Project> | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment