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
20 #include "MapManager.h"
21 #include "RandomMovementGenerator.h"
22 #include "DestinationHolderImp.h"
28 RandomMovementGenerator
<Creature
>::_setRandomLocation(Creature
&creature
)
30 float X
,Y
,Z
,z
,nx
,ny
,nz
,wander_distance
,ori
,dist
;
32 creature
.GetRespawnCoord(X
, Y
, Z
, &ori
, &wander_distance
);
34 z
= creature
.GetPositionZ();
35 Map
const* map
= creature
.GetBaseMap();
37 // For 2D/3D system selection
38 //bool is_land_ok = creature.canWalk(); // not used?
39 //bool is_water_ok = creature.canSwim(); // not used?
40 bool is_air_ok
= creature
.canFly();
42 const float angle
= rand_norm()*(M_PI
*2);
43 const float range
= rand_norm()*wander_distance
;
44 const float distanceX
= range
* cos(angle
);
45 const float distanceY
= range
* sin(angle
);
50 // prevent invalid coordinates generation
51 MaNGOS::NormalizeMapCoord(nx
);
52 MaNGOS::NormalizeMapCoord(ny
);
54 dist
= distanceX
*distanceX
+ distanceY
*distanceY
;
56 if (is_air_ok
) // 3D system above ground and above water (flying mode)
58 const float distanceZ
= rand_norm() * sqrtf(dist
)/2;// Limit height change
60 float tz
= map
->GetHeight(nx
, ny
, nz
-2.0f
, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
61 float wz
= map
->GetWaterLevel(nx
, ny
);
63 // Problem here, we must fly above the ground and water, not under. Let's try on next tick
64 if (tz
>= nz
|| wz
>= nz
)
67 //else if (is_water_ok) // 3D system under water and above ground (swimming mode)
70 dist
= dist
>= 100.0f
? 10.0f
: sqrtf(dist
); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
72 // The fastest way to get an accurate result 90% of the time.
73 // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
74 nz
= map
->GetHeight(nx
, ny
, Z
+dist
-2.0f
, false);
76 if (fabs(nz
-Z
) > dist
) // Map check
78 nz
= map
->GetHeight(nx
, ny
, Z
-2.0f
, true); // Vmap Horizontal or above
80 if (fabs(nz
-Z
) > dist
)
83 nz
= map
->GetHeight(nx
, ny
, Z
+dist
-2.0f
, true);
85 // let's forget this bad coords where a z cannot be find and retry at next tick
86 if (fabs(nz
-Z
) > dist
)
92 Traveller
<Creature
> traveller(creature
);
94 creature
.SetOrientation(creature
.GetAngle(nx
, ny
));
95 i_destinationHolder
.SetDestination(traveller
, nx
, ny
, nz
);
96 creature
.addUnitState(UNIT_STAT_ROAMING_MOVE
);
100 i_nextMoveTime
.Reset(i_destinationHolder
.GetTotalTravelTime());
101 creature
.AddMonsterMoveFlag(MONSTER_MOVE_FLY
);
103 //else if (is_water_ok) // Swimming mode to be done with more than this check
106 i_nextMoveTime
.Reset(urand(500+i_destinationHolder
.GetTotalTravelTime(), 10000+i_destinationHolder
.GetTotalTravelTime()));
107 creature
.AddMonsterMoveFlag(MONSTER_MOVE_WALK
);
112 void RandomMovementGenerator
<Creature
>::Initialize(Creature
&creature
)
114 if (!creature
.isAlive())
117 if (creature
.canFly())
118 creature
.AddMonsterMoveFlag(MONSTER_MOVE_FLY
);
120 creature
.AddMonsterMoveFlag(MONSTER_MOVE_WALK
);
122 creature
.addUnitState(UNIT_STAT_ROAMING
|UNIT_STAT_ROAMING_MOVE
);
123 _setRandomLocation(creature
);
127 void RandomMovementGenerator
<Creature
>::Reset(Creature
&creature
)
129 Initialize(creature
);
133 void RandomMovementGenerator
<Creature
>::Interrupt(Creature
&creature
)
135 creature
.clearUnitState(UNIT_STAT_ROAMING
|UNIT_STAT_ROAMING_MOVE
);
140 RandomMovementGenerator
<Creature
>::Finalize(Creature
&creature
)
142 creature
.clearUnitState(UNIT_STAT_ROAMING
|UNIT_STAT_ROAMING_MOVE
);
147 RandomMovementGenerator
<Creature
>::Update(Creature
&creature
, const uint32
&diff
)
149 if (creature
.hasUnitState(UNIT_STAT_NOT_MOVE
))
151 i_nextMoveTime
.Update(i_nextMoveTime
.GetExpiry()); // Expire the timer
152 creature
.clearUnitState(UNIT_STAT_ROAMING_MOVE
);
156 i_nextMoveTime
.Update(diff
);
158 if (i_destinationHolder
.HasArrived() && !creature
.IsStopped() && !creature
.canFly())
159 creature
.clearUnitState(UNIT_STAT_ROAMING_MOVE
);
161 if (!i_destinationHolder
.HasArrived() && creature
.IsStopped())
162 creature
.addUnitState(UNIT_STAT_ROAMING_MOVE
);
164 CreatureTraveller
traveller(creature
);
166 if (i_destinationHolder
.UpdateTraveller(traveller
, diff
, false, true))
168 if (i_nextMoveTime
.Passed())
170 if (creature
.canFly())
171 creature
.AddMonsterMoveFlag(MONSTER_MOVE_FLY
);
173 creature
.AddMonsterMoveFlag(MONSTER_MOVE_WALK
);
175 _setRandomLocation(creature
);
177 else if (creature
.isPet() && creature
.GetOwner() && !creature
.IsWithinDist(creature
.GetOwner(), PET_FOLLOW_DIST
+2.5f
))
179 creature
.AddMonsterMoveFlag(MONSTER_MOVE_WALK
);
180 _setRandomLocation(creature
);