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

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

[svn] *** Source: MaNGOS ***
* Implement localization of creature/gameobject name that say/yell. Author: evilstar (rewrited by: Vladimir)
* Fix auth login queue. Author: Derex
* Allowed switching INVTYPE_HOLDABLE items during combat, used correct spells for triggering global cooldown at weapon switch. Author: mobel/simak
* Fixed some format arg type/value pairs. Other warnings. Author: Vladimir
* [238_world.sql] Allow have team dependent graveyards at entrance map for instances. Author: Vladimir

NOTE:
Entrance map graveyards selected by same way as local (by distance from entrance) Until DB support will work in old way base at current DB data.

Original author: visagalis
Date: 2008-11-14 17:03:03-06: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            i_owner->GetGUIDLow(),
192            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
193            target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
194        Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
195    }
196    else
197    {
198        DEBUG_LOG("Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)",
199            i_owner->GetEntry(), i_owner->GetGUIDLow(),
200            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
201            target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
202        Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
203    }
204}
205
206void
207MotionMaster::MoveFollow(Unit* target, float dist, float angle)
208{
209    Clear();
210
211    // ignore movement request if target not exist
212    if(!target)
213        return;
214
215    i_owner->addUnitState(UNIT_STAT_FOLLOW);
216    if(i_owner->GetTypeId()==TYPEID_PLAYER)
217    {
218        DEBUG_LOG("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(),
219            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
220            target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() );
221        Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle));
222    }
223    else
224    {
225        DEBUG_LOG("Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)",
226            i_owner->GetEntry(), i_owner->GetGUIDLow(),
227            target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
228            target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
229        Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle));
230    }
231}
232
233void
234MotionMaster::MovePoint(uint32 id, float x, float y, float z)
235{
236    if(i_owner->GetTypeId()==TYPEID_PLAYER)
237    {
238        DEBUG_LOG("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z );
239        Mutate(new PointMovementGenerator<Player>(id,x,y,z));
240    }
241    else
242    {
243        DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)",
244            i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z );
245        Mutate(new PointMovementGenerator<Creature>(id,x,y,z));
246    }
247}
248
249void
250MotionMaster::MoveFleeing(Unit* enemy)
251{
252    if(!enemy)
253        return;
254
255    if(i_owner->GetTypeId()==TYPEID_PLAYER)
256    {
257        DEBUG_LOG("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(),
258            enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
259            enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
260        Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()));
261    }
262    else
263    {
264        DEBUG_LOG("Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)",
265            i_owner->GetEntry(), i_owner->GetGUIDLow(),
266            enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
267            enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() );
268        Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()));
269    }
270}
271
272void
273MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
274{
275    if(i_owner->GetTypeId()==TYPEID_PLAYER)
276    {
277        DEBUG_LOG("Player (GUID: %u) taxi to (Path %u node %u)", i_owner->GetGUIDLow(), path, pathnode);
278        FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode);
279        Mutate(mgen);
280    }
281    else
282    {
283        sLog.outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)",
284            i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode );
285    }
286}
287
288void
289MotionMaster::MoveDistract(uint32 timer)
290{
291    if(i_owner->GetTypeId()==TYPEID_PLAYER)
292    {
293        DEBUG_LOG("Player (GUID: %u) distracted (timer: %u)", i_owner->GetGUIDLow(), timer);
294    }
295    else
296    {
297        DEBUG_LOG("Creature (Entry: %u GUID: %u) (timer: %u)",
298            i_owner->GetEntry(), i_owner->GetGUIDLow(), timer);
299    }
300
301    DistractMovementGenerator* mgen = new DistractMovementGenerator(timer);
302    Mutate(mgen);
303}
304
305void MotionMaster::Mutate(MovementGenerator *m)
306{
307    if (!empty())
308    {
309        switch(top()->GetMovementGeneratorType())
310        {
311            // HomeMovement is not that important, delete it if meanwhile a new comes
312            case HOME_MOTION_TYPE:
313            // DistractMovement interrupted by any other movement
314            case DISTRACT_MOTION_TYPE:
315                MovementExpired(false);
316        }
317    }
318    m->Initialize(*i_owner);
319    push(m);
320}
321
322void MotionMaster::propagateSpeedChange()
323{
324    Impl::container_type::iterator it = Impl::c.begin();
325    for ( ;it != end(); ++it)
326    {
327        (*it)->unitSpeedChanged();
328    }
329}
330
331MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
332{
333   if(empty())
334       return IDLE_MOTION_TYPE;
335
336   return top()->GetMovementGeneratorType();
337}
338
339bool MotionMaster::GetDestination(float &x, float &y, float &z)
340{
341   if(empty())
342       return false;
343
344   return top()->GetDestination(x,y,z);
345}
Note: See TracBrowser for help on using the browser.