// Ryzom - MMORPG Framework // 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 . // // User Privilege set in the mysql database must be like that ":GM:" or "" or ":GM:ADMIN:" .... // // // // // Includes // #include "stdpch.h" #include "admin.h" #include "nel/misc/common.h" #include "nel/misc/command.h" #include "nel/misc/variable.h" #include "nel/misc/eid_translator.h" #include "nel/misc/algo.h" #include "nel/misc/sstring.h" #include "nel/net/admin.h" #include "nel/net/service.h" #include "game_share/scores.h" #include "game_share/send_chat.h" #include "game_share/time_weather_season/time_date_season_manager.h" #include "game_share/permanent_ban_magic_number.h" #include "game_share/fame.h" #include "game_share/outpost.h" #include "game_share/visual_slot_manager.h" #include "game_share/shard_names.h" #include "game_share/http_client.h" #include "server_share/log_command_gen.h" #include "server_share/r2_vision.h" #include "egs_sheets/egs_sheets.h" #include "egs_sheets/egs_static_rolemaster_phrase.h" #include "egs_sheets/egs_static_encyclo.h" #include "player_manager/player_manager.h" #include "player_manager/player.h" #include "player_manager/character.h" #include "player_manager/character_encyclopedia.h" #include "creature_manager/creature_manager.h" #include "phrase_manager/phrase_manager.h" #include "mission_manager/mission_manager.h" #include "mission_manager/mission_queue_manager.h" #include "entities_game_service.h" #include "player_manager/character_respawn_points.h" #include "weather_everywhere.h" #include "phrase_manager/fg_prospection_phrase.h" #include "team_manager/team_manager.h" #include "world_instances.h" #include "egs_variables.h" #include "building_manager/building_manager.h" #include "building_manager/building_physical.h" #include "player_manager/gm_tp_pending_command.h" #include "guild_manager/guild_manager.h" #include "guild_manager/guild.h" #include "guild_manager/guild_member.h" #include "guild_manager/guild_member_module.h" #include "guild_manager/guild_char_proxy.h" #include "guild_manager/fame_manager.h" #include "mission_manager/mission_solo.h" #include "mission_manager/mission_solo.h" #include "position_flag_manager.h" //#include "name_manager.h" #include "zone_manager.h" #include "player_manager/character_game_event.h" #include "game_event_manager.h" #include "dyn_chat_egs.h" #include "pvp_manager/pvp.h" #include "pvp_manager/pvp_manager_2.h" #include "player_manager/admin_properties.h" #include "shop_type/offline_character_command.h" #include "player_manager/item_service_manager.h" #include "outpost_manager/outpost_manager.h" #include "primitives_parser.h" #include "shop_type/named_items.h" #include "progression/progression_pvp.h" #include "modules/shard_unifier_client.h" #include "modules/client_command_forwarder.h" #include "modules/guild_unifier.h" #include "server_share/log_command_gen.h" #include "server_share/log_item_gen.h" #include "server_share/log_character_gen.h" #include "server_share/used_continent.h" // // Externs // // Max number of user channel character can be have #define NB_MAX_USER_CHANNELS 2 extern CPlayerManager PlayerManager; extern CCreatureManager CreatureManager; extern CPlayerService *PS; extern CGenericXmlMsgHeaderManager GenericMsgManager; extern CBSAIDeathReport BotDeathReport; extern NLMISC::CVariable FixedSessionId; // // Namespaces // using namespace NLMISC; using namespace NLNET; using namespace std; extern CVariable BannerPriv; // // Functions // // // ALL THESE COMMANDS ARE USED BY THE CLIENT *AND* THE ADMIN TOOL TO MANAGE A PLAYER // // You can assume here that the user can execute the command, you don't have to check it // // Don't forget to add your command in the AdminCommandsInit array if you want the command to be executed on the client // // If you change parameter or add/remove something, please update the wiki: // // http://www.nevrax.net/wiki/index.php/Main/CommandesAdmin // // AddEid must be true if you want to have the eid in the args[0] of the command // Privileges are now stored in a text file (data_shard/client_commands_privileges.txt), do not forget to update it. // please update the following stuff if you add new GM titles // player_manager.cpp : NLMISC_COMMAND(setPriv,"set a privilege to a user using his user id, must be in form :priv1:priv2:priv3:"," ") // player_manager.cpp : hasBetterCSRGrade static const struct { const char * Name; bool AddEId; } AdminCommandsInit[] = { // player character accessible commands "teamInvite", true, "setLeague", true, "leagueInvite", true, "leagueKick", true, "guildInvite", true, "roomInvite", true, "roomKick", true, "setGuildMessage", true, "clearGuildMessage", true, "dodge", true, "parry", true, "respawnAfterDeath", true, "resurrected", true, "validateRespawnPoint", true, "summonPet", true, "connectUserChannel", true, "connectLangChannel", true, "updateTarget", true, "resetName", true, "showOnline", true, // Web commands managment "webExecCommand", true, "webDelCommandsIds", true, "webAddCommandsIds", true, "addPetAnimal", true, "addSkillPoints", true, "addXPToSkill", true, "changeMode", true, "checkTargetSP", true, "clearFriendsList", true, "clearIgnoreList", true, "clearIsFriendOfList", true, "createItemInBag", true, "createItemInInv", true, "createItemInTmpInv", true, "createNamedItemInBag", true, "createFullArmorSet", true, "displayInfosOnTarget", true, "execPhrase", true, "execMemorizedPhrase", true, "executeSabrinaPhrase", true, "forceTargetToDie", true, "learnAllBricks", true, "learnAllRolemasterBricks", true, "learnAllPhrases", true, "learnBrick", true, "unlearnBrick", true, "learnPhrase", true, "learnAllForagePhrases", true, "learnAllFaberPlans", true, "logXpGain", true, "memorizePhrase", true, "resetPowerFlags", true, "setSkillsToMaxValue", true, "displayForageRM", true, "setItemSapLoad", true, "showFBT", true, "allowSummonPet", true, "setPetAnimalSatiety", true, "getPetAnimalSatiety", true, "setPetAnimalName", true, "taskPass", true, "setFamePlayer", true, "guildMOTD", true, // CSR commands "setSalt", true, "motd", false, "broadcast", false, "summon", true, "dismiss", true, "teleport", true, "renamePlayerForEvent", true, "renamePlayer", true, "renameGuild", true, "setGuildDescription", false, "setGuildIcon", false, "killMob", true, "changeVar", true, "root", true, "unroot", true, "ignoreTells", true, // hierarchy "showCSR", true, "monitorMissions", true, "stopMonitorMissions", true, "failMission", true, "progressMission", true, "mute", true, "unmute", true, "muteUniverse", true, "unmuteUniverse", true, "universe", true, "setGMGuild", true, "targetInfos", true, "infos", true, "addPosFlag", true, "setPosFlag", true, "delPosFlag", true, "lPosFlags", true, "listPosFlags", true, "tpPosFlag", true, "updateGuildMembersList", true, "listGuildMembers", true, "addGuildMember", true, "setGuildMemberGrade", true, "setGuildLeader", true, "startEvent", true, "stopEvent", true, "getEventFaction", true, "setEventFaction", true, "clearEventFaction", true, "giveRespawnPoint", true, "provideItemService", true, "dumpFactionPVPDamage", true, "changeHairCut", true, "farTPPush", true, "farTPReplace", true, "farTPReturn", true, "resetPVPTimers", true, "savePlayerActiveChar", false, "reloadPlayer", false, "characterMissionDump", true, "removeMission", true, "addMission", true, // CSR variables "Invisible", true, // not in /who; hierarchy except for user with privilege "God", true, "Invulnerable", true, "ShowFactionChannels", true, "CreateCharacterStartSkillsValue", false, "HP", true, "MaxHP", true, "Speed", true, "Money", true, "MoneyGuild", true, "FactionPoint", true, "Name", true, "Position", true, "Priv", true, "PriviledgePVP", true, "FullPVP", true, "FBT", true, "RyzomDate", false, "RyzomTime", false, "addGuildXp", false, "setGuildChargePoint", false, "characterInventoryDump", true, "deleteInventoryItem", true, "setSimplePhrase", false, // PUT HERE THE VARIABLE / COMMAND THAT ARE TEMPORARY // remove when message of the day interface is ready // remove this when death interface is ready "respawnCharacter", true, "buyPact", true, "cancelTopPhrase", true, //temp : to remove "EntitiesNoActionFailure", false, "EntitiesNoCastBreak", false, "EntitiesNoResist", false, "lockItem", true, "setTeamLeader", true, // aggroable state "Aggro", true, // outpost commands "outpostBanGuild", false, "outpostBanPlayer", false, "outpostUnbanGuild", false, "outpostUnbanPlayer", false, "outpostChallengeByGuild", false, "outpostSimulateTimer0End", false, "outpostSimulateTimer1End", false, "outpostSimulateTimer2End", false, "outpostSetFightData", false, "setOutpostLevel", false, "outpostAccelerateConstruction", false, "outpostSetOutpostOwner", false, "outpostChallengeOutpost", true, "outpostGiveupOutpost", true, "outpostDisplayGuildOutposts", true, "outpostForceOpenGuildInventory", true, "outpostForceCloseGuildInventory", true, "outpostSetPlayerPvpSide", true, "outpostSetOutpostToPlayer", true, "outpostSelectOutpost", true, "outpostUnselectOutpost", true, "setPvpClan", true, //remove it when interface fo choose pvp clan is ready "setPvPTag", true, //set pvp tag to true or false // stuff added by sadge for testing character read/ write stuff "saveToXML", true, "loadFromXML", true, "saveToPDR", true, "loadFromPDR", true, // queues related stuff "acceptProposalForQueue", true, "awakePlayerInQueue", true, "displayShopSelector", true, "addFactionAttackableToTarget", true, "eventCreateNpcGroup", true, "eScript", true, "eventNpcGroupScript", true, "eventSetBotName", true, "eventSetBotScale", true, "eventSetNpcGroupAggroRange", true, "eventSetNpcGroupEmote", true, "eventSetFaunaBotAggroRange", true, "eventResetFaunaBotAggroRange", true, "eventSetBotCanAggro", true, "eventSetItemCustomText", true, "eventResetItemCustomText", true, "eventSetBotSheet", true, "eventSetBotFaction", true, "eventSetBotFameByKill", true, "dssTarget", true, //ring stuff "forceMissionProgress", true, "eventSetBotURL", true, "eventSetBotURLName", true, "eventSpawnToxic", true, "eventNpcSay", true, "eventSetBotFacing", true, "eventGiveControl", true, "eventLeaveControl", true, "setOrganization", true, "setOrganizationStatus", true, "addGuildBuilding", true, }; static vector AdminCommands; static string CommandsPrivilegesFileName; static string PositionFlagsFileName; static const char * DefaultPriv = ":DEV:"; static string Salt; // forward declarations static void loadCommandsPrivileges(const string & fileName, bool init); void cbRemoteClientCallback (uint32 rid, const std::string &cmd, const std::string &entityNames); // // get AI instance and remove it form the group name bool getAIInstanceFromGroupName(string& groupName, uint32& instanceNumber) { if (groupName.find("@") != string::npos) { string continent = groupName.substr(0, groupName.find('@')); uint32 nr = CUsedContinent::instance().getInstanceForContinent(continent); if (nr == ~0) { return false; } instanceNumber = nr; groupName = groupName.substr(groupName.find('@') + 1, groupName.size()); } return true; } CAdminCommand * findAdminCommand(const string & name) { H_AUTO(findAdminCommand); const uint nbCommands = (uint)AdminCommands.size(); for (uint i = 0; i < nbCommands; i++) { if (name == AdminCommands[i].Name) return &AdminCommands[i]; } return NULL; } static void cbCommandsPrivilegesFileChange(const string & fileName) { H_AUTO(cbCommandsPrivilegesFileChange); if (fileName != CommandsPrivilegesFileName) return; loadCommandsPrivileges(fileName, false); } void initAdmin () { const uint nbCommands = sizeof(AdminCommandsInit) / sizeof(AdminCommandsInit[0]); for (uint i = 0; i < nbCommands; i++) { CAdminCommand cmd; cmd.Name = AdminCommandsInit[i].Name; cmd.AddEId = AdminCommandsInit[i].AddEId; cmd.Priv = DefaultPriv; cmd.Audit = false; AdminCommands.push_back(cmd); } setRemoteClientCallback (cbRemoteClientCallback); } void initCommandsPrivileges(const std::string & fileName) { H_AUTO(initCommandsPrivileges); initSalt(); loadCommandsPrivileges(fileName, true); } static void loadCommandsPrivileges(const string & fileName, bool init) { H_AUTO(loadCommandsPrivileges); CIFile ifile; if (!ifile.open(fileName)) { nlwarning ("ADMIN: file '%s' cannot be opened", fileName.c_str()); return; } if (init) { const string filePath = CPath::getFullPath(fileName, false); CFile::removeFileChangeCallback(CommandsPrivilegesFileName); CFile::addFileChangeCallback(filePath, cbCommandsPrivilegesFileChange); CommandsPrivilegesFileName = filePath; } // reset privileges with default value const uint nbCommands = (uint)AdminCommands.size(); for (uint i = 0; i < nbCommands; i++) { AdminCommands[i].Priv = DefaultPriv; } // load file content CSString fileContent; uint32 fileSize = ifile.getFileSize(); uint8 * buf = new uint8[fileSize + 1]; ifile.serialBuffer(buf, fileSize); ifile.close(); buf[fileSize] = 0; fileContent = (char *)buf; delete [] buf; while (!fileContent.empty()) { CSString line = fileContent.strtok("\r\n"); // remove any comment line = line.splitTo("//"); if (line.strip().empty()) continue; CSString fullLine = line; // only extract the first 4 params CVectorSString params; for (uint i = 0; !line.empty() && i < 4; i++) { string param = line.strtok(" \t"); if (param.empty()) break; params.push_back(param); } if (params.size() < 1) { nlwarning("ADMIN: invalid entry: '%s'.", fullLine.c_str()); continue; } // check second param if it is a forward info if (params.size() > 1 && params[1][0] == '[') { // this is a forward } else if (params.size() > 3) { nlwarning("ADMIN: invalid entry: '%s'.", fullLine.c_str()); continue; } else { // no forward params.insert(params.begin()+1, "[]"); } if (params.size() < 3) { // no required privilege params.push_back(""); } if (params.size() < 4) { // no audit specified params.push_back(""); } const string & cmdName = params[0]; const string & forward = params[1]; const string & cmdPriv = params[2]; const bool & audit = (params[3] == "audit"); CAdminCommand * cmd = findAdminCommand(cmdName); if (cmd) { cmd->Priv = cmdPriv; cmd->ForwardToservice = forward.substr(1, forward.size()-2); cmd->Audit = audit; nlinfo("ADMIN: command '%s' forwarded to [%s] has new privileges '%s'.", cmdName.c_str(), cmd->ForwardToservice.c_str(), cmdPriv.c_str()); } else { nlwarning("ADMIN: command '%s' is unknown.", cmdName.c_str()); } } } void initPositionFlags(const std::string & fileName) { H_AUTO(initPositionFlags); string fileNameAndPath = Bsi.getLocalPath() + fileName; if (CFile::fileExists(fileNameAndPath)) { CPositionFlagManager::getInstance().loadFromFile(fileName); } PositionFlagsFileName = fileName; } struct SaltFileLoadCallback: public IBackupFileReceiveCallback { std::string FileName; SaltFileLoadCallback(const std::string& fileName): FileName(fileName) {} virtual void callback(const CFileDescription& fileDescription, NLMISC::IStream& dataStream) { // if the file isn't found then just give up DROP_IF(fileDescription.FileName.empty()," file not found: "<< FileName, return); dataStream.serial(Salt); nlinfo("Salt loaded : %s", Salt.c_str()); } }; void initSalt() { H_AUTO(initSalt); string fileNameAndPath = Bsi.getLocalPath() + "salt_egs.txt"; if (CFile::fileExists(fileNameAndPath)) { nlinfo("Salt loading : salt_egs.txt"); Bsi.syncLoadFile("salt_egs.txt", new SaltFileLoadCallback("salt_egs.txt")); } } const string &getSalt() { if (Salt.empty()) Salt = "abcdefghijklmnopqrstuvwxyz0123456"; return Salt; } void saveSalt(const string salt) { Salt = salt; CBackupMsgSaveFile msg("salt_egs.txt", CBackupMsgSaveFile::SaveFile, Bsi ); msg.DataMsg.serial(Salt); Bsi.sendFile(msg); } static void selectEntities (const string &entityName, vector &entities) { H_AUTO(selectEntities); if (entityName.empty ()) return; /* * * valid name formats: * * - * Select all entities * - Select the specified entity using his eid */ if (entityName == "*") { // we want all entities for (CPlayerManager::TMapPlayers::const_iterator it = PlayerManager.getPlayers().begin(); it != PlayerManager.getPlayers().end(); ++it) { if ((*it).second.Player != 0) { const CCharacter *c = (*it).second.Player->getActiveCharacter(); if (c != 0) { entities.push_back (c->getId()); } } } } else if (entityName[0] == '(') { // we want a specific entity id CEntityId eid (entityName); if (eid != CEntityId::Unknown) entities.push_back (eid); } else { // try with the name CEntityId eid = CEntityIdTranslator::getInstance()->getByEntity(CShardNames::getInstance().makeFullNameFromRelative(TSessionId(FixedSessionId), entityName)); if (eid != CEntityId::Unknown) entities.push_back (eid); } } #define ENTITY_VARIABLE(__name,__help) \ struct __name##Class : public NLMISC::ICommand \ { \ __name##Class () : NLMISC::ICommand("variables",#__name, __help, " []") { Type = Variable; } \ virtual bool execute(const std::string &rawCommandString, const std::vector &args, NLMISC::CLog &log, bool quiet, bool human) \ { \ if (args.size () != 1 && args.size () != 2) \ return false; \ \ vector entities; \ selectEntities (args[0], entities); \ \ for (uint i = 0; i < entities.size(); i++) \ { \ string value; \ if (args.size()==2) \ value = args[1]; \ else \ value = "???"; \ pointer (entities[i], (args.size()==1), value); \ if (quiet) \ log.displayNL ("%s %s", entities[i].toString().c_str(), value.c_str()); \ else \ log.displayNL ("Entity %s Variable %s = %s", entities[i].toString().c_str(), _CommandName.c_str(), value.c_str()); \ } \ return true; \ } \ void pointer(CEntityId entity, bool get, std::string &value); \ }; \ __name##Class __name##Instance; \ void __name##Class::pointer(CEntityId entity, bool get, std::string &value) // // This macro get an eid and return c that is a pointer to a CCharacter. // #define ENTITY_GET_ENTITY \ TLogContext_Character_AdminCommand commandContext(entity); \ CEntityBase *e = CEntityBaseManager::getEntityBasePtr(entity); \ if(e == 0) \ { \ nlwarning ("Unknown entity '%s'", entity.toString().c_str()); \ if(get) value = "UnknownEntity"; \ return; \ } \ if(!TheDataset.isAccessible(e->getEntityRowId())) \ { \ nlwarning ("'%s' is not valid in mirror", entity.toString().c_str()); \ if(get) value = "NotValidInMirror"; \ return; \ } #define ENTITY_GET_CHARACTER \ TLogContext_Character_AdminCommand commandContext(entity); \ CCharacter *c = PlayerManager.getChar(entity); \ if(c == 0) \ { \ nlwarning ("Unknown player '%s'", entity.toString().c_str()); \ if(get) value = "UnknownPlayer"; \ return; \ } \ if(!c->getEnterFlag()) \ { \ nlwarning ("'%s' is not entered", entity.toString().c_str()); \ if(get) value = "NotEntered"; \ return; \ } \ if(!TheDataset.isAccessible(c->getEntityRowId())) \ { \ nlwarning ("'%s' is not valid in mirror", entity.toString().c_str()); \ if(get) value = "NotValidInMirror"; \ return; \ } void GET_CHARACTER_Helper(std::string& command, const NLMISC::CEntityId& id, const std::string& adminCommand) { CAdminOfflineCommand::makeStringCommande( command, id, adminCommand ); COfflineCharacterCommand::getInstance()->addOfflineCommandWithoutApply( command ); } #define GET_ENTITY \ if (args.size() < 1) { nlwarning ("Missing argument number 0 that should be the eid"); return false; } \ CEntityId eid(args[0]); \ if (eid == CEntityId::Unknown) \ return true; \ TLogContext_Character_AdminCommand commandContext(eid); \ CEntityBase *e = CEntityBaseManager::getEntityBasePtr(eid); \ if(e == 0) \ { \ nlwarning ("Unknown entity '%s'", eid.toString().c_str()); \ return true; \ } \ if(!TheDataset.isAccessible(e->getEntityRowId())) \ { \ nlwarning ("'%s' is not valid in mirror", eid.toString().c_str()); \ return true; \ } #define TRY_GET_CHARACTER \ if (args.size() < 1) { nlwarning ("Missing argument number 0 that should be the eid"); return false; } \ CEntityId eid(args[0]); \ TLogContext_Character_AdminCommand commandContext(eid); \ CCharacter *c = PlayerManager.getChar(eid); \ if (!c) \ { \ nlwarning("Unknown character '%s'", args[0].c_str()); \ return false; \ } #define CHECK_RIGHT( csr, target ) \ {\ if ( !PlayerManager.hasBetterCSRGrade( csr, target ) )\ {\ if ( csr )\ CCharacter::sendDynamicSystemMessage( csr->getEntityRowId(), "CSR_BAD_RIGHTS" );\ return false;\ }\ } #define GET_GUILD(argPos, onlyLocal, eId) \ CGuild * guild = CGuildManager::getInstance()->getGuildByName( args[argPos] );\ if ( guild == NULL )\ {\ /* try to find the guild with an id*/ \ uint32 shardId =0; \ uint32 guildId =0; \ sscanf(args[argPos].c_str(), "%u:%u", &shardId, &guildId); \ guild = CGuildManager::getInstance()->getGuildFromId((shardId<<20)+guildId); \ \ if (guild == NULL) \ { \ if (eId != NLMISC::CEntityId::Unknown)\ {\ CCharacter::sendDynamicSystemMessage(eId, "GUILD_IS_PROXY");\ }\ log.displayNL("Invalid guild '%s'",args[argPos].c_str());\ return true;\ } \ } \ if (onlyLocal && guild->isProxy())\ {\ log.displayNL("The guild '%s' is a foreign guild, operation forbidden", guild->getName().toString().c_str());\ return true;\ }\ // // You can here all variables for a player. // // Don't forget to add your command in the AdminCommandsInit array if you want the command to be executed on the client // ENTITY_VARIABLE(HP, "Hit points of a player") { ENTITY_GET_ENTITY if (get) { value = toString (e->currentHp()); } else { sint32 v; NLMISC::fromString(value, v); e->getScores()._PhysicalScores[SCORES::hit_points].Current = v; } } ENTITY_VARIABLE(MaxHP, "Max hit points of a player") { ENTITY_GET_ENTITY if (get) { value = toString (e->maxHp()); } else { sint32 v; NLMISC::fromString(value, v); e->getScores()._PhysicalScores[SCORES::hit_points].Max = v; } } ENTITY_VARIABLE(Speed, "Speed modifier of an entity") { ENTITY_GET_ENTITY if (get) { value = toString (e->getEventSpeedVariationModifier()); } else { e->setEventSpeedVariationModifier((float)atof(value.c_str())); } } ENTITY_VARIABLE(Name, "Name of a player") { ENTITY_GET_ENTITY if (get) { // value = CEntityIdTranslator::getInstance()->getByEntity(entity).toString(); value = e->getName ().toString(); } else { } } ENTITY_VARIABLE(Money, "Money") { ENTITY_GET_CHARACTER if (get) { value = toString("%"NL_I64"u", c->getMoney()); } else { sint dir = 0; if (!value.empty()) { if(value[0] == '+') dir = +1; else if(value[0] == '-') dir = -1; else if(!isdigit(value[0])) { nlwarning ("Bad money format for %s right format is [] sign can be +,- or nothing to set the money", value.c_str()); return; } } else { nlwarning ("You must provide a []"); return; } if(dir == 0) { c->setMoney(NLMISC::atoiInt64(value.c_str())); } else { uint64 val = NLMISC::atoiInt64(value.substr(1).c_str()); if(dir == 1) c->giveMoney(val); else c->spendMoney(val); } nlinfo ("Player %s money is %"NL_I64"u", entity.toString().c_str(),c->getMoney()); } } ENTITY_VARIABLE(MoneyGuild, "MoneyGuild") { ENTITY_GET_CHARACTER CGuild * guild = CGuildManager::getInstance()->getGuildFromId(c->getGuildId()); if (guild == NULL) { nlwarning("Invalid guild"); return; } if (get) { value = toString("%"NL_I64"u", guild->getMoney()); } else { sint dir = 0; if (!value.empty()) { if(value[0] == '+') dir = +1; else if(value[0] == '-') dir = -1; else if(!isdigit(value[0])) { nlwarning ("Bad money format for %s right format is [] sign can be +,- or nothing to set the money", value.c_str()); return; } } else { nlwarning ("You must provide a []"); return; } if(dir == 0) { guild->setMoney(NLMISC::atoiInt64(value.c_str())); } else { uint32 val; NLMISC::fromString(value.substr(1), val); if(dir == 1) guild->addMoney(val); else guild->spendMoney(val); } nlinfo ("Player %s guild money is %"NL_I64"u", entity.toString().c_str(),guild->getMoney()); } } ENTITY_VARIABLE(FactionPoint, "FactionPoint") { ENTITY_GET_CHARACTER if (get) { string sTmp; for (uint i = PVP_CLAN::BeginClans; i <= PVP_CLAN::EndClans; ++i) sTmp += PVP_CLAN::toString((PVP_CLAN::TPVPClan)i) + " : " + toString(c->getFactionPoint((PVP_CLAN::TPVPClan)i)) + "\n"; value = sTmp; } else { string sFactionName = value.substr(0, value.find(',')); string sNumber = value.substr(value.find(',')+1); if (value.empty() || sFactionName.empty() || sNumber.empty()) { nlwarning ("You must provide : []"); return; } sint dir = 0; if(sNumber[0] == '+') dir = +1; else if(sNumber[0] == '-') dir = -1; else if(!isdigit(sNumber[0])) { nlwarning ("Bad format for '%s' right format is [] sign can be +,- or nothing", sNumber.c_str()); return; } PVP_CLAN::TPVPClan clan = PVP_CLAN::fromString(sFactionName); if ((clan < PVP_CLAN::BeginClans) || (clan > PVP_CLAN::EndClans)) { nlwarning ("'%s' is not a valid faction name", sFactionName.c_str()); return; } if(dir == 0) { uint32 val; NLMISC::fromString(sNumber, val); c->setFactionPoint(clan, val, true); } else { uint32 val; NLMISC::fromString(sNumber.substr(1), val); if(dir == 1) c->setFactionPoint(clan, c->getFactionPoint(clan)+val, true); else c->setFactionPoint(clan, c->getFactionPoint(clan)-val, true); } } } ENTITY_VARIABLE (Priv, "User privilege") { ENTITY_GET_CHARACTER CPlayer *p = PlayerManager.getPlayer(PlayerManager.getPlayerId(c->getId())); if (p == 0) { nlwarning ("Can't find player with UserId %d for checking privilege, assume no priv", PlayerManager.getPlayerId(c->getId())); return; } if (get) { value = p->getUserPriv(); } else { p->setUserPriv(value); nlinfo ("%s have now this priv '%s'", entity.toString().c_str(), value.c_str()); } return; } ENTITY_VARIABLE (FBT, "Focus Beta Tester") { ENTITY_GET_CHARACTER CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( c->getId() )); if (p == NULL) { nlwarning ("Can't find player with UserId %d", PlayerManager.getPlayerId( c->getId() )); return; } if (get) { value = NLMISC::toString(p->isBetaTester()); } else { if (value == "1" || value == "on" || strlwr(value) == "true") { p->isBetaTester(true); } else if (value == "0" || value == "off" || strlwr(value) == "false") { p->isBetaTester(false); } nlinfo ("%s %s now a Focus Beta Tester", entity.toString().c_str(), (p->isBetaTester() ? "is" : "isn't")); } } ENTITY_VARIABLE(Position, "Position of a player (in meter) ,[,][,] | | | home | ") { H_AUTO(Position); ENTITY_GET_ENTITY vector res; sint32 x = 0, y = 0, z = 0; sint32 cell = 0; if (get) { x = e->getState().X() / 1000; y = e->getState().Y() / 1000; z = e->getState().Z() / 1000; value = toString ("%d,%d,%d", x, y, z); } else { if ( value.find(',') != string::npos ) { explode (value, string(","), res); if (res.size() >= 2) { fromString(res[0], x); x *= 1000; fromString(res[1], y); y *= 1000; } if (res.size() >= 3) { fromString(res[2], z); z *= 1000; } } else { if ( value.find(".creature") != string::npos ) { CSheetId creatureSheetId(value); if( creatureSheetId != CSheetId::Unknown ) { double minDistance = -1.; CCreature * creature = NULL; TMapCreatures::const_iterator it; const TMapCreatures& creatures = CreatureManager.getCreature(); for( it = creatures.begin(); it != creatures.end(); ++it ) { CSheetId sheetId = (*it).second->getType(); if( sheetId == creatureSheetId ) { double distance = PHRASE_UTILITIES::getDistance( e->getEntityRowId(), (*it).second->getEntityRowId() ); if( !creature || (creature && distance < minDistance) ) { creature = (*it).second; minDistance = distance; } } } if( creature ) { x = creature->getState().X(); y = creature->getState().Y(); z = creature->getState().Z(); } } else { nlwarning (" '%s' is an invalid creature", value.c_str()); } } else { // try to find the player name CCharacter *c = dynamic_cast(e); if (c == NULL) { nlwarning (" '%s' is not a player", entity.toString().c_str()); return; } CEntityBase *entityBase = PlayerManager.getCharacterByName (CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), value)); if (entityBase == 0) { // try to find the bot name vector aliases; CAIAliasTranslator::getInstance()->getNPCAliasesFromName( value, aliases ); if ( aliases.empty() ) { nldebug (" Ignoring attempt to teleport because no NPC found matching name '%s'", value.c_str()); return; } TAIAlias alias = aliases[0]; const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId (alias); if ( botId != CEntityId::Unknown ) { entityBase = CreatureManager.getCreature (botId); } else { nlwarning ("'%s' has no eId. Is it Spawned???", value.c_str()); return; } } if (entityBase != 0) { x = entityBase->getState().X + sint32 (cos (entityBase->getState ().Heading) * 2000); y = entityBase->getState().Y + sint32 (sin (entityBase->getState ().Heading) * 2000); z = entityBase->getState().Z; TDataSetRow dsr = entityBase->getEntityRowId(); CMirrorPropValueRO mirrorCell( TheDataset, dsr, DSPropertyCELL ); cell = mirrorCell; } } } if (x == 0 && y == 0 && z == 0) { nlwarning ("'%s' is a bad value for position, don't change position", value.c_str()); return; } CCharacter * c = dynamic_cast(e); if( c ) { CContinent * cont = CZoneManager::getInstance().getContinent(x,y); if(c->getCurrentContinent() == CONTINENT::NEWBIELAND ) { if( cont == 0 || cont->getId() != CONTINENT::NEWBIELAND ) { log_Command_TPOutsideNewbieland(c->getId()); // nlwarning("Position %s player outside NEWBIELAND, this is logged.", c->getId().toString().c_str()); } } c->allowNearPetTp(); if (res.size() >= 4) { // season included uint8 season; NLMISC::fromString(res[3], season); c->teleportCharacter(x,y,z,true, false, 0.f, 0xFF, cell, season); } else { c->teleportCharacter(x,y,z,true, false, 0.f, 0xFF, cell); } if ( cont ) { c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(cont->getId()) ); } } else { e->tpWanted (x, y, z); } } } //----------------------------------------------- // change_mode : //----------------------------------------------- NLMISC_COMMAND(changeMode," change_mode"," ") { if( args.size() == 2 ) { CEntityId id; id.fromString( args[0].c_str() ); sint iMode; NLMISC::fromString(args[1], iMode); MBEHAV::EMode mode = MBEHAV::EMode(iMode); CEntityBase *e = 0; if( id.getType() == 0 ) { e = PlayerManager.getChar(id); } if (e) { e->setMode( mode, true ); log.displayNL("Character %s mode changed to %d", id.toString().c_str(), mode); } else { log.displayNL("Unknown entity %s ",id.toString().c_str()); } return true; } return false; } // change_mode // //----------------------------------------------- // checkTargetSP :check target player SP //----------------------------------------------- NLMISC_COMMAND(checkTargetSP," check target player skill points (if there is lost SP)","") { if( args.size() < 1 ) return false; GET_CHARACTER CCharacter *targetPlayer = PlayerManager.getChar( c->getTargetDataSetRow() ); if (!targetPlayer) { log.displayNL("No target or invalid target"); return true; } uint32 totalEarnedSp = targetPlayer->getTotalEarnedSP(); uint32 spentSp = targetPlayer->getActionsSPValue() - targetPlayer->getStartActionsSPValue(); uint32 currentSp = (uint32) targetPlayer->getSP(EGSPD::CSPType::Craft); currentSp += (uint32) targetPlayer->getSP(EGSPD::CSPType::Fight); currentSp += (uint32) targetPlayer->getSP(EGSPD::CSPType::Magic); currentSp += (uint32) targetPlayer->getSP(EGSPD::CSPType::Harvest); // log result log.displayNL("Player %s : Current SP total = %u, totalEarnedSp = %u, spentTotalSP = %u, MISSING SP = %d", targetPlayer->getId().toString().c_str(), currentSp, totalEarnedSp, spentSp, totalEarnedSp-spentSp-currentSp); // send result to asker string strTemp = NLMISC::toString("Player %s : Current SP total = %u, totalEarnedSp = %u, spentTotalSP = %d, MISSING SP = %d",targetPlayer->getId().toString().c_str(), currentSp, totalEarnedSp, spentSp, totalEarnedSp-spentSp-currentSp); chatToPlayer(eid, strTemp); return true; } // checkSP // NLMISC_COMMAND (createItemInBag, "Create an item and put it in the player bag", " | [force]") { if (args.size() < 4 || args.size() > 5) return false; GET_CHARACTER string sheetName = args[1]; CSheetId sheet; uint32 sheetId; NLMISC::fromString(sheetName, sheetId); if (sheetId != 0) { sheet = CSheetId(sheetId); } else { if (sheetName.find(".") == string::npos) sheetName += ".sitem"; sheet = CSheetId(sheetName.c_str()); } if (sheet == CSheetId::Unknown) { log.displayNL("sheetId '%s' is Unknown", sheetName.c_str()); return false; } // banners are the only items in game which use privilege if( sheetName.find("banner") != string::npos ) { CPlayer * player = PlayerManager.getPlayer( PlayerManager.getPlayerId(eid) ); // if (player != NULL && !player->havePriv(":DEV:") ) if (player != NULL && player->havePriv(BannerPriv) ) { if( sheetName.find("_gu") != string::npos && !player->havePriv(":G:") ) return false; if( sheetName.find("_sgu") != string::npos && !player->havePriv(":SG:") ) return false; if( sheetName.find("_vgu") != string::npos && !player->havePriv(":VG:") ) return false; if( sheetName.find("_gm") != string::npos && !player->havePriv(":GM:") ) return false; if( sheetName.find("_sgm") != string::npos && !player->havePriv(":SGM:") ) return false; } } const CStaticItem *form = CSheets::getForm (sheet); if (form == 0) { log.displayNL ("sheetId '%s' is not found", sheetName.c_str()); return false; } sint quantity; NLMISC::fromString(args[2], quantity); if (quantity < 1) { log.displayNL ("Quantity must be > 0"); return false; } sint quality; NLMISC::fromString(args[3], quality); if (quality < 1) { log.displayNL ("Quality must be > 0"); return false; } bool res = c->createItemInInventory(INVENTORIES::bag, quality, quantity, sheet); bool forceCreate; if (args.size() == 5 && args[4] == "force") forceCreate = true; else forceCreate = false; if (!res && forceCreate) { CGameItemPtr item = GameItemManager.createItem(sheet, quality, true, true); if (item != NULL) { res = c->addItemToInventory(INVENTORIES::bag, item); if (!res) item.deleteItem(); } } if (res) log.displayNL ("Item '%s' created and set in the bag of the player %s", sheet.toString ().c_str(), eid.toString().c_str()); else log.displayNL ("Failed to create and set the item '%s' for the player %s", sheet.toString ().c_str(), eid.toString().c_str()); return res; } NLMISC_COMMAND (createItemInTmpInv, "Create an item and put it in the player temp inventory", " | ") { if (args.size () != 4) return false; GET_CHARACTER string sheetName = args[1]; CSheetId sheet; uint32 sheetId; NLMISC::fromString(sheetName, sheetId); if (sheetId != 0) { sheet = CSheetId(sheetId); } else { if (sheetName.find(".") == string::npos) sheetName += ".item"; sheet = CSheetId(sheetName.c_str()); } if (sheet == CSheetId::Unknown) { log.displayNL("sheetId '%s' is Unknown", sheetName.c_str()); return false; } // banners are the only items in game which use privilege if( sheetName.find("banner") != string::npos ) { CPlayer * player = PlayerManager.getPlayer( PlayerManager.getPlayerId(eid) ); if (player != NULL && player->havePriv(BannerPriv) ) { if( sheetName.find("_gu") != string::npos && !player->havePriv(":G:") ) return false; if( sheetName.find("_sgu") != string::npos && !player->havePriv(":SG:") ) return false; if( sheetName.find("_vgu") != string::npos && !player->havePriv(":VG:") ) return false; if( sheetName.find("_gm") != string::npos && !player->havePriv(":GM:") ) return false; if( sheetName.find("_sgm") != string::npos && !player->havePriv(":SGM:") ) return false; } } const CStaticItem *form = CSheets::getForm (sheet); if (form == 0) { log.displayNL ("sheetId '%s' is not found", sheetName.c_str()); return false; } sint quantity; NLMISC::fromString(args[2], quantity); if (quantity < 1) { log.displayNL ("Quantity must be > 0"); return false; } sint quality; NLMISC::fromString(args[3], quality); if (quality < 1) { log.displayNL ("Quality must be > 0"); return false; } bool res = c->createItemInInventory(INVENTORIES::temporary, quality, quantity, sheet); if (res) log.displayNL ("Item '%s' created and set in the temp inventory of the player %s", sheet.toString ().c_str(), eid.toString().c_str()); else log.displayNL ("Failed to create and set the item '%s' for the player %s", sheet.toString ().c_str(), eid.toString().c_str()); return res; } NLMISC_COMMAND (createItemInInv, "Create items and put them in the given inventory", " | ") { if (args.size () != 6) return false; GET_CHARACTER string sheetName = args[2]; CSheetId sheet; uint32 sheetId; NLMISC::fromString(sheetName, sheetId); if (sheetId != 0) { sheet = CSheetId(sheetId); } else { if (sheetName.find(".") == string::npos) sheetName += ".sitem"; sheet = CSheetId(sheetName.c_str()); } if (sheet == CSheetId::Unknown) { log.displayNL("sheetId '%s' is Unknown", sheetName.c_str()); return false; } // banners are the only items in game which use privilege if( sheetName.find("banner") != string::npos ) { CPlayer * player = PlayerManager.getPlayer( PlayerManager.getPlayerId(eid) ); if (player != NULL && player->havePriv(BannerPriv) ) { if( sheetName.find("_gu") != string::npos && !player->havePriv(":G:") ) return false; if( sheetName.find("_sgu") != string::npos && !player->havePriv(":SG:") ) return false; if( sheetName.find("_vgu") != string::npos && !player->havePriv(":VG:") ) return false; if( sheetName.find("_gm") != string::npos && !player->havePriv(":GM:") ) return false; if( sheetName.find("_sgm") != string::npos && !player->havePriv(":SGM:") ) return false; } } const CStaticItem *form = CSheets::getForm (sheet); if (form == 0) { log.displayNL ("sheetId '%s' is not found", sheetName.c_str()); return false; } sint quantity; NLMISC::fromString(args[3], quantity); if (quantity < 1) { log.displayNL ("Quantity must be > 0"); return false; } sint quality; NLMISC::fromString(args[4], quality); if (quality < 1) { log.displayNL ("Quality must be > 0"); return false; } uint nb; NLMISC::fromString(args[5], nb); uint nbItems = min(nb, 1000U); uint nbCreatedItems = 0; for (uint i = 0; i < nbItems; i++) { if ( !c->createItemInInventory(INVENTORIES::toInventory(args[1]), quality, quantity, sheet, CEntityId::Unknown) ) break; nbCreatedItems++; } log.displayNL("%u (of %u) items '%s' created and set in the inventory '%s' of the player %s", nbCreatedItems, nbItems, sheet.toString ().c_str(), args[1].c_str(), eid.toString().c_str()); return true; } NLMISC_COMMAND(createNamedItemInBag, "create a named item in bag", " []") { if (args.size() > 3) return false; if (args.size() < 2 ) return false; CCharacter * user = PlayerManager.getChar(CEntityId(args[0])); if (!user) { log.displayNL("invalid char '%s'", args[0].c_str()); return true; } uint16 quantity; if (args.size() == 3) { NLMISC::fromString(args[2], quantity); if (quantity == 0) { log.displayNL("invalid quantity '%s'", args[2].c_str()); return true; } } else { quantity = 1; } TLogNoContext_Item noLog; CGameItemPtr item = CNamedItems::getInstance().createNamedItem(args[1], quantity); if (item == NULL) { log.displayNL("invalid item '%s'", args[1].c_str()); return true; } user->addItemToInventory(INVENTORIES::bag, item); return true; } NLMISC_COMMAND (createFullArmorSet, "Create and equip player with chosen full armor set"," ") { static string armors[]= { "boots", "gloves", "pants", "sleeves", "vest", }; static string heavyArmors[]= { "boots", "gloves", "helmet", "pants", "sleeves", "vest", }; if (args.size () != 4) return false; GET_CHARACTER const string &race = args[1]; const string &type = args[2]; uint16 quality; NLMISC::fromString(args[3], quality); const uint16 min = quality - (quality-1)%5; const string minStr = (min < 10) ? string("0") + toString(min) : toString(min); const uint16 max = min+4; const string maxStr = (max < 10) ? string("0") + toString(max) : toString(max); const string endName = string("_") + minStr + string("_") + maxStr + string(".item"); // create the armor pieces if (type == "heavy") { for ( int i = 0 ; i < sizeof(heavyArmors)/sizeof(heavyArmors[0]) ; ++i) { const string sheetName = race + string("_") + type + string("_") + heavyArmors[i] + endName; CSheetId sheetId(sheetName); if ( !c->createItemInInventory(INVENTORIES::bag, quality, 1, sheetId, eid) ) { log.displayNL ("For entity %s Failed to create item %s", eid.toString().c_str(), sheetName.c_str() ); } } } else { for ( int i = 0 ; i < sizeof(armors)/sizeof(armors[0]) ; ++i) { const string sheetName = race + string("_") + type + string("_") + armors[i] + endName; CSheetId sheetId(sheetName); if ( !c->createItemInInventory(INVENTORIES::bag, quality, 1, sheetId, eid) ) { log.displayNL ("For entity %s Failed to create item %s", eid.toString().c_str(), sheetName.c_str() ); } } } return true; } NLMISC_COMMAND (displayInfosOnTarget, "display info on entity target", "") { if (args.size () < 1) return false; GET_CHARACTER TDataSetRow target = c->getTargetDataSetRow(); if (TheDataset.isAccessible(target)) { // little slow but acceptable in command CMirrorPropValueRO instanceNumber(TheDataset, target, DSPropertyAI_INSTANCE); CAIAskForInfosOnEntityMsg msg; msg.EntityRowId = target; msg.AskerRowID = c->getEntityRowId(); CWorldInstances::instance().msgToAIInstance(instanceNumber, msg); } else log.displayNL (" Entity %s has no valid target", eid.toString().c_str() ); return true; } NLMISC_COMMAND (forceTargetToDie, "(debug) Force entity target to die", "") { if (args.size () != 1) return false; GET_CHARACTER // force sending of target as dead (can only be done on creature) CCreature *target = CreatureManager.getCreature(c->getTargetDataSetRow()); if (target) { if (!target->isDead()) target->changeCurrentHp(-100000); BotDeathReport.Bots.push_back(target->getEntityRowId()); TDataSetRow emptyRow; BotDeathReport.Killers.push_back(emptyRow); BotDeathReport.Zombies.push_back(true); } return true; } NLMISC_COMMAND (learnAllBricks, "Specified player learns all possible bricks for it's skill values", "") { H_AUTO(learnAllBricks); if (args.size () != 1) return false; GET_CHARACTER // get all phrases and bypass brick requirements vector phrases; vector tempPhrases; static const EGSPD::CPeople::TPeople races[] = { EGSPD::CPeople::Common, EGSPD::CPeople::Tryker, EGSPD::CPeople::Fyros, EGSPD::CPeople::Matis, EGSPD::CPeople::Zorai }; const uint nbRaces = sizeof(races) / sizeof(races[0]); for (uint i = 0 ; i < nbRaces ; ++i) { // fight string filter = "bf"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // magic filter = "bm"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // craft filter = "bc"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // harvest filter = "bh"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // special powers filter = "bs"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); } // learn all bricks uint nbBricks = 0; for (uint i = 0; i < phrases.size() ; ++i) { const CStaticRolemasterPhrase *phrase = CSheets::getSRolemasterPhrase(phrases[i]); if(phrase != NULL) { const uint size = (uint)phrase->Bricks.size(); for ( uint j = 0; j < size ; ++j) { c->addKnownBrick( phrase->Bricks[j] ); ++nbBricks; } } } log.displayNL ("%s learnt %u bricks", eid.toString().c_str(), nbBricks); return true; } NLMISC_COMMAND (learnAllRolemasterBricks, "Specified player learns all possible bricks sold by rolemaster for it's skill values", "") { H_AUTO(learnAllRolemasterBricks); if (args.size () != 1) return false; GET_CHARACTER // get all phrases and bypass brick requirements vector phrases; vector tempPhrases; static const EGSPD::CPeople::TPeople races[] = { EGSPD::CPeople::Common, EGSPD::CPeople::Tryker, EGSPD::CPeople::Fyros, EGSPD::CPeople::Matis, EGSPD::CPeople::Zorai }; const uint nbRaces = sizeof(races) / sizeof(races[0]); for (uint i = 0 ; i < nbRaces ; ++i) { // fight string filter = "bf"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // magic filter = "bm"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // craft filter = "bc"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // harvest filter = "bh"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // special powers filter = "bs"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); } // learn all bricks uint nbBricks = 0; for (uint i = 0; i < phrases.size() ; ++i) { const CStaticRolemasterPhrase *phrase = CSheets::getSRolemasterPhrase(phrases[i]); if(phrase != NULL) { const uint size = (uint)phrase->Bricks.size(); for ( uint j = 0; j < size ; ++j) { c->addKnownBrick( phrase->Bricks[j] ); ++nbBricks; } } } log.displayNL ("%s learnt %u bricks", eid.toString().c_str(), nbBricks); return true; } NLMISC_COMMAND (learnAllPhrases, "Specified player learns all possible phrases for it's skill values", "") { H_AUTO(learnAllPhrases); if (args.size () != 1) return false; GET_CHARACTER // get all phrases and bypass brick requirements vector phrases; vector tempPhrases; static const EGSPD::CPeople::TPeople races[] = { EGSPD::CPeople::Common, EGSPD::CPeople::Tryker, EGSPD::CPeople::Fyros, EGSPD::CPeople::Matis, EGSPD::CPeople::Zorai }; const uint nbRaces = sizeof(races) / sizeof(races[0]); for (uint i = 0 ; i < nbRaces ; ++i) { // fight string filter = "bf"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // magic filter = "bm"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // craft filter = "bc"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // harvest filter = "bh"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); // special powers filter = "bs"; c->getAvailablePhrasesList( filter, tempPhrases, races[i], true ); phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() ); tempPhrases.clear(); } // learn all phrases uint16 nbPhrases = 0; for (uint i = 0; i < phrases.size() ; ++i) { uint16 index = c->getFirstFreeSlotInKnownPhrase(); if ( !c->learnPrebuiltPhrase(phrases[i], index) ) log.displayNL ("%s FAILED to learn phrase id %s", eid.toString().c_str(), phrases[i].toString().c_str()); else ++nbPhrases; } log.displayNL ("%s learnt %u phrases", eid.toString().c_str(), nbPhrases); return true; } NLMISC_COMMAND(learnBrick, "Specified player learns given brick"," ") { if (args.size () != 2) return false; GET_CHARACTER CSheetId brickId(args[1]); c->addKnownBrick(brickId); log.displayNL ("%s learnt brick %s", eid.toString().c_str(), brickId.toString().c_str()); return true; } NLMISC_COMMAND(unlearnBrick, "Specified player unlearns given brick"," ") { if (args.size () != 2) return false; GET_CHARACTER CSheetId brickId(args[1]); c->removeKnownBrick(brickId); log.displayNL ("%s unlearnt brick %s", eid.toString().c_str(), brickId.toString().c_str()); return true; } NLMISC_COMMAND (learnPhrase, "Specified player learns a phrase and set it at index knownPhraseIndex", " ") { if (args.size () != 2) return false; GET_CHARACTER CSheetId phraseId(args[1]); const CStaticRolemasterPhrase *phrase = CSheets::getSRolemasterPhrase( phraseId ); if (!phrase) { log.displayNL ("%s isn't a valid phrase !", phraseId.toString().c_str()); return false; } uint16 index = c->getFirstFreeSlotInKnownPhrase(); if ( c->learnPrebuiltPhrase(phraseId, index) ) log.displayNL ("%s learnt phrase id %s", eid.toString().c_str(), phraseId.toString().c_str()); else log.displayNL ("%s FAILED to learn phrase id %s", eid.toString().c_str(), phraseId.toString().c_str()); return true; } NLMISC_COMMAND (logXpGain, "log or not xp gain infos for specified player", " ") { if (args.size () != 2) return false; GET_CHARACTER bool flag; if (args[1]=="1" || strlwr(args[1])=="on" || strlwr(args[1])=="true" ) { flag = true; } else if (args[1]=="0" || strlwr(args[1])=="off" || strlwr(args[1])=="false" ) { flag = false; } else return false; PlayerManager.logXPGain(c->getEntityRowId(), flag); log.displayNL ("Player %s. Flag logXpGain is now %s", eid.toString().c_str(), (flag?"ON":"OFF") ); return true; } NLMISC_COMMAND (learnAllForagePhrases, "Learn all forage phrase, begin at specified index", " " ) { H_AUTO(learnAllForagePhrases); if ( args.size() != 2 ) return false; GET_CHARACTER uint i; NLMISC::fromString(args[1], i); uint nbSuccess = 0, nbFail = 0; const CAllRolemasterPhrases& phrases = CSheets::getSRolemasterPhrasesMap(); for ( CAllRolemasterPhrases::const_iterator ip=phrases.begin(); ip!=phrases.end(); ++ip ) { const string phraseCode = (*ip).first.toString(); if ( phraseCode.find( "abhf" ) == 0 ) { if ( c->learnPrebuiltPhrase( (*ip).first, i ) ) ++nbSuccess; else ++nbFail; ++i; } } log.displayNL( "%u phrases learned, %u phrases failed", nbSuccess, nbFail ); return true; } /* NLMISC_COMMAND (learnAllFaberPlans, "Specified player learns all faber plans", "") { if (args.size () != 1) return false; GET_CHARACTER c->learnAllFaberPlans(); log.displayNL ("%s learnt all faber plans", eid.toString().c_str()); return true; } */ /* Don't use this command, use Money variable instead (same syntax for example "Money +10") NLMISC_COMMAND(giveMoney, "Give money to a player"," ") { if (args.size () != 2) return false; GET_CHARACTER c->giveMoney ( NLMISC::atoiInt64( args[1].c_str() ) ); log.displayNL ("You gave money to player %s", eid.toString().c_str()); return true; }*/ /* Don't use this command, use SP variable instead (same syntax for example "SP +10") NLMISC_COMMAND(giveSP, "Give SP (skill points) to a player"," ") { if (args.size () != 2) return false; GET_CHARACTER uint32 nbSp = atol(args[1].c_str()); c->addSP( (double)nbSp ); log.displayNL ("You gave %u SP to player %s", nbSp, eid.toString().c_str()); return true; }*/ NLMISC_COMMAND(respawn, "Same as '/a Position home' but without any privilege","") { if (args.size () != 1) return false; GET_CHARACTER //TODO rules of spawn point // COfflineEntityState state = PlayerManager.getStartState (c->getActiveRole ()); COfflineEntityState state; c->forbidNearPetTp(); c->tpWanted (state.X, state.Y, state.Z); return true; } //----------------------------------------------- // saveToXML //----------------------------------------------- NLMISC_CATEGORISED_COMMAND(pdr,saveToXML,"save a character to an XML file"," ") { if (args.size () < 2) return false; GET_CHARACTER std::string fileName = args[1]; if( c ) { static CPersistentDataRecordRyzomStore pdr; pdr.clear(); c->store(pdr); pdr.writeToTxtFile((fileName+".xml").c_str()); return true; } return false; } //----------------------------------------------- // loadFromXML //----------------------------------------------- NLMISC_CATEGORISED_COMMAND(pdr,loadFromXML,"load a character from an XML file"," ") { if (args.size () < 2) return false; GET_CHARACTER std::string fileName = args[1]; if( c ) { ucstring name= c->getName(); uint32 guildId= c->getGuildId(); NLMISC::CEntityId id= c->getId(); static CPersistentDataRecord pdr; pdr.clear(); pdr.readFromTxtFile((fileName+".xml").c_str()); c->apply(pdr); c->setName(name); c->setGuildId(guildId); c->setId(id); c->allowNearPetTp(); c->tpWanted(c->getX(), c->getY(), c->getZ(), true, c->getHeading()); return true; } return false; } //----------------------------------------------- // saveToPDR //----------------------------------------------- NLMISC_CATEGORISED_COMMAND(pdr,saveToPDR,"save a character to a binary PDR file"," ") { if (args.size () < 2) return false; GET_CHARACTER std::string fileName = args[1]; if( c ) { static CPersistentDataRecordRyzomStore pdr; pdr.clear(); c->store(pdr); pdr.writeToBinFile((fileName+".pdr").c_str()); return true; } return false; } //----------------------------------------------- // loadFromPDR //----------------------------------------------- NLMISC_CATEGORISED_COMMAND(pdr,loadFromPDR,"load a character from a binary PDR file"," ") { if (args.size () < 2) return false; GET_CHARACTER std::string fileName = args[1]; if( c ) { ucstring name= c->getName(); uint32 guildId= c->getGuildId(); NLMISC::CEntityId id= c->getId(); static CPersistentDataRecord pdr; pdr.clear(); pdr.readFromBinFile((fileName+".pdr").c_str()); c->apply(pdr); c->setName(name); c->setGuildId(guildId); c->setId(id); c->allowNearPetTp(); c->tpWanted(c->getX(), c->getY(), c->getZ(), true, c->getHeading()); return true; } return false; } //----------------------------------------------- // listPDRFiles //----------------------------------------------- NLMISC_CATEGORISED_COMMAND(pdr,listPDRFiles,"list files in the current directory","[]") { if (args.size()!=0) return false; std::vector files; NLMISC::CPath::getPathContent(".",false,false,true,files); for (uint32 i=(uint32)files.size();i--;) { if (!NLMISC::testWildCard(files[i],"*.xml") && !NLMISC::testWildCard(files[i],"*.pdr")) { files[i]=files.back(); files.pop_back(); } } std::sort(files.begin(),files.end()); for (uint32 i=0;i ") { if (args.size () < 2) return false; GET_CHARACTER CSheetId ticket = CSheetId( args[1] ); if( c ) { if( ticket != CSheetId::Unknown ) { CGameItemPtr item = c->createItemInInventoryFreeSlot(INVENTORIES::bag, 1, 1, ticket); if( item != 0 ) { if ( ! c->addCharacterAnimal( ticket, 0, item )) { item.deleteItem(); return false; } return true; } log.displayNL(" command, cannot create item in bag '%s'", args[1].c_str() ); } log.displayNL(" command, unknown pet ticket '%s'", args[1].c_str() ); } return false; } // addPetAnimal // NLMISC_COMMAND(setPetAnimalSatiety,"Set the satiety of pet animal (petIndex in 0..3)"," full| []") { if (args.size () < 3) return false; GET_CHARACTER if ( c ) { // Set the new satiety string result; uint petIndex; NLMISC::fromString(args[1], petIndex); float previousSatiety, maxSatiety; if ( c->getAnimalSatiety( petIndex, previousSatiety, maxSatiety ) ) { if ( args[2] == "full" ) c->setAnimalSatietyToMax( petIndex ); else { float value = (float)atof( args[2].c_str() ); c->setAnimalSatiety( petIndex, value ); } float currentSatiety; if ( c->getAnimalSatiety( petIndex, currentSatiety, maxSatiety ) ) result = toString( "Satiety changed from %.1f to %.1f / %.1f", previousSatiety, currentSatiety, maxSatiety ); else result = toString( "Internal error" ); } else result = toString( "Pet %u not found", petIndex ); // Send result if requested if ( args.size() > 3 ) { CCharacter *addressee = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[3]) ); if ( addressee ) { CHECK_RIGHT( addressee, c ); SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal); params[0].Literal = trim(result); CCharacter::sendDynamicSystemMessage(addressee->getId(), "LITERAL", params); } else result += " nameForAnswer not found"; } log.displayNL( result.c_str() ); } return true; } NLMISC_COMMAND(getPetAnimalSatiety,"Get the satiety of pet animal (petIndex in 0..3)"," []") { if (args.size () < 2) return false; GET_CHARACTER uint petIndex; NLMISC::fromString(args[1], petIndex); if ( c ) { // Get the satiety string result; float currentSatiety, maxSatiety; if ( c->getAnimalSatiety( petIndex, currentSatiety, maxSatiety ) ) result = toString( "Satiety: %.1f / %.1f", currentSatiety, maxSatiety ); else result = toString( "Pet %u not found", petIndex ); // Send result if requested if ( args.size() > 2 ) { CCharacter *addressee = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[2] )); if ( addressee ) { CHECK_RIGHT( addressee, c ); SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal); params[0].Literal = trim(result); CCharacter::sendDynamicSystemMessage(addressee->getId(), "LITERAL", params); } else result += " nameForAnswer not found"; } log.displayNL( result.c_str() ); } return true; } NLMISC_COMMAND(setPetAnimalName, "Set the name of a pet animal"," []") { if (args.size () < 2) return false; GET_CHARACTER if ( c ) { uint petIndex; fromString(args[1], petIndex); ucstring customName; if (args.size () == 3) customName = args[2]; c->setAnimalName(petIndex, customName); } return true; } NLMISC_COMMAND (addSkillPoints, "add skill points of given type (Fight = 0, Magic = 1,Craft = 2, Harvest = 3)", " ") { if (args.size () < 3) return false; GET_CHARACTER EGSPD::CSPType::TSPType type = (EGSPD::CSPType::TSPType) atoi (args[1].c_str()); if (type >= EGSPD::CSPType::EndSPType) { log.displayNL ("Unknown SP type %u", atoi (args[1].c_str()) ); return false; } uint32 nbSP; fromString(args[2], nbSP); c->addSP( nbSP, type ); log.displayNL ("Added %d skill points of type %u (%s) to player %s", nbSP, (uint8) type, EGSPD::CSPType::toString(type).c_str(), eid.toString().c_str()); return true; } // addSkillPoints // NLMISC_COMMAND (addXPToSkill, "Gain experience in a given skills", " []") { if (args.size () < 3) return false; GET_CHARACTER uint32 xp; NLMISC::fromString(args[1], xp); string skill = args[2]; uint count; if(args.size()==3) count = 1; else NLMISC::fromString(args[3], count); count = min( count, (uint)100); uint i; for( i=0; iaddXpToSkill( (double) xp, skill ); } log.displayNL ("Added %d xp skill '%s' to player %s %d time(s)", xp, skill.c_str(), eid.toString().c_str(),count); return true; } NLMISC_COMMAND(setSkillsToMaxValue, "Set skills character to max value of each skill","") { if (args.size () != 1) return false; GET_CHARACTER c->setSkillsToMaxValue(); log.displayNL ("You set skills of player %s to max value of each skill", eid.toString().c_str()); return true; } NLMISC_COMMAND(cancelTopPhrase, "cancelTopPhrase","") { if (args.size () != 1) return false; GET_CHARACTER CPhraseManager::getInstance().cancelTopPhrase( c->getEntityRowId()); return true; } NLMISC_COMMAND (clearFriendsList, "clear the friend list of a player", "") { if ( args.size() < 1 ) return false; GET_CHARACTER if(c != 0) { c->clearFriendList(); log.displayNL("player %s friends list cleared",eid.toString().c_str()); } return true; } NLMISC_COMMAND (clearIgnoreList, "clear the ignore list of a player", "") { if ( args.size() < 1 ) return false; GET_CHARACTER if(c != 0) { c->clearIgnoreList(); log.displayNL("player %s ignore list cleared",eid.toString().c_str()); } return true; } NLMISC_COMMAND (clearIsFriendOfList, "clear the ignore list of a player", "") { if ( args.size() < 1 ) return false; GET_CHARACTER if(c != 0) { c->clearFriendOfList(); log.displayNL("player %s 'IsFriendOf' list cleared",eid.toString().c_str()); } return true; } //----------------------------------------------- // set the defense mode to dodge //----------------------------------------------- NLMISC_COMMAND(dodge,"set the defense mode to dodge","") { if ( args.size() >= 1 ) { GET_CHARACTER c->dodgeAsDefense(true); log.displayNL("player id %s defense mode is now dodge",eid.toString().c_str()); return true; } return false; } // dodge // //----------------------------------------------- // set the defense mode to parry //----------------------------------------------- NLMISC_COMMAND(parry,"set the defense mode to parry","") { if ( args.size() >= 1 ) { GET_CHARACTER c->dodgeAsDefense(false); log.displayNL("player id %s defense mode is now parry",c->getId().toString().c_str()); return true; } return false; } // parry // //----------------------------------------------- // reset the ineffective aura and the power flags for given player //----------------------------------------------- NLMISC_COMMAND(resetPowerFlags,"reset the ineffective aura and the power flags for given character","") { if ( args.size() == 1) { GET_CHARACTER c->resetPowerFlags(); log.displayNL("resetPowerFlags for character %s ", c->getId().toString().c_str()); return true; } return false; } // resetPowerFlags //----------------------------------------------- // excute a sabrina phrase //----------------------------------------------- NLMISC_COMMAND(execPhrase,"execute a sabrina phrase"," [...]") { if ( args.size() >= 3 ) { GET_CHARACTER bool cyclic; NLMISC::fromString(args[1], cyclic); vector brickIds; for (uint i = 2 ; i < args.size() ; ++i) { CSheetId sheet(args[i]); brickIds.push_back( sheet ); } CPhraseManager::getInstance().executePhrase(c->getEntityRowId(), c->getTargetDataSetRow(), brickIds, cyclic); return true; } return false; } // execPhrase // //----------------------------------------------- // excute a sabrina phrase //----------------------------------------------- NLMISC_COMMAND(executeSabrinaPhrase,"execute a sabrina phrase, an sphrase"," ") { if ( args.size() == 3 ) { GET_CHARACTER bool cyclic; NLMISC::fromString(args[1], cyclic); CSheetId phraseSheet(args[2]); CPhraseManager::getInstance().executePhrase(c->getEntityRowId(), c->getTargetDataSetRow(), phraseSheet, cyclic); return true; } return false; } // executeSabrinaPhrase // //----------------------------------------------- // memorize a sabrina phrase //----------------------------------------------- NLMISC_COMMAND(memorizePhrase,"memorize a sabrina phrase"," [...]") { /* if ( args.size() >= 3 ) { CEntityId id; id.fromString(args[0].c_str()); uint8 index; NLMISC::fromString(args[1], index); CCharacter * c = PlayerManager.getChar( id ); if (c ) { vector brickIds; for (uint i = 2 ; i < args.size() ; ++i) { CSheetId sheet(args[i]); brickIds.push_back( sheet ); } c->memorize(index, brickIds ); } else { log.displayNL("invalid player id %s",id.toString().c_str()); } return true; } */ return false; } // memorizePhrase // //----------------------------------------------- // execute a memorized sabrina phrase //----------------------------------------------- NLMISC_COMMAND(execMemorizedPhrase,"memorize a memorized sabrina phrase"," ") { /* if ( args.size() >= 2 ) { CEntityId id; id.fromString(args[0].c_str()); uint8 index; NLMISC::fromString(args[1], index); bool cyclic; NLMISC::fromString(args[2], cyclic); CCharacter * c = PlayerManager.getChar( id ); if (c ) { c->executeMemorizedPhrase(index, cyclic,false); } else { log.displayNL("invalid player id %s",id.toString().c_str()); } return true; } */ return false; } // execMemorizedPhrase // ////////////////////////////////////////////////////////////////////////////// // Death commands until client interface is ready // ////////////////////////////////////////////////////////////////////////////// //----------------------------------------------- // Simulate character choice a re-spawn point until UI is ready //----------------------------------------------- NLMISC_COMMAND(respawnAfterDeath,"respawnAfterDeath at re-spawn point name, it must be valid (validated by PC and usable)","") { if ( args.size() == 2 ) { GET_CHARACTER uint16 idx; NLMISC::fromString(args[1], idx); // A death character can choose to re-spawn to a previously validated re-spawn point, a last of one re-spawn point is always valid c->respawn(idx); return true; } return false; } // execMemorizedPhrase // //----------------------------------------------- // Simulate Resurrection by other PC until UI is ready //----------------------------------------------- NLMISC_COMMAND(resurrected,"Another PC resurrect PC by giving some energy","") { if( args.size() == 1 ) { GET_CHARACTER c->resurrected(); return true; } return false; } //----------------------------------------------- // Simulate buy kami / karavan pact until UI is ready //----------------------------------------------- NLMISC_COMMAND(buyPact,"Buy Kami or Karavan pact","") { if( args.size() == 3 ) { GET_CHARACTER // Character buy pact with Kami / Karavan by botchat (same has trade) // effect is validate re-spawn point for one use c->buyPact( args[1] ); return true; } return false; } //----------------------------------------------- // Simulate validate re-spawn point until UI is ready //----------------------------------------------- NLMISC_COMMAND(validateRespawnPoint,"Validate re-spawn point","") { if( args.size() == 2 ) { GET_CHARACTER CCharacterRespawnPoints::TRespawnPoint respawnPoint; NLMISC::fromString(args[1], respawnPoint); c->getRespawnPoints().addRespawnPoint(respawnPoint); return true; } return false; } NLMISC_COMMAND(displayForageRM,"Display forageable raw materials near by or at the exact position of a player"," ") { if ( args.size() < 1 ) return false; GET_CHARACTER bool exactPos = ! ((args.size() > 1) && (args[1] == "0")); bool extendedInfo = (args.size() > 2) && (args[2] == "1"); CFgProspectionPhrase::displayRMNearBy( c, exactPos, extendedInfo, &log ); return true; } NLMISC_COMMAND(setItemSapLoad,"set an item sap load","") { if ( args.size() != 3) return false; GET_CHARACTER uint slot; NLMISC::fromString(args[1], slot); float value = (float)atof(args[2].c_str()); // vector& items = (vector &)c->getInventory()[INVENTORIES::bag]->getChildren(); CInventoryPtr invent = c->getInventory(INVENTORIES::bag); // if ( slot >= invent->getNumChildren() ) if ( slot >= invent->getSlotCount() ) { // log.displayNL("Invalid slot %u max = %u",slot, items.size()-1); log.displayNL("Invalid slot %u max = %u",slot, invent->getSlotCount()-1); return true; } // if( items[slot] == NULL ) if( invent->getItem(slot) == NULL ) { log.displayNL("empty slot %u",slot); return true; } uint32 sapLoad = 0; // CGameItemPtr item = invent->getChildItem(slot); CGameItemPtr item = invent->getItem(slot); // if ( items[slot]->getSheetId() == CSheetId("stack.sitem") ) // if (item->getSheetId() == CSheetId("stack.sitem") ) // { //// for ( uint i = 0; i < items[slot]->getChildren().size(); i++ ) // for ( uint i = 0; i < item->getNumChildren(); i++ ) // { //// if ( items[slot]->getChildren()[i] != NULL) // if ( item->getChildItem(i) != NULL) // { //// items[slot]->getChildren()[i]->setMaxSapLoad( value ); // item->getChildItem(i)->setMaxSapLoad( value ); //// sapLoad = items[slot]->getChildren()[i]->maxSapLoad(); // sapLoad = item->getChildItem(i)->maxSapLoad(); // } // } // } // else { // items[slot]->setMaxSapLoad( value ); item->setMaxSapLoad( value ); // sapLoad = items[slot]->maxSapLoad(); sapLoad = item->maxSapLoad(); } //trap c->incSlotVersion( INVENTORIES::bag,slot); log.displayNL("item in slot %u has now a sap load of %u",slot,sapLoad); return true; } NLMISC_COMMAND( showFBT, "show Focus Beta Tester title if the player is a FBT", "" ) { if ( args.size() != 1 ) return false; GET_CHARACTER CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( c->getId() ) ); if (p == NULL) { nlwarning ("ADMIN: Can't find player with UserId %d", PlayerManager.getPlayerId(c->getId())); return false; } if (!p->isBetaTester()) { nlwarning ("ADMIN: UserId %d is not a FBT", PlayerManager.getPlayerId(c->getId())); return false; } c->setTitle(CHARACTER_TITLE::FBT); c->registerName(); return true; } NLMISC_COMMAND( summonPet, "player can summon it's pet one time only", "" ) { if ( args.size() != 2 ) return false; GET_CHARACTER uint32 index; NLMISC::fromString(args[1], index); --index; const std::vector< CPetAnimal >& pet = c->getPlayerPets(); if( index < pet.size() ) { if( pet[ index ].PetStatus != CPetAnimal::not_present ) { if( pet[ index ].IsTpAllowed ) { c->sendPetCommand( CPetCommandMsg::DESPAWN, index, true ); c->setPetStatus( index, CPetAnimal::waiting_spawn ); c->setSpawnPetFlag( index ); c->petTpAllowed( index, false ); } } } return true; } NLMISC_COMMAND( allowSummonPet, "autorize player summon it's pet one time only", "" ) { if ( args.size() != 2 ) return false; GET_CHARACTER uint32 index; NLMISC::fromString(args[1], index); --index; const std::vector< CPetAnimal >& pet = c->getPlayerPets(); if( index < pet.size() ) { if( pet[ index ].PetStatus != CPetAnimal::not_present ) { c->petTpAllowed( index, true ); } } return true; } // // // You can add here all variables to administrate this service. // // NLMISC_DYNVARIABLE (float, RyzomTime, "Current ryzom time") { if (get) { *pointer = CTimeDateSeasonManager::getRyzomTimeReference().getRyzomTime (); } /* else { CMessage msgout ("SET_RYZOM_TIME"); msgout.serial (*pointer); CUnifiedNetwork::getInstance()->send( "WOS", msgout ); } */ } NLMISC_DYNVARIABLE (uint32, RyzomDate, "Current ryzom date") { if (get) { *pointer = CTimeDateSeasonManager::getRyzomTimeReference().getRyzomDay (); } /* else { CMessage msgout ("SET_RYZOM_DAY"); msgout.serial (*pointer); CUnifiedNetwork::getInstance()->send( "WOS", msgout ); } */ } // // // // void audit(const CAdminCommand *cmd, const string &rawCommand, const CEntityId &eid, const string &name, const string &targetName) { if (cmd == NULL) return; CConfigFile::CVar *varHost = IService::getInstance()->ConfigFile.getVarPtr("AdminCommandAuditHost"); CConfigFile::CVar *varPage = IService::getInstance()->ConfigFile.getVarPtr("AdminCommandAuditPage"); if (varHost == NULL || varPage == NULL) return; string host = varHost->asString(); string page = varPage->asString(); if (host == "" || page == "") return; char params[1024]; sprintf(params, "action=audit&cmd=%s&raw=%s&name=(%s,%s)&target=%s", cmd->Name.c_str(), rawCommand.c_str(), eid.toString().c_str(), name.c_str(), targetName.c_str()); IThread *thread = IThread::create(new CHttpPostTask(host, page, params)); thread->start(); } // all admin /a /b commands executed by the client go in this callback void cbClientAdmin (NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId) { H_AUTO(cbClientAdmin); CEntityId eid; CEntityId targetEid; msgin.serial (eid); bool onTarget; msgin.serial (onTarget); CSString cmdName, arg; msgin.serial (cmdName, arg); nlinfo("ADMIN: Executing admin command: eid=%s onTarget=%s cmdName=%s arg=%s",eid.toString().c_str(),onTarget?"true":"false",cmdName.quote().c_str(),arg.quote().c_str()); TLogContext_Command_ExecCtx logContext(eid); // find the character CCharacter *c = PlayerManager.getChar( eid ); if (c == 0) { nlwarning ("ADMIN: Unknown player %s", eid.toString().c_str()); chatToPlayer (eid, "Unknown player"); return; } // test character is ready and valid if (!c->getEnterFlag()) { nlwarning("ADMIN: player %s not ready", eid.toString().c_str()); return; } if (!TheDataset.isAccessible(c->getEntityRowId())) { nlwarning("ADMIN: player %s not ready in mirror (invalid rowid)", eid.toString().c_str()); return; } // find if the command is available const CAdminCommand * cmd = findAdminCommand(cmdName); if (!cmd) { nlinfo("ADMIN: Player %s tried to execute a no valid client admin command '%s'", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "Unknown command"); return; } if (!c->havePriv(cmd->Priv)) { nlinfo("ADMIN: Player %s doesn't have privilege to execute the client admin command '%s' ", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return; } if (onTarget && !c->haveAnyPrivilege()) { nlinfo("ADMIN: Player %s doesn't have privilege to execute /b command onTarget '%s' ", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return; } if (!cmd->ForwardToservice.empty()) { // we need to forward the command to another service if (IClientCommandForwader::getInstance()) { IClientCommandForwader::getInstance()->sendCommand(cmd->ForwardToservice, cmdName, eid, onTarget, onTarget ? c->getTarget() : CEntityId::Unknown, arg); } } else { // execute locally // create the command line string res = cmdName + " "; if( cmdName == string("Position") ) { // check validity of Position command if( onTarget ) { if( !c->havePriv(":DEV:SGM:GM:EM:") ) { nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command /b '%s' ", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return; } } } std::string targetName = string("implicite"); // add the eid of the player or target if necessary if (cmd->AddEId) { if(onTarget) { log_Command_ExecOnTarget(c->getTarget(), cmdName, arg); res += c->getTarget().toString(); targetEid = c->getTarget(); targetName = NLMISC::toString("(%s,%s)", c->getTarget().toString().c_str(), CEntityIdTranslator::getInstance()->getByEntity(c->getTarget()).toString().c_str()); } else { log_Command_Exec(cmdName, arg); res += eid.toString(); targetEid = eid; targetName = string("Himself"); } res += " "; } res += arg; TLogContext_Item_Command itemCtx(onTarget ? c->getTarget() : eid); TLogContext_Character_BuyRolemasterPhrase characterCtx(onTarget ? c->getTarget() : eid); std::string csName = CEntityIdTranslator::getInstance()->getByEntity(eid).toString(); NLMISC::CSString cs_res = CSString(res); cs_res = cs_res.replace("#player", eid.toString().c_str()); if (c->getTarget() != CEntityId::Unknown) { cs_res = cs_res.replace("#target", c->getTarget().toString().c_str()); cs_res = cs_res.replace("#gtarget", string("#"+c->getTarget().toString()).c_str()); } res = (string)cs_res; nlinfo ("ADMIN: Player (%s,%s) will execute client admin command '%s' on target %s", eid.toString().c_str(), csName.c_str(), res.c_str(), targetName.c_str()); audit(cmd, res, eid, csName, targetName); CLightMemDisplayer *CmdDisplayer = new CLightMemDisplayer("CmdDisplayer"); CLog *CmdLogger = new CLog( CLog::LOG_NO ); CmdLogger->addDisplayer( CmdDisplayer ); NLMISC::ICommand::execute(res, *CmdLogger, true); const std::deque &strs = CmdDisplayer->lockStrings (); for (uint i = 0; i < strs.size(); i++) { InfoLog->displayNL("%s", trim(strs[i]).c_str()); SM_STATIC_PARAMS_1(params,STRING_MANAGER::literal); params[0].Literal = trim(strs[i]); CCharacter::sendDynamicSystemMessage( eid, "LITERAL", params ); } CmdDisplayer->unlockStrings(); CmdLogger->removeDisplayer (CmdDisplayer); delete CmdDisplayer; delete CmdLogger; } } // all admin /c commands executed by the client go in this callback void cbClientAdminOffline (NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId) { H_AUTO(cbClientAdminOffline); CEntityId eid; msgin.serial (eid); string characterName; msgin.serial(characterName); string cmdName, arg; msgin.serial (cmdName, arg); nlinfo("ADMIN: Executing admin /c command: eid=%s onTarget=%s cmdName=%s arg=%s",eid.toString().c_str(),characterName.c_str(),cmdName.c_str(),arg.c_str()); // find the character CCharacter *c = PlayerManager.getChar( eid ); if (c == 0) { nlwarning ("ADMIN: Unknown player %s", eid.toString().c_str()); chatToPlayer (eid, "Unknown player"); return; } // test character is ready and valid if (!c->getEnterFlag()) { nlwarning("ADMIN: player %s not ready", eid.toString().c_str()); return; } if (!TheDataset.isAccessible(c->getEntityRowId())) { nlwarning("ADMIN: player %s not ready in mirror (invalid rowid)", eid.toString().c_str()); return; } // find if the command is available const CAdminCommand * cmd = findAdminCommand(cmdName); if (!cmd) { nlwarning ("ADMIN: Player %s tried to execute a no valid client admin command '%s'", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "Unknown command"); return; } if (!c->havePriv(cmd->Priv)) { nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command '%s' ", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return; } if (!c->haveAnyPrivilege()) { nlinfo("ADMIN: Player %s doesn't have privilege to execute /c command '%s' ", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return; } // find the character eid CEntityId charEid = CEntityIdTranslator::getInstance()->getByEntity(characterName); if (charEid == CEntityId::Unknown) { nlwarning ("ADMIN: Unknown character %s", characterName.c_str()); return; } if( cmdName == string("Position") ) { // check validity of Position command if( !c->havePriv(":DEV:SGM:GM:EM:") ) { nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command /c '%s' ", eid.toString().c_str(), cmdName.c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return; } } // create the command line string res = cmdName + " "; // add the eid of the player or target if necessary if (cmd->AddEId) { res += charEid.toString(); res += " "; } res += arg; std::string csName = CEntityIdTranslator::getInstance()->getByEntity(eid).toString(); std::string targetName = NLMISC::toString("(%s,%s)", CEntityIdTranslator::getInstance()->getByEntity( ucstring(characterName) ).toString().c_str(), characterName.c_str() ); nlinfo("ADMINOFFLINE: Player (%s,%s) will execute client admin command '%s' on target %s", eid.toString().c_str(), csName.c_str(), res.c_str(), targetName.c_str()); NLMISC::ICommand::execute(res, *InfoLog); } void cbRemoteClientCallback (uint32 rid, const std::string &cmd, const std::string &entityNames) { vector entities; selectEntities (entityNames, entities); for (uint i = 0; i < entities.size(); i++) { CCharacter *c = PlayerManager.getChar(entities[i]); if (c != 0) { nlinfo ("ADMIN: I have to send a request for admin to a client : rid %d cmd '%s' eid %s", rid, cmd.c_str(), entities[i].toString().c_str()); CMessage msgout ("IMPULSION_ID"); msgout.serial (entities[i]); CBitMemStream bms; if (!GenericMsgManager.pushNameToStream ("COMMAND:REMOTE_ADMIN", bms)) nlstopex (("Missing a message in the msg.xml")); bms.serial (rid); bms.serial (const_cast(cmd)); msgout.serialBufferWithSize ((uint8*)bms.buffer(), bms.length()); sendMessageViaMirror (NLNET::TServiceId(entities[i].getDynamicId()), msgout); } } } void cbClientRemoteAdmin( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId) { H_AUTO(cbClientRemoteAdmin); CEntityId eid; msgin.serial (eid); uint32 rid; msgin.serial (rid); string cmd; msgin.serial (cmd); string answer; msgin.serial (answer); vector vara, vala; if (ICommand::isCommand(cmd)) { vara.push_back ("__log"); vala.push_back ("----- Result from "+eid.toString()+" "+IService::getInstance()->getServiceUnifiedName()+" of command '"+cmd+"'\n"); vala.push_back (answer); } else { vara.push_back ("service"); vala.push_back (IService::getInstance ()->getServiceUnifiedName()); vara.push_back ("entity"); vala.push_back (eid.toString()); vara.push_back (cmd); vala.push_back (answer); } nlinfo ("ADMIN: received an answer from %s for command '%s' that is '%s' for rid %d", eid.toString().c_str(), cmd.c_str(), answer.c_str(), rid); addRequestAnswer (rid, vara, vala); } //---------------------------------------------------------------------------- NLMISC_COMMAND( displayWeather, "Display current weather at specified pos", " " ) { if ( args.size() < 2 ) return false; CVector pos; pos.x = (float)atof( args[0].c_str() ); pos.y = (float)atof( args[1].c_str() ); pos.z = 0; CRyzomTime::EWeather weather = WeatherEverywhere.getWeather( pos, CTimeDateSeasonManager::getRyzomTimeReference() ); log.displayNL( "Weather: %u", (uint)weather ); return true; } /*********************************************************************************************************************** BELOW ARE OFFICIAL CSR COMMANDS ***********************************************************************************************************************/ NLMISC_COMMAND( csrCmd, "Invoke a CSR command from service console or admin tool without the need to have a CSR logged in", " +" ) { if (args.empty()) return false; // build the command line string command = args[0]; command += string(" (0x0000000000:00:00:00) "); for (uint i=1; i" ) { if ( args.empty() ) return false; string msg = args[0]; for ( uint i = 1; i < args.size(); i++ ) { msg+= " " + args[i]; } MessageOfTheDay = msg; return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( summon, "summon a player in front of the CSR", "" ) { if ( args.size() !=2 ) return false; GET_CHARACTER CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[1]) ); if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) ) { CCharacter::sendDynamicSystemMessage( eid, "CSR_PENDING_CHARACTER_LOG" ); COfflineEntityState state; state.X = c->getState().X; state.Y = c->getState().Y; state.Z = c->getState().Z; state.Heading = c->getState().Heading; CGmTpPendingCommand::getInstance()->addTpPendingforCharacter( args[1], state ); return true; } CHECK_RIGHT( c,target ); if(target->getCurrentContinent() == CONTINENT::NEWBIELAND ) { if( c->getCurrentContinent() != CONTINENT::NEWBIELAND ) { log.displayNL( "Summon player outside NEWBIELAND is forbiden, try to made an illegal action, this is loged.", eid.toString().c_str()); chatToPlayer (eid, "You don't have privilege to execute this command"); return true; } } COfflineEntityState state; state.X = target->getState().X; state.Y = target->getState().Y; state.Z = target->getState().Z; state.Heading = target->getState().Heading; PlayerManager.addSummonnedUser( target->getEntityRowId(), state ); state.X = c->getState().X + sint32 (cos (c->getState().Heading) * 2000); state.Y = c->getState().Y + sint32 (sin (c->getState().Heading) * 2000); state.Z = c->getState().Z; state.Heading = c->getState().Heading + (float)NLMISC::Pi; if ( state.Heading >= (float)NLMISC::Pi ) state.Heading -= 2* (float)NLMISC::Pi; target->allowNearPetTp(); target->tpWanted( state.X, state.Y, state.Z, true, state.Heading ); return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( dismiss, "teleport a player back to its former position ( before last call to summonPlayer )", "" ) { if ( args.size() !=2 ) return false; TRY_GET_CHARACTER CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) ); if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) ) { CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" ); return true; } CHECK_RIGHT( c,target ); COfflineEntityState state; if ( PlayerManager.getDismissCoords( target->getEntityRowId(), state ) ) { target->allowNearPetTp(); target->tpWanted( state.X, state.Y, state.Z, true, state.Heading ); CContinent * cont = CZoneManager::getInstance().getContinent(state.X, state.Y); if ( cont ) { target->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(cont->getId()) ); } PlayerManager.removeSummonedUser( target->getEntityRowId() ); } else { CCharacter::sendDynamicSystemMessage( eid, "CSR_NOT_SUMMONED" ); } return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( teleport, "teleport the CSR in front of a player", "" ) { if ( args.size() !=2 ) return false; GET_CHARACTER CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) ); if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) ) { CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" ); return true; } float heading = target->getState().Heading; sint32 x = target->getState().X + sint32 (cos (target->getState ().Heading) * 2000); sint32 y = target->getState().Y + sint32 (sin (target->getState ().Heading) * 2000); sint32 z = target->getState().Z; heading += (float)NLMISC::Pi; if ( heading >= (float)NLMISC::Pi ) heading -= 2* (float)NLMISC::Pi; c->allowNearPetTp(); c->teleportCharacter(x, y, z, true, true, heading); CContinent * continent = CZoneManager::getInstance().getContinent(x, y); if (continent != NULL) { c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(continent->getId()) ); } return true; } //---------------------------------------------------------------------------- //static string capitalize(const string & s) //{ // if ( s.empty() ) // return s; // // return toUpper( s.substr(0,1) ) + toLower( s.substr(1,string::npos) ); //} //---------------------------------------------------------------------------- NLMISC_COMMAND( renamePlayerForEvent, "rename a player for the event", "" ) { if ( args.size() != 3 ) return false; ucstring newName( args[2] ); TRY_GET_CHARACTER CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) ); if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) ) { CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" ); return true; } CHECK_RIGHT( c,target ); // assign new name to player // PlayerManager.addEntityForStringIdRequest( target->getId() ); target->registerName(newName); return true; } //---------------------------------------------------------------------------- //NLMISC_COMMAND( renamePlayer, "rename a player", "" ) //{ // if ( args.size() != 3 ) // return false; // // ucstring oldName( capitalize(args[1]) ); // ucstring newName( capitalize(args[2]) ); // TRY_GET_CHARACTER // CCharacter * target = PlayerManager.getCharacterByName( args[1] ); // if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) ) // { // CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" ); // return true; // } // CHECK_RIGHT( c,target ); // // if ( CEntityIdTranslator::getInstance()->entityNameExists( newName ) ) // { // CCharacter::sendDynamicSystemMessage( eid, "CSR_NAME_EXISTS" ); // return true; // } // // // assign new name to player // bool result = CNameManager::getInstance()->assignName( target->getId(), newName ); // if ( !result ) // { // CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_NAME" ); // nlwarning("assignName failed for name: %s", newName.toUtf8().c_str() ); // return true; // } // PlayerManager.addEntityForStringIdRequest( target->getId() ); // target->setName( newName ); // target->registerName(); // // if ( toLower(newName) != toLower(oldName) ) // { // // liberate old name // CNameManager::getInstance()->liberateName( target->getId(), oldName ); // } // // return true; //} //---------------------------------------------------------------------------- NLMISC_COMMAND( renameGuild, "rename a guild", " | " ) { if ( args.size() != 3 ) return false; if (args[0]!="admin_tool") { TRY_GET_CHARACTER } GET_GUILD(1, true, NLMISC::CEntityId::Unknown); ucstring name( args[2] ); // check if name already exists in the player list if ( NLMISC::CEntityIdTranslator::getInstance()->entityNameExists( name ) /*|| EGSPD::PDSLib.getStringManager().stringExists(name, RYZOMID::guildName)*/ ) { if (args[0]=="admin_tool") { log.displayNL("renameGuild failed because the name is already taken: ",args[2].c_str()); } else { TRY_GET_CHARACTER CCharacter::sendDynamicSystemMessage( eid,"CSR_NAME_EXISTS" ); } return false; } guild->setName( name ); if (IGuildUnifier::getInstance() != NULL) IGuildUnifier::getInstance()->broadcastGuildUpdate(guild); // CGuildManager::getInstance()->addGuildsAwaitingString(name,guild->getId()); return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( setGuildDescription, "set a guild description", "| " ) { if ( args.size() != 2) return false; GET_GUILD(0, true, NLMISC::CEntityId::Unknown); ucstring desc( args[1] ); guild->setDescription( desc ); if (IGuildUnifier::getInstance() != NULL) IGuildUnifier::getInstance()->broadcastGuildUpdate(guild); // CGuildManager::getInstance()->addGuildsAwaitingString(desc,guild->getId()); return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( setGuildIcon, "set a guild icon", "| " ) { if ( args.size() != 2) return false; GET_GUILD(0, true, NLMISC::CEntityId::Unknown); uint64 icon = atoiInt64( args[1].c_str() ); guild->setIcon( icon ); if (IGuildUnifier::getInstance() != NULL) IGuildUnifier::getInstance()->broadcastGuildUpdate(guild); return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( killMob, "kill a mob ( /a killMob )", "" ) { if ( args.size() != 1 ) return false; TRY_GET_CHARACTER CCreature * creature = CreatureManager.getCreature( c->getTarget() ); if( creature == 0 ) { nlwarning ("Unknown creature '%s'", c->getTarget().toString().c_str() ); return false; } if(!TheDataset.isAccessible(creature->getEntityRowId())) { nlwarning ("'%s' is not valid in mirror", c->getTarget().toString().c_str()); return false; } if ( !creature->getContextualProperty().directAccessForStructMembers().attackable() ) { if ( ! creature->checkFactionAttackable(c->getId())) { CCharacter::sendDynamicSystemMessage( eid, "CSR_NOT_ATTACKABLE" ); return true; } } creature->getScores()._PhysicalScores[SCORES::hit_points].Current = 0; return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( dssTarget, "target a mob and send information to dss( /b dssTarget )", "[]" ) { if ( args.size() < 1 ) return false; TRY_GET_CHARACTER CCreature * creature = CreatureManager.getCreature( c->getTarget() ); if( creature == 0 ) { nlwarning ("Unknown creature '%s'", c->getTarget().toString().c_str() ); return false; } if(!TheDataset.isAccessible(creature->getEntityRowId())) { nlwarning ("'%s' is not valid in mirror", c->getTarget().toString().c_str()); return false; } NLMISC::CEntityId creatureId = creature->getId(); TAIAlias alias = CAIAliasTranslator::getInstance()->getAIAlias(creatureId); TDataSetRow entityRowId = creature->getEntityRowId(); if (alias == CAIAliasTranslator::Invalid) { nlwarning ("'%s' has no alias translation", creatureId.toString().c_str()); return false; } CMessage msgout("DSS_TARGET"); msgout.serial(eid); //eid of the player msgout.serial(creatureId); // eid of the mob msgout.serial(alias); //mob targeted msgout.serial(entityRowId); //datasetrow uint32 args_size = (uint32)args.size() - 1; uint32 i = 0; msgout.serial(args_size); for ( ; i != args_size ; ++i) { std::string str = args[1+i]; msgout.serial(str); } CUnifiedNetwork::getInstance()->send("DSS", msgout); return true; } //---------------------------------------------------------------------------- NLMISC_COMMAND( root, "root a player", "