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

Revision 39, 24.1 kB (checked in by yumileroy, 17 years ago)

[svn] * Various small changes here and there.
* Implementing MangChat? IRC system.
* Added new config option, MAX_WHO, can be used to set the limit of characters being sent in a /who request from client.

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