static bool HandleGoInstanceCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) { return(false); } uint mapId = 0; string mapIdOrScriptNameStr = args.NextString(); if (mapIdOrScriptNameStr.IsNumber()) { mapId = uint.Parse(mapIdOrScriptNameStr); } if (mapId == 0) { List <Tuple <uint, string> > matches = new(); foreach (var pair in Global.ObjectMgr.GetInstanceTemplates()) { string scriptName = Global.ObjectMgr.GetScriptName(pair.Value.ScriptId); if (scriptName.Contains(mapIdOrScriptNameStr)) { matches.Add(Tuple.Create(pair.Key, scriptName)); } } if (matches.Empty()) { handler.SendSysMessage(CypherStrings.CommandNoInstancesMatch); return(false); } if (matches.Count > 1) { handler.SendSysMessage(CypherStrings.CommandMultipleInstancesMatch); return(false); } mapId = matches[0].Item1; } if (mapId == 0) { return(false); } InstanceTemplate temp = Global.ObjectMgr.GetInstanceTemplate(mapId); if (temp == null) { handler.SendSysMessage(CypherStrings.CommandMapNotInstance, mapId); return(false); } string scriptname = Global.ObjectMgr.GetScriptName(temp.ScriptId); Player player = handler.GetSession().GetPlayer(); if (player.IsInFlight()) { player.FinishTaxiFlight(); } else { player.SaveRecallPosition(); } // try going to entrance AreaTriggerStruct exit = Global.ObjectMgr.GetGoBackTrigger(mapId); if (exit == null) { handler.SendSysMessage(CypherStrings.CommandInstanceNoExit, mapId, scriptname); } if (exit != null && player.TeleportTo(exit.target_mapId, exit.target_X, exit.target_Y, exit.target_Z, exit.target_Orientation + MathF.PI)) { handler.SendSysMessage(CypherStrings.CommandWentToInstanceGate, mapId, scriptname); return(true); } // try going to start AreaTriggerStruct entrance = Global.ObjectMgr.GetMapEntranceTrigger(mapId); if (entrance == null) { handler.SendSysMessage(CypherStrings.CommandInstanceNoEntrance, mapId, scriptname); } if (entrance != null && player.TeleportTo(entrance.target_mapId, entrance.target_X, entrance.target_Y, entrance.target_Z, entrance.target_Orientation)) { handler.SendSysMessage(CypherStrings.CommandWentToInstanceStart, mapId, scriptname); return(true); } handler.SendSysMessage(CypherStrings.CommandGoInstanceFailed, mapId, scriptname, exit != null ? exit.target_mapId : -1); return(false); }
void HandleAreaTrigger(AreaTriggerPkt packet) { Player player = GetPlayer(); if (player.IsInFlight()) { Log.outDebug(LogFilter.Network, "HandleAreaTrigger: Player '{0}' (GUID: {1}) in flight, ignore Area Trigger ID:{2}", player.GetName(), player.GetGUID().ToString(), packet.AreaTriggerID); return; } AreaTriggerRecord atEntry = CliDB.AreaTriggerStorage.LookupByKey(packet.AreaTriggerID); if (atEntry == null) { Log.outDebug(LogFilter.Network, "HandleAreaTrigger: Player '{0}' (GUID: {1}) send unknown (by DBC) Area Trigger ID:{2}", player.GetName(), player.GetGUID().ToString(), packet.AreaTriggerID); return; } if (packet.Entered && !player.IsInAreaTriggerRadius(atEntry)) { Log.outDebug(LogFilter.Network, "HandleAreaTrigger: Player '{0}' ({1}) too far, ignore Area Trigger ID: {2}", player.GetName(), player.GetGUID().ToString(), packet.AreaTriggerID); return; } if (player.IsDebugAreaTriggers) { player.SendSysMessage(packet.Entered ? CypherStrings.DebugAreatriggerEntered : CypherStrings.DebugAreatriggerLeft, packet.AreaTriggerID); } if (Global.ScriptMgr.OnAreaTrigger(player, atEntry, packet.Entered)) { return; } if (player.IsAlive()) { List <uint> quests = Global.ObjectMgr.GetQuestsForAreaTrigger(packet.AreaTriggerID); if (quests != null) { foreach (uint questId in quests) { Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questId); if (qInfo != null && player.GetQuestStatus(questId) == QuestStatus.Incomplete) { foreach (QuestObjective obj in qInfo.Objectives) { if (obj.Type == QuestObjectiveType.AreaTrigger && !player.IsQuestObjectiveComplete(obj)) { player.SetQuestObjectiveData(obj, 1); player.SendQuestUpdateAddCreditSimple(obj); break; } } if (player.CanCompleteQuest(questId)) { player.CompleteQuest(questId); } } } } } if (Global.ObjectMgr.IsTavernAreaTrigger(packet.AreaTriggerID)) { // set resting flag we are in the inn player.GetRestMgr().SetRestFlag(RestFlag.Tavern, atEntry.Id); if (Global.WorldMgr.IsFFAPvPRealm()) { player.RemovePvpFlag(UnitPVPStateFlags.FFAPvp); } return; } Battleground bg = player.GetBattleground(); if (bg) { bg.HandleAreaTrigger(player, packet.AreaTriggerID, packet.Entered); } OutdoorPvP pvp = player.GetOutdoorPvP(); if (pvp != null) { if (pvp.HandleAreaTrigger(player, packet.AreaTriggerID, packet.Entered)) { return; } } AreaTriggerStruct at = Global.ObjectMgr.GetAreaTrigger(packet.AreaTriggerID); if (at == null) { return; } bool teleported = false; if (player.GetMapId() != at.target_mapId) { EnterState denyReason = Global.MapMgr.PlayerCannotEnter(at.target_mapId, player, false); if (denyReason != 0) { bool reviveAtTrigger = false; // should we revive the player if he is trying to enter the correct instance? switch (denyReason) { case EnterState.CannotEnterNoEntry: Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' attempted to enter map with id {1} which has no entry", player.GetName(), at.target_mapId); break; 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); break; case EnterState.CannotEnterDifficultyUnavailable: { 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); MapRecord entry = CliDB.MapStorage.LookupByKey(at.target_mapId); if (entry != null) { player.SendTransferAborted(entry.Id, TransferAbortReason.Difficulty, (byte)player.GetDifficultyID(entry)); } } 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: player.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); break; case EnterState.CannotEnterInstanceBindMismatch: { MapRecord entry = CliDB.MapStorage.LookupByKey(at.target_mapId); if (entry != null) { string mapName = entry.MapName[player.GetSession().GetSessionDbcLocale()]; Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' cannot enter instance map '{1}' because their permanent bind is incompatible with their group's", player.GetName(), mapName); // is there a special opcode for this? // @todo figure out how to get player localized difficulty string (e.g. "10 player", "Heroic" etc) player.SendSysMessage(CypherStrings.InstanceBindMismatch, mapName); } reviveAtTrigger = true; } break; case EnterState.CannotEnterTooManyInstances: 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); reviveAtTrigger = true; break; case EnterState.CannotEnterMaxPlayers: player.SendTransferAborted(at.target_mapId, TransferAbortReason.MaxPlayers); reviveAtTrigger = true; break; case EnterState.CannotEnterZoneInCombat: player.SendTransferAborted(at.target_mapId, TransferAbortReason.ZoneInCombat); reviveAtTrigger = true; break; default: break; } if (reviveAtTrigger) // check if the player is touching the areatrigger leading to the map his corpse is on { if (!player.IsAlive() && player.HasCorpse()) { if (player.GetCorpseLocation().GetMapId() == at.target_mapId) { player.ResurrectPlayer(0.5f); player.SpawnCorpseBones(); } } } return; } Group group = player.GetGroup(); if (group) { if (group.IsLFGGroup() && player.GetMap().IsDungeon()) { teleported = player.TeleportToBGEntryPoint(); } } } if (!teleported) { WorldSafeLocsEntry entranceLocation = null; InstanceSave instanceSave = player.GetInstanceSave(at.target_mapId); if (instanceSave != null) { // Check if we can contact the instancescript of the instance for an updated entrance location Map map = Global.MapMgr.FindMap(at.target_mapId, player.GetInstanceSave(at.target_mapId).GetInstanceId()); if (map) { InstanceMap instanceMap = map.ToInstanceMap(); if (instanceMap != null) { InstanceScript instanceScript = instanceMap.GetInstanceScript(); if (instanceScript != null) { entranceLocation = Global.ObjectMgr.GetWorldSafeLoc(instanceScript.GetEntranceLocation()); } } } // Finally check with the instancesave for an entrance location if we did not get a valid one from the instancescript if (entranceLocation == null) { entranceLocation = Global.ObjectMgr.GetWorldSafeLoc(instanceSave.GetEntranceLocation()); } } if (entranceLocation != null) { player.TeleportTo(entranceLocation.Loc, TeleportToOptions.NotLeaveTransport); } else { player.TeleportTo(at.target_mapId, at.target_X, at.target_Y, at.target_Z, at.target_Orientation, TeleportToOptions.NotLeaveTransport); } } }
static bool HandleGoInstanceCommand(CommandHandler handler, string[] labels) { if (labels.Empty()) { return(false); } MultiMap <uint, Tuple <uint, string, string> > matches = new(); foreach (var pair in Global.ObjectMgr.GetInstanceTemplates()) { uint count = 0; string scriptName = Global.ObjectMgr.GetScriptName(pair.Value.ScriptId); string mapName1 = CliDB.MapStorage.LookupByKey(pair.Key).MapName[handler.GetSessionDbcLocale()]; foreach (var label in labels) { if (scriptName.Contains(label)) { ++count; } } if (count != 0) { matches.Add(count, Tuple.Create(pair.Key, mapName1, scriptName)); } } if (matches.Empty()) { handler.SendSysMessage(CypherStrings.CommandNoInstancesMatch); return(false); } // see if we have multiple equal matches left var keyValueList = matches.KeyValueList; uint maxCount = keyValueList.Last().Key; for (var i = keyValueList.Count; i > 0;) { if ((++i) != 0 && keyValueList[i].Key == maxCount) { handler.SendSysMessage(CypherStrings.CommandMultipleInstancesMatch); --i; do { handler.SendSysMessage(CypherStrings.CommandMultipleInstancesEntry, keyValueList[i].Value.Item2, keyValueList[i].Value.Item1, keyValueList[i].Value.Item3); }while (((++i) != 0) && (keyValueList[i].Key == maxCount)); return(false); } } var it = matches.Last(); uint mapId = it.Value.Item1; string mapName = it.Value.Item2; Player player = handler.GetSession().GetPlayer(); if (player.IsInFlight()) { player.FinishTaxiFlight(); } else { player.SaveRecallPosition(); } // try going to entrance AreaTriggerStruct exit = Global.ObjectMgr.GetGoBackTrigger(mapId); if (exit != null) { if (player.TeleportTo(exit.target_mapId, exit.target_X, exit.target_Y, exit.target_Z, exit.target_Orientation + MathF.PI)) { handler.SendSysMessage(CypherStrings.CommandWentToInstanceGate, mapName, mapId); return(true); } else { uint parentMapId = exit.target_mapId; string parentMapName = CliDB.MapStorage.LookupByKey(parentMapId).MapName[handler.GetSessionDbcLocale()]; handler.SendSysMessage(CypherStrings.CommandGoInstanceGateFailed, mapName, mapId, parentMapName, parentMapId); } } else { handler.SendSysMessage(CypherStrings.CommandInstanceNoExit, mapName, mapId); } // try going to start AreaTriggerStruct entrance = Global.ObjectMgr.GetMapEntranceTrigger(mapId); if (entrance != null) { if (player.TeleportTo(entrance.target_mapId, entrance.target_X, entrance.target_Y, entrance.target_Z, entrance.target_Orientation)) { handler.SendSysMessage(CypherStrings.CommandWentToInstanceStart, mapName, mapId); return(true); } else { handler.SendSysMessage(CypherStrings.CommandGoInstanceStartFailed, mapName, mapId); } } else { handler.SendSysMessage(CypherStrings.CommandInstanceNoEntrance, mapName, mapId); } return(false); }