root/trunk/src/game/MotionMaster.cpp @ 37

Revision 37, 9.8 kB (checked in by yumileroy, 17 years ago)

[svn] * svn:eol-style native set on all files that need it

Original author: Neo2003
Date: 2008-10-11 14:16:25-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
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.
8 *
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.
13 *
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
17 */
18
19#include "MotionMaster.h"
20#include "CreatureAISelector.h"
21#include "Creature.h"
22#include "Traveller.h"
23
24#include "ConfusedMovementGenerator.h"
25#include "FleeingMovementGenerator.h"
26#include "HomeMovementGenerator.h"
27#include "IdleMovementGenerator.h"
28#include "PointMovementGenerator.h"
29#include "TargetedMovementGenerator.h"
30#include "WaypointMovementGenerator.h"
31
32#include <cassert>
33
34inline bool isStatic(MovementGenerator *mv)
35{
36    return (mv == &si_idleMovement);
37}
38
39void
40MotionMaster::Initialize()
41{
42    // clear ALL movement generators (including default)
43    while(!empty())
44    {
45        MovementGenerator *curr = top();
46        curr->Finalize(*i_owner);
47        pop();
48        if( !isStatic( curr ) )
49            delete curr;
50    }
51
52    // set new default movement generator
53    if(i_owner->GetTypeId() == TYPEID_UNIT)
54    {
55        MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner);
56        push(  movement == NULL ? &si_idleMovement : movement );
57        top()->Initialize(*i_owner);
58    }
59    else
60        push(&si_idleMovement);
61}
62
63MotionMaster::~MotionMaster()
64{
65    // clear ALL movement generators (including default)
66    while(!empty())
67    {
68        MovementGenerator *curr = top();
69        curr->Finalize(*i_owner);
70        pop();
71        if( !isStatic( curr ) )
72            delete curr;
73    }
74}
75
76void
77MotionMaster::UpdateMotion(const uint32 &diff)
78{
79    if( i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED) )
80        return;
81    assert( !empty() );
82    if (!top()->Update(*i_owner, diff))
83        MovementExpired();
84}
85
86void
87MotionMaster::Clear(bool reset)
88{
89    while( !empty() && size() > 1 )
90    {
91        MovementGenerator *curr = top();
92        curr->Finalize(*i_owner);
93        pop();
94        if( !isStatic( curr ) )
95            delete curr;
96    }
97
98    if (reset)
99    {
100        assert( !empty() );
101        top()->Reset(*i_owner);
102    }
103}
104
105void
106MotionMaster::MovementExpired(bool reset)
107{
108    if( empty() || size() == 1 )
109        return;
110
111    MovementGenerator *curr = top();
112    curr->Finalize(*i_owner);
113    pop();
114
115    if( !isStatic(curr) )
116        delete curr;
117
118    assert( !empty() );
119    while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
120    {
121        // Should check if target is still valid? If not valid it will crash.
122        curr = top();
123        curr->Finalize(*i_owner);
124        pop();
125        delete curr;
126    }
127    if( empty() )
128        Initialize();
129    if (reset) top()->Reset(*i_owner);
130}
131
132void MotionMaster::MoveIdle()
133{
134    if( empty() || !isStatic( top() ) )
135        push( &si_idleMovement );
136}
137
138void
139MotionMaster::MoveTargetedHome()
140{
141    if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
142        return;
143
144    Clear(false);
145
146    if(i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID())
147    {
148        DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow());
149        Mutate(new HomeMovementGenerator<Creature>());
150    }
151    else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID())
152    {
153        sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home",
154            i_owner->GetEntry(), i_owner->GetGUIDLow() );
155    }
156    else
157    {
158        sLog.outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow() );
159    }
160}
161
162void
163MotionMaster::MoveConfused()
164{
165    if(i_owner->GetTypeId()==TYPEID_PLAYER)
166    {
167        DEBUG_LOG("Player (GUID: %u) move confused", i_owner->GetGUIDLow() );
168        Mutate(new ConfusedMovementGenerator<Player>());
169    }
170    else
171    {
172        DEBUG_LOG("Creature (Entry: %u GUID: %u) move confused",
173            i_owner->GetEntry(), i_owner->GetGUIDLow() );
174        Mutate(new ConfusedMovementGenerator<Creature>());
175    }
176}
177
178void
179MotionMaster::MoveChase(Unit* target, float dist, float angle)
180{
181    // ignore movement request if target not exist
182    if(!target)
183        return;
184
185    i_owner->clearUnitState(UNIT_STAT_FOLLOW);
186    if(i_owner->GetTypeId()==TYPEID_PLAYER)
187    {
188        DEBUG_LOG("Player (GUID: %u) chase to %s (GUID: %u)",
189            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
190            target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
191        Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
192    }
193    else
194    {
195        DEBUG_LOG("Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)",
196            i_owner->GetEntry(), i_owner->GetGUIDLow(),
197            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
198            target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
199        Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
200    }
201}
202
203void
204MotionMaster::MoveFollow(Unit* target, float dist, float angle)
205{
206    Clear();
207
208    // ignore movement request if target not exist
209    if(!target)
210        return;
211
212    i_owner->addUnitState(UNIT_STAT_FOLLOW);
213    if(i_owner->GetTypeId()==TYPEID_PLAYER)
214    {
215        DEBUG_LOG("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(),
216            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
217            target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
218        Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
219    }
220    else
221    {
222        DEBUG_LOG("Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)",
223            i_owner->GetEntry(), i_owner->GetGUIDLow(),
224            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
225            target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
226        Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
227    }
228}
229
230void
231MotionMaster::MovePoint(uint32 id, float x, float y, float z)
232{
233    if(i_owner->GetTypeId()==TYPEID_PLAYER)
234    {
235        DEBUG_LOG("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z );
236        Mutate(new PointMovementGenerator<Player>(id,x,y,z));
237    }
238    else
239    {
240        DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)",
241            i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z );
242        Mutate(new PointMovementGenerator<Creature>(id,x,y,z));
243    }
244}
245
246void
247MotionMaster::MoveFleeing(Unit* enemy)
248{
249    if(!enemy)
250        return;
251
252    if(i_owner->GetTypeId()==TYPEID_PLAYER)
253    {
254        DEBUG_LOG("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(),
255            enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
256            enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
257        Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()));
258    }
259    else
260    {
261        DEBUG_LOG("Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)",
262            i_owner->GetEntry(), i_owner->GetGUIDLow(),
263            enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
264            enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
265        Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()));
266    }
267}
268
269void
270MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
271{
272    if(i_owner->GetTypeId()==TYPEID_PLAYER)
273    {
274        DEBUG_LOG("Player (GUID: %u) taxi to (Path %u node %u)", i_owner->GetGUIDLow(), path, pathnode);
275        FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode);
276        Mutate(mgen);
277    }
278    else
279    {
280        sLog.outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)",
281            i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode );
282    }
283}
284
285void
286MotionMaster::MoveDistract(uint32 timer)
287{
288    if(i_owner->GetTypeId()==TYPEID_PLAYER)
289    {
290        DEBUG_LOG("Player (GUID: %u) distracted (timer: %u)", i_owner->GetGUIDLow(), timer);
291    }
292    else
293    {
294        DEBUG_LOG("Creature (Entry: %u GUID: %u) (timer: %u)",
295            i_owner->GetEntry(), i_owner->GetGUIDLow(), timer);
296    }
297
298    DistractMovementGenerator* mgen = new DistractMovementGenerator(timer);
299    Mutate(mgen);
300}
301
302void MotionMaster::Mutate(MovementGenerator *m)
303{
304    if (!empty())
305    {
306        switch(top()->GetMovementGeneratorType())
307        {
308            // HomeMovement is not that important, delete it if meanwhile a new comes
309            case HOME_MOTION_TYPE:
310            // DistractMovement interrupted by any other movement
311            case DISTRACT_MOTION_TYPE:
312                MovementExpired(false);
313        }
314    }
315    m->Initialize(*i_owner);
316    push(m);
317}
318
319void MotionMaster::propagateSpeedChange()
320{
321    Impl::container_type::iterator it = Impl::c.begin();
322    for ( ;it != end(); ++it)
323    {
324        (*it)->unitSpeedChanged();
325    }
326}
327
328MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
329{
330   if(empty())
331       return IDLE_MOTION_TYPE;
332
333   return top()->GetMovementGeneratorType();
334}
335
336bool MotionMaster::GetDestination(float &x, float &y, float &z)
337{
338   if(empty())
339       return false;
340
341   return top()->GetDestination(x,y,z);
342}
Note: See TracBrowser for help on using the browser.