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.
ryzom-core/code/ryzom/client/src/commands.cpp

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;
}