[2685] Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / TargetedMovementGenerator.cpp
blobb765cb9cb7e7edb1dc461f0ad0c6f8a9635bf51d
1 /*
2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
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 "MapManager.h"
24 #include "Spell.h"
25 #include "DestinationHolderImp.h"
27 #define SMALL_ALPHA 0.05
29 #include <cmath>
31 struct StackCleaner
33 Creature &i_creature;
34 StackCleaner(Creature &creature) : i_creature(creature) {}
35 void Done(void) { i_creature.StopMoving(); }
36 ~StackCleaner()
38 i_creature->Clear();
42 void
43 TargetedMovementGenerator::_setTargetLocation(Creature &owner, float offset)
45 if( !&i_target || !&owner )
46 return;
48 if( owner.hasUnitState(UNIT_STAT_ROOT) || owner.hasUnitState(UNIT_STAT_STUNDED) )
49 return;
51 float x, y, z;
52 i_target.GetContactPoint( &owner, x, y, z );
53 Traveller<Creature> traveller(owner);
54 i_destinationHolder.SetDestination(traveller, x, y, z, offset);
55 owner.addUnitState(UNIT_STAT_CHASE);
58 void
59 TargetedMovementGenerator::_setAttackRadius(Creature &owner)
61 if(!&owner)
62 return;
63 float combat_reach = owner.GetFloatValue(UNIT_FIELD_COMBATREACH);
64 if( combat_reach <= 0.0f )
65 combat_reach = 1.0f;
66 //float bounding_radius = owner.GetFloatValue(UNIT_FIELD_BOUNDINGRADIUS);
67 i_attackRadius = combat_reach; // - SMALL_ALPHA);
70 void
71 TargetedMovementGenerator::Initialize(Creature &owner)
73 if(!&owner)
74 return;
75 owner.setMoveRunFlag(true);
76 _setAttackRadius(owner);
77 _setTargetLocation(owner, 0);
80 void
81 TargetedMovementGenerator::Reset(Creature &owner)
83 Initialize(owner);
86 void
87 TargetedMovementGenerator::TargetedHome(Creature &owner)
89 if(!&owner)
90 return;
91 if(owner.hasUnitState(UNIT_STAT_FLEEING))
92 return;
93 DEBUG_LOG("Target home location %u", owner.GetGUIDLow());
94 float x, y, z;
95 owner.GetRespawnCoord(x, y, z);
96 Traveller<Creature> traveller(owner);
97 i_destinationHolder.SetDestination(traveller, x, y, z);
98 traveller.Relocation(x,y,z);
99 i_targetedHome = true;
100 owner.clearUnitState(UNIT_STAT_ALL_STATE);
103 void
104 TargetedMovementGenerator::Update(Creature &owner, const uint32 & time_diff)
106 if( !&owner || !owner.isAlive() || !&i_target || i_targetedHome )
107 return;
108 if( owner.hasUnitState(UNIT_STAT_ROOT) || owner.hasUnitState(UNIT_STAT_STUNDED) || owner.hasUnitState(UNIT_STAT_FLEEING))
109 return;
110 if( !owner.isInCombat() && !owner.hasUnitState(UNIT_STAT_FOLLOW) )
112 owner.AIM_Initialize();
113 return;
116 // prevent crash after creature killed pet
117 if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != &i_target)
118 return;
120 Traveller<Creature> traveller(owner);
121 if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
123 // put targeted movement generators on a higher priority
124 i_destinationHolder.ResetUpdate(50);
125 float dist = i_target.GetObjectSize() + owner.GetObjectSize() + OBJECT_CONTACT_DISTANCE;
126 // try to counter precision differences
127 if( i_destinationHolder.GetDistanceFromDestSq(i_target) > dist * dist + 0.1)
128 _setTargetLocation(owner, 0);
129 else if ( !owner.HasInArc( 0.1f, &i_target ) )
131 owner.SetInFront(&i_target);
132 if( i_target.GetTypeId() == TYPEID_PLAYER )
133 owner.SendUpdateToPlayer( (Player*)&i_target );
135 if( !owner.IsStopped() && i_destinationHolder.HasArrived())
137 owner.StopMoving();
138 if(owner.canReachWithAttack(&i_target) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
139 owner.Attack(&i_target);
144 //SpellEntry* spellInfo;
145 if( reach )
147 if( owner.GetDistance2dSq( &i_target ) > 0.0f )
149 DEBUG_LOG("MOVEMENT : Distance = %f",owner.GetDistance2dSq( &i_target ));
150 owner.addUnitState(UNIT_STAT_CHASE);
151 _setTargetLocation(owner, 0);
153 else if ( !owner.HasInArc( 0.0f, &i_target ) )
155 DEBUG_LOG("MOVEMENT : Orientation = %f",owner.GetAngle(&i_target));
156 owner.SetInFront(&i_target);
157 if( i_target.GetTypeId() == TYPEID_PLAYER )
158 owner.SendUpdateToPlayer( (Player*)&i_target );
160 if( !owner.isInCombat() )
162 owner.AIM_Initialize();
163 return;
166 else if( i_target.isAlive() )
168 if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.isInCombat() )
170 if( spellInfo = owner.reachWithSpellAttack( &i_target ) )
172 _spellAtack(owner, spellInfo);
173 return;
176 if( owner.GetDistance2dSq( &i_target ) > 0.0f )
178 DEBUG_LOG("MOVEMENT : Distance = %f",owner.GetDistance2dSq( &i_target ));
179 owner.addUnitState(UNIT_STAT_CHASE);
180 _setTargetLocation(owner, 0);
183 else if( !i_targetedHome )
185 if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.isInCombat() && (spellInfo = owner.reachWithSpellAttack(&i_target)) )
187 _spellAtack(owner, spellInfo);
188 return;
190 _setTargetLocation(owner, 0);
191 if(reach)
193 if( reach && owner.canReachWithAttack(&i_target) )
195 owner.StopMoving();
196 if(!owner.hasUnitState(UNIT_STAT_FOLLOW))
197 owner.Attack(&i_target);
198 owner.clearUnitState(UNIT_STAT_CHASE);
199 DEBUG_LOG("UNIT IS THERE");
201 else
203 _setTargetLocation(owner, 0);
204 DEBUG_LOG("Continue to chase");
210 void TargetedMovementGenerator::_spellAtack(Creature &owner, SpellEntry* spellInfo)
212 if(!spellInfo)
213 return;
214 owner.StopMoving();
215 owner->Idle();
216 if(owner.m_currentSpell)
218 if(owner.m_currentSpell->m_spellInfo->Id == spellInfo->Id )
219 return;
220 else
222 owner.m_currentSpell->cancel();
225 Spell *spell = new Spell(&owner, spellInfo, false, 0);
226 spell->SetAutoRepeat(true);
227 //owner.addUnitState(UNIT_STAT_ATTACKING);
228 owner.Attack(&owner); //??
229 owner.clearUnitState(UNIT_STAT_CHASE);
230 SpellCastTargets targets;
231 targets.setUnitTarget( &i_target );
232 spell->prepare(&targets);
233 owner.m_canMove = false;
234 DEBUG_LOG("Spell Attack.");
237 void TargetedMovementGenerator::spellAtack(Creature &owner,Unit &who,uint32 spellId)
239 SpellEntry *spellInfo = sSpellStore.LookupEntry(spellId );
241 if(!spellInfo)
243 sLog.outError("WORLD: unknown spell id %i\n", spellId);
244 return;
247 owner.StopMoving();
248 owner->Idle();
249 if(owner.m_currentSpell)
251 if(owner.m_currentSpell->m_spellInfo->Id == spellInfo->Id )
252 return;
253 else
255 owner.m_currentSpell->cancel();
258 Spell *spell = new Spell(&owner, spellInfo, false, 0);
259 spell->SetAutoRepeat(false);
260 //owner.addUnitState(UNIT_STAT_ATTACKING);
261 //owner.clearUnitState(UNIT_STAT_CHASE);
262 SpellCastTargets targets;
263 targets.setUnitTarget( &who );
264 spell->prepare(&targets);
265 owner.m_canMove = false;
266 DEBUG_LOG("Spell Attack.");