root/trunk/src/game/GameEvent.cpp @ 23

Revision 2, 23.8 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-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 "GameEvent.h"
20#include "World.h"
21#include "ObjectMgr.h"
22#include "ProgressBar.h"
23#include "Language.h"
24#include "Log.h"
25#include "MapManager.h"
26#include "Policies/SingletonImp.h"
27
28INSTANTIATE_SINGLETON_1(GameEvent);
29
30bool GameEvent::CheckOneGameEvent(uint16 entry) const
31{
32    // Get the event information
33    time_t currenttime = time(NULL);
34    if( mGameEvent[entry].start < currenttime && currenttime < mGameEvent[entry].end &&
35        ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE)) < (mGameEvent[entry].length * MINUTE) )
36        return true;
37    else
38        return false;
39}
40
41uint32 GameEvent::NextCheck(uint16 entry) const
42{
43    time_t currenttime = time(NULL);
44
45    // outdated event: we return max
46    if (currenttime > mGameEvent[entry].end)
47        return max_ge_check_delay;
48
49    // never started event, we return delay before start
50    if (mGameEvent[entry].start > currenttime)
51        return (mGameEvent[entry].start - currenttime);
52
53    uint32 delay;
54    // in event, we return the end of it
55    if ((((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * 60)) < (mGameEvent[entry].length * 60)))
56        // we return the delay before it ends
57        delay = (mGameEvent[entry].length * MINUTE) - ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE));
58    else                                                    // not in window, we return the delay before next start
59        delay = (mGameEvent[entry].occurence * MINUTE) - ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE));
60    // In case the end is before next check
61    if (mGameEvent[entry].end  < time_t(currenttime + delay))
62        return (mGameEvent[entry].end - currenttime);
63    else
64        return delay;
65}
66
67void GameEvent::StartEvent( uint16 event_id, bool overwrite )
68{
69    AddActiveEvent(event_id);
70    ApplyNewEvent(event_id);
71    if(overwrite)
72    {
73        mGameEvent[event_id].start = time(NULL);
74        if(mGameEvent[event_id].end <= mGameEvent[event_id].start)
75            mGameEvent[event_id].end = mGameEvent[event_id].start+mGameEvent[event_id].length;
76    }
77}
78
79void GameEvent::StopEvent( uint16 event_id, bool overwrite )
80{
81    RemoveActiveEvent(event_id);
82    UnApplyEvent(event_id);
83    if(overwrite)
84    {
85        mGameEvent[event_id].start = time(NULL) - mGameEvent[event_id].length * MINUTE;
86        if(mGameEvent[event_id].end <= mGameEvent[event_id].start)
87            mGameEvent[event_id].end = mGameEvent[event_id].start+mGameEvent[event_id].length;
88    }
89}
90
91void GameEvent::LoadFromDB()
92{
93    {
94        QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM game_event");
95        if( !result )
96        {
97            sLog.outString(">> Table game_event is empty.");
98            sLog.outString();
99            return;
100        }
101
102        Field *fields = result->Fetch();
103
104        uint32 max_event_id = fields[0].GetUInt16();
105        delete result;
106
107        mGameEvent.resize(max_event_id+1);
108    }
109
110    QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,description FROM game_event");
111    if( !result )
112    {
113        mGameEvent.clear();
114        sLog.outString(">> Table game_event is empty:");
115        sLog.outString();
116        return;
117    }
118
119    uint32 count = 0;
120
121    barGoLink bar( result->GetRowCount() );
122    do
123    {
124        ++count;
125        Field *fields = result->Fetch();
126
127        bar.step();
128
129        uint16 event_id = fields[0].GetUInt16();
130        if(event_id==0)
131        {
132            sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id);
133            continue;
134        }
135
136        GameEventData& pGameEvent = mGameEvent[event_id];
137        uint64 starttime        = fields[1].GetUInt64();
138        pGameEvent.start        = time_t(starttime);
139        uint64 endtime          = fields[2].GetUInt64();
140        pGameEvent.end          = time_t(endtime);
141        pGameEvent.occurence    = fields[3].GetUInt32();
142        pGameEvent.length       = fields[4].GetUInt32();
143
144        if(pGameEvent.length==0)                            // length>0 is validity check
145        {
146            sLog.outErrorDb("`game_event` game event id (%i) have length 0 and can't be used.",event_id);
147            continue;
148        }
149
150        pGameEvent.description  = fields[5].GetCppString();
151
152    } while( result->NextRow() );
153
154    sLog.outString();
155    sLog.outString( ">> Loaded %u game events", count );
156    delete result;
157
158    mGameEventCreatureGuids.resize(mGameEvent.size()*2-1);
159    //                                   1              2
160    result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event "
161        "FROM creature JOIN game_event_creature ON creature.guid = game_event_creature.guid");
162
163    count = 0;
164    if( !result )
165    {
166        barGoLink bar2(1);
167        bar2.step();
168
169        sLog.outString();
170        sLog.outString(">> Loaded %u creatures in game events", count );
171    }
172    else
173    {
174
175        barGoLink bar2( result->GetRowCount() );
176        do
177        {
178            Field *fields = result->Fetch();
179
180            bar2.step();
181
182            uint32 guid    = fields[0].GetUInt32();
183            int16 event_id = fields[1].GetInt16();
184
185            int32 internal_event_id = mGameEvent.size() + event_id - 1;
186
187            if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
188            {
189                sLog.outErrorDb("`game_event_creature` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
190                continue;
191            }
192
193            ++count;
194            GuidList& crelist = mGameEventCreatureGuids[internal_event_id];
195            crelist.push_back(guid);
196
197        } while( result->NextRow() );
198        sLog.outString();
199        sLog.outString( ">> Loaded %u creatures in game events", count );
200        delete result;
201    }
202
203    mGameEventGameobjectGuids.resize(mGameEvent.size()*2-1);
204    //                                   1                2
205    result = WorldDatabase.Query("SELECT gameobject.guid, game_event_gameobject.event "
206        "FROM gameobject JOIN game_event_gameobject ON gameobject.guid=game_event_gameobject.guid");
207
208    count = 0;
209    if( !result )
210    {
211        barGoLink bar3(1);
212        bar3.step();
213
214        sLog.outString();
215        sLog.outString(">> Loaded %u gameobjects in game events", count );
216    }
217    else
218    {
219
220        barGoLink bar3( result->GetRowCount() );
221        do
222        {
223            Field *fields = result->Fetch();
224
225            bar3.step();
226
227            uint32 guid    = fields[0].GetUInt32();
228            int16 event_id = fields[1].GetInt16();
229
230            int32 internal_event_id = mGameEvent.size() + event_id - 1;
231
232            if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
233            {
234                sLog.outErrorDb("`game_event_gameobject` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
235                continue;
236            }
237
238            ++count;
239            GuidList& golist = mGameEventGameobjectGuids[internal_event_id];
240            golist.push_back(guid);
241
242        } while( result->NextRow() );
243        sLog.outString();
244        sLog.outString( ">> Loaded %u gameobjects in game events", count );
245
246        delete result;
247    }
248
249    mGameEventModelEquip.resize(mGameEvent.size());
250    //                                   0              1                             2
251    result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid,"
252    //   3
253        "game_event_model_equip.equipment_id "
254        "FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid");
255
256    count = 0;
257    if( !result )
258    {
259        barGoLink bar3(1);
260        bar3.step();
261
262        sLog.outString();
263        sLog.outString(">> Loaded %u model/equipment changes in game events", count );
264    }
265    else
266    {
267
268        barGoLink bar3( result->GetRowCount() );
269        do
270        {
271            Field *fields = result->Fetch();
272
273            bar3.step();
274            uint32 guid     = fields[0].GetUInt32();
275            uint16 event_id = fields[1].GetUInt16();
276
277            if(event_id >= mGameEventModelEquip.size())
278            {
279                sLog.outErrorDb("`game_event_model_equip` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
280                continue;
281            }
282
283            ++count;
284            ModelEquipList& equiplist = mGameEventModelEquip[event_id];
285            ModelEquip newModelEquipSet;
286            newModelEquipSet.modelid = fields[2].GetUInt32();
287            newModelEquipSet.equipment_id = fields[3].GetUInt32();
288            newModelEquipSet.equipement_id_prev = 0;
289            newModelEquipSet.modelid_prev = 0;
290
291            if(newModelEquipSet.equipment_id > 0)
292            {
293                if(!objmgr.GetEquipmentInfo(newModelEquipSet.equipment_id))
294                {
295                    sLog.outErrorDb("Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newModelEquipSet.equipment_id);
296                    continue;
297                }
298            }
299
300            equiplist.push_back(std::pair<uint32, ModelEquip>(guid, newModelEquipSet));
301
302        } while( result->NextRow() );
303        sLog.outString();
304        sLog.outString( ">> Loaded %u model/equipment changes in game events", count );
305
306        delete result;
307    }
308
309    mGameEventQuests.resize(mGameEvent.size());
310    //                                   0   1      2
311    result = WorldDatabase.Query("SELECT id, quest, event FROM game_event_creature_quest");
312
313    count = 0;
314    if( !result )
315    {
316        barGoLink bar3(1);
317        bar3.step();
318
319        sLog.outString();
320        sLog.outString(">> Loaded %u quests additions in game events", count );
321    }
322    else
323    {
324
325        barGoLink bar3( result->GetRowCount() );
326        do
327        {
328            Field *fields = result->Fetch();
329
330            bar3.step();
331            uint32 id       = fields[0].GetUInt32();
332            uint32 quest    = fields[1].GetUInt32();
333            uint16 event_id = fields[2].GetUInt16();
334
335            if(event_id >= mGameEventQuests.size())
336            {
337                sLog.outErrorDb("`game_event_creature_quest` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
338                continue;
339            }
340
341            ++count;
342            QuestRelList& questlist = mGameEventQuests[event_id];
343            questlist.push_back(QuestRelation(id, quest));
344
345        } while( result->NextRow() );
346        sLog.outString();
347        sLog.outString( ">> Loaded %u quests additions in game events", count );
348
349        delete result;
350    }
351}
352
353uint32 GameEvent::Initialize()                              // return the next event delay in ms
354{
355    m_ActiveEvents.clear();
356    uint32 delay = Update();
357    sLog.outBasic("Game Event system initialized." );
358    isSystemInit = true;
359    return delay;
360}
361
362uint32 GameEvent::Update()                                  // return the next event delay in ms
363{
364    uint32 nextEventDelay = max_ge_check_delay;             // 1 day
365    uint32 calcDelay;
366    for (uint16 itr = 1; itr < mGameEvent.size(); itr++)
367    {
368        //sLog.outErrorDb("Checking event %u",itr);
369        if (CheckOneGameEvent(itr))
370        {
371            //sLog.outDebug("GameEvent %u is active",itr->first);
372            if (!IsActiveEvent(itr))
373                StartEvent(itr);
374        }
375        else
376        {
377            //sLog.outDebug("GameEvent %u is not active",itr->first);
378            if (IsActiveEvent(itr))
379                StopEvent(itr);
380            else
381            {
382                if (!isSystemInit)
383                {
384                    int16 event_nid = (-1) * (itr);
385                    // spawn all negative ones for this event
386                    GameEventSpawn(event_nid);
387                }
388            }
389        }
390        calcDelay = NextCheck(itr);
391        if (calcDelay < nextEventDelay)
392            nextEventDelay = calcDelay;
393    }
394    sLog.outBasic("Next game event check in %u seconds.", nextEventDelay + 1);
395    return (nextEventDelay + 1) * 1000;                     // Add 1 second to be sure event has started/stopped at next call
396}
397
398void GameEvent::UnApplyEvent(uint16 event_id)
399{
400    sLog.outString("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str());
401    // un-spawn positive event tagged objects
402    GameEventUnspawn(event_id);
403    // spawn negative event tagget objects
404    int16 event_nid = (-1) * event_id;
405    GameEventSpawn(event_nid);
406    // restore equipment or model
407    ChangeEquipOrModel(event_id, false);
408    // Remove quests that are events only to non event npc
409    UpdateEventQuests(event_id, false);
410}
411
412void GameEvent::ApplyNewEvent(uint16 event_id)
413{
414    switch(sWorld.getConfig(CONFIG_EVENT_ANNOUNCE))
415    {
416        case 0:                                             // disable
417            break;
418        case 1:                                             // announce events
419            sWorld.SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str());
420            break;
421    }
422
423    sLog.outString("GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str());
424    // spawn positive event tagget objects
425    GameEventSpawn(event_id);
426    // un-spawn negative event tagged objects
427    int16 event_nid = (-1) * event_id;
428    GameEventUnspawn(event_nid);
429    // Change equipement or model
430    ChangeEquipOrModel(event_id, true);
431    // Add quests that are events only to non event npc
432    UpdateEventQuests(event_id, true);
433}
434
435void GameEvent::GameEventSpawn(int16 event_id)
436{
437    int32 internal_event_id = mGameEvent.size() + event_id - 1;
438
439    if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
440    {
441        sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
442        return;
443    }
444
445    for (GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();itr != mGameEventCreatureGuids[internal_event_id].end();++itr)
446    {
447        // Add to correct cell
448        CreatureData const* data = objmgr.GetCreatureData(*itr);
449        if (data)
450        {
451            objmgr.AddCreatureToGrid(*itr, data);
452
453            // Spawn if necessary (loaded grids only)
454            Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(data->mapid));
455            // We use spawn coords to spawn
456            if(!map->Instanceable() && !map->IsRemovalGrid(data->posX,data->posY))
457            {
458                Creature* pCreature = new Creature;
459                //sLog.outDebug("Spawning creature %u",*itr);
460                if (!pCreature->LoadFromDB(*itr, map))
461                {
462                    delete pCreature;
463                }
464                else
465                {
466                    map->Add(pCreature);
467                }
468            }
469        }
470    }
471
472    if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
473    {
474        sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
475        return;
476    }
477
478    for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();itr != mGameEventGameobjectGuids[internal_event_id].end();++itr)
479    {
480        // Add to correct cell
481        GameObjectData const* data = objmgr.GetGOData(*itr);
482        if (data)
483        {
484            objmgr.AddGameobjectToGrid(*itr, data);
485            // Spawn if necessary (loaded grids only)
486            // this base map checked as non-instanced and then only existed
487            Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(data->mapid));
488            // We use current coords to unspawn, not spawn coords since creature can have changed grid
489            if(!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY))
490            {
491                GameObject* pGameobject = new GameObject;
492                //sLog.outDebug("Spawning gameobject %u", *itr);
493                if (!pGameobject->LoadFromDB(*itr, map))
494                {
495                    delete pGameobject;
496                }
497                else
498                {
499                    if(pGameobject->isSpawnedByDefault())
500                        map->Add(pGameobject);
501                }
502            }
503        }
504    }
505}
506
507void GameEvent::GameEventUnspawn(int16 event_id)
508{
509    int32 internal_event_id = mGameEvent.size() + event_id - 1;
510
511    if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
512    {
513        sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
514        return;
515    }
516
517    for (GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();itr != mGameEventCreatureGuids[internal_event_id].end();++itr)
518    {
519        // Remove the creature from grid
520        if( CreatureData const* data = objmgr.GetCreatureData(*itr) )
521        {
522            objmgr.RemoveCreatureFromGrid(*itr, data);
523
524            if( Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_UNIT), (Creature*)NULL) )
525            {
526                pCreature->CleanupsBeforeDelete();
527                pCreature->AddObjectToRemoveList();
528            }
529        }
530    }
531
532    if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
533    {
534        sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
535        return;
536    }
537
538    for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();itr != mGameEventGameobjectGuids[internal_event_id].end();++itr)
539    {
540        // Remove the gameobject from grid
541        if(GameObjectData const* data = objmgr.GetGOData(*itr))
542        {
543            objmgr.RemoveGameobjectFromGrid(*itr, data);
544
545            if( GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL) )
546                pGameobject->AddObjectToRemoveList();
547        }
548    }
549}
550
551void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate)
552{
553    for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr)
554    {
555        // Remove the creature from grid
556        CreatureData const* data = objmgr.GetCreatureData(itr->first);
557        if(!data)
558            continue;
559
560        // Update if spawned
561        Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(itr->first, data->id,HIGHGUID_UNIT), (Creature*)NULL);
562        if (pCreature)
563        {
564            if (activate)
565            {
566                itr->second.equipement_id_prev = pCreature->GetCurrentEquipmentId();
567                itr->second.modelid_prev = pCreature->GetDisplayId();
568                pCreature->LoadEquipment(itr->second.equipment_id, true);
569                if (itr->second.modelid >0 && itr->second.modelid_prev != itr->second.modelid)
570                {
571                    CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(itr->second.modelid);
572                    if (minfo)
573                    {
574                        pCreature->SetDisplayId(itr->second.modelid);
575                        pCreature->SetNativeDisplayId(itr->second.modelid);
576                        pCreature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius);
577                        pCreature->SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach );
578                    }
579                }
580            }
581            else
582            {
583                pCreature->LoadEquipment(itr->second.equipement_id_prev, true);
584                if (itr->second.modelid_prev >0 && itr->second.modelid_prev != itr->second.modelid)
585                {
586                    CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(itr->second.modelid_prev);
587                    if (minfo)
588                    {
589                        pCreature->SetDisplayId(itr->second.modelid_prev);
590                        pCreature->SetNativeDisplayId(itr->second.modelid_prev);
591                        pCreature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius);
592                        pCreature->SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach );
593                    }
594                }
595            }
596        }
597        else                                                // If not spawned
598        {
599            CreatureData const* data = objmgr.GetCreatureData(itr->first);
600            if (data && activate)
601            {
602                CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(data->id);
603                uint32 display_id = objmgr.ChooseDisplayId(0,cinfo,data);
604                CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
605                if (minfo)
606                    display_id = minfo->modelid;
607                if (data->equipmentId == 0)
608                    itr->second.equipement_id_prev = cinfo->equipmentId;
609                else if (data->equipmentId != -1)
610                    itr->second.equipement_id_prev = data->equipmentId;
611                itr->second.modelid_prev = display_id;
612            }
613        }
614        // now last step: put in data
615                                                            // just to have write access to it
616        CreatureData& data2 = objmgr.NewOrExistCreatureData(itr->first);
617        if (activate)
618        {
619            data2.displayid = itr->second.modelid;
620            data2.equipmentId = itr->second.equipment_id;
621        }
622        else
623        {
624            data2.displayid = itr->second.modelid_prev;
625            data2.equipmentId = itr->second.equipement_id_prev;
626        }
627    }
628}
629
630void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate)
631{
632    QuestRelList::iterator itr;
633    for (itr = mGameEventQuests[event_id].begin();itr != mGameEventQuests[event_id].end();++itr)
634    {
635        QuestRelations &CreatureQuestMap = objmgr.mCreatureQuestRelations;
636        if (Activate)                                       // Add the pair(id,quest) to the multimap
637            CreatureQuestMap.insert(QuestRelations::value_type(itr->first, itr->second));
638        else
639        {                                                   // Remove the pair(id,quest) from the multimap
640            QuestRelations::iterator qitr = CreatureQuestMap.find(itr->first);
641            if (qitr == CreatureQuestMap.end())
642                continue;
643            QuestRelations::iterator lastElement = CreatureQuestMap.upper_bound(itr->first);
644            for ( ;qitr != lastElement;++qitr)
645            {
646                if (qitr->second == itr->second)
647                {
648                    CreatureQuestMap.erase(qitr);           // iterator is now no more valid
649                    break;                                  // but we can exit loop since the element is found
650                }
651            }
652        }
653    }
654}
655
656GameEvent::GameEvent()
657{
658    isSystemInit = false;
659}
Note: See TracBrowser for help on using the browser.