Updated Copyright year to 2013
[getmangos.git] / src / game / TargetedMovementGenerator.cpp
blob610e50727356b0e7af8da150f608574f4a3a0f96
1 /*
2 * Copyright (C) 2005-2013 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "ByteBuffer.h"
20 #include "TargetedMovementGenerator.h"
21 #include "Errors.h"
22 #include "Creature.h"
23 #include "Player.h"
24 #include "World.h"
25 #include "movement/MoveSplineInit.h"
26 #include "movement/MoveSpline.h"
28 //-----------------------------------------------//
29 template<class T, typename D>
30 void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T& owner, bool updateDestination)
32 if (!i_target.isValid() || !i_target->IsInWorld())
33 return;
35 if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
36 return;
38 float x, y, z;
40 // i_path can be NULL in case this is the first call for this MMGen (via Update)
41 // Can happen for example if no path was created on MMGen-Initialize because of the owner being stunned
42 if (updateDestination || !i_path)
44 // prevent redundant micro-movement for pets, other followers.
45 if (i_offset && i_target->IsWithinDistInMap(&owner, 2 * i_offset))
47 if (!owner.movespline->Finalized())
48 return;
50 owner.GetPosition(x, y, z);
52 else if (!i_offset)
54 // to nearest contact position
55 i_target->GetContactPoint(&owner, x, y, z);
57 else
59 // to at i_offset distance from target and i_angle from target facing
60 i_target->GetClosePoint(x, y, z, owner.GetObjectBoundingRadius(), i_offset, i_angle, &owner);
63 else
65 // the destination has not changed, we just need to refresh the path (usually speed change)
66 G3D::Vector3 end = i_path->getEndPosition();
67 x = end.x;
68 y = end.y;
69 z = end.z;
72 if (!i_path)
73 i_path = new PathFinder(&owner);
75 // allow pets following their master to cheat while generating paths
76 bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->IsPet()
77 && owner.hasUnitState(UNIT_STAT_FOLLOW));
78 i_path->calculate(x, y, z, forceDest);
79 if (i_path->getPathType() & PATHFIND_NOPATH)
80 return;
82 D::_addUnitStateMove(owner);
83 i_targetReached = false;
84 m_speedChanged = false;
86 Movement::MoveSplineInit init(owner);
87 init.MovebyPath(i_path->getPath());
88 init.SetWalk(((D*)this)->EnableWalking());
89 init.Launch();
92 template<class T, typename D>
93 bool TargetedMovementGeneratorMedium<T, D>::Update(T& owner, const uint32& time_diff)
95 if (!i_target.isValid() || !i_target->IsInWorld())
96 return false;
98 if (!owner.isAlive())
99 return true;
101 if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
103 D::_clearUnitStateMove(owner);
104 return true;
107 // prevent movement while casting spells with cast time or channel time
108 if (owner.IsNonMeleeSpellCasted(false, false, true))
110 if (!owner.IsStopped())
111 owner.StopMoving();
112 return true;
115 // prevent crash after creature killed pet
116 if (static_cast<D*>(this)->_lostTarget(owner))
118 D::_clearUnitStateMove(owner);
119 return true;
122 bool targetMoved = false;
123 i_recheckDistance.Update(time_diff);
124 if (i_recheckDistance.Passed())
126 i_recheckDistance.Reset(100);
128 // More distance let have better performance, less distance let have more sensitive reaction at target move.
129 float allowed_dist = owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
130 G3D::Vector3 dest = owner.movespline->FinalDestination();
132 if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly())
133 targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
134 else
135 targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);
138 if (m_speedChanged || targetMoved)
139 _setTargetLocation(owner, targetMoved);
141 if (owner.movespline->Finalized())
143 if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget()))
144 owner.SetInFront(i_target.getTarget());
146 if (!i_targetReached)
148 i_targetReached = true;
149 static_cast<D*>(this)->_reachTarget(owner);
152 return true;
155 //-----------------------------------------------//
156 template<class T>
157 void ChaseMovementGenerator<T>::_reachTarget(T& owner)
159 if (owner.CanReachWithMeleeAttack(this->i_target.getTarget()))
160 owner.Attack(this->i_target.getTarget(), true);
163 template<>
164 void ChaseMovementGenerator<Player>::Initialize(Player& owner)
166 owner.addUnitState(UNIT_STAT_CHASE | UNIT_STAT_CHASE_MOVE);
167 _setTargetLocation(owner, true);
170 template<>
171 void ChaseMovementGenerator<Creature>::Initialize(Creature& owner)
173 owner.SetWalk(false, false); // Chase movement is running
174 owner.addUnitState(UNIT_STAT_CHASE | UNIT_STAT_CHASE_MOVE);
175 _setTargetLocation(owner, true);
178 template<class T>
179 void ChaseMovementGenerator<T>::Finalize(T& owner)
181 owner.clearUnitState(UNIT_STAT_CHASE | UNIT_STAT_CHASE_MOVE);
184 template<class T>
185 void ChaseMovementGenerator<T>::Interrupt(T& owner)
187 owner.clearUnitState(UNIT_STAT_CHASE | UNIT_STAT_CHASE_MOVE);
190 template<class T>
191 void ChaseMovementGenerator<T>::Reset(T& owner)
193 Initialize(owner);
196 //-----------------------------------------------//
197 template<>
198 bool FollowMovementGenerator<Creature>::EnableWalking() const
200 return i_target.isValid() && i_target->IsWalking();
203 template<>
204 bool FollowMovementGenerator<Player>::EnableWalking() const
206 return false;
209 template<>
210 void FollowMovementGenerator<Player>::_updateSpeed(Player& /*u*/)
212 // nothing to do for Player
215 template<>
216 void FollowMovementGenerator<Creature>::_updateSpeed(Creature& u)
218 // pet only sync speed with owner
219 if (!((Creature&)u).IsPet() || !i_target.isValid() || i_target->GetObjectGuid() != u.GetOwnerGuid())
220 return;
222 u.UpdateSpeed(MOVE_RUN, true);
223 u.UpdateSpeed(MOVE_WALK, true);
224 u.UpdateSpeed(MOVE_SWIM, true);
227 template<>
228 void FollowMovementGenerator<Player>::Initialize(Player& owner)
230 owner.addUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE);
231 _updateSpeed(owner);
232 _setTargetLocation(owner, true);
235 template<>
236 void FollowMovementGenerator<Creature>::Initialize(Creature& owner)
238 owner.addUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE);
239 _updateSpeed(owner);
240 _setTargetLocation(owner, true);
243 template<class T>
244 void FollowMovementGenerator<T>::Finalize(T& owner)
246 owner.clearUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE);
247 _updateSpeed(owner);
250 template<class T>
251 void FollowMovementGenerator<T>::Interrupt(T& owner)
253 owner.clearUnitState(UNIT_STAT_FOLLOW | UNIT_STAT_FOLLOW_MOVE);
254 _updateSpeed(owner);
257 template<class T>
258 void FollowMovementGenerator<T>::Reset(T& owner)
260 Initialize(owner);
263 //-----------------------------------------------//
264 template void TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::_setTargetLocation(Player&, bool);
265 template void TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::_setTargetLocation(Player&, bool);
266 template void TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature&, bool);
267 template void TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::_setTargetLocation(Creature&, bool);
268 template bool TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::Update(Player&, const uint32&);
269 template bool TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::Update(Player&, const uint32&);
270 template bool TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::Update(Creature&, const uint32&);
271 template bool TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::Update(Creature&, const uint32&);
273 template void ChaseMovementGenerator<Player>::_reachTarget(Player&);
274 template void ChaseMovementGenerator<Creature>::_reachTarget(Creature&);
275 template void ChaseMovementGenerator<Player>::Finalize(Player&);
276 template void ChaseMovementGenerator<Creature>::Finalize(Creature&);
277 template void ChaseMovementGenerator<Player>::Interrupt(Player&);
278 template void ChaseMovementGenerator<Creature>::Interrupt(Creature&);
279 template void ChaseMovementGenerator<Player>::Reset(Player&);
280 template void ChaseMovementGenerator<Creature>::Reset(Creature&);
282 template void FollowMovementGenerator<Player>::Finalize(Player&);
283 template void FollowMovementGenerator<Creature>::Finalize(Creature&);
284 template void FollowMovementGenerator<Player>::Interrupt(Player&);
285 template void FollowMovementGenerator<Creature>::Interrupt(Creature&);
286 template void FollowMovementGenerator<Player>::Reset(Player&);
287 template void FollowMovementGenerator<Creature>::Reset(Creature&);