/* * Copyright (C) 2012-2020 CypherCore * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using Framework.Constants; using Framework.Database; using Framework.IO; using Game.DataStorage; using Game.Entities; using Game.Maps; using Game.SupportSystem; using System; using System.Collections.Generic; namespace Game.Chat.Commands { [CommandGroup("go", RBACPermissions.CommandGo)] class GoCommands { [Command("bugticket", RBACPermissions.CommandGo)] static bool HandleGoBugTicketCommand(StringArguments args, CommandHandler handler) { return HandleGoTicketCommand(args, handler); } [Command("complaintticket", RBACPermissions.CommandGo)] static bool HandleGoComplaintTicketCommand(StringArguments args, CommandHandler handler) { return HandleGoTicketCommand(args, handler); } [Command("graveyard", RBACPermissions.CommandGo)] static bool HandleGoGraveyardCommand(StringArguments args, CommandHandler handler) { Player player = handler.GetSession().GetPlayer(); if (args.Empty()) return false; uint graveyardId = args.NextUInt32(); if (graveyardId == 0) return false; WorldSafeLocsEntry gy = Global.ObjectMgr.GetWorldSafeLoc(graveyardId); if (gy == null) { handler.SendSysMessage(CypherStrings.CommandGraveyardnoexist, graveyardId); return false; } if (!GridDefines.IsValidMapCoord(gy.Loc)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, gy.Loc.GetPositionX(), gy.Loc.GetPositionY(), gy.Loc.GetMapId()); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(gy.Loc); return true; } [Command("grid", RBACPermissions.CommandGo)] static bool HandleGoGridCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); if (!float.TryParse(args.NextString(), out float gridX)) return false; if (!float.TryParse(args.NextString(), out float gridY)) return false; if (!uint.TryParse(args.NextString(), out uint mapId)) mapId = player.GetMapId(); // center of grid float x = (gridX - MapConst.CenterGridId + 0.5f) * MapConst.SizeofGrids; float y = (gridY - MapConst.CenterGridId + 0.5f) * MapConst.SizeofGrids; if (!GridDefines.IsValidMapCoord(mapId, x, y)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, mapId); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case Map map = Global.MapMgr.CreateBaseMap(mapId); float z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y)); player.TeleportTo(mapId, x, y, z, player.GetOrientation()); return true; } [Command("instance", RBACPermissions.CommandGo)] 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> 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) { if (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; } else handler.SendSysMessage(CypherStrings.CommandGoInstanceGateFailed, mapId, scriptname, exit.target_mapId); } else handler.SendSysMessage(CypherStrings.CommandInstanceNoExit, mapId, scriptname); // 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, mapId, scriptname); return true; } else handler.SendSysMessage(CypherStrings.CommandGoInstanceStartFailed, mapId, scriptname); } else handler.SendSysMessage(CypherStrings.CommandInstanceNoEntrance, mapId, scriptname); return false; } [Command("offset", RBACPermissions.CommandGo)] static bool HandleGoOffsetCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); string goX = args.NextString(); string goY = args.NextString(); string goZ = args.NextString(); string port = args.NextString(); float x, y, z, o; player.GetPosition(out x, out y, out z, out o); if (!goX.IsEmpty()) x += float.Parse(goX); if (!goY.IsEmpty()) y += float.Parse(goY); if (!goZ.IsEmpty()) z += float.Parse(goZ); if (!port.IsEmpty()) o += float.Parse(port); if (!GridDefines.IsValidMapCoord(x, y, z, o)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, player.GetMapId()); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(player.GetMapId(), x, y, z, o); return true; } [Command("quest", RBACPermissions.CommandGo)] static bool HandleGoQuestCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); string id = handler.ExtractKeyFromLink(args, "Hquest"); if (string.IsNullOrEmpty(id)) return false; if (!uint.TryParse(id, out uint questID) || questID == 0) return false; if (Global.ObjectMgr.GetQuestTemplate(questID) == null) { handler.SendSysMessage(CypherStrings.CommandQuestNotfound, questID); return false; } float x, y, z; uint mapId; var poiData = Global.ObjectMgr.GetQuestPOIData(questID); if (poiData != null) { var data = poiData.Blobs[0]; mapId = (uint)data.MapID; x = data.Points[0].X; y = data.Points[0].Y; } else { handler.SendSysMessage(CypherStrings.CommandQuestNotfound, questID); return false; } if (!GridDefines.IsValidMapCoord(mapId, x, y) || Global.ObjectMgr.IsTransportMap(mapId)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, mapId); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case Map map = Global.MapMgr.CreateBaseMap(mapId); z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y)); player.TeleportTo(mapId, x, y, z, 0.0f); return true; } [Command("suggestionticket", RBACPermissions.CommandGo)] static bool HandleGoSuggestionTicketCommand(StringArguments args, CommandHandler handler) { return HandleGoTicketCommand(args, handler); } [Command("taxinode", RBACPermissions.CommandGo)] static bool HandleGoTaxinodeCommand(StringArguments args, CommandHandler handler) { Player player = handler.GetSession().GetPlayer(); if (args.Empty()) return false; string id = handler.ExtractKeyFromLink(args, "Htaxinode"); if (string.IsNullOrEmpty(id)) return false; if (!uint.TryParse(id, out uint nodeId) || nodeId == 0) return false; TaxiNodesRecord node = CliDB.TaxiNodesStorage.LookupByKey(nodeId); if (node == null) { handler.SendSysMessage(CypherStrings.CommandGotaxinodenotfound, nodeId); return false; } if ((node.Pos.X == 0.0f && node.Pos.Y == 0.0f && node.Pos.Z == 0.0f) || !GridDefines.IsValidMapCoord(node.ContinentID, node.Pos.X, node.Pos.Y, node.Pos.Z)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, node.Pos.X, node.Pos.Y, node.ContinentID); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(node.ContinentID, node.Pos.X, node.Pos.Y, node.Pos.Z, player.GetOrientation()); return true; } [Command("areatrigger", RBACPermissions.CommandGo)] static bool HandleGoAreaTriggerCommand(StringArguments args, CommandHandler handler) { Player player = handler.GetSession().GetPlayer(); if (args.Empty()) return false; uint areaTriggerId = args.NextUInt32(); if (areaTriggerId == 0) return false; AreaTriggerRecord at = CliDB.AreaTriggerStorage.LookupByKey(areaTriggerId); if (at == null) { handler.SendSysMessage(CypherStrings.CommandGoareatrnotfound, areaTriggerId); return false; } if (!GridDefines.IsValidMapCoord(at.ContinentID, at.Pos.X, at.Pos.Y, at.Pos.Z)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, at.Pos.X, at.Pos.Y, at.ContinentID); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(at.ContinentID, at.Pos.X, at.Pos.Y, at.Pos.Z, player.GetOrientation()); return true; } //teleport at coordinates, including Z and orientation [Command("xyz", RBACPermissions.CommandGo)] static bool HandleGoXYZCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); if (!float.TryParse(args.NextString(), out float x)) return false; if (!float.TryParse(args.NextString(), out float y)) return false; string goZ = args.NextString(); if (!uint.TryParse(args.NextString(), out uint mapId)) mapId = player.GetMapId(); if (!float.TryParse(args.NextString(), out float ort)) ort = player.GetOrientation(); float z; if (!goZ.IsEmpty()) { if (!float.TryParse(goZ, out z)) return false; if (!GridDefines.IsValidMapCoord(mapId, x, y, z)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, mapId); return false; } } else { if (!GridDefines.IsValidMapCoord(mapId, x, y)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, mapId); return false; } Map map = Global.MapMgr.CreateBaseMap(mapId); z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y)); } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(mapId, x, y, z, ort); return true; } //teleport at coordinates [Command("zonexy", RBACPermissions.CommandGo)] static bool HandleGoZoneXYCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); if (!float.TryParse(args.NextString(), out float x)) return false; if (!float.TryParse(args.NextString(),out float y)) return false; // prevent accept wrong numeric args if (x == 0.0f || y == 0.0f) return false; string idStr = handler.ExtractKeyFromLink(args, "Harea"); // string or [name] Shift-click form |color|Harea:area_id|h[name]|h|r if (!uint.TryParse(idStr, out uint areaId)) areaId = player.GetZoneId(); AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId); if (x < 0 || x > 100 || y < 0 || y > 100 || areaEntry == null) { handler.SendSysMessage(CypherStrings.InvalidZoneCoord, x, y, areaId); return false; } // update to parent zone if exist (client map show only zones without parents) AreaTableRecord zoneEntry = areaEntry.ParentAreaID != 0 ? CliDB.AreaTableStorage.LookupByKey(areaEntry.ParentAreaID) : areaEntry; Cypher.Assert(zoneEntry != null); Map map = Global.MapMgr.CreateBaseMap(zoneEntry.ContinentID); if (map.Instanceable()) { handler.SendSysMessage(CypherStrings.InvalidZoneMap, areaId, areaEntry.AreaName[handler.GetSessionDbcLocale()], map.GetId(), map.GetMapName()); return false; } x /= 100.0f; y /= 100.0f; Global.DB2Mgr.Zone2MapCoordinates(areaEntry.ParentAreaID != 0 ? areaEntry.ParentAreaID : areaId, ref x, ref y); if (!GridDefines.IsValidMapCoord(zoneEntry.ContinentID, x, y)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, zoneEntry.ContinentID); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case float z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y)); player.TeleportTo(zoneEntry.ContinentID, x, y, z, player.GetOrientation()); return true; } static bool HandleGoTicketCommand(StringArguments args, CommandHandler handler)where T : Ticket { if (args.Empty()) return false; uint ticketId = args.NextUInt32(); if (ticketId == 0) return false; T ticket = Global.SupportMgr.GetTicket(ticketId); if (ticket == null) { handler.SendSysMessage(CypherStrings.CommandTicketnotexist); return true; } Player player = handler.GetSession().GetPlayer(); // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case ticket.TeleportTo(player); return true; } [CommandGroup("creature", RBACPermissions.CommandGo)] class GoCommandCreature { [Command("", RBACPermissions.CommandGo)] static bool HandleGoCreatureSpawnIdCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r string param1 = handler.ExtractKeyFromLink(args, "Hcreature"); if (param1.IsEmpty()) return false; string whereClause = ""; // User wants to teleport to the NPC's template entry if (param1.Equals("id")) { // Get the "creature_template.entry" // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r string id = handler.ExtractKeyFromLink(args, "Hcreature_entry"); if (id.IsEmpty()) return false; if (!uint.TryParse(id, out uint entry)) return false; whereClause += "WHERE id = '" + entry + '\''; } else { ulong.TryParse(param1, out ulong guidLow); if (guidLow != 0) { whereClause += "WHERE guid = '" + guidLow + '\''; } else { // param1 is not a number, must be mob's name whereClause += ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name LIKE '" + args.GetString() + '\''; } } SQLResult result = DB.World.Query("SELECT position_x, position_y, position_z, orientation, map FROM creature {0}", whereClause); if (result.IsEmpty()) { handler.SendSysMessage(CypherStrings.CommandGocreatnotfound); return false; } float x = result.Read(0); float y = result.Read(1); float z = result.Read(2); float o = result.Read(3); uint mapId = result.Read(4); if (result.NextRow()) handler.SendSysMessage(CypherStrings.CommandGocreatmultiple); if (!GridDefines.IsValidMapCoord(mapId, x, y, z, o) || Global.ObjectMgr.IsTransportMap(mapId)) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, x, y, mapId); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(mapId, x, y, z, o); return true; } [Command("id", RBACPermissions.CommandGo)] static bool HandleGoCreatureCIdCommand(StringArguments args, CommandHandler handler) { //temp fix till rework command system. return HandleGoCreatureSpawnIdCommand(args, handler); } } [CommandGroup("gameobject", RBACPermissions.CommandGo)] class GoCommandGameobject { [Command("", RBACPermissions.CommandGo)] static bool HandleGoGameObjectSpawnIdCommand(StringArguments args, CommandHandler handler) { if (args.Empty()) return false; Player player = handler.GetSession().GetPlayer(); // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r string id = handler.ExtractKeyFromLink(args, "Hgameobject"); if (string.IsNullOrEmpty(id)) return false; if (!ulong.TryParse(id, out ulong guidLow) || guidLow == 0) return false; // by DB guid GameObjectData goData = Global.ObjectMgr.GetGameObjectData(guidLow); if (goData == null) { handler.SendSysMessage(CypherStrings.CommandGoobjnotfound); return false; } if (!GridDefines.IsValidMapCoord(goData.spawnPoint) || Global.ObjectMgr.IsTransportMap(goData.spawnPoint.GetMapId())) { handler.SendSysMessage(CypherStrings.InvalidTargetCoord, goData.spawnPoint.GetPositionX(), goData.spawnPoint.GetPositionY(), goData.spawnPoint.GetMapId()); return false; } // stop flight if need if (player.IsInFlight()) player.FinishTaxiFlight(); else player.SaveRecallPosition(); // save only in non-flight case player.TeleportTo(goData.spawnPoint); return true; } [Command("id", RBACPermissions.CommandGo)] static bool HandleGoGameObjectGOIdCommand(StringArguments args, CommandHandler handler) { //temp fix till rework command system. return HandleGoGameObjectSpawnIdCommand(args, handler); } } } }