2010-11-16 21:27:25 +01:00
/*
2020-01-02 06:44:10 +01:00
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
2010-11-16 21:27:25 +01:00
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* ScriptData
Name: gobject_commandscript
%Complete: 100
Comment: All gobject related commands
Category: commandscripts
EndScriptData */
2017-05-20 00:09:37 +02:00
#include "ScriptMgr.h"
2010-11-16 21:27:25 +01:00
#include "Chat.h"
2017-05-18 23:52:58 +02:00
#include "DatabaseEnv.h"
2017-06-04 01:00:45 +02:00
#include "DB2Stores.h"
2017-05-18 23:52:58 +02:00
#include "GameEventMgr.h"
2017-06-04 01:00:45 +02:00
#include "GameObject.h"
2018-07-18 14:19:24 +02:00
#include "GameObjectAI.h"
2017-12-10 12:39:37 +01:00
#include "GameTime.h"
2012-11-20 12:30:30 +01:00
#include "Language.h"
2017-05-18 23:52:58 +02:00
#include "Log.h"
#include "MapManager.h"
2017-06-04 01:00:45 +02:00
#include "ObjectAccessor.h"
2017-05-18 23:52:58 +02:00
#include "ObjectMgr.h"
2012-11-20 14:54:33 +01:00
#include "Opcodes.h"
2018-01-28 11:37:20 +01:00
#include "PhasingHandler.h"
2017-05-18 23:52:58 +02:00
#include "Player.h"
#include "PoolMgr.h"
2017-05-20 00:09:37 +02:00
#include "RBAC.h"
2017-06-04 01:00:45 +02:00
#include "WorldSession.h"
2020-04-03 18:12:07 +02:00
#include <sstream>
2010-11-16 21:27:25 +01:00
2017-05-07 21:48:41 +01:00
2019-07-08 11:33:09 +02:00
using namespace Trinity :: ChatCommands ;
2020-09-03 22:16:57 +02:00
using GameObjectSpawnId = Variant < Hyperlink < gameobject > , ObjectGuid :: LowType > ;
using GameObjectEntry = Variant < Hyperlink < gameobject_entry > , uint32 > ;
2020-09-04 00:58:23 +02:00
// definitions are over in cs_npc.cpp
2020-09-10 15:19:17 +02:00
bool HandleNpcSpawnGroup ( ChatHandler * handler , std :: vector < Variant < uint32 , EXACT_SEQUENCE ( "force" ), EXACT_SEQUENCE ( "ignorerespawn" ) >> const & opts );
bool HandleNpcDespawnGroup ( ChatHandler * handler , std :: vector < Variant < uint32 , EXACT_SEQUENCE ( "removerespawntime" ) >> const & opts );
2020-09-04 00:58:23 +02:00
2010-11-16 21:27:25 +01:00
class gobject_commandscript : public CommandScript
{
2010-11-19 14:04:21 +01:00
public :
gobject_commandscript () : CommandScript ( "gobject_commandscript" ) { }
2010-11-16 21:27:25 +01:00
2015-10-22 20:26:56 +02:00
std :: vector < ChatCommand > GetCommands () const override
2010-11-19 14:04:21 +01:00
{
2015-10-22 20:26:56 +02:00
static std :: vector < ChatCommand > gobjectAddCommandTable =
2010-11-16 21:27:25 +01:00
{
2015-10-22 20:26:56 +02:00
{ "temp" , rbac :: RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP , false , & HandleGameObjectAddTempCommand , "" },
{ "" , rbac :: RBAC_PERM_COMMAND_GOBJECT_ADD , false , & HandleGameObjectAddCommand , "" },
2010-11-19 14:04:21 +01:00
};
2015-10-22 20:26:56 +02:00
static std :: vector < ChatCommand > gobjectSetCommandTable =
2010-11-19 14:04:21 +01:00
{
2015-10-22 20:26:56 +02:00
{ "phase" , rbac :: RBAC_PERM_COMMAND_GOBJECT_SET_PHASE , false , & HandleGameObjectSetPhaseCommand , "" },
{ "state" , rbac :: RBAC_PERM_COMMAND_GOBJECT_SET_STATE , false , & HandleGameObjectSetStateCommand , "" },
2010-11-19 14:04:21 +01:00
};
2015-10-22 20:26:56 +02:00
static std :: vector < ChatCommand > gobjectCommandTable =
2010-11-19 14:04:21 +01:00
{
2017-05-07 21:48:41 +01:00
{ "activate" , rbac :: RBAC_PERM_COMMAND_GOBJECT_ACTIVATE , false , & HandleGameObjectActivateCommand , "" },
{ "delete" , rbac :: RBAC_PERM_COMMAND_GOBJECT_DELETE , false , & HandleGameObjectDeleteCommand , "" },
{ "info" , rbac :: RBAC_PERM_COMMAND_GOBJECT_INFO , false , & HandleGameObjectInfoCommand , "" },
{ "move" , rbac :: RBAC_PERM_COMMAND_GOBJECT_MOVE , false , & HandleGameObjectMoveCommand , "" },
{ "near" , rbac :: RBAC_PERM_COMMAND_GOBJECT_NEAR , false , & HandleGameObjectNearCommand , "" },
{ "target" , rbac :: RBAC_PERM_COMMAND_GOBJECT_TARGET , false , & HandleGameObjectTargetCommand , "" },
{ "turn" , rbac :: RBAC_PERM_COMMAND_GOBJECT_TURN , false , & HandleGameObjectTurnCommand , "" },
2020-09-04 13:38:24 +02:00
{ "spawngroup" , rbac :: RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP , false , & HandleNpcSpawnGroup , "" },
{ "despawngroup" , rbac :: RBAC_PERM_COMMAND_GOBJECT_DESPAWNGROUP , false , & HandleNpcDespawnGroup , "" },
2017-05-07 21:48:41 +01:00
{ "add" , rbac :: RBAC_PERM_COMMAND_GOBJECT_ADD , false , nullptr , "" , gobjectAddCommandTable },
{ "set" , rbac :: RBAC_PERM_COMMAND_GOBJECT_SET , false , nullptr , "" , gobjectSetCommandTable },
2010-11-19 14:04:21 +01:00
};
2015-10-22 20:26:56 +02:00
static std :: vector < ChatCommand > commandTable =
2010-11-19 14:04:21 +01:00
{
2020-08-14 17:06:03 +02:00
{ "gobject" , rbac :: RBAC_PERM_COMMAND_GOBJECT , false , nullptr , "" , gobjectCommandTable },
2010-11-19 14:04:21 +01:00
};
return commandTable ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectActivateCommand ( ChatHandler * handler , GameObjectSpawnId guidLow )
2010-11-19 14:04:21 +01:00
{
2017-03-11 12:29:37 +01:00
GameObject * object = handler -> GetObjectFromPlayerMapByDbGuid ( guidLow );
2011-10-10 10:33:13 -03:00
if ( ! object )
2010-11-19 14:04:21 +01:00
{
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , std :: to_string ( guidLow ). c_str ());
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
2017-06-18 15:23:45 +02:00
uint32_t const autoCloseTime = object -> GetGOInfo () -> GetAutoCloseTime () ? 10000u : 0u ;
2010-11-19 14:04:21 +01:00
// Activate
2011-10-10 10:33:13 -03:00
object -> SetLootState ( GO_READY );
2017-06-18 15:23:45 +02:00
object -> UseDoorOrButton ( autoCloseTime , false , handler -> GetSession () -> GetPlayer ());
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
handler -> PSendSysMessage ( "Object activated!" );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
//spawn go
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectAddCommand ( ChatHandler * handler , GameObjectEntry objectId , Optional < int32 > spawnTimeSecs )
2010-11-19 14:04:21 +01:00
{
2011-10-10 10:33:13 -03:00
if ( ! objectId )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2016-09-03 22:30:51 +02:00
GameObjectTemplate const * objectInfo = sObjectMgr -> GetGameObjectTemplate ( objectId );
2011-10-10 10:33:13 -03:00
if ( ! objectInfo )
2010-11-19 14:04:21 +01:00
{
2011-10-10 10:33:13 -03:00
handler -> PSendSysMessage ( LANG_GAMEOBJECT_NOT_EXIST , objectId );
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
if ( objectInfo -> displayId && ! sGameObjectDisplayInfoStore . LookupEntry ( objectInfo -> displayId ))
2010-11-19 14:04:21 +01:00
{
// report to DB errors log as in loading case
2020-09-03 22:16:57 +02:00
TC_LOG_ERROR ( "sql.sql" , "Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned." , * objectId , objectInfo -> type , objectInfo -> displayId );
2011-10-10 10:33:13 -03:00
handler -> PSendSysMessage ( LANG_GAMEOBJECT_HAVE_INVALID_DATA , objectId );
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
Player * player = handler -> GetSession () -> GetPlayer ();
Map * map = player -> GetMap ();
2010-11-16 21:27:25 +01:00
2018-01-27 21:47:37 +01:00
GameObject * object = GameObject :: CreateGameObject ( objectInfo -> entry , map , * player , QuaternionData :: fromEulerAnglesZYX ( player -> GetOrientation (), 0.0f , 0.0f ), 255 , GO_STATE_READY );
if ( ! object )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2018-01-28 11:37:20 +01:00
PhasingHandler :: InheritPhaseShift ( object , player );
2014-06-01 22:27:29 -05:00
2020-09-03 22:16:57 +02:00
if ( spawnTimeSecs )
object -> SetRespawnTime ( * spawnTimeSecs );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
// fill the gameobject data and save to the db
2018-09-15 17:55:26 +02:00
object -> SaveToDB ( map -> GetId (), { map -> GetDifficultyID () });
2016-06-12 00:11:00 +02:00
ObjectGuid :: LowType spawnId = object -> GetSpawnId ();
2015-05-16 12:12:47 +02:00
2014-04-13 16:02:41 +02:00
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
// this is required to avoid weird behavior and memory leaks
2014-04-13 15:01:20 +02:00
delete object ;
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
// this will generate a new guid if the object is in an instance
2018-01-27 21:47:37 +01:00
object = GameObject :: CreateGameObjectFromDB ( spawnId , map );
if ( ! object )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2013-03-08 21:41:30 +01:00
/// @todo is it really necessary to add both the real and DB table guid here ?
2021-12-28 14:24:10 +02:00
sObjectMgr -> AddGameobjectToGrid ( ASSERT_NOTNULL ( sObjectMgr -> GetGameObjectData ( spawnId )));
2010-11-16 21:27:25 +01:00
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_GAMEOBJECT_ADD , objectId , objectInfo -> name . c_str (), std :: to_string ( spawnId ). c_str (), player -> GetPositionX (), player -> GetPositionY (), player -> GetPositionZ ());
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
// add go, temp only
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectAddTempCommand ( ChatHandler * handler , GameObjectEntry objectId , Optional < uint64 > spawntime )
2010-11-19 14:04:21 +01:00
{
2011-10-10 10:33:13 -03:00
Player * player = handler -> GetSession () -> GetPlayer ();
2020-09-03 22:16:57 +02:00
Seconds spawntm ( spawntime . value_or ( 300 ));
2010-11-16 21:27:25 +01:00
2014-04-12 14:45:51 +02:00
if ( ! sObjectMgr -> GetGameObjectTemplate ( objectId ))
{
handler -> PSendSysMessage ( LANG_GAMEOBJECT_NOT_EXIST , objectId );
handler -> SetSentErrorMessage ( true );
return false ;
}
2017-06-04 01:00:45 +02:00
player -> SummonGameObject ( objectId , * player , QuaternionData :: fromEulerAnglesZYX ( player -> GetOrientation (), 0.0f , 0.0f ), spawntm );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectTargetCommand ( ChatHandler * handler , Optional < Variant < GameObjectEntry , std :: string_view >> objectId )
2010-11-16 21:27:25 +01:00
{
2011-10-10 10:33:13 -03:00
Player * player = handler -> GetSession () -> GetPlayer ();
2010-11-19 14:04:21 +01:00
QueryResult result ;
2010-12-22 21:25:23 +01:00
GameEventMgr :: ActiveEvents const & activeEventsList = sGameEventMgr -> GetActiveEventList ();
2011-10-10 10:33:13 -03:00
2020-09-03 22:16:57 +02:00
if ( objectId )
2010-11-19 14:04:21 +01:00
{
2020-09-03 22:16:57 +02:00
if ( objectId -> holds_alternative < GameObjectEntry > ())
{
2015-04-05 20:55:49 +02:00
result = WorldDatabase . PQuery ( "SELECT guid, id, position_x, position_y, position_z, orientation, map, PhaseId, PhaseGroup, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1" ,
2020-09-03 22:16:57 +02:00
player -> GetPositionX (), player -> GetPositionY (), player -> GetPositionZ (), player -> GetMapId (), static_cast < uint32 > ( objectId -> get < GameObjectEntry > ()));
}
2010-11-19 14:04:21 +01:00
else
{
2020-09-03 22:16:57 +02:00
std :: string name = std :: string ( objectId -> get < std :: string_view > ());
2011-06-30 14:52:44 +02:00
WorldDatabase . EscapeString ( name );
2010-11-19 14:04:21 +01:00
result = WorldDatabase . PQuery (
2015-04-05 20:55:49 +02:00
"SELECT guid, id, position_x, position_y, position_z, orientation, map, PhaseId, PhaseGroup, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ "
2017-05-12 18:49:51 +02:00
"FROM gameobject LEFT JOIN gameobject_template ON gameobject_template.entry = gameobject.id WHERE map = %i AND name LIKE '%%%s%%' ORDER BY order_ ASC LIMIT 1" ,
2011-10-10 10:33:13 -03:00
player -> GetPositionX (), player -> GetPositionY (), player -> GetPositionZ (), player -> GetMapId (), name . c_str ());
2010-11-19 14:04:21 +01:00
}
}
2010-11-16 21:27:25 +01:00
else
{
2010-11-19 14:04:21 +01:00
std :: ostringstream eventFilter ;
2011-03-19 18:10:28 +01:00
eventFilter << " AND (eventEntry IS NULL " ;
2010-11-19 14:04:21 +01:00
bool initString = true ;
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
for ( GameEventMgr :: ActiveEvents :: const_iterator itr = activeEventsList . begin (); itr != activeEventsList . end (); ++ itr )
2010-11-16 21:27:25 +01:00
{
2010-11-19 14:04:21 +01:00
if ( initString )
{
2011-10-10 10:33:13 -03:00
eventFilter << "OR eventEntry IN (" << * itr ;
initString = false ;
2010-11-19 14:04:21 +01:00
}
else
2011-07-29 14:18:28 +02:00
eventFilter << ',' << * itr ;
2010-11-16 21:27:25 +01:00
}
2010-11-19 14:04:21 +01:00
if ( ! initString )
eventFilter << "))" ;
else
2011-07-29 14:18:28 +02:00
eventFilter << ')' ;
2010-11-16 21:27:25 +01:00
2015-04-05 20:55:49 +02:00
result = WorldDatabase . PQuery ( "SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, PhaseId, PhaseGroup, "
2010-11-19 14:04:21 +01:00
"(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
2011-03-18 18:49:15 +01:00
"LEFT OUTER JOIN game_event_gameobject on gameobject.guid = game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10" ,
handler -> GetSession () -> GetPlayer () -> GetPositionX (), handler -> GetSession () -> GetPlayer () -> GetPositionY (), handler -> GetSession () -> GetPlayer () -> GetPositionZ (),
2011-04-29 20:47:02 +02:00
handler -> GetSession () -> GetPlayer () -> GetMapId (), eventFilter . str (). c_str ());
2010-11-19 14:04:21 +01:00
}
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
if ( ! result )
{
handler -> SendSysMessage ( LANG_COMMAND_TARGETOBJNOTFOUND );
return true ;
}
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
bool found = false ;
float x , y , z , o ;
2014-10-26 02:57:28 +02:00
ObjectGuid :: LowType guidLow ;
2015-04-05 20:55:49 +02:00
uint32 id , phaseId , phaseGroup ;
2013-07-19 04:03:40 +01:00
uint16 mapId ;
2011-10-10 10:33:13 -03:00
uint32 poolId ;
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2015-04-05 20:55:49 +02:00
guidLow = fields [ 0 ]. GetUInt64 ();
id = fields [ 1 ]. GetUInt32 ();
x = fields [ 2 ]. GetFloat ();
y = fields [ 3 ]. GetFloat ();
z = fields [ 4 ]. GetFloat ();
o = fields [ 5 ]. GetFloat ();
mapId = fields [ 6 ]. GetUInt16 ();
phaseId = fields [ 7 ]. GetUInt32 ();
phaseGroup = fields [ 8 ]. GetUInt32 ();
2011-10-10 10:33:13 -03:00
poolId = sPoolMgr -> IsPartOfAPool < GameObject > ( guidLow );
if ( ! poolId || sPoolMgr -> IsSpawnedObject < GameObject > ( guidLow ))
2010-11-19 14:04:21 +01:00
found = true ;
2011-10-10 10:33:13 -03:00
} while ( result -> NextRow () && ! found );
2010-11-19 14:04:21 +01:00
if ( ! found )
{
2011-04-29 20:47:02 +02:00
handler -> PSendSysMessage ( LANG_GAMEOBJECT_NOT_EXIST , id );
2010-11-19 14:04:21 +01:00
return false ;
}
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
GameObjectTemplate const * objectInfo = sObjectMgr -> GetGameObjectTemplate ( id );
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
if ( ! objectInfo )
2010-11-19 14:04:21 +01:00
{
2011-04-29 20:47:02 +02:00
handler -> PSendSysMessage ( LANG_GAMEOBJECT_NOT_EXIST , id );
2010-11-19 14:04:21 +01:00
return false ;
}
2010-11-16 21:27:25 +01:00
2017-03-11 12:29:37 +01:00
GameObject * target = handler -> GetObjectFromPlayerMapByDbGuid ( guidLow );
2010-11-16 21:27:25 +01:00
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_GAMEOBJECT_DETAIL , std :: to_string ( guidLow ). c_str (), objectInfo -> name . c_str (), std :: to_string ( guidLow ). c_str (), id , x , y , z , mapId , o , phaseId , phaseGroup );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
if ( target )
{
2017-12-10 12:39:37 +01:00
int32 curRespawnDelay = int32 ( target -> GetRespawnTimeEx () - GameTime :: GetGameTime ());
2010-11-19 14:04:21 +01:00
if ( curRespawnDelay < 0 )
curRespawnDelay = 0 ;
2010-11-16 21:27:25 +01:00
2020-02-23 00:31:37 +04:00
std :: string curRespawnDelayStr = secsToTimeString ( curRespawnDelay , TimeFormat :: ShortText );
std :: string defRespawnDelayStr = secsToTimeString ( target -> GetRespawnDelay (), TimeFormat :: ShortText );
2010-11-16 21:27:25 +01:00
2011-04-29 20:47:02 +02:00
handler -> PSendSysMessage ( LANG_COMMAND_RAWPAWNTIMES , defRespawnDelayStr . c_str (), curRespawnDelayStr . c_str ());
2010-11-19 14:04:21 +01:00
}
return true ;
2010-11-16 21:27:25 +01:00
}
2010-11-19 14:04:21 +01:00
//delete object by selection or guid
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectDeleteCommand ( ChatHandler * handler , GameObjectSpawnId spawnId )
2010-11-19 14:04:21 +01:00
{
2019-07-08 11:33:09 +02:00
if ( GameObject * object = handler -> GetObjectFromPlayerMapByDbGuid ( spawnId ))
2010-11-19 14:04:21 +01:00
{
2019-07-08 11:33:09 +02:00
Player const * const player = handler -> GetSession () -> GetPlayer ();
ObjectGuid ownerGuid = object -> GetOwnerGUID ();
if ( ! ownerGuid . IsEmpty ())
2010-11-19 14:04:21 +01:00
{
2019-07-08 11:33:09 +02:00
Unit * owner = ObjectAccessor :: GetUnit ( * player , ownerGuid );
if ( ! owner || ! ownerGuid . IsPlayer ())
{
handler -> PSendSysMessage ( LANG_COMMAND_DELOBJREFERCREATURE , ownerGuid . GetCounter (), spawnId );
handler -> SetSentErrorMessage ( true );
return false ;
}
owner -> RemoveGameObject ( object , false );
2010-11-19 14:04:21 +01:00
}
}
2010-11-16 21:27:25 +01:00
2019-07-08 11:33:09 +02:00
if ( GameObject :: DeleteFromDB ( spawnId ))
{
handler -> PSendSysMessage ( LANG_COMMAND_DELOBJMESSAGE , std :: to_string ( spawnId ));
return true ;
}
else
{
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , std :: to_string ( spawnId ));
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
}
2010-11-19 14:04:21 +01:00
//turn selected object
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectTurnCommand ( ChatHandler * handler , GameObjectSpawnId guidLow , Optional < float > oz , Optional < float > oy , Optional < float > ox )
2010-11-16 21:27:25 +01:00
{
2011-10-10 10:33:13 -03:00
if ( ! guidLow )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2017-03-11 12:29:37 +01:00
GameObject * object = handler -> GetObjectFromPlayerMapByDbGuid ( guidLow );
2011-10-10 10:33:13 -03:00
if ( ! object )
2010-11-19 14:04:21 +01:00
{
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , std :: to_string ( guidLow ). c_str ());
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
if ( ! oz )
oz = handler -> GetSession () -> GetPlayer () -> GetOrientation ();
2010-11-16 21:27:25 +01:00
2015-09-25 21:26:31 +02:00
Map * map = object -> GetMap ();
2020-09-03 22:16:57 +02:00
object -> Relocate ( object -> GetPositionX (), object -> GetPositionY (), object -> GetPositionZ (), * oz );
object -> SetLocalRotationAngles ( * oz , oy . value_or ( 0.0f ), ox . value_or ( 0.0f ));
2011-10-10 10:33:13 -03:00
object -> SaveToDB ();
2010-11-16 21:27:25 +01:00
2015-09-25 21:26:31 +02:00
// Generate a completely new spawn with new guid
// 3.3.5a client caches recently deleted objects and brings them back to life
// when CreateObject block for this guid is received again
// however it entirely skips parsing that block and only uses already known location
object -> Delete ();
object = GameObject :: CreateGameObjectFromDB ( guidLow , map );
if ( ! object )
return false ;
2010-11-16 21:27:25 +01:00
2015-09-25 21:26:31 +02:00
handler -> PSendSysMessage ( LANG_COMMAND_TURNOBJMESSAGE , std :: to_string ( object -> GetSpawnId ()). c_str (), object -> GetGOInfo () -> name . c_str (), object -> GetGUID (). ToString (). c_str (), object -> GetOrientation ());
2010-11-19 14:04:21 +01:00
return true ;
2010-11-16 21:27:25 +01:00
}
2010-11-19 14:04:21 +01:00
//move selected object
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectMoveCommand ( ChatHandler * handler , GameObjectSpawnId guidLow , Optional < std :: array < float , 3 >> xyz )
2010-11-16 21:27:25 +01:00
{
2011-10-10 10:33:13 -03:00
if ( ! guidLow )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2017-03-11 12:29:37 +01:00
GameObject * object = handler -> GetObjectFromPlayerMapByDbGuid ( guidLow );
2011-10-10 10:33:13 -03:00
if ( ! object )
2010-11-16 21:27:25 +01:00
{
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , std :: to_string ( guidLow ). c_str ());
2010-11-16 21:27:25 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
2020-09-03 22:16:57 +02:00
Position pos ;
if ( xyz )
2010-11-19 14:04:21 +01:00
{
2020-09-03 22:16:57 +02:00
pos = { ( * xyz )[ 0 ], ( * xyz )[ 1 ], ( * xyz )[ 2 ] };
if ( ! MapManager :: IsValidMapCoord ( object -> GetMapId (), pos ))
2010-11-19 14:04:21 +01:00
{
2020-09-03 22:16:57 +02:00
handler -> PSendSysMessage ( LANG_INVALID_TARGET_COORD , pos . GetPositionX (), pos . GetPositionY (), object -> GetMapId ());
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
}
2020-09-03 22:16:57 +02:00
else
{
pos = handler -> GetSession () -> GetPlayer () -> GetPosition ();
}
2010-11-16 21:27:25 +01:00
2015-09-25 21:26:31 +02:00
Map * map = object -> GetMap ();
2015-06-07 00:09:08 +02:00
2020-09-03 22:16:57 +02:00
pos . SetOrientation ( object -> GetOrientation ());
object -> Relocate ( pos );
2019-01-15 16:54:57 +01:00
// update which cell has this gameobject registered for loading
2021-12-28 14:24:10 +02:00
sObjectMgr -> RemoveGameobjectFromGrid ( object -> GetGameObjectData ());
2011-10-10 10:33:13 -03:00
object -> SaveToDB ();
2021-12-28 14:24:10 +02:00
sObjectMgr -> AddGameobjectToGrid ( object -> GetGameObjectData ());
2010-11-16 21:27:25 +01:00
2015-09-25 21:26:31 +02:00
// Generate a completely new spawn with new guid
// 3.3.5a client caches recently deleted objects and brings them back to life
// when CreateObject block for this guid is received again
// however it entirely skips parsing that block and only uses already known location
object -> Delete ();
2010-11-16 21:27:25 +01:00
2015-09-25 21:26:31 +02:00
object = GameObject :: CreateGameObjectFromDB ( guidLow , map );
if ( ! object )
return false ;
handler -> PSendSysMessage ( LANG_COMMAND_MOVEOBJMESSAGE , std :: to_string ( object -> GetSpawnId ()). c_str (), object -> GetGOInfo () -> name . c_str (), object -> GetGUID (). ToString (). c_str ());
2010-11-19 14:04:21 +01:00
return true ;
2010-11-16 21:27:25 +01:00
}
2011-10-10 10:33:13 -03:00
//set phasemask for selected object
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectSetPhaseCommand ( ChatHandler * handler , GameObjectSpawnId guidLow , uint32 phaseId )
2010-11-16 21:27:25 +01:00
{
2011-10-10 10:33:13 -03:00
if ( ! guidLow )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2017-03-11 12:29:37 +01:00
GameObject * object = handler -> GetObjectFromPlayerMapByDbGuid ( guidLow );
2011-10-10 10:33:13 -03:00
if ( ! object )
2010-11-16 21:27:25 +01:00
{
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , std :: to_string ( guidLow ). c_str ());
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
if ( ! phaseId )
2010-11-19 14:04:21 +01:00
{
handler -> SendSysMessage ( LANG_BAD_VALUE );
handler -> SetSentErrorMessage ( true );
return false ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
PhasingHandler :: AddPhase ( object , phaseId , true );
object -> SaveToDB ();
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectNearCommand ( ChatHandler * handler , Optional < float > dist )
2010-11-19 14:04:21 +01:00
{
2020-09-03 22:16:57 +02:00
float distance = dist . value_or ( 10.0f );
2010-11-19 14:04:21 +01:00
uint32 count = 0 ;
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
Player * player = handler -> GetSession () -> GetPlayer ();
2012-03-24 01:25:08 +01:00
2019-07-27 01:00:37 +02:00
WorldDatabasePreparedStatement * stmt = WorldDatabase . GetPreparedStatement ( WORLD_SEL_GAMEOBJECT_NEAREST );
2012-03-24 01:25:08 +01:00
stmt -> setFloat ( 0 , player -> GetPositionX ());
stmt -> setFloat ( 1 , player -> GetPositionY ());
stmt -> setFloat ( 2 , player -> GetPositionZ ());
stmt -> setUInt32 ( 3 , player -> GetMapId ());
stmt -> setFloat ( 4 , player -> GetPositionX ());
stmt -> setFloat ( 5 , player -> GetPositionY ());
stmt -> setFloat ( 6 , player -> GetPositionZ ());
stmt -> setFloat ( 7 , distance * distance );
PreparedQueryResult result = WorldDatabase . Query ( stmt );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
if ( result )
{
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2014-10-26 02:57:28 +02:00
ObjectGuid :: LowType guid = fields [ 0 ]. GetUInt64 ();
2010-11-19 14:04:21 +01:00
uint32 entry = fields [ 1 ]. GetUInt32 ();
float x = fields [ 2 ]. GetFloat ();
float y = fields [ 3 ]. GetFloat ();
float z = fields [ 4 ]. GetFloat ();
2011-10-10 10:33:13 -03:00
uint16 mapId = fields [ 5 ]. GetUInt16 ();
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
GameObjectTemplate const * gameObjectInfo = sObjectMgr -> GetGameObjectTemplate ( entry );
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
if ( ! gameObjectInfo )
2010-11-19 14:04:21 +01:00
continue ;
2010-11-16 21:27:25 +01:00
2017-05-07 21:48:41 +01:00
handler -> PSendSysMessage ( LANG_GO_LIST_CHAT , std :: to_string ( guid ). c_str (), entry , std :: to_string ( guid ). c_str (), gameObjectInfo -> name . c_str (), x , y , z , mapId , "" , "" );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
++ count ;
} while ( result -> NextRow ());
}
2011-04-29 20:47:02 +02:00
handler -> PSendSysMessage ( LANG_COMMAND_NEAROBJMESSAGE , distance , count );
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
//show info of gameobject
2020-09-10 15:19:17 +02:00
static bool HandleGameObjectInfoCommand ( ChatHandler * handler , Optional < EXACT_SEQUENCE ( "guid" ) > isGuid , Variant < Hyperlink < gameobject_entry > , Hyperlink < gameobject > , uint32 > data )
2010-11-19 14:04:21 +01:00
{
uint32 entry = 0 ;
uint32 type = 0 ;
2011-10-10 10:33:13 -03:00
uint32 displayId = 0 ;
2010-11-19 14:04:21 +01:00
std :: string name ;
uint32 lootId = 0 ;
2018-10-28 11:07:56 +02:00
GameObject * thisGO = nullptr ;
2020-09-03 22:16:57 +02:00
GameObjectData const * spawnData = nullptr ;
2018-10-28 11:07:56 +02:00
2018-02-24 20:57:55 -03:00
ObjectGuid :: LowType spawnId = 0 ;
2020-09-03 22:16:57 +02:00
if ( isGuid || data . holds_alternative < Hyperlink < gameobject >> ())
2010-11-22 10:10:46 +01:00
{
2020-09-03 22:16:57 +02:00
spawnId = * data ;
spawnData = sObjectMgr -> GetGameObjectData ( spawnId );
if ( ! spawnData )
2018-10-28 11:07:56 +02:00
{
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , spawnId );
handler -> SetSentErrorMessage ( true );
2017-03-11 12:29:37 +01:00
return false ;
2018-10-28 11:07:56 +02:00
}
2020-09-03 22:16:57 +02:00
entry = spawnData -> id ;
2018-10-28 11:07:56 +02:00
thisGO = handler -> GetObjectFromPlayerMapByDbGuid ( spawnId );
2017-03-11 12:29:37 +01:00
}
else
{
2020-09-03 22:16:57 +02:00
entry = * data ;
2017-03-11 12:29:37 +01:00
}
2010-11-16 21:27:25 +01:00
2011-10-10 10:33:13 -03:00
GameObjectTemplate const * gameObjectInfo = sObjectMgr -> GetGameObjectTemplate ( entry );
if ( ! gameObjectInfo )
2018-10-28 11:07:56 +02:00
{
handler -> PSendSysMessage ( LANG_GAMEOBJECT_NOT_EXIST , entry );
handler -> SetSentErrorMessage ( true );
2010-11-19 14:04:21 +01:00
return false ;
2018-10-28 11:07:56 +02:00
}
2017-05-07 21:48:41 +01:00
2011-10-10 10:33:13 -03:00
type = gameObjectInfo -> type ;
displayId = gameObjectInfo -> displayId ;
name = gameObjectInfo -> name ;
2014-10-30 20:02:42 +01:00
lootId = gameObjectInfo -> GetLootId ();
2010-11-16 21:27:25 +01:00
2017-05-07 21:48:41 +01:00
// If we have a real object, send some info about it
if ( thisGO )
{
handler -> PSendSysMessage ( LANG_SPAWNINFO_GUIDINFO , thisGO -> GetGUID (). ToString (). c_str ());
2018-10-28 11:07:56 +02:00
handler -> PSendSysMessage ( LANG_SPAWNINFO_COMPATIBILITY_MODE , thisGO -> GetRespawnCompatibilityMode ());
2018-02-15 09:11:28 -06:00
2018-07-18 14:19:24 +02:00
if ( thisGO -> GetGameObjectData () && thisGO -> GetGameObjectData () -> spawnGroupData -> groupId )
2017-05-07 21:48:41 +01:00
{
2018-07-18 14:19:24 +02:00
SpawnGroupTemplateData const * groupData = thisGO -> GetGameObjectData () -> spawnGroupData ;
handler -> PSendSysMessage ( LANG_SPAWNINFO_GROUP_ID , groupData -> name . c_str (), groupData -> groupId , groupData -> flags , thisGO -> GetMap () -> IsSpawnGroupActive ( groupData -> groupId ));
2017-05-07 21:48:41 +01:00
}
2018-02-15 09:11:28 -06:00
2018-10-28 11:07:56 +02:00
GameObjectOverride const * goOverride = sObjectMgr -> GetGameObjectOverride ( spawnId );
if ( ! goOverride )
goOverride = sObjectMgr -> GetGameObjectTemplateAddon ( entry );
if ( goOverride )
handler -> PSendSysMessage ( LANG_GOINFO_ADDON , goOverride -> Faction , goOverride -> Flags );
}
2020-09-03 22:16:57 +02:00
if ( spawnData )
2018-10-28 11:07:56 +02:00
{
float yaw , pitch , roll ;
2020-09-03 22:16:57 +02:00
spawnData -> rotation . toEulerAnglesZYX ( yaw , pitch , roll );
handler -> PSendSysMessage ( LANG_SPAWNINFO_SPAWNID_LOCATION , std :: to_string ( spawnData -> spawnId ), spawnData -> spawnPoint . GetPositionX (), spawnData -> spawnPoint . GetPositionY (), spawnData -> spawnPoint . GetPositionZ ());
2018-10-28 11:07:56 +02:00
handler -> PSendSysMessage ( LANG_SPAWNINFO_ROTATION , yaw , pitch , roll );
2017-05-07 21:48:41 +01:00
}
2018-02-15 09:11:28 -06:00
2018-10-28 11:07:56 +02:00
handler -> PSendSysMessage ( LANG_GOINFO_ENTRY , entry );
handler -> PSendSysMessage ( LANG_GOINFO_TYPE , type );
handler -> PSendSysMessage ( LANG_GOINFO_LOOTID , lootId );
handler -> PSendSysMessage ( LANG_GOINFO_DISPLAYID , displayId );
2010-11-19 14:04:21 +01:00
handler -> PSendSysMessage ( LANG_GOINFO_NAME , name . c_str ());
2017-03-11 12:29:37 +01:00
handler -> PSendSysMessage ( LANG_GOINFO_SIZE , gameObjectInfo -> size );
2018-02-15 09:11:28 -06:00
handler -> PSendSysMessage ( LANG_OBJECTINFO_AIINFO , gameObjectInfo -> AIName . c_str (), sObjectMgr -> GetScriptName ( gameObjectInfo -> ScriptId ). c_str ());
2018-07-18 14:19:24 +02:00
if ( GameObjectAI const * ai = thisGO ? thisGO -> AI () : nullptr )
2020-09-12 19:42:10 +02:00
handler -> PSendSysMessage ( LANG_OBJECTINFO_AITYPE , GetTypeName ( * ai ). c_str ());
2018-02-15 09:11:28 -06:00
2017-03-11 12:29:37 +01:00
if ( GameObjectDisplayInfoEntry const * modelInfo = sGameObjectDisplayInfoStore . LookupEntry ( displayId ))
handler -> PSendSysMessage ( LANG_GOINFO_MODEL , modelInfo -> GeoBoxMax . X , modelInfo -> GeoBoxMax . Y , modelInfo -> GeoBoxMax . Z , modelInfo -> GeoBoxMin . X , modelInfo -> GeoBoxMin . Y , modelInfo -> GeoBoxMin . Z );
2010-11-16 21:27:25 +01:00
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
static bool HandleGameObjectSetStateCommand ( ChatHandler * handler , GameObjectSpawnId guidLow , int32 objectType , Optional < int32 > objectState )
2010-11-16 21:27:25 +01:00
{
2011-10-10 10:33:13 -03:00
if ( ! guidLow )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2017-03-11 12:29:37 +01:00
GameObject * object = handler -> GetObjectFromPlayerMapByDbGuid ( guidLow );
2011-10-10 10:33:13 -03:00
if ( ! object )
2010-11-16 21:27:25 +01:00
{
2017-07-22 10:22:17 +03:00
handler -> PSendSysMessage ( LANG_COMMAND_OBJNOTFOUND , std :: to_string ( guidLow ). c_str ());
2010-11-19 14:04:21 +01:00
handler -> SetSentErrorMessage ( true );
2010-11-16 21:27:25 +01:00
return false ;
}
2011-10-10 10:33:13 -03:00
if ( objectType < 0 )
2010-11-19 14:04:21 +01:00
{
2011-10-10 10:33:13 -03:00
if ( objectType == - 1 )
2016-11-16 22:46:37 +01:00
object -> SendGameObjectDespawn ();
2011-10-10 10:33:13 -03:00
else if ( objectType == - 2 )
2010-11-19 14:04:21 +01:00
return false ;
return true ;
}
2010-11-16 21:27:25 +01:00
2020-09-03 22:16:57 +02:00
if ( ! objectState )
2010-11-19 14:04:21 +01:00
return false ;
2010-11-16 21:27:25 +01:00
2019-06-03 20:40:34 +02:00
switch ( objectType )
{
case 0 :
2020-09-03 22:16:57 +02:00
object -> SetGoState ( GOState ( * objectState ));
2019-06-03 20:40:34 +02:00
break ;
case 1 :
2020-09-03 22:16:57 +02:00
object -> SetGoType ( GameobjectTypes ( * objectState ));
2019-06-03 20:40:34 +02:00
break ;
case 2 :
2020-09-03 22:16:57 +02:00
object -> SetGoArtKit ( * objectState );
2019-06-03 20:40:34 +02:00
break ;
case 3 :
2020-09-03 22:16:57 +02:00
object -> SetGoAnimProgress ( * objectState );
2019-06-03 20:40:34 +02:00
break ;
case 4 :
2020-09-03 22:16:57 +02:00
object -> SendCustomAnim ( * objectState );
2019-06-03 20:40:34 +02:00
break ;
case 5 :
if ( objectState < 0 || objectState > GO_DESTRUCTIBLE_REBUILDING )
return false ;
2020-09-03 22:16:57 +02:00
object -> SetDestructibleState ( GameObjectDestructibleState ( * objectState ));
2019-06-03 20:40:34 +02:00
break ;
default :
break ;
2018-03-25 18:41:05 +02:00
}
2020-09-03 22:16:57 +02:00
handler -> PSendSysMessage ( "Set gobject type %d state %u" , objectType , * objectState );
2010-11-19 14:04:21 +01:00
return true ;
}
2010-11-16 21:27:25 +01:00
};
void AddSC_gobject_commandscript ()
{
new gobject_commandscript ();
}