/*
* This file is part of the AzerothCore 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 Affero 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 Affero 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 .
*/
#include "Chat.h"
#include "CommandScript.h"
#include "Player.h"
#include "WaypointMgr.h"
#if AC_COMPILER == AC_COMPILER_GNU
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
using namespace Acore::ChatCommands;
class wp_commandscript : public CommandScript
{
public:
wp_commandscript() : CommandScript("wp_commandscript") { }
ChatCommandTable GetCommands() const override
{
static ChatCommandTable wpCommandTable =
{
{ "add", HandleWpAddCommand, SEC_ADMINISTRATOR, Console::No },
{ "event", HandleWpEventCommand, SEC_ADMINISTRATOR, Console::No },
{ "load", HandleWpLoadCommand, SEC_ADMINISTRATOR, Console::No },
{ "modify", HandleWpModifyCommand, SEC_ADMINISTRATOR, Console::No },
{ "unload", HandleWpUnLoadCommand, SEC_ADMINISTRATOR, Console::No },
{ "reload", HandleWpReloadCommand, SEC_ADMINISTRATOR, Console::No },
{ "show", HandleWpShowCommand, SEC_ADMINISTRATOR, 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 args if the user did not provide a GUID, it is nullptr
*
* @return true - command did succeed, false - something went wrong
*/
static bool HandleWpAddCommand(ChatHandler* handler, const char* args)
{
// optional
char* path_number = nullptr;
uint32 pathid = 0;
if (*args)
path_number = strtok((char*)args, " ");
uint32 point = 0;
Creature* target = handler->getSelectedCreature();
if (!path_number)
{
if (target)
pathid = target->GetWaypointPath();
else
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_MAX_ID);
PreparedQueryResult result = WorldDatabase.Query(stmt);
uint32 maxpathid = result->Fetch()->Get();
pathid = maxpathid + 1;
handler->PSendSysMessage("{}{}|r", "|cff00ff00", "New path started.");
}
}
else
pathid = atoi(path_number);
// path_id -> ID of the Path
// point -> number of the waypoint (if not 0)
if (!pathid)
{
handler->PSendSysMessage("{}{}|r", "|cffff33ff", "Current creature haven't loaded path.");
return true;
}
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_MAX_POINT);
stmt->SetData(0, pathid);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (result)
point = (*result)[0].Get();
Player* player = handler->GetSession()->GetPlayer();
//Map* map = player->GetMap();
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_DATA);
stmt->SetData(0, pathid);
stmt->SetData(1, point + 1);
stmt->SetData(2, player->GetPositionX());
stmt->SetData(3, player->GetPositionY());
stmt->SetData(4, player->GetPositionZ());
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("{}{}{}{}{}{}|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point + 1, "|r|cff00ff00 created. ");
return true;
} // HandleWpAddCommand
static bool HandleWpLoadCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
// optional
char* path_number = nullptr;
if (*args)
path_number = strtok((char*)args, " ");
uint32 pathid = 0;
ObjectGuid::LowType guidLow = 0;
Creature* target = handler->getSelectedCreature();
// Did player provide a path_id?
if (!path_number)
return false;
if (!target)
{
handler->SendErrorMessage(LANG_SELECT_CREATURE);
return false;
}
if (target->GetEntry() == 1)
{
handler->SendErrorMessage("{}{}|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?");
return false;
}
pathid = atoi(path_number);
if (!pathid)
{
handler->PSendSysMessage("{}{}|r", "|cffff33ff", "No valid path number provided.");
return true;
}
guidLow = target->GetSpawnId();
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID);
stmt->SetData(0, guidLow);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (result)
{
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ADDON_PATH);
stmt->SetData(0, pathid);
stmt->SetData(1, guidLow);
}
else
{
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE_ADDON);
stmt->SetData(0, guidLow);
stmt->SetData(1, pathid);
}
WorldDatabase.Execute(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
stmt->SetData(0, uint8(WAYPOINT_MOTION_TYPE));
stmt->SetData(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, const char* args)
{
if (!*args)
return false;
uint32 id = atoi(args);
if (!id)
return false;
handler->PSendSysMessage("{}{}|r|cff00ffff{}|r", "|cff00ff00", "Loading Path: ", id);
sWaypointMgr->ReloadPath(id);
return true;
}
static bool HandleWpUnLoadCommand(ChatHandler* handler, const char* /*args*/)
{
Creature* target = handler->getSelectedCreature();
if (!target)
{
handler->PSendSysMessage("{}{}|r", "|cff33ffff", "You must select target.");
return true;
}
uint32 guildLow = target->GetSpawnId();
if (target->GetCreatureAddon())
{
if (target->GetCreatureAddon()->path_id != 0)
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
stmt->SetData(0, guildLow);
WorldDatabase.Execute(stmt);
target->UpdateWaypointID(0);
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
stmt->SetData(0, uint8(IDLE_MOTION_TYPE));
stmt->SetData(1, guildLow);
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;
}
handler->PSendSysMessage("{}{}|r", "|cffff33ff", "Target have no loaded path.");
}
return true;
}
static bool HandleWpEventCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* show_str = strtok((char*)args, " ");
std::string show = show_str;
// Check
if ((show != "add") && (show != "mod") && (show != "del") && (show != "listid"))
return false;
char* arg_id = strtok(nullptr, " ");
uint32 id = 0;
if (show == "add")
{
if (arg_id)
id = atoi(arg_id);
if (id)
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID);
stmt->SetData(0, id);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_SCRIPT);
stmt->SetData(0, id);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("{}{}{}|r", "|cff00ff00", "Wp Event: New waypoint event added: ", id);
}
else
handler->PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: {}|r", id);
}
else
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID);
PreparedQueryResult result = WorldDatabase.Query(stmt);
id = result->Fetch()->Get();
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_SCRIPT);
stmt->SetData(0, id + 1);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("{}{}{}|r", "|cff00ff00", "Wp Event: New waypoint event added: |r|cff00ffff", id + 1);
}
return true;
}
if (show == "listid")
{
if (!arg_id)
{
handler->PSendSysMessage("{}{}|r", "|cff33ffff", "Wp Event: You must provide waypoint script id.");
return true;
}
id = atoi(arg_id);
uint32 a2, a3, a4, a5, a6;
float a8, a9, a10, a11;
char const* a7;
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID);
stmt->SetData(0, id);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->PSendSysMessage("{}{}{}|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id);
return true;
}
Field* fields;
do
{
fields = result->Fetch();
a2 = fields[0].Get();
a3 = fields[1].Get();
a4 = fields[2].Get();
a5 = fields[3].Get();
a6 = fields[4].Get();
a7 = fields[5].Get().c_str();
a8 = fields[6].Get();
a9 = fields[7].Get();
a10 = fields[8].Get();
a11 = fields[9].Get();
handler->PSendSysMessage("|cffff33ffid:|r|cff00ffff {}|r|cff00ff00, guid: |r|cff00ffff{}|r|cff00ff00, delay: |r|cff00ffff{}|r|cff00ff00, command: |r|cff00ffff{}|r|cff00ff00, datalong: |r|cff00ffff{}|r|cff00ff00, datalong2: |r|cff00ffff{}|r|cff00ff00, datatext: |r|cff00ffff{}|r|cff00ff00, posx: |r|cff00ffff{}|r|cff00ff00, posy: |r|cff00ffff{}|r|cff00ff00, posz: |r|cff00ffff{}|r|cff00ff00, orientation: |r|cff00ffff{}|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
} while (result->NextRow());
}
if (show == "del")
{
if (!arg_id)
{
handler->SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r");
return true;
}
id = atoi(arg_id);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID);
stmt->SetData(0, id);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (result)
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_SCRIPT);
stmt->SetData(0, id);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("{}{}{}|r", "|cff00ff00", "Wp Event: Waypoint script removed: ", id);
}
else
handler->PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: {}|r", id);
return true;
}
if (show == "mod")
{
if (!arg_id)
{
handler->SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r");
return true;
}
id = atoi(arg_id);
if (!id)
{
handler->SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r");
return true;
}
char* arg_2 = strtok(nullptr, " ");
if (!arg_2)
{
handler->SendSysMessage("|cffff33ffERROR: No argument present.|r");
return true;
}
std::string arg_string = arg_2;
if ((arg_string != "setid") && (arg_string != "delay") && (arg_string != "command")
&& (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx")
&& (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation"))
{
handler->SendSysMessage("|cffff33ffERROR: No valid argument present.|r");
return true;
}
char* arg_3;
std::string arg_str_2 = arg_2;
arg_3 = strtok(nullptr, " ");
if (!arg_3)
{
handler->SendSysMessage("|cffff33ffERROR: No additional argument present.|r");
return true;
}
if (arg_str_2 == "setid")
{
uint32 newid = atoi(arg_3);
handler->PSendSysMessage("{}{}|r|cff00ffff{}|r|cff00ff00{}|r|cff00ffff{}|r", "|cff00ff00", "Wp Event: Wypoint scipt guid: ", newid, " id changed: ", id);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_ID);
stmt->SetData(0, newid);
stmt->SetData(1, id);
WorldDatabase.Execute(stmt);
return true;
}
else
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID);
stmt->SetData(0, id);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r");
return true;
}
if (arg_str_2 == "posx")
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_X);
stmt->SetData(0, float(atof(arg_3)));
stmt->SetData(1, id);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff {}|r|cff00ff00 position_x updated.|r", id);
return true;
}
else if (arg_str_2 == "posy")
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_Y);
stmt->SetData(0, float(atof(arg_3)));
stmt->SetData(1, id);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("|cff00ff00Waypoint script: {} position_y updated.|r", id);
return true;
}
else if (arg_str_2 == "posz")
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_Z);
stmt->SetData(0, float(atof(arg_3)));
stmt->SetData(1, id);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff{}|r|cff00ff00 position_z updated.|r", id);
return true;
}
else if (arg_str_2 == "orientation")
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_O);
stmt->SetData(0, float(atof(arg_3)));
stmt->SetData(1, id);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff{}|r|cff00ff00 orientation updated.|r", id);
return true;
}
else if (arg_str_2 == "dataint")
{
WorldDatabase.Execute("UPDATE waypoint_scripts SET {}='{}' WHERE guid='{}'", arg_2, atoi(arg_3), id); // Query can't be a prepared statement
handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff{}|r|cff00ff00 dataint updated.|r", id);
return true;
}
else
{
std::string arg_str_3 = arg_3;
WorldDatabase.EscapeString(arg_str_3);
WorldDatabase.Execute("UPDATE waypoint_scripts SET {}='{}' WHERE guid='{}'", arg_2, arg_str_3, id); // Query can't be a prepared statement
}
}
handler->PSendSysMessage("{}{}|r|cff00ffff{}:|r|cff00ff00 {} {}|r", "|cff00ff00", "Waypoint script:", id, arg_2, "updated.");
}
return true;
}
static bool HandleWpModifyCommand(ChatHandler* handler, const char* 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;
// Check
// Remember: "show" must also be the name of a column!
if ((show != "delay") && (show != "action") && (show != "action_chance")
&& (show != "move_type") && (show != "del") && (show != "move") && (show != "wpadd")
)
{
return false;
}
// Next arg is:
char* arg_str = nullptr;
// Did user provide a GUID
// or did the user select a creature?
// -> variable lowguid is filled with the GUID of the NPC
uint32 pathid = 0;
uint32 point = 0;
Creature* target = handler->getSelectedCreature();
if (!target || target->GetEntry() != VISUAL_WAYPOINT)
{
handler->SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r");
return false;
}
// The visual waypoint
ObjectGuid::LowType wpSpawnId = target->GetSpawnId();
// User did select a visual waypoint?
// Check the creature
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_WPGUID);
stmt->SetData(0, wpSpawnId);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, wpSpawnId);
// Select waypoint number from database
// Since we compare float values, we have to deal with
// some difficulties.
// Here we search for all waypoints that only differ in one from 1 thousand
// (0.001) - There is no other way to compare C++ floats with mySQL floats
// See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
std::string maxDiff = "0.01";
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_POS);
stmt->SetData(0, target->GetPositionX());
stmt->SetData(1, maxDiff);
stmt->SetData(2, target->GetPositionY());
stmt->SetData(3, maxDiff);
stmt->SetData(4, target->GetPositionZ());
stmt->SetData(5, maxDiff);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpSpawnId);
return true;
}
}
do
{
Field* fields = result->Fetch();
pathid = fields[0].Get();
point = fields[1].Get();
} while (result->NextRow());
// We have the waypoint number and the GUID of the "master npc"
// Text is enclosed in "<>", all other arguments not
arg_str = strtok((char*)nullptr, " ");
// Check for argument
if (show != "del" && show != "move" && arg_str == nullptr)
{
handler->PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
return false;
}
if (show == "del")
{
handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff{}|r", pathid);
if (wpSpawnId != 0)
if (Creature* wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(target->GetGUID()))
{
wpCreature->CombatStop();
wpCreature->DeleteFromDB();
wpCreature->AddObjectToRemoveList();
}
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA);
stmt->SetData(0, pathid);
stmt->SetData(1, point);
WorldDatabase.Execute(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POINT);
stmt->SetData(0, pathid);
stmt->SetData(1, point);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_WAYPOINT_REMOVED);
return true;
} // del
if (show == "move")
{
handler->PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff{}|r", pathid);
Player* chr = handler->GetSession()->GetPlayer();
Map* map = chr->GetMap();
{
// What to do:
// Move the visual spawnpoint
// Respawn the owner of the waypoints
if (wpSpawnId != 0)
{
if (Creature* wpCreature = map->GetCreature(target->GetGUID()))
{
wpCreature->CombatStop();
wpCreature->DeleteFromDB();
wpCreature->AddObjectToRemoveList();
}
// re-create
Creature* wpCreature2 = new Creature;
if (!wpCreature2->Create(map->GenerateLowGuid(), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature2;
wpCreature2 = nullptr;
return false;
}
wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
//TODO: Should we first use "Create" then use "LoadFromDB"?
if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature2;
wpCreature2 = nullptr;
return false;
}
//sMapMgr->GetMap(npcCreature->GetMapId())->Add(wpCreature2);
}
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POSITION);
stmt->SetData(0, chr->GetPositionX());
stmt->SetData(1, chr->GetPositionY());
stmt->SetData(2, chr->GetPositionZ());
stmt->SetData(3, pathid);
stmt->SetData(4, point);
WorldDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_WAYPOINT_CHANGED);
}
return true;
} // move
const char* text = arg_str;
if (text == 0)
{
// show_str check for present in list of correct values, no sql injection possible
WorldDatabase.Execute("UPDATE waypoint_data SET {}=nullptr WHERE id='{}' AND point='{}'", show_str, pathid, point); // Query can't be a prepared statement
}
else
{
// show_str check for present in list of correct values, no sql injection possible
std::string text2 = text;
WorldDatabase.EscapeString(text2);
WorldDatabase.Execute("UPDATE waypoint_data SET {}='{}' WHERE id='{}' AND point='{}'", show_str, text2, pathid, point); // Query can't be a prepared statement
}
handler->PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
return true;
}
static bool HandleWpShowCommand(ChatHandler* handler, const char* 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->SendErrorMessage(LANG_SELECT_CREATURE);
return false;
}
pathid = target->GetWaypointPath();
}
else
{
// PathID provided
// Warn if player also selected a creature
// -> Creature selection is ignored <-
if (target)
handler->SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
pathid = atoi((char*)guid_str);
}
std::string show = show_str;
//handler->PSendSysMessage("wpshow - show: {}", show);
// Show info for the selected waypoint
if (show == "info")
{
// Check if the user did specify a visual waypoint
if (!target || target->GetEntry() != VISUAL_WAYPOINT)
{
handler->SendErrorMessage(LANG_WAYPOINT_VP_SELECT);
return false;
}
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID);
stmt->SetData(0, target->GetSpawnId());
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->SendErrorMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetSpawnId());
return false;
}
handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r");
do
{
Field* fields = result->Fetch();
pathid = fields[0].Get();
uint32 point = fields[1].Get();
uint32 delay = fields[2].Get();
uint32 flag = fields[3].Get();
uint32 ev_id = fields[4].Get();
uint32 ev_chance = fields[5].Get();
handler->PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff{}|r|cff00ff00, Path ID: |r|cff00ffff{}|r", point, pathid);
handler->PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff{}|r", delay);
handler->PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff{}|r", flag);
handler->PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff{}|r", ev_id);
handler->PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff{}|r", ev_chance);
} while (result->NextRow());
return true;
}
if (show == "on")
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_BY_ID);
stmt->SetData(0, pathid);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->SendErrorMessage("|cffff33ffPath no found.|r");
return false;
}
handler->PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff{}|r", pathid);
// Delete all visuals for this NPC
stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID);
stmt->SetData(0, pathid);
PreparedQueryResult result2 = WorldDatabase.Query(stmt);
if (result2)
{
bool hasError = false;
do
{
Field* fields = result2->Fetch();
uint32 wpguid = fields[0].Get();
Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid::Create(VISUAL_WAYPOINT, wpguid));
if (!creature)
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
hasError = true;
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE);
stmt->SetData(0, wpguid);
WorldDatabase.Execute(stmt);
}
else
{
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
}
} while (result2->NextRow());
if (hasError)
{
handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
}
}
do
{
Field* fields = result->Fetch();
uint32 point = fields[0].Get();
float x = fields[1].Get();
float y = fields[2].Get();
float z = fields[3].Get();
uint32 id = VISUAL_WAYPOINT;
Player* chr = handler->GetSession()->GetPlayer();
Map* map = chr->GetMap();
float o = chr->GetOrientation();
Creature* wpCreature = new Creature;
if (!wpCreature->Create(map->GenerateLowGuid(), map, chr->GetPhaseMaskForSpawn(), id, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
return false;
}
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
// Set "wpguid" column to the visual waypoint
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID);
stmt->SetData(0, wpCreature->GetSpawnId());
stmt->SetData(1, pathid);
stmt->SetData(2, point);
WorldDatabase.Execute(stmt);
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
return false;
}
if (target)
{
wpCreature->SetDisplayId(target->GetDisplayId());
wpCreature->SetObjectScale(0.5f);
wpCreature->SetLevel(point > STRONG_MAX_LEVEL ? STRONG_MAX_LEVEL : point);
}
} while (result->NextRow());
handler->SendSysMessage("|cff00ff00Showing the current creature's path.|r");
return true;
}
if (show == "first")
{
handler->PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: {}|r", pathid);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID);
stmt->SetData(0, pathid);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->SendErrorMessage(LANG_WAYPOINT_NOTFOUND, pathid);
return false;
}
Field* fields = result->Fetch();
float x = fields[0].Get();
float y = fields[1].Get();
float z = fields[2].Get();
uint32 id = VISUAL_WAYPOINT;
Player* chr = handler->GetSession()->GetPlayer();
float o = chr->GetOrientation();
Map* map = chr->GetMap();
Creature* creature = new Creature;
if (!creature->Create(map->GenerateLowGuid(), map, chr->GetPhaseMaskForSpawn(), id, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
return false;
}
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
return false;
}
if (target)
{
creature->SetDisplayId(target->GetDisplayId());
creature->SetObjectScale(0.5f);
}
return true;
}
if (show == "last")
{
handler->PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff{}|r", pathid);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID);
stmt->SetData(0, pathid);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->SendErrorMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid);
return false;
}
Field* fields = result->Fetch();
float x = fields[0].Get();
float y = fields[1].Get();
float z = fields[2].Get();
float o = fields[3].Get();
uint32 id = VISUAL_WAYPOINT;
Player* chr = handler->GetSession()->GetPlayer();
Map* map = chr->GetMap();
Creature* creature = new Creature;
if (!creature->Create(map->GenerateLowGuid(), map, chr->GetPhaseMaskForSpawn(), id, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete creature;
return false;
}
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map, true, true))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete creature;
return false;
}
if (target)
{
creature->SetDisplayId(target->GetDisplayId());
creature->SetObjectScale(0.5f);
}
return true;
}
if (show == "off")
{
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_BY_ID);
stmt->SetArguments(1, 1, 1);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
handler->SendErrorMessage(LANG_WAYPOINT_VP_NOTFOUND);
return false;
}
bool hasError = false;
do
{
Field* fields = result->Fetch();
ObjectGuid::LowType guid = fields[0].Get();
Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid::Create(VISUAL_WAYPOINT, guid));
if (!creature)
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
hasError = true;
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE);
stmt->SetData(0, guid);
WorldDatabase.Execute(stmt);
}
else
{
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
}
} while (result->NextRow());
// set "wpguid" column to "empty" - no visual waypoint spawned
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID);
WorldDatabase.Execute(stmt);
if (hasError)
{
handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
}
handler->SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
return true;
}
handler->PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r");
return true;
}
};
void AddSC_wp_commandscript()
{
new wp_commandscript();
}