gdle/Source/ClientCommands.cpp
2019-07-07 20:56:15 +00:00

5441 lines
141 KiB
C++

#include <StdAfx.h>
#include "Client.h"
#include "ClientEvents.h"
#include "ClientCommands.h"
#include "WeenieObject.h"
#include "Monster.h"
#include "Player.h"
#include "Door.h"
#include "Network.h"
#include "World.h"
#include "ChatMsgs.h"
#include "Portal.h"
#include "Database2.h"
#include "GameMode.h"
#include "Lifestone.h"
#include "Setup.h"
#include "WorldLandBlock.h"
#include "ClothingTable.h"
#include "PalSet.h"
#include "ClothingCache.h"
#include "GfxObj.h"
#include "Surface.h"
#include "ObjDesc.h"
#include "MotionTable.h"
#include "Movement.h"
#include "MovementManager.h"
#include "PartArray.h"
#include "MonsterAI.h"
#include "WeenieFactory.h"
#include "TownCrier.h"
#include "Vendor.h"
#include "Monster.h"
#include "SpellcastingManager.h"
#include "WClassID.h"
#include "Config.h"
#include "PacketController.h"
#include "InferredPortalData.h"
#include "RandomRange.h"
#include "House.h"
#include "GameEventManager.h"
#include "easylogging++.h"
#include "ObjectMsgs.h"
#include "EnumUtil.h"
#include "ChessManager.h"
#include "AllegianceManager.h"
#include "HouseManager.h"
// Most of these commands are just for experimenting and never meant to be used in a real game
// TODO: Add flags to these commands so they are only accessible under certain modes such as a sandbox mode
//CommandMap CommandBase::m_mCommands;
void CommandBase::Create(const char* szName, const char* szArguments, const char* szHelp, pfnCommandCallback pCallback, int iAccessLevel, int iCategory, bool bSource)
{
CommandEntry i =
{
szName,
szArguments,
szHelp,
pCallback,
iAccessLevel,
iCategory,
bSource
};
GetCommandMap()[std::string(szName)] = i;
//m_mCommands[std::string(szName)] = i;
}
bool g_bSilence = false;
bool g_bSpawnMonsterDisabled = false;
bool SpawningEnabled(CPlayerWeenie *pPlayer, bool item = false)
{
if (g_bSilence || (!item && g_bSpawnMonsterDisabled))
{
if (pPlayer->GetClient() && pPlayer->GetClient()->GetAccessLevel() < ADMIN_ACCESS)
{
return false;
}
}
return true;
}
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(skillspendexp, "<skillID> <exp>", "Attempts to spend the input exp to the given skill.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 2)
{
pPlayer->SendText("An arg is missing", LTT_DEFAULT);
return true;
}
uint32_t seq = 1;
uint32_t eventNum = 0x0046;
uint32_t dwSkill = (unsigned)atoi(argv[0]);
uint32_t dwXP = (unsigned)atoi(argv[1]);
std::vector<uint32_t> data;
data.push_back(seq);
data.push_back(eventNum);
data.push_back(dwSkill);
data.push_back(dwXP);
BinaryReader reader(data.data(), data.size() * sizeof(uint32_t));
player_client->GetEvents()->ProcessEvent(&reader);
pPlayer->SendText(csprintf("Attempted to add %i exp to the skill", dwXP), LTT_DEFAULT);
return false;
}
#endif
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(simulateaccess, "<level>", "Simulate access level.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
pPlayer->GetClient()->SetAccessLevel((unsigned) atoi(argv[0]));
return false;
}
#endif
CLIENT_COMMAND(myloc, "", "Info on your current location.", BASIC_ACCESS, EXPLORE_CATEGORY)
{
pPlayer->SendText(csprintf("%08X %.2f %.2f %.2f %.2f %.2f %.2f %.2f",
player_physobj->m_Position.objcell_id,
player_physobj->m_Position.frame.m_origin.x, player_physobj->m_Position.frame.m_origin.y, player_physobj->m_Position.frame.m_origin.z,
player_physobj->m_Position.frame.m_angles.w, player_physobj->m_Position.frame.m_angles.x, player_physobj->m_Position.frame.m_angles.y, player_physobj->m_Position.frame.m_angles.z), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(loc_other, "", "Info on your last assessed target's location.", SENTINEL_ACCESS, EXPLORE_CATEGORY)
{
CWeenieObject *other = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!other)
return false;
pPlayer->SendText(csprintf("%08X %.2f %.2f %.2f %.2f %.2f %.2f %.2f",
other->m_Position.objcell_id,
other->m_Position.frame.m_origin.x, other->m_Position.frame.m_origin.y, other->m_Position.frame.m_origin.z,
other->m_Position.frame.m_angles.w, other->m_Position.frame.m_angles.x, other->m_Position.frame.m_angles.y, other->m_Position.frame.m_angles.z), LTT_DEFAULT);
return false;
}
#if 0
CLIENT_COMMAND(startgame, "[gameid]", "Spawns something by name (right now works for monsters, NPCs, players.)", ADMIN_ACCESS)
{
if (argc < 1)
return true;
int game = atoi(argv[0]);
switch (game)
{
case 0:
g_pWorld->SetNewGameMode(NULL);
break;
case 1:
g_pWorld->SetNewGameMode(new CGameMode_Tag());
break;
}
return false;
}
CLIENT_COMMAND(spawnportal, "", "Spawns a dysfunctional portal near you.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
CPortal *pPortal = new CPortal();
pPortal->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pPortal);
return false;
}
CLIENT_COMMAND(spawndoor, "", "Spawns a door at your location.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
CWeenieObject *pDoor = new CBaseDoor();
pDoor->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pDoor);
return false;
}
#endif
CLIENT_COMMAND(global, "<text> [color=1]", "Displays text globally.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
{
return true;
}
if (g_bSilence)
{
return false;
}
const char* szText = argv[0];
int32_t lColor = (argc >= 2) ? atoi(argv[1]) : 1;
g_pWorld->BroadcastGlobal(ServerText(szText, lColor), PRIVATE_MSG);
return false;
}
#if 0
CLIENT_COMMAND(overlay, "<text>", "Displays <text> at the top-middle of the 3D window.", ADMIN_ACCESS)
{
if (argc < 1)
{
return true;
}
const char* szText = argv[0];
pPlayer->SendTextToOverlay(szText);
return false;
}
#endif
CLIENT_COMMAND(animationall, "<num> [speed]", "Performs an animation for everyone.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
{
return true;
}
WORD wIndex = atoi(argv[0]);
float fSpeed = (argc >= 2) ? (float)atof(argv[1]) : 1.0f;
fSpeed = min(10.0f, max(0.1f, fSpeed));
PlayerWeenieMap *pPlayers = g_pWorld->GetPlayers();
for (PlayerWeenieMap::iterator i = pPlayers->begin(); i != pPlayers->end(); i++)
{
i->second->_server_control_timestamp += 2;
i->second->last_move_was_autonomous = false;
MovementParameters params;
params.action_stamp = ++pPlayer->m_wAnimSequence;
params.speed = fSpeed;
params.autonomous = 0;
params.modify_interpreted_state = 1;
MovementStruct mvs;
mvs.motion = GetCommandID(wIndex);
mvs.params = &params;
mvs.type = MovementTypes::RawCommand;
i->second->get_minterp()->PerformMovement(mvs);
i->second->Animation_Update();
}
return false;
}
CLIENT_COMMAND(freezeall, "", "Freezes or unfreezes everyone.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
{
return true;
}
PlayerWeenieMap *pPlayers = g_pWorld->GetPlayers();
for (PlayerWeenieMap::iterator i = pPlayers->begin(); i != pPlayers->end(); i++)
{
i->second->set_state(i->second->m_PhysicsState ^ (uint32_t)(FROZEN_PS), TRUE);
}
return false;
}
#if 0
CLIENT_COMMAND(lineall, "", "Moves everyone.", ADMIN_ACCESS)
{
Position targetPosition = player_physobj->m_Position;
PlayerWeenieMap *pPlayers = g_pWorld->GetPlayers();
for (PlayerWeenieMap::iterator i = pPlayers->begin(); i != pPlayers->end(); i++)
{
if (i->second != pPlayer)
{
targetPosition.frame.m_origin.x += 1.5f;
i->second->SendText("Teleporting you...", LTT_DEFAULT);
i->second->Movement_Teleport(targetPosition);
}
}
return false;
}
#endif
CLIENT_COMMAND(effect, "<index> [scale=1]", "Emits a particle effect.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
uint32_t dwIndex;
float flScale;
dwIndex = atol(argv[0]);
if (argc >= 2) flScale = (float)atof(argv[1]);
else flScale = (float)1.0f;
pPlayer->EmitEffect(dwIndex, flScale);
return false;
}
CLIENT_COMMAND(sound, "<index> [speed?=1]", "Emits a sound effect.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
uint32_t dwIndex = atol(argv[0]);
float flSpeed = (float)((argc >= 2) ? atof(argv[1]) : 1.0f);
pPlayer->EmitSound(dwIndex, flSpeed);
return false;
}
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(arwic, "", "Teleports you to Arwic.", SENTINEL_ACCESS, EXPLORE_CATEGORY)
{
pPlayer->SendText("Teleporting you to Arwic..", LTT_DEFAULT);
pPlayer->Movement_Teleport(Position(0xC6A90023, Vector(102.4f, 70.1f, 44.0f), Quaternion(0.70710677f, 0, 0, 0.70710677f)));
return false;
}
CLIENT_COMMAND(removethis, "", "Removes an object.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
std::string itemRemoved = pPlayer->RemoveLastAssessed(true);
if (itemRemoved != "")
{
pPlayer->SendText(std::string("Removed object: ").append(itemRemoved).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to clear!").append(itemRemoved).c_str(), LTT_DEFAULT);
return true;
}
return false;
}
#endif
CLIENT_COMMAND(targeteffect, "[effect] [scale]", "Plays an effect on the last target you assessed.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
if (!pPlayer->m_LastAssessed)
return true;
if (argc < 1)
return true;
uint32_t dwIndex = atol(argv[0]);
float flScale;
if (argc >= 2)
flScale = (float)atof(argv[1]);
else
flScale = (float)1.0f;
CWeenieObject *pTarget = g_pWorld->FindWithinPVS(pPlayer, pPlayer->m_LastAssessed);
if (pTarget)
{
pTarget->EmitEffect(dwIndex, flScale);
}
return false;
}
CLIENT_COMMAND(targetsound, "[effect] [speed]", "Plays an effect on the last target you assessed.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
if (!pPlayer->m_LastAssessed)
return true;
if (argc < 1)
return true;
uint32_t dwIndex = atol(argv[0]);
float flScale;
if (argc >= 2)
flScale = (float)atof(argv[1]);
else
flScale = (float)1.0f;
CWeenieObject *pTarget = g_pWorld->FindWithinPVS(pPlayer, pPlayer->m_LastAssessed);
if (pTarget)
{
pTarget->EmitSound(dwIndex, flScale);
}
return false;
}
#if 0
CLIENT_COMMAND(spawnorbiter, "", "Just a test.", BASIC_ACCESS)
{
if (argc < 3)
return true;
CTargetDrudge *pDrudge = new CTargetDrudge();
pDrudge->SetID(g_pWorld->GenerateGUID(eDynamicGUID));
pDrudge->m_Position = player_physobj->m_Position;
pDrudge->m_Position.frame.m_origin.x += 10.0f;
pDrudge->m_velocityVector = Vector(0, 2, 0);
pDrudge->m_Omega = Vector(atof(argv[0]), atof(argv[1]), atof(argv[2]));
pDrudge->m_dwSoundSet = 0x20000037;
pDrudge->m_dwEffectSet = 0x34000000 | strtoul(argv[3], NULL, 16);
pDrudge->m_fFriction = 0.0f;
pDrudge->m_fElasticity = 0.0f;
pDrudge->m_PhysicsState = INELASTIC_PS | SCRIPTED_COLLISION_PS | REPORT_COLLISIONS_PS | MISSILE_PS | LIGHTING_ON_PS | PATHCLIPPED_PS | ALIGNPATH_PS;
pDrudge->m_dwModel = 0x0200087C;
pDrudge->m_scale = 0.25f;
g_pWorld->CreateEntity(pDrudge);
return false;
}
#endif
CLIENT_COMMAND(tele, "<player name>", "Teleports you to a player.", BASIC_ACCESS, EXPLORE_CATEGORY)
{
if (!g_pConfig->EnableTeleCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is now only available on servers running in Explorer mode.", LTT_DEFAULT);
return false;
}
if (argc < 1)
return true;
CPlayerWeenie *pTarget = g_pWorld->FindPlayer(argv[0]);
if (pTarget)
{
if (pTarget->m_bPrivacyMode && player_client->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText(csprintf("Cannot teleport to %s. They have privacy mode enabled.", pTarget->GetName().c_str()), LTT_DEFAULT);
}
else
{
pPlayer->SendText(csprintf("Teleporting to %s ..", argv[0]), LTT_DEFAULT);
pPlayer->Movement_Teleport(pTarget->m_Position);
}
}
else
{
pPlayer->SendText(csprintf("Couldn't find player \"%s\" ?", argv[0]), LTT_DEFAULT);
}
return false;
}
CLIENT_COMMAND(teletome, "<player name>", "Teleports someone to you.", ADVOCATE_ACCESS, EXPLORE_CATEGORY)
{
if (argc < 1)
return true;
CPlayerWeenie *pTarget = g_pWorld->FindPlayer(argv[0]);
if (pTarget)
{
pTarget->SendText(csprintf("Teleporting to %s ..", pPlayer->GetName().c_str()), LTT_DEFAULT);
pTarget->Movement_Teleport(pPlayer->m_Position);
}
else
pPlayer->SendText(csprintf("Couldn't find player \"%s\" ?", argv[0]), LTT_DEFAULT);
return false;
}
#if 0
CLIENT_COMMAND(teleall, "<target>", "Teleports all players target. If no target specified, teleports to you.", ADMIN_ACCESS)
{
CPlayerWeenie* target;
if (argc < 1)
{
target = pPlayer;
}
else
{
target = g_pWorld->FindPlayer(argv[0]);
if (target == NULL)
{
pPlayer->SendText("Invalid target!", LTT_DEFAULT);
return true;
}
}
PlayerWeenieMap* map = g_pWorld->GetPlayers();
PlayerWeenieMap::iterator pit = map->begin();
PlayerWeenieMap::iterator pend = map->end();
//This is probably really bad..
bool teleportedOne = false;
while (pit != pend)
{
CPlayerWeenie *them = pit->second;
if (them != target)
{
teleportedOne = true;
pPlayer->SendText(std::string("Teleported: ").append(them->GetName()).c_str(), LTT_DEFAULT);
them->Movement_Teleport(target->m_Position);
them->SendText(std::string("Teleported by: ").append(pPlayer->GetName()).c_str(), LTT_DEFAULT);
}
pit++;
}
if (teleportedOne)
{
return false;
}
else
{
pPlayer->SendText("Didn't teleport anyone! Nobody on server?", LTT_DEFAULT);
}
return true;
}
#endif
CLIENT_COMMAND(teletown, "<town name>", "Teleports you to a town.", BASIC_ACCESS, EXPLORE_CATEGORY)
{
if (!g_pConfig->EnableTeleCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is now only available on servers running in Explorer mode.", LTT_DEFAULT);
return false;
}
if (argc == 0)
{
pPlayer->SendText("Your teleporting choices are:", LTT_DEFAULT);
pPlayer->SendText(g_pWorld->GetTeleportList().c_str(), LTT_DEFAULT);
return true;
}
std::string cmdString = argv[0];
for (int i = 1; i < argc; i++)
{
cmdString.append(" ");
cmdString.append(argv[i]);
}
TeleTownList_s var = g_pWorld->GetTeleportLocation(cmdString);
if (var.m_teleString != "")
{
pPlayer->SendText(std::string("Portaling To: ").append(var.m_teleString).c_str(), LTT_DEFAULT);
pPlayer->Movement_Teleport(var.position);
return false;
}
else
{
pPlayer->SendText("Town Not Found! Try again...", LTT_DEFAULT);
}
return true;
}
CLIENT_COMMAND(teleto, "<coords>", "Teleports you to coordinates.", BASIC_ACCESS, EXPLORE_CATEGORY)
{
if (!g_pConfig->EnableTeleCommands() && pPlayer->GetAccessLevel() < ADVOCATE_ACCESS)
{
pPlayer->SendText("This command is now only available on servers running in Explorer mode.", LTT_DEFAULT);
return false;
}
if (argc < 2)
{
return true;
}
float NS = NorthSouth(argv[0]);
float EW = EastWest(argv[1]);
char cNS = ' ';
char cEW = ' ';
if (NS < 0) cNS = 'S'; else if (NS > 0) cNS = 'N';
if (EW < 0) cEW = 'W'; else if (EW > 0) cEW = 'E';
Position position;
GetLocation(NS, EW, position);
if (!position.objcell_id)
{
pPlayer->SendText("Bad coordinate location!", LTT_DEFAULT);
}
else if (IsWaterBlock(position.objcell_id))
{
pPlayer->SendText("Bad location! That's a water block, dummy!", LTT_DEFAULT);
}
else
{
char *szTP = csprintf("Teleporting to %0.1f%c %0.1f%c (Cell: %08X Z: %.1f)", fabs(NS), cNS, fabs(EW), cEW, position.objcell_id, position.frame.m_origin.z);
pPlayer->SendText(szTP, LTT_DEFAULT);
pPlayer->Movement_Teleport(position);
}
return false;
}
bool g_bReviveOverride = false;
Position g_RevivePosition;
bool g_bStartOverride = false;
Position g_StartPosition;
#if 0
CLIENT_COMMAND(reviveoverride, "<setting>", "", ADMIN_ACCESS)
{
if (argc < 1)
return true;
g_bReviveOverride = atoi(argv[0]) ? true : false;
g_RevivePosition = pPlayer->m_Position;
return false;
}
CLIENT_COMMAND(startoverride, "<setting>", "", ADMIN_ACCESS)
{
if (argc < 1)
return true;
g_bStartOverride = atoi(argv[0]) ? true : false;
g_StartPosition = pPlayer->m_Position;
return false;
}
#endif
CLIENT_COMMAND(adminvision, "<enabled>", "", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
{
return true;
}
/*
if (_stricmp(pPlayer->GetClient()->GetAccountInfo().username.c_str(), "admin") &&
_stricmp(pPlayer->GetClient()->GetAccountInfo().username.c_str(), "cmoskitest") &&
_stricmp(pPlayer->GetClient()->GetAccountInfo().username.c_str(), "peatest"))
return false;
*/
pPlayer->m_bAdminVision = atoi(argv[0]) ? true : false;
if (pPlayer->GetBlock())
pPlayer->GetBlock()->ExchangePVS(pPlayer, 0);
return false;
}
CLIENT_COMMAND(serverstatus, "", "Provides information on the server's status.", SENTINEL_ACCESS, SERVER_CATEGORY)
{
pPlayer->SendText(csprintf("Server status:\n%s", g_pWorld->GetServerStatus().c_str()), LTT_DEFAULT);
g_pWorld->m_SendPerformanceInfoToPlayer = pPlayer->GetID();
return false;
}
//CLIENT_COMMAND(netinfo, "", "Provides information on the player's network connection.", BASIC_ACCESS)
//{
// int sendbuf = 0;
// int sendbuflen = sizeof(sendbuf);
// getsockopt(g_pNetwork->m_sockets[0], SOL_SOCKET, SO_SNDBUF, (char *)&sendbuf, &sendbuflen);
// pPlayer->SendText(csprintf("SNDBUF: %u", sendbuf), LTT_DEFAULT);
//
// int recvbuf = 0;
// int recvbuflen = sizeof(recvbuf);
// getsockopt(g_pNetwork->m_sockets[0], SOL_SOCKET, SO_RCVBUF, (char *)&recvbuf, &recvbuflen);
// pPlayer->SendText(csprintf("RCVBUF: %u", recvbuf), LTT_DEFAULT);
//
// pPlayer->SendText(csprintf("INSEQ: %u", player_client->GetPacketController()->m_in.sequence), LTT_DEFAULT);
// pPlayer->SendText(csprintf("ACTIVESEQ: %u", player_client->GetPacketController()->m_in.activesequence), LTT_DEFAULT);
// pPlayer->SendText(csprintf("FLUSHSEQ: %u", player_client->GetPacketController()->m_in.flushsequence), LTT_DEFAULT);
// pPlayer->SendText(csprintf("OUTSEQ: %u", player_client->GetPacketController()->m_out.sequence), LTT_DEFAULT);
// pPlayer->SendText(csprintf("RECEIVED: %I64u", player_client->GetPacketController()->m_in.receivedbytes), LTT_DEFAULT);
// pPlayer->SendText(csprintf("SENT: %I64u", player_client->GetPacketController()->m_out._sentBytes), LTT_DEFAULT);
// pPlayer->SendText(csprintf("RETRANSMIT: %u", player_client->GetPacketController()->m_out.numretransmit), LTT_DEFAULT);
// pPlayer->SendText(csprintf("DENIED: %u", player_client->GetPacketController()->m_out.numdenied), LTT_DEFAULT);
// pPlayer->SendText(csprintf("REQUESTED: %u", player_client->GetPacketController()->m_in.numresendrequests), LTT_DEFAULT);
//
// return false;
//}
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(debug, "<index>", "", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
/*
if (_stricmp(pPlayer->GetClient()->GetAccountInfo().username.c_str(), "admin") &&
_stricmp(pPlayer->GetClient()->GetAccountInfo().username.c_str(), "cmoskitest") &&
_stricmp(pPlayer->GetClient()->GetAccountInfo().username.c_str(), "peatest"))
return false;
*/
int debugLevel = atoi(argv[0]);
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!target)
return false;
float respawnTime = 0.0f;
CWeenieObject *pGenerator = g_pWorld->FindObject(target->InqIIDQuality(GENERATOR_IID, 0));
std::string info;
info += csprintf("ID: %08X WCID: %u\nWClass: %s @ %08X %.1f %.1f %.1f (%.f away)\nGen: %08X Act: %08X RespawnTime: %.1fm",
target->GetID(),
target->m_Qualities.id,
GetWCIDName(target->m_Qualities.id),
target->m_Position.objcell_id,
target->m_Position.frame.m_origin.x,
target->m_Position.frame.m_origin.y,
target->m_Position.frame.m_origin.z,
pPlayer->DistanceTo(target, true),
target->InqIIDQuality(GENERATOR_IID, 0),
target->InqIIDQuality(ACTIVATION_TARGET_IID, 0),
pGenerator ? pGenerator->InqFloatQuality(REGENERATION_INTERVAL_FLOAT, 0.0f) * g_pConfig->RespawnTimeMultiplier() / 60.0f : 0.0f);
double initInterval = 0.0;
if (target->m_Qualities.InqFloat(GENERATOR_INITIAL_DELAY_FLOAT, initInterval, TRUE))
{
info += csprintf(" GenInitDelay: %.1fm", initInterval * g_pConfig->RespawnTimeMultiplier() / 60.0);
}
double regenInterval = 0.0;
if (target->m_Qualities.InqFloat(REGENERATION_INTERVAL_FLOAT, regenInterval, TRUE))
{
info += csprintf(" GenRegenInterval: %.1fm", regenInterval * g_pConfig->RespawnTimeMultiplier() / 60.0);
}
double genRadius = 0.0;
if (target->m_Qualities.InqFloat(GENERATOR_RADIUS_FLOAT, genRadius, TRUE))
{
info += csprintf(" GenRadius: %.1fm", genRadius);
}
double resetInterval = 0.0;
if (target->m_Qualities.InqFloat(RESET_INTERVAL_FLOAT, resetInterval, TRUE))
{
info += csprintf(" Reset: %.1fm", resetInterval * g_pConfig->RespawnTimeMultiplier() / 60.0);
}
int initGen = 0;
if (target->m_Qualities.InqInt(INIT_GENERATED_OBJECTS_INT, initGen, TRUE))
{
info += csprintf(" InitGen: %d", initGen);
}
int maxGen = 0;
if (target->m_Qualities.InqInt(MAX_GENERATED_OBJECTS_INT, maxGen, TRUE))
{
info += csprintf(" MaxGen: %d", maxGen);
}
std::string eventString;
if (target->m_Qualities.InqString(GENERATOR_EVENT_STRING, eventString))
{
info += csprintf(" GenEvent: %s", eventString.c_str());
}
if (target->_nextRegen >= 0)
{
info += csprintf(" NextRegen: %.1fm", (target->_nextRegen - Timer::cur_time) / 60.0);
}
if (!target->cell)
{
info += " NOT IN CELL";
}
if (target->m_Qualities._create_list)
{
info += csprintf("\nCreate List:");
for (auto &entry : *target->m_Qualities._create_list)
{
info += csprintf("\n%u (%s) try_to_bond %u palette %u shade/probability %f destination/regen_algorithm %u stack_size/max_number/amount %d",
entry.wcid, GetWCIDName(entry.wcid), entry.try_to_bond, entry.palette, entry.shade, entry.destination, entry.stack_size);
}
}
if (target->m_Qualities._emote_table)
{
info += csprintf("\nEmote Table:");
for (auto &emoteCategory : target->m_Qualities._emote_table->_emote_table)
{
info += csprintf("\nEmoteCategory %s (%u)", Emote::EmoteCategoryToName((EmoteCategory) emoteCategory.first), emoteCategory.first);
for (auto &emoteSet : emoteCategory.second)
{
info += csprintf("\n EmoteSet %s (%u) probability %f", Emote::EmoteCategoryToName((EmoteCategory)emoteSet.category), emoteSet.category, emoteSet.probability);
switch (emoteSet.category)
{
case Refuse_EmoteCategory:
case Give_EmoteCategory:
info += csprintf(" %d (%s)", emoteSet.classID, GetWCIDName(emoteSet.classID));
break;
case HeartBeat_EmoteCategory:
info += csprintf(" 0x%08X 0x%08X", emoteSet.style, emoteSet.substyle);
break;
case QuestSuccess_EmoteCategory: // 12 0xC
case QuestFailure_EmoteCategory: // 13 0xD
case TestSuccess_EmoteCategory: // 22 0x16
case TestFailure_EmoteCategory: // 23 0x17
case EventSuccess_EmoteCategory: // 27 0x1B
case EventFailure_EmoteCategory: // 28 0x1C
case TestNoQuality_EmoteCategory: // 29 0x1D
case QuestNoFellow_EmoteCategory: // 30 0x1E
case TestNoFellow_EmoteCategory: // 31 0x1F
case GotoSet_EmoteCategory: // 32 0x20
case NumFellowsSuccess_EmoteCategory: // 33 0x21
case NumFellowsFailure_EmoteCategory: // 34 0x22
case NumCharacterTitlesSuccess_EmoteCategory: // 35 0x23
case NumCharacterTitlesFailure_EmoteCategory: // 36 0x24
case ReceiveLocalSignal_EmoteCategory: // 37 0x25
case ReceiveTalkDirect_EmoteCategory: // 38 0x26
info += csprintf(" %s", emoteSet.quest.c_str());
break;
case Vendor_EmoteCategory:
// 1 = open vendor
// 2 = walk away
// 3 = sell
// 4 = buy
// 5 = performs a motion 0x87 or 0x7d or 0x86 or 0x83
info += csprintf(" %d", emoteSet.vendorType);
break;
case WoundedTaunt_EmoteCategory:
info += csprintf(" %f %f", emoteSet.minhealth, emoteSet.maxhealth);
break;
}
for (auto &emote : emoteSet.emotes)
{
info += csprintf("\n %s (%u) %.1f %.1f %s", Emote::EmoteTypeToName(emote.type), emote.type, emote.delay, emote.extent, emote.msg.c_str());
switch (emote.type)
{
case CastSpellInstant_EmoteType:
info += csprintf(" %u", emote.spellid);
break;
case Motion_EmoteType:
case ForceMotion_EmoteType:
info += csprintf(" 0x%X", emote.motion);
break;
case 0x22u:
case 0x2Fu:
case InflictVitaePenalty_EmoteType:
case 0x5Au:
case 0x77u:
case 0x78u:
info += csprintf(" %d", emote.amount);
break;
case InqStringStat_EmoteType:
case InqYesNo_EmoteType:
info += csprintf(" %s %d", emote.teststring.c_str(), emote.stat);
break;
case InqIntStat_EmoteType:
case InqAttributeStat_EmoteType:
case InqRawAttributeStat_EmoteType:
case InqSecondaryAttributeStat_EmoteType:
case InqRawSecondaryAttributeStat_EmoteType:
case InqSkillStat_EmoteType:
case InqRawSkillStat_EmoteType:
info += csprintf(" %d %d %d", emote.min, emote.max, emote.stat);
break;
case Give_EmoteType:
case TakeItems_EmoteType:
info += csprintf(" %u (%s) %d", emote.cprof.wcid, GetWCIDName(emote.cprof.wcid), emote.cprof.amount);
break;
case SetIntStat_EmoteType:
case IncrementIntStat_EmoteType:
case DecrementIntStat_EmoteType:
case SetBoolStat_EmoteType:
info += csprintf(" %d %d", emote.stat, emote.amount);
break;
case InqQuestSolves_EmoteType:
case InqFellowNum_EmoteType:
case InqNumCharacterTitles_EmoteType:
case InqMyQuestSolves_EmoteType:
info += csprintf(" %u %u", emote.min, emote.max);
break;
case AwardXP_EmoteType:
case AwardNoShareXP_EmoteType:
info += csprintf(" %I64u %I64u", emote.amount64, emote.heroxp64);
break;
case AwardSkillXP_EmoteType:
case AwardSkillPoints_EmoteType:
info += csprintf(" %u %u", emote.amount, emote.stat);
break;
}
}
}
}
}
if (target->m_Qualities._generator_table && (debugLevel & 1))
{
info += csprintf("\nGenerator Table:");
for (auto &profile : target->m_Qualities._generator_table->_profile_list)
{
info += csprintf("\nProfile probability %f type %d (%s) delay %f init %d maxNum %d when %d where %d stack %d ptid %d shade %f slot %d",
profile.probability, profile.type, GetWCIDName(profile.type), profile.delay, profile.initCreate, profile.maxNum, profile.whenCreate, profile.whereCreate, profile.stackSize, profile.ptid, profile.shade, profile.slot);
}
}
if (target->m_Qualities._generator_queue && (debugLevel & 2))
{
info += csprintf("\nGenerator Queue:");
for (auto &entry : target->m_Qualities._generator_queue->_queue)
{
info += csprintf("\nSlot %u When %ds",
entry.slot, (int)(entry.when - Timer::cur_time));
}
}
if (target->m_Qualities._generator_registry && (debugLevel & 2))
{
info += csprintf("\nGenerator Registry:");
for (auto &entry : target->m_Qualities._generator_registry->_registry)
{
info += csprintf("\n0x%08X - type %u (%s)",
entry.first, entry.second.m_wcidOrTtype, GetWCIDName(entry.second.m_wcidOrTtype));
}
}
pPlayer->SendText(info.c_str(), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(getinfo, "", "Get Info from targetted object.", BASIC_ACCESS, GENERAL_CATEGORY)
{
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!target)
return false;
std::string info;
info += csprintf("WCID: %u \nWClass: %s Name: %s \n Loc: %08X %.2f %.2f %.2f %.2f %.2f %.2f %.2f",
target->m_Qualities.id,
GetWCIDName(target->m_Qualities.id),
target->m_Qualities.GetString(NAME_STRING,"").c_str(), target->m_Position.objcell_id,
target->m_Position.frame.m_origin.x, target->m_Position.frame.m_origin.y, target->m_Position.frame.m_origin.z,
target->m_Position.frame.m_angles.w, target->m_Position.frame.m_angles.x, target->m_Position.frame.m_angles.y, target->m_Position.frame.m_angles.z);
pPlayer->SendText(info.c_str(), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(monsterbrawl, "", "Toggle monsters fighting each other.", ADMIN_ACCESS, SERVER_CATEGORY)
{
monster_brawl = !monster_brawl;
if (monster_brawl)
pPlayer->SendText("Enabled brawling monsters.", LTT_DEFAULT);
else
pPlayer->SendText("Disabled brawling monsters.", LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(damagesources, "", "Lists all damage sources and values for the last assessed target if it's a monster.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!target)
return false;
if (target->AsMonster())
{
std::string info;
for (std::map<uint32_t, int>::iterator it = target->AsMonster()->m_aDamageSources.begin(), ite = target->AsMonster()->m_aDamageSources.end(); it != ite; ++it)
{
CWeenieObject *source = g_pWorld->FindObject(it->first);
info += csprintf("%s has done %d damage.\n", source->GetName().c_str(), it->second);
}
if (!info.empty())
{
pPlayer->SendText(info.c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText("No damage taken.", LTT_DEFAULT);
}
}
return false;
}
CLIENT_COMMAND(sweartime, "<unix timestamp>", "Sets the time that the last assessed player swore to their patron to <unix timestamp> seconds. If no argument is given, shows the current timestamp.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!target)
return false;
if (target->AsPlayer())
{
if (AllegianceTreeNode* targetNode = g_pAllegianceManager->GetTreeNode(target->id))
{
if (targetNode->_patronID) {
int oldSwornAt = targetNode->_unixTimeSwornAt;
if (argc < 1)
{
pPlayer->SendText(csprintf("%s's unix time sworn at is %d.", targetNode->_charName.c_str(), oldSwornAt), LTT_DEFAULT);
return false;
}
targetNode->_unixTimeSwornAt = atoi(argv[0]);
pPlayer->SendText(csprintf("%s's unix time sworn at has been changed from %d to %d.", targetNode->_charName.c_str(), oldSwornAt, targetNode->_unixTimeSwornAt), LTT_DEFAULT);
}
}
}
return false;
}
CLIENT_COMMAND(addtitle, "id", "Grants the last assessed player's the Title ID.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
CPlayerWeenie *target = g_pWorld->FindPlayer(pPlayer->m_LastAssessed);
if (!target)
return false;
if (target)
{
int input = atoi(argv[0]);
if (input > 0)
target->AddTitle(input);
}
return false;
}
CLIENT_COMMAND(passupbool, "<0 | 1>", "Sets the last assessed player's XP passup bool. If no argument is given, shows the current state.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!target)
return false;
if (target->AsPlayer())
{
if (AllegianceTreeNode* targetNode = g_pAllegianceManager->GetTreeNode(target->id))
{
bool canPassup = target->InqBoolQuality(EXISTED_BEFORE_ALLEGIANCE_XP_CHANGES_BOOL, 0);
if (argc < 1)
pPlayer->SendText(csprintf("%s's XP passup is currently %s.", target->GetName().c_str(), canPassup ? "enabled" : "disabled"), LTT_DEFAULT);
else
{
int input = atoi(argv[0]);
if (!input || input == 1)
{
target->m_Qualities.SetBool(EXISTED_BEFORE_ALLEGIANCE_XP_CHANGES_BOOL, input);
pPlayer->SendText(csprintf("%s's XP passup has now been %s.", target->GetName().c_str(), input ? "enabled" : "disabled"), LTT_DEFAULT);
}
}
}
}
return false;
}
CLIENT_COMMAND(envmode, "<mode>", "", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
BinaryWriter envMode;
envMode.Write<uint32_t>(0xEA60);
envMode.Write<uint32_t>(strtoul(argv[0], NULL, 16));
g_pWorld->BroadcastGlobal(&envMode, PRIVATE_MSG, 0, FALSE, FALSE);
/* /*
1 = red
2 = blue
3 = grey
4 = dark green
5 = black
6 = black
'Sound_UI_Roar' 0x65
'Sound_UI_Bell'
'Sound_UI_Chant1'
'Sound_UI_Chant2'
'Sound_UI_DarkWhispers1'
'Sound_UI_DarkWhispers2'
'Sound_UI_DarkLaugh'
'Sound_UI_DarkWind'
'Sound_UI_DarkSpeech'
'Sound_UI_Drums'
'Sound_UI_GhostSpeak'
'Sound_UI_Breathing' 0x70
'Sound_UI_Howl'
'Sound_UI_LostSouls'
'Sound_UI_Squeal' 0x75
'Sound_UI_Thunder1'
'Sound_UI_Thunder2'
'Sound_UI_Thunder3'
'Sound_UI_Thunder4'
'Sound_UI_Thunder5'
'Sound_UI_Thunder6' 0x7b
*/
return false;
}
#endif
CLIENT_COMMAND(vismode, "<mode>", "Changes your physics state.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
pPlayer->set_state(strtoul(argv[0], NULL, 16), TRUE);
return false;
}
/*
CLIENT_COMMAND(spawnbael, "", "Spawns Bael'Zharon.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
CBaelZharon *pBael = new CBaelZharon();
pBael->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pBael);
return false;
}
*/
extern double g_TimeAdjustment;
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(timeadjust, "", "Time adjustment. Careful.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
g_TimeAdjustment = atof(argv[0]);
return false;
}
#endif
CLIENT_COMMAND(squelchall, "", "Squelch all.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
g_bSilence = atoi(argv[0]) ? true : false;
if (g_bSilence)
pPlayer->SendText("Silenced all players and spawning.", LTT_DEFAULT);
else
pPlayer->SendText("Unsilenced all players and spawning.", LTT_DEFAULT);
return false;
}
#if 0
CLIENT_COMMAND(spawnmonsterenabled, "", "Toggle spawning.", ADMIN_ACCESS)
{
if (argc < 1)
return true;
g_bSpawnMonsterDisabled = atoi(argv[0]) ? false : true;
if (g_bSpawnMonsterDisabled)
pPlayer->SendText("Disabled spawning of monsters.", LTT_DEFAULT);
else
pPlayer->SendText("Enabled spawning of monsters.", LTT_DEFAULT);
return false;
}
#endif
/*
CLIENT_COMMAND(targetdrudge, "", "Spawns a Target Drudge.", BASIC_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
CTargetDrudge *pDrudge = new CTargetDrudge();
pDrudge->SetInitialPosition(pPlayer->GetPosition().add_offset(Vector(0, 0, 1.0f)));
g_pWorld->CreateEntity(pDrudge);
return false;
}
*/
#if 0
CLIENT_COMMAND(spawnperks, "", "Spawns a aura caster for contributors.", DONOR_ACCESS)
{
if (!SpawningEnabled(pPlayer, true))
{
return false;
}
pPlayer->SpawnInContainer(100004);
return false;
}
#endif
CLIENT_COMMAND(spawnwand, "", "Spawns a wand.", BASIC_ACCESS, SPAWN_CATEGORY)
{
if (!g_pConfig->EnableTeleCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is now only available on servers running in Explorer mode.", LTT_DEFAULT);
return false;
}
if (!SpawningEnabled(pPlayer, true))
{
return false;
}
/*
CBaseWand* pWand = new CBaseWand();
pWand->SetInitialPosition(pPlayer->GetPosition());
pWand->m_bDontClear = false;
g_pWorld->CreateEntity(pWand);
*/
CWeenieObject *weenie = g_pWeenieFactory->CreateWeenieByName("Drudge Wand", &pPlayer->m_Position, true);
if (weenie)
weenie->m_bDontClear = false;
return false;
}
const char *skipHexPrefix(const char *hexString)
{
if (hexString[0] == '0' && hexString[1] == 'x')
hexString += 2;
return hexString;
}
const char *skipBracketPrefix(const char *OBracketString)
{
if (OBracketString[0] == '[')
OBracketString += 1;
return OBracketString;
}
const char *skipBracketSuffix(const char *CBracketString)
{
if (strlen(CBracketString) - 1 == ']')
CBracketString[strlen(CBracketString)-1];
return CBracketString;
}
CLIENT_COMMAND(teleloc, "<landcell> [x=0] [y=0] [z=0] [anglew=1] [anglex=0] [angley=0] [anglez=0]", "Teleports to a specific location.", BASIC_ACCESS, EXPLORE_CATEGORY)
{
if (!g_pConfig->EnableTeleCommands() && pPlayer->GetAccessLevel() < ADVOCATE_ACCESS)
{
pPlayer->SendText("This command is now only available on servers running in Explorer mode.", LTT_DEFAULT);
return false;
}
if (argc < 1)
return false;
Position target;
target.objcell_id = strtoul(skipHexPrefix(argv[0]), NULL, 16);
target.frame.m_origin.x = (float)((argc >= 2) ? atof(skipBracketPrefix(argv[1])) : 0);
target.frame.m_origin.y = (float)((argc >= 3) ? atof(argv[2]) : 0);
target.frame.m_origin.z = (float)((argc >= 4) ? atof(skipBracketSuffix(argv[3])) : 0);
target.frame.m_angles.w = (float)((argc >= 8) ? atof(argv[4]) : 1.0f);
target.frame.m_angles.x = (float)((argc >= 8) ? atof(argv[5]) : 0);
target.frame.m_angles.y = (float)((argc >= 8) ? atof(argv[6]) : 0);
target.frame.m_angles.z = (float)((argc >= 8) ? atof(argv[7]) : 0);
if (!target.objcell_id)
return false;
pPlayer->Movement_Teleport(target);
return false;
}
#if 0
CLIENT_COMMAND(spawnmodel, "<model index> [scale=1] [name=*]", "Spawns a model.", ADMIN_ACCESS)
{
if (argc < 1)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
uint32_t dwModel = strtoul(argv[0], NULL, 16);
if (!(dwModel & 0xFF000000))
dwModel |= 0x02000000;
float flScale = max(0.1f, min(10.0f, (float)((argc >= 2) ? atof(argv[1]) : 1.0f)));
const char* szName = (argc >= 3) ? argv[2] : csprintf("Model #%08X", dwModel);
CWeenieObject *pSpawn = new CWeenieObject();
pSpawn->SetSetupID(dwModel);
pSpawn->SetScale(flScale);
pSpawn->SetName(szName);
pSpawn->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pSpawn);
pSpawn->SetLongDescription(csprintf("This model was spawned by %s.\nModel #: %08X\nScale: %f\n", pPlayer->GetName().c_str(), dwModel, flScale));
return false;
}
CLIENT_COMMAND(spawnmodels, "<start index> <end index>", "Spawns a range of models.", ADMIN_ACCESS)
{
if (argc < 2)
{
return true;
}
if (!SpawningEnabled(pPlayer))
return false;
uint32_t dwModelStart = strtoul(argv[0], NULL, 16);
if (!(dwModelStart & 0xFF000000))
dwModelStart |= 0x02000000;
uint32_t dwModelEnd = strtoul(argv[1], NULL, 16);
if (!(dwModelEnd & 0xFF000000))
dwModelEnd |= 0x02000000;
if (dwModelStart > dwModelEnd && dwModelStart != 0)
{
return true;
}
uint32_t dwCount = (dwModelEnd - dwModelStart) + 1;
uint32_t dwWidth = (int)sqrt((double)dwCount);
if ((dwModelEnd - dwModelStart) >= 50)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
int x = 0;
int y = 0;
for (uint32_t i = dwModelStart; i <= dwModelEnd; i++)
{
CWeenieObject *pSpawn = new CWeenieObject();
pSpawn->SetSetupID(i);
pSpawn->SetScale(1.0f);
pSpawn->SetName(csprintf("Model #%08X", i));
pSpawn->SetInitialPosition(pPlayer->GetPosition().add_offset(Vector(x * 10.0f, y * 10.0f, 0)));
pSpawn->SetLongDescription(csprintf("This model was spawned by %s.\nModel #: %08X", pPlayer->GetName().c_str(), i));
g_pWorld->CreateEntity(pSpawn);
if (x == dwWidth)
{
x = 0;
y += 1;
}
else
x++;
}
return false;
}
#endif
/*
CLIENT_COMMAND(spawnmonster2, "<model index> <base palette>", "Spawns a monster.", BASIC_ACCESS)
{
if (argc < 3)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
uint32_t dwModel = strtoul(argv[0], NULL, 16);
if (!(dwModel & 0xFF000000))
dwModel |= 0x02000000;
uint32_t dwPalette1 = strtoul(argv[1], NULL, 16);
uint32_t dwPalette2 = strtoul(argv[2], NULL, 16);
dwPalette1 &= 0xFFFFF;
dwPalette2 &= 0xFFFFF;
CMonsterWeenie *pSpawn = new CMonsterWeenie();
pSpawn->SetSetupID(dwModel);
pSpawn->m_scale = 1.0f;
pSpawn->SetName(csprintf("0x%X 0x%X 0x%X", dwModel, dwPalette1, dwPalette2));
pSpawn->SetInitialPosition(pPlayer->GetPosition());
pSpawn->m_miBaseModel.dwBasePalette = dwPalette1;
pSpawn->m_miBaseModel.lPalettes.push_back(PaletteRpl(dwPalette2, 0, 0));
g_pWorld->CreateEntity(pSpawn);
pSpawn->SetLongDescription(csprintf("This monster was spawned by %s.\nModel #: %08X\nPalette #: %08X %08X\n", pPlayer->GetName().c_str(), dwModel, dwPalette1, dwPalette2));
return false;
}
*/
#if 0
CLIENT_COMMAND(spawnmonster, "<model index> [scale=1] [name=*] [dotcolor]", "Spawns a monster.", ADMIN_ACCESS)
{
if (argc < 1)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
uint32_t dwModel = strtoul(argv[0], NULL, 16);
if (!(dwModel & 0xFF000000))
dwModel |= 0x02000000;
float flScale = max(0.1f, min(10.0f, (float)((argc >= 2) ? atof(argv[1]) : 1.0f)));
const char* szName = (argc >= 3) ? argv[2] : csprintf("Model #%08X", dwModel);
int dotColor = (int)((argc >= 4) ? atoi(argv[3]) : 0);
CMonsterWeenie *pSpawn = new CMonsterWeenie();
pSpawn->SetSetupID(dwModel);
pSpawn->SetScale(flScale);
pSpawn->SetName(szName);
pSpawn->SetInitialPosition(pPlayer->GetPosition().add_offset(Vector(0, 6, 6)));
pSpawn->SetRadarBlipColor((RadarBlipEnum) dotColor);
g_pWorld->CreateEntity(pSpawn);
pSpawn->SetLongDescription(csprintf("This monster was spawned by %s.\nModel #: %08X\nScale: %f\n", pPlayer->GetName().c_str(), dwModel, flScale));
return false;
}
CLIENT_COMMAND(spawnitem, "<model index> [scale=1] [name=*]", "Spawns an item.", ADMIN_ACCESS)
{
if (argc < 1)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
uint32_t dwModel = strtoul(argv[0], NULL, 16);
if (!(dwModel & 0xFF000000))
dwModel |= 0x02000000;
float flScale = max(0.1, min(10, (float)((argc >= 2) ? atof(argv[1]) : 1.0f)));
const char* szName = (argc >= 3) ? argv[2] : csprintf("Model #%08X", dwModel);
CWeenieObject *pSpawn = new CWeenieObject();
pSpawn->m_Qualities.SetBool(STUCK_BOOL, FALSE);
pSpawn->SetSetupID(dwModel);
pSpawn->SetScale(flScale);
pSpawn->SetName(szName);
pSpawn->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pSpawn);
pSpawn->SetLongDescription(csprintf("This item was spawned by %s.\nModel #: %08X\nScale: %f\n", pPlayer->GetName().c_str(), dwModel, flScale));
return false;
}
CLIENT_COMMAND(spawnlifestone, "", "Spawns a lifestone.", ADVOCATE_ACCESS)
{
if (!SpawningEnabled(pPlayer))
return false;
CBaseLifestone *pSpawn = new CBaseLifestone();
pSpawn->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pSpawn);
pSpawn->SetLongDescription(csprintf("Life Stone spawned by %s.", pPlayer->GetName().c_str()));
return false;
}
#endif
CLIENT_COMMAND(clearspawns, "<force clear on/off>", "Clears the spawns in your current landblock", SENTINEL_ACCESS, SPAWN_CATEGORY)
{
bool forced = false;
if (argc >= 1)
{
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
forced = true;
}
if (!SpawningEnabled(pPlayer))
return false;
CWorldLandBlock *pBlock = pPlayer->GetBlock();
if (pBlock)
pBlock->ClearSpawns(forced);
pPlayer->SendText("Clearing spawns in your landblock.", LTT_DEFAULT);
return false;
}
#if 0
CLIENT_COMMAND(clearallspawns, "", "Clears all spawns in all landblocks (slow.)", SENTINEL_ACCESS)
{
g_pWorld->ClearAllSpawns();
pPlayer->SendText("Clearing spawns in all landblocks.", LTT_DEFAULT);
return false;
}
#endif
SERVER_COMMAND(kick, "<player name>", "Kicks the specified player.", SENTINEL_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
if (pPlayer)
{
SERVER_INFO << pPlayer->GetName().c_str() << "is using the kick command.";
}
else
{
SERVER_INFO << "Server is using the kick command.";
}
CPlayerWeenie *pTarget = g_pWorld->FindPlayer(argv[0]);
if (pTarget)
g_pNetwork->KickClient(pTarget->GetClient());
else
pPlayer->SendText("Couldn't find target player.", LTT_DEFAULT);
return false;
}
SERVER_COMMAND(ban, "<add/remove/list> <player name (if adding) or IP (if removing)> <reason (if adding)> <duration in seonds (if adding)>", "Kicks the specified player.", SENTINEL_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
if (!stricmp(argv[0], "list"))
{
std::string banList = g_pNetwork->GetBanList();
pPlayer->SendText(banList.c_str(), LTT_DEFAULT);
return false;
}
else if (!stricmp(argv[0], "add"))
{
// Need a reason
if (argc < 3)
return true;
CPlayerWeenie *other = g_pWorld->FindPlayer(argv[1]);
CClient *client;
if (other)
client = other->GetClient();
if (other && client)
{
// If no duration then default to a perma ban
if (argc < 4)
{
// Perma Ban
g_pNetwork->AddBan(client->GetHostAddress()->sin_addr, pPlayer->GetName().c_str(), argv[2], client->GetAccountInfo().id);
g_pNetwork->KickBannedClient(client, 0);
g_pDBIO->UpdateBan(client->GetAccountInfo().id, 1);
}
else if (atol(argv[3]) > 0)
{
// Timed Ban
g_pNetwork->AddBan(client->GetHostAddress()->sin_addr, pPlayer->GetName().c_str(), argv[2], atol(argv[3]), client->GetAccountInfo().id);
g_pNetwork->KickBannedClient(client, atol(argv[3]));
g_pDBIO->UpdateBan(client->GetAccountInfo().id, 1);
}
pPlayer->SendText("Ban added.", LTT_DEFAULT);
SERVER_INFO << "Client" << client->GetSlot() << "(" << client->GetAccount() << ") has been banned.";
}
else
{
pPlayer->SendText("Couldn't find player.", LTT_DEFAULT);
}
return false;
}
else if (!stricmp(argv[0], "remove"))
{
if (argc < 2)
return true;
uint32_t ipaddr = inet_addr(argv[1]);
uint32_t accountid = g_pNetwork->GetBanID(*(in_addr *)&ipaddr);
if (ipaddr != 0 && ipaddr != 0xFFFFFFFF)
{
if (g_pNetwork->RemoveBan(*(in_addr *)&ipaddr))
{
pPlayer->SendText("Ban removed.", LTT_DEFAULT);
g_pDBIO->UpdateBan(accountid, 0);
}
else
pPlayer->SendText(csprintf("Couldn't find ban for IP \"%s\"", argv[1]), LTT_DEFAULT);
}
else
{
pPlayer->SendText("Please specify an IP address.", LTT_DEFAULT);
}
return false;
}
return true;
}
CLIENT_COMMAND_WITH_CUSTOM_NAME(_private, private, "<on/off>", "Prevents other users from teleporting to you.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("Privacy mode enabled. Other users can no longer teleport to you using the @tele command.", LTT_DEFAULT);
pPlayer->m_bPrivacyMode = true;
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("Privacy mode disabled. Other users can now teleport to you using @tele command.", LTT_DEFAULT);
pPlayer->m_bPrivacyMode = false;
}
return true;
}
CLIENT_COMMAND(instakill, "<radius>", "Deals damage to all nearby creatures.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
int radius = argc >= 1 ? atoi(argv[0]) : 30;
if (radius < 0)
radius = 0;
std::list<CWeenieObject *> results;
g_pWorld->EnumNearby(pPlayer, radius, &results);
for (auto &entry : results)
{
if (!entry->IsCreature())
continue;
if (entry->_IsPlayer())
continue;
if (entry->IsDead())
continue;
if (!entry->IsAttackable())
continue;
DamageEventData dmgEvent;
dmgEvent.weapon = NULL;
dmgEvent.source = pPlayer;
dmgEvent.target = entry;
dmgEvent.damage_form = DF_PHYSICAL;
dmgEvent.damage_type = DAMAGE_TYPE::BLUDGEON_DAMAGE_TYPE;
dmgEvent.damageAfterMitigation = dmgEvent.damageBeforeMitigation = 1000000;
pPlayer->TryToDealDamage(dmgEvent);
}
return false;
}
CLIENT_COMMAND(attackable, "<on/off>", "Prevents you from being targeted by monsters.", BASIC_ACCESS, GENERAL_CATEGORY)
{
if (!g_pConfig->EnableAttackableCommand() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is not enabled on this server.", LTT_DEFAULT);
return false;
}
if (argc < 1)
return true;
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("You are now attackable.", LTT_DEFAULT);
pPlayer->m_Qualities.SetBool(ATTACKABLE_BOOL, TRUE);
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("You are no longer attackable.", LTT_DEFAULT);
pPlayer->m_Qualities.SetBool(ATTACKABLE_BOOL, FALSE);
}
else
return true;
return false;
}
CLIENT_COMMAND(dropitemsondeath, "<on/off>", "Determines if you should or not drop items when you die.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("You now drop items when you die.", LTT_DEFAULT);
pPlayer->m_Qualities.SetInt(BONDED_INT, 0);
pPlayer->NotifyIntStatUpdated(BONDED_INT);
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("You no longer drop items when you die.", LTT_DEFAULT);
pPlayer->m_Qualities.SetInt(BONDED_INT, 1);
pPlayer->NotifyIntStatUpdated(BONDED_INT);
}
else
return true;
return false;
}
CLIENT_COMMAND(usecomponents, "<on/off>", "Allows you to cast spells without having the necessary components.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("You now require components to cast spells.", LTT_DEFAULT);
pPlayer->m_Qualities.SetBool(SPELL_COMPONENTS_REQUIRED_BOOL, TRUE);
pPlayer->NotifyBoolStatUpdated(SPELL_COMPONENTS_REQUIRED_BOOL);
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("You no longer require components to cast spells.", LTT_DEFAULT);
pPlayer->m_Qualities.SetBool(SPELL_COMPONENTS_REQUIRED_BOOL, FALSE);
pPlayer->NotifyBoolStatUpdated(SPELL_COMPONENTS_REQUIRED_BOOL);
}
else
return true;
return false;
}
CLIENT_COMMAND(learnschool, "school", "Adds all spells of the given school (war, life, item, creature).", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
std::string school = argv[0];
int schoolNum = 0;
if (school == "war")
{
schoolNum = 1;
}
else if (school == "life")
{
schoolNum = 2;
}
else if (school == "item")
{
schoolNum = 3;
}
else if (school == "creature")
{
schoolNum = 4;
}
else
{
pPlayer->SendText("Invalid spell school.", LTT_DEFAULT);
return false;
}
CSpellTable* pSpellTable = MagicSystem::GetSpellTable();
for (auto spell : pSpellTable->_spellBaseHash)
{
if (spell.second._school == schoolNum)
{
unsigned int sp = spell.second._meta_spell._spell->_spell_id;
pPlayer->m_Qualities.AddSpell(sp);
BinaryWriter addSpellToSpellbook;
addSpellToSpellbook.Write<uint32_t>(0x2C1);
addSpellToSpellbook.Write<uint32_t>(sp);
pPlayer->SendNetMessage(&addSpellToSpellbook, PRIVATE_MSG, TRUE, FALSE);
}
}
return false;
}
CLIENT_COMMAND(addspellbyid, "id", "Adds a spell by ID", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
int id = atoi(argv[0]);
CSpellTable * pSpellTable = MagicSystem::GetSpellTable();
if (!id || !pSpellTable || !pSpellTable->GetSpellBase(id))
{
pPlayer->SendText("Invalid spell id.", LTT_DEFAULT);
return false;
}
pPlayer->LearnSpell(id, true);
return false;
}
#if 0
CLIENT_COMMAND(atkc, "", "Commence attack test.", ADMIN_ACCESS)
{
pPlayer->NotifyCommenceAttack();
return false;
}
CLIENT_COMMAND(atkd, "", "Attack done test.", ADMIN_ACCESS)
{
pPlayer->NotifyAttackDone();
return false;
}
#endif
#if 0
CLIENT_COMMAND(testburden, "", "", ADMIN_ACCESS)
{
float burden = -1.0f;
pPlayer->m_Qualities.InqLoad(burden);
pPlayer->SendText(csprintf("Your burden is %f", burden), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(test, "<index>", "Performs the specified test.", ADMIN_ACCESS)
{
if (argc < 1)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
Position position = player_physobj->m_Position;
switch (atoi(argv[0]))
{
case 1:
{
float goodZ = CalcSurfaceZ(position.objcell_id, position.frame.m_origin.x, position.frame.m_origin.y);
const char* text = csprintf("CalcZ: %f PlayerZ: %f", goodZ, position.frame.m_origin.z);
pPlayer->SendText(text, LTT_DEFAULT);
break;
}
case 2:
{
double v = -1.0;
int i = -1;
pPlayer->m_Qualities.InqInt(ARMOR_LEVEL_INT, i);
pPlayer->SendText(csprintf("ArmorMod: %d", i), LTT_DEFAULT);
pPlayer->m_Qualities.InqFloat(ARMOR_MOD_VS_FIRE_FLOAT, v);
pPlayer->SendText(csprintf("ArmorFireMod: %f", v), LTT_DEFAULT);
pPlayer->m_Qualities.InqFloat(ARMOR_MOD_VS_BLUDGEON_FLOAT, v);
pPlayer->SendText(csprintf("ArmorBludgeonMod: %f", v), LTT_DEFAULT);
pPlayer->m_Qualities.InqFloat(RESIST_FIRE_FLOAT, v);
pPlayer->SendText(csprintf("ResistFireMod: %f", v), LTT_DEFAULT);
pPlayer->m_Qualities.InqFloat(RESIST_BLUDGEON_FLOAT, v);
pPlayer->SendText(csprintf("ResistBludgeonMod: %f", v), LTT_DEFAULT);
break;
}
case 3:
{
CWeenieObject *weenie = g_pWeenieFactory->CreateWeenieByName("Virindi Puppet", &pPlayer->m_Position.add_offset(Vector(0.0, 5, 1)), true);
if (weenie)
{
CMonsterWeenie *monster = (CMonsterWeenie *)weenie;
}
break;
}
case 4:
{
CWeenieObject *weenie = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (weenie && weenie->AsMonster() && !weenie->AsPlayer())
{
weenie->AsMonster()->MakeSpellcastingManager()->CreatureBeginCast(pPlayer->GetID(), 27);
}
break;
}
case 5:
{
pPlayer->set_state(pPlayer->m_PhysicsState & ~(GRAVITY_PS), TRUE);
break;
}
case 6:
{
pPlayer->set_state(pPlayer->m_PhysicsState | (GRAVITY_PS), TRUE);
break;
}
case 3: {
CBaseItem *pSpawn = new CBoboHelm();
pSpawn->m_Position = position;
g_pWorld->CreateEntity(pSpawn);
BinaryWriter* co = pSpawn->CreateMessage();
//OutputConsoleBytes(co->GetData(), co->GetSize());
delete co;
break;
}
case 4: {
CBaseItem *pSpawn = new CPhatRobe();
pSpawn->m_Position = position;
g_pWorld->CreateEntity(pSpawn);
BinaryWriter* co = pSpawn->CreateMessage();
//OutputConsoleBytes(co->GetData(), co->GetSize());
delete co;
break;
}
}
return false;
}
#endif
CLIENT_COMMAND(animation, "<index> [speed=1]", "Plays a primary animation.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
WORD wIndex = atoi(argv[0]);
float fSpeed = (argc >= 2) ? (float)atof(argv[1]) : 1.0f;
fSpeed = min(10.0f, max(0.1f, fSpeed));
pPlayer->_server_control_timestamp += 2;
pPlayer->last_move_was_autonomous = false;
MovementParameters params;
params.action_stamp = ++pPlayer->m_wAnimSequence;
params.speed = fSpeed;
params.autonomous = 0;
params.modify_interpreted_state = 1;
MovementStruct mvs;
mvs.motion = GetCommandID(wIndex);
mvs.params = &params;
mvs.type = MovementTypes::RawCommand;
pPlayer->get_minterp()->PerformMovement(mvs);
pPlayer->Animation_Update();
return false;
}
CLIENT_COMMAND(animationother, "<index> [speed=1]", "Plays a primary animation.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
if (argc < 1)
return true;
CWeenieObject *other = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!other)
return false;
WORD wIndex = atoi(argv[0]);
float fSpeed = (argc >= 2) ? (float)atof(argv[1]) : 1.0f;
fSpeed = min(10.0f, max(0.1f, fSpeed));
other->_server_control_timestamp += 2;
other->last_move_was_autonomous = false;
MovementParameters params;
params.action_stamp = ++other->m_wAnimSequence;
params.speed = fSpeed;
params.autonomous = 0;
params.modify_interpreted_state = 1;
MovementStruct mvs;
mvs.motion = GetCommandID(wIndex);
mvs.params = &params;
mvs.type = MovementTypes::RawCommand;
other->get_minterp()->PerformMovement(mvs);
other->Animation_Update();
return false;
}
CLIENT_COMMAND(setprefix, "<1 for on, 0 for off>", "Adds a prefix to your name such as +Donor.", DONOR_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
std::string nameString = pPlayer->InqStringQuality(NAME_STRING, "");
ReplaceString(nameString, "+Contributor ", "");
ReplaceString(nameString, "+Advocate ", "");
ReplaceString(nameString, "+Donor ", "");
ReplaceString(nameString, "+Sentinel ", "");
ReplaceString(nameString, "+Admin ", "");
ReplaceString(nameString, "+", "");
if (atoi(argv[0]))
{
if (player_client->GetAccessLevel() >= ADMIN_ACCESS)
nameString = std::string("+") + nameString;
else if (player_client->GetAccessLevel() >= SENTINEL_ACCESS)
nameString = std::string("+Sentinel ") + nameString;
else if (player_client->GetAccessLevel() >= ADVOCATE_ACCESS)
nameString = std::string("+Advocate ") + nameString;
else if (player_client->GetAccessLevel() >= DONOR_ACCESS)
nameString = std::string("+Donor ") + nameString;
}
if (strcmp(nameString.c_str(), pPlayer->InqStringQuality(NAME_STRING, "").c_str()))
{
pPlayer->m_Qualities.SetString(NAME_STRING, nameString.c_str());
pPlayer->NotifyStringStatUpdated(NAME_STRING, false);
}
return false;
}
#if 0
CLIENT_COMMAND(setbael, "", "Sets you to be Bael'Zharon.", ADMIN_ACCESS)
{
if (argc < 1)
return true;
g_pWeenieFactory->ApplyWeenieDefaults(pPlayer, 0x2275);
pPlayer->m_Qualities.SetInt(RADARBLIP_COLOR_INT, 2);
pPlayer->m_Qualities.SetInt(PLAYER_KILLER_STATUS_INT, Baelzharon_PKStatus);
pPlayer->m_Qualities.SetInt(CONTAINERS_CAPACITY_INT, 7);
pPlayer->m_Qualities.SetInt(ITEMS_CAPACITY_INT, 200);
player_client->GetEvents()->BeginLogout();
return false;
}
#endif
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(setplayer, "[wcid]", "Sets your Player Character defaults to that of the given wcid.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
g_pWeenieFactory->ApplyWeenieDefaults(pPlayer, atoi(argv[0]));
pPlayer->m_Qualities.SetInt(RADARBLIP_COLOR_INT, 2);
pPlayer->m_Qualities.SetInt(PLAYER_KILLER_STATUS_INT, Baelzharon_PKStatus);
pPlayer->m_Qualities.SetInt(CONTAINERS_CAPACITY_INT, 7);
pPlayer->m_Qualities.SetInt(ITEMS_CAPACITY_INT, 200);
player_client->GetEvents()->BeginLogout();
return false;
}
#endif
CLIENT_COMMAND(setname, "[name]", "Changes the last assessed target's name.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
if (pPlayer->m_LastAssessed)
{
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (target)
{
target->m_Qualities.SetString(NAME_STRING, argv[0]);
target->NotifyStringStatUpdated(NAME_STRING, false);
pPlayer->SendText("Target name changed successfully.", LTT_DEFAULT);
}
}
return false;
}
#if 0
CLIENT_COMMAND(setmodel, "[monster]", "Changes your model to a monster.", ADMIN_ACCESS)
{
pPlayer->SendText("Command disabled.", LTT_DEFAULT);
return false;
/*
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
{
return true;
}
CCapturedWorldObjectInfo *pMonsterInfo = g_pGameDatabase->GetCapturedMonsterData(argv[0]);
if (!pMonsterInfo)
{
pPlayer->SendText("Couldn't find that monster!", LTT_DEFAULT);
return false;
}
float fScale = 1.0f;
if (argc >= 2)
{
fScale = (float)atof(argv[1]);
if (fScale < 0.01)
fScale = 0.01f;
if (fScale > 1000.0)
fScale = 1000;
}
pPlayer->m_miBaseModel = pMonsterInfo->appearance;
pPlayer->SetSetupID(pMonsterInfo->physics.setup_id);
pPlayer->SetMotionTableID(pMonsterInfo->physics.mtable_id);
pPlayer->SetSoundTableID(pMonsterInfo->physics.stable_id);
pPlayer->SetPETableID(pMonsterInfo->physics.phstable_id);
pPlayer->m_scale = pMonsterInfo->physics.object_scale * fScale;
pPlayer->UpdateEntity(pPlayer);
return false;
*/
}
#endif
CLIENT_COMMAND(invis, "<on/off>", "Turn invisibility on or off", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("You are now invisible.", LTT_DEFAULT);
pPlayer->m_Qualities.SetBool(VISIBILITY_BOOL, false);
pPlayer->NotifyBoolStatUpdated(VISIBILITY_BOOL, false);
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("You are now visible.", LTT_DEFAULT);
pPlayer->m_Qualities.RemoveBool(VISIBILITY_BOOL);
pPlayer->NotifyBoolStatUpdated(VISIBILITY_BOOL, false);
}
else
return true;
return false;
}
CLIENT_COMMAND(radar, "<on/off>", "Turn Radar visibility on or off.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("You are now visible on radar.", LTT_DEFAULT);
pPlayer->m_Qualities.SetInt(SHOWABLE_ON_RADAR_INT, 4);
pPlayer->NotifyIntStatUpdated(SHOWABLE_ON_RADAR_INT, false);
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("You are no longer visible on radar.", LTT_DEFAULT);
pPlayer->m_Qualities.SetInt(SHOWABLE_ON_RADAR_INT, 1);
pPlayer->NotifyIntStatUpdated(SHOWABLE_ON_RADAR_INT, false);
}
else
return true;
return false;
}
/*
CLIENT_COMMAND(motion, "<index> [speed=1]", "Plays a sequenced animation.", BASIC_ACCESS)
{
if (argc < 1)
return true;
WORD wIndex = atoi(argv[0]);
float fSpeed = (argc >= 2) ? (float)atof(argv[1]) : 1.0f;
pPlayer->Animation_PlaySimpleAnimation(wIndex, fSpeed);
return false;
}
*/
void SendDungeonInfo(CPlayerWeenie* pPlayer, DungeonDesc_t* pInfo)
{
pPlayer->SendText(csprintf("Information for ID %04X:", pInfo->wBlockID), LTT_DEFAULT);
pPlayer->SendText(csprintf("Name: %s\nAuthor: %s\nDescription: %s", pInfo->szDungeonName, pInfo->szAuthor, pInfo->szDescription), LTT_DEFAULT);
}
void SendDungeonInfo(CPlayerWeenie* pPlayer, WORD wBlockID)
{
uint32_t bitshift = wBlockID * 65536;
DungeonDesc_t* pInfo = g_pWorld->GetDungeonDesc(wBlockID);
if (!pInfo)
{
if (!g_pWorld->DungeonExists(wBlockID))
pPlayer->SendText("That's not a dungeon.", LTT_DEFAULT);
else
pPlayer->SendText("That dungeon has not been described.", LTT_DEFAULT);
}
else
SendDungeonInfo(pPlayer, pInfo);
}
CLIENT_COMMAND(exportrecipe, "<recipeid>", "Export recipe number", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
{
pPlayer->SendText("No recipe ID given", LTT_DEFAULT);
return true;
}
uint32_t recipeId = stoi(argv[0], NULL, 10);
// Get CCraftOperation that aligns with recipeid
CCraftOperation *craft = g_pPortalDataEx->_craftTableData._operations.lookup(recipeId);
if (!craft)
{
pPlayer->SendText(csprintf("Unable to find recipe ID: %s.", recipeId), LTT_DEFAULT);
return true;
}
JsonCraftOperation jcraft(*craft, recipeId);
json recipeData;
//craft->PackJson(recipeData);
jcraft.PackJson(recipeData);
string dataFile = std::to_string(recipeId) + ".json";
ofstream ofstream(dataFile);
if (!ofstream.bad())
{
ofstream << recipeData;
ofstream.close();
}
pPlayer->SendText("RecipeID saved in recipe folder.", LTT_DEFAULT);
return true;
}
CLIENT_COMMAND(importrecipe, "<recipeid>", "Import a recipes", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
{
pPlayer->SendText("No recipe ID given", LTT_DEFAULT);
return true;
}
uint32_t recipeId = stoi(argv[0], NULL, 10);
// Get CCraftOperation that aligns with recipeid
CCraftOperation *craft = g_pPortalDataEx->_craftTableData._operations.lookup(recipeId);
if (!craft)
{
pPlayer->SendText(csprintf("Unable to find recipe ID: %s.", recipeId), LTT_DEFAULT);
return true;
}
string dataFile = std::to_string(recipeId) + ".json";
ifstream ifstream(dataFile.c_str());
if (ifstream.is_open())
{
json recipeData;
ifstream >> recipeData;
ifstream.close();
CCraftOperation newcraft;
newcraft.UnPackJson(recipeData);
g_pPortalDataEx->_craftTableData._operations[recipeId] = newcraft;
}
pPlayer->SendText(csprintf("RecipeID %d loaded and updated.", recipeId), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(dungeon, "<command>", "Dungeon commands.", BASIC_ACCESS, EXPLORE_CATEGORY)
{
if (argc < 1)
return true;
if (!g_pConfig->EnableTeleCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is now only available on servers running in Explorer mode.", LTT_DEFAULT);
return false;
}
if (!stricmp(argv[0], "help"))
{
if (argc < 2)
{
pPlayer->SendText("Dungeon commands:", LTT_DEFAULT);
pPlayer->SendText("@dungeon help [command]\n@dungeon info [block/name]\n@dungeon list\n@dungeon random\n@dungeon search <substring>\n@dungeon set <name>\n@dungeon tele <block/name>\n@dungeon unknown", LTT_DEFAULT);
return false;
}
if (!stricmp(argv[1], "info"))
{
pPlayer->SendText("@dungeon info - Retrieves information about your current dungeon.", LTT_DEFAULT);
pPlayer->SendText("@dungeon info [block] - Retrieves dungeon information using a hex BlockID.", LTT_DEFAULT);
pPlayer->SendText("@dungeon info [name] - Retrieves dungeon information by name.", LTT_DEFAULT);
}
else if (!stricmp(argv[1], "list"))
pPlayer->SendText("@dungeon list - Displays a list of named dungeons.", LTT_DEFAULT);
else if (!stricmp(argv[1], "set"))
pPlayer->SendText("@dungeon set <name> - Sets your current dungeon's name, and its drop point.", LTT_DEFAULT);
else if (!stricmp(argv[1], "tele"))
{
pPlayer->SendText("@dungeon tele <block> - Teleports to a dungeon by BlockID.", LTT_DEFAULT);
pPlayer->SendText("@dungeon tele <name> - Teleports to a dungeon by name.", LTT_DEFAULT);
}
else if (!stricmp(argv[1], "unknown"))
pPlayer->SendText("@dungeon unknown - List of unnamed dungeon BlockIDs.", LTT_DEFAULT);
else if (!stricmp(argv[1], "random"))
pPlayer->SendText("@dungeon random - Teleports you to a random dungeon.", LTT_DEFAULT);
else if (!stricmp(argv[1], "search"))
pPlayer->SendText("@dungeon search <substring> - Searchs for dungeon names that contain the substring.", LTT_DEFAULT);
else
pPlayer->SendText("Unknown @dungeon command. Type @dungeon help for a list of valid choices.", LTT_DEFAULT);
return false;
}
else if (!stricmp(argv[0], "unknown"))
{
LocationMap* pDungeons = g_pWorld->GetDungeons();
LocationMap::iterator i = pDungeons->begin();
LocationMap::iterator e = pDungeons->end();
uint32_t dwCount = 0;
std::string UnkList = "Unknown Dungeons:\n";
while (i != e)
{
//uint32_t dwCell = i->first;
WORD wBlockID = BLOCK_WORD(i->first);
if (!g_pWorld->GetDungeonDesc(wBlockID))
{
UnkList += csprintf("%04X, ", wBlockID);
dwCount++;
}
i++;
}
UnkList += csprintf("\nEnd of Unknown Dungeons (%lu unknown)", dwCount);
pPlayer->SendText(UnkList.c_str(), LTT_DEFAULT);
}
else if (!stricmp(argv[0], "tele"))
{
if (argc < 2)
return true;
if (strlen(argv[1]) < 5)
{
//by ID
WORD wBlockID = (WORD)strtoul(argv[1], NULL, 16);
bool forceFindDrop = false;
if (argc >= 3)
{
forceFindDrop = atoi(argv[2]) ? true : false;
}
if (!wBlockID)
{
pPlayer->SendText("Bad block ID. Please use a valid hex value.", LTT_DEFAULT);
return false;
}
DungeonDesc_t *pInfo = g_pWorld->GetDungeonDesc(wBlockID);
if (!pInfo || forceFindDrop)
{
if (!g_pWorld->DungeonExists(wBlockID))
{
pPlayer->SendText("That dungeon doesn't exist!", LTT_DEFAULT);
}
else
{
Position position = g_pWorld->FindDungeonDrop(wBlockID);
if (!position.objcell_id)
pPlayer->SendText("Couldn't find a drop zone there.", LTT_DEFAULT);
else
{
pPlayer->SendText(csprintf("Teleporting you to BlockID %04X ..", wBlockID), LTT_DEFAULT);
pPlayer->Movement_Teleport(position);
}
}
}
else
{
pPlayer->SendText(csprintf("Teleporting you to %s (%04X) ..", pInfo->szDungeonName, pInfo->wBlockID), LTT_DEFAULT);
pPlayer->Movement_Teleport(pInfo->position);
}
}
else
{
//by name
const char *name = argv[1];
DungeonDesc_t* pInfo = g_pWorld->GetDungeonDesc(name);
if (pInfo)
{
pPlayer->SendText(csprintf("Teleporting you to %s (%04X) ..", pInfo->szDungeonName, pInfo->wBlockID), LTT_DEFAULT);
pPlayer->Movement_Teleport(pInfo->position);
}
else
pPlayer->SendText("There is no dungeon by that name. Use @dungeon list for named dungeons. Remember to use quotes.", LTT_DEFAULT);
}
}
else if (!stricmp(argv[0], "set"))
{
if (argc < 2)
return true;
uint32_t dwCell = pPlayer->GetLandcell();
if (CELL_WORD(dwCell) < 0xFF) {
pPlayer->SendText("Go inside first, silly!", LTT_DEFAULT);
return false;
}
if (strlen(argv[1]) < 5) {
pPlayer->SendText("Please enter a name of at least 5 characters in length.", LTT_DEFAULT);
return false;
}
if (strlen(argv[1]) > 80) {
pPlayer->SendText("Please enter a shorter name.", LTT_DEFAULT);
return false;
}
time_t ltime = time(NULL);
tm* tptr = localtime(&ltime);
char* szTime;
if (tptr)
{
szTime = asctime(tptr);
szTime[strlen(szTime) - 1] = 0; //Remove \n
}
else
szTime = "???";
WORD wBlockID = BLOCK_WORD(dwCell);
const char* szName = argv[1];
const char* szAuthor = pPlayer->GetName().c_str();
const char* szDescription = csprintf("Recorded %s", szTime);
g_pWorld->SetDungeonDesc(wBlockID, szName, szAuthor, szDescription, player_physobj->m_Position);
pPlayer->SendText(csprintf("Dungeon information set. (%04X = \"%s\")", wBlockID, szName), LTT_DEFAULT);
}
else if (!stricmp(argv[0], "info"))
{
if (argc < 2)
{
uint32_t dwCell = pPlayer->GetLandcell();
if (CELL_WORD(dwCell) < 0xFF) {
pPlayer->SendText("Go inside first, silly!", LTT_DEFAULT);
return false;
}
SendDungeonInfo(pPlayer, BLOCK_WORD(dwCell));
return false;
}
if (strlen(argv[1]) < 6)
{
//by ID
WORD wBlockID = (WORD)strtoul(argv[1], NULL, 16);
if (!wBlockID)
{
pPlayer->SendText("Bad block ID. Please use a valid hex value. Remember to use quotes around names!", LTT_DEFAULT);
return false;
}
SendDungeonInfo(pPlayer, wBlockID);
}
else
{
//by name
const char* szName = argv[1];
DungeonDesc_t* pInfo = g_pWorld->GetDungeonDesc(szName);
if (pInfo)
SendDungeonInfo(pPlayer, pInfo);
else
pPlayer->SendText("There is no dungeon by that name. Use @dungeon list for named dungeons. Use quotes around names.", LTT_DEFAULT);
}
}
else if (!stricmp(argv[0], "list"))
{
DungeonDescMap* pDDs = g_pWorld->GetDungeonDescs();
DungeonDescMap::iterator i = pDDs->begin();
DungeonDescMap::iterator e = pDDs->end();
std::string DL = "Dungeon List:";
while (i != e)
{
DL += csprintf("\n%04X - %s", i->second.wBlockID, i->second.szDungeonName);
i++;
}
DL += csprintf("\nEnd of Dungeon List (%lu named dungeons)", (uint32_t)pDDs->size());
pPlayer->SendText(DL.c_str(), LTT_DEFAULT);
}
else if (!stricmp(argv[0], "search"))
{
if ((argc < 2) || (strlen(argv[1]) <= 0))
{
pPlayer->SendText("You must enter a search string.", LTT_DEFAULT);
return 0;
}
DungeonDescMap* pDDs = g_pWorld->GetDungeonDescs();
DungeonDescMap::iterator i = pDDs->begin();
DungeonDescMap::iterator e = pDDs->end();
uint32_t dwCount = 0;
std::string DL = "Dungeon Matches:";
while (i != e)
{
std::string name(i->second.szDungeonName);
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
std::string arg(argv[1]);
std::transform(arg.begin(), arg.end(), arg.begin(), ::tolower);
//static char szDungeonName[100];
//strncpy(szDungeonName, i->second.szDungeonName, 100);
//if (strstr(strlwr(szDungeonName), strlwr(argv[1])))
if (name.find(arg))
{
DL += csprintf("\n%04X - %s", i->second.wBlockID, i->second.szDungeonName);
dwCount++;
}
i++;
}
DL += csprintf("\nEnd of List (%lu matches)", dwCount);
pPlayer->SendText(DL.c_str(), LTT_DEFAULT);
}
else if (!stricmp(argv[0], "random"))
{
Position position = g_pWorld->FindDungeonDrop();
if (!position.objcell_id)
{
pPlayer->SendText("No dungeons to teleport to.", LTT_DEFAULT);
}
else
{
WORD wBlockID = BLOCK_WORD(position.objcell_id);
DungeonDesc_t *pDD;
if (pDD = g_pWorld->GetDungeonDesc(wBlockID))
{
pPlayer->SendText(csprintf("Teleporting you to %s ..", pDD->szDungeonName), LTT_DEFAULT);
position = pDD->position;
}
else
pPlayer->SendText("Teleporting you to a random dungeon..", LTT_DEFAULT);
pPlayer->Movement_Teleport(position);
}
}
else
return true;
return false;
}
CLIENT_COMMAND(player, "<command>", "Player commands.", BASIC_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return 1;
if (!stricmp(argv[0], "help"))
{
if (argc < 2)
{
pPlayer->SendText("Player commands:", LTT_DEFAULT);
pPlayer->SendText("@player help [command]\n@player info <name>\n@player list\n@player tele <name>", LTT_DEFAULT);
return false;
}
if (!stricmp(argv[1], "info"))
pPlayer->SendText("@player info <name> - Retrieves information on a player, by name.", LTT_DEFAULT);
else if (!stricmp(argv[1], "list"))
pPlayer->SendText("@player list - Displays a list of players currently logged in.", LTT_DEFAULT);
else if (!stricmp(argv[1], "tele"))
{
pPlayer->SendText("@player tele <name> - Teleports to a player by name.", LTT_DEFAULT);
pPlayer->SendText("NOTE: This is the same as the @tele command.", LTT_DEFAULT);
}
else
pPlayer->SendText("Unknown @player command. Type @player help for a list of valid choices.", LTT_DEFAULT);
return false;
}
else if (!stricmp(argv[0], "tele"))
{
pPlayer->SendText("NOTE: Use @tele instead. ;)", LTT_DEFAULT);
tele(player_client, pPlayer, player_physobj, &argv[1], argc - 1);
}
else if (!stricmp(argv[0], "info"))
{
if (argc < 2)
return true;
CPlayerWeenie *pOther = g_pWorld->FindPlayer(argv[1]);
if (!pOther)
pPlayer->SendText(csprintf("Couldn't find player \"%s\"", argv[1]), LTT_DEFAULT);
else
{
if (pPlayer->IsSentinel())
{
const char *info = csprintf(
"Player Info:\nGUID: 0x%08X\nName: %s\nLocation: %08X %.1f %.1f %.1f",
pOther->GetID(), pOther->GetName().c_str(), pOther->GetLandcell(),
pOther->m_Position.frame.m_origin.x, pOther->m_Position.frame.m_origin.y, pOther->m_Position.frame.m_origin.z);
pPlayer->SendText(info, LTT_DEFAULT);
}
else
{
pPlayer->SendText("You do not have the access to use this command.", LTT_DEFAULT);
}
}
}
else if (!stricmp(argv[0], "list"))
{
PlayerWeenieMap *pPlayers = g_pWorld->GetPlayers();
std::string playerList = "Player List:";
for (auto &entry : *pPlayers)
{
if (!entry.second->GetClient())
continue;
if (player_client->GetAccessLevel() >= SENTINEL_ACCESS)
{
playerList += csprintf("\n%s (Account: %s IP: %s)",
entry.second->GetName().c_str(),
entry.second->GetClient()->GetAccount(),
inet_ntoa(entry.second->GetClient()->GetHostAddress()->sin_addr));
}
else
{
playerList += csprintf("\n%s", entry.second->GetName().c_str());
}
}
playerList += csprintf("\nEnd of Player List (%u) - Unique IPs (%u)", (uint32_t)pPlayers->size(), g_pNetwork->GetUniques());
pPlayer->SendText(playerList.c_str(), LTT_DEFAULT);
}
else
return true;
return false;
}
/*
CLIENT_COMMAND(doomshard, "[palette=0xBF7]", "Spawns a doom shard.", BASIC_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
WORD palette = 0xBF7;
if (argc >= 1)
palette = (unsigned short)strtoul(argv[0], NULL, 16);
CMonsterWeenie *pDoomShard = new CMonsterWeenie();
pDoomShard->SetSetupID(0x02000700);
pDoomShard->SetScale(1.6f);
pDoomShard->SetName("Doom Shard");
pDoomShard->SetInitialPosition(pPlayer->GetPosition());
pDoomShard->m_miBaseModel.dwBasePalette = 0xBEF;
pDoomShard->m_miBaseModel.lPalettes.push_back(PaletteRpl(palette, 0x00, 0x00));
g_pWorld->CreateEntity(pDoomShard);
return false;
}
*/
#if 0
CLIENT_COMMAND(spawnbsd, "", "Spawn bsd for testing if the data is available.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
g_pGameDatabase->SpawnBSD();
return false;
}
#endif
CLIENT_COMMAND(freecam, "", "Allows free camera movement.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
pPlayer->set_state(pPlayer->m_PhysicsState ^ (uint32_t)(PARTICLE_EMITTER_PS), TRUE);
return false;
}
#if 0
CLIENT_COMMAND(spawnsetup, "[id]", "Spawns something by setup ID using default palettes, animations, effect sets etc.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
{
return true;
}
uint32_t setupID = strtoul(argv[0], NULL, 16);
if (!(setupID & 0xFF000000))
setupID |= 0x02000000;
CSetup *pSetup = CSetup::Get(setupID);
if (!pSetup)
{
pPlayer->SendText(csprintf("Could not find setup ID 0x%08X", setupID), 1);
return false;
}
CMonsterWeenie *pSpawn = new CMonsterWeenie();
pSpawn->SetSetupID(setupID);
pSpawn->SetName(csprintf("Model #%08X", setupID));
pSpawn->SetInitialPosition(pPlayer->GetPosition());
pSpawn->SetSoundTableID(pSetup->default_stable_id);
pSpawn->SetMotionTableID(pSetup->default_mtable_id);
pSpawn->SetPETableID(pSetup->default_phstable_id);
g_pWorld->CreateEntity(pSpawn);
pSpawn->SetLongDescription(csprintf("This monster was spawned by %s.\nSetup #: %08X\n", pPlayer->GetName().c_str(), setupID));
CSetup::Release(pSetup);
return false;
}
CLIENT_COMMAND(spawn2, "[name] [replacement index] [palette index] [shade from 0 to 1]", "Spawns a custom decorated monster.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
CCapturedWorldObjectInfo *pMonsterInfo = g_pGameDatabase->GetCapturedMonsterData(argv[0]);
if (!pMonsterInfo)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
if (argc < 2)
{
pPlayer->SendText(csprintf("Monster has %u replacement types.", g_ClothingCache.GetNumTablesOfSetupID(pMonsterInfo->physics.setup_id)), LTT_DEFAULT);
return false;
}
ClothingTable *pCT = g_ClothingCache.GetTableByIndexOfSetupID(pMonsterInfo->physics.setup_id, atoi(argv[1]));
if (!pCT)
{
pPlayer->SendText(csprintf("Bad replacement index. Monster has %u replacement types.", g_ClothingCache.GetNumTablesOfSetupID(pMonsterInfo->physics.setup_id)), LTT_DEFAULT);
return true;
}
if (argc < 3)
{
pPlayer->SendText(csprintf("Monster replacement has %u palette variations.", pCT->_paletteTemplatesHash.size()), LTT_DEFAULT);
ClothingTable::Release(pCT);
return false;
}
unsigned int paletteIndex = (unsigned)atoi(argv[2]);
if (paletteIndex >= pCT->_paletteTemplatesHash.size())
{
pPlayer->SendText(csprintf("Bad palette index. Monster replacement has %u palette variations.", pCT->_paletteTemplatesHash.size()), LTT_DEFAULT);
ClothingTable::Release(pCT);
return false;
}
float fScale = 1.0f;
bool bAnimate = false;
CWeenieObject *pMonster = g_pGameDatabase->CreateFromCapturedData(pMonsterInfo);
// Modify these
pMonster->SetInitialPosition(pPlayer->GetPosition());
pMonster->m_bObjDescOverride = true;
CSetup *pSetup = CSetup::Get(pMonster->GetSetupID());
if (pSetup)
{
if (pSetup->num_parts > 0 && pSetup->parts)
{
uint32_t gfxID = pSetup->parts[0];
CGfxObj *gfxobj = CGfxObj::Get(gfxID);
if (gfxobj)
{
for (uint32_t i = 0; i < gfxobj->num_surfaces; i++)
{
if (gfxobj->m_rgSurfaces[i])
{
pMonster->m_ObjDescOverride.paletteID = gfxobj->m_rgSurfaces[i]->GetOriginalPaletteID();
}
}
CGfxObj::Release(gfxobj);
}
}
CSetup::Release(pSetup);
}
float shade = 1.0f;
if (argc >= 4)
{
shade = atof(argv[3]);
if (shade < 0)
shade = 0;
if (shade > 1)
shade = 1;
}
uint32_t pt = 0;
for (auto &it : pCT->_paletteTemplatesHash)
{
if (paletteIndex == 0)
{
pt = it.first;
break;
}
paletteIndex--;
}
pMonster->m_ObjDescOverride.Clear();
pCT->BuildObjDesc(pMonsterInfo->physics.setup_id, pt, &ShadePackage(shade), &pMonster->m_ObjDescOverride);
ClothingTable::Release(pCT);
// Add and spawn it
g_pWorld->CreateEntity(pMonster);
return false;
}
#endif
bool IsNumeric(const char *text)
{
if (!*text)
return false;
if (*text == '-')
text++;
do
{
if (*text < '0' || *text > '9')
return false;
} while (*++text);
return true;
}
bool IsHexNumeric(const char *text)
{
if (text[0] != '0' || text[1] != 'x')
return false;
text += 2;
do
{
if ((*text < '0' || *text > '9') && (*text < 'a' || *text > 'f') && (*text < 'A' || *text > 'F'))
return false;
} while (*++text);
return true;
}
#if 0
CLIENT_COMMAND(spawnpreset, "[preset]", "Spawn preset.", SENTINEL_ACCESS)
{
if (argc < 1)
return true;
int preset = atoi(argv[0]);
switch (preset)
{
case 1:
g_pWeenieFactory->CreateWeenieByClassID(23781, &pPlayer->m_Position, true);
g_pWeenieFactory->CreateWeenieByClassID(23789, &pPlayer->m_Position, true);
g_pWeenieFactory->CreateWeenieByClassID(24206, &pPlayer->m_Position, true);
break;
case 2:
g_pWeenieFactory->CreateWeenieByClassID(6600, &pPlayer->m_Position, true);
g_pWeenieFactory->CreateWeenieByClassID(6606, &pPlayer->m_Position, true);
g_pWeenieFactory->CreateWeenieByClassID(11986, &pPlayer->m_Position, true);
break;
case 3:
g_pWeenieFactory->CreateWeenieByClassID(100005, &pPlayer->m_Position, true);
g_pWeenieFactory->CreateWeenieByClassID(100006, &pPlayer->m_Position, true);
break;
}
return false;
}
#endif
bool g_bRestartOnNextTick = false;
#if 0
CLIENT_COMMAND(restartserver, "<yes>", "Restarts the server.", ADVOCATE_ACCESS)
{
if (argc < 1)
return true;
if (_stricmp(argv[0], "yes"))
return true;
if (g_pConfig->GetValue("weapons_testing", "0") == 0)
{
if (pPlayer->GetAccessLevel() < ADMIN_ACCESS)
{
pPlayer->SendText("You do not have access to this command.", LTT_DEFAULT);
return false;
}
}
g_bRestartOnNextTick = true;
return false;
}
#endif
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(debugresistances, "", "", ADMIN_ACCESS, GENERAL_CATEGORY)
{
CWeenieObject *target = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!target)
{
pPlayer->SendText("Assess an object first.", LTT_DEFAULT);
return false;
}
pPlayer->SendText(csprintf("Resistances of the last assessed object:\n"
"Slash: %.2f (%.2f base)\n"
"Pierce: %.2f (%.2f base)\n"
"Bludgeon: %.2f (%.2f base)\n"
"Fire: %.2f (%.2f base)\n"
"Cold: %.2f (%.2f base)\n"
"Acid: %.2f (%.2f base)\n"
"Lightning: %.2f (%.2f base)\n",
target->InqFloatQuality(RESIST_SLASH_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_SLASH_FLOAT, 1.0f, TRUE),
target->InqFloatQuality(RESIST_PIERCE_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_PIERCE_FLOAT, 1.0f, TRUE),
target->InqFloatQuality(RESIST_BLUDGEON_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_BLUDGEON_FLOAT, 1.0f, TRUE),
target->InqFloatQuality(RESIST_FIRE_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_FIRE_FLOAT, 1.0f, TRUE),
target->InqFloatQuality(RESIST_COLD_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_COLD_FLOAT, 1.0f, TRUE),
target->InqFloatQuality(RESIST_ACID_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_ACID_FLOAT, 1.0f, TRUE),
target->InqFloatQuality(RESIST_ELECTRIC_FLOAT, 1.0f, FALSE),
target->InqFloatQuality(RESIST_ELECTRIC_FLOAT, 1.0f, TRUE)), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(activeevents, "", "", ADMIN_ACCESS, SERVER_CATEGORY)
{
std::string eventText = "Enabled events:";
for (auto &entry : g_pGameEventManager->_gameEvents)
{
if (entry.second._eventState != GameEventState::Off_GameEventState)
{
eventText += "\n";
eventText += entry.first;
}
}
pPlayer->SendText(eventText.c_str(), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(startevent, "[event]", "Starts an event.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
auto &events = g_pGameEventManager->_gameEvents;
std::string eventText = "Event started.";
std::string normalizedEventName = g_pGameEventManager->NormalizeEventName(argv[0]);
if (GameEventDef *eventDesc = events.lookup(normalizedEventName))
{
if (eventDesc->_eventState != GameEventState::On_GameEventState)
{
eventDesc->_eventState = GameEventState::On_GameEventState;
g_pWorld->NotifyEventStarted(normalizedEventName.c_str());
}
}
else {
eventText = "Event already started.";
}
pPlayer->SendText(eventText.c_str(), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(stopevent, "[event]", "Stops an event.", ADMIN_ACCESS, SERVER_CATEGORY)
{
if (argc < 1)
return true;
auto &events = g_pGameEventManager->_gameEvents;
std::string eventText = "Event stopped.";
std::string normalizedEventName = g_pGameEventManager->NormalizeEventName(argv[0]);
if (GameEventDef *eventDesc = events.lookup(normalizedEventName.c_str()))
{
if (eventDesc->_eventState != GameEventState::Off_GameEventState)
{
eventDesc->_eventState = GameEventState::Off_GameEventState;
g_pWorld->NotifyEventStopped(normalizedEventName.c_str());
}
}
else {
eventText = "Event not active.";
}
pPlayer->SendText(eventText.c_str(), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(myquests, "", "", BASIC_ACCESS, CHARACTER_CATEGORY)
{
for (auto &entry : pPlayer->_questTable._quest_table)
{
std::string text = csprintf("%s - %u solves (%d)", entry.first.c_str(), entry.second._num_completions, entry.second._real_time);
if (QuestDef *questDef = CQuestDefDB::GetQuestDef(entry.first.c_str()))
{
text += csprintf("\"%s\" %d %d", questDef->_fullname.c_str(), questDef->_maxsolves, questDef->_mindelta);
}
pPlayer->SendText(text.c_str(), LTT_DEFAULT);
}
if (pPlayer->_questTable._quest_table.empty())
pPlayer->SendText("Quest list is empty.", LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(erasequest, "<name>", "", SENTINEL_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
pPlayer->_questTable.RemoveQuest(argv[0]);
pPlayer->SendText(csprintf("%s erased.",argv[0]), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(clearquests, "", "", SENTINEL_ACCESS, CHARACTER_CATEGORY)
{
pPlayer->_questTable.PurgeQuests();
pPlayer->SendText(csprintf("Quests cleared."), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(stampquest, "<name>", "", SENTINEL_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
pPlayer->_questTable.StampQuest(argv[0]);
pPlayer->SendText(csprintf("%s stamped.", argv[0]), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(setquest, "<name> [# of times to stamp]", "", SENTINEL_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 2)
return true;
if (argc > 1)
{
pPlayer->_questTable.SetQuestCompletions(argv[0], atoi(argv[1]));
pPlayer->SendText(csprintf("%s stamped %s times.", argv[0], argv[1]), LTT_DEFAULT);
}
return false;
}
CLIENT_COMMAND(incquest, "<name>", "", SENTINEL_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
pPlayer->_questTable.IncrementQuest(argv[0]);
pPlayer->SendText(csprintf("%s incremented.", argv[0]), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(decquest, "<name>", "", SENTINEL_ACCESS, CHARACTER_CATEGORY)
{
if (argc < 1)
return true;
pPlayer->_questTable.DecrementQuest(argv[0]);
pPlayer->SendText(csprintf("%s decremented.", argv[0]), LTT_DEFAULT);
return false;
}
#endif
CLIENT_COMMAND(spawntreasure, "<tier>, <amount>, <category>", "Spawn treasure of a specific tier.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
int tier = atoi(argv[0]);
int num = 1;
int cat;
if (argc < 1)
return true;
if (argc >= 2)
num = atoi(argv[1]);
if (argc >= 3)
cat = atoi(argv[2]);
for (int i = 0; i < num; i++)
{
if (argc < 3)
cat = (eTreasureCategory)getRandomNumber(2, 8);
CWeenieObject *treasure = g_pTreasureFactory->GenerateTreasure((tier), (eTreasureCategory)cat);
//CWeenieObject *treasure = g_pTreasureFactory->GenerateTreasure(atoi(argv[0]), eTreasureCategory::TreasureCategory_Armor);
if (treasure)
{
treasure->SetInitialPosition(pPlayer->m_Position.add_offset(Vector(Random::GenFloat(-2.0, 2.0), Random::GenFloat(-2.0, 2.0), 1.0)));
if (!g_pWorld->CreateEntity(treasure))
{
treasure->m_bDontClear = false;
delete treasure;
return false;
}
}
else
continue;
}
return false;
}
CLIENT_COMMAND(spawnsalvagewcid, "wcid", "Spawn full sack of salvage.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
CWeenieObject *weenieTemplate;
if (!IsNumeric(argv[0]))
return false;
weenieTemplate = g_pWeenieFactory->CreateWeenieByClassID(atoi(argv[0]), NULL, false);
if (weenieTemplate->m_Qualities.GetInt(ITEM_TYPE_INT, 0) != 1073741824)
return false;
if (weenieTemplate->m_Qualities.GetInt(ITEM_USEABLE_INT, 0) != 524296)
return false;
weenieTemplate->m_Qualities.SetInt(STRUCTURE_INT, 100);
pPlayer->SpawnCloneInContainer(weenieTemplate, 1);
delete weenieTemplate;
return false;
}
CLIENT_COMMAND(spawnwcidinv, "<name> [amount] [ptid] [shade]", "Spawn by wcid into inventory.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (g_pConfig->GetValue("weapons_testing", "0") == 0)
{
if (pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("You do not have access to this command.", LTT_DEFAULT);
return false;
}
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
CWeenieObject *weenieTemplate;
if (IsNumeric(argv[0]))
{
weenieTemplate = g_pWeenieFactory->CreateWeenieByClassID(atoi(argv[0]), NULL, false);
}
else if (IsHexNumeric(argv[0]))
{
weenieTemplate = g_pWeenieFactory->CreateWeenieByClassID(strtoul(argv[0] + 2, NULL, 16), NULL, false);
}
else
{
weenieTemplate = g_pWeenieFactory->CreateWeenieByName(argv[0], NULL, false);
}
if (!weenieTemplate)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
if (!pPlayer->IsAdmin() && atoi(g_pConfig->GetValue("weapons_testing", "0")) != 0)
{
if (weenieTemplate->m_Qualities.m_WeenieType != MeleeWeapon_WeenieType)
{
pPlayer->SendText("Only weapon spawning is enabled.", LTT_DEFAULT);
delete weenieTemplate;
return false;
}
}
int amount = 1;
if (argc >= 2)
amount = atoi(argv[1]);
if (argc >= 3)
weenieTemplate->m_Qualities.SetInt(PALETTE_TEMPLATE_INT, atoi(argv[1]));
if (argc >= 4)
weenieTemplate->m_Qualities.SetFloat(SHADE_FLOAT, atof(argv[2]));
if (!weenieTemplate->CanPickup())
{
pPlayer->SendText("That can't be spawned in a container.", LTT_DEFAULT);
delete weenieTemplate;
return false;
}
int maxStackSize = weenieTemplate->InqIntQuality(MAX_STACK_SIZE_INT, 1);
if (amount > maxStackSize * 100)
{
pPlayer->SendText("The amount requested is too large.", LTT_DEFAULT);
delete weenieTemplate;
return false;
}
pPlayer->SpawnCloneInContainer(weenieTemplate, amount);
delete weenieTemplate;
return false;
}
CLIENT_COMMAND(spawnwcidinvfresh, "<name> [amount] [ptid] [shade]", "Reload weenie and spawn by wcid into inventory.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (g_pConfig->GetValue("weapons_testing", "0") == 0)
{
if (pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("You do not have access to this command.", LTT_DEFAULT);
return false;
}
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
bool refreshed = false;
if (IsNumeric(argv[0]))
{
refreshed = g_pWeenieFactory->RefreshLocalWeenie(atoi(argv[0]));
}
else if (IsHexNumeric(argv[0]))
{
refreshed = g_pWeenieFactory->RefreshLocalWeenie(strtoul(argv[0] + 2, NULL, 16));
}
else
{
refreshed = g_pWeenieFactory->RefreshLocalWeenie(g_pWeenieFactory->GetWCIDByName(argv[0]));
}
if (!refreshed)
{
pPlayer->SendText("Couldn't reload that weenie!", LTT_DEFAULT);
return false;
}
CWeenieObject *weenieTemplate;
if (IsNumeric(argv[0]))
{
weenieTemplate = g_pWeenieFactory->CreateWeenieByClassID(atoi(argv[0]), NULL, false);
}
else if (IsHexNumeric(argv[0]))
{
weenieTemplate = g_pWeenieFactory->CreateWeenieByClassID(strtoul(argv[0] + 2, NULL, 16), NULL, false);
}
else
{
weenieTemplate = g_pWeenieFactory->CreateWeenieByName(argv[0], NULL, false);
}
if (!weenieTemplate)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
if (!pPlayer->IsAdmin() && atoi(g_pConfig->GetValue("weapons_testing", "0")) != 0)
{
if (weenieTemplate->m_Qualities.m_WeenieType != MeleeWeapon_WeenieType)
{
pPlayer->SendText("Only weapon spawning is enabled.", LTT_DEFAULT);
delete weenieTemplate;
return false;
}
}
int amount = 1;
if (argc >= 2)
amount = atoi(argv[1]);
if (argc >= 3)
weenieTemplate->m_Qualities.SetInt(PALETTE_TEMPLATE_INT, atoi(argv[1]));
if (argc >= 4)
weenieTemplate->m_Qualities.SetFloat(SHADE_FLOAT, atof(argv[2]));
if (!weenieTemplate->CanPickup())
{
pPlayer->SendText("That can't be spawned in a container.", LTT_DEFAULT);
delete weenieTemplate;
return false;
}
int maxStackSize = weenieTemplate->InqIntQuality(MAX_STACK_SIZE_INT, 1);
if (amount > maxStackSize * 100)
{
pPlayer->SendText("The amount requested is too large.", LTT_DEFAULT);
delete weenieTemplate;
return false;
}
pPlayer->SpawnCloneInContainer(weenieTemplate, amount);
delete weenieTemplate;
return false;
}
CLIENT_COMMAND(spawnwcid, "<name> [num] [ptid] [shade]", "Spawn by wcid.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
int num = 1;
if (g_pConfig->GetValue("weapons_testing", "0") == 0)
{
if (pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("You do not have access to this command.", LTT_DEFAULT);
return false;
}
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
if (argc >= 2)
num = atoi(argv[1]);
CWeenieObject *weenie;
for (int i = 0; i < num; i++)
{
if (IsNumeric(argv[0]))
{
weenie = g_pWeenieFactory->CreateWeenieByClassID(atoi(argv[0]), &pPlayer->m_Position, false);
}
else if (IsHexNumeric(argv[0]))
{
weenie = g_pWeenieFactory->CreateWeenieByClassID(strtoul(argv[0] + 2, NULL, 16), &pPlayer->m_Position, false);
}
else
{
weenie = g_pWeenieFactory->CreateWeenieByName(argv[0], &pPlayer->m_Position, false);
}
if (i > 1)
{
weenie->SetInitialPosition(pPlayer->m_Position.add_offset(Vector(Random::GenFloat(-2.0, 2.0), Random::GenFloat(-2.0, 2.0), 1.0)));
}
if (!weenie)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
if (!pPlayer->IsAdmin() && atoi(g_pConfig->GetValue("weapons_testing", "0")) != 0)
{
if (weenie->m_Qualities.m_WeenieType != MeleeWeapon_WeenieType)
{
pPlayer->SendText("Only weapon spawning is enabled.", LTT_DEFAULT);
delete weenie;
return false;
}
}
if (argc >= 3)
weenie->m_Qualities.SetInt(PALETTE_TEMPLATE_INT, atoi(argv[2]));
if (argc >= 4)
weenie->m_Qualities.SetFloat(SHADE_FLOAT, atof(argv[3]));
if (!g_pWorld->CreateEntity(weenie))
return false;
if (weenie->IsCreature())
{
pPlayer->m_dwLastSpawnedCreatureID = weenie->GetID();
}
pPlayer->m_dwLastSpawnedObjectID = weenie->GetID();
if (weenie)
weenie->m_bDontClear = false;
}
return false;
}
CLIENT_COMMAND(spawnwcidfresh, "<name> [ptid] [shade]", "Spawn by wcid.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (g_pConfig->GetValue("weapons_testing", "0") == 0)
{
if (pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("You do not have access to this command.", LTT_DEFAULT);
return false;
}
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
bool refreshed = false;
if (IsNumeric(argv[0]))
{
refreshed = g_pWeenieFactory->RefreshLocalWeenie(atoi(argv[0]));
}
else if (IsHexNumeric(argv[0]))
{
refreshed = g_pWeenieFactory->RefreshLocalWeenie(strtoul(argv[0] + 2, NULL, 16));
}
else
{
refreshed = g_pWeenieFactory->RefreshLocalWeenie(g_pWeenieFactory->GetWCIDByName(argv[0]));
}
if (!refreshed)
{
pPlayer->SendText("Couldn't reload that weenie!", LTT_DEFAULT);
return false;
}
CWeenieObject *weenie;
if (IsNumeric(argv[0]))
{
weenie = g_pWeenieFactory->CreateWeenieByClassID(atoi(argv[0]), &pPlayer->m_Position, false);
}
else if (IsHexNumeric(argv[0]))
{
weenie = g_pWeenieFactory->CreateWeenieByClassID(strtoul(argv[0] + 2, NULL, 16), &pPlayer->m_Position, false);
}
else
{
weenie = g_pWeenieFactory->CreateWeenieByName(argv[0], &pPlayer->m_Position, false);
}
if (!weenie)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
if (!pPlayer->IsAdmin() && atoi(g_pConfig->GetValue("weapons_testing", "0")) != 0)
{
if (weenie->m_Qualities.m_WeenieType != MeleeWeapon_WeenieType)
{
pPlayer->SendText("Only weapon spawning is enabled.", LTT_DEFAULT);
delete weenie;
return false;
}
}
if (argc >= 2)
weenie->m_Qualities.SetInt(PALETTE_TEMPLATE_INT, atoi(argv[1]));
if (argc >= 3)
weenie->m_Qualities.SetFloat(SHADE_FLOAT, atof(argv[2]));
if (!g_pWorld->CreateEntity(weenie))
return false;
if (weenie->IsCreature())
{
pPlayer->m_dwLastSpawnedCreatureID = weenie->GetID();
}
weenie->m_bDontClear = false;
return false;
}
CLIENT_COMMAND(spawnfresh, "<wcid>", "Refresh local json and spawn by wcid only.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (g_pConfig->GetValue("weapons_testing", "0") == 0)
{
if (pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("You do not have access to this command.", LTT_DEFAULT);
return false;
}
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (!IsNumeric(argv[0]))
{
pPlayer->SendText("Only wcids are supported.", LTT_DEFAULT);
return false;
}
if (argc < 1)
return true;
g_pWeenieFactory->RefreshLocalWeenie(atoi(argv[0]));
CWeenieObject *weenie;
weenie = g_pWeenieFactory->CreateWeenieByClassID(atoi(argv[0]), &pPlayer->m_Position, false);
if (!weenie)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
if (!g_pWorld->CreateEntity(weenie))
return false;
weenie->m_bDontClear = false;
if (weenie->IsCreature())
{
pPlayer->m_dwLastSpawnedCreatureID = weenie->GetID();
}
return false;
}
void SpawnAllAppearancesForWeenie(CPlayerWeenie *pPlayer, uint32_t wcid, bool bSpawnWithoutVariances = false, uint32_t setup_override = 0)
{
CWeenieDefaults *weenieDefs = g_pWeenieFactory->GetWeenieDefaults(wcid);
if (!weenieDefs)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return;
}
uint32_t clothing_did = 0;
if (!weenieDefs->m_Qualities.InqDataID(CLOTHINGBASE_DID, clothing_did))
{
if (bSpawnWithoutVariances)
{
CWeenieObject *weenie = g_pWeenieFactory->CreateWeenieByClassID(wcid, &pPlayer->m_Position, false);
weenie->SetInitialPosition(pPlayer->m_Position.add_offset(Vector(Random::GenFloat(-10.0, 10.0), Random::GenFloat(-10.0, 10.0), 1.0)));
if (setup_override)
{
weenie->m_Qualities.SetDataID(SETUP_DID, setup_override);
}
g_pWorld->CreateEntity(weenie);
}
pPlayer->SendText("Does not have appearance variances.", LTT_DEFAULT);
return;
}
ClothingTable *ct = ClothingTable::Get(clothing_did);
if (!ct)
{
pPlayer->SendText("Could not get clothing table.", LTT_DEFAULT);
return;
}
for (auto ptit = ct->_paletteTemplatesHash.begin(); ptit != ct->_paletteTemplatesHash.end(); ptit++)
{
CWeenieObject *weenie = g_pWeenieFactory->CreateWeenieByClassID(wcid, &pPlayer->m_Position, false);
weenie->m_Qualities.SetInt(PALETTE_TEMPLATE_INT, ptit->first);
weenie->SetInitialPosition(pPlayer->m_Position.add_offset(Vector(Random::GenFloat(-30.0, 30.0), Random::GenFloat(-30.0, 30.0), 1.0)));
if (setup_override)
{
weenie->m_Qualities.SetDataID(SETUP_DID, setup_override);
weenie->SetName(csprintf("Model 0x%08X PTID: %u (%s)", setup_override, ptit->first, CClothingCache::PaletteTemplateIDToString(ptit->first)));
}
g_pWorld->CreateEntity(weenie);
}
ClothingTable::Release(ct);
}
CLIENT_COMMAND(spawnwcidpts, "<name>", "Spawn all base appearances of a wcid.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
CWeenieDefaults *weenieDefs;
if (IsNumeric(argv[0]))
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(atoi(argv[0]));
}
else if (IsHexNumeric(argv[0]))
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(strtoul(argv[0] + 2, NULL, 16));
}
else
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(argv[0]);
}
if (!weenieDefs)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
SpawnAllAppearancesForWeenie(pPlayer, weenieDefs->m_WCID);
return false;
}
#if 0
CLIENT_COMMAND(spawnweenieswithsamemotiontable, "<name>", "Spawn all setups with motion table.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
return true;
CWeenieDefaults *weenieDefs;
if (IsNumeric(argv[0]))
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(atoi(argv[0]));
}
else if (IsHexNumeric(argv[0]))
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(strtoul(argv[0] + 2, NULL, 16));
}
else
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(argv[0]);
}
if (!weenieDefs)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
uint32_t motion_table_did = 0;
if (!weenieDefs->m_Qualities.InqDataID(MOTION_TABLE_DID, motion_table_did))
{
pPlayer->SendText("Does not have a motion table.", LTT_DEFAULT);
return false;
}
std::list<uint32_t> sameMotionTable = g_pWeenieFactory->GetWCIDsWithMotionTable(motion_table_did);
for (auto entry : sameMotionTable)
{
SpawnAllAppearancesForWeenie(pPlayer, entry);
}
return false;
}
#endif
CSetup *original_setup_to_find = NULL;
void FindSetupWithMotionID(void *argument, uint32_t id, BTEntry *entry)
{
CSetup *mySetup = CSetup::Get(id);
if (mySetup)
{
if ((!!original_setup_to_find->sphere == !!mySetup->sphere) && (!mySetup->sphere || (mySetup->sphere->center.is_equal(original_setup_to_find->sphere->center) && fabs(mySetup->sphere->radius - original_setup_to_find->sphere->radius) < F_EPSILON)))
{
if (mySetup->num_parts == original_setup_to_find->num_parts &&
fabs(mySetup->step_down_height - original_setup_to_find->step_down_height) < F_EPSILON &&
fabs(mySetup->step_up_height - original_setup_to_find->step_up_height) < F_EPSILON)
{
((std::list<uint32_t> *)argument)->push_back(id);
}
}
CSetup::Release(mySetup);
}
}
#if 0
CLIENT_COMMAND(spawnsimilarsetups, "<name> <todonly>", "Spawn all setups with motion table.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 2)
return true;
int todOnly = atoi(argv[1]);
CWeenieDefaults *weenieDefs;
if (IsNumeric(argv[0]))
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(atoi(argv[0]));
}
else if (IsHexNumeric(argv[0]))
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(strtoul(argv[0] + 2, NULL, 16));
}
else
{
weenieDefs = g_pWeenieFactory->GetWeenieDefaults(argv[0]);
}
if (!weenieDefs)
{
pPlayer->SendText("Couldn't find that to spawn!", LTT_DEFAULT);
return false;
}
uint32_t setup_did = 0;
if (!weenieDefs->m_Qualities.InqDataID(SETUP_DID, setup_did))
{
pPlayer->SendText("Does not have a setup.", LTT_DEFAULT);
return false;
}
CSetup *setup = CSetup::Get(setup_did);
if (!setup)
{
pPlayer->SendText("Could not get setup.", LTT_DEFAULT);
return false;
}
original_setup_to_find = setup;
std::list<uint32_t> setupList;
DATDisk::pPortal->FindFileIDsWithinRange(0x02000000, 0x02FFFFFF, FindSetupWithMotionID, NULL, &setupList);
for (auto entry : setupList)
{
if (todOnly && entry < 0x020012F0)
continue;
SpawnAllAppearancesForWeenie(pPlayer, weenieDefs->m_WCID, true, entry);
}
CSetup::Release(setup);
return false;
}
CLIENT_COMMAND(spawnarchitect, "[name]", "Spawn architect.", ADMIN_ACCESS)
{
pPlayer->SendText("Disabled.", 1);
return false;
if (!SpawningEnabled(pPlayer))
{
return false;
}
CWeenieObject *weenie;
weenie = g_pWeenieFactory->CreateWeenieByClassID(6854, &pPlayer->m_Position, false);
if (!weenie)
{
pPlayer->SendText("Couldn't find that to spawn!", 1);
return false;
}
weenie->SetScale(2.0f);
weenie->SetName("The Architect");
((CVendor *)weenie)->GenerateAllItems();
g_pWorld->CreateEntity(weenie);
return false;
}
CLIENT_COMMAND(spawnavatarvendor, "[name]", "Spawn avatar vendor.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
CAvatarVendor *pVendor = new CAvatarVendor();
g_pWeenieFactory->ApplyWeenieDefaults(pVendor, 719);
SafeDelete(pVendor->m_Qualities._emote_table);
SafeDelete(pVendor->m_Qualities._create_list);
pVendor->SetInitialPosition(pPlayer->m_Position);
pVendor->SetScale(1.0f);
// Jumpsuit Vendor
pVendor->SetName("Jumpsuit Tailor");
g_pWorld->CreateEntity(pVendor);
return false;
}
#endif
#ifndef PUBLIC_BUILD
CLIENT_COMMAND(barber, "", "", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
BinaryWriter writer;
writer.Write<uint32_t>(0x75);
writer.Write<uint32_t>(pPlayer->InqDIDQuality(PALETTE_BASE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(HEAD_OBJECT_DID, 0));
writer.Write<uint32_t>(0); // Head Texture
writer.Write<uint32_t>(0); // Default Head Texture
writer.Write<uint32_t>(pPlayer->InqDIDQuality(EYES_TEXTURE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(DEFAULT_EYES_TEXTURE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(NOSE_TEXTURE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(DEFAULT_NOSE_TEXTURE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(MOUTH_TEXTURE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(DEFAULT_MOUTH_TEXTURE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(SKIN_PALETTE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(HAIR_PALETTE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(EYES_PALETTE_DID, 0));
writer.Write<uint32_t>(pPlayer->InqDIDQuality(SETUP_DID, 0));
if (pPlayer->m_Qualities.GetInt(HERITAGE_GROUP_INT, 0) == Empyrean_HeritageGroup)
{
// Option1 for Undead - TODO check for hover enabled, if yes, send 1, else 0.
writer.Write<int>(0);
}
else if (pPlayer->m_Qualities.GetInt(HERITAGE_GROUP_INT, 0) == Undead_HeritageGroup)
{
// Option1 for Undead - TODO check for head flame enabled, if yes, send 1, else 0.
writer.Write<int>(0);
}
else
writer.Write<int>(0);
writer.Write<int>(0); // Option2 - Unused?
pPlayer->SendNetMessage(&writer, PRIVATE_MSG, FALSE, FALSE);
return false;
}
CLIENT_COMMAND(spawnfollow, "", "", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (!pPlayer->m_dwLastSpawnedCreatureID)
return false;
CWeenieObject *pObject = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedCreatureID);
if (!pObject)
return false;
MovementParameters params;
params.can_charge = 1;
// params.desired_heading = fmod(pObject->m_Position.frame.get_heading() + 90.0, 360.0);
pObject->MoveToObject(pPlayer->GetID(), &params);
return false;
}
CLIENT_COMMAND(spawnfollow2, "", "", ADMIN_ACCESS, SPAWN_CATEGORY)
{
if (!pPlayer->m_dwLastSpawnedCreatureID)
return false;
CWeenieObject *pObject = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedCreatureID);
if (!pObject)
return false;
MovementParameters params;
params.can_charge = 1;
// params.desired_heading = fmod(pObject->m_Position.frame.get_heading() + 90.0, 360.0);
pPlayer->MoveToObject(pObject->GetID(), &params);
return false;
}
#endif
#if 0
CLIENT_COMMAND(spawnamuli, "[#] [#]", "Spawns an amuli variation.", BASIC_ACCESS)
{
if (!SpawningEnabled(pPlayer, true))
{
return false;
}
if (argc < 2)
{
return true;
}
int variation = atoi(argv[0]);
float shade = atof(argv[1]);
CCapturedWorldObjectInfo *pItemInfo = g_pGameDatabase->GetCapturedArmorData("Greater Amuli Shadow Coat");
if (!pItemInfo)
{
pPlayer->SendText("Couldn't find that to spawn!", 1);
return false;
}
CWeenieObject *pItem = g_pGameDatabase->CreateFromCapturedData(pItemInfo);
if (!pItem)
{
return false;
}
pItem->SetInitialPosition(pPlayer->GetPosition());
ClothingTable *pCT = ClothingTable::Get(0x100001A1);
if (!pCT)
{
delete pItem;
return false;
}
pItem->m_miWornModel.ClearInfo();
pItem->m_miWornModel.dwBasePalette = 0x7E;
uint32_t sid = pPlayer->GetSetupID();
const ClothingBase *pCB = pCT->_cloBaseHash.lookup(sid);
if (pCB)
{
for (uint32_t i = 0; i < pCB->numObjectEffects; i++)
{
pItem->m_miWornModel.lModels.push_back(
ModelRpl(
(BYTE)pCB->objectEffects[i].partNum,
(WORD)pCB->objectEffects[i].objectID));
for (uint32_t j = 0; j < pCB->objectEffects[i].numTextureEffects; j++)
{
pItem->m_miWornModel.lTextures.push_back(
TextureRpl(
(BYTE)pCB->objectEffects[i].partNum,
(WORD)pCB->objectEffects[i].textureEffects[j].oldTexID,
(WORD)pCB->objectEffects[i].textureEffects[j].newTexID
));
}
}
}
if (variation < 0 || variation >= pCT->_paletteTemplatesHash.size())
variation = 0;
std::map<uint32_t, CloPaletteTemplate>::iterator entry = pCT->_paletteTemplatesHash.begin();
while (variation != 0 && entry != pCT->_paletteTemplatesHash.end())
{
variation--;
entry++;
}
if (entry != pCT->_paletteTemplatesHash.end())
{
pItem->SetIcon(entry->second.iconID);
for (uint32_t i = 0; i < entry->second.numSubpalEffects; i++)
{
uint32_t set = entry->second.subpalEffects[i].palSet;
PalSet *pPS = PalSet::Get(set);
if (pPS)
{
uint32_t pal = pPS->GetPaletteID(shade);
for (uint32_t j = 0; j < entry->second.subpalEffects[i].numRanges; j++)
{
pItem->m_miWornModel.lPalettes.push_back(
PaletteRpl(
(WORD)pal,
entry->second.subpalEffects[i].rangeStart[j] >> 3,
entry->second.subpalEffects[i].rangeLength[j] >> 3
));
}
PalSet::Release(pPS);
}
}
}
ClothingTable::Release(pCT);
g_pWorld->CreateEntity(pItem);
return false;
}
#endif
#if 0
CLIENT_COMMAND(spawnarmor, "[name]", "Spawns armor by name.", BASIC_ACCESS)
{
if (!SpawningEnabled(pPlayer))
{
return false;
}
if (argc < 1)
{
return true;
}
CCapturedWorldObjectInfo *pItemInfo = g_pGameDatabase->GetCapturedArmorData(argv[0]);
if (!pItemInfo)
{
pPlayer->SendText("Couldn't find that to spawn!", 1);
return false;
}
float fScale = 1.0f;
bool bAnimate = true;
if (argc >= 2)
{
fScale = (float)atof(argv[1]);
if (fScale < 0.01)
fScale = 0.01f;
if (fScale > 1000.0)
fScale = 1000;
}
if (argc >= 3)
{
bAnimate = atoi(argv[2]) ? true : false;
}
CWeenieObject *pItem = g_pGameDatabase->CreateFromCapturedData(pItemInfo);
pItem->m_scale = pItemInfo->physics.object_scale * fScale;
pItem->m_dwCoverage2 = 0;
pItem->SetInitialPosition(pPlayer->GetPosition());
if (!bAnimate)
{
pItem->m_AnimOverrideData = NULL;
pItem->m_AnimOverrideDataLen = 0;
pItem->m_AutonomousMovement = 0;
}
g_pWorld->CreateEntity(pItem);
return false;
}
#endif
#if 0
CLIENT_COMMAND(spawnarmor, "[name] [palette] [shade]", "Spawns armor by name.", ADMIN_ACCESS)
{
if (!SpawningEnabled(pPlayer, true))
{
return false;
}
if (argc < 1)
{
return true;
}
CCapturedWorldObjectInfo *pItemInfo = g_pGameDatabase->GetCapturedItemData(argv[0]);
if (!pItemInfo)
{
pPlayer->SendText("Couldn't find that to spawn!", 1);
return false;
}
if (!(pItemInfo->weenie._type & (ITEM_TYPE::TYPE_ARMOR | ITEM_TYPE::TYPE_CLOTHING)))
{
pPlayer->SendText("That's not armor?", 1);
return false;
}
CWeenieObject *pItem = g_pGameDatabase->CreateFromCapturedData(pItemInfo);
pItem->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pItem);
return false;
}
CLIENT_COMMAND(spawnlist, "[num to list]", "Lists spawnable objects.", ADMIN_ACCESS)
{
int num = 20;
if (argc >= 1)
{
num = atoi(argv[0]);
if (num < 0)
num = 0;
if (num >= 100)
num = 100;
}
while (num > 0)
{
CCapturedWorldObjectInfo *pMonsterInfo = g_pGameDatabase->GetRandomCapturedMonsterData();
if (!pMonsterInfo)
{
pPlayer->SendText("Couldn't find anything to spawn!", 1);
return false;
}
pPlayer->SendText(pMonsterInfo->weenie._name.c_str(), 1);
num--;
}
return false;
}
CLIENT_COMMAND(spawnrandomarmor, "", "Spawns random armor.", SENTINEL_ACCESS)
{
if (!SpawningEnabled(pPlayer, true))
{
return false;
}
CCapturedWorldObjectInfo *pItemInfo = g_pGameDatabase->GetRandomCapturedArmorData();
if (!pItemInfo)
{
pPlayer->SendText("Couldn't find anything to spawn!", 1);
return false;
}
CWeenieObject *pItem = g_pGameDatabase->CreateFromCapturedData(pItemInfo);
pItem->SetInitialPosition(pPlayer->GetPosition());
g_pWorld->CreateEntity(pItem);
return false;
}
CLIENT_COMMAND(spawnrandom, "[num to spawn] [scale]", "Spawns random objects.", SENTINEL_ACCESS)
{
if (argc < 1)
{
return true;
}
if (!SpawningEnabled(pPlayer))
{
return false;
}
int num = atoi(argv[0]);
if (num < 0)
num = 0;
if (num >= 20)
num = 20;
float fScale = 1.0f;
if (argc >= 2)
fScale = max(0.1f, min(10.0f, (float) atof(argv[1])));
int total = num;
while (num > 0)
{
CCapturedWorldObjectInfo *pMonsterInfo = g_pGameDatabase->GetRandomCapturedMonsterData();
if (!pMonsterInfo)
{
pPlayer->SendText("Couldn't find anything to spawn!", 1);
return false;
}
CWeenieObject *pMonster = g_pGameDatabase->CreateFromCapturedData(pMonsterInfo);
pMonster->SetScale(pMonsterInfo->physics.object_scale * fScale);
pMonster->SetInitialPosition(pPlayer->GetPosition().add_offset(Vector(Random::GenFloat(-2.0f * total, 2.0f * total), Random::GenFloat(-2.0f * total, 2.0f * total), 0)));
g_pWorld->CreateEntity(pMonster);
num--;
}
return false;
}
CLIENT_COMMAND(spawnrandomshadows, "[phase] [num to spawn]", "Spawns random shadows.", ADMIN_ACCESS)
{
if (argc < 2)
return true;
int phase = atoi(argv[0]);
if (phase < 1)
return true;
if (phase > 4)
return true;
int num = atoi(argv[1]);
if (num < 0)
num = 0;
if (num >= 20)
num = 20;
std::vector<std::string> phase_monsters[4];
phase_monsters[0].push_back("Shadow Child");
phase_monsters[0].push_back("Shadow Child");
phase_monsters[0].push_back("Devious Shadow");
phase_monsters[0].push_back("Devious Shadow");
phase_monsters[0].push_back("Shadow Sprite");
phase_monsters[1].push_back("Shadow Flyer");
phase_monsters[1].push_back("Shadow Phantom");
phase_monsters[1].push_back("Abyssal Shadow");
phase_monsters[1].push_back("Tenebrous Shadow");
phase_monsters[1].push_back("Panumbris Shadow");
phase_monsters[1].push_back("Sinister Shadow");
phase_monsters[1].push_back("Shadow");
phase_monsters[1].push_back("Shadow Spectre");
phase_monsters[1].push_back("Umbris Shadow");
phase_monsters[1].push_back("Shadow Wraith");
phase_monsters[2].push_back("Paroxysm Shadow");
phase_monsters[2].push_back("Pandemonium Shadow");
phase_monsters[3].push_back("Shadow");
int total = num;
while (num > 0)
{
std::string spawnName = phase_monsters[phase-1][Random::GenInt(0, (unsigned int)(phase_monsters[phase-1].size() - 1))];
CCapturedWorldObjectInfo *pMonsterInfo = g_pGameDatabase->GetCapturedMonsterData(spawnName.c_str());
if (pMonsterInfo)
{
CMonsterWeenie *pMonster = (CMonsterWeenie *)g_pGameDatabase->CreateFromCapturedData(pMonsterInfo);
Position spawnPos = pPlayer->GetPosition().add_offset(Vector(Random::GenFloat(-4.0f * total, 4.0f * total), Random::GenFloat(-4.0f * total, 4.0f * total), 0));
pMonster->SetInitialPosition(spawnPos);
switch (phase)
{
case 1:
pMonster->m_Qualities.SetInt(LEVEL_INT, 50);
pMonster->m_Qualities.SetAttribute(STRENGTH_ATTRIBUTE, 100);
pMonster->m_Qualities.SetAttribute(ENDURANCE_ATTRIBUTE, 100);
pMonster->m_Qualities.SetAttribute(COORDINATION_ATTRIBUTE, 100);
pMonster->m_Qualities.SetAttribute(QUICKNESS_ATTRIBUTE, 100);
pMonster->m_Qualities.SetAttribute(FOCUS_ATTRIBUTE, 100);
pMonster->m_Qualities.SetAttribute(SELF_ATTRIBUTE, 100);
pMonster->m_Qualities.SetAttribute2nd(MAX_HEALTH_ATTRIBUTE_2ND, 120);
pMonster->SetMaxVitals();
pMonster->m_MeleeDamageBonus = 3;
break;
case 2:
pMonster->m_Qualities.SetInt(LEVEL_INT, 100);
pMonster->m_Qualities.SetAttribute(STRENGTH_ATTRIBUTE, 200);
pMonster->m_Qualities.SetAttribute(ENDURANCE_ATTRIBUTE, 200);
pMonster->m_Qualities.SetAttribute(COORDINATION_ATTRIBUTE, 200);
pMonster->m_Qualities.SetAttribute(QUICKNESS_ATTRIBUTE, 200);
pMonster->m_Qualities.SetAttribute(FOCUS_ATTRIBUTE, 200);
pMonster->m_Qualities.SetAttribute(SELF_ATTRIBUTE, 200);
pMonster->m_Qualities.SetAttribute2nd(MAX_HEALTH_ATTRIBUTE_2ND, 300);
pMonster->SetMaxVitals();
pMonster->m_MeleeDamageBonus = 6;
break;
case 3:
pMonster->m_Qualities.SetInt(LEVEL_INT, 200);
pMonster->m_Qualities.SetAttribute(STRENGTH_ATTRIBUTE, 300);
pMonster->m_Qualities.SetAttribute(ENDURANCE_ATTRIBUTE, 300);
pMonster->m_Qualities.SetAttribute(COORDINATION_ATTRIBUTE, 300);
pMonster->m_Qualities.SetAttribute(QUICKNESS_ATTRIBUTE, 300);
pMonster->m_Qualities.SetAttribute(FOCUS_ATTRIBUTE, 300);
pMonster->m_Qualities.SetAttribute(SELF_ATTRIBUTE, 300);
pMonster->m_Qualities.SetAttribute2nd(MAX_HEALTH_ATTRIBUTE_2ND, 600);
pMonster->SetMaxVitals();
pMonster->m_MeleeDamageBonus = 13;
break;
case 4:
pMonster->m_Qualities.SetInt(LEVEL_INT, 500);
pMonster->m_Qualities.SetAttribute(STRENGTH_ATTRIBUTE, 400);
pMonster->m_Qualities.SetAttribute(ENDURANCE_ATTRIBUTE, 400);
pMonster->m_Qualities.SetAttribute(COORDINATION_ATTRIBUTE, 400);
pMonster->m_Qualities.SetAttribute(QUICKNESS_ATTRIBUTE, 400);
pMonster->m_Qualities.SetAttribute(FOCUS_ATTRIBUTE, 400);
pMonster->m_Qualities.SetAttribute(SELF_ATTRIBUTE, 400);
pMonster->m_Qualities.SetAttribute2nd(MAX_HEALTH_ATTRIBUTE_2ND, 12000);
pMonster->SetMaxVitals();
pMonster->m_MeleeDamageBonus = 50;
pMonster->SetName("Shadow of Turbine");
pMonster->SetScale(pMonsterInfo->physics.object_scale * 2.5f);
break;
}
g_pWorld->CreateEntity(pMonster);
}
num--;
}
return false;
}
#endif
CLIENT_COMMAND(pk, "", "Makes you a player killer.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
if (!pPlayer->IsAdmin() && !g_pConfig->AllowPKCommands())
{
pPlayer->SendText("This command is no longer enabled. You should use the PK/NPK altars instead.", LTT_DEFAULT);
return false;
}
pPlayer->m_Qualities.SetInt(PLAYER_KILLER_STATUS_INT, PK_PKStatus);
pPlayer->NotifyIntStatUpdated(PLAYER_KILLER_STATUS_INT, false);
pPlayer->m_Qualities.RemoveFloat(PK_TIMESTAMP_FLOAT);
//pPlayer->m_Qualities.SetInt(RADARBLIP_COLOR_INT, 5);
//pPlayer->NotifyIntStatUpdated(RADARBLIP_COLOR_INT, false);
pPlayer->SendText("You are now a player killer.", 1);
return false;
}
CLIENT_COMMAND(npk, "", "Makes you a non-player killer.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!pPlayer->IsAdmin() && !g_pConfig->AllowPKCommands())
{
pPlayer->SendText("This command is no longer enabled. You should use the PK/NPK altars instead.", LTT_DEFAULT);
return false;
}
pPlayer->m_Qualities.SetInt(PLAYER_KILLER_STATUS_INT, NPK_PKStatus);
pPlayer->NotifyIntStatUpdated(PLAYER_KILLER_STATUS_INT, false);
pPlayer->m_Qualities.RemoveFloat(PK_TIMESTAMP_FLOAT);
//if (player_client && player_client->GetAccessLevel() >= ADVOCATE_ACCESS)
// pPlayer->m_Qualities.SetInt(RADARBLIP_COLOR_INT, 9);
//else
// pPlayer->m_Qualities.SetInt(RADARBLIP_COLOR_INT, 3);
// pPlayer->NotifyIntStatUpdated(RADARBLIP_COLOR_INT, false);
pPlayer->SendText("You are now a non-player killer.", 1);
return false;
}
CLIENT_COMMAND(decent, "[name]", "Gives you great attributes.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableGodlyCommand() && pPlayer->GetClient()->GetAccessLevel() < ADMIN_ACCESS)
{
pPlayer->SendText("Command disabled.", 1);
return false;
}
pPlayer->m_Qualities.SetAttribute(STRENGTH_ATTRIBUTE, 10);
pPlayer->m_Qualities.SetAttribute(ENDURANCE_ATTRIBUTE, 100);
pPlayer->m_Qualities.SetAttribute(QUICKNESS_ATTRIBUTE, 10);
pPlayer->m_Qualities.SetAttribute(COORDINATION_ATTRIBUTE, 10);
pPlayer->m_Qualities.SetAttribute(FOCUS_ATTRIBUTE, 100);
pPlayer->m_Qualities.SetAttribute(SELF_ATTRIBUTE, 100);
pPlayer->m_Qualities.SetInt(LEVEL_INT, 100);
pPlayer->NotifyAttributeStatUpdated(STRENGTH_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(ENDURANCE_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(QUICKNESS_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(COORDINATION_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(FOCUS_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(SELF_ATTRIBUTE);
pPlayer->NotifyIntStatUpdated(LEVEL_INT);
pPlayer->EmitEffect(138, 1.0f);
Skill runSkill;
pPlayer->m_Qualities.InqSkill(RUN_SKILL, runSkill);
runSkill._init_level = 0;
pPlayer->m_Qualities.SetSkill(RUN_SKILL, runSkill);
pPlayer->NotifySkillStatUpdated(RUN_SKILL);
Skill jumpSkill;
pPlayer->m_Qualities.InqSkill(JUMP_SKILL, jumpSkill);
jumpSkill._init_level = 0;
pPlayer->m_Qualities.SetSkill(JUMP_SKILL, jumpSkill);
pPlayer->NotifySkillStatUpdated(JUMP_SKILL);
// pPlayer->SetHealth(pPlayer->GetMaxHealth());
// pPlayer->SetStamina(pPlayer->GetMaxStamina());
// pPlayer->SetMana(pPlayer->GetMaxMana());
pPlayer->SendText("Your attributes have been made decent.", 1);
pPlayer->CheckVitalRanges();
return false;
}
CLIENT_COMMAND(godly, "", "Gives you great attributes.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableGodlyCommand() && pPlayer->GetClient()->GetAccessLevel() < ADMIN_ACCESS)
{
pPlayer->SendText("Command disabled.", 1);
return false;
}
pPlayer->SendText("Use /decent instead if you want to play fair.", 1);
pPlayer->m_Qualities.SetAttribute(STRENGTH_ATTRIBUTE, 1000000);
pPlayer->m_Qualities.SetAttribute(ENDURANCE_ATTRIBUTE, 1000000);
pPlayer->m_Qualities.SetAttribute(QUICKNESS_ATTRIBUTE, 790);
pPlayer->m_Qualities.SetAttribute(COORDINATION_ATTRIBUTE, 1000000);
pPlayer->m_Qualities.SetAttribute(FOCUS_ATTRIBUTE, 1000000);
pPlayer->m_Qualities.SetAttribute(SELF_ATTRIBUTE, 1000000);
pPlayer->m_Qualities.SetInt(LEVEL_INT, 999);
pPlayer->m_Qualities.SetInt64(AVAILABLE_EXPERIENCE_INT64, 100000000000);
pPlayer->NotifyAttributeStatUpdated(STRENGTH_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(ENDURANCE_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(QUICKNESS_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(COORDINATION_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(FOCUS_ATTRIBUTE);
pPlayer->NotifyAttributeStatUpdated(SELF_ATTRIBUTE);
pPlayer->NotifyIntStatUpdated(LEVEL_INT);
pPlayer->NotifyInt64StatUpdated(AVAILABLE_EXPERIENCE_INT64);
pPlayer->EmitEffect(138, 1.0f);
Skill runSkill;
pPlayer->m_Qualities.InqSkill(RUN_SKILL, runSkill);
runSkill._init_level = 0;
pPlayer->m_Qualities.SetSkill(RUN_SKILL, runSkill);
pPlayer->NotifySkillStatUpdated(RUN_SKILL);
Skill jumpSkill;
pPlayer->m_Qualities.InqSkill(JUMP_SKILL, jumpSkill);
jumpSkill._init_level = 1000000000;
pPlayer->m_Qualities.SetSkill(JUMP_SKILL, jumpSkill);
pPlayer->NotifySkillStatUpdated(JUMP_SKILL);
Skill axeSkill;
pPlayer->m_Qualities.InqSkill(AXE_SKILL, axeSkill);
axeSkill._init_level = 1000000000;
pPlayer->m_Qualities.SetSkill(AXE_SKILL, axeSkill);
pPlayer->NotifySkillStatUpdated(AXE_SKILL);
if (!pPlayer->IsDead())
{
pPlayer->SetHealth(pPlayer->GetMaxHealth());
pPlayer->SetStamina(pPlayer->GetMaxStamina());
pPlayer->SetMana(pPlayer->GetMaxMana());
}
pPlayer->SendText("Your attributes have been greatly increased.", 1);
return false;
}
CLIENT_COMMAND(givexp, "[value]", "Gives you some XP for testing.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableXPCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is not enabled on this server.", LTT_DEFAULT);
return false;
}
uint32_t amount = 0;
if (argc >= 1)
{
amount = strtoul(argv[0], NULL, 10);
}
amount = min(amount, 4000000000u);
// pPlayer->m_Qualities.SetInt64(AVAILABLE_EXPERIENCE_INT64, amount);
// pPlayer->SendText("Your attributes have been greatly increased.", 1);
pPlayer->GiveXP(amount, true);
return false;
}
CLIENT_COMMAND(getcreditother, "", "Gets the current unassigned skill credits of the last identified target.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableXPCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is not enabled on this server.", LTT_DEFAULT);
return false;
}
CWeenieObject *targetID = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (!targetID)
{
pPlayer->SendText("You must assess a valid target.", LTT_DEFAULT);
return true;
}
if (!targetID->AsPlayer())
{
pPlayer->SendText("You must assess a player target.", LTT_DEFAULT);
return true;
}
auto targetName = targetID->GetName();
uint32_t currentcredits = targetID->AsPlayer()->GetTotalSkillCredits();
uint32_t expectedCredits = targetID->AsPlayer()->GetExpectedSkillCredits();
const char *AunR = "";
const char *Oswald = "";
if (targetID->InqQuest("arantahkill1")) //Aun Ralirea
AunR = "Aun Ralirea";
if (targetID->InqQuest("ChasingOswaldDone")) //Finding Oswald
Oswald = "Finding Oswald";
//todo add Luminance Skill Credit Checks (2 credits).
BinaryWriter popupMessage;
popupMessage.Write<uint32_t>(0x4);
popupMessage.WriteString(csprintf("%s has %d skill credits total. \n\n A character of level %d should have %d skill credits. \n\n Skill Credit Quests Complete: \n %s \n %s",
targetName.c_str(),
currentcredits,
targetID->InqIntQuality(LEVEL_INT, 0, TRUE),
expectedCredits,
AunR,
Oswald));
pPlayer->SendNetMessage(&popupMessage, PRIVATE_MSG, TRUE, FALSE);
return false;
}
CLIENT_COMMAND(givecreditother, "<player name> [value]", "Gives your last assessed AND named target some skill credits.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableXPCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is not enabled on this server.", LTT_DEFAULT);
return false;
}
CPlayerWeenie *targetID = g_pWorld->FindPlayer(pPlayer->m_LastAssessed);
if (!targetID)
{
pPlayer->SendText("You must assess a player target", LTT_DEFAULT);
return true;
}
auto targetName = targetID->GetName();
if (targetID->GetName() != string(argv[0]))
{
pPlayer->SendText("Last Assessed player target does not match named target!", LTT_DEFAULT);
return true;
}
int initialcredits = targetID->GetSkillCredits();
int amount = 0;
if (argc >= 1)
{
amount = stoi(argv[1], NULL, 10);
}
else
return true;
// Cant go below Initialcredits if initialcredits at 0 or if amount would take available below 0
// Can give neg credits
if ((amount + initialcredits) < 0)
amount = (-initialcredits);
targetID->GiveSkillCredit(amount);
uint32_t postcredits = targetID->GetSkillCredits();
if (postcredits - amount == initialcredits)
pPlayer->SendText(csprintf("%s has been awarded %d skill credits! Initial skill credits were %d, post command credits are %d.", targetName.c_str(), amount, initialcredits, postcredits), LTT_DEFAULT);
else
pPlayer->SendText(csprintf("Failed to award %s %d skill credits. Initial skill credits were %d, post command credits are %d.", targetName.c_str(), amount, initialcredits, postcredits), LTT_DEFAULT);
return false;
}
CLIENT_COMMAND(givecredit, "[value]", "Gives you some skill credits for testing.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableXPCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is not enabled on this server.", LTT_DEFAULT);
return false;
}
uint32_t amount = 0;
if (argc >= 1)
{
amount = strtoul(argv[0], NULL, 10);
}
amount = max(amount, (uint32_t)1);
amount = min(amount, (uint32_t)100);
pPlayer->GiveSkillCredit(amount);
return false;
}
CLIENT_COMMAND(givexpother, "[value]", "Gives you some XP for testing.", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
uint32_t amount = 0;
if (argc >= 1)
{
amount = strtoul(argv[0], NULL, 10);
}
amount = min(amount, 4000000000u);
// pPlayer->m_Qualities.SetInt64(AVAILABLE_EXPERIENCE_INT64, amount);
// pPlayer->SendText("Your attributes have been greatly increased.", 1);
CWeenieObject *assessed = g_pWorld->FindObject(pPlayer->m_LastAssessed);
if (assessed && assessed->AsPlayer())
{
assessed->GiveXP(amount, true);
}
return false;
}
CLIENT_COMMAND(hover, "<on / off>", "Turns hovering on or off.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (pPlayer->InqIntQuality(HERITAGE_GROUP_INT, 0, true) != 9)
{
pPlayer->SendText("Command only available for Empyrean characters.", LTT_DEFAULT);
return false;
}
if (argc < 1)
{
pPlayer->SendText("Usage: /hover on | off", LTT_DEFAULT);
return false;
}
if (!stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
pPlayer->SendText("Hovering on. You may need to relog for the change to take effect.", LTT_DEFAULT);
pPlayer->m_Qualities.SetDataID(MOTION_TABLE_DID, 0x9000207);
pPlayer->NotifyDIDStatUpdated(MOTION_TABLE_DID);
}
else if (!stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
{
pPlayer->SendText("Hovering off. You may need to relog for the change to take effect.", LTT_DEFAULT);
pPlayer->m_Qualities.SetDataID(MOTION_TABLE_DID, 0x900020D);
pPlayer->NotifyDIDStatUpdated(MOTION_TABLE_DID);
}
return false;
}
CLIENT_COMMAND(movetome, "", "Brings an object to you.", ADMIN_ACCESS, GENERAL_CATEGORY)
{
CWeenieObject *pObject = g_pWorld->FindWithinPVS(pPlayer, pPlayer->m_LastAssessed);
if (pObject)
{
pObject->Movement_Teleport(pPlayer->GetPosition());
}
else
{
pPlayer->SendText("Please assess a valid object you wish to move!", LTT_DEFAULT);
return true;
}
return false;
}
CLIENT_COMMAND(challengeai, "", "Challenge an AI to a game of Chess.", BASIC_ACCESS, GENERAL_CATEGORY)
{
sChessManager->ChallengeAi(pPlayer);
return false;
}
CLIENT_COMMAND(sethealth, "[value]", "Set my health to value must be below max health", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
uint32_t amount = 0;
if (argc >= 1)
{
amount = strtoul(argv[0], NULL, 10);
}
else
return false;
pPlayer->SetHealth(amount, true);
return true;
}
CLIENT_COMMAND(setstamina, "[value]", "Set my staminahealth to value must be below max health", ADMIN_ACCESS, CHARACTER_CATEGORY)
{
uint32_t amount = 0;
if (argc >= 1)
{
amount = strtoul(argv[0], NULL, 10);
}
else
return false;
pPlayer->SetStamina(amount, true);
return true;
}
CLIENT_COMMAND(givelum, "[value]", "Gives you some Luminance for testing.", BASIC_ACCESS, CHARACTER_CATEGORY)
{
if (!g_pConfig->EnableXPCommands() && pPlayer->GetAccessLevel() < SENTINEL_ACCESS)
{
pPlayer->SendText("This command is not enabled on this server.", LTT_DEFAULT);
return false;
}
uint32_t amount = 0;
uint32_t total = pPlayer->m_Qualities.GetInt64(AVAILABLE_LUMINANCE_INT64, 0);
if (argc >= 1)
{
amount = strtoul(argv[0], NULL, 10);
}
amount = min(amount, (uint32_t)1000000);
pPlayer->m_Qualities.SetInt64(AVAILABLE_LUMINANCE_INT64, min(amount + total, (uint32_t)1000000));
pPlayer->NotifyInt64StatUpdated(AVAILABLE_LUMINANCE_INT64, false);
if (!pPlayer->m_Qualities.GetInt64(MAXIMUM_LUMINANCE_INT64, 0))
{
pPlayer->m_Qualities.SetInt64(MAXIMUM_LUMINANCE_INT64, 1000000);
pPlayer->NotifyInt64StatUpdated(MAXIMUM_LUMINANCE_INT64, false);
}
return false;
}
CLIENT_COMMAND(setsolid, "", "Toggles ethereal for an object.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if(!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
if (editedItem && stricmp(argv[0], "on") || !stricmp(argv[0], "1"))
{
editedItem->m_Qualities.SetBool(ETHEREAL_BOOL, 0);
}
else if (editedItem && stricmp(argv[0], "off") || !stricmp(argv[0], "0"))
editedItem->m_Qualities.SetBool(ETHEREAL_BOOL, 1);
else
pPlayer->SendText(std::string("Please assess a valid object you wish to set as ethereal!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Ethereal set for: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to set as ethereal!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
CLIENT_COMMAND(nudge_z, "", "Nudges an item in the z axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_origin.z += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to nudge!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Nudged object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to nudge!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
CLIENT_COMMAND(nudge_x, "", "Nudges an item in the x axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_origin.x += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to nudge!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Nudged object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to nudge!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
CLIENT_COMMAND(nudge_y, "", "Nudges an item in the y axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_origin.y += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to nudge!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Nudged object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to nudge!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
#if 0
CLIENT_COMMAND(spin_w, "", "Spins an item in the w axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_angles.w += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Spun object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
CLIENT_COMMAND(spin_x, "", "Spins an item in the x axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_angles.x += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Spun object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
CLIENT_COMMAND(spin_y, "", "Spins an item in the y axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_angles.y += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Spun object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
CLIENT_COMMAND(spin_z, "", "Spins an item in the z axis.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
float value = 0.0f;
if (editedItem && argc >= 1)
{
value = atof(argv[0]);
if (value)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_angles.z += value;
editedItem->Movement_Teleport(pos, false);
}
}
else
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
if (itemString != "")
{
pPlayer->SendText(std::string("Spun object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
#endif
CLIENT_COMMAND(spin, "", "Sets the spin of an item to that of the player.", ADMIN_ACCESS, SPAWN_CATEGORY)
{
CWeenieObject *editedItem = g_pWorld->FindObject(pPlayer->m_dwLastSpawnedObjectID);
if (!editedItem)
editedItem = g_pWorld->FindObject(pPlayer->m_LastAssessed);
std::string itemString = editedItem->GetName();
Position pos = editedItem->GetPosition();
Position playerpos = pPlayer->GetPosition();
if (editedItem)
{
if (!pos.objcell_id)
pos.objcell_id = pPlayer->m_Position.objcell_id;
pos.frame.m_angles.w = playerpos.frame.m_angles.w;
pos.frame.m_angles.x = playerpos.frame.m_angles.x;
pos.frame.m_angles.y = playerpos.frame.m_angles.y;
pos.frame.m_angles.z = playerpos.frame.m_angles.z;
editedItem->Movement_Teleport(pos, false);
}
if (itemString != "")
{
pPlayer->SendText(std::string("Spun object: ").append(itemString).c_str(), LTT_DEFAULT);
}
else
{
pPlayer->SendText(std::string("Please assess a valid object you wish to spin!").append(itemString).c_str(), LTT_DEFAULT);
return false;
}
return false;
}
const char* CommandBase::Info(CommandEntry* pCommand)
{
const char* szName = pCommand->name;
const char* szArgs = pCommand->args;
const char* szHelp = pCommand->help;
if (strlen(szArgs) <= 0)
return csprintf("Syntax: @%s - %s", szName, szHelp);
else
return csprintf("Syntax: @%s %s - %s", szName, szArgs, szHelp);
}
CommandEntry* CommandBase::FindCommand(const char* szName, int iAccessLevel)
{
CommandMap& commands = GetCommandMap();
CommandMap::iterator i = commands.find(szName);
if (i == commands.end())
return NULL;
if (iAccessLevel == -1 || iAccessLevel >= i->second.access)
return &i->second;
else
return NULL;
}
void CommandBase::PrintCommandList(CWeenieObject* sendto, int category, int access_level, char* cmdName)
{
if (cmdName)
{
CommandEntry* pCommand = FindCommand(cmdName, access_level);
if (pCommand)
{
sendto->SendText(Info(pCommand), 1);
}
else
{
sendto->SendText("Unknown command. Use !help to receive a list of commands.", 1);
}
}
else
{
// List all commands.
std::string strCommandList = "Command List: \n";
CommandMap& commands = GetCommandMap();
for (CommandMap::iterator it = commands.begin(); it != commands.end(); it++)
{
if (it->second.access <= access_level && it->second.category == category) {
strCommandList += Info(&it->second);
strCommandList += "\n";
}
}
strCommandList += "Use !help <command> to receive command syntax.\n";
sendto->SendText(strCommandList.c_str(), 1);
}
}
bool CommandBase::Execute(char *command, CClient *client)
{
if (!client)
return true;
char* argv[MAX_ARGUMENTS];
int argc = 0;
bool inquote = false;
char *argstart = command;
char *p = command;
// Quote-delimited arguments.
for (; p[0] != '\0' && argc < MAX_ARGUMENTS; p++)
{
char feed = p[0];
if (inquote)
{
if (feed == '\"')
{
inquote = false;
*p = 0;
argv[argc++] = argstart;
argstart = p + 1;
continue;
}
}
else
{
if (feed == ' ')
{
if (argstart == p)
argstart++;
else
{
*p = 0;
argv[argc++] = argstart;
argstart = p + 1;
}
}
if (feed == '\"')
{
inquote = true;
argstart = p + 1;
}
}
}
if (argstart[0] != 0 && argc < MAX_ARGUMENTS)
{
argv[argc++] = argstart;
}
if (argc > 0)
{
CPlayerWeenie *player_weenie = client ? client->GetEvents()->GetPlayer() : NULL;
CPhysicsObj *player_physobj = player_weenie ? player_weenie->_phys_obj : NULL;
int access_level = client ? client->GetAccessLevel() : BASIC_ACCESS;
char *command_name = argv[0];
if (!stricmp(command_name, "emuhelp"))
{
player_weenie->SendText("Please use one of the following to see a list of commands:\n/generalhelp - Lists general commands that don't fall into any other category.\n/explorehelp - Lists commands pertaining to exploring (dungeon information, teleport commands (if enabled), etc.. \n/spawnhelp - Lists commands pertaining to the spawning of items and mobs.\n/characterhelp - Lists commands pertaining to your character.\n/serverhelp - Lists commands that affect the entire server.", 1);
}
else if (!stricmp(command_name, "generalhelp") || !stricmp(command_name, "ghelp"))
{
PrintCommandList(player_weenie, GENERAL_CATEGORY, access_level, (argc > 1) ? argv[1] : NULL);
}
else if (!stricmp(command_name, "explorehelp") || !stricmp(command_name, "ehelp"))
{
PrintCommandList(player_weenie, EXPLORE_CATEGORY, access_level, (argc > 1) ? argv[1] : NULL);
}
else if (!stricmp(command_name, "spawnhelp") || !stricmp(command_name, "sphelp"))
{
PrintCommandList(player_weenie, SPAWN_CATEGORY, access_level, (argc > 1) ? argv[1] : NULL);
}
else if (!stricmp(command_name, "characterhelp") || !stricmp(command_name, "chelp"))
{
PrintCommandList(player_weenie, CHARACTER_CATEGORY, access_level, (argc > 1) ? argv[1] : NULL);
}
else if (!stricmp(command_name, "serverhelp") || !stricmp(command_name, "svhelp"))
{
PrintCommandList(player_weenie, SERVER_CATEGORY, access_level, (argc > 1) ? argv[1] : NULL);
}
else
{
CommandEntry* pCommand = FindCommand(command_name, access_level);
if (!pCommand)
{
if (player_weenie)
player_weenie->SendText("Unknown command!", 1);
}
else
{
if (!pCommand->source || player_weenie)
{
SERVER_INFO << "EXECUTING CLIENT COMMAND" << command << "FROM" << client->GetDescription();
// run the command callback
if ((*pCommand->func)(client, player_weenie, player_physobj, argv + 1, argc - 1))
{
// send error text
if (player_weenie)
player_weenie->SendText(Info(pCommand), 1);
}
else
return true;
}
}
}
}
return false;
}
ClientCommand::ClientCommand(const char* szName, const char* szArguments, const char* szHelp, pfnCommandCallback pCallback, int iAccessLevel, int iCategory)
: CommandBase()
{
CommandBase::Create(szName, szArguments, szHelp, pCallback, iAccessLevel, iCategory, true);
}
ServerCommand::ServerCommand(const char* szName, const char* szArguments, const char* szHelp, pfnCommandCallback pCallback, int iAccessLevel, int iCategory)
: CommandBase()
{
CommandBase::Create(szName, szArguments, szHelp, pCallback, iAccessLevel, iCategory, false);
}