/*
* 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"
using namespace Trinity::ChatCommands;
class wp_commandscript : public CommandScript
{
public:
wp_commandscript() : CommandScript("wp_commandscript") { }
ChatCommandTable GetCommands() const override
{
static ChatCommandTable wpCommandTable =
{
{ "add", HandleWpAddCommand, rbac::RBAC_PERM_COMMAND_WP_ADD, Console::No },
{ "load", HandleWpLoadCommand, rbac::RBAC_PERM_COMMAND_WP_LOAD, Console::No },
{ "modify", HandleWpModifyCommand, rbac::RBAC_PERM_COMMAND_WP_MODIFY, Console::No },
{ "unload", HandleWpUnLoadCommand, rbac::RBAC_PERM_COMMAND_WP_UNLOAD, Console::No },
{ "reload", HandleWpReloadCommand, rbac::RBAC_PERM_COMMAND_WP_RELOAD, Console::No },
{ "show", HandleWpShowCommand, rbac::RBAC_PERM_COMMAND_WP_SHOW, Console::No },
};
static ChatCommandTable commandTable =
{
{ "wp", 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 pathid (optional)
*
* @return true - command did succeed, false - something went wrong
*/
static bool HandleWpAddCommand(ChatHandler* handler, Optional pathid)
{
Creature* target = handler->getSelectedCreature();
if (!pathid)
{
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.");
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_PATH);
stmt->setUInt32(0, *pathid); // PathId
stmt->setUInt8(1, AsUnderlyingType(WaypointMoveType::Walk)); // MoveType
stmt->setUInt8(2, AsUnderlyingType(WaypointPathFlags::None)); // Flags
stmt->setNull(3); // Velocity
stmt->setString(4, "Created by .wp add"sv); // Comment
WorldDatabase.Execute(stmt);
}
}
// PathId -> ID of the Path
// point -> number of the waypoint (if not 0)
if (!pathid || pathid == 0u)
{
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();
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, uint32 pathid)
{
Creature* target = handler->getSelectedCreature();
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;
}
if (!pathid)
{
handler->PSendSysMessage("%s%s|r", "|cffff33ff", "No valid path number provided.");
return true;
}
ObjectGuid::LowType 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, uint32 id)
{
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)
{
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, Variant show)
{
// 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.holds_alternative())
{
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.holds_alternative())
{
handler->PSendSysMessage("|cff00ff00DEBUG: .wp modify 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, Variant show, Optional pathid)
{
Creature* target = handler->getSelectedCreature();
// Did player provide a PathID?
if (!pathid)
{
// 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);
}
// Show info for the selected waypoint
if (show.holds_alternative())
{
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.holds_alternative())
{
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.holds_alternative())
{
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();
}