/*
* Copyright (C) 2008-2011 TrinityCore
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
/* ScriptData
Name: npc_commandscript
%Complete: 100
Comment: All npc related commands
Category: commandscripts
EndScriptData */
#include "ScriptMgr.h"
#include "ObjectMgr.h"
#include "Chat.h"
#include "Transport.h"
#include "CreatureGroups.h"
#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
class npc_commandscript : public CommandScript
{
public:
npc_commandscript() : CommandScript("npc_commandscript") { }
ChatCommand* GetCommands() const
{
static ChatCommand npcAddCommandTable[] =
{
{ "formation", SEC_MODERATOR, false, &HandleNpcAddFormationCommand, "", NULL },
{ "item", SEC_GAMEMASTER, false, &HandleNpcAddVendorItemCommand, "", NULL },
{ "move", SEC_GAMEMASTER, false, &HandleNpcAddMoveCommand, "", NULL },
{ "temp", SEC_GAMEMASTER, false, &HandleNpcAddTempSpawnCommand, "", NULL },
//{ TODO: fix or remove this command
{ "weapon", SEC_ADMINISTRATOR, false, &HandleNpcAddWeaponCommand, "", NULL },
//}
{ "", SEC_GAMEMASTER, false, &HandleNpcAddCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand npcDeleteCommandTable[] =
{
{ "item", SEC_GAMEMASTER, false, &HandleNpcDeleteVendorItemCommand, "", NULL },
{ "", SEC_GAMEMASTER, false, &HandleNpcDeleteCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand npcFollowCommandTable[] =
{
{ "stop", SEC_GAMEMASTER, false, &HandleNpcUnFollowCommand, "", NULL },
{ "", SEC_GAMEMASTER, false, &HandleNpcFollowCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand npcSetCommandTable[] =
{
{ "allowmove", SEC_ADMINISTRATOR, false, &HandleNpcSetAllowMovementCommand, "", NULL },
{ "deathstate", SEC_GAMEMASTER, false, &HandleNpcSetDeathStateCommand, "", NULL },
{ "entry", SEC_ADMINISTRATOR, false, &HandleNpcSetEntryCommand, "", NULL },
{ "factionid", SEC_GAMEMASTER, false, &HandleNpcSetFactionIdCommand, "", NULL },
{ "flag", SEC_GAMEMASTER, false, &HandleNpcSetFlagCommand, "", NULL },
{ "level", SEC_GAMEMASTER, false, &HandleNpcSetLevelCommand, "", NULL },
{ "link", SEC_GAMEMASTER, false, &HandleNpcSetLinkCommand, "", NULL },
{ "model", SEC_GAMEMASTER, false, &HandleNpcSetModelCommand, "", NULL },
{ "movetype", SEC_GAMEMASTER, false, &HandleNpcSetMoveTypeCommand, "", NULL },
{ "phase", SEC_GAMEMASTER, false, &HandleNpcSetPhaseCommand, "", NULL },
{ "spawndist", SEC_GAMEMASTER, false, &HandleNpcSetSpawnDistCommand, "", NULL },
{ "spawntime", SEC_GAMEMASTER, false, &HandleNpcSetSpawnTimeCommand, "", NULL },
//{ TODO: fix or remove these commands
{ "name", SEC_GAMEMASTER, false, &HandleNpcSetNameCommand, "", NULL },
{ "subname", SEC_GAMEMASTER, false, &HandleNpcSetSubNameCommand, "", NULL },
//}
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand npcCommandTable[] =
{
{ "info", SEC_ADMINISTRATOR, false, &HandleNpcInfoCommand, "", NULL },
{ "move", SEC_GAMEMASTER, false, &HandleNpcMoveCommand, "", NULL },
{ "playemote", SEC_ADMINISTRATOR, false, &HandleNpcPlayEmoteCommand, "", NULL },
{ "say", SEC_MODERATOR, false, &HandleNpcSayCommand, "", NULL },
{ "textemote", SEC_MODERATOR, false, &HandleNpcTextEmoteCommand, "", NULL },
{ "whisper", SEC_MODERATOR, false, &HandleNpcWhisperCommand, "", NULL },
{ "yell", SEC_MODERATOR, false, &HandleNpcYellCommand, "", NULL },
{ "tame", SEC_GAMEMASTER, false, &HandleNpcTameCommand, "", NULL },
{ "add", SEC_GAMEMASTER, false, NULL, "", npcAddCommandTable },
{ "delete", SEC_GAMEMASTER, false, NULL, "", npcDeleteCommandTable },
{ "follow", SEC_GAMEMASTER, false, NULL, "", npcFollowCommandTable },
{ "set", SEC_GAMEMASTER, false, NULL, "", npcSetCommandTable },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
{
{ "npc", SEC_MODERATOR, false, NULL, "", npcCommandTable },
{ NULL, 0, false, NULL, "", NULL }
};
return commandTable;
}
//add spawn of creature
static bool HandleNpcAddCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* charID = handler->extractKeyFromLink((char*)args,"Hcreature_entry");
if (!charID)
return false;
char* team = strtok(NULL, " ");
int32 teamval = 0;
if (team) { teamval = atoi(team); }
if (teamval < 0) { teamval = 0; }
uint32 id = atoi(charID);
Player *chr = handler->GetSession()->GetPlayer();
float x = chr->GetPositionX();
float y = chr->GetPositionY();
float z = chr->GetPositionZ();
float o = chr->GetOrientation();
Map *map = chr->GetMap();
if (chr->GetTransport())
{
uint32 tguid = chr->GetTransport()->AddNPCPassenger(0, id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
if (tguid > 0)
WorldDatabase.PQuery("INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (%u, %u, %f, %f, %f, %f, %u)", tguid, id, chr->GetTransport()->GetEntry(), chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
return true;
}
Creature* pCreature = new Creature;
if (!pCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
{
delete pCreature;
return false;
}
pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
uint32 db_guid = pCreature->GetDBTableGUIDLow();
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
pCreature->LoadFromDB(db_guid, map);
map->Add(pCreature);
sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid));
return true;
}
//add item in vendorlist
static bool HandleNpcAddVendorItemCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* pitem = handler->extractKeyFromLink((char*)args,"Hitem");
if (!pitem)
{
handler->SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
handler->SetSentErrorMessage(true);
return false;
}
uint32 itemId = atol(pitem);
char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
uint32 maxcount = 0;
if (fmaxcount)
maxcount = atol(fmaxcount);
char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
uint32 incrtime = 0;
if (fincrtime)
incrtime = atol(fincrtime);
char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
Creature* vendor = handler->getSelectedCreature();
if (!vendor)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
if (!sObjectMgr->IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,handler->GetSession()->GetPlayer()))
{
handler->SetSentErrorMessage(true);
return false;
}
sObjectMgr->AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
handler->PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,itemTemplate->Name1,maxcount,incrtime,extendedcost);
return true;
}
//add move for creature
static bool HandleNpcAddMoveCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* guid_str = strtok((char*)args, " ");
char* wait_str = strtok((char*)NULL, " ");
uint32 lowguid = atoi((char*)guid_str);
Creature* pCreature = NULL;
/* FIXME: impossible without entry
if (lowguid)
pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
*/
// attempt check creature existence by DB data
if (!pCreature)
{
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
}
else
{
// obtain real GUID for DB operations
lowguid = pCreature->GetDBTableGUIDLow();
}
int wait = wait_str ? atoi(wait_str) : 0;
if (wait < 0)
wait = 0;
//Player* player = handler->GetSession()->GetPlayer();
//WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
// update movement type
WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
if (pCreature && pCreature->GetWaypointPath())
{
pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
pCreature->GetMotionMaster()->Initialize();
if (pCreature->isAlive()) // dead creature will reset movement generator at respawn
{
pCreature->setDeathState(JUST_DIED);
pCreature->Respawn(true);
}
pCreature->SaveToDB();
}
handler->SendSysMessage(LANG_WAYPOINT_ADDED);
return true;
}
static bool HandleNpcSetAllowMovementCommand(ChatHandler* handler, const char* /*args*/)
{
if (sWorld->getAllowMovement())
{
sWorld->SetAllowMovement(false);
handler->SendSysMessage(LANG_CREATURE_MOVE_DISABLED);
}
else
{
sWorld->SetAllowMovement(true);
handler->SendSysMessage(LANG_CREATURE_MOVE_ENABLED);
}
return true;
}
static bool HandleNpcSetEntryCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 newEntryNum = atoi(args);
if (!newEntryNum)
return false;
Unit* unit = handler->getSelectedUnit();
if (!unit || unit->GetTypeId() != TYPEID_UNIT)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
Creature* creature = unit->ToCreature();
if (creature->UpdateEntry(newEntryNum))
handler->SendSysMessage(LANG_DONE);
else
handler->SendSysMessage(LANG_ERROR);
return true;
}
//change level of creature or pet
static bool HandleNpcSetLevelCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint8 lvl = (uint8) atoi((char*)args);
if (lvl < 1 || lvl > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
if (pCreature->isPet())
{
if (((Pet*)pCreature)->getPetType() == HUNTER_PET)
{
pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr->GetXPForLevel(lvl)/4);
pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
}
((Pet*)pCreature)->GivePetLevel(lvl);
}
else
{
pCreature->SetMaxHealth(100 + 30*lvl);
pCreature->SetHealth(100 + 30*lvl);
pCreature->SetLevel(lvl);
pCreature->SaveToDB();
}
return true;
}
static bool HandleNpcDeleteCommand(ChatHandler* handler, const char* args)
{
Creature* unit = NULL;
if (*args)
{
// number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
char* cId = handler->extractKeyFromLink((char*)args,"Hcreature");
if (!cId)
return false;
uint32 lowguid = atoi(cId);
if (!lowguid)
return false;
if (CreatureData const* cr_data = sObjectMgr->GetCreatureData(lowguid))
unit = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
}
else
unit = handler->getSelectedCreature();
if (!unit || unit->isPet() || unit->isTotem())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
// Delete the creature
unit->CombatStop();
unit->DeleteFromDB();
unit->AddObjectToRemoveList();
handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
return true;
}
//del item from vendor list
static bool HandleNpcDeleteVendorItemCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
Creature* vendor = handler->getSelectedCreature();
if (!vendor || !vendor->isVendor())
{
handler->SendSysMessage(LANG_COMMAND_VENDORSELECTION);
handler->SetSentErrorMessage(true);
return false;
}
char* pitem = handler->extractKeyFromLink((char*)args,"Hitem");
if (!pitem)
{
handler->SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
handler->SetSentErrorMessage(true);
return false;
}
uint32 itemId = atol(pitem);
if (!sObjectMgr->RemoveVendorItem(vendor->GetEntry(),itemId))
{
handler->PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
handler->SetSentErrorMessage(true);
return false;
}
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
handler->PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,itemTemplate->Name1);
return true;
}
//set faction of creature
static bool HandleNpcSetFactionIdCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 factionId = (uint32) atoi((char*)args);
if (!sFactionTemplateStore.LookupEntry(factionId))
{
handler->PSendSysMessage(LANG_WRONG_FACTION, factionId);
handler->SetSentErrorMessage(true);
return false;
}
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->setFaction(factionId);
// faction is set in creature_template - not inside creature
// update in memory
if (CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
{
const_cast(cinfo)->faction_A = factionId;
const_cast(cinfo)->faction_H = factionId;
}
// and DB
WorldDatabase.PExecute("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
return true;
}
//set npcflag of creature
static bool HandleNpcSetFlagCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 npcFlags = (uint32) atoi((char*)args);
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
WorldDatabase.PExecute("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
handler->SendSysMessage(LANG_VALUE_SAVED_REJOIN);
return true;
}
//npc follow handling
static bool HandleNpcFollowCommand(ChatHandler* handler, const char* /*args*/)
{
Player *player = handler->GetSession()->GetPlayer();
Creature *creature = handler->getSelectedCreature();
if (!creature)
{
handler->PSendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
// Follow player - Using pet's default dist and angle
creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, creature->GetFollowAngle());
handler->PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
return true;
}
static bool HandleNpcInfoCommand(ChatHandler* handler, const char* /*args*/)
{
Creature* target = handler->getSelectedCreature();
if (!target)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
uint32 faction = target->getFaction();
uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS);
uint32 displayid = target->GetDisplayId();
uint32 nativeid = target->GetNativeDisplayId();
uint32 Entry = target->GetEntry();
CreatureInfo const* cInfo = target->GetCreatureInfo();
int64 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
if (curRespawnDelay < 0)
curRespawnDelay = 0;
std::string curRespawnDelayStr = secsToTimeString(uint64(curRespawnDelay),true);
std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), target->GetGUIDLow(), faction, npcflags, Entry, displayid, nativeid);
handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
handler->PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
handler->PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction());
handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
handler->PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid,cInfo->pickpocketLootId,cInfo->SkinLootId);
handler->PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId());
handler->PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask());
handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor());
handler->PSendSysMessage(LANG_NPCINFO_POSITION,float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ()));
if ((npcflags & UNIT_NPC_FLAG_VENDOR))
{
handler->SendSysMessage(LANG_NPCINFO_VENDOR);
}
if ((npcflags & UNIT_NPC_FLAG_TRAINER))
{
handler->SendSysMessage(LANG_NPCINFO_TRAINER);
}
return true;
}
//move selected creature
static bool HandleNpcMoveCommand(ChatHandler* handler, const char* args)
{
uint32 lowguid = 0;
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
// number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
char* cId = handler->extractKeyFromLink((char*)args,"Hcreature");
if (!cId)
return false;
lowguid = atoi(cId);
/* FIXME: impossible without entry
if (lowguid)
pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
*/
// Attempting creature load from DB data
if (!pCreature)
{
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
uint32 map_id = data->mapid;
if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
{
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
}
else
{
lowguid = pCreature->GetDBTableGUIDLow();
}
}
else
{
lowguid = pCreature->GetDBTableGUIDLow();
}
float x = handler->GetSession()->GetPlayer()->GetPositionX();
float y = handler->GetSession()->GetPlayer()->GetPositionY();
float z = handler->GetSession()->GetPlayer()->GetPositionZ();
float o = handler->GetSession()->GetPlayer()->GetOrientation();
if (pCreature)
{
if (CreatureData const* data = sObjectMgr->GetCreatureData(pCreature->GetDBTableGUIDLow()))
{
const_cast(data)->posX = x;
const_cast(data)->posY = y;
const_cast(data)->posZ = z;
const_cast(data)->orientation = o;
}
pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
pCreature->GetMotionMaster()->Initialize();
if (pCreature->isAlive()) // dead creature will reset movement generator at respawn
{
pCreature->setDeathState(JUST_DIED);
pCreature->Respawn();
}
}
WorldDatabase.PExecute("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
handler->PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
return true;
}
//play npc emote
static bool HandleNpcPlayEmoteCommand(ChatHandler* handler, const char* args)
{
uint32 emote = atoi((char*)args);
Creature* target = handler->getSelectedCreature();
if (!target)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
if (target->GetTransport())
if (target->GetGUIDTransport())
WorldDatabase.PQuery("UPDATE creature_transport SET emote=%u WHERE transport_entry=%u AND guid=%u", emote, target->GetTransport()->GetEntry(), target->GetGUIDTransport());
target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote);
return true;
}
//set model of creature
static bool HandleNpcSetModelCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 displayId = (uint32) atoi((char*)args);
Creature *pCreature = handler->getSelectedCreature();
if (!pCreature || pCreature->isPet())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->SetDisplayId(displayId);
pCreature->SetNativeDisplayId(displayId);
pCreature->SaveToDB();
return true;
}
/**HandleNpcSetMoveTypeCommand
* Set the movement type for an NPC.
*
* Valid movement types are:
*
* - stay - NPC wont move
* - random - NPC will move randomly according to the spawndist
* - way - NPC will move with given waypoints set
*
* additional parameter: NODEL - so no waypoints are deleted, if you
* change the movement type
*/
static bool HandleNpcSetMoveTypeCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
// 3 arguments:
// GUID (optional - you can also select the creature)
// stay|random|way (determines the kind of movement)
// NODEL (optional - tells the system NOT to delete any waypoints)
// this is very handy if you want to do waypoints, that are
// later switched on/off according to special events (like escort
// quests, etc)
char* guid_str = strtok((char*)args, " ");
char* type_str = strtok((char*)NULL, " ");
char* dontdel_str = strtok((char*)NULL, " ");
bool doNotDelete = false;
if (!guid_str)
return false;
uint32 lowguid = 0;
Creature* pCreature = NULL;
if (dontdel_str)
{
//sLog->outError("DEBUG: All 3 params are set");
// All 3 params are set
// GUID
// type
// doNotDEL
if (stricmp(dontdel_str, "NODEL") == 0)
{
//sLog->outError("DEBUG: doNotDelete = true;");
doNotDelete = true;
}
}
else
{
// Only 2 params - but maybe NODEL is set
if (type_str)
{
sLog->outError("DEBUG: Only 2 params ");
if (stricmp(type_str, "NODEL") == 0)
{
//sLog->outError("DEBUG: type_str, NODEL ");
doNotDelete = true;
type_str = NULL;
}
}
}
if (!type_str) // case .setmovetype $move_type (with selected creature)
{
type_str = guid_str;
pCreature = handler->getSelectedCreature();
if (!pCreature || pCreature->isPet())
return false;
lowguid = pCreature->GetDBTableGUIDLow();
}
else // case .setmovetype #creature_guid $move_type (with selected creature)
{
lowguid = atoi((char*)guid_str);
/* impossible without entry
if (lowguid)
pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
*/
// attempt check creature existence by DB data
if (!pCreature)
{
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
}
else
{
lowguid = pCreature->GetDBTableGUIDLow();
}
}
// now lowguid is low guid really existed creature
// and pCreature point (maybe) to this creature or NULL
MovementGeneratorType move_type;
std::string type = type_str;
if (type == "stay")
move_type = IDLE_MOTION_TYPE;
else if (type == "random")
move_type = RANDOM_MOTION_TYPE;
else if (type == "way")
move_type = WAYPOINT_MOTION_TYPE;
else
return false;
// update movement type
//if (doNotDelete == false)
// WaypointMgr.DeletePath(lowguid);
if (pCreature)
{
// update movement type
if (doNotDelete == false)
pCreature->LoadPath(0);
pCreature->SetDefaultMovementType(move_type);
pCreature->GetMotionMaster()->Initialize();
if (pCreature->isAlive()) // dead creature will reset movement generator at respawn
{
pCreature->setDeathState(JUST_DIED);
pCreature->Respawn();
}
pCreature->SaveToDB();
}
if (doNotDelete == false)
{
handler->PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
}
else
{
handler->PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
}
return true;
}
//npc phasemask handling
//change phasemask of creature or pet
static bool HandleNpcSetPhaseCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 phasemask = (uint32) atoi((char*)args);
if (phasemask == 0)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->SetPhaseMask(phasemask,true);
if (!pCreature->isPet())
pCreature->SaveToDB();
return true;
}
//set spawn dist of creature
static bool HandleNpcSetSpawnDistCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
float option = (float)(atof((char*)args));
if (option < 0.0f)
{
handler->SendSysMessage(LANG_BAD_VALUE);
return false;
}
MovementGeneratorType mtype = IDLE_MOTION_TYPE;
if (option >0.0f)
mtype = RANDOM_MOTION_TYPE;
Creature *pCreature = handler->getSelectedCreature();
uint32 u_guidlow = 0;
if (pCreature)
u_guidlow = pCreature->GetDBTableGUIDLow();
else
return false;
pCreature->SetRespawnRadius((float)option);
pCreature->SetDefaultMovementType(mtype);
pCreature->GetMotionMaster()->Initialize();
if (pCreature->isAlive()) // dead creature will reset movement generator at respawn
{
pCreature->setDeathState(JUST_DIED);
pCreature->Respawn();
}
WorldDatabase.PExecute("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
handler->PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
return true;
}
//spawn time handling
static bool HandleNpcSetSpawnTimeCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* stime = strtok((char*)args, " ");
if (!stime)
return false;
int i_stime = atoi((char*)stime);
if (i_stime < 0)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
Creature *pCreature = handler->getSelectedCreature();
uint32 u_guidlow = 0;
if (pCreature)
u_guidlow = pCreature->GetDBTableGUIDLow();
else
return false;
WorldDatabase.PExecute("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
pCreature->SetRespawnDelay((uint32)i_stime);
handler->PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
return true;
}
static bool HandleNpcSayCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->MonsterSay(args, LANG_UNIVERSAL, 0);
// make some emotes
char lastchar = args[strlen(args) - 1];
switch(lastchar)
{
case '?': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_QUESTION); break;
case '!': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); break;
default: pCreature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); break;
}
return true;
}
//show text emote by creature in chat
static bool HandleNpcTextEmoteCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->MonsterTextEmote(args, 0);
return true;
}
//npc unfollow handling
static bool HandleNpcUnFollowCommand(ChatHandler* handler, const char* /*args*/)
{
Player *player = handler->GetSession()->GetPlayer();
Creature *creature = handler->getSelectedCreature();
if (!creature)
{
handler->PSendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
if (/*creature->GetMotionMaster()->empty() ||*/
creature->GetMotionMaster()->GetCurrentMovementGeneratorType () != TARGETED_MOTION_TYPE)
{
handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName());
handler->SetSentErrorMessage(true);
return false;
}
TargetedMovementGenerator const* mgen
= static_cast const*>((creature->GetMotionMaster()->top()));
if (mgen->GetTarget() != player)
{
handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName());
handler->SetSentErrorMessage(true);
return false;
}
// reset movement
creature->GetMotionMaster()->MovementExpired(true);
handler->PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
return true;
}
// make npc whisper to player
static bool HandleNpcWhisperCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* receiver_str = strtok((char*)args, " ");
char* text = strtok(NULL, "");
uint64 guid = handler->GetSession()->GetPlayer()->GetSelection();
Creature* pCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(guid);
if (!pCreature || !receiver_str || !text)
{
return false;
}
uint64 receiver_guid= atol(receiver_str);
// check online security
if (handler->HasLowerSecurity(sObjectMgr->GetPlayer(receiver_guid), 0))
return false;
pCreature->MonsterWhisper(text,receiver_guid);
return true;
}
static bool HandleNpcYellCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->MonsterYell(args, LANG_UNIVERSAL, 0);
// make an emote
pCreature->HandleEmoteCommand(EMOTE_ONESHOT_SHOUT);
return true;
}
// add creature, temp only
static bool HandleNpcAddTempSpawnCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
char* charID = strtok((char*)args, " ");
if (!charID)
return false;
Player *chr = handler->GetSession()->GetPlayer();
uint32 id = atoi(charID);
if (!id)
return false;
chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120);
return true;
}
//npc tame handling
static bool HandleNpcTameCommand(ChatHandler* handler, const char* /*args*/)
{
Creature *creatureTarget = handler->getSelectedCreature ();
if (!creatureTarget || creatureTarget->isPet ())
{
handler->PSendSysMessage (LANG_SELECT_CREATURE);
handler->SetSentErrorMessage (true);
return false;
}
Player *player = handler->GetSession()->GetPlayer ();
if (player->GetPetGUID ())
{
handler->SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
handler->SetSentErrorMessage (true);
return false;
}
CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
if (!cInfo->isTameable (player->CanTameExoticPets()))
{
handler->PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
handler->SetSentErrorMessage (true);
return false;
}
// Everything looks OK, create new pet
Pet* pet = player->CreateTamedPetFrom (creatureTarget);
if (!pet)
{
handler->PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
handler->SetSentErrorMessage (true);
return false;
}
// place pet before player
float x,y,z;
player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
// set pet to defensive mode by default (some classes can't control controlled pets in fact).
pet->SetReactState(REACT_DEFENSIVE);
// calculate proper level
uint8 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
// prepare visual effect for levelup
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
// add to world
pet->GetMap()->Add(pet->ToCreature());
// visual effect for levelup
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
// caster have pet now
player->SetMinion(pet, true);
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
player->PetSpellInitialize();
return true;
}
//npc deathstate handling
static bool HandleNpcSetDeathStateCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature || pCreature->isPet())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
if (strncmp(args, "on", 3) == 0)
pCreature->SetDeadByDefault(true);
else if (strncmp(args, "off", 4) == 0)
pCreature->SetDeadByDefault(false);
else
{
handler->SendSysMessage(LANG_USE_BOL);
handler->SetSentErrorMessage(true);
return false;
}
pCreature->SaveToDB();
pCreature->Respawn();
return true;
}
static bool HandleNpcAddFormationCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 leaderGUID = (uint32) atoi((char*)args);
Creature *pCreature = handler->getSelectedCreature();
if (!pCreature || !pCreature->GetDBTableGUIDLow())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
uint32 lowguid = pCreature->GetDBTableGUIDLow();
if (pCreature->GetFormation())
{
handler->PSendSysMessage("Selected creature is already member of group %u", pCreature->GetFormation()->GetId());
return false;
}
if (!lowguid)
return false;
Player *chr = handler->GetSession()->GetPlayer();
FormationInfo *group_member;
group_member = new FormationInfo;
group_member->follow_angle = (pCreature->GetAngle(chr) - chr->GetOrientation()) * 180 / M_PI;
group_member->follow_dist = sqrtf(pow(chr->GetPositionX() - pCreature->GetPositionX(),int(2))+pow(chr->GetPositionY()-pCreature->GetPositionY(),int(2)));
group_member->leaderGUID = leaderGUID;
group_member->groupAI = 0;
CreatureGroupMap[lowguid] = group_member;
pCreature->SearchFormation();
WorldDatabase.PExecute("INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES ('%u','%u','%f', '%f', '%u')",
leaderGUID, lowguid, group_member->follow_dist, group_member->follow_angle, group_member->groupAI);
handler->PSendSysMessage("Creature %u added to formation with leader %u", lowguid, leaderGUID);
return true;
}
static bool HandleNpcSetLinkCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
uint32 linkguid = (uint32) atoi((char*)args);
Creature* pCreature = handler->getSelectedCreature();
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
if (!pCreature->GetDBTableGUIDLow())
{
handler->PSendSysMessage("Selected creature %u isn't in creature table", pCreature->GetGUIDLow());
handler->SetSentErrorMessage(true);
return false;
}
if (!sObjectMgr->SetCreatureLinkedRespawn(pCreature->GetDBTableGUIDLow(), linkguid))
{
handler->PSendSysMessage("Selected creature can't link with guid '%u'", linkguid);
handler->SetSentErrorMessage(true);
return false;
}
handler->PSendSysMessage("LinkGUID '%u' added to creature with DBTableGUID: '%u'", linkguid, pCreature->GetDBTableGUIDLow());
return true;
}
//TODO: NpcCommands that need to be fixed :
static bool HandleNpcAddWeaponCommand(ChatHandler* /*handler*/, const char* /*args*/)
{
/*if (!*args)
return false;
uint64 guid = handler->GetSession()->GetPlayer()->GetSelection();
if (guid == 0)
{
handler->SendSysMessage(LANG_NO_SELECTION);
return true;
}
Creature *pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), guid);
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
return true;
}
char* pSlotID = strtok((char*)args, " ");
if (!pSlotID)
return false;
char* pItemID = strtok(NULL, " ");
if (!pItemID)
return false;
uint32 ItemID = atoi(pItemID);
uint32 SlotID = atoi(pSlotID);
ItemPrototype* tmpItem = sObjectMgr->GetItemTemplate(ItemID);
bool added = false;
if (tmpItem)
{
switch(SlotID)
{
case 1:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID);
added = true;
break;
case 2:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID);
added = true;
break;
case 3:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID);
added = true;
break;
default:
handler->PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID);
added = false;
break;
}
if (added)
handler->PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID);
}
else
{
handler->PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID);
return true;
}
*/
return true;
}
static bool HandleNpcSetNameCommand(ChatHandler* /*handler*/, const char* /*args*/)
{
/* Temp. disabled
if (!*args)
return false;
if (strlen((char*)args)>75)
{
handler->PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
return true;
}
for (uint8 i = 0; i < strlen(args); ++i)
{
if (!isalpha(args[i]) && args[i] != ' ')
{
handler->SendSysMessage(LANG_CHARS_ONLY);
return false;
}
}
uint64 guid;
guid = handler->GetSession()->GetPlayer()->GetSelection();
if (guid == 0)
{
handler->SendSysMessage(LANG_NO_SELECTION);
return true;
}
Creature* pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), guid);
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
return true;
}
pCreature->SetName(args);
uint32 idname = sObjectMgr->AddCreatureTemplate(pCreature->GetName());
pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
pCreature->SaveToDB();
*/
return true;
}
static bool HandleNpcSetSubNameCommand(ChatHandler* /*handler*/, const char* /*args*/)
{
/* Temp. disabled
if (!*args)
args = "";
if (strlen((char*)args)>75)
{
handler->PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
return true;
}
for (uint8 i = 0; i < strlen(args); i++)
{
if (!isalpha(args[i]) && args[i] != ' ')
{
handler->SendSysMessage(LANG_CHARS_ONLY);
return false;
}
}
uint64 guid;
guid = handler->GetSession()->GetPlayer()->GetSelection();
if (guid == 0)
{
handler->SendSysMessage(LANG_NO_SELECTION);
return true;
}
Creature* pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), guid);
if (!pCreature)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
return true;
}
uint32 idname = sObjectMgr->AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
pCreature->SaveToDB();
*/
return true;
}
};
void AddSC_npc_commandscript()
{
new npc_commandscript();
}