/* - return the right instance for the object, based on its InstanceId - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player) { if (GetId() != mapId || !player) return NULL; Map* map = NULL; uint32 NewInstanceId = 0; // instanceId of the resulting map if (IsBattlegroundOrArena()) { // instantiate or find existing bg map for player // the instance id is set in battlegroundid NewInstanceId = player->GetBattlegroundId(); if (!NewInstanceId) return NULL; map = _FindMap(NewInstanceId); if (!map) if (Battleground* NewBattleground = player->GetBattleground()) map = CreateBattleground(NewInstanceId, NewBattleground); } else { InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); InstanceSave *pSave = pBind ? pBind->save : NULL; // the player's permanent player bind is taken into consideration first // then the player's group bind and finally the solo bind. if (!pBind || !pBind->perm) { InstanceGroupBind *groupBind = NULL; Group *group = player->GetGroup(); // use the player's difficulty setting (it may not be the same as the group's) if (group) { groupBind = group->GetBoundInstance(this); if (groupBind) pSave = groupBind->save; } } if (pSave) { // solo/perm/group NewInstanceId = pSave->GetInstanceId(); map = _FindMap(NewInstanceId); // it is possible that the save exists but the map doesn't if (!map) map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time NewInstanceId = sMapMgr->GenerateInstanceId(); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); map = CreateInstance(NewInstanceId, NULL, diff); } } return map; }
/// returns a new or existing Instance /// in case of battlegrounds it will only return an existing map, those maps are created by bg-system Map* MapInstanced::CreateInstance(Player * player) { Map* map; uint32 NewInstanceId; // instanceId of the resulting map if(IsBattleGroundOrArena()) { // find existing bg map for player NewInstanceId = player->GetBattleGroundId(); MANGOS_ASSERT(NewInstanceId); map = _FindMap(NewInstanceId); MANGOS_ASSERT(map); } else if (InstanceSave* pSave = player->GetBoundInstanceSaveForSelfOrGroup(GetId())) { // solo/perm/group NewInstanceId = pSave->GetInstanceId(); map = _FindMap(NewInstanceId); // it is possible that the save exists but the map doesn't if (!map) map = CreateInstanceMap(NewInstanceId, pSave->GetDifficulty(), pSave); } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time NewInstanceId = sObjectMgr.GenerateLowGuid(HIGHGUID_INSTANCE); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); map = CreateInstanceMap(NewInstanceId, diff); } return map; }
/* - return the right instance for the object, based on its InstanceId - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, uint32 loginInstanceId) { if (GetId() != mapId || !player) return nullptr; Map* map = nullptr; uint32 newInstanceId = 0; // instanceId of the resulting map if (IsBattlegroundOrArena()) { // instantiate or find existing bg map for player // the instance id is set in battlegroundid newInstanceId = player->GetBattlegroundId(); if (!newInstanceId) return nullptr; map = sMapMgr->FindMap(mapId, newInstanceId); if (!map) { if (Battleground* bg = player->GetBattleground()) map = CreateBattleground(newInstanceId, bg); else { player->TeleportToBGEntryPoint(); return nullptr; } } } else { InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); InstanceSave* pSave = pBind ? pBind->save : nullptr; // priority: // 1. player's permanent bind // 2. player's current instance id if this is at login // 3. group's current bind // 4. player's current bind if (!pBind || !pBind->perm) { if (loginInstanceId) // if the player has a saved instance id on login, we either use this instance or relocate him out (return null) { map = FindInstanceMap(loginInstanceId); return (map && map->GetId() == GetId()) ? map : nullptr; // is this check necessary? or does MapInstanced only find instances of itself? } InstanceGroupBind* groupBind = nullptr; Group* group = player->GetGroup(); // use the player's difficulty setting (it may not be the same as the group's) if (group) { groupBind = group->GetBoundInstance(this); if (groupBind) { // solo saves should be reset when entering a group's instance player->UnbindInstance(GetId(), player->GetDifficulty(IsRaid())); pSave = groupBind->save; } } } if (pSave) { // solo/perm/group newInstanceId = pSave->GetInstanceId(); map = FindInstanceMap(newInstanceId); // it is possible that the save exists but the map doesn't if (!map) map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty()); } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time newInstanceId = sMapMgr->GenerateInstanceId(); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); //Seems it is now possible, but I do not know if it should be allowed //ASSERT(!FindInstanceMap(NewInstanceId)); map = FindInstanceMap(newInstanceId); if (!map) map = CreateInstance(newInstanceId, NULL, diff); } } return map; }
/* - return the right instance for the object, based on its InstanceId - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) { if (GetId() != mapId || !player) return NULL; Map* map = NULL; uint32 newInstanceId = 0; // instanceId of the resulting map. if (IsBattlegroundOrArena()) { // Instantiate or find existing bg map for player. The instance id is set in battlegroundid. newInstanceId = player->GetBattlegroundId(); if (!newInstanceId) return NULL; map = sMapMgr->FindMap(mapId, newInstanceId); if (!map) { if (Battleground* bg = player->GetBattleground()) map = CreateBattleground(newInstanceId, bg); else { player->TeleportToBGEntryPoint(); return NULL; } } } else { InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); InstanceSave* pSave = pBind ? pBind->save : NULL; // The player's permanent player bind is taken into consideration first, then the player's group bind and finally the solo bind. if (!pBind || !pBind->perm) { InstanceGroupBind* groupBind = NULL; Group* group = player->GetGroup(); // Use the player's difficulty setting (it may not be the same as the group's). if (group) { groupBind = group->GetBoundInstance(this); if (groupBind) pSave = groupBind->save; } } if (pSave) { // Solo / permanent / group lock exists. newInstanceId = pSave->GetInstanceId(); map = FindInstanceMap(newInstanceId); if (IsRaid()) { if (player->IsOnDynamicDifficultyMap()) { // Dynamic Difficulty lock: create an instance that matches the difficulty the player changes to. if (player->GetDifficulty(IsRaid()) != pSave->GetDifficulty() || map && map->GetSpawnMode() != player->GetDifficulty(IsRaid())) map = CreateInstance(newInstanceId, pSave, player->GetDifficulty(IsRaid())); } else { // Shared locks: create an instance to match the current player raid difficulty, if the save and player difficulties don't match. // We must check for save difficulty going original diff -> new one, and map spawn mode going new -> original, to make sure all cases are handled. // Although Heroic 10 / 25 Man also theoretically share a cooldown, if you kill a boss on 10 / 25 Heroic you cannot enter any other Heroic size version of the raid (cannot switch). // Heroic size switching is already handled with no checks needed. The map is created on the save difficulty and you can only switch difficulty dynamically, from inside. if (pSave->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL || pSave->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) { // Normal. The map is created on the player difficulty. if (player->GetDifficulty(IsRaid()) != pSave->GetDifficulty() || map && map->GetSpawnMode() != player->GetDifficulty(IsRaid())) map = CreateInstance(newInstanceId, pSave, player->GetDifficulty(IsRaid())); } } } // It is possible that the save exists but the map doesn't, create it. if (!map) map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty()); } else { // If no instanceId via group members or instance saves is found, the instance will be created for the first time. newInstanceId = sMapMgr->GenerateInstanceId(); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); map = FindInstanceMap(newInstanceId); if (!map) map = CreateInstance(newInstanceId, NULL, diff); } } return map; }
/* - return the right instance for the object, based on its InstanceId - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) { if (GetId() != mapId || !player) return NULL; Map* map = NULL; uint32 newInstanceId = 0; // instanceId of the resulting map if (IsBattlegroundOrArena()) { // instantiate or find existing bg map for player // the instance id is set in battlegroundid newInstanceId = player->GetBattlegroundId(); if (!newInstanceId) return NULL; map = sMapMgr->FindMap(mapId, newInstanceId); if (!map) { if (Battleground* bg = player->GetBattleground()) map = CreateBattleground(newInstanceId, bg); else { player->TeleportToBGEntryPoint(); return NULL; } } } else { InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); if (pBind && !pBind->CanBeUsed()) pBind = NULL; InstanceSave* pSave = pBind ? pBind->save : NULL; // the player's permanent player bind is taken into consideration first // then the player's group bind and finally the solo bind. if (!pBind || !pBind->perm) { InstanceGroupBind* groupBind = NULL; Group* group = player->GetGroup(); // use the player's difficulty setting (it may not be the same as the group's) if (group) { groupBind = group->GetBoundInstance(this); if (groupBind) pSave = groupBind->save; } } if (pSave) { // solo/perm/group newInstanceId = pSave->GetInstanceId(); map = FindInstanceMap(newInstanceId); // it is possible that the save exists but the map doesn't if (!map) map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty()); } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time newInstanceId = sMapMgr->GenerateInstanceId(); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); //Seems it is now possible, but I do not know if it should be allowed //ASSERT(!FindInstanceMap(NewInstanceId)); map = FindInstanceMap(newInstanceId); if (!map) map = CreateInstance(newInstanceId, NULL, diff); } } return map; }
/* - return the right instance for the object, based on its InstanceId - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) { if (GetId() != mapId || !player) return NULL; Map* map = NULL; if (IsBattlegroundOrArena()) { // instantiate or find existing bg map for player // the instance id is set in battlegroundid uint32 newInstanceId = player->GetBattlegroundId(); if (!newInstanceId) return NULL; map = sMapMgr->FindMap(mapId, newInstanceId); if (!map) { Battleground* bg = player->GetBattleground(true); if (bg && bg->GetStatus() < STATUS_WAIT_LEAVE) map = CreateBattleground(newInstanceId, bg); else { player->TeleportToEntryPoint(); return NULL; } } } else { Difficulty realdiff = player->GetDifficulty(IsRaid()); uint32 destInstId = sInstanceSaveMgr->PlayerGetDestinationInstanceId(player, GetId(), realdiff); if (destInstId) { InstanceSave* pSave = sInstanceSaveMgr->GetInstanceSave(destInstId); ASSERT(pSave); // pussywizard: must exist map = FindInstanceMap(destInstId); if (!map) map = CreateInstance(destInstId, pSave, realdiff); else if ((mapId == 631 || mapId == 724) && !map->HavePlayers() && map->GetDifficulty() != realdiff) { if (player->isBeingLoaded()) // pussywizard: crashfix (assert(passengers.empty) fail in ~transport), could be added to a transport during loading from db return NULL; if (!map->AllTransportsEmpty()) map->AllTransportsRemovePassengers(); // pussywizard: gameobjects / summons (assert(passengers.empty) fail in ~transport) for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) if (i->first == destInstId) { DestroyInstance(i); map = CreateInstance(destInstId, pSave, realdiff); break; } } } else { uint32 newInstanceId = sMapMgr->GenerateInstanceId(); ASSERT(!FindInstanceMap(newInstanceId)); // pussywizard: instance with new id can't exist Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); map = CreateInstance(newInstanceId, NULL, diff); } } return map; }