Core/Maps: Changed functions checking if map can be entered to use TransferAbortReason directly instead of intermediate Map::EnterState enum
Port From (https://github.com/TrinityCore/TrinityCore/commit/c3e1ff90a5a217691990ea4662bcaa2405b57fde)
This commit is contained in:
@@ -178,24 +178,6 @@ namespace Framework.Constants
|
|||||||
Max
|
Max
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EnterState
|
|
||||||
{
|
|
||||||
CanEnter = 0,
|
|
||||||
CannotEnterAlreadyInMap = 1, // Player Is Already In The Map
|
|
||||||
CannotEnterNoEntry, // No Map Entry Was Found For The Target Map Id
|
|
||||||
CannotEnterUninstancedDungeon, // No Instance Template Was Found For Dungeon Map
|
|
||||||
CannotEnterDifficultyUnavailable, // Requested Instance Difficulty Is Not Available For Target Map
|
|
||||||
CannotEnterNotInRaid, // Target Instance Is A Raid Instance And The Player Is Not In A Raid Group
|
|
||||||
CannotEnterCorpseInDifferentInstance, // Player Is Dead And Their Corpse Is Not In Target Instance
|
|
||||||
CannotEnterInstanceBindMismatch, // Player'S Permanent Instance Save Is Not Compatible With Their Group'S Current Instance Bind
|
|
||||||
CannotEnterAlreadyCompletedEncounter, // Player is locked to encounter that wasn't defeated in the instance yet
|
|
||||||
CannotEnterTooManyInstances, // Player Has Entered Too Many Instances Recently
|
|
||||||
CannotEnterMaxPlayers, // Target Map Already Has The Maximum Number Of Players Allowed
|
|
||||||
CannotEnterZoneInCombat, // A Boss Encounter Is Currently In Progress On The Target Map
|
|
||||||
CannotEnterInstanceShuttingDown,
|
|
||||||
CannotEnterUnspecifiedReason
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ModelIgnoreFlags
|
public enum ModelIgnoreFlags
|
||||||
{
|
{
|
||||||
Nothing = 0x00,
|
Nothing = 0x00,
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ namespace Framework.Constants
|
|||||||
DifficultyNotFound = 22, // Client Writes To Console "Unable To Resolve Requested Difficultyid %U To Actual Difficulty For Map %D"
|
DifficultyNotFound = 22, // Client Writes To Console "Unable To Resolve Requested Difficultyid %U To Actual Difficulty For Map %D"
|
||||||
XrealmZoneDown = 24, // Transfer ed: Cross-Realm Zone Is Down
|
XrealmZoneDown = 24, // Transfer ed: Cross-Realm Zone Is Down
|
||||||
SoloPlayerSwitchDifficulty = 26, // This Instance Is Already In Progress. You May Only Switch Difficulties From Inside The Instance.
|
SoloPlayerSwitchDifficulty = 26, // This Instance Is Already In Progress. You May Only Switch Difficulties From Inside The Instance.
|
||||||
|
NotCrossFactionCompatible = 33, // This instance isn't available for cross-faction groups
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RaidGroupReason
|
public enum RaidGroupReason
|
||||||
|
|||||||
@@ -2925,32 +2925,10 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
else if (map.IsDungeon()) // if map is dungeon...
|
else if (map.IsDungeon()) // if map is dungeon...
|
||||||
{
|
{
|
||||||
EnterState denyReason = ((InstanceMap)map).CannotEnter(this);
|
TransferAbortParams denyReason = map.CannotEnter(this); // ... and can't enter map, then look for entry point.
|
||||||
if (denyReason != 0) // ... and can't enter map, then look for entry point.
|
if (denyReason != null)
|
||||||
{
|
{
|
||||||
switch (denyReason)
|
SendTransferAborted(map.GetId(), denyReason.Reason, denyReason.Arg, denyReason.MapDifficultyXConditionId);
|
||||||
{
|
|
||||||
case EnterState.CannotEnterDifficultyUnavailable:
|
|
||||||
SendTransferAborted(map.GetId(), TransferAbortReason.Difficulty, (byte)map.GetDifficultyID());
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterInstanceBindMismatch:
|
|
||||||
SendSysMessage(CypherStrings.InstanceBindMismatch, map.GetMapName());
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterTooManyInstances:
|
|
||||||
SendTransferAborted(map.GetId(), TransferAbortReason.TooManyInstances);
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterMaxPlayers:
|
|
||||||
SendTransferAborted(map.GetId(), TransferAbortReason.MaxPlayers);
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterZoneInCombat:
|
|
||||||
SendTransferAborted(map.GetId(), TransferAbortReason.ZoneInCombat);
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterInstanceShuttingDown:
|
|
||||||
SendTransferAborted(map.GetId(), TransferAbortReason.NotFound);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
areaTrigger = Global.ObjectMgr.GetGoBackTrigger(mapId);
|
areaTrigger = Global.ObjectMgr.GetGoBackTrigger(mapId);
|
||||||
check = true;
|
check = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ namespace Game.Entities
|
|||||||
SendPacket(instanceInfo);
|
SendPacket(instanceInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Satisfy(AccessRequirement ar, uint target_map, bool report = false)
|
public bool Satisfy(AccessRequirement ar, uint target_map, TransferAbortParams abortParams = null, bool report = false)
|
||||||
{
|
{
|
||||||
if (!IsGameMaster())
|
if (!IsGameMaster())
|
||||||
{
|
{
|
||||||
@@ -380,12 +380,6 @@ namespace Game.Entities
|
|||||||
else if (ar.item2 != 0 && !HasItemCount(ar.item2))
|
else if (ar.item2 != 0 && !HasItemCount(ar.item2))
|
||||||
missingItem = ar.item2;
|
missingItem = ar.item2;
|
||||||
|
|
||||||
if (Global.DisableMgr.IsDisabledFor(DisableType.Map, target_map, this))
|
|
||||||
{
|
|
||||||
GetSession().SendNotification("{0}", Global.ObjectMgr.GetCypherString(CypherStrings.InstanceClosed));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetTeam() == Team.Alliance && ar.quest_A != 0 && !GetQuestRewardStatus(ar.quest_A))
|
if (GetTeam() == Team.Alliance && ar.quest_A != 0 && !GetQuestRewardStatus(ar.quest_A))
|
||||||
missingQuest = ar.quest_A;
|
missingQuest = ar.quest_A;
|
||||||
else if (GetTeam() == Team.Horde && ar.quest_H != 0 && !GetQuestRewardStatus(ar.quest_H))
|
else if (GetTeam() == Team.Horde && ar.quest_H != 0 && !GetQuestRewardStatus(ar.quest_H))
|
||||||
@@ -403,12 +397,22 @@ namespace Game.Entities
|
|||||||
|
|
||||||
if (LevelMin != 0 || LevelMax != 0 || failedMapDifficultyXCondition != 0 || missingItem != 0 || missingQuest != 0 || missingAchievement != 0)
|
if (LevelMin != 0 || LevelMax != 0 || failedMapDifficultyXCondition != 0 || missingItem != 0 || missingQuest != 0 || missingAchievement != 0)
|
||||||
{
|
{
|
||||||
|
if (abortParams != null)
|
||||||
|
abortParams.Reason = TransferAbortReason.Error;
|
||||||
|
|
||||||
if (report)
|
if (report)
|
||||||
{
|
{
|
||||||
if (missingQuest != 0 && !string.IsNullOrEmpty(ar.questFailedText))
|
if (missingQuest != 0 && !string.IsNullOrEmpty(ar.questFailedText))
|
||||||
SendSysMessage("{0}", ar.questFailedText);
|
SendSysMessage("{0}", ar.questFailedText);
|
||||||
else if (mapDiff.Message[Global.WorldMgr.GetDefaultDbcLocale()][0] != '\0' || failedMapDifficultyXCondition != 0) // if (missingAchievement) covered by this case
|
else if (mapDiff.Message[Global.WorldMgr.GetDefaultDbcLocale()][0] != '\0' || failedMapDifficultyXCondition != 0) // if (missingAchievement) covered by this case
|
||||||
SendTransferAborted(target_map, TransferAbortReason.Difficulty, (byte)target_difficulty, failedMapDifficultyXCondition);
|
{
|
||||||
|
if (abortParams != null)
|
||||||
|
{
|
||||||
|
abortParams.Reason = TransferAbortReason.Difficulty;
|
||||||
|
abortParams.Arg = (byte)target_difficulty;
|
||||||
|
abortParams.MapDifficultyXConditionId = failedMapDifficultyXCondition;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (missingItem != 0)
|
else if (missingItem != 0)
|
||||||
GetSession().SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.LevelMinrequiredAndItem), LevelMin, Global.ObjectMgr.GetItemTemplate(missingItem).GetName());
|
GetSession().SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.LevelMinrequiredAndItem), LevelMin, Global.ObjectMgr.GetItemTemplate(missingItem).GetName());
|
||||||
else if (LevelMin != 0)
|
else if (LevelMin != 0)
|
||||||
|
|||||||
@@ -1783,8 +1783,12 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// Check enter rights before map getting to avoid creating instance copy for player
|
// Check enter rights before map getting to avoid creating instance copy for player
|
||||||
// this check not dependent from map instance copy and same for all instance copies of selected map
|
// this check not dependent from map instance copy and same for all instance copies of selected map
|
||||||
if (Map.PlayerCannotEnter(mapid, this, false) != 0)
|
TransferAbortParams abortParams = Map.PlayerCannotEnter(mapid, this);
|
||||||
|
if (abortParams != null)
|
||||||
|
{
|
||||||
|
SendTransferAborted(mapid, abortParams.Reason, abortParams.Arg, abortParams.MapDifficultyXConditionId);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Seamless teleport can happen only if cosmetic maps match
|
// Seamless teleport can happen only if cosmetic maps match
|
||||||
if (!oldmap || (oldmap.GetEntry().CosmeticParentMapID != mapid && GetMapId() != mEntry.CosmeticParentMapID &&
|
if (!oldmap || (oldmap.GetEntry().CosmeticParentMapID != mapid && GetMapId() != mEntry.CosmeticParentMapID &&
|
||||||
@@ -1795,13 +1799,13 @@ namespace Game.Entities
|
|||||||
SetSemaphoreTeleportNear(false);
|
SetSemaphoreTeleportNear(false);
|
||||||
//setup delayed teleport flag
|
//setup delayed teleport flag
|
||||||
SetDelayedTeleportFlag(IsCanDelayTeleport());
|
SetDelayedTeleportFlag(IsCanDelayTeleport());
|
||||||
//if teleport spell is casted in Unit.Update() func
|
//if teleport spell is cast in Unit::Update() func
|
||||||
//then we need to delay it until update process will be finished
|
//then we need to delay it until update process will be finished
|
||||||
if (IsHasDelayedTeleport())
|
if (IsHasDelayedTeleport())
|
||||||
{
|
{
|
||||||
SetSemaphoreTeleportFar(true);
|
SetSemaphoreTeleportFar(true);
|
||||||
//lets save teleport destination for player
|
//lets save teleport destination for player
|
||||||
teleportDest = new WorldLocation(mapid, x, y, z, orientation);
|
teleportDest = new(mapid, x, y, z, orientation);
|
||||||
m_teleport_instanceId = instanceId;
|
m_teleport_instanceId = instanceId;
|
||||||
m_teleport_options = options;
|
m_teleport_options = options;
|
||||||
return true;
|
return true;
|
||||||
@@ -1837,12 +1841,12 @@ namespace Game.Entities
|
|||||||
if (pet)
|
if (pet)
|
||||||
UnsummonPetTemporaryIfAny();
|
UnsummonPetTemporaryIfAny();
|
||||||
|
|
||||||
// remove all areatriggers entities
|
|
||||||
RemoveAllAreaTriggers();
|
|
||||||
|
|
||||||
// remove all dyn objects
|
// remove all dyn objects
|
||||||
RemoveAllDynObjects();
|
RemoveAllDynObjects();
|
||||||
|
|
||||||
|
// remove all areatriggers entities
|
||||||
|
RemoveAllAreaTriggers();
|
||||||
|
|
||||||
// stop spellcasting
|
// stop spellcasting
|
||||||
// not attempt interrupt teleportation spell at caster teleport
|
// not attempt interrupt teleportation spell at caster teleport
|
||||||
if (!options.HasAnyFlag(TeleportToOptions.Spell))
|
if (!options.HasAnyFlag(TeleportToOptions.Spell))
|
||||||
|
|||||||
@@ -274,76 +274,76 @@ namespace Game
|
|||||||
bool teleported = false;
|
bool teleported = false;
|
||||||
if (player.GetMapId() != at.target_mapId)
|
if (player.GetMapId() != at.target_mapId)
|
||||||
{
|
{
|
||||||
EnterState denyReason = Map.PlayerCannotEnter(at.target_mapId, player, false);
|
if (!player.IsAlive())
|
||||||
if (denyReason != 0)
|
|
||||||
{
|
{
|
||||||
bool reviveAtTrigger = false; // should we revive the player if he is trying to enter the correct instance?
|
if (player.HasCorpse())
|
||||||
switch (denyReason)
|
|
||||||
{
|
{
|
||||||
case EnterState.CannotEnterNoEntry:
|
// let enter in ghost mode in instance that connected to inner instance with corpse
|
||||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' attempted to enter map with id {1} which has no entry", player.GetName(), at.target_mapId);
|
uint corpseMap = player.GetCorpseLocation().GetMapId();
|
||||||
break;
|
do
|
||||||
case EnterState.CannotEnterUninstancedDungeon:
|
{
|
||||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' attempted to enter dungeon map {1} but no instance template was found", player.GetName(), at.target_mapId);
|
if (corpseMap == at.target_mapId)
|
||||||
break;
|
break;
|
||||||
case EnterState.CannotEnterDifficultyUnavailable:
|
|
||||||
{
|
InstanceTemplate corpseInstance = Global.ObjectMgr.GetInstanceTemplate(corpseMap);
|
||||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' attempted to enter instance map {1} but the requested difficulty was not found", player.GetName(), at.target_mapId);
|
corpseMap = corpseInstance != null ? corpseInstance.Parent : 0;
|
||||||
MapRecord entry = CliDB.MapStorage.LookupByKey(at.target_mapId);
|
} while (corpseMap != 0);
|
||||||
if (entry != null)
|
|
||||||
player.SendTransferAborted(entry.Id, TransferAbortReason.Difficulty, (byte)player.GetDifficultyID(entry));
|
if (corpseMap == 0)
|
||||||
}
|
{
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterNotInRaid:
|
|
||||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' must be in a raid group to enter map {1}", player.GetName(), at.target_mapId);
|
|
||||||
player.SendRaidGroupOnlyMessage(RaidGroupReason.Only, 0);
|
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterCorpseInDifferentInstance:
|
|
||||||
SendPacket(new AreaTriggerNoCorpse());
|
SendPacket(new AreaTriggerNoCorpse());
|
||||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' does not have a corpse in instance map {1} and cannot enter", player.GetName(), at.target_mapId);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' has corpse in instance {at.target_mapId} and can enter.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.outDebug(LogFilter.Maps, $"Map::CanPlayerEnter - player '{player.GetName()}' is dead but does not have a corpse!");
|
||||||
|
}
|
||||||
|
|
||||||
|
TransferAbortParams denyReason = Map.PlayerCannotEnter(at.target_mapId, player);
|
||||||
|
if (denyReason != null)
|
||||||
|
{
|
||||||
|
switch (denyReason.Reason)
|
||||||
|
{
|
||||||
|
case TransferAbortReason.MapNotAllowed:
|
||||||
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' attempted to enter map with id {at.target_mapId} which has no entry");
|
||||||
break;
|
break;
|
||||||
case EnterState.CannotEnterInstanceBindMismatch:
|
case TransferAbortReason.Difficulty:
|
||||||
player.SendTransferAborted(at.target_mapId, TransferAbortReason.LockedToDifferentInstance);
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' attempted to enter instance map {at.target_mapId} but the requested difficulty was not found");
|
||||||
|
break;
|
||||||
|
case TransferAbortReason.NeedGroup:
|
||||||
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' must be in a raid group to enter map {at.target_mapId}");
|
||||||
|
player.SendRaidGroupOnlyMessage(RaidGroupReason.Only, 0);
|
||||||
|
break;
|
||||||
|
case TransferAbortReason.LockedToDifferentInstance:
|
||||||
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' cannot enter instance map {at.target_mapId} because their permanent bind is incompatible with their group's");
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' cannot enter instance map {at.target_mapId} because their permanent bind is incompatible with their group's");
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
break;
|
||||||
case EnterState.CannotEnterAlreadyCompletedEncounter:
|
case TransferAbortReason.AlreadyCompletedEncounter:
|
||||||
player.SendTransferAborted(at.target_mapId, TransferAbortReason.AlreadyCompletedEncounter);
|
|
||||||
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' cannot enter instance map {at.target_mapId} because their permanent bind is incompatible with their group's");
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' cannot enter instance map {at.target_mapId} because their permanent bind is incompatible with their group's");
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
break;
|
||||||
case EnterState.CannotEnterTooManyInstances:
|
case TransferAbortReason.TooManyInstances:
|
||||||
player.SendTransferAborted(at.target_mapId, TransferAbortReason.TooManyInstances);
|
|
||||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' cannot enter instance map {1} because he has exceeded the maximum number of instances per hour.", player.GetName(), at.target_mapId);
|
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' cannot enter instance map {1} because he has exceeded the maximum number of instances per hour.", player.GetName(), at.target_mapId);
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
break;
|
||||||
case EnterState.CannotEnterMaxPlayers:
|
case TransferAbortReason.MaxPlayers:
|
||||||
player.SendTransferAborted(at.target_mapId, TransferAbortReason.MaxPlayers);
|
case TransferAbortReason.ZoneInCombat:
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
break;
|
||||||
case EnterState.CannotEnterZoneInCombat:
|
case TransferAbortReason.NotFound:
|
||||||
player.SendTransferAborted(at.target_mapId, TransferAbortReason.ZoneInCombat);
|
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
|
||||||
case EnterState.CannotEnterInstanceShuttingDown:
|
|
||||||
player.SendTransferAborted(at.target_mapId, TransferAbortReason.NotFound);
|
|
||||||
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' cannot enter instance map {at.target_mapId} because instance is resetting.");
|
Log.outDebug(LogFilter.Maps, $"MAP: Player '{player.GetName()}' cannot enter instance map {at.target_mapId} because instance is resetting.");
|
||||||
reviveAtTrigger = true;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reviveAtTrigger) // check if the player is touching the areatrigger leading to the map his corpse is on
|
if (denyReason.Reason != TransferAbortReason.NeedGroup)
|
||||||
|
player.SendTransferAborted(at.target_mapId, denyReason.Reason, denyReason.Arg, denyReason.MapDifficultyXConditionId);
|
||||||
|
|
||||||
|
if (!player.IsAlive() && player.HasCorpse())
|
||||||
{
|
{
|
||||||
if (!player.IsAlive() && player.HasCorpse())
|
if (player.GetCorpseLocation().GetMapId() == at.target_mapId)
|
||||||
{
|
{
|
||||||
if (player.GetCorpseLocation().GetMapId() == at.target_mapId)
|
player.ResurrectPlayer(0.5f);
|
||||||
{
|
player.SpawnCorpseBones();
|
||||||
player.ResurrectPlayer(0.5f);
|
|
||||||
player.SpawnCorpseBones();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ namespace Game
|
|||||||
// relocate the player to the teleport destination
|
// relocate the player to the teleport destination
|
||||||
// the CannotEnter checks are done in TeleporTo but conditions may change
|
// the CannotEnter checks are done in TeleporTo but conditions may change
|
||||||
// while the player is in transit, for example the map may get full
|
// while the player is in transit, for example the map may get full
|
||||||
if (newMap == null || newMap.CannotEnter(player) != 0)
|
if (newMap == null || newMap.CannotEnter(player) != null)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Network, $"Map {loc.GetMapId()} could not be created for {(newMap ? newMap.GetMapName() : "Unknown")} ({player.GetGUID()}), porting player to homebind");
|
Log.outError(LogFilter.Network, $"Map {loc.GetMapId()} could not be created for {(newMap ? newMap.GetMapName() : "Unknown")} ({player.GetGUID()}), porting player to homebind");
|
||||||
player.TeleportTo(player.GetHomebind());
|
player.TeleportTo(player.GetHomebind());
|
||||||
|
|||||||
+44
-53
@@ -1654,60 +1654,36 @@ namespace Game.Maps
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EnterState PlayerCannotEnter(uint mapid, Player player, bool loginCheck)
|
public static TransferAbortParams PlayerCannotEnter(uint mapid, Player player)
|
||||||
{
|
{
|
||||||
var entry = CliDB.MapStorage.LookupByKey(mapid);
|
var entry = CliDB.MapStorage.LookupByKey(mapid);
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
return EnterState.CannotEnterNoEntry;
|
return new TransferAbortParams(TransferAbortReason.MapNotAllowed);
|
||||||
|
|
||||||
if (!entry.IsDungeon())
|
if (!entry.IsDungeon())
|
||||||
return EnterState.CanEnter;
|
return TransferAbortParams.None;
|
||||||
|
|
||||||
Difficulty targetDifficulty, requestedDifficulty;
|
Difficulty targetDifficulty = player.GetDifficultyID(entry);
|
||||||
targetDifficulty = requestedDifficulty = player.GetDifficultyID(entry);
|
|
||||||
// Get the highest available difficulty if current setting is higher than the instance allows
|
// Get the highest available difficulty if current setting is higher than the instance allows
|
||||||
var mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(mapid, ref targetDifficulty);
|
var mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(mapid, ref targetDifficulty);
|
||||||
if (mapDiff == null)
|
if (mapDiff == null)
|
||||||
return EnterState.CannotEnterDifficultyUnavailable;
|
return new TransferAbortParams(TransferAbortReason.Difficulty);
|
||||||
|
|
||||||
//Bypass checks for GMs
|
//Bypass checks for GMs
|
||||||
if (player.IsGameMaster())
|
if (player.IsGameMaster())
|
||||||
return EnterState.CanEnter;
|
return TransferAbortParams.None;
|
||||||
|
|
||||||
//Other requirements
|
//Other requirements
|
||||||
if (!player.Satisfy(Global.ObjectMgr.GetAccessRequirement(mapid, targetDifficulty), mapid, true))
|
{
|
||||||
return EnterState.CannotEnterUnspecifiedReason;
|
TransferAbortParams abortParams = new();
|
||||||
|
if (!player.Satisfy(Global.ObjectMgr.GetAccessRequirement(mapid, targetDifficulty), mapid, abortParams, true))
|
||||||
string mapName = entry.MapName[Global.WorldMgr.GetDefaultDbcLocale()];
|
return abortParams;
|
||||||
|
}
|
||||||
|
|
||||||
Group group = player.GetGroup();
|
Group group = player.GetGroup();
|
||||||
if (entry.IsRaid() && (int)entry.Expansion() >= WorldConfig.GetIntValue(WorldCfg.Expansion)) // can only enter in a raid group but raids from old expansion don't need a group
|
if (entry.IsRaid() && (int)entry.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))
|
if ((!group || !group.IsRaidGroup()) && !WorldConfig.GetBoolValue(WorldCfg.InstanceIgnoreRaid))
|
||||||
return EnterState.CannotEnterNotInRaid;
|
return new TransferAbortParams(TransferAbortReason.NeedGroup);
|
||||||
|
|
||||||
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 '{player.GetName()}' has corpse in instance '{mapName}' and can enter.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Log.outDebug(LogFilter.Maps, $"Map::CanPlayerEnter - player '{player.GetName()}' is dead but does not have a corpse!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.Instanceable())
|
if (entry.Instanceable())
|
||||||
{
|
{
|
||||||
@@ -1716,17 +1692,17 @@ namespace Game.Maps
|
|||||||
Map boundMap = Global.MapMgr.FindMap(mapid, instanceIdToCheck);
|
Map boundMap = Global.MapMgr.FindMap(mapid, instanceIdToCheck);
|
||||||
if (boundMap != null)
|
if (boundMap != null)
|
||||||
{
|
{
|
||||||
EnterState denyReason = boundMap.CannotEnter(player);
|
TransferAbortParams denyReason = boundMap.CannotEnter(player);
|
||||||
if (denyReason != 0)
|
if (denyReason != null)
|
||||||
return denyReason;
|
return denyReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
// players are only allowed to enter 10 instances per hour
|
// players are only allowed to enter 10 instances per hour
|
||||||
if (!entry.GetFlags2().HasFlag(MapFlags2.IgnoreInstanceFarmLimit) && entry.IsDungeon() && !player.CheckInstanceCount(instanceIdToCheck) && !player.IsDead())
|
if (!entry.GetFlags2().HasFlag(MapFlags2.IgnoreInstanceFarmLimit) && entry.IsDungeon() && !player.CheckInstanceCount(instanceIdToCheck) && !player.IsDead())
|
||||||
return EnterState.CannotEnterTooManyInstances;
|
return new TransferAbortParams(TransferAbortReason.TooManyInstances);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EnterState.CanEnter;
|
return TransferAbortParams.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetMapName()
|
public string GetMapName()
|
||||||
@@ -3243,7 +3219,7 @@ namespace Game.Maps
|
|||||||
return i_InstanceId;
|
return i_InstanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual EnterState CannotEnter(Player player) { return EnterState.CanEnter; }
|
public virtual TransferAbortParams CannotEnter(Player player) { return TransferAbortParams.None; }
|
||||||
|
|
||||||
public Difficulty GetDifficultyID()
|
public Difficulty GetDifficultyID()
|
||||||
{
|
{
|
||||||
@@ -4789,13 +4765,13 @@ namespace Game.Maps
|
|||||||
m_VisibilityNotifyPeriod = Global.WorldMgr.GetVisibilityNotifyPeriodInInstances();
|
m_VisibilityNotifyPeriod = Global.WorldMgr.GetVisibilityNotifyPeriodInInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override EnterState CannotEnter(Player player)
|
public override TransferAbortParams CannotEnter(Player player)
|
||||||
{
|
{
|
||||||
if (player.GetMap() == this)
|
if (player.GetMap() == this)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "InstanceMap:CannotEnter - player {0} ({1}) already in map {2}, {3}, {4}!", player.GetName(), player.GetGUID().ToString(), GetId(), GetInstanceId(), GetDifficultyID());
|
Log.outError(LogFilter.Maps, "InstanceMap:CannotEnter - player {0} ({1}) already in map {2}, {3}, {4}!", player.GetName(), player.GetGUID().ToString(), GetId(), GetInstanceId(), GetDifficultyID());
|
||||||
Cypher.Assert(false);
|
Cypher.Assert(false);
|
||||||
return EnterState.CannotEnterAlreadyInMap;
|
return new TransferAbortParams(TransferAbortReason.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow GM's to enter
|
// allow GM's to enter
|
||||||
@@ -4807,22 +4783,19 @@ namespace Game.Maps
|
|||||||
if (GetPlayersCountExceptGMs() >= maxPlayers)
|
if (GetPlayersCountExceptGMs() >= maxPlayers)
|
||||||
{
|
{
|
||||||
Log.outInfo(LogFilter.Maps, "MAP: Instance '{0}' of map '{1}' cannot have more than '{2}' players. Player '{3}' rejected", GetInstanceId(), GetMapName(), maxPlayers, player.GetName());
|
Log.outInfo(LogFilter.Maps, "MAP: Instance '{0}' of map '{1}' cannot have more than '{2}' players. Player '{3}' rejected", GetInstanceId(), GetMapName(), maxPlayers, player.GetName());
|
||||||
return EnterState.CannotEnterMaxPlayers;
|
return new TransferAbortParams(TransferAbortReason.MaxPlayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted)
|
// cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted)
|
||||||
if (!player.IsLoading() && IsRaid() && GetInstanceScript() != null && GetInstanceScript().IsEncounterInProgress())
|
if (!player.IsLoading() && IsRaid() && GetInstanceScript() != null && GetInstanceScript().IsEncounterInProgress())
|
||||||
return EnterState.CannotEnterZoneInCombat;
|
return new TransferAbortParams(TransferAbortReason.ZoneInCombat);
|
||||||
|
|
||||||
if (i_instanceLock != null)
|
if (i_instanceLock != null)
|
||||||
{
|
{
|
||||||
// cannot enter if player is permanent saved to a different instance id
|
// cannot enter if player is permanent saved to a different instance id
|
||||||
TransferAbortReason lockError = Global.InstanceLockMgr.CanJoinInstanceLock(player.GetGUID(), new MapDb2Entries(GetEntry(), GetMapDifficulty()), i_instanceLock);
|
TransferAbortReason lockError = Global.InstanceLockMgr.CanJoinInstanceLock(player.GetGUID(), new MapDb2Entries(GetEntry(), GetMapDifficulty()), i_instanceLock);
|
||||||
if (lockError == TransferAbortReason.LockedToDifferentInstance)
|
if (lockError != TransferAbortReason.None)
|
||||||
return EnterState.CannotEnterInstanceBindMismatch;
|
return new TransferAbortParams(lockError);
|
||||||
|
|
||||||
if (lockError == TransferAbortReason.AlreadyCompletedEncounter)
|
|
||||||
return EnterState.CannotEnterAlreadyCompletedEncounter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CannotEnter(player);
|
return base.CannotEnter(player);
|
||||||
@@ -5196,17 +5169,17 @@ namespace Game.Maps
|
|||||||
m_VisibilityNotifyPeriod = IsBattleArena() ? Global.WorldMgr.GetVisibilityNotifyPeriodInArenas() : Global.WorldMgr.GetVisibilityNotifyPeriodInBG();
|
m_VisibilityNotifyPeriod = IsBattleArena() ? Global.WorldMgr.GetVisibilityNotifyPeriodInArenas() : Global.WorldMgr.GetVisibilityNotifyPeriodInBG();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override EnterState CannotEnter(Player player)
|
public override TransferAbortParams CannotEnter(Player player)
|
||||||
{
|
{
|
||||||
if (player.GetMap() == this)
|
if (player.GetMap() == this)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "BGMap:CannotEnter - player {0} is already in map!", player.GetGUID().ToString());
|
Log.outError(LogFilter.Maps, "BGMap:CannotEnter - player {0} is already in map!", player.GetGUID().ToString());
|
||||||
Cypher.Assert(false);
|
Cypher.Assert(false);
|
||||||
return EnterState.CannotEnterAlreadyInMap;
|
return new TransferAbortParams(TransferAbortReason.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.GetBattlegroundId() != GetInstanceId())
|
if (player.GetBattlegroundId() != GetInstanceId())
|
||||||
return EnterState.CannotEnterInstanceBindMismatch;
|
return new TransferAbortParams(TransferAbortReason.LockedToDifferentInstance);
|
||||||
|
|
||||||
return base.CannotEnter(player);
|
return base.CannotEnter(player);
|
||||||
}
|
}
|
||||||
@@ -5244,6 +5217,24 @@ namespace Game.Maps
|
|||||||
Battleground m_bg;
|
Battleground m_bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TransferAbortParams
|
||||||
|
{
|
||||||
|
public static TransferAbortParams None = new TransferAbortParams();
|
||||||
|
|
||||||
|
public TransferAbortReason Reason;
|
||||||
|
public byte Arg;
|
||||||
|
public uint MapDifficultyXConditionId;
|
||||||
|
|
||||||
|
public TransferAbortParams(TransferAbortReason reason = TransferAbortReason.None, byte arg = 0, uint mapDifficultyXConditionId = 0)
|
||||||
|
{
|
||||||
|
Reason = reason;
|
||||||
|
Arg = arg;
|
||||||
|
MapDifficultyXConditionId = mapDifficultyXConditionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFailed() { return Reason != TransferAbortReason.None; }
|
||||||
|
}
|
||||||
|
|
||||||
public struct ScriptAction
|
public struct ScriptAction
|
||||||
{
|
{
|
||||||
public ObjectGuid ownerGUID;
|
public ObjectGuid ownerGUID;
|
||||||
|
|||||||
Reference in New Issue
Block a user