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"
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())
35 if (owner
.hasUnitState(UNIT_STAT_NOT_MOVE
))
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())
50 owner
.GetPosition(x
, y
, z
);
54 // to nearest contact position
55 i_target
->GetContactPoint(&owner
, x
, y
, z
);
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
);
65 // the destination has not changed, we just need to refresh the path (usually speed change)
66 G3D::Vector3 end
= i_path
->getEndPosition();
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
)
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());
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())
101 if (owner
.hasUnitState(UNIT_STAT_NOT_MOVE
))
103 D::_clearUnitStateMove(owner
);
107 // prevent movement while casting spells with cast time or channel time
108 if (owner
.IsNonMeleeSpellCasted(false, false, true))
110 if (!owner
.IsStopped())
115 // prevent crash after creature killed pet
116 if (static_cast<D
*>(this)->_lostTarget(owner
))
118 D::_clearUnitStateMove(owner
);
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
);
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
);
155 //-----------------------------------------------//
157 void ChaseMovementGenerator
<T
>::_reachTarget(T
& owner
)
159 if (owner
.CanReachWithMeleeAttack(this->i_target
.getTarget()))
160 owner
.Attack(this->i_target
.getTarget(), true);
164 void ChaseMovementGenerator
<Player
>::Initialize(Player
& owner
)
166 owner
.addUnitState(UNIT_STAT_CHASE
| UNIT_STAT_CHASE_MOVE
);
167 _setTargetLocation(owner
, true);
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);
179 void ChaseMovementGenerator
<T
>::Finalize(T
& owner
)
181 owner
.clearUnitState(UNIT_STAT_CHASE
| UNIT_STAT_CHASE_MOVE
);
185 void ChaseMovementGenerator
<T
>::Interrupt(T
& owner
)
187 owner
.clearUnitState(UNIT_STAT_CHASE
| UNIT_STAT_CHASE_MOVE
);
191 void ChaseMovementGenerator
<T
>::Reset(T
& owner
)
196 //-----------------------------------------------//
198 bool FollowMovementGenerator
<Creature
>::EnableWalking() const
200 return i_target
.isValid() && i_target
->IsWalking();
204 bool FollowMovementGenerator
<Player
>::EnableWalking() const
210 void FollowMovementGenerator
<Player
>::_updateSpeed(Player
& /*u*/)
212 // nothing to do for Player
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())
222 u
.UpdateSpeed(MOVE_RUN
, true);
223 u
.UpdateSpeed(MOVE_WALK
, true);
224 u
.UpdateSpeed(MOVE_SWIM
, true);
228 void FollowMovementGenerator
<Player
>::Initialize(Player
& owner
)
230 owner
.addUnitState(UNIT_STAT_FOLLOW
| UNIT_STAT_FOLLOW_MOVE
);
232 _setTargetLocation(owner
, true);
236 void FollowMovementGenerator
<Creature
>::Initialize(Creature
& owner
)
238 owner
.addUnitState(UNIT_STAT_FOLLOW
| UNIT_STAT_FOLLOW_MOVE
);
240 _setTargetLocation(owner
, true);
244 void FollowMovementGenerator
<T
>::Finalize(T
& owner
)
246 owner
.clearUnitState(UNIT_STAT_FOLLOW
| UNIT_STAT_FOLLOW_MOVE
);
251 void FollowMovementGenerator
<T
>::Interrupt(T
& owner
)
253 owner
.clearUnitState(UNIT_STAT_FOLLOW
| UNIT_STAT_FOLLOW_MOVE
);
258 void FollowMovementGenerator
<T
>::Reset(T
& 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
&);