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"
23 #include "DestinationHolderImp.h"
26 #define SMALL_ALPHA 0.05f
30 //-----------------------------------------------//
31 template<class T
, typename D
>
32 void TargetedMovementGeneratorMedium
<T
,D
>::_setTargetLocation(T
&owner
)
34 if (!i_target
.isValid() || !i_target
->IsInWorld())
37 if (owner
.hasUnitState(UNIT_STAT_NOT_MOVE
))
40 // prevent redundant micro-movement for pets, other followers.
41 if (i_offset
&& i_target
->IsWithinDistInMap(&owner
,2*i_offset
))
47 // to nearest contact position
48 i_target
->GetContactPoint( &owner
, x
, y
, z
);
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.
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 )
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
);
81 void TargetedMovementGeneratorMedium
<Player
,ChaseMovementGenerator
<Player
> >::UpdateFinalDistance(float /*fDistance*/)
83 // nothing to do for Player
87 void TargetedMovementGeneratorMedium
<Player
,FollowMovementGenerator
<Player
> >::UpdateFinalDistance(float /*fDistance*/)
89 // nothing to do for Player
93 void TargetedMovementGeneratorMedium
<Creature
,ChaseMovementGenerator
<Creature
> >::UpdateFinalDistance(float fDistance
)
96 i_recalculateTravel
= true;
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())
112 if (!owner
.isAlive())
115 if (owner
.hasUnitState(UNIT_STAT_NOT_MOVE
))
117 D::_clearUnitStateMove(owner
);
121 // prevent movement while casting spells with cast time or channel time
122 if (owner
.IsNonMeleeSpellCasted(false, false, true))
124 if (!owner
.IsStopped())
129 // prevent crash after creature killed pet
130 if (static_cast<D
*>(this)->_lostTarget(owner
))
132 D::_clearUnitStateMove(owner
);
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
);
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());
180 static_cast<D
*>(this)->_reachTarget(owner
);
186 //-----------------------------------------------//
188 void ChaseMovementGenerator
<T
>::_reachTarget(T
&owner
)
190 if(owner
.canReachWithAttack(this->i_target
.getTarget()))
191 owner
.Attack(this->i_target
.getTarget(),true);
195 void ChaseMovementGenerator
<Player
>::Initialize(Player
&owner
)
197 owner
.addUnitState(UNIT_STAT_CHASE
|UNIT_STAT_CHASE_MOVE
);
198 _setTargetLocation(owner
);
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
);
214 void ChaseMovementGenerator
<T
>::Finalize(T
&owner
)
216 owner
.clearUnitState(UNIT_STAT_CHASE
|UNIT_STAT_CHASE_MOVE
);
220 void ChaseMovementGenerator
<T
>::Interrupt(T
&owner
)
222 owner
.clearUnitState(UNIT_STAT_CHASE
|UNIT_STAT_CHASE_MOVE
);
226 void ChaseMovementGenerator
<T
>::Reset(T
&owner
)
231 //-----------------------------------------------//
233 void FollowMovementGenerator
<Creature
>::_updateWalkMode(Creature
&u
)
235 if (i_target
.isValid() && u
.isPet())
236 u
.UpdateWalkMode(i_target
.getTarget());
240 void FollowMovementGenerator
<Player
>::_updateWalkMode(Player
&)
245 void FollowMovementGenerator
<Player
>::_updateSpeed(Player
&/*u*/)
247 // nothing to do for Player
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())
257 u
.UpdateSpeed(MOVE_RUN
,true);
258 u
.UpdateSpeed(MOVE_WALK
,true);
259 u
.UpdateSpeed(MOVE_SWIM
,true);
263 void FollowMovementGenerator
<Player
>::Initialize(Player
&owner
)
265 owner
.addUnitState(UNIT_STAT_FOLLOW
|UNIT_STAT_FOLLOW_MOVE
);
266 _updateWalkMode(owner
);
268 _setTargetLocation(owner
);
272 void FollowMovementGenerator
<Creature
>::Initialize(Creature
&owner
)
274 owner
.addUnitState(UNIT_STAT_FOLLOW
|UNIT_STAT_FOLLOW_MOVE
);
275 _updateWalkMode(owner
);
278 if (((Creature
*)&owner
)->canFly())
279 owner
.AddSplineFlag(SPLINEFLAG_UNKNOWN7
);
281 _setTargetLocation(owner
);
285 void FollowMovementGenerator
<T
>::Finalize(T
&owner
)
287 owner
.clearUnitState(UNIT_STAT_FOLLOW
|UNIT_STAT_FOLLOW_MOVE
);
288 _updateWalkMode(owner
);
293 void FollowMovementGenerator
<T
>::Interrupt(T
&owner
)
295 owner
.clearUnitState(UNIT_STAT_FOLLOW
|UNIT_STAT_FOLLOW_MOVE
);
296 _updateWalkMode(owner
);
301 void FollowMovementGenerator
<T
>::Reset(T
&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
&);