TrinityCore
Loading...
Searching...
No Matches
cs_wp.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* ScriptData
19Name: wp_commandscript
20%Complete: 100
21Comment: All wp related commands
22Category: commandscripts
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "Chat.h"
27#include "Creature.h"
28#include "DatabaseEnv.h"
29#include "Language.h"
30#include "Map.h"
31#include "MotionMaster.h"
32#include "ObjectMgr.h"
33#include "Player.h"
34#include "RBAC.h"
35#include "WaypointDefines.h"
36#include "WaypointManager.h"
37#include "WorldSession.h"
38
39#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
40#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
41#endif
42
44{
45public:
46 wp_commandscript() : CommandScript("wp_commandscript") { }
47
48 std::vector<ChatCommand> GetCommands() const override
49 {
50 static std::vector<ChatCommand> wpCommandTable =
51 {
59 };
60 static std::vector<ChatCommand> commandTable =
61 {
62 { "wp", rbac::RBAC_PERM_COMMAND_WP, false, nullptr, "", wpCommandTable },
63 };
64 return commandTable;
65 }
87 static bool HandleWpAddCommand(ChatHandler* handler, char const* args)
88 {
89 // optional
90 char* path_number = nullptr;
91 uint32 pathid = 0;
92
93 if (*args)
94 path_number = strtok((char*)args, " ");
95
96 uint32 point = 0;
97 Creature* target = handler->getSelectedCreature();
98
99 if (!path_number)
100 {
101 if (target)
102 pathid = target->GetWaypointPath();
103 else
104 {
106
107 PreparedQueryResult result = WorldDatabase.Query(stmt);
108
109 uint32 maxpathid = result->Fetch()->GetInt32();
110 pathid = maxpathid+1;
111 handler->PSendSysMessage("%s%s|r", "|cff00ff00", "New path started.");
112 }
113 }
114 else
115 pathid = atoi(path_number);
116
117 // path_id -> ID of the Path
118 // point -> number of the waypoint (if not 0)
119
120 if (!pathid)
121 {
122 handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Current creature haven't loaded path.");
123 return true;
124 }
125
127 stmt->setUInt32(0, pathid);
128 PreparedQueryResult result = WorldDatabase.Query(stmt);
129
130 if (result)
131 point = (*result)[0].GetUInt32();
132
133 Player* player = handler->GetSession()->GetPlayer();
134 //Map* map = player->GetMap();
135
136 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_DATA);
137
138 stmt->setUInt32(0, pathid);
139 stmt->setUInt32(1, point + 1);
140 stmt->setFloat(2, player->GetPositionX());
141 stmt->setFloat(3, player->GetPositionY());
142 stmt->setFloat(4, player->GetPositionZ());
143 stmt->setFloat(5, player->GetOrientation());
144
145 WorldDatabase.Execute(stmt);
146
147 handler->PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point+1, "|r|cff00ff00 created. ");
148 return true;
149 } // HandleWpAddCommand
150
151 static bool HandleWpLoadCommand(ChatHandler* handler, char const* args)
152 {
153 if (!*args)
154 return false;
155
156 // optional
157 char* path_number = nullptr;
158
159 if (*args)
160 path_number = strtok((char*)args, " ");
161
162 uint32 pathid = 0;
163 ObjectGuid::LowType guidLow = 0;
164 Creature* target = handler->getSelectedCreature();
165
166 // Did player provide a path_id?
167 if (!path_number)
168 return false;
169
170 if (!target)
171 {
173 handler->SetSentErrorMessage(true);
174 return false;
175 }
176
177 if (target->GetEntry() == 1)
178 {
179 handler->PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?");
180 handler->SetSentErrorMessage(true);
181 return false;
182 }
183
184 pathid = atoi(path_number);
185
186 if (!pathid)
187 {
188 handler->PSendSysMessage("%s%s|r", "|cffff33ff", "No valid path number provided.");
189 return true;
190 }
191
192 guidLow = target->GetSpawnId();
193
195
196 stmt->setUInt32(0, guidLow);
197
198 PreparedQueryResult result = WorldDatabase.Query(stmt);
199
200 if (result)
201 {
202 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ADDON_PATH);
203
204 stmt->setUInt32(0, pathid);
205 stmt->setUInt32(1, guidLow);
206 }
207 else
208 {
209 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE_ADDON);
210
211 stmt->setUInt32(0, guidLow);
212 stmt->setUInt32(1, pathid);
213 }
214
215 WorldDatabase.Execute(stmt);
216
217 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
218
220 stmt->setUInt32(1, guidLow);
221
222 WorldDatabase.Execute(stmt);
223
224 target->LoadPath(pathid);
226 target->GetMotionMaster()->Initialize();
227 target->Say("Path loaded.", LANG_UNIVERSAL);
228
229 return true;
230 }
231
232 static bool HandleWpReloadCommand(ChatHandler* handler, char const* args)
233 {
234 if (!*args)
235 return false;
236
237 uint32 id = atoi(args);
238
239 if (!id)
240 return false;
241
242 handler->PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id);
243 sWaypointMgr->ReloadPath(id);
244 return true;
245 }
246
247 static bool HandleWpUnLoadCommand(ChatHandler* handler, char const* /*args*/)
248 {
249 Creature* target = handler->getSelectedCreature();
250 WorldDatabasePreparedStatement* stmt = nullptr;
251
252 if (!target)
253 {
254 handler->PSendSysMessage("%s%s|r", "|cff33ffff", "You must select a target.");
255 return true;
256 }
257
258 ObjectGuid::LowType guidLow = target->GetSpawnId();
259 if (!guidLow)
260 {
261 handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target is not saved to DB.");
262 return true;
263 }
264
265 CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(guidLow);
266 if (!addon || addon->path_id == 0)
267 {
268 handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target does not have a loaded path.");
269 return true;
270 }
271
272 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
273 stmt->setUInt32(0, guidLow);
274 WorldDatabase.Execute(stmt);
275
276 target->UpdateCurrentWaypointInfo(0, 0);
277
278 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
280 stmt->setUInt32(1, guidLow);
281 WorldDatabase.Execute(stmt);
282
283 target->LoadPath(0);
286 target->GetMotionMaster()->Initialize();
287 target->Say("Path unloaded.", LANG_UNIVERSAL);
288 return true;
289 }
290
291 static bool HandleWpEventCommand(ChatHandler* handler, char const* args)
292 {
293 if (!*args)
294 return false;
295
296 char* show_str = strtok((char*)args, " ");
297 std::string show = show_str;
298 WorldDatabasePreparedStatement* stmt = nullptr;
299
300 // Check
301 if ((show != "add") && (show != "mod") && (show != "del") && (show != "listid"))
302 return false;
303
304 char* arg_id = strtok(nullptr, " ");
305
306 if (show == "add")
307 {
309 if (arg_id)
310 id = Trinity::StringTo<uint32>(arg_id);
311
312 if (id)
313 {
314 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID);
315 stmt->setUInt32(0, *id);
316 PreparedQueryResult result = WorldDatabase.Query(stmt);
317
318 if (!result)
319 {
320 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_SCRIPT);
321 stmt->setUInt32(0, *id);
322 WorldDatabase.Execute(stmt);
323
324 handler->PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: ", *id);
325 }
326 else
327 handler->PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: %u|r", *id);
328 }
329 else
330 {
331 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID);
332 PreparedQueryResult result = WorldDatabase.Query(stmt);
333 id = result->Fetch()->GetUInt32();
334 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_SCRIPT);
335 stmt->setUInt32(0, *id + 1);
336 WorldDatabase.Execute(stmt);
337
338 handler->PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: |r|cff00ffff", *id+1);
339 }
340
341 return true;
342 }
343
344 if (show == "listid")
345 {
346 if (!arg_id)
347 {
348 handler->PSendSysMessage("%s%s|r", "|cff33ffff", "Wp Event: You must provide waypoint script id.");
349 return true;
350 }
351
352 uint32 id = Trinity::StringTo<uint32>(arg_id).value_or(0);
353
354 uint32 a2, a3, a4, a5, a6, a7;
355 float a8, a9, a10, a11;
356
357 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID);
358 stmt->setUInt32(0, id);
359 PreparedQueryResult result = WorldDatabase.Query(stmt);
360
361 if (!result)
362 {
363 handler->PSendSysMessage("%s%s%u|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id);
364 return true;
365 }
366
367 Field* fields;
368
369 do
370 {
371 fields = result->Fetch();
372 a2 = fields[0].GetUInt32();
373 a3 = fields[1].GetUInt32();
374 a4 = fields[2].GetUInt32();
375 a5 = fields[3].GetUInt32();
376 a6 = fields[4].GetUInt32();
377 a7 = fields[5].GetUInt32();
378 a8 = fields[6].GetFloat();
379 a9 = fields[7].GetFloat();
380 a10 = fields[8].GetFloat();
381 a11 = fields[9].GetFloat();
382
383 handler->PSendSysMessage("|cffff33ffid:|r|cff00ffff %u|r|cff00ff00, guid: |r|cff00ffff%u|r|cff00ff00, delay: |r|cff00ffff%u|r|cff00ff00, command: |r|cff00ffff%u|r|cff00ff00, datalong: |r|cff00ffff%u|r|cff00ff00, datalong2: |r|cff00ffff%u|r|cff00ff00, dataint: |r|cff00ffff%u|r|cff00ff00, posx: |r|cff00ffff%f|r|cff00ff00, posy: |r|cff00ffff%f|r|cff00ff00, posz: |r|cff00ffff%f|r|cff00ff00, orientation: |r|cff00ffff%f|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
384 }
385 while (result->NextRow());
386 }
387
388 if (show == "del")
389 {
390 if (!arg_id)
391 {
392 handler->SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r");
393 return true;
394 }
395
396 uint32 id = Trinity::StringTo<uint32>(arg_id).value_or(0);
397
398 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID);
399 stmt->setUInt32(0, id);
400 PreparedQueryResult result = WorldDatabase.Query(stmt);
401
402 if (result)
403 {
404 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_SCRIPT);
405 stmt->setUInt32(0, id);
406 WorldDatabase.Execute(stmt);
407
408 handler->PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: Waypoint script removed: ", id);
409 }
410 else
411 handler->PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: %u|r", id);
412
413 return true;
414 }
415
416 if (show == "mod")
417 {
418 if (!arg_id)
419 {
420 handler->SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r");
421 return true;
422 }
423
424 uint32 id = Trinity::StringTo<uint32>(arg_id).value_or(0);
425
426 if (!id)
427 {
428 handler->SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r");
429 return true;
430 }
431
432 char* arg_2 = strtok(nullptr, " ");
433
434 if (!arg_2)
435 {
436 handler->SendSysMessage("|cffff33ffERROR: No argument present.|r");
437 return true;
438 }
439
440 std::string arg_string = arg_2;
441
442 if ((arg_string != "setid") && (arg_string != "delay") && (arg_string != "command")
443 && (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx")
444 && (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation"))
445 {
446 handler->SendSysMessage("|cffff33ffERROR: No valid argument present.|r");
447 return true;
448 }
449
450 char* arg_3;
451 std::string arg_str_2 = arg_2;
452 arg_3 = strtok(nullptr, " ");
453
454 if (!arg_3)
455 {
456 handler->SendSysMessage("|cffff33ffERROR: No additional argument present.|r");
457 return true;
458 }
459
460 if (arg_str_2 == "setid")
461 {
462 uint32 newid = Trinity::StringTo<uint32>(arg_3).value_or(0);
463 handler->PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r", "|cff00ff00", "Wp Event: Waypoint script guid: ", newid, " id changed: ", id);
464
465 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_ID);
466 stmt->setUInt32(0, newid);
467 stmt->setUInt32(1, id);
468 WorldDatabase.Execute(stmt);
469
470 return true;
471 }
472 else
473 {
474 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID);
475 stmt->setUInt32(0, id);
476 PreparedQueryResult result = WorldDatabase.Query(stmt);
477
478 if (!result)
479 {
480 handler->SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r");
481 return true;
482 }
483
484 if (arg_str_2 == "posx")
485 {
486 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_X);
487 stmt->setFloat(0, float(atof(arg_3)));
488 stmt->setUInt32(1, id);
489
490 WorldDatabase.Execute(stmt);
491
492 handler->PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id);
493 return true;
494 }
495 else if (arg_str_2 == "posy")
496 {
497 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_Y);
498 stmt->setFloat(0, float(atof(arg_3)));
499 stmt->setUInt32(1, id);
500
501 WorldDatabase.Execute(stmt);
502
503 handler->PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id);
504 return true;
505 }
506 else if (arg_str_2 == "posz")
507 {
508 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_Z);
509 stmt->setFloat(0, float(atof(arg_3)));
510 stmt->setUInt32(1, id);
511
512 WorldDatabase.Execute(stmt);
513
514 handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id);
515 return true;
516 }
517 else if (arg_str_2 == "orientation")
518 {
519 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_O);
520 stmt->setFloat(0, float(atof(arg_3)));
521 stmt->setUInt32(1, id);
522
523 WorldDatabase.Execute(stmt);
524
525 handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id);
526 return true;
527 }
528 else if (arg_str_2 == "dataint")
529 {
530 WorldDatabase.PExecute("UPDATE waypoint_scripts SET {}='{}' WHERE guid='{}'", arg_2, arg_3, id); // Query can't be a prepared statement
531
532 handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id);
533 return true;
534 }
535 else
536 {
537 std::string arg_str_3 = arg_3;
538 WorldDatabase.EscapeString(arg_str_3);
539 WorldDatabase.PExecute("UPDATE waypoint_scripts SET {}='{}' WHERE guid='{}'", arg_2, arg_str_3, id); // Query can't be a prepared statement
540 }
541 }
542 handler->PSendSysMessage("%s%s|r|cff00ffff%u:|r|cff00ff00 %s %s|r", "|cff00ff00", "Waypoint script:", id, arg_2, "updated.");
543 }
544 return true;
545 }
546
547 static bool HandleWpModifyCommand(ChatHandler* handler, char const* args)
548 {
549 if (!*args)
550 return false;
551
552 // first arg: add del text emote spell waittime move
553 char* show_str = strtok((char*)args, " ");
554 if (!show_str)
555 {
556 return false;
557 }
558
559 std::string show = show_str;
560 // Check
561 // Remember: "show" must also be the name of a column!
562 if ((show != "delay") && (show != "action") && (show != "action_chance")
563 && (show != "move_type") && (show != "del") && (show != "move")
564 )
565 {
566 return false;
567 }
568
569 // Next arg is: <PATHID> <WPNUM> <ARGUMENT>
570 char* arg_str = nullptr;
571
572 // Did user provide a GUID
573 // or did the user select a creature?
574 // -> variable lowguid is filled with the GUID of the NPC
575 uint32 pathid = 0;
576 uint32 point = 0;
577 Creature* target = handler->getSelectedCreature();
578 WorldDatabasePreparedStatement* stmt = nullptr;
579
580 // User did select a visual waypoint?
581 if (!target || target->GetEntry() != VISUAL_WAYPOINT)
582 {
583 handler->SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r");
584 return false;
585 }
586
587 // Check the creature
588 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_WPGUID);
589 stmt->setUInt32(0, target->GetSpawnId());
590 PreparedQueryResult result = WorldDatabase.Query(stmt);
591
592 if (!result)
593 {
595 // Select waypoint number from database
596 // Since we compare float values, we have to deal with
597 // some difficulties.
598 // Here we search for all waypoints that only differ in one from 1 thousand
599 // (0.001) - There is no other way to compare C++ floats with mySQL floats
600 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
601 std::string maxDiff = "0.01";
602
603 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_POS);
604 stmt->setFloat(0, target->GetPositionX());
605 stmt->setString(1, maxDiff);
606 stmt->setFloat(2, target->GetPositionY());
607 stmt->setString(3, maxDiff);
608 stmt->setFloat(4, target->GetPositionZ());
609 stmt->setString(5, maxDiff);
610 result = WorldDatabase.Query(stmt);
611
612 if (!result)
613 {
615 return true;
616 }
617 }
618
619 do
620 {
621 Field* fields = result->Fetch();
622 pathid = fields[0].GetUInt32();
623 point = fields[1].GetUInt32();
624 }
625 while (result->NextRow());
626
627 // We have the waypoint number and the GUID of the "master npc"
628 // Text is enclosed in "<>", all other arguments not
629 arg_str = strtok((char*)nullptr, " ");
630
631 // Check for argument
632 if (show != "del" && show != "move" && arg_str == nullptr)
633 {
634 handler->PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
635 return false;
636 }
637
638 if (show == "del")
639 {
640 handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid);
641
642 if (Creature::DeleteFromDB(target->GetSpawnId()))
643 {
644 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA);
645 stmt->setUInt32(0, pathid);
646 stmt->setUInt32(1, point);
647 WorldDatabase.Execute(stmt);
648
649 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POINT);
650 stmt->setUInt32(0, pathid);
651 stmt->setUInt32(1, point);
652 WorldDatabase.Execute(stmt);
653
655 return true;
656 }
657 else
658 {
660 handler->SetSentErrorMessage(true);
661 return false;
662 }
663 } // del
664
665 if (show == "move")
666 {
667 handler->PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid);
668
669 Player* chr = handler->GetSession()->GetPlayer();
670 Map* map = chr->GetMap();
671 // What to do:
672 // Move the visual spawnpoint
673 // Respawn the owner of the waypoints
674 if (!Creature::DeleteFromDB(target->GetSpawnId()))
675 {
677 handler->SetSentErrorMessage(true);
678 return false;
679 }
680
681 // re-create
682 Creature* wpCreature = new Creature();
683 if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, *chr))
684 {
686 delete wpCreature;
687 return false;
688 }
689
690 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
691 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
692 if (!wpCreature->LoadFromDB(wpCreature->GetSpawnId(), map, true, true))
693 {
695 delete wpCreature;
696 return false;
697 }
698
699 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POSITION);
700 stmt->setFloat(0, chr->GetPositionX());
701 stmt->setFloat(1, chr->GetPositionY());
702 stmt->setFloat(2, chr->GetPositionZ());
703 stmt->setFloat(3, chr->GetOrientation());
704 stmt->setUInt32(4, pathid);
705 stmt->setUInt32(5, point);
706 WorldDatabase.Execute(stmt);
707
709 return true;
710 } // move
711
712 const char *text = arg_str;
713
714 if (text == 0)
715 {
716 // show_str check for present in list of correct values, no sql injection possible
717 WorldDatabase.PExecute("UPDATE waypoint_data SET {}=NULL WHERE id='{}' AND point='{}'", show_str, pathid, point); // Query can't be a prepared statement
718 }
719 else
720 {
721 // show_str check for present in list of correct values, no sql injection possible
722 std::string text2 = text;
723 WorldDatabase.EscapeString(text2);
724 WorldDatabase.PExecute("UPDATE waypoint_data SET {}='{}' WHERE id='{}' AND point='{}'", show_str, text2, pathid, point); // Query can't be a prepared statement
725 }
726
727 handler->PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
728 return true;
729 }
730
731 static bool HandleWpShowCommand(ChatHandler* handler, char const* args)
732 {
733 if (!*args)
734 return false;
735
736 // first arg: on, off, first, last
737 char* show_str = strtok((char*)args, " ");
738 if (!show_str)
739 return false;
740
741 // second arg: GUID (optional, if a creature is selected)
742 char* guid_str = strtok((char*)nullptr, " ");
743
744 uint32 pathid = 0;
745 Creature* target = handler->getSelectedCreature();
746 WorldDatabasePreparedStatement* stmt = nullptr;
747
748 // Did player provide a PathID?
749
750 if (!guid_str)
751 {
752 // No PathID provided
753 // -> Player must have selected a creature
754
755 if (!target)
756 {
758 handler->SetSentErrorMessage(true);
759 return false;
760 }
761
762 pathid = target->GetWaypointPath();
763 }
764 else
765 {
766 // PathID provided
767 // Warn if player also selected a creature
768 // -> Creature selection is ignored <-
769 if (target)
771
772 pathid = Trinity::StringTo<uint32>(guid_str).value_or(0);
773 }
774
775 std::string show = show_str;
776
777 //handler->PSendSysMessage("wpshow - show: %s", show);
778
779 // Show info for the selected waypoint
780 if (show == "info")
781 {
782 // Check if the user did specify a visual waypoint
783 if (!target || target->GetEntry() != VISUAL_WAYPOINT)
784 {
786 handler->SetSentErrorMessage(true);
787 return false;
788 }
789
790 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID);
791 stmt->setUInt32(0, target->GetSpawnId());
792 PreparedQueryResult result = WorldDatabase.Query(stmt);
793
794 if (!result)
795 {
797 return true;
798 }
799
800 handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r");
801 do
802 {
803 Field* fields = result->Fetch();
804 pathid = fields[0].GetUInt32();
805 uint32 point = fields[1].GetUInt32();
806 uint32 delay = fields[2].GetUInt32();
807 uint32 flag = fields[3].GetUInt32();
808 uint32 ev_id = fields[4].GetUInt32();
809 uint32 ev_chance = fields[5].GetUInt16();
810
811 handler->PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid);
812 handler->PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay);
813 handler->PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag);
814 handler->PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id);
815 handler->PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance);
816 }
817 while (result->NextRow());
818
819 return true;
820 }
821
822 if (show == "on")
823 {
824 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_BY_ID);
825 stmt->setUInt32(0, pathid);
826 PreparedQueryResult result = WorldDatabase.Query(stmt);
827
828 if (!result)
829 {
830 handler->SendSysMessage("|cffff33ffPath no found.|r");
831 handler->SetSentErrorMessage(true);
832 return false;
833 }
834
835 handler->PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid);
836
837 // Delete all visuals for this NPC
838 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID);
839
840 stmt->setUInt32(0, pathid);
841
842 PreparedQueryResult result2 = WorldDatabase.Query(stmt);
843
844 if (result2)
845 {
846 bool hasError = false;
847 do
848 {
849 Field* fields = result2->Fetch();
850 ObjectGuid::LowType wpguid = fields[0].GetUInt32();
851 if (!Creature::DeleteFromDB(wpguid))
852 {
854 hasError = true;
855 }
856
857 }
858 while (result2->NextRow());
859
860 if (hasError)
861 {
865 }
866 }
867
868 do
869 {
870 Field* fields = result->Fetch();
871 uint32 point = fields[0].GetUInt32();
872 float x = fields[1].GetFloat();
873 float y = fields[2].GetFloat();
874 float z = fields[3].GetFloat();
875 float o = fields[4].GetFloat();
876
878
879 Player* chr = handler->GetSession()->GetPlayer();
880 Map* map = chr->GetMap();
881
882 Creature* wpCreature = new Creature();
883 if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, { x, y, z, o }))
884 {
886 delete wpCreature;
887 return false;
888 }
889
890 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
891
892 // Set "wpguid" column to the visual waypoint
893 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID);
894 stmt->setUInt32(0, wpCreature->GetSpawnId());
895 stmt->setUInt32(1, pathid);
896 stmt->setUInt32(2, point);
897 WorldDatabase.Execute(stmt);
898
899 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
900 if (!wpCreature->LoadFromDB(wpCreature->GetSpawnId(), map, true, true))
901 {
903 delete wpCreature;
904 return false;
905 }
906
907 if (target)
908 {
909 wpCreature->SetDisplayId(target->GetDisplayId());
910 wpCreature->SetObjectScale(0.5f);
911 wpCreature->SetLevel(std::min<uint32>(point, STRONG_MAX_LEVEL));
912 }
913 }
914 while (result->NextRow());
915
916 handler->SendSysMessage("|cff00ff00Showing the current creature's path.|r");
917 return true;
918 }
919
920 if (show == "first")
921 {
922 handler->PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid);
923
924 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID);
925 stmt->setUInt32(0, pathid);
926 PreparedQueryResult result = WorldDatabase.Query(stmt);
927
928 if (!result)
929 {
930 handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid);
931 handler->SetSentErrorMessage(true);
932 return false;
933 }
934
935 Field* fields = result->Fetch();
936 float x = fields[0].GetFloat();
937 float y = fields[1].GetFloat();
938 float z = fields[2].GetFloat();
939 float o = fields[3].GetFloat();
940
942
943 Player* chr = handler->GetSession()->GetPlayer();
944 Map* map = chr->GetMap();
945
946 Creature* creature = new Creature();
947 if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, { x, y, z, o }))
948 {
950 delete creature;
951 return false;
952 }
953
954 creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
955 if (!creature->LoadFromDB(creature->GetSpawnId(), map, true, true))
956 {
958 delete creature;
959 return false;
960 }
961
962 if (target)
963 {
964 creature->SetDisplayId(target->GetDisplayId());
965 creature->SetObjectScale(0.5f);
966 }
967
968 return true;
969 }
970
971 if (show == "last")
972 {
973 handler->PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid);
974
975 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID);
976 stmt->setUInt32(0, pathid);
977 PreparedQueryResult result = WorldDatabase.Query(stmt);
978
979 if (!result)
980 {
982 handler->SetSentErrorMessage(true);
983 return false;
984 }
985 Field* fields = result->Fetch();
986 float x = fields[0].GetFloat();
987 float y = fields[1].GetFloat();
988 float z = fields[2].GetFloat();
989 float o = fields[3].GetFloat();
991
992 Player* chr = handler->GetSession()->GetPlayer();
993 Map* map = chr->GetMap();
994
995 Creature* creature = new Creature();
996 if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, { x, y, z, o }))
997 {
999 delete creature;
1000 return false;
1001 }
1002
1003 creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
1004 if (!creature->LoadFromDB(creature->GetSpawnId(), map, true, true))
1005 {
1007 delete creature;
1008 return false;
1009 }
1010
1011 if (target)
1012 {
1013 creature->SetDisplayId(target->GetDisplayId());
1014 creature->SetObjectScale(0.5f);
1015 }
1016
1017 return true;
1018 }
1019
1020 if (show == "off")
1021 {
1022 stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_BY_ID);
1023 stmt->setUInt32(0, 1);
1024 PreparedQueryResult result = WorldDatabase.Query(stmt);
1025
1026 if (!result)
1027 {
1029 handler->SetSentErrorMessage(true);
1030 return false;
1031 }
1032 bool hasError = false;
1033 do
1034 {
1035 Field* fields = result->Fetch();
1036 ObjectGuid::LowType lowguid = fields[0].GetUInt32();
1037
1038 if (!Creature::DeleteFromDB(lowguid))
1039 {
1040 handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, lowguid);
1041 hasError = true;
1042 }
1043 }
1044 while (result->NextRow());
1045 // set "wpguid" column to "empty" - no visual waypoint spawned
1046 stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID);
1047
1048 WorldDatabase.Execute(stmt);
1049 //WorldDatabase.PExecute("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
1050
1051 if (hasError)
1052 {
1056 }
1057
1059 return true;
1060 }
1061
1062 handler->PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r");
1063 return true;
1064 }
1065};
1066
1068{
1069 new wp_commandscript();
1070}
@ STRONG_MAX_LEVEL
Definition DBCEnums.h:53
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ LANG_WAYPOINT_TOOFAR2
Definition Language.h:291
@ LANG_WAYPOINT_REMOVED
Definition Language.h:288
@ LANG_SELECT_CREATURE
Definition Language.h:32
@ LANG_WAYPOINT_CHANGED
Definition Language.h:283
@ LANG_WAYPOINT_CHANGED_NO
Definition Language.h:284
@ LANG_WAYPOINT_ARGUMENTREQ
Definition Language.h:280
@ LANG_WAYPOINT_VP_NOTFOUND
Definition Language.h:274
@ LANG_WAYPOINT_NOTFOUNDLAST
Definition Language.h:268
@ LANG_WAYPOINT_VP_NOTCREATED
Definition Language.h:275
@ LANG_WAYPOINT_NOTREMOVED
Definition Language.h:289
@ LANG_WAYPOINT_NOTFOUNDDBPROBLEM
Definition Language.h:270
@ LANG_WAYPOINT_NOTFOUND
Definition Language.h:267
@ LANG_WAYPOINT_NOTFOUNDSEARCH
Definition Language.h:269
@ LANG_WAYPOINT_NOTCREATED
Definition Language.h:277
@ LANG_WAYPOINT_CREATSELECTED
Definition Language.h:271
@ LANG_WAYPOINT_VP_ALLREMOVED
Definition Language.h:276
@ LANG_WAYPOINT_TOOFAR1
Definition Language.h:290
@ LANG_WAYPOINT_VP_SELECT
Definition Language.h:273
@ LANG_WAYPOINT_TOOFAR3
Definition Language.h:292
@ IDLE_MOTION_TYPE
@ WAYPOINT_MOTION_TYPE
#define sObjectMgr
Definition ObjectMgr.h:1721
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
Role Based Access Control related classes definition.
@ LANG_UNIVERSAL
#define VISUAL_WAYPOINT
Definition Unit.h:34
#define sWaypointMgr
@ WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID
@ WORLD_SEL_WAYPOINT_DATA_BY_WPGUID
@ WORLD_DEL_WAYPOINT_DATA
@ WORLD_UPD_WAYPOINT_SCRIPT_O
@ WORLD_INS_WAYPOINT_DATA
@ WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID
@ WORLD_INS_CREATURE_ADDON
@ WORLD_SEL_CREATURE_ADDON_BY_GUID
@ WORLD_UPD_WAYPOINT_DATA_POINT
@ WORLD_UPD_WAYPOINT_SCRIPT_Z
@ WORLD_UPD_WAYPOINT_DATA_POSITION
@ WORLD_UPD_CREATURE_MOVEMENT_TYPE
@ WORLD_SEL_WAYPOINT_DATA_BY_POS
@ WORLD_UPD_CREATURE_ADDON_PATH
@ WORLD_DEL_CREATURE_ADDON
@ WORLD_UPD_WAYPOINT_SCRIPT_X
@ WORLD_INS_WAYPOINT_SCRIPT
@ WORLD_SEL_WAYPOINT_DATA_POS_BY_ID
@ WORLD_SEL_CREATURE_BY_ID
@ WORLD_DEL_WAYPOINT_SCRIPT
@ WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID
@ WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID
@ WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID
@ WORLD_UPD_WAYPOINT_DATA_WPGUID
@ WORLD_SEL_WAYPOINT_SCRIPT_BY_ID
@ WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID
@ WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID
@ WORLD_SEL_WAYPOINT_DATA_MAX_ID
@ WORLD_SEL_WAYPOINT_DATA_MAX_POINT
@ WORLD_UPD_WAYPOINT_SCRIPT_Y
@ WORLD_UPD_WAYPOINT_SCRIPT_ID
WorldSession * GetSession()
Definition Chat.h:46
Creature * getSelectedCreature()
Definition Chat.cpp:338
void SetSentErrorMessage(bool val)
Definition Chat.h:134
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:69
virtual void SendSysMessage(std::string_view str, bool escapeCharacters=false)
Definition Chat.cpp:101
bool LoadFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap, bool allowDuplicate)
void SetDisplayId(uint32 modelId) override
void SetObjectScale(float scale) override
uint32 GetWaypointPath() const
Definition Creature.h:303
void UpdateCurrentWaypointInfo(uint32 nodeId, uint32 pathId)
Definition Creature.h:308
ObjectGuid::LowType GetSpawnId() const
Definition Creature.h:83
static bool DeleteFromDB(ObjectGuid::LowType spawnId)
void SaveToDB()
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 phaseMask, uint32 entry, Position const &pos, CreatureData const *data=nullptr, uint32 vehId=0, bool dynamic=false)
void SetDefaultMovementType(MovementGeneratorType mgt)
Definition Creature.h:112
void LoadPath(uint32 pathid)
Definition Creature.h:304
Class used to access individual fields of database query result.
Definition Field.h:92
uint16 GetUInt16() const
Definition Field.cpp:45
float GetFloat() const
Definition Field.cpp:93
uint32 GetUInt32() const
Definition Field.cpp:61
Definition Map.h:281
uint8 GetSpawnMode() const
Definition Map.h:388
ObjectGuid::LowType GenerateLowGuid()
Definition Map.h:587
uint32 GetId() const
Definition Map.cpp:4216
void MoveTargetedHome()
uint32 LowType
Definition ObjectGuid.h:142
uint32 GetEntry() const
Definition Object.h:81
uint32 GetPhaseMaskForSpawn() const
Definition Player.cpp:24769
void setUInt32(uint8 index, uint32 value)
void setFloat(uint8 index, float value)
void setUInt8(uint8 index, uint8 value)
void setString(uint8 index, std::string const &value)
virtual void Say(std::string_view text, Language language, WorldObject const *target=nullptr)
Definition Unit.cpp:13834
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
uint32 GetDisplayId() const
Definition Unit.h:1582
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:9344
Map * GetMap() const
Definition Object.h:449
Player * GetPlayer() const
static bool HandleWpShowCommand(ChatHandler *handler, char const *args)
Definition cs_wp.cpp:731
static bool HandleWpAddCommand(ChatHandler *handler, char const *args)
Definition cs_wp.cpp:87
static bool HandleWpUnLoadCommand(ChatHandler *handler, char const *)
Definition cs_wp.cpp:247
static bool HandleWpLoadCommand(ChatHandler *handler, char const *args)
Definition cs_wp.cpp:151
std::vector< ChatCommand > GetCommands() const override
Definition cs_wp.cpp:48
static bool HandleWpEventCommand(ChatHandler *handler, char const *args)
Definition cs_wp.cpp:291
static bool HandleWpModifyCommand(ChatHandler *handler, char const *args)
Definition cs_wp.cpp:547
static bool HandleWpReloadCommand(ChatHandler *handler, char const *args)
Definition cs_wp.cpp:232
void AddSC_wp_commandscript()
Definition cs_wp.cpp:1067
@ RBAC_PERM_COMMAND_WP_SHOW
Definition RBAC.h:644
@ RBAC_PERM_COMMAND_WP_MODIFY
Definition RBAC.h:641
@ RBAC_PERM_COMMAND_WP_UNLOAD
Definition RBAC.h:642
@ RBAC_PERM_COMMAND_WP_LOAD
Definition RBAC.h:640
@ RBAC_PERM_COMMAND_WP_ADD
Definition RBAC.h:638
@ RBAC_PERM_COMMAND_WP
Definition RBAC.h:637
@ RBAC_PERM_COMMAND_WP_EVENT
Definition RBAC.h:639
@ RBAC_PERM_COMMAND_WP_RELOAD
Definition RBAC.h:643
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80