[9529] Make Player::IsValidPos const
[getmangos.git] / src / game / TargetedMovementGenerator.cpp
blobb59e6c8f188b8ba25e5450a95904edf7d8939aed
1 /*
2 * Copyright (C) 2005-2010 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 "DestinationHolderImp.h"
24 #include "World.h"
26 #define SMALL_ALPHA 0.05f
28 #include <cmath>
30 //-----------------------------------------------//
31 template<class T, typename D>
32 void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
34 if (!i_target.isValid() || !i_target->IsInWorld())
35 return;
37 if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
38 return;
40 // prevent redundant micro-movement for pets, other followers.
41 if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
42 return;
44 float x, y, z;
45 if (!i_offset)
47 // to nearest contact position
48 i_target->GetContactPoint( &owner, x, y, z );
50 else
52 // to at i_offset distance from target and i_angle from target facing
53 i_target->GetClosePoint(x,y,z,owner.GetObjectSize(),i_offset,i_angle);
57 We MUST not check the distance difference and avoid setting the new location for smaller distances.
58 By that we risk having far too many GetContactPoint() calls freezing the whole system.
59 In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
60 some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
61 If the distance to the target it too large to ignore,
62 but the distance to the new contact point is short enough to be ignored,
63 we will calculate a new contact point each update loop, but will never move to it.
64 The system will freeze.
65 ralf
67 //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
68 float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
69 if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
70 return;
72 Traveller<T> traveller(owner);
73 i_destinationHolder.SetDestination(traveller, x, y, z);
75 D::_addUnitStateMove(owner);
76 if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
77 ((Creature&)owner).AddSplineFlag(SPLINEFLAG_UNKNOWN7);
80 template<>
81 void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::UpdateFinalDistance(float /*fDistance*/)
83 // nothing to do for Player
86 template<>
87 void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::UpdateFinalDistance(float /*fDistance*/)
89 // nothing to do for Player
92 template<>
93 void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::UpdateFinalDistance(float fDistance)
95 i_offset = fDistance;
96 i_recalculateTravel = true;
99 template<>
100 void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::UpdateFinalDistance(float fDistance)
102 i_offset = fDistance;
103 i_recalculateTravel = true;
106 template<class T, typename D>
107 bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_diff)
109 if (!i_target.isValid() || !i_target->IsInWorld())
110 return false;
112 if (!owner.isAlive())
113 return true;
115 if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
117 D::_clearUnitStateMove(owner);
118 return true;
121 // prevent movement while casting spells with cast time or channel time
122 if (owner.IsNonMeleeSpellCasted(false, false, true))
124 if (!owner.IsStopped())
125 owner.StopMoving();
126 return true;
129 // prevent crash after creature killed pet
130 if (static_cast<D*>(this)->_lostTarget(owner))
132 D::_clearUnitStateMove(owner);
133 return true;
136 Traveller<T> traveller(owner);
138 if (!i_destinationHolder.HasDestination())
139 _setTargetLocation(owner);
140 if (owner.IsStopped() && !i_destinationHolder.HasArrived())
142 D::_addUnitStateMove(owner);
143 if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
144 ((Creature&)owner).AddSplineFlag(SPLINEFLAG_UNKNOWN7);
146 i_destinationHolder.StartTravel(traveller);
147 return true;
150 if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
152 if (!IsActive(owner)) // force stop processing (movement can move out active zone with cleanup movegens list)
153 return true; // not expire now, but already lost
155 // put targeted movement generators on a higher priority
156 if (owner.GetObjectSize())
157 i_destinationHolder.ResetUpdate(50);
159 float dist = i_target->GetObjectSize() + owner.GetObjectSize() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
161 //More distance let have better performance, less distance let have more sensitive reaction at target move.
163 // try to counter precision differences
164 if (i_destinationHolder.GetDistance3dFromDestSq(*i_target.getTarget()) >= dist * dist)
166 owner.SetInFront(i_target.getTarget()); // Set new Angle For Map::
167 _setTargetLocation(owner); //Calculate New Dest and Send data To Player
169 // Update the Angle of the target only for Map::, no need to send packet for player
170 else if (!i_angle && !owner.HasInArc(0.01f, i_target.getTarget()))
171 owner.SetInFront(i_target.getTarget());
173 if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
175 i_recalculateTravel = false;
176 //Angle update will take place into owner.StopMoving()
177 owner.SetInFront(i_target.getTarget());
179 owner.StopMoving();
180 static_cast<D*>(this)->_reachTarget(owner);
183 return true;
186 //-----------------------------------------------//
187 template<class T>
188 void ChaseMovementGenerator<T>::_reachTarget(T &owner)
190 if(owner.canReachWithAttack(this->i_target.getTarget()))
191 owner.Attack(this->i_target.getTarget(),true);
194 template<>
195 void ChaseMovementGenerator<Player>::Initialize(Player &owner)
197 owner.addUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
198 _setTargetLocation(owner);
201 template<>
202 void ChaseMovementGenerator<Creature>::Initialize(Creature &owner)
204 owner.addUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
205 owner.RemoveSplineFlag(SPLINEFLAG_WALKMODE);
207 if (((Creature*)&owner)->canFly())
208 owner.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
210 _setTargetLocation(owner);
213 template<class T>
214 void ChaseMovementGenerator<T>::Finalize(T &owner)
216 owner.clearUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
219 template<class T>
220 void ChaseMovementGenerator<T>::Interrupt(T &owner)
222 owner.clearUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE);
225 template<class T>
226 void ChaseMovementGenerator<T>::Reset(T &owner)
228 Initialize(owner);
231 //-----------------------------------------------//
232 template<>
233 void FollowMovementGenerator<Creature>::_updateWalkMode(Creature &u)
235 if (i_target.isValid() && u.isPet())
236 u.UpdateWalkMode(i_target.getTarget());
239 template<>
240 void FollowMovementGenerator<Player>::_updateWalkMode(Player &)
244 template<>
245 void FollowMovementGenerator<Player>::_updateSpeed(Player &/*u*/)
247 // nothing to do for Player
250 template<>
251 void FollowMovementGenerator<Creature>::_updateSpeed(Creature &u)
253 // pet only sync speed with owner
254 if (!((Creature&)u).isPet() || !i_target.isValid() || i_target->GetGUID() != u.GetOwnerGUID())
255 return;
257 u.UpdateSpeed(MOVE_RUN,true);
258 u.UpdateSpeed(MOVE_WALK,true);
259 u.UpdateSpeed(MOVE_SWIM,true);
262 template<>
263 void FollowMovementGenerator<Player>::Initialize(Player &owner)
265 owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
266 _updateWalkMode(owner);
267 _updateSpeed(owner);
268 _setTargetLocation(owner);
271 template<>
272 void FollowMovementGenerator<Creature>::Initialize(Creature &owner)
274 owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
275 _updateWalkMode(owner);
276 _updateSpeed(owner);
278 if (((Creature*)&owner)->canFly())
279 owner.AddSplineFlag(SPLINEFLAG_UNKNOWN7);
281 _setTargetLocation(owner);
284 template<class T>
285 void FollowMovementGenerator<T>::Finalize(T &owner)
287 owner.clearUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
288 _updateWalkMode(owner);
289 _updateSpeed(owner);
292 template<class T>
293 void FollowMovementGenerator<T>::Interrupt(T &owner)
295 owner.clearUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE);
296 _updateWalkMode(owner);
297 _updateSpeed(owner);
300 template<class T>
301 void FollowMovementGenerator<T>::Reset(T &owner)
303 Initialize(owner);
306 //-----------------------------------------------//
307 template void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::_setTargetLocation(Player &);
308 template void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::_setTargetLocation(Player &);
309 template void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature &);
310 template void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::_setTargetLocation(Creature &);
311 template bool TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::Update(Player &, const uint32 &);
312 template bool TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::Update(Player &, const uint32 &);
313 template bool TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::Update(Creature &, const uint32 &);
314 template bool TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::Update(Creature &, const uint32 &);
316 template void ChaseMovementGenerator<Player>::_reachTarget(Player &);
317 template void ChaseMovementGenerator<Creature>::_reachTarget(Creature &);
318 template void ChaseMovementGenerator<Player>::Finalize(Player &);
319 template void ChaseMovementGenerator<Creature>::Finalize(Creature &);
320 template void ChaseMovementGenerator<Player>::Interrupt(Player &);
321 template void ChaseMovementGenerator<Creature>::Interrupt(Creature &);
322 template void ChaseMovementGenerator<Player>::Reset(Player &);
323 template void ChaseMovementGenerator<Creature>::Reset(Creature &);
325 template void FollowMovementGenerator<Player>::Finalize(Player &);
326 template void FollowMovementGenerator<Creature>::Finalize(Creature &);
327 template void FollowMovementGenerator<Player>::Interrupt(Player &);
328 template void FollowMovementGenerator<Creature>::Interrupt(Creature &);
329 template void FollowMovementGenerator<Player>::Reset(Player &);
330 template void FollowMovementGenerator<Creature>::Reset(Creature &);