You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5575 lines
150 KiB
C++
5575 lines
150 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
//////////////
|
|
// Includes //
|
|
//////////////
|
|
|
|
#include "stdpch.h"
|
|
|
|
// very nice \\// :)
|
|
|
|
#include "nel/misc/bit_mem_stream.h"
|
|
#include "nel/misc/command.h"
|
|
#include "nel/misc/i18n.h"
|
|
#include "nel/misc/o_xml.h"
|
|
#include "nel/misc/async_file_manager.h"
|
|
|
|
#include "nel/3d/u_particle_system_instance.h"
|
|
#include "nel/3d/u_play_list_manager.h"
|
|
#include "nel/3d/u_animation_set.h"
|
|
#include "nel/3d/u_landscape.h"
|
|
#include "nel/3d/u_play_list.h"
|
|
#include "nel/3d/u_animation.h"
|
|
#include "nel/3d/u_scene.h"
|
|
#include "nel/3d/u_track.h"
|
|
|
|
#include "nel/ligo/primitive.h"
|
|
|
|
#include "game_share/player_visual_properties.h"
|
|
#include "game_share/generic_xml_msg_mngr.h"
|
|
#include "game_share/visual_slot_manager.h"
|
|
#include "game_share/mode_and_behaviour.h"
|
|
#include "game_share/ryzom_version.h"
|
|
#include "game_share/brick_types.h"
|
|
#include "game_share/time_weather_season/time_and_season.h"
|
|
|
|
#include "entity_animation_manager.h"
|
|
#include "ingame_database_manager.h"
|
|
#include "world_database_manager.h"
|
|
#include "string_manager_client.h"
|
|
#include "interface_v3/input_handler_manager.h"
|
|
#include "interface_v3/people_interraction.h"
|
|
#include "client_chat_manager.h"
|
|
#include "continent_manager.h"
|
|
#include "interface_v3/interface_manager.h"
|
|
#include "interface_v3/group_compas.h"
|
|
#include "init_main_loop.h"
|
|
#include "sheet_manager.h"
|
|
#include "sound_manager.h"
|
|
#include "interface_v3/group_editbox.h"
|
|
#include "debug_client.h"
|
|
#include "user_entity.h"
|
|
#include "time_client.h"
|
|
#include "net_manager.h"
|
|
#include "pacs_client.h"
|
|
#include "continent.h"
|
|
#include "ig_client.h"
|
|
#include "commands.h"
|
|
#include "entities.h"
|
|
#include "teleport.h"
|
|
#include "cdb_leaf.h"
|
|
#include "view.h"
|
|
#include "misc.h"
|
|
#include "demo.h"
|
|
#include "dummy_progress.h"
|
|
#include "interface_v3/sphrase_manager.h"
|
|
#include "interface_v3/sbrick_manager.h"
|
|
#include "interface_v3/inventory_manager.h"
|
|
#include "interface_v3/action_handler_help.h"
|
|
#include "projectile_manager.h"
|
|
#include "fx_manager.h"
|
|
#include "actions_client.h"
|
|
#include "attack_list.h"
|
|
#include "interface_v3/player_trade.h"
|
|
#include "interface_v3/ctrl_base_button.h"
|
|
#include "weather.h"
|
|
#include "forage_source_cl.h"
|
|
#include "connection.h"
|
|
#include "interface_v3/lua_object.h"
|
|
#include "interface_v3/lua_ihm.h"
|
|
#include "init.h"
|
|
#include "interface_v3/people_interraction.h"
|
|
#include "far_tp.h"
|
|
#include "zone_util.h"
|
|
|
|
|
|
//
|
|
// Only the define FINAL_VERSION can be defined on the project, not in this file
|
|
// to desactive some commands
|
|
//
|
|
|
|
|
|
|
|
////////////////
|
|
// Namespaces //
|
|
////////////////
|
|
using namespace NLMISC;
|
|
using namespace NLNET;
|
|
using namespace NL3D;
|
|
using namespace std;
|
|
|
|
|
|
/////////////
|
|
// Externs //
|
|
/////////////
|
|
extern CGenericXmlMsgHeaderManager GenericMsgHeaderMngr;
|
|
extern CEntityAnimationManager *EAM;
|
|
extern CClientChatManager ChatMngr;
|
|
extern ULandscape *Landscape;
|
|
extern UScene *Scene;
|
|
extern CLog g_log;
|
|
|
|
|
|
///////////////
|
|
// Variables //
|
|
///////////////
|
|
|
|
NLLIGO::CPrimitives *LDPrim = 0;
|
|
static std::vector<UInstance> ShapeAddedByCommand; // list of shapes added with the 'shape' command
|
|
|
|
|
|
|
|
///////////////
|
|
// FUNCTIONS //
|
|
///////////////
|
|
|
|
// Function to release all things allocated for commands.
|
|
void releaseCommands()
|
|
{
|
|
if(LDPrim)
|
|
{
|
|
delete LDPrim;
|
|
LDPrim = 0;
|
|
}
|
|
}
|
|
|
|
//////////////
|
|
// COMMANDS //
|
|
//////////////
|
|
|
|
// connect to the support chat
|
|
NLMISC_COMMAND(supportChat, "connect to the external support chat", "")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
pIM->connectYuboChat();
|
|
return true;
|
|
}
|
|
|
|
// 'follow' : To Follow the target.
|
|
NLMISC_COMMAND(follow, "Follow the target", "")
|
|
{
|
|
// switch
|
|
if(UserEntity->follow())
|
|
UserEntity->disableFollow();
|
|
else
|
|
// enable follow, reseting the camera rotation
|
|
UserEntity->enableFollow(true);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(where, "Ask information on the position", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() == 0)
|
|
{ // Create the message and send.
|
|
const string msgName = "COMMAND:WHERE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("command 'where': unknown message named '%s'", msgName.c_str());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
NLMISC_COMMAND(who, "Display all players currently in game","[<options (GM)>]")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() > 1)
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if(!GenericMsgHeaderMngr.pushNameToStream("DEBUG:WHO", out))
|
|
{
|
|
nlwarning("Unknown message name DEBUG:WHO");
|
|
return false;
|
|
}
|
|
|
|
string opt;
|
|
if ( args.size() == 1 )
|
|
{
|
|
opt = args[0];
|
|
}
|
|
out.serial(opt);
|
|
NetMngr.push(out);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(afk, "Set the player as 'away from keyboard'","[<custom text>]")
|
|
{
|
|
string customText;
|
|
if( args.size() > 0 )
|
|
{
|
|
customText = args[0];
|
|
}
|
|
for(uint i = 1; i < args.size(); ++i )
|
|
{
|
|
customText += " ";
|
|
customText += args[i];
|
|
}
|
|
|
|
if (UserEntity != NULL)
|
|
UserEntity->setAFK(true,customText);
|
|
/*
|
|
CBitMemStream out;
|
|
if(!GenericMsgHeaderMngr.pushNameToStream("DEBUG:AFK", out))
|
|
{
|
|
nlwarning("Unknown message name DEBUG:AFK");
|
|
return false;
|
|
}
|
|
NetMngr.push(out);
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
bool randomCheckCharset(std::string const& str)
|
|
{
|
|
std::string::const_iterator it, itEnd = str.end();
|
|
for (it=str.begin(); it!=itEnd; ++it)
|
|
if (*it<'0' || *it>'9')
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// returns true if a<=b
|
|
bool randomLexicographicLess(std::string a, std::string b)
|
|
{
|
|
// Remove leading zeros
|
|
while (a.length()>1 && a[0]=='0')
|
|
a = a.substr(1);
|
|
while (b.length()>1 && b[0]=='0')
|
|
b = b.substr(1);
|
|
// Longest is the biggest
|
|
if (a.length()>b.length())
|
|
return false;
|
|
if (a.length()<b.length())
|
|
return true;
|
|
// Skip equal characters
|
|
size_t i = 0;
|
|
while (i<a.length() && a[i]==b[i])
|
|
++i;
|
|
// If all characters are equal a==b
|
|
if (i==a.length())
|
|
return false;
|
|
// Check highest weight different character
|
|
return a[i] < b[i];
|
|
}
|
|
|
|
bool randomFromString(std::string const& str, sint16& val, sint16 min = -32768, sint16 max = 32767)
|
|
{
|
|
bool negative = str[0]=='-';
|
|
std::string sAbsVal = str.substr(negative?1:0);
|
|
// Check we have only numerical characters
|
|
if (!randomCheckCharset(sAbsVal))
|
|
return false;
|
|
// Check sign
|
|
if (negative && min>0) return false;
|
|
if (!negative && max<0) return false;
|
|
// Check number is not too big nor too small with a lexicographic compare
|
|
std::string smin = NLMISC::toString(std::max<sint16>(min,-min));
|
|
std::string smax = NLMISC::toString(std::max<sint16>(max,-max));
|
|
bool tooSmall = false, tooBig = false;
|
|
if (min>=0 && randomLexicographicLess(sAbsVal, smin))
|
|
tooSmall = true;
|
|
if (min<0 && randomLexicographicLess(smin, sAbsVal))
|
|
tooSmall = true;
|
|
if (max>=0 && randomLexicographicLess(smax, sAbsVal))
|
|
tooBig = true;
|
|
if (max<0 && randomLexicographicLess(sAbsVal, smax))
|
|
tooBig = true;
|
|
if (!tooSmall && !tooBig)
|
|
{
|
|
NLMISC::fromString(str, val);
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
NLMISC_COMMAND(random, "Roll a dice and say the result around","[<min>] <max>")
|
|
{
|
|
// Check parameters.
|
|
if (args.size()<1 || args.size()>2)
|
|
return false;
|
|
|
|
sint16 min = 1;
|
|
sint16 max;
|
|
if (!randomFromString(args[0], max))
|
|
{
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
ucstring msg = CI18N::get("uiRandomBadParameter");
|
|
strFindReplace(msg, "%s", args[0] );
|
|
pIM->displaySystemInfo(msg);
|
|
return false;
|
|
}
|
|
if (args.size()==2)
|
|
{
|
|
if (!randomFromString(args[1], min))
|
|
{
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
ucstring msg = CI18N::get("uiRandomBadParameter");
|
|
strFindReplace(msg, "%s", args[0] );
|
|
pIM->displaySystemInfo(msg);
|
|
return false;
|
|
}
|
|
}
|
|
if (min>max)
|
|
std::swap(min, max);
|
|
|
|
if (UserEntity != NULL)
|
|
UserEntity->rollDice(min, max);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(bugReport, "Call the bug report tool with dump", "<AddScreenshot>")
|
|
{
|
|
const char *brname[] = { "bug_report.exe", "bug_report_r.exe", "bug_report_rd.exe", "bug_report_df.exe", "bug_report_d.exe" };
|
|
|
|
string brn;
|
|
|
|
for (uint i = 0; i < sizeof(brname)/sizeof(brname[0]); i++)
|
|
{
|
|
if (CFile::fileExists (brname[i]))
|
|
{
|
|
brn = brname[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (brn.empty())
|
|
{
|
|
log.displayNL("bug_report*.exe not found");
|
|
return false;
|
|
}
|
|
|
|
string sys;
|
|
|
|
sys = "Language "+CI18N::getCurrentLanguageName().toString() +" ";
|
|
|
|
if (args.size()>0)
|
|
{
|
|
uint8 quality;
|
|
fromString(args[0], quality);
|
|
if (quality == 0)
|
|
quality = 80;
|
|
|
|
CBitmap btm;
|
|
Driver->getBuffer(btm);
|
|
string filename = CFile::findNewFile ("screenshot.jpg");
|
|
COFile fs(filename);
|
|
btm.writeJPG(fs, quality);
|
|
sys += "AttachedFile "+filename+" ";
|
|
}
|
|
|
|
sys += "ClientVersion "RYZOM_VERSION" ";
|
|
|
|
// for now, set the same version than client one
|
|
sys += "ShardVersion "RYZOM_VERSION" ";
|
|
|
|
if (ClientCfg.Local)
|
|
sys += "ShardName OFFLINE ";
|
|
|
|
FILE *fp = fopen ("bug_report.txt", "wb");
|
|
if (fp != NULL)
|
|
{
|
|
string res = addSlashR(getDebugInformation());
|
|
|
|
// must put \r\n each line
|
|
fprintf(fp, "%s", res.c_str());
|
|
|
|
// // must put \r\n each line
|
|
// fprintf (fp, "UserId: %u\r\n", NetMngr.getUserId());
|
|
// fprintf (fp, "Player Name: '%s'.\r\n", UserEntity->getName().toString().c_str());
|
|
// fprintf (fp, "UserPosition: %.2f %.2f %.2f\r\n", UserEntity->pos().x, UserEntity->pos().y, UserEntity->pos().z);
|
|
// fprintf (fp, "ViewPosition: %.2f %.2f %.2f\r\n", View.viewPos().x, View.viewPos().y, View.viewPos().z);
|
|
// time_t ts; time( &ts );
|
|
// fprintf (fp, "LocalTime: %s\r\n", NLMISC::IDisplayer::dateToHumanString( ts ) );
|
|
// fprintf (fp, "ServerTick: %u\r\n", NetMngr.getCurrentServerTick());
|
|
// fprintf (fp, "ConnectState: %s\r\n", NetMngr.getConnectionStateCStr());
|
|
// fprintf (fp, "LocalAddress: %s\r\n", NetMngr.getAddress().asString().c_str());
|
|
|
|
fclose (fp);
|
|
|
|
sys += "DumpFilename bug_report.txt ";
|
|
}
|
|
|
|
nlinfo ("Calling for bug report : '%s %s'", brn.c_str(), sys.c_str());
|
|
|
|
launchProgram(brn, sys);
|
|
|
|
// give some cpu to the launched application
|
|
nlSleep (3000);
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
//
|
|
// This command is use to do all admin execution commands on you
|
|
//
|
|
// For example: "/a God 1" will set you in god mode
|
|
//
|
|
|
|
NLMISC_COMMAND(a, "Execute an admin command on you","<cmd> <arg>")
|
|
{
|
|
if(args.size() == 0)
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if (!GenericMsgHeaderMngr.pushNameToStream("COMMAND:ADMIN", out))
|
|
return false;
|
|
|
|
string cmd, arg;
|
|
cmd = args[0];
|
|
for (uint i = 1; i < args.size(); i++)
|
|
{
|
|
// temporary fix for utf-8
|
|
// servers commands are not decoded so convert them to ansi
|
|
std::string tmp = ucstring::makeFromUtf8(args[i]).toString();
|
|
|
|
if (!arg.empty())
|
|
arg += ' ';
|
|
if (tmp.find(' ') != std::string::npos)
|
|
{
|
|
arg += "\"" + tmp + "\"";
|
|
}
|
|
else
|
|
{
|
|
arg += tmp;
|
|
}
|
|
}
|
|
bool onTarget = false;
|
|
out.serial (onTarget);
|
|
out.serial (cmd);
|
|
out.serial (arg);
|
|
NetMngr.push (out);
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
//
|
|
// This command is use to do all admin execution commands on the target
|
|
//
|
|
// For example: "/b God 1" will set the target in god mod
|
|
//
|
|
|
|
NLMISC_COMMAND(b, "Execute an admin command on your target","<cmd> <arg>")
|
|
{
|
|
if(args.size() == 0)
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if (!GenericMsgHeaderMngr.pushNameToStream("COMMAND:ADMIN", out))
|
|
return false;
|
|
|
|
string cmd, arg;
|
|
cmd = args[0];
|
|
for (uint i = 1; i < args.size(); i++)
|
|
{
|
|
// temporary fix for utf-8
|
|
// servers commands are not decoded so convert them to ansi
|
|
std::string tmp = ucstring::makeFromUtf8(args[i]).toString();
|
|
|
|
if (!arg.empty())
|
|
arg += ' ';
|
|
if (tmp.find(' ') != std::string::npos)
|
|
{
|
|
arg += "\"" + tmp + "\"";
|
|
}
|
|
else
|
|
{
|
|
arg += tmp;
|
|
}
|
|
}
|
|
bool onTarget = true;
|
|
out.serial (onTarget);
|
|
out.serial (cmd);
|
|
out.serial (arg);
|
|
NetMngr.push (out);
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
//
|
|
// This command is used to do all admin execution commands on a character
|
|
//
|
|
// For example: "/c charName God 1" will set god mod on character if it's online, or keep
|
|
// command for wait character login
|
|
//
|
|
|
|
NLMISC_COMMAND(c, "Execute an admin command on character name","<Character Name> <cmd> <arg>")
|
|
{
|
|
if(args.size() < 2)
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if (!GenericMsgHeaderMngr.pushNameToStream("COMMAND:ADMIN_OFFLINE", out))
|
|
return false;
|
|
|
|
string characterName, cmd, arg;
|
|
|
|
characterName = args[0];
|
|
cmd = args[1];
|
|
for (uint i = 2; i < args.size(); i++)
|
|
{
|
|
// temporary fix for utf-8
|
|
// servers commands are not decoded so convert them to ansi
|
|
std::string tmp = ucstring::makeFromUtf8(args[i]).toString();
|
|
|
|
if (!arg.empty())
|
|
arg += ' ';
|
|
if (tmp.find(' ') != std::string::npos)
|
|
{
|
|
arg += "\"" + tmp + "\"";
|
|
}
|
|
else
|
|
{
|
|
arg += tmp;
|
|
}
|
|
}
|
|
out.serial (characterName);
|
|
out.serial (cmd);
|
|
out.serial (arg);
|
|
NetMngr.push (out);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(boxes, "Show/Hide selection boxes", "[<state> : 0 to Hide, anything else to Show. Invert the current state if nothing specified.]")
|
|
{
|
|
#if FINAL_VERSION
|
|
if (!ClientCfg.ExtendedCommands) return false;
|
|
|
|
if( !ClientCfg.Local && !hasPrivilegeDEV() && !hasPrivilegeSGM() && !hasPrivilegeGM() )
|
|
return true;
|
|
#endif // FINAL_VERSION
|
|
|
|
// Invert Current State
|
|
if(args.size() == 0)
|
|
{
|
|
// Invert the current value.
|
|
ClientCfg.DrawBoxes = !ClientCfg.DrawBoxes;
|
|
return true;
|
|
}
|
|
// Set Current State
|
|
else if(args.size() == 1)
|
|
{
|
|
// Invert the current value.
|
|
fromString(args[0], ClientCfg.DrawBoxes);
|
|
return true;
|
|
}
|
|
// Bad parameters.
|
|
else
|
|
return false;
|
|
}
|
|
|
|
NLMISC_COMMAND(dump, "Command to create a file with the current state of the client", "[<dump name>]")
|
|
{
|
|
if(args.size() > 1)
|
|
return false;
|
|
|
|
string dumpName;
|
|
if(args.size() == 1)
|
|
dumpName = args[0];
|
|
else
|
|
dumpName = "default";
|
|
|
|
dump(dumpName);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(verbose, "Enable/Disable some Debug Informations", "none or magic")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 1)
|
|
{
|
|
// Help
|
|
CInterfaceManager *IM = CInterfaceManager::getInstance();
|
|
IM->displaySystemInfo(ucstring("This command need 1 parameter :"));
|
|
IM->displaySystemInfo(ucstring("<string> :"));
|
|
IM->displaySystemInfo(ucstring("- none(to remove all verboses)"));
|
|
IM->displaySystemInfo(ucstring("- magic(to add debug infos about magic)"));
|
|
IM->displaySystemInfo(ucstring("- anim (to add debug infos about animation)"));
|
|
}
|
|
else
|
|
{
|
|
std::string type = NLMISC::strlwr(args[0]);
|
|
if (type == "none")
|
|
Verbose = VerboseNone;
|
|
else if(type == "magic")
|
|
Verbose |= VerboseMagic;
|
|
else if(type == "anim")
|
|
Verbose |= VerboseAnim;
|
|
else
|
|
{
|
|
CInterfaceManager *IM = CInterfaceManager::getInstance();
|
|
IM->displaySystemInfo(ucstring("This command need 1 parameter :"));
|
|
IM->displaySystemInfo(ucstring("<string> :"));
|
|
IM->displaySystemInfo(ucstring("- none(to remove all verboses)"));
|
|
IM->displaySystemInfo(ucstring("- magic(to add debug infos about magic)"));
|
|
IM->displaySystemInfo(ucstring("- anim (to add debug infos about animation)"));
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(verboseAnimSelection, "Enable/Disable the animation log for the current selection", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 0)
|
|
return false;
|
|
|
|
VerboseAnimSelection = !VerboseAnimSelection;
|
|
if(VerboseAnimSelection)
|
|
nlinfo("Enable VerboseAnimSelection");
|
|
else
|
|
nlinfo("Disable VerboseAnimSelection");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(verboseAnimUser, "Enable/Disable the animation log for the user", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 0)
|
|
return false;
|
|
|
|
VerboseAnimUser = !VerboseAnimUser;
|
|
if(VerboseAnimUser)
|
|
nlinfo("Enable VerboseAnimUser");
|
|
else
|
|
nlinfo("Disable VerboseAnimUser");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(verboseDatabase, "Enable/Disable the log for the database", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 0)
|
|
return false;
|
|
|
|
VerboseDatabase = !VerboseDatabase;
|
|
if(VerboseDatabase)
|
|
nlinfo("Enable VerboseDatabase");
|
|
else
|
|
nlinfo("Disable VerboseDatabase");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(verbosePropertiesLoggingMode, "Set logging mode", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 0)
|
|
return false;
|
|
|
|
CNetworkConnection::LoggingMode = !CNetworkConnection::LoggingMode;
|
|
if(CNetworkConnection::LoggingMode)
|
|
nlinfo("Enable LoggingMode");
|
|
else
|
|
nlinfo("Disable LoggingMode");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(logEntities, "Write the position and orientation af all entities in the vision in the file 'entities.txt'", "")
|
|
{
|
|
// Check parameters
|
|
if(args.size() != 0)
|
|
return false;
|
|
|
|
// Log entities
|
|
EntitiesMngr.writeEntities();
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(log, "Add/Del Positive/Negative Filters for logs", "Log System <debug, info, warning, assert>, Type <pos/neg/del/reset>, Filter <string>")
|
|
{
|
|
// check args, if there s not the right number of parameter, return bad
|
|
if(args.size() < 2 || args.size() > 3)
|
|
return false;
|
|
|
|
CLog *logSys;
|
|
// Debug log system.
|
|
if (string(args[0].c_str()) == "debug")
|
|
logSys = DebugLog;
|
|
// Info log system.
|
|
else if(string(args[0].c_str()) == "info")
|
|
logSys = InfoLog;
|
|
// Warning log system.
|
|
else if(string(args[0].c_str()) == "warning")
|
|
logSys = WarningLog;
|
|
// Assert log system.
|
|
else if(string(args[0].c_str()) == "assert")
|
|
logSys = AssertLog;
|
|
// Unknown Log System -> return false.
|
|
else
|
|
return false;
|
|
|
|
// Add a positive filter.
|
|
if (string(args[1].c_str()) == "pos")
|
|
logSys->addPositiveFilter(args[2].c_str());
|
|
// Add a negative filter.
|
|
else if(string(args[1].c_str()) == "neg")
|
|
logSys->addNegativeFilter(args[2].c_str());
|
|
// Removes a filter by name (in both filters).
|
|
else if(string(args[1].c_str()) == "del")
|
|
logSys->removeFilter(args[2].c_str());
|
|
// Reset both filters.
|
|
else if(string(args[1].c_str()) == "reset")
|
|
logSys->resetFilters();
|
|
// Unknown Filter -> return false.
|
|
else
|
|
return false;
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(execScript, "Execute a script file (.cmd)","<FileName>")
|
|
{
|
|
int size = args.size();
|
|
if (size != 1)
|
|
return false;
|
|
|
|
CIFile iFile;
|
|
|
|
if (iFile.open(CPath::lookup(args[0], false)))
|
|
{
|
|
char line[512];
|
|
char *buffer;
|
|
// Read line by line and execute each line
|
|
|
|
sint inComment= 0;
|
|
bool eof = false;
|
|
while (!eof)
|
|
{
|
|
buffer = &line[0];
|
|
uint read = 0;
|
|
for(;;)
|
|
{
|
|
if (read == 512 -1)
|
|
{
|
|
*buffer = '\0';
|
|
break;
|
|
}
|
|
|
|
try
|
|
{
|
|
// read one byte
|
|
iFile.serialBuffer ((uint8 *)buffer, 1);
|
|
}
|
|
catch (EFile &)
|
|
{
|
|
*buffer = '\0';
|
|
eof = true;
|
|
break;
|
|
}
|
|
|
|
if (*buffer == '\n')
|
|
{
|
|
*buffer = '\0';
|
|
break;
|
|
}
|
|
|
|
// skip '\r' char
|
|
if (*buffer != '\r')
|
|
{
|
|
buffer++;
|
|
read++;
|
|
}
|
|
}
|
|
|
|
// execute line
|
|
if (strlen(line) > 0)
|
|
{
|
|
// if not a single comment
|
|
if(strncmp(line, "//", 2)!=0)
|
|
{
|
|
if(strncmp(line, "/*", 2)==0)
|
|
inComment++;
|
|
if(inComment<=0)
|
|
ICommand::execute(line, g_log);
|
|
if(strncmp(line, "*/", 2)==0)
|
|
inComment--;
|
|
}
|
|
}
|
|
|
|
// end?
|
|
if (iFile.eof())
|
|
eof = true;
|
|
}
|
|
iFile.close();
|
|
}
|
|
else
|
|
{
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("Cannot open file"));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(db, "Modify Database","<Property> <Value>")
|
|
{
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
int size = args.size();
|
|
if (size == 2)
|
|
{
|
|
#if !FINAL_VERSION
|
|
// check if 2nd arg is a sheet name
|
|
if (args[1].empty()) return false;
|
|
sint64 value;
|
|
if (isalpha(args[1][0]))
|
|
{
|
|
CSheetId sheet(args[1]);
|
|
value = (sint64) sheet.asInt();
|
|
}
|
|
else
|
|
{
|
|
// Convert the string into an sint64.
|
|
fromString(args[1], value);
|
|
}
|
|
|
|
// Set the property.
|
|
CCDBNodeLeaf *node= pIM->getDbProp(args[0], false);
|
|
if(node)
|
|
node->setValue64(value);
|
|
else
|
|
pIM->displaySystemInfo(toString("DB %s don't exist.", args[0].c_str()));
|
|
#else
|
|
pIM->displaySystemInfo(ucstring("Can't write to DB when in Final Version."));
|
|
#endif
|
|
}
|
|
else if (size == 1)
|
|
{
|
|
CCDBNodeLeaf *node= pIM->getDbProp(args[0], false);
|
|
if(node)
|
|
{
|
|
sint64 prop = node->getValue64();
|
|
string str = toString(prop);
|
|
pIM->displaySystemInfo(ucstring(str));
|
|
nlinfo("%s", str.c_str());
|
|
}
|
|
else
|
|
pIM->displaySystemInfo(toString("DB %s don't exist.", args[0].c_str()));
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool talkInChan(uint32 nb,std::vector<std::string>args)
|
|
{
|
|
uint32 maxChans = CChatGroup::MaxDynChanPerPlayer;
|
|
if (nb<0||nb>=maxChans)
|
|
{
|
|
return false;
|
|
}
|
|
if(args.size()>0)
|
|
{
|
|
std::string tmp="";
|
|
std::vector<std::string>::const_iterator first(args.begin()),last(args.end());
|
|
|
|
for(;first!=last;++first)
|
|
{
|
|
tmp = tmp + (*first);
|
|
tmp = tmp+" ";
|
|
}
|
|
|
|
PeopleInterraction.talkInDynamicChannel(nb,ucstring(tmp));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
NLMISC_COMMAND(0,"talk in 0th dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(0,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(1,"talk in first dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(1,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(2,"talk in 2nd dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(2,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(3,"talk in 3rd dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(3,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(4,"talk in 4th dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(4,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(5,"talk in 5th dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(5,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(6,"talk in 6th dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(6,args);
|
|
}
|
|
|
|
NLMISC_COMMAND(7,"talk in 7th dynamic chat channel","<channel_nb> <sentence>")
|
|
{
|
|
return talkInChan(7,args);
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////// COMMANDS after should NOT appear IN the FINAL VERSION ///////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
#if !FINAL_VERSION
|
|
|
|
NLMISC_COMMAND(ah, "Launch an action handler", "<ActionHandler> <AHparam>")
|
|
{
|
|
if (args.size() == 0)
|
|
return false;
|
|
|
|
if (!ClientCfg.AllowDebugLua && strlwr(args[0]) == "lua")
|
|
{
|
|
return false; // not allowed!!
|
|
}
|
|
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
if (args.size() == 1)
|
|
{
|
|
pIM->runActionHandler(args[0], NULL);
|
|
}
|
|
else
|
|
{
|
|
pIM->runActionHandler(args[0], NULL, args[1]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void setDynString(uint32 strID, const std::string &value)
|
|
{
|
|
STRING_MANAGER::CStringManagerClient *pSMC = STRING_MANAGER::CStringManagerClient::instance();
|
|
pSMC->receiveString(strID, ucstring(value));
|
|
CBitMemStream bm;
|
|
if (bm.isReading()) bm.invert();
|
|
bm.serial(strID);
|
|
bm.serial(strID);
|
|
bm.invert();
|
|
bm.seek(0, NLMISC::IStream::begin);
|
|
pSMC->receiveDynString(bm);
|
|
}
|
|
|
|
// for debug purposes, insert a string in the
|
|
NLMISC_COMMAND(setDynString, "set a dynamic string","<stringID> <asciiValue>")
|
|
{
|
|
if (args.size() != 2) return false;
|
|
uint32 strID;
|
|
fromString(args[0], strID);
|
|
setDynString(strID, args[1]);
|
|
return true;
|
|
}
|
|
|
|
class CAnimProgress : public IProgressCallback
|
|
{
|
|
public:
|
|
// Update the progress bar
|
|
virtual void progress (float value)
|
|
{
|
|
// can't do anything if no driver
|
|
if(Driver == NULL)
|
|
return;
|
|
// Get croped value
|
|
value = getCropedValue (value);
|
|
// Set matrix
|
|
Driver->setMatrixMode2D11();
|
|
// Display a progress bar background
|
|
Driver->drawQuad (PROGRESS_BAR_LEFT, 0.5f-PROGRESS_BAR_HEIGHT/2.0f, PROGRESS_BAR_LEFT+ PROGRESS_BAR_WIDTH, 0.5f+PROGRESS_BAR_HEIGHT/2.0f,
|
|
PROGRESS_BAR_BG_COLOR);
|
|
// Display a progress bar
|
|
Driver->drawQuad (PROGRESS_BAR_LEFT, 0.5f-PROGRESS_BAR_HEIGHT/2.0f, PROGRESS_BAR_LEFT+value*PROGRESS_BAR_WIDTH, 0.5f+PROGRESS_BAR_HEIGHT/2.0f,
|
|
PROGRESS_BAR_COLOR);
|
|
if(TextContext != NULL)
|
|
{
|
|
// Init the Pen.
|
|
TextContext->setKeep800x600Ratio(false);
|
|
TextContext->setColor(CRGBA(255,255,255));
|
|
TextContext->setFontSize(20);
|
|
TextContext->setHotSpot(UTextContext::MiddleMiddle);
|
|
|
|
// Display the Text.
|
|
TextContext->printfAt(0.5f, 0.5f, _ProgressMessage.c_str());
|
|
}
|
|
// Display to screen.
|
|
Driver->swapBuffers();
|
|
}
|
|
// New message
|
|
void newMessage(const std::string &message) {_ProgressMessage = message;}
|
|
|
|
private:
|
|
std::string _ProgressMessage;
|
|
};
|
|
|
|
NLMISC_COMMAND(reloadSearchPaths, "reload the search paths","")
|
|
{
|
|
if (!args.empty()) return false;
|
|
CPath::memoryUncompress();
|
|
CAnimProgress progress;
|
|
// remove all objects that may depend on an animation
|
|
CProjectileManager::getInstance().reset();
|
|
|
|
// Pathes
|
|
progress.newMessage("Reloading pathes");
|
|
progress.progress(0.0f);
|
|
progress.pushCropedValues(0.0f, 1.0f);
|
|
//
|
|
|
|
addSearchPaths(progress);
|
|
CPath::memoryCompress();
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(reloadAnim, "reload animations","")
|
|
{
|
|
CPath::memoryUncompress();
|
|
CAnimProgress dummy;
|
|
// remove all objects that may depend on an animation
|
|
CProjectileManager::getInstance().reset();
|
|
|
|
// Pathes
|
|
dummy.newMessage("Pathes");
|
|
dummy.progress(0.0f);
|
|
dummy.pushCropedValues(0.0f, 0.5f);
|
|
|
|
|
|
addSearchPaths(dummy);
|
|
|
|
if (ClientCfg.UpdatePackedSheet)
|
|
{
|
|
for(uint i = 0; i < ClientCfg.UpdatePackedSheetPath.size(); i++)
|
|
{
|
|
dummy.progress((float)i/(float)ClientCfg.UpdatePackedSheetPath.size());
|
|
dummy.pushCropedValues ((float)i/(float)ClientCfg.UpdatePackedSheetPath.size(), (float)(i+1)/(float)ClientCfg.UpdatePackedSheetPath.size());
|
|
CPath::addSearchPath(ClientCfg.UpdatePackedSheetPath[i], true, false, &dummy);
|
|
dummy.popCropedValues();
|
|
}
|
|
}
|
|
|
|
|
|
dummy.popCropedValues();
|
|
// Animations
|
|
dummy.newMessage("Anims");
|
|
dummy.progress(0.5f);
|
|
dummy.pushCropedValues(0.5f, 1.0f);
|
|
EAM->load(dummy, true);
|
|
dummy.popCropedValues();
|
|
// Reload Animations
|
|
EntitiesMngr.reloadAnims();
|
|
CPath::memoryCompress();
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(reloadAttack, "reload attack", "")
|
|
{
|
|
if (!args.empty()) return false;
|
|
// remove all objects that may depend on an animation
|
|
ClientSheetsStrings.memoryUncompress();
|
|
CProjectileManager::getInstance().reset();
|
|
EntitiesMngr.removeAllAttachedFX();
|
|
FXMngr.reset();
|
|
//
|
|
std::vector<std::string> exts;
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// replace attack list of creature in place (so pointers on character sheets remains valid)
|
|
CSheetManager sheetManager;
|
|
exts;
|
|
// exts.push_back("creature");
|
|
exts.push_back("race_stats");
|
|
NLMISC::IProgressCallback progress;
|
|
sheetManager.loadAllSheet(progress, true, false, false, true, &exts);
|
|
//
|
|
const CSheetManager::TEntitySheetMap &sm = SheetMngr.getSheets();
|
|
for(CSheetManager::TEntitySheetMap::const_iterator it = sm.begin(); it != sm.end(); ++it)
|
|
{
|
|
if (it->second.EntitySheet && it->second.EntitySheet->Type == CEntitySheet::FAUNA)
|
|
{
|
|
// find matching sheet in new sheetManager
|
|
const CEntitySheet *other = sheetManager.get(it->first);
|
|
if (other)
|
|
{
|
|
// replace data in place
|
|
((CCharacterSheet &) *it->second.EntitySheet).AttackLists = ((const CCharacterSheet &) *other).AttackLists;
|
|
}
|
|
}
|
|
else if(it->second.EntitySheet && it->second.EntitySheet->Type == CEntitySheet::RACE_STATS)
|
|
{
|
|
// find matching sheet in new sheetManager
|
|
const CEntitySheet *other = sheetManager.get(it->first);
|
|
if (other)
|
|
{
|
|
// replace data in place
|
|
((CRaceStatsSheet &) *it->second.EntitySheet).AttackLists = ((const CRaceStatsSheet &) *other).AttackLists;
|
|
}
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CAttackListManager::getInstance().release();
|
|
// form to reload all sheets of interest
|
|
exts.clear();
|
|
exts.push_back("attack_list");
|
|
exts.push_back("animation_fx_set");
|
|
exts.push_back("id_to_string_array");
|
|
CDummyProgress dp;
|
|
SheetMngr.loadAllSheet(dp, true, false, true, true, &exts);
|
|
CAttackListManager::getInstance().init();
|
|
//
|
|
ClientSheetsStrings.memoryCompress();
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(reloadSky, "reload new style sky", "")
|
|
{
|
|
if (!args.empty()) return false;
|
|
ContinentMngr.reloadSky();
|
|
return false;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(missionReward, "debug"," ")
|
|
{
|
|
if (args.size() == 1)
|
|
{
|
|
uint8 index;
|
|
fromString(args[0], index);
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("BOTCHAT:COMPLETE_MISSION", out))
|
|
{
|
|
out.serial(index);
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("<CBotChat acceptMission> : unknown message name : BOTCHAT:COMPLETE_MISSION");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
NLMISC_COMMAND(missionProgress, "debug"," ")
|
|
{
|
|
if (args.size() == 1)
|
|
{
|
|
uint8 index;
|
|
fromString(args[0], index);
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("BOTCHAT:PROGRESS_MISSION", out))
|
|
{
|
|
out.serial(index);
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("<CBotChat acceptMission> : unknown message name : BOTCHAT:PROGRESS_MISSION");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
NLMISC_COMMAND( displayDBModifs, "display server database modification in the chat window"," ")
|
|
{
|
|
if ( VerboseDatabase )
|
|
CInterfaceManager::getInstance()->getChatOutput()->addTextChild(ucstring("the database is already in verbose mode"),CRGBA(255,255,255,255));
|
|
else
|
|
{
|
|
CInterfaceManager::getInstance()->getChatOutput()->addTextChild(ucstring("database is now in verbose mode"),CRGBA(255,255,255,255));
|
|
VerboseDatabase = true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND( hideDBModifs, "stop displaying server database modification in the chat window"," ")
|
|
{
|
|
if ( !VerboseDatabase )
|
|
CInterfaceManager::getInstance()->getChatOutput()->addTextChild(ucstring("the database is already not in verbose mode"),CRGBA(255,255,255,255));
|
|
else
|
|
{
|
|
CInterfaceManager::getInstance()->getChatOutput()->addTextChild(ucstring("database is not in verbose mode anymore"),CRGBA(255,255,255,255));
|
|
VerboseDatabase = false;
|
|
}
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
NLMISC_COMMAND(save_sentences, "save sentences"," ")
|
|
{
|
|
CSentenceDisplayer::saveSentences();
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
NLMISC_COMMAND(getSheetId, "get_sheet_id","<sheet file name>")
|
|
{
|
|
if (args.size() != 1)
|
|
return false;
|
|
CSheetId id(args[0]);
|
|
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(toString(id.asInt())));
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(getSheetName, "get_sheet_name","<Sheet Id>")
|
|
{
|
|
if (args.size() != 1)
|
|
return false;
|
|
uint32 nId;
|
|
fromString(args[0], nId);
|
|
CSheetId id( nId );
|
|
|
|
string name = id.toString();
|
|
|
|
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(name));
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(forgetAll, "forget all bricks", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 0)
|
|
{
|
|
return false;
|
|
}
|
|
char buf[100];
|
|
for (uint i = 0;i<20;i++)
|
|
{
|
|
sprintf(buf,"SERVER:BRICK_FAMILY:%d:BRICKS",i);
|
|
CCDBNodeLeaf * node= CInterfaceManager::getInstance()->getDbProp(buf);
|
|
node->setValue64(0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(usePreprogMagic, "use the specified magic preprog sentence", "<sentence id>")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "SENTENCE:EXECUTE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("SENTENCE:EXECUTE", out))
|
|
{
|
|
uint8 phrase;
|
|
fromString(args[0], phrase);
|
|
out.serial(phrase);
|
|
|
|
BRICK_TYPE::EBrickType type = BRICK_TYPE::MAGIC;
|
|
out.serialEnum( type );
|
|
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(usePreprogCombat, "use the specified combat preprog sentence", "<sentence id>")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "SENTENCE:EXECUTE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("SENTENCE:EXECUTE", out))
|
|
{
|
|
uint8 phrase;
|
|
fromString(args[0], phrase);
|
|
out.serial(phrase);
|
|
|
|
BRICK_TYPE::EBrickType type = BRICK_TYPE::COMBAT;
|
|
out.serialEnum( type );
|
|
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(engage, "engage target in combat", "")
|
|
{
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "COMBAT:ENGAGE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(defaultAttack, "use default attack on target", "")
|
|
{
|
|
// Default attack on the current selection.
|
|
UserEntity->attack();
|
|
|
|
// Well Done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(disengage, "disengage from combat", "")
|
|
{
|
|
// Disengage from combat.
|
|
UserEntity->disengage();
|
|
|
|
// Well Done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(leaveTeam, "leave team", "")
|
|
{
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "TEAM:LEAVE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(joinTeam, "join the specified team", "")
|
|
{
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "TEAM:JOIN";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(joinTeamProposal, "propose to current target to join the team", "")
|
|
{
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "TEAM:JOIN_PROPOSAL";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(joinTeamDecline, "decline a join team proposal", "")
|
|
{
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "TEAM:JOIN_PROPOSAL_DECLINE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(kickTeammate, "kick someone from your team", "")
|
|
{
|
|
// Create the message for the server to execute a phrase.
|
|
const string msgName = "TEAM:KICK";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(cancelCurrentSentence, "cancel the sentence being executed", "")
|
|
{
|
|
// no parameter needed
|
|
|
|
// Create the message for the server to cancel the phrase being executed
|
|
const string msgName = "SENTENCE:CANCEL_CURRENT";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("command : unknown message name : '%s'", msgName.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(cancelAllPhrases, "cancel all the phrases being executed", "")
|
|
{
|
|
// no parameter needed
|
|
|
|
UserEntity->cancelAllPhrases();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
NLMISC_COMMAND(drop,"drop an item to the ground","<id>")
|
|
{
|
|
if( args.size() < 1 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
uint32 id;
|
|
fromString(args[0], id);
|
|
CEntityId itemId(RYZOMID::object,id);
|
|
|
|
sint32 x = (sint32)UserEntity->pos().x * 1000;
|
|
sint32 y = (sint32)UserEntity->pos().y * 1000;
|
|
sint32 z = (sint32)UserEntity->pos().z * 1000;
|
|
|
|
CBitMemStream bms;
|
|
string msgType = "ITEM:DROP";
|
|
if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) )
|
|
{
|
|
bms.serial( itemId );
|
|
bms.serial( x );
|
|
bms.serial( y );
|
|
bms.serial( z );
|
|
NetMngr.push( bms );
|
|
nldebug("<drop> sending 'ITEM:DROP' message to server");
|
|
}
|
|
else
|
|
{
|
|
nlwarning("<drop> unknown message name : ITEM:DROP");
|
|
}*
|
|
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
NLMISC_COMMAND(pos, "Change the position of the user (in local only)", "<x, y, (z)> OR 1 name of 'tp.teleport_list'. or a bot name")
|
|
{
|
|
CVectorD newPos;
|
|
|
|
// Named destination.
|
|
if(args.size() == 1)
|
|
{
|
|
string dest = args[0];
|
|
newPos = CTeleport::getPos(NLMISC::strlwr(dest));
|
|
if(newPos == CTeleport::Unknown)
|
|
{
|
|
//here we try to teleport to a bot destination
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("TP:BOT", out))
|
|
{
|
|
string str = args[0];
|
|
out.serial( str );
|
|
nldebug("/pos: TP:BOT sent");
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("/pos: unknown message name : 'TP:BOT'");
|
|
return true;
|
|
}
|
|
}
|
|
// Teleport to anywhere.
|
|
else if(args.size() == 2 || args.size() == 3)
|
|
{
|
|
fromString(args[0], newPos.x);
|
|
fromString(args[1], newPos.y);
|
|
if(args.size() == 3)
|
|
fromString(args[2], newPos.z);
|
|
else
|
|
newPos.z = 0.0;
|
|
}
|
|
// Bad argument number.
|
|
else
|
|
return false;
|
|
|
|
/*
|
|
CANNOT USE ProgressBar here, because it does pumpEvents(), and
|
|
ICommand::execute() is typically called from a pumpEvents() too...
|
|
=> cause crash
|
|
*/
|
|
|
|
// Fade out the Game Sound
|
|
if(SoundMngr)
|
|
SoundMngr->fadeOutGameSound(ClientCfg.SoundTPFade);
|
|
|
|
// Remove the selection.
|
|
UserEntity->selection(CLFECOMMON::INVALID_SLOT);
|
|
// Remove the target.
|
|
UserEntity->targetSlot(CLFECOMMON::INVALID_SLOT);
|
|
// Change the position of the entity and in Pacs.
|
|
UserEntity->pos(newPos);
|
|
// Select the closest continent from the new position.
|
|
CDummyProgress progress;
|
|
ContinentMngr.select(newPos, progress);
|
|
// Teleport the User.
|
|
UserEntity->tp(newPos);
|
|
|
|
// First frame (for sound fade in)
|
|
extern bool FirstFrame;
|
|
FirstFrame = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(removeEntity, "Remove an entity", "<Slot>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
uint slot;
|
|
fromString(args[0], slot);
|
|
EntitiesMngr.remove(slot, true);
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(entity, "Create an entity on the user or just remove it if Form not valid", "<Slot> <Form> [posx posy posz] [relativeToPlayer]")
|
|
{
|
|
CInterfaceManager *IM = CInterfaceManager::getInstance ();
|
|
|
|
// Check parameters.
|
|
if(args.size() != 2 && args.size() != 5 && args.size() != 6)
|
|
return false;
|
|
|
|
// read pos.
|
|
CVector entityPos;
|
|
if(args.size()>=5)
|
|
{
|
|
fromString(args[2], entityPos.x);
|
|
fromString(args[3], entityPos.y);
|
|
fromString(args[4], entityPos.z);
|
|
// if want pos local to UserEntity
|
|
if(args.size()==6)
|
|
{
|
|
sint32 tmp;
|
|
fromString(args[5], tmp);
|
|
if (tmp != 0)
|
|
{
|
|
CMatrix mat;
|
|
mat.setRot(CVector::I, UserEntity->front(), CVector::K);
|
|
mat.normalize(CMatrix::YZX);
|
|
mat.setPos(UserEntity->pos());
|
|
entityPos= mat * entityPos;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
entityPos= UserEntity->pos()+UserEntity->front()*2.0;
|
|
}
|
|
|
|
// Try to create the sheet with the parameter as a string.
|
|
CSheetId sheetId;
|
|
if(!sheetId.buildSheetId(args[1]))
|
|
{
|
|
// Try to create the sheet with the parameter as an int.
|
|
uint32 nSheetId;
|
|
fromString(args[1], nSheetId);
|
|
sheetId = CSheetId(nSheetId);
|
|
if(sheetId == CSheetId::Unknown)
|
|
{
|
|
nlwarning("Command 'entity': '%s' is not a valid form", args[1].c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// The slot where the new entity will be.
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
|
|
// Debug Infos
|
|
nldebug("Command 'entity' : AddNewEntity with form %s in the slot %d", args[1].c_str(), slot);
|
|
// Remove the old entity.
|
|
EntitiesMngr.remove(slot, false);
|
|
// Create the new entity.
|
|
|
|
TNewEntityInfo emptyEntityInfo;
|
|
emptyEntityInfo.reset();
|
|
CEntityCL *entity = EntitiesMngr.create(slot, sheetId.asInt(), emptyEntityInfo);
|
|
if(entity)
|
|
{
|
|
sint64 *prop = 0;
|
|
CCDBNodeLeaf *node = 0;
|
|
// Set The property 'CLFECOMMON::PROPERTY_POSITION'.
|
|
node = IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_POSX), false);
|
|
if(node)
|
|
{
|
|
sint64 x = (sint64)(entityPos.x*1000.0);
|
|
sint64 y = (sint64)(entityPos.y*1000.0);
|
|
sint64 z = (sint64)(entityPos.z*1000.0);
|
|
node->setValue64(x);
|
|
node = IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_POSY), false);
|
|
if(node)
|
|
{
|
|
node->setValue64(y);
|
|
node = IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_POSZ), false);
|
|
if(node)
|
|
node->setValue64(z);
|
|
}
|
|
}
|
|
// Set The property 'PROPERTY_ORIENTATION'.
|
|
node = IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_ORIENTATION), false);
|
|
if(node)
|
|
{
|
|
float dir = (float)atan2(UserEntity->front().y, UserEntity->front().x);
|
|
prop = (sint64 *)(&dir);
|
|
node->setValue64(*prop);
|
|
}
|
|
// Set Mode
|
|
node = IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_MODE), false);
|
|
if(node)
|
|
{
|
|
MBEHAV::EMode m = MBEHAV::NORMAL;
|
|
prop = (sint64 *)&m;
|
|
node->setValue64(*prop);
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_MODE);
|
|
}
|
|
// Set Visual Properties
|
|
if(dynamic_cast<CPlayerCL *>(entity))
|
|
{
|
|
SPropVisualA visualA;
|
|
visualA.PropertySubData.Sex = ClientCfg.Sex;
|
|
SPropVisualB visualB;
|
|
// Initialize the Visual Property C (Default parameters).
|
|
SPropVisualC visualC;
|
|
visualC.PropertySubData.CharacterHeight = 7;
|
|
visualC.PropertySubData.ArmsWidth = 7;
|
|
visualC.PropertySubData.LegsWidth = 7;
|
|
visualC.PropertySubData.TorsoWidth = 7;
|
|
visualC.PropertySubData.BreastSize = 7;
|
|
// Set The Database
|
|
prop = (sint64 *)&visualB;
|
|
IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_VPB))->setValue64(*prop);
|
|
prop = (sint64 *)&visualC;
|
|
IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_VPC))->setValue64(*prop);
|
|
prop = (sint64 *)&visualA;
|
|
IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_VPA))->setValue64(*prop);
|
|
// Apply Changes.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_VPA);
|
|
}
|
|
// Forage Source special
|
|
if(dynamic_cast<CForageSourceCL*>(entity))
|
|
{
|
|
sint64 barVal;
|
|
barVal= 32; barVal<<= 7;
|
|
barVal+= 32; barVal<<= 7;
|
|
barVal+= 10; barVal<<= 7;
|
|
barVal+= 127;
|
|
IM->getDbProp("SERVER:Entities:E"+toString("%d", slot)+":P"+toString("%d", CLFECOMMON::PROPERTY_BARS))->setValue64(barVal);
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_BARS);
|
|
// must also update position, else don't work
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_POSITION);
|
|
}
|
|
else
|
|
if (dynamic_cast<CFxCL*>(entity)) // FX cl special
|
|
{
|
|
// must also update position, else don't work
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_POSITION);
|
|
}
|
|
//
|
|
nlinfo("entity: slot: %d \"%s\", \"%f\", \"%f\", \"%f\" ",
|
|
slot,args[1].c_str(),
|
|
entityPos.x, entityPos.y, entityPos.z);
|
|
}
|
|
else
|
|
nldebug("command 'entity' : entity in slot %d removed", slot);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(primPoint, "add a primitive point", "<pointName>")
|
|
{
|
|
if(args.size() != 2)
|
|
return false;
|
|
|
|
if(LDPrim == 0)
|
|
{
|
|
LDPrim = new NLLIGO::CPrimitives;
|
|
if(LDPrim == 0)
|
|
{
|
|
nlwarning("primPoint: LDPrim == 0");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(LDPrim->RootNode == 0)
|
|
{
|
|
nlwarning("primPoint: LDPrim.RootNode == 0");
|
|
return true;
|
|
}
|
|
|
|
NLLIGO::CPropertyString *str = 0;
|
|
NLLIGO::CPrimPoint *point = 0;
|
|
|
|
point = new NLLIGO::CPrimPoint;
|
|
if(point == 0)
|
|
{
|
|
nlwarning("primPoint: point == 0");
|
|
return true;
|
|
}
|
|
point->Point.x = (float)UserEntity->pos().x;
|
|
point->Point.y = (float)UserEntity->pos().y;
|
|
point->Point.z = (float)UserEntity->pos().z;
|
|
|
|
str = new NLLIGO::CPropertyString;
|
|
if(str == 0)
|
|
{
|
|
nlwarning("primPoint: str == 0 (1)");
|
|
return true;
|
|
}
|
|
point->addPropertyByName("class", str);
|
|
str->String = "reference_point";
|
|
|
|
str = new NLLIGO::CPropertyString;
|
|
if(str == 0)
|
|
{
|
|
nlwarning("primPoint: str == 0 (2)");
|
|
return true;
|
|
}
|
|
point->addPropertyByName("name", str);
|
|
str->String = args[1];
|
|
|
|
// Add the point to the primitive.
|
|
LDPrim->RootNode->insertChild(point);
|
|
|
|
// Open the file.
|
|
NLMISC::COFile file;
|
|
if(file.open(args[0]))
|
|
{
|
|
// Create the XML stream
|
|
NLMISC::COXml output;
|
|
// Init
|
|
if(output.init(&file, "1.0"))
|
|
{
|
|
LDPrim->write(output.getDocument(), args[0].c_str());
|
|
// Flush the stream, write all the output file
|
|
output.flush();
|
|
}
|
|
else
|
|
nlwarning("primPoint: ");
|
|
// Close the File.
|
|
file.close();
|
|
}
|
|
else
|
|
nlwarning("primPoint: cannot open/create the file '%s'", args[0].c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef ENABLE_INCOMING_MSG_RECORDER
|
|
|
|
NLMISC_COMMAND(record, "Start Recording", "<name>")
|
|
{
|
|
CInterfaceManager *IM = CInterfaceManager::getInstance ();
|
|
|
|
// Check parameters.
|
|
if(args.size() != 1)
|
|
return false;
|
|
|
|
// Warning when already recording.
|
|
if(NetMngr.isRecording())
|
|
{
|
|
IM->displaySystemInfo(ucstring("Already Recording. Stop the current Record first"));
|
|
return true;
|
|
}
|
|
|
|
// Save entities and DB.
|
|
dump(args[0]);
|
|
|
|
// On/Off record.
|
|
if(!ClientCfg.Local)
|
|
NetMngr.setRecordingMode(true, args[0]+"_net.rec");
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(replay, "replay", "<name>")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 1)
|
|
return false;
|
|
|
|
// Load entities and DB.
|
|
loadDump(args[0]);
|
|
|
|
// On/Off record.
|
|
if(ClientCfg.Local)
|
|
NetMngr.setReplayingMode(!NetMngr.isReplaying(), args[0]+"_net.rec");
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(stopRecord, "Stop Recording", "")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 0)
|
|
return false;
|
|
|
|
// On/Off record.
|
|
if(!ClientCfg.Local)
|
|
NetMngr.setRecordingMode(false);
|
|
return true;
|
|
}
|
|
|
|
#endif // ENABLE_INCOMING_MSG_RECORDER
|
|
|
|
NLMISC_COMMAND(loadDump, "Command to load a dump file", "[<dump name>]")
|
|
{
|
|
if(args.size() > 1)
|
|
return false;
|
|
|
|
string dumpName;
|
|
if(args.size() == 1)
|
|
dumpName = args[0];
|
|
else
|
|
dumpName = "default";
|
|
|
|
loadDump(dumpName);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(sheet2idx, "Return the index of a sheet", "<sheet name> <visual slot number>")
|
|
{
|
|
CInterfaceManager *IM = CInterfaceManager::getInstance ();
|
|
|
|
if(args.size() != 2)
|
|
return false;
|
|
|
|
string result;
|
|
NLMISC::CSheetId sheetId;
|
|
|
|
if(sheetId.buildSheetId(args[0]))
|
|
{
|
|
uint slot;
|
|
fromString(args[1], slot);
|
|
uint32 idx = CVisualSlotManager::getInstance()->sheet2Index(sheetId, (SLOTTYPE::EVisualSlot)slot);
|
|
result = NLMISC::toString("Index = %d", idx);
|
|
}
|
|
else
|
|
result = NLMISC::toString("sheet '%s' not valid", args[0].c_str());
|
|
|
|
IM->displaySystemInfo(ucstring(result));
|
|
nlinfo("'sheet2idx': %s", result.c_str());
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(watchEntity, "Choose the entity to watch", "<slot>")
|
|
{
|
|
if(args.size() != 1)
|
|
return false;
|
|
|
|
// Set the new debug entity slot.
|
|
fromString(args[0], WatchedEntitySlot);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dynstr, "display a dyn string value", "<dyn string_id>")
|
|
{
|
|
if (args.size() != 1)
|
|
return false;
|
|
|
|
uint dynId;
|
|
fromString(args[0], dynId);
|
|
|
|
ucstring result;
|
|
STRING_MANAGER::CStringManagerClient::instance()->getDynString(dynId, result);
|
|
|
|
CInterfaceManager::getInstance()->displaySystemInfo(result);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(serverstr, "display a server string value", "<serverstr string_id>")
|
|
{
|
|
if (args.size() != 1)
|
|
return false;
|
|
|
|
uint dynId;
|
|
fromString(args[0], dynId);
|
|
|
|
ucstring result;
|
|
STRING_MANAGER::CStringManagerClient::instance()->getString(dynId, result);
|
|
|
|
CInterfaceManager::getInstance()->displaySystemInfo(result);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(cmd, "Send a command to a server","<service name> <cmd>")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 2)
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("DEBUG:CMD", out))
|
|
{
|
|
bool addentity = false;
|
|
string dest = args[0];
|
|
string cmd = args[1];
|
|
string arg;
|
|
for (uint i = 2; i < args.size(); i++)
|
|
{
|
|
arg += args[i] + " ";
|
|
}
|
|
out.serial(addentity);
|
|
out.serial(dest);
|
|
out.serial(cmd);
|
|
out.serial(arg);
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name DEBUG:CMD");
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(cmde, "Send a command to a server with entityid","<service name> <cmd>")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 2)
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("DEBUG:CMD", out))
|
|
{
|
|
bool addentity = true;
|
|
string dest = args[0];
|
|
string cmd = args[1];
|
|
string arg;
|
|
for (uint i = 2; i < args.size(); i++)
|
|
{
|
|
arg += args[i] + " ";
|
|
}
|
|
out.serial(addentity);
|
|
out.serial(dest);
|
|
out.serial(cmd);
|
|
out.serial(arg);
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("mainLoop : unknown message name DEBUG:CMD");
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(askservices, "Ask the server all services up", "")
|
|
{
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("DEBUG:SERVICES", out))
|
|
{
|
|
// Add the message to the send list.
|
|
NetMngr.push(out);
|
|
nlinfo("command 'services': 'DEBUG:SERVICES' sent");
|
|
}
|
|
else
|
|
nlwarning("command 'services': unknown message named 'DEBUG:SERVICES'");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(mode, "Change the mode for an entity in a slot", "<Slot> <Mode> [dt(tick)]")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 2)
|
|
{
|
|
// Help
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("This command need 2 paramters :"));
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Slot> : the slot number of the entity to change"));
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Mode> : the mode wanted for the entity, one of the following number :"));
|
|
for(uint i = 0; i<MBEHAV::NUMBER_OF_MODES; ++i)
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d - %s", i, MBEHAV::modeToString((MBEHAV::EMode)i).c_str())));
|
|
}
|
|
// Right parameters number
|
|
else
|
|
{
|
|
// Compute parameters
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
MBEHAV::EMode mod = MBEHAV::stringToMode(args[1]);
|
|
if(mod==MBEHAV::UNKNOWN_MODE)
|
|
{
|
|
sint32 nMode;
|
|
fromString(args[1], nMode);
|
|
mod = (MBEHAV::EMode)nMode;
|
|
}
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
// Write the behaviour in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P" + toString(CLFECOMMON::PROPERTY_MODE), mod);
|
|
// Update the behaviour.
|
|
sint32 dt= 10;
|
|
if(args.size() > 2)
|
|
fromString(args[2], dt);
|
|
entity->updateVisualProperty(NetMngr.getCurrentServerTick()+dt, CLFECOMMON::PROPERTY_MODE);
|
|
}
|
|
// Invalid slot.
|
|
else
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("There is no entity in the given slot"));
|
|
}
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(behaviour, "Change the behaviour for an entity in a slot", "<Slot> <Behaviour> [<Attack Intensity>] [<Impact Intensity>] [<delta HP>] [dt(tick)]")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 2 || args.size() > 6)
|
|
{
|
|
// Help
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("This command need 2 to 6 paramters :"));
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Slot> : the slot number of the entity to change"));
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Behaviour> : the behaviour to play for the entity, one of the following number :"));
|
|
for(uint i = 0; i<MBEHAV::EMOTE_BEGIN; ++i)
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d - %s", i, MBEHAV::behaviourToString((MBEHAV::EBehaviour)i).c_str())));
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d-%d - Emotes", MBEHAV::EMOTE_BEGIN, MBEHAV::EMOTE_END)));
|
|
}
|
|
else
|
|
{
|
|
// Compute parameters
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
MBEHAV::EBehaviour beh = MBEHAV::stringToBehaviour(args[1]);
|
|
if(beh==MBEHAV::UNKNOWN_BEHAVIOUR)
|
|
{
|
|
sint32 temp;
|
|
fromString(args[1], temp);
|
|
beh= (MBEHAV::EBehaviour)temp;
|
|
}
|
|
|
|
// Make the behaviour
|
|
MBEHAV::CBehaviour behaviour(beh);
|
|
// Get the Power
|
|
if ( (beh == MBEHAV::PROSPECTING) || (beh == MBEHAV::PROSPECTING_END) )
|
|
{
|
|
if(args.size() > 2)
|
|
{
|
|
uint16 range;
|
|
fromString(args[2], range);
|
|
behaviour.ForageProspection.Range = range; // 0..127
|
|
}
|
|
if(args.size() > 3)
|
|
{
|
|
uint16 angle;
|
|
fromString(args[3], angle);
|
|
behaviour.ForageProspection.Angle = angle; // 0..3
|
|
}
|
|
if(args.size() > 4)
|
|
{
|
|
uint16 level;
|
|
fromString(args[4], level);
|
|
behaviour.ForageProspection.Level = level; // 0..4
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(args.size() > 2)
|
|
{
|
|
uint16 impactIntensity;
|
|
fromString(args[2], impactIntensity);
|
|
behaviour.Combat.ImpactIntensity = impactIntensity;
|
|
}
|
|
if(args.size() > 3)
|
|
{
|
|
uint16 impactIntensity;
|
|
fromString(args[3], impactIntensity);
|
|
behaviour.Combat.ImpactIntensity = impactIntensity;
|
|
}
|
|
if(args.size() > 4)
|
|
fromString(args[4], behaviour.DeltaHP);
|
|
}
|
|
// get the dt
|
|
sint32 dt= 10;
|
|
if(args.size() > 5)
|
|
fromString(args[5], dt);
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
// Write the behaviour in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P" + toString(CLFECOMMON::PROPERTY_BEHAVIOUR), behaviour);
|
|
// Update the behaviour.
|
|
entity->updateVisualProperty(NetMngr.getCurrentServerTick()+dt, CLFECOMMON::PROPERTY_BEHAVIOUR);
|
|
}
|
|
else
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("There is no entity in the given slot"));
|
|
}
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
NLMISC_COMMAND(magic, "Cast a spell", "\n"
|
|
"<Slot> : the one who cast the spell\n"
|
|
"<type> : 0->GOOD 1->Bad 2->NEUTRAL\n"
|
|
"<success> : 0->success 1->Fail 2->Fumble\n"
|
|
"<Spell Power> : \n"
|
|
"<Impact Intensity> : \n"
|
|
"<resist> : 0->not resisted, any other->resisted.\n")
|
|
{
|
|
CInterfaceManager *IM = CInterfaceManager::getInstance ();
|
|
|
|
// Check parameters.
|
|
if(args.size() != 6)
|
|
{
|
|
// Help
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring("This command need 2 or 3 paramters :"));
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Slot> : the slot number of the entity to change"));
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Behaviour> : the behaviour to play for the entity, one of the following number :"));
|
|
// for(uint i = 0; i<MBEHAV::EMOTE_BEGIN; ++i)
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d - %s", i, MBEHAV::behaviourToString((MBEHAV::EBehaviour)i))));
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d-%d - Emotes", MBEHAV::EMOTE_BEGIN, MBEHAV::EMOTE_END)));
|
|
}
|
|
else
|
|
{
|
|
// Compute parameters
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
// Magic Type (good bad neutral)
|
|
uint type;
|
|
fromString(args[1], type);
|
|
type %= 3;
|
|
MBEHAV::EBehaviour behTmp = (MBEHAV::EBehaviour)(MBEHAV::CASTING_GOOD+type);
|
|
MBEHAV::CBehaviour castingBeh(behTmp);
|
|
// Result
|
|
MBEHAV::CBehaviour behaviour;
|
|
uint result;
|
|
fromString(args[2], result);
|
|
result %= %3;
|
|
if (type==0)
|
|
behaviour.Behaviour = (MBEHAV::EBehaviour)(MBEHAV::END_CASTING_GOOD_SUCCESS + result);
|
|
else if(type==1)
|
|
behaviour.Behaviour = (MBEHAV::EBehaviour)(MBEHAV::END_CASTING_BAD_SUCCESS + result);
|
|
else
|
|
behaviour.Behaviour = (MBEHAV::EBehaviour)(MBEHAV::END_CASTING_NEUTRAL_SUCCESS + result);
|
|
uint16 spellPower, impactIntensity;
|
|
// Spell Power
|
|
fromString(args[3], spellPower);
|
|
behaviour.Magic.SpellPower = spellPower;
|
|
// Impact Intensity
|
|
fromString(args[4], impactIntensity);
|
|
behaviour.Magic.ImpactIntensity = impactIntensity;
|
|
// Resist
|
|
bool targetResists;
|
|
fromString(args[5], targetResists);
|
|
behaviour.Magic.TargetResists = targetResists;
|
|
// Get the entity
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
// Write the behaviour in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P" + toString(CLFECOMMON::PROPERTY_BEHAVIOUR), castingBeh);
|
|
// Update the behaviour.
|
|
entity->updateVisualProperty(NetMngr.getCurrentServerTick()+10, CLFECOMMON::PROPERTY_BEHAVIOUR);
|
|
// Write the behaviour in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P" + toString(CLFECOMMON::PROPERTY_BEHAVIOUR), behaviour);
|
|
// Update the behaviour.
|
|
entity->updateVisualProperty(NetMngr.getCurrentServerTick()+50, CLFECOMMON::PROPERTY_BEHAVIOUR);
|
|
}
|
|
else
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("There is no entity in the given slot"));
|
|
}
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
*/
|
|
NLMISC_COMMAND(spell, "Cast a spell", "\n"
|
|
"<Slot> : the one who cast the spell\n"
|
|
"<type> : 0->OFF 1->CUR 2->MIX\n"
|
|
"<success> : 0->Fail 1->Fumble 2->Success 3->Link\n"
|
|
"<Resist> : 0->Resist 1->Not Resist\n"
|
|
"<Spell Id> : \n"
|
|
"<Intensity> : [0, 5]\n")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 6)
|
|
{
|
|
// Help
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring("This command need 2 or 3 paramters :"));
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Slot> : the slot number of the entity to change"));
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(" <Behaviour> : the behaviour to play for the entity, one of the following number :"));
|
|
// for(uint i = 0; i<MBEHAV::EMOTE_BEGIN; ++i)
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d - %s", i, MBEHAV::behaviourToString((MBEHAV::EBehaviour)i))));
|
|
// CInterfaceManager::getInstance()->displaySystemInfo(ucstring(NLMISC::toString(" %d-%d - Emotes", MBEHAV::EMOTE_BEGIN, MBEHAV::EMOTE_END)));
|
|
}
|
|
else
|
|
{
|
|
// Compute parameters
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
// Magic Type (good bad neutral)
|
|
uint type;
|
|
fromString(args[1], type);
|
|
type %= 3;
|
|
MBEHAV::EBehaviour behTmp = (MBEHAV::EBehaviour)(MBEHAV::CAST_OFF+type);
|
|
MBEHAV::CBehaviour castingBeh(behTmp);
|
|
// Result
|
|
MBEHAV::CBehaviour behaviour;
|
|
uint result;
|
|
fromString(args[2], result);
|
|
result %= 4;
|
|
behaviour.Behaviour = (MBEHAV::EBehaviour)(MBEHAV::CAST_OFF_FAIL+type*4+result);
|
|
// Spell Power
|
|
uint16 spellMode;
|
|
fromString(args[3], spellMode);
|
|
behaviour.Spell.SpellMode = spellMode;
|
|
// Impact Intensity
|
|
uint16 spellId;
|
|
fromString(args[4], spellId);
|
|
behaviour.Spell.SpellId = spellId;
|
|
// Resist
|
|
uint16 spellIntensity;
|
|
fromString(args[5], spellIntensity);
|
|
behaviour.Spell.SpellIntensity = spellIntensity;
|
|
// Get the entity
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
uint64 beha = castingBeh;
|
|
sint64 beha2 = *((sint64 *)(&beha));
|
|
// Write the behaviour in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P" + toString(CLFECOMMON::PROPERTY_BEHAVIOUR), beha2);
|
|
// Update the behaviour.
|
|
entity->updateVisualProperty(NetMngr.getCurrentServerTick()+10, CLFECOMMON::PROPERTY_BEHAVIOUR);
|
|
beha = behaviour;
|
|
beha2 = *((sint64 *)(&beha));
|
|
// Write the behaviour in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P" + toString(CLFECOMMON::PROPERTY_BEHAVIOUR), beha2);
|
|
// Update the behaviour.
|
|
entity->updateVisualProperty(NetMngr.getCurrentServerTick()+50, CLFECOMMON::PROPERTY_BEHAVIOUR);
|
|
}
|
|
else
|
|
CInterfaceManager::getInstance()->displaySystemInfo(ucstring("There is no entity in the given slot"));
|
|
}
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(settarget, "Set a target for an entity. Do not set the target slot to remove the target", "<Slot> [<Target Slot>]")
|
|
{
|
|
CLFECOMMON::TCLEntityId targetSlot = CLFECOMMON::INVALID_SLOT;
|
|
|
|
// Check parameters.
|
|
switch(args.size())
|
|
{
|
|
// Set the target for the entity.
|
|
case 2:
|
|
fromString(args[1], targetSlot);
|
|
|
|
// Remove the target for the entity.
|
|
case 1:
|
|
{
|
|
uint entitySlot;
|
|
fromString(args[0], entitySlot);
|
|
CEntityCL *entity = EntitiesMngr.entity(entitySlot);
|
|
if(entity)
|
|
entity->targetSlot(targetSlot);
|
|
else
|
|
nlwarning("command 'settarget': there is no entity in the slot %d", entitySlot);
|
|
}
|
|
break;
|
|
|
|
// Bad command.
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
// Well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(particle, "Create a particule at the user position (play FireWorkA_with_sound.ps by default)", "[<filename.ps>]")
|
|
{
|
|
string fn;
|
|
|
|
// Check parameters.
|
|
if(args.size() == 0)
|
|
{
|
|
fn = "FireWorkA_with_sound.ps";
|
|
}
|
|
else if(args.size() == 1)
|
|
{
|
|
fn = args[0];
|
|
}
|
|
else
|
|
return false;
|
|
|
|
UInstance fx = Scene->createInstance(fn);
|
|
|
|
// not found
|
|
if(fx.empty())
|
|
{
|
|
log.displayNL ("Can't create instance '%s'", fn.c_str());
|
|
return false;
|
|
}
|
|
|
|
fx.setPos(UserEntity->pos());
|
|
fx.setClusterSystem(UserEntity->skeleton()->getClusterSystem());
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(move, "Move an entity", "Slot: [1-254]")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 1)
|
|
return false;
|
|
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
sint64 x = (sint64)((entity->pos().x+UserEntity->front().x*10.0)*1000.0);
|
|
sint64 y = (sint64)((entity->pos().y+UserEntity->front().y*10.0)*1000.0);
|
|
sint64 z = (sint64)((entity->pos().z+UserEntity->front().z*10.0)*1000.0);
|
|
// Write the position in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P0", x);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P1", y);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P2", z);
|
|
// Update the position.
|
|
EntitiesMngr.updateVisualProperty(NetMngr.getCurrentServerTick()+30, slot, 0);
|
|
|
|
x = (sint64)((entity->pos().x)*1000.0);
|
|
y = (sint64)((entity->pos().y)*1000.0);
|
|
z = (sint64)((entity->pos().z)*1000.0);
|
|
// Write the position in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P0", x);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P1", y);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P2", z);
|
|
// Update the position.
|
|
EntitiesMngr.updateVisualProperty(NetMngr.getCurrentServerTick()+60, slot, 0);
|
|
}
|
|
else
|
|
nlwarning("command 'move' : there is no entity allocated in slot %d", slot);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(moveRel, "Move an entity, specifying delta pos from current", "Slot: [1-254] dx(m) dy(m) [dt(tick)] [predictedIV(tick)]")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() <3)
|
|
return false;
|
|
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
float dx, dy;
|
|
fromString(args[1], dx);
|
|
fromString(args[2], dy);
|
|
sint32 dt= 10;
|
|
if(args.size()>=4)
|
|
fromString(args[3], dt);
|
|
sint32 pi= 0;
|
|
if(args.size()>=5)
|
|
fromString(args[4], pi);
|
|
sint64 x = (sint64)((entity->pos().x+dx)*1000.0);
|
|
sint64 y = (sint64)((entity->pos().y+dy)*1000.0);
|
|
sint64 z = (sint64)((entity->pos().z+0)*1000.0);
|
|
// Write the position in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P0", x);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P1", y);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P2", z);
|
|
// Update the position.
|
|
EntitiesMngr.updateVisualProperty(NetMngr.getCurrentServerTick()+dt, slot, 0, pi);
|
|
}
|
|
else
|
|
nlwarning("command 'move' : there is no entity allocated in slot %d", slot);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(orient, "Orient an entity", "Slot: [1-254] orient(degree) [dt(tick)]")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 2)
|
|
return false;
|
|
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
sint32 rot;
|
|
fromString(args[1], rot);
|
|
sint32 dt= 10;
|
|
if(args.size()> 2)
|
|
fromString(args[2], dt);
|
|
// Write the position in the DB.
|
|
float fRot= (float)(rot*Pi/180.f);
|
|
uint64 val= *(uint32*)(&fRot);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P"+toString(CLFECOMMON::PROPERTY_ORIENTATION), val);
|
|
// Update the position.
|
|
EntitiesMngr.updateVisualProperty(NetMngr.getCurrentServerTick()+dt, slot, CLFECOMMON::PROPERTY_ORIENTATION);
|
|
}
|
|
else
|
|
nlwarning("command 'move' : there is no entity allocated in slot %d", slot);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(moveTo, "Move an entity to another one", "<slot(from)>:[1-254], <slot(to)>:[0-254] default 0")
|
|
{
|
|
sint64 x, y, z;
|
|
|
|
// Check parameters.
|
|
if(args.size() == 1)
|
|
{
|
|
x = (sint64)(UserEntity->pos().x*1000.0);
|
|
y = (sint64)(UserEntity->pos().y*1000.0);
|
|
z = (sint64)(UserEntity->pos().z*1000.0);
|
|
}
|
|
else if(args.size() == 2)
|
|
{
|
|
CLFECOMMON::TCLEntityId slotDest;
|
|
fromString(args[1], slotDest);
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slotDest);
|
|
if(entity)
|
|
{
|
|
x = (sint64)(entity->pos().x*1000.0);
|
|
y = (sint64)(entity->pos().y*1000.0);
|
|
z = (sint64)(entity->pos().z*1000.0);
|
|
}
|
|
else
|
|
{
|
|
// Command is correct but not all the parameters are valid.
|
|
nlwarning("command 'move_to' : there is no entity allocated for the dest in slot %d", slotDest);
|
|
return true;
|
|
}
|
|
}
|
|
// Wrong number of parameters.
|
|
else
|
|
return false;
|
|
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
// Write the position in the DB.
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P0", x);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P1", y);
|
|
IngameDbMngr.setProp("Entities:E" + toString(slot) + ":P2", z);
|
|
// Update the position.
|
|
EntitiesMngr.updateVisualProperty(NetMngr.getCurrentServerTick()+30, slot, 0);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(setMode, "Set The Mode for an Entity without to add a stage for it", "<slot> <mode>")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 2)
|
|
return false;
|
|
|
|
// Get the Slot and the Mode.
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
sint32 nMode;
|
|
fromString(args[1], nMode);
|
|
MBEHAV::EMode mod = (MBEHAV::EMode)nMode;
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
entity->mode(mod);
|
|
else
|
|
nlwarning("command 'setMode' : there is no entity allocated in slot '%d'", slot);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
NLMISC_COMMAND(paintTarget, "Modify the target color",
|
|
"\n"
|
|
"<color> color for the target (0-7)\n")
|
|
{
|
|
// Check parameters
|
|
if(args.size() != 1)
|
|
return false;
|
|
// Get the entity slot
|
|
CLFECOMMON::TCLEntityId slot = UserEntity->selection();
|
|
if(slot == CLFECOMMON::INVALID_SLOT)
|
|
return true;
|
|
//
|
|
SPropVisualA vA;
|
|
SPropVisualB vB;
|
|
SPropVisualC vC;
|
|
const string propNameA = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPA);
|
|
const string propNameB = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPB);
|
|
const string propNameC = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPC);
|
|
vA.PropertyA = CInterfaceManager::getInstance()->getDbProp(propNameA)->getValue64();
|
|
vB.PropertyB = CInterfaceManager::getInstance()->getDbProp(propNameB)->getValue64();
|
|
vC.PropertyC = CInterfaceManager::getInstance()->getDbProp(propNameC)->getValue64();
|
|
|
|
// Get the visual item index
|
|
uint value;
|
|
fromString(args[0], value);
|
|
// Change color
|
|
vA.PropertySubData.JacketColor = value;
|
|
vA.PropertySubData.TrouserColor = value;
|
|
vA.PropertySubData.ArmColor = value;
|
|
vA.PropertySubData.HatColor = value;
|
|
vB.PropertySubData.HandsColor = value;
|
|
vB.PropertySubData.FeetColor = value;
|
|
|
|
// Set the database.
|
|
CInterfaceManager::getInstance()->getDbProp(propNameA)->setValue64((sint64)vA.PropertyA);
|
|
CInterfaceManager::getInstance()->getDbProp(propNameB)->setValue64((sint64)vB.PropertyB);
|
|
CInterfaceManager::getInstance()->getDbProp(propNameC)->setValue64((sint64)vC.PropertyC);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_VPA);
|
|
|
|
// Done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(playAnim, "Try to play the animation to the target", "<anim name>")
|
|
{
|
|
// Check parameters
|
|
if(args.size() != 1)
|
|
return false;
|
|
|
|
CLFECOMMON::TCLEntityId slot = UserEntity->selection();
|
|
if(slot == CLFECOMMON::INVALID_SLOT)
|
|
return true;
|
|
if(EAM == 0)
|
|
return true;
|
|
NL3D::UAnimationSet *animset = EAM->getAnimationSet();
|
|
if(animset == 0)
|
|
return true;
|
|
uint animId = animset->getAnimationIdByName(args[0]);
|
|
if(animId == UAnimationSet::NotFound)
|
|
{
|
|
nlwarning("anim not found %s", args[0].c_str());
|
|
return true;
|
|
}
|
|
CEntityCL *selection = EntitiesMngr.entity(slot);
|
|
CCharacterCL *character = dynamic_cast<CCharacterCL *>(selection);
|
|
if(character)
|
|
character->setAnim(CAnimationStateSheet::Idle, (TAnimStateKey)CAnimation::UnknownAnim, animId);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(vP, "Modify the Visual Property",
|
|
"\n"
|
|
"<slot> of the entity to change.\n"
|
|
"<type> the property to change :\n"
|
|
" 0->CHEST (0~511)\n"
|
|
" 1->LEG (0~255)\n"
|
|
" 2->ARM (0~255)\n"
|
|
" 3->HEAD (0~127)\n"
|
|
" 4->WEAPON_R (0~2047)\n"
|
|
" 5->WEAPON_L (0~255)\n"
|
|
" 6->FEET (0~511)\n"
|
|
" 7->HAND (0~511)\n"
|
|
" 8->EYES COLOR (0~7)\n"
|
|
" 9->SEX (0: Male, 1: Female)\n"
|
|
" 10->TATOO (0~31)\n"
|
|
" 11->CHEST COLOR (0~7)\n"
|
|
" 12->LEG COLOR (0~7)\n"
|
|
" 13->ARM COLOR (0~7)\n"
|
|
" 14->HAIR COLOR (0~7)\n"
|
|
" 15->HAND COLOR (0~7)\n"
|
|
" 16->FEET COLOR (0~7)\n"
|
|
" 17->MORPH 1 (0~7)\n"
|
|
" 18->MORPH 2 (0~7)\n"
|
|
" 19->MORPH 3 (0~7)\n"
|
|
" 20->MORPH 4 (0~7)\n"
|
|
" 21->MORPH 5 (0~7)\n"
|
|
" 22->MORPH 6 (0~7)\n"
|
|
" 23->MORPH 7 (0~7)\n"
|
|
" 24->CHARACTER HEIGHT (0~15)\n"
|
|
" 25->TORSO WIDTH (0~15)\n"
|
|
" 26->ARMS WIDTH (0~15)\n"
|
|
" 27->LEGS WIDTH (0~15)\n"
|
|
" 28->BREASTS SIZE (0~15)\n"
|
|
"<value> for the property.\n")
|
|
{
|
|
// Check parameters
|
|
if(args.size() != 3)
|
|
return false;
|
|
|
|
// Get the database entry.
|
|
SPropVisualA vA;
|
|
SPropVisualB vB;
|
|
SPropVisualC vC;
|
|
uint slot;
|
|
fromString(args[0], slot);
|
|
const string propNameA = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPA);
|
|
const string propNameB = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPB);
|
|
const string propNameC = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPC);
|
|
vA.PropertyA = CInterfaceManager::getInstance()->getDbProp(propNameA)->getValue64();
|
|
vB.PropertyB = CInterfaceManager::getInstance()->getDbProp(propNameB)->getValue64();
|
|
vC.PropertyC = CInterfaceManager::getInstance()->getDbProp(propNameC)->getValue64();
|
|
// Get the visual item index
|
|
uint value;
|
|
fromString(args[2], value);
|
|
// Get the visual slot to change.
|
|
uint type;
|
|
fromString(args[1], type);
|
|
// if .sitem visual slot, try translate .sitem to VSIndex
|
|
if(type<=7)
|
|
{
|
|
SLOTTYPE::EVisualSlot vslot= SLOTTYPE::HIDDEN_SLOT;
|
|
switch(type)
|
|
{
|
|
case 0: vslot= SLOTTYPE::CHEST_SLOT; break;
|
|
case 1: vslot= SLOTTYPE::LEGS_SLOT; break;
|
|
case 2: vslot= SLOTTYPE::ARMS_SLOT; break;
|
|
case 3: vslot= SLOTTYPE::HEAD_SLOT; break;
|
|
case 4: vslot= SLOTTYPE::RIGHT_HAND_SLOT; break;
|
|
case 5: vslot= SLOTTYPE::LEFT_HAND_SLOT; break;
|
|
case 6: vslot= SLOTTYPE::FEET_SLOT; break;
|
|
case 7: vslot= SLOTTYPE::HANDS_SLOT; break;
|
|
default: break;
|
|
}
|
|
if(vslot!=SLOTTYPE::HIDDEN_SLOT && value==0)
|
|
{
|
|
sint vsIndex= SheetMngr.getVSIndex(args[2], vslot);
|
|
// succed!
|
|
if(vsIndex!=-1)
|
|
value= vsIndex;
|
|
}
|
|
}
|
|
// setup
|
|
switch(type)
|
|
{
|
|
case 0:
|
|
vA.PropertySubData.JacketModel = value;
|
|
break;
|
|
case 1:
|
|
vA.PropertySubData.TrouserModel = value;
|
|
break;
|
|
case 2:
|
|
vA.PropertySubData.ArmModel = value;
|
|
break;
|
|
case 3:
|
|
vA.PropertySubData.HatModel = value;
|
|
break;
|
|
case 4:
|
|
vA.PropertySubData.WeaponRightHand = value;
|
|
break;
|
|
case 5:
|
|
vA.PropertySubData.WeaponLeftHand = value;
|
|
break;
|
|
case 6:
|
|
vB.PropertySubData.FeetModel = value;
|
|
break;
|
|
case 7:
|
|
vB.PropertySubData.HandsModel = value;
|
|
break;
|
|
case 8:
|
|
vC.PropertySubData.EyesColor = value;
|
|
break;
|
|
case 9:
|
|
vA.PropertySubData.Sex = value;
|
|
break;
|
|
case 10:
|
|
vC.PropertySubData.Tattoo = value;
|
|
break;
|
|
case 11:
|
|
vA.PropertySubData.JacketColor = value;
|
|
break;
|
|
case 12:
|
|
vA.PropertySubData.TrouserColor = value;
|
|
break;
|
|
case 13:
|
|
vA.PropertySubData.ArmColor = value;
|
|
break;
|
|
case 14:
|
|
vA.PropertySubData.HatColor = value;
|
|
break;
|
|
case 15:
|
|
vB.PropertySubData.HandsColor = value;
|
|
break;
|
|
case 16:
|
|
vB.PropertySubData.FeetColor = value;
|
|
break;
|
|
case 17:
|
|
vC.PropertySubData.MorphTarget1 = value;
|
|
break;
|
|
case 18:
|
|
vC.PropertySubData.MorphTarget2 = value;
|
|
break;
|
|
case 19:
|
|
vC.PropertySubData.MorphTarget3 = value;
|
|
break;
|
|
case 20:
|
|
vC.PropertySubData.MorphTarget4 = value;
|
|
break;
|
|
case 21:
|
|
vC.PropertySubData.MorphTarget5 = value;
|
|
break;
|
|
case 22:
|
|
vC.PropertySubData.MorphTarget6 = value;
|
|
break;
|
|
case 23:
|
|
vC.PropertySubData.MorphTarget7 = value;
|
|
break;
|
|
case 24:
|
|
vC.PropertySubData.CharacterHeight = value;
|
|
break;
|
|
case 25:
|
|
vC.PropertySubData.TorsoWidth = value;
|
|
break;
|
|
case 26:
|
|
vC.PropertySubData.ArmsWidth = value;
|
|
break;
|
|
case 27:
|
|
vC.PropertySubData.LegsWidth = value;
|
|
break;
|
|
case 28:
|
|
vC.PropertySubData.BreastSize = value;
|
|
break;
|
|
|
|
default:
|
|
nlwarning("command 'vP': type not valid");
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
// Set the database.
|
|
CInterfaceManager::getInstance()->getDbProp(propNameA)->setValue64((sint64)vA.PropertyA);
|
|
CInterfaceManager::getInstance()->getDbProp(propNameB)->setValue64((sint64)vB.PropertyB);
|
|
CInterfaceManager::getInstance()->getDbProp(propNameC)->setValue64((sint64)vC.PropertyC);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_VPA);
|
|
|
|
// Done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(altLook, "Modify the Alternative Look Property",
|
|
"\n"
|
|
"<slot> of the entity to change.\n"
|
|
"<colorTop>\n"
|
|
"<colorBottom>\n"
|
|
"<rWeapon>\n"
|
|
"<lWeapon>\n"
|
|
"<seed>\n"
|
|
"<hairColor>\n"
|
|
"<putHelm>\n"
|
|
"[<colorGlove>]\n"
|
|
"[<colorBoot>]\n"
|
|
"[<colorArm>]\n")
|
|
{
|
|
// Check parameters
|
|
if(args.size() < 8 || args.size() > 11)
|
|
return false;
|
|
|
|
// Get the database entry.
|
|
uint slot;
|
|
fromString(args[0], slot);
|
|
const string propName = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_VPA);
|
|
// Get the old value (not useful since we change the whole property).
|
|
SAltLookProp altLookProp;
|
|
altLookProp.Summary = CInterfaceManager::getInstance()->getDbProp(propName)->getValue64();
|
|
uint32 colorTop, colorBot, weaponRightHand, weaponLeftHand, seed, colorHair, hat;
|
|
fromString(args[1], colorTop);
|
|
fromString(args[2], colorBot);
|
|
fromString(args[3], weaponRightHand);
|
|
fromString(args[4], weaponLeftHand);
|
|
fromString(args[5], seed);
|
|
fromString(args[6], colorHair);
|
|
fromString(args[7], hat);
|
|
altLookProp.Element.ColorTop = colorTop;
|
|
altLookProp.Element.ColorBot = colorBot;
|
|
altLookProp.Element.WeaponRightHand = weaponRightHand;
|
|
altLookProp.Element.WeaponLeftHand = weaponLeftHand;
|
|
altLookProp.Element.Seed = seed;
|
|
altLookProp.Element.ColorHair = colorHair;
|
|
altLookProp.Element.Hat = hat;
|
|
// New colours
|
|
if(args.size() == 11)
|
|
{
|
|
uint32 colorGlove, colorBoot, colorArm;
|
|
fromString(args[8], colorGlove);
|
|
fromString(args[9], colorBoot);
|
|
fromString(args[10], colorArm);
|
|
altLookProp.Element.ColorGlove = colorGlove;
|
|
altLookProp.Element.ColorBoot = colorBoot;
|
|
altLookProp.Element.ColorArm = colorArm;
|
|
}
|
|
// Old Colours
|
|
else
|
|
{
|
|
altLookProp.Element.ColorGlove = altLookProp.Element.ColorTop;
|
|
altLookProp.Element.ColorArm = altLookProp.Element.ColorTop;
|
|
altLookProp.Element.ColorBoot = altLookProp.Element.ColorBot;
|
|
}
|
|
|
|
// Set the database.
|
|
CInterfaceManager::getInstance()->getDbProp(propName)->setValue64((sint64)altLookProp.Summary);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_VPA);
|
|
|
|
// Done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(color, "Command to color an entity",
|
|
"\n"
|
|
"<Slot>: whole number (if <0 slot will be the current selection)\n"
|
|
"<UserColor>: whole number\n"
|
|
"<Hair>: whole number\n"
|
|
"<Eyes>: whole number\n"
|
|
"[<Part>]: whole number\n"
|
|
" default=the whole body\n"
|
|
" 0=CHEST\n"
|
|
" 1=LEG\n"
|
|
" 2=HEAD\n"
|
|
" 3=ARMS\n"
|
|
" 4=HANDS\n"
|
|
" 5=FEET\n")
|
|
{
|
|
// Check parameters.
|
|
if(args.size() != 4 && args.size() != 5)
|
|
return false;
|
|
|
|
// Witch part to dye ?
|
|
sint part = -1;
|
|
if(args.size() == 5)
|
|
fromString(args[4], part);
|
|
|
|
// Get the entity slot to dye.
|
|
sint slotTmp;
|
|
fromString(args[0], slotTmp);
|
|
CLFECOMMON::TCLEntityId slot;
|
|
if(slotTmp >= 0)
|
|
slot = (CLFECOMMON::TCLEntityId)slotTmp;
|
|
else
|
|
slot = (CLFECOMMON::TCLEntityId)UserEntity->selection();
|
|
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(entity)
|
|
{
|
|
sint color, hair, eyes;
|
|
fromString(args[1], color);
|
|
fromString(args[2], hair);
|
|
fromString(args[3], eyes);
|
|
entity->changeColors(color, hair, eyes, part);
|
|
}
|
|
else
|
|
nlwarning("command 'changeColors': there is no entity allocated in slot '%d'", slot);
|
|
|
|
// Command well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(saveIntCfg, "save the interface config file","")
|
|
{
|
|
CInterfaceManager::getInstance()->saveConfig ("save/interface.icfg");
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(loadIntCfg, "load the interface config file","")
|
|
{
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->loadConfig ("save/interface.icfg");
|
|
// reset the compass target
|
|
CGroupCompas *gc = dynamic_cast<CGroupCompas *>(im->getElementFromId("ui:interface:compass"));
|
|
if (gc && gc->isSavedTargetValid())
|
|
{
|
|
gc->setTarget(gc->getSavedTarget());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(harvestDeposit, "harvest a deposit", "")
|
|
{
|
|
// no parameter needed
|
|
|
|
// Create the message for the server
|
|
/* CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("HARVEST:DEPOSIT", out))
|
|
{
|
|
uint16 skill = SKILLS::digging;
|
|
|
|
out.serial(skill);
|
|
|
|
NetMngr.push(out);
|
|
|
|
// open the interface
|
|
// CInterfaceManager::getInstance()->getWindowFromId("ui:interface:harvest")->setActive(true);
|
|
}
|
|
else
|
|
nlwarning("command : unknown message name : 'HARVEST:DEPOSIT'");
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(training, "start a training action", "")
|
|
{
|
|
// no parameter needed
|
|
|
|
// Create the message for the server
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("TRAINING", out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("command : unknown message name : 'TRAINING'");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(testMount, "Set the entity to mount","<Slot> <Mount>")
|
|
{
|
|
CLFECOMMON::TCLEntityId slot;
|
|
CLFECOMMON::TCLEntityId mount = CLFECOMMON::INVALID_SLOT;
|
|
|
|
switch(args.size())
|
|
{
|
|
case 2:
|
|
fromString(args[1], mount);
|
|
case 1:
|
|
fromString(args[0], slot);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
// Set the database.
|
|
string propName = toString("SERVER:Entities:E%d:P%d", mount, CLFECOMMON::PROPERTY_RIDER_ENTITY_ID);
|
|
CInterfaceManager::getInstance()->getDbProp(propName)->setValue64(slot);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, mount, CLFECOMMON::PROPERTY_RIDER_ENTITY_ID);
|
|
// Set the database.
|
|
propName = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID);
|
|
CInterfaceManager::getInstance()->getDbProp(propName)->setValue64(mount);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(mount, "Set the entity to mount","<Slot> [<Mount>]")
|
|
{
|
|
CLFECOMMON::TCLEntityId slot;
|
|
CLFECOMMON::TCLEntityId mount = CLFECOMMON::INVALID_SLOT;
|
|
|
|
switch(args.size())
|
|
{
|
|
case 2:
|
|
fromString(args[1], mount);
|
|
case 1:
|
|
fromString(args[0], slot);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
// Set the database.
|
|
string propName = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID);
|
|
CInterfaceManager::getInstance()->getDbProp(propName)->setValue64(mount);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID);
|
|
|
|
// Command well done
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(rider, "Set the rider","<Slot> [<rider>]")
|
|
{
|
|
CLFECOMMON::TCLEntityId slot;
|
|
CLFECOMMON::TCLEntityId rider = CLFECOMMON::INVALID_SLOT;
|
|
|
|
switch(args.size())
|
|
{
|
|
case 2:
|
|
fromString(args[1], rider);
|
|
case 1:
|
|
fromString(args[0], slot);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
// Set the database.
|
|
string propName = toString("SERVER:Entities:E%d:P%d", slot, CLFECOMMON::PROPERTY_RIDER_ENTITY_ID);
|
|
CInterfaceManager::getInstance()->getDbProp(propName)->setValue64(rider);
|
|
// Force to update properties.
|
|
EntitiesMngr.updateVisualProperty(0, slot, CLFECOMMON::PROPERTY_RIDER_ENTITY_ID);
|
|
|
|
// Command well done
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(disbandConvoy, "disband current beasts convoy", "")
|
|
{
|
|
// no parameter needed
|
|
|
|
// Create the message for the server
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("ANIMALS:DISBAND_CONVOY", out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
else
|
|
nlwarning("command : unknown message name : 'ANIMALS:DISBAND_CONVOY'");
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(learnAllBrick, "learn all bricks (only in local mode)", "")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
uint i=0;
|
|
for(;;)
|
|
{
|
|
CCDBNodeLeaf * node= pIM->getDbProp(toString("SERVER:BRICK_FAMILY:%d:BRICKS", i), false);
|
|
if(node)
|
|
node->setValue64(SINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
|
|
else
|
|
break;
|
|
i++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(learnBrick, "learn a specified brick (only in local mode)", "<brick number or name>")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
CSBrickManager *pBM= CSBrickManager::getInstance();
|
|
|
|
if(args.size()<1)
|
|
return false;
|
|
|
|
// translate to brick sheet id
|
|
CSheetId brickSheetId;
|
|
uint testId;
|
|
fromString(args[0], testId);
|
|
if(testId!=0)
|
|
{
|
|
brickSheetId= CSheetId(testId);
|
|
}
|
|
else
|
|
{
|
|
string str= args[0];
|
|
if(str.find(".sbrick")==string::npos)
|
|
str+= ".sbrick";
|
|
brickSheetId.buildSheetId(str);
|
|
}
|
|
|
|
// get the brick sheet
|
|
CSBrickSheet *brick= pBM->getBrick(brickSheetId);
|
|
if(!brick)
|
|
{
|
|
pIM->displaySystemInfo(toString("brick '%s' not found", args[0].c_str()));
|
|
return false;
|
|
}
|
|
|
|
// force learn it.
|
|
CCDBNodeLeaf * node= pBM->getKnownBrickBitFieldDB(brick->BrickFamily);
|
|
if(node)
|
|
{
|
|
uint64 flags= node->getValue64();
|
|
flags|= uint64(1)<<(brick->IndexInFamily-1);
|
|
node->setValue64(flags);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(learnPhrase, "learn all bricks of a specified phrase (only in local mode)", "<phrase sheetId or name>")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
CSBrickManager *pBM= CSBrickManager::getInstance();
|
|
CSPhraseManager *pPM= CSPhraseManager::getInstance();
|
|
|
|
if(args.size()<1)
|
|
return false;
|
|
|
|
// translate to brick sheet id
|
|
CSheetId phraseSheetId;
|
|
uint testId;
|
|
fromString(args[0], testId);
|
|
if(testId!=0)
|
|
{
|
|
phraseSheetId= CSheetId(testId);
|
|
}
|
|
else
|
|
{
|
|
string str= args[0];
|
|
if(str.find(".sphrase")==string::npos)
|
|
str+= ".sphrase";
|
|
phraseSheetId.buildSheetId(str);
|
|
}
|
|
|
|
// get the brick sheet
|
|
CSPhraseCom phrase;
|
|
pPM->buildPhraseFromSheet(phrase, phraseSheetId.asInt());
|
|
if(phrase.empty())
|
|
{
|
|
pIM->displaySystemInfo(toString("phrase '%s' not found", args[0].c_str()));
|
|
return false;
|
|
}
|
|
|
|
// For all bricks of this phrase
|
|
for(uint i=0;i<phrase.Bricks.size();i++)
|
|
{
|
|
CSBrickSheet *brick= pBM->getBrick(phrase.Bricks[i]);
|
|
if(brick)
|
|
{
|
|
// force learn it.
|
|
CCDBNodeLeaf * node= pBM->getKnownBrickBitFieldDB(brick->BrickFamily);
|
|
if(node)
|
|
{
|
|
uint64 flags= node->getValue64();
|
|
flags|= uint64(1)<<(brick->IndexInFamily-1);
|
|
node->setValue64(flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*NLMISC_COMMAND(xp, "To gain XP in a given Skill","<Amount Xp> <Skill> [<Speciality>]")
|
|
{
|
|
// Check parameters.
|
|
if( args.size() < 2 || args.size() > 3 )
|
|
return false;
|
|
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream("CHEAT:XP", out))
|
|
{
|
|
uint32 xp;
|
|
fromString(args[0], xp);
|
|
string skill = args[1];
|
|
string speciality;
|
|
if( args.size() == 3 )
|
|
speciality = args[2];
|
|
out.serial( xp );
|
|
out.serial( skill );
|
|
out.serial( speciality );
|
|
// Add the message to the send list.
|
|
NetMngr.push(out);
|
|
// send CHEAT:XP
|
|
nlinfo("command 'xp': CHEAT:XP pushed");
|
|
}
|
|
else
|
|
nlwarning("command 'xp': unknown message named 'CHEAT:XP'");
|
|
|
|
// Done.
|
|
return true;
|
|
}*/
|
|
|
|
NLMISC_COMMAND(money, "To earn Money (only in local mode)","<very big seed> [<big seed>] [<medium seed>] [<small seed>]")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
uint64 money;
|
|
fromString(args[0], money);
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->getDbProp("SERVER:INVENTORY:MONEY")->setValue64(money);
|
|
return true;
|
|
/*
|
|
sint32 a = 0;
|
|
sint32 b = 0;
|
|
sint32 c = 0;
|
|
sint32 d = 0;
|
|
|
|
// Check parameters.
|
|
switch(args.size())
|
|
{
|
|
case 4:
|
|
fromString(args[3], d);
|
|
case 3:
|
|
fromString(args[2], c);
|
|
case 2:
|
|
fromString(args[1], b);
|
|
case 1:
|
|
fromString(args[0], a);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
string ls = im->getDefine("money_1");
|
|
string ms = im->getDefine("money_2");
|
|
string bs = im->getDefine("money_3");
|
|
string vbs = im->getDefine("money_4");
|
|
im->getDbProp(ls + ":QUANTITY")->setValue32(a);
|
|
im->getDbProp(ms + ":QUANTITY")->setValue32(b);
|
|
im->getDbProp(bs + ":QUANTITY")->setValue32(c);
|
|
im->getDbProp(vbs + ":QUANTITY")->setValue32(d);
|
|
return true;
|
|
*/
|
|
}
|
|
/*
|
|
NLMISC_COMMAND( createPerso, "create a new character", "Parameters:\n-Character name\n-Race( Fyros, Tryker...)\n-gender(Male, Female)\n-Role( MeleeFighter, RangeFighter, AttackCaster, BufferCaster, HealerCaster...)\n-Level (1-25 (but more accepted)>" )
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 5) return false;
|
|
|
|
// read params
|
|
string characterName = args[0];
|
|
EGSPD::CPeople::TPeople race = EGSPD::CPeople::fromString( args[1] );
|
|
if( race == EGSPD::CPeople::EndPeople ) return false;
|
|
|
|
GSGENDER::EGender gender = GSGENDER::stringToEnum( args[2] );
|
|
if( gender == GSGENDER::unknown ) return false;
|
|
|
|
ROLES::ERole role = ROLES::toRoleId( args[3] );
|
|
if( role == ROLES::role_unknown ) return false;
|
|
|
|
uint16 level;
|
|
fromString(args[4], level);
|
|
|
|
CBitMemStream bms;
|
|
string msgType = "CHEAT:CREATE_CHARACTER";
|
|
if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) )
|
|
{
|
|
bms.serial( characterName );
|
|
bms.serialEnum( race );
|
|
bms.serialEnum( gender );
|
|
bms.serialEnum( role );
|
|
bms.serial( level );
|
|
NetMngr.push( bms );
|
|
nldebug("<create_perso> sending 'CHEAT:CREATE_CHARACTER' message to server");
|
|
}
|
|
else
|
|
{
|
|
nlwarning("<create_perso> unknown message name : CHEAT:CREATE_CHARACTER");
|
|
}
|
|
return true;
|
|
}
|
|
*/
|
|
/*
|
|
NLMISC_COMMAND( add_role, "add role to character", "<Role( MeleeFighter, RangeFighter, AttackCaster, BufferCaster, HealerCaster...), Level (1-25 (but more accepted))>" )
|
|
{
|
|
// Check parameters.
|
|
if(args.size() < 2) return false;
|
|
|
|
ROLES::ERole role = ROLES::toRoleId( args[0] );
|
|
if( role == ROLES::role_unknown ) return false;
|
|
|
|
uint16 level;
|
|
fromString(args[1], level);
|
|
|
|
CBitMemStream bms;
|
|
string msgType = "CHEAT:ADD_ROLE";
|
|
if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) )
|
|
{
|
|
bms.serialEnum( role );
|
|
bms.serial( level );
|
|
NetMngr.push( bms );
|
|
nldebug("<add_role> sending 'CHEAT:ADD_ROLE' message to server");
|
|
}
|
|
else
|
|
{
|
|
nlwarning("<add_role> unknown message name : CHEAT:ADD_ROLE");
|
|
}
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
NLMISC_COMMAND(test, "", "")
|
|
{
|
|
sint64 x, y, z;
|
|
CLFECOMMON::TCLEntityId entSlot = UserEntity->selection();
|
|
CEntityCL *entPtr = EntitiesMngr.entity(entSlot);
|
|
if(entPtr)
|
|
{
|
|
if(entPtr->skeleton())
|
|
{
|
|
if(entPtr->skeleton()->getLastClippedState())
|
|
{
|
|
NLMISC::CMatrix mat = entPtr->skeleton()->getLastWorldMatrixComputed();
|
|
NLMISC::CVectorD newPos = entPtr->pos() + mat.getJ()*0.5f;
|
|
x = (sint64)(newPos.x*1000.0);
|
|
y = (sint64)(newPos.y*1000.0);
|
|
z = (sint64)(newPos.z*1000.0);
|
|
IngameDbMngr.setProp("Entities:E" + toString("%d", entSlot) + ":P" + toString("%d", CLFECOMMON::PROPERTY_POSX), x);
|
|
IngameDbMngr.setProp("Entities:E" + toString("%d", entSlot) + ":P" + toString("%d", CLFECOMMON::PROPERTY_POSY), y);
|
|
IngameDbMngr.setProp("Entities:E" + toString("%d", entSlot) + ":P" + toString("%d", CLFECOMMON::PROPERTY_POSZ), z);
|
|
entPtr->updateVisualProperty(NetMngr.getCurrentServerTick(), CLFECOMMON::PROPERTY_POSITION);
|
|
|
|
x = (sint64)(entPtr->pos().x*1000.0);
|
|
y = (sint64)(entPtr->pos().y*1000.0);
|
|
z = (sint64)(entPtr->pos().z*1000.0);
|
|
IngameDbMngr.setProp("Entities:E" + toString("%d", entSlot) + ":P" + toString("%d", CLFECOMMON::PROPERTY_POSX), x);
|
|
IngameDbMngr.setProp("Entities:E" + toString("%d", entSlot) + ":P" + toString("%d", CLFECOMMON::PROPERTY_POSY), y);
|
|
IngameDbMngr.setProp("Entities:E" + toString("%d", entSlot) + ":P" + toString("%d", CLFECOMMON::PROPERTY_POSZ), z);
|
|
entPtr->updateVisualProperty(NetMngr.getCurrentServerTick()+5, CLFECOMMON::PROPERTY_POSITION);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
/// Macro to set the new dist to front(back or side) for a given sheet.
|
|
/// commandName : Name of the command.
|
|
/// variableName : Variable Name to change.
|
|
//-----------------------------------------------
|
|
#define DIST_TO_COMMAND(commandName, variableName) \
|
|
/* Check Parameters */ \
|
|
if(args.size() != 2) \
|
|
{ \
|
|
nlwarning("Command '" #commandName "': need 2 parameters, try '/help " #commandName "' for more details."); \
|
|
return false; \
|
|
} \
|
|
\
|
|
/* Try to create the sheet with the parameter as a string. */ \
|
|
CSheetId sheetId; \
|
|
if(!sheetId.buildSheetId(args[0])) \
|
|
{ \
|
|
/* Try to create the sheet with the parameter as an int. */ \
|
|
uint32 nSheetId; \
|
|
fromString(args[0], nSheetId); \
|
|
sheetId = CSheetId(nSheetId); \
|
|
if(sheetId == CSheetId::Unknown) \
|
|
{ \
|
|
nlwarning("Command '" #commandName "': '%s' is not a valid form.", args[0].c_str()); \
|
|
return false; \
|
|
} \
|
|
} \
|
|
\
|
|
/* Get the new distance. */ \
|
|
float dist; \
|
|
fromString(args[1], dist); \
|
|
if(dist < 0) \
|
|
{ \
|
|
nlwarning("Command '" #commandName "': distance < 0, this is not good."); \
|
|
return false; \
|
|
} \
|
|
\
|
|
CCharacterSheet *ch = dynamic_cast<CCharacterSheet *>(SheetMngr.get(sheetId)); \
|
|
if(ch == 0) \
|
|
{ \
|
|
nlwarning("Command '" #commandName "': cannot find the character for the given sheet."); \
|
|
return false; \
|
|
} \
|
|
\
|
|
/* Set the new distance for this sheet. */ \
|
|
ch->variableName = dist; \
|
|
\
|
|
/* Well Done */ \
|
|
return true; \
|
|
|
|
//-----------------------------------------------
|
|
// 'dist2front' : Change the distance to the front for a given sheet.
|
|
//-----------------------------------------------
|
|
NLMISC_COMMAND(dist2front, "Change the distance to the front for a given sheet.", "<form> <dist>")
|
|
{
|
|
DIST_TO_COMMAND(dist2front, DistToFront);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
// 'dist2back' : Change the distance to the back for a given sheet.
|
|
//-----------------------------------------------
|
|
NLMISC_COMMAND(dist2back, "Change the distance to the back for a given sheet.", "<form> <dist>")
|
|
{
|
|
DIST_TO_COMMAND(dist2back, DistToBack);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
// 'dist2side' : Change the distance to the side for a given sheet.
|
|
//-----------------------------------------------
|
|
NLMISC_COMMAND(dist2side, "Change the distance to the side for a given sheet.", "<form> <dist>")
|
|
{
|
|
DIST_TO_COMMAND(dist2side, DistToSide);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------
|
|
// 'clearShape' : Remove all shapes added with the 'shape' command
|
|
//-----------------------------------------------
|
|
NLMISC_COMMAND(clearShape, "Remove all shapes added with the 'shape' command.", "")
|
|
{
|
|
if (!Scene) return false;
|
|
for(uint k = 0; k < ShapeAddedByCommand.size(); ++k)
|
|
{
|
|
Scene->deleteInstance(ShapeAddedByCommand[k]);
|
|
}
|
|
ShapeAddedByCommand.clear();
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------
|
|
// 'setShapeX' : Set X position for last created shape
|
|
//-----------------------------------------------------
|
|
NLMISC_COMMAND(setShapeX, "Set X position for last created shape.", "<x coordinate>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
if (ShapeAddedByCommand.empty())
|
|
{
|
|
nlwarning("No shape created yet");
|
|
return false;
|
|
}
|
|
float coord;
|
|
if (!fromString(args[0], coord))
|
|
{
|
|
nlwarning("Can't get position");
|
|
return false;
|
|
}
|
|
CVector pos = ShapeAddedByCommand.back().getPos();
|
|
pos.x = coord;
|
|
ShapeAddedByCommand.back().setPos(pos);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------
|
|
// 'setShapeY' : Set Y position for last created shape
|
|
//-----------------------------------------------------
|
|
NLMISC_COMMAND(setShapeY, "Set Y position for last created shape.", "<y coordinate>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
if (ShapeAddedByCommand.empty())
|
|
{
|
|
nlwarning("No shape created yet");
|
|
return false;
|
|
}
|
|
float coord;
|
|
if (!fromString(args[0], coord))
|
|
{
|
|
nlwarning("Can't get position");
|
|
return false;
|
|
}
|
|
CVector pos = ShapeAddedByCommand.back().getPos();
|
|
pos.y = coord;
|
|
ShapeAddedByCommand.back().setPos(pos);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------
|
|
// 'setShapeZ' : Set Z position for last created shape
|
|
//-----------------------------------------------------
|
|
NLMISC_COMMAND(setShapeZ, "Set Z position for last created shape.", "<z coordinate>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
if (ShapeAddedByCommand.empty())
|
|
{
|
|
nlwarning("No shape created yet");
|
|
return false;
|
|
}
|
|
float coord;
|
|
if (!fromString(args[0], coord))
|
|
{
|
|
nlwarning("Can't get position");
|
|
return false;
|
|
}
|
|
CVector pos = ShapeAddedByCommand.back().getPos();
|
|
pos.z = coord;
|
|
ShapeAddedByCommand.back().setPos(pos);
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
// 'shape' : Add a shape in the scene.
|
|
//-----------------------------------------------
|
|
NLMISC_COMMAND(shape, "Add a shape in the scene.", "<shape file>")
|
|
{
|
|
if(args.size() < 1)
|
|
{
|
|
nlwarning("Command 'shape': need at least 1 parameter, try '/help shape' for more details.");
|
|
return false;
|
|
}
|
|
if (!Scene)
|
|
{
|
|
nlwarning("No scene available");
|
|
return false;
|
|
}
|
|
UInstance instance = Scene->createInstance(args[0]);
|
|
if(!instance.empty())
|
|
{
|
|
ShapeAddedByCommand.push_back(instance);
|
|
// Set the position
|
|
instance.setPos(UserEntity->pos());
|
|
instance.setClusterSystem(UserEntity->getClusterSystem()); // for simplicity, assume it is in the same
|
|
// cluster system than the user
|
|
// Compute the direction Matrix
|
|
CMatrix dir;
|
|
dir.identity();
|
|
CVector vi = UserEntity->dir()^CVector(0.f, 0.f, 1.f);
|
|
CVector vk = vi^UserEntity->dir();
|
|
dir.setRot(vi, UserEntity->dir(), vk, true);
|
|
// Set Orientation : User Direction should be normalized.
|
|
instance.setRotQuat(dir.getRot());
|
|
// if the shape is a particle system, additionnal parameters are user params
|
|
UParticleSystemInstance psi;
|
|
psi.cast (instance);
|
|
if (!psi.empty())
|
|
{
|
|
// set each user param that is present
|
|
for(uint k = 0; k < 4; ++k)
|
|
{
|
|
if (args.size() >= (k + 2))
|
|
{
|
|
float uparam;
|
|
if (fromString(args[k + 1], uparam))
|
|
{
|
|
psi.setUserParam(k, uparam);
|
|
}
|
|
else
|
|
{
|
|
nlwarning("Cant read param %d", k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
nlwarning("Command 'shape': cannot find the shape %s.", args[0].c_str());
|
|
|
|
// Command Well Done
|
|
return true;
|
|
}
|
|
|
|
|
|
// Change the parent of an entity. 'parent slot' not defined remove the current parent.
|
|
NLMISC_COMMAND(parent, "Change the parent of an entity.", "<slot> [<parent slot>]")
|
|
{
|
|
CLFECOMMON::TCLEntityId parentSlot = CLFECOMMON::INVALID_SLOT;
|
|
|
|
// Check parameters.
|
|
switch(args.size())
|
|
{
|
|
// Set the target for the entity.
|
|
case 2:
|
|
fromString(args[1], parentSlot);
|
|
|
|
// Remove the target for the entity.
|
|
case 1:
|
|
{
|
|
uint entitySlot;
|
|
fromString(args[0], entitySlot);
|
|
CEntityCL *entity = EntitiesMngr.entity(entitySlot);
|
|
if(entity)
|
|
{
|
|
entity->parent(parentSlot);
|
|
entity->pos(CVectorD::Null);
|
|
}
|
|
else
|
|
nlwarning("command 'parent': there is no entity in the slot %d", entitySlot);
|
|
}
|
|
break;
|
|
|
|
// Bad command.
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
// Well done.
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(displayInventoryCounter, "display the Inventory counter to compare with db counter", "")
|
|
{
|
|
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
|
|
uint srvVal= pIM->getDbProp("SERVER:INVENTORY:COUNTER")->getValue32();
|
|
uint locVal= pIM->getLocalSyncActionCounter() ;
|
|
srvVal&= pIM->getLocalSyncActionCounterMask();
|
|
locVal&= pIM->getLocalSyncActionCounterMask();
|
|
|
|
pIM->displaySystemInfo(ucstring( "ServerCounter: " + toString(srvVal) + "/ LocalCounter: " + toString(locVal)) );
|
|
|
|
// Well done.
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(displayActionCounter, "display the action counters", "")
|
|
{
|
|
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
CSPhraseManager *pPM= CSPhraseManager::getInstance();
|
|
|
|
// next
|
|
uint srvVal= pIM->getDbProp(PHRASE_DB_COUNTER_NEXT)->getValue32();
|
|
uint locVal= pPM->getPhraseNextExecuteCounter() ;
|
|
srvVal&= PHRASE_EXECUTE_COUNTER_MASK;
|
|
locVal&= PHRASE_EXECUTE_COUNTER_MASK;
|
|
|
|
pIM->displaySystemInfo(ucstring( "NextCounter: " + toString(srvVal) + "/ LocalCounter: " + toString(locVal)) );
|
|
|
|
// cycle
|
|
srvVal= pIM->getDbProp(PHRASE_DB_COUNTER_CYCLE)->getValue32();
|
|
locVal= pPM->getPhraseCycleExecuteCounter() ;
|
|
srvVal&= PHRASE_EXECUTE_COUNTER_MASK;
|
|
locVal&= PHRASE_EXECUTE_COUNTER_MASK;
|
|
|
|
pIM->displaySystemInfo(ucstring( "CycleCounter: " + toString(srvVal) + "/ LocalCounter: " + toString(locVal)) );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
#if defined(NL_OS_WINDOWS)
|
|
NLMISC_COMMAND (url, "launch a browser to the specified url", "<url>")
|
|
{
|
|
if (args.size () != 1)
|
|
return false;
|
|
|
|
HINSTANCE result = ShellExecute(NULL, "open", args[0].c_str(), NULL,NULL, SW_SHOW);
|
|
if ((sint32)result > 32)
|
|
return true;
|
|
else
|
|
{
|
|
log.displayNL ("ShellExecute failed %d", (uint32)result);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
NLMISC_COMMAND( reconnect, "Reconnect to the same shard (self Far TP)", "")
|
|
{
|
|
// If the server is up, the egs will begin the quit sequence (shortened only if we are in edition or animation mode).
|
|
// If the server is down or frozen, a second /reconnect will be necessary to make the client reconnect
|
|
// but if you reconnect before letting the EGS save the character file, the previous saved file will be loaded.
|
|
switch ( LoginSM.getCurrentState() )
|
|
{
|
|
case CLoginStateMachine::st_ingame:
|
|
LoginSM.pushEvent( CLoginStateMachine::ev_connect );
|
|
break;
|
|
case CLoginStateMachine::st_leave_shard:
|
|
FarTP.onServerQuitOk();
|
|
break;
|
|
default:
|
|
log.displayNL( "Can't reconnect from LoginSM state %u", (uint)LoginSM.getCurrentState() );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif // !FINAL_VERSION
|
|
|
|
struct CItemSheetSort
|
|
{
|
|
const CItemSheet *IS;
|
|
CSheetId ID;
|
|
ITEMFAMILY::EItemFamily Family;
|
|
};
|
|
|
|
static inline bool operator < (const CItemSheetSort &lhs, const CItemSheetSort &rhs)
|
|
{
|
|
return lhs.Family < rhs.Family;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpItems, "Sort items by category & display their sheet ids", "")
|
|
{
|
|
std::vector<CItemSheetSort> isVect;
|
|
const CSheetManager::TEntitySheetMap &sheets = SheetMngr.getSheets();
|
|
for(CSheetManager::TEntitySheetMap::const_iterator it = sheets.begin(); it != sheets.end(); ++it)
|
|
{
|
|
const CEntitySheet *es = it->second.EntitySheet;
|
|
if (es && es->type() == CEntitySheet::ITEM)
|
|
{
|
|
CItemSheetSort iss;
|
|
iss.IS = static_cast<const CItemSheet *>(es);
|
|
iss.ID = it->first;
|
|
iss.Family = iss.IS->Family;
|
|
isVect.push_back(iss);
|
|
}
|
|
}
|
|
//
|
|
// sort items
|
|
std::sort(isVect.begin(), isVect.end());
|
|
//
|
|
for(std::vector<CItemSheetSort>::iterator itemIt = isVect.begin(); itemIt != isVect.end(); ++itemIt)
|
|
{
|
|
std::string info;
|
|
info = "FAMILY: ";
|
|
info += ITEMFAMILY::toString(itemIt->Family);
|
|
info += "; Name = ";
|
|
info += itemIt->IS->Id.toString();
|
|
info += "; Sheet ID = ";
|
|
info += toString(itemIt->ID.asInt());
|
|
nlwarning(info.c_str());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpVisualSlots, "dump the visual slots", "")
|
|
{
|
|
if (!args.empty()) return false;
|
|
SheetMngr.dumpVisualSlots();
|
|
SheetMngr.dumpVisualSlotsIndex();
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(skillToInt, "Convert a skill to an int", "")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->displaySystemInfo(ucstring(toString((uint) SKILLS::toSkill(args[0]))));
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(browse, "Browse a HTML document with the internal help web browser.", "")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->runActionHandler("browse", NULL, "name=ui:interface:help_browser:content:html|url="+args[0]);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(openRingWindow, "Browse the main page in the ring web browser.", "")
|
|
{
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->runActionHandler("browse", NULL, "name=ui:interface:r2ed_web_admin:content:admin_web_page|url="+RingMainURL);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(browseRingAdmin, "Browse a HTML document with the ring web browser.", "")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->runActionHandler("browse", NULL, "name=ui:interface:r2ed_web_admin:content:admin_web_page|url="+args[0]);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUCreate, "create a guild", "<guild name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:CREATE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUQuit, "quit a guild", "")
|
|
{
|
|
if (args.size() != 0) return false;
|
|
const string msgName = "GUILD:QUIT";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GULeaveLeadership, "abandon leadership of a guild", "")
|
|
{
|
|
if (args.size() != 0) return false;
|
|
const string msgName = "GUILD:ABANDON_LEADERSHIP";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
NLMISC_COMMAND(GULeaveOfficerTitle, "abandon officer title", "")
|
|
{
|
|
if (args.size() != 0) return false;
|
|
const string msgName = "GUILD:ABANDON_OFFICER_TITLE";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUNameOfficer, "name an officer", "<player name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:NAME_OFFICER";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUDismissOfficer, "dismiss an officer", "<player name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:DISMISS_OFFICER";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUKick, "kick a member", "<player name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:KICK_MEMBER";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(GUAccept, "accept an invitation", "")
|
|
{
|
|
CInterfaceManager::getInstance()->runActionHandler("accept_guild_invitation",NULL);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GURefuse, "refuse an invitation", "")
|
|
{
|
|
CInterfaceManager::getInstance()->runActionHandler("refuse_guild_invitation",NULL);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUFriend, "invite a player to become a friend of the guild", "<player name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:FRIEND_INVITATION";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUFriendAccept, "accept to be a friend of a guild that invited you", "")
|
|
{
|
|
if (args.size() != 0) return false;
|
|
const string msgName = "GUILD:ACCEPT_FRIEND_INVITATION";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUFriendRefuse, "refuse to be a friend of a guild that invited you", "")
|
|
{
|
|
if (args.size() != 0) return false;
|
|
const string msgName = "GUILD:REFUSE_FRIEND_INVITATION";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUSetSuccessor, "set the successor of the guild leader", "<player name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:SET_SUCCESSOR";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUInfos, "get information on a guild", "<guild name>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
const string msgName = "GUILD:GET_INFOS";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
string buf = args[0];
|
|
out.serial( buf );
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(GUJournal, "get the guild journal", "")
|
|
{
|
|
if (args.size() != 0) return false;
|
|
const string msgName = "GUILD:GET_LOG";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(buildingTeleport, "teleport to a building", "building index")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
uint16 index;
|
|
fromString(args[0], index);
|
|
const string msgName = "GUILD:TELEPORT";
|
|
CBitMemStream out;
|
|
if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
|
|
{
|
|
out.serial(index);
|
|
NetMngr.push(out);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(logFaberMpCompatibles, "log all MP compatibles for faber the item", "sheetid")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
uint32 sheetId;
|
|
fromString(args[0], sheetId);
|
|
CSBrickManager *pBM= CSBrickManager::getInstance();
|
|
|
|
// get the faber plan
|
|
CSBrickSheet *brick= pBM->getBrick(CSheetId(sheetId));
|
|
// get the origin of the item built
|
|
CItemSheet *itemBuilt= NULL;
|
|
if(brick)
|
|
itemBuilt= dynamic_cast<CItemSheet*>(SheetMngr.get(brick->FaberPlan.ItemBuilt));
|
|
if(brick && itemBuilt)
|
|
{
|
|
|
|
// build array of MP sheetId
|
|
std::vector<CItemSheet*> mps;
|
|
mps.reserve(100);
|
|
const CSheetManager::TEntitySheetMap &sheetMap= SheetMngr.getSheets();
|
|
CSheetManager::TEntitySheetMap::const_iterator it;
|
|
for(it= sheetMap.begin(); it!=sheetMap.end(); it++)
|
|
{
|
|
CItemSheet *mp= const_cast<CItemSheet*>( dynamic_cast<const CItemSheet*>(it->second.EntitySheet) );
|
|
if(mp && mp->Family == ITEMFAMILY::RAW_MATERIAL)
|
|
mps.push_back(mp);
|
|
}
|
|
|
|
// header
|
|
uint numMpSlots= brick->FaberPlan.ItemPartMps.size();
|
|
nlinfo("********** FABERLOG **********");
|
|
nlinfo(" ItemBuilt Origin: %s", ITEM_ORIGIN::enumToString(itemBuilt->ItemOrigin).c_str() );
|
|
nlinfo(" NumMPSlot: %d", numMpSlots);
|
|
|
|
// Parse All Slots.
|
|
for(uint i=0;i<numMpSlots;i++)
|
|
{
|
|
CSBrickSheet::CFaberPlan::CItemPartMP &mpSlot= brick->FaberPlan.ItemPartMps[i];
|
|
nlinfo(" MPSlot %d", i);
|
|
nlinfo(" Quantity: %d", mpSlot.Quantity);
|
|
nlinfo(" TypeReq: %s", RM_FABER_TYPE::toString(mpSlot.FaberTypeFilter).c_str() );
|
|
nlinfo(" List Of Compatibles MPs:");
|
|
|
|
for(uint i=0;i<mps.size();i++)
|
|
{
|
|
CItemSheet *itemSheet= mps[i];
|
|
bool ok= true;
|
|
// check faber type filter
|
|
if( mpSlot.FaberTypeFilter!=RM_FABER_TYPE::Unknown && !itemSheet->canBuildItemPart(mpSlot.FaberTypeFilter, itemBuilt->ItemOrigin))
|
|
ok= false;
|
|
|
|
if(ok)
|
|
{
|
|
nlinfo(" %s", itemSheet->Id.toString().c_str() );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(debugItemInfo, "simulate a ItemInfo received from server", "itemSlotId version [enchant]")
|
|
{
|
|
CItemInfos itemInfo;
|
|
|
|
if (args.size() < 2 || args.size() > 3) return false;
|
|
bool enchant= false;
|
|
if(args.size()==3)
|
|
fromString(args[2], enchant);
|
|
|
|
fromString(args[0], itemInfo.slotId);
|
|
fromString(args[1], itemInfo.versionInfo);
|
|
|
|
itemInfo.CurrentDamage= 10;
|
|
itemInfo.MaxDamage= 15;
|
|
itemInfo.DodgeModifier= 5;
|
|
itemInfo.ParryModifier= -10;
|
|
itemInfo.AdversaryDodgeModifier= 666;
|
|
itemInfo.AdversaryParryModifier= 333;
|
|
itemInfo.HpBuff= 12;
|
|
itemInfo.SapBuff= -14;
|
|
itemInfo.StaBuff= 0;
|
|
itemInfo.FocusBuff= 1;
|
|
itemInfo.MagicProtection[0]= PROTECTION_TYPE::Electricity;
|
|
itemInfo.MagicProtectionFactor[0]= 43;
|
|
itemInfo.MagicProtection[1]= PROTECTION_TYPE::Shockwave;
|
|
itemInfo.MagicProtectionFactor[1]= 21;
|
|
itemInfo.MagicProtection[2]= PROTECTION_TYPE::Rot;
|
|
itemInfo.MagicProtectionFactor[2]= 100;
|
|
itemInfo.DesertMagicResistance= 133;
|
|
itemInfo.ForestMagicResistance= 500;
|
|
itemInfo.PrimaryRootMagicResistance= 341;
|
|
itemInfo.Hp= 66;
|
|
itemInfo.HpMax= 100;
|
|
itemInfo.Range= 169;
|
|
itemInfo.SapLoadCurrent= 6;
|
|
itemInfo.SapLoadMax= 30;
|
|
itemInfo.HitRate= 8;
|
|
itemInfo.ProtectionFactor= 0.25;
|
|
itemInfo.MaxSlashingProtection= 38;
|
|
itemInfo.MaxPiercingProtection= 48;
|
|
itemInfo.MaxBluntProtection= 58;
|
|
itemInfo.WearEquipmentMalus= 0.31f;
|
|
|
|
if(enchant)
|
|
{
|
|
itemInfo.Enchantment.Name="pipoSort";
|
|
itemInfo.Enchantment.Bricks.resize(3);
|
|
itemInfo.Enchantment.Bricks[0]= CSheetId("bmpa01.sbrick");
|
|
itemInfo.Enchantment.Bricks[1]= CSheetId("bmlchea01.sbrick");
|
|
itemInfo.Enchantment.Bricks[2]= CSheetId("bmlchmh00005.sbrick");
|
|
}
|
|
|
|
switch(rand()%4)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
{
|
|
itemInfo.CastingSpeedFactor[1]= 1.0f;
|
|
itemInfo.MagicPowerFactor[1]= 0.2f;
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
itemInfo.CastingSpeedFactor[0]= 0.4f;
|
|
itemInfo.MagicPowerFactor[0]= 0.2f;
|
|
itemInfo.CastingSpeedFactor[2]= 0.8f;
|
|
itemInfo.MagicPowerFactor[2]= 0.3f;
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
itemInfo.CastingSpeedFactor[0]= 0.3f;
|
|
itemInfo.MagicPowerFactor[0]= 0.3f;
|
|
itemInfo.CastingSpeedFactor[1]= 0.3f;
|
|
itemInfo.MagicPowerFactor[1]= 0.3f;
|
|
itemInfo.CastingSpeedFactor[2]= 0.3f;
|
|
itemInfo.MagicPowerFactor[2]= 0.3f;
|
|
itemInfo.CastingSpeedFactor[3]= 0.3f;
|
|
itemInfo.MagicPowerFactor[3]= 0.3f;
|
|
}
|
|
break;
|
|
};
|
|
|
|
|
|
getInventory().onReceiveItemInfo(itemInfo);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(debugItemInfoWaiters, "log ItemInfoWaiters", "")
|
|
{
|
|
getInventory().debugItemInfoWaiters();
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(debugInfoWindows, "log info windows sheetId", "")
|
|
{
|
|
CInterfaceHelp::debugOpenedInfoWindows();
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(getSkillValue, "get a skill value by its name", "skill_name")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
uint skillId= (uint) SKILLS::toSkill(args[0]);
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:CHARACTER_INFO:SKILLS:%d:SKILL", skillId), false);
|
|
if(node)
|
|
{
|
|
pIM->displaySystemInfo(ucstring(toString(node->getValue32())));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(setSkillValue, "set a skill value by its name", "skill_name value")
|
|
{
|
|
if (args.size() != 2) return false;
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
uint skillId= (uint) SKILLS::toSkill(args[0]);
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:CHARACTER_INFO:SKILLS:%d:SKILL", skillId), false);
|
|
if(node)
|
|
{
|
|
sint32 value;
|
|
fromString(args[1], value);
|
|
node->setValue32(value);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(getBaseSkillValue, "get a baseskill value by its name", "skill_name")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
uint skillId= (uint) SKILLS::toSkill(args[0]);
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:CHARACTER_INFO:SKILLS:%d:BaseSKILL", skillId), false);
|
|
if(node)
|
|
{
|
|
pIM->displaySystemInfo(ucstring(toString(node->getValue32())));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(setBaseSkillValue, "set a baseskill value by its name", "skill_name value")
|
|
{
|
|
if (args.size() != 2) return false;
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
uint skillId= (uint) SKILLS::toSkill(args[0]);
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:CHARACTER_INFO:SKILLS:%d:BaseSKILL", skillId), false);
|
|
if(node)
|
|
{
|
|
sint32 value;
|
|
fromString(args[1], value);
|
|
node->setValue32(value);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(setAllSkillValue, "set all Skill and baseskill to the given value", "value")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
uint value;
|
|
fromString(args[0], value);
|
|
for(uint i=0;i<SKILLS::NUM_SKILLS;i++)
|
|
{
|
|
CCDBNodeLeaf *node;
|
|
node= pIM->getDbProp(toString("SERVER:CHARACTER_INFO:SKILLS:%d:BaseSKILL", i), false);
|
|
if(node)
|
|
node->setValue32(value);
|
|
node= pIM->getDbProp(toString("SERVER:CHARACTER_INFO:SKILLS:%d:SKILL", i), false);
|
|
if(node)
|
|
node->setValue32(value);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(setEntityName, "set a entity name id", "entitySlot nameId")
|
|
{
|
|
if (args.size() != 2) return false;
|
|
uint slot;
|
|
fromString(args[0], slot);
|
|
|
|
CCharacterCL *entity= dynamic_cast<CCharacterCL*>(EntitiesMngr.entity(slot));
|
|
if(entity)
|
|
{
|
|
uint32 nameId;
|
|
fromString(args[1], nameId);
|
|
entity->debugSetNameId(nameId);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(reloadWeather, "reload the weather sheets", "")
|
|
{
|
|
if (!args.empty()) return false;
|
|
ContinentMngr.reloadWeather();
|
|
return true;
|
|
}
|
|
|
|
|
|
// Common method to reload sheets (hope it works later...)
|
|
template<class T>
|
|
bool reloadSheets(string filter, string wildcardFilter)
|
|
{
|
|
CSheetManager sheetManager;
|
|
std::vector<std::string> filters;
|
|
filters.push_back(filter);
|
|
ClientSheetsStrings.memoryUncompress();
|
|
NLMISC::IProgressCallback progress;
|
|
sheetManager.loadAllSheetNoPackedSheet(progress, filters, wildcardFilter);
|
|
ClientSheetsStrings.memoryCompress();
|
|
// copy sheets into current sheet manager (because numerous ptr are kept on the previous sheets in various places)
|
|
const CSheetManager::TEntitySheetMap &sheetMap= sheetManager.getSheets();
|
|
CSheetManager::TEntitySheetMap::const_iterator it;
|
|
for(it=sheetMap.begin();it!=sheetMap.end();it++)
|
|
{
|
|
T *dest = dynamic_cast<T*>(SheetMngr.get(it->first));
|
|
if (dest)
|
|
{
|
|
const T *src = dynamic_cast<T*>(it->second.EntitySheet);
|
|
if (src)
|
|
{
|
|
*dest = *src;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::string extendWildcard(const std::string &in)
|
|
{
|
|
string out;
|
|
// append * at begin if not present (or if enp
|
|
if(in.empty() || in[0]!='*')
|
|
out= '*';
|
|
out+= in;
|
|
// append .* at end if no . found
|
|
if(in.find('.')==string::npos)
|
|
out+= ".*";
|
|
return out;
|
|
}
|
|
|
|
// macros to reload Sheets
|
|
#define CMD_RELOAD_SHEET(_cmd_name, _filter, _type) \
|
|
NLMISC_COMMAND(_cmd_name, #_cmd_name, "") \
|
|
{ \
|
|
if (args.size()>1) return false; \
|
|
string wildcardFilter; \
|
|
if (args.size()>=1) \
|
|
wildcardFilter= extendWildcard(args[0]); \
|
|
return reloadSheets<_type>(_filter, wildcardFilter); \
|
|
}
|
|
// Important ones
|
|
CMD_RELOAD_SHEET(reloadCreature, "creature", CCharacterSheet)
|
|
CMD_RELOAD_SHEET(reloadSbrick, "sbrick", CSBrickSheet)
|
|
CMD_RELOAD_SHEET(reloadSphrase, "sphrase", CSPhraseSheet)
|
|
CMD_RELOAD_SHEET(reloadSitem, "sitem", CItemSheet)
|
|
// Not tested ones
|
|
/*
|
|
CMD_RELOAD_SHEET(reloadPlayer, "player", CPlayerSheet)
|
|
CMD_RELOAD_SHEET(reloadFx, "fx", CFXSheet)
|
|
CMD_RELOAD_SHEET(reloadBuilding, "building", CBuildingSheet)
|
|
CMD_RELOAD_SHEET(reloadDeath_impact, "death_impact", CPactSheet)
|
|
CMD_RELOAD_SHEET(reloadMission, "mission", CMissionSheet)
|
|
CMD_RELOAD_SHEET(reloadRace_stats, "race_stats", CRaceStatsSheet)
|
|
CMD_RELOAD_SHEET(reloadLight_cycle, "light_cycle", CLightCycleSheet)
|
|
CMD_RELOAD_SHEET(reloadContinent, "continent", CContinentSheet)
|
|
CMD_RELOAD_SHEET(reloadWorld, "world", CWorldSheet)
|
|
CMD_RELOAD_SHEET(reloadMission_icon, "mission_icon", CMissionIconSheet)
|
|
CMD_RELOAD_SHEET(reloadSkill_tree, "skill_tree", CSkillsTreeSheet)
|
|
CMD_RELOAD_SHEET(reloadTitles, "titles", CUnblockTitlesSheet)
|
|
CMD_RELOAD_SHEET(reloadSucces_chances_table, "succes_chances_table", CSuccessTableSheet)
|
|
CMD_RELOAD_SHEET(reloadAutomaton_list, "automaton_list", CAutomatonListSheet)
|
|
CMD_RELOAD_SHEET(reloadAnimset_list, "animset_list", CAnimationSetListSheet)
|
|
CMD_RELOAD_SHEET(reloadAnimation_fx, "animation_fx", CAnimationFXSheet)
|
|
CMD_RELOAD_SHEET(reloadEmot, "emot", CEmotListSheet)
|
|
CMD_RELOAD_SHEET(reloadForage_source, "forage_source", CForageSourceSheet)
|
|
CMD_RELOAD_SHEET(reloadText_emotes, "text_emotes", CTextEmotListSheet)
|
|
*/
|
|
|
|
NLMISC_COMMAND(vprop, "Flush the Visual Property (local only). you must write to the DB before (but if you give the value in the 3rd arg)", "slot propId [val]")
|
|
{
|
|
if(args.size()!=2 && args.size()!=3) return false;
|
|
uint slot;
|
|
fromString(args[0], slot);
|
|
uint propId;
|
|
fromString(args[1], propId);
|
|
|
|
// set value in the DB?
|
|
if(args.size()==3)
|
|
{
|
|
sint64 val= 0;
|
|
fromString(args[2], val);
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:Entities:E%d:P%d", slot, propId), false);
|
|
if(node)
|
|
node->setValue64(val);
|
|
}
|
|
|
|
EntitiesMngr.updateVisualProperty(0, slot, propId);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dataSetId, "Set the UID of an entity", "slot uid")
|
|
{
|
|
if(args.size()!=2) return false;
|
|
uint slot;
|
|
fromString(args[0], slot);
|
|
uint uid;
|
|
fromString(args[1], uid);
|
|
|
|
CEntityCL *entity= EntitiesMngr.entity(slot);
|
|
if(!entity)
|
|
return false;
|
|
|
|
entity->dataSetId(uid);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(forceDisplayFXBBoxes, "Force to display bboxes of all fxs", "0=off, 1=off")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
bool on;
|
|
fromString(args[0], on);
|
|
UParticleSystemInstance::forceDisplayBBox(on);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpVillages, "Dump villages loading zones in a bitmap", "filename>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
ContinentMngr.cur()->dumpVillagesLoadingZones(args[0]);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpFogDayMap, "Dump fog day map", "filename>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
ContinentMngr.cur()->dumpFogMap(CFogMapBuild::Day, args[0]);
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(dumpFogDepthMap, "Dump fog depth map", "filename>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
ContinentMngr.cur()->dumpFogMap(CFogMapBuild::Depth, args[0]);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpFogDistMap, "Dump fog depth map", "filename>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
ContinentMngr.cur()->dumpFogMap(CFogMapBuild::Distance, args[0]);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpRainMap, "Dump fog rain map", "filename>")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CRGBA colorLookup[256];
|
|
for(uint8 k = 1; k < 255; ++k)
|
|
{
|
|
colorLookup[k] = CRGBA(k, k, k, 1);
|
|
}
|
|
colorLookup[0] = CRGBA::Red;
|
|
colorLookup[255] = CRGBA::Blue;
|
|
ContinentMngr.cur()->dumpFogMap(CFogMapBuild::NoPrecipitation, args[0], CContinent::ChannelR, colorLookup);
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(stick_log, "", "<slot>")
|
|
{
|
|
if(args.size()!=1)
|
|
return false;
|
|
CLFECOMMON::TCLEntityId slot;
|
|
fromString(args[0], slot);
|
|
|
|
// Compute the position.
|
|
CEntityCL *entity = EntitiesMngr.entity(slot);
|
|
if(!entity)
|
|
return false;
|
|
|
|
USkeleton *skel= entity->skeleton();
|
|
if(skel)
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
nlinfo("Skel Log: %s", skel->getShapeName().c_str());
|
|
|
|
std::vector<UTransform> sticks;
|
|
skel->getStickedObjects(sticks);
|
|
|
|
nlinfo("StickedModels: %d", sticks.size());
|
|
pIM->displaySystemInfo(ucstring(toString("StickedModels: %d", sticks.size())));
|
|
|
|
for(uint i=0;i<sticks.size();i++)
|
|
{
|
|
UInstance inst;
|
|
inst.cast(sticks[i]);
|
|
if(!inst.empty())
|
|
{
|
|
string str= toString(" %d: %X. %s", i, inst.getObjectPtr(), inst.getShapeName().c_str());
|
|
nlinfo(str.c_str());
|
|
pIM->displaySystemInfo(str);
|
|
}
|
|
else
|
|
{
|
|
string str= toString(" %d: %X. NOT a TransformShape", i, sticks[i].getObjectPtr());
|
|
nlinfo(str.c_str());
|
|
pIM->displaySystemInfo(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(print_sys, "", "<cat> <str>")
|
|
{
|
|
if(args.size()<1)
|
|
return false;
|
|
string cat= args[0];
|
|
string str;
|
|
for (uint i = 1; i < args.size(); i++)
|
|
{
|
|
str += args[i] + " ";
|
|
}
|
|
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
pIM->displaySystemInfo(str, cat);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(fillAllInfoVersion, "", "<version>")
|
|
{
|
|
if(args.size()!=1)
|
|
return false;
|
|
|
|
uint i,j;
|
|
uint ver;
|
|
fromString(args[0], ver);
|
|
CInventoryManager &im= getInventory();
|
|
|
|
// BAG
|
|
for(i=0;i<MAX_BAGINV_ENTRIES;i++)
|
|
im.getServerBagItem(i).setInfoVersion(ver);
|
|
|
|
// PACK_ANIMAL
|
|
for(j=0;j<MAX_PACK_ANIMAL;j++)
|
|
{
|
|
for(i=0;i<MAX_ANIMALINV_ENTRIES;i++)
|
|
im.getServerPAItem(j,i).setInfoVersion(ver);
|
|
}
|
|
|
|
// EXCHANGE
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
for(i=0;i<CPlayerTrade::NumTradeSlot;i++)
|
|
{
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:EXCHANGE:GIVE:%d:INFO_VERSION", i), false);
|
|
if(node)
|
|
node->setValue32(ver);
|
|
node= pIM->getDbProp(toString("SERVER:EXCHANGE:RECEIVE:%d:INFO_VERSION", i), false);
|
|
if(node)
|
|
node->setValue32(ver);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(fullFillInventory, "", "dbstring sheetName")
|
|
{
|
|
if(args.size()!=2)
|
|
return false;
|
|
|
|
// read value
|
|
sint64 value;
|
|
if (isalpha(args[1][0]))
|
|
{
|
|
CSheetId sheet(args[1]);
|
|
value = (sint64) sheet.asInt();
|
|
}
|
|
else
|
|
{
|
|
// Convert the string into an sint64.
|
|
fromString(args[1], value);
|
|
}
|
|
|
|
// read db dest
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
CCDBNodeBranch *nb= pIM->getDbBranch(args[0]);
|
|
if(!nb)
|
|
return false;
|
|
|
|
uint num= nb->getNbNodes();
|
|
for(uint i=0;i<num;i++)
|
|
{
|
|
CCDBNodeLeaf *nl;
|
|
nl= pIM->getDbProp(args[0]+":"+toString(i)+":SHEET", false);
|
|
if(nl)
|
|
{
|
|
nl->setValue64(value);
|
|
nl= pIM->getDbProp(args[0]+":"+toString(i)+":QUALITY", false);
|
|
if(nl)
|
|
nl->setValue64(i);
|
|
nl= pIM->getDbProp(args[0]+":"+toString(i)+":PREREQUISIT_VALID", false);
|
|
if(nl)
|
|
nl->setValue64(1);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(fillAllItemPreReq, "", "dbstring value")
|
|
{
|
|
if(args.size()!=2)
|
|
return false;
|
|
|
|
// read value
|
|
sint32 value;
|
|
fromString(args[1], value);
|
|
string dbBase= args[0];
|
|
|
|
// write prop for all elements of the branch
|
|
uint index= 0;
|
|
for(;;)
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
CCDBNodeLeaf *node= pIM->getDbProp(toString("%s:%d:PREREQUISIT_VALID", dbBase.c_str(), index), false);
|
|
if(!node)
|
|
break;
|
|
node->setValue32(value);
|
|
index++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(eventMusic, "", "music")
|
|
{
|
|
if(args.size()<1 && args.size()>3)
|
|
return false;
|
|
|
|
string fileName= args[0].c_str();
|
|
bool loop= false;
|
|
if(args.size() > 1)
|
|
fromString(args[1], loop);
|
|
uint fadeTime= 1000;
|
|
if(args.size() > 2)
|
|
fromString(args[2], fadeTime);
|
|
|
|
if(SoundMngr)
|
|
SoundMngr->playEventMusic(fileName, fadeTime, loop);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(setLightHour, "force the light hour, (negative value to reset to auto)", "<hour>")
|
|
{
|
|
if( args.size()!=1 )
|
|
return false;
|
|
|
|
float hour;
|
|
fromString(args[0], hour);
|
|
if( hour < LightCycleManager.getLightDesc().NumHours )
|
|
{
|
|
// check for privileges if this is the final build
|
|
#if FINAL_VERSION
|
|
// test that user has privilege
|
|
if (hasPrivilegeDEV() ||
|
|
hasPrivilegeSGM() ||
|
|
hasPrivilegeGM() ||
|
|
hasPrivilegeVG() ||
|
|
hasPrivilegeSG() ||
|
|
hasPrivilegeG() ||
|
|
hasPrivilegeEM() ||
|
|
hasPrivilegeEG())
|
|
#endif
|
|
{
|
|
ForcedDayNightCycleHour = hour;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
NLMISC_COMMAND(jobAnim, "set the job anim specialisation of an entity", "eid number")
|
|
{
|
|
if(args.size()!=2)
|
|
return false;
|
|
|
|
uint eid;
|
|
fromString(args[0], eid);
|
|
uint jas;
|
|
fromString(args[1], jas);
|
|
CCharacterCL *ent= dynamic_cast<CCharacterCL*>(EntitiesMngr.entity(eid));
|
|
if(ent)
|
|
{
|
|
ent->setAnimJobSpecialisation(jas);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(startLogStageChange, "start to log the change of stages of watched entity", "")
|
|
{
|
|
// stop first any log
|
|
EntitiesMngr.stopLogStageChange();
|
|
|
|
// start the log
|
|
EntitiesMngr.startLogStageChange(NetMngr.getCurrentClientTick(), T1);
|
|
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(stopLogStageChange, "stop to log the change of watched entity stages", "")
|
|
{
|
|
EntitiesMngr.stopLogStageChange();
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(testReceiveMissionInfo, "emulate a dummy receive of mission info", "")
|
|
{
|
|
CBotChatManager::getInstance()->debugLocalReceiveMissionInfo();
|
|
return true;
|
|
}
|
|
|
|
// command to dump the ui, no indentation full name
|
|
NLMISC_COMMAND(dumpUIIndent, "Debug only : Dump the ui hierarchy in the output debug window", "")
|
|
{
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->dumpUI(true);
|
|
return true;
|
|
}
|
|
|
|
// command to dump the ui, no indentation full name
|
|
NLMISC_COMMAND(dumpUIFull, "Debug only : Dump the ui hierarchy in the output debug window", "")
|
|
{
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->dumpUI(false);
|
|
return true;
|
|
}
|
|
|
|
// command to dump coordinates of a UI, for debug
|
|
NLMISC_COMMAND(dumpUICoords, "Debug only : dump all coords info of an UI", "uiid")
|
|
{
|
|
if(args.size()!=1)
|
|
return false;
|
|
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
CInterfaceElement *el= pIM->getElementFromId(args[0]);
|
|
if(!el)
|
|
{
|
|
pIM->displaySystemInfo(toString("dumpUICoords: '%s' does not exist", args[0].c_str()));
|
|
}
|
|
else
|
|
{
|
|
pIM->displaySystemInfo(toString("dumpUICoords: **** '%s'", args[0].c_str()));
|
|
pIM->displaySystemInfo(toString(" active= %d", uint(el->getActive()) ));
|
|
pIM->displaySystemInfo(toString(" x= %d", el->getX() ));
|
|
pIM->displaySystemInfo(toString(" y= %d", el->getY() ));
|
|
pIM->displaySystemInfo(toString(" w= %d", el->getW() ));
|
|
pIM->displaySystemInfo(toString(" h= %d", el->getH() ));
|
|
pIM->displaySystemInfo(toString(" xreal= %d", el->getXReal() ));
|
|
pIM->displaySystemInfo(toString(" yreal= %d", el->getYReal() ));
|
|
pIM->displaySystemInfo(toString(" wreal= %d", el->getWReal() ));
|
|
pIM->displaySystemInfo(toString(" hreal= %d", el->getHReal() ));
|
|
pIM->displaySystemInfo(toString(" parent= '%s'", el->getParent()?el->getParent()->getId().c_str():""));
|
|
pIM->displaySystemInfo(toString(" parentpos= '%s'", el->getParentPos()?el->getParentPos()->getId().c_str():""));
|
|
pIM->displaySystemInfo(toString(" parentsize= '%s'", el->getParentSize()?el->getParentSize()->getId().c_str():""));
|
|
|
|
// SizeRef
|
|
string sr;
|
|
switch(el->getSizeRef())
|
|
{
|
|
case 1: sr= "w"; break;
|
|
case 2: sr= "h"; break;
|
|
case 3: sr= "wh"; break;
|
|
default:break;
|
|
}
|
|
pIM->displaySystemInfo(toString(" sizeref= '%s'", sr.c_str()));
|
|
|
|
// PosRef
|
|
string pr;
|
|
THotSpot hsParent= el->getParentPosRef();
|
|
THotSpot hsSelf= el->getPosRef();
|
|
// parent
|
|
if(hsParent & Hotspot_Bx) pr+= "B";
|
|
else if(hsParent & Hotspot_Mx) pr+= "M";
|
|
else if(hsParent & Hotspot_Tx) pr+= "T";
|
|
else pr+= "?";
|
|
if(hsParent & Hotspot_xL) pr+= "L";
|
|
else if(hsParent & Hotspot_xM) pr+= "M";
|
|
else if(hsParent & Hotspot_xR) pr+= "R";
|
|
else pr+= "?";
|
|
pr+=" ";
|
|
// self
|
|
if(hsSelf & Hotspot_Bx) pr+= "B";
|
|
else if(hsSelf & Hotspot_Mx) pr+= "M";
|
|
else if(hsSelf & Hotspot_Tx) pr+= "T";
|
|
else pr+= "?";
|
|
if(hsSelf & Hotspot_xL) pr+= "L";
|
|
else if(hsSelf & Hotspot_xM) pr+= "M";
|
|
else if(hsSelf & Hotspot_xR) pr+= "R";
|
|
else pr+= "?";
|
|
pIM->displaySystemInfo(toString(" posref= '%s'", pr.c_str()));
|
|
|
|
pIM->displaySystemInfo(string("dumpUICoords: **** END"));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Command to clear the dump of done Files opened and Async File Manager done files (for debug)
|
|
NLMISC_COMMAND(clearDumpFiles, "clear the CAsyncFileManager and CIFile Debug list of opened files", "")
|
|
{
|
|
CIFile::clearDump();
|
|
CAsyncFileManager::getInstance().clearDump();
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif // FINAL_VERSION
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////// COMMANDS before should NOT appear IN the FINAL VERSION //////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
NLMISC_COMMAND(reloadFogMaps, "Force to reload all the fog maps", "<>")
|
|
{
|
|
if (!args.empty()) return false;
|
|
ContinentMngr.cur()->reloadFogMap();
|
|
return true;
|
|
}
|
|
|
|
// dump the names of all loaded sounds
|
|
NLMISC_COMMAND(dumpSounds, "Dump names of all loaded sound", "<>")
|
|
{
|
|
if (!args.empty()) return false;
|
|
std::vector<NLMISC::TStringId> sounds;
|
|
extern CSoundManager *SoundMngr;
|
|
if (!SoundMngr) return false;
|
|
if (!SoundMngr->getMixer()) return false;
|
|
SoundMngr->getMixer()->getSoundNames(sounds);
|
|
for(uint k = 0; k < sounds.size(); ++k)
|
|
{
|
|
nlinfo(NLMISC::CStringMapper::unmap(sounds[k]).c_str());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
// LUA
|
|
// ***************************************************************************
|
|
const char *LUADebugNotEnabledMsg= "Lua Commands are available only if you add 'AllowDebugLua= 1;' in your client.cfg";
|
|
|
|
NLMISC_COMMAND(luaReload, "reload all .lua script files", "")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
if(ClientCfg.AllowDebugLua)
|
|
{
|
|
pIM->reloadAllLuaFileScripts();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
pIM->displaySystemInfo(pIM->formatLuaErrorSysInfo(LUADebugNotEnabledMsg));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
NLMISC_COMMAND(luaScript, "Execute a lua script", "direct_script_code")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
if(ClientCfg.AllowDebugLua)
|
|
{
|
|
if(args.size()<1)
|
|
return false;
|
|
|
|
// Concat list of string in one script
|
|
string script;
|
|
for(uint i=0;i<args.size();i++)
|
|
{
|
|
script+= args[i] + " ";
|
|
}
|
|
|
|
// not smallScript because suppose var can change a lot
|
|
pIM->executeLuaScript(script, false);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
pIM->displaySystemInfo(pIM->formatLuaErrorSysInfo(LUADebugNotEnabledMsg));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
NLMISC_COMMAND(luaInfo, "Dump some informations on LUA state", "detaillevel from 0 to 2")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
if(ClientCfg.AllowDebugLua)
|
|
{
|
|
if(args.size()!=1)
|
|
return false;
|
|
|
|
uint detail;
|
|
fromString(args[0], detail);
|
|
|
|
pIM->dumpLuaState(detail);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
pIM->displaySystemInfo(pIM->formatLuaErrorSysInfo(LUADebugNotEnabledMsg));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
NLMISC_COMMAND(luaObject, "Dump the content of a lua object", "<table name> [maxDepth = 20, 0 for no limits]")
|
|
{
|
|
if (args.empty()) return false;
|
|
if (args.size() > 2) return false;
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
if (!ClientCfg.AllowDebugLua)
|
|
{
|
|
pIM->displaySystemInfo(pIM->formatLuaErrorSysInfo(LUADebugNotEnabledMsg));
|
|
return false;
|
|
}
|
|
CLuaState *luaState = pIM->getLuaState();
|
|
if (!luaState) return false;
|
|
CLuaStackChecker lsc(luaState);
|
|
// get the table
|
|
static const char *inspectedTable = "_____inspected_table";
|
|
try
|
|
{
|
|
// make a reference to the table to be inspected (is this this a primitive type, just make a copy)
|
|
luaState->executeScript(std::string(inspectedTable) + " = " + args[0]);
|
|
}
|
|
catch(ELuaError &e)
|
|
{
|
|
CLuaIHM::debugInfo(e.what());
|
|
return false;
|
|
}
|
|
luaState->pushValue(LUA_GLOBALSINDEX);
|
|
CLuaObject env;
|
|
env.pop(*luaState);
|
|
uint maxDepth;
|
|
if (args.size() > 1)
|
|
fromString(args[1], maxDepth);
|
|
else
|
|
maxDepth = 20;
|
|
//CLuaIHM::debugInfo(env[inspectedTable].toStringRecurse(0, maxDepth));
|
|
env[inspectedTable].dump();
|
|
env.eraseValue(inspectedTable);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
// GC allowed only in Dev version
|
|
#if !FINAL_VERSION
|
|
NLMISC_COMMAND(luaGC, "Force a garbage collector of lua", "")
|
|
{
|
|
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
if(ClientCfg.AllowDebugLua)
|
|
{
|
|
pIM->luaGarbageCollect();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
pIM->displaySystemInfo(pIM->formatLuaErrorSysInfo(LUADebugNotEnabledMsg));
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
// ***************************************************************************
|
|
// CUserCommand
|
|
// ***************************************************************************
|
|
|
|
std::map<std::string, CUserCommand*> CUserCommand::CommandMap;
|
|
|
|
// release memory
|
|
void CUserCommand::release()
|
|
{
|
|
std::map<std::string, CUserCommand*>::iterator it = CommandMap.begin();
|
|
while( it != CommandMap.end() )
|
|
delete (*it++).second;
|
|
CommandMap.clear();
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
CUserCommand::CUserCommand(const string &commandName, const ucstring &help, const ucstring &argsHelp)
|
|
: ICommand("user", commandName.c_str(), toString(help).c_str(), toString(argsHelp).c_str())
|
|
{
|
|
CommandName = commandName;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CUserCommand::addMode (const string &action, uint numArg, bool infiniteAgr, const std::vector<string> &keywords)
|
|
{
|
|
CMode *mode;
|
|
if (!infiniteAgr)
|
|
mode = &(FixedArgModes[numArg]);
|
|
else
|
|
mode = &InfiniteMode;
|
|
mode->Action = action;
|
|
mode->KeywordsCount = numArg;
|
|
mode->Keywords = keywords;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CUserCommand::execute(const std::string &/* rawCommandString */, const std::vector<std::string> &args, NLMISC::CLog &/* log */, bool /* quiet */, bool /* human */)
|
|
{
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
|
|
// Find the good keyword table
|
|
CMode *mode = NULL;
|
|
if (FixedArgModes.find (args.size()) != FixedArgModes.end())
|
|
mode = &(FixedArgModes[args.size()]);
|
|
else
|
|
if (!InfiniteMode.Keywords.empty() && (args.size() >= InfiniteMode.KeywordsCount))
|
|
mode = &InfiniteMode;
|
|
|
|
if (mode)
|
|
{
|
|
// Build the final string
|
|
static string finalArgs;
|
|
finalArgs = "";
|
|
uint i;
|
|
uint index = 0;
|
|
const vector<string> &keywords = mode->Keywords;
|
|
for (i=0; i<keywords.size(); i++)
|
|
{
|
|
if ((keywords[i] == "$") || (keywords[i] == "+"))
|
|
{
|
|
if ((uint)index >= args.size())
|
|
{
|
|
// Not enough argument
|
|
pIM->displaySystemInfo (ucstring(CommandName+" : ")+CI18N::get ("uiCommandWrongArgumentCount"));
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (keywords[i] == "$")
|
|
finalArgs += /*ucstring(*/args[index++]/*).toUtf8()*/;
|
|
else
|
|
{
|
|
finalArgs += /*ucstring(*/args[index++]/*).toUtf8()*/;
|
|
while (index<args.size())
|
|
{
|
|
finalArgs += " ";
|
|
finalArgs += /*ucstring(*/args[index++]/*).toUtf8()*/;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
finalArgs += keywords[i];
|
|
}
|
|
}
|
|
|
|
// Run the action handler
|
|
pIM->runActionHandler (mode->Action, pIM->getOldCaptureKeyboard(), finalArgs);
|
|
}
|
|
else
|
|
{
|
|
// Not enough argument
|
|
pIM->displaySystemInfo (ucstring(CommandName+" : ")+CI18N::get ("uiCommandWrongArgumentCount"));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CUserCommand::createCommand (const char *name, const char *action, const char *ptrParams)
|
|
{
|
|
// Parse the params
|
|
std::vector<string> keywords;
|
|
|
|
// Get the help and the argument help
|
|
uint countArgument = 0;
|
|
bool infiniteArgument = false;
|
|
string params = ptrParams;
|
|
string::size_type pos = 0;
|
|
while (pos < params.size())
|
|
{
|
|
// Token ?
|
|
string::size_type last;
|
|
switch (params[pos])
|
|
{
|
|
case '|':
|
|
case '=':
|
|
case '$':
|
|
case '+':
|
|
if ((params[pos] == '$') || (params[pos] == '+'))
|
|
countArgument++;
|
|
if (params[pos] == '+')
|
|
infiniteArgument = true;
|
|
last = pos+1;
|
|
break;
|
|
default:
|
|
last = params.find_first_of ("|=$+", pos);
|
|
if (last == string::npos)
|
|
last = params.size();
|
|
break;
|
|
}
|
|
|
|
// Add a keyword
|
|
keywords.push_back (params.substr (pos, last-pos));
|
|
pos = last;
|
|
}
|
|
|
|
// Find action name
|
|
ucstring help;
|
|
const CBaseAction *ab = Actions.getBaseAction (::CAction::CName (action, ptrParams));
|
|
if (ab)
|
|
help = CI18N::get(ab->LocalizedName);
|
|
|
|
// Build a argument help
|
|
ucstring argsHelp;
|
|
|
|
if (ab)
|
|
{
|
|
// Look for each arguments
|
|
uint i;
|
|
for (i=0; i<keywords.size(); i++)
|
|
{
|
|
// Look for a '$'
|
|
if ((keywords[i] == "$") || (keywords[i] == "+"))
|
|
{
|
|
// Have a "=" ?
|
|
if ((i > 1) && (keywords[i-1]=="="))
|
|
{
|
|
// Argument
|
|
bool bFound = false;
|
|
for (uint j=0; j<ab->Parameters.size(); j++)
|
|
{
|
|
// Argument found
|
|
if (ab->Parameters[j].Name == keywords[i-2])
|
|
{
|
|
// Add the string
|
|
if (!argsHelp.empty())
|
|
argsHelp += " ";
|
|
argsHelp += ucstring("<") + CI18N::get(ab->Parameters[j].LocalizedName) + ucstring(">");
|
|
bFound = true;
|
|
}
|
|
}
|
|
// Not found ? Warning
|
|
if (!bFound)
|
|
{
|
|
nlwarning ("Argument %s not found in command %s using action %s", keywords[i-2].c_str(), name, action);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ugly : never deleted, but who cares ?
|
|
// Command exist ?
|
|
CUserCommand *currentCommand;
|
|
if (CommandMap.find (name) != CommandMap.end())
|
|
currentCommand = CommandMap[name];
|
|
else
|
|
{
|
|
currentCommand = new CUserCommand (name, help, argsHelp);
|
|
CommandMap[name] = currentCommand;
|
|
}
|
|
|
|
// Add keywords
|
|
currentCommand->addMode (action, countArgument, infiniteArgument, keywords);
|
|
}
|
|
|
|
NLMISC_COMMAND(doAssert, "Create an assert", "")
|
|
{
|
|
nlassert(0);
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpPosAsPrim, "ld helper : add current position to pos.primitive with the given comment", "")
|
|
{
|
|
if (!EntitiesMngr.entity(0)) return false;
|
|
std::string comment;
|
|
for(uint k = 0; k < args.size(); ++k)
|
|
{
|
|
if (k != 0) comment += " ";
|
|
comment += args[k];
|
|
}
|
|
std::string srcFile;
|
|
const std::string path = "save/pos.primitive";
|
|
if (CFile::fileExists(path))
|
|
{
|
|
try
|
|
{
|
|
uint32 fileSize = CFile::getFileSize(path);
|
|
srcFile.resize(fileSize);
|
|
CIFile stream;
|
|
stream.open(path);
|
|
stream.serialBuffer((uint8 *) &srcFile[0], fileSize);
|
|
}
|
|
catch(NLMISC::EStream &e)
|
|
{
|
|
nlinfo(e.what());
|
|
srcFile.clear();
|
|
}
|
|
}
|
|
std::string newPrim =
|
|
NLMISC::toString("<CHILD TYPE=\"CPrimPoint\"> \n\
|
|
<PT X=\"%f\" Y=\"%f\" Z=\"%f\"/> \n\
|
|
<PROPERTY TYPE=\"string\"> \n\
|
|
<NAME>class</NAME> \n\
|
|
<STRING>plot</STRING> \n\
|
|
</PROPERTY> \n\
|
|
<PROPERTY TYPE=\"string\"> \n\
|
|
<NAME>name</NAME> \n\
|
|
<STRING>%s</STRING> \n\
|
|
</PROPERTY> \n\
|
|
</CHILD>\n", (float) EntitiesMngr.entity(0)->pos().x, (float) EntitiesMngr.entity(0)->pos().y, (float) EntitiesMngr.entity(0)->pos().z, comment.c_str());
|
|
|
|
// try to append result to current file
|
|
const std::string LAST_CHILD_MARKER = "</CHILD>";
|
|
std::string::size_type insertPos = srcFile.rfind(LAST_CHILD_MARKER);
|
|
if (insertPos != std::string::npos)
|
|
{
|
|
insertPos += LAST_CHILD_MARKER.size();
|
|
srcFile.insert(insertPos, "\n" + newPrim);
|
|
}
|
|
else
|
|
{
|
|
srcFile.clear();
|
|
}
|
|
if (srcFile.empty())
|
|
{
|
|
srcFile = "<?xml version=\"1.0\"?> \n\
|
|
<PRIMITIVES VERSION=\"1\"> \n\
|
|
<ROOT_PRIMITIVE TYPE=\"CPrimNode\"> \n"
|
|
+ newPrim
|
|
+ " </ROOT_PRIMITIVE> \n\
|
|
</PRIMITIVES>\n";
|
|
}
|
|
|
|
// write result
|
|
try
|
|
{
|
|
COFile stream;
|
|
stream.open(path);
|
|
stream.serialBuffer((uint8 *) &srcFile[0], srcFile.size());
|
|
}
|
|
catch(NLMISC::EStream &e)
|
|
{
|
|
nlinfo(e.what());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(clear, "clear content of current char window", "<chat window caller id>")
|
|
{
|
|
if (args.size() > 1) return false;
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
im->flushDebugWindow();
|
|
CChatWindow *cw;
|
|
if (args.size() == 1)
|
|
{
|
|
cw = getChatWndMgr().getChatWindowFromCaller(dynamic_cast<CCtrlBase *>(im->getElementFromId(args[0])));
|
|
}
|
|
else
|
|
{
|
|
// if no chat window (or enclosed control) id is given then see if a chat window called this command
|
|
cw = CChatWindow::getChatWindowLaunchingCommand();
|
|
}
|
|
if (cw && cw->getContainer())
|
|
{
|
|
CGroupList *gl = dynamic_cast<CGroupList *>(cw->getContainer()->getGroup("text_list"));
|
|
if (gl)
|
|
{
|
|
gl->deleteAllChildren();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NLMISC_COMMAND(dumpAllLoadedZones, "dump all loaded zones", "")
|
|
{
|
|
if (!args.empty()) return false;
|
|
if (Landscape)
|
|
{
|
|
std::vector<std::string> loadedZones;
|
|
Landscape->getAllZoneLoaded(loadedZones);
|
|
for(uint k = 0; k < loadedZones.size(); ++k)
|
|
{
|
|
nlwarning(loadedZones[k].c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nlwarning("Landscape has no loaded zones ");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(tickToDate, "convert a tick value into a readable ryzom time", "")
|
|
{
|
|
if (args.size() != 1) return false;
|
|
CRyzomTime rt;
|
|
uint32 tick;
|
|
fromString(args[0], tick);
|
|
rt.updateRyzomClock(tick);
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
float ryTime = rt.getRyzomTime();
|
|
std::string readableDate = toString("Day = %d, hour = %d:%d", rt.getRyzomDay(), (int) floorf(ryTime), (int) floorf(60.f * fmodf(ryTime, 1.f)));
|
|
im->displaySystemInfo(ucstring(readableDate));
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(dumpShapeMaxDist, "dump max dist for shapes", "")
|
|
{
|
|
/*
|
|
std::set<std::string> shapeSet;
|
|
typedef CHashMultiMap<float, std::string> TShapeMap;
|
|
TShapeMap shapes;
|
|
const CSheetManager::TEntitySheetMap &sheets = SheetMngr.getSheets();
|
|
std::vector<const CCharacterSheet::CEquipment*> equipList;
|
|
for (CSheetManager::TEntitySheetMap::const_iterator it = sheets.begin(); it != sheets.end(); ++it)
|
|
{
|
|
CCharacterSheet *cs = dynamic_cast<CCharacterSheet *>(SheetMngr.get(it->first));
|
|
if (cs)
|
|
{
|
|
equipList.clear();
|
|
cs->getWholeEquipmentList(equipList);
|
|
for (uint k = 0; k < equipList.size(); ++k)
|
|
{
|
|
std::string item = toLower(equipList[k]->getItem());
|
|
if (!item.empty())
|
|
{
|
|
|
|
string ext = CFile::getExtension(item);
|
|
if (ext == "shape")
|
|
{
|
|
if (!shapeSet.count(item))
|
|
{
|
|
UInstance inst = Scene->createInstance(item);
|
|
if (!inst.empty())
|
|
{
|
|
shapes.insert(make_pair(inst.getDistMax(), item));
|
|
Scene->deleteInstance(inst);
|
|
}
|
|
shapeSet.insert(item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (TShapeMap::iterator it = shapes.begin(); it != shapes.end(); ++it)
|
|
{
|
|
nlwarning("Dist = %f, shape = %s", it->first, it->second.c_str());
|
|
}
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
|
|
NLMISC_COMMAND(dumpContinentCorners, "dump max dist for shapes", "")
|
|
{
|
|
if (!args.empty()) return false;
|
|
if (!ContinentMngr.cur()) return false;
|
|
|
|
CVector2f posMin;
|
|
CVector2f posMax;
|
|
getPosFromZoneName(ContinentMngr.cur()->ZoneMin, posMin);
|
|
getPosFromZoneName(ContinentMngr.cur()->ZoneMax, posMax);
|
|
if (posMin.x > posMax.x) std::swap(posMin.x, posMax.x);
|
|
if (posMin.y > posMax.y) std::swap(posMin.y, posMax.y);
|
|
posMax.x += 160.f;
|
|
posMax.y += 160.f;
|
|
nlwarning("min = (%f, %f), max = (%f, %f)", posMin.x, posMin.y, posMax.x, posMax.y);
|
|
return true;
|
|
}
|
|
|
|
|
|
#if !FINAL_VERSION
|
|
NLMISC_COMMAND(setMission, "locally set a mission text for test", "<mission index><text>")
|
|
{
|
|
if (!ClientCfg.Local) return false;
|
|
if (args.size() != 2) return false;
|
|
uint index;
|
|
fromString(args[0], index);
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
static sint32 strID = 10000; // any abitrary string id will do in local
|
|
if (index >= 30) return false;
|
|
if (index < 15)
|
|
{
|
|
im->getDbProp(toString("SERVER:MISSIONS:%d:TITLE", (int) index))->setValue32(strID);
|
|
im->getDbProp(toString("SERVER:MISSIONS:%d:FINISHED", (int) index))->setValue32(0);
|
|
}
|
|
else
|
|
{
|
|
im->getDbProp(toString("SERVER:GROUP:MISSIONS:%d:TITLE", (int) index - 15))->setValue32(strID);
|
|
im->getDbProp(toString("SERVER:GROUP:MISSIONS:%d:FINISHED", (int) index - 15))->setValue32(0);
|
|
}
|
|
setDynString(strID++, args[1]);
|
|
return true;
|
|
}
|
|
|
|
static bool setMissionStep(uint missionIndex, uint stepIndex, uint32 strID)
|
|
{
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
if (stepIndex >= 30) return false;
|
|
if (stepIndex >= 20) return false;
|
|
if (missionIndex < 15)
|
|
{
|
|
im->getDbProp(toString("SERVER:MISSIONS:%d:GOALS:%d:TEXT", (int) missionIndex, (int) stepIndex))->setValue32(strID);
|
|
}
|
|
else
|
|
{
|
|
im->getDbProp(toString("SERVER:GROUP:MISSIONS:%d:GOALS:%d:TEXT", (int) (missionIndex - 15), (int) stepIndex))->setValue32(strID);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// add a new step in a mission, the mission must already exist
|
|
NLMISC_COMMAND(setMissionStep, "locally set a mission step for test", "<mission index><step index><text>")
|
|
{
|
|
if (!ClientCfg.Local) return false;
|
|
if (args.size() != 3) return false;
|
|
uint missionIndex;
|
|
fromString(args[0], missionIndex);
|
|
uint stepIndex;
|
|
fromString(args[1], stepIndex);
|
|
|
|
static sint32 strID = 20000; // any abitrary string id will do in local
|
|
if (!setMissionStep(missionIndex, stepIndex, strID)) return false;
|
|
setDynString(strID++, args[2]);
|
|
return true;
|
|
}
|
|
|
|
// add a newstepin a mission, the mission must already exist
|
|
NLMISC_COMMAND(clearMissionStep, "locally set a mission step for test", "<mission index><step index><text>")
|
|
{
|
|
if (!ClientCfg.Local) return false;
|
|
if (args.size() != 2) return false;
|
|
uint missionIndex;
|
|
fromString(args[0], missionIndex);
|
|
uint stepIndex;
|
|
fromString(args[1], stepIndex);
|
|
return setMissionStep(missionIndex, stepIndex, 0);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#if !FINAL_VERSION
|
|
static bool debugSetMissionState(uint index, sint32 /* state */)
|
|
{
|
|
if (index >= 30) return false;
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
if (index < 15)
|
|
{
|
|
im->getDbProp(toString("SERVER:MISSIONS:%d:TITLE", (int) index))->setValue32(0);
|
|
}
|
|
else
|
|
{
|
|
im->getDbProp(toString("SERVER:GROUP:MISSIONS:%d:TITLE", (int) index - 15))->setValue32(0);
|
|
}
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !FINAL_VERSION
|
|
NLMISC_COMMAND(clearMission, "clear the content of a mission", "<mission index>")
|
|
{
|
|
if (!ClientCfg.Local) return false;
|
|
if (args.size() != 1) return false;
|
|
uint index;
|
|
fromString(args[0], index);
|
|
return debugSetMissionState(index, 0);
|
|
|
|
}
|
|
#endif
|
|
|
|
#if !FINAL_VERSION
|
|
NLMISC_COMMAND(finishMission, "clear the content of a mission", "<mission index>")
|
|
{
|
|
if (!ClientCfg.Local) return false;
|
|
if (args.size() != 1) return false;
|
|
uint index;
|
|
fromString(args[0], index);
|
|
return debugSetMissionState(index, 1);
|
|
}
|
|
#endif
|
|
|
|
#if !FINAL_VERSION
|
|
NLMISC_COMMAND(failMission, "clear the content of a mission", "<mission index>")
|
|
{
|
|
if (!ClientCfg.Local) return false;
|
|
if (args.size() != 1) return false;
|
|
uint index;
|
|
fromString(args[0], index);
|
|
return debugSetMissionState(index, 2);
|
|
}
|
|
#endif
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
NLMISC_COMMAND(em, "emote command", "<emote phrase>")
|
|
{
|
|
if (args.size() < 1) return false;
|
|
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
if( pIM )
|
|
{
|
|
string emotePhrase;
|
|
if( args.size() > 0 )
|
|
{
|
|
emotePhrase = args[0];
|
|
}
|
|
for(uint i = 1; i < args.size(); ++i )
|
|
{
|
|
emotePhrase += " ";
|
|
emotePhrase += args[i];
|
|
}
|
|
pIM->runActionHandler("emote", NULL, "nb=0|behav=255|custom_phrase="+emotePhrase);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
NLMISC_COMMAND(guildmotd, "Set the guild message of the day","<msg of the day>")
|
|
{
|
|
CBitMemStream out;
|
|
if (!GenericMsgHeaderMngr.pushNameToStream("COMMAND:GUILDMOTD", out))
|
|
return false;
|
|
|
|
string gmotd;
|
|
if( args.size() > 0 )
|
|
{
|
|
gmotd = args[0];
|
|
}
|
|
for(uint i = 1; i < args.size(); ++i )
|
|
{
|
|
gmotd += " ";
|
|
gmotd += args[i];
|
|
}
|
|
|
|
out.serial (gmotd);
|
|
NetMngr.push (out);
|
|
|
|
return true;
|
|
}
|