EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ModuleManager.cpp
Go to the documentation of this file.
1 /*
2  * ModuleManager.cpp
3  *
4  * this class manages all aspects of modules and charges loaded in ships
5  *
6  * Author: Allan
7  * Started: 30Mar16
8  *
9  * loosely based on original evemu code by Aknor Jaden and Luck
10  */
11 
12 
13 #include "eve-server.h"
14 
15 #include "EVEServerConfig.h"
16 #include "Client.h"
17 #include "StaticDataMgr.h"
18 #include "effects/EffectsDataMgr.h"
19 #include "ship/Ship.h"
24 #include "station/Station.h"
25 #include "system/DestinyManager.h"
26 
27 /*
28  * MODULE__ERROR
29  * MODULE__WARNING
30  * MODULE__MESSAGE
31  * MODULE__INFO
32  * MODULE__TRACE
33  * MODULE__DEBUG
34  * MODULE__DAMAG
35  */
36 
38 : pShipItem(pShip),
39 m_initalized(false),
40 m_rigScanBonus(0),
41 m_LowSlots(0),
42 m_MidSlots(0),
43 m_HighSlots(0),
44 m_RigSlots(0),
45 m_SubSystemSlots(0)
46 {
47  assert(pShip != nullptr);
48 }
49 
51 {
52  std::map<uint8, GenericModule*>::iterator itr = m_modules.begin();
53  for (; itr != m_modules.end(); ++itr)
54  SafeDelete(itr->second);
55 }
56 
58  if (m_initalized)
59  return true;
60 
61  _log(MODULE__TRACE, "MM::Initialize() - ship %s", pShipItem->name() );
62 
68 
69  // modules - 3 banks of 8 slots each
71  m_modules.insert(std::pair<uint8, GenericModule*>(flag, nullptr));
72  m_fittings.insert(std::pair<uint8, GenericModule*>(flag, nullptr));
73  }
74  // rigs - one bank of 3 slots
76  m_modules.insert(std::pair<uint8, GenericModule*>(flag, nullptr));
77  m_systems.insert(std::pair<uint8, GenericModule*>(flag, nullptr));
78  }
79  //subsystems - one bank of 5 slots
81  m_modules.insert(std::pair<uint8, GenericModule*>(flag, nullptr));
82  m_systems.insert(std::pair<uint8, GenericModule*>(flag, nullptr));
83  }
84 
85  // Load modules, rigs and subsystems into module maps:
86  std::vector<InventoryItemRef> itemVec;
87  // this will order by mod, charge, cargo
89  GenericModule* pMod(nullptr);
90  for (auto cur : itemVec) {
91  // this is a hack. dont know why any ship item would have flagNone set, but have seen random errors where charges are set to flagNone
92  if (cur->flag() == flagNone) {
93  _log(MODULE__ERROR, "MM::Initialize() - %s(%u) has flagNone set in ship %s",\
94  cur->name(), cur->itemID(), pShipItem->name() );
95  // put that bitch back in cargo
96  cur->SetFlag(flagCargoHold);
97  }
98  if (IsModuleSlot(cur->flag())) {
99  switch (cur->categoryID()) {
101  _log(MODULE__TRACE, "MM::Initialize() - loading %s(%u) to %s.",\
102  cur->name(), cur->itemID(), sDataMgr.GetFlagName(cur->flag()));
104  // hack to get total scan bonus from rigs, if applicable
105  // do we need to check for and set anything else here?
107  switch (mRef->typeID()) {
108  case 25936: // Large Gravity Capacitor Upgrade I
109  case 31213: // Small Gravity Capacitor Upgrade I
110  case 31215: // Medium Gravity Capacitor Upgrade I
111  case 31217: // Capital Gravity Capacitor Upgrade I
112  case 26350: // Large Gravity Capacitor Upgrade II
113  case 31220: // Small Gravity Capacitor Upgrade II
114  case 31222: // Medium Gravity Capacitor Upgrade II
115  case 31224: { // Capital Gravity Capacitor Upgrade II
117  } break;
118  }
119  }
120  AddModule(mRef, cur->flag());
121  } break;
123  _log(MODULE__TRACE, "MM::Initialize() - loading %s(%u) to %s.",\
124  cur->name(), cur->itemID(), sDataMgr.GetFlagName(cur->flag()));
126  AddModule(mRef, cur->flag());
127  } break;
129  pMod = GetModule(cur->flag());
130  if (pMod == nullptr) {
131  // module to load not found...
132  _log(MODULE__ERROR, "MM::Initialize() - No module at %s to load charge %s(%u) into",\
133  sDataMgr.GetFlagName(cur->flag()), cur->name(), cur->itemID() );
134  // put that bitch back in cargo
135  cur->SetFlag(flagCargoHold);
136  } else {
137  if (pMod->IsLoaded()) {
138  _log(MODULE__TRACE, "MM::Initialize() - %s at %s is already loaded. Moving %s to cargo.",\
139  pMod->GetSelf()->name(), sDataMgr.GetFlagName(cur->flag()), cur->name());
140  // put that bitch back in cargo
141  cur->SetFlag(flagCargoHold);
142  continue;
143  }
144  _log(MODULE__TRACE, "MM::Initialize() - loading %s(%u) at %s with %s(%u).",\
145  pMod->GetSelf()->name(), pMod->GetSelf()->itemID(), \
146  sDataMgr.GetFlagName(cur->flag()), cur->name(), cur->itemID());
147  pMod->LoadCharge(cur);
148  //cur->SetQuantity(cur->quantity()); //OIC
149  cur->SetAttribute(AttrQuantity, cur->quantity(), false); // OMAC
150  m_charges.emplace(cur->flag(), cur);
151  }
152  pMod = nullptr;
153  } break;
154  }
155  }
156  }
157 
158  return m_initalized = true;
159 }
160 
162  // must proc modules in order of (subsys -> rig -> low -> mid -> high) for proper fx application
163  // online subsystems, then rigs before hi,mid,lo slots
164  std::map<uint8, GenericModule*>::reverse_iterator ritr = m_systems.rbegin(), rend = m_systems.rend();
165  while (ritr != rend) {
166  if (ritr->second != nullptr)
167  ritr->second->Online();
168  ++ritr;
169  }
170  // process lo,mid,hi slots in that order.
171  std::map<uint8, GenericModule*>::iterator itr = m_fittings.begin(), end = m_fittings.end();
172  while (itr != end) {
173  if (itr->second != nullptr)
174  if (itr->second->GetAttribute(AttrOnline).get_bool())
175  itr->second->Online();
176  ++itr;
177  }
178 }
179 
181 {
182  double profileStartTime = GetTimeUSeconds();
183 
184  // proc modules in order of (low -> mid -> high) for proper fx application
185  // NOTE: rigs and subsystems dont need proc tic.
186  std::map<uint8, GenericModule*>::iterator itr = m_fittings.begin(), end = m_fittings.end();
187  while (itr != end) {
188  if (itr->second != nullptr)
189  if (itr->second->GetAttribute(AttrOnline).get_bool())
190  itr->second->Process();
191  ++itr;
192  }
193 
194  if (sConfig.debug.UseProfiling)
195  sProfiler.AddTime(Profile::modules, GetTimeUSeconds() - profileStartTime);
196 }
197 
199 {
200  return (m_modules.find((uint8)flag)->second != nullptr);
201 }
202 
204  for (auto cur : m_modules)
205  if (cur.second != nullptr)
206  cur.second->RemoveTarget(pSE);
207  /*
208  for (auto cur : m_fittings)
209  if (cur.second != nullptr)
210  cur.second->RemoveTarget(pSE);
211  */
212 }
213 
215 {
216  switch (slotBank) {
217  case EVEEffectID::loPower: {
219  for (uint8 slot=flagLowSlot0; slot < max; ++slot)
220  if ( m_modules[slot] == nullptr )
221  return slot;
222  } break;
223  case EVEEffectID::medPower: {
225  for (uint8 slot=flagMidSlot0; slot < max; ++slot)
226  if ( m_modules[slot] == nullptr )
227  return slot;
228  } break;
229  case EVEEffectID::hiPower: {
231  for (uint8 slot=flagHiSlot0; slot < max; ++slot)
232  if ( m_modules[slot] == nullptr )
233  return slot;
234  } break;
235  case EVEEffectID::rigSlot: {
237  for (uint8 slot=flagRigSlot0; slot < max; ++slot)
238  if ( m_modules[slot] == nullptr )
239  return slot;
240  } break;
241  case EVEEffectID::subSystem: {
243  for (uint8 slot=flagSubSystem0; slot < max; ++slot)
244  if ( m_modules[slot] == nullptr )
245  return slot;
246  } break;
247  }
248  return flagIllegal;
249 }
250 
251 void ModuleManager::GetModulesInBank(EVEItemFlags flag, std::vector<GenericModule*>& modVec)
252 {
253  switch (flag) {
254  case flagLowSlot0:
255  case flagLowSlot1:
256  case flagLowSlot2:
257  case flagLowSlot3:
258  case flagLowSlot4:
259  case flagLowSlot5:
260  case flagLowSlot6:
261  case flagLowSlot7: {
262  for (uint8 slot=flagLowSlot0; slot < (flagLowSlot0 + 8); ++slot)
263  if ( m_modules[slot] != nullptr )
264  modVec.push_back(m_modules[slot]);
265  } break;
266  case flagMidSlot0:
267  case flagMidSlot1:
268  case flagMidSlot2:
269  case flagMidSlot3:
270  case flagMidSlot4:
271  case flagMidSlot5:
272  case flagMidSlot6:
273  case flagMidSlot7: {
274  for (uint8 slot=flagMidSlot0; slot < (flagMidSlot0 + 8); ++slot)
275  if ( m_modules[slot] != nullptr )
276  modVec.push_back(m_modules[slot]);
277  } break;
278  case flagHiSlot0:
279  case flagHiSlot1:
280  case flagHiSlot2:
281  case flagHiSlot3:
282  case flagHiSlot4:
283  case flagHiSlot5:
284  case flagHiSlot6:
285  case flagHiSlot7: {
286  for (uint8 slot=flagHiSlot0; slot < (flagHiSlot0 + 8); ++slot)
287  if ( m_modules[slot] != nullptr )
288  modVec.push_back(m_modules[slot]);
289  } break;
290  }
291 }
292 
294 {
295  std::map<uint8, GenericModule*>::iterator itr = m_modules.find((uint8)flag);
296  if (itr != m_modules.end())
297  return itr->second;
298 
299  return nullptr;
300 }
301 
303 {
304  InventoryItemRef iRef = sItemFactory.GetItem(itemID);
305  if (iRef.get() != nullptr)
306  return GetModule(iRef->flag());
307 
308  return nullptr;
309 }
310 
312 {
313  std::vector<GenericModule*> modVec;
315  if (m_modules[flag] != nullptr)
316  modVec.push_back(m_modules[flag]);
317 
318  if (modVec.empty () == true)
319  return nullptr;
320 
321  return modVec[MakeRandomInt(0, modVec.size())];
322 }
323 
327  AddModule(mRef,flag);
328  // hack to get total scan bonus from rigs, if applicable
329  // do we need to check for and set anything else here?
331  switch (mRef->typeID()) {
332  case 25936: // Large Gravity Capacitor Upgrade I
333  case 31213: // Small Gravity Capacitor Upgrade I
334  case 31215: // Medium Gravity Capacitor Upgrade I
335  case 31217: // Capital Gravity Capacitor Upgrade I
336  case 26350: // Large Gravity Capacitor Upgrade II
337  case 31220: // Small Gravity Capacitor Upgrade II
338  case 31222: // Medium Gravity Capacitor Upgrade II
339  case 31224: { // Capital Gravity Capacitor Upgrade II
341  } break;
342  }
343  }
344  return true;
345  } else {
346  codelog(MODULE__TRACE, "ModuleManager","%s tried to fit item %s(%u), which is not a rig", pShipItem->GetPilot()->GetName(), mRef->name(), mRef->itemID());
347  }
348 
349  return false;
350 
351  /*
352  10%
353  15%
354  */
355 }
356 
358 {
359  GenericModule* pMod = GetModule(itemID);
360  if (pMod == nullptr) {
361  _log(MODULE__ERROR, "MM::UninstallRig() - Rig %u not found", itemID);
362  return;
363  }
364 
365  _log(MODULE__TRACE, "%s(%u) calling MM::UninstallRig()", pMod->GetSelf()->name(), pMod->itemID());
366 
367  pMod->Offline();
368 
370  switch (pMod->typeID()) {
371  case 25936: // Large Gravity Capacitor Upgrade I
372  case 31213: // Small Gravity Capacitor Upgrade I
373  case 31215: // Medium Gravity Capacitor Upgrade I
374  case 31217: // Capital Gravity Capacitor Upgrade I
375  case 26350: // Large Gravity Capacitor Upgrade II
376  case 31220: // Small Gravity Capacitor Upgrade II
377  case 31222: // Medium Gravity Capacitor Upgrade II
378  case 31224: { // Capital Gravity Capacitor Upgrade II
380  } break;
381  }
382  }
383 
384  if (!sConfig.debug.IsTestServer)
385  pMod->RemoveRig();
386  deleteModuleRef(pMod->flag(), pMod);
387 }
388 
390 {
392  sLog.Warning("ModuleManager","%s tried to fit %s(%u) at %s, which is not a subsystem", \
393  pShipItem->GetPilot()->GetName(), mRef->name(), mRef->itemID(), sDataMgr.GetFlagName(flag));
394  return false;
395  }
396 
397  AddModule(mRef,flag);
398  return true;
399 }
400 
401 // not used
403 {
404  if (IsRigSlot(flag))
405  if (m_RigSlots)
406  return;
407  if (IsHiSlot(flag))
408  if (m_HighSlots)
409  return;
410  if (IsMidSlot(flag))
411  if (m_MidSlots)
412  return;
413  if (IsLowSlot(flag))
414  if (m_LowSlots)
415  return;
416  if (IsSubSystem(flag))
417  if (m_SubSystemSlots)
418  return;
419 
420  throw UserError ("NoFreeShipSlots");
421 }
422 
423 // not used
425 {
426  if (iRef->HasAttribute(AttrMaxGroupFitted)) {
427  // some of these are checked client-side (by attrib) so this may not be needed.
428  if (GetFittedModuleCountByGroup(iRef->groupID()) >= iRef->GetAttribute(AttrMaxGroupFitted).get_int()) {
429  /*
430  std::map<std::string, PyRep *> args;
431  args["noOfModules"] = new PyInt(iRef->GetAttribute(AttrMaxGroupFitted).get_int());
432  args["noOfModulesFitted"] = new PyInt(GetFittedModuleCountByGroup(iRef->groupID()));
433  args["ship"] = new PyInt(pShipItem->itemID());
434  args["groupName"] = new PyString(sDataMgr.GetGroupName(iRef->groupID()));
435  args["module"] = new PyInt(iRef->itemID());
436  throw PyException( MakeUserError("CantFitTooManyByGroup", args)); // bad msgID in client.
437  */
438  throw CustomError ("Group Fit Limited.<br>You cannot fit the %s to your %s.", iRef->name(), pShipItem->name());
439  /*CantFitTooManyByGroupBody'}(
440  * u"You're unable to fit {[item]module.name} to {[item]ship.name}.
441  * You can only fit {[numeric]noOfModules} of type {groupName} but already have {[numeric]noOfModulesFitted}.", None,
442  * {u'{[numeric]noOfModules}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'noOfModules'},
443  * u'{[numeric]noOfModulesFitted}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'noOfModulesFitted'},
444  * u'{[item]ship.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'ship'},
445  * u'{groupName}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'groupName'},
446  * u'{[item]module.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'module'}})
447  */
448  }
449  }
450 }
451 
453 {
454  GenericModule* pMod = GetModule(itemID);
455  if (pMod == nullptr) {
456  _log(MODULE__ERROR, "MM::UnfitModule() - Module %u not found", itemID);
457  return;
458  }
459 
460  _log(MODULE__TRACE, "%s(%u) calling MM::UnfitModule(itemID)", pMod->GetSelf()->name(), pMod->itemID());
461 
462  pMod->AbortCycle();
463  if (pMod->IsLoaded())
464  UnloadCharge(pMod);
465 
466  if (pMod->IsLinked())
467  pShipItem->UnlinkGroup(itemID, true);
468 
469  pMod->Offline();
470 
471  deleteModuleRef(pMod->flag(), pMod);
472  // delete the GenericModule object (but not the ModuleItem object)
473  SafeDelete(pMod);
474 }
475 
477  GenericModule* pMod = GetModule(flag);
478  if (pMod == nullptr) {
479  _log(MODULE__ERROR, "MM::UnfitModule() - Module not found at %s", sDataMgr.GetFlagName(flag));
480  return;
481  }
482 
483  _log(MODULE__TRACE, "%s(%u) calling MM::UnfitModule(flag)", pMod->GetSelf()->name(), pMod->itemID());
484 
485  pMod->AbortCycle();
486  if (pMod->IsLoaded())
487  UnloadCharge(pMod);
488 
489  if (pMod->IsLinked())
490  pShipItem->UnlinkGroup(pMod->itemID(), true);
491 
492  pMod->Offline();
493 
494  deleteModuleRef(flag, pMod);
495  // delete the GenericModule object (but not the ModuleItem object)
496  SafeDelete(pMod);
497 }
498 
499 // cannot throw without test
501 {
502  if (!IsModuleSlot(flag)) {
503  sLog.Warning("MM::AddModule","%s is not a module slot.", sDataMgr.GetFlagName(flag));
504  return false;
505  }
506  if (IsSlotOccupied(flag)) {
507  GenericModule* pMod = GetModule(flag);
508  if (pMod == nullptr)
509  return false;
510 
511  if (pShipItem->HasPilot()) {
512  if (!pShipItem->GetPilot()->IsLogin()) {
513  if (pShipItem->GetPilot()->CanThrow()) {
514  pShipItem->GetPilot()->SendErrorMsg("You cannot add %s to %s because %s is already there.", \
515  mRef->name(), sDataMgr.GetFlagName(flag), pMod->GetSelf()->name());
516  } else {
517  throw UserError ("SlotAlreadyOccupied");
518  }
519  }
520  }
521 
522  // change this to use movemodule?
523  return false;
524  }
525 
526  // create new module object
528  if (pMod == nullptr)
529  return false; // error here?
530 
532 
533  addModuleRef(flag, pMod);
534 
535  if (m_initalized and pShipItem->HasPilot())
536  if (mRef->GetAttribute(AttrOnline).get_bool())
537  pMod->Online();
538 
539  // verify module's singleton flag is set
540  mRef->ChangeSingleton(true, pShipItem->HasPilot()?pShipItem->GetPilot()->IsInSpace():false);
541 
542  return true;
543  /*
544  if (is_log_enabled(MODULE__DEBUG)) { // debug msg?
545  std::map<std::string, PyRep *> args;
546  args["item"] = new PyString(iRef->itemName());
547  args["slot"] = new PyString(sDataMgr.GetFlagName(flag));
548  throw PyException( MakeUserError("ModuleFit", args));
549  */
550  /*{'messageKey': 'ModuleFit', 'dataID': 17883325, 'suppressable': False, 'bodyID': 259463, 'messageType': 'notify', 'urlAudio': 'wise:/msg_ModuleFit_play', 'urlIcon': '', 'titleID': None, 'messageID': 1227}
551  * u'ModuleFitBody'}(u'{item} fitted onto slot {slot}', None, {
552  * u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'},
553  * u'{slot}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'slot'}})
554  *
555  }*/
556 }
557 
559 {
560  GenericModule* pMod = GetModule(itemID);
561  if (pMod == nullptr) {
562  _log(MODULE__ERROR, "MM::Online(itemID) - Module %u not found", itemID);
563  return;
564  }
565  if (pMod->isOnline()) {
566  _log(MODULE__WARNING, "MM::Online(itemID) - %s already Online", pMod->GetSelf()->name());
567  if (pShipItem->HasPilot())
568  if (pShipItem->GetPilot()->CanThrow()) {
569  throw UserError ("EffectAlreadyActive2")
570  .AddTypeName ("modulename", pMod->GetSelf ()->typeID ());
571  }
572  return;
573  }
574 
575  _log(MODULE__MESSAGE, "MM::Online(itemID) - %s going Online", pMod->GetSelf()->name());
576  pMod->Online();
577 }
578 
580 {
581  GenericModule* pMod = GetModule(flag);
582  if (pMod == nullptr) {
583  _log(MODULE__ERROR, "MM::Online(flag) - Module not found in %s", sDataMgr.GetFlagName(flag));
584  return;
585  }
586  if (pMod->isOnline()) {
587  _log(MODULE__WARNING, "MM::Online(flag) - %s already Online", pMod->GetSelf()->name());
588  return;
589  }
590 
591  _log(MODULE__MESSAGE, "MM::Online(flag) - %s going Online", pMod->GetSelf()->name());
592  pMod->Online();
593 }
594 
596 {
597  GenericModule* pMod = GetModule(itemID);
598  if (pMod == nullptr) {
599  _log(MODULE__ERROR, "MM::Offline(itemID) - Module %u not found", itemID);
600  return;
601  }
602  if (!pMod->isOnline()) {
603  _log(MODULE__WARNING, "MM::Offline(itemID) - %s not Online", pMod->GetSelf()->name());
605  return;
606  }
607 
608  _log(MODULE__MESSAGE, "MM::Offline(itemID) - %s going Offline", pMod->GetSelf()->name());
609  pMod->Offline();
610 }
611 
613 {
614  GenericModule* pMod = GetModule(flag);
615  if (pMod == nullptr) {
616  _log(MODULE__ERROR, "MM::Offline(flag) - Module not found in %s", sDataMgr.GetFlagName(flag));
617  return;
618  }
619  if (!pMod->isOnline()) {
620  _log(MODULE__WARNING, "MM::Offline(flag) - %s not Online", pMod->GetSelf()->name());
622  return;
623  }
624  _log(MODULE__MESSAGE, "MM::Offline(flag) - %s going Offline", pMod->GetSelf()->name());
625  pMod->Offline();
626 }
627 
629 {
630  for (auto cur : m_modules)
631  if (cur.second != nullptr)
632  cur.second->AbortCycle();
633 }
634 
636 {
637  // must proc modules in order of (subsys -> rig -> high -> mid -> low) for proper fx application
638  std::map<uint8, GenericModule*>::reverse_iterator itr = m_modules.rbegin(), end = m_modules.rend();
639  while (itr != end) {
640  if (itr->second != nullptr)
641  itr->second->Online();
642  ++itr;
643  }
644 }
645 
647 {
648  for (auto cur : m_modules)
649  if (cur.second != nullptr)
650  cur.second->Offline();
651 }
652 
654 {
655  for (auto cur : m_modules)
656  if (cur.second != nullptr)
657  cur.second->Deactivate();
658 }
659 
660 void ModuleManager::Activate(int32 itemID, uint16 effectID, int32 targetID, int32 repeat)
661 {
662  if (!pShipItem->HasPilot()) {
663  _log(MODULE__ERROR, "MM::Activate() - Called from a ship with no pilot." );
664  return;
665  }
666 
668  if (pDestiny == nullptr) {
669  _log(PLAYER__ERROR, "%s: Ship has no destiny manager!", pShipItem->GetPilot()->GetName());
670  return;
671  }
672 
673  GenericModule* pMod = GetModule(itemID);
674  if (pMod == nullptr) {
675  _log(MODULE__ERROR, "MM::Activate() - Called on module %u that is not loaded.", itemID );
676  return;
677  }
678 
679  _log(MODULE__TRACE, "MM::Activate() - %s (%u - %s) targetID: %i, repeat: %i.", \
680  pMod->GetSelf()->name(), effectID, sFxDataMgr.GetEffectName(effectID).c_str(), targetID, repeat);
681 
682  if (effectID == 16) { //16 online
683  pMod->Online();
684  return;
685  }
686  /*{'FullPath': u'UI/Messages', 'messageID': 259628, 'label': u'InvalidTargetCanAlreadyTractoredBody'}(u'The {[item]module.name} cannot engage a tractor beam on that object as it is already being tractor beamed by something else.', None, {u'{[item]module.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'module'}})
687  * {'FullPath': u'UI/Messages', 'messageID': 259629, 'label': u'InvalidTargetCanOwnerBody'}(u'The {[item]module.name} cannot engage a tractor beam on that object as it is not owned by you, a fellow fleet member or another member of a player corporation you belong to.', None, {u'{[item]module.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'module'}})
688  * {'FullPath': u'UI/Messages', 'messageID': 259630, 'label': u'InvalidTargetGroupBody'}(u'Invalid target, can only activate this on {groupName}.', None, {u'{groupName}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'groupName'}})
689  */
690 
691  if (effectID == 2255) { // tractorBeamCan
692  SystemEntity* pSE = pShipItem->GetPilot()->SystemMgr()->GetSE(targetID);
693  if (pSE == nullptr)
694  throw UserError ("DeniedActivateTargetNotPresent");
695  if (pSE->DestinyMgr()->IsTractored()) {
696  // report player tractoring item?
697  pShipItem->GetPilot()->SendNotifyMsg("Your %s cannot engage the %s, which is already being tractor beamed by something else.", pMod->GetSelf()->name(), pSE->GetName());
698  return;
699  //std::map<std::string, PyRep *> args;
700  //args["module"] = new PyInt(itemID);
701  //throw PyException(MakeUserError("InvalidTargetCanAlreadyTractored", args));
702  }
703  }
704 
705  if (!pMod->isOnline()) {
706  // client wont allow activating an offline module. this is catchall. (but should never hit)
707  pShipItem->GetPilot()->SendErrorMsg("You cannot activate an offline module. Ref: ServerError 25164");
708  return;
709  } else if (pDestiny->IsWarping()) {
710  if (pMod->HasAttribute(AttrDisallowActivateOnWarp) or !sFxDataMgr.isWarpSafe(effectID))
711  throw UserError ("DeniedActivateInWarp");
712  } else if (pDestiny->IsCloaked()) {
713  throw UserError ("DeniedActivateCloaked");
714  } else if (pShipItem->GetPilot()->IsJump()) {
715  throw UserError ("DeniedActivateInJump");
716  }
717 
718  if (!pMod->IsLinked() or pMod->IsMaster())
719  pMod->Activate(effectID, targetID, repeat);
720 }
721 
722 void ModuleManager::Deactivate(uint32 itemID, std::string effectName)
723 {
724  GenericModule* pMod = GetModule(itemID);
725  if (pMod == nullptr) {
726  _log(MODULE__ERROR, "MM::Deactivate() - Called on module %u that is not loaded.", itemID );
727  return;
728  }
729 
730  // test for effectName "online", which is sent thru rclick menu in HUD to offline module
731  if (effectName.compare("online") == 0) {
732  _log(MODULE__TRACE, "MM::Deactivate() - %s Offlining - '%s'", pMod->GetSelf()->name(), effectName.c_str());
733  pMod->Offline();
734  return;
735  }
736  if (pMod->GetModuleState() != Module::State::Activated) // we dont need an error msgs here....this is acceptable, as the module may not be active
737  return;
738 
739  _log(MODULE__TRACE, "MM::Deactivate() - %s Deactivating - '%s'", pMod->GetSelf()->name(), effectName.c_str());
740  pMod->Deactivate(effectName);
741 }
742 
744 {
745  GenericModule* pMod = GetModule(itemID);
746  if (pMod == nullptr) {
747  _log(MODULE__ERROR, "MM::Overload() - Called on module %u that is not loaded.", itemID);
748  return;
749  }
750  _log(MODULE__TRACE, "MM::Overload() - %s Overloading...", pMod->GetSelf()->name());
751  pMod->Overload();
752 }
753 
755 {
756  GenericModule* pMod = GetModule(itemID);
757  if (pMod == nullptr) {
758  _log(MODULE__ERROR, "MM::DeOverload() - Called on module %u that is not loaded.", itemID);
759  return;
760  }
761  _log(MODULE__TRACE, "MM::DeOverload() - %s DeOverload...", pMod->GetSelf()->name());
762  pMod->DeOverload();
763 }
764 
766 {
767  DamageModule(GetModule(itemID), amount);
768 }
769 
771 {
772  DamageModule(GetRandModule(), 1.0f);
773 }
774 
776 {
777  DamageModule(GetRandModule(), amount);
778 }
779 
781 {
782  if (pMod == nullptr) {
783  _log(MODULE__ERROR, "MM::DamageModule() - Module not found.");
784  return;
785  }
786 
787  pMod->SetAttribute(AttrDamage, (pMod->GetAttribute(AttrDamage) + amount)); //verify this works as intended
788  _log(MODULE__DAMAGE, "MM::DamageModule() - %s taking %.2f damage. current damage %.2f", \
789  pMod->GetSelf()->name(), amount, pMod->GetAttribute(AttrDamage).get_float());
790  if (pMod->GetAttribute(AttrDamage) >= pMod->GetAttribute(AttrHP)) {
791  // this is for offlining entire group...this isnt right.
792  /*
793  if (pMod->IsLinked()) {
794  // loop thru linked modules and offline all
795  pShipItem->GetPilot()->SendNotifyMsg("Your group of %s has gone offline due to damage.", pMod->GetSelf()->name());
796  pShipItem->OfflineGroup(pMod);
797  } else */
798  pShipItem->GetPilot()->SendNotifyMsg("Your %s in %s has gone offline due to damage.", pMod->GetSelf()->name(), sDataMgr.GetFlagName(pMod->flag()));
799  pMod->Offline();
800  }
801 }
802 
804 {
805  RepairModule(GetModule(itemID), amount);
806 }
807 
809 {
810  if (pMod != nullptr){
811  _log(MODULE__ERROR, "MM::RepairModule() - Called on module that is not loaded.");
812  return;
813  }
814  pMod->Repair(amount);
815 }
816 
818 {
819  for (auto cur : m_modules)
820  if (cur.second != nullptr)
821  cur.second->Repair();
822 }
823 
825 {
826  /* Restrictions/Capabilities
827  *
828  * Cannot be used while overloading any modules.
829  * Cannot be used on an active module.
830  * Cannot be used to repair a 100% damaged module (0/40hp). These must first be repaired to at least 1hp at a station.
831  * Can be used to repair an offline module with at least 1hp remaining.
832  * Can be used on an inactive module while other modules are active.
833  * Can be used to repair any inactive modules while cloaked (everything but the cloak itself, of course).
834  * Can repair multiple modules at once.
835  * Can be canceled mid-repair, and will retain whatever repairs could be completed in the time it was active. Canceling a repair on a module that takes 1-2 paste to repair fully is occasionally problematic, and will round down - e.g. you need to have repaired enough HP to take at least one unit of paste before canceling mid-repair will result in any repaired damage or paste consumed. No paste is ever consumed without appropriate repairs being done, however.
836  * You can jump or dock while repairing, which will have the same effect as canceling the repair manually.
837  * You can repair a passive module (such as a plate, extender, or EANM) without taking it offline, and you still receive the benefit from passive modules while repairing them. Capacitor batteries were fixed and can now be repaired while online!
838  *
839  * Efficiency
840  *
841  * Nanite efficiency is based on the base cost of the module, rather than amount of HP repaired.
842  * All modules have 40hp, but base cost varies wildly.
843  * Base efficiency for a theoretical (but impossible) full repair (0/40hp remaining) is approximately 0.0000775 paste per isk of base item cost.
844  * To couch this in more relatable terms, this means that an item with a base cost of 100k isk will cost 7 or 8 paste to repair; an item with a base cost of 1m isk will cost 77-78 paste to repair.
845  * The Nanite Operation skill reduces consumption by 5% per level. At V, nanite efficiency will be 0.000058125/isk, or ~58 units of paste per 1m isk base cost.
846  * NPC station repair costs are equal to the item base cost, modified marginally by standing. Base repair cost with nanites is 7.7x11700=90,090 per 100,000 isk, or 10% less. Even without the Nanite Operation skill, repairs with nanite paste are always slightly cheaper than repairs at NPC stations. With Nanite Operation trained up, repairing with nanite paste is significantly cheaper than at NPC stations.
847  *
848  * Speed
849  *
850  * Nanite paste has a base repair speed of 10hp per minute, independent of module type or cost.
851  * As all modules have 40hp, and paste cannot be used to repair 100% damaged items, the most time a repair can take at base skill levels is 3:54 on a 97% damaged module.
852  * The Nanite Interfacing skill improves repair speed by 20% (or 2hp) per level. At V, repair rate is 20hp per minute with a max repair time of 1:57.
853  *
854  * Module Repair Costs
855  *
856  * Again, the quantity of nanite paste consumed to repair an item is dependent on its base cost.
857  * You can easily find the base cost of a module by looking it up in the Item Browser subsection of Evemon's skill plans.
858  *
859  * As a general rule, base cost is usually around 1/4 of the Empire price of an item. This mostly applies to T1 items, but T2 items for which demand is not extremely high tend to follow this as well.
860  * As you might suspect, battleship-class modules have much higher base costs than frigate-class modules. This applies mostly to Afterburners, Microwarpdrives, Armor Repairers, and Shield Boosters. Most larger modules also produce less heat damage however, so the difference in nanites consumed per amount of time overheated is not as pronounced.
861  * T2 items have the highest base cost at around 2-6x that of T1.
862  * Named items often have lower base costs than T1, and are never higher.
863  * Faction, Deadspace, and Officer items have wildly varying base costs.
864  * Most are similar or identical to named, others T1, and a few are higher than T1 but still much lower than T2.
865  * Officer/Deadspace MWDs are an odd exception to this, as all of them have the same base cost regardless of size class (790k).
866  * In most cases, this makes faction items prime candidates for overloading as they produce similar or less heat damage while being radically more
867  * effective and cheaper to repair than their T1 or T2 counterparts.
868  */
869 
870  GenericModule* pMod = GetModule(modID);
871  if (pMod == nullptr) {
872  _log(MODULE__ERROR, "MM::ModuleRepair() - module %s not found.", modID);
873  return PyStatic.NewFalse();
874  }
875 
876 
877 
878  //return PyStatic.NewTrue(); // can repair
879  return PyStatic.NewFalse(); // cannot repair (for whatever reason) do they/we send msgs based on why here?
880 }
881 
883 {
884  GenericModule* pMod = GetModule(modID);
885  if (pMod == nullptr) {
886  _log(MODULE__ERROR, "MM::ModuleRepair() - module %s not found.", modID);
887  return;
888  }
889 
890 
891 }
892 
894 {
895  GenericModule* pMod = GetModule(flag);
896  if (pMod == nullptr) {
897  _log(MODULE__ERROR, "MM::LoadCharge() - module not found at %s", sDataMgr.GetFlagName(flag));
898  return;
899  }
900  float modCapacity = pMod->GetAttribute(AttrCapacity).get_float();
901  float chargeVolume = chargeRef->GetAttribute(AttrVolume).get_float();
902 
903  bool loaded = pMod->IsLoaded();
904 
905  if (loaded) {
906  if (chargeRef->typeID() == pMod->GetLoadedChargeRef()->typeID()) {
907  modCapacity -= (chargeVolume * pMod->GetLoadedChargeRef()->quantity());
908  _log(MODULE__TRACE, "MM::LoadCharge() - %s reloading with same type. remaining capy:%.2f", pMod->GetSelf()->name(), modCapacity);
909  } else {
910  // change charges
911  UnloadCharge(pMod);
912  loaded = false;
913  // update module capy
914  modCapacity = pMod->GetAttribute(AttrCapacity).get_float();
915  _log(MODULE__TRACE, "MM::LoadCharge() - %s reloading with different type. empty capy:%.2f", pMod->GetSelf()->name(), modCapacity);
916  }
917  } else {
918  _log(MODULE__TRACE, "MM::LoadCharge() - %s not loaded. capy:%.2f", pMod->GetSelf()->name(), modCapacity);
919  }
920 
921  //{'FullPath': u'UI/Messages', 'messageID': 256676, 'label': u'CannotLoadNotEnoughChargesBody'}(u'There are not enough charges to fully load all of your modules. Some of your modules have been left partially loaded or empty.', None, None)
922 
923  // check quantities
924  if (modCapacity < chargeVolume)
925  return;
926 
927  int32 loadQty = floor((modCapacity / chargeVolume));
928  if (loadQty < 1)
929  return;
930 
931  if (loadQty < chargeRef->quantity()) {
932  InventoryItemRef cRef(chargeRef);
933  chargeRef = chargeRef->Split(loadQty, false, true);
934  if (chargeRef.get() == nullptr) {
935  _log(MODULE__ERROR, "");
936  if (pShipItem->HasPilot())
937  pShipItem->GetPilot()->SendNotifyMsg("Could not split stack of %s. %s was not reloaded.", \
938  cRef->name(), pMod->GetSelf()->name());
939  return;
940  }
941  } else {
942  loadQty = chargeRef->quantity();
943  }
944 
945  /* loaded charges are set in a "SubLocation" in client.
946  * they then become a nullItem, with only type and qty references.
947  * the sublocation is identified as a tuple of itemKey(shipID, flagID, typeID)
948  * all updates for that charge (which seems to be only attrib changes), are referenced using it's itemKey
949  * when sending charge item change with locationID or flagID, client will correctly add as sublocation
950  * when in space, but only for the first update. subsequent changes need to use OnModuleAttributeChange (OMAC)
951  *
952  * when docked, List() sends charges as invItem, and client doesnt process that as a sublocation. (OMAC method)
953  * because of this, OMAC isn't used when docked, and OnItemChange (OIC) is the update client will correctly process.
954  */
955 
956  if (loaded) {
957  // merge addt'l charges with currently loaded charges (fillup)
958  pMod->GetLoadedChargeRef()->Merge(chargeRef, loadQty);
959  } else {
960  // if module wasnt previously loaded, add to ship's inventory and charge map
961  chargeRef->SetAttribute(AttrQuantity, EvilZero, false); // OMAC
962  chargeRef->Move(pShipItem->itemID(), flag, pShipItem->HasPilot()?pShipItem->GetPilot()->IsDocked():false);
963  //chargeRef->Move(pShipItem->itemID(), flag, false);
964  m_charges.emplace(flag, chargeRef);
965  }
966 
967  // this will enable module loading blink if ship in space, even on reload/fillup
968  pMod->LoadCharge(chargeRef);
969 
970  // just found a call i was missing.... 19Aug20
971  /*
972  * [PyTuple 3 items]
973  * [PyString "OnGodmaPrimeItem"]
974  * [PyIntegerVar 1002332228246] <<-- item locationID
975  * [PyObjectData Name: util.KeyVal]
976  * [PyDict 5 kvp]
977  * [PyString "itemID"]
978  * [PyTuple 3 items]
979  * [PyIntegerVar 1002332228246]
980  * [PyInt 27]
981  * [PyInt 30028]
982  * [PyString "attributes"]
983  * [PyDict 23 kvp]
984  * [PyString "invItem"]
985  * [PyNone]
986  * [PyString "time"]
987  * [PyIntegerVar 129527520208602524]
988  * [PyString "activeEffects"]
989  * [PyDict 0 kvp]
990  * [PyDict 1 kvp]
991  * [PyString "sn"]
992  * [PyIntegerVar 131]
993  */
994  // send update to client for processing new subLocation -found/added 19Aug20
995  if (!loaded)
996  if (pShipItem->HasPilot() and pShipItem->GetPilot()->IsInSpace()) {
997  Rsp_CommonGetInfo_Entry entry2;
998  if (chargeRef->Populate(entry2)) {
999  PyTuple* tuple = new PyTuple(3);
1000  tuple->SetItem(0, new PyInt(chargeRef->locationID()));
1001  tuple->SetItem(1, new PyInt(chargeRef->flag()));
1002  tuple->SetItem(2, new PyInt(chargeRef->typeID()));
1003  PyTuple* result = new PyTuple(2);
1004  result->SetItem(0, new PyInt(chargeRef->locationID()));
1005  result->SetItem(1, new PyObject("util.KeyVal", entry2.Encode()));
1006  pShipItem->GetPilot()->SendNotification("OnGodmaPrimeItem", "clientID", result); // this is sequenced
1007  } else {
1008  sLog.Error("MM::LoadCharge","cannot Populate() %s", chargeRef->name());
1009  }
1010  }
1011 
1012  //chargeRef->SetQuantity(loadQty, true); // OIC
1013  chargeRef->SetAttribute(AttrQuantity, loadQty, true); // OMAC
1014 }
1015 
1017 {
1018  if (pMod == nullptr) {
1019  _log(MODULE__ERROR, "MM::UnloadCharge() - module invalid");
1020  return;
1021  }
1022 
1023  _log(MODULE__TRACE, "%s(%u) calling MM::UnloadCharge()", pMod->GetSelf()->name(), pMod->itemID());
1024 
1025  // verify no charge at flag in map
1026  m_charges.erase(pMod->flag());
1027 
1028  if (!pMod->IsLoaded()) {
1029  _log(MODULE__ERROR, "MM::UnloadCharge() - %s at %s is not loaded", \
1030  pMod->GetSelf()->name(), sDataMgr.GetFlagName(pMod->flag()));
1031  return;
1032  }
1033 
1034  InventoryItemRef chargeRef(pMod->GetLoadedChargeRef());
1035  if (chargeRef.get() == nullptr) {
1036  _log(MODULE__ERROR, "MM::UnloadCharge() - charge not found on module %s at %s", \
1037  pMod->GetSelf()->name(), sDataMgr.GetFlagName(pMod->flag()));
1038  return;
1039  }
1040 
1041  pMod->UnloadCharge();
1042 
1043  // if charge is depleted, update has already been sent to client thru OMAC
1044  if (chargeRef->quantity() < 1)
1045  return;
1046 
1047  // at this point, we are changing a loaded charge. remove charge from module, check for stacking, update client.
1048  /* to trigger client to remove and clear out a loaded charge, send a qty=0 update using either
1049  * OnModuleAttributeChange thru Godma when in space or OnItemChange thru InventoryItem when docked
1050  */
1051 
1052  chargeRef->SetAttribute(AttrQuantity, EvilZero); // OMAC
1053 
1054  if (sDataMgr.IsStation(pShipItem->locationID())) {
1055  StationItemRef sRef = sEntityList.GetStationByID(pShipItem->locationID());
1056  if (sRef.get() != nullptr) {
1057  InventoryItemRef iRef = sRef->GetMyInventory()->GetByTypeFlag(chargeRef->typeID(), flagHangar);
1058  if (iRef.get() != nullptr) {
1059  // merge with existing item
1060  iRef->Merge(chargeRef); // OIC preferred
1061  //iRef->AlterQuantity(chargeRef->quantity() + iRef->quantity(), true);
1062  //chargeRef->SetQuantity(0, true); // OIC alternate
1063  return;
1064  } else {
1065  chargeRef->Move(pShipItem->locationID(), flagHangar, true);
1066  }
1067  } else { // this will be an error. cant find station ship is docked in
1068  _log(MODULE__ERROR, "MM::UnloadCharge() - Station %u not found for ship %u owned by %s",\
1071  chargeRef->Move(pShipItem->locationID(), flagHangar, true);
1072  }
1073  } else {
1074  /*
1075  EVEItemFlags flag = flagCargoHold;
1076  // check for existence of ammohold...not yet. only one ship has it (cockroach)
1077  if (pShipItem->HasAttribute(AttrAmmoHoldCapacity)) {
1078  // verify hold capy
1079  if (pShipItem->GetMyInventory()->HasAvailableSpace(flag, chargeRef))
1080  flag = flagAmmoHold;
1081  } else
1082  */
1084  InventoryItemRef iRef = pShipItem->GetMyInventory()->GetByTypeFlag(chargeRef->typeID(), flagCargoHold);
1085  if (iRef.get() != nullptr) {
1086  // merge with existing item
1087  // in case we're merging into existing stack, get current qty
1088  int16 qty(chargeRef->quantity());
1089  chargeRef->Delete();
1090  iRef->AlterQuantity(qty, true);
1091  return;
1092  }
1093 
1094  chargeRef->Relocate(pShipItem->itemID(), flagCargoHold);
1095  } else {
1096  // dunno what to do at this point....the charge is already removed but cargo is full...pilot not paying attention
1097  // fuckit....space the bitch
1098  if (pShipItem->HasPilot())
1099  pShipItem->GetPilot()->SendNotifyMsg("Your cargo is full, so your %s was jettisoned and lost.", chargeRef->name());
1100 
1101  chargeRef->Delete();
1102  }
1103  }
1104 }
1105 
1107  GenericModule* pMod = GetModule(flag);
1108  if ((pMod != nullptr) and pMod->IsLoaded() )
1109  return pMod->GetLoadedChargeRef();
1110  return InventoryItemRef(nullptr);
1111 }
1112 
1114  return GetLoadedChargeOnModule(moduleRef->flag());
1115 }
1116 
1118  GenericModule* pMod = GetModule(itemID);
1119  if (pMod == nullptr) {
1120  _log(MODULE__ERROR, "MM::UnloadModule() - module not found for %u", itemID);
1121  return;
1122  }
1123 
1124  _log(MODULE__TRACE, "%s(%u) calling MM::UnloadModule(item)", pMod->GetSelf()->name(), pMod->itemID());
1125 
1126  UnloadCharge(pMod);
1127 }
1128 
1130  GenericModule* pMod = GetModule(flag);
1131  if (pMod == nullptr) {
1132  _log(MODULE__ERROR, "MM::UnloadModule() - module not found at %s", sDataMgr.GetFlagName(flag));
1133  return;
1134  }
1135 
1136  _log(MODULE__TRACE, "%s(%u) calling MM::UnloadModule(flag)", pMod->GetSelf()->name(), pMod->itemID());
1137 
1138  UnloadCharge(pMod);
1139 }
1140 
1142  _log(MODULE__TRACE, "%s(%u) calling MM::UnloadModule(mod)", pMod->GetSelf()->name(), pMod->itemID());
1143 
1144  UnloadCharge(pMod);
1145 }
1146 
1148 {
1149  std::map<uint8, GenericModule*>::iterator mItr;
1150  for (uint8 i = flagHiSlot0; 1 < flagFixedSlot; ++i) {
1151  mItr = m_modules.find((uint8)i);
1152  if (mItr->second != nullptr)
1153  UnloadCharge(mItr->second);
1154  }
1155 }
1156 
1158 {
1160  for (auto cur : m_modules)
1161  if (cur.second != nullptr)
1162  cur.second->UnloadCharge();
1163  // can this be called when docked?
1164  //bool docked = sDataMgr.IsStation(pShipItem->locationID());
1165  for (auto cur : m_charges)
1166  UnloadModule(cur.second->flag());
1167 
1168  m_charges.clear();
1169 }
1170 
1171 void ModuleManager::UpdateModules(std::vector<uint32> modVec)
1172 {
1173  if (is_log_enabled(MODULE__WARNING))
1174  sLog.Magenta("MM::UpdateModules()","testing");
1175  // this one is called from BoardShip() and Ship::Undock()
1179  //OfflineAll(); // set all modules to offline. this verifies the following Online() call will only online previously-set modules. (elusive error)
1180  if (!modVec.empty()) {
1181  _log(MODULE__TRACE, "MM::UpdateModules(modVec)");
1182  // gotta add rigs and Subsystems to the vector, as they wont be listed in the "modules to online" list when undocking.
1183  GetShipRigs(modVec);
1184  GetShipSubSystems(modVec);
1185  std::vector< GenericModule* > modList;
1186  SortModulesBySlotDec(modVec, modList);
1188  for (auto cur : modList) {
1189  cur->Update();
1190  cur->Online();
1191  }
1192  }
1193 }
1194 
1196 {
1198  // this should update all ship attribs for this bank.
1199  if (is_log_enabled(MODULE__WARNING))
1200  sLog.Magenta("MM::UpdateModules(flag)","Needs to be implemented");
1201 
1202  // reset ship and module effect data, and reapply?
1203  // call ProcessEffects(false), ApplyEffects(), then UpdateModules() ?
1204  std::vector< GenericModule* > modVec;
1205  // this returns only populated modules for this bank
1206  GetModulesInBank(flag, modVec);
1207  for (auto cur : modVec)
1208  cur->Online();
1209 }
1210 
1212 {
1213  if (is_log_enabled(MODULE__WARNING))
1214  sLog.Magenta("MM::CharacterBoardingShip()","Needs to be tested");
1215  if (!m_initalized)
1216  Initialize();
1217  std::vector<uint32> modVec;
1218  GetShipRigs(modVec);
1219  GetShipSubSystems(modVec);
1220  std::vector< GenericModule* > modList;
1221  SortModulesBySlotDec(modVec, modList);
1223  for (auto cur : modList)
1224  if (cur->GetAttribute(AttrOnline).get_bool())
1225  cur->Online();
1226 }
1227 
1229 {
1230  // if ship is killed, no point setting modules to offline...just return
1231  if (pShipItem->IsPopped())
1232  return;
1233 
1234  //OfflineAll();
1235 
1236  /* this is complicated and im gonna leave it alone for now
1237  * this will include checking ship HP, cargo holds, and possibably other things
1238  * that havent been written yet.
1239  * see if these can throw, else we'll have to do a bool return from calls and go from there.
1240  *
1241  * will also have to check current levels of hp and cargo AFTER pilot has been removed (lost skills)
1242  if (is_log_enabled(MODULE__WARNING))
1243  sLog.Magenta("MM::CharacterLeavingShip()","Needs to be implemented");
1244  */
1245  //CheckNewHP();
1246  //CheckNewCargo();
1247 }
1248 
1250 {
1251  if (is_log_enabled(MODULE__WARNING))
1252  sLog.Magenta("MM::ShipWarping()","Deactivating non-warpsafe modules.");
1253  // check modules for warpsafe-ness and Deactivate accordingly
1254  for (auto cur : m_modules)
1255  if (cur.second != nullptr)
1256  if (!cur.second->isWarpSafe())
1257  cur.second->AbortCycle();
1258 }
1259 
1261 {
1262  if (is_log_enabled(MODULE__WARNING))
1263  sLog.Magenta("MM::ShipJumping()","Deactivating all modules.");
1264 
1265  // no modules are jumpsafe
1266  AbortCycle();
1267 }
1268 
1270  // loop thru modules and deactivate anything that drops items in cargo
1271  //std::string effect = "CargoFull";
1272  for (auto cur : m_modules)
1273  if (cur.second != nullptr)
1274  switch (cur.second->groupID()) {
1281  cur.second->Deactivate();
1282  } break;
1283  // no default
1284  }
1285 }
1286 
1287 void ModuleManager::GetWeapons(std::list< GenericModule* >& weaponList)
1288 {
1290  if (m_modules[flag] != nullptr)
1291  if (m_modules[flag]->IsLauncherModule() or m_modules[flag]->IsTurretModule())
1292  weaponList.push_back(m_modules[flag]);
1293 }
1294 
1295 void ModuleManager::GetModuleListOfRefsAsc(std::vector<InventoryItemRef>& modVec)
1296 {
1297  for (auto cur : m_modules)
1298  if (cur.second != nullptr)
1299  modVec.push_back(cur.second->GetSelf());
1300 }
1301 
1302 void ModuleManager::GetModuleListOfRefsDec(std::vector< InventoryItemRef >& modVec)
1303 {
1304  std::map<uint8, GenericModule*>::reverse_iterator itr = m_modules.rbegin(), end = m_modules.rend();
1305  while (itr != end) {
1306  if (itr->second != nullptr)
1307  modVec.push_back( itr->second->GetSelf() );
1308  ++itr;
1309  }
1310 }
1311 
1312 void ModuleManager::GetModuleListOfRefsOrdered( std::vector< InventoryItemRef >& modVec )
1313 {
1314  // this is to list all ship modules by order of subsys, rig, low, mid, hi
1315  // subsystems
1317  if (m_modules[flag] != nullptr)
1318  modVec.push_back(m_modules[flag]->GetSelf());
1319  // rigs
1321  if (m_modules[flag] != nullptr)
1322  modVec.push_back(m_modules[flag]->GetSelf());
1323  // low slots
1325  if (m_modules[flag] != nullptr)
1326  modVec.push_back(m_modules[flag]->GetSelf());
1327  // mid slots
1328  for (uint8 flag = flagMidSlot0; flag < flagHiSlot0; ++flag)
1329  if (m_modules[flag] != nullptr)
1330  modVec.push_back(m_modules[flag]->GetSelf());
1331  // hi slots
1332  for (uint8 flag = flagHiSlot0; flag < flagFixedSlot; ++flag)
1333  if (m_modules[flag] != nullptr)
1334  modVec.push_back(m_modules[flag]->GetSelf());
1335 }
1336 
1337 void ModuleManager::GetModuleListOfRefsOrderedRev( std::vector< InventoryItemRef >& modVec ) {
1338 
1339  // this is to list all ship modules by order of hi, mid, low, rig, subsys
1340  // hi slots
1342  if (m_modules[flag] != nullptr)
1343  modVec.push_back(m_modules[flag]->GetSelf());
1344  // mid slots
1345  for (uint8 flag = flagMidSlot0; flag < flagHiSlot0; ++flag)
1346  if (m_modules[flag] != nullptr)
1347  modVec.push_back(m_modules[flag]->GetSelf());
1348  // low slots
1350  if (m_modules[flag] != nullptr)
1351  modVec.push_back(m_modules[flag]->GetSelf());
1352  // rigs
1354  if (m_modules[flag] != nullptr)
1355  modVec.push_back(m_modules[flag]->GetSelf());
1356  // subsystems
1358  if (m_modules[flag] != nullptr)
1359  modVec.push_back(m_modules[flag]->GetSelf());
1360 }
1361 
1362 void ModuleManager::GetModuleListByReqSkill(uint16 skillID, std::vector< InventoryItemRef >& modVec)
1363 {
1364  std::vector<InventoryItemRef> moduleList;
1365  GetModuleListOfRefsAsc(moduleList);
1366  for (auto cur : moduleList)
1367  if (cur->HasReqSkill(skillID))
1368  modVec.push_back(cur);
1369 }
1370 
1372 {
1373  for (auto cur : m_modules)
1374  if (cur.second != nullptr)
1375  cur.second->GetSelf()->SaveItem();
1376  for (auto cur : m_charges)
1377  cur.second->SaveItem();
1378 }
1379 
1380 void ModuleManager::GetShipRigs(std::vector< uint32 >& modVec)
1381 {
1382  // get rigs on ship, by itemID (there's only 3 slots...)
1383  GenericModule* pMod(nullptr);
1384  for (uint8 i = flagRigSlot0; i < flagRigSlot3; ++i) {
1385  pMod = GetModule((EVEItemFlags)i);
1386  if (pMod != nullptr)
1387  modVec.push_back(pMod->itemID());
1388  pMod = nullptr;
1389  }
1390 }
1391 
1392 void ModuleManager::GetShipSubSystems(std::vector< uint32 >& modVec)
1393 {
1394  // get subsystems on ship, by itemID (there's only 5 slots...)
1395  GenericModule* pMod(nullptr);
1396  for (uint8 i = flagSubSystem0; i < flagSubSystem5; ++i) {
1397  pMod = GetModule((EVEItemFlags)i);
1398  if (pMod != nullptr)
1399  modVec.push_back(pMod->itemID());
1400  pMod = nullptr;
1401  }
1402 }
1403 
1404 void ModuleManager::SortModulesBySlotDec(std::vector<uint32>& modVec, std::vector< GenericModule* >& pModList)
1405 {
1406  if (modVec.empty())
1407  return;
1408  GenericModule* pMod(nullptr);
1409  std::map<uint8, GenericModule*> tmpList;
1410  for (auto cur : modVec) {
1411  pMod = GetModule(cur);
1412  if (pMod != nullptr)
1413  tmpList.insert(std::pair<uint8, GenericModule*>((uint8)pMod->flag(), pMod));
1414  pMod = nullptr;
1415  }
1416  if (tmpList.empty())
1417  return;
1418  std::map<uint8, GenericModule*>::reverse_iterator itr = tmpList.rbegin();
1419  for (; itr != tmpList.rend(); ++itr)
1420  pModList.push_back(itr->second);
1421 }
1422 
1423 void ModuleManager::GetActiveModules(uint8 rack, std::vector< GenericModule* >& modVec)
1424 {
1425  std::vector< GenericModule* > modVecAll;
1426  switch (rack) {
1427  case EVEEffectID::hiPower: {
1428  GetModulesInBank(flagHiSlot0, modVecAll);
1429  } break;
1430  case EVEEffectID::medPower: {
1431  GetModulesInBank(flagMidSlot0, modVecAll);
1432  } break;
1433  case EVEEffectID::loPower: {
1434  GetModulesInBank(flagLowSlot0, modVecAll);
1435  } break;
1436  }
1437 
1438  for (auto cur : modVecAll)
1439  if (cur->IsActive())
1440  if (!cur->IsOverloaded())
1441  modVec.push_back(cur);
1442 }
1443 
1445 {
1446  std::vector< GenericModule* > modVecAll;
1447  switch (rack) {
1448  case EVEEffectID::hiPower: {
1449  GetModulesInBank(flagHiSlot0, modVecAll);
1450  } break;
1451  case EVEEffectID::medPower: {
1452  GetModulesInBank(flagMidSlot0, modVecAll);
1453  } break;
1454  case EVEEffectID::loPower: {
1455  GetModulesInBank(flagLowSlot0, modVecAll);
1456  } break;
1457  }
1458 
1459  for (auto cur : modVecAll)
1460  if (cur->IsActive()) {
1461  if (!cur->IsOverloaded())
1462  heat += cur->GetAttribute(AttrHeatDamage).get_float() /10;
1463  } else {
1464  //AttrHeatAbsorbtionRateModifier -- if this module is inactive, it will absorb this much heat.
1465  heat -= cur->GetAttribute(AttrHeatAbsorbtionRateModifier).get_float() *10;
1466  }
1467 }
1468 
1470 {
1471  uint8 count = 0;
1472  std::vector< GenericModule* > modVec;
1473  switch (rack) {
1474  case EVEEffectID::hiPower: {
1475  GetModulesInBank(flagHiSlot0, modVec);
1476  } break;
1477  case EVEEffectID::medPower: {
1478  GetModulesInBank(flagMidSlot0, modVec);
1479  } break;
1480  case EVEEffectID::loPower: {
1481  GetModulesInBank(flagLowSlot0, modVec);
1482  } break;
1483  }
1484 
1485  for (auto cur : modVec)
1486  if (cur->IsActive())
1487  if (!cur->IsOverloaded())
1488  ++count;
1489 
1490  return count;
1491 }
1492 
1494 {
1495  if (m_modByGroup.find(groupID) != m_modByGroup.end() )
1496  return m_modByGroup.find(groupID)->second;
1497 
1498  return 0;
1499 }
1500 
1502 {
1503  // add module to main map
1504  m_modules.at(flag) = pMod;
1505  // add module to proc maps
1506  if (IsFittingSlot(flag)) {
1507  m_fittings.at(flag) = pMod;
1508  } else if (IsRigSlot(flag)) {
1509  m_systems.at(flag) = pMod;
1510  } else if (IsSubSystem(flag)) {
1511  m_systems.at(flag) = pMod;
1512  } else { // error here.
1513  sLog.Error("MM::addModuleRef()", "%s(%u) sent flag '%s'", pMod->GetSelf()->name(), pMod->itemID(), sDataMgr.GetFlagName(flag));
1514  if (sConfig.debug.IsTestServer)
1515  EvE::traceStack();
1516  return;
1517  }
1518 
1519  _log(MODULE__TRACE, "MM::addModuleRef() - adding %s in %s to map.", pMod->GetSelf()->name(), sDataMgr.GetFlagName(flag));
1520 
1521  // Maintain the Modules Fitted By Group counter for this module group:
1522  if (m_modByGroup.find(pMod->groupID()) != m_modByGroup.end()) {
1523  m_modByGroup.find(pMod->groupID())->second += 1;
1524  } else {
1525  m_modByGroup.emplace(pMod->groupID(), 1);
1526  }
1527 
1528  // update available slots
1529  if (pMod->isHighPower()) {
1530  bool update = !pShipItem->GetPilot()->IsLogin();
1531  if (pMod->isTurretFitted()) {
1532  // apply config modifier, if applicable
1533  pMod->GetSelf()->MultiplyAttribute(AttrSpeed, sConfig.rates.turretRoF);
1535  pShipItem->SetAttribute(AttrTurretSlotsLeft, count, update);
1536  } else if (pMod->isLauncherFitted()) {
1537  // apply config modifier, if applicable
1538  pMod->GetSelf()->MultiplyAttribute(AttrSpeed, sConfig.rates.missileRoF);
1540  pShipItem->SetAttribute(AttrLauncherSlotsLeft, count, update);
1541  }
1542  --m_HighSlots;
1543  } else if (pMod->isMediumPower()) {
1544  --m_MidSlots;
1545  } else if (pMod->isLowPower()) {
1546  --m_LowSlots;
1547  } else if (pMod->isSubSystem()) {
1548  --m_SubSystemSlots;
1549  } else if (pMod->isRig()) {
1550  --m_RigSlots;
1551  bool update = !pShipItem->GetPilot()->IsLogin();
1554  }
1555 }
1556 
1558 {
1559  // remove module from main map
1560  m_modules.at(flag) = nullptr;
1561  // remove module from proc maps
1562  if (IsFittingSlot(flag)) {
1563  m_fittings.at(flag) = nullptr;
1564  } else if (IsRigSlot(flag)) {
1565  m_systems.at(flag) = nullptr;
1566  } else if (IsSubSystem(flag)) {
1567  m_systems.at(flag) = nullptr;
1568  } else { // error here.
1569  sLog.Error("MM::deleteModuleRef()", "%s(%u) sent flag '%s'", pMod->GetSelf()->name(), pMod->itemID(), sDataMgr.GetFlagName(flag));
1570  if (sConfig.debug.IsTestServer)
1571  EvE::traceStack();
1572  return;
1573  }
1574 
1575  _log(MODULE__TRACE, "MM::deleteModuleRef() - removing %s from %s.", pMod->GetSelf()->name(), sDataMgr.GetFlagName(flag));
1576 
1577  // Maintain the Modules Fitted By Group counter for this module group:
1578  if (m_modByGroup.find(pMod->groupID()) != m_modByGroup.end()) {
1579  m_modByGroup.find(pMod->groupID())->second -= 1;
1580  if (m_modByGroup.find(pMod->groupID())->second < 1) {
1581  // This was the last (or only) module of this group fitted, so remove the entry from the map:
1582  m_modByGroup.erase(pMod->groupID());
1583  }
1584  }
1585 
1586  // update available slots
1587  if (pMod->isHighPower()) {
1588  if (pMod->isTurretFitted()) {
1591  } else if (pMod->isLauncherFitted()) {
1594  }
1595  ++m_HighSlots;
1596  } else if (pMod->isMediumPower()) {
1597  ++m_MidSlots;
1598  } else if (pMod->isLowPower()) {
1599  ++m_LowSlots;
1600  } else if (pMod->isSubSystem()) {
1601  ++m_SubSystemSlots;
1602  } else if (pMod->isRig()) {
1603  ++m_RigSlots;
1606  }
1607 }
1608 
1610 {
1611  if (!IsSlotOccupied(slot1) or !IsSlotOccupied(slot2))
1612  return true;
1613  return (GetModule(slot1)->GetModulePowerLevel() == GetModule(slot2)->GetModulePowerLevel());
1614 }
1615 
1616 /*
1617  * {'messageKey': 'EffectDeactivationCloaking', 'dataID': 17883455, 'suppressable': False, 'bodyID': 259510, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 849}
1618  * {'messageKey': 'EffectDeactivationWarping', 'dataID': 17883458, 'suppressable': False, 'bodyID': 259511, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 850}
1619  *
1620  * {'FullPath': u'UI/Messages', 'messageID': 259510, 'label': u'EffectDeactivationCloakingBody'}(u'As certain activated effects interfere with the warping process, these are automatically being deactivated before the warp proceeds.', None, None)
1621  * {'FullPath': u'UI/Messages', 'messageID': 259511, 'label': u'EffectDeactivationWarpingBody'}(u'As certain activated effects interfere with the warping process, these are automatically being deactivated before the warp proceeds.', None, None)
1622  */
1623 
1625  for (auto cur : m_charges) {
1626  cur.second->AlterQuantity(+1, false);
1627  cur.second->AlterQuantity(-1, false);
1628  }
1629 }
bool IsLogin()
Definition: Client.h:235
Base Python wire object.
Definition: PyRep.h:66
bool isHighPower()
Definition: GenericModule.h:92
#define sConfig
A macro for easier access to the singleton.
unsigned __int8 uint8
Definition: eve-compat.h:46
void addModuleRef(EVEItemFlags flag, GenericModule *pMod)
void GetInventoryVec(std::vector< InventoryItemRef > &itemVec)
Definition: Inventory.cpp:345
void SendNotification(const PyAddress &dest, EVENotificationStream &noti, bool seq=true)
Definition: Client.cpp:2245
SystemEntity * GetSE(uint32 entityID) const
void CheckSlotFitLimited(EVEItemFlags flag)
void deleteModuleRef(EVEItemFlags flag, GenericModule *pMod)
void DeOverload(uint32 itemID)
bool isLauncherFitted()
Definition: GenericModule.h:57
void SendErrorMsg(const char *fmt,...)
Definition: Client.cpp:2719
#define _log(type, fmt,...)
Definition: logsys.h:124
InventoryItemRef GetLoadedChargeOnModule(EVEItemFlags flag)
virtual void AbortCycle()
virtual bool Merge(InventoryItemRef to_merge, int32 qty=0, bool notify=true)
bool isMediumPower()
Definition: GenericModule.h:93
bool HasAttribute(uint32 attrID)
Definition: GenericModule.h:50
uint32 groupID()
Definition: GenericModule.h:99
bool get_bool()
Definition: EvilNumber.cpp:157
uint32 ownerID() const
Definition: InventoryItem.h:99
void UnfitModule(uint32 itemID)
uint8 m_SubSystemSlots
bool HasAvailableSpace(EVEItemFlags flag, InventoryItemRef iRef) const
Definition: Inventory.cpp:625
virtual void DeOverload()
EVEItemFlags
Definition: EVE_Flags.h:13
UserError & AddTypeName(const char *name, uint32 typeID)
Shorthand method for adding a type's name.
#define sProfiler
Definition: dbcore.cpp:39
void UnloadModule(uint32 itemID)
virtual bool HasPilot()
Definition: Ship.h:71
virtual void RemoveRig()
InventoryItemRef GetLoadedChargeRef()
#define sEntityList
Definition: EntityList.h:208
void GetActiveModules(uint8 rack, std::vector< GenericModule * > &modVec)
void CheckGroupFitLimited(EVEItemFlags flag, InventoryItemRef iRef)
void GetShipRigs(std::vector< uint32 > &modVec)
#define IsMidSlot(flag)
Definition: EVE_Defines.h:361
this is a class that kinda mimics how python polymorph's numbers.
Definition: EvilNumber.h:59
const char * name()
bool IsInSpace()
Definition: Client.h:228
#define IsLowSlot(flag)
Definition: EVE_Defines.h:364
void SendNotifyMsg(const char *fmt,...)
Definition: Client.cpp:2776
Python tuple.
Definition: PyRep.h:567
void SetAttribute(uint32 attrID, EvilNumber val, bool update=true)
Definition: GenericModule.h:51
Advanced version of UserError that allows to send a full custom message.
Definition: PyExceptions.h:453
uint32 itemID()
Definition: GenericModule.h:97
void UninstallRig(uint32 itemID)
float m_rigScanBonus
void GetModulesInBank(EVEItemFlags flag, std::vector< GenericModule * > &modVec)
#define IsHiSlot(flag)
Definition: EVE_Defines.h:358
EvilNumber EvilZero
Definition: EvilNumber.cpp:32
void SafeDelete(T *&p)
Deletes and nullifies a pointer.
Definition: SafeMem.h:83
int8 GetModuleState()
uint16 groupID() const
signed __int32 int32
Definition: eve-compat.h:49
void GetWeapons(std::list< GenericModule * > &weaponList)
std::map< uint8, GenericModule * > m_fittings
#define is_log_enabled(type)
Definition: logsys.h:78
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
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
void GetModuleListOfRefsAsc(std::vector< InventoryItemRef > &modVec)
DestinyManager * DestinyMgr()
Definition: SystemEntity.h:198
double GetTimeUSeconds()
Definition: utils_time.cpp:116
GenericModule * GetModule(EVEItemFlags flag)
PyRep * ModuleRepair(uint32 modID)
Python object.
Definition: PyRep.h:826
void UpdateModules(std::vector< uint32 > modVec)
bool VerifySlotExchange(EVEItemFlags slot1, EVEItemFlags slot2)
void GetModuleListOfRefsOrderedRev(std::vector< InventoryItemRef > &modVec)
virtual void Activate(uint16 effectID, uint32 targetID=0, int16 repeat=0)
bool InstallRig(ModuleItemRef mRef, EVEItemFlags flag)
void GetModuleListOfRefsOrdered(std::vector< InventoryItemRef > &modVec)
ModuleItemRef GetSelf()
Definition: GenericModule.h:42
#define codelog(type, fmt,...)
Definition: logsys.h:128
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
bool IsDocked()
Definition: Client.h:229
SystemManager * SystemMgr() const
Definition: Client.h:92
uint32 get_uint32()
Definition: EvilNumber.cpp:173
#define sFxDataMgr
bool isLowPower()
Definition: GenericModule.h:91
bool InstallSubSystem(ModuleItemRef mRef, EVEItemFlags flag)
uint32 locationID() const
virtual void Overload()
Python integer.
Definition: PyRep.h:231
bool CanThrow()
Definition: Client.h:431
std::map< EVEItemFlags, InventoryItemRef > m_charges
void DeactivateAllModules()
void Activate(int32 itemID, uint16 effectID, int32 targetID, int32 repeat)
void SetAttribute(uint16 attrID, int num, bool notify=true)
EVEEffectID
Definition: EVE_Effects.h:16
#define PyStatic
Definition: PyRep.h:1209
X * get() const
Definition: RefPtr.h:213
#define IsFittingSlot(flag)
Definition: EVE_Defines.h:355
uint8 GetFittedModuleCountByGroup(uint16 groupID)
void GetShipSubSystems(std::vector< uint32 > &modVec)
const char * GetName() const
Definition: Client.h:94
const char * GetName() const
Definition: SystemEntity.h:210
static GenericModule * ModuleFactory(ModuleItemRef mRef, ShipItemRef sRef)
Definition: ModuleFactory.h:41
void StopModuleRepair(uint32 modID)
Python object "ccp_exceptions.UserError".
Definition: PyExceptions.h:121
#define IsSubSystem(flag)
Definition: EVE_Defines.h:370
bool IsPopped()
Definition: Ship.h:89
bool ChangeSingleton(bool singleton, bool notify=false)
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
void DamageRandModule()
void SortModulesBySlotDec(std::vector< uint32 > &modVec, std::vector< GenericModule * > &pModList)
GenericModule * GetRandModule()
void RemoveTarget(SystemEntity *pSE)
void MultiplyAttribute(uint16 attrID, EvilNumber num, bool notify=false)
EVEItemFlags flag() const
void UnloadCharge(GenericModule *pMod)
ShipItem * pShipItem
void GetModuleListByReqSkill(uint16 skillID, std::vector< InventoryItemRef > &modVec)
void Deactivate(uint32 itemID, std::string effectName)
std::map< uint16, uint8 > m_modByGroup
RefPtr< InventoryItem > InventoryItemRef
Definition: ItemRef.h:52
void CharacterLeavingShip()
Definition: Ship.h:46
bool isTurretFitted()
Definition: GenericModule.h:56
RefPtr< ShipItem > ShipItemRef
Definition: ItemRef.h:54
uint16 GetAvailableSlotInBank(EVEEffectID slotBank)
#define IsModuleSlot(flag)
Definition: EVE_Defines.h:350
EVEItemFlags flag()
int64 MakeRandomInt(int64 low, int64 high)
Generates random integer from interval [low; high].
Definition: misc.cpp:109
ShipSE * GetShipSE()
Definition: Client.h:168
int64 max(int64 x, int64 y=0)
Definition: misc.h:103
bool IsJump()
Definition: Client.h:232
virtual Client * GetPilot()
Definition: Ship.h:72
void Offline(uint32 itemID)
virtual void UnloadCharge()
EvilNumber GetAttribute(const uint16 attrID) const
void LoadCharge(InventoryItemRef chargeRef, EVEItemFlags flag)
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
void RepairModule(uint32 itemID, EvilNumber amount)
signed __int16 int16
Definition: eve-compat.h:47
virtual void LoadCharge(InventoryItemRef charge)
bool AddModule(ModuleItemRef mRef, EVEItemFlags flag)
#define IsRigSlot(flag)
Definition: EVE_Defines.h:367
std::map< uint8, GenericModule * > m_systems
void Online(uint32 itemID)
void traceStack(void)
Definition: misc.cpp:169
void GetActiveModulesHeat(uint8 rack, float &heat)
#define sItemFactory
Definition: ItemFactory.h:165
void CharacterBoardingShip()
void Overload(uint32 itemID)
float get_float()
Definition: EvilNumber.cpp:184
std::map< uint8, GenericModule * > m_modules
bool isSubSystem()
Definition: GenericModule.h:95
bool IsSlotOccupied(EVEItemFlags flag)
ModuleManager(ShipItem *const pShip)
void DamageModule(uint32 itemID, float amount)
Inventory * GetMyInventory()
Definition: InventoryItem.h:91
unsigned __int16 uint16
Definition: eve-compat.h:48
EvilNumber GetAttribute(uint32 attrID)
Definition: GenericModule.h:53
virtual void Deactivate(std::string effect="")
InventoryItemRef GetByTypeFlag(uint32 typeID, EVEItemFlags flag) const
Definition: Inventory.cpp:444
uint16 typeID() const
void SetModuleState(int8 state)
uint8 categoryID() const
uint8 GetActiveModulesCount(uint8 rack)
const char * itoa(int64 num)
Convers num to string.
uint32 typeID()
Definition: GenericModule.h:98
uint32 itemID() const
Definition: InventoryItem.h:98
void GetModuleListOfRefsDec(std::vector< InventoryItemRef > &modVec)
void UnlinkGroup(uint32 memberID, bool update=false)
Definition: Ship.cpp:1602
int32 quantity() const
Definition: InventoryItem.h:97
#define sDataMgr