Fix
[ryzomcore.git] / ryzom / server / src / entities_game_service / admin.cpp
blobc47fdb1f73e7f607755b183d08e9c28996dcd176
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2019-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 // User Privilege set in the mysql database must be like that ":GM:" or "" or ":GM:ADMIN:" ....
31 // Includes
34 #include "stdpch.h"
36 #include "admin.h"
38 #include "nel/misc/common.h"
39 #include "nel/misc/command.h"
40 #include "nel/misc/variable.h"
41 #include "nel/misc/eid_translator.h"
42 #include "nel/misc/algo.h"
43 #include "nel/misc/sstring.h"
44 #include "nel/misc/i18n.h"
45 #include "nel/misc/string_view.h"
47 #include "nel/net/admin.h"
48 #include "nel/net/service.h"
50 #include "game_share/scores.h"
51 #include "game_share/send_chat.h"
52 #include "game_share/time_weather_season/time_date_season_manager.h"
53 #include "game_share/permanent_ban_magic_number.h"
54 #include "game_share/fame.h"
55 #include "game_share/outpost.h"
56 #include "game_share/visual_slot_manager.h"
57 #include "game_share/shard_names.h"
58 #include "game_share/http_client.h"
59 #include "server_share/log_command_gen.h"
60 #include "server_share/r2_vision.h"
61 #include "server_share/mongo_wrapper.h"
63 #include "egs_sheets/egs_sheets.h"
64 #include "egs_sheets/egs_static_rolemaster_phrase.h"
65 #include "egs_sheets/egs_static_encyclo.h"
67 #include "player_manager/player_manager.h"
68 #include "player_manager/player.h"
69 #include "player_manager/character.h"
70 #include "player_manager/character_encyclopedia.h"
71 #include "player_manager/player_room.h"
72 #include "creature_manager/creature_manager.h"
73 #include "phrase_manager/phrase_manager.h"
74 #include "mission_manager/mission_manager.h"
75 #include "mission_manager/mission_queue_manager.h"
77 #include "entities_game_service.h"
78 #include "player_manager/character_respawn_points.h"
79 #include "weather_everywhere.h"
80 #include "phrase_manager/fg_prospection_phrase.h"
81 #include "team_manager/team_manager.h"
82 #include "world_instances.h"
83 #include "egs_variables.h"
84 #include "building_manager/building_manager.h"
85 #include "building_manager/building_physical.h"
86 #include "player_manager/gm_tp_pending_command.h"
87 #include "guild_manager/guild_manager.h"
88 #include "guild_manager/guild.h"
89 #include "guild_manager/guild_member.h"
90 #include "guild_manager/guild_member_module.h"
91 #include "guild_manager/guild_char_proxy.h"
92 #include "guild_manager/fame_manager.h"
93 #include "mission_manager/mission_solo.h"
94 #include "position_flag_manager.h"
95 //#include "name_manager.h"
96 #include "zone_manager.h"
97 #include "player_manager/character_game_event.h"
98 #include "game_event_manager.h"
99 #include "dyn_chat_egs.h"
100 #include "admin_log.h"
102 #include "pvp_manager/pvp.h"
103 #include "pvp_manager/pvp_manager_2.h"
104 #include "player_manager/admin_properties.h"
105 #include "shop_type/offline_character_command.h"
106 #include "player_manager/item_service_manager.h"
107 #include "outpost_manager/outpost_manager.h"
108 #include "primitives_parser.h"
109 #include "shop_type/named_items.h"
110 #include "progression/progression_pvp.h"
112 #include "modules/shard_unifier_client.h"
113 #include "modules/client_command_forwarder.h"
114 #include "modules/guild_unifier.h"
115 #include "server_share/log_command_gen.h"
116 #include "server_share/log_item_gen.h"
117 #include "server_share/log_character_gen.h"
118 #include "server_share/used_continent.h"
121 // Externs
124 // Max number of user channel character can be have
125 #define NB_MAX_USER_CHANNELS 2
127 extern CPlayerManager PlayerManager;
128 extern CCreatureManager CreatureManager;
129 extern CPlayerService *PS;
130 extern CGenericXmlMsgHeaderManager GenericMsgManager;
131 extern CBSAIDeathReport BotDeathReport;
132 extern NLMISC::CVariable<uint32> FixedSessionId;
135 // Namespaces
138 using namespace NLMISC;
139 using namespace NLNET;
140 using namespace std;
142 extern CVariable<string> BannerPriv;
143 extern CVariable<string> ArkSalt;
146 // Functions
150 // ALL THESE COMMANDS ARE USED BY THE CLIENT *AND* THE ADMIN TOOL TO MANAGE A PLAYER
152 // You can assume here that the user can execute the command, you don't have to check it
154 // Don't forget to add your command in the AdminCommandsInit array if you want the command to be executed on the client
156 // If you change parameter or add/remove something, please update the wiki:
158 // http://www.nevrax.net/wiki/index.php/Main/CommandesAdmin
161 // AddEid must be true if you want to have the eid in the args[0] of the command
163 // Privileges are now stored in a text file (data_shard/client_commands_privileges.txt), do not forget to update it.
166 // please update the following stuff if you add new GM titles
167 // player_manager.cpp : NLMISC_COMMAND(setPriv,"set a privilege to a user using his user id, must be in form :priv1:priv2:priv3:","<uid> <priv>")
168 // player_manager.cpp : hasBetterCSRGrade
169 static const struct
171 const char * Name;
172 bool AddEId;
174 AdminCommandsInit[] =
176 // player character accessible commands
177 "teamInvite", true,
178 "setLeague", true,
179 "leagueInvite", true,
180 "leagueKick", true,
181 "guildInvite", true,
182 "roomInvite", true,
183 "roomKick", true,
184 "setGuildMessage", true,
185 "clearGuildMessage", true,
186 "dodge", true,
187 "parry", true,
188 "respawnAfterDeath", true,
189 "resurrected", true,
190 "validateRespawnPoint", true,
191 "summonPet", true,
192 "connectUserChannel", true,
193 "connectLangChannel", true,
194 "setDontTranslateLangs", true,
195 "updateTarget", true,
196 "resetName", true,
197 "showOnline", true,
199 "openTargetApp", true,
200 "openTargetUrl", true,
202 // DEPECRATED !!!
203 "webExecCommand", true,
204 "webDelCommandsIds", true,
205 "webAddCommandsIds", true,
207 "addPetAnimal", true,
208 "addSkillPoints", true,
209 "addXPToSkill", true,
210 "changeMode", true,
211 "checkTargetSP", true,
212 "clearFriendsList", true,
213 "clearIgnoreList", true,
214 "clearIsFriendOfList", true,
215 "createItemInBag", true,
216 "createItemInInv", true,
217 "createItemInTmpInv", true,
218 "createNamedItemInBag", true,
219 "createFullArmorSet", true,
220 "displayInfosOnTarget", true,
221 "execPhrase", true,
222 "execMemorizedPhrase", true,
223 "executeSabrinaPhrase", true,
224 "forceTargetToDie", true,
225 "learnAllBricks", true,
226 "learnAllRolemasterBricks", true,
227 "learnAllPhrases", true,
228 "learnBrick", true,
229 "unlearnBrick", true,
230 "learnPhrase", true,
231 "learnAllForagePhrases", true,
232 "learnAllFaberPlans", true,
233 "logXpGain", true,
234 "memorizePhrase", true,
235 "resetPowerFlags", true,
236 "setSkillsToMaxValue", true,
237 "displayForageRM", true,
238 "setItemSapLoad", true,
239 "showFBT", true,
240 "allowSummonPet", true,
241 "setPetAnimalSatiety", true,
242 "getPetAnimalSatiety", true,
243 "setPetAnimalName", true,
244 "taskPass", true,
245 "setFamePlayer", true,
246 "guildMOTD", true,
248 // CSR commands
249 "motd", false,
250 "broadcast", false,
251 "summon", true,
252 "dismiss", true,
253 "teleport", true,
254 "renamePlayerForEvent", true,
255 "renamePlayer", true,
256 "renameGuild", true,
257 "setGuildDescription", false,
258 "setGuildIcon", false,
259 "killMob", true,
260 "changeVar", true,
261 "root", true,
262 "unroot", true,
263 "ignoreTells", true, // hierarchy
264 "showCSR", true,
265 "monitorMissions", true,
266 "stopMonitorMissions", true,
267 "failMission", true,
268 "progressMission", true,
269 "mute", true,
270 "unmute", true,
271 "muteUniverse", true,
272 "unmuteUniverse", true,
273 "universe", true,
274 "setGMGuild", true,
275 "targetInfos", true,
276 "infos", true,
277 "addPosFlag", true,
278 "setPosFlag", true,
279 "delPosFlag", true,
280 "lPosFlags", true,
281 "listPosFlags", true,
282 "tpPosFlag", true,
283 "updateGuildMembersList", true,
284 "listGuildMembers", true,
285 "addGuildMember", true,
286 "setGuildMemberGrade", true,
287 "setGuildLeader", true,
288 "startEvent", true,
289 "stopEvent", true,
290 "getEventFaction", true,
291 "setEventFaction", true,
292 "clearEventFaction", true,
293 "giveRespawnPoint", true,
294 "provideItemService", true,
295 "dumpFactionPVPDamage", true,
296 "changeHairCut", true,
297 "farTPPush", true,
298 "farTPReplace", true,
299 "farTPReturn", true,
300 "resetPVPTimers", true,
301 "savePlayerActiveChar", false,
302 "reloadPlayer", false,
303 "characterMissionDump", true,
304 "removeMission", true,
305 "addMission", true,
306 // CSR variables
307 "Invisible", true, // not in /who; hierarchy except for user with privilege
308 "God", true,
309 "Invulnerable", true,
310 "ShowFactionChannels", true,
311 "CreateCharacterStartSkillsValue", false,
312 "HP", true,
313 "MaxHP", true,
314 "Speed", true,
315 "Money", true,
316 "MoneyGuild", true,
317 "FactionPoint", true,
318 "Name", true,
319 "Position", true,
320 "Priv", true,
321 "PriviledgePVP", true,
322 "FullPVP", true,
323 "FBT", true,
324 "RyzomDate", false,
325 "RyzomTime", false,
326 "addGuildXp", false,
327 "setGuildChargePoint", false,
328 "characterInventoryDump", true,
329 "deleteInventoryItem", true,
330 "setSimplePhrase", false,
332 // PUT HERE THE VARIABLE / COMMAND THAT ARE TEMPORARY
333 // remove when message of the day interface is ready
334 // remove this when death interface is ready
335 "respawnCharacter", true,
336 "buyPact", true,
337 "cancelTopPhrase", true, //temp : to remove
338 "EntitiesNoActionFailure", false,
339 "EntitiesNoCastBreak", false,
340 "EntitiesNoResist", false,
341 "lockItem", true,
342 "setTeamLeader", true,
343 // aggroable state
344 "Aggro", true,
346 // outpost commands
347 "outpostBanGuild", false,
348 "outpostBanPlayer", false,
349 "outpostUnbanGuild", false,
350 "outpostUnbanPlayer", false,
351 "outpostChallengeByGuild", false,
352 "outpostSimulateTimer0End", false,
353 "outpostSimulateTimer1End", false,
354 "outpostSimulateTimer2End", false,
355 "outpostSetFightData", false,
356 "setOutpostLevel", false,
357 "outpostAccelerateConstruction", false,
358 "outpostSetOutpostOwner", false,
359 "outpostChallengeOutpost", true,
360 "outpostGiveupOutpost", true,
361 "outpostDisplayGuildOutposts", true,
362 "outpostForceOpenGuildInventory", true,
363 "outpostForceCloseGuildInventory", true,
364 "outpostSetPlayerPvpSide", true,
365 "outpostSetOutpostToPlayer", true,
366 "outpostSelectOutpost", true,
367 "outpostUnselectOutpost", true,
369 "setPvpClan", true, //remove it when interface fo choose pvp clan is ready
370 "setPvPTag", true, //set pvp tag to true or false
372 // stuff added by sadge for testing character read/ write stuff
373 "saveToXML", true,
374 "loadFromXML", true,
375 "saveToPDR", true,
376 "loadFromPDR", true,
378 // queues related stuff
379 "acceptProposalForQueue", true,
380 "awakePlayerInQueue", true,
382 "displayShopSelector", true,
384 "addFactionAttackableToTarget", true,
385 "eventCreateNpcGroup", true,
386 "eScript", true,
387 "eventNpcGroupScript", true,
388 "eventSetBotName", true,
389 "eventSetBotScale", true,
390 "eventSetNpcGroupAggroRange", true,
391 "eventSetNpcGroupEmote", true,
392 "eventSetFaunaBotAggroRange", true,
393 "eventResetFaunaBotAggroRange", true,
394 "eventSetBotCanAggro", true,
395 "eventSetItemCustomText", true,
396 "eventResetItemCustomText", true,
397 "eventSetBotSheet", true,
398 "eventSetBotFaction", true,
399 "eventSetBotFameByKill", true,
400 "dssTarget", true, //ring stuff
401 "forceMissionProgress", true,
402 "eventSetBotURL", true,
403 "eventSetBotURLName", true,
404 "eventSpawnToxic", true,
405 "eventNpcSay", true,
406 "eventSetBotFacing", true,
407 "eventGiveControl", true,
408 "eventLeaveControl", true,
409 "eventSpawnDamageLine", true,
411 "setOrganization", true,
412 "setOrganizationStatus", true,
414 "addGuildBuilding", true,
417 static vector<CAdminCommand> AdminCommands;
418 static string CommandsPrivilegesFileName;
419 static string PositionFlagsFileName;
420 static const char * DefaultPriv = ":DEV:";
422 // forward declarations
423 static void loadCommandsPrivileges(const string & fileName, bool init);
424 void cbRemoteClientCallback (uint32 rid, const std::string &cmd, const std::string &entityNames);
428 // get AI instance and remove it form the group name
429 bool getAIInstanceFromGroupName(string& groupName, uint32& instanceNumber)
431 if (groupName.find("@") != string::npos)
433 string continent = groupName.substr(0, groupName.find('@'));
434 uint32 nr = CUsedContinent::instance().getInstanceForContinent(continent);
435 if (nr == std::numeric_limits<uint32>::max())
437 return false;
439 instanceNumber = nr;
440 groupName = groupName.substr(groupName.find('@') + 1, groupName.size());
442 return true;
445 bool checkBannerPriv(const string &sheetName, CEntityId eid)
448 if (sheetName.find("banner") == string::npos)
450 // Not a banner
451 return true;
454 CPlayer* player = PlayerManager.getPlayer( PlayerManager.getPlayerId(eid) );
456 if (player == NULL)
458 return false;
461 if (player->havePriv(":DEV:"))
463 // Dev should be able to get all banners
464 return true;
467 if ( ! player->havePriv(BannerPriv))
469 // Player has no banner privs
470 return false;
473 if (sheetName.find("_gu") != string::npos)
475 if (player->havePriv(":G:"))
477 return true;
480 else if (sheetName.find("_sgu") != string::npos)
482 if (player->havePriv(":SG:"))
484 return true;
486 // VG uses SG banner for now
487 if (player->havePriv(":VG:"))
489 return true;
492 else if (sheetName.find("_vgu") != string::npos)
494 if (player->havePriv(":VG:"))
496 return true;
499 else if (sheetName.find("_gm") != string::npos)
501 if (player->havePriv(":GM:"))
503 return true;
506 else if (sheetName.find("_sgm") != string::npos)
508 if (player->havePriv(":SGM:"))
510 return true;
514 return false;
517 CAdminCommand * findAdminCommand(const string & name)
519 H_AUTO(findAdminCommand);
521 const uint nbCommands = (uint)AdminCommands.size();
522 for (uint i = 0; i < nbCommands; i++)
524 if (name == AdminCommands[i].Name)
525 return &AdminCommands[i];
528 return NULL;
531 static void cbCommandsPrivilegesFileChange(const string & fileName)
533 H_AUTO(cbCommandsPrivilegesFileChange);
535 if (fileName != CommandsPrivilegesFileName)
536 return;
538 loadCommandsPrivileges(fileName, false);
541 void initAdmin ()
543 const uint nbCommands = sizeof(AdminCommandsInit) / sizeof(AdminCommandsInit[0]);
544 for (uint i = 0; i < nbCommands; i++)
546 CAdminCommand cmd;
547 cmd.Name = AdminCommandsInit[i].Name;
548 cmd.AddEId = AdminCommandsInit[i].AddEId;
549 cmd.Priv = DefaultPriv;
550 cmd.Audit = false;
552 AdminCommands.push_back(cmd);
555 setRemoteClientCallback (cbRemoteClientCallback);
558 void initCommandsPrivileges(const std::string & fileName)
560 //init the admin log system
561 CConfigFile::CVar *varPtr = IService::getInstance()->ConfigFile.getVarPtr("AdminLogFile");
562 if ( !varPtr )
563 AdminLog.init("admin_cmds.log");
564 else
565 AdminLog.init( varPtr->asString() );
567 H_AUTO(initCommandsPrivileges);
569 loadCommandsPrivileges(fileName, true);
572 static void loadCommandsPrivileges(const string & fileName, bool init)
574 H_AUTO(loadCommandsPrivileges);
576 CIFile ifile;
577 if (!ifile.open(fileName))
579 nlwarning ("ADMIN: file '%s' cannot be opened", fileName.c_str());
580 return;
583 if (init)
585 const string filePath = CPath::getFullPath(fileName, false);
586 CFile::removeFileChangeCallback(CommandsPrivilegesFileName);
587 CFile::addFileChangeCallback(filePath, cbCommandsPrivilegesFileChange);
588 CommandsPrivilegesFileName = filePath;
591 // reset privileges with default value
592 const uint nbCommands = (uint)AdminCommands.size();
593 for (uint i = 0; i < nbCommands; i++)
595 AdminCommands[i].Priv = DefaultPriv;
598 // load file content
599 CSString fileContent;
600 uint32 fileSize = ifile.getFileSize();
601 uint8 * buf = new uint8[fileSize + 1];
603 ifile.serialBuffer(buf, fileSize);
604 ifile.close();
606 buf[fileSize] = 0;
607 fileContent = (char *)buf;
608 delete [] buf;
610 while (!fileContent.empty())
612 CSString line = fileContent.strtok("\r\n");
614 // remove any comment
615 line = line.splitTo("//");
617 if (line.strip().empty())
618 continue;
620 CSString fullLine = line;
622 // only extract the first 4 params
623 CVectorSString params;
624 for (uint i = 0; !line.empty() && i < 4; i++)
626 string param = line.strtok(" \t");
627 if (param.empty())
628 break;
629 params.push_back(param);
632 if (params.size() < 1)
634 nlwarning("ADMIN: invalid entry: '%s'.", fullLine.c_str());
635 continue;
638 // check second param if it is a forward info
639 if (params.size() > 1 && params[1][0] == '[')
641 // this is a forward
643 else if (params.size() > 3)
645 nlwarning("ADMIN: invalid entry: '%s'.", fullLine.c_str());
646 continue;
648 else
650 // no forward
651 params.insert(params.begin()+1, "[]");
654 if (params.size() < 3)
656 // no required privilege
657 params.push_back("");
660 if (params.size() < 4)
662 // no audit specified
663 params.push_back("");
666 const string & cmdName = params[0];
667 const string & forward = params[1];
668 const string & cmdPriv = params[2];
669 const bool & audit = (params[3] == "audit");
671 CAdminCommand * cmd = findAdminCommand(cmdName);
672 if (cmd)
674 cmd->Priv = cmdPriv;
675 cmd->ForwardToservice = forward.substr(1, forward.size()-2);
676 cmd->Audit = audit;
677 nlinfo("ADMIN: command '%s' forwarded to [%s] has new privileges '%s'.", cmdName.c_str(), cmd->ForwardToservice.c_str(), cmdPriv.c_str());
679 else
681 nlwarning("ADMIN: command '%s' is unknown.", cmdName.c_str());
686 void initPositionFlags(const std::string & fileName)
688 H_AUTO(initPositionFlags);
690 string fileNameAndPath = Bsi.getLocalPath() + fileName;
691 if (CFile::fileExists(fileNameAndPath))
693 CPositionFlagManager::getInstance().loadFromFile(fileName);
695 PositionFlagsFileName = fileName;
698 string getStringFromHash(const string &hash)
700 ucstring finaltext;
701 getUCstringFromHash(hash, finaltext);
703 return finaltext.toUtf8();
706 void getUCstringFromHash(const string &hash, ucstring &finaltext)
708 string fullhash = hash;
709 // fill hash with space to be a *2
710 if (hash.size() % 2)
712 fullhash += " ";
715 // cut hash in portion of 4
716 for (uint i=0; i<fullhash.size()/4; i++) {
717 string part = fullhash.substr((i*4)+2, 2)+fullhash.substr(i*4, 2);
718 ucstring ucpart;
719 uint ch;
720 uint n;
721 if (sscanf(part.c_str(), "%4x%n", &ch, &n) != 1) {
722 // Unexpected string format
723 break;
726 finaltext.push_back((ucchar)ch);
730 static void selectEntities (const string &entityName, vector <CEntityId> &entities)
732 H_AUTO(selectEntities);
734 if (entityName.empty ())
735 return;
739 * valid name formats:
741 * - * Select all entities
742 * - <entity id(id:type:crea:dyn)> Select the specified entity using his eid
745 if (entityName == "*")
747 // we want all entities
748 for (CPlayerManager::TMapPlayers::const_iterator it = PlayerManager.getPlayers().begin(); it != PlayerManager.getPlayers().end(); ++it)
750 if ((*it).second.Player != 0)
752 const CCharacter *c = (*it).second.Player->getActiveCharacter();
753 if (c != 0)
755 entities.push_back (c->getId());
760 else if (entityName[0] == '(')
762 // we want a specific entity id
763 CEntityId eid (entityName);
764 if (eid != CEntityId::Unknown)
765 entities.push_back (eid);
767 else
769 // try with the name
770 CEntityId eid = CEntityIdTranslator::getInstance()->getByEntity(CShardNames::getInstance().makeFullNameFromRelative(TSessionId(FixedSessionId), entityName));
771 if (eid != CEntityId::Unknown)
772 entities.push_back (eid);
776 #define ENTITY_VARIABLE(__name,__help) \
777 struct __name##Class : public NLMISC::ICommand \
779 __name##Class () : NLMISC::ICommand("variables",#__name, __help, "<entity> [<value>]") { Type = Variable; } \
780 virtual bool execute(const std::string &rawCommandString, const std::vector<std::string> &args, NLMISC::CLog &log, bool quiet, bool human) \
782 if (args.size () != 1 && args.size () != 2) \
783 return false; \
785 vector <CEntityId> entities; \
786 selectEntities (args[0], entities); \
788 for (uint i = 0; i < entities.size(); i++) \
790 string value; \
791 if (args.size()==2) \
792 value = args[1]; \
793 else \
794 value = "???"; \
795 pointer (entities[i], (args.size()==1), value); \
796 if (quiet) \
797 log.displayNL ("%s %s", entities[i].toString().c_str(), value.c_str()); \
798 else \
799 log.displayNL ("Entity %s Variable %s = %s", entities[i].toString().c_str(), _CommandName.c_str(), value.c_str()); \
801 return true; \
803 void pointer(CEntityId entity, bool get, std::string &value); \
804 }; \
805 __name##Class __name##Instance; \
806 void __name##Class::pointer(CEntityId entity, bool get, std::string &value)
810 // This macro get an eid and return c that is a pointer to a CCharacter.
813 #define ENTITY_GET_ENTITY \
814 TLogContext_Character_AdminCommand commandContext(entity); \
815 CEntityBase *e = CEntityBaseManager::getEntityBasePtr(entity); \
816 if(e == NULL) \
818 nlwarning ("Unknown entity '%s'", entity.toString().c_str()); \
819 if(get) value = "UnknownEntity"; \
820 return; \
822 if(!TheDataset.isAccessible(e->getEntityRowId())) \
824 nlwarning ("'%s' is not valid in mirror", entity.toString().c_str()); \
825 if(get) value = "NotValidInMirror"; \
826 return; \
829 #define ENTITY_GET_CHARACTER \
830 TLogContext_Character_AdminCommand commandContext(entity); \
831 CCharacter *c = PlayerManager.getChar(entity); \
832 if(c == NULL) \
834 nlwarning ("Unknown player '%s'", entity.toString().c_str()); \
835 if(get) value = "UnknownPlayer"; \
836 return; \
838 if(!c->getEnterFlag()) \
840 nlwarning ("'%s' is not entered", entity.toString().c_str()); \
841 if(get) value = "NotEntered"; \
842 return; \
844 if(!TheDataset.isAccessible(c->getEntityRowId())) \
846 nlwarning ("'%s' is not valid in mirror", entity.toString().c_str()); \
847 if(get) value = "NotValidInMirror"; \
848 return; \
851 void GET_CHARACTER_Helper(std::string& command, const NLMISC::CEntityId& id, const std::string& adminCommand)
853 CAdminOfflineCommand::makeStringCommande( command, id, adminCommand );
854 COfflineCharacterCommand::getInstance()->addOfflineCommandWithoutApply( command );
857 #define TRY_GET_CHARACTER \
858 if (args.size() < 1) { nlwarning ("Missing argument number 0 that should be the eid"); return false; } \
859 CEntityId eid(args[0]); \
860 TLogContext_Character_AdminCommand commandContext(eid); \
861 CCharacter *c = PlayerManager.getChar(eid); \
862 if (!c) \
864 nlwarning("Unknown character '%s'", args[0].c_str()); \
865 return false; \
870 #define CHECK_RIGHT( csr, target ) \
872 if ( !PlayerManager.hasBetterCSRGrade( csr, target ) )\
874 if ( csr )\
875 CCharacter::sendDynamicSystemMessage( csr->getEntityRowId(), "CSR_BAD_RIGHTS" );\
876 return false;\
880 #define GET_GUILD(argPos, onlyLocal, eId) \
881 CGuild * guild = CGuildManager::getInstance()->getGuildByName( args[argPos] );\
882 if ( guild == NULL )\
884 /* try to find the guild with an id*/ \
885 uint32 shardId =0; \
886 uint32 guildId =0; \
887 sscanf(args[argPos].c_str(), "%u:%u", &shardId, &guildId); \
888 guild = CGuildManager::getInstance()->getGuildFromId((shardId<<20)+guildId); \
890 if (guild == NULL) \
892 if (eId != NLMISC::CEntityId::Unknown)\
894 CCharacter::sendDynamicSystemMessage(eId, "GUILD_IS_PROXY");\
896 log.displayNL("Invalid guild '%s'",args[argPos].c_str());\
897 return true;\
900 if (onlyLocal && guild->isProxy())\
902 log.displayNL("The guild '%s' is a foreign guild, operation forbidden", guild->getName().toString().c_str());\
903 return true;\
907 // You can here all variables for a player.
909 // Don't forget to add your command in the AdminCommandsInit array if you want the command to be executed on the client
912 ENTITY_VARIABLE(HP, "Hit points of a player")
914 ENTITY_GET_ENTITY
916 if (get)
918 value = toString (e->currentHp());
920 else
922 sint32 v;
923 NLMISC::fromString(value, v);
924 e->getScores()._PhysicalScores[SCORES::hit_points].Current = v;
928 ENTITY_VARIABLE(MaxHP, "Max hit points of a player")
930 ENTITY_GET_ENTITY
932 if (get)
934 value = toString (e->maxHp());
936 else
938 sint32 v;
939 NLMISC::fromString(value, v);
940 e->getScores()._PhysicalScores[SCORES::hit_points].Max = v;
944 ENTITY_VARIABLE(Speed, "Speed modifier of an entity")
946 ENTITY_GET_ENTITY
948 if (get)
950 value = toString (e->getEventSpeedVariationModifier());
952 else
954 e->setEventSpeedVariationModifier((float)atof(value.c_str()));
958 ENTITY_VARIABLE(Name, "Name of a player")
960 ENTITY_GET_ENTITY
962 if (get)
964 // value = CEntityIdTranslator::getInstance()->getByEntity(entity).toString();
965 value = e->getName ().toString();
967 else
972 ENTITY_VARIABLE(Money, "Money")
974 ENTITY_GET_CHARACTER
976 if (get)
978 value = toString("%" NL_I64 "u", c->getMoney());
980 else
982 sint dir = 0;
984 if (!value.empty())
986 if(value[0] == '+') dir = +1;
987 else if(value[0] == '-') dir = -1;
988 else if(!isdigit(value[0]))
990 nlwarning ("Bad money format for %s right format is [<sign>]<value> sign can be +,- or nothing to set the money", value.c_str());
991 return;
994 else
996 nlwarning ("You must provide a [<sign>]<value>");
997 return;
1000 if(dir == 0)
1002 c->setMoney(NLMISC::atoiInt64(value.c_str()));
1004 else
1006 uint64 val = NLMISC::atoiInt64(value.substr(1).c_str());
1007 if(dir == 1)
1008 c->giveMoney(val);
1009 else
1010 c->spendMoney(val);
1013 nlinfo ("Player %s money is %" NL_I64 "u", entity.toString().c_str(),c->getMoney());
1017 ENTITY_VARIABLE(MoneyGuild, "MoneyGuild")
1019 ENTITY_GET_CHARACTER
1021 CGuild * guild = CGuildManager::getInstance()->getGuildFromId(c->getGuildId());
1022 if (guild == NULL)
1024 nlwarning("Invalid guild");
1025 return;
1028 if (get)
1030 value = toString("%" NL_I64 "u", guild->getMoney());
1032 else
1034 sint dir = 0;
1036 if (!value.empty())
1038 if(value[0] == '+') dir = +1;
1039 else if(value[0] == '-') dir = -1;
1040 else if(!isdigit(value[0]))
1042 nlwarning ("Bad money format for %s right format is [<sign>]<value> sign can be +,- or nothing to set the money", value.c_str());
1043 return;
1046 else
1048 nlwarning ("You must provide a [<sign>]<value>");
1049 return;
1052 if(dir == 0)
1054 guild->setMoney(NLMISC::atoiInt64(value.c_str()));
1056 else
1058 uint32 val;
1059 NLMISC::fromString(value.substr(1), val);
1060 if(dir == 1)
1061 guild->addMoney(val);
1062 else
1063 guild->spendMoney(val);
1066 nlinfo ("Player %s guild money is %" NL_I64 "u", entity.toString().c_str(),guild->getMoney());
1070 ENTITY_VARIABLE(FactionPoint, "FactionPoint")
1072 ENTITY_GET_CHARACTER
1074 if (get)
1076 string sTmp;
1078 for (uint i = PVP_CLAN::BeginClans; i <= PVP_CLAN::EndClans; ++i)
1079 sTmp += PVP_CLAN::toString((PVP_CLAN::TPVPClan)i) + " : " + toString(c->getFactionPoint((PVP_CLAN::TPVPClan)i)) + "\n";
1081 value = sTmp;
1083 else
1085 string sFactionName = value.substr(0, value.find(','));
1086 string sNumber = value.substr(value.find(',')+1);
1088 if (value.empty() || sFactionName.empty() || sNumber.empty())
1090 nlwarning ("You must provide : <faction_name> [<sign>]<value>");
1091 return;
1094 sint dir = 0;
1095 if(sNumber[0] == '+') dir = +1;
1096 else if(sNumber[0] == '-') dir = -1;
1097 else if(!isdigit(sNumber[0]))
1099 nlwarning ("Bad format for '%s' right format is [<sign>]<value> sign can be +,- or nothing", sNumber.c_str());
1100 return;
1103 PVP_CLAN::TPVPClan clan = PVP_CLAN::fromString(sFactionName);
1104 if ((clan < PVP_CLAN::BeginClans) || (clan > PVP_CLAN::EndClans))
1106 nlwarning ("'%s' is not a valid faction name", sFactionName.c_str());
1107 return;
1110 if(dir == 0)
1112 uint32 val;
1113 NLMISC::fromString(sNumber, val);
1114 c->setFactionPoint(clan, val, true);
1116 else
1118 uint32 val;
1119 NLMISC::fromString(sNumber.substr(1), val);
1120 if(dir == 1)
1121 c->setFactionPoint(clan, c->getFactionPoint(clan)+val, true);
1122 else
1123 c->setFactionPoint(clan, c->getFactionPoint(clan)-val, true);
1129 ENTITY_VARIABLE (Priv, "User privilege")
1131 ENTITY_GET_CHARACTER
1133 CPlayer *p = PlayerManager.getPlayer(PlayerManager.getPlayerId(c->getId()));
1134 if (p == NULL)
1136 nlwarning ("Can't find player with UserId %d for checking privilege, assume no priv", PlayerManager.getPlayerId(c->getId()));
1137 return;
1140 if (get)
1142 value = p->getUserPriv();
1144 else
1146 p->setUserPriv(value);
1147 nlinfo ("%s have now this priv '%s'", entity.toString().c_str(), value.c_str());
1150 return;
1153 ENTITY_VARIABLE (FBT, "Focus Beta Tester")
1155 ENTITY_GET_CHARACTER
1157 CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( c->getId() ));
1158 if (p == NULL)
1160 nlwarning ("Can't find player with UserId %d", PlayerManager.getPlayerId( c->getId() ));
1161 return;
1164 if (get)
1166 value = NLMISC::toString(p->isBetaTester());
1168 else
1170 if (value == "1" || value == "on" || strlwr(value) == "true")
1172 p->isBetaTester(true);
1174 else if (value == "0" || value == "off" || strlwr(value) == "false")
1176 p->isBetaTester(false);
1178 nlinfo ("%s %s now a Focus Beta Tester", entity.toString().c_str(), (p->isBetaTester() ? "is" : "isn't"));
1182 ENTITY_VARIABLE(Position, "Position of a player (in meter) <eid> <posx>,<posy>[,<posz>][,<season>] | <bot_name> | <player_name> | home | <creature>")
1184 H_AUTO(Position);
1186 ENTITY_GET_ENTITY
1188 vector<string> res;
1190 float fx = 0, fy = 0, fz = 0;
1191 sint32 x = 0, y = 0, z = 0;
1193 TDataSetRow dsr = e->getEntityRowId();
1194 CMirrorPropValueRO<TYPE_CELL> playerCell(TheDataset, dsr, DSPropertyCELL);
1195 sint32 cell = playerCell;
1197 if (get)
1199 fx = e->getState().X() / 1000.f;
1200 fy = e->getState().Y() / 1000.f;
1201 fz = e->getState().Z() / 1000.f;
1202 if (cell < 0)
1203 value = toString ("%.2f,%.2f,%.2f@%d", fx, fy, fz, -cell);
1204 else
1205 value = toString ("%.2f,%.2f,%.2f", fx, fy, fz);
1207 else
1209 if ( value.find(',') != string::npos )
1211 explode (value, string(","), res);
1212 if (res.size() >= 2)
1214 fromString(res[0], fx);
1215 x = sint32(fx*1000);
1216 fromString(res[1], fy);
1217 y = sint32(fy*1000);
1219 if (res.size() >= 3)
1221 fromString(res[2], fz);
1222 z = sint32(fz*1000);
1225 else if ( value.find('@') != string::npos )
1227 x = e->getState().X();
1228 y = e->getState().Y();
1229 z = e->getState().Z();
1230 explode (value, string("@"), res);
1231 if (res.size() == 1)
1233 fromString(res[0], cell);
1236 else
1238 if ( value.find(".creature") != string::npos )
1240 CSheetId creatureSheetId(value);
1241 if( creatureSheetId != CSheetId::Unknown )
1243 double minDistance = -1.;
1244 CCreature * creature = NULL;
1246 TMapCreatures::const_iterator it;
1247 const TMapCreatures& creatures = CreatureManager.getCreature();
1248 for( it = creatures.begin(); it != creatures.end(); ++it )
1250 CSheetId sheetId = (*it).second->getType();
1251 if( sheetId == creatureSheetId )
1253 double distance = PHRASE_UTILITIES::getDistance( e->getEntityRowId(), (*it).second->getEntityRowId() );
1254 if( !creature || (creature && distance < minDistance) )
1256 creature = (*it).second;
1257 minDistance = distance;
1261 if( creature )
1263 x = creature->getState().X();
1264 y = creature->getState().Y();
1265 z = creature->getState().Z();
1268 else
1270 nlwarning ("<Position> '%s' is an invalid creature", value.c_str());
1273 else
1275 // try to find the player name
1276 CCharacter *c = dynamic_cast<CCharacter*>(e);
1277 if (c == NULL)
1279 nlwarning ("<Position> '%s' is not a player", entity.toString().c_str());
1280 return;
1282 CEntityBase *entityBase = PlayerManager.getCharacterByName (CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), value));
1283 if (entityBase == NULL)
1285 // try to find the bot name
1286 vector<TAIAlias> aliases;
1287 CAIAliasTranslator::getInstance()->getNPCAliasesFromName( value, aliases );
1288 if ( aliases.empty() )
1290 nldebug ("<Position> Ignoring attempt to teleport because no NPC found matching name '%s'", value.c_str());
1291 return;
1294 TAIAlias alias = aliases[0];
1296 const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId (alias);
1297 if ( botId != CEntityId::Unknown )
1299 entityBase = CreatureManager.getCreature (botId);
1301 else
1303 nlwarning ("'%s' has no eId. Is it Spawned???", value.c_str());
1304 return;
1308 if (entityBase != NULL)
1310 x = entityBase->getState().X + sint32 (cos (entityBase->getState ().Heading) * 2000);
1311 y = entityBase->getState().Y + sint32 (sin (entityBase->getState ().Heading) * 2000);
1312 z = entityBase->getState().Z;
1314 TDataSetRow dsr = entityBase->getEntityRowId();
1315 CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, dsr, DSPropertyCELL );
1316 cell = mirrorCell;
1321 if (x == 0 && y == 0 && z == 0)
1323 nlwarning ("'%s' is a bad value for position, don't change position", value.c_str());
1324 return;
1327 CCharacter * c = dynamic_cast<CCharacter*>(e);
1328 if( c )
1330 CContinent * cont = CZoneManager::getInstance().getContinent(x,y);
1331 /*if(c->getCurrentContinent() == CONTINENT::NEWBIELAND )
1333 if( cont == 0 || cont->getId() != CONTINENT::NEWBIELAND )
1335 log_Command_TPOutsideNewbieland(c->getId());
1336 // nlwarning("Position %s player outside NEWBIELAND, this is logged.", c->getId().toString().c_str());
1341 c->allowNearPetTp();
1342 if (res.size() >= 4)
1344 // season included
1345 uint8 season;
1346 NLMISC::fromString(res[3], season);
1347 c->teleportCharacter(x,y,z,true, false, 0.f, 0xFF, cell, season);
1349 else
1351 c->teleportCharacter(x,y,z,true, false, 0.f, 0xFF, cell);
1354 if ( cont )
1356 c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(cont->getId()) );
1359 else
1361 e->tpWanted (x, y, z);
1366 //-----------------------------------------------
1367 // change_mode :
1368 //-----------------------------------------------
1369 NLMISC_COMMAND(changeMode," change_mode","<entity id(id:type:crea:dyn)> <mode>")
1371 if( args.size() == 2 )
1373 CEntityId id;
1374 id.fromString( args[0].c_str() );
1376 sint iMode;
1377 NLMISC::fromString(args[1], iMode);
1378 MBEHAV::EMode mode = MBEHAV::EMode(iMode);
1380 CEntityBase *e = 0;
1381 if( id.getType() == 0 )
1383 e = PlayerManager.getChar(id);
1385 if (e)
1387 e->setMode( mode, true );
1388 log.displayNL("Character %s mode changed to %d", id.toString().c_str(), mode);
1390 else
1392 log.displayNL("Unknown entity %s ",id.toString().c_str());
1394 return true;
1396 return false;
1397 } // change_mode //
1400 //-----------------------------------------------
1401 // checkTargetSP :check target player SP
1402 //-----------------------------------------------
1403 NLMISC_COMMAND(checkTargetSP," check target player skill points (if there is lost SP)","<entity id(id:type:crea:dyn)>")
1405 if( args.size() < 1 )
1406 return false;
1408 GET_CHARACTER
1410 CCharacter *targetPlayer = PlayerManager.getChar( c->getTargetDataSetRow() );
1411 if (!targetPlayer)
1413 log.displayNL("No target or invalid target");
1414 return true;
1417 uint32 totalEarnedSp = targetPlayer->getTotalEarnedSP();
1418 uint32 spentSp = targetPlayer->getActionsSPValue() - targetPlayer->getStartActionsSPValue();
1420 uint32 currentSp = (uint32) targetPlayer->getSP(EGSPD::CSPType::Craft);
1421 currentSp += (uint32) targetPlayer->getSP(EGSPD::CSPType::Fight);
1422 currentSp += (uint32) targetPlayer->getSP(EGSPD::CSPType::Magic);
1423 currentSp += (uint32) targetPlayer->getSP(EGSPD::CSPType::Harvest);
1425 // log result
1426 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);
1428 // send result to asker
1429 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);
1430 chatToPlayer(eid, strTemp);
1432 return true;
1433 } // checkSP //
1436 NLMISC_COMMAND (createItemInBag, "Create an item and put it in the player bag", "<eid> <sheetId>|<sheetName> <quantity> <quality> [force]")
1438 if (args.size() < 4 || args.size() > 5) return false;
1439 GET_CHARACTER
1441 string sheetName = args[1];
1442 CSheetId sheet;
1443 uint32 sheetId;
1444 NLMISC::fromString(sheetName, sheetId);
1445 if (sheetId != 0)
1447 sheet = CSheetId(sheetId);
1449 else
1451 if (sheetName.find(".") == string::npos)
1452 sheetName += ".sitem";
1453 sheet = CSheetId(sheetName.c_str());
1456 if (sheet == CSheetId::Unknown)
1458 log.displayNL("sheetId '%s' is Unknown", sheetName.c_str());
1459 return false;
1462 // banners are the only items in game which use privilege
1463 // banners are the only items in game which use privilege
1464 bool ok = checkBannerPriv(sheetName, eid);
1465 if ( ! ok)
1467 log.displayNL("Invalid banner priviledge");
1468 return false;
1471 const CStaticItem *form = CSheets::getForm (sheet);
1472 if (form == NULL)
1474 log.displayNL ("sheetId '%s' is not found", sheetName.c_str());
1475 return false;
1478 sint quantity;
1479 NLMISC::fromString(args[2], quantity);
1480 if (quantity < 1)
1482 log.displayNL ("Quantity must be > 0");
1483 return false;
1486 sint quality;
1487 NLMISC::fromString(args[3], quality);
1488 if (quality < 1)
1490 log.displayNL ("Quality must be > 0");
1491 return false;
1494 bool res = c->createItemInInventory(INVENTORIES::bag, quality, quantity, sheet);
1496 bool forceCreate;
1497 if (args.size() == 5 && args[4] == "force")
1498 forceCreate = true;
1499 else
1500 forceCreate = false;
1502 if (!res && forceCreate)
1504 CGameItemPtr item = GameItemManager.createItem(sheet, quality, true, true);
1505 if (item != NULL)
1507 res = c->addItemToInventory(INVENTORIES::bag, item);
1508 if (!res)
1509 item.deleteItem();
1513 if (res)
1514 log.displayNL ("Item '%s' created and set in the bag of the player %s", sheet.toString ().c_str(), eid.toString().c_str());
1515 else
1516 log.displayNL ("Failed to create and set the item '%s' for the player %s", sheet.toString ().c_str(), eid.toString().c_str());
1518 return res;
1521 NLMISC_COMMAND (createItemInTmpInv, "Create an item and put it in the player temp inventory", "<eid> <sheetId>|<sheetName> <quantity> <quality>")
1523 if (args.size () != 4) return false;
1524 GET_CHARACTER
1526 string sheetName = args[1];
1527 CSheetId sheet;
1528 uint32 sheetId;
1529 NLMISC::fromString(sheetName, sheetId);
1530 if (sheetId != 0)
1532 sheet = CSheetId(sheetId);
1534 else
1536 if (sheetName.find(".") == string::npos)
1537 sheetName += ".item";
1538 sheet = CSheetId(sheetName.c_str());
1541 if (sheet == CSheetId::Unknown)
1543 log.displayNL("sheetId '%s' is Unknown", sheetName.c_str());
1544 return false;
1547 // banners are the only items in game which use privilege
1548 bool ok = checkBannerPriv(sheetName, eid);
1549 if ( ! ok)
1551 log.displayNL("Invalid banner priviledge");
1552 return false;
1555 const CStaticItem *form = CSheets::getForm (sheet);
1556 if (form == NULL)
1558 log.displayNL ("sheetId '%s' is not found", sheetName.c_str());
1559 return false;
1562 sint quantity;
1563 NLMISC::fromString(args[2], quantity);
1564 if (quantity < 1)
1566 log.displayNL ("Quantity must be > 0");
1567 return false;
1570 sint quality;
1571 NLMISC::fromString(args[3], quality);
1572 if (quality < 1)
1574 log.displayNL ("Quality must be > 0");
1575 return false;
1578 bool res = c->createItemInInventory(INVENTORIES::temporary, quality, quantity, sheet);
1580 if (res)
1581 log.displayNL ("Item '%s' created and set in the temp inventory of the player %s", sheet.toString ().c_str(), eid.toString().c_str());
1582 else
1583 log.displayNL ("Failed to create and set the item '%s' for the player %s", sheet.toString ().c_str(), eid.toString().c_str());
1585 return res;
1588 NLMISC_COMMAND (createItemInInv, "Create items and put them in the given inventory", "<eid> <invId> <sheetId>|<sheetName> <quantity> <quality> <nb items>")
1590 if (args.size () != 6) return false;
1591 GET_CHARACTER
1593 string sheetName = args[2];
1594 CSheetId sheet;
1595 uint32 sheetId;
1596 NLMISC::fromString(sheetName, sheetId);
1597 if (sheetId != 0)
1599 sheet = CSheetId(sheetId);
1601 else
1603 if (sheetName.find(".") == string::npos)
1604 sheetName += ".sitem";
1605 sheet = CSheetId(sheetName.c_str());
1608 if (sheet == CSheetId::Unknown)
1610 log.displayNL("sheetId '%s' is Unknown", sheetName.c_str());
1611 return false;
1614 // banners are the only items in game which use privilege
1615 bool ok = checkBannerPriv(sheetName, eid);
1616 if ( ! ok)
1618 log.displayNL("Invalid banner priviledge");
1619 return false;
1622 const CStaticItem *form = CSheets::getForm (sheet);
1623 if (form == NULL)
1625 log.displayNL ("sheetId '%s' is not found", sheetName.c_str());
1626 return false;
1629 sint quantity;
1630 NLMISC::fromString(args[3], quantity);
1631 if (quantity < 1)
1633 log.displayNL ("Quantity must be > 0");
1634 return false;
1637 sint quality;
1638 NLMISC::fromString(args[4], quality);
1639 if (quality < 1)
1641 log.displayNL ("Quality must be > 0");
1642 return false;
1645 uint nb;
1646 NLMISC::fromString(args[5], nb);
1647 uint nbItems = min(nb, 1000U);
1648 uint nbCreatedItems = 0;
1649 for (uint i = 0; i < nbItems; i++)
1651 if ( !c->createItemInInventory(INVENTORIES::toInventory(args[1]), quality, quantity, sheet, CEntityId::Unknown) )
1652 break;
1653 nbCreatedItems++;
1656 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());
1658 return true;
1661 NLMISC_COMMAND(createNamedItemInBag, "create a named item in bag", "<eId> <item> [<quantity>]")
1663 if (args.size() > 3)
1664 return false;
1666 if (args.size() < 2 )
1667 return false;
1669 CCharacter * user = PlayerManager.getChar(CEntityId(args[0]));
1670 if (!user)
1672 log.displayNL("invalid char '%s'", args[0].c_str());
1673 return true;
1676 uint16 quantity;
1677 if (args.size() == 3)
1679 NLMISC::fromString(args[2], quantity);
1680 if (quantity == 0)
1682 log.displayNL("invalid quantity '%s'", args[2].c_str());
1683 return true;
1686 else
1688 quantity = 1;
1691 TLogNoContext_Item noLog;
1692 CGameItemPtr item = CNamedItems::getInstance().createNamedItem(args[1], quantity);
1693 if (item == NULL)
1695 log.displayNL("invalid item '%s'", args[1].c_str());
1696 return true;
1699 user->addItemToInventory(INVENTORIES::bag, item);
1701 return true;
1704 NLMISC_COMMAND (createFullArmorSet, "Create and equip player with chosen full armor set","<eid> <race (fyros/matis/zorai/tryker)> <type (light/medium/heavy)> <quality>")
1706 static string armors[]=
1708 "boots",
1709 "gloves",
1710 "pants",
1711 "sleeves",
1712 "vest",
1714 static string heavyArmors[]=
1716 "boots",
1717 "gloves",
1718 "helmet",
1719 "pants",
1720 "sleeves",
1721 "vest",
1724 if (args.size () != 4) return false;
1725 GET_CHARACTER
1727 const string &race = args[1];
1728 const string &type = args[2];
1729 uint16 quality;
1730 NLMISC::fromString(args[3], quality);
1732 const uint16 min = quality - (quality-1)%5;
1733 const string minStr = (min < 10) ? string("0") + toString(min) : toString(min);
1734 const uint16 max = min+4;
1735 const string maxStr = (max < 10) ? string("0") + toString(max) : toString(max);
1737 const string endName = string("_") + minStr + string("_") + maxStr + string(".item");
1739 // create the armor pieces
1740 if (type == "heavy")
1742 for ( int i = 0 ; i < sizeof(heavyArmors)/sizeof(heavyArmors[0]) ; ++i)
1744 const string sheetName = race + string("_") + type + string("_") + heavyArmors[i] + endName;
1745 CSheetId sheetId(sheetName);
1747 if ( !c->createItemInInventory(INVENTORIES::bag, quality, 1, sheetId, eid) )
1749 log.displayNL ("For entity %s Failed to create item %s", eid.toString().c_str(), sheetName.c_str() );
1753 else
1755 for ( int i = 0 ; i < sizeof(armors)/sizeof(armors[0]) ; ++i)
1757 const string sheetName = race + string("_") + type + string("_") + armors[i] + endName;
1758 CSheetId sheetId(sheetName);
1760 if ( !c->createItemInInventory(INVENTORIES::bag, quality, 1, sheetId, eid) )
1762 log.displayNL ("For entity %s Failed to create item %s", eid.toString().c_str(), sheetName.c_str() );
1766 return true;
1769 NLMISC_COMMAND (displayInfosOnTarget, "display info on entity target", "<eid>")
1771 if (args.size () < 1) return false;
1772 GET_CHARACTER
1774 TDataSetRow target = c->getTargetDataSetRow();
1775 if (TheDataset.isAccessible(target))
1777 // little slow but acceptable in command
1778 CMirrorPropValueRO<uint32> instanceNumber(TheDataset, target, DSPropertyAI_INSTANCE);
1780 CAIAskForInfosOnEntityMsg msg;
1781 msg.EntityRowId = target;
1782 msg.AskerRowID = c->getEntityRowId();
1784 CWorldInstances::instance().msgToAIInstance(instanceNumber, msg);
1786 else
1787 log.displayNL ("<displayInfosOnTarget> Entity %s has no valid target", eid.toString().c_str() );
1789 return true;
1792 NLMISC_COMMAND (forceTargetToDie, "(debug) Force entity target to die", "<eid>")
1794 if (args.size () != 1)
1795 return false;
1797 GET_CHARACTER
1799 // force sending of target as dead (can only be done on creature)
1800 CCreature *target = CreatureManager.getCreature(c->getTargetDataSetRow());
1801 if (target)
1803 if (!target->isDead())
1804 target->changeCurrentHp(-100000);
1806 BotDeathReport.Bots.push_back(target->getEntityRowId());
1807 TDataSetRow emptyRow;
1808 BotDeathReport.Killers.push_back(emptyRow);
1809 BotDeathReport.Zombies.push_back(true);
1812 return true;
1815 NLMISC_COMMAND (learnAllBricks, "Specified player learns all possible bricks for it's skill values", "<eid>")
1817 H_AUTO(learnAllBricks);
1819 if (args.size () != 1)
1820 return false;
1822 GET_CHARACTER
1824 // get all phrases and bypass brick requirements
1826 vector<CSheetId> phrases;
1827 vector<CSheetId> tempPhrases;
1829 static const EGSPD::CPeople::TPeople races[] =
1831 EGSPD::CPeople::Common,
1832 EGSPD::CPeople::Tryker,
1833 EGSPD::CPeople::Fyros,
1834 EGSPD::CPeople::Matis,
1835 EGSPD::CPeople::Zorai
1838 const uint nbRaces = sizeof(races) / sizeof(races[0]);
1840 for (uint i = 0 ; i < nbRaces ; ++i)
1842 // fight
1843 string filter = "bf";
1844 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
1845 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1846 tempPhrases.clear();
1847 // magic
1848 filter = "bm";
1849 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
1850 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1851 tempPhrases.clear();
1852 // craft
1853 filter = "bc";
1854 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
1855 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1856 tempPhrases.clear();
1857 // harvest
1858 filter = "bh";
1859 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
1860 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1861 tempPhrases.clear();
1862 // special powers
1863 filter = "bs";
1864 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
1865 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1866 tempPhrases.clear();
1869 // learn all bricks
1870 uint nbBricks = 0;
1871 for (uint i = 0; i < phrases.size() ; ++i)
1873 const CStaticRolemasterPhrase *phrase = CSheets::getSRolemasterPhrase(phrases[i]);
1874 if(phrase != NULL)
1876 const uint size = (uint)phrase->Bricks.size();
1877 for ( uint j = 0; j < size ; ++j)
1879 c->addKnownBrick( phrase->Bricks[j] );
1880 ++nbBricks;
1885 log.displayNL ("%s learnt %u bricks", eid.toString().c_str(), nbBricks);
1887 return true;
1891 NLMISC_COMMAND (learnAllRolemasterBricks, "Specified player learns all possible bricks sold by rolemaster for it's skill values", "<eid>")
1893 H_AUTO(learnAllRolemasterBricks);
1895 if (args.size () != 1)
1896 return false;
1898 GET_CHARACTER
1900 // get all phrases and bypass brick requirements
1902 vector<CSheetId> phrases;
1903 vector<CSheetId> tempPhrases;
1905 static const EGSPD::CPeople::TPeople races[] =
1907 EGSPD::CPeople::Common,
1908 EGSPD::CPeople::Tryker,
1909 EGSPD::CPeople::Fyros,
1910 EGSPD::CPeople::Matis,
1911 EGSPD::CPeople::Zorai
1914 const uint nbRaces = sizeof(races) / sizeof(races[0]);
1916 for (uint i = 0 ; i < nbRaces ; ++i)
1918 // fight
1919 string filter = "bf";
1920 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false );
1921 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1922 tempPhrases.clear();
1923 // magic
1924 filter = "bm";
1925 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false );
1926 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1927 tempPhrases.clear();
1928 // craft
1929 filter = "bc";
1930 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false );
1931 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1932 tempPhrases.clear();
1933 // harvest
1934 filter = "bh";
1935 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false );
1936 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1937 tempPhrases.clear();
1938 // special powers
1939 filter = "bs";
1940 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true, false );
1941 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1942 tempPhrases.clear();
1945 // learn all bricks
1946 uint nbBricks = 0;
1947 for (uint i = 0; i < phrases.size() ; ++i)
1949 const CStaticRolemasterPhrase *phrase = CSheets::getSRolemasterPhrase(phrases[i]);
1950 if(phrase != NULL)
1952 const uint size = (uint)phrase->Bricks.size();
1953 for ( uint j = 0; j < size ; ++j)
1955 c->addKnownBrick( phrase->Bricks[j] );
1956 ++nbBricks;
1961 log.displayNL ("%s learnt %u bricks", eid.toString().c_str(), nbBricks);
1963 return true;
1967 NLMISC_COMMAND (learnAllPhrases, "Specified player learns all possible phrases for it's skill values", "<eid>")
1969 H_AUTO(learnAllPhrases);
1971 if (args.size () != 1)
1972 return false;
1974 GET_CHARACTER
1976 // get all phrases and bypass brick requirements
1977 vector<CSheetId> phrases;
1978 vector<CSheetId> tempPhrases;
1980 static const EGSPD::CPeople::TPeople races[] =
1982 EGSPD::CPeople::Common,
1983 EGSPD::CPeople::Tryker,
1984 EGSPD::CPeople::Fyros,
1985 EGSPD::CPeople::Matis,
1986 EGSPD::CPeople::Zorai
1989 const uint nbRaces = sizeof(races) / sizeof(races[0]);
1991 for (uint i = 0 ; i < nbRaces ; ++i)
1993 // fight
1994 string filter = "bf";
1995 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
1996 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
1997 tempPhrases.clear();
1998 // magic
1999 filter = "bm";
2000 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
2001 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
2002 tempPhrases.clear();
2003 // craft
2004 filter = "bc";
2005 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
2006 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
2007 tempPhrases.clear();
2008 // harvest
2009 filter = "bh";
2010 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
2011 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
2012 tempPhrases.clear();
2013 // special powers
2014 filter = "bs";
2015 c->getAvailablePhrasesList( filter, tempPhrases, races[i], true );
2016 phrases.insert( phrases.end(), tempPhrases.begin(), tempPhrases.end() );
2017 tempPhrases.clear();
2020 // learn all phrases
2021 uint16 nbPhrases = 0;
2022 for (uint i = 0; i < phrases.size() ; ++i)
2024 uint16 index = c->getFirstFreeSlotInKnownPhrase();
2026 if ( !c->learnPrebuiltPhrase(phrases[i], index) )
2027 log.displayNL ("%s FAILED to learn phrase id %s", eid.toString().c_str(), phrases[i].toString().c_str());
2028 else
2029 ++nbPhrases;
2032 log.displayNL ("%s learnt %u phrases", eid.toString().c_str(), nbPhrases);
2034 return true;
2038 NLMISC_COMMAND(learnBrick, "Specified player learns given brick","<eid> <brickid>")
2040 if (args.size () != 2) return false;
2041 GET_CHARACTER
2043 CSheetId brickId(args[1]);
2045 c->addKnownBrick(brickId);
2047 log.displayNL ("%s learnt brick %s", eid.toString().c_str(), brickId.toString().c_str());
2048 return true;
2052 NLMISC_COMMAND(unlearnBrick, "Specified player unlearns given brick","<eid> <brickid>")
2054 if (args.size () != 2) return false;
2055 GET_CHARACTER
2057 CSheetId brickId(args[1]);
2059 c->removeKnownBrick(brickId);
2061 log.displayNL ("%s unlearnt brick %s", eid.toString().c_str(), brickId.toString().c_str());
2062 return true;
2066 NLMISC_COMMAND (learnPhrase, "Specified player learns a phrase and set it at index knownPhraseIndex", "<eid> <phraseSheet>")
2068 if (args.size () != 2) return false;
2069 GET_CHARACTER
2071 CSheetId phraseId(args[1]);
2072 const CStaticRolemasterPhrase *phrase = CSheets::getSRolemasterPhrase( phraseId );
2073 if (!phrase)
2075 log.displayNL ("%s isn't a valid phrase !", phraseId.toString().c_str());
2076 return false;
2079 uint16 index = c->getFirstFreeSlotInKnownPhrase();
2081 if ( c->learnPrebuiltPhrase(phraseId, index) )
2082 log.displayNL ("%s learnt phrase id %s", eid.toString().c_str(), phraseId.toString().c_str());
2083 else
2084 log.displayNL ("%s FAILED to learn phrase id %s", eid.toString().c_str(), phraseId.toString().c_str());
2085 return true;
2088 NLMISC_COMMAND (logXpGain, "log or not xp gain infos for specified player", "<eid> <on/off>")
2090 if (args.size () != 2) return false;
2091 GET_CHARACTER
2093 bool flag;
2094 if (args[1]=="1" || strlwr(args[1])=="on" || strlwr(args[1])=="true" )
2096 flag = true;
2098 else if (args[1]=="0" || strlwr(args[1])=="off" || strlwr(args[1])=="false" )
2100 flag = false;
2102 else
2103 return false;
2105 PlayerManager.logXPGain(c->getEntityRowId(), flag);
2106 log.displayNL ("Player %s. Flag logXpGain is now %s", eid.toString().c_str(), (flag?"ON":"OFF") );
2109 return true;
2112 NLMISC_COMMAND (learnAllForagePhrases, "Learn all forage phrase, begin at specified index", "<eid> <index>" )
2114 H_AUTO(learnAllForagePhrases);
2116 if ( args.size() != 2 ) return false;
2117 GET_CHARACTER
2119 uint i;
2120 NLMISC::fromString(args[1], i);
2122 uint nbSuccess = 0, nbFail = 0;
2123 const CAllRolemasterPhrases& phrases = CSheets::getSRolemasterPhrasesMap();
2124 for ( CAllRolemasterPhrases::const_iterator ip=phrases.begin(); ip!=phrases.end(); ++ip )
2126 const string phraseCode = (*ip).first.toString();
2127 if ( phraseCode.find( "abhf" ) == 0 )
2129 if ( c->learnPrebuiltPhrase( (*ip).first, i ) )
2130 ++nbSuccess;
2131 else
2132 ++nbFail;
2133 ++i;
2136 log.displayNL( "%u phrases learned, %u phrases failed", nbSuccess, nbFail );
2137 return true;
2142 NLMISC_COMMAND (learnAllFaberPlans, "Specified player learns all faber plans", "<eid>")
2144 if (args.size () != 1) return false;
2145 GET_CHARACTER
2147 c->learnAllFaberPlans();
2148 log.displayNL ("%s learnt all faber plans", eid.toString().c_str());
2150 return true;
2154 /* Don't use this command, use Money variable instead (same syntax for example "Money <eid> +10")
2155 NLMISC_COMMAND(giveMoney, "Give money to a player","<eid> <money>")
2157 if (args.size () != 2) return false;
2158 GET_CHARACTER
2160 c->giveMoney ( NLMISC::atoiInt64( args[1].c_str() ) );
2161 log.displayNL ("You gave money to player %s", eid.toString().c_str());
2163 return true;
2166 /* Don't use this command, use SP variable instead (same syntax for example "SP <eid> +10")
2167 NLMISC_COMMAND(giveSP, "Give SP (skill points) to a player","<eid> <SP>")
2169 if (args.size () != 2) return false;
2170 GET_CHARACTER
2172 uint32 nbSp = atol(args[1].c_str());
2174 c->addSP( (double)nbSp );
2175 log.displayNL ("You gave %u SP to player %s", nbSp, eid.toString().c_str());
2177 return true;
2180 NLMISC_COMMAND(respawn, "Same as '/a Position home' but without any privilege","<eid>")
2182 if (args.size () != 1) return false;
2183 GET_CHARACTER
2185 //TODO rules of spawn point
2186 // COfflineEntityState state = PlayerManager.getStartState (c->getActiveRole ());
2187 COfflineEntityState state;
2188 c->forbidNearPetTp();
2189 c->tpWanted (state.X, state.Y, state.Z);
2191 return true;
2194 //-----------------------------------------------
2195 // saveToXML
2196 //-----------------------------------------------
2197 NLMISC_CATEGORISED_COMMAND(pdr,saveToXML,"save a character to an XML file","<eid> <file name>")
2199 if (args.size () < 2) return false;
2200 GET_CHARACTER
2202 std::string fileName = args[1];
2204 if( c )
2206 static CPersistentDataRecordRyzomStore pdr;
2207 pdr.clear();
2208 c->store(pdr);
2209 pdr.writeToTxtFile(fileName+".xml");
2210 return true;
2213 return false;
2217 //-----------------------------------------------
2218 // loadFromXML
2219 //-----------------------------------------------
2220 NLMISC_CATEGORISED_COMMAND(pdr,loadFromXML,"load a character from an XML file","<eid> <file name>")
2222 if (args.size () < 2) return false;
2223 GET_CHARACTER
2225 std::string fileName = args[1];
2227 if( c )
2229 ucstring name= c->getName();
2230 uint32 guildId= c->getGuildId();
2231 NLMISC::CEntityId id= c->getId();
2233 static CPersistentDataRecord pdr;
2234 pdr.clear();
2235 pdr.readFromTxtFile(fileName+".xml");
2236 c->apply(pdr);
2237 c->setName(name);
2238 c->setGuildId(guildId);
2239 c->setId(id);
2241 c->allowNearPetTp();
2242 c->tpWanted(c->getX(), c->getY(), c->getZ(), true, c->getHeading());
2244 return true;
2247 return false;
2251 //-----------------------------------------------
2252 // saveToPDR
2253 //-----------------------------------------------
2254 NLMISC_CATEGORISED_COMMAND(pdr,saveToPDR,"save a character to a binary PDR file","<eid> <file name>")
2256 if (args.size () < 2) return false;
2257 GET_CHARACTER
2259 std::string fileName = args[1];
2261 if( c )
2263 static CPersistentDataRecordRyzomStore pdr;
2264 pdr.clear();
2265 c->store(pdr);
2266 pdr.writeToBinFile(fileName+".pdr");
2267 return true;
2270 return false;
2274 //-----------------------------------------------
2275 // loadFromPDR
2276 //-----------------------------------------------
2277 NLMISC_CATEGORISED_COMMAND(pdr,loadFromPDR,"load a character from a binary PDR file","<eid> <file name>")
2279 if (args.size () < 2) return false;
2280 GET_CHARACTER
2282 std::string fileName = args[1];
2284 if( c )
2286 ucstring name= c->getName();
2287 uint32 guildId= c->getGuildId();
2288 NLMISC::CEntityId id= c->getId();
2290 static CPersistentDataRecord pdr;
2291 pdr.clear();
2292 pdr.readFromBinFile(fileName+".pdr");
2293 c->apply(pdr);
2295 c->setName(name);
2296 c->setGuildId(guildId);
2297 c->setId(id);
2299 c->allowNearPetTp();
2300 c->tpWanted(c->getX(), c->getY(), c->getZ(), true, c->getHeading());
2302 return true;
2305 return false;
2309 //-----------------------------------------------
2310 // listPDRFiles
2311 //-----------------------------------------------
2312 NLMISC_CATEGORISED_COMMAND(pdr,listPDRFiles,"list files in the current directory","[<wildcard>]")
2314 if (args.size()!=0)
2315 return false;
2317 std::vector<std::string> files;
2318 NLMISC::CPath::getPathContent(".",false,false,true,files);
2319 for (uint32 i=(uint32)files.size();i--;)
2321 if (!NLMISC::testWildCard(files[i],"*.xml") && !NLMISC::testWildCard(files[i],"*.pdr"))
2323 files[i]=files.back();
2324 files.pop_back();
2327 std::sort(files.begin(),files.end());
2328 for (uint32 i=0;i<files.size();++i)
2330 log.displayNL("%-40s %10d",files[i].c_str(),NLMISC::CFile::getFileSize(files[i]));
2333 return true;
2337 //-----------------------------------------------
2338 // addPetAnimal
2339 //-----------------------------------------------
2340 NLMISC_COMMAND(addPetAnimal,"Add pet animal to character","<eid> <PetTicket>")
2342 if (args.size () < 2) return false;
2343 GET_CHARACTER
2345 CSheetId ticket = CSheetId( args[1] );
2347 if( c )
2349 if( ticket != CSheetId::Unknown )
2351 CGameItemPtr item = c->createItemInInventoryFreeSlot(INVENTORIES::bag, 1, 1, ticket);
2352 if( item != 0 )
2354 if ( ! c->addCharacterAnimal( ticket, 0, item ))
2356 item.deleteItem();
2357 return false;
2359 return true;
2362 log.displayNL("<addPetAnimal> command, cannot create item in bag '%s'", args[1].c_str() );
2365 log.displayNL("<addPetAnimal> command, unknown pet ticket '%s'", args[1].c_str() );
2368 return false;
2369 } // addPetAnimal //
2371 NLMISC_COMMAND(setPetAnimalSatiety,"Set the satiety of pet animal (petIndex in 0..3)","<eid> <petIndex> full|<value> [<nameForAnswer>]")
2373 if (args.size () < 3) return false;
2374 GET_CHARACTER
2376 if ( c )
2378 // Set the new satiety
2379 string result;
2380 uint petIndex;
2381 NLMISC::fromString(args[1], petIndex);
2382 float previousSatiety, maxSatiety;
2383 if ( c->getAnimalSatiety( petIndex, previousSatiety, maxSatiety ) )
2385 if ( args[2] == "full" )
2386 c->setAnimalSatietyToMax( petIndex );
2387 else
2389 float value = (float)atof( args[2].c_str() );
2390 c->setAnimalSatiety( petIndex, value );
2392 float currentSatiety;
2393 if ( c->getAnimalSatiety( petIndex, currentSatiety, maxSatiety ) )
2394 result = toString( "Satiety changed from %.1f to %.1f / %.1f", previousSatiety, currentSatiety, maxSatiety );
2395 else
2396 result = toString( "Internal error" );
2398 else
2399 result = toString( "Pet %u not found", petIndex );
2401 // Send result if requested
2402 if ( args.size() > 3 )
2404 CCharacter *addressee = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[3]) );
2405 if ( addressee )
2407 CHECK_RIGHT( addressee, c );
2408 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
2409 params[0].Literal = trim(result);
2410 CCharacter::sendDynamicSystemMessage(addressee->getId(), "LITERAL", params);
2412 else
2413 result += " nameForAnswer not found";
2416 log.displayNL( result.c_str() );
2419 return true;
2422 NLMISC_COMMAND(getPetAnimalSatiety,"Get the satiety of pet animal (petIndex in 0..3)","<eid> <petIndex> [<nameForAnswer>]")
2424 if (args.size () < 2) return false;
2425 GET_CHARACTER
2427 uint petIndex;
2428 NLMISC::fromString(args[1], petIndex);
2429 if ( c )
2431 // Get the satiety
2432 string result;
2433 float currentSatiety, maxSatiety;
2434 if ( c->getAnimalSatiety( petIndex, currentSatiety, maxSatiety ) )
2435 result = toString( "Satiety: %.1f / %.1f", currentSatiety, maxSatiety );
2436 else
2437 result = toString( "Pet %u not found", petIndex );
2439 // Send result if requested
2440 if ( args.size() > 2 )
2442 CCharacter *addressee = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[2] ));
2443 if ( addressee )
2445 CHECK_RIGHT( addressee, c );
2446 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
2447 params[0].Literal = trim(result);
2448 CCharacter::sendDynamicSystemMessage(addressee->getId(), "LITERAL", params);
2450 else
2451 result += " nameForAnswer not found";
2454 log.displayNL( result.c_str() );
2456 return true;
2459 NLMISC_COMMAND(setPetAnimalName, "Set the name of a pet animal","<eid> <petIndex (0..3)> [<name>]")
2461 if (args.size () < 2) return false;
2462 GET_CHARACTER
2464 if ( c )
2466 uint petIndex;
2467 fromString(args[1], petIndex);
2468 ucstring customName;
2469 if (args.size () == 3)
2470 customName = args[2];
2471 c->setAnimalName(petIndex, customName);
2474 return true;
2477 NLMISC_COMMAND (addSkillPoints, "add skill points of given type (Fight = 0, Magic = 1,Craft = 2, Harvest = 3)", "<eid> <SP type [0..3]> <nb SP>")
2479 if (args.size () < 3) return false;
2480 GET_CHARACTER
2482 EGSPD::CSPType::TSPType type = (EGSPD::CSPType::TSPType) atoi (args[1].c_str());
2483 if (type >= EGSPD::CSPType::EndSPType)
2485 log.displayNL ("Unknown SP type %u", atoi (args[1].c_str()) );
2486 return false;
2489 uint32 nbSP;
2490 fromString(args[2], nbSP);
2492 c->addSP( nbSP, type );
2494 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());
2496 return true;
2497 } // addSkillPoints //
2500 NLMISC_COMMAND (addXPToSkill, "Gain experience in a given skills", "<eid> <xp> <skill> [<count>]")
2502 if (args.size () < 3) return false;
2503 GET_CHARACTER
2505 uint32 xp;
2506 NLMISC::fromString(args[1], xp);
2508 string skill = args[2];
2510 uint count;
2511 if(args.size()==3)
2512 count = 1;
2513 else
2514 NLMISC::fromString(args[3], count);
2516 count = min( count, (uint)100);
2518 uint i;
2519 for( i=0; i<count; ++i)
2521 c->addXpToSkill( (double) xp, skill );
2523 log.displayNL ("Added %d xp skill '%s' to player %s %d time(s)", xp, skill.c_str(), eid.toString().c_str(),count);
2525 return true;
2528 NLMISC_COMMAND(setSkillsToMaxValue, "Set skills character to max value of each skill","<eid>")
2530 if (args.size () != 1) return false;
2531 GET_CHARACTER
2533 c->setSkillsToMaxValue();
2534 log.displayNL ("You set skills of player %s to max value of each skill", eid.toString().c_str());
2536 return true;
2539 NLMISC_COMMAND(cancelTopPhrase, "cancelTopPhrase","<eid>")
2541 if (args.size () != 1) return false;
2542 GET_CHARACTER
2544 CPhraseManager::getInstance().cancelTopPhrase( c->getEntityRowId());
2546 return true;
2549 NLMISC_COMMAND (clearFriendsList, "clear the friend list of a player", "<eid>")
2551 if ( args.size() < 1 ) return false;
2552 GET_CHARACTER
2554 if(c != 0)
2556 c->clearFriendList();
2557 log.displayNL("player %s friends list cleared",eid.toString().c_str());
2560 return true;
2564 NLMISC_COMMAND (clearIgnoreList, "clear the ignore list of a player", "<eid>")
2566 if ( args.size() < 1 ) return false;
2567 GET_CHARACTER
2569 if(c != 0)
2571 c->clearIgnoreList();
2572 log.displayNL("player %s ignore list cleared",eid.toString().c_str());
2575 return true;
2578 NLMISC_COMMAND (clearIsFriendOfList, "clear the ignore list of a player", "<eid>")
2580 if ( args.size() < 1 ) return false;
2581 GET_CHARACTER
2583 if(c != 0)
2585 c->clearFriendOfList();
2586 log.displayNL("player %s 'IsFriendOf' list cleared",eid.toString().c_str());
2589 return true;
2593 //-----------------------------------------------
2594 // set the defense mode to dodge
2595 //-----------------------------------------------
2596 NLMISC_COMMAND(dodge,"set the defense mode to dodge","<player id(id:type:crea:dyn)>")
2598 if ( args.size() >= 1 )
2600 GET_CHARACTER
2602 c->dodgeAsDefense(true);
2604 log.displayNL("player id %s defense mode is now dodge",eid.toString().c_str());
2606 return true;
2608 return false;
2609 } // dodge //
2611 //-----------------------------------------------
2612 // set the defense mode to parry
2613 //-----------------------------------------------
2614 NLMISC_COMMAND(parry,"set the defense mode to parry","<player id(id:type:crea:dyn)>")
2616 if ( args.size() >= 1 )
2618 GET_CHARACTER
2619 c->dodgeAsDefense(false);
2620 log.displayNL("player id %s defense mode is now parry",c->getId().toString().c_str());
2622 return true;
2624 return false;
2625 } // parry //
2628 //-----------------------------------------------
2629 // reset the ineffective aura and the power flags for given player
2630 //-----------------------------------------------
2631 NLMISC_COMMAND(resetPowerFlags,"reset the ineffective aura and the power flags for given character","<eId>")
2633 if ( args.size() == 1)
2635 GET_CHARACTER
2637 c->resetPowerFlags();
2638 log.displayNL("resetPowerFlags for character %s ", c->getId().toString().c_str());
2639 return true;
2641 return false;
2642 } // resetPowerFlags
2645 //-----------------------------------------------
2646 // excute a sabrina phrase
2647 //-----------------------------------------------
2648 NLMISC_COMMAND(execPhrase,"execute a sabrina phrase","<player id(id:type:crea:dyn)> <cyclic 0/1> [<brick ids>...]")
2650 if ( args.size() >= 3 )
2652 GET_CHARACTER
2653 bool cyclic;
2654 NLMISC::fromString(args[1], cyclic);
2656 vector<CSheetId> brickIds;
2657 for (uint i = 2 ; i < args.size() ; ++i)
2659 CSheetId sheet(args[i]);
2660 brickIds.push_back( sheet );
2663 CPhraseManager::getInstance().executePhrase(c->getEntityRowId(), c->getTargetDataSetRow(), brickIds, cyclic);
2665 return true;
2667 return false;
2668 } // execPhrase //
2670 //-----------------------------------------------
2671 // excute a sabrina phrase
2672 //-----------------------------------------------
2673 NLMISC_COMMAND(executeSabrinaPhrase,"execute a sabrina phrase, an sphrase","<player id(id:type:crea:dyn)> <cyclic 0/1> <phraseId>")
2675 if ( args.size() == 3 )
2677 GET_CHARACTER
2679 bool cyclic;
2680 NLMISC::fromString(args[1], cyclic);
2682 CSheetId phraseSheet(args[2]);
2683 CPhraseManager::getInstance().executePhrase(c->getEntityRowId(), c->getTargetDataSetRow(), phraseSheet, cyclic);
2685 return true;
2687 return false;
2688 } // executeSabrinaPhrase //
2691 //-----------------------------------------------
2692 // memorize a sabrina phrase
2693 //-----------------------------------------------
2694 NLMISC_COMMAND(memorizePhrase,"memorize a sabrina phrase","<player id(id:type:crea:dyn)> <index> [<brick ids>...]")
2696 /* if ( args.size() >= 3 )
2698 CEntityId id;
2699 id.fromString(args[0].c_str());
2701 uint8 index;
2702 NLMISC::fromString(args[1], index);
2704 CCharacter * c = PlayerManager.getChar( id );
2705 if (c )
2707 vector<CSheetId> brickIds;
2708 for (uint i = 2 ; i < args.size() ; ++i)
2710 CSheetId sheet(args[i]);
2711 brickIds.push_back( sheet );
2714 c->memorize(index, brickIds );
2716 else
2718 log.displayNL("invalid player id %s",id.toString().c_str());
2720 return true;
2723 return false;
2724 } // memorizePhrase //
2727 //-----------------------------------------------
2728 // execute a memorized sabrina phrase
2729 //-----------------------------------------------
2730 NLMISC_COMMAND(execMemorizedPhrase,"memorize a memorized sabrina phrase","<player id(id:type:crea:dyn)> <index> <cyclic 0/1>")
2732 /* if ( args.size() >= 2 )
2734 CEntityId id;
2735 id.fromString(args[0].c_str());
2737 uint8 index;
2738 NLMISC::fromString(args[1], index);
2739 bool cyclic;
2740 NLMISC::fromString(args[2], cyclic);
2742 CCharacter * c = PlayerManager.getChar( id );
2743 if (c )
2745 c->executeMemorizedPhrase(index, cyclic,false);
2747 else
2749 log.displayNL("invalid player id %s",id.toString().c_str());
2751 return true;
2753 */ return false;
2754 } // execMemorizedPhrase //
2756 //////////////////////////////////////////////////////////////////////////////
2757 // Death commands until client interface is ready //
2758 //////////////////////////////////////////////////////////////////////////////
2760 //-----------------------------------------------
2761 // Simulate character choice a re-spawn point until UI is ready
2762 //-----------------------------------------------
2763 NLMISC_COMMAND(respawnAfterDeath,"respawnAfterDeath at re-spawn point name, it must be valid (validated by PC and usable)","<player id(id:type:crea:dyn)><Respawn idx>")
2765 if ( args.size() == 2 )
2767 GET_CHARACTER
2769 uint16 idx;
2770 NLMISC::fromString(args[1], idx);
2772 // 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
2773 c->respawn(idx);
2775 return true;
2777 return false;
2778 } // execMemorizedPhrase //
2781 //-----------------------------------------------
2782 // Simulate Resurrection by other PC until UI is ready
2783 //-----------------------------------------------
2784 NLMISC_COMMAND(resurrected,"Another PC resurrect PC by giving some energy","<player id(id:type:crea:dyn)><Hp gived><Sta gived><Sap gived><Focus gived>")
2786 if( args.size() == 1 )
2788 GET_CHARACTER
2789 c->resurrected();
2791 return true;
2793 return false;
2797 //-----------------------------------------------
2798 // Simulate buy kami / karavan pact until UI is ready
2799 //-----------------------------------------------
2800 NLMISC_COMMAND(buyPact,"Buy Kami or Karavan pact","<player id(id:type:crea:dyn)><Pact Name>")
2802 if( args.size() == 3 )
2804 GET_CHARACTER
2806 // Character buy pact with Kami / Karavan by botchat (same has trade)
2807 // effect is validate re-spawn point for one use
2808 c->buyPact( args[1] );
2810 return true;
2812 return false;
2816 //-----------------------------------------------
2817 // Simulate validate re-spawn point until UI is ready
2818 //-----------------------------------------------
2819 NLMISC_COMMAND(validateRespawnPoint,"Validate re-spawn point","<player id(id:type:crea:dyn)><Re-spawn point idx>")
2821 if( args.size() == 2 )
2823 GET_CHARACTER
2825 CCharacterRespawnPoints::TRespawnPoint respawnPoint;
2826 NLMISC::fromString(args[1], respawnPoint);
2827 c->getRespawnPoints().addRespawnPoint(respawnPoint);
2828 return true;
2830 return false;
2833 NLMISC_COMMAND(displayForageRM,"Display forageable raw materials near by or at the exact position of a player","<eid> <exactPos=1> <extendedInfo=0>")
2835 if ( args.size() < 1 ) return false;
2836 GET_CHARACTER
2838 bool exactPos = ! ((args.size() > 1) && (args[1] == "0"));
2839 bool extendedInfo = (args.size() > 2) && (args[2] == "1");
2840 CFgProspectionPhrase::displayRMNearBy( c, exactPos, extendedInfo, &log );
2841 return true;
2845 NLMISC_COMMAND(setItemSapLoad,"set an item sap load","<eId><slot index in bag (starts at 0)><float value>")
2847 if ( args.size() != 3)
2848 return false;
2850 GET_CHARACTER
2851 uint slot;
2852 NLMISC::fromString(args[1], slot);
2853 float value = (float)atof(args[2].c_str());
2854 // vector<CGameItemPtr>& items = (vector<CGameItemPtr> &)c->getInventory()[INVENTORIES::bag]->getChildren();
2855 CInventoryPtr invent = c->getInventory(INVENTORIES::bag);
2856 // if ( slot >= invent->getNumChildren() )
2857 if ( slot >= invent->getSlotCount() )
2859 // log.displayNL("Invalid slot %u max = %u",slot, items.size()-1);
2860 log.displayNL("Invalid slot %u max = %u",slot, invent->getSlotCount()-1);
2861 return true;
2863 // if( items[slot] == NULL )
2864 if( invent->getItem(slot) == NULL )
2866 log.displayNL("empty slot %u",slot);
2867 return true;
2870 uint32 sapLoad = 0;
2871 // CGameItemPtr item = invent->getChildItem(slot);
2872 CGameItemPtr item = invent->getItem(slot);
2873 // if ( items[slot]->getSheetId() == CSheetId("stack.sitem") )
2874 // if (item->getSheetId() == CSheetId("stack.sitem") )
2875 // {
2876 //// for ( uint i = 0; i < items[slot]->getChildren().size(); i++ )
2877 // for ( uint i = 0; i < item->getNumChildren(); i++ )
2878 // {
2879 //// if ( items[slot]->getChildren()[i] != NULL)
2880 // if ( item->getChildItem(i) != NULL)
2881 // {
2882 //// items[slot]->getChildren()[i]->setMaxSapLoad( value );
2883 // item->getChildItem(i)->setMaxSapLoad( value );
2884 //// sapLoad = items[slot]->getChildren()[i]->maxSapLoad();
2885 // sapLoad = item->getChildItem(i)->maxSapLoad();
2886 // }
2887 // }
2888 // }
2889 // else
2891 // items[slot]->setMaxSapLoad( value );
2892 item->setMaxSapLoad( value );
2893 // sapLoad = items[slot]->maxSapLoad();
2894 sapLoad = item->maxSapLoad();
2896 //trap c->incSlotVersion( INVENTORIES::bag,slot);
2897 log.displayNL("item in slot %u has now a sap load of %u",slot,sapLoad);
2899 return true;
2903 NLMISC_COMMAND( showFBT, "show Focus Beta Tester title if the player is a FBT", "<FBT id>" )
2905 if ( args.size() != 1 )
2906 return false;
2907 GET_CHARACTER
2908 CPlayer * p = PlayerManager.getPlayer(PlayerManager.getPlayerId( c->getId() ) );
2909 if (p == NULL)
2911 nlwarning ("ADMIN: Can't find player with UserId %d", PlayerManager.getPlayerId(c->getId()));
2912 return false;
2915 if (!p->isBetaTester())
2917 nlwarning ("ADMIN: UserId %d is not a FBT", PlayerManager.getPlayerId(c->getId()));
2918 return false;
2921 c->setTitle(CHARACTER_TITLE::FBT);
2922 c->registerName();
2923 return true;
2926 NLMISC_COMMAND( summonPet, "player can summon it's pet one time only", "<eid><Pet Number>" )
2928 if ( args.size() != 2 )
2929 return false;
2930 GET_CHARACTER
2932 uint32 index;
2933 NLMISC::fromString(args[1], index);
2934 --index;
2935 const std::vector< CPetAnimal >& pet = c->getPlayerPets();
2936 if( index < pet.size() )
2938 if( pet[ index ].PetStatus != CPetAnimal::not_present )
2940 if( pet[ index ].IsTpAllowed )
2942 c->sendPetCommand( CPetCommandMsg::DESPAWN, index, true );
2943 c->setPetStatus( index, CPetAnimal::waiting_spawn );
2944 c->setSpawnPetFlag( index );
2945 c->petTpAllowed( index, false );
2949 return true;
2952 NLMISC_COMMAND( allowSummonPet, "autorize player summon it's pet one time only", "<eid><Pet Number>" )
2954 if ( args.size() != 2 )
2955 return false;
2956 GET_CHARACTER
2958 uint32 index;
2959 NLMISC::fromString(args[1], index);
2960 --index;
2962 const std::vector< CPetAnimal >& pet = c->getPlayerPets();
2963 if( index < pet.size() )
2965 if( pet[ index ].PetStatus != CPetAnimal::not_present )
2967 c->petTpAllowed( index, true );
2970 return true;
2976 // You can add here all variables to administrate this service.
2981 NLMISC_DYNVARIABLE (float, RyzomTime, "Current ryzom time")
2983 if (get)
2985 *pointer = CTimeDateSeasonManager::getRyzomTimeReference().getRyzomTime ();
2987 /* else
2989 CMessage msgout ("SET_RYZOM_TIME");
2990 msgout.serial (*pointer);
2991 CUnifiedNetwork::getInstance()->send( "WOS", msgout );
2997 NLMISC_DYNVARIABLE (uint32, RyzomDate, "Current ryzom date")
2999 if (get)
3001 *pointer = CTimeDateSeasonManager::getRyzomTimeReference().getRyzomDay ();
3003 /* else
3005 CMessage msgout ("SET_RYZOM_DAY");
3006 msgout.serial (*pointer);
3007 CUnifiedNetwork::getInstance()->send( "WOS", msgout );
3017 void audit(const CAdminCommand *cmd, const string &rawCommand, const CEntityId &eid, const string &name, const string &targetName)
3019 if (cmd == NULL)
3020 return;
3022 CConfigFile::CVar *varHost = IService::getInstance()->ConfigFile.getVarPtr("AdminCommandAuditHost");
3023 CConfigFile::CVar *varPage = IService::getInstance()->ConfigFile.getVarPtr("AdminCommandAuditPage");
3025 if (varHost == NULL || varPage == NULL)
3026 return;
3028 string host = varHost->asString();
3029 string page = varPage->asString();
3031 if (host.empty() || page.empty())
3032 return;
3034 char params[1024];
3035 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());
3037 IThread *thread = IThread::create(new CHttpPostTask(host, page, params));
3038 thread->start();
3041 // all admin /a /b commands executed by the client go in this callback
3042 void cbClientAdmin (NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
3044 H_AUTO(cbClientAdmin);
3047 CEntityId eid;
3048 CEntityId targetEid;
3049 msgin.serial (eid);
3051 bool onTarget;
3052 msgin.serial (onTarget);
3054 CSString cmdName, arg;
3055 msgin.serial (cmdName, arg);
3057 //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());
3058 TLogContext_Command_ExecCtx logContext(eid);
3060 // find the character
3061 CCharacter *c = PlayerManager.getChar( eid );
3062 if (c == NULL)
3064 nlwarning ("ADMIN: Unknown player %s", eid.toString().c_str());
3065 chatToPlayer (eid, "Unknown player");
3066 return;
3069 // test character is ready and valid
3070 if (!c->getEnterFlag())
3072 nlwarning("ADMIN: player %s not ready", eid.toString().c_str());
3073 return;
3075 if (!TheDataset.isAccessible(c->getEntityRowId()))
3077 nlwarning("ADMIN: player %s not ready in mirror (invalid rowid)", eid.toString().c_str());
3078 return;
3081 // find if the command is available
3082 const CAdminCommand * cmd = findAdminCommand(cmdName);
3083 if (!cmd)
3085 nlinfo("ADMIN: Player %s tried to execute a no valid client admin command '%s'", eid.toString().c_str(), cmdName.c_str());
3086 chatToPlayer (eid, "Unknown command");
3087 return;
3090 if (!c->havePriv(cmd->Priv))
3092 nlinfo("ADMIN: Player %s doesn't have privilege to execute the client admin command '%s' ", eid.toString().c_str(), cmdName.c_str());
3093 chatToPlayer (eid, "You don't have privilege to execute this command");
3094 return;
3097 if (onTarget && !c->haveAnyPrivilege())
3099 nlinfo("ADMIN: Player %s doesn't have privilege to execute /b command onTarget '%s' ", eid.toString().c_str(), cmdName.c_str());
3100 chatToPlayer (eid, "You don't have privilege to execute this command");
3101 return;
3104 if (!cmd->ForwardToservice.empty())
3106 // we need to forward the command to another service
3107 if (IClientCommandForwader::getInstance())
3109 IClientCommandForwader::getInstance()->sendCommand(cmd->ForwardToservice, cmdName, eid, onTarget, onTarget ? c->getTarget() : CEntityId::Unknown, arg);
3112 else
3114 // execute locally
3115 // create the command line
3116 string res = cmdName + " ";
3118 if( cmdName == string("Position") )
3120 // check validity of Position command
3121 if( onTarget )
3123 if( !c->havePriv(":DEV:SGM:GM:EM:") )
3125 nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command /b '%s' ", eid.toString().c_str(), cmdName.c_str());
3126 chatToPlayer (eid, "You don't have privilege to execute this command");
3127 return;
3132 std::string targetName = string("Implicite");
3134 // add the eid of the player or target if necessary
3135 if (cmd->AddEId)
3137 if(onTarget)
3139 log_Command_ExecOnTarget(c->getTarget(), cmdName, arg);
3140 res += c->getTarget().toString();
3141 targetEid = c->getTarget();
3142 targetName = NLMISC::toString("%s,%s", c->getTarget().toString().c_str(), CEntityIdTranslator::getInstance()->getByEntity(c->getTarget()).toString().c_str());
3144 else
3146 log_Command_Exec(cmdName, arg);
3147 res += eid.toString();
3148 targetEid = eid;
3149 targetName = string("Himself");
3151 res += " ";
3154 res += arg;
3156 TLogContext_Item_Command itemCtx(onTarget ? c->getTarget() : eid);
3157 TLogContext_Character_BuyRolemasterPhrase characterCtx(onTarget ? c->getTarget() : eid);
3158 std::string csName = CEntityIdTranslator::getInstance()->getByEntity(eid).toString();
3160 strFindReplace(res, "#player", eid.toString().c_str());
3161 if (c->getTarget() != CEntityId::Unknown)
3163 strFindReplace(res, "#target", c->getTarget().toString().c_str());
3164 strFindReplace(res, "#gtarget", string("#"+c->getTarget().toString()).c_str());
3166 ADMINLOG("/a %s %s %s", csName.c_str(), targetName.c_str(), res.c_str());
3167 // 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());
3169 //audit(cmd, res, eid, csName, targetName);
3171 CLightMemDisplayer *CmdDisplayer = new CLightMemDisplayer("CmdDisplayer");
3172 CLog *CmdLogger = new CLog( CLog::LOG_NO );
3173 CmdLogger->addDisplayer( CmdDisplayer );
3174 NLMISC::ICommand::execute(res, *CmdLogger, true);
3175 const std::deque<std::string> &strs = CmdDisplayer->lockStrings ();
3176 for (uint i = 0; i < strs.size(); i++)
3178 InfoLog->displayNL("%s", trim(strs[i]).c_str());
3180 SM_STATIC_PARAMS_1(params,STRING_MANAGER::literal);
3181 params[0].Literal = trim(strs[i]);
3182 CCharacter::sendDynamicSystemMessage( eid, "LITERAL", params );
3184 CmdDisplayer->unlockStrings();
3185 CmdLogger->removeDisplayer (CmdDisplayer);
3186 delete CmdDisplayer;
3187 delete CmdLogger;
3191 // all admin /c commands executed by the client go in this callback
3192 void cbClientAdminOffline (NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
3194 H_AUTO(cbClientAdminOffline);
3196 CEntityId eid;
3197 msgin.serial (eid);
3199 string characterName;
3200 msgin.serial(characterName);
3202 string cmdName, arg;
3203 msgin.serial (cmdName, arg);
3205 ADMINLOG("/c %s %s %s", eid.toString().c_str(), characterName.c_str(), cmdName.c_str(), arg.c_str());
3206 //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());
3208 // find the character
3209 CCharacter *c = PlayerManager.getChar( eid );
3210 if (c == NULL)
3212 nlwarning ("ADMIN: Unknown player %s", eid.toString().c_str());
3213 chatToPlayer (eid, "Unknown player");
3214 return;
3217 // test character is ready and valid
3218 if (!c->getEnterFlag())
3220 nlwarning("ADMIN: player %s not ready", eid.toString().c_str());
3221 return;
3223 if (!TheDataset.isAccessible(c->getEntityRowId()))
3225 nlwarning("ADMIN: player %s not ready in mirror (invalid rowid)", eid.toString().c_str());
3226 return;
3229 // find if the command is available
3230 const CAdminCommand * cmd = findAdminCommand(cmdName);
3231 if (!cmd)
3233 nlwarning ("ADMIN: Player %s tried to execute a no valid client admin command '%s'", eid.toString().c_str(), cmdName.c_str());
3234 chatToPlayer (eid, "Unknown command");
3235 return;
3238 if (!c->havePriv(cmd->Priv))
3240 nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command '%s' ", eid.toString().c_str(), cmdName.c_str());
3241 chatToPlayer (eid, "You don't have privilege to execute this command");
3242 return;
3245 if (!c->haveAnyPrivilege())
3247 nlinfo("ADMIN: Player %s doesn't have privilege to execute /c command '%s' ", eid.toString().c_str(), cmdName.c_str());
3248 chatToPlayer (eid, "You don't have privilege to execute this command");
3249 return;
3252 // find the character eid
3253 CEntityId charEid = CEntityIdTranslator::getInstance()->getByEntity(characterName);
3254 if (charEid == CEntityId::Unknown)
3256 nlwarning ("ADMIN: Unknown character %s", characterName.c_str());
3257 return;
3260 if( cmdName == string("Position") )
3262 // check validity of Position command
3263 if( !c->havePriv(":DEV:SGM:GM:EM:") )
3265 nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command /c '%s' ", eid.toString().c_str(), cmdName.c_str());
3266 chatToPlayer (eid, "You don't have privilege to execute this command");
3267 return;
3271 // create the command line
3272 string res = cmdName + " ";
3274 // add the eid of the player or target if necessary
3275 if (cmd->AddEId)
3277 res += charEid.toString();
3278 res += " ";
3281 res += arg;
3283 std::string csName = CEntityIdTranslator::getInstance()->getByEntity(eid).toString();
3284 std::string targetName = NLMISC::toString("(%s,%s)", CEntityIdTranslator::getInstance()->getByEntity( ucstring(characterName) ).toString().c_str(), characterName.c_str() );
3286 ADMINLOG("/o %s %s %s", csName.c_str(), targetName.c_str(), res.c_str());
3287 //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());
3288 NLMISC::ICommand::execute(res, *InfoLog);
3291 void cbRemoteClientCallback (uint32 rid, const std::string &cmd, const std::string &entityNames)
3293 vector <CEntityId> entities;
3294 selectEntities (entityNames, entities);
3296 for (uint i = 0; i < entities.size(); i++)
3298 CCharacter *c = PlayerManager.getChar(entities[i]);
3299 if (c != 0)
3301 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());
3303 CMessage msgout ("IMPULSION_ID");
3304 msgout.serial (entities[i]);
3305 CBitMemStream bms;
3307 if (!GenericMsgManager.pushNameToStream ("COMMAND:REMOTE_ADMIN", bms))
3308 nlstopex (("Missing a message in the msg.xml"));
3310 bms.serial (rid);
3311 bms.serial (const_cast<string&>(cmd));
3313 msgout.serialBufferWithSize ((uint8*)bms.buffer(), bms.length());
3314 sendMessageViaMirror (NLNET::TServiceId(entities[i].getDynamicId()), msgout);
3319 void cbClientRemoteAdmin( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId)
3321 H_AUTO(cbClientRemoteAdmin);
3323 CEntityId eid;
3324 msgin.serial (eid);
3326 uint32 rid;
3327 msgin.serial (rid);
3329 string cmd;
3330 msgin.serial (cmd);
3332 string answer;
3333 msgin.serial (answer);
3335 vector<string> vara, vala;
3337 if (ICommand::isCommand(cmd))
3339 vara.push_back ("__log");
3340 vala.push_back ("----- Result from "+eid.toString()+" "+IService::getInstance()->getServiceUnifiedName()+" of command '"+cmd+"'\n");
3341 vala.push_back (answer);
3343 else
3345 vara.push_back ("service");
3346 vala.push_back (IService::getInstance ()->getServiceUnifiedName());
3348 vara.push_back ("entity");
3349 vala.push_back (eid.toString());
3351 vara.push_back (cmd);
3352 vala.push_back (answer);
3355 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);
3357 addRequestAnswer (rid, vara, vala);
3360 //----------------------------------------------------------------------------
3361 NLMISC_COMMAND( displayWeather, "Display current weather at specified pos", "<x> <y>" )
3363 if ( args.size() < 2 )
3364 return false;
3365 CVector pos;
3366 pos.x = (float)atof( args[0].c_str() );
3367 pos.y = (float)atof( args[1].c_str() );
3368 pos.z = 0;
3369 CRyzomTime::EWeather weather = WeatherEverywhere.getWeather( pos, CTimeDateSeasonManager::getRyzomTimeReference() );
3370 log.displayNL( "Weather: %u", (uint)weather );
3372 return true;
3377 /***********************************************************************************************************************
3379 BELOW ARE OFFICIAL CSR COMMANDS
3381 ***********************************************************************************************************************/
3383 NLMISC_COMMAND( csrCmd, "Invoke a CSR command from service console or admin tool without the need to have a CSR logged in", "<csrCommandName> <command params>+" )
3385 if (args.empty())
3386 return false;
3388 // build the command line
3389 string command = args[0];
3390 command += string(" (0x0000000000:00:00:00) ");
3391 for (uint i=1; i<args.size(); ++i)
3393 command += "\""+args[i]+"\"";
3394 if (i<args.size()-1)
3395 command += " ";
3398 ICommand::execute(command, log, quiet, human);
3400 return true;
3404 //----------------------------------------------------------------------------
3405 NLMISC_COMMAND( motd, "set the current message of the day", "<message to be displayed (string)>" )
3407 if ( args.empty() )
3408 return false;
3410 string msg = args[0];
3411 for ( uint i = 1; i < args.size(); i++ )
3413 msg+= " " + args[i];
3415 MessageOfTheDay = msg;
3416 return true;
3419 //----------------------------------------------------------------------------
3420 NLMISC_COMMAND( summon, "summon a player in front of the CSR", "<CSR eId><player name>" )
3422 if ( args.size() !=2 )
3423 return false;
3424 GET_CHARACTER
3425 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[1]) );
3426 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3428 CCharacter::sendDynamicSystemMessage( eid, "CSR_PENDING_CHARACTER_LOG" );
3430 COfflineEntityState state;
3431 state.X = c->getState().X;
3432 state.Y = c->getState().Y;
3433 state.Z = c->getState().Z;
3434 state.Heading = c->getState().Heading;
3435 CGmTpPendingCommand::getInstance()->addTpPendingforCharacter( args[1], state );
3437 return true;
3439 CHECK_RIGHT( c,target );
3441 /* if(target->getCurrentContinent() == CONTINENT::NEWBIELAND )
3443 if( c->getCurrentContinent() != CONTINENT::NEWBIELAND )
3445 log.displayNL( "Summon player outside NEWBIELAND is forbiden, <CSR eId %s> try to made an illegal action, this is loged.", eid.toString().c_str());
3446 chatToPlayer (eid, "You don't have privilege to execute this command");
3447 return true;
3451 COfflineEntityState state;
3452 state.X = target->getState().X;
3453 state.Y = target->getState().Y;
3454 state.Z = target->getState().Z;
3455 state.Heading = target->getState().Heading;
3456 PlayerManager.addSummonnedUser( target->getEntityRowId(), state );
3458 state.X = c->getState().X + sint32 (cos (c->getState().Heading) * 2000);
3459 state.Y = c->getState().Y + sint32 (sin (c->getState().Heading) * 2000);
3460 state.Z = c->getState().Z;
3461 state.Heading = c->getState().Heading + (float)NLMISC::Pi;
3462 if ( state.Heading >= (float)NLMISC::Pi )
3463 state.Heading -= 2* (float)NLMISC::Pi;
3465 target->allowNearPetTp();
3466 target->tpWanted( state.X, state.Y, state.Z, true, state.Heading );
3467 return true;
3470 //----------------------------------------------------------------------------
3471 NLMISC_COMMAND( dismiss, "teleport a player back to its former position ( before last call to summonPlayer )", "<CSR eId><player name>" )
3473 if ( args.size() !=2 )
3474 return false;
3475 TRY_GET_CHARACTER
3476 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3477 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3479 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3480 return true;
3482 CHECK_RIGHT( c,target );
3483 COfflineEntityState state;
3484 if ( PlayerManager.getDismissCoords( target->getEntityRowId(), state ) )
3486 target->allowNearPetTp();
3487 target->tpWanted( state.X, state.Y, state.Z, true, state.Heading );
3488 CContinent * cont = CZoneManager::getInstance().getContinent(state.X, state.Y);
3489 if ( cont )
3491 target->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(cont->getId()) );
3493 PlayerManager.removeSummonedUser( target->getEntityRowId() );
3495 else
3497 CCharacter::sendDynamicSystemMessage( eid, "CSR_NOT_SUMMONED" );
3499 return true;
3502 //----------------------------------------------------------------------------
3503 NLMISC_COMMAND( teleport, "teleport the CSR in front of a player", "<CSR eId><player name>" )
3505 if ( args.size() !=2 )
3506 return false;
3507 GET_CHARACTER
3508 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3509 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3511 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3512 return true;
3514 float heading = target->getState().Heading;
3515 sint32 x = target->getState().X + sint32 (cos (target->getState ().Heading) * 2000);
3516 sint32 y = target->getState().Y + sint32 (sin (target->getState ().Heading) * 2000);
3517 sint32 z = target->getState().Z;
3518 heading += (float)NLMISC::Pi;
3519 if ( heading >= (float)NLMISC::Pi )
3520 heading -= 2* (float)NLMISC::Pi;
3522 c->allowNearPetTp();
3523 c->teleportCharacter(x, y, z, true, true, heading);
3524 CContinent * continent = CZoneManager::getInstance().getContinent(x, y);
3525 if (continent != NULL)
3527 c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(continent->getId()) );
3529 return true;
3532 //----------------------------------------------------------------------------
3533 //static string capitalize(const string & s)
3535 // if ( s.empty() )
3536 // return s;
3538 // return toUpper( s.substr(0,1) ) + toLower( s.substr(1,string::npos) );
3541 //----------------------------------------------------------------------------
3542 NLMISC_COMMAND( renamePlayerForEvent, "rename a player for the event", "<CSR eId><player name><new playerName>" )
3544 if ( args.size() != 3 )
3545 return false;
3547 ucstring newName( args[2] );
3548 TRY_GET_CHARACTER
3549 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3550 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3552 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3553 return true;
3555 CHECK_RIGHT( c,target );
3557 // assign new name to player
3559 // PlayerManager.addEntityForStringIdRequest( target->getId() );
3560 target->registerName(newName);
3562 return true;
3565 //----------------------------------------------------------------------------
3566 //NLMISC_COMMAND( renamePlayer, "rename a player", "<CSR eId><player name><new playerName>" )
3568 // if ( args.size() != 3 )
3569 // return false;
3571 // ucstring oldName( capitalize(args[1]) );
3572 // ucstring newName( capitalize(args[2]) );
3573 // TRY_GET_CHARACTER
3574 // CCharacter * target = PlayerManager.getCharacterByName( args[1] );
3575 // if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3576 // {
3577 // CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3578 // return true;
3579 // }
3580 // CHECK_RIGHT( c,target );
3582 // if ( CEntityIdTranslator::getInstance()->entityNameExists( newName ) )
3583 // {
3584 // CCharacter::sendDynamicSystemMessage( eid, "CSR_NAME_EXISTS" );
3585 // return true;
3586 // }
3588 // // assign new name to player
3589 // bool result = CNameManager::getInstance()->assignName( target->getId(), newName );
3590 // if ( !result )
3591 // {
3592 // CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_NAME" );
3593 // nlwarning("assignName failed for name: %s", newName.toUtf8().c_str() );
3594 // return true;
3595 // }
3596 // PlayerManager.addEntityForStringIdRequest( target->getId() );
3597 // target->setName( newName );
3598 // target->registerName();
3600 // if ( toLower(newName) != toLower(oldName) )
3601 // {
3602 // // liberate old name
3603 // CNameManager::getInstance()->liberateName( target->getId(), oldName );
3604 // }
3606 // return true;
3609 //----------------------------------------------------------------------------
3610 NLMISC_COMMAND( renameGuild, "rename a guild", "<CSR_eId> <guild_name>|<shardId:guildId> <new_guild_name>" )
3612 if ( args.size() != 3 )
3613 return false;
3614 if (args[0]!="admin_tool")
3616 TRY_GET_CHARACTER
3618 GET_GUILD(1, true, NLMISC::CEntityId::Unknown);
3620 ucstring name( args[2] );
3621 // check if name already exists in the player list
3622 if ( NLMISC::CEntityIdTranslator::getInstance()->entityNameExists( name ) /*|| EGSPD::PDSLib.getStringManager().stringExists(name, RYZOMID::guildName)*/ )
3624 if (args[0]=="admin_tool")
3626 log.displayNL("renameGuild failed because the name is already taken: ",args[2].c_str());
3628 else
3630 TRY_GET_CHARACTER
3631 CCharacter::sendDynamicSystemMessage( eid,"CSR_NAME_EXISTS" );
3633 return false;
3636 guild->setName( name );
3638 if (IGuildUnifier::getInstance() != NULL)
3639 IGuildUnifier::getInstance()->broadcastGuildUpdate(guild);
3640 // CGuildManager::getInstance()->addGuildsAwaitingString(name,guild->getId());
3641 return true;
3644 //----------------------------------------------------------------------------
3645 NLMISC_COMMAND( setGuildDescription, "set a guild description", "<guild_name>|<shardId:guildId> <new_guild_description>" )
3647 if ( args.size() != 2)
3648 return false;
3649 GET_GUILD(0, true, NLMISC::CEntityId::Unknown);
3650 ucstring desc( args[1] );
3651 guild->setDescription( desc );
3653 if (IGuildUnifier::getInstance() != NULL)
3654 IGuildUnifier::getInstance()->broadcastGuildUpdate(guild);
3656 // CGuildManager::getInstance()->addGuildsAwaitingString(desc,guild->getId());
3657 return true;
3660 //----------------------------------------------------------------------------
3661 NLMISC_COMMAND( setGuildIcon, "set a guild icon", "<guild_name>|<shardId:guildId> <new_icon_code(on 64 bits)>" )
3663 if ( args.size() != 2)
3664 return false;
3665 GET_GUILD(0, true, NLMISC::CEntityId::Unknown);
3667 uint64 icon = atoiInt64( args[1].c_str() );
3668 guild->setIcon( icon );
3670 if (IGuildUnifier::getInstance() != NULL)
3671 IGuildUnifier::getInstance()->broadcastGuildUpdate(guild);
3673 return true;
3676 //----------------------------------------------------------------------------
3677 NLMISC_COMMAND( killMob, "kill a mob ( /a killMob )", "<CSR eId>" )
3679 if ( args.size() != 1 )
3680 return false;
3681 TRY_GET_CHARACTER
3683 CCreature * creature = CreatureManager.getCreature( c->getTarget() );
3684 if (creature == NULL)
3686 nlwarning ("Unknown creature '%s'", c->getTarget().toString().c_str() );
3687 return false;
3689 if(!TheDataset.isAccessible(creature->getEntityRowId()))
3691 nlwarning ("'%s' is not valid in mirror", c->getTarget().toString().c_str());
3692 return false;
3694 if ( !creature->getContextualProperty().directAccessForStructMembers().attackable() )
3696 if ( ! creature->checkFactionAttackable(c->getId()))
3698 CCharacter::sendDynamicSystemMessage( eid, "CSR_NOT_ATTACKABLE" );
3699 return true;
3702 creature->getScores()._PhysicalScores[SCORES::hit_points].Current = 0;
3703 return true;
3707 //----------------------------------------------------------------------------
3708 NLMISC_COMMAND( dssTarget, "target a mob and send information to dss( /b dssTarget )", "<ring player eId>[<cmd>]" )
3710 if ( args.size() < 1 )
3711 return false;
3713 TRY_GET_CHARACTER
3715 CCreature * creature = CreatureManager.getCreature( c->getTarget() );
3716 if (creature == NULL)
3718 nlwarning ("Unknown creature '%s'", c->getTarget().toString().c_str() );
3719 return false;
3721 if(!TheDataset.isAccessible(creature->getEntityRowId()))
3723 nlwarning ("'%s' is not valid in mirror", c->getTarget().toString().c_str());
3724 return false;
3728 NLMISC::CEntityId creatureId = creature->getId();
3729 TAIAlias alias = CAIAliasTranslator::getInstance()->getAIAlias(creatureId);
3730 TDataSetRow entityRowId = creature->getEntityRowId();
3732 if (alias == CAIAliasTranslator::Invalid)
3734 nlwarning ("'%s' has no alias translation", creatureId.toString().c_str());
3735 return false;
3737 CMessage msgout("DSS_TARGET");
3738 msgout.serial(eid); //eid of the player
3739 msgout.serial(creatureId); // eid of the mob
3740 msgout.serial(alias); //mob targeted
3741 msgout.serial(entityRowId); //datasetrow
3743 uint32 args_size = (uint32)args.size() - 1;
3744 uint32 i = 0;
3745 msgout.serial(args_size);
3746 for ( ; i != args_size ; ++i)
3748 std::string str = args[1+i];
3749 msgout.serial(str);
3752 CUnifiedNetwork::getInstance()->send("DSS", msgout);
3755 return true;
3761 //----------------------------------------------------------------------------
3762 NLMISC_COMMAND( root, "root a player", "<CSR id><player name><time in second>" )
3764 if ( args.size() != 3 )
3765 return false;
3766 TRY_GET_CHARACTER
3767 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3768 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3770 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3771 return true;
3773 CHECK_RIGHT( c,target );
3775 NLMISC::TGameCycle cycle;
3776 NLMISC::fromString(args[2], cycle);
3777 cycle = TGameCycle(NLMISC::TGameTime(cycle) / CTickEventHandler::getGameTimeStep() + CTickEventHandler::getGameCycle());
3778 PlayerManager.addGMRoot( eid, target->getId(), cycle );
3779 return true;
3782 //----------------------------------------------------------------------------
3783 NLMISC_COMMAND( unroot, "stop rooting a player", "<CSR id> <player name>" )
3785 if ( args.size() != 2 )
3786 return false;
3787 TRY_GET_CHARACTER
3788 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3789 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3791 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3792 return true;
3794 CHECK_RIGHT( c,target );
3795 PlayerManager.removeGMRoot(eid , target->getId() );
3796 return true;
3799 //----------------------------------------------------------------------------
3800 NLMISC_COMMAND( ignoreTells, "ignore incoming tell", "<CSR id> <0 / false / 1 / true >" )
3802 if ( args.size() != 2 )
3803 return false;
3804 GET_CHARACTER
3806 CMessage msgout("IGNORE_TELL_MODE");
3807 msgout.serial(eid);
3808 bool ignore = (args[1]=="1" || strlwr(args[1])=="on" || strlwr(args[1])=="true" );
3809 msgout.serial( ignore );
3810 CUnifiedNetwork::getInstance()->send("IOS", msgout);
3811 return true;
3814 //----------------------------------------------------------------------------
3815 NLMISC_COMMAND( showCSR, "activate GM title", "<CSR id>" )
3817 if ( args.size() != 1 )
3818 return false;
3819 GET_CHARACTER
3820 CPlayer *p = PlayerManager.getPlayer(PlayerManager.getPlayerId( eid ) );
3821 if (p == NULL)
3823 nlwarning ("ADMIN: Can't find player with UserId %d", PlayerManager.getPlayerId(eid));
3824 return false;
3826 CHARACTER_TITLE::ECharacterTitle title = CHARACTER_TITLE::getGMTitleFromPriv( p->getUserPriv() );
3827 if ( title == CHARACTER_TITLE::NB_CHARACTER_TITLE )
3829 nlwarning ("ADMIN: UserId %d has an invalid privilege %s", PlayerManager.getPlayerId(eid), p->getUserPriv().c_str() );
3830 return false;
3832 c->setTitle( title );
3833 c->registerName();
3834 return true;
3837 //----------------------------------------------------------------------------
3838 NLMISC_COMMAND( monitorMissions, "monitor a player missions", "<CSR id><player name>" )
3840 if ( args.size() != 2 )
3841 return false;
3842 GET_CHARACTER;
3843 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3844 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3846 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3847 return true;
3849 CHECK_RIGHT( c,target );
3851 // CSR must have no missions to monitor a player
3852 if ( c->getMissionsBegin() != c->getMissionsEnd() )
3854 CCharacter::sendDynamicSystemMessage( c->getEntityRowId() , "CSR_HAS_MISSION" );
3855 return true;
3858 // target missions must not be monitored
3859 if ( target->getMonitoringCSR() != TDataSetRow::createFromRawIndex( INVALID_DATASET_ROW ) )
3861 CCharacter::sendDynamicSystemMessage( c->getEntityRowId() , "CSR_MISSION_MONITORED" );
3862 return true;
3864 target->setMonitoringCSR( c->getEntityRowId() );
3865 c->getAdminProperties().setMissionMonitoredUser( target->getEntityRowId() );
3867 for ( map<TAIAlias, CMission*>::iterator it = target->getMissionsBegin(); it != target->getMissionsEnd(); ++it )
3869 (*it).second->updateUsersJournalEntry();
3871 return true;
3874 //----------------------------------------------------------------------------
3875 NLMISC_COMMAND( stopMonitorMissions, "monitor a player missions", "<CSR id>" )
3877 if ( args.size() != 1 )
3878 return false;
3879 GET_CHARACTER;
3881 CCharacter * target = PlayerManager.getChar( c->getAdminProperties().getMissionMonitoredUser() );
3882 c->getAdminProperties().setMissionMonitoredUser( TDataSetRow::createFromRawIndex( INVALID_DATASET_ROW) );
3883 if ( target )
3884 target->setMonitoringCSR( TDataSetRow::createFromRawIndex( INVALID_DATASET_ROW ) );
3886 /// todo mission
3887 return true;
3890 //----------------------------------------------------------------------------
3891 NLMISC_COMMAND( failMission, "force mission failure", "<CSR id><mission idx>" )
3893 if ( args.size() != 2 )
3894 return false;
3895 GET_CHARACTER;
3897 uint index;
3898 NLMISC::fromString(args[1], index);
3899 CMission * mission = c->getAdminProperties().getMission(index);
3900 if ( !mission )
3902 CCharacter::sendDynamicSystemMessage( c->getEntityRowId(), "CSR_BAD_MISSION" );
3903 return true;
3905 mission->onFailure(true);
3906 return true;
3909 //----------------------------------------------------------------------------
3910 NLMISC_COMMAND( progressMission, "force mission progression", "<CSR id><mission idx>[repeat]")
3912 if ( args.size() != 2 && args.size() != 3 )
3913 return false;
3914 GET_CHARACTER;
3916 uint index;
3917 NLMISC::fromString(args[1], index);
3918 CMission * mission = c->getAdminProperties().getMission(index);
3919 if ( !mission )
3921 CCharacter::sendDynamicSystemMessage( c->getEntityRowId(), "CSR_BAD_MISSION" );
3922 return true;
3924 CCharacter * user = mission->getMainEntity();
3925 uint repeat = 1;
3926 if ( args.size() == 3 )
3927 NLMISC::fromString(args[2], repeat);
3928 CMissionEventDebug event;
3929 for ( uint i = 0; i < repeat; i++ )
3930 user->processMissionEvent(event);
3931 return true;
3934 //----------------------------------------------------------------------------
3935 NLMISC_COMMAND (changeVar, "change a variable of a player", "<eid> <var> <val>")
3937 if (args.size() != 3)
3938 return false;
3940 CEntityId eid (args[0]);
3942 string var = args[1];
3943 string value = args[2];
3945 CEntityBase *e = CEntityBaseManager::getEntityBasePtr(eid);
3946 if(e != 0)
3948 if (e->setValue (var, value))
3949 log.displayNL("Change Var of Entity %s Var %s Value %s", eid.toString().c_str(), var.c_str(), value.c_str());
3951 else
3953 log.displayNL("Unknown entity %s (not a player or a creature)", eid.toString().c_str());
3956 return true;
3959 //----------------------------------------------------------------------------
3960 NLMISC_COMMAND (mute, "mute a user", "<csr id> <player name><duration>")
3962 if ( args.size() != 3 )
3963 return false;
3964 GET_CHARACTER;
3965 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3966 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3968 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3969 return true;
3971 CHECK_RIGHT( c,target );
3972 uint32 duration;
3973 NLMISC::fromString(args[2], duration);
3974 NLMISC::TGameCycle cycle = (NLMISC::TGameCycle) ( duration / CTickEventHandler::getGameTimeStep() + CTickEventHandler::getGameCycle() );
3975 PlayerManager.addGMMute( eid, target->getId(), cycle );
3976 return true;
3979 //----------------------------------------------------------------------------
3980 NLMISC_COMMAND (unmute, "unmute a user", "<csr id> <player name>")
3982 if ( args.size() != 2 )
3983 return false;
3984 GET_CHARACTER;
3985 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
3986 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
3988 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
3989 return true;
3992 PlayerManager.removeGMMute( eid, target->getId() );
3993 return true;
3996 //----------------------------------------------------------------------------
3997 NLMISC_COMMAND (universe, "chat in universe mode", "<boolean>")
3999 if ( args.size() != 2 )
4000 return false;
4001 GET_CHARACTER;
4002 bool on = (args[1]=="1" || strlwr(args[1])=="on" || strlwr(args[1])=="true" );
4004 CMessage msgOut("UNIVERSE_MODE");
4006 msgOut.serial( const_cast<CEntityId&>(eid) );
4007 msgOut.serial( on );
4008 CUnifiedNetwork::getInstance()->send( "IOS", msgOut );
4009 return true;
4012 //----------------------------------------------------------------------------
4013 NLMISC_COMMAND (muteUniverse, "mute the univers chat", "<csr id><player name><duration>")
4015 if ( args.size() != 3 )
4016 return false;
4017 GET_CHARACTER;
4019 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
4020 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
4022 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
4023 return true;
4026 // find if the command is available
4027 const CAdminCommand * cmd = findAdminCommand("muteUniverse");
4028 if (!cmd)
4030 nlwarning ("ADMIN: Player %s tried to execute a no valid client admin command '%s'", c->getId().toString().c_str(), "muteUniverse");
4031 chatToPlayer (c->getId(), "Unknown command");
4032 return true;
4035 if (!c->havePriv(cmd->Priv))
4037 nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command '%s' ", c->getId().toString().c_str(), "muteUniverse");
4038 chatToPlayer (c->getId(), "You don't have privilege to execute this command");
4039 return true;
4042 uint32 duration;
4043 NLMISC::fromString(args[2], duration);
4044 NLMISC::TGameCycle cycle = (NLMISC::TGameCycle) (duration / CTickEventHandler::getGameTimeStep() + CTickEventHandler::getGameCycle() );
4045 PlayerManager.muteUniverse( eid, cycle, target->getId() );
4046 return true;
4049 //----------------------------------------------------------------------------
4050 NLMISC_COMMAND (unmuteUniverse, "unmute the univers chat", "<csr id><player name>")
4052 if ( args.size() != 2 )
4053 return false;
4054 GET_CHARACTER;
4056 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1]) );
4057 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
4059 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
4060 return true;
4063 // find if the command is available
4064 const CAdminCommand * cmd = findAdminCommand("unmuteUniverse");
4065 if (!cmd)
4067 nlwarning ("ADMIN: Player %s tried to execute a no valid client admin command '%s'", c->getId().toString().c_str(), "unmuteUniverse");
4068 chatToPlayer (c->getId(), "Unknown command");
4069 return true;
4072 if (!c->havePriv(cmd->Priv))
4074 nlwarning ("ADMIN: Player %s doesn't have privilege to execute the client admin command '%s' ", c->getId().toString().c_str(), "unmuteUniverse");
4075 chatToPlayer (c->getId(), "You don't have privilege to execute this command");
4076 return true;
4079 PlayerManager.unmuteUniverse(eid, target->getId());
4080 return true;
4083 //----------------------------------------------------------------------------
4084 NLMISC_COMMAND (setGMGuild, "set the current GM guild", "")
4086 GET_CHARACTER;
4087 uint32 guildId = c->getGuildId();
4088 CGuildManager::getInstance()->setGMGuild( guildId );
4089 return true;
4092 //----------------------------------------------------------------------------
4093 NLMISC_COMMAND (targetInfos, "give infos on the target", "")
4095 if ( args.size() != 1 )
4096 return false;
4097 GET_CHARACTER;
4099 string answer = "displaying info on target : \n";
4100 if ( c->getTarget().getType() == RYZOMID::creature || c->getTarget().getType() == RYZOMID::npc )
4102 CCreature * target = CreatureManager.getCreature( c->getTarget() );
4103 if ( !target )
4104 answer = "invalid creature target";
4105 else
4107 answer = NLMISC::toString( "HP : %u / %u",
4108 target->getScores()._PhysicalScores[SCORES::hit_points].Current(),
4109 target->getScores()._PhysicalScores[SCORES::hit_points].Max() );
4112 else if ( c->getTarget().getType() == RYZOMID::player )
4114 CCharacter * target = PlayerManager.getChar( c->getTarget() );
4115 if ( !target )
4116 answer += "invalid player target";
4117 else
4119 const std::vector< SCharacteristicsAndScores > & scores = target->getScores()._PhysicalScores;
4120 answer = NLMISC::toString( "HP : %d / %d \nSAP : %d / %d \nSTA : %d / %d \nFOCUS : %d / %d \n",
4121 scores[SCORES::hit_points].Current(),scores[SCORES::hit_points].Max(),
4122 scores[SCORES::sap].Current(),scores[SCORES::sap].Max(),
4123 scores[SCORES::stamina].Current(),scores[SCORES::stamina].Max(),
4124 scores[SCORES::focus].Current(),scores[SCORES::focus].Max() );
4125 answer += "\n Displaying skills > 1:\n";
4126 for ( uint i = 0; i < target->getSkills()._Skills.size();i++ )
4128 sint32 base = target->getSkillBaseValue( ( SKILLS::ESkills ) i );
4129 sint32 current = target->getSkillValue( ( SKILLS::ESkills ) i );
4130 if ( base > 1 || current > 1 )
4132 answer+= NLMISC::toString( "%s: %d / %d\n", SKILLS::toString( i ).c_str(), current,base );
4138 else
4139 answer += "invalid target type";
4141 SM_STATIC_PARAMS_1(params,STRING_MANAGER::literal);
4142 params[0].Literal = answer;
4144 CCharacter::sendDynamicSystemMessage( eid,"LITERAL", params );
4145 return true;
4148 //----------------------------------------------------------------------------
4149 NLMISC_COMMAND (infos, "give info on character (GodMode, Invisible...)", "")
4151 CSString str("INFO: ");
4152 GET_CHARACTER
4153 if( c->invulnerableMode() )
4155 str << "INVULNERABLE_MODE ";
4157 if( c->godMode() )
4159 str << "GOD_MODE ";
4161 else
4163 if( c->invulnerableMode() == false )
4164 str << "VULNERABLE ";
4167 if( R2_VISION::isEntityVisibleToPlayers(c->getWhoSeesMe()) )
4169 str << "VISIBLE ";
4171 else
4173 if (IsRingShard)
4175 str << "INVISIBLE(" <<R2_VISION::extractInvisibilityLevel(c->getWhoSeesMe()) << ") ";
4177 else
4179 str << "INVISIBLE ";
4183 if ( IsRingShard && R2_VISION::extractVisionLevel(c->getWhoSeesMe())!=R2_VISION::VISIBLE )
4185 str << "SEEINVIS(" << R2_VISION::extractVisionLevel(c->getWhoSeesMe()) << ") ";
4188 if (c->getAggroableSave())
4190 str << "AGGROABLE ";
4192 else
4194 str << "NOT_AGGROABLE ";
4197 log.displayNL(str.c_str());
4198 return true;
4201 //----------------------------------------------------------------------------
4202 //NLMISC_COMMAND(addGuildXp,"add xp of a guild","<guild_name>|<shardId:guildId> <xp ( positive or negative )>")
4204 // if ( args.size() != 2 )
4205 // return false;
4207 // GET_GUILD(0, true, NLMISC::CEntityId::Unknown);
4208 // sint xp;
4209 // NLMISC::fromString(args[1], xp);
4210 // if ( xp < 0 )
4211 // {
4212 // uint32 uXP = (uint32)(-xp);
4213 // if ( uXP > guild->getXP() )
4214 // guild->spendXP( guild->getXP() );
4215 // else
4216 // guild->spendXP( uXP );
4217 // }
4218 // else
4219 // {
4220 // uint32 uXP = (uint32)xp;
4221 // guild->addXP ( uXP );
4222 // }
4223 // log.displayNL( "added %d xp. Current xp is %u", xp, guild->getXP() );
4224 // return true;
4227 //----------------------------------------------------------------------------
4228 //NLMISC_COMMAND(setGuildChargePoint,"set the charge points of a guild","<guild_name>|<shardId:guildId> <points>")
4230 // if ( args.size() != 2 )
4231 // return false;
4232 // GET_GUILD(0, true, NLMISC::CEntityId::Unknown);
4233 // uint32 points;
4234 // NLMISC::fromString(args[1], points);
4235 // guild->clearChargePoints();
4236 // guild->addChargePoints( points );
4237 // log.displayNL( "set charge points to %u", points );
4238 // return true;
4241 //----------------------------------------------------------------------------
4242 ENTITY_VARIABLE(Invisible, "Invisibility of a player")
4244 ENTITY_GET_ENTITY
4246 if (get)
4248 value = R2_VISION::isEntityVisibleToPlayers(e->getWhoSeesMe()) ?"0":"1";
4250 else
4252 TDataSetRow userRow = TheDataset.getDataSetRow( e->getId() );
4253 if ( !TheDataset.isAccessible( userRow ) )
4254 return;
4256 // may be null !
4257 CCharacter *c = dynamic_cast<CCharacter*>(e);
4259 uint64 val;
4260 bool isVisible = R2_VISION::isEntityVisibleToPlayers(e->getWhoSeesMe());
4262 if (value=="1" || value=="on" || strlwr(value)=="true" || (strlwr(value)=="toggle" && isVisible))
4264 if (c != NULL)
4265 c->setInvisibility(true);
4267 if (IsRingShard)
4269 // seup the default value to use
4270 val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_PLAYER,false);
4272 CPlayer * player = PlayerManager.getPlayer( PlayerManager.getPlayerId(entity) );
4273 if (player != NULL )
4275 if( player->havePriv(":VG:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_VG,false);
4276 if( player->havePriv(":SG:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_SG,false);
4277 if( player->havePriv(":EG:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_EG,false);
4278 if( player->havePriv(":EM:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_EM,false);
4279 if( player->havePriv(":GM:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_GM,false);
4280 if( player->havePriv(":SGM:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_SGM,false);
4281 if( player->havePriv(":DEV:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_INVISIBLE_DEV,false);
4284 else
4286 val=0;
4289 else if (value=="0" || value=="off" || strlwr(value)=="false" || strlwr(value)=="toggle")
4291 if (c != NULL)
4292 c->setInvisibility(false);
4294 if (IsRingShard)
4296 // seup the default value to use
4297 val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_PLAYER,false);
4299 CPlayer * player = PlayerManager.getPlayer( PlayerManager.getPlayerId(entity) );
4300 if (player != NULL )
4302 if( player->havePriv(":VG:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_VG,false);
4303 if( player->havePriv(":SG:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_SG,false);
4304 if( player->havePriv(":EG:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_EG,false);
4305 if( player->havePriv(":EM:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_EM,false);
4306 if( player->havePriv(":GM:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_GM,false);
4307 if( player->havePriv(":SGM:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_SGM,false);
4308 if( player->havePriv(":DEV:") ) val = R2_VISION::buildWhoSeesMe(R2_VISION::WHOSEESME_VISIBLE_DEV,false);
4311 else
4313 val=~0;
4316 else
4317 return;
4319 // Set visibility of character
4320 e->setWhoSeesMe( val );
4322 // Force unmounting (can't be invisible on a mount)
4323 if ( c )
4325 CEntityBase *mount = c->getMountEntity();
4326 if ( mount )
4327 c->unmount( true );
4330 // Ignore tells if invisible
4331 CMessage msgout("IGNORE_TELL_MODE");
4332 msgout.serial( const_cast<CEntityId&>(e->getId()) );
4333 bool ignore = (val == 0);
4334 msgout.serial( ignore );
4335 CUnifiedNetwork::getInstance()->send("IOS", msgout);
4337 nlinfo ("%s has now '%" NL_I64 "X' in invisibility", entity.toString().c_str(), e->getWhoSeesMe());
4341 //----------------------------------------------------------------------------
4342 NLMISC_COMMAND(broadcast, "Broadcast a text", "[repeat=<num repeat> or during=<time in seconds>] [every=<delay in seconds>] <message>")
4344 if( args.size() < 1 )
4346 return false;
4349 string message;
4350 uint i;
4351 for( i = 0; i< args.size(); i++ )
4353 message += args[i];
4354 if( i != args.size() - 1 )
4356 message += " ";
4360 uint32 repeat = 1;
4361 uint32 during = 0;
4362 uint32 every = 0;
4364 string::size_type posMessage = 0;
4366 string::size_type pos = message.find("repeat");
4367 if( pos != string::npos )
4369 string::size_type posEgale = message.find("=", pos);
4370 if( posEgale != string::npos )
4372 NLMISC::fromString(message.substr( posEgale+1 ), repeat);
4373 if( posEgale + 1 > posMessage )
4374 posMessage = posEgale + 1;
4378 pos = message.find("during");
4379 if( pos != string::npos )
4381 string::size_type posEgale = message.find("=", pos);
4382 if( posEgale != string::npos )
4384 NLMISC::fromString(message.substr( posEgale+1 ), during);
4385 if( posEgale + 1 > posMessage )
4386 posMessage = posEgale + 1;
4390 pos = message.find("every");
4391 if( pos != string::npos )
4393 string::size_type posEgale = message.find("=", pos);
4394 if( posEgale != string::npos )
4396 NLMISC::fromString(message.substr( posEgale+1 ), every);
4397 if( posEgale + 1 > posMessage )
4398 posMessage = posEgale + 1;
4402 if( posMessage != 0 )
4404 posMessage = message.find( " ", posMessage+1 );
4405 if( posMessage != string::npos )
4407 message = message.substr( posMessage+1 );
4409 else
4411 message.clear();
4415 if( message.size() == 0 )
4417 log.displayNL("You must enter a message");
4418 return false;
4421 if( repeat > 1 && during != 0 )
4423 log.displayNL("You can't use repeat and during option in same time");
4424 return false;
4427 if( ( ( repeat > 1 || during > 0 ) && every == 0 ) || ( ( every > during ) && during > 0 ) )
4429 log.displayNL("Can't execute broadcast command, check your repeat/during/every parameters");
4430 return false;
4433 log.displayNL("Execute Broadcast: repeat=%d during=%d every=%d message=%s", repeat, during, every, message.c_str() );
4434 PlayerManager.broadcastMessage( repeat, during, every, message );
4435 return true;
4438 //----------------------------------------------------------------------------
4439 ENTITY_VARIABLE (God, "God mode, invulnerability")
4441 ENTITY_GET_CHARACTER
4443 if (get)
4445 value = c->godMode()?"1":"0";
4447 else
4449 if (value=="1" || value=="on" || strlwr(value)=="god" || strlwr(value)=="true" || (strlwr(value)=="toggle" && !c->godMode()))
4451 c->setGodModeSave(true);
4452 c->setGodMode(true);
4453 c->setBonusMalusName("god", c->addEffectInDB(CSheetId("berserk.sbrick"), true));
4455 else if (value=="0" || value=="off" || strlwr(value)=="false" || strlwr(value)=="toggle")
4457 c->setGodModeSave(false);
4458 c->setGodMode(false);
4459 c->removeEffectInDB(c->getBonusMalusName("god"), true);
4461 nlinfo ("%s %s now in god mode", entity.toString().c_str(), c->godMode()?"is":"isn't");
4465 //----------------------------------------------------------------------------
4466 ENTITY_VARIABLE (Invulnerable, "Invulnerable mode, invulnerability too all")
4468 ENTITY_GET_CHARACTER
4470 if (get)
4472 value = c->invulnerableMode()?"1":"0";
4474 else
4476 if (value=="1" || value=="on" || strlwr(value)=="invulnerable" || strlwr(value)=="true" || (strlwr(value)=="toggle" && !c->invulnerableMode()))
4478 c->setInvulnerableMode(true);
4479 c->setBonusMalusName("invulnerability", c->addEffectInDB(CSheetId("invulnerability.sbrick"), true));
4481 else if (value=="0" || value=="off" || strlwr(value)=="false" || strlwr(value)=="toggle")
4483 c->setInvulnerableMode(false);
4484 c->removeEffectInDB(c->getBonusMalusName("invulnerability"), true);
4486 nlinfo ("%s %s now in invulnerable mode", entity.toString().c_str(), c->invulnerableMode()?"is":"isn't");
4490 //----------------------------------------------------------------------------
4491 NLMISC_COMMAND (ShowFactionChannels, "Show faction channels", "<csr id> <channel> <0|1>")
4493 if (args.size() != 3)
4494 return false;
4495 GET_CHARACTER
4497 // PVP_CLAN::TPVPClan channelClan = PVP_CLAN::fromString( args[1] );
4499 bool display = (args[2]=="1" || strlwr(args[2])=="on" || strlwr(args[2])=="true" );
4501 TChanID channel = CPVPManager2::getInstance()->getFactionDynChannel(args[1]);
4502 if (channel == DYN_CHAT_INVALID_CHAN)
4504 log.displayNL("Invalid Faction name: '%s'", args[1].c_str());
4505 return false;
4507 CPVPManager2::getInstance()->addRemoveFactionChannelToUserWithPriviledge(channel, c, display);
4508 nlinfo ("%s %s now in show %s channel mode", eid.toString().c_str(), display?"is":"isn't", channel.toString().c_str());
4510 return true;
4514 //----------------------------------------------------------------------------
4515 // If channel not exists create it
4516 NLMISC_COMMAND (connectUserChannel, "Connect to user channels", "<user id> <channel_name> [<pass>]")
4518 if ((args.size() < 2) || (args.size() > 3))
4519 return false;
4520 GET_CHARACTER
4522 CPVPManager2 *inst = CPVPManager2::getInstance();
4524 string pass;
4525 string name = args[1];
4526 string nameLwr = toCaseInsensitive(args[1]);
4527 TChanID channel = inst->getUserDynChannel(nameLwr);
4529 if (args.size() < 3)
4530 pass = nameLwr;
4531 else
4532 pass = args[2];
4534 if ( (channel == DYN_CHAT_INVALID_CHAN) && (pass != nlstr("*")) && (pass != nlstr("***")) )
4536 // Don't allow channels starting with "FACTION_" (to not clash with the faction channels)
4537 if (!c->havePriv(":DEV:") && !c->havePriv(":SGM:") && !c->havePriv(":EM:") && nameLwr.substr(0, 8) == toCaseInsensitive("FACTION_"))
4538 channel = DYN_CHAT_INVALID_CHAN;
4539 else
4540 channel = inst->createUserChannel(nameLwr, pass);
4543 if (channel != DYN_CHAT_INVALID_CHAN)
4545 string channelPass = inst->getPassUserChannel(channel);
4547 if ( pass == nlstr("***") && (c->havePriv(":DEV:") || c->havePriv(":SGM:") || c->havePriv(":GM:") || c->havePriv(":EM:")))
4549 inst->deleteUserChannel(nameLwr);
4551 else if (channelPass == pass)
4553 std::vector<TChanID> userChannels = inst->getCharacterUserChannels(c);
4554 if (userChannels.size() >= NB_MAX_USER_CHANNELS)
4556 inst->removeFactionChannelForCharacter(userChannels[0], c, true);
4558 inst->addFactionChannelToCharacter(channel, c, true, true);
4560 else if (pass == nlstr("*"))
4562 inst->removeFactionChannelForCharacter(channel, c, true);
4564 else
4566 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
4567 params[0].Literal = name;
4568 CCharacter::sendDynamicSystemMessage( eid, nlstr("EGS_CHANNEL_NO_RIGHTS"), params );
4571 return true;
4574 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
4575 params[0].Literal = name;
4576 CCharacter::sendDynamicSystemMessage( eid, nlstr("EGS_CHANNEL_INVALID_NAME"), params );
4577 return false;
4581 NLMISC_COMMAND (connectLangChannel, "Connect to lang channel", "<user id> <lang> <leave:0|1>")
4583 if ((args.size() < 2) || (args.size() > 3))
4584 return false;
4585 GET_CHARACTER
4587 CPVPManager2 *inst = CPVPManager2::getInstance();
4589 string lang = args[1];
4590 if (lang != "en" && lang != "fr" && lang != "de" && lang != "ru" && lang != "es" && lang != "rf" && !c->havePriv(":DEV:"))
4591 return false;
4593 bool leave = false;
4594 if (args.size() > 2)
4595 leave = args[2] == "1";
4597 string channelName = lang;
4598 // Convert langs to usr lang channels
4599 if (lang == "en" || lang == "fr" || lang == "de" || lang == "ru" || lang == "es")
4600 channelName = "usr_"+lang;
4602 TChanID channel = inst->getFactionDynChannel(channelName);
4604 if (channel != DYN_CHAT_INVALID_CHAN)
4606 string current_channels = c->getLangChannel();
4607 if (leave)
4609 strFindReplace(current_channels, lang+" ", "");
4610 strFindReplace(current_channels, " "+lang, "");
4611 inst->removeFactionChannelForCharacter(channel, c);
4612 c->setLangChannel(current_channels);
4614 else if (current_channels.find(lang) == string::npos)
4616 inst->addFactionChannelToCharacter(channel, c, true);
4617 c->setLangChannel(current_channels + " "+lang);
4619 return true;
4622 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
4623 params[0].Literal = lang;
4624 CCharacter::sendDynamicSystemMessage( eid, "EGS_CHANNEL_INVALID_NAME", params );
4625 return false;
4629 NLMISC_COMMAND (setDontTranslateLangs, "Set langs that a player dont want to see translated", "<user id> <langs>")
4631 if (args.size() != 2)
4632 return false;
4634 GET_CHARACTER
4636 TDataSetRow player = c->getEntityRowId();
4639 CMessage msgout("SET_USER_DONT_TRANSLATE_LANGS");
4640 msgout.serial(player);
4641 string langs = args[1];
4642 msgout.serial(langs);
4643 CUnifiedNetwork::getInstance()->send("IOS", msgout);
4644 c->setDontTranslate(langs);
4645 return true;
4650 NLMISC_COMMAND (updateTarget, "Update current target", "<user id>")
4652 GET_CHARACTER
4653 c->updateTarget();
4654 return true;
4657 // !!! Deprecated !!!
4658 NLMISC_COMMAND (webAddCommandsIds, "Add ids of commands will be run from webig", "<user id> <bot_name> <web_app_url> <indexes>")
4660 if (args.size() != 4)
4661 return false;
4663 GET_CHARACTER
4665 string web_app_url = args[2];
4666 string indexes = args[3];
4668 c->addWebCommandCheck(web_app_url, indexes, ArkSalt.get());
4669 return true;
4672 // !!! Deprecated !!!
4673 NLMISC_COMMAND (webDelCommandsIds, "Del ids of commands", "<user id> <web_app_url>")
4675 if (args.size() != 2)
4676 return false;
4678 GET_CHARACTER
4680 string web_app_url = args[1];
4681 uint item_idx = c->getWebCommandCheck(web_app_url);
4682 if (item_idx == INVENTORIES::NbBagSlots)
4683 return false;
4685 CInventoryPtr inv = c->getInventory(INVENTORIES::bag);
4686 CGameItemPtr item = inv->getItem(item_idx);
4687 inv->removeItem(item_idx);
4688 item.deleteItem();
4689 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=deleted");
4690 return true;
4693 CInventoryPtr getInv(CCharacter *c, const string &inv)
4695 CInventoryPtr inventoryPtr = NULL;
4696 if (!inv.empty())
4698 INVENTORIES::TInventory selectedInv = INVENTORIES::toInventory(inv);
4699 switch (selectedInv)
4701 case INVENTORIES::temporary:
4702 case INVENTORIES::bag:
4703 case INVENTORIES::equipment:
4704 case INVENTORIES::pet_animal1:
4705 case INVENTORIES::pet_animal2:
4706 case INVENTORIES::pet_animal3:
4707 case INVENTORIES::pet_animal4:
4708 case INVENTORIES::pet_animal5:
4709 case INVENTORIES::pet_animal6:
4710 case INVENTORIES::pet_animal7:
4711 case INVENTORIES::guild:
4712 case INVENTORIES::player_room:
4713 inventoryPtr = c->getInventory(selectedInv);
4714 break;
4716 default:
4717 // No-op
4718 break;
4721 return inventoryPtr;
4724 NLMISC_COMMAND (webExecCommand, "Execute a web command", "<user id> <web_app_url> <index> <command> <hmac> [<new_check=0|1|2|3>] [<next_step=0|1>] [<send_url=0|1|2>]")
4727 if (args.size() < 5)
4728 return false;
4730 GET_CHARACTER
4732 bool new_check = false;
4733 bool new_separator = false;
4734 // New check using HMagic
4735 if (args.size() >= 6 && (args[5] == "1" || args[5] == "3"))
4736 new_check = true;
4738 // New separator "|"
4739 if (args.size() >= 6 && (args[5] == "2" || args[5] == "3"))
4740 new_separator = true;
4742 bool next_step = false;
4743 if (args.size() >= 7 && args[6] == "1")
4744 next_step = true;
4746 bool send_url = false;
4747 if (args.size() >= 8 && args[7] == "1")
4748 send_url = true;
4750 bool save_index = false;
4751 if (args.size() >= 8 && args[7] == "2")
4753 send_url = true;
4754 save_index = true;
4757 c->setAfkState(false);
4759 string web_app_url = args[1];
4760 string index = args[2];
4761 uint32 iindex;
4762 NLMISC::fromString(index, iindex);
4763 string command = args[3];
4764 string hmac = args[4];
4766 vector<string> infos;
4767 CGameItemPtr item;
4769 if (new_check)
4771 uint32 saved_index = c->getWebCommandIndex();
4772 if (iindex <= saved_index && command != "is_valid_index")
4774 // Index of command must be higher than last used index to prevent re-use of commands
4775 if (send_url)
4776 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_index");
4777 return false;
4779 if (next_step && (iindex != saved_index+1))
4781 // Next step commands wants an index who follow the last used index.
4782 if (send_url)
4783 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_next_index");
4784 return false;
4787 string checksumEid = web_app_url + toString(c->getLastConnectedDate()) + index + command + c->getId().toString();
4789 string checksumRowId = web_app_url + toString(c->getLastConnectedDate()) + index + command + toString(c->getEntityRowId().getIndex());
4791 string salt = ArkSalt.get();
4793 string realhmacEid = getHMacSHA1((uint8*)&checksumEid[0], checksumEid.size(), (uint8*)&salt[0], salt.size()).toString();
4794 string realhmacRowId = getHMacSHA1((uint8*)&checksumRowId[0], checksumRowId.size(), (uint8*)&salt[0], salt.size()).toString();
4795 if (realhmacEid != hmac && realhmacRowId != hmac && command != "is_valid_index")
4797 if (send_url)
4798 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_auth");
4799 return false;
4802 else
4804 // !!! DEPRECATED !!!
4805 CInventoryPtr check_inv = c->getInventory(INVENTORIES::bag);
4806 if (!c->havePriv(":DEV:") || (web_app_url != "debug"))
4808 uint item_idx = c->checkWebCommand(web_app_url, index+command, hmac, "");
4809 if (item_idx == INVENTORIES::NbBagSlots)
4811 nlwarning("Bad web command check");
4812 return false;
4815 item = check_inv->getItem(item_idx);
4816 string cText = item->getCustomText().toString();
4817 NLMISC::splitString(cText, "\n", infos);
4819 vector<string> indexes;
4820 NLMISC::splitString(infos[1], ",", indexes);
4822 if (index != indexes[0])
4823 return false;
4827 string pName = CEntityIdTranslator::getInstance()->getByEntity(c->getId()).toString();
4828 nlinfo("(%s ,%s) %s[%s]%d", c->getId().toString().c_str(), pName.c_str(), web_app_url.c_str(), command.c_str(), iindex);
4830 if (command == "is_valid_index")
4832 if (!c->isValidWebCommandIndex(iindex)) {
4833 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=unvalid_index");
4835 else
4837 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=finished&desc=valid_index");
4839 return true;
4842 std::vector<std::string> command_args;
4843 if (new_separator)
4844 NLMISC::splitString(command, "|", command_args);
4845 else
4846 NLMISC::splitString(command, "!", command_args);
4847 if (command_args.empty())
4848 return false;
4850 //*************************************************
4851 //***************** give_item sheet quality quantity inv is_min_qual[0|1]=0
4852 //*************************************************
4854 if (command_args[0] == "give_item")
4856 if (command_args.size() < 4)
4857 return false;
4859 const CSheetId sheetId(command_args[1]);
4860 if (sheetId == CSheetId::Unknown)
4861 return false;
4862 uint32 quality;
4863 fromString(command_args[2], quality);
4864 if (quality == 0)
4865 return false;
4866 uint32 quantity;
4867 fromString(command_args[3], quantity);
4868 if (quantity == 0)
4869 return false;
4871 string selected_inv;
4872 if (command_args.size() >= 5)
4873 selected_inv = command_args[4];
4874 CInventoryPtr inventory = getInv(c, selected_inv);
4876 if (inventory == NULL)
4878 if (send_url)
4879 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_inventory");
4880 return false;
4883 bool is_min_quality = false;
4884 if (command_args.size() >= 6)
4885 selected_inv = command_args[5];
4887 uint32 numberEqualItem = 0;
4888 uint32 numberItem = 0;
4889 for ( uint32 i = 0; i < inventory->getSlotCount(); ++ i)
4891 const CGameItemPtr itemPtr = inventory->getItem(i);
4892 if ( itemPtr != NULL )
4894 if ( (itemPtr->getSheetId() == sheetId) )
4896 if (itemPtr->quality() == quality)
4897 numberEqualItem += itemPtr->getStackSize();
4898 if (itemPtr->quality() >= quality)
4899 numberItem += itemPtr->getStackSize();
4904 if ( (is_min_quality && numberItem < quantity) || (!is_min_quality && numberEqualItem < quantity) )
4906 if (send_url)
4907 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_items");
4908 return false;
4911 numberItem = quantity;
4912 numberEqualItem = quantity;
4913 for(uint32 i = 0; i < inventory->getSlotCount(); ++i)
4915 const CGameItemPtr itemPtr = inventory->getItem(i);
4916 if ( itemPtr != NULL )
4918 if ( (itemPtr->getSheetId() == sheetId) )
4920 if (is_min_quality && itemPtr->quality() >= quality)
4922 numberEqualItem -= inventory->deleteStackItem(i, quantity);
4923 if(numberEqualItem == 0)
4924 break;
4926 else if (!is_min_quality && itemPtr->quality() == quality)
4928 numberItem -= inventory->deleteStackItem(i, quantity);
4929 if(numberItem == 0)
4930 break;
4937 //*************************************************
4938 //***************** recv_item
4939 //*************************************************
4941 else if (command_args[0] == "recv_item" || command_args[0] == "recv_unique_item")
4943 if (command_args.size() < 4)
4944 return false;
4946 uint32 quality;
4947 fromString(command_args[2], quality);
4948 if (quality == 0)
4949 return false;
4950 uint32 quantity;
4951 fromString(command_args[3], quantity);
4952 if (quantity == 0)
4953 return false;
4955 // Inventory to put item in; can be temp, bag or animals.
4956 INVENTORIES::TInventory inventory = INVENTORIES::bag;
4957 if (command_args.size() == 5)
4959 INVENTORIES::TInventory inv = INVENTORIES::toInventory(command_args[4].c_str());
4960 switch (inv)
4962 case INVENTORIES::temporary:
4963 case INVENTORIES::bag:
4964 case INVENTORIES::pet_animal1:
4965 case INVENTORIES::pet_animal2:
4966 case INVENTORIES::pet_animal3:
4967 case INVENTORIES::pet_animal4:
4968 case INVENTORIES::pet_animal5:
4969 case INVENTORIES::pet_animal6:
4970 case INVENTORIES::pet_animal7:
4971 case INVENTORIES::guild:
4972 case INVENTORIES::player_room:
4973 inventory = inv;
4974 break;
4976 default:
4977 inventory = INVENTORIES::bag;
4981 CGameItemPtr new_item;
4982 string sheet = command_args[1];
4984 if ( sheet.find(".sitem") == string::npos ) // try named item
4986 new_item = CNamedItems::getInstance().createNamedItem(command_args[1], quantity);
4988 else
4990 const CSheetId sheetId(sheet);
4991 if (sheetId == CSheetId::Unknown)
4992 return true;
4994 if (command_args[0] == "recv_unique_item")
4996 CInventoryPtr selected_inv = c->getInventory(inventory);
4997 for( uint32 i = 0; i < selected_inv->getSlotCount(); ++ i )
4999 const CGameItemPtr itemPtr = selected_inv->getItem(i);
5000 if( itemPtr != NULL )
5002 if( itemPtr->getSheetId() == sheetId && itemPtr->quality() == quality )
5004 if (send_url)
5005 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=allready_have_item");
5006 return false;
5012 new_item = c->createItem(quality, quantity, sheetId);
5015 if (new_item == NULL)
5016 return true;
5018 if (!c->addItemToInventory(inventory, new_item))
5020 new_item.deleteItem();
5021 if (send_url)
5022 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=cant_add_item");
5023 return false;
5026 if (new_item != NULL) // When the item is stacked, it's deleted by addItemToInventory. Need be checked again to prevent crash of egs
5028 ucstring customValue;
5030 if (command_args.size() >= 6 && command_args[5] != "*")
5032 //deprecated
5033 //customValue.fromUtf8(command_args[5]);
5034 //new_item->setCustomName(customValue);
5037 if (command_args.size() >= 7 && command_args[6] != "*")
5039 customValue.fromUtf8(command_args[6]);
5040 new_item->setCustomText(customValue);
5043 if (command_args.size() >= 8)
5045 new_item->setMovable(command_args[7] == "1");
5048 if (command_args.size() >= 9)
5050 new_item->setUnMovable(command_args[8] == "1");
5054 //*************************************************
5055 //***************** check_position
5056 //*************************************************
5058 else if (command_args[0] == "check_position")
5060 if (command_args.size () != 5) return false;
5061 sint32 x = (sint32)(c->getX() / 1000);
5062 sint32 y = (sint32)(c->getY() / 1000);
5064 sint32 min_x;
5065 sint32 min_y;
5066 sint32 max_x;
5067 sint32 max_y;
5070 NLMISC::fromString(command_args[1], min_x);
5071 NLMISC::fromString(command_args[2], min_y);
5072 NLMISC::fromString(command_args[3], max_x);
5073 NLMISC::fromString(command_args[4], max_y);
5075 nlinfo("x = %d, y = %d", x, y);
5076 nlinfo("min_x = %d, min_y = %d", min_x, min_y);
5077 nlinfo("max_x = %d, max_y = %d", max_x, max_y);
5078 if ((x < min_x || y < min_y || x > max_x || y > max_y))
5080 if (send_url)
5081 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_position");
5082 return false;
5086 //*************************************************
5087 //***************** check_fame
5088 //*************************************************
5089 else if (command_args[0] == "check_fame")
5091 if (command_args.size () != 4) return false;
5093 uint32 factionIndex = CStaticFames::getInstance().getFactionIndex(command_args[1]);
5094 if (factionIndex == CStaticFames::INVALID_FACTION_INDEX)
5095 return false;
5096 sint32 fame = CFameInterface::getInstance().getFameIndexed(c->getId(), factionIndex);
5098 sint32 value;
5099 NLMISC::fromString(command_args[3], value);
5100 value = value*6000;
5102 nlinfo("fame = %d, value = %d", fame, value);
5104 if ((command_args[2] != "below" && command_args[2] != "above"))
5105 return false;
5107 if ((command_args[2] == "below" && fame > value) || (command_args[2] == "above" && fame < value))
5109 if (send_url)
5110 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_fame");
5111 return false;
5116 //*************************************************
5117 //***************** set_fame (need x6000 to change 1 point)
5118 //*************************************************
5119 else if (command_args[0] == "change_fame")
5121 if (command_args.size () < 4) return false;
5123 uint32 factionIndex = CStaticFames::getInstance().getFactionIndex(command_args[1]);
5124 if (factionIndex == CStaticFames::INVALID_FACTION_INDEX)
5125 return false;
5126 sint32 fame = CFameInterface::getInstance().getFameIndexed(c->getId(), factionIndex);
5128 sint32 value;
5129 NLMISC::fromString(command_args[3], value);
5131 if (command_args[2] == "add")
5133 CFameManager::getInstance().setEntityFame(c->getId(), factionIndex, fame+value, false);
5134 nlinfo("fame : %d => %d", fame, fame+value);
5136 else if (command_args[2] == "del")
5138 CFameManager::getInstance().setEntityFame(c->getId(), factionIndex, fame-value, false);
5139 nlinfo("fame : %d => %d", fame, fame-value);
5141 else if (command_args[2] == "set")
5143 CFameManager::getInstance().setEntityFame(c->getId(), factionIndex, value, false);
5144 nlinfo("fame : %d => %d", fame, value);
5147 if (command_args.size() == 4 || (command_args.size () == 5 && command_args[4] != "0"))
5149 // Make sure fame values are properly capped.
5150 CFameManager::getInstance().enforceFameCaps(c->getId(), c->getOrganization(), c->getAllegiance());
5152 // set tribe fame threshold and clamp fame if necessary
5153 CFameManager::getInstance().setAndEnforceTribeFameCap(c->getId(), c->getOrganization(), c->getAllegiance());
5157 //*************************************************
5158 //***************** check_target
5159 //*************************************************
5160 else if (command_args[0] == "check_target")
5162 const CEntityId &target = c->getTarget();
5164 if (command_args.size () < 2) return false;
5166 if (command_args[1] == "leaguemate")
5168 if (target == CEntityId::Unknown || target.getType() != RYZOMID::player)
5170 if (send_url)
5171 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_type");
5172 return false;
5174 CCharacter * targetTarget = dynamic_cast<CCharacter*>(CEntityBaseManager::getEntityBasePtr(target));
5175 if (targetTarget->getLeagueId() == DYN_CHAT_INVALID_CHAN || c->getLeagueId() != targetTarget->getLeagueId())
5177 if (send_url)
5178 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_league");
5179 return false;
5182 else if (command_args[1] == "guildmate")
5184 if (target == CEntityId::Unknown || target.getType() != RYZOMID::player)
5186 if (send_url)
5187 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_type");
5188 return false;
5190 CCharacter * targetTarget = dynamic_cast<CCharacter*>(CEntityBaseManager::getEntityBasePtr(target));
5191 if (targetTarget->getGuildId() == 0 || c->getGuildId() != targetTarget->getGuildId())
5193 if (send_url)
5194 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_guild");
5195 return false;
5198 else if (command_args[1] == "teammate")
5200 if (target == CEntityId::Unknown || target.getType() != RYZOMID::player)
5202 if (send_url)
5203 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_type");
5204 return false;
5206 CCharacter * targetTarget = dynamic_cast<CCharacter*>(CEntityBaseManager::getEntityBasePtr(target));
5207 if (targetTarget->getTeamId() == CTEAM::InvalidTeamId || c->getTeamId() != targetTarget->getTeamId())
5209 if (send_url)
5210 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_team");
5211 return false;
5215 if (command_args.size () < 3) return false;
5217 if (command_args[1] == "sheet")
5219 CSheetId creatureSheetId(command_args[2]);
5220 CCreature *creature = CreatureManager.getCreature(target);
5222 if (creature == NULL || creatureSheetId == CSheetId::Unknown || creatureSheetId != creature->getType())
5224 if (send_url)
5225 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_sheet");
5226 return false;
5229 else if (command_args[1] == "bot_name")
5231 if (target == CEntityId::Unknown || target.getType() == RYZOMID::player)
5233 if (send_url)
5234 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_type");
5235 return false;
5237 vector<TAIAlias> aliases;
5238 CAIAliasTranslator::getInstance()->getNPCAliasesFromName(command_args[2], aliases);
5240 bool found = false;
5241 for(uint k = 0; k < aliases.size(); ++k)
5243 const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId(aliases[k]);
5244 if (botId != CEntityId::Unknown && botId == target)
5246 found = true;
5249 if (!found)
5251 if (send_url)
5252 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_bot");
5253 return false;
5256 else if (command_args[1] == "player_name")
5258 if (target == CEntityId::Unknown || target.getType() != RYZOMID::player)
5260 if (send_url)
5261 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_type");
5262 return false;
5264 CEntityBase *entityBase = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), command_args[2]));
5265 if (entityBase == NULL)
5267 if (send_url)
5268 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_player");
5269 return false;
5271 } else
5272 return false;
5275 //*************************************************
5276 //***************** check_brick
5277 //*************************************************
5278 else if (command_args[0] == "check_brick")
5280 if (command_args.size () != 2) return false;
5282 if (!c->haveBrick(CSheetId(command_args[1])))
5284 if (send_url)
5285 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_brick");
5286 return false;
5290 //*************************************************
5291 //***************** set_brick
5292 //*************************************************
5293 else if (command_args[0] == "set_brick")
5295 if (command_args.size () != 3) return false;
5297 if (command_args[1] == "add")
5299 c->addKnownBrick(CSheetId(command_args[2]));
5301 else if (command_args[1] == "del")
5303 c->removeKnownBrick(CSheetId(command_args[2]));
5305 else
5307 if (send_url)
5308 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_brick_action");
5309 return false;
5313 //*************************************************
5314 //***************** check_item
5315 //*************************************************
5316 else if (command_args[0] == "check_item" || command_args[0] == "check_no_item") // sheetid ! quality ! quantity ! inv ! iscrafted ! customName
5318 if (command_args.size() < 4)
5319 return false;
5321 const CSheetId sheetId(command_args[1]);
5322 if (sheetId == CSheetId::Unknown)
5323 return false;
5324 const uint32 quality = (uint32)atoi(command_args[2].c_str());
5325 if (quality == 0)
5326 return false;
5327 const uint32 quantity = (uint32)atoi(command_args[3].c_str());
5328 if (quantity == 0)
5329 return false;
5331 string selected_inv = "bag";
5332 if (command_args.size() == 5)
5333 selected_inv = command_args[4];
5334 CInventoryPtr inventory = getInv(c, selected_inv);
5336 if (inventory == NULL)
5338 if (send_url)
5339 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=bad_inventory");
5340 return false;
5343 bool crafted = false;
5344 if (command_args.size() == 6)
5345 crafted = (command_args[5] == "1");
5347 ucstring needCustomName;
5348 if (command_args.size() == 7)
5349 needCustomName.fromUtf8(command_args[6]);
5351 uint32 numberItem = 0;
5352 for( uint32 i = 0; i < inventory->getSlotCount(); ++ i)
5354 const CGameItemPtr itemPtr = inventory->getItem(i);
5355 if( itemPtr != NULL )
5357 if( (itemPtr->getSheetId() == sheetId) && (itemPtr->quality() == quality) )
5359 if (!crafted || itemPtr->getCreator() == c->getId())
5361 // deprecated
5362 //if (needCustomName.empty() || itemPtr->getCustomName() == needCustomName)
5364 numberItem += itemPtr->getStackSize();
5371 if (numberItem < quantity)
5373 if (command_args[0] == "check_item")
5375 if (send_url)
5376 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_items");
5377 return false;
5380 else
5382 if (command_args[0] == "check_no_item")
5384 if (send_url)
5385 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=have_items");
5386 return false;
5391 //*************************************************
5392 //***************** check_outpost
5393 //*************************************************
5394 else if (command_args[0] == "check_outpost")
5396 if (command_args.size() != 3)
5397 return false;
5399 CSmartPtr<COutpost> outpost;
5400 TAIAlias outpostAlias = CPrimitivesParser::aliasFromString(command_args[1]);
5401 outpost = COutpostManager::getInstance().getOutpostFromAlias(outpostAlias);
5402 if (outpost == NULL)
5404 CSheetId outpostSheet(command_args[1]);
5405 outpost = COutpostManager::getInstance().getOutpostFromSheet(outpostSheet);
5408 if (outpost == NULL)
5410 return false;
5413 if ((command_args[2] != "attacker") && (command_args[2] != "defender") && (command_args[2] != "attack") && (command_args[2] != "defend"))
5414 return false;
5416 nlinfo("oupost name : %s, State : %s, Owner : %d, Attacker = %d", outpost->getName().c_str(), outpost->getStateName().c_str(), outpost->getOwnerGuild(), outpost->getAttackerGuild() );
5417 if ((command_args[2] == "attacker" && (outpost->getAttackerGuild() == 0 || outpost->getAttackerGuild() != c->getGuildId())) ||
5418 (command_args[2] == "defender" && (outpost->getOwnerGuild() == 0 || outpost->getOwnerGuild() != c->getGuildId())) ||
5419 (command_args[2] == "attack" && outpost->getState() != OUTPOSTENUMS::AttackRound) ||
5420 (command_args[2] == "defend" && outpost->getState() != OUTPOSTENUMS::DefenseRound))
5422 if (send_url)
5423 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc="+command_args[2]);
5424 return false;
5428 //*************************************************
5429 //***************** create_group
5430 //*************************************************
5431 else if (command_args[0] == "create_group")
5433 if (command_args.size () < 3) return false;
5435 uint32 instanceNumber = c->getInstanceNumber();
5436 sint32 x = c->getX();
5437 sint32 y = c->getY();
5438 sint32 z = c->getZ();
5439 sint32 orientation = 6666; // used to specify a random orientation
5441 uint32 nbBots;
5442 fromString(command_args[1], nbBots);
5443 if (nbBots<=0)
5445 log.displayNL("invalid bot count");
5446 return false;
5449 NLMISC::CSheetId sheetId(command_args[2]);
5450 if (sheetId == NLMISC::CSheetId::Unknown)
5451 sheetId = command_args[2] + ".creature";
5452 if (sheetId == NLMISC::CSheetId::Unknown)
5453 return true;
5455 double dispersionRadius = 10.;
5456 if (command_args.size()>3)
5458 fromString(command_args[3], dispersionRadius);
5459 if (dispersionRadius < 0.)
5460 return true;
5463 bool spawnBots = true;
5465 if (command_args.size()>4)
5467 if (command_args[4] == "self")
5469 orientation = (sint32)(c->getHeading() * 1000.0);
5471 else if (command_args[4] != "random")
5473 NLMISC::fromString(command_args[4], orientation);
5474 orientation = (sint32)((double)orientation / 360.0 * (NLMISC::Pi * 2.0) * 1000.0);
5478 string botsName;
5479 if (command_args.size()>5) botsName = command_args[5];
5480 if (botsName == "*")
5481 botsName.clear();
5483 if (command_args.size() > 7)
5486 if (command_args[6] != "*") {
5487 float userX;
5488 NLMISC::fromString(command_args[6], userX);
5489 x = (sint32)(userX * 1000.0);
5492 if (command_args[7] != "*") {
5493 float userY;
5494 NLMISC::fromString(command_args[7], userY);
5495 y = (sint32)(userY * 1000.0);
5499 if (command_args.size() > 8)
5501 if (command_args[8] != "*") {
5502 NLMISC::fromString(command_args[8], z);
5506 std::string look;
5507 if (command_args.size() > 9)
5509 if (command_args[9] != "*")
5511 look = command_args[9];
5512 if (look.find(".creature") == string::npos)
5513 look += ".creature";
5517 //[[inVillage=0/1][inOutpost=0/1][inStable=0/1][InAtys=0/1]]
5518 std::string validation;
5519 if (command_args.size() > 10)
5521 validation = command_args[10];
5522 if (validation.length() == 4)
5524 bool inVillage = validation[0] == '1';
5525 bool inOutpost = validation[1] == '1';
5526 bool inStable = validation[2] == '1';
5527 bool inAtys = validation[3] == '1';
5529 if (!c->isSpawnValid(inVillage, inOutpost, inStable, inAtys))
5530 return false;
5535 // See if another AI instance has been specified
5536 if ( ! getAIInstanceFromGroupName(botsName, instanceNumber))
5538 return false;
5541 TDataSetRow dsr = c->getEntityRowId();
5542 CMirrorPropValueRO<TYPE_CELL> srcCell( TheDataset, dsr, DSPropertyCELL );
5543 sint32 cell = srcCell;
5545 CEntityId playerId = c->getId();
5547 CMessage msgout("EVENT_CREATE_NPC_GROUP");
5548 uint32 messageVersion = 1;
5549 msgout.serial(messageVersion);
5550 msgout.serial(instanceNumber);
5551 msgout.serial(playerId);
5552 msgout.serial(x);
5553 msgout.serial(y);
5554 msgout.serial(z);
5555 msgout.serial(orientation);
5556 msgout.serial(nbBots);
5557 msgout.serial(sheetId);
5558 msgout.serial(dispersionRadius);
5559 msgout.serial(spawnBots);
5560 msgout.serial(botsName);
5561 msgout.serial(look);
5562 msgout.serial(cell);
5563 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
5566 //*************************************************
5567 //***************** group_script
5568 //*************************************************
5570 else if (command_args[0] == "group_script")
5572 if (command_args.size () < 3) return false;
5574 uint32 instanceNumber = c->getInstanceNumber();
5575 uint32 nbString = (uint32)command_args.size();
5577 // See if it needs another AI instance
5578 string botsName = command_args[1];
5579 if ( ! getAIInstanceFromGroupName(botsName, instanceNumber))
5581 return false;
5584 CMessage msgout("EVENT_NPC_GROUP_SCRIPT");
5585 uint32 messageVersion = 1;
5586 msgout.serial(messageVersion);
5587 msgout.serial(nbString);
5589 string command = command_args[0];
5590 msgout.serial(command);
5591 msgout.serial(botsName);
5592 for (uint32 i=2; i<nbString; ++i)
5594 string arg = command_args[i]+";";
5596 size_t pos = 0;
5597 while((pos = arg.find("&nbsp&", pos)) != string::npos)
5599 arg.replace(pos, 6, " ");
5600 pos ++;
5602 pos = 0;
5603 while((pos = arg.find("_NBSP_", pos)) != string::npos)
5605 arg.replace(pos, 6, " ");
5606 pos ++;
5608 pos = 0;
5609 while((pos = arg.find("__OR__", pos)) != string::npos)
5611 arg.replace(pos, 6, "|");
5612 pos ++;
5614 msgout.serial(arg);
5616 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
5619 //*************************************************
5620 //***************** change_hair
5621 //*************************************************
5623 else if (command_args[0] == "change_hair")
5625 if (command_args.size () != 3) return false;
5627 CCharacter *target = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), command_args[1]));
5629 CSheetId sheetId(command_args[2]);
5631 const CStaticItem * form = CSheets::getForm(sheetId);
5632 if (form == NULL)
5634 nlwarning("unknown item : '%s'", sheetId.toString().c_str());
5635 return true;
5638 if (form->Type != ITEM_TYPE::HAIR_MALE && form->Type != ITEM_TYPE::HAIR_FEMALE)
5640 nlwarning("'%s' is not a haircut item", sheetId.toString().c_str());
5641 return true;
5644 uint32 hairValue = CVisualSlotManager::getInstance()->sheet2Index(form->SheetId, SLOTTYPE::HEAD_SLOT);
5645 if (target->setHair(hairValue))
5647 target->resetHairCutDiscount();
5651 //*************************************************
5652 //***************** change_hair_color
5653 //*************************************************
5655 else if (command_args[0] == "change_hair_color") {
5656 if (command_args.size () != 3) return false;
5658 CCharacter *target = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), command_args[1]));
5660 uint32 value;
5661 fromString(command_args[2], value);
5662 if (target)
5663 target->setHairColor(value);
5664 else
5665 return false;
5668 //*************************************************
5669 //***************** change_vpx
5670 //*************************************************
5672 else if (command_args[0] == "change_vpx")
5674 if (command_args.size () != 4) return false;
5676 CCharacter *target = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), command_args[1]));
5678 string name = command_args[2];
5680 uint32 value;
5681 fromString(command_args[3], value);
5683 if(target && target->getEnterFlag())
5685 if( name == string("Sex") )
5687 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.Sex, value );
5689 else if( name == string("HatModel") )
5691 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.HatModel, value );
5693 else if( name == string("HatColor") )
5695 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.HatColor, value );
5697 else if( name == string("JacketModel") )
5699 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.JacketModel, value );
5701 else if( name == string("JacketColor") )
5703 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.JacketColor, value );
5705 else if( name == string("TrouserModel") )
5707 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.TrouserModel, value );
5709 else if( name == string("TrouserColor") )
5711 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.TrouserColor, value );
5713 else if( name == string("WeaponRightHand") )
5715 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.WeaponRightHand, value );
5717 else if( name == string("WeaponLeftHand") )
5719 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.WeaponLeftHand, value );
5721 else if( name == string("ArmModel") )
5723 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.ArmModel, value );
5725 else if( name == string("ArmColor") )
5727 SET_STRUCT_MEMBER( target->getVisualPropertyA(), PropertySubData.ArmColor, value );
5729 else if( name == string("HandsModel") )
5731 SET_STRUCT_MEMBER( target->getVisualPropertyB(), PropertySubData.HandsModel, value );
5733 else if( name == string("HandsColor") )
5735 SET_STRUCT_MEMBER( target->getVisualPropertyB(), PropertySubData.HandsColor, value );
5737 else if( name == string("FeetModel") )
5739 SET_STRUCT_MEMBER( target->getVisualPropertyB(), PropertySubData.FeetModel, value );
5741 else if( name == string("FeetColor") )
5743 SET_STRUCT_MEMBER( target->getVisualPropertyB(), PropertySubData.FeetColor, value );
5745 else if( name == string("MorphTarget1") )
5747 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget1, value );
5749 else if( name == string("MorphTarget2") )
5751 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget2, value );
5753 else if( name == string("MorphTarget3") )
5755 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget3, value );
5757 else if( name == string("MorphTarget4") )
5759 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget4, value );
5761 else if( name == string("MorphTarget5") )
5763 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget5, value );
5765 else if( name == string("MorphTarget6") )
5767 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget6, value );
5769 else if( name == string("MorphTarget7") )
5771 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget7, value );
5773 else if( name == string("MorphTarget8") )
5775 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.MorphTarget8, value );
5777 else if( name == string("EyesColor") )
5779 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.EyesColor, value );
5781 else if( name == string("Tattoo") )
5783 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.Tattoo, value );
5785 else if( name == string("CharacterHeight") )
5787 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.CharacterHeight, value );
5789 else if( name == string("TorsoWidth") )
5791 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.TorsoWidth, value );
5793 else if( name == string("ArmsWidth") )
5795 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.ArmsWidth, value );
5797 else if( name == string("LegsWidth") )
5799 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.LegsWidth, value );
5801 else if( name == string("BreastSize") )
5803 SET_STRUCT_MEMBER( target->getVisualPropertyC(), PropertySubData.BreastSize, value );
5806 else
5808 if (send_url)
5809 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_vpx_def");
5812 //*************************************************
5813 //***************** set_title
5814 //*************************************************
5815 // /a webExecCommand debug 1 set_title!#toto# hmac 0
5816 else if (command_args[0] == "set_title")
5818 if (command_args.size () != 2) return false;
5819 TDataSetRow row = c->getEntityRowId();
5820 c->setNewTitle(command_args[1]);
5821 string fullname = c->getName().toString()+"$"+command_args[1]+"#"+c->getTagPvPA()+"#"+c->getTagPvPB()+"#"+c->getTagA()+"#"+c->getTagB()+"$";
5822 ucstring name;
5823 name.fromUtf8(fullname);
5824 NLNET::CMessage msgout("CHARACTER_NAME");
5825 msgout.serial(row);
5826 msgout.serial(name);
5827 sendMessageViaMirror("IOS", msgout);
5830 //*************************************************
5831 //***************** rename
5832 //*************************************************
5833 // /a webExecCommand debug 1 rename!moondev!ulukyndev hmac 0
5834 else if (command_args[0] == "rename")
5836 if (command_args.size () != 3) return false;
5837 string arg = command_args[1]+" "+command_args[2];
5838 const CAdminCommand * cmd = findAdminCommand("renamePlayer");
5839 if (!cmd->ForwardToservice.empty())
5841 // we need to forward the command to another service
5842 if (IClientCommandForwader::getInstance())
5844 IClientCommandForwader::getInstance()->sendCommand(cmd->ForwardToservice, "renamePlayer", c->getId(), false, CEntityId::Unknown, arg);
5849 //*************************************************
5850 //***************** set_tag
5851 //*************************************************
5853 else if (command_args[0] == "set_tag") {
5854 if (command_args.size () != 3) return false;
5855 TDataSetRow row = c->getEntityRowId();
5856 if (command_args[1] == "pvpA") c->setTagPvPA(command_args[2]);
5857 if (command_args[1] == "pvpB") c->setTagPvPB(command_args[2]);
5858 if (command_args[1] == "A") c->setTagA(command_args[2]);
5859 if (command_args[1] == "B") c->setTagB(command_args[2]);
5860 string fullname = c->getName().toString()+"$"+c->getNewTitle()+"#"+c->getTagPvPA()+"#"+c->getTagPvPB()+"#"+c->getTagA()+"#"+c->getTagB()+"$";
5861 ucstring name;
5862 name.fromUtf8(fullname);
5863 NLNET::CMessage msgout("CHARACTER_NAME");
5864 msgout.serial(row);
5865 msgout.serial(name);
5866 sendMessageViaMirror("IOS", msgout);
5869 //*************************************************
5870 //***************** teleport
5871 //*************************************************
5873 else if (command_args[0] == "teleport") // teleport![x,y,z|player name|bot name]!teleport mektoub?!checks!Same Cell?
5875 if (command_args.size () < 2) return false;
5877 // Checks : PvP Flag, PvP Tag, Sitting, Water, Mount, Fear, Sleep, Invu, Stun
5878 if (command_args.size () > 3)
5880 bool pvpFlagValid = (c->getPvPRecentActionFlag() == false || c->getPVPFlag() == false);
5881 if (command_args[3][0] == '1' && !pvpFlagValid) {
5882 CCharacter::sendDynamicSystemMessage(c->getEntityRowId(), "PVP_TP_FORBIDEN");
5883 return true;
5886 bool pvpTagValid = c->getPVPFlag() == false;
5887 if (command_args[3].length() > 1 && command_args[3][1] == '1' && !pvpTagValid)
5889 CCharacter::sendDynamicSystemMessage(c->getEntityRowId(), "PVP_TP_FORBIDEN");
5890 return true;
5893 if (command_args[3].length() > 2)
5895 CBypassCheckFlags bypassCheckFlags;
5896 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::WhileSitting, command_args[3].length() > 2 && command_args[3][2] == '1');
5897 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::InWater, command_args[3].length() > 3 && command_args[3][3] == '1');
5898 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::OnMount, command_args[3].length() > 4 && command_args[3][4] == '1');
5899 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::Fear, command_args[3].length() > 5 && command_args[3][5] == '1');
5900 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::Sleep, command_args[3].length() > 6 && command_args[3][6] == '1');
5901 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::Invulnerability, command_args[3].length() > 7 && command_args[3][7] == '1');
5902 bypassCheckFlags.setFlag(CHECK_FLAG_TYPE::Stun, command_args[3].length() > 8 && command_args[3][8] == '1');
5904 if (!c->canEntityUseAction(bypassCheckFlags, true))
5905 return true;
5909 string value = command_args[1];
5911 vector<string> res;
5912 sint32 x = 0, y = 0, z = 0;
5913 float h = 0;
5914 sint32 cell;
5915 if ( value.find(',') != string::npos ) // Position x,y,z,a
5917 explode (value, string(","), res);
5918 if (res.size() >= 2)
5920 fromString(res[0], x);
5921 x *= 1000;
5922 fromString(res[1], y);
5923 y *= 1000;
5925 if (res.size() >= 3)
5927 fromString(res[2], z);
5928 z *= 1000;
5930 if (res.size() >= 4)
5931 fromString(res[3], h);
5933 else
5935 if ( value.find(".creature") != string::npos )
5937 CSheetId creatureSheetId(value);
5938 if( creatureSheetId != CSheetId::Unknown )
5940 double minDistance = -1.;
5941 CCreature * creature = NULL;
5943 TMapCreatures::const_iterator it;
5944 const TMapCreatures& creatures = CreatureManager.getCreature();
5945 for( it = creatures.begin(); it != creatures.end(); ++it )
5947 CSheetId sheetId = (*it).second->getType();
5948 if( sheetId == creatureSheetId )
5950 double distance = PHRASE_UTILITIES::getDistance( c->getEntityRowId(), (*it).second->getEntityRowId() );
5951 if( !creature || (creature && distance < minDistance) )
5953 creature = (*it).second;
5954 minDistance = distance;
5958 if( creature )
5960 x = creature->getState().X();
5961 y = creature->getState().Y();
5962 z = creature->getState().Z();
5963 h = creature->getState().Heading();
5966 else
5968 nlwarning ("<Position> '%s' is an invalid creature", value.c_str());
5971 else
5974 CEntityBase *entityBase = PlayerManager.getCharacterByName (CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), value));
5975 if (entityBase == NULL)
5977 // try to find the bot name
5978 vector<TAIAlias> aliases;
5979 CAIAliasTranslator::getInstance()->getNPCAliasesFromName( value, aliases );
5980 if ( aliases.empty() )
5982 nldebug ("<Position> Ignoring attempt to teleport because no NPC found matching name '%s'", value.c_str());
5983 return true;
5986 TAIAlias alias = aliases[0];
5988 const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId (alias);
5989 if ( botId != CEntityId::Unknown )
5991 entityBase = CreatureManager.getCreature (botId);
5993 else
5995 nlwarning ("'%s' has no eId. Is it Spawned???", value.c_str());
5996 return true;
6000 if (entityBase != NULL)
6002 x = entityBase->getState().X + sint32 (cos (entityBase->getState ().Heading) * 2000);
6003 y = entityBase->getState().Y + sint32 (sin (entityBase->getState ().Heading) * 2000);
6004 z = entityBase->getState().Z;
6005 h = entityBase->getState().Heading;
6007 TDataSetRow dsr = entityBase->getEntityRowId();
6008 CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, dsr, DSPropertyCELL );
6009 cell = mirrorCell;
6014 if (x == 0 && y == 0 && z == 0)
6016 nlwarning ("'%s' is a bad value for position, don't change position", value.c_str());
6017 return true;
6020 CContinent * cont = CZoneManager::getInstance().getContinent(x,y);
6022 bool allowPetTp = false;
6023 if (command_args.size () > 2 && command_args[2] == "1")
6024 allowPetTp = true;
6026 if (allowPetTp)
6027 c->allowNearPetTp();
6028 else
6029 c->forbidNearPetTp();
6031 // Respawn player if dead
6032 if (c->isDead())
6034 PROGRESSIONPVP::CCharacterProgressionPVP::getInstance()->playerRespawn(c);
6035 // apply respawn effects because user is dead
6036 c->applyRespawnEffects();
6039 // Use same Cell
6040 if (command_args.size () > 4 && command_args[4] == "1")
6042 TDataSetRow dsr = c->getEntityRowId();
6043 CMirrorPropValueRO<TYPE_CELL> mirrorCell( TheDataset, dsr, DSPropertyCELL );
6044 cell = mirrorCell;
6047 c->teleportCharacter(x,y,z,allowPetTp,true,h,0xFF,cell);
6049 if ( cont )
6051 c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(cont->getId()) );
6055 //*************************************************
6056 //***************** slide
6057 //*************************************************
6058 else if (command_args[0] == "slide") // x,y,z,a!building![player name|guild name]!teleport mektoub?
6060 if (command_args.size () < 4) return false;
6062 nlinfo("ok");
6063 string value = command_args[1];
6064 vector<string> res;
6065 sint32 x = c->getState().X();
6066 sint32 y = c->getState().Y();
6067 sint32 z = c->getState().Z();
6068 float h = c->getState().Heading();
6069 sint32 cell;
6070 if ( value.find(',') != string::npos ) // Position x,y,z,a
6072 explode (value, string(","), res);
6073 if (res.size() >= 2)
6075 fromString(res[0], x);
6076 x *= 1000;
6077 fromString(res[1], y);
6078 y *= 1000;
6080 if (res.size() >= 3)
6082 fromString(res[2], z);
6083 z *= 1000;
6085 if (res.size() >= 4)
6086 fromString(res[3], h);
6089 bool allowPetTp = false;
6090 if (command_args.size() > 4 && command_args[4] == "1")
6091 allowPetTp = true;
6093 if (allowPetTp)
6094 c->allowNearPetTp();
6095 else
6096 c->forbidNearPetTp();
6098 IBuildingPhysical * building = CBuildingManager::getInstance()->getBuildingPhysicalsByName(command_args[2]);
6099 if ( building )
6102 if (building->getTemplate()->Type == BUILDING_TYPES::Player)
6105 /*TDataSetRow dsr = c->getEntityRowId();
6106 CMirrorPropValueRO<TYPE_CELL> srcCell( TheDataset, dsr, DSPropertyCELL );
6107 sint32 cell = srcCell;*/
6109 /*if (cell >= 0)
6111 CBuildingPhysicalPlayer * buildingPlayer = dynamic_cast<CBuildingPhysicalPlayer *>( building );
6113 CEntityBase *entityBase = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), command_args[3]));
6114 if (buildingPlayer && entityBase)
6116 CBuildingManager::getInstance()->removePlayerFromRoom( c );
6117 uint16 ownerId = buildingPlayer->getOwnerIdx( entityBase->getId() );
6118 nlinfo("Gettting ownerId : %d", ownerId);
6120 buildingPlayer->addUser(c, 0, ownerId, cell);
6122 //CBuildingManager::getInstance()->setRoomLifeTime(cell, TGameCycle(NLMISC::TGameTime(4*60*60) / CTickEventHandler::getGameTimeStep()));
6123 nlinfo("Gettting cell : %d", cell);
6124 c->teleportCharacter(x,y,z,allowPetTp,true,h,0xFF,cell);
6131 //*************************************************
6132 //***************** rename_animal
6133 //*************************************************
6134 else if (command_args[0] == "rename_animal")
6136 if (command_args.size () < 3) return false;
6138 uint petIndex = atoi( command_args[1].c_str() );
6139 ucstring customName = ucstring(command_args[2]);
6140 c->setAnimalName(petIndex, customName);
6143 //*************************************************
6144 //***************** organization
6145 //*************************************************
6146 else if (command_args[0] == "organization")
6148 if (command_args.size () < 3) return false;
6150 string action = command_args[1]; // change, add_points, set_status, add_status
6151 sint32 value;
6152 fromString(command_args[2], value);
6154 if (action == "change" && value >= 0)
6155 c->setOrganization((uint32)value);
6156 else if (action == "add_points")
6157 c->changeOrganizationPoints(value);
6158 else if (action == "set_status" && value >= 0)
6159 c->setOrganizationStatus(value);
6160 else if (action == "add_status")
6161 c->changeOrganizationStatus(value);
6164 //*************************************************
6165 //***************** buildings
6166 // /a webExecCommand debug 1 building!set_player_room!building_instance_ARCC_player_320 hmac 0
6167 //*************************************************
6168 else if (command_args[0] == "building")
6170 if (command_args.size() < 2) return false;
6172 string action = command_args[1]; // trigger_in, trigger_out, add_guild_room, add_player_room
6174 if (action == "trigger_in" && command_args.size () == 3)
6176 uint32 liftId = atoi(command_args[2].c_str());
6177 CBuildingManager::getInstance()->addTriggerRequest(c->getEntityRowId(), liftId);
6179 else if (action == "trigger_out")
6181 CBuildingManager::getInstance()->removeTriggerRequest(c->getEntityRowId());
6184 else if (action == "add_guild_room" && command_args.size () == 3)
6186 CBuildingPhysicalGuild * building = dynamic_cast<CBuildingPhysicalGuild *>(CBuildingManager::getInstance()->getBuildingPhysicalsByName(command_args[2]));
6187 if ( building )
6189 building->addGuild(c->getGuildId());
6192 else if (action == "add_player_room" && command_args.size () == 3)
6194 CBuildingPhysicalPlayer * building = dynamic_cast<CBuildingPhysicalPlayer *>(CBuildingManager::getInstance()->getBuildingPhysicalsByName(command_args[2]));
6195 if ( building )
6197 building->addPlayer(c->getId());
6200 else if (action == "buy_guild_room" && command_args.size () == 3)
6202 CBuildingPhysicalGuild * building = dynamic_cast<CBuildingPhysicalGuild *>(CBuildingManager::getInstance()->getBuildingPhysicalsByName(command_args[2]));
6203 if ( building )
6205 CGuild * guild = CGuildManager::getInstance()->getGuildFromId(c->getGuildId());
6206 if (guild != NULL)
6208 guild->setBuilding(building->getAlias());
6212 else if (action == "buy_player_room" && command_args.size () == 3)
6214 CBuildingPhysicalPlayer * building = dynamic_cast<CBuildingPhysicalPlayer *>(CBuildingManager::getInstance()->getBuildingPhysicalsByName(command_args[2]));
6215 if ( building )
6217 CBuildingManager::getInstance()->buyBuilding(c->getId(), building->getAlias());
6220 else if (action == "set_player_room" && command_args.size () == 3)
6222 CBuildingPhysicalPlayer * building = dynamic_cast<CBuildingPhysicalPlayer *>(CBuildingManager::getInstance()->getBuildingPhysicalsByName(command_args[2]));
6223 if ( building )
6225 c->getRoomInterface().setBuilding(building);
6226 building->addPlayer(c->getId());
6229 else if (action == "get_access_room" && command_args.size () == 3)
6232 CCharacter *owner = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), command_args[2]));
6233 if (owner)
6234 owner->addRoomAccessToPlayer(c->getId());
6238 //*************************************************
6239 //***************** Skill
6240 //*************************************************
6242 else if (command_args[0] == "skill")
6244 if (command_args.size() < 4) return false;
6246 string action = command_args[1]; // check, best, add_xp
6248 if (action == "check")
6250 SKILLS::ESkills skillEnum = SKILLS::toSkill( command_args[2] );
6251 uint32 wantedValue;
6252 fromString(command_args[3], wantedValue);
6254 if (c->getSkillValue(skillEnum) < wantedValue) {
6255 if (send_url)
6256 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_enough_skill");
6257 return true;
6260 else if (action == "best")
6262 SKILLS::ESkills skillEnum = SKILLS::toSkill( command_args[2] );
6263 uint32 wantedValue;
6264 fromString(command_args[3], wantedValue);
6266 if (c->getBestChildSkillValue(skillEnum) < wantedValue) {
6267 if (send_url)
6268 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_best_skill");
6269 return true;
6272 else if (action == "add_xp")
6274 double xp;
6275 fromString(command_args[3], xp);
6276 c->addXpToSkill(xp, command_args[2]);
6280 //*************************************************
6281 //***************** Dead
6282 //*************************************************
6284 else if (command_args[0] == "check_state")
6286 if (command_args.size() < 3) return false;
6288 string action = command_args[1]; // dead, alive, tag, flag
6290 if (action == "dead")
6292 if (!c->isDead()) {
6293 if (send_url)
6294 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=not_dead");
6295 return true;
6298 else if (action == "alive")
6300 if (c->isDead()) {
6301 if (send_url)
6302 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=not_alive");
6303 return true;
6306 else if (action == "tag")
6308 if (!c->getPVPFlag()) {
6309 if (send_url)
6310 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=not_tag");
6311 return true;
6314 else if (action == "flag")
6316 if (!c->getPvPRecentActionFlag()) {
6317 if (send_url)
6318 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=not_flag");
6319 return true;
6324 //*************************************************
6325 //***************** Money
6326 //*************************************************
6328 else if (command_args[0] == "money")
6330 if (command_args.size() < 3) return false;
6332 string action = command_args[1]; // check, give, spend
6334 if (action == "check")
6336 uint64 wantedMoney;
6337 fromString(command_args[2], wantedMoney);
6338 if (c->getMoney() < wantedMoney) {
6339 if (send_url)
6340 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_enough_money");
6341 return true;
6344 else if (action == "give")
6346 uint64 money;
6347 fromString(command_args[2], money);
6348 c->giveMoney(money);
6350 else if (action == "spend")
6352 uint64 money;
6353 fromString(command_args[2], money);
6354 c->spendMoney(money);
6358 //*************************************************
6359 //***************** Guild
6360 //*************************************************
6362 else if (command_args[0] == "guild")
6364 if (command_args.size() < 3) return false;
6366 CGuild * guild = CGuildManager::getInstance()->getGuildFromId(c->getGuildId());
6367 if (guild == NULL)
6369 if (send_url)
6370 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_guild");
6371 return true;
6374 string action = command_args[1]; // check, give, spend
6376 if (action == "check_money")
6378 uint64 wantedMoney;
6379 fromString(command_args[2], wantedMoney);
6380 if (guild->getMoney() < wantedMoney) {
6381 if (send_url)
6382 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_enough_money");
6383 return true;
6386 else if (action == "money_give")
6388 uint64 money;
6389 fromString(command_args[2], money);
6390 guild->addMoney(money);
6392 else if (action == "money_spend")
6394 uint64 money;
6395 fromString(command_args[2], money);
6396 guild->spendMoney(money);
6398 else if (action == "check_rank")
6400 CGuildMember * member = guild->getMemberFromEId(c->getId());
6401 if ( member == NULL )
6403 return false;
6406 EGSPD::CGuildGrade::TGuildGrade wanted_grade = EGSPD::CGuildGrade::fromString(command_args[2]);
6407 if (wanted_grade == EGSPD::CGuildGrade::Unknown)
6408 return false;
6410 EGSPD::CGuildGrade::TGuildGrade memberGrade = member->getGrade();
6411 if( memberGrade > wanted_grade)
6413 if (send_url)
6414 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_enough_rank");
6415 return true;
6421 //*************************************************
6422 //***************** Resets
6423 //*************************************************
6425 else if (command_args[0] == "reset")
6427 if (command_args.size() < 2) return false;
6429 string action = command_args[1]; // pvp, powers
6431 if (action == "pvp")
6433 c->resetPVPTimers();
6435 else if (action == "powers")
6437 c->resetPowerFlags();
6441 //*************************************************
6442 //***************** Faction Points
6443 //*************************************************
6445 else if (command_args[0] == "faction_points")
6447 if (command_args.size() < 4) return false;
6449 string action = command_args[1]; // check, set, add, remove
6452 PVP_CLAN::TPVPClan clan = PVP_CLAN::fromString(command_args[2]);
6453 if ((clan < PVP_CLAN::BeginClans) || (clan > PVP_CLAN::EndClans))
6455 return false;
6458 uint32 value;
6459 fromString(command_args[3], value);
6461 if (action=="check")
6463 if (c->getFactionPoint(clan) < value)
6465 if (send_url)
6466 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_enough_faction_points");
6467 return true;
6470 else if (action=="set")
6472 c->setFactionPoint(clan, value, true);
6474 else if (action=="add")
6476 c->setFactionPoint(clan, c->getFactionPoint(clan)+value, true);
6478 else if (action=="remove")
6480 if (c->getFactionPoint(clan) < value)
6481 c->setFactionPoint(clan, 0, true);
6482 else
6483 c->setFactionPoint(clan, c->getFactionPoint(clan)-value, true);
6487 //*************************************************
6488 //***************** Pvp Points
6489 //*************************************************
6491 else if (command_args[0] == "pvp_points")
6493 if (command_args.size() < 3) return false;
6495 string action = command_args[1]; // check, set, add, remove
6497 uint32 value;
6498 fromString(command_args[2], value);
6500 if (action=="check")
6502 if (c->getPvpPoint() < value)
6504 if (send_url)
6505 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=failed&desc=no_enough_pvp_points");
6506 return true;
6509 else if (action=="set")
6511 c->setPvpPoint(value);
6513 else if (action=="add")
6515 c->setPvpPoint(c->getPvpPoint()+value);
6517 else if (action=="remove")
6519 c->setPvpPoint(c->getPvpPoint()-value);
6523 //*************************************************
6524 //***************** ios
6525 //*************************************************
6527 else if (command_args[0] == "ios")
6530 if (command_args.size() < 4)
6531 return false;
6533 string action = command_args[1]; // single_phrase
6535 if (action == "single_phrase")
6537 string phraseName = command_args[2];
6538 ucstring phraseContent = phraseName;
6539 ucstring phraseText;
6540 phraseText.fromUtf8(command_args[3]);
6541 phraseContent += "(){[";
6542 phraseContent += phraseText;
6543 phraseContent += "]}";
6545 string msgname = "SET_PHRASE";
6546 bool withLang = false;
6547 string lang = "";
6548 if (command_args.size() == 5)
6550 lang = command_args[3];
6551 if (lang != "all")
6553 withLang = true;
6554 msgname = "SET_PHRASE_LANG";
6558 NLNET::CMessage msgout(msgname);
6559 msgout.serial(phraseName);
6560 msgout.serial(phraseContent);
6561 if (withLang)
6562 msgout.serial(lang);
6563 sendMessageViaMirror("IOS", msgout);
6564 return true;
6568 //*************************************************
6569 //***************** sendurl
6570 //*************************************************
6572 else if (command_args[0] == "sendurl")
6575 if (command_args.size() != 4)
6576 return false;
6578 string player = command_args[1]; // player
6579 string app = command_args[2]; // app
6580 string params = command_args[3]; // params
6581 CCharacter *destPlayer;
6583 if (player != "_target_") {
6584 CEntityBase *entityBase = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), player));
6585 destPlayer = dynamic_cast<CCharacter*>(CEntityBaseManager::getEntityBasePtr(entityBase->getId()));
6586 } else {
6587 const CEntityId &target = c->getTarget();
6588 destPlayer = dynamic_cast<CCharacter*>(CEntityBaseManager::getEntityBasePtr(target));
6590 if (destPlayer)
6591 destPlayer->sendUrl(app+" "+params);
6595 //*************************************************
6596 //***************** dt_bot
6597 // /a webExecCommand debug 1 dt_bot!bejc hmac 0
6598 //*************************************************
6600 /* else if (command_args[0] == "dt_bot")
6603 if (command_args.size() != 2)
6604 return false;
6606 string botname = command_args[1]; // bot_name
6607 vector<TAIAlias> aliases;
6609 CAIAliasTranslator::getInstance()->getNPCAliasesFromName( botname, aliases );
6610 if ( aliases.empty() )
6612 nldebug ("Bot not found '%s'", botname.c_str());
6613 return true;
6616 TAIAlias alias = aliases[0];
6618 const CEntityId & botId = CAIAliasTranslator::getInstance()->getEntityId (alias);
6619 if ( botId != CEntityId::Unknown )
6621 nlinfo("Openning window trad...");
6622 c->setDirectTradeNpc(botId);
6623 if ( !c->startDirectBotChat( BOTCHATTYPE::TradeItemFlag ) )
6625 nlinfo("failed !");
6626 return true;
6628 c->resetRawMaterialItemPartFilter();
6629 c->resetItemTypeFilter();
6630 c->refreshTradeList();
6631 nlinfo("done!");
6633 else
6635 nlwarning ("'%s' has no eId. Is it Spawned???", botname.c_str());
6636 return true;
6641 //*************************************************
6642 //***************** missions
6643 //*************************************************
6645 else if (command_args[0] == "mission") // Please set params before spawn mission
6647 if (command_args.size() < 3)
6648 return false;
6650 string action = command_args[1]; // spawn, set_params, add_param
6652 if (action == "spawn" && command_args.size() == 4)
6654 // try to find the bot name
6655 vector<TAIAlias> aliases;
6656 CAIAliasTranslator::getInstance()->getNPCAliasesFromName(command_args[2], aliases);
6657 if (aliases.empty())
6659 nldebug ("<spawn_mission> No NPC found matching name '%s'", command_args[2].c_str());
6660 return false;
6663 TAIAlias giverAlias = aliases[0];
6665 TAIAlias missionAlias = CAIAliasTranslator::getInstance()->getMissionUniqueIdFromName(command_args[3]);
6667 if (missionAlias == CAIAliasTranslator::Invalid)
6669 nldebug ("<addMissionByName> No Mission found matching name '%s'", command_args[3].c_str());
6670 return false;
6673 c->endBotChat();
6675 std::list< CMissionEvent* > eventList;
6676 CMissionManager::getInstance()->instanciateMission(c, missionAlias, giverAlias, eventList);
6677 c->processMissionEventList(eventList,true, CAIAliasTranslator::Invalid);
6679 else if (action == "remove")
6681 TAIAlias missionAlias = CAIAliasTranslator::getInstance()->getMissionUniqueIdFromName(command_args[2]);
6682 c->removeMission(missionAlias, 0);
6683 c->removeMissionFromHistories(missionAlias);
6685 else if (action == "finish")
6687 TAIAlias missionAlias = CAIAliasTranslator::getInstance()->getMissionUniqueIdFromName(command_args[2]);
6688 c->removeMission(missionAlias, 0, true);
6689 c->removeMissionFromHistories(missionAlias);
6691 else if (action == "add_compass" && command_args.size() == 4)
6693 TVectorParamCheck params(1);
6694 sint32 x = 0;
6695 sint32 y = 0;
6696 string msg;
6697 if (command_args[2] == "bot")
6699 vector<TAIAlias> aliases;
6700 CAIAliasTranslator::getInstance()->getNPCAliasesFromName(command_args[3], aliases);
6701 if (aliases.empty())
6702 return false;
6703 CCreature * bot = CreatureManager.getCreature(CAIAliasTranslator::getInstance()->getEntityId(aliases[0]));
6704 if (bot)
6706 x = bot->getState().X();
6707 y = bot->getState().Y();
6708 params[0].Type = STRING_MANAGER::bot;
6709 params[0].setEIdAIAlias( bot->getId(), aliases[0] );
6710 msg = "COMPASS_BOT";
6711 uint32 txt = STRING_MANAGER::sendStringToClient(c->getEntityRowId(), msg, params);
6712 PlayerManager.sendImpulseToClient(c->getId(), "JOURNAL:ADD_COMPASS_BOT", x, y, txt, bot->getEntityRowId().getCompressedIndex());
6715 else if (command_args[2] == "place")
6717 CPlace * place = CZoneManager::getInstance().getPlaceFromName(command_args[3]);
6718 if (place)
6720 x = place->getCenterX();
6721 y = place->getCenterY();
6723 params[0].Identifier = place->getName();
6724 params[0].Type = STRING_MANAGER::place;
6725 msg = "COMPASS_PLACE";
6726 uint32 txt = STRING_MANAGER::sendStringToClient(c->getEntityRowId(), msg, params);
6727 PlayerManager.sendImpulseToClient(c->getId(), "JOURNAL:ADD_COMPASS", x, y, txt);
6731 else if (action == "set_text" && command_args.size() >= 4)
6733 uint32 nbString = (uint32)command_args.size();
6734 string text = getStringFromHash(command_args[3]);
6736 for (uint32 i=4; i<nbString; ++i)
6737 text += "\n"+getStringFromHash(command_args[i]);
6738 c->setCustomMissionParams(command_args[2], text);
6740 else if (action == "set_params" && command_args.size() == 4)
6742 c->setCustomMissionParams(command_args[2], web_app_url+","+command_args[3]);
6744 else if (action == "add_params" && command_args.size() == 4)
6746 c->addCustomMissionParam(command_args[2], command_args[3]);
6749 else
6751 return false;
6754 if (!new_check)
6756 if (!c->havePriv(":DEV:") || (web_app_url != "debug"))
6758 string::size_type pos = infos[1].find(",");
6759 if (pos!=string::npos && pos!=(infos[1].length()-1))
6761 item->setCustomText(ucstring(infos[0]+"\n"+infos[1].substr(pos+1)));
6763 else
6765 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=finished");
6768 else
6770 if (save_index)
6772 c->validateWebCommandIndex(iindex);
6774 if (send_url)
6775 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=finished");
6778 else
6780 c->setWebCommandIndex(iindex);
6781 if (save_index)
6782 c->validateWebCommandIndex(iindex);
6783 if (send_url)
6784 c->sendUrl(web_app_url+"&player_eid="+c->getId().toString()+"&event=finished");
6787 return true;
6790 //----------------------------------------------------------------------------
6791 ENTITY_VARIABLE (PriviledgePVP, "Priviledge Pvp Mode")
6793 ENTITY_GET_CHARACTER
6795 if (get)
6797 value = c->priviledgePVP()?"1":"0";
6799 else
6801 if (value=="1" || value=="on" || strlwr(value)=="pvp" || strlwr(value)=="true" )
6802 c->setPriviledgePVP(true);
6803 else if (value=="0" || value=="off" || strlwr(value)=="false" )
6804 c->setPriviledgePVP(false);
6805 // c->setPVPRecentActionFlag();
6806 CPVPManager2::getInstance()->setPVPModeInMirror(c);
6807 nlinfo ("%s %s now in pvp mode", entity.toString().c_str(), c->priviledgePVP()?"is":"isn't");
6811 //----------------------------------------------------------------------------
6812 ENTITY_VARIABLE (FullPVP, "Full Pvp Mode")
6814 ENTITY_GET_CHARACTER
6816 if (get)
6818 value = c->getFullPVP()?"1":"0";
6820 else
6822 if (value=="1" || value=="on" || toLowerAscii(value)=="pvp" || toLowerAscii(value)=="true" )
6823 c->setFullPVP(true);
6824 else if (value=="0" || value=="off" || toLowerAscii(value)=="false" )
6825 c->setFullPVP(false);
6826 // c->setPVPRecentActionFlag();
6827 CPVPManager2::getInstance()->setPVPModeInMirror(c);
6828 nlinfo ("%s %s now in pvp mode", entity.toString().c_str(), c->getFullPVP()?"is":"isn't");
6832 //----------------------------------------------------------------------------
6833 NLMISC_COMMAND(addPosFlag, "add a new position flag", "<csr_eid> <flag_name>")
6835 if (args.size() != 2)
6836 return false;
6837 GET_CHARACTER
6839 const string & flagName = args[1];
6840 if (CPositionFlagManager::getInstance().flagExists(flagName))
6842 CCharacter::sendDynamicSystemMessage(eid, "CSR_POS_FLAG_EXISTS");
6843 return false;
6846 CFlagPosition flagPos( c->getState().X()/1000, c->getState().Y()/1000, c->getState().Z()/1000 );
6847 CPositionFlagManager::getInstance().setFlag(flagName, flagPos);
6848 CPositionFlagManager::getInstance().saveToFile(PositionFlagsFileName);
6850 return true;
6853 //----------------------------------------------------------------------------
6854 NLMISC_COMMAND(setPosFlag, "set a position flag", "<csr_eid> <flag_name>")
6856 if (args.size() != 2)
6857 return false;
6858 GET_CHARACTER
6860 const string & flagName = args[1];
6861 if (!CPositionFlagManager::getInstance().flagExists(flagName))
6863 CCharacter::sendDynamicSystemMessage(eid, "CSR_POS_FLAG_NOT_EXISTS");
6864 return false;
6867 CFlagPosition flagPos( c->getState().X()/1000, c->getState().Y()/1000, c->getState().Z()/1000 );
6868 CPositionFlagManager::getInstance().setFlag(flagName, flagPos);
6869 CPositionFlagManager::getInstance().saveToFile(PositionFlagsFileName);
6871 return true;
6874 //----------------------------------------------------------------------------
6875 NLMISC_COMMAND(delPosFlag, "delete a position flag", "<csr_eid> <flag_name>")
6877 if (args.size() != 2)
6878 return false;
6879 GET_CHARACTER
6881 const string & flagName = args[1];
6882 if (!CPositionFlagManager::getInstance().flagExists(flagName))
6884 CCharacter::sendDynamicSystemMessage(eid, "CSR_POS_FLAG_NOT_EXISTS");
6885 return false;
6888 CPositionFlagManager::getInstance().removeFlag(flagName);
6889 CPositionFlagManager::getInstance().saveToFile(PositionFlagsFileName);
6891 return true;
6894 //----------------------------------------------------------------------------
6895 NLMISC_COMMAND(lPosFlags, "list position flags (short format)", "<csr_eid> [<radius_in_meters>]")
6897 if (args.size() < 1 || args.size() > 2)
6898 return false;
6899 GET_CHARACTER
6901 uint32 radius = 0;
6902 if (args.size() == 2)
6904 NLMISC::fromString(args[1], radius);
6907 CPositionFlagManager::getInstance().sendFlagsList(eid, true, radius);
6909 return true;
6912 //----------------------------------------------------------------------------
6913 NLMISC_COMMAND(listPosFlags, "list position flags (long format)", "<csr_eid> [<radius_in_meters>]")
6915 if (args.size() < 1 || args.size() > 2)
6916 return false;
6917 GET_CHARACTER
6919 uint32 radius = 0;
6920 if (args.size() == 2)
6922 NLMISC::fromString(args[1], radius);
6925 CPositionFlagManager::getInstance().sendFlagsList(eid, false, radius);
6927 return true;
6930 //----------------------------------------------------------------------------
6931 NLMISC_COMMAND(tpPosFlag, "teleport a player to a position flag", "<eid> <flag_name>")
6933 if (args.size() != 2)
6934 return false;
6935 GET_CHARACTER
6937 const string & flagName = args[1];
6938 const CFlagPosition * flagPos = CPositionFlagManager::getInstance().getFlagPosition(flagName);
6939 if (flagPos == NULL)
6941 CCharacter::sendDynamicSystemMessage(eid, "CSR_POS_FLAG_NOT_EXISTS");
6942 return false;
6945 const sint32 x = flagPos->X * 1000;
6946 const sint32 y = flagPos->Y * 1000;
6947 const sint32 z = flagPos->Z * 1000;
6949 c->allowNearPetTp();
6950 c->teleportCharacter(x, y, z, true);
6952 CContinent * continent = CZoneManager::getInstance().getContinent(x, y);
6953 if (continent != NULL)
6955 c->getRespawnPoints().addDefaultRespawnPoint( CONTINENT::TContinent(continent->getId()) );
6958 return true;
6961 //----------------------------------------------------------------------------
6962 NLMISC_COMMAND(updateGuildMembersList, "update guild members list on members clients", "<csr eid> <guild_name>|<shardId:guildId>")
6964 if (args.size() != 2)
6965 return false;
6967 TRY_GET_CHARACTER;
6969 GET_GUILD(1, false, eid);
6971 guild->updateMembersStringIds();
6973 std::map<EGSPD::TCharacterId,EGSPD::CGuildMemberPD*>::iterator it;
6974 for (it = guild->getMembersBegin(); it != guild->getMembersEnd(); ++it)
6976 CGuildMember * member = EGS_PD_CAST<CGuildMember *>( (*it).second );
6977 BOMB_IF( !member, "null guild member!!!", continue );
6978 guild->setMemberClientDB( member );
6981 return true;
6984 //----------------------------------------------------------------------------
6985 NLMISC_COMMAND(listGuildMembers, "display guild members list", "<csr eid> <guild_name>|<shardId:guildId>")
6987 if (args.size() != 2)
6988 return false;
6990 GET_CHARACTER;
6992 GET_GUILD(1, false, eid);
6994 std::map<EGSPD::TCharacterId,EGSPD::CGuildMemberPD*>::iterator it;
6995 for (it = guild->getMembersBegin(); it != guild->getMembersEnd(); ++it)
6997 CGuildMember * member = EGS_PD_CAST<CGuildMember *>( (*it).second );
6998 BOMB_IF( !member, "null guild member!!!", continue );
7000 const string memberName = CEntityIdTranslator::getInstance()->getByEntity( member->getIngameEId() ).toUtf8();
7002 SM_STATIC_PARAMS_2(params, STRING_MANAGER::literal, STRING_MANAGER::literal);
7003 params[0].Literal.fromUtf8( memberName );
7004 params[1].Literal = EGSPD::CGuildGrade::toString( member->getGrade() );
7005 CCharacter::sendDynamicSystemMessage(eid, "CSR_GUILD_MEMBER_LIST", params);
7008 return true;
7011 //----------------------------------------------------------------------------
7012 NLMISC_COMMAND(roomInvite, "send a room invite to a player character", "<eid> <member name>")
7014 if(args.size() != 2 )
7015 return false;
7017 CEntityId eId;
7018 eId.fromString(args[0].c_str());
7020 CCharacter * user = PlayerManager.getChar( eId );
7021 if (!user)
7023 log.displayNL("<ROOMINVITE>'%s' is not a valid char. Cant process command",eId.toString().c_str());
7024 return true;
7026 if (!user->getEnterFlag())
7028 log.displayNL("'%s' is not entered", eId.toString().c_str());
7029 return true;
7031 if (!TheDataset.isAccessible(user->getEntityRowId()))
7033 log.displayNL("'%s' is not valid in mirror", eId.toString().c_str());
7034 return true;
7037 CCharacter * target = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(user->getHomeMainlandSessionId(), args[1]));
7039 if(target == NULL || target->getEnterFlag() == false )
7041 CCharacter::sendDynamicSystemMessage( user->getId(), "TEAM_INVITED_CHARACTER_MUST_BE_ONLINE" );
7042 return true;
7046 SM_STATIC_PARAMS_1(params, STRING_MANAGER::player);
7047 params[0].setEIdAIAlias( user->getId(), CAIAliasTranslator::getInstance()->getAIAlias(user->getId()) );
7048 CCharacter::sendDynamicSystemMessage(target->getId(), "ROOM_INVITED_BY", params);
7049 params[0].setEIdAIAlias( target->getId(), CAIAliasTranslator::getInstance()->getAIAlias(target->getId()) );
7050 CCharacter::sendDynamicSystemMessage(user->getId(), "ROOM_YOU_INVITE", params);
7052 user->addRoomAccessToPlayer(target->getId());
7054 return true;
7057 //----------------------------------------------------------------------------
7058 NLMISC_COMMAND(roomKick, "kick player from room", "<eid> <member name>")
7060 if(args.size() != 2 )
7061 return false;
7063 CEntityId eId;
7064 eId.fromString(args[0].c_str());
7066 CCharacter * user = PlayerManager.getChar( eId );
7067 if (!user)
7069 log.displayNL("<ROOMKICK>'%s' is not a valid char. Cant process command",eId.toString().c_str());
7070 return true;
7072 if (!user->getEnterFlag())
7074 log.displayNL("'%s' is not entered", eId.toString().c_str());
7075 return true;
7077 if (!TheDataset.isAccessible(user->getEntityRowId()))
7079 log.displayNL("'%s' is not valid in mirror", eId.toString().c_str());
7080 return true;
7082 CCharacter * target = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(user->getHomeMainlandSessionId(), args[1]));
7084 if(target == NULL || target->getEnterFlag() == false )
7086 CCharacter::sendDynamicSystemMessage( user->getId(), "TEAM_KICKED_CHARACTER_MUST_BE_ONLINE" );
7087 return true;
7090 user->removeRoomAccesToPlayer(target->getId(), false);
7092 return true;
7095 //----------------------------------------------------------------------------
7096 NLMISC_COMMAND(guildInvite, "send a guild invite to a player character", "<eid> <member name>")
7098 if(args.size() != 2 )
7099 return false;
7101 CEntityId eId;
7102 eId.fromString(args[0].c_str());
7104 CCharacter * user = PlayerManager.getChar( eId );
7105 if (!user)
7107 log.displayNL("<GUILDINVITE>'%s' is not a valid char. Cant process command",eId.toString().c_str());
7108 return true;
7110 if (!user->getEnterFlag())
7112 log.displayNL("'%s' is not entered", eId.toString().c_str());
7113 return true;
7115 if (!TheDataset.isAccessible(user->getEntityRowId()))
7117 log.displayNL("'%s' is not valid in mirror", eId.toString().c_str());
7118 return true;
7121 CGuildMemberModule * gmModule = NULL;
7122 if ( !user->getModuleParent().getModule( gmModule ))
7124 log.displayNL("<GUILD>'%s' has no valid guild module, Cant process command",eId.toString().c_str());
7125 return true;
7128 uint32 guildId = user->getGuildId();
7129 CGuild *guild = CGuildManager::getInstance()->getGuildFromId(guildId);
7130 if ( guild == NULL)
7132 log.displayNL("<GUILD>'%s' Failed to find guild %u",eId.toString().c_str(), guildId);
7133 return true;
7136 // make sure the guild is local
7137 if (guild->isProxy() )
7139 log.displayNL("<GUILD>'%s' is in a foreign guild, Cant process command", eId.toString().c_str());
7140 CCharacter::sendDynamicSystemMessage( eId, "GUILD_INVITE_ONLY_LOCAL_GUILD" );
7141 return true;
7144 gmModule->inviteCharacterInGuild(PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(user->getHomeMainlandSessionId(), args[1])));
7145 return true;
7148 //----------------------------------------------------------------------------
7149 NLMISC_COMMAND(addGuildMember, "add a new member to a guild", "<csr eid> <guild_name>|<shardId:guildId> <member name>")
7151 if (args.size() != 3)
7152 return false;
7154 TRY_GET_CHARACTER;
7156 GET_GUILD(1, true, eid);
7158 string memberName = CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[2]);
7159 CCharacter * memberChar = PlayerManager.getCharacterByName( memberName);
7160 if ( !memberChar || !memberChar->getEnterFlag() || !TheDataset.isAccessible(memberChar->getEntityRowId()) )
7162 if ( CEntityIdTranslator::getInstance()->getByEntity( ucstring(memberName) ) == CEntityId::Unknown )
7164 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7165 params[0].Literal.fromUtf8( memberName );
7166 CCharacter::sendDynamicSystemMessage(eid, "CSR_UNKNOWN_PLAYER", params);
7168 else
7170 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7171 params[0].Literal.fromUtf8( memberName );
7172 CCharacter::sendDynamicSystemMessage(eid, "CSR_OFFLINE_PLAYER", params);
7174 return true;
7177 CGuildCharProxy proxy(memberChar);
7179 CGuildMemberModule * module;
7180 if ( proxy.getModule(module) )
7182 SM_STATIC_PARAMS_1(params, STRING_MANAGER::player);
7183 params[0].setEIdAIAlias( proxy.getId(), CAIAliasTranslator::getInstance()->getAIAlias(proxy.getId()) );
7184 CCharacter::sendDynamicSystemMessage(eid, "CSR_GUILD_ALREADY_MEMBER", params);
7185 return true;
7188 // message for all guild members about the new member
7190 SM_STATIC_PARAMS_1(params, STRING_MANAGER::player);
7191 params[0].setEIdAIAlias( proxy.getId(), CAIAliasTranslator::getInstance()->getAIAlias(proxy.getId()) );
7192 guild->sendMessageToGuildMembers("GUILD_JOIN", params);
7195 proxy.setGuildId( guild->getId() );
7197 // message for the new member
7199 SM_STATIC_PARAMS_1(params, STRING_MANAGER::string_id);
7200 params[0].StringId = guild->getNameId();
7201 proxy.sendSystemMessage("GUILD_YOU_JOIN", params);
7204 CGuildMember * member = guild->newMember( proxy.getId() );
7205 BOMB_IF( !member, "created null guild member!", return true );
7207 // ask the client to open it's guild interface
7208 PlayerManager.sendImpulseToClient( proxy.getId(),"GUILD:OPEN_GUILD_WINDOW" );
7210 // module = new CGuildMemberModule( proxy, member );
7211 // BOMB_IF( !module, "created null guild member module!", return true );
7213 // member->setMemberGrade( EGSPD::CGuildGrade::Member );
7214 // guild->setMemberOnline( member, proxy.getId().getDynamicId() );
7216 log.displayNL("%s now is a member of guild '%s'", memberName.c_str(), guild->getName().toString().c_str() );
7218 SM_STATIC_PARAMS_2(params, STRING_MANAGER::player, STRING_MANAGER::string_id);
7219 params[0].setEIdAIAlias( proxy.getId(), CAIAliasTranslator::getInstance()->getAIAlias(proxy.getId()) );
7220 params[1].StringId = guild->getNameId();
7221 CCharacter::sendDynamicSystemMessage(eid, "CSR_GUILD_NEW_MEMBER", params);
7224 return true;
7227 //----------------------------------------------------------------------------
7228 NLMISC_COMMAND(setGuildMemberGrade, "set the grade of a guild member", "<csr eid> <guild_name>|<shardId:guildId> <memberName> <grade = Member/Officer/HighOfficer/Leader>")
7230 if (args.size() != 4)
7231 return false;
7233 TRY_GET_CHARACTER;
7235 GET_GUILD(1, true, eid);
7237 string memberName = CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[2]);
7238 CEntityId memberEId = CEntityIdTranslator::getInstance()->getByEntity( ucstring(memberName) );
7239 if (memberEId == CEntityId::Unknown)
7241 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7242 params[0].Literal.fromUtf8( memberName );
7243 CCharacter::sendDynamicSystemMessage(eid, "CSR_UNKNOWN_PLAYER", params);
7244 return true;
7247 EGSPD::CGuildGrade::TGuildGrade grade = EGSPD::CGuildGrade::fromString( args[3] );
7249 CGuildMember * member = guild->getMemberFromEId( memberEId );
7250 if ( !member )
7252 SM_STATIC_PARAMS_2(params, STRING_MANAGER::literal, STRING_MANAGER::string_id);
7253 params[0].Literal.fromUtf8( memberName );
7254 params[1].StringId = uint32(guild->getNameId());
7255 CCharacter::sendDynamicSystemMessage(eid, "CSR_GUILD_NOT_MEMBER", params);
7256 return true;
7259 guild->setMemberGrade( member, grade, &log, eid );
7261 return true;
7264 //----------------------------------------------------------------------------
7265 NLMISC_COMMAND(setGuildLeader, "set the leader of a guild", "<csr eid> <guild_name>|<shardId:guildId> <member name>")
7267 if (args.size() != 3)
7268 return false;
7270 TRY_GET_CHARACTER;
7272 GET_GUILD(1, true, eid);
7274 string memberName = CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), args[2]);
7275 CEntityId memberEId = CEntityIdTranslator::getInstance()->getByEntity( ucstring(memberName) );
7276 if (memberEId == CEntityId::Unknown)
7278 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7279 params[0].Literal.fromUtf8( memberName );
7280 CCharacter::sendDynamicSystemMessage(eid, "CSR_UNKNOWN_PLAYER", params);
7281 return true;
7284 CGuildMember * member = guild->getMemberFromEId( memberEId );
7285 if ( !member )
7287 SM_STATIC_PARAMS_2(params, STRING_MANAGER::literal, STRING_MANAGER::string_id);
7288 params[0].Literal.fromUtf8( memberName );
7289 params[1].StringId = guild->getNameId();
7290 CCharacter::sendDynamicSystemMessage(eid, "CSR_GUILD_NOT_MEMBER", params);
7291 return true;
7294 if (member->getGrade() == EGSPD::CGuildGrade::Leader)
7296 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7297 params[0].Literal.fromUtf8( memberName );
7298 CCharacter::sendDynamicSystemMessage(eid, "CSR_GUILD_ALREADY_HAS_GRADE", params);
7299 return true;
7302 CGuildMember * leader = guild->getLeader();
7303 if (leader)
7304 guild->setMemberGrade( leader, EGSPD::CGuildGrade::Member, &log, eid );
7306 guild->setMemberGrade( member, EGSPD::CGuildGrade::Leader, &log, eid );
7308 return true;
7311 //----------------------------------------------------------------------------
7313 NLMISC_COMMAND(setPvpClan, "set the pv clan for player", "<csr eid> <clan number 0=neutral, 1=clan1, 2=clan2 >")
7315 if (args.size() != 2)
7316 return false;
7318 TRY_GET_CHARACTER;
7320 uint8 clan;
7321 NLMISC::fromString(args[1], clan);
7323 if ( c && c->getEnterFlag() )
7325 if ( c->getPVPInterface().isValid() )
7326 c->getPVPInterface().setUserClan( clan );
7328 return true;
7332 //----------------------------------------------------------------------------
7333 NLMISC_COMMAND(startEvent, "start an event with the given name", "<csr eid> <event name> [<faction1> <faction2> [<Faction 1 GM channel name> <faction2 GM channel Name> [<zone only ?>]]]")
7335 if (args.size() != 2 && args.size() < 4)
7336 return false;
7338 TRY_GET_CHARACTER;
7340 const string & eventName = args[1];
7341 string eventFaction1;
7342 string eventFaction2;
7343 string eventFaction1ChannelName;
7344 string eventFaction2ChannelName;
7345 bool factionChanelInZoneOnly = false;
7347 if( args.size() > 3 )
7349 eventFaction1 = args[2];
7350 eventFaction2 = args[3];
7352 if( args.size() > 5 )
7354 eventFaction1ChannelName = args[4];
7355 eventFaction2ChannelName = args[5];
7358 if( args.size() > 6 )
7360 NLMISC::fromString(args[6], factionChanelInZoneOnly);
7364 CGameEventManager::getInstance().resetGameEvent(eventName, eventFaction1, eventFaction2, eventFaction1ChannelName, eventFaction2ChannelName, factionChanelInZoneOnly);
7366 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7367 params[0].Literal.fromUtf8(eventName);
7368 CCharacter::sendDynamicSystemMessage(eid, "CSR_START_EVENT", params);
7370 return true;
7373 //----------------------------------------------------------------------------
7374 NLMISC_COMMAND(stopEvent, "stop previous started event", "<csr eid>")
7376 if (args.size() != 1)
7377 return false;
7379 TRY_GET_CHARACTER;
7381 const string & eventName = CGameEventManager::getInstance().getGameEventName();
7382 CGameEventManager::getInstance().resetGameEvent(string(""),string(""),string(""),string(""),string(""),false);
7384 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7385 params[0].Literal.fromUtf8(eventName);
7386 CCharacter::sendDynamicSystemMessage(eid, "CSR_STOP_EVENT", params);
7388 return true;
7391 //----------------------------------------------------------------------------
7392 NLMISC_COMMAND(setEventFaction, "set the event faction of player", "<csr eid> <player name> <event faction>")
7394 if (args.size() != 3)
7395 return false;
7397 TRY_GET_CHARACTER;
7399 const string & playerName = args[1];
7400 const string & eventFaction = args[2];
7402 CCharacter * player = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),playerName));
7403 if (!player)
7405 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7406 params[0].Literal.fromUtf8( playerName );
7407 CCharacter::sendDynamicSystemMessage(eid, "CSR_UNKNOWN_PLAYER", params);
7408 return true;
7411 player->getGameEvent().setEventFaction(eventFaction);
7413 SM_STATIC_PARAMS_2(params, STRING_MANAGER::player, STRING_MANAGER::event_faction);
7414 params[0].setEIdAIAlias( player->getId(), CAIAliasTranslator::getInstance()->getAIAlias(player->getId()) );
7415 params[1].Identifier = eventFaction;
7416 CCharacter::sendDynamicSystemMessage(eid, "CSR_GET_EVENT_FACTION", params);
7418 return true;
7421 //----------------------------------------------------------------------------
7422 NLMISC_COMMAND(clearEventFaction, "clear the event faction of player", "<csr eid> <player name>")
7424 if (args.size() != 2)
7425 return false;
7427 TRY_GET_CHARACTER;
7429 const string & playerName = args[1];
7431 CCharacter * player = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),playerName));
7432 if (!player)
7434 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7435 params[0].Literal.fromUtf8( playerName );
7436 CCharacter::sendDynamicSystemMessage(eid, "CSR_UNKNOWN_PLAYER", params);
7437 return true;
7440 player->getGameEvent().clearEventFaction();
7442 SM_STATIC_PARAMS_1(params, STRING_MANAGER::player);
7443 params[0].setEIdAIAlias( player->getId(), CAIAliasTranslator::getInstance()->getAIAlias(player->getId()) );
7444 CCharacter::sendDynamicSystemMessage(eid, "CSR_CLEAR_EVENT_FACTION", params);
7446 return true;
7449 //----------------------------------------------------------------------------
7450 NLMISC_COMMAND(getEventFaction, "get the event faction of player", "<csr eid> <player name>")
7452 if (args.size() != 2)
7453 return false;
7455 GET_CHARACTER;
7457 const string & playerName = args[1];
7459 CCharacter * player = PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),playerName));
7460 if (!player)
7462 SM_STATIC_PARAMS_1(params, STRING_MANAGER::literal);
7463 params[0].Literal.fromUtf8( playerName );
7464 CCharacter::sendDynamicSystemMessage(eid, "CSR_UNKNOWN_PLAYER", params);
7465 return true;
7468 SM_STATIC_PARAMS_2(params, STRING_MANAGER::player, STRING_MANAGER::event_faction);
7469 params[0].setEIdAIAlias( player->getId(), CAIAliasTranslator::getInstance()->getAIAlias(player->getId()) );
7470 params[1].Identifier = player->getGameEvent().getEventFaction();
7471 CCharacter::sendDynamicSystemMessage(eid, "CSR_GET_EVENT_FACTION", params);
7473 return true;
7476 //----------------------------------------------------------------------------
7477 NLMISC_COMMAND(provideItemService, "provide a service from an item to a player", "<eid> <sheet name>")
7479 if (args.size() != 2)
7480 return false;
7482 GET_CHARACTER;
7484 CSheetId sheetId(args[1]);
7485 const CStaticItem * form = CSheets::getForm(sheetId);
7486 if (form)
7488 CItemServiceManager::getInstance()->provideService(form, c);
7491 return true;
7494 //----------------------------------------------------------------------------
7495 NLMISC_COMMAND(dumpFactionPVPDamage, "dump damage made in Faction PvP", "<eid>")
7497 if (args.size() != 1)
7498 return false;
7500 GET_CHARACTER;
7502 PROGRESSIONPVP::CCharacterProgressionPVP::getInstance()->dumpPlayerDamageScoreTable(c, log);
7503 log.displayNL("----------------------------------------------------------------------------");
7505 return true;
7508 //----------------------------------------------------------------------------
7509 NLMISC_COMMAND(changeHairCut, "change the haircut of a player", "<eid> <sheet name>")
7511 if (args.size() != 2)
7512 return false;
7514 GET_CHARACTER;
7516 CSheetId sheetId(args[1]);
7517 const CStaticItem * form = CSheets::getForm(sheetId);
7518 if (form == NULL)
7520 nlwarning("unknown item : '%s'", sheetId.toString().c_str());
7521 return true;
7524 if (form->Type != ITEM_TYPE::HAIR_MALE && form->Type != ITEM_TYPE::HAIR_FEMALE)
7526 nlwarning("'%s' is not a haircut item", sheetId.toString().c_str());
7527 return true;
7530 uint32 hairValue = CVisualSlotManager::getInstance()->sheet2Index(form->SheetId, SLOTTYPE::HEAD_SLOT);
7531 if (c->setHair(hairValue))
7533 c->resetHairCutDiscount();
7536 return true;
7539 /***********************************************************************************************************************
7541 END OF OFFICIAL CSR COMMANDS
7543 ***********************************************************************************************************************/
7546 ///////////////////////
7547 // DYN CHAT COMMANDS //
7548 ///////////////////////
7550 //============================================================================================================
7551 // create a new channel with a localized name
7552 NLMISC_COMMAND(addLocalizedChan,"Add a new dyn chat channel","<string name of the channel localized name>")
7554 if (args.size() != 1) return false;
7555 TChanID chanID = DynChatEGS.addLocalizedChan(args[0]);
7556 if (chanID == DYN_CHAT_INVALID_CHAN)
7558 nlwarning("Can't create localized channel %s", args[0].c_str());
7559 return true;
7561 return true;
7564 //============================================================================================================
7565 // create a new channel
7566 NLMISC_COMMAND(addChan,"Add a new dyn chat channel","<string name of the channel localized name>")
7568 if (args.size() < 2) return false;
7569 ucstring mess;
7570 for (uint k = 2; k < args.size(); ++k)
7572 if (k != 0) mess += ucstring(" ");
7573 mess += ucstring(args[k]);
7575 TChanID chanID = DynChatEGS.addChan(args[0], mess);
7576 if (chanID == DYN_CHAT_INVALID_CHAN)
7578 nlwarning("Can't create channel %s", args[0].c_str());
7579 return true;
7581 return true;
7585 //============================================================================================================
7586 // remove a channel
7587 NLMISC_COMMAND(removeChan, "Remove a new dyn chat channel","<string name of the channel localized name>")
7589 if (args.size() != 1) return false;
7590 TChanID chanID = DynChatEGS.getChanIDFromName(args[0]);
7591 if (chanID == DYN_CHAT_INVALID_CHAN)
7593 nlwarning("Unknown channel : %s", args[1].c_str());
7594 return true;
7596 bool res = DynChatEGS.removeChan(chanID);
7597 if (!res)
7599 nlwarning("Couldn't remove chan : %s", args[1].c_str());
7601 return true;
7604 //============================================================================================================
7605 // set historic size for a channel
7606 NLMISC_COMMAND(setChanHistoricSize, "Set size of the historic for a localized channel", "<string name of the channel localized name><size>")
7608 if (args.size() != 2) return false;
7609 TChanID chanID = DynChatEGS.getChanIDFromName(args[0]);
7610 if (chanID == DYN_CHAT_INVALID_CHAN)
7612 nlwarning("Unknown channel : %s", args[0].c_str());
7613 return true;
7615 uint historicSize;
7616 NLMISC::fromString(args[1], historicSize);
7618 if (historicSize > 1000)
7620 nlwarning("Historic size too big");
7621 return true;
7623 DynChatEGS.setHistoricSize(chanID, historicSize);
7624 return true;
7627 //============================================================================================================
7628 // add a client to a channel
7629 NLMISC_COMMAND(addChanClient, "add a client to a channel", "<client name or user id><string name of the channel localized name>[1=Read/Write,0=ReadOnly(default)]")
7631 if (args.size() < 2 || args.size() > 3) return false;
7632 GET_CHARACTER
7633 TChanID chanID = DynChatEGS.getChanIDFromName(args[1]);
7634 if (chanID == DYN_CHAT_INVALID_CHAN)
7636 nlwarning("Unknown channel : %s", args[1].c_str());
7637 return true;
7639 bool writeRight = true;
7640 if (args.size() > 2)
7642 NLMISC::fromString(args[2], writeRight);
7644 bool res = DynChatEGS.addSession(chanID, c->getEntityRowId(), writeRight);
7645 if (!res)
7647 nlwarning("Couldn't add character %s to channel %s", args[0].c_str(), args[1].c_str());
7649 return true;
7652 //============================================================================================================
7653 // remove clients from channels
7654 NLMISC_COMMAND(removeChanClient, "remove a client to a channel", "<client name or user id><string name of the channel localized name>")
7656 if (args.size() != 2) return false;
7657 GET_CHARACTER
7658 TChanID chanID = DynChatEGS.getChanIDFromName(args[1]);
7659 if (chanID == DYN_CHAT_INVALID_CHAN)
7661 nlwarning("Unknown channel : %s", args[1].c_str());
7662 return true;
7664 bool res = DynChatEGS.removeSession(chanID, c->getEntityRowId());
7665 if (!res)
7667 nlwarning("Couldn't remove character %s from channel %s", args[0].c_str(), args[1].c_str());
7669 return true;
7672 //============================================================================================================
7673 // Set the read only for a client in a channel
7674 NLMISC_COMMAND(setChanClientWriteRight, "set write right for a client in the given channel", "<client name or user id><string name of the channel localized name><1=Read/Write,0=ReadOnly(default)>")
7676 if (args.size() != 3) return false;
7677 GET_CHARACTER
7678 TChanID chanID = DynChatEGS.getChanIDFromName(args[1]);
7679 if (chanID == DYN_CHAT_INVALID_CHAN)
7681 nlwarning("Unknown channel : %s", args[1].c_str());
7682 return true;
7684 bool canWrite;
7685 NLMISC::fromString(args[2], canWrite);
7686 bool res = DynChatEGS.setWriteRight(chanID, c->getEntityRowId(), canWrite);
7687 if (!res)
7689 nlwarning("Couldn't remove character %s from channel %s", args[0].c_str(), args[1].c_str());
7691 return true;
7694 //============================================================================================================
7695 // Display the list of all channels
7696 NLMISC_COMMAND(chanList, "display the list of all channels", "<>")
7698 if (!args.empty()) return false;
7699 std::vector<CDynChatChan *> chans;
7700 DynChatEGS.getChans(chans);
7701 for(uint k = 0; k < chans.size(); ++k)
7703 ucstring name = DynChatEGS.getChanNameFromID(chans[k]->getID());
7704 nlinfo("Channel name : %s, num sessions = %d, historic size = %d", name.toString().c_str(), (int) chans[k]->getSessionCount(), (int) chans[k]->HistoricSize);
7706 return true;
7709 //----------------------------------------------------------------------------
7710 ENTITY_VARIABLE (Aggro, "Aggroable by creatures")
7712 ENTITY_GET_CHARACTER
7714 if (get)
7716 value = toString (c->getAggroableOverride());
7718 else
7720 TDataSetRow userRow = TheDataset.getDataSetRow( c->getId() );
7721 if ( !TheDataset.isAccessible( userRow ) )
7722 return;
7724 sint8 aggroable;
7725 NLMISC::fromString(value, aggroable);
7726 c->setAggroableOverride(aggroable);
7727 c->setAggroableSave(aggroable);
7729 if (aggroable > 0)
7730 nlinfo ("%s is now aggroable", entity.toString().c_str());
7731 else if (aggroable < 0)
7732 nlinfo ("%s aggroable is defined by privilege", entity.toString().c_str());
7733 else
7734 nlinfo ("%s is now non aggroable", entity.toString().c_str());
7739 //----------------------------------------------------------------------------
7740 NLMISC_COMMAND(acceptProposalForQueue, "player accept to enter critical part (for queue Id i)", "<eid> <accept (0/1)> [<queueId>]")
7742 if (args.size() < 2 || args.size() > 3 ) return false;
7744 CEntityId eid(args[0]);
7745 bool accept;
7746 NLMISC::fromString(args[1], accept);
7748 uint32 queueId = 0;
7749 if (args.size() == 3)
7750 NLMISC::fromString(args[1], queueId);
7751 else
7753 CCharacter *player = PlayerManager.getChar(eid);
7754 if (player)
7755 queueId = player->getEnterCriticalZoneProposalQueueId();
7758 CMissionQueueManager::getInstance()->playerEntersCriticalArea(eid, queueId, accept);
7760 return true;
7763 //----------------------------------------------------------------------------
7764 NLMISC_COMMAND(awakePlayerInQueue, "awake player in given queue", "<eid> <queueId>")
7766 if (args.size() != 2) return false;
7768 CEntityId eid(args[0]);
7769 uint32 queueId;
7770 NLMISC::fromString(args[1], queueId);
7772 CMissionQueueManager::getInstance()->playerWakesUp( eid, queueId);
7774 return true;
7778 //----------------------------------------------------------------------------
7779 NLMISC_COMMAND(debugMissionsQueues, "dump mission queues for debug", "")
7781 CMissionQueueManager::getInstance()->dump();
7783 return true;
7786 static bool serialMagicNumberMsg(const std::string &msgName, const std::string &userID, uint64 magicNumber)
7788 CMessage msgout( "IMPULSION_ID" );
7789 CEntityId eid(userID);
7790 msgout.serial(eid);
7791 CBitMemStream bms;
7792 if ( ! GenericMsgManager.pushNameToStream(msgName, bms) )
7794 nlwarning("Msg name %s not found", msgName.c_str());
7795 return false;
7797 bms.serial(magicNumber);
7798 msgout.serialBufferWithSize((uint8*)bms.buffer(), bms.length());
7799 CUnifiedNetwork::getInstance()->send(NLNET::TServiceId(eid.getDynamicId()), msgout );
7800 return true;
7803 //----------------------------------------------------------------------------
7804 NLMISC_COMMAND(permanentBan, "permanently ban a player (player must be online)", "")
7806 if (args.size() != 1) return false;
7807 return serialMagicNumberMsg("CONNECTION:PERMANENT_BAN", args[0], PermanentBanMSGMagicNumber);
7810 //----------------------------------------------------------------------------
7811 NLMISC_COMMAND(permanentUnban, "unban a player (player must be online)", "")
7813 if (args.size() != 1) return false;
7814 return serialMagicNumberMsg("CONNECTION:UNBAN", args[0], PermanentUnbanMSGMagicNumber);
7817 //----------------------------------------------------------------------------
7818 NLMISC_COMMAND(nbKnownPhrases, "display nb of known phrases for player", "<eid>")
7820 if (args.size() != 1)
7821 return false;
7823 CEntityId eid(args[0]);
7825 CCharacter *player= PlayerManager.getChar(eid);
7826 if (!player)
7828 nlwarning("Player %s not found", eid.toString().c_str());
7829 return true;
7832 const vector<CKnownPhrase> &kp = player->getKnownPhrases();
7833 nlinfo("For player %s, size of Known Phrases vector = %u", eid.toString().c_str(), kp.size());
7835 uint count = 0;
7836 for (uint i = 0;i < kp.size() ; ++i )
7838 if (!kp[i].empty())
7839 ++count;
7841 nlinfo("Total nb of non null known phrases = %u", count);
7843 return true;
7846 //----------------------------------------------------------------------------
7847 NLMISC_COMMAND(displayShopSelector, "display shop selector for a NPC", "")
7849 if (args.size() != 1) return false;
7851 CEntityId eid(args[0]);
7852 CCreature *c = CreatureManager.getCreature( eid );
7853 if( c != 0 )
7855 c->displayShopSelectors( log );
7857 return true;
7860 //----------------------------------------------------------------------------
7861 NLMISC_COMMAND(addFactionAttackableToTarget, "Add a faction to attackable list to given entity target creature/npc", "<player eid> <faction name> <fameLevel -600+600> <0/1 0 = below 1 = above>")
7863 if (args.size () < 4) return false;
7864 GET_CHARACTER
7866 // get faction
7867 uint factionIndex = CStaticFames::getInstance().getFactionIndex(args[1]);
7868 if (factionIndex != CStaticFames::INVALID_FACTION_INDEX)
7870 const CEntityId &target = c->getTarget();
7871 if (target != CEntityId::Unknown && target.getType() != RYZOMID::player)
7873 CCreature *creature = CreatureManager.getCreature(target);
7874 if (creature)
7876 sint32 fameLevel;
7877 NLMISC::fromString(args[2], fameLevel);
7878 bool above;
7879 NLMISC::fromString(args[3], above);
7880 creature->addFactionAttackable(factionIndex, fameLevel * FameAbsoluteMax / 100, above);
7885 return true;
7889 //----------------------------------------------------------------------------
7890 NLMISC_COMMAND(taskPass, "pass a task from a rite", "<player eid> <rite> [<task>]")
7892 if (args.size () != 2 && args.size () != 3) return false;
7893 GET_CHARACTER
7895 string rite = args[1];
7896 uint32 nAlbum = 0;
7897 uint32 nThema = 0;
7898 uint32 taskCount = 0;
7899 CSheets::getEncyclopedia().getRiteInfos( rite, nAlbum, nThema, taskCount );
7901 if( nAlbum!=0 && nThema!=0 && taskCount!=0 )
7903 CCharacterEncyclopedia &rEncy = c->getEncyclopedia();
7904 if( args.size() == 3 )
7906 uint32 nTask;
7907 NLMISC::fromString(args[2], nTask);
7908 if( nTask > 7 )
7910 nlwarning("<taskPass> task index too high : %d",nTask);
7911 return false;
7913 rEncy.updateTask(nAlbum, nThema, nTask, 2, true);
7915 else
7917 uint i;
7918 for( i=0; i<=taskCount; ++i )
7920 rEncy.updateTask(nAlbum, nThema, i, 2, true);
7924 else
7926 nlwarning("<taskPass> wrong rite ? %s",rite.c_str());
7929 return true;
7933 //----------------------------------------------------------------------------
7934 NLMISC_COMMAND(setFamePlayer, "set the fame value of a player in the given faction", "<player eid> <faction> <fame>")
7936 if (args.size () != 3)
7937 return false;
7939 GET_CHARACTER
7941 uint32 factionIndex =CStaticFames::getInstance().getFactionIndex(args[1]);
7942 if (factionIndex == CStaticFames::INVALID_FACTION_INDEX)
7943 return false;
7945 sint32 fame;
7946 NLMISC::fromString(args[2], fame);
7948 CFameManager::getInstance().setEntityFame(c->getId(), factionIndex, fame, true);
7950 return true;
7954 //----------------------------------------------------------------------------
7955 NLMISC_COMMAND(addGuildBuilding, "sadd a building to guild", "<player eid> <building name>")
7957 if (args.size () != 2)
7958 return false;
7960 GET_CHARACTER
7962 IBuildingPhysical *building = CBuildingManager::getInstance()->getBuildingPhysicalsByName(args[1]);
7964 if (building == NULL)
7965 return true;
7967 if (c->getGuildId() == 0)
7968 return true;
7970 CBuildingManager::getInstance()->registerGuild( c->getGuildId(), building->getAlias() );
7972 return true;
7975 //----------------------------------------------------------------------------
7976 NLMISC_COMMAND(setOrganization, "set the organization of a player to the given faction", "<player eid> <faction>")
7978 if (args.size () != 2)
7979 return false;
7981 GET_CHARACTER
7983 uint32 factionIndex = CStaticFames::getInstance().getFactionIndex(args[1]);
7984 if (factionIndex == CStaticFames::INVALID_FACTION_INDEX)
7985 return false;
7987 c->setOrganization(factionIndex);
7989 return true;
7992 //----------------------------------------------------------------------------
7993 NLMISC_COMMAND(setOrganizationStatus, "set the organization status of a player", "<player eid> <status>")
7995 if (args.size () != 2)
7996 return false;
7998 GET_CHARACTER
8000 sint32 status;
8002 if (args[1][0] == '+')
8004 NLMISC::fromString(args[1].substr(1), status);
8006 else if (args[1][0] == '-')
8008 NLMISC::fromString(args[1], status);
8010 else
8012 NLMISC::fromString(args[1], status);
8013 c->setOrganizationStatus(status);
8014 return true;
8017 c->changeOrganizationStatus(status);
8019 return true;
8022 //----------------------------------------------------------------------------
8023 NLMISC_COMMAND(eventCreateNpcGroup, "create an event npc group", "<player eid> <nbBots> <sheet> [<dispersionRadius=10m>] [<spawnBots=true>] [<orientation=random|self|-360..360>] [<name>] [<x>] [<y>] [<z>] [client_sheet] [inVIllage?inOutpost?inStable?inAtys?]")
8025 if (args.size () < 3) return false;
8026 GET_CHARACTER
8028 sint32 x = c->getX();
8029 sint32 y = c->getY();
8030 sint32 z = c->getZ();
8031 sint32 orientation = 6666; // used to specify a random orientation
8033 uint32 nbBots;
8034 fromString(args[1], nbBots);
8035 if (nbBots<=0)
8037 log.displayNL("invalid bot count");
8038 return true;
8041 string sheetName = args[2];
8042 if (sheetName.find(".creature") == string::npos)
8043 sheetName += ".creature";
8044 NLMISC::CSheetId sheetId(sheetName);
8045 if (sheetId==CSheetId::Unknown)
8047 log.displayNL("invalid sheet id");
8048 return true;
8051 double dispersionRadius = 10.;
8052 if (args.size()>3)
8054 fromString(args[3], dispersionRadius);
8055 if (dispersionRadius < 0.)
8057 log.displayNL("invalid dispersion radius");
8058 return true;
8062 bool spawnBots = true;
8063 if (args.size()>4)
8064 fromString(args[4], spawnBots);
8066 if (args.size()>5)
8068 if (args[5] == "self")
8070 orientation = (sint32)(c->getHeading() * 1000.0);
8072 else if (args[5] != "random")
8074 fromString(args[5], orientation);
8075 orientation = (sint32)((double)orientation / 360.0 * (NLMISC::Pi * 2.0) * 1000.0);
8079 std::string botsName;
8080 if (args.size()>6) botsName = args[6];
8081 if (botsName == "*")
8082 botsName.clear();
8084 if (args.size() > 8)
8086 if (args[7] != "*")
8088 float userX;
8089 NLMISC::fromString(args[7], userX);
8090 x = (sint32)(userX * 1000.0);
8093 if (args[8] != "*")
8095 float userY;
8096 NLMISC::fromString(args[8], userY);
8097 y = (sint32)(userY * 1000.0);
8101 if (args.size() > 9)
8103 if (args[9] != "*") {
8104 NLMISC::fromString(args[9], z);
8108 std::string look;
8109 if (args.size() > 10)
8111 look = args[10];
8112 if (look.find(".creature") == string::npos)
8113 look += ".creature";
8117 //Get instance number from position
8118 CContinent * continent = CZoneManager::getInstance().getContinent(x, y);
8119 if (!continent)
8121 log.displayNL("ERR: invalid continent");
8122 return false;
8124 uint32 instanceNumber = CUsedContinent::instance().getInstanceForContinent((CONTINENT::TContinent)continent->getId());
8126 if (instanceNumber == ~0)
8128 log.displayNL("ERR: invalid continent");
8129 return false;
8132 TDataSetRow dsr = c->getEntityRowId();
8133 CMirrorPropValueRO<TYPE_CELL> srcCell( TheDataset, dsr, DSPropertyCELL );
8134 sint32 cell = srcCell;
8136 CEntityId playerId = c->getId();
8138 CMessage msgout("EVENT_CREATE_NPC_GROUP");
8139 uint32 messageVersion = 1;
8140 msgout.serial(messageVersion);
8141 msgout.serial(instanceNumber);
8142 msgout.serial(playerId);
8143 msgout.serial(x);
8144 msgout.serial(y);
8145 msgout.serial(z);
8146 msgout.serial(orientation);
8147 msgout.serial(nbBots);
8148 msgout.serial(sheetId);
8149 msgout.serial(dispersionRadius);
8150 msgout.serial(spawnBots);
8151 msgout.serial(botsName);
8152 msgout.serial(look);
8153 msgout.serial(cell);
8154 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8156 return true;
8159 //----------------------------------------------------------------------------
8160 NLMISC_COMMAND(eventNpcGroupScript, "executes a script on an event npc group", "<bot eid> <script>")
8162 if (args.size () < 1) return false;
8163 GET_ENTITY
8165 uint32 instanceNumber = e->getInstanceNumber();
8167 uint32 nbString = (uint32)args.size();
8169 CMessage msgout("EVENT_NPC_GROUP_SCRIPT");
8170 uint32 messageVersion = 1;
8171 msgout.serial(messageVersion);
8172 msgout.serial(nbString);
8173 for (uint32 i=0; i<nbString; ++i)
8175 string arg = args[i];
8176 msgout.serial(arg);
8178 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8180 return true;
8183 //----------------------------------------------------------------------------
8184 NLMISC_COMMAND(eScript, "executes a script on an event npc group", "<player eid> <groupname> <script>")
8186 if (args.size () < 3) return false;
8187 GET_CHARACTER
8189 uint32 instanceNumber = c->getInstanceNumber();
8191 uint32 nbString = (uint32)args.size();
8193 string botsName = args[1];
8194 if ( ! getAIInstanceFromGroupName(botsName, instanceNumber))
8196 return false;
8199 CMessage msgout("EVENT_NPC_GROUP_SCRIPT");
8200 uint32 messageVersion = 1;
8201 msgout.serial(messageVersion);
8202 msgout.serial(nbString);
8204 string playerEid = args[0];
8205 msgout.serial(playerEid);
8206 msgout.serial(botsName);
8207 for (uint32 i=2; i<nbString; ++i)
8209 string arg = args[i]+";";
8211 size_t pos = 0;
8212 while((pos = arg.find("&nbsp&", pos)) != string::npos)
8214 arg.replace(pos, 6, " ");
8215 pos ++;
8218 // Replace "(eid:<player name>)" with player Entity ID string
8219 pos = arg.find("(eid:");
8220 while (pos != string::npos)
8222 string s = arg.substr(pos, arg.find(")\"", pos) - pos + 1);
8223 if (s.length() > 6)
8225 string name = s.substr(5, s.length() - 6);
8226 CCharacter * player = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(), name) );
8227 CEntityId id = CEntityId::Unknown;
8228 if (player != NULL)
8230 id = player->getId();
8232 strFindReplace(arg, s, id.toString());
8234 pos = arg.find("(eid:");
8237 strFindReplace(arg, "#item:", "");
8238 strFindReplace(arg, "#rrp:", "");
8239 msgout.serial(arg);
8241 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8243 return true;
8246 NLMISC_COMMAND(eventSetBotName, "changes the name of a bot", "<bot eid> <name>")
8248 if (args.size () < 2) return false;
8249 GET_ENTITY
8251 TDataSetRow row = e->getEntityRowId();
8252 ucstring name;
8253 name.fromUtf8(args[1]);
8254 NLNET::CMessage msgout("CHARACTER_NAME");
8255 msgout.serial(row);
8256 msgout.serial(name);
8257 sendMessageViaMirror("IOS", msgout);
8259 return true;
8262 //----------------------------------------------------------------------------
8263 NLMISC_COMMAND(eventSetBotScale, "changes the scale of a bot (in % up to 255)", "<bot eid> <scale in %>")
8265 if (args.size () < 2) return false;
8266 GET_ENTITY
8268 TDataSetRow row = e->getEntityRowId();
8269 uint32 scale;
8270 NLMISC::fromString(args[1], scale);
8271 if (scale>255)
8272 scale = 0;
8273 CMirrorPropValue< SAltLookProp2, CPropLocationPacked<2> > visualPropertyB( TheDataset, row, DSPropertyVPB );
8274 SET_STRUCT_MEMBER( visualPropertyB, PropertySubData.Scale, scale );
8276 return true;
8279 //----------------------------------------------------------------------------
8280 NLMISC_COMMAND(eventSetNpcGroupAggroRange, "changes the aggro range of a npc group", "<bot eid> <range>")
8282 if (args.size() < 2) return false;
8283 GET_ENTITY
8285 uint32 instanceNumber = e->getInstanceNumber();
8287 std::vector<std::string> args2;
8289 args2.push_back(args[0]);
8290 args2.push_back(NLMISC::toString("()setAggro(%f, 0);", atof(args[1].c_str())));
8292 uint32 nbString = (uint32)args2.size();
8294 CMessage msgout("EVENT_NPC_GROUP_SCRIPT");
8295 uint32 messageVersion = 1;
8296 msgout.serial(messageVersion);
8297 msgout.serial(nbString);
8298 for (uint32 i=0; i<nbString; ++i)
8300 string arg = args2[i];
8301 msgout.serial(arg);
8303 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8305 return true;
8308 //----------------------------------------------------------------------------
8309 NLMISC_COMMAND(eventSetNpcGroupEmote, "Set emote animation to a npc group", "<bot eid> <emote>")
8311 if (args.size() < 2) return false;
8312 GET_ENTITY
8314 CEntityId entityId(args[0]);
8316 uint32 instanceNumber = e->getInstanceNumber();
8318 std::vector<std::string> args2;
8320 args2.push_back(args[0]);
8321 args2.push_back(NLMISC::toString("()emote(\"%s\",\"%s\");", entityId.toString().c_str(), args[1].c_str()));
8323 uint32 nbString = (uint32)args2.size();
8325 CMessage msgout("EVENT_NPC_GROUP_SCRIPT");
8326 uint32 messageVersion = 1;
8327 msgout.serial(messageVersion);
8328 msgout.serial(nbString);
8329 for (uint32 i=0; i<nbString; ++i)
8331 string arg = args2[i];
8332 msgout.serial(arg);
8334 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8336 return true;
8338 //----------------------------------------------------------------------------
8339 NLMISC_COMMAND(eventSetFaunaBotAggroRange, "changes the aggro range of a fauna bot", "<bot eid> <not hungry range> [<hungry range> [<hunting range>]]")
8341 if (args.size() < 2) return false;
8342 GET_ENTITY
8344 uint32 instanceNumber = e->getInstanceNumber();
8346 uint32 messageVersion = 1;
8347 string botName = args[0];
8348 float notHungryRadius = (float)atof(args[1].c_str());
8349 float hungryRadius = -1.f;
8350 if (args.size() > 2)
8351 hungryRadius = (float)atof(args[2].c_str());
8352 float huntingRadius = -1.f;
8353 if (args.size() > 3)
8354 huntingRadius = (float)atof(args[3].c_str());
8356 CMessage msgout("EVENT_FAUNA_BOT_SET_RADII");
8357 msgout.serial(messageVersion);
8358 msgout.serial(botName);
8359 msgout.serial(notHungryRadius);
8360 msgout.serial(hungryRadius);
8361 msgout.serial(huntingRadius);
8362 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8364 return true;
8367 //----------------------------------------------------------------------------
8368 NLMISC_COMMAND(eventResetFaunaBotAggroRange, "reset the aggro range of a fauna bot to sheet defaults", "<bot eid>")
8370 if (args.size() < 1) return false;
8371 GET_ENTITY
8373 uint32 instanceNumber = e->getInstanceNumber();
8375 uint32 messageVersion = 1;
8376 string botName = args[0];
8378 CMessage msgout("EVENT_FAUNA_BOT_RESET_RADII");
8379 msgout.serial(messageVersion);
8380 msgout.serial(botName);
8381 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8383 return true;
8386 //----------------------------------------------------------------------------
8387 NLMISC_COMMAND(eventSetBotCanAggro, "tells the bot if he can aggro or not", "<bot eid> <can aggro>")
8389 if (args.size() < 2) return false;
8390 GET_ENTITY
8392 uint32 instanceNumber = e->getInstanceNumber();
8394 uint32 messageVersion = 1;
8395 string botName = args[0];
8396 bool canAggro = true;
8397 NLMISC::fromString(args[1], canAggro);
8399 CMessage msgout("EVENT_BOT_CAN_AGGRO");
8400 msgout.serial(messageVersion);
8401 msgout.serial(botName);
8402 msgout.serial(canAggro);
8403 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8405 return true;
8408 //----------------------------------------------------------------------------
8409 NLMISC_COMMAND(eventSetBotSheet, "Change the sheet of a bot", "<bot eid> <sheet id>")
8411 if (args.size() < 2) return false;
8412 GET_ENTITY
8414 uint32 instanceNumber = e->getInstanceNumber();
8416 uint32 messageVersion = 3;
8417 bool bAutoSpawnDespawn = false;
8418 string botName = args[0];
8419 string sCustomName; // Not needed here
8420 CSheetId sheetId(args[1]);
8421 if (sheetId==CSheetId::Unknown)
8422 sheetId = CSheetId(args[1]+".creature");
8423 if (sheetId==CSheetId::Unknown)
8425 log.displayNL("Unknown sheet id '%s'", args[1].c_str());
8426 return true;
8429 CMessage msgout("EVENT_BOT_SHEET");
8430 msgout.serial(messageVersion);
8431 msgout.serial(botName);
8432 msgout.serial(sheetId);
8433 msgout.serial(bAutoSpawnDespawn);
8434 msgout.serial(sCustomName);
8435 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
8437 return true;
8440 //----------------------------------------------------------------------------
8441 extern sint32 clientEventSetItemCustomText(CCharacter* character, INVENTORIES::TInventory inventory, uint32 slot, ucstring const& text);
8443 NLMISC_COMMAND(eventSetItemCustomText, "set an item custom text, which replaces help text", "<eId> <inventory> <slot in inventory> <text>")
8445 if (args.size() < 4)
8446 return false;
8448 GET_CHARACTER
8449 if (!c)
8451 log.displayNL("Invalid character '%s'", args[0].c_str());
8452 return true;
8454 INVENTORIES::TInventory inventory;
8455 uint32 slot;
8456 ucstring text;
8457 inventory = INVENTORIES::toInventory(args[1]);
8458 NLMISC::fromString(args[2], slot);
8459 text.fromUtf8(args[3]);
8461 sint32 ret = clientEventSetItemCustomText(c, inventory, slot, text);
8463 switch (ret)
8465 case 0:
8466 log.displayNL("Item in slot %u has now the custom text \"%s\"", slot, text.toUtf8().c_str());
8467 break;
8468 case -1:
8469 log.displayNL("'%s' is not a valid inventory name", args[1].c_str());
8470 break;
8471 case -2:
8472 log.displayNL("Invalid slot %u", slot);
8473 break;
8474 case -3:
8475 log.displayNL("Empty slot %u", slot);
8476 break;
8477 default:
8478 log.displayNL("Unknown error");
8480 return true;
8483 //----------------------------------------------------------------------------
8484 NLMISC_COMMAND(eventResetItemCustomText, "set an item custom text, which replaces help text", "<eId> <inventory> <slot in inventory>")
8486 if (args.size() < 3)
8488 log.displayNL("not enough parameters");
8489 return false;
8492 GET_CHARACTER
8493 INVENTORIES::TInventory inventory = INVENTORIES::toInventory(args[1]);
8494 if (inventory==INVENTORIES::UNDEFINED)
8496 log.displayNL("'%s' is not a valid inventory name", args[1].c_str());
8497 return true;
8499 uint32 slot;
8500 NLMISC::fromString(args[2], slot);
8501 CInventoryPtr invent = c->getInventory(inventory);
8502 if (slot >= invent->getSlotCount())
8504 log.displayNL("Invalid slot %u max = %u", slot, invent->getSlotCount()-1);
8505 return true;
8507 if (invent->getItem(slot) == NULL)
8509 log.displayNL("empty slot %u", slot);
8510 return true;
8513 CGameItemPtr item = invent->getItem(slot);
8514 item->setCustomText(ucstring());
8515 // Following line was commented out by trap, reason unknown
8516 c->incSlotVersion(INVENTORIES::bag, slot);
8517 log.displayNL("item in slot %u has now its default text displayed", slot);
8519 return true;
8522 //----------------------------------------------------------------------------
8524 NLMISC_COMMAND(eventSpawnToxic, "Spawn a toxic cloud", "<player eid> <posXm> <posYm> <iRadius{0,1,2}=0> <dmgPerHit=0> <updateFrequency=ToxicCloudUpdateFrequency> <lifetimeInTicks=ToxicCloudDefaultLifetime>" )
8526 if ( args.size() < 1 )
8527 return false;
8529 GET_CHARACTER
8531 float x = (float)c->getX();
8532 float y = (float)c->getY();
8534 if (args.size() > 1)
8536 NLMISC::fromString(args[1], x);
8538 if (args.size() > 2)
8540 NLMISC::fromString(args[2], y);
8543 CVector cloudPos( x, y, 0.0f );
8544 sint iRadius = 0;
8545 sint32 dmgPerHit = 100;
8546 TGameCycle updateFrequency = ToxicCloudUpdateFrequency;
8547 TGameCycle lifetime = CToxicCloud::ToxicCloudDefaultLifetime;
8548 if ( args.size() > 3 )
8550 iRadius = atoi( args[3].c_str() );
8551 if ( args.size() > 4 )
8553 dmgPerHit = atoi( args[4].c_str() );
8554 if ( args.size() > 5 )
8556 updateFrequency = atoi( args[5].c_str() );
8557 if ( args.size() > 6 )
8558 lifetime = atoi( args[6].c_str() );
8563 CToxicCloud *tc = new CToxicCloud();
8564 float radius = (float)(iRadius*2 + 1); // {1, 3, 5} corresponding to the 3 sheets
8565 tc->init( cloudPos, radius, dmgPerHit, updateFrequency, lifetime );
8566 CSheetId sheet( toString( "toxic_cloud_%d.fx", iRadius ));
8567 if ( tc->spawn( sheet ) )
8569 CEnvironmentalEffectManager::getInstance()->addEntity( tc );
8570 log.displayNL( "Toxic cloud spawned (radius %g)", radius );
8572 else
8574 log.displayNL( "Unable to spawn toxic cloud (mirror range full?)" );
8576 return true;
8579 //----------------------------------------------------------------------------
8581 /a eventSpawnDamageLine test_ulu 40900,-12198|40651,-12148 teanwen_haleine
8583 NLMISC_COMMAND(eventSpawnDamageLine, "Spawn a damage line", "<player eid> <name> [<px1,py1|px2,py2|...>] [<dammage>]" )
8585 if ( args.size() < 2 )
8586 return false;
8588 GET_CHARACTER
8589 string path = "";
8590 if (args.size() > 2 )
8591 path = args[2];
8593 string dammage = "";
8594 if (args.size() > 3 )
8595 dammage = args[3];
8597 CZoneManager::getInstance().parseGooBorder( args[1], path, dammage );
8599 return true;
8603 //----------------------------------------------------------------------------
8604 NLMISC_COMMAND(useCatalyser, "use an xp catalyser", "<eId> [<slot in bag>]")
8606 if (args.size() != 2)
8608 log.displayNL("not enough parameters");
8609 return false;
8612 GET_CHARACTER
8613 sint32 slot;
8614 NLMISC::fromString(args[1], slot);
8615 if( slot > 0 )
8617 c->useItem( (uint32)slot );
8620 return true;
8623 //----------------------------------------------------------------------------
8624 NLMISC_COMMAND(eventSetBotFaction, "changes the faction of a bot", "<bot eid> <faction>|default")
8626 if (args.size() < 2) return false;
8628 CEntityId eid(args[0]);
8629 CCreature* creature = CreatureManager.getCreature(eid);
8630 if (creature)
8632 if (args[1]=="default")
8633 creature->resetFaction();
8634 else
8635 creature->setFaction(CStaticFames::getInstance().getFactionIndex(args[1]));
8637 return true;
8640 //----------------------------------------------------------------------------
8641 NLMISC_COMMAND(eventSetBotFameByKill, "set the fame a player win after killing a bot", "<bot eid> <fame>|default")
8643 if (args.size() < 2) return false;
8645 CEntityId eid(args[0]);
8646 sint32 fame = 0;
8647 NLMISC::fromString(args[1], fame);
8648 CCreature* creature = CreatureManager.getCreature(eid);
8649 if (creature)
8651 if (args[1]=="default")
8653 creature->resetFameByKill();
8654 creature->resetFameByKillValid();
8656 else
8658 creature->setFameByKill(fame);
8659 creature->setFameByKillValid(true);
8662 return true;
8665 // Dev only ------------------------------------------------------------------
8666 NLMISC_COMMAND(displayPositionStack, "Display the position stack of a character (top to bottom) (works as soon as player is connected)", "<eid>")
8668 if ( args.size() < 1 )
8669 return false;
8671 // Get character without using GET_CHARACTER to prevent from issueing an "offline command"
8672 CEntityId eid(args[0]);
8673 if (eid == CEntityId::Unknown)
8674 return true;
8675 CCharacter *c = PlayerManager.getChar(eid);
8676 if (c == NULL)
8678 log.displayNL( "Character not found" );
8679 return true;
8681 if ( c->sessionId() == SessionLockPositionStack )
8683 COfflineEntityState st( c->getState() );
8684 log.displayNL( "[STACK LOCKED] Current pos: %s", st.toString().c_str() );
8686 for ( sint p=((sint)(c->PositionStack.size()))-1; p>=0; --p )
8688 log.displayNL( "%u: Session %u, %s", p, c->PositionStack[p].SessionId.asInt(), c->PositionStack[p].PosState.toString().c_str() );
8690 return true;
8693 // Dev only ------------------------------------------------------------------
8694 NLMISC_COMMAND(popPosition, "Remove the top position in the stack of a character", "<eid>")
8696 if ( args.size() < 1 )
8697 return false;
8699 GET_CHARACTER
8700 if ( ! c->PositionStack.empty() )
8702 c->PositionStack.pop();
8703 log.displayNL( "OK, %u remaining in stack", c->PositionStack.size() );
8705 else
8706 log.displayNL( "No pos in stack" );
8707 return true;
8710 //----------------------------------------------------------------------------
8711 NLMISC_COMMAND(farTPPush, "Far TP a character, but let the current position in the stack for returning. Pos in meters.", "<eid> <destSessionId> [<X> <Y> [<Z> [<Heading>]]]")
8713 if ( args.size() < 2 )
8714 return false;
8716 GET_CHARACTER
8718 // Push the new position into the stack
8719 c->pushCurrentPosition();
8720 uint32 sessionId;
8721 NLMISC::fromString(args[1], sessionId);
8722 c->PositionStack.topToModify().SessionId = TSessionId(sessionId);
8723 if ( args.size() > 3 )
8725 NLMISC::fromString(args[2], c->PositionStack.topToModify().PosState.X);
8726 c->PositionStack.topToModify().PosState.X *= 1000;
8727 NLMISC::fromString(args[3], c->PositionStack.topToModify().PosState.Y);
8728 c->PositionStack.topToModify().PosState.Y *= 1000;
8729 if ( args.size() > 4 )
8731 NLMISC::fromString(args[4], c->PositionStack.topToModify().PosState.Z);
8732 c->PositionStack.topToModify().PosState.Z *= 1000;
8733 if ( args.size() > 5 )
8735 NLMISC::fromString(args[5], c->PositionStack.topToModify().PosState.Heading);
8740 // Lock the stack to save it in this state, and make the client Far TP
8741 c->setSessionId( SessionLockPositionStack );
8742 c->requestFarTP( c->PositionStack.topToModify().SessionId );
8743 return true;
8746 //----------------------------------------------------------------------------
8747 NLMISC_COMMAND(farTPReplace, "Far TP a character. Pos in meters. Default values = current values", "<eid> [<destSessionId> [<X> <Y> [<Z> [<Heading>]]]]")
8749 if ( args.size() < 1 )
8750 return false;
8752 GET_CHARACTER
8754 // Modify the top position in the stack
8755 if ( c->PositionStack.empty() )
8756 c->pushCurrentPosition();
8757 if ( args.size() > 1 ) // with the same session id: will make the client reconnect
8759 uint32 sessionId;
8760 NLMISC::fromString(args[1], sessionId);
8761 c->PositionStack.topToModify().SessionId = TSessionId(sessionId);
8762 if ( args.size() > 3 )
8764 NLMISC::fromString(args[2], c->PositionStack.topToModify().PosState.X);
8765 c->PositionStack.topToModify().PosState.X *= 1000;
8766 NLMISC::fromString(args[3], c->PositionStack.topToModify().PosState.Y);
8767 c->PositionStack.topToModify().PosState.Y *= 1000;
8768 if ( args.size() > 4 )
8770 NLMISC::fromString(args[4], c->PositionStack.topToModify().PosState.Z);
8771 c->PositionStack.topToModify().PosState.Z *= 1000;
8772 if ( args.size() > 5 )
8774 NLMISC::fromString(args[5], c->PositionStack.topToModify().PosState.Heading);
8780 // Lock the stack to save it in this state, and make the client Far TP
8781 c->setSessionId( SessionLockPositionStack );
8782 c->requestFarTP( c->PositionStack.topToModify().SessionId, false );
8783 return true;
8786 //----------------------------------------------------------------------------
8787 NLMISC_COMMAND(farTPReturn, "Far TP a character back to the previous session in the stack", "")
8789 if ( args.size() < 1 )
8790 return false;
8792 GET_CHARACTER
8793 c->returnToPreviousSession(~0, ~0, 0);
8794 return true;
8797 //----------------------------------------------------------------------------
8798 NLMISC_COMMAND(farTPSubst, "Substitute a position in the stack (no immediate far TP, does not lock the stack, works as soon as player is connected). Pos in meters. Default values = current values", "<eid> index <sessionId> [<X> <Y> [<Z> [<Heading>]]]")
8800 if ( args.size() < 3 )
8801 return false;
8803 // Get character without using GET_CHARACTER to prevent from issueing an "offline command"
8804 CEntityId eid(args[0]);
8805 if (eid == CEntityId::Unknown)
8806 return true;
8807 CCharacter *c = PlayerManager.getChar(eid);
8808 if (c == NULL)
8810 log.displayNL( "Character not found" );
8811 return true;
8814 // Access the specified position in the stack
8815 uint index;
8816 NLMISC::fromString(args[1], index);
8817 if ( c->PositionStack.size() <= index )
8819 log.displayNL( "Index out of bounds" );
8820 return true;
8823 // Modify
8824 CFarPosition newFarPos = c->PositionStack[index];
8825 uint32 sessionId;
8826 NLMISC::fromString(args[2], sessionId);
8827 newFarPos.SessionId = TSessionId(sessionId);
8828 if ( args.size() > 3 )
8830 NLMISC::fromString(args[3], newFarPos.PosState.X);
8831 newFarPos.PosState.X *= 1000;
8832 NLMISC::fromString(args[4], newFarPos.PosState.Y);
8833 newFarPos.PosState.Y *= 1000;
8834 if ( args.size() > 5 )
8836 NLMISC::fromString(args[5], newFarPos.PosState.Z);
8837 newFarPos.PosState.Z *= 1000;
8838 if ( args.size() > 6 )
8840 newFarPos.PosState.Heading = (float)atof(args[6].c_str());
8844 c->PositionStack.substFarPosition( index, newFarPos );
8845 return true;
8849 //----------------------------------------------------------------------------
8850 NLMISC_COMMAND(teamInvite, "send a team invite to a player character", "<eid> <member name>")
8852 if(args.size() != 2 )
8853 return false;
8855 CEntityId eId;
8856 eId.fromString(args[0].c_str());
8858 // check user
8859 CCharacter * user = PlayerManager.getChar( eId );
8860 if (!user)
8862 log.displayNL("<TEAMINVITE>'%s' is not a valid char. Cant process command",eId.toString().c_str());
8863 return true;
8865 if (!user->getEnterFlag())
8867 log.displayNL("'%s' is not entered", eId.toString().c_str());
8868 return true;
8870 if (!TheDataset.isAccessible(user->getEntityRowId()))
8872 log.displayNL("'%s' is not valid in mirror", eId.toString().c_str());
8873 return true;
8876 // Get target
8877 CCharacter *invitedCharacter= PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(user->getHomeMainlandSessionId(), args[1]));
8878 if (invitedCharacter == NULL || invitedCharacter->getEnterFlag() == false )
8880 CCharacter::sendDynamicSystemMessage( user->getId(),"TEAM_INVITED_CHARACTER_MUST_BE_ONLINE" );
8881 return true;
8884 // Join
8885 user->setAfkState(false);
8886 TeamManager.joinProposal( user, invitedCharacter->getId() );
8888 return true;
8891 //----------------------------------------------------------------------------
8892 NLMISC_COMMAND(leagueInvite, "send a League invite to a player character", "<eid> <player name>")
8894 if(args.size() != 2 )
8895 return false;
8897 CEntityId eId;
8898 eId.fromString(args[0].c_str());
8900 // check user
8901 CCharacter * user = PlayerManager.getChar( eId );
8902 if (!user)
8904 log.displayNL("<LEAGUE_INVITE>'%s' is not a valid char. Cant process command",eId.toString().c_str());
8905 return true;
8907 if (!user->getEnterFlag())
8909 log.displayNL("'%s' is not entered", eId.toString().c_str());
8910 return true;
8912 if (!TheDataset.isAccessible(user->getEntityRowId()))
8914 log.displayNL("'%s' is not valid in mirror", eId.toString().c_str());
8915 return true;
8918 // Get target
8919 CCharacter *invitedCharacter= PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(user->getHomeMainlandSessionId(), args[1]));
8920 if (invitedCharacter == NULL || invitedCharacter->getEnterFlag() == false )
8922 CCharacter::sendDynamicSystemMessage( user->getId(),"TEAM_INVITED_CHARACTER_MUST_BE_ONLINE" );
8923 return true;
8926 // Join
8927 user->setAfkState(false);
8928 TeamManager.joinLeagueProposal( user, invitedCharacter->getId() );
8930 return true;
8933 //----------------------------------------------------------------------------
8934 NLMISC_COMMAND(leagueKick, "kick a player character from league", "<eid> <member name>")
8936 if(args.size() != 2 )
8937 return false;
8939 CEntityId eId;
8940 eId.fromString(args[0].c_str());
8942 // check user
8943 CCharacter * user = PlayerManager.getChar( eId );
8944 if (!user)
8946 log.displayNL("<LEAGUE_INVITE>'%s' is not a valid char. Cant process command",eId.toString().c_str());
8947 return true;
8949 if (!user->getEnterFlag())
8951 log.displayNL("'%s' is not entered", eId.toString().c_str());
8952 return true;
8954 if (!TheDataset.isAccessible(user->getEntityRowId()))
8956 log.displayNL("'%s' is not valid in mirror", eId.toString().c_str());
8957 return true;
8960 // Get target
8961 CCharacter *invitedCharacter= PlayerManager.getCharacterByName(CShardNames::getInstance().makeFullNameFromRelative(user->getHomeMainlandSessionId(), args[1]));
8962 if (invitedCharacter == NULL || invitedCharacter->getEnterFlag() == false )
8964 CCharacter::sendDynamicSystemMessage( user->getId(),"TEAM_INVITED_CHARACTER_MUST_BE_ONLINE" );
8965 return true;
8968 // Kick
8969 user->setAfkState(false);
8971 CTeam * team = TeamManager.getTeam( user->getTeamId() );
8972 if (!team)
8973 return true;
8975 if (team->getLeader() != eId )
8976 return true;
8978 if (user->getLeagueId() != invitedCharacter->getLeagueId())
8979 return true;
8981 team = TeamManager.getTeam( invitedCharacter->getTeamId() );
8982 if (!team) {
8983 invitedCharacter->setLeagueId(DYN_CHAT_INVALID_CHAN);
8984 } else {
8985 team->setLeagueId(DYN_CHAT_INVALID_CHAN);
8986 team->updateLeague();
8989 return true;
8994 //----------------------------------------------------------------------------
8995 NLMISC_COMMAND(resetPVPTimers, "Reset the pvp timers of a player", "<CSR eId><player name>")
8997 if ( args.size() < 2 )
8998 return false;
9000 GET_CHARACTER
9002 CCharacter * target = PlayerManager.getCharacterByName( CShardNames::getInstance().makeFullNameFromRelative(c->getHomeMainlandSessionId(),args[1] ));
9003 if ( !target || !TheDataset.isAccessible( target->getEntityRowId() ) )
9005 CCharacter::sendDynamicSystemMessage( eid, "CSR_BAD_TARGET" );
9006 return true;
9008 CHECK_RIGHT( c,target );
9010 target->resetPVPTimers();
9012 return true;
9016 //----------------------------------------------------------------------------
9017 NLMISC_COMMAND(revive, "player revives at full health at his location", "<eId>")
9019 if ( args.size() < 1 )
9020 return false;
9022 GET_CHARACTER
9024 c->revive();
9026 return true;
9030 //----------------------------------------------------------------------------
9031 NLMISC_COMMAND(quitDelay, "Inform the player that the shard will be stopped in N seconds", "<timeBeforeShutdown>")
9033 if (args.size() != 1)
9034 return false;
9036 sint delay;
9037 NLMISC::fromString(args[0], delay);
9039 SM_STATIC_PARAMS_1(params, STRING_MANAGER::integer);
9041 params[0].Int = delay;
9043 IPlayerManager &pm = CPlayerManager::getInstance();
9045 const IPlayerManager::TMapPlayers &players = pm.getPlayers();
9047 IPlayerManager::TMapPlayers::const_iterator first(players.begin()), last(players.end());
9048 for (; first != last; ++first)
9050 CCharacter * character = pm.getActiveChar(first->first);
9052 if (character != NULL)
9054 CCharacter::sendDynamicSystemMessage(TheDataset.getDataSetRow(character->getId()), "SHUTDOWN_WARNING", params);
9058 return true;
9061 //----------------------------------------------------------------------------
9062 NLMISC_COMMAND(openTargetApp, "open target app", "<user_id>")
9064 if (args.size() < 1)
9065 return false;
9067 GET_CHARACTER
9069 CCreature* creature = CreatureManager.getCreature(c->getTarget());
9070 if (!creature)
9071 return false;
9073 uint32 program = creature->getBotChatProgram();
9074 if (program & (1 << BOTCHATTYPE::WebPageFlag))
9076 c->sendUrl(creature->getWebPage());
9080 //----------------------------------------------------------------------------
9081 // (ulukyn) Very special case to use with ARK.
9082 // !!! Never let user call openTargetUrl with a custom url or player
9083 // will able to sign any url with server salt.
9084 // It's why the url are hardcoded here
9085 NLMISC_COMMAND(openTargetUrl, "Open target url", "<user_id> [bullying]")
9087 if (args.size() < 1)
9088 return false;
9090 GET_CHARACTER
9092 if (args.size() > 1 && args[1] == "1")
9093 c->sendUrl("app_arcc action=mScript_Run&script_name=TalkNpc&bullying=1&command=reset_all");
9094 else
9095 c->sendUrl("app_arcc action=mScript_Run&script_name=TalkNpc&command=reset_all");
9099 //----------------------------------------------------------------------------
9100 NLMISC_COMMAND(eventSetBotURL, "changes the url of a bot", "<bot eid> [<url>]")
9102 if (args.size() < 1) return false;
9104 CEntityId eid(args[0]);
9105 CCreature* creature = CreatureManager.getCreature(eid);
9106 if (!creature)
9108 log.displayNL("Not a creature");
9109 return false;
9112 uint32 program = creature->getBotChatProgram();
9113 if(!(program & (1<<BOTCHATTYPE::WebPageFlag)))
9115 log.displayNL("Add web program on this creature");
9116 program |= 1 << BOTCHATTYPE::WebPageFlag;
9117 creature->setBotChatProgram(program);
9120 const string &wp = creature->getWebPage();
9121 if(args.size() < 2)
9123 log.displayNL("Remove web program on this creature");
9124 (string &)wp = "";
9125 program &= ~(1 << BOTCHATTYPE::WebPageFlag);
9126 creature->setBotChatProgram(program);
9128 else
9129 (string &)wp = args[1];
9131 log.displayNL("Set url '%s'", creature->getWebPage().c_str());
9133 return true;
9136 //----------------------------------------------------------------------------
9137 NLMISC_COMMAND(eventSetBotURLName, "changes the url name of a bot", "<bot eid> <name>")
9139 if (args.size() < 2) return false;
9141 CEntityId eid(args[0]);
9142 CCreature* creature = CreatureManager.getCreature(eid);
9143 if (!creature)
9145 log.displayNL("Not a creature");
9146 return false;
9149 uint32 program = creature->getBotChatProgram();
9150 if(!(program & (1<<BOTCHATTYPE::WebPageFlag)))
9152 log.displayNL("This creature is not flagged as chat in web 0x%x", program);
9153 return false;
9156 const string &wpn = creature->getWebPageName();
9157 (string &)wpn = args[1];
9159 log.displayNL("Set url name '%s'", creature->getWebPageName().c_str());
9161 return true;
9164 //----------------------------------------------------------------------------
9165 NLMISC_COMMAND(eventNpcSay, "have a bot say a text", "<bot eid> <text to say> <optional mode ('say', 'shout'...)> ")
9167 if (args.size() < 2 || args.size() > 3) return false;
9168 GET_ENTITY
9170 string text(args[1]);
9172 CChatGroup::TGroupType mode = CChatGroup::say;
9173 if (args.size() == 3)
9175 mode = CChatGroup::stringToGroupType(args[2]);
9178 std::string prefix = NLMISC::CSString(text).left(3);
9179 if (NLMISC::nlstricmp(prefix.c_str(), "ID:") == 0)
9181 NLMISC::CSString phrase = NLMISC::CSString(text).right(text.length()-3);
9182 npcChatToChannel(e->getEntityRowId(), mode, phrase);
9184 else
9186 ucstring ucstr = text;
9187 npcChatToChannelSentence(e->getEntityRowId(), mode, ucstr);
9190 return true;
9193 //----------------------------------------------------------------------------
9194 NLMISC_COMMAND(eventSetBotFacing, "Set the direction in which a bot faces", "<bot eid> <angle 0-360|random> [<whole group (0,1)>]")
9196 if (args.size () < 2) return false;
9197 GET_ENTITY
9199 float orientation = 0;
9200 std::string param = args[1];
9201 if (param == "random")
9203 orientation = 6666; // used to specify a random orientation
9205 else
9207 NLMISC::fromString(args[1], orientation);
9208 orientation = (orientation / 360.0 * (NLMISC::Pi * 2.0));
9212 std::vector<std::string> args2;
9214 if (args.size() == 3 && args[2] != "0")
9216 // Do the whole group
9217 args2.push_back(args[0]);
9218 args2.push_back(NLMISC::toString("()facing(%f);", orientation));
9220 else
9222 // This bot only
9223 TAIAlias alias = CAIAliasTranslator::getInstance()->getAIAlias(eid);
9224 args2.push_back(args[0]);
9225 args2.push_back(NLMISC::toString("()facing(\"%s\",%f);", NLMISC::toString(alias).c_str(), orientation));
9228 uint32 instanceNumber = e->getInstanceNumber();
9229 uint32 nbString = args2.size();
9231 CMessage msgout("EVENT_NPC_GROUP_SCRIPT");
9232 uint32 messageVersion = 1;
9233 msgout.serial(messageVersion);
9234 msgout.serial(nbString);
9235 for (uint32 i=0; i<nbString; ++i)
9237 string arg = args2[i];
9238 msgout.serial(arg);
9240 CWorldInstances::instance().msgToAIInstance2(instanceNumber, msgout);
9242 return true;
9247 //----------------------------------------------------------------------------
9248 NLMISC_COMMAND(characterInventoryDump, "Dump character inventory info", "<eid> <inventory> [<from slot> <to slot>]")
9250 if (args.size () < 2)
9252 log.displayNL("Invalid number of parameters. Parameters: <inventory> [<from slot> <to slot>]");
9253 return false;
9255 GET_CHARACTER
9257 string selected_inv = args[1];
9259 CInventoryPtr inventory = getInv(c, selected_inv);
9261 if (inventory == NULL)
9263 log.displayNL("Invalid inventory '%s'.", selected_inv.c_str());
9264 return false;
9267 uint32 start_slot = 0;
9268 uint32 end_slot = inventory->getSlotCount();
9270 if (args.size() == 4)
9272 fromString(args[2], start_slot);
9273 fromString(args[3], end_slot);
9274 start_slot = std::max(uint32(0), start_slot);
9275 end_slot = std::min(end_slot, inventory->getSlotCount());
9278 uint32 j = 0;
9279 string msg;
9280 for (uint32 i = start_slot; i < end_slot; ++i)
9282 CGameItemPtr itemPtr = inventory->getItem(i);
9283 if (itemPtr != NULL)
9285 string sheet = itemPtr->getSheetId().toString();
9286 uint32 quality = itemPtr->quality();
9287 uint32 stacksize = itemPtr->getStackSize();
9289 msg += NLMISC::toString("- Slot %3d: SHEETID: %s QUALITY: %d QUANTITY: %d\n",
9291 sheet.c_str(),
9292 quality,
9293 stacksize);
9295 ++j;
9296 if ( ! (j % 3)) {
9297 log.displayNL(msg.c_str());
9298 msg = "";
9299 j = 0;
9304 log.displayNL("Showing slot %d - %d for inventory '%s':", start_slot, end_slot, selected_inv.c_str());
9305 if (msg.length() > 0)
9307 log.displayNL(msg.c_str());
9309 else {
9310 log.displayNL("Nothing to display.");
9313 return true;
9316 //----------------------------------------------------------------------------
9317 NLMISC_COMMAND(deleteInventoryItem, "Delete an item from a characters inventory", "<eid> <inventory> <slot> <sheetname> <quality> <quantity>")
9319 if (args.size () < 6)
9321 log.displayNL("Invalid number of parameters. Parameters: <inventory> <slot> <sheetname> <quality> <quantity>");
9322 return false;
9325 GET_CHARACTER
9327 string selected_inv = args[1];
9329 sint32 slot = -1;
9330 fromString(args[2], slot);
9332 string sheet_name = args[3];
9334 uint32 quality = 0;
9335 fromString(args[4], quality);
9337 uint32 quantity = 0;
9338 fromString(args[5], quantity);
9340 if (sheet_name.find(".") == string::npos)
9341 sheet_name += ".sitem";
9343 CInventoryPtr inventory = getInv(c, selected_inv);
9345 if (inventory == NULL)
9347 log.displayNL("Invalid inventory '%s'.", selected_inv.c_str());
9348 return false;
9351 if (slot < 0 || quality == 0 || quantity == 0)
9353 log.displayNL("Invalid slot or quantity.");
9354 return false;
9357 const CGameItemPtr itemPtr = inventory->getItem(slot);
9358 if (itemPtr != NULL)
9360 if (itemPtr->getSheetId().toString() == sheet_name &&
9361 itemPtr->quality() == quality &&
9362 itemPtr->getStackSize() >= quantity)
9364 log.displayNL("Deleted item '%s' in slot %d of inventory '%s'",
9365 itemPtr->getSheetId().toString().c_str(),
9366 slot,
9367 INVENTORIES::toString(inventory->getInventoryId()).c_str()
9369 inventory->deleteStackItem(slot, quantity);
9370 return true;
9372 log.displayNL("Incorrect sheetid, quality, or quantity.");
9373 return false;
9376 log.displayNL("Invalid slot or item.");
9377 return false;
9380 //----------------------------------------------------------------------------
9381 NLMISC_COMMAND (resetName, "Reset your name; undo a temporary rename", "<user id>")
9383 GET_CHARACTER
9384 c->registerName();
9385 return true;
9388 //----------------------------------------------------------------------------
9389 NLMISC_COMMAND(showOnline, "Set friend visibility", "<user id> <mode=0,1,2>")
9391 if (args.size() < 2) return false;
9392 GET_CHARACTER;
9394 uint8 mode = 0;
9395 NLMISC::fromString(args[1], mode);
9396 if (mode < NB_FRIEND_VISIBILITY)
9398 c->setFriendVisibility((TFriendVisibility)mode);
9400 return true;
9403 //----------------------------------------------------------------------------
9404 NLMISC_COMMAND (lockItem, "Lock/unlock item in inventory", "<user id> <inventory> <slot> <lock=0,1>")
9406 if (args.size () < 4) return false;
9407 GET_CHARACTER;
9409 string selected_inv = args[1];
9410 bool lock = (args[3] != "0");
9411 sint32 slot = -1;
9412 fromString(args[2], slot);
9414 if (selected_inv == "guild") return false;
9416 CInventoryPtr inventory = getInv(c, selected_inv);
9417 if (inventory == NULL) return false;
9419 if (slot < 0 || slot >= INVENTORIES::NbBagSlots) return false;
9421 const CGameItemPtr itemPtr = inventory->getItem(slot);
9422 if (itemPtr != NULL)
9424 // If some of the stack is locked for trading, cannot owner-lock.
9425 if (itemPtr->getNonLockedStackSize() < itemPtr->getStackSize())
9427 // TODO: send error message to client?
9428 return false;
9430 itemPtr->setLockedByOwner(lock);
9432 return true;
9435 //----------------------------------------------------------------------------
9436 NLMISC_COMMAND (setTeamLeader, "Set the leader of the team", "<user id> <member>")
9438 if (args.size () < 2) return false;
9439 GET_CHARACTER;
9441 uint8 idx = 0;
9442 fromString(args[1], idx);
9444 CTeam *team = TeamManager.getTeam(c->getTeamId());
9446 if ( ! team)
9448 nlwarning("<TEAM> Invalid team for user %s",c->getId().toString().c_str() );
9449 return false;
9451 if (team->getLeader() != c->getId())
9453 nlwarning("<TEAM> user %s is not leader: cant set leader",c->getId().toString().c_str() );
9454 return false;
9457 // increment the target index as the leader is not in his own team list
9458 ++idx;
9459 team->setLeader(idx);
9460 team->updateMembersDb();
9461 return true;
9464 //----------------------------------------------------------------------------
9465 NLMISC_COMMAND (setLeague, "Set the League of the team", "<user id> [<name>]")
9467 GET_CHARACTER;
9469 CTeam *team = TeamManager.getTeam(c->getTeamId());
9471 if (!team)
9473 if (args.size () != 2)
9474 c->setLeagueId(DYN_CHAT_INVALID_CHAN);
9475 else
9476 CCharacter::sendDynamicSystemMessage( c->getId(),"LEAGUE_INVITOR_NOT_LEADER" );
9477 return true;
9480 if (team->getLeader() != c->getId())
9482 CCharacter::sendDynamicSystemMessage( c->getId(),"LEAGUE_INVITOR_NOT_LEADER" );
9483 return false;
9486 if (args.size () == 2)
9487 team->setLeague(args[1]);
9488 else
9489 team->setLeague("");
9490 return true;
9493 //----------------------------------------------------------------------------
9494 NLMISC_COMMAND(eventGiveControl, "Give control of entity A to entity B", "<eid> <master eid> <slave eid>")
9496 if (args.size() != 3) return false;
9498 CEntityId masterEid(args[1]);
9499 CEntityId slaveEid(args[2]);
9501 nlinfo("%s takes control of %s", args[1].c_str(), args[2].c_str());
9503 CMessage msgout("ACQUIRE_CONTROL");
9504 msgout.serial( slaveEid );
9505 msgout.serial( masterEid );
9506 sint32 local = 0;
9507 msgout.serial( local );
9508 msgout.serial( local );
9509 msgout.serial( local );
9510 sendMessageViaMirror( "GPMS", msgout );
9512 return true;
9515 //----------------------------------------------------------------------------
9516 NLMISC_COMMAND(eventLeaveControl, "Leave control of entity", "<eid> <master eid>")
9518 if (args.size() != 2) return false;
9520 CEntityId masterEid(args[1]);
9522 nlinfo("%s leaves control", args[1].c_str());
9524 CMessage msgout("LEAVE_CONTROL");
9525 msgout.serial( masterEid );
9526 sendMessageViaMirror( "GPMS", msgout );
9528 return true;
9531 //----------------------------------------------------------------------------
9532 NLMISC_COMMAND(setSimplePhrase, "Set an IOS phrase", "<id> <phrase> [<language code>]")
9534 if (args.size() < 2)
9535 return false;
9537 string phraseName = args[0];
9538 ucstring phraseContent;
9539 ucstring phraseText;
9540 phraseContent.fromUtf8(phraseName);
9541 phraseText.fromUtf8(args[1]);
9542 phraseContent += ucstring("(){[");
9543 phraseContent += phraseText;
9544 phraseContent += ucstring("]}");
9546 string msgname = "SET_PHRASE";
9547 bool withLang = false;
9548 string lang = "";
9549 if (args.size() == 3)
9551 lang = args[2];
9552 if (lang != "all")
9554 withLang = true;
9555 msgname = "SET_PHRASE_LANG";
9559 NLNET::CMessage msgout(msgname);
9560 msgout.serial(phraseName);
9561 msgout.serial(phraseContent);
9562 if (withLang)
9563 msgout.serial(lang);
9564 sendMessageViaMirror("IOS", msgout);
9565 return true;