/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * 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 2 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 . */ /* ScriptData Name: wp_commandscript %Complete: 100 Comment: All wp related commands Category: commandscripts EndScriptData */ #include "ScriptMgr.h" #include "Chat.h" #include "ChatCommand.h" #include "Creature.h" #include "DatabaseEnv.h" #include "Language.h" #include "Map.h" #include "MotionMaster.h" #include "ObjectMgr.h" #include "PhasingHandler.h" #include "Player.h" #include "RBAC.h" #include "WaypointManager.h" #include "WorldSession.h" #if TRINITY_COMPILER == TRINITY_COMPILER_GNU #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif class wp_commandscript : public CommandScript { public: wp_commandscript() : CommandScript("wp_commandscript") { } std::vector GetCommands() const override { static std::vector wpCommandTable = { { "add", rbac::RBAC_PERM_COMMAND_WP_ADD, false, &HandleWpAddCommand, "" }, { "load", rbac::RBAC_PERM_COMMAND_WP_LOAD, false, &HandleWpLoadCommand, "" }, { "modify", rbac::RBAC_PERM_COMMAND_WP_MODIFY, false, &HandleWpModifyCommand, "" }, { "unload", rbac::RBAC_PERM_COMMAND_WP_UNLOAD, false, &HandleWpUnLoadCommand, "" }, { "reload", rbac::RBAC_PERM_COMMAND_WP_RELOAD, false, &HandleWpReloadCommand, "" }, { "show", rbac::RBAC_PERM_COMMAND_WP_SHOW, false, &HandleWpShowCommand, "" }, }; static std::vector commandTable = { { "wp", rbac::RBAC_PERM_COMMAND_WP, false, nullptr, "", wpCommandTable }, }; return commandTable; } /** * Add a waypoint to a creature. * * The user can either select an npc or provide its GUID. * * The user can even select a visual waypoint - then the new waypoint * is placed *after* the selected one - this makes insertion of new * waypoints possible. * * eg: * .wp add 12345 * -> adds a waypoint to the npc with the GUID 12345 * * .wp add * -> adds a waypoint to the currently selected creature * * * @param args if the user did not provide a GUID, it is NULL * * @return true - command did succeed, false - something went wrong */ static bool HandleWpAddCommand(ChatHandler* handler, char const* args) { // optional char* path_number = nullptr; uint32 pathid = 0; if (*args) path_number = strtok((char*)args, " "); Creature* target = handler->getSelectedCreature(); if (!path_number) { if (target) pathid = target->GetWaypointPathId(); else { WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_PATH_NODE_MAX_PATHID); PreparedQueryResult result = WorldDatabase.Query(stmt); uint32 maxpathid = result->Fetch()->GetInt32(); pathid = maxpathid+1; handler->PSendSysMessage("%s%s|r", "|cff00ff00", "New path started."); } } else pathid = atoi(path_number); // PathId -> ID of the Path // point -> number of the waypoint (if not 0) if (!pathid) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Current creature haven't loaded path."); return true; } WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_PATH_NODE_MAX_NODEID); stmt->setUInt32(0, pathid); PreparedQueryResult result = WorldDatabase.Query(stmt); uint32 nodeId = 0; if (result) nodeId = (*result)[0].GetUInt32() + 1; Player* player = handler->GetPlayer(); //Map* map = player->GetMap(); stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_PATH_NODE); stmt->setUInt32(0, pathid); stmt->setUInt32(1, nodeId); stmt->setFloat(2, player->GetPositionX()); stmt->setFloat(3, player->GetPositionY()); stmt->setFloat(4, player->GetPositionZ()); stmt->setFloat(5, player->GetOrientation()); WorldDatabase.Execute(stmt); if (target) { uint32 displayId = target->GetDisplayId(); WaypointPath const* path = sWaypointMgr->GetPath(pathid); if (!path) return true; sWaypointMgr->DevisualizePath(handler->GetPlayer(), path); sWaypointMgr->ReloadPath(pathid); sWaypointMgr->VisualizePath(handler->GetPlayer(), path, displayId); } handler->PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", nodeId, "|r|cff00ff00 created. "); return true; } // HandleWpAddCommand static bool HandleWpLoadCommand(ChatHandler* handler, char const* args) { if (!*args) return false; // optional char* path_number = nullptr; if (*args) path_number = strtok((char*)args, " "); uint32 pathid = 0; ObjectGuid::LowType guidLow = UI64LIT(0); Creature* target = handler->getSelectedCreature(); // Did player provide a PathId? if (!path_number) return false; if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } if (target->GetEntry() == 1) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?"); handler->SetSentErrorMessage(true); return false; } pathid = atoi(path_number); if (!pathid) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "No valid path number provided."); return true; } guidLow = target->GetSpawnId(); WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID); stmt->setUInt64(0, guidLow); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) { stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ADDON_PATH); stmt->setUInt32(0, pathid); stmt->setUInt64(1, guidLow); } else { stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE_ADDON); stmt->setUInt64(0, guidLow); stmt->setUInt32(1, pathid); } WorldDatabase.Execute(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE); stmt->setUInt8(0, uint8(WAYPOINT_MOTION_TYPE)); stmt->setUInt64(1, guidLow); WorldDatabase.Execute(stmt); target->LoadPath(pathid); target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); target->GetMotionMaster()->Initialize(); target->Say("Path loaded.", LANG_UNIVERSAL); return true; } static bool HandleWpReloadCommand(ChatHandler* handler, char const* args) { if (!*args) return false; uint32 id = atoi(args); if (!id) return false; handler->PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id); sWaypointMgr->ReloadPath(id); return true; } static bool HandleWpUnLoadCommand(ChatHandler* handler, char const* /*args*/) { Creature* target = handler->getSelectedCreature(); WorldDatabasePreparedStatement* stmt = nullptr; if (!target) { handler->PSendSysMessage("%s%s|r", "|cff33ffff", "You must select a target."); return true; } ObjectGuid::LowType guidLow = target->GetSpawnId(); if (!guidLow) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target is not saved to DB."); return true; } CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(guidLow); if (!addon || addon->PathId == 0) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target does not have a loaded path."); return true; } stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON); stmt->setUInt64(0, guidLow); WorldDatabase.Execute(stmt); target->UpdateCurrentWaypointInfo(0, 0); stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE); stmt->setUInt8(0, uint8(IDLE_MOTION_TYPE)); stmt->setUInt64(1, guidLow); WorldDatabase.Execute(stmt); target->LoadPath(0); target->SetDefaultMovementType(IDLE_MOTION_TYPE); target->GetMotionMaster()->MoveTargetedHome(); target->GetMotionMaster()->Initialize(); target->Say("Path unloaded.", LANG_UNIVERSAL); return true; } static bool HandleWpModifyCommand(ChatHandler* handler, char const* args) { if (!*args) return false; // first arg: add del text emote spell waittime move char* show_str = strtok((char*)args, " "); if (!show_str) { return false; } std::string show = show_str; // Did user provide a GUID // or did the user select a creature? // -> variable lowguid is filled with the GUID of the NPC Creature* target = handler->getSelectedCreature(); // User did select a visual waypoint? if (!target || target->GetEntry() != VISUAL_WAYPOINT) { handler->SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); return false; } WaypointPath const* path = sWaypointMgr->GetPathByVisualGUID(target->GetGUID()); if (!path) { handler->PSendSysMessage("|cff00ff00Path does not exist or target has no path|r"); handler->SetSentErrorMessage(true); return false; } WaypointNode const* node = sWaypointMgr->GetNodeByVisualGUID(target->GetGUID()); if (!node) { handler->PSendSysMessage("|cff00ff00Path does not exist or target has no path|r"); handler->SetSentErrorMessage(true); return false; } if (show == "del") { handler->PSendSysMessage("|cff00ff00DEBUG: .wp modify del, PathId: |r|cff00ffff%u|r, NodeId: |r|cff00ffff%u|r", path->Id, node->Id); uint32 displayId = target->GetDisplayId(); sWaypointMgr->DevisualizePath(handler->GetPlayer(), path); sWaypointMgr->DeleteNode(path, node); sWaypointMgr->ReloadPath(path->Id); sWaypointMgr->VisualizePath(handler->GetPlayer(), path, displayId); handler->SendSysMessage(LANG_WAYPOINT_REMOVED); return true; } else if (show == "move") { handler->PSendSysMessage("|cff00ff00DEBUG: .wp move, PathId: |r|cff00ffff%u|r, NodeId: |r|cff00ffff%u|r", path->Id, node->Id); uint32 displayId = target->GetDisplayId(); sWaypointMgr->DevisualizePath(handler->GetPlayer(), path); sWaypointMgr->MoveNode(path, node, handler->GetPlayer()->GetPosition()); sWaypointMgr->ReloadPath(path->Id); sWaypointMgr->VisualizePath(handler->GetPlayer(), path, displayId); handler->PSendSysMessage(LANG_WAYPOINT_CHANGED); return true; } return false; } static bool HandleWpShowCommand(ChatHandler* handler, char const* args) { if (!*args) return false; // first arg: on, off, first, last char* show_str = strtok((char*)args, " "); if (!show_str) return false; // second arg: GUID (optional, if a creature is selected) char* guid_str = strtok((char*)nullptr, " "); uint32 pathid = 0; Creature* target = handler->getSelectedCreature(); // Did player provide a PathID? if (!guid_str) { // No PathID provided // -> Player must have selected a creature if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } pathid = target->GetWaypointPathId(); } else { // PathID provided // Warn if player also selected a creature // -> Creature selection is ignored <- if (target) handler->SendSysMessage(LANG_WAYPOINT_CREATSELECTED); pathid = Trinity::StringTo(guid_str).value_or(0); } std::string show = show_str; //handler->PSendSysMessage("wpshow - show: %s", show); // Show info for the selected waypoint if (show == "info") { if (!target || target->GetEntry() != VISUAL_WAYPOINT) { handler->PSendSysMessage(LANG_WAYPOINT_VP_SELECT); handler->SetSentErrorMessage(true); return false; } WaypointPath const* path = sWaypointMgr->GetPathByVisualGUID(target->GetGUID()); if (!path) { handler->PSendSysMessage("|cff00ff00Path does not exist or target has no path|r"); handler->SetSentErrorMessage(true); return false; } WaypointNode const* node = sWaypointMgr->GetNodeByVisualGUID(target->GetGUID()); if (!node) { handler->PSendSysMessage("|cff00ff00Path does not exist or target has no path|r"); handler->SetSentErrorMessage(true); return false; } handler->SendSysMessage("|cff00ffffDEBUG: .wp show info:|r"); handler->PSendSysMessage("|cff00ff00Show info: Path Id: |r|cff00ffff%u|r", path->Id); handler->PSendSysMessage("|cff00ff00Show info: Path MoveType: |r|cff00ffff%u|r", AsUnderlyingType(path->MoveType)); handler->PSendSysMessage("|cff00ff00Show info: Path Flags: |r|cff00ffff%u|r", path->Flags.AsUnderlyingType()); handler->PSendSysMessage("|cff00ff00Show info: Node Id: |r|cff00ffff%u|r", node->Id); handler->PSendSysMessage("|cff00ff00Show info: Node Delay: |r|cff00ffff%u|r", node->Id); return true; } else if (show == "on") { WaypointPath const* path = sWaypointMgr->GetPath(pathid); if (!path) { handler->PSendSysMessage("|cff00ff00Path does not exist: id %u|r", pathid); return true; } if (path->Nodes.empty()) { handler->PSendSysMessage("|cff00ff00Path does not have any nodes: id %u|r", pathid); return true; } Optional displayId; if (target) displayId = target->GetDisplayId(); sWaypointMgr->VisualizePath(handler->GetPlayer(), path, displayId); ObjectGuid const& guid = sWaypointMgr->GetVisualGUIDByNode(path->Id, path->Nodes.front().Id); if (!guid.IsEmpty()) { handler->SendSysMessage("|cff00ff00Path with id %u is already showing.|r", pathid); return true; } handler->SendSysMessage("|cff00ff00Showing path with id %u.|r", pathid); return true; } else if (show == "off") { WaypointPath const* path = sWaypointMgr->GetPath(pathid); if (!path) { handler->PSendSysMessage("|cff00ff00Path does not exist: id %u|r", pathid); return true; } sWaypointMgr->DevisualizePath(handler->GetPlayer(), path); handler->SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); return true; } handler->PSendSysMessage("|cffff33ffDEBUG: .wp show - no valid command found|r"); return true; } }; void AddSC_wp_commandscript() { new wp_commandscript(); }