2 * Copyright (C) 2005-2009 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
20 #include "MapManager.h"
21 #include "FleeingMovementGenerator.h"
22 #include "DestinationHolderImp.h"
23 #include "ObjectAccessor.h"
25 #define MIN_QUIET_DISTANCE 28.0f
26 #define MAX_QUIET_DISTANCE 43.0f
30 FleeingMovementGenerator
<T
>::_setTargetLocation(T
&owner
)
35 if( owner
.hasUnitState(UNIT_STAT_ROOT
| UNIT_STAT_STUNNED
) )
38 if(!_setMoveData(owner
))
42 if(!_getPoint(owner
, x
, y
, z
))
45 owner
.addUnitState(UNIT_STAT_FLEEING
);
46 Traveller
<T
> traveller(owner
);
47 i_destinationHolder
.SetDestination(traveller
, x
, y
, z
);
52 FleeingMovementGenerator
<T
>::_getPoint(T
&owner
, float &x
, float &y
, float &z
)
57 x
= owner
.GetPositionX();
58 y
= owner
.GetPositionY();
59 z
= owner
.GetPositionZ();
61 float temp_x
, temp_y
, angle
;
62 const Map
* _map
= MapManager::Instance().GetBaseMap(owner
.GetMapId());
63 //primitive path-finding
64 for(uint8 i
= 0; i
< 18; i
++)
66 if(i_only_forward
&& i
> 2)
69 float distance
= 5.0f
;
85 angle
= i_cur_angle
+ M_PI
/4.0f
;
88 angle
= i_cur_angle
- M_PI
/4.0f
;
91 angle
= i_cur_angle
+ M_PI
/4.0f
;
95 angle
= i_cur_angle
- M_PI
/4.0f
;
99 angle
= i_cur_angle
+ M_PI
/2.0f
;
102 angle
= i_cur_angle
- M_PI
/2.0f
;
105 angle
= i_cur_angle
+ M_PI
/2.0f
;
109 angle
= i_cur_angle
- M_PI
/2.0f
;
113 angle
= i_cur_angle
+ M_PI
/4.0f
;
117 angle
= i_cur_angle
- M_PI
/4.0f
;
121 angle
= i_cur_angle
+ M_PI
/2.0f
;
125 angle
= i_cur_angle
- M_PI
/2.0f
;
129 angle
= i_cur_angle
+ M_PI
*3/4.0f
;
133 angle
= i_cur_angle
- M_PI
*3/4.0f
;
137 angle
= i_cur_angle
+ M_PI
;
141 temp_x
= x
+ distance
* cos(angle
);
142 temp_y
= y
+ distance
* sin(angle
);
143 MaNGOS::NormalizeMapCoord(temp_x
);
144 MaNGOS::NormalizeMapCoord(temp_y
);
145 if( owner
.IsWithinLOS(temp_x
,temp_y
,z
))
147 bool is_water_now
= _map
->IsInWater(x
,y
,z
);
149 if(is_water_now
&& _map
->IsInWater(temp_x
,temp_y
,z
))
155 float new_z
= _map
->GetHeight(temp_x
,temp_y
,z
,true);
157 if(new_z
<= INVALID_HEIGHT
)
160 bool is_water_next
= _map
->IsInWater(temp_x
,temp_y
,new_z
);
162 if((is_water_now
&& !is_water_next
&& !is_land_ok
) || (!is_water_now
&& is_water_next
&& !is_water_ok
))
165 if( !(new_z
- z
) || distance
/ fabs(new_z
- z
) > 1.0f
)
167 float new_z_left
= _map
->GetHeight(temp_x
+ 1.0f
*cos(angle
+M_PI
/2),temp_y
+ 1.0f
*sin(angle
+M_PI
/2),z
,true);
168 float new_z_right
= _map
->GetHeight(temp_x
+ 1.0f
*cos(angle
-M_PI
/2),temp_y
+ 1.0f
*sin(angle
-M_PI
/2),z
,true);
169 if(fabs(new_z_left
- new_z
) < 1.2f
&& fabs(new_z_right
- new_z
) < 1.2f
)
179 i_to_distance_from_caster
= 0.0f
;
180 i_nextCheckTime
.Reset( urand(500,1000) );
186 FleeingMovementGenerator
<T
>::_setMoveData(T
&owner
)
188 float cur_dist_xyz
= owner
.GetDistance(i_caster_x
, i_caster_y
, i_caster_z
);
190 if(i_to_distance_from_caster
> 0.0f
)
192 if((i_last_distance_from_caster
> i_to_distance_from_caster
&& cur_dist_xyz
< i_to_distance_from_caster
) ||
193 // if we reach lower distance
194 (i_last_distance_from_caster
> i_to_distance_from_caster
&& cur_dist_xyz
> i_last_distance_from_caster
) ||
195 // if we can't be close
196 (i_last_distance_from_caster
< i_to_distance_from_caster
&& cur_dist_xyz
> i_to_distance_from_caster
) ||
197 // if we reach bigger distance
198 (cur_dist_xyz
> MAX_QUIET_DISTANCE
) || // if we are too far
199 (i_last_distance_from_caster
> MIN_QUIET_DISTANCE
&& cur_dist_xyz
< MIN_QUIET_DISTANCE
) )
200 // if we leave 'quiet zone'
202 // we are very far or too close, stopping
203 i_to_distance_from_caster
= 0.0f
;
204 i_nextCheckTime
.Reset( urand(500,1000) );
209 // now we are running, continue
210 i_last_distance_from_caster
= cur_dist_xyz
;
216 float angle_to_caster
;
218 Unit
* fright
= ObjectAccessor::GetUnit(owner
, i_frightGUID
);
222 cur_dist
= fright
->GetDistance(&owner
);
223 if(cur_dist
< cur_dist_xyz
)
225 i_caster_x
= fright
->GetPositionX();
226 i_caster_y
= fright
->GetPositionY();
227 i_caster_z
= fright
->GetPositionZ();
228 angle_to_caster
= fright
->GetAngle(&owner
);
232 cur_dist
= cur_dist_xyz
;
233 angle_to_caster
= owner
.GetAngle(i_caster_x
, i_caster_y
) + M_PI
;
238 cur_dist
= cur_dist_xyz
;
239 angle_to_caster
= owner
.GetAngle(i_caster_x
, i_caster_y
) + M_PI
;
242 // if we too close may use 'path-finding' else just stop
243 i_only_forward
= cur_dist
>= MIN_QUIET_DISTANCE
/3;
245 //get angle and 'distance from caster' to run
248 if(i_cur_angle
== 0.0f
&& i_last_distance_from_caster
== 0.0f
) //just started, first time
250 angle
= rand_norm()*(1.0f
- cur_dist
/MIN_QUIET_DISTANCE
) * M_PI
/3 + rand_norm()*M_PI
*2/3;
251 i_to_distance_from_caster
= MIN_QUIET_DISTANCE
;
252 i_only_forward
= true;
254 else if(cur_dist
< MIN_QUIET_DISTANCE
)
256 angle
= M_PI
/6 + rand_norm()*M_PI
*2/3;
257 i_to_distance_from_caster
= cur_dist
*2/3 + rand_norm()*(MIN_QUIET_DISTANCE
- cur_dist
*2/3);
259 else if(cur_dist
> MAX_QUIET_DISTANCE
)
261 angle
= rand_norm()*M_PI
/3 + M_PI
*2/3;
262 i_to_distance_from_caster
= MIN_QUIET_DISTANCE
+ 2.5f
+ rand_norm()*(MAX_QUIET_DISTANCE
- MIN_QUIET_DISTANCE
- 2.5f
);
266 angle
= rand_norm()*M_PI
;
267 i_to_distance_from_caster
= MIN_QUIET_DISTANCE
+ 2.5f
+ rand_norm()*(MAX_QUIET_DISTANCE
- MIN_QUIET_DISTANCE
- 2.5f
);
270 int8 sign
= rand_norm() > 0.5f
? 1 : -1;
271 i_cur_angle
= sign
*angle
+ angle_to_caster
;
274 i_last_distance_from_caster
= cur_dist
;
281 FleeingMovementGenerator
<T
>::Initialize(T
&owner
)
287 owner
.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE
);
289 if(Unit
* fright
= ObjectAccessor::GetUnit(owner
, i_frightGUID
))
291 i_caster_x
= fright
->GetPositionX();
292 i_caster_y
= fright
->GetPositionY();
293 i_caster_z
= fright
->GetPositionZ();
297 i_caster_x
= owner
.GetPositionX();
298 i_caster_y
= owner
.GetPositionY();
299 i_caster_z
= owner
.GetPositionZ();
302 i_only_forward
= true;
304 i_last_distance_from_caster
= 0.0f
;
305 i_to_distance_from_caster
= 0.0f
;
306 _setTargetLocation(owner
);
311 FleeingMovementGenerator
<Creature
>::_Init(Creature
&owner
)
315 owner
.SetUInt64Value(UNIT_FIELD_TARGET
, 0);
316 is_water_ok
= owner
.canSwim();
317 is_land_ok
= owner
.canWalk();
322 FleeingMovementGenerator
<Player
>::_Init(Player
&)
330 FleeingMovementGenerator
<T
>::Finalize(T
&owner
)
332 owner
.clearUnitState(UNIT_STAT_FLEEING
);
337 FleeingMovementGenerator
<T
>::Reset(T
&owner
)
344 FleeingMovementGenerator
<T
>::Update(T
&owner
, const uint32
& time_diff
)
346 if( !&owner
|| !owner
.isAlive() )
348 if( owner
.hasUnitState(UNIT_STAT_ROOT
| UNIT_STAT_STUNNED
) )
351 Traveller
<T
> traveller(owner
);
353 i_nextCheckTime
.Update(time_diff
);
355 if( (owner
.IsStopped() && !i_destinationHolder
.HasArrived()) || !i_destinationHolder
.HasDestination() )
357 _setTargetLocation(owner
);
361 if (i_destinationHolder
.UpdateTraveller(traveller
, time_diff
, false))
363 i_destinationHolder
.ResetUpdate(50);
364 if(i_nextCheckTime
.Passed() && i_destinationHolder
.HasArrived())
366 _setTargetLocation(owner
);
373 template void FleeingMovementGenerator
<Player
>::Initialize(Player
&);
374 template void FleeingMovementGenerator
<Creature
>::Initialize(Creature
&);
375 template bool FleeingMovementGenerator
<Player
>::_setMoveData(Player
&);
376 template bool FleeingMovementGenerator
<Creature
>::_setMoveData(Creature
&);
377 template bool FleeingMovementGenerator
<Player
>::_getPoint(Player
&, float &, float &, float &);
378 template bool FleeingMovementGenerator
<Creature
>::_getPoint(Creature
&, float &, float &, float &);
379 template void FleeingMovementGenerator
<Player
>::_setTargetLocation(Player
&);
380 template void FleeingMovementGenerator
<Creature
>::_setTargetLocation(Creature
&);
381 template void FleeingMovementGenerator
<Player
>::Finalize(Player
&);
382 template void FleeingMovementGenerator
<Creature
>::Finalize(Creature
&);
383 template void FleeingMovementGenerator
<Player
>::Reset(Player
&);
384 template void FleeingMovementGenerator
<Creature
>::Reset(Creature
&);
385 template bool FleeingMovementGenerator
<Player
>::Update(Player
&, const uint32
&);
386 template bool FleeingMovementGenerator
<Creature
>::Update(Creature
&, const uint32
&);