EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
GMCommands.cpp
Go to the documentation of this file.
1  /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Updates: Allan
25 */
26 
30 #include "eve-server.h"
31 
32 #include "Client.h"
33 #include "ConsoleCommands.h"
34 #include "admin/AllCommands.h"
35 #include "admin/CommandDB.h"
37 #include "inventory/InventoryDB.h"
40 #include "map/MapConnections.h"
41 #include "npc/Drone.h"
42 #include "npc/NPC.h"
43 #include "npc/NPCAI.h"
44 #include "system/Damage.h"
45 #include "system/DestinyManager.h"
46 #include "system/SystemManager.h"
47 #include "system/SystemBubble.h"
49 
51  if (args.argCount() < 2) {
52  throw CustomError ("Correct Usage: /search [text]");
53  }
54 
55  const std::string& query = args.arg(1);
56 
57  //an empty query is a bad idea.
58  if (query.length() == 0)
59  throw CustomError ("Usage: /search [text]");
60 
61  std::map<uint32, std::string> matches;
62  if (!db->ItemSearch(query.c_str(), matches))
63  throw CustomError ("Failed to query DB.");
64 
65  std::string result(std::to_string(matches.size()));
66  result += " matches found.<br>";
67 
68  std::map<uint32, std::string>::iterator cur, end;
69  cur = matches.begin();
70  end = matches.end();
71  for(; cur != end; cur++) {
72  result += std::to_string(cur->first);
73  result += ": ";
74  result += cur->second;
75  result += "<br>";
76  }
77 
78  if (10 < matches.size()) {
79  //send the results in an evemail.
80  std::string subject("Search results for ");
81  subject += query;
82 
83  who->SelfEveMail(subject.c_str(), result.c_str());
84 
85  return new PyString("Results sent via evemail.");
86  } else
87  return new PyString(result);
88 }
89 
91 {
92 
93  if (args.argCount() < 3) {
94  throw CustomError ("Correct Usage: /giveisk [entityID ('me'=self)] [amount]");
95  }
96 
97  // Check for target (arg #1) for either a number or the string "me":
98  std::string target = "";
99  if (!args.isNumber(1))
100  {
101  target = args.arg(1);
102  if (target != "me")
103  throw CustomError ("Argument 1 should be an entity ID ('me'=self)");
104  }
105 
106  // If target (arg #1) is not the string "me" then decode number from argument string, otherwise get this character's ID:
107  uint32 entity;
108  if (target == "")
109  entity = atol(args.arg(1).c_str());
110  else
111  entity = who->GetCharacterID();
112 
113  if (!args.isNumber(2))
114  throw CustomError ("Argument 2 should be an amount of ISK");
115  double amount = strtod(args.arg(2).c_str(), NULL);
116 
117  Client* tgt;
118  if (entity >= maxNPCItem)
119  {
120  tgt = sEntityList.FindClientByCharID(entity);
121  if (!tgt)
122  throw CustomError ("Unable to find character %u", entity);
123  }
124  else
125  throw CustomError ("Invalid entityID for characters %u", entity);
126 
127  // GiveCash
128  tgt->AddBalance(amount, Account::CreditType::ISK);
129  return new PyString("Operation successful.");
130 }
131 
133 {
134  if (4 != args.argCount())
135  throw CustomError ("Correct Usage: /pop [message type] [key] [text]");
136 
137  //CustomNotify: notify
138  //ServerMessage: msg
139  //CustomError: error
140 
141  const std::string& msgType = args.arg(1);
142  const std::string& key = args.arg(2);
143  const std::string& text = args.arg(3);
144 
145  Notify_OnRemoteMessage n;
146  n.msgType = msgType;
147  n.args[ key ] = new PyString(text);
148 
149  PyTuple* t = n.Encode();
150  who->SendNotification("OnRemoteMessage", "charid", &t);
151  PySafeDecRef(t);
152 
153  return new PyString("Message sent.");
154 }
155 
157 {
158  int typeID = 0;
159  uint32 actualTypeID = 0;
160  std::string actualTypeName = "";
161  uint32 actualGroupID = 0;
162  uint32 actualCategoryID = 0;
163  double actualRadius = 0.0;
166 
167  // Updated(groove)
168  // "/spawnn" arguments:
169  // #1 = quantity ?
170  // #2 = some double value deviation
171  // #3 = typeID
172 
173  if ((args.argCount() < 4) || (args.argCount() > 4))
174  {
175  throw CustomError ("LOL, we don't know the correct usage of /spawnn, sorry you're S.O.L., BUT it should have 4 arguments.");
176  }
177 
178  // Since we don't know what args 1 and 2 are, we don't care about them right now...
179 
180  if (!args.isNumber(3))
181  throw CustomError ("Argument 3 should be an item type ID");
182 
183  typeID = atoi(args.arg(3).c_str());
184  if (typeID < 34)
185  throw CustomError ("Invalid Type ID.");
186 
187  if (!who->IsInSpace())
188  throw CustomError ("You must be in space to spawn things.");
189 
190  // Search for item type using typeID:
191  if (!db->ItemSearch(typeID, actualTypeID, actualTypeName, actualGroupID, actualCategoryID, actualRadius)) {
192  return new PyString("Unknown typeID or typeName returned no matches.");
193  }
194 
195  GPoint loc(who->GetShipSE()->GetPosition());
196  // Calculate a random coordinate on the sphere centered on the player's position with
197  // a radius equal to the radius of the ship/celestial being spawned times 10 for really good measure of separation:
198  double radius = (actualRadius * 5.0) * (double)(MakeRandomInt(1, 3)); // Scale the distance from player that the object will spawn to between 10x and 15x the object's radius
199  loc.MakeRandomPointOnSphere(radius);
200 
201  // Spawn the item:
202  ItemData idata(
203  actualTypeID,
204  1, // owner is EVE System
205  who->GetLocationID(),
206  flagNone,
207  actualTypeName.c_str(),
208  loc
209  );
210 
211  item = sItemFactory.SpawnItem(idata);
212  if (item.get() == nullptr)
213  throw CustomError ("Unable to spawn item of type %u.", typeID);
214 
216  entity.categoryID = actualCategoryID;
217  entity.groupID = actualGroupID;
218  entity.itemID = item->itemID();
219  entity.itemName = actualTypeName;
220  entity.typeID = actualTypeID;
221  entity.position = loc;
223  entity.allianceID = 1;
224  entity.corporationID = 1;
225  entity.factionID = 1;
226  entity.ownerID = 1;
227 
228  // Actually do the spawn using SystemManager's BuildEntity:
229  if (!who->SystemMgr()->BuildDynamicEntity(entity))
230  return new PyString("Spawn Failed: typeID or typeName not supported.");
231 
232  sLog.Yellow("Command", "%s: Spawned %u.", who->GetName(), typeID);
233 
234  return new PyString("Spawn successful.");
235 }
236 
238 {
239  int spawnCount = 1;
240  uint32 spawnIndex = 0;
241  uint32 maximumSpawnCountAllowed = 100;
242  uint32 actualTypeID = 0;
243  std::string actualTypeName = "";
244  uint32 actualGroupID = 0;
245  uint32 actualCategoryID = 0;
246  double actualRadius = 0.0;
249  double radius;
250  bool offsetLocationSet = false;
251  std::string usage = "Correct Usage: <br><br> /spawn [typeID(int)/typeName(string)] <br><br>With optional spawn count: <br> /spawn [typeID(int)/typeName(string)] [count] <br><br>With optional count and (X,Y,Z) coordinate: <br> /spawn [typeID(int/typeName(string)] [count] [x(float)] [y(float)] [z(float)]";
252 
253  if (!pClient->IsInSpace())
254  throw CustomError ("You must be in space to spawn things.");
255 
256  if (args.argCount() < 2) {
257  throw CustomError (usage.c_str());
258  }
259 
260  if (!args.isNumber(1))
261  throw CustomError ("Argument 1 should be an item type ID");
262 
263  int typeID = atoi(args.arg(1).c_str());
264 
265  // Search for item type using typeID:
266  if (!(db->ItemSearch(typeID, actualTypeID, actualTypeName, actualGroupID, actualCategoryID, actualRadius)))
267  {
268  return new PyString("Unknown typeID or typeName returned no matches.");
269  }
270 
271  if (args.argCount() > 2)
272  {
273  if (!(args.isNumber(2)))
274  throw CustomError ("Argument 3 should be the number of spawns of this type you want to create");
275 
276  spawnCount = atoi(args.arg(2).c_str());
277  if (spawnCount > maximumSpawnCountAllowed)
278  throw CustomError ("Argument 3, spawn count, is allowed to be no more than 100");
279  }
280 
281  // Check to see if the X Y Z optional coordinates were supplied with the command:
282  GPoint offsetLocation;
283  if (args.argCount() > 3)
284  {
285  if (!(args.isNumber(3)))
286  throw CustomError ("Argument 4 should be the X distance from your ship in meters you want the item spawned");
287 
288  if (args.argCount() > 4)
289  {
290  if (!(args.isNumber(4)))
291  throw CustomError ("Argument 5 should be the Y distance from your ship in meters you want the item spawned");
292  }
293  else
294  throw CustomError ("TOO FEW PARAMETERS: %s", usage.c_str());
295 
296  if (args.argCount() > 5)
297  {
298  if (!(args.isNumber(5)))
299  throw CustomError ("Argument 6 should be the Z distance from your ship in meters you want the item spawned");
300  }
301  else
302  throw CustomError ("TOO FEW PARAMETERS: %s", usage.c_str());
303 
304  offsetLocation.x = atoll(args.arg(3).c_str());
305  offsetLocation.y = atoll(args.arg(4).c_str());
306  offsetLocation.z = atoll(args.arg(5).c_str());
307  offsetLocationSet = true;
308  }
309 
310  GPoint loc;
311 
312  for(spawnIndex=0; spawnIndex < spawnCount; ++spawnIndex)
313  {
314  loc = pClient->GetShipSE()->GetPosition();
315 
316  if (offsetLocationSet)
317  {
318  // An X, Y, Z coordinate offset was specified along with the command, so use this to calculate
319  // the final cooridnate of the newly spawned item:
320  loc.x += offsetLocation.x;
321  loc.y += offsetLocation.y;
322  loc.z += offsetLocation.z;
323  }
324  else
325  {
326  // Calculate a random coordinate on the sphere centered on the player's position with
327  // a radius equal to the radius of the ship/celestial being spawned times 10 for really good measure of separation:
328  radius = (actualRadius * 5.0) * (double)(MakeRandomInt(1, 3)); // Scale the distance from player that the object will spawn to between 10x and 15x the object's radius
329  loc.MakeRandomPointOnSphere(radius);
330  }
331 
332  // Spawn the item:
333  ItemData idata(
334  actualTypeID,
335  1, // owner is EVE System
336  pClient->GetLocationID(),
337  flagNone,
338  actualTypeName.c_str(),
339  loc
340  );
341 
342  item = sItemFactory.SpawnItem(idata);
343  if (item.get() == nullptr)
344  throw CustomError ("Unable to spawn item of type %u.", typeID);
345 
347  entity.categoryID = actualCategoryID;
348  entity.groupID = actualGroupID;
349  entity.itemID = item->itemID();
350  entity.itemName = actualTypeName;
351  entity.typeID = actualTypeID;
352  entity.position = loc;
353  // set owner data according to type and location
354  switch (actualCategoryID) {
356  // owned by system rats
357  entity.factionID = sDataMgr.GetRegionRatFaction(pClient->GetRegionID());
358  entity.allianceID = entity.factionID;
359  entity.corporationID = sDataMgr.GetFactionCorp(entity.factionID);
360  entity.ownerID = entity.corporationID;
361  } break;
363  // owned by calling char
364  entity.allianceID = pClient->GetAllianceID();
365  entity.corporationID = pClient->GetCorporationID();
366  entity.factionID = pClient->GetWarFactionID();
367  entity.ownerID = pClient->GetCharacterID();
368  } break;
369  default: {
370  //owned by system sov holder
371  entity.factionID = sDataMgr.GetRegionFaction(pClient->GetRegionID());
372  entity.allianceID = entity.factionID;
373  entity.corporationID = sDataMgr.GetFactionCorp(entity.factionID);
374  entity.ownerID = entity.corporationID;
375  } break;
376  }
377 
378 
379  // Actually do the spawn using SystemManager's BuildEntity:
380  if (!pClient->SystemMgr()->BuildDynamicEntity(entity)) {
381  return new PyString("Spawn Failed: typeID or typeName not supported.");
382  }
383  }
384 
385  sLog.Yellow("Command_spawn", "%s: Spawned %u in space, %u times", pClient->GetName(), typeID, spawnCount);
386 
387  return new PyString("Spawn successful.");
388 }
389 
390 // command to modify blueprint's attributes, we have to give it blueprint's itemID ...
391 // isn't much comfortable, but I don't know about better solution ...
393 {
394  if (args.argCount() < 6)
395  throw CustomError ("Correct Usage: /setbpattr [blueprintID] [0 (not copy) or 1 (copy)] [material level] [productivity level] [remaining runs]");
396  if (!args.isNumber(1))
397  throw CustomError ("Argument 1 must be blueprint ID. (got %s)", args.arg(1).c_str());
398  if ("0" != args.arg(2) && "1" != args.arg(2))
399  throw CustomError ("Argument 2 must be 0 (original) or 1 (copy). (got %s)", args.arg(2).c_str());
400  if (!args.isNumber(3))
401  throw CustomError ("Argument 3 must be material level. (got %s)", args.arg(3).c_str());
402  if (!args.isNumber(4))
403  throw CustomError ("Argument 4 must be productivity level. (got %s)", args.arg(4).c_str());
404  if (!args.isNumber(5))
405  throw CustomError ("Argument 5 must be remaining licensed production runs. (got %s)", args.arg(5).c_str());
406 
407  int blueprintID = atoi(args.arg(1).c_str());
408  BlueprintRef bp = sItemFactory.GetBlueprint(blueprintID);
409  if (!bp)
410  throw CustomError ("Failed to load blueprint %u.", blueprintID);
411 
412  // these need to check current settings to see if anything changed
413  bp->SetCopy((atoi(args.arg(2).c_str()) ? true : false));
414  bp->SetMLevel(atoi(args.arg(3).c_str()));
415  bp->SetPLevel(atoi(args.arg(4).c_str()));
416  bp->SetRuns(atoi(args.arg(5).c_str()));
417 
418  return new PyString("Properties modified.");
419 }
420 
422 {
439  //return item->attributes.PyGet(attribute);
440  //return item->GetAttribute(attribute).GetPyObject();
441  return nullptr;
442 }
443 
445 {
446  throw CustomError ("disabled");
447  if (0) {
448  if (args.argCount() < 4) {
449  throw CustomError ("Correct Usage: /setattr [itemID] [attributeID] [value]");
450  }
451 
452  // Check for target (arg #1) for either a number or the string "myship":
453  int itemID = 0;
454  std::string target = "";
455  if (!args.isNumber(1))
456  {
457  target = args.arg(1);
458  if (target != "myship")
459  throw CustomError ("1st argument should be an entity ID ('myship'=current ship) (got %s).", args.arg(1).c_str());
460 
461  itemID = who->GetShipID();
462  }
463  else
464  {
465  // target (arg #1) is a number, so decode it and move on:
466  itemID = atoi(args.arg(1).c_str());
467  }
468 
469  if (!args.isNumber(2))
470  throw CustomError ("2nd argument must be attributeID (got %s).", args.arg(2).c_str());
471  //const ItemAttributeMgr::Attr attribute = (ItemAttributeMgr::Attr)atoi(args.arg(2).c_str());
472 
473  if (!args.isNumber(3))
474  throw CustomError ("3rd argument must be value (got %s).", args.arg(3).c_str());
475  //const double value = atof(args.arg(3).c_str());
476 
477  if (itemID < minPlayerItem)
478  throw CustomError ("1st argument must be a valid 'entity' table itemID that MUST be larger >= 140000000. (got %s)", args.arg(1).c_str());
479 
480  InventoryItemRef item = sItemFactory.GetItem(itemID);
481  if (item.get() == nullptr)
482  throw CustomError ("Failed to load item %u.", itemID);
483 
484  //item->attributes.SetReal(attribute, value);
485  sLog.Warning("GMCommands: Command_setattr()", "This command will modify attribute and send change to client, but change does not take effect in client for some reason.");
486  // item->SetAttribute(attribute, (float)value);
487 
488  return new PyString("Operation successful.");
489  }
490 }
491 
493 {
494 
495  throw CustomError ("This command is currently disabled.");
496 /*
497  uint32 typeID = 0;
498  uint32 itemID = 0;
499  EVEItemFlags flag = (EVEItemFlags)0;
500  uint32 powerSlot = 0;
501  uint32 useableSlot = 0;
502  std::string affectName = "online";
503 
504  if (args.argCount() < 3) {
505  throw CustomError ("Correct Usage: /fit [me|itemID] [typeID] [flag=??]");
506  }
507 
508  // DNA tells us what slot to use but we're going to ignore it
509  if (args.arg(1) == "me") {
510  itemID = who->GetShip()->itemID();
511  } else {
512  itemID = atoi(args.arg(1).c_str());
513  }
514 
515  typeID = atoi(args.arg(2).c_str());
516  if (args.argCount() >= 4) {
517  std::string::size_type n = args.arg(3).find("flag=");
518  if (n != std::string::npos) {
519  flag = (EVEItemFlags)atoi(args.arg(3).substr(5).c_str());
520  }
521  }
522 
523 
524  if (typeID == 0) {
525  throw PyException(MakeCustomError("Unable to create item of type %u.", typeID));
526  } else {
527  ItemData idata(
528  typeID,
529  who->GetCharacterID(),
530  30002187, //temp location
531  flagHangar,
532  1
533  );
534 
535  InventoryItemRef i = sItemFactory.SpawnItem(idata);
536  if (!i) {
537  throw PyException(MakeCustomError("Unable to create item of type %u.", typeID));
538  }
539 
540  //ShipItemRef ship = services->item_factory->GetShip(itemID);
541  //who->MoveItem(i->itemID(), itemID, flag);
542  //i->Move(itemID, flag);
543  //ship->AddItem(i);
544 
545  //return new PyBool(true);
546  }
547  //return new PyBool(false);
548  return PyStatic.NewOne();
549  */
550 }
551 
553  uint8 level = 5; // Ensure that ALL skills are trained to level 5
555  uint32 ownerID = 0;
556  Client * pTarget = NULL;
557 
558  if (args.argCount() >= 2) {
559  if (args.isNumber(1)) {
560  ownerID = atoi(args.arg(1).c_str());
561  pTarget = sEntityList.FindClientByCharID(ownerID);
562  if (!pTarget)
563  throw CustomError ("ERROR: Cannot find character #%d", ownerID);
564  else
565  character = pTarget->GetChar();
566  } else if (args.arg(1) == "me") {
567  ownerID = who->GetCharacterID();
568  character = who->GetChar();
569  pTarget = who;
570  } else if (!args.isNumber(1)) {
571  throw CustomError ("The use of string based Character names for this command is not yet supported! Use 'me' instead or the entityID of the character to which you wish to give skills.");
572  /*
573  * const char *name = args.arg(1).c_str();
574  * Client *target = sEntityList.FindCharacter(name);
575  * if (target == NULL)
576  * throw PyException(MakeCustomError("Cannot find Character by the name of %s", name));
577  * ownerID = target->GetCharacterID();
578  * character = target->GetChar();
579  */
580  } else
581  throw CustomError ("Argument 1 must be Character ID or Character Name ");
582  } else
583  throw CustomError ("Correct Usage: /giveallskills [Character Name or ID]");
584 
585  // Make sure character reference is not NULL before trying to use it:
586  if (character.get()) {
587  // Query Database to get list of ALL skills, then LOOP through each one, checking character for skill, setting level to 5:
588  std::vector<uint32> skillList;
589  db->FullSkillList(skillList);
590 
591  SkillRef skill;
592  //uint8 oldLevel = 0;
593  uint16 skillID = 0;
594  //uint32 oldPoints = 0, newPoints = 0;
595 
596  std::vector<uint32>::const_iterator cur = skillList.begin();
597  for (; cur != skillList.end(); ++cur) {
598  skillID = *cur;
599  if (character->HasSkillTrainedToLevel(skillID, level)) {
600  return PyStatic.NewNone();
601  } else if (character->HasSkill(skillID)) {
602  skill = character->GetSkill(skillID);
603  //oldLevel = skill->GetAttribute(AttrSkillLevel).get_uint32();
604  //oldPoints = skill->GetAttribute(AttrSkillPoints).get_uint32();
605  skill->SetAttribute(AttrSkillLevel, level);
606  skill->SetAttribute(AttrSkillPoints, skill->GetSPForLevel(level));
607  if (skill->flag() == flagSkillInTraining) {
608  skill->SetFlag(flagSkill, false);
609  }
610  } else { // Character DOES NOT have this skill
611  ItemData idata(skillID, ownerID, ownerID, flagSkill, 1);
612  InventoryItemRef item = sItemFactory.SpawnItem(idata);
613 
614  if (item.get() == nullptr) {
615  throw CustomError ("Unable to create item of type %s.", item->typeID());
616  } else {
617  skill = SkillRef::StaticCast(item);
618  skill->SetAttribute(AttrSkillLevel, level);
619  skill->SetAttribute(AttrSkillPoints, skill->GetSPForLevel(level));
620  }
621  }
622 
623  // save gm skill gift in history -allan
624  // maybe not for this....WAAAAYYY to much DB traffic for this.
625  //character->SaveSkillHistory(EvESkill::Event::GMGift, Win32TimeNow(), ownerID, skillID.get_uint32(), level, \
626  skill->GetAttribute(AttrSkillPoints).get_double());
627  }
628  // END LOOP
629  pTarget->SendErrorMsg("You need to relog for skills to get saved and show in character sheet.");
630  return new PyString ("Gifting skills complete");
631  }
632 
633  return new PyString ("Skill Gifting Failure");
634 }
635 
637  //pass to command_giveskill
638  Command_giveskill(who, db, services, args);
639  return nullptr;
640 }
641 
643  uint32 ownerID = 0, skillID = 0, level = 0;
644  uint32 newPoints = 0;
646  Client *pTarget(nullptr);
647 
648  if (args.argCount() == 4) {
649  if (args.isNumber(1)) {
650  ownerID = atoi(args.arg(1).c_str());
651  character = sEntityList.FindClientByCharID(ownerID)->GetChar();
652  pTarget = character->GetClient();
653  } else if (args.arg(1) == "me") {
654  ownerID = who->GetCharacterID();
655  character = who->GetChar();
656  pTarget = who;
657  } else if (!args.isNumber(1)) {
658  throw CustomError ("The use of string based Character names for this command is not yet supported! Use 'me' instead or the entityID of the character to which you wish to give skills.");
659  /*
660  const char *name = args.arg(1).c_str();
661  pTarget = sEntityList.FindClientByName(name);
662  if (!pTarget)
663  throw PyException(MakeCustomError("Cannot find Character by the name of %s", name));
664  ownerID = pTarget->GetCharacterID();
665  character = pTarget->GetChar();
666  */
667  } else
668  throw CustomError ("Argument 1 must be Character ID or Character Name ");
669 
670  if (!args.isNumber(2))
671  throw CustomError ("Argument 2 must be type ID.");
672  skillID = atoi(args.arg(2).c_str());
673 
674  if (!args.isNumber(3))
675  throw CustomError ("Argument 3 must be level");
676  level = atoi(args.arg(3).c_str());
677 
678  if (level > EvESkill::MAXSKILLLEVEL)
679  level = EvESkill::MAXSKILLLEVEL;
680  } else
681  throw CustomError ("Correct Usage: .giveskill [me/CharacterID] [skillID] [level]");
682 
683  // Make sure references are not NULL before trying to use them
684  if ((pTarget == nullptr) or (character.get() == nullptr))
685  throw CustomError ("ERROR: Unable to validate character object.");
686 
687  SkillRef skill;
688  if (character->HasSkillTrainedToLevel(skillID, level)) {
689  // already trained to requested level
690  return PyStatic.NewNone();
691  } else if (character->HasSkill(skillID)) {
692  // has skill injected, so update level
693  skill = character->GetSkill(skillID);
694  if (skill.get() == nullptr){
695  throw CustomError ("Unable to get item for skillID %u.", skillID);
696  return new PyString ("Skill Gifting Failure - Unable to get item for skillID %u.", skillID);
697  }
698  newPoints = skill->GetSPForLevel(level);
699  skill->SetAttribute(AttrSkillLevel, level);
700  skill->SetAttribute(AttrSkillPoints, newPoints);
701  //check for and remove this skill from training queue
702  character->RemoveFromQueue(skill);
703  } else {
704  // Character does not have this skill
705  std::ostringstream str;
706  str << "Skill Gift by ";
707  str << who->GetCharName();
708  ItemData idata(skillID, ownerID, pTarget->GetLocationID(), flagSkill, 1, str.str().c_str());
709  skill = sItemFactory.SpawnSkill(idata);
710  if (skill.get() == nullptr)
711  throw CustomError ("Unable to create item for skillID %u.", skillID);
712 
713  newPoints = skill->GetSPForLevel(level);
714  skill->SetAttribute(AttrSkillLevel, level);
715  skill->SetAttribute(AttrSkillPoints, newPoints);
716  skill->ChangeSingleton(true);
717  skill->Move(pTarget->GetCharacterID(), flagSkill, true);
718  }
719 
720  skill->SaveItem();
721  // save gm skill gift in history -allan
722  character->SaveSkillHistory(EvESkill::Event::GMGift, GetFileTimeNow(), ownerID, skillID, level, newPoints);
723 
724  OnAdminSkillChange oasc;
725  oasc.skillItemID = skill->itemID();
726  oasc.skillTypeID = skillID;
727  oasc.newSP = newPoints;
728  PyTuple* tmp = oasc.Encode();
729  pTarget->QueueDestinyEvent(&tmp);
730 
731  _log(SKILL__MESSAGE, "GiveSkill - skill %u set to level %u with %u SP.", skillID, level, newPoints);
732  return PyStatic.NewNone();
733 }
734 
736 
737  if (args.argCount() == 2)
738  {
739  if (strcmp("me", args.arg(1).c_str())!=0)
740  if (!args.isNumber(1))
741  throw CustomError ("Argument 1 should be an entity ID or me (me=self)");
742  uint32 entity = atoi(args.arg(1).c_str());
743 
744  Client* tgt;
745  if (strcmp("me", args.arg(1).c_str())==0)
746  tgt = who;
747  else
748  {
749  tgt = sEntityList.FindClientByCharID(entity);
750  if (!tgt)
751  throw CustomError ("Unable to find character %u", entity);
752  }
753 
754  if (!tgt->InPod())
755  tgt->GetShip()->OnlineAll();
756  else
757  throw CustomError ("Command failed: You can't activate modules while in a pod");
758 
759  return(new PyString("All modules have been put Online"));
760  }
761  else
762  throw CustomError ("Command failed: You got the arguments all wrong.");
763 }
764 
766 // this means 'remove'
767 
768  if (args.argCount() >= 2 && args.argCount() <= 3)
769  {
770  uint32 itemID=0,entityID=0;
771 
772  if (strcmp("me", args.arg(1).c_str())!=0)
773  if (!args.isNumber(1))
774  {
775  throw CustomError ("Argument 1 should be an entity ID or me (me=self)");
776  }
777  entityID = atoi(args.arg(1).c_str());
778 
779  if (args.argCount() ==3)
780  {
781  if (strcmp("all", args.arg(2).c_str())!=0)
782  if (!args.isNumber(2))
783  throw CustomError ("Argument 2 should be an item ID or all");
784  itemID = atoi(args.arg(2).c_str());
785  }
786 
787  //select character
788  Client* tgt(nullptr);
789  if (strcmp("me", args.arg(1).c_str())==0)
790  tgt = who;
791  else
792  {
793  tgt = sEntityList.FindClientByCharID( entityID );
794 
795  if (!tgt)
796  throw CustomError ("Unable to find character %u", entityID );
797  }
798 
800  //if (tgt->IsInSpace())
801  // throw CustomError ("Character needs to be docked.");
802 
803  if (args.argCount() == 3 && strcmp("all", args.arg(2).c_str())!=0)
804  tgt->GetShip()->GetModuleManager()->UnfitModule( itemID );
805 
806  if (args.argCount() == 3 && strcmp("all", args.arg(2).c_str())==0)
807  tgt->GetShip()->UnloadAllModules();
808 
809  return(new PyString("All Modules have been unloaded"));
810  }
811  else
812  throw CustomError ("Command failed: You got the arguments all wrong.");
813 }
814 
816 {
817 
818  if (args.argCount()==1)
819  who->GetShip()->RepairModules();
820  if (args.argCount()==2) {
821  if (!args.isNumber(1))
822  throw CustomError ("Argument 1 should be a character ID");
823  uint32 charID = atoi(args.arg(1).c_str());
824 
825  Client *target = sEntityList.FindClientByCharID(charID);
826  if (target == NULL)
827  throw CustomError ("Cannot find CharacterID %u", charID);
828  target->GetShip()->RepairModules();
829  }
830 
831  return(new PyString("Modules repaired successful."));
832 }
833 
835 {
836  //"dogma" "140019878" "agility" "=" "0.2"
837 
838  if (!(args.argCount() == 5)) {
839  throw CustomError ("Correct Usage: /dogma [itemID|me] [attributeName] = [value]");
840  }
841 
842  // First argument could be both
843  if (args.isNumber(2)) {
844  throw CustomError ("/dogma Second argument must be a string");
845  }
846 
847  if (args.arg(3) != "=") {
848  throw CustomError ("/dogma You didn't use an '=' in between your attribute name and value.");
849  }
850  if (!args.isNumber(4)) {
851  throw CustomError ("/dogma The last argument must be a number");
852  }
853 
854  const char *attributeName = args.arg(2).c_str();
855  float attributeValue = atof(args.arg(4).c_str());
856 
858  if (args.arg(1) == "me") {
859  i = sItemFactory.GetItem(who->GetShip().get()->itemID());
860  } else {
861  i = sItemFactory.GetItem(atoi(args.arg(1).c_str()));
862  }
863 
864 
865  i->SetAttribute(db->GetAttributeID(attributeName), attributeValue);
868  return nullptr;
869 }
870 
872 {
873  Client *target;
874  if (args.argCount() == 2) {
875  if (args.isNumber(1)) {
876  int id = atoi(args.arg(1).c_str());
877  target = sEntityList.FindClientByCharID(id);
878  } else {
879  const char *name = args.arg(1).c_str();
880  target = sEntityList.FindClientByName(name);
881  }
882  }
883  //support for characters with first and last names
884  else if (args.argCount() == 3) {
885  if (args.isHexNumber(1))
886  throw CustomError ("Unknown arguments");
887 
888  std::string name = args.arg(1) + " " + args.arg(2);
889  target = sEntityList.FindClientByName(name.c_str()) ;
890  } else {
891  throw CustomError ("Correct Usage: /kick [Character Name]");
892  }
893 
894  if (target == NULL) {
895  throw CustomError ("Cannot find Character");
896  } else {
897  target->DisconnectClient();
898  }
899 
900  return nullptr;
901 }
902 
904 {
905  Client *target;
906 
907  if (args.argCount() == 2)
908  {
909 
910  if (!args.isNumber(1))
911  {
912  const char *name = args.arg(1).c_str();
913  target = sEntityList.FindClientByName(name);
914  }
915  else
916  throw CustomError ("Correct Usage: /ban [Character Name]");
917  }
918  //support for characters with first and last names
919  else if (args.argCount() == 3)
920  {
921  if (args.isHexNumber(1))
922  throw CustomError ("Unknown arguments");
923 
924  std::string name = args.arg(1) + " " + args.arg(2);
925  target = sEntityList.FindClientByName(name.c_str()) ;
926  }
927  else
928  throw CustomError ("Correct Usage: /ban [Character Name]");
929 
930  //ban client
931  target->BanClient();
932 
933  //disconnect client
934  target->DisconnectClient();
935 
936  return nullptr;
937 }
938 
940 {
941  if (args.argCount() == 2)
942  {
943 
944  if (!args.isNumber(1))
945  {
946  const char *name = args.arg(1).c_str();
948  }
949  else
950  throw CustomError ("Correct Usage: /ban [Character Name]");
951  }
952  //support for characters with first and last names
953  else if (args.argCount() == 3)
954  {
955  if (args.isHexNumber(1))
956  throw CustomError ("Unknown arguments");
957 
958  std::string name = args.arg(1) + " " + args.arg(2);
960  }
961  else
962  throw CustomError ("Correct Usage: /unban [Character Name / Character ID]");
963 
964  return nullptr;
965 }
uint32 GetShipID() const
Definition: Client.h:150
int GetAccountID(std::string name)
Definition: CommandDB.cpp:193
unsigned __int8 uint8
Definition: eve-compat.h:46
SkillRef GetSkill(uint16 skillTypeID) const
Definition: Character.cpp:566
void SendNotification(const PyAddress &dest, EVENotificationStream &noti, bool seq=true)
Definition: Client.cpp:2245
PyResult Command_giveskills(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:636
uint32 GetLocationID() const
Definition: Client.h:151
void SendErrorMsg(const char *fmt,...)
Definition: Client.cpp:2719
#define _log(type, fmt,...)
Definition: logsys.h:124
bool ItemSearch(const char *query, std::map< uint32, std::string > &into)
Definition: CommandDB.cpp:89
#define maxNPCItem
Definition: EVE_Defines.h:139
const std::string & arg(size_t index) const
Definition: Seperator.h:43
Python string.
Definition: PyRep.h:430
void DisconnectClient()
Definition: Client.cpp:2279
#define minPlayerItem
Definition: EVE_Defines.h:149
ModuleManager * GetModuleManager()
Definition: Ship.h:80
void UnfitModule(uint32 itemID)
void SaveSkillHistory(uint16 eventID, double logDate, uint32 characterID, uint16 skillTypeID, uint8 skillLevel, uint32 absolutePoints)
Definition: Character.cpp:689
uint32 GetRegionID() const
Definition: Client.h:154
PyResult Command_getattr(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:421
void QueueDestinyEvent(PyTuple **multiEvent)
Definition: Client.cpp:2124
PyResult Command_ban(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:903
int32 GetCharacterID() const
Definition: Client.h:113
int32 GetWarFactionID() const
Definition: Client.h:126
PyResult Command_pop(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:132
int32 GetCorporationID() const
Definition: Client.h:123
#define sEntityList
Definition: EntityList.h:208
bool FullSkillList(std::vector< uint32 > &skillList)
Definition: CommandDB.cpp:213
static void SetAccountBanStatus(uint32 accountID, bool banned=false)
Definition: ServiceDB.cpp:205
bool IsInSpace()
Definition: Client.h:228
Separates string to arguments.
Definition: Seperator.h:36
CharacterRef GetChar() const
Definition: Client.h:164
Python tuple.
Definition: PyRep.h:567
GaFloat x
Definition: GaTypes.h:207
bool BuildDynamicEntity(const DBSystemDynamicEntity &entity, uint32 launcherID=0)
PyResult Command_giveallskills(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:552
Advanced version of UserError that allows to send a full custom message.
Definition: PyExceptions.h:453
itemID[count] Create count or of the specified item(from Insider)" ) COMMAND( goto
void SelfEveMail(const char *subject, const char *fmt,...)
int32 GetAllianceID() const
Definition: Client.h:125
const GPoint & GetPosition() const
Definition: SystemEntity.h:211
PyResult Command_unban(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:939
* args
PyResult Command_setbpattr(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:392
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
size_t argCount() const
Definition: Seperator.h:44
typeID Spawn an NPC with the specified type text Search for items matching the specified query() type()() itemID() copy() materialLevel()()() itemID() itemID Fits selected item to active ship() skillID(level)-gives skillID to specified level." ) COMMAND( online
Definition: gpoint.h:33
int GetAttributeID(const char *attributeName)
Definition: CommandDB.cpp:163
PyResult Command_fit(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:492
PyResult Command_kick(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:871
bool isHexNumber(size_t index) const
Definition: Seperator.h:47
SystemManager * SystemMgr() const
Definition: Client.h:92
const uint8 MAXSKILLLEVEL
Definition: EvEMath.h:19
PyResult Command_repairmodules(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:815
PyResult Command_setattr(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:444
#define PyStatic
Definition: PyRep.h:1209
PyResult Command_online(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:735
X * get() const
Definition: RefPtr.h:213
void BanClient()
Definition: Client.cpp:2287
PyResult Command_search(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:50
ShipItemRef GetShip() const
Definition: Client.h:167
const char * GetName() const
Definition: Client.h:94
Definition: Client.h:66
itemID[count] Create count or of the specified() x() entityID Translocate to the specified entity Immediately stops ship
static RefPtr StaticCast(const RefPtr< Y > &oth)
Acts as static_cast from one RefPtr to another.
Definition: RefPtr.h:238
unsigned __int32 uint32
Definition: eve-compat.h:50
PyResult Command_unload(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:765
std::string GetCharName()
Definition: Client.h:165
PyResult Command_dogma(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:834
GaFloat y
Definition: GaTypes.h:207
bool HasSkillTrainedToLevel(uint16 skillTypeID, uint8 skillLevel) const
Definition: Character.cpp:584
double GetFileTimeNow()
Definition: utils_time.cpp:84
int64 MakeRandomInt(int64 low, int64 high)
Generates random integer from interval [low; high].
Definition: misc.cpp:109
ShipSE * GetShipSE()
Definition: Client.h:168
PyResult Command_spawn(Client *pClient, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:237
bool isNumber(size_t index) const
Definition: Seperator.h:46
void UnloadAllModules()
Definition: Ship.h:132
typeID Spawn an NPC with the specified type text Search for items matching the specified query() type()() itemID() copy() materialLevel()() itemID(attributeID)-Retrieves attribute value." ) COMMAND( setattr
#define PySafeDecRef(op)
Definition: PyRep.h:61
#define sItemFactory
Definition: ItemFactory.h:165
typeID Spawn an NPC with the specified type text Search for items matching the specified query() type() key(value)-Send an OnRemoteMessage" ) COMMAND( setbpattr
PyResult Command_giveskill(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:642
void MakeRandomPointOnSphere(double radius)
Definition: gpoint.h:46
void RepairModules(std::vector< InventoryItemRef > &itemRefVec, float fraction)
Definition: Ship.cpp:981
void RemoveFromQueue(SkillRef sRef)
Definition: Character.cpp:642
unsigned __int16 uint16
Definition: eve-compat.h:48
uint16 typeID() const
PyResult Command_giveisk(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:90
GaFloat z
Definition: GaTypes.h:207
PyResult Command_spawnn(Client *who, CommandDB *db, PyServiceMgr *services, const Seperator &args)
Definition: GMCommands.cpp:156
uint32 itemID() const
Definition: InventoryItem.h:98
bool HasSkill(uint16 skillTypeID) const
Definition: Character.cpp:538
#define sDataMgr
void usage()