EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Structure.cpp
Go to the documentation of this file.
1 
11 /*
12  * POS__ERROR
13  * POS__WARNING
14  * POS__MESSAGE
15  * POS__DUMP
16  * POS__DEBUG
17  * POS__DESTINY
18  * POS__SLIMITEM
19  * POS__TRACE
20  */
21 
22 #include "Client.h"
23 #include "EntityList.h"
24 #include "EVEServerConfig.h"
25 #include "StaticDataMgr.h"
27 #include "planet/Moon.h"
28 #include "planet/Planet.h"
29 #include <planet/CustomsOffice.h>
30 #include "pos/Tower.h"
31 #include "pos/sovStructures/TCU.h"
32 #include "pos/sovStructures/SBU.h"
33 #include "pos/sovStructures/IHub.h"
34 #include "pos/JumpBridge.h"
35 #include "pos/Structure.h"
36 #include "system/Container.h"
37 #include "system/Damage.h"
38 #include "system/SystemManager.h"
41 
42 /*
43  * Base Structure Item for all POS types
44  */
45 StructureItem::StructureItem(uint32 _structureID, const ItemType &_itemType, const ItemData &_data)
46  : InventoryItem(_structureID, _itemType, _data)
47 {
49  _log(ITEM__TRACE, "Created StructureItem for %s (%u).", name(), itemID());
50  _log(POS__TRACE, "Created StructureItem for %s (%u).", name(), itemID());
51 }
52 
54 {
56 }
57 
59 {
60  return InventoryItem::Load<StructureItem>(structureID);
61 }
62 
64 {
65  if (!pInventory->LoadContents())
66  return false;
67 
68  return InventoryItem::_Load();
69 }
70 
72 {
73  uint32 structureID = InventoryItem::CreateItemID(data);
74  if (structureID < 1)
75  return StructureItemRef(nullptr);
76  StructureItemRef sRef = StructureItem::Load(structureID);
77  // check for customs offices and set global flag
79  {
80  sRef->SetAttribute(AttrIsGlobal, EvilOne);
81  }
82  // Create default dynamic attributes in the AttributeMap:
83  sRef->SetAttribute(AttrMass, sRef->type().mass(), false);
84  sRef->SetAttribute(AttrRadius, sRef->type().radius(), false);
85  sRef->SetAttribute(AttrVolume, sRef->type().volume(), false);
86  sRef->SetAttribute(AttrCapacity, sRef->type().capacity(), false);
87  sRef->SetAttribute(AttrShieldCharge, sRef->GetAttribute(AttrShieldCapacity), false);
88 
89  // Check for existence of some attributes that may or may not have already been loaded and set them
90  // to default values:
91  if (!sRef->HasAttribute(AttrDamage))
92  sRef->SetAttribute(AttrDamage, EvilZero, false);
93  if (!sRef->HasAttribute(AttrArmorDamage))
94  sRef->SetAttribute(AttrArmorDamage, EvilZero, false);
95  if (!sRef->HasAttribute(AttrArmorMaxDamageResonance))
96  sRef->SetAttribute(AttrArmorMaxDamageResonance, EvilOne, false);
97  if (!sRef->HasAttribute(AttrShieldMaxDamageResonance))
98  sRef->SetAttribute(AttrShieldMaxDamageResonance, EvilOne, false);
99 
100  // Shield Resonance
101  if (!sRef->HasAttribute(AttrShieldEmDamageResonance))
102  sRef->SetAttribute(AttrShieldEmDamageResonance, EvilOne, false);
103  if (!sRef->HasAttribute(AttrShieldExplosiveDamageResonance))
104  sRef->SetAttribute(AttrShieldExplosiveDamageResonance, EvilOne, false);
105  if (!sRef->HasAttribute(AttrShieldKineticDamageResonance))
106  sRef->SetAttribute(AttrShieldKineticDamageResonance, EvilOne, false);
107  if (!sRef->HasAttribute(AttrShieldThermalDamageResonance))
108  sRef->SetAttribute(AttrShieldThermalDamageResonance, EvilOne, false);
109  // Armor Resonance
110  if (!sRef->HasAttribute(AttrArmorEmDamageResonance))
111  sRef->SetAttribute(AttrArmorEmDamageResonance, EvilOne, false);
112  if (!sRef->HasAttribute(AttrArmorExplosiveDamageResonance))
113  sRef->SetAttribute(AttrArmorExplosiveDamageResonance, EvilOne, false);
114  if (!sRef->HasAttribute(AttrArmorKineticDamageResonance))
115  sRef->SetAttribute(AttrArmorKineticDamageResonance, EvilOne, false);
116  if (!sRef->HasAttribute(AttrArmorThermalDamageResonance))
117  sRef->SetAttribute(AttrArmorThermalDamageResonance, EvilOne, false);
118  // Hull Resonance
119  if (!sRef->HasAttribute(AttrEmDamageResonance))
120  sRef->SetAttribute(AttrEmDamageResonance, EvilOne, false);
121  if (!sRef->HasAttribute(AttrExplosiveDamageResonance))
122  sRef->SetAttribute(AttrExplosiveDamageResonance, EvilOne, false);
123  if (!sRef->HasAttribute(AttrKineticDamageResonance))
124  sRef->SetAttribute(AttrKineticDamageResonance, EvilOne, false);
125  if (!sRef->HasAttribute(AttrThermalDamageResonance))
126  sRef->SetAttribute(AttrThermalDamageResonance, EvilOne, false);
127 
128  return sRef;
129 }
130 
132 {
133  // delete contents first
135 
137 }
138 
140 {
141  if (!pInventory->LoadContents()) {
142  codelog(ITEM__ERROR, "%s (%u): Failed to load contents for Structure", name(), m_itemID);
143  return nullptr;
144  }
145 
146  Rsp_CommonGetInfo result;
147  Rsp_CommonGetInfo_Entry entry;
148 
149  //first populate the Structure.
150  if (!Populate(entry))
151  return nullptr;
152 
153  result.items[m_itemID] = entry.Encode();
154 
155  return result.Encode();
156 }
157 
159 {
160  if (iRef.get() == nullptr)
161  return;
162 
163  // test for item types and verify flags here...
164 
166 
167  if (mySE->IsCOSE())
168  mySE->GetCOSE()->VerifyAddItem(iRef);
169 }
170 
172 {
173  if (iRef.get() == nullptr)
174  return;
175 
177 }
178 
179 void StructureItem::Rename(std::string name)
180 {
182  {
183  InventoryItem::Rename(name);
185  }
186  else
187  {
188  throw UserError ("SetNameObjectMustBeAnchoredInSpace");
189  }
190  // {'FullPath': u'UI/Messages', 'messageID': 258480, 'label': u'SetNameObjectMustBeAnchoredInSpaceBody'}(u'You can only rename this type of object if it is anchored in space (and you have a right to do so).', None, None)
191 }
192 
194  : DynamicSystemEntity(structure, services, system),
195  m_moonSE(nullptr),
196  m_planetSE(nullptr),
197  m_towerSE(nullptr),
198  m_tcuSE(nullptr),
199  m_sbuSE(nullptr),
200  m_ihubSE(nullptr),
201  m_gateSE(nullptr),
202  m_bridgeSE(nullptr),
203  m_procTimer(10000), // arbitrary default
204  m_tcu(false),
205  m_sbu(false),
206  m_ihub(false),
207  m_miner(false),
208  m_tower(false),
209  m_bridge(false),
210  m_jammer(false),
211  m_generator(false),
212  m_loaded(false),
213  m_module(false),
214  m_outpost(false),
215  m_reactor(false),
216  m_duration(0),
217  m_anchorPointID(0),
218  m_delayTime(0),
220  m_rotation(NULL_ORIGIN),
221  m_procState(EVEPOS::ProcState::Invalid),
222  m_data(EVEPOS::StructureData())// zero-init data
223 {
225 
226  m_warID = data.factionID;
227  m_allyID = data.allianceID;
228  m_corpID = data.corporationID;
229  m_ownerID = data.ownerID;
230 
231  // update StructureItem with SE;
232  structure->SetMySE(this);
233 
234  // set valid stateName
236 
237  _log(SE__DEBUG, "Created StructureSE for item %s (%u).", structure->name(), structure->itemID());
238 }
239 
241 {
242  // this item is a module. get towerID from bubble and save
243  if (m_module)
244  if (m_bubble->HasTower())
246 
247  if (m_bridge)
248  {
251 
253  data.itemID = m_data.itemID;
254  data.towerID = m_data.towerID;
255  data.corpID = m_corpID;
256  data.allyID = m_allyID;
257  data.systemID = m_system->GetID();
258  data.allowCorp = false;
259  data.allowAlliance = false;
260  m_db.SaveBridgeData(data);
261  }
262 
263  if (m_sbu)
264  { //SBUs are placed near stargates
267  }
268  else
269  { //Everything else is places near a moon
272  }
273 }
274 
276 {
277  // are we already initialized?
278  if (m_loaded)
279  return;
280 
281  // init all data here.
282  m_data.itemID = m_self->itemID();
283  if (m_data.itemID == 0)
284  {
285  // how the hell is itemID 0 here??
286  sLog.Error("StructureSE::Init", "ItemID is 0.");
287  EvE::traceStack();
288  m_system->RemoveEntity(this); //this may segfault here....
289  return;
290  }
293 
294  switch (m_self->groupID()) {
296  // should not hit here, but dont want to use 'default'
297  sLog.Error("StructureSE::Init", "groupID is Orbital_Infrastructure.");
298  EvE::traceStack();
299  } break;
301  m_sbu = true;
302  } break;
304  m_tower = true;
306  } break;
308  m_tcu = true;
309  } break;
311  m_bridge = true;
312  m_module = true;
313  } break;
319  m_jammer = true;
320  m_module = true;
321  } break;
323  m_generator = true;
324  m_module = true;
325  } break;
328  m_module = true;
329  m_reactor = true;
330  } break;
332  m_miner = true;
333  m_module = true;
334  m_reactor = true;
335  } break;
337  m_ihub = true;
338  } break;
339  default: {
340  m_module = true;
341  }
342  }
343 
344  if (!m_db.GetBaseData(m_data))
345  {
346  _log(POS__MESSAGE, "StructureSE::Init %s(%u) has no saved data. Initializing default set.", m_self->name(), m_data.itemID);
347  InitData();
349  }
350 
351  m_loaded = true;
352 
353  if (m_tcu or m_ihub) {
356  return;
357  }
358 
360  // make error here. this should never hit.
361  _log(POS__MESSAGE, "StructureSE::Init %s(%u) - anchorpointID is invalid. Load Failure.", m_self->name(), m_data.itemID);
362  m_loaded = false;
363  return;
364  }
365 
366  //Get entity for anchor point (type is determined by what is being anchored)
368  if (pSE == nullptr)
369  {
370  _log(POS__WARNING, "StructureSE::Init %s(%u) - Cannot find SE for anchorpointID %u. Load Failure.", \
372  m_loaded = false;
373  return;
374  }
375 
376  if (m_tcu)
377  {
378  m_tcuSE = pSE->GetTCUSE();
379  }
380 
381  if (m_sbu) //anchored near stargates, so we need a stargate
382  {
383  m_sbuSE = pSE->GetSBUSE();
384  if (m_gateSE == nullptr)
385  {
386  m_gateSE = pSE->GetGateSE();
387  }
388  }
389  if (m_ihub)
390  {
391  m_ihubSE = pSE->GetIHubSE();
392  }
393  if (m_bridge)
394  {
395  m_bridgeSE = pSE->GetJumpBridgeSE();
396  }
397  else //everything else is anchored near a moon
398  {
399  if (m_moonSE == nullptr)
400  {
401  m_moonSE = pSE->GetMoonSE();
402  }
403  }
404 
405  if (m_miner)
406  {
407  // need to verify m_moonSE isnt null at this point.
408  if (m_moonSE == nullptr)
409  {
410  //iRef->Delete(); // really delete this?
411  _log(POS__ERROR, "StructureSE::Init MoonSE for %s(%u) is invalid.", m_self->name(), m_data.itemID);
412  return;
413  }
415  dir.normalize();
416  m_rotation = dir;
417  }
418 
419  // all POS have 1h duration
420  if (m_tower)
421  {
423  }
424  else if (m_module)
425  {
427  if (pSE == nullptr)
428  {
429  _log(POS__ERROR, "StructureSE::Init %s(%u) is invalid. why are we here?", m_self->name(), m_data.itemID);
430  return;
431  }
432  m_towerSE = pSE->GetTowerSE();
433  m_towerSE->AddModule(this);
434  m_duration = 3600000; // modules default to 1h
435  }
436 
440  if (m_data.timestamp > 0)
441  {
442  // do something constructive here.
443  }
444 
447 }
448 
450 {
453 
454  // repackage item?
455  m_self->ChangeSingleton(false);
456 }
457 
459 {
460  /* called by EntityList::Process on every loop */
461  /* Enable base call to Process Targeting and Movement */
463 
464  if (m_procTimer.Check(false))
465  {
467  m_delayTime = 0;
468 
469  _log(POS__DEBUG, "Module %s(%u) Processing State '%s'", GetName(), m_data.itemID, sDataMgr.GetProcStateName(m_procState));
470 
471  using namespace EVEPOS;
472  switch (m_procState)
473  {
475  {
476  SendSlimUpdate();
477  m_destiny->SendSpecialEffect(m_data.itemID, m_data.itemID, m_self->typeID(), 0, 0, "effects.AnchorLift", 0, 0, 0, -1, 0);
479  }
480  break;
482  {
483  SendSlimUpdate();
484  m_destiny->SendSpecialEffect(m_data.itemID, m_data.itemID, m_self->typeID(), 0, 0, "effects.AnchorDrop", 0, 0, 0, -1, 0);
485  if (m_tower)
486  m_moonSE->SetTower(this);
487  if (m_sbu)
488  m_gateSE->SetSBU(this);
489 
491  }
492  break;
494  {
496  SetOffline();
497  SendSlimUpdate();
499  }
500  break;
501  case ProcState::Onlining:
502  {
504  SetOnline();
505  SendSlimUpdate();
507  }
508  break;
509  case ProcState::Online:
510  {
511  Online();
512  }
513  break;
515  {
516  // this is virtual, overridden in specific class' for their needs
517  // take resources or whatever needs to be done
518  Operating();
519  }
520  break;
521  // those below are not coded yet
525  {
528  //m_data.state = StructureState::Reinforced;
530  // set timer for time to come out of reinforced
531  /*Reinforcement is an established system in EVE where a structure becomes invulnerable for a period of time.
532  * The purpose is for the defending corporation to have a chance to react when their structure is attacked.
533  * The Control Tower enters reinforced mode when it reaches 25% shield and exits reinforcement somewhere
534  * within the time of day, specified by the owner at least 24 hours after it entered reinforcement.
535  * So if you set the reinforcement time to “23.00 – 01.00” that means that the Control Tower will, if attacked,
536  * exit reinforcement at some time between 23.00 and 01.00 the day after the attack was initiated.
537  * Your corporation will receive notification if your Control Tower enters reinforcement mode and that leaves you
538  * at least 24 hours to plan the defense.
539  * In order to reset the reinforcement cycle, the Control Tower Shield must be repaired back above 25%;
540  * note that it exits reinforcement with 0% shield.
541  *
542  */
543  }
544  break;
545  default:
546  case ProcState::Invalid:
547  {
548  // not sure what needs to be done at this point....we're nowhere close to having this coded.
549  }
550  break;
551  }
552 
553  // this will need more work
555 
558  }
559 }
560 
562 {
563  // this is for dropping POS where Init() and Add() each need info from the other.
564  m_bubble = pBubble;
565  Init();
566  // now null bubble to be added correctly
567  m_bubble = nullptr;
568 }
569 
570 /*{'messageKey': 'CantObjectInsideForceField', 'dataID': 17885214, 'suppressable': False, 'bodyID': 260153, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 399}
571  * {'messageKey': 'CantOnlineAnotherClaimMarkerOnlining', 'dataID': 17876439, 'suppressable': False, 'bodyID': 256876, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3091}
572  * {'messageKey': 'CantOnlineDamagedGoods', 'dataID': 17885104, 'suppressable': False, 'bodyID': 260116, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 400}
573  * {'messageKey': 'CantOnlineDisruptorAnchored', 'dataID': 17877056, 'suppressable': False, 'bodyID': 257107, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3116}
574  * {'messageKey': 'CantOnlineDisruptorNotClaimed', 'dataID': 17877530, 'suppressable': False, 'bodyID': 257286, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 2931}
575  * {'messageKey': 'CantOnlineDisruptorOutpostProtecting', 'dataID': 17876457, 'suppressable': False, 'bodyID': 256882, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3106}
576  * {'messageKey': 'CantOnlineDisruptorsOnline', 'dataID': 17877687, 'suppressable': False, 'bodyID': 257346, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 2932}
577  * {'messageKey': 'CantOnlineInfrastructureDontOwnFlag', 'dataID': 17876442, 'suppressable': False, 'bodyID': 256877, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3153}
578  * {'messageKey': 'CantOnlineInfrastructureHubAlreadyInSystem', 'dataID': 17876267, 'suppressable': False, 'bodyID': 256810, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3056}
579  * {'messageKey': 'CantOnlineInfrastructureHubNoSovereignty', 'dataID': 17876796, 'suppressable': False, 'bodyID': 257014, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3125}
580  * {'messageKey': 'CantOnlineInfrastructurePresent', 'dataID': 17877059, 'suppressable': False, 'bodyID': 257108, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3115}
581  * {'messageKey': 'CantOnlineMissingUpgrade', 'dataID': 17876891, 'suppressable': False, 'bodyID': 257047, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3080}
582  * {'messageKey': 'CantOnlineNoInfrastructureHub', 'dataID': 17876280, 'suppressable': False, 'bodyID': 256815, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3078}
583  * {'messageKey': 'CantOnlineNotLinked', 'dataID': 17879371, 'suppressable': False, 'bodyID': 257982, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 2294}
584  * {'messageKey': 'CantOnlineNotSovereign', 'dataID': 17876923, 'suppressable': False, 'bodyID': 257058, 'messageType': 'hint', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3144}
585  * {'messageKey': 'CantOnlineRequireTower', 'dataID': 17885220, 'suppressable': False, 'bodyID': 260155, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 401}
586  * {'messageKey': 'CantOnlineSovInWormhole', 'dataID': 17877461, 'suppressable': False, 'bodyID': 257260, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 2935}
587  * {'messageKey': 'CantOnlineSovereigntyAlreadyClaimed', 'dataID': 17876445, 'suppressable': False, 'bodyID': 256878, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3044}
588  * {'messageKey': 'CantOnlineStructureGroupLimit', 'dataID': 17879595, 'suppressable': False, 'bodyID': 258065, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 2407}
589  * {'messageKey': 'CantOnlineStructureOwnerBad', 'dataID': 17885124, 'suppressable': False, 'bodyID': 260123, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 402}
590  * {'messageKey': 'CantOnlineStructureRequiresSovereigntyLevel', 'dataID': 17879395, 'suppressable': False, 'bodyID': 257991, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 2254}
591  * {'messageKey': 'CantOnlineTowerLacksCpuResources', 'dataID': 17885223, 'suppressable': False, 'bodyID': 260156, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 403}
592  * {'messageKey': 'CantOnlineTowerLacksPowerResources', 'dataID': 17885226, 'suppressable': False, 'bodyID': 260157, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 404}
593  * {'messageKey': 'CantOnlineTowerLacksResources', 'dataID': 17885363, 'suppressable': False, 'bodyID': 260207, 'messageType': 'notify', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 405}
594  * {'messageKey': 'CantOnlineWithinGlobalDisruptor', 'dataID': 17876951, 'suppressable': False, 'bodyID': 257068, 'messageType': 'hint', 'urlAudio': '', 'urlIcon': '', 'titleID': None, 'messageID': 3180}
595  *{'FullPath': u'UI/Messages', 'messageID': 260213, 'label': u'CannotRemoveFromLowShieldTowerBody'}(u'You cannot remove {[item]item.name} from the {[item]type.name} while it is reinforced or has a shield level lower than {[numeric]level}%.', None, {u'{[item]item.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{[item]type.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'type'}, u'{[numeric]level}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'level'}})
596  *
597  * {'FullPath': u'UI/Messages', 'messageID': 259215, 'label': u'OnlineRequiredAnchorBody'}(u'The {item} can only be brought online when it is firmly anchored. It cannot be brought online while unanchored, unanchoring or while anchoring.', None, {u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'}})
598  *
599  */
601 {
603  {
604  pClient->SendErrorMsg("The %s is already anchored", m_self->name());
605  return; // make error here?
606  }
607 
608  /* returns SetBallPosition for towers.
609  * ct will anchor in the middle of the grid that you warp-in to....supposed to, but i dont know how yet.
610  */
611 
614  /* @todo set min/max anchor distances....this will need more work...
615  uint32 anchorMin(m_self->GetAttribute(AttrAnchorDistanceMin).get_uint32());
616  uint32 anchorMax(m_self->GetAttribute(AttrAnchorDistanceMax).get_uint32());
617  */
618 
619  // this is incomplete. there may be client error msgs (havent looked or found)
620  // these errors should throw instead of return.
621 
622  // Check for required sovereignty upgrades for certain structures
623  if ((m_generator) || (m_jammer) || (m_bridge)) {
624  SovereigntyData sovData = svDataMgr.GetSovereigntyData(pClient->GetLocationID());
625  InventoryItemRef ihubRef = sItemFactory.GetItem(sovData.hubID);
627 
628  if (!ihubRef->GetMyInventory()->ContainsTypeQty(upgType,1)) {
629  pClient->SendErrorMsg("This module requires %s to be installed in the Infrastructure Hub.",
630  sItemFactory.GetType(upgType)->name().c_str());
631  return;
632  }
633 
634  if ((m_generator) && (sovData.jammerID != 0)) {
635  pClient->SendErrorMsg("This module cannot be anchored as the system is currently being jammed.");
636  return;
637  }
638 
639  if ((m_jammer) && (sovData.beaconID != 0)) {
640  pClient->SendErrorMsg("This module cannot be anchored as the system currently has an active beacon.");
641  return;
642  }
643  }
644 
645  if (m_tower)
646  {
647  // hack for warping to moons
648  // this puts ship at Az: 0.785332, Ele: 0.615505, angle: 1.5708
649  //warpToPoint -= (radius * 1.25);
650 
651  uint32 dist = /*BUBBLE_RADIUS_METERS + 10000*/ m_self->GetAttribute(AttrMoonAnchorDistance).get_uint32();
652  uint32 radius = m_moonSE->GetRadius();
653  float rad = EvE::Trig::Deg2Rad(90);
654 
655  pos = m_moonSE->GetPosition();
656  pos.x += radius + dist * std::sin(rad);
657  pos.z += radius + dist * std::cos(rad);
658  m_destiny->SetPosition(pos);
659  sBubbleMgr.Add(this);
660 
661  if (is_log_enabled(POS__TRACE))
662  _log(POS__TRACE, "StructureSE::Anchor() - TowerSE %s(%u) new position %.2f, %.2f, %.2f at %s",
663  GetName(), m_data.itemID, pos.x, pos.y, pos.z, m_moonSE->GetName());
664  }
665  else if (m_sbu)
666  {
667  //verify anchor distance from stargate
669  //uint32 anchorMin(m_self->GetAttribute(AttrAnchorDistanceMin).get_uint32());
671 
672  if (distance > anchorMax) {
673  pClient->SendErrorMsg("You cannot anchor the %s farther than %u meters from a stargate.", \
674  m_self->name(), anchorMax);
675  return;
676  }
677 
678  if (distance < 1000) {
679  pClient->SendErrorMsg("You cannot anchor the %s closer than %u meters from a stargate.", \
680  m_self->name(), 1000);
681  return;
682  }
683 
684  // position is within range. allow anchoring
685  m_destiny->SetPosition(pos);
686 
687  if (is_log_enabled(POS__TRACE))
688  _log(POS__TRACE, "StructureSE::Anchor() - SBUSE %s(%u) is anchoring %u m from %s",
689  GetName(), m_data.itemID, distance, m_gateSE->GetName());
690  }
691  else if (m_tcu or m_ihub)
692  {
693  // these are anchored anywhere in system.
694  m_destiny->SetPosition(pos);
695  }
696  else
697  {
698  if (!m_moonSE->HasTower())
699  {
700  // this should never hit...
701  pClient->SendErrorMsg("There is no tower anchored at this moon. You cannot anchor any structure without a tower");
702  return;
703  }
704  /* few attribs to look into...
705  * maxStructureDistance
706  * posStructureControlDistanceMax (maybe multiply this by tower size, or some fraction thereof?)
707  */
708  m_destiny->SetPosition(pos);
709  }
710 
711  m_self->SaveItem();
712 
718 
719  SendSlimUpdate();
720 
721  std::vector<PyTuple *> updates;
722  SetBallFree sbf;
723  sbf.entityID = m_self->itemID();
724  sbf.is_free = false;
725  updates.push_back(sbf.Encode());
726  SetBallRadius sbr;
727  sbr.entityID = m_self->itemID();
728  sbr.radius = m_self->radius();
729  updates.push_back(sbr.Encode());
730  m_destiny->SendDestinyUpdate(updates); //consumed
731  m_destiny->SendSpecialEffect(m_data.itemID, m_data.itemID, m_self->typeID(), 0, 0, "effects.AnchorDrop", 0, 1, 1, -1, 0);
732 }
733 
735 {
737  return; // make error here?
738 
742  //m_towerSE->GetSOI();
743 
749 
750  SendSlimUpdate();
751 
752  if (m_tower)
753  m_bubble->SetTowerSE(nullptr);
754 
755  /*
756  if (m_tower)
757  SendEffectUpdate(anchorLiftForStructures, true);
758  else if (m_co)
759  SendEffectUpdate(anchorLiftForOrbitals, true);
760  else
761  */
762  m_destiny->SendSpecialEffect(m_data.itemID, m_data.itemID, m_self->typeID(), 0, 0, "effects.AnchorLift", 0, 1, 1, -1, 0);
763 }
764 
765 /*
766  * 556 anchoringDelay 1800000 NULL
767  * 650 maxStructureDistance 50000 NULL
768  * 676 unanchoringDelay NULL 3600000
769  * 677 onliningDelay 1800000 NULL
770  * 680 shieldRadius 30000 NULL
771  * 711 moonAnchorDistance 100000 NULL
772  * 1214 posStructureControlDistanceMax NULL 15000
773  */
774 
776 {
778  return; // make error here?
779 
782  // check effectID, check current state, check current timer, set new state, update timer
783 
784  if (m_tower)
785  {
786  // if tower, check fuel quantity for onlining
787  // if qty sufficient, begin online proc and send OnSlimItemChange and OnSpecialFX
788  }
789  else if (m_module)
790  {
791  if (m_towerSE == nullptr)
792  {
793  _log(POS__ERROR, "POS Module %s(%u) has no TowerSE for tower %u", m_self->name(), m_data.itemID, m_data.towerID);
794  return;
795  }
797  {
798  // throwing an error negates further processing
800  float remaining = total - m_towerSE->GetCPULoad();
801  throw UserError ("NotEnoughCpu")
802  .AddAmount ("total", total)
803  .AddAmount ("require", m_self->GetAttribute (AttrCpu).get_float ())
804  .AddAmount ("remaining", remaining)
805  .AddFormatValue ("moduleType", new PyInt (m_self->typeID ()));
806  }
808  {
809  // throwing an error negates further processing
811  float remaining = total - m_towerSE->GetPGLoad();
812  throw UserError ("NotEnoughPower")
813  .AddAmount ("total", total)
814  .AddAmount ("require", m_self->GetAttribute (AttrPower).get_float ())
815  .AddAmount ("remaining", remaining)
816  .AddFormatValue ("moduleType", new PyInt (m_self->typeID ()));
817  }
818  }
819 
820  // check for things that DONT use a tower. not sure if we need anymore checks here.
821  //yes....all sov structures will need checks for activation
822  // ?? can you activate a sov structure?
823  else if (m_tcu)
824  {
825  // Check some things for TCU onlining
826 
827  /*
828  Is there already a TCU in the system?
829  */
830  }
831  else if (m_sbu)
832  {
833  // Check some things for SBU onlining
834  }
835  else if (m_ihub)
836  {
837  // Check some things for IHUB onlining
838  }
839 
845 
846  SendSlimUpdate();
847  m_destiny->SendSpecialEffect(m_data.itemID, m_data.itemID, m_self->typeID(), 0, 0, "effects.StructureOnline", 0, 1, 1, -1, 0);
848 
849  // should this be done here?
850  if (m_module)
851  m_towerSE->OnlineModule(this);
852 
854 }
855 
857 {
859  m_delayTime = 500 /*m_self->GetAttribute(AttrOnliningDelay).get_uint32()*/;
862 
864 
865  SendSlimUpdate();
866  //m_destiny->SendSpecialEffect(m_data.itemID,m_data.itemID,m_self->typeID(),0,0,"effects.StructureOnline",0,0,0,-1,0);
867 }
868 
870 {
871  // this state is persistent until out of resources or changed
875 
878  m_destiny->SendSpecialEffect(m_data.itemID, m_data.itemID, m_self->typeID(), 0, 0, "effects.StructureOnline", 0, 1, 1, -1, 0);
879 
880  if (m_generator) {
881  svDataMgr.UpdateSystemBeaconID(m_self->locationID(),m_self->itemID());
882  }
883  if (m_jammer) {
884  svDataMgr.UpdateSystemJammerID(m_self->locationID(),m_self->itemID());
885  }
886 }
887 
889 {
891  if (m_module)
892  m_towerSE->OfflineModule(this);
893  if (m_generator) {
894  svDataMgr.UpdateSystemBeaconID(m_self->locationID(),0);
895  }
896  if (m_jammer) {
897  svDataMgr.UpdateSystemJammerID(m_self->locationID(),0);
898  }
899 }
900 
902 {
905  SendSlimUpdate();
907 }
908 
910 {
914  SendSlimUpdate();
916 }
917 
919 {
920  // structure online, but not operating
921  // take resources or whatever needs to be done
922 
923  if (!m_tower)
924  {
925  // do module shit here....tower online methods handled in tower class
926  }
927 
929 }
930 
932 {
933  // this state is persistant until out of resources or changed
937 
939 
940  SendSlimUpdate();
941 
943 }
944 
946 {
947  // structure operating
948  // take resources, move items, process reactions or whatever needs to be done (follow PI proc code)
949 
950  if (!m_tower)
951  {
952  // do module shit here....tower operating methods handled in tower class
953  }
954 
956 }
957 
958 void StructureSE::SetUsageFlags(int8 view /*0*/, int8 take /*0*/, int8 use /*0*/)
959 {
960  m_data.use = use;
961  m_data.view = view;
962  m_data.take = take;
964 }
965 
967 {
968  PyDict *slim = new PyDict();
969  slim->SetItemString("name", new PyString(m_self->itemName()));
970  slim->SetItemString("itemID", new PyLong(m_data.itemID));
971  slim->SetItemString("typeID", new PyInt(m_self->typeID()));
972  slim->SetItemString("ownerID", new PyInt(m_ownerID));
973  slim->SetItemString("corpID", IsCorp(m_corpID) ? new PyInt(m_corpID) : PyStatic.NewNone());
974  slim->SetItemString("allianceID", IsAlliance(m_allyID) ? new PyInt(m_allyID) : PyStatic.NewNone());
975  slim->SetItemString("warFactionID", IsFaction(m_warID) ? new PyInt(m_warID) : PyStatic.NewNone());
976  slim->SetItemString("posTimestamp", new PyLong(m_data.timestamp));
977  slim->SetItemString("posState", new PyInt(m_data.state));
978  slim->SetItemString("incapacitated", new PyInt(0));
979  slim->SetItemString("posDelayTime", new PyInt(m_delayTime));
980  PyTuple *shipData = new PyTuple(2);
981  shipData->SetItem(0, new PyLong(m_data.itemID));
982  shipData->SetItem(1, new PyObject("foo.SlimItem", slim));
983  PyTuple *sItem = new PyTuple(2);
984  sItem->SetItem(0, new PyString("OnSlimItemChange"));
985  sItem->SetItem(1, shipData);
986  m_destiny->SendSingleDestinyUpdate(&sItem); // consumed
987 }
988 
989 void StructureSE::SendEffectUpdate(int16 effectID, bool active)
990 {
991  GodmaEnvironment ge;
992  ge.selfID = m_data.itemID;
993  ge.charID = m_ownerID;
994  ge.shipID = m_data.itemID;
995  ge.target = PyStatic.NewNone();
996  ge.subLoc = PyStatic.NewNone();
997  ge.area = new PyList();
998  ge.effectID = effectID;
999  Notify_OnGodmaShipEffect shipEff;
1000  shipEff.itemID = ge.selfID;
1001  shipEff.effectID = effectID;
1002  shipEff.timeNow = GetFileTimeNow();
1003  shipEff.start = (active ? 1 : 0);
1004  shipEff.active = (active ? 1 : 0);
1005  shipEff.environment = ge.Encode();
1006  shipEff.startTime = shipEff.timeNow; // do we need to adjust this?
1007  shipEff.duration = (active ? 0 : -1);
1008  shipEff.repeat = (active ? 1 : 0);
1009  shipEff.error = PyStatic.NewNone();
1010  PyList *events = new PyList();
1011  events->AddItem(shipEff.Encode());
1012  PyTuple *event = new PyTuple(1);
1013  event->SetItem(0, events);
1014  m_destiny->SendSingleDestinyEvent(&event); // consumed
1015 }
1016 
1018 {
1019  using namespace Destiny;
1020  //const uint16 miniballsCount = GetMiniBalls();
1021  BallHeader head = BallHeader();
1022  head.entityID = m_data.itemID;
1023  head.radius = GetRadius();
1024  head.posX = x();
1025  head.posY = y();
1026  head.posZ = z();
1027  if (m_tcu or m_ihub or m_sbu)
1028  {
1029  // may need to update this after things are working
1030  head.mode = Ball::Mode::RIGID;
1031  head.flags = Ball::Flag::IsGlobal;
1032  }
1033  else if (m_tower)
1034  {
1035  head.mode = Ball::Mode::STOP;
1036  head.flags = (m_data.state < EVEPOS::StructureState::Anchored ? Ball::Flag::IsFree : 0) /*Ball::Flag::HasMiniBalls*/;
1037  }
1038  else
1039  {
1040  head.mode = Ball::Mode::RIGID;
1041  //TODO check for miniballs and add here if found.
1042  head.flags = (m_data.state < EVEPOS::StructureState::Anchored ? Ball::Flag::IsFree : 0 /*Ball::Flag::IsMassive*/) /*Ball::Flag::HasMiniBalls*/;
1043  }
1044  into.Append(head);
1045 
1047  if (head.mode != Ball::Mode::RIGID)
1048  {
1049  MassSector mass = MassSector();
1050  mass.cloak = 0;
1051  mass.corporationID = m_corpID;
1052  mass.allianceID = (IsAlliance(m_allyID) ? m_allyID : -1);
1053  mass.harmonic = m_harmonic;
1054  mass.mass = m_self->type().mass();
1055  into.Append(mass);
1056  }
1057 
1059  DataSector data = DataSector();
1060  data.inertia = 1;
1061  data.velX = 0;
1062  data.velY = 0;
1063  data.velZ = 0;
1064  data.maxSpeed = 1;
1065  data.speedfraction = 0;
1066  into.Append( data );
1067  }
1068 
1069 
1070  /* TODO query and configure miniballs for entity
1071  * NOTE MiniBalls are BROKEN!!! DO NOT USE!
1072  into.Append( miniballsCount );
1073  MiniBall miniball;
1074  for (int16 i; i<miniballsCount; i++) {
1075  miniball.x = -7701.181;
1076  miniball.y = 8060.06;
1077  miniball.z = 27878.900;
1078  miniball.radius = 1639.241;
1079  into.Append( miniball );
1080  miniball.clear();
1081  }
1082  [MiniBall]
1083  [Radius: 963.8593]
1084  [Offset: (0, -2302, 1)]
1085  [MiniBall]
1086  [Radius: 1166.27]
1087  [Offset: (0, 1298, 1)]
1088  [MiniBall]
1089  [Radius: 876.2357]
1090  [Offset: (0, -502, 1)]
1091  [MiniBall]
1092  [Radius: 796.5781]
1093  [Offset: (0, 2598, 1)]
1094  */
1095  if (head.mode == Ball::Mode::RIGID)
1096  {
1098  main.formationID = 0xFF;
1099  into.Append(main);
1100  }
1101  else if (head.mode == Ball::Mode::STOP)
1102  {
1103  STOP_Struct main;
1104  main.formationID = 0xFF;
1105  into.Append(main);
1106  }
1107 
1108  _log(SE__DESTINY, "StructureSE::EncodeDestiny(): %s - id:%li, mode:%u, flags:0x%X", GetName(), head.entityID, head.mode, head.flags);
1109  _log(POS__DESTINY, "StructureSE::EncodeDestiny(): %s - id:%li, mode:%u, flags:0x%X", GetName(), head.entityID, head.mode, head.flags);
1110 }
1111 
1113 {
1114  _log(SE__SLIMITEM, "MakeSlimItem for StructureSE %u", m_data.itemID);
1115  _log(POS__SLIMITEM, "MakeSlimItem for StructureSE %u", m_data.itemID);
1117  PyDict *slim = new PyDict();
1118  slim->SetItemString("name", new PyString(m_self->itemName()));
1119  slim->SetItemString("itemID", new PyLong(m_data.itemID));
1120  slim->SetItemString("typeID", new PyInt(m_self->typeID()));
1121  slim->SetItemString("posState", new PyInt(m_data.state));
1122 
1123  slim->SetItemString("ownerID", new PyInt(m_ownerID));
1124  slim->SetItemString("corpID", IsCorp(m_corpID) ? new PyInt(m_corpID) : PyStatic.NewNone());
1125  slim->SetItemString("allianceID", IsAlliance(m_allyID) ? new PyInt(m_allyID) : PyStatic.NewNone());
1126  slim->SetItemString("warFactionID", IsFaction(m_warID) ? new PyInt(m_warID) : PyStatic.NewNone());
1127 
1128  if (m_module or m_tower)
1129  { // for control towers and structures
1130  slim->SetItemString("posTimestamp", new PyLong(m_data.timestamp));
1131  slim->SetItemString("incapacitated", new PyInt(m_data.state == EVEPOS::StructureState::Incapacitated));
1132  slim->SetItemString("posDelayTime", new PyInt(m_delayTime));
1133  }
1134  if (m_outpost)
1135  {
1136  slim->SetItemString("startTimestamp", new PyLong(m_data.timestamp));
1137  slim->SetItemString("structureState", new PyInt(m_data.state));
1138  slim->SetItemString("posDelayTime", new PyInt(m_delayTime));
1139  }
1140  else if (m_tcu)
1141  {
1142  slim->SetItemString("posDelayTime", new PyInt(m_delayTime));
1143  slim->SetItemString("posTimestamp", PyStatic.NewNone());
1144  }
1145  else if (m_miner)
1146  {
1147  PyTuple *tuple = new PyTuple(3);
1148  tuple->SetItem(0, new PyFloat(m_rotation.x));
1149  tuple->SetItem(1, new PyFloat(m_rotation.y));
1150  tuple->SetItem(2, new PyFloat(m_rotation.z));
1151  slim->SetItemString("dunRotation", tuple); // direction to moon
1152  slim->SetItemString("controlTowerID", new PyLong(m_data.towerID));
1153  }
1154 
1155  if (m_module)
1156  slim->SetItemString("controlTowerID", new PyLong(m_data.towerID));
1157 
1158  if (is_log_enabled(POS__SLIMITEM))
1159  {
1160  _log(POS__SLIMITEM, "StructureSE::MakeSlimItem() - %s(%u)", GetName(), m_data.itemID);
1161  slim->Dump(POS__SLIMITEM, " ");
1162  }
1163  return slim;
1164 }
1165 
1166 /* Log events...not sure what this is for yet.
1167 eventTCUExploded = 280
1168 eventTCUInvulnerable = 283
1169 eventTCUOffline = 259
1170 eventTCUOnline = 258
1171 eventTCUVulnerable = 282
1172 eventControlTowerAnchored = 364
1173 eventControlTowerUnanchored = 365
1174 eventControlTowerDestroyed = 366
1175 eventSovereigntyClaimed = 197
1176 eventSovereigntyLost = 194
1177 eventSBUExploded = 279
1178 eventSBUOffline = 257
1179 eventSBUOnline = 256
1180 */
1181 
1183 {
1184  // this is for sending structure state info in destiny state data
1186  return;
1187 
1188  OnSpecialFX13 effect;
1189  if (m_module)
1190  {
1191  effect.entityID = m_data.towerID; /* control tower id */
1192  }
1193  else
1194  {
1195  effect.entityID = m_data.itemID; /* control tower id */
1196  }
1197  effect.moduleID = m_data.itemID; /* structure/module id as part of above tower system */
1198  effect.moduleTypeID = m_self->typeID();
1199  effect.duration = -1;
1200  effect.guid = "effects.StructureOnline"; // this is sent in destiny::SetState. check for actual effect of this pos
1201  effect.isOffensive = false;
1202  effect.start = 1;
1203  effect.active = 1;
1204  effect.startTime = m_data.timestamp; /* time this effect started */
1205  into.AddItem(effect.Encode());
1206 }
1207 
1208 void StructureSE::Killed(Damage &fatal_blow)
1209 {
1210  if ((m_bubble == nullptr) or (m_destiny == nullptr) or (m_system == nullptr))
1211  return; // make error here?
1212 
1213  if (m_tower)
1214  m_bubble->SetTowerSE(nullptr);
1215 
1216  uint32 killerID = 0;
1217  Client *pClient(nullptr);
1218  SystemEntity *killer = fatal_blow.srcSE;
1219 
1220  if (killer->HasPilot())
1221  {
1222  pClient = killer->GetPilot();
1223  killerID = pClient->GetCharacterID();
1224  }
1225  else if (killer->IsDroneSE())
1226  {
1227  pClient = sEntityList.FindClientByCharID(killer->GetSelf()->ownerID());
1228  if (pClient == nullptr)
1229  {
1230  sLog.Error("StructureSE::Killed()", "killer == IsDrone and pPlayer == nullptr");
1231  }
1232  else
1233  {
1234  killerID = pClient->GetCharacterID();
1235  }
1236  }
1237  else
1238  {
1239  killerID = killer->GetID();
1240  }
1241 
1242  std::stringstream blob;
1243  blob << "<items>";
1244  std::vector<InventoryItemRef> survivedItems;
1245  std::map<uint32, InventoryItemRef> deadShipInventory;
1246  deadShipInventory.clear();
1247  m_self->GetMyInventory()->GetInventoryMap(deadShipInventory);
1248  if (!deadShipInventory.empty())
1249  {
1250  uint32 s = 0, d = 0, x = 0;
1251  for (auto cur : deadShipInventory)
1252  {
1253  d = 0;
1254  x = cur.second->quantity();
1255  s = (cur.second->isSingleton() ? 1 : 0);
1256  if (cur.second->categoryID() == EVEDB::invCategories::Blueprint)
1257  {
1258  // singleton for bpo = 1, bpc = 2.
1259  BlueprintRef bpRef = BlueprintRef::StaticCast(cur.second);
1260  s = (bpRef->copy() ? 2 : s);
1261  }
1262  blob << "<i t=" << cur.second->typeID() << " f=" << cur.second->flag() << " s=" << s;
1263  // all items have 50% chance of drop, even from popped ship
1264  if (IsEven(MakeRandomInt(0, 100)))
1265  {
1266  // item survived. check qty for drop
1267  if (x > 1)
1268  {
1269  d = MakeRandomInt(0, x);
1270  x -= d;
1271  }
1272  // move item to vector for insertion into wreck later on
1273  survivedItems.push_back(cur.second);
1274  }
1275  blob << " d=" << d << " x=" << x << "/>";
1276  }
1277  }
1278  blob << "</items>";
1279 
1280  /* populate kill data for killMail and save to db -allan 01May16 --updated 13July17 */
1283  CharKillData data = CharKillData();
1284  data.solarSystemID = m_system->GetID();
1285  data.victimCharacterID = 0; // charID = 0 means strucuture/item
1287  data.victimAllianceID = m_allyID;
1288  data.victimFactionID = m_warID;
1289  data.victimShipTypeID = GetTypeID();
1290 
1291  data.finalCharacterID = killerID;
1292  data.finalCorporationID = killer->GetCorporationID();
1293  data.finalAllianceID = killer->GetAllianceID();
1294  data.finalFactionID = killer->GetWarFactionID();
1295  data.finalShipTypeID = killer->GetTypeID();
1296  data.finalWeaponTypeID = fatal_blow.weaponRef->typeID();
1297  data.finalSecurityStatus = 0; /* fix this */
1298  data.finalDamageDone = fatal_blow.GetTotal();
1299 
1300  uint32 totalHP = m_self->GetAttribute(AttrHP).get_uint32();
1301  totalHP += m_self->GetAttribute(AttrArmorHP).get_uint32();
1303  data.victimDamageTaken = totalHP;
1304 
1305  data.killBlob = blob.str().c_str();
1306  data.killTime = GetFileTimeNow();
1307  data.moonID = m_moonSE->GetID(); /* denotes moonID for POS/Structure kills */
1308 
1310 
1311  uint32 locationID = GetLocationID();
1312  // log faction kill in dynamic data -allan
1313  MapDB::AddKill(locationID);
1314  MapDB::AddFactionKill(locationID);
1315 
1316  if (pClient != nullptr)
1317  {
1318  //award kill bounty.
1319  //AwardBounty( pClient );
1320  if (m_system->GetSystemSecurityRating() > 0)
1321  AwardSecurityStatus(m_self, pClient->GetChar().get()); // this awards secStatusChange for npcs in empire space
1322  }
1323 
1324  GPoint wreckPosition = m_destiny->GetPosition();
1325  if (wreckPosition.isNaN())
1326  {
1327  sLog.Error("StructureSE::Killed()", "Wreck Position is NaN");
1328  return;
1329  }
1330  uint32 wreckTypeID = sDataMgr.GetWreckID(m_self->typeID());
1331  if (!IsWreckTypeID(wreckTypeID))
1332  {
1333  sLog.Error("StructureSE::Killed()", "Could not get wreckType for %s of type %u", m_self->name(), m_self->typeID());
1334  // default to generic frigate wreck till i get better checks and/or complete wreck data
1335  wreckTypeID = 26557;
1336  }
1337 
1338  std::string wreck_name = m_self->itemName();
1339  wreck_name += " Wreck";
1340  ItemData wreckItemData(wreckTypeID, killerID, locationID, flagNone, wreck_name.c_str(), wreckPosition, itoa(m_allyID));
1341  WreckContainerRef wreckItemRef = sItemFactory.SpawnWreckContainer(wreckItemData);
1342  if (wreckItemRef.get() == nullptr)
1343  {
1344  sLog.Error("StructureSE::Killed()", "Creating Wreck Item Failed for %s of type %u", wreck_name.c_str(), wreckTypeID);
1345  return;
1346  }
1347 
1348  if (is_log_enabled(PHYSICS__TRACE))
1349  _log(PHYSICS__TRACE, "StructureSE::Killed() - Structure %s(%u) Position: %.2f,%.2f,%.2f. Wreck %s(%u) Position: %.2f,%.2f,%.2f.",
1350  GetName(), GetID(), x(), y(), z(), wreckItemRef->name(), wreckItemRef->itemID(), wreckPosition.x, wreckPosition.y, wreckPosition.z);
1351 
1353  wreckEntity.allianceID = killer->GetAllianceID();
1355  wreckEntity.corporationID = killer->GetCorporationID();
1356  wreckEntity.factionID = m_warID;
1357  wreckEntity.groupID = EVEDB::invGroups::Wreck;
1358  wreckEntity.itemID = wreckItemRef->itemID();
1359  wreckEntity.itemName = wreck_name;
1360  wreckEntity.ownerID = killerID;
1361  wreckEntity.typeID = wreckTypeID;
1362  wreckEntity.position = wreckPosition;
1363 
1364  if (!m_system->BuildDynamicEntity(wreckEntity, m_self->itemID()))
1365  {
1366  sLog.Error("StructureSE::Killed()", "Spawning Wreck Failed: typeID or typeName not supported: '%u'", wreckTypeID);
1367  wreckItemRef->Delete();
1368  return;
1369  }
1371 
1372  DropLoot(wreckItemRef, m_self->groupID(), killerID);
1373 
1374  for (auto cur : survivedItems)
1375  cur->Move(wreckItemRef->itemID(), flagNone); // populate wreck with items that survived
1376 }
1377 
1379 {
1380 }
1382 {
1383 }
1384 
1385 /* GetHybridBridgeMenu
1386  * GetAllianceBeaconSubMenu
1387  * lots of other bridge/beacon/fleet menus in
1388  * /eve/client/script/ui/services/menusvc.py
1389  */
1390 /*
1391  * class BasicOrbital(spaceObject.PlayerOwnedStructure):
1392  *
1393  * def Assemble(self):
1394  * self.SetStaticRotation()
1395  *
1396  * def OnSlimItemUpdated(self, slimItem):
1397  * orbitalState = getattr(slimItem, 'orbitalState', None)
1398  * orbitalTimestamp = getattr(slimItem, 'orbitalTimestamp', blue.os.GetSimTime())
1399  * fxSequencer = sm.GetService('FxSequencer')
1400  * if not hasattr(self, 'orbitalState'):
1401  * if orbitalState in (entities.STATE_ANCHORING, entities.STATE_ANCHORED):
1402  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.AnchorDrop', 0, 1, 0)
1403  * elif orbitalState in (entities.STATE_IDLE, entities.STATE_OPERATING):
1404  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.StructureOnlined', 0, 1, 0)
1405  * else:
1406  * if orbitalState == entities.STATE_ANCHORING and self.orbitalState == entities.STATE_UNANCHORED:
1407  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.AnchorDrop', 0, 1, 0)
1408  * if orbitalState == entities.STATE_ONLINING and self.orbitalState == entities.STATE_ANCHORED:
1409  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.StructureOnline', 0, 1, 0)
1410  * if orbitalState == entities.STATE_IDLE and self.orbitalState == entities.STATE_ONLINING:
1411  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.StructureOnlined', 0, 1, 0)
1412  * if orbitalState == entities.STATE_ANCHORED and self.orbitalState in (entities.STATE_OFFLINING, entities.STATE_IDLE, entities.STATE_OPERATING):
1413  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.StructureOffline', 0, 1, 0)
1414  * if orbitalState == entities.STATE_UNANCHORING and self.orbitalState == entities.STATE_ANCHORED:
1415  * uthread.pool('SpaceObject::BasicOrbital::OnSlimItemUpdated', fxSequencer.OnSpecialFX, slimItem.itemID, slimItem.itemID, None, None, None, [], 'effects.AnchorLift', 0, 1, 0)
1416  * self.orbitalState = orbitalState
1417  * self.orbitalTimestamp = orbitalTimestamp
1418  *
1419  * def IsAnchored(self):
1420  * self.LogInfo('Anchor State = ', not self.isFree)
1421  * return not self.isFree
1422  *
1423  * def IsOnline(self):
1424  * slimItem = sm.StartService('michelle').GetBallpark().GetInvItem(self.id)
1425  * return slimItem.orbitalState is not None and slimItem.orbitalState in (entities.STATE_OPERATING, entities.STATE_IDLE)
1426  *
1427  */
void Append(const T &value)
Appends a single value to buffer.
Definition: Buffer.h:437
bool m_loaded
Definition: Structure.h:236
bool m_tower
Definition: Structure.h:231
void Anchor()
Definition: Structure.cpp:1378
bool m_outpost
Definition: Structure.h:239
virtual void Process()
uint32 finalDamageDone
SystemEntity * GetSE(uint32 entityID) const
double radius() const
uint32 GetLocationID() const
Definition: Client.h:151
uint32 finalCorporationID
uint32 victimDamageTaken
static StructureItemRef Load(uint32 structureID)
Definition: Structure.cpp:58
void SendErrorMsg(const char *fmt,...)
Definition: Client.cpp:2719
void SetTimer(uint32 time)
Definition: Structure.h:178
#define _log(type, fmt,...)
Definition: logsys.h:124
SBUSE * m_sbuSE
Definition: Structure.h:207
void Disable()
Definition: timer.h:39
Python string.
Definition: PyRep.h:430
#define IsWreckTypeID(typeID)
Definition: EVE_Defines.h:203
DestinyManager * m_destiny
Definition: SystemEntity.h:265
double GetRadius()
Definition: SystemEntity.h:208
SystemEntity * mySE
Definition: Structure.h:79
virtual MoonSE * GetMoonSE()
Definition: SystemEntity.h:102
uint32 finalCharacterID
void Drop(SystemBubble *pBubble)
Definition: Structure.cpp:561
virtual void SetInvulnerable()
Definition: Structure.cpp:901
Python's dictionary.
Definition: PyRep.h:719
void SetTimer(uint32 setTimerTime=0)
Definition: timer.cpp:102
uint32 m_ownerID
Definition: SystemEntity.h:283
bool SetFlag(EVEItemFlags flag, bool notify=false)
void UpdateBaseData(EVEPOS::StructureData &data)
Definition: PosMgrDB.cpp:132
uint8 GetState() const
Definition: Structure.h:170
virtual void RemoveItem(InventoryItemRef iRef)
virtual void SetOperating()
Definition: Structure.cpp:931
uint32 ownerID() const
Definition: InventoryItem.h:99
virtual void AddItem(InventoryItemRef iRef)
const GPoint & position() const
void SendJettisonPacket() const
float GetCPULoad()
Definition: Tower.h:115
PyObject * StructureGetInfo()
Definition: Structure.cpp:139
uint32 m_delayTime
Definition: Structure.h:217
double y()
Definition: SystemEntity.h:214
virtual bool HasPilot()
Definition: SystemEntity.h:258
GaExpInl bool isNaN() const
Definition: GaTypes.h:194
static void AddKill(uint32 sysID)
Definition: MapDB.cpp:250
virtual Client * GetPilot()
Definition: SystemEntity.h:259
Python floating point number.
Definition: PyRep.h:292
SystemEntity * GetClosestGateSE(const GPoint &myPos)
SystemBubble * m_bubble
Definition: SystemEntity.h:262
int32 GetCharacterID() const
Definition: Client.h:113
void DeleteContents()
Definition: Inventory.cpp:273
virtual CustomsSE * GetCOSE()
Definition: SystemEntity.h:128
IHubSE * m_ihubSE
Definition: Structure.h:208
void SendDestinyUpdate(std::vector< PyTuple * > &updates, bool self_only=false) const
StructureSE(StructureItemRef structure, PyServiceMgr &services, SystemManager *system, const FactionData &data)
Definition: Structure.cpp:193
StargateSE * m_gateSE
Definition: Structure.h:210
static void AddFactionKill(uint32 sysID)
Definition: MapDB.cpp:256
virtual bool _Load()
SystemEntity * srcSE
Definition: Damage.h:84
#define sEntityList
Definition: EntityList.h:208
const float GetSystemSecurityRating()
Definition: SystemManager.h:86
uint32 GetID() const
Definition: SystemManager.h:80
bool m_ihub
Definition: Structure.h:230
bool m_reactor
Definition: Structure.h:238
virtual void SetOnline()
Definition: Structure.cpp:869
static void SaveKillOrLoss(CharKillData &data)
Definition: ServiceDB.cpp:212
Timer m_procTimer
Definition: Structure.h:226
int8 m_procState
Definition: Structure.h:214
UserError & AddFormatValue(const char *name, PyRep *value)
Fluent version of the protected AddKeyword, allows for adding a keyword to the exception.
int32 victimFactionID
void GetEffectState(PyList &into)
Definition: Structure.cpp:1182
const char * name()
CharacterRef GetChar() const
Definition: Client.h:164
Python tuple.
Definition: PyRep.h:567
uint32 m_duration
Definition: Structure.h:224
GaFloat x
Definition: GaTypes.h:207
bool BuildDynamicEntity(const DBSystemDynamicEntity &entity, uint32 launcherID=0)
int32 m_harmonic
Definition: SystemEntity.h:276
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
signed __int8 int8
Definition: eve-compat.h:45
const GPoint & GetPosition() const
Definition: SystemEntity.h:211
bool HasCPU(float amount)
Definition: Tower.h:112
TowerSE * GetTowerSE()
Definition: SystemBubble.h:142
EvilNumber EvilZero
Definition: EvilNumber.cpp:32
void AddItem(PyRep *i)
Definition: PyRep.h:701
void SafeDelete(T *&p)
Deletes and nullifies a pointer.
Definition: SafeMem.h:83
bool m_jammer
Definition: Structure.h:234
uint16 groupID() const
signed __int32 int32
Definition: eve-compat.h:49
GaExpInl GaFloat normalize()
Definition: GaTypes.h:163
void OfflineModule(StructureSE *pSE)
Definition: Tower.h:107
const ItemType & type() const
bool m_generator
Definition: Structure.h:235
virtual ~StructureItem()
Definition: Structure.cpp:53
#define is_log_enabled(type)
Definition: logsys.h:78
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
void VerifyAddItem(InventoryItemRef iRef)
void SendSpecialEffect(uint32 entityID, uint32 moduleID, uint32 moduleTypeID, uint32 targetID, uint32 chargeTypeID, std::string guid, bool isOffensive, bool start, bool isActive, int32 duration, uint32 repeat, int32 graphicInfo=0) const
bool m_tcu
Definition: Structure.h:228
UserError & AddAmount(const char *name, int quantity)
Shorthand method for adding a quantity value.
Definition: gpoint.h:33
virtual bool IsCOSE()
Definition: SystemEntity.h:164
InventoryItemRef m_self
Definition: SystemEntity.h:269
bool IsEven(int64 number)
Definition: misc.h:88
void Deactivate(int32 effectID)
Definition: Structure.cpp:856
Generic class for buffers.
Definition: Buffer.h:40
void SaveBaseData(EVEPOS::StructureData &data)
Definition: PosMgrDB.cpp:122
InventoryItemRef GetSelf()
Definition: SystemEntity.h:202
double GetTimeMSeconds()
Definition: utils_time.cpp:104
Python object.
Definition: PyRep.h:826
uint32 m_corpID
Definition: SystemEntity.h:281
void SaveBridgeData(EVEPOS::JumpBridgeData &data)
Definition: PosMgrDB.cpp:222
uint32 GetLocationID()
Definition: SystemEntity.h:209
int64 get_int()
Definition: EvilNumber.cpp:166
void PullAnchor()
Definition: Structure.cpp:734
double Deg2Rad(double deg)
Definition: Trig.h:25
virtual void Delete()
Definition: Structure.cpp:131
Inventory * pInventory
uint32 solarSystemID
#define codelog(type, fmt,...)
Definition: logsys.h:128
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
float GetPGLoad()
Definition: Tower.h:114
virtual void Killed(Damage &fatal_blow)
Definition: Structure.cpp:1208
static const GPoint NULL_ORIGIN(0, 0, 0)
void RemoveEntity(SystemEntity *pSE)
uint32 get_uint32()
Definition: EvilNumber.cpp:173
Definition: Damage.h:33
uint32 victimCorporationID
float mass() const
Definition: ItemType.h:69
void Activate(int32 effectID)
Definition: Structure.cpp:775
uint32 locationID() const
Python integer.
Definition: PyRep.h:231
virtual void Rename(std::string name)
Definition: Structure.cpp:179
SystemManager * m_system
Definition: SystemEntity.h:263
uint16 finalShipTypeID
double z()
Definition: SystemEntity.h:215
int32 GetAllianceID()
Definition: SystemEntity.h:216
uint32 GetID()
Definition: SystemEntity.h:207
bool Check(bool reset=true)
Definition: timer.cpp:62
#define PyStatic
Definition: PyRep.h:1209
X * get() const
Definition: RefPtr.h:213
JumpBridgeSE * m_bridgeSE
Definition: Structure.h:209
TowerSE * m_towerSE
Definition: Structure.h:205
void SetUsageFlags(int8 view=0, int8 take=0, int8 use=0)
Definition: Structure.cpp:958
virtual void InitData()
Definition: Structure.cpp:240
uint32 victimCharacterID
int32 finalFactionID
const char * GetName() const
Definition: SystemEntity.h:210
virtual SBUSE * GetSBUSE()
Definition: SystemEntity.h:130
void Offline()
Definition: Structure.cpp:1381
EVEPOS::StructureData m_data
Definition: Structure.h:212
bool Populate(Rsp_CommonGetInfo_Entry &into)
void SendEffectUpdate(int16 effectID, bool active)
Definition: Structure.cpp:989
virtual void Online()
Definition: Structure.cpp:918
double x()
Definition: SystemEntity.h:213
Python object "ccp_exceptions.UserError".
Definition: PyExceptions.h:121
Definition: Client.h:66
void SetAnchor(Client *pClient, GPoint &pos)
Definition: Structure.cpp:600
SystemEntity * GetClosestMoonSE(const GPoint &myPos)
void DeleteData(uint32 itemID)
Definition: PosMgrDB.cpp:17
bool ChangeSingleton(bool singleton, bool notify=false)
virtual void Process()
Definition: Structure.cpp:458
double finalSecurityStatus
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 SetPosition(const GPoint &pt, bool update=false)
uint16 typeID
Definition: ItemType.h:188
virtual StructureSE * GetPOSSE()
Definition: SystemEntity.h:116
virtual PyDict * MakeSlimItem()
Definition: Structure.cpp:1112
virtual JumpBridgeSE * GetJumpBridgeSE()
Definition: SystemEntity.h:118
void SendSingleDestinyUpdate(PyTuple **up, bool self_only=false) const
uint32 corporationID
virtual void Scoop()
Definition: Structure.cpp:449
#define IsCorp(itemID)
Definition: EVE_Defines.h:234
virtual void SetOffline()
Definition: Structure.cpp:888
void GetInventoryMap(std::map< uint32, InventoryItemRef > &invMap)
Definition: Inventory.cpp:453
bool HasTower()
Definition: Moon.h:46
GVector m_rotation
Definition: Structure.h:220
RefPtr< InventoryItem > InventoryItemRef
Definition: ItemRef.h:52
GaFloat y
Definition: GaTypes.h:207
virtual void EncodeDestiny(Buffer &into)
Definition: Structure.cpp:1017
double GetFileTimeNow()
Definition: utils_time.cpp:84
void SetSBU(StructureSE *pSE)
Definition: SystemEntity.h:361
virtual TowerSE * GetTowerSE()
Definition: SystemEntity.h:120
int64 MakeRandomInt(int64 low, int64 high)
Generates random integer from interval [low; high].
Definition: misc.cpp:109
uint32 GetCorporationID()
Definition: SystemEntity.h:218
const std::string & itemName() const
int main(int argc, char *argv[])
float GetTotal() const
Definition: Damage.h:48
TCUSE * m_tcuSE
Definition: Structure.h:206
bool HasTower()
Definition: SystemBubble.h:141
bool m_miner
Definition: Structure.h:232
void SetTowerSE(TowerSE *pTower)
Definition: SystemBubble.h:143
void SendSlimUpdate()
Definition: Structure.cpp:966
virtual bool _Load()
Definition: Structure.cpp:63
static uint32 CreateItemID(ItemData &data)
void DropLoot(WreckContainerRef wreckRef, uint32 groupID, uint32 owner)
EvilNumber GetAttribute(const uint16 attrID) const
RefPtr< StructureItem > StructureItemRef
Definition: ItemRef.h:60
void SendSingleDestinyEvent(PyTuple **ev, bool self_only=false) const
#define IsStaticMapItem(itemID)
Definition: EVE_Defines.h:270
bool LoadContents()
Definition: Inventory.cpp:113
uint16 finalWeaponTypeID
#define IsFaction(itemID)
Definition: EVE_Defines.h:250
uint16 victimShipTypeID
MoonSE * m_moonSE
Definition: Structure.h:203
void AwardSecurityStatus(InventoryItemRef iRef, Character *pChar)
virtual void Rename(std::string name)
signed __int16 int16
Definition: eve-compat.h:47
virtual void Operating()
Definition: Structure.cpp:945
void SetTower(StructureSE *pSE)
Definition: Moon.h:47
bool m_sbu
Definition: Structure.h:229
virtual void RemoveItem(InventoryItemRef iRef)
Definition: Structure.cpp:171
const GPoint & GetPosition() const
bool GetBaseData(EVEPOS::StructureData &data)
Definition: PosMgrDB.cpp:97
void AddModule(StructureSE *pSE)
Definition: Tower.h:92
void traceStack(void)
Definition: misc.cpp:169
virtual void SetVulnerable()
Definition: Structure.cpp:909
virtual void Delete()
void OnlineModule(StructureSE *pSE)
Definition: Tower.h:106
virtual StargateSE * GetGateSE()
Definition: SystemEntity.h:103
#define sItemFactory
Definition: ItemFactory.h:165
EvilNumber EvilOne
Definition: EvilNumber.cpp:34
#define IsAlliance(itemID)
Definition: EVE_Defines.h:244
float get_float()
Definition: EvilNumber.cpp:184
Definition: gpoint.h:70
PosMgrDB m_db
Definition: Structure.h:201
StructureItem(uint32 _structureID, const ItemType &_itemType, const ItemData &_data)
Definition: Structure.cpp:45
GaExpInl GaFloat distance(const GaVec3 &oth) const
Definition: GaTypes.h:158
#define svDataMgr
virtual TCUSE * GetTCUSE()
Definition: SystemEntity.h:129
uint16 GetTypeID()
Definition: SystemEntity.h:203
bool m_module
Definition: Structure.h:237
bool HasPG(float amount)
Definition: Tower.h:110
#define sBubbleMgr
virtual IHubSE * GetIHubSE()
Definition: SystemEntity.h:131
int32 finalAllianceID
Inventory * GetMyInventory()
Definition: InventoryItem.h:91
InventoryItemRef weaponRef
Definition: Damage.h:86
int32 victimAllianceID
std::string killBlob
virtual bool IsDroneSE()
Definition: SystemEntity.h:187
static StructureItemRef Spawn(ItemData &data)
Definition: Structure.cpp:71
uint16 typeID() const
bool ContainsTypeQty(uint16 typeID, uint32 qty=0) const
Definition: Inventory.cpp:526
Definition: EVE_POS.h:14
bool m_bridge
Definition: Structure.h:233
Python list.
Definition: PyRep.h:639
GaFloat z
Definition: GaTypes.h:207
const char * itoa(int64 num)
Convers num to string.
virtual void Init()
Definition: Structure.cpp:275
uint32 itemID() const
Definition: InventoryItem.h:98
void SetItemString(const char *key, PyRep *value)
SetItemString adds or sets a database entry.
Definition: PyRep.h:812
int32 GetWarFactionID()
Definition: SystemEntity.h:217
Python long integer.
Definition: PyRep.h:261
virtual void AddItem(InventoryItemRef iRef)
Definition: Structure.cpp:158
Reference-counting-based smart pointer.
Definition: RefPtr.h:133
#define sDataMgr