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

Revision 102, 9.9 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

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