public bool IsDisabledFor(DisableType type, uint entry, Unit unit, byte flags = 0) { Cypher.Assert(type < DisableType.Max); if (!m_DisableMap.ContainsKey(type) || m_DisableMap[type].Empty()) { return(false); } var data = m_DisableMap[type].LookupByKey(entry); if (data == null) // not disabled { return(false); } switch (type) { case DisableType.Spell: { byte spellFlags = data.flags; if (unit != null) { if ((spellFlags.HasAnyFlag(DisableFlags.SpellPlayer) && unit.IsTypeId(TypeId.Player)) || (unit.IsTypeId(TypeId.Unit) && ((unit.IsPet() && spellFlags.HasAnyFlag(DisableFlags.SpellPet)) || spellFlags.HasAnyFlag(DisableFlags.SpellCreature)))) { if (spellFlags.HasAnyFlag(DisableFlags.SpellMap)) { List <uint> mapIds = data.param0; if (mapIds.Contains(unit.GetMapId())) { return(true); // Spell is disabled on current map } if (!spellFlags.HasAnyFlag(DisableFlags.SpellArea)) { return(false); // Spell is disabled on another map, but not this one, return false } // Spell is disabled in an area, but not explicitly our current mapId. Continue processing. } if (spellFlags.HasAnyFlag(DisableFlags.SpellArea)) { var areaIds = data.param1; if (areaIds.Contains(unit.GetAreaId())) { return(true); // Spell is disabled in this area } return(false); // Spell is disabled in another area, but not this one, return false } else { return(true); // Spell disabled for all maps } } return(false); } else if (spellFlags.HasAnyFlag(DisableFlags.SpellDeprecatedSpell)) // call not from spellcast { return(true); } else if (flags.HasAnyFlag(DisableFlags.SpellLOS)) { return(spellFlags.HasAnyFlag(DisableFlags.SpellLOS)); } break; } case DisableType.Map: case DisableType.LFGMap: Player player = unit.ToPlayer(); if (player != null) { MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry); if (mapEntry.IsDungeon()) { byte disabledModes = data.flags; Difficulty targetDifficulty = player.GetDifficultyID(mapEntry); Global.DB2Mgr.GetDownscaledMapDifficultyData(entry, ref targetDifficulty); switch (targetDifficulty) { case Difficulty.Normal: return(disabledModes.HasAnyFlag(DisableFlags.DungeonStatusNormal)); case Difficulty.Heroic: return(disabledModes.HasAnyFlag(DisableFlags.DungeonStatusHeroic)); case Difficulty.Raid10HC: return(disabledModes.HasAnyFlag(DisableFlags.DungeonStatusHeroic10Man)); case Difficulty.Raid25HC: return(disabledModes.HasAnyFlag(DisableFlags.DungeonStatusHeroic25Man)); default: return(false); } } else if (mapEntry.InstanceType == MapTypes.Common) { return(true); } } return(false); case DisableType.Quest: if (unit == null) { return(true); } Player player1 = unit.ToPlayer(); if (player1 != null) { if (player1.IsGameMaster()) { return(false); } } return(true); case DisableType.Battleground: case DisableType.OutdoorPVP: case DisableType.Criteria: case DisableType.MMAP: return(true); case DisableType.VMAP: return(flags.HasAnyFlag(data.flags)); } return(false); }
public void LoadGroups() { { uint oldMSTime = Time.GetMSTime(); // Delete all groups whose leader does not exist DB.Characters.Execute("DELETE FROM groups WHERE leaderGuid NOT IN (SELECT guid FROM characters)"); // Delete all groups with less than 2 members DB.Characters.Execute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); // 0 1 2 3 4 5 6 7 8 9 SQLResult result = DB.Characters.Query("SELECT g.leaderGuid, g.lootMethod, g.looterGuid, g.lootThreshold, g.icon1, g.icon2, g.icon3, g.icon4, g.icon5, g.icon6" + // 10 11 12 13 14 15 16 17 18 19 ", g.icon7, g.icon8, g.groupType, g.difficulty, g.raiddifficulty, g.legacyRaidDifficulty, g.masterLooterGuid, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 group definitions. DB table `groups` is empty!"); return; } uint count = 0; do { Group group = new Group(); group.LoadGroupFromDB(result.GetFields()); AddGroup(group); // Get the ID used for storing the group in the database and register it in the pool. uint storageId = group.GetDbStoreId(); RegisterGroupDbStoreId(storageId, group); // Increase the next available storage ID if (storageId == NextGroupDbStoreId) { NextGroupDbStoreId++; } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} group definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } Log.outInfo(LogFilter.ServerLoading, "Loading Group members..."); { uint oldMSTime = Time.GetMSTime(); // Delete all rows from group_member or group_instance with no group DB.Characters.Execute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); DB.Characters.Execute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); // Delete all members that does not exist DB.Characters.Execute("DELETE FROM group_member WHERE memberGuid NOT IN (SELECT guid FROM characters)"); // 0 1 2 3 4 SQLResult result = DB.Characters.Query("SELECT guid, memberGuid, memberFlags, subgroup, roles FROM group_member ORDER BY guid"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 group members. DB table `group_member` is empty!"); return; } uint count = 0; do { Group group = GetGroupByDbStoreId(result.Read <uint>(0)); if (group) { group.LoadMemberFromDB(result.Read <uint>(1), result.Read <byte>(2), result.Read <byte>(3), (LfgRoles)result.Read <byte>(4)); } else { Log.outError(LogFilter.Server, "GroupMgr:LoadGroups: Consistency failed, can't find group (storage id: {0})", result.Read <uint>(0)); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} group members in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } Log.outInfo(LogFilter.ServerLoading, "Loading Group instance saves..."); { uint oldMSTime = Time.GetMSTime(); // 0 1 2 3 4 5 6 7 SQLResult result = DB.Characters.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, i.entranceId, COUNT(g.guid) " + "FROM group_instance gi INNER JOIN instance i ON gi.instance = i.id " + "LEFT JOIN character_instance ci LEFT JOIN groups g ON g.leaderGuid = ci.guid ON ci.instance = gi.instance AND ci.permanent = 1 GROUP BY gi.instance ORDER BY gi.guid"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 group-instance saves. DB table `group_instance` is empty!"); return; } uint count = 0; do { Group group = GetGroupByDbStoreId(result.Read <uint>(0)); // group will never be NULL (we have run consistency sql's before loading) MapRecord mapEntry = CliDB.MapStorage.LookupByKey(result.Read <ushort>(1)); if (mapEntry == null || !mapEntry.IsDungeon()) { Log.outError(LogFilter.Sql, "Incorrect entry in group_instance table : no dungeon map {0}", result.Read <ushort>(1)); continue; } uint diff = result.Read <byte>(4); DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(diff); if (difficultyEntry == null || difficultyEntry.InstanceType != mapEntry.InstanceType) { continue; } InstanceSave save = Global.InstanceSaveMgr.AddInstanceSave(mapEntry.Id, result.Read <uint>(2), (Difficulty)diff, result.Read <uint>(5), result.Read <uint>(6), result.Read <ulong>(7) != 0, true); group.BindToInstance(save, result.Read <bool>(3), true); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} group-instance saves in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } }
void HandleMoveWorldportAck() { // ignore unexpected far teleports if (!GetPlayer().IsBeingTeleportedFar()) { return; } bool seamlessTeleport = GetPlayer().IsBeingTeleportedSeamlessly(); GetPlayer().SetSemaphoreTeleportFar(false); // get the teleport destination WorldLocation loc = GetPlayer().GetTeleportDest(); // possible errors in the coordinate validity check if (!GridDefines.IsValidMapCoord(loc)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapRecord mapEntry = CliDB.MapStorage.LookupByKey(loc.GetMapId()); InstanceTemplate mInstance = Global.ObjectMgr.GetInstanceTemplate(loc.GetMapId()); // reset instance validity, except if going to an instance inside an instance if (!GetPlayer().m_InstanceValid&& mInstance == null) { GetPlayer().m_InstanceValid = true; } Map oldMap = GetPlayer().GetMap(); Map newMap = Global.MapMgr.CreateMap(loc.GetMapId(), GetPlayer()); if (GetPlayer().IsInWorld) { Log.outError(LogFilter.Network, "Player (Name {0}) is still in world when teleported from map {1} to new map {2}", GetPlayer().GetName(), oldMap.GetId(), loc.GetMapId()); oldMap.RemovePlayerFromMap(GetPlayer(), false); } // relocate the player to the teleport destination // the CannotEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if (newMap == null || newMap.CannotEnter(GetPlayer()) != 0) { Log.outError(LogFilter.Network, "Map {0} could not be created for {1} ({2}), porting player to homebind", loc.GetMapId(), newMap ? newMap.GetMapName() : "Unknown", GetPlayer().GetGUID().ToString()); GetPlayer().TeleportTo(GetPlayer().GetHomebind()); return; } float z = loc.GetPositionZ(); if (GetPlayer().HasUnitMovementFlag(MovementFlag.Hover)) { z += GetPlayer().m_unitData.HoverHeight; } GetPlayer().Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); GetPlayer().SetFallInformation(0, GetPlayer().GetPositionZ()); GetPlayer().ResetMap(); GetPlayer().SetMap(newMap); ResumeToken resumeToken = new ResumeToken(); resumeToken.SequenceIndex = _player.m_movementCounter; resumeToken.Reason = seamlessTeleport ? 2 : 1u; SendPacket(resumeToken); if (!seamlessTeleport) { GetPlayer().SendInitialPacketsBeforeAddToMap(); } if (!GetPlayer().GetMap().AddPlayerToMap(GetPlayer(), !seamlessTeleport)) { Log.outError(LogFilter.Network, "WORLD: failed to teleport player {0} ({1}) to map {2} ({3}) because of unknown reason!", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), loc.GetMapId(), newMap ? newMap.GetMapName() : "Unknown"); GetPlayer().ResetMap(); GetPlayer().SetMap(oldMap); GetPlayer().TeleportTo(GetPlayer().GetHomebind()); return; } // Battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if (GetPlayer().InBattleground()) { // cleanup setting if outdated if (!mapEntry.IsBattlegroundOrArena()) { // We're not in BG GetPlayer().SetBattlegroundId(0, BattlegroundTypeId.None); // reset destination bg team GetPlayer().SetBGTeam(0); } // join to bg case else { Battleground bg = GetPlayer().GetBattleground(); if (bg) { if (GetPlayer().IsInvitedForBattlegroundInstance(GetPlayer().GetBattlegroundId())) { bg.AddPlayer(GetPlayer()); } } } } if (!seamlessTeleport) { GetPlayer().SendInitialPacketsAfterAddToMap(); } else { GetPlayer().UpdateVisibilityForPlayer(); Garrison garrison = GetPlayer().GetGarrison(); if (garrison != null) { garrison.SendRemoteInfo(); } } // flight fast teleport case if (GetPlayer().GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Flight) { if (!GetPlayer().InBattleground()) { if (!seamlessTeleport) { // short preparations to continue flight FlightPathMovementGenerator flight = (FlightPathMovementGenerator)GetPlayer().GetMotionMaster().Top(); flight.Initialize(GetPlayer()); } return; } // Battlegroundstate prepare, stop flight GetPlayer().GetMotionMaster().MovementExpired(); GetPlayer().CleanupAfterTaxiFlight(); } // resurrect character at enter into instance where his corpse exist after add to map if (mapEntry.IsDungeon() && !GetPlayer().IsAlive()) { if (GetPlayer().GetCorpseLocation().GetMapId() == mapEntry.Id) { GetPlayer().ResurrectPlayer(0.5f, false); GetPlayer().SpawnCorpseBones(); } } bool allowMount = !mapEntry.IsDungeon() || mapEntry.IsBattlegroundOrArena(); if (mInstance != null) { // check if this instance has a reset time and send it to player if so Difficulty diff = newMap.GetDifficultyID(); MapDifficultyRecord mapDiff = Global.DB2Mgr.GetMapDifficultyData(mapEntry.Id, diff); if (mapDiff != null) { if (mapDiff.GetRaidDuration() != 0) { long timeReset = Global.InstanceSaveMgr.GetResetTimeFor(mapEntry.Id, diff); if (timeReset != 0) { uint timeleft = (uint)(timeReset - Time.UnixTime); GetPlayer().SendInstanceResetWarning(mapEntry.Id, diff, timeleft, true); } } } // check if instance is valid if (!GetPlayer().CheckInstanceValidity(false)) { GetPlayer().m_InstanceValid = false; } // instance mounting is handled in InstanceTemplate allowMount = mInstance.AllowMount; } // mount allow check if (!allowMount) { GetPlayer().RemoveAurasByType(AuraType.Mounted); } // update zone immediately, otherwise leave channel will cause crash in mtmap uint newzone, newarea; GetPlayer().GetZoneAndAreaId(out newzone, out newarea); GetPlayer().UpdateZone(newzone, newarea); // honorless target if (GetPlayer().pvpInfo.IsHostile) { GetPlayer().CastSpell(GetPlayer(), 2479, true); } // in friendly area else if (GetPlayer().IsPvP() && !GetPlayer().HasPlayerFlag(PlayerFlags.InPVP)) { GetPlayer().UpdatePvP(false, false); } // resummon pet GetPlayer().ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer().ProcessDelayedOperations(); }
public EnterState PlayerCannotEnter(uint mapid, Player player, bool loginCheck = false) { MapRecord entry = CliDB.MapStorage.LookupByKey(mapid); if (entry == null) { return(EnterState.CannotEnterNoEntry); } if (!entry.IsDungeon()) { return(EnterState.CanEnter); } InstanceTemplate instance = Global.ObjectMgr.GetInstanceTemplate(mapid); if (instance == null) { return(EnterState.CannotEnterUninstancedDungeon); } Difficulty targetDifficulty = player.GetDifficultyID(entry); // Get the highest available difficulty if current setting is higher than the instance allows MapDifficultyRecord mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(entry.Id, ref targetDifficulty); if (mapDiff == null) { return(EnterState.CannotEnterDifficultyUnavailable); } //Bypass checks for GMs if (player.IsGameMaster()) { return(EnterState.CanEnter); } string mapName = entry.MapName[Global.WorldMgr.GetDefaultDbcLocale()]; Group group = player.GetGroup(); if (entry.IsRaid() && entry.Expansion() >= (Expansion)WorldConfig.GetIntValue(WorldCfg.Expansion)) // can only enter in a raid group but raids from old expansion don't need a group { if ((!group || !group.isRaidGroup()) && WorldConfig.GetBoolValue(WorldCfg.InstanceIgnoreRaid)) { return(EnterState.CannotEnterNotInRaid); } } if (!player.IsAlive()) { if (player.HasCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint corpseMap = player.GetCorpseLocation().GetMapId(); do { if (corpseMap == mapid) { break; } InstanceTemplate corpseInstance = Global.ObjectMgr.GetInstanceTemplate(corpseMap); corpseMap = corpseInstance != null ? corpseInstance.Parent : 0; } while (corpseMap != 0); if (corpseMap == 0) { return(EnterState.CannotEnterCorpseInDifferentInstance); } Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' has corpse in instance '{1}' and can enter.", player.GetName(), mapName); } else { Log.outDebug(LogFilter.Maps, "Map.CanPlayerEnter - player '{0}' is dead but does not have a corpse!", player.GetName()); } } //Get instance where player's group is bound & its map if (!loginCheck && group) { InstanceBind boundInstance = group.GetBoundInstance(entry); if (boundInstance != null && boundInstance.save != null) { Map boundMap = FindMap(mapid, boundInstance.save.GetInstanceId()); if (boundMap != null) { EnterState denyReason = boundMap.CannotEnter(player); if (denyReason != 0) { return(denyReason); } } } } // players are only allowed to enter 10 instances per hour if (entry.IsDungeon() && (player.GetGroup() == null || (player.GetGroup() != null && !player.GetGroup().isLFGGroup()))) { uint instaceIdToCheck = 0; InstanceSave save = player.GetInstanceSave(mapid); if (save != null) { instaceIdToCheck = save.GetInstanceId(); } // instanceId can never be 0 - will not be found if (!player.CheckInstanceCount(instaceIdToCheck) && !player.IsDead()) { return(EnterState.CannotEnterTooManyInstances); } } //Other requirements if (player.Satisfy(Global.ObjectMgr.GetAccessRequirement(mapid, targetDifficulty), mapid, true)) { return(EnterState.CanEnter); } else { return(EnterState.CannotEnterUnspecifiedReason); } }