root/trunk/src/game/MapInstanced.cpp @ 9

Revision 9, 9.1 kB (checked in by yumileroy, 17 years ago)

[svn] -enabled instantiated battlegrounds
-enabled arena matches
-rewritten battleground queuing to support joining as group
-removed queue announcements

Original author: w12x
Date: 2008-10-05 08:48:32-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 "MapInstanced.h"
20#include "ObjectMgr.h"
21#include "MapManager.h"
22#include "BattleGround.h"
23#include "VMapFactory.h"
24#include "InstanceSaveMgr.h"
25#include "World.h"
26
27MapInstanced::MapInstanced(uint32 id, time_t expiry, uint32 aInstanceId) : Map(id, expiry, 0, 0)
28{
29    // initialize instanced maps list
30    m_InstancedMaps.clear();
31    // fill with zero
32    memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16));
33}
34
35void MapInstanced::Update(const uint32& t)
36{
37    // take care of loaded GridMaps (when unused, unload it!)
38    Map::Update(t);
39
40    // update the instanced maps
41    InstancedMaps::iterator i = m_InstancedMaps.begin();
42
43    while (i != m_InstancedMaps.end())
44    {
45        if(i->second->CanUnload(t))
46        {
47            DestroyInstance(i);                             // iterator incremented
48        }
49        else
50        {
51            // update only here, because it may schedule some bad things before delete
52            i->second->Update(t);
53            ++i;
54        }
55    }
56}
57
58void MapInstanced::MoveAllCreaturesInMoveList()
59{
60    for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++)
61    {
62        i->second->MoveAllCreaturesInMoveList();
63    }
64
65    Map::MoveAllCreaturesInMoveList();
66}
67
68void MapInstanced::RemoveAllObjectsInRemoveList()
69{
70    for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++)
71    {
72        i->second->RemoveAllObjectsInRemoveList();
73    }
74
75    Map::RemoveAllObjectsInRemoveList();
76}
77
78bool MapInstanced::RemoveBones(uint64 guid, float x, float y)
79{
80    bool remove_result = false;
81
82    for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++)
83    {
84        remove_result = remove_result || i->second->RemoveBones(guid, x, y);
85    }
86
87    return remove_result || Map::RemoveBones(guid,x,y);
88}
89
90void MapInstanced::UnloadAll(bool pForce)
91{
92    // Unload instanced maps
93    for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++)
94        i->second->UnloadAll(pForce);
95
96    // Delete the maps only after everything is unloaded to prevent crashes
97    for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); i++)
98        delete i->second;
99
100    m_InstancedMaps.clear();
101
102    // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!)
103    Map::UnloadAll(pForce);
104}
105
106/*
107- return the right instance for the object, based on its InstanceId
108- create the instance if it's not created already
109- the player is not actually added to the instance (only in InstanceMap::Add)
110*/
111Map* MapInstanced::GetInstance(const WorldObject* obj)
112{
113    uint32 CurInstanceId = obj->GetInstanceId();
114    Map* map = NULL;
115
116    if (obj->GetMapId() == GetId() && CurInstanceId != 0)
117    {
118        // the object wants to be put in a certain instance of this map
119        map = _FindMap(CurInstanceId);
120        if(!map)
121        {
122            // For players if the instanceId is set, it's assumed they are already in a map,
123            // hence the map must be loaded. For Creatures, GameObjects etc the map must exist
124            // prior to calling GetMap, they are not allowed to create maps for themselves.
125            sLog.outError("GetInstance: object %s(%d), typeId %d, in world %d, should be in map %d,%d but that's not loaded yet.", obj->GetName(), obj->GetGUIDLow(), obj->GetTypeId(), obj->IsInWorld(), obj->GetMapId(), obj->GetInstanceId());
126            assert(false);
127        }
128        return(map);
129    }
130    else
131    {
132        // instance not specified, find an existing or create a new one
133        if(obj->GetTypeId() != TYPEID_PLAYER)
134        {
135            sLog.outError("MAPINSTANCED: WorldObject '%u' (Entry: %u TypeID: %u) is in map %d,%d and requested base map instance of map %d, this must not happen", obj->GetGUIDLow(), obj->GetEntry(), obj->GetTypeId(), obj->GetMapId(), obj->GetInstanceId(), GetId());
136            assert(false);
137            return NULL;
138        }
139        else
140        {
141            uint32 NewInstanceId = 0;                       // instanceId of the resulting map
142            Player* player = (Player*)obj;
143
144            if(IsBattleGroundOrArena())
145            {
146                // instantiate or find existing bg map for player
147                // the instance id is set in battlegroundid
148                NewInstanceId = player->GetBattleGroundId();
149                assert(NewInstanceId);
150                map = _FindMap(NewInstanceId);
151                if(!map)
152                    map = CreateBattleGround(NewInstanceId);
153                return map;
154            }
155
156            InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty());
157            InstanceSave *pSave = pBind ? pBind->save : NULL;
158
159            // the player's permanet player bind is taken into consideration first
160            // then the player's group bind and finally the solo bind.
161            if(!pBind || !pBind->perm)
162            {
163                InstanceGroupBind *groupBind = NULL;
164                Group *group = player->GetGroup();
165                // use the player's difficulty setting (it may not be the same as the group's)
166                if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDifficulty())))
167                    pSave = groupBind->save;
168            }
169
170            if(pSave)
171            {
172                // solo/perm/group
173                NewInstanceId = pSave->GetInstanceId();
174                map = _FindMap(NewInstanceId);
175                // it is possible that the save exists but the map doesn't
176                if(!map)
177                    map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty());
178                return map;
179            }
180            else
181            {
182                // if no instanceId via group members or instance saves is found
183                // the instance will be created for the first time
184                NewInstanceId = MapManager::Instance().GenerateInstanceId();
185                return CreateInstance(NewInstanceId, NULL, player->GetDifficulty());
186            }
187        }
188    }
189}
190
191InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty)
192{
193    // load/create a map
194    Guard guard(*this);
195
196    // make sure we have a valid map id
197    const MapEntry* entry = sMapStore.LookupEntry(GetId());
198    if(!entry)
199    {
200        sLog.outError("CreateInstance: no entry for map %d", GetId());
201        assert(false);
202    }
203    const InstanceTemplate * iTemplate = objmgr.GetInstanceTemplate(GetId());
204    if(!iTemplate)
205    {
206        sLog.outError("CreateInstance: no instance template for map %d", GetId());
207        assert(false);
208    }
209
210    // some instances only have one difficulty
211    if(!entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL;
212
213    sLog.outDebug("MapInstanced::CreateInstance: %smap instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal");
214
215    InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty);
216    assert(map->IsDungeon());
217
218    bool load_data = save != NULL;
219    map->CreateInstanceData(load_data);
220
221    m_InstancedMaps[InstanceId] = map;
222    return map;
223}
224
225BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId)
226{
227    // load/create a map
228    Guard guard(*this);
229
230    sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId());
231
232    BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId);
233    assert(map->IsBattleGroundOrArena());
234
235    m_InstancedMaps[InstanceId] = map;
236    return map;
237}
238
239void MapInstanced::DestroyInstance(uint32 InstanceId)
240{
241    InstancedMaps::iterator itr = m_InstancedMaps.find(InstanceId);
242    if(itr != m_InstancedMaps.end())
243        DestroyInstance(itr);
244}
245
246// increments the iterator after erase
247void MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
248{
249    itr->second->UnloadAll(true);
250    // should only unload VMaps if this is the last instance and grid unloading is enabled
251    if(m_InstancedMaps.size() <= 1 && sWorld.getConfig(CONFIG_GRID_UNLOAD))
252    {
253        VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId());
254        // in that case, unload grids of the base map, too
255        // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
256        Map::UnloadAll(true);
257    }
258    // erase map
259    delete itr->second;
260    m_InstancedMaps.erase(itr++);
261}
262
Note: See TracBrowser for help on using the browser.