EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
FleetService.cpp
Go to the documentation of this file.
1 
13 //work in progress
14 
15 #include "eve-server.h"
16 #include "chat/LSCService.h"
17 #include "fleet/FleetService.h"
18 #include "system/SystemBubble.h"
19 #include "system/SystemManager.h"
20 
21 /*
22 FLEET__ERROR
23 FLEET__WARNING
24 FLEET__MESSAGE
25 FLEET__DEBUG
26 FLEET__INFO
27 FLEET__TRACE
28 FLEET__DUMP
29 FLEET__BIND_DUMP
30 */
31 
32 // Manager class functions and methods...
33 
35 : m_services(nullptr),
36 m_initalized(false)
37 {
38 
39 }
40 
42 {
43  m_services = svc;
44 
45  m_joinReq.clear();
46  m_inviteData.clear();
47  m_fleetWings.clear();
48  m_wingSquads.clear();
49  m_wingDataMap.clear();
50  m_fleetMembers.clear();
51  m_fleetDataMap.clear();
52  m_squadDataMap.clear();
53  m_fleetAdvertMap.clear();
54 
55  // these will have to be incremented individually, then stored according to fleet
56  m_fleetID = FLEET_ID; //950000000
57  m_wingID = WING_ID; //960000000
58  m_squadID = SQUAD_ID; //970000000
59 
60  m_initalized = true;
61  sLog.Blue(" FleetService", "Fleet Service Initialized.");
62 }
63 
64 
66 {
67  if (pClient == nullptr)
68  return 0;
69 
70  Character* pChar = pClient->GetChar().get();
71  if (pChar == nullptr)
72  return 0;
73 
74  FleetData fData = FleetData();
75  fData.isFreeMove = true;
76  fData.isLootLogging = false;
77  fData.isRegistered = false;
78  fData.isVoiceEnabled = sConfig.chat.EnableVoiceChat; //false
79  fData.creator = pClient;
80  fData.leader = pClient;
81  fData.booster = pClient;
82  fData.name = pChar->itemName();
83  fData.name += "'s Fleet";
84  fData.motd = "default motd";
85  fData.isMutedByLeader.clear();
86  fData.isExcludedFromMuting.clear();
87  fData.squads = 1;
88  fData.dateCreated = GetFileTimeNow();
89  m_fleetDataMap.emplace(m_fleetID, fData);
90 
91  WingData wData = WingData();
92  wData.fleetID = m_fleetID;
93  wData.name = "Wing 1";
94  wData.booster = nullptr;
95  wData.leader = nullptr;
96  m_wingDataMap.emplace(m_wingID, wData);
98 
99  BoostData bData = BoostData();
105  SquadData sData = SquadData();
106  sData.boost = bData;
107  sData.name = "Squad 1";
108  sData.booster = nullptr;
109  sData.leader = nullptr;
110  sData.wingID = m_wingID;
111  sData.fleetID = m_fleetID;
112  sData.members.clear();
113  m_squadDataMap.emplace(m_squadID, sData);
114  m_wingSquads.emplace(m_wingID, m_squadID);
115 
116  // set char fleet data and send to client
118  fleet.fleetID = m_fleetID; //this is also lsc channel #
119  fleet.wingID = -1;
120  fleet.squadID = -1;
121  fleet.job = Fleet::Job::Creator;
124  fleet.joinTime = GetFileTimeNow();
125  pChar->SetFleetData(fleet);
126 
127  // update the fleet member map with new member for this fleet.
128  m_fleetMembers.emplace(m_fleetID, pClient);
129 
130  _log(FLEET__INFO, "FleetService::CreateFleet() - fleetID: %u, wingID: %u, squadID: %u, leaderID: %u", m_fleetID, m_wingID, m_squadID, pChar->itemID());
131 
132  sLog.Cyan("CreateFleet", "bData -- leader: %i, armored: %i, info: %i, siege: %i, skirmish: %i, mining: %i", \
133  sData.boost.leader, sData.boost.armored, sData.boost.info, sData.boost.siege, sData.boost.skirmish, sData.boost.mining);
134 
135  if (sConfig.chat.EnableFleetChat)
137  if (sConfig.chat.EnableWingChat)
139  if (sConfig.chat.EnableSquadChat)
141 
142  // increment counters after channels are created (to avoid wrong channel creation)
143  ++m_fleetID;
144  ++m_wingID;
145  ++m_squadID;
146 
147  return fleet.fleetID;
148 }
149 
151 {
152  int8 count = m_fleetWings.count(fleetID);
153  // do we need an error here?
154  if (count > 4)
155  return nullptr;
156  WingData wData = WingData();
157  wData.fleetID = fleetID;
158  wData.name = "Wing ";
159  wData.name += std::to_string(count + 1);
160  wData.booster = nullptr;
161  wData.leader = nullptr;
162  m_wingDataMap.emplace(m_wingID, wData);
163  m_fleetWings.emplace(fleetID, m_wingID);
164 
165  _log(FLEET__INFO, "FleetService::CreateWing() - fleetID: %u, wingID: %u", fleetID, m_wingID);
166 
167  PyTuple* tuple1 = new PyTuple(1);
168  tuple1->SetItem(0, new PyInt(m_wingID));
169  SendFleetUpdate(fleetID, "OnFleetWingAdded", tuple1);
170 
171  if (sConfig.chat.EnableWingChat)
173 
174  std::list<int32> wing, squad;
175  wing.clear();
176  squad.clear();
177  wing.emplace(wing.end(), m_wingID);
178  UpdateBoost(fleetID, true, wing, squad);
179 
180  PyInt* res = new PyInt(m_wingID);
181  ++m_wingID;
182  return res;
183 }
184 
186 {
187  // do we need an error here?
188  if (m_wingSquads.count(wingID) == 5)
189  return;
190  IncFleetSquads(fleetID, wingID);
191  FleetData data = FleetData();
192  GetFleetData(fleetID, data);
193  BoostData bData = BoostData();
194  SquadData sData = SquadData();
195  sData.boost = bData;
196  sData.name = "Squad ";
197  sData.name += std::to_string(data.squads);
198  sData.wingID = wingID;
199  sData.fleetID = fleetID;
200  sData.booster = nullptr;
201  sData.leader = nullptr;
202  sData.members.clear();
203  m_squadDataMap.emplace(m_squadID, sData);
204  m_wingSquads.emplace(wingID, m_squadID);
205 
206  _log(FLEET__INFO, "FleetService::CreateSquad() - fleetID: %u, wingID: %u, squadID: %u", fleetID, wingID, m_squadID);
207 
208  PyTuple* tuple = new PyTuple(2);
209  tuple->SetItem(0, new PyInt(wingID));
210  tuple->SetItem(1, new PyInt(m_squadID));
211  SendFleetUpdate(fleetID, "OnFleetSquadAdded", tuple);
212 
213  if (sConfig.chat.EnableSquadChat)
215 
216  std::list<int32> wing, squad;
217  wing.clear();
218  wing.emplace(wing.end(), wingID);
219  squad.clear();
220  squad.emplace(squad.end(), m_squadID);
221  UpdateBoost(fleetID, true, wing, squad);
222 
223  ++m_squadID;
224 }
225 
227 {
229  std::map<uint32, FleetAdvert>::iterator itr = m_fleetAdvertMap.find(fleetID);
230  if (itr != m_fleetAdvertMap.end()) {
231  m_fleetAdvertMap.erase(fleetID);
232  _log(FLEET__INFO, "CreateFleetAdvert() Updating Advert for FleetID: %u, Scope: %u", fleetID, data.inviteScope);
233  } else {
234  _log(FLEET__INFO, "CreateFleetAdvert() Creating Advert for FleetID: %u, Scope: %u", fleetID, data.inviteScope);
235  }
236 
237  m_fleetAdvertMap.emplace(fleetID, data);
238  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
239  if (fItr != m_fleetDataMap.end())
240  UpdateOptions(fleetID, fItr->second.isFreeMove, /*isRegistered*/true, fItr->second.isVoiceEnabled);
241 
242  // update chat channel(s) with new description?
243 }
244 
245 bool FleetService::AddMember(Client* pClient, uint32 fleetID, int32 wingID, int32 squadID, int8 job, int8 role, int8 booster)
246 {
247  Character* pChar = pClient->GetChar().get();
248  if (pChar == nullptr)
249  return false;
250 
251  _log(FLEET__TRACE, "AddMember - CharID: %u, FleetID: %u, WingID: %i, Squad: %i, Job: %s, Role: %s, Booster: %s", \
252  pChar->itemID(), fleetID, wingID, squadID, GetJobName(job).c_str(), GetRoleName(role).c_str(), GetBoosterName(booster).c_str());
253 
254  // add new member to fleet data
255  m_fleetMembers.emplace(fleetID, pClient);
256 
257  // set char fleet data and send to client
258  CharFleetData fData = CharFleetData();
259  fData.fleetID = fleetID;
260  fData.wingID = wingID;
261  fData.squadID = squadID;
262  fData.job = job; //Fleet::Job::None;
263  fData.role = role;
264  fData.booster = booster;
265  fData.joinTime = GetFileTimeNow();
266  pChar->SetFleetData(fData);
267 
268  PyDict* dict = new PyDict();
269  dict->SetItemString("targetTags", new PyDict());
270  PyTuple* obj = new PyTuple(1);
271  obj->SetItem(0, new PyObject("util.KeyVal", dict));
272  pClient->SendNotification("OnFleetStateChange", "charid", obj, true);
273 
274  bool fleet(false);
275  if (role == Fleet::Role::FleetLeader) {
276  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
277  if (fItr == m_fleetDataMap.end()) {
278  _log(FLEET__ERROR, "Fleet Data for fleetID: %u not foune.", fleetID);
279  return false;
280  }
281  if (fItr->second.booster == nullptr) {
282  fItr->second.booster = pClient;
283  fleet = true;
284  }
285  if (fItr->second.leader == nullptr) {
286  fItr->second.leader = pClient;
287  fleet = true;
288  } else {
289  _log(FLEET__ERROR, "FC is already filled.");
290  return false;
291  }
292  }
293 
294  PyTuple* count = new PyTuple(1);
295  count->SetItem(0, new PyInt((255 - m_fleetMembers.count(fleetID)))); // this is slots left from 255 (256 - leader)
296  pClient->SendNotification("OnFleetActive", "clientID", count, true);
297 
298  std::list<int32> wing, squad;
299  wing.clear();
300  squad.clear();
301 
302  if (IsWingID(wingID)) {
303  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(wingID);
304  if (itr == m_wingDataMap.end()) {
305  _log(FLEET__ERROR, "Wing Data for wingID: %u not foune.", wingID);
306  return false;
307  }
308  if (role == Fleet::Role::WingLeader) {
309  if (itr->second.booster == nullptr) {
310  itr->second.booster = pClient;
311  wing.emplace(wing.end(), wingID);
312  }
313  if (itr->second.leader == nullptr) {
314  itr->second.leader = pClient;
315  } else {
316  _log(FLEET__ERROR, "WC is already filled.");
317  return false;
318  }
319  }
320  PyTuple* count = new PyTuple(2);
321  count->SetItem(0, new PyInt(wingID));
322  count->SetItem(1, new PyInt(IsWingActive(wingID) ? 0 : 1));
323  pClient->SendNotification("OnWingActive", "clientID", count, true);
324 
325  if (!IsSquadID(squadID))
326  wing.emplace(wing.end(), wingID);
327  }
328 
329  if (IsSquadID(squadID)) {
330  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
331  if (itr == m_squadDataMap.end()) {
332  _log(FLEET__ERROR, "Squad Data for squadID: %u not foune.", squadID);
333  return false;
334  }
335  if (role == Fleet::Role::SquadLeader) {
336  if (itr->second.booster == nullptr) {
337  itr->second.booster = pClient;
338  squad.emplace(squad.end(), squadID);
339  }
340  if (itr->second.leader == nullptr) {
341  itr->second.leader = pClient;
342  } else {
343  _log(FLEET__ERROR, "SC is already filled.");
344  return false;
345  }
346  }
347  itr->second.members.emplace(pChar->itemID(), pClient);
348  PyTuple* count = new PyTuple(2);
349  count->SetItem(0, new PyInt(squadID));
350  count->SetItem(1, PyStatic.NewOne());
351  pClient->SendNotification("OnSquadActive", "clientID", count, true);
352 
353  squad.emplace(squad.end(), squadID);
354  }
355 
356  // update all members with new member data
357  JoinFleetRSP join;
358  join.charID = pClient->GetCharacterID();
359  join.clientID = pClient->GetClientID();
360  join.job = pChar->fleetJob();
361  join.role = pChar->fleetRole();
362  join.shipTypeID = pClient->GetShip()->typeID();
363  join.skillFleetCommand = pChar->GetSkillLevel(EvESkill::FleetCommand);
364  join.skillLeadership = pChar->GetSkillLevel(EvESkill::Leadership);
365  join.skillWingCommand = pChar->GetSkillLevel(EvESkill::WingCommand);
366  join.squadID = pChar->squadID();
367  join.roleBooster = pChar->fleetBooster();
368  join.solarSystemID = pClient->GetSystemID();
369  join.wingID = pChar->wingID();
370  join.timestamp = pChar->fleetJoinTime();
371  PyTuple* res = new PyTuple(1);
372  res->SetItem(0, join.Encode());
373  SendFleetUpdate(fleetID, "OnFleetJoin", res);
374 
375  UpdateBoost(fleetID, fleet, wing, squad);
376  return true;
377 }
378 
379 bool FleetService::UpdateMember(uint32 charID, uint32 fleetID, int32 newWingID, int32 newSquadID, int8 newJob, int8 newRole, int8 newBooster)
380 {
381  bool fleet(false);
382  std::list<int32> wing, squad;
383  wing.clear();
384  squad.clear();
385  int8 oldRole(0), oldJob(0), oldBooster(0);
386  int32 oldWingID(0), oldSquadID(0);
387  // verify member data
388  Client* pClient = sEntityList.FindClientByCharID(charID);
389  if (pClient == nullptr)
390  return false;
391  Character* pChar = pClient->GetChar().get();
392  if (pChar == nullptr)
393  return false;
394 
395  oldJob = pChar->fleetJob();
396  oldRole = pChar->fleetRole();
397  oldWingID = pChar->wingID();
398  oldSquadID = pChar->squadID();
399  oldBooster = pChar->fleetBooster();
400 
401  // update fleet data
402  if (oldBooster != newBooster) {
403  if (oldBooster == Fleet::Booster::Fleet) {
404  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
405  if (fItr == m_fleetDataMap.end())
406  return false;
407  fItr->second.booster = nullptr;
408  fleet = true;
409  }
410 
411  if (newBooster == Fleet::Booster::Fleet) {
412  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
413  if (fItr == m_fleetDataMap.end())
414  return false;
415  fItr->second.booster = pClient;
416  fleet = true;
417  }
418  }
419 
420  if (oldRole != newRole) {
421  if (oldRole == Fleet::Role::FleetLeader) {
422  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
423  if (fItr == m_fleetDataMap.end())
424  return false;
425  fItr->second.leader = nullptr;
426  }
427 
428  if (newRole == Fleet::Role::FleetLeader) {
429  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
430  if (fItr == m_fleetDataMap.end())
431  return false;
432  fItr->second.leader = pClient;
433  if (fItr->second.booster == nullptr) {
434  fItr->second.booster = pClient;
435  newBooster = Fleet::Booster::Fleet;
436  fleet = true;
437  }
438  }
439  }
440  // update wing data
441  if (IsWingID(oldWingID)) {
442  std::map<uint32, WingData>::iterator wItr = m_wingDataMap.find(oldWingID);
443  if (wItr == m_wingDataMap.end())
444  return false;
445  if ((oldRole != newRole) and (oldRole == Fleet::Role::WingLeader)) {
446  wItr->second.leader = nullptr;
447  }
448  if ((oldBooster != newBooster) and (oldBooster == Fleet::Booster::Wing)) {
449  wItr->second.booster = nullptr;
450  wing.emplace(wing.end(), oldWingID);
451  }
452  }
453 
454  if (newWingID == 0) {
455  newWingID = oldWingID;
456  } else if (IsWingID(newWingID)) {
457  std::map<uint32, WingData>::iterator wItr = m_wingDataMap.find(newWingID);
458  if (wItr == m_wingDataMap.end())
459  return false;
460  if ((oldBooster != newBooster) and (newBooster == Fleet::Booster::Wing)) {
461  wItr->second.booster = pClient;
462  wing.emplace(wing.end(), newWingID);
463  }
464  if ((oldRole != newRole) and (newRole == Fleet::Role::WingLeader)) {
465  wItr->second.leader = pClient;
466  if (wItr->second.booster == nullptr) {
467  wItr->second.booster = pClient;
468  newBooster = Fleet::Booster::Wing;
469  wing.emplace(wing.end(), newWingID);
470  }
471  }
472  }
473 
474  // update squad data
475  if (IsSquadID(oldSquadID)) {
476  std::map<uint32, SquadData>::iterator sItr = m_squadDataMap.find(oldSquadID);
477  if (sItr == m_squadDataMap.end())
478  return false;
479  if ((oldRole != newRole) and (oldRole == Fleet::Role::SquadLeader))
480  sItr->second.leader = nullptr;
481  if ((oldBooster != newBooster) and (oldBooster == Fleet::Booster::Squad)) {
482  sItr->second.booster = nullptr;
483  squad.emplace(squad.end(), oldSquadID);
484  }
485  if (oldSquadID != newSquadID) {
486  sItr->second.members.erase(charID);
487  // need a fast way to iterate thru wing data for active status...
488  SendActiveStatus(fleetID, oldWingID, oldSquadID);
489  }
490  }
491 
492  if (newSquadID == 0) {
493  newSquadID = oldSquadID;
494  } else if (IsSquadID(newSquadID)) {
495  std::map<uint32, SquadData>::iterator sItr = m_squadDataMap.find(newSquadID);
496  if (sItr == m_squadDataMap.end())
497  return false;
498  if ((oldBooster != newBooster) and (newBooster == Fleet::Booster::Squad)) {
499  sItr->second.booster = pClient;
500  squad.emplace(squad.end(), newSquadID);
501  }
502  if ((oldRole != newRole) and (newRole == Fleet::Role::SquadLeader)) {
503  sItr->second.leader = pClient;
504  if (sItr->second.booster == nullptr) {
505  sItr->second.booster = pClient;
506  newBooster = Fleet::Booster::Squad;
507  squad.emplace(squad.end(), newSquadID);
508  }
509  }
510  if (newSquadID != oldSquadID) {
511  sItr->second.members.emplace(charID, pClient);
512  SendActiveStatus(fleetID, newWingID, newSquadID);
513  }
514  }
515 
516  _log(FLEET__TRACE, "UpdateMember - CharID: %u, FleetID: %u, oldWingID: %i, newWingID: %i, oldSquad: %i, newSquadID: %i, oldJob: %s, newJob: %s, oldRole: %s, newRole: %s, oldBooster: %s, newBooster: %s", \
517  charID, fleetID, oldWingID, newWingID, oldSquadID, newSquadID, \
518  GetJobName(oldJob).c_str(), GetJobName(newJob).c_str(), GetRoleName(oldRole).c_str(), GetRoleName(newRole).c_str(), \
519  GetBoosterName(oldBooster).c_str(), GetBoosterName(newBooster).c_str());
520 
521  // update char data
522  CharFleetData fData = CharFleetData();
523  fData.fleetID = fleetID;
524  fData.wingID = newWingID;
525  fData.squadID = newSquadID;
526  fData.job = newJob;
527  fData.role = newRole;
528  fData.booster = newBooster;
529  fData.joinTime = pChar->fleetJoinTime();
530  pChar->SetFleetData(fData);
531 
532  // update fleet members with new data
533  MemberChangedRSP res;
534  res.charID = charID;
535  res.fleetID = fleetID;
536  res.oldWingID = oldWingID;
537  res.oldSquadID = oldSquadID;
538  res.oldRole = oldRole;
539  res.oldJob = oldJob;
540  res.oldBooster = oldBooster;
541  res.newWingID = newWingID;
542  res.newSquadID = newSquadID;
543  res.newRole = newRole;
544  res.newJob = newJob;
545  res.newBooster = newBooster;
546  res.isOnlyMember = (m_fleetMembers.count(fleetID) > 1 ? false : true);
547  SendFleetUpdate(fleetID, "OnFleetMemberChanged", res.Encode());
548 
549  UpdateBoost(fleetID, fleet, wing, squad);
550 
551  // send "OnFleetMove" (empty tuple) if/when voice is enabled for this fleet
552 
553  return true;
554 }
555 
556 void FleetService::UpdateBoost(uint32 fleetID, bool fleet, std::list<int32>& wing, std::list<int32>& squad)
557 {
558  double start = GetTimeUSeconds();
559  /* this needs to check all boosters to update squad boost levels
560  * we will also check current levels to see if members need to be updated
561  */
562  std::vector< uint32 > wingIDs, squadIDs;
563  std::map<ShipSE*, BoostData> memberUpdateMap;
564 
565  bool fBoost(false);
566  int8 armored(0), info(0), leader(0), mining(0), siege(0), skirmish(0);
567 
568  BoostData fData = BoostData();
569  BoostData bData = BoostData();
570 
571  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
572  if (fItr != m_fleetDataMap.end()) {
573  // set base boost data from FB
574  if ((fItr->second.leader != nullptr) and (fItr->second.leader->IsInSpace()))
575  if (m_fleetWings.count(fleetID) <= fItr->second.leader->GetChar()->GetSkillLevel(EvESkill::FleetCommand)) {
576  if ((fItr->second.booster != nullptr) and (fItr->second.booster->IsInSpace()))
577  if (fItr->second.leader->GetSystemID() == fItr->second.booster->GetSystemID()) {
578  Character* pChar = fItr->second.booster->GetChar().get();
579  if (pChar != nullptr) {
590  if (fData.armored or fData.info or fData.leader or fData.mining or fData.siege or fData.skirmish)
591  fBoost = true;
592  }
593  }
594  // this is for FC only. will always get own skill, and here they get their fleet boost, also
595  fData.leader = fItr->second.leader->GetChar()->GetSkillLevel(EvESkill::Leadership);
596  if (fItr->second.leader->IsInSpace())
597  fItr->second.leader->GetShipSE()->ApplyBoost(fData);
598  }
599  }
600 
601  _log( FLEET__TRACE, "UpdateBoost - FB: %s, leader: %i, armored: %i, info: %i, siege: %i, skirmish: %i, mining: %i", \
602  (fBoost ? "true" : "false"), fData.leader, fData.armored, fData.info, fData.siege, fData.skirmish, fData.mining);
603 
604  // check squad boost updates....sb overwriting higher boosts
605  if (fleet) {
606  // update all fleet members due to fleet booster update
607  wingIDs.clear();
608  GetWingIDs(fleetID, wingIDs);
609  for (auto wingID : wingIDs) {
610  if (!IsWingID(wingID)) // if WingID is invalid, remove it from map!!
611  continue;
612  bData = BoostData();
613  if (fBoost) {
614  bData.armored = fData.armored;
615  bData.info = fData.info;
616  bData.mining = fData.mining;
617  bData.siege = fData.siege;
618  bData.skirmish = fData.skirmish;
619  }
620  SetWingBoostData(wingID, bData);
621 
622  squadIDs.clear();
623  GetSquadIDs(wingID, squadIDs);
624  for (auto squadID : squadIDs) {
625  if (!IsSquadID(squadID))
626  continue;
627  bool sboost(false);
628  SetSquadBoostData(squadID, bData, sboost);
629  SquadData sData = SquadData();
630  GetSquadData(squadID, sData);
631  for (auto cur : sData.members) // SC is a member
632  if ((sboost) and (cur.second->GetSystemID() == sData.booster->GetSystemID()))
633  memberUpdateMap.emplace(cur.second->GetShipSE(), sData.boost);
634  }
635  }
636  } else if (!wing.empty()) {
637  wing.sort();
638  wing.unique();
639  for (auto wingID : wing) {
640  if (!IsWingID(wingID))
641  continue;
642  bData = BoostData();
643  if (fBoost) {
644  bData.armored = fData.armored;
645  bData.info = fData.info;
646  bData.mining = fData.mining;
647  bData.siege = fData.siege;
648  bData.skirmish = fData.skirmish;
649  }
650  SetWingBoostData(wingID, bData);
651 
652  squadIDs.clear();
653  GetSquadIDs(wingID, squadIDs);
654  for (auto squadID : squadIDs) {
655  if (!IsSquadID(squadID))
656  continue;
657  bool sboost(false);
658  SetSquadBoostData(squadID, bData, sboost);
659  SquadData sData = SquadData();
660  GetSquadData(squadID, sData);
661  for (auto cur : sData.members)
662  if ((sboost) and (cur.second->GetSystemID() == sData.booster->GetSystemID()))
663  memberUpdateMap.emplace(cur.second->GetShipSE(), sData.boost);
664  }
665  }
666  } else if (!squad.empty()) {
667  squad.sort();
668  squad.unique();
669  for (auto squadID : squad) {
670  if (!IsSquadID(squadID)) // if squadID is invalid, remove it from map!!
671  continue;
672  bData = BoostData();
673  if (fBoost) {
674  bData.armored = fData.armored;
675  bData.info = fData.info;
676  bData.mining = fData.mining;
677  bData.siege = fData.siege;
678  bData.skirmish = fData.skirmish;
679  }
680  SquadData sData = SquadData();
681  GetSquadData(squadID, sData);
682  SetWingBoostData(sData.wingID, bData);
683  bool sboost(false);
684  SetSquadBoostData(squadID, bData, sboost);
685  for (auto cur : sData.members)
686  if (sboost and (cur.second->GetSystemID() == sData.booster->GetSystemID()))
687  memberUpdateMap.emplace(cur.second->GetShipSE(), sData.boost);
688  }
689  }
690 
691  // update boost effects on these members' ships using updated boost levels
692  // this is for fleet boost only, as modules will apply/remove their effects using the FxSystem
693  for (auto cur : memberUpdateMap)
694  cur.first->ApplyBoost(cur.second);
695 
696  _log( FLEET__TRACE, "FleetService::UpdateBoost() - Updated %u members of fleetID: %u in %.2fus. fleet: %s, wing: %s, squad: %s", \
697  memberUpdateMap.size(), fleetID, GetTimeUSeconds() - start, (fleet ? "true" : "false"), (wing.empty() ? "false" : "true"), (squad.empty() ? "false" : "true"));
698 }
699 
701 {
702  bool boost(false);
703  int8 leader(0), armored(0), info(0), mining(0), siege(0), skirmish(0);
704  std::map<uint32, WingData>::iterator wItr = m_wingDataMap.find(wingID);
705  if (wItr == m_wingDataMap.end())
706  return;
707  if ((wItr->second.leader != nullptr) and (wItr->second.leader->IsInSpace()))
708  if (m_wingSquads.count(wingID) <= wItr->second.leader->GetChar()->GetSkillLevel(EvESkill::WingCommand)) {
709  if ((wItr->second.booster != nullptr) and (wItr->second.booster->IsInSpace()))
710  if (wItr->second.leader->GetSystemID() == wItr->second.booster->GetSystemID()) {
711  Character* pChar = wItr->second.booster->GetChar().get();
712  if (pChar != nullptr) {
713  leader = wItr->second.leader->GetChar()->GetSkillLevel(EvESkill::Leadership); // this applies ONLY to self
715  armored = pChar->GetSkillLevel(EvESkill::ArmoredWarfare);
719  siege = pChar->GetSkillLevel(EvESkill::SiegeWarfare);
721  skirmish = pChar->GetSkillLevel(EvESkill::SkirmishWarfare);
724  }
725  boost = true;
726  wItr->second.boost.armored = ((armored < bData.armored) ? bData.armored : armored);
727  wItr->second.boost.info = ((info < bData.info) ? bData.info : info);
728  wItr->second.boost.mining = ((mining < bData.mining) ? bData.mining : mining);
729  wItr->second.boost.siege = ((siege < bData.siege) ? bData.siege : siege);
730  wItr->second.boost.skirmish = ((skirmish < bData.skirmish) ? bData.skirmish : skirmish);
731  } else {
732  wItr->second.boost = BoostData();
733  }
734  // this is for WC only. will always get own skill, and here they get their wing boost, also
735  wItr->second.boost.leader = leader;
736  wItr->second.leader->GetShipSE()->ApplyBoost(wItr->second.boost);
737  }
738 
739  if (!boost)
740  wItr->second.boost = BoostData();
741 
742  _log( FLEET__TRACE, "BoostData - WB: %s, wingID: %u - leader: %i, armored: %i, info: %i, siege: %i, skirmish: %i, mining: %i", \
743  (boost ? "true" : "false"), wingID, wItr->second.boost.leader, wItr->second.boost.armored, wItr->second.boost.info, \
744  wItr->second.boost.siege, wItr->second.boost.skirmish, wItr->second.boost.mining);
745 }
746 
747 void FleetService::SetSquadBoostData(uint32 squadID, BoostData bData, bool& sboost)
748 {
749  int8 leader(0), armored(0), info(0), mining(0), siege(0), skirmish(0);
750  std::map<uint32, SquadData>::iterator sItr = m_squadDataMap.find(squadID);
751  if (sItr == m_squadDataMap.end())
752  return;
753  if ((sItr->second.leader != nullptr) and (sItr->second.leader->IsInSpace()))
754  if (sItr->second.members.size() <= (sItr->second.leader->GetChar()->GetSkillLevel(EvESkill::Leadership) * 2)) {
755  if ((sItr->second.booster != nullptr) and (sItr->second.booster->IsInSpace()))
756  if (sItr->second.leader->GetSystemID() == sItr->second.booster->GetSystemID()) {
757  Character* pChar = sItr->second.booster->GetChar().get();
758  if (pChar != nullptr) {
759  leader = sItr->second.leader->GetChar()->GetSkillLevel(EvESkill::Leadership); // this applies ONLY to self
761  armored = pChar->GetSkillLevel(EvESkill::ArmoredWarfare);
765  siege = pChar->GetSkillLevel(EvESkill::SiegeWarfare);
767  skirmish = pChar->GetSkillLevel(EvESkill::SkirmishWarfare);
770  }
771  sItr->second.boost.armored = ((armored < bData.armored) ? bData.armored : armored);
772  sItr->second.boost.info = ((info < bData.info) ? bData.info : info);
773  sItr->second.boost.mining = ((mining < bData.mining) ? bData.mining : mining);
774  sItr->second.boost.siege = ((siege < bData.siege) ? bData.siege : siege);
775  sItr->second.boost.skirmish = ((skirmish < bData.skirmish) ? bData.skirmish : skirmish);
776  } else {
777  sItr->second.boost = BoostData();
778  }
779  // squad will always get this if SC is skilled
780  sboost = true;
781  sItr->second.boost.leader = leader;
782  }
783 
784  if (!sboost)
785  sItr->second.boost = BoostData();
786 
787  _log( FLEET__TRACE, "BoostData - SB: %s, squadID: %u - leader: %i, armored: %i, info: %i, siege: %i, skirmish: %i, mining: %i", \
788  (sboost ? "true" : "false"), squadID, sItr->second.boost.leader, sItr->second.boost.armored, sItr->second.boost.info, \
789  sItr->second.boost.siege, sItr->second.boost.skirmish, sItr->second.boost.mining);
790 }
791 
792 void FleetService::UpdateOptions(uint32 fleetID, bool isFreeMove, bool isRegistered, bool isVoiceEnabled)
793 {
794  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
795  if (itr == m_fleetDataMap.end())
796  return;
797  // if nothing changed, do nothing
798  if ((itr->second.isFreeMove == isFreeMove) and (itr->second.isRegistered == isRegistered) and (itr->second.isVoiceEnabled == isVoiceEnabled))
799  return;
800 
801  PyDict* was = new PyDict();
802  was->SetItemString("isFreeMove", new PyBool(itr->second.isFreeMove));
803  was->SetItemString("isRegistered", new PyBool(itr->second.isRegistered));
804  was->SetItemString("isVoiceEnabled", new PyBool(itr->second.isVoiceEnabled));
805  PyDict* is = new PyDict();
806  is->SetItemString("isFreeMove", new PyBool(isFreeMove));
807  is->SetItemString("isRegistered", new PyBool(isRegistered));
808  is->SetItemString("isVoiceEnabled", new PyBool(isVoiceEnabled));
809  PyTuple* tuple = new PyTuple(2);
810  tuple->SetItem(0, new PyObject("util.KeyVal", was));
811  tuple->SetItem(1, new PyObject("util.KeyVal", is));
812  SendFleetUpdate(fleetID, "OnFleetOptionsChanged", tuple);
813 
814  _log(FLEET__TRACE, "FleetService::UpdateOptions() - fleetID: %u FreeMove: %s, Registered: %s, Voice: %s", \
815  fleetID, isFreeMove ? "true" : "false", isRegistered ? "true" : "false", isVoiceEnabled ? "true" : "false");
816  itr->second.isFreeMove = isFreeMove;
817  itr->second.isRegistered = isRegistered;
818  itr->second.isVoiceEnabled = isVoiceEnabled;
819 }
820 
822 {
823  PyTuple* tuple = new PyTuple(1);
824  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
825  if (itr != m_fleetDataMap.end()) {
826  tuple->SetItem(0, new PyString(itr->second.motd));
827  } else {
828  tuple->SetItem(0, PyStatic.NewNone());
829  }
830  return tuple;
831 }
832 
833 void FleetService::SetMOTD(uint32 fleetID, std::string motd)
834 {
835  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
836  if (itr != m_fleetDataMap.end())
837  itr->second.motd = motd;
838 
839  PyTuple* tuple = new PyTuple(1);
840  tuple->SetItem(0, new PyString(motd));
841  SendFleetUpdate(fleetID, "OnFleetMotdChanged", tuple);
842 
844 }
845 
846 void FleetService::RenameWing(uint32 wingID, std::string name)
847 {
848  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(wingID);
849  if (itr == m_wingDataMap.end())
850  return;
851 
852  itr->second.name = name;
853 
854  PyTuple* tuple = new PyTuple(2);
855  tuple->SetItem(0, new PyInt(wingID));
856  tuple->SetItem(1, new PyString(name));
857  SendFleetUpdate(itr->second.fleetID, "OnFleetWingNameChanged", tuple);
858 
859  _log(FLEET__TRACE, "FleetService::RenameWing() %u to %s", wingID, name.c_str());
860 }
861 
862 void FleetService::RenameSquad(uint32 squadID, std::string name)
863 {
864  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
865  if (itr == m_squadDataMap.end())
866  return;
867 
868  itr->second.name = name;
869 
870  PyTuple* tuple = new PyTuple(2);
871  tuple->SetItem(0, new PyInt(squadID));
872  tuple->SetItem(1, new PyString(name));
873  SendFleetUpdate(itr->second.fleetID, "OnFleetSquadNameChanged", tuple);
874 
875  _log(FLEET__TRACE, "FleetService::RenameSquad() %u to %s", squadID, name.c_str());
876 }
877 
879 {
880  auto range = m_wingSquads.equal_range(wingID);
881  for (auto itr = range.first; itr != range.second; ++itr) {
882  std::map<uint32, SquadData>::iterator sItr = m_squadDataMap.find(itr->second);
883  if (sItr != m_squadDataMap.end())
884  if (sItr->second.members.size() > 0)
885  return true;
886  }
887  return false;
888 }
889 
890 void FleetService::GetSquadIDs(uint32 wingID, std::vector< uint32 >& squadIDs)
891 {
892  auto range = m_wingSquads.equal_range(wingID);
893  for (auto itr = range.first; itr != range.second; ++itr)
894  squadIDs.push_back(itr->second);
895 }
896 
897 void FleetService::GetWingIDs(uint32 fleetID, std::vector< uint32 >& wingIDs)
898 {
899  auto range = m_fleetWings.equal_range(fleetID);
900  for (auto itr = range.first; itr != range.second; ++itr)
901  wingIDs.push_back(itr->second);
902 }
903 
905 {
906  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
907  if (itr != m_fleetDataMap.end())
908  data = itr->second;
909 }
910 
912 {
913  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(wingID);
914  if (itr != m_wingDataMap.end())
915  data = itr->second;
916 }
917 
919 {
920  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
921  if (itr != m_squadDataMap.end())
922  data = itr->second;
923 }
924 
925 void FleetService::GetMemeberVec(uint32 fleetID, std::vector< Client* >& data)
926 {
927  auto range = m_fleetMembers.equal_range(fleetID);
928  for (auto itr = range.first; itr != range.second; ++itr)
929  data.push_back(itr->second);
930 }
931 
933 {
934  Client* pClient(nullptr);
935  std::map<uint32, FleetAdvert>::iterator itr = m_fleetAdvertMap.find(fleetID);
936  if (itr == m_fleetAdvertMap.end())
937  return nullptr;
938 
939  pClient = itr->second.leader;
940  if (pClient == nullptr)
941  return nullptr;
942  AvalibleFleetsRSP fleetRSP;
943  fleetRSP.fleetID = itr->first;
944  fleetRSP.local_minSecurity = itr->second.local_minSecurity;
945  fleetRSP.description = itr->second.description;
946  fleetRSP.public_minStanding = itr->second.public_minStanding;
947  fleetRSP.fleetName = itr->second.fleetName;
948  fleetRSP.advertTime = itr->second.advertTime;
949  fleetRSP.dateCreated = itr->second.dateCreated;
950  fleetRSP.joinNeedsApproval = itr->second.joinNeedsApproval;
951 
952  PyTuple* localTuple = new PyTuple(1);
953  PyList* localList = new PyList();
954  for (auto cur1 : itr->second.local_allowedEntities) // corpID, allianceID, militiaID - if applicable
955  localList->AddItemInt(cur1);
956  localTuple->SetItem(0, localList);
957  PyToken* token = new PyToken("__builtin__.set");
958  PyTuple* localTuple2 = new PyTuple(2);
959  localTuple2->SetItem(0, token);
960  localTuple2->SetItem(1, localTuple);
961  fleetRSP.local_allowedEntities = new PyObjectEx(false, localTuple2);
962 
963  PyTuple* publicTuple = new PyTuple(1);
964  PyList* publicList = new PyList();
965  for (auto cur2 : itr->second.public_allowedEntities) // searches creator's addy book and addes charIDs based on standings
966  publicList->AddItemInt(cur2);
967  publicTuple->SetItem(0, publicList);
968  PyTuple* publicTuple2 = new PyTuple(2);
969  PyIncRef(token);
970  publicTuple2->SetItem(0, token);
971  publicTuple2->SetItem(1, publicTuple);
972  fleetRSP.public_allowedEntities = new PyObjectEx(false, publicTuple2);
973 
974  fleetRSP.local_minStanding = itr->second.local_minStanding;
975  fleetRSP.numMembers = m_fleetMembers.count(itr->first);
976  fleetRSP.hideInfo = itr->second.hideInfo;
977  fleetRSP.public_minSecurity = itr->second.public_minSecurity;
978  fleetRSP.inviteScope = itr->second.inviteScope;
979  fleetRSP.solarSystemID = itr->second.solarSystemID;
980  fleetRSP.charID = pClient->GetCharacterID();
981  fleetRSP.corpID = pClient->GetCorporationID();
982  fleetRSP.warFactionID = pClient->GetWarFactionID();
983  fleetRSP.securityStatus = pClient->GetSecurityRating();
984  fleetRSP.allianceID = pClient->GetAllianceID();
985 
986  fleetRSP.Dump(FLEET__DEBUG);
987  return fleetRSP.Encode();
988 }
989 
991 {
992  _log(FLEET__TRACE, "RemoveFleetAdvert for FleetID: %u", fleetID);
993  m_fleetAdvertMap.erase(fleetID);
994  // set options to remove registration
995  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
996  if (fItr != m_fleetDataMap.end())
997  UpdateOptions(fleetID, fItr->second.isFreeMove, /*isRegistered*/false, fItr->second.isVoiceEnabled);
998 }
999 
1001 {
1002  std::vector<uint32> wings, squads;
1003  GetWingIDs(fleetID, wings);
1004  for (auto wing : wings) {
1005  m_wingDataMap.erase(wing);
1006  squads.clear();
1007  GetSquadIDs(wing, squads);
1008  for (auto squad : squads)
1009  m_squadDataMap.erase(squad);
1010  }
1011  m_fleetDataMap.erase(fleetID);
1012  RemoveFleetAdvert(fleetID);
1013 }
1014 
1016 {
1017  std::map<uint32, WingData>::iterator wItr = m_wingDataMap.find(wingID);
1018  if (wItr == m_wingDataMap.end())
1019  return;
1020 
1021  DecFleetSquads(wItr->second.fleetID, wingID);
1022 
1023  std::vector<uint32> squads;
1024  GetSquadIDs(wingID, squads);
1025  std::map<uint32, SquadData>::iterator sItr;
1026  for (auto cur : squads) {
1027  sItr = m_squadDataMap.find(cur);
1028  if (sItr == m_squadDataMap.end())
1029  continue;
1030  m_squadDataMap.erase(sItr);
1031  }
1032 
1033  PyTuple* tuple = new PyTuple(1);
1034  tuple->SetItem(0, new PyInt(wingID));
1035  SendFleetUpdate(wItr->second.fleetID, "OnFleetWingDeleted", tuple);
1036 
1037  m_wingDataMap.erase(wItr);
1038 }
1039 
1041 {
1042  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
1043  if (itr == m_squadDataMap.end())
1044  return;
1045 
1046  DecFleetSquads(itr->second.fleetID, itr->second.wingID);
1047 
1048  PyTuple* tuple = new PyTuple(1);
1049  tuple->SetItem(0, new PyInt(squadID));
1050  SendFleetUpdate(itr->second.fleetID, "OnFleetSquadDeleted", tuple);
1051 
1052  m_squadDataMap.erase(itr);
1053 }
1054 
1056 {
1057  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
1058  if (fItr == m_fleetDataMap.end())
1059  return;
1060  ++(fItr->second.squads);
1061 }
1062 
1064 {
1065  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
1066  if (fItr == m_fleetDataMap.end())
1067  return;
1068  --(fItr->second.squads);
1069 }
1070 
1072 {
1073  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
1074  if (itr == m_fleetDataMap.end())
1075  return nullptr;
1076  return itr->second.leader;
1077 }
1078 
1080 {
1081  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
1082  if (itr == m_fleetDataMap.end())
1083  return 0;
1084  return itr->second.leader->GetCharacterID();
1085 }
1086 
1088 {
1089  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(wingID);
1090  if (itr == m_wingDataMap.end())
1091  return nullptr;
1092  return itr->second.leader;
1093 }
1094 
1096 {
1097  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(wingID);
1098  if (itr == m_wingDataMap.end())
1099  return 0;
1100  return itr->second.leader->GetCharacterID();
1101 }
1102 
1104 {
1105  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
1106  if (itr == m_squadDataMap.end())
1107  return nullptr;
1108  return itr->second.leader;
1109 }
1110 
1112 {
1113  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
1114  if (itr == m_squadDataMap.end())
1115  return 0;
1116  return itr->second.leader->GetCharacterID();
1117 }
1118 
1120 {
1121  std::map<uint32, FleetData>::iterator itr = m_fleetDataMap.find(fleetID);
1122  if (itr == m_fleetDataMap.end())
1123  return "Fleet";
1124  return itr->second.name;
1125 }
1126 
1128 {
1129  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(wingID);
1130  if (itr == m_wingDataMap.end())
1131  return "Wing";
1132  return itr->second.name;
1133 }
1134 
1136 {
1137  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
1138  if (itr == m_squadDataMap.end())
1139  return "Squad";
1140  return itr->second.name;
1141 }
1142 
1144 {
1145  std::map<uint32, FleetAdvert>::iterator itr = m_fleetAdvertMap.find(fleetID);
1146  if (itr == m_fleetAdvertMap.end())
1147  return "No Info";
1148  return itr->second.description;
1149 }
1150 
1151 void FleetService::GetRandUnitIDs(uint32 fleetID, int32& wingID, int32& squadID)
1152 {
1153  std::vector<uint32> wings, squads;
1154  auto range = m_fleetWings.equal_range(fleetID);
1155  for (auto itr = range.first; itr != range.second; ++itr)
1156  wings.push_back(itr->second);
1157 
1158  wingID = wings.at(MakeRandomInt(0, wings.size()));
1159 
1160  range = m_wingSquads.equal_range(wingID);
1161  for (auto itr = range.first; itr != range.second; ++itr)
1162  squads.push_back(itr->second);
1163 
1164  // make sure there is room in this squad for another member
1165  squadID = squads.at(MakeRandomInt(0, squads.size()));
1166 }
1167 
1169 {
1170  Character* pChar = pClient->GetChar().get();
1171  if (pChar == nullptr)
1172  return;
1173 
1174  PyTuple* tuple = new PyTuple(1);
1175  tuple->SetItem(0, new PyInt(pChar->itemID()));
1176  SendFleetUpdate(pChar->fleetID(), "OnFleetLeave", tuple);
1177 
1178  RemoveMember(pClient);
1179 
1181  //call updates on fleet session data
1182  pChar->SetFleetData(fleet);
1183 }
1184 
1186 {
1187  Character* pChar = pClient->GetChar().get();
1188  if (pChar == nullptr)
1189  return;
1190 
1191  uint32 fleetID = pChar->fleetID();
1192 
1193  // update fleet data
1194  if (fleetID) {
1195  std::map<uint32, FleetData>::iterator fItr = m_fleetDataMap.find(fleetID);
1196  if (fItr != m_fleetDataMap.end()) {
1197  if (pChar->fleetBooster() == Fleet::Booster::Fleet)
1198  fItr->second.booster = nullptr;
1200  fItr->second.leader = nullptr;
1201  }
1202  }
1203 
1204  // update wing data
1205  if (pChar->wingID()) {
1206  std::map<uint32, WingData>::iterator itr = m_wingDataMap.find(pChar->wingID());
1207  if (itr != m_wingDataMap.end()) {
1208  if (pChar->fleetBooster() == Fleet::Booster::Wing)
1209  itr->second.booster = nullptr;
1211  itr->second.leader = nullptr;
1212  }
1213  }
1214 
1215  // update squad data
1216  if (pChar->squadID()) {
1217  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(pChar->squadID());
1218  if (itr != m_squadDataMap.end()) {
1219  itr->second.members.erase(pChar->itemID());
1220  if (pChar->fleetBooster() == Fleet::Booster::Squad)
1221  itr->second.booster = nullptr;
1223  itr->second.leader = nullptr;
1224  }
1225  }
1226 
1227  auto range = m_fleetMembers.equal_range(fleetID);
1228  for (auto itr = range.first; itr != range.second; ++itr)
1229  if (itr->second == pClient) {
1230  m_fleetMembers.erase(itr);
1231  break;
1232  }
1233 }
1234 
1236 {
1237  std::vector< uint32 > wingIDs, squadIDs;
1238  wingIDs.clear();
1239  GetWingIDs(fleetID, wingIDs);
1240  PyDict* dict = new PyDict();
1241  for (auto wingID : wingIDs) {
1242  squadIDs.clear();
1243  WingData wData = WingData();
1244  GetWingData(wingID, wData);
1245  WingRSP wing;
1246  wing.name = wData.name;
1247  wing.wingID = wingID;
1248  GetSquadIDs(wingID, squadIDs);
1249  PyDict* dict2 = new PyDict();
1250  for (auto squadID : squadIDs) {
1251  SquadData sData = SquadData();
1252  GetSquadData(squadID, sData);
1253  SquadRSP squad;
1254  squad.name = sData.name;
1255  squad.squadID = squadID;
1256  dict2->SetItem(new PyInt(squadID), squad.Encode());
1257  }
1258  wing.squads = dict2;
1259  dict->SetItem(new PyInt(wingID), wing.Encode());
1260  }
1261 
1262  dict->Dump(FLEET__DEBUG, " ");
1263  return dict;
1264 }
1265 
1267  Client* pClient(nullptr);
1268 
1269  PyDict* fleetDict = new PyDict();
1270  for (auto cur : m_fleetAdvertMap) {
1271  pClient = cur.second.leader;
1272  if (pClient == nullptr)
1273  continue;
1274  AvalibleFleetsRSP fleetRSP;
1275  fleetRSP.fleetID = cur.first;
1276  fleetRSP.local_minSecurity = cur.second.local_minSecurity;
1277  fleetRSP.description = cur.second.description;
1278  fleetRSP.public_minStanding = cur.second.public_minStanding;
1279  fleetRSP.fleetName = cur.second.fleetName;
1280  fleetRSP.advertTime = cur.second.advertTime;
1281  fleetRSP.dateCreated = cur.second.dateCreated;
1282  fleetRSP.joinNeedsApproval = cur.second.joinNeedsApproval;
1283 
1284  PyTuple* localTuple = new PyTuple(1);
1285  PyList* localList = new PyList();
1286  for (auto cur1 : cur.second.local_allowedEntities)
1287  localList->AddItemInt(cur1);
1288  localTuple->SetItem(0, localList);
1289  PyToken* token = new PyToken("__builtin__.set");
1290  PyTuple* localTuple2 = new PyTuple(2);
1291  localTuple2->SetItem(0, token);
1292  localTuple2->SetItem(1, localTuple);
1293  fleetRSP.local_allowedEntities = new PyObjectEx(false, localTuple2);
1294 
1295  PyTuple* publicTuple = new PyTuple(1);
1296  PyList* publicList = new PyList();
1297  for (auto cur2 : cur.second.public_allowedEntities)
1298  publicList->AddItemInt(cur2);
1299  publicTuple->SetItem(0, publicList);
1300  PyTuple* publicTuple2 = new PyTuple(2);
1301  PyIncRef(token);
1302  publicTuple2->SetItem(0, token);
1303  publicTuple2->SetItem(1, publicTuple);
1304  fleetRSP.public_allowedEntities = new PyObjectEx(false, publicTuple2);
1305 
1306  fleetRSP.local_minStanding = cur.second.local_minStanding;
1307  fleetRSP.numMembers = m_fleetMembers.count(cur.first);
1308  fleetRSP.hideInfo = cur.second.hideInfo;
1309  fleetRSP.public_minSecurity = cur.second.public_minSecurity;
1310  fleetRSP.inviteScope = cur.second.inviteScope;
1311  fleetRSP.solarSystemID = cur.second.solarSystemID;
1312  fleetRSP.charID = pClient->GetCharacterID();
1313  fleetRSP.corpID = pClient->GetCorporationID();
1314  fleetRSP.warFactionID = pClient->GetWarFactionID();
1315  fleetRSP.securityStatus = pClient->GetSecurityRating();
1316  fleetRSP.allianceID = pClient->GetAllianceID();
1317  fleetDict->SetItem(new PyLong(cur.first), fleetRSP.Encode() );
1318  }
1319 
1320  fleetDict->Dump(FLEET__DEBUG, " ");
1321  return fleetDict;
1322 }
1323 
1324 void FleetService::FleetBroadcast(Client* pFrom, uint32 itemID, int8 scope, int8 group, std::string msg)
1325 {
1326  uint32 fleetID = pFrom->GetChar()->fleetID();
1327  if (!IsFleetID(fleetID)) {
1328  _log(FLEET__WARNING, "%s called FleetBroadcast with invalid fleetID %u.", pFrom->GetName(), fleetID);
1329  return;
1330  }
1331  if (group == Fleet::BCast::Group::None) {
1332  _log(FLEET__WARNING, "%s called FleetBroadcast with group = None for fleet %u.", pFrom->GetName(), fleetID);
1333  return;
1334  }
1335 
1336  int32 wingID(pFrom->GetChar()->wingID());
1337  if ((wingID > 0) and !IsWingID(wingID)) {
1338  _log(FLEET__WARNING, "%s called FleetBroadcast with invalid wing %i for fleet %u.", pFrom->GetName(), wingID, fleetID);
1339  return;
1340  }
1341  int32 squadID(pFrom->GetChar()->squadID());
1342  if ((squadID > 0) and !IsSquadID(squadID)) {
1343  _log(FLEET__WARNING, "%s called FleetBroadcast with invalid squad %i for fleet %u.", pFrom->GetName(), squadID, fleetID);
1344  return;
1345  }
1346 
1347  uint16 scopeID(0);
1348  std::vector<Client*> members;
1349  switch (scope) {
1351  scopeID = pFrom->GetSystemID();
1352  } break;
1354  scopeID = pFrom->GetShipSE()->SysBubble()->GetID();
1355  } break;
1356  }
1357  switch (group) {
1358  case Fleet::BCast::Group::All: {
1359  auto range = m_fleetMembers.equal_range(fleetID);
1360  for (auto fItr = range.first; fItr != range.second; ++fItr) {
1361  if (scope == Fleet::BCast::Scope::Universe) {
1362  members.push_back(fItr->second);
1363  } else if (scope == Fleet::BCast::Scope::System) {
1364  if (fItr->second->GetSystemID() == scopeID)
1365  members.push_back(fItr->second);
1366  } else if (scope == Fleet::BCast::Scope::Bubble) {
1367  if (fItr->second->GetShipSE()->SysBubble()->GetID() == scopeID)
1368  members.push_back(fItr->second);
1369  }
1370  }
1371  } break;
1372  // these 2 need to check fleet hierarchy for proper member list
1374  if (wingID == -1) {
1375  auto range = m_fleetMembers.equal_range(fleetID);
1376  for (auto fItr = range.first; fItr != range.second; ++fItr) {
1377  if (scope == Fleet::BCast::Scope::Universe) {
1378  members.push_back(fItr->second);
1379  } else if (scope == Fleet::BCast::Scope::System) {
1380  if (fItr->second->GetSystemID() == scopeID)
1381  members.push_back(fItr->second);
1382  } else if (scope == Fleet::BCast::Scope::Bubble) {
1383  if (fItr->second->GetShipSE()->SysBubble()->GetID() == scopeID)
1384  members.push_back(fItr->second);
1385  }
1386  }
1387  } else {
1388  if (squadID == -1) {
1389  std::vector<uint32> squads;
1390  GetSquadIDs(wingID, squads);
1391  std::map<uint32, SquadData>::iterator itr;
1392  for (auto cur : squads) {
1393  itr = m_squadDataMap.find(cur);
1394  if (itr == m_squadDataMap.end())
1395  continue;
1396  for (auto member : itr->second.members)
1397  if (scope == Fleet::BCast::Scope::Universe) {
1398  members.push_back(member.second);
1399  } else if (scope == Fleet::BCast::Scope::System) {
1400  if (member.second->GetSystemID() == scopeID)
1401  members.push_back(member.second);
1402  } else if (scope == Fleet::BCast::Scope::Bubble) {
1403  if (member.second->GetShipSE()->SysBubble()->GetID() == scopeID)
1404  members.push_back(member.second);
1405  }
1406  }
1407  } else {
1408  std::map<uint32, SquadData>::iterator itr = m_squadDataMap.find(squadID);
1409  if (itr == m_squadDataMap.end())
1410  break;
1411  for (auto member : itr->second.members)
1412  if (scope == Fleet::BCast::Scope::Universe) {
1413  members.push_back(member.second);
1414  } else if (scope == Fleet::BCast::Scope::System) {
1415  if (member.second->GetSystemID() == scopeID)
1416  members.push_back(member.second);
1417  } else if (scope == Fleet::BCast::Scope::Bubble) {
1418  if (member.second->GetShipSE()->SysBubble()->GetID() == scopeID)
1419  members.push_back(member.second);
1420  }
1421  }
1422  }
1423  } break;
1424  case Fleet::BCast::Group::Up: {
1425  if (wingID == -1) {
1426  // pFrom is FC. nobody above to msg. make error here
1427  _log(FLEET__WARNING, "FC %s called FleetBroadcast with group == Up for fleet %u.", pFrom->GetName(), fleetID);
1428  pFrom->SendErrorMsg("You cannot broadcast to Superiors as FC.");
1429  } else {
1430  if (squadID == -1) {
1431  members.push_back(GetFleetLeader(fleetID));
1432  members.push_back(GetWingLeader(wingID));
1433  } else {
1434  members.push_back(GetFleetLeader(fleetID));
1435  members.push_back(GetWingLeader(wingID));
1436  members.push_back(GetSquadLeader(squadID));
1437  }
1438  }
1439  } break;
1440  }
1441 
1442  // Broadcast(name, group, charID, solarSystemID = None, itemID = None, broadcastName(BroadcastEvent/label) = None):
1443  //OnFleetBroadcast(name, group, charID, solarSystemID, itemID):
1444  // ('HealCapacitor', 3, 95895066, 30003500, 1019274373727L, None)))
1445 
1446  PyTuple* payload = new PyTuple(5);
1447  payload->SetItem(0, new PyString(msg));
1448  payload->SetItem(1, new PyInt(group));
1449  payload->SetItem(2, new PyInt(pFrom->GetCharacterID()));
1450  payload->SetItem(3, new PyInt(pFrom->GetSystemID()));
1451  payload->SetItem(4, new PyInt(itemID));
1452  // if BCastName(label) then add next item properly
1453  payload->SetItem(5, PyStatic.NewNone());
1454 
1455  uint8 count(0);
1456  for (auto cur : members) {
1457  if (cur == nullptr)
1458  continue;
1459  PySafeIncRef(payload);
1460  cur->SendNotification("OnFleetBroadcast", "clientID", payload, true);
1461  ++count;
1462  }
1463 
1464  if (is_log_enabled(FLEET__BCAST_DUMP)) {
1465  std::ostringstream grp;
1466  switch (group) {
1467  case Fleet::BCast::Group::All: {
1468  grp << "All " << std::to_string(count);
1469  } break;
1471  case Fleet::BCast::Group::Up: {
1472  grp << std::to_string(count);
1473  grp << " " << GetBCastGroupName(group).c_str();
1474  } break;
1475  }
1476 
1477  _log(FLEET__BCAST_DUMP, "%s FleetBroadcast '%s' to %s members of fleet %u.", GetBCastScopeName(scope).c_str(), msg.c_str(), grp.str().c_str() , fleetID);
1478  payload->Dump(FLEET__BCAST_DUMP, " ");
1479  }
1480 }
1481 
1482 void FleetService::SendFleetUpdate(uint32 fleetID, const char* notifyType, PyTuple* payload)
1483 {
1484  if (is_log_enabled(FLEET__UPDATE_DUMP)) {
1485  _log(FLEET__UPDATE_DUMP, "SendFleetUpdate '%s' to members of fleet %u.", notifyType, fleetID);
1486  payload->Dump(FLEET__UPDATE_DUMP, " ");
1487  }
1488 
1489  std::vector<Client*> members;
1490  auto range = m_fleetMembers.equal_range(fleetID);
1491  for (auto fItr = range.first; fItr != range.second; ++fItr)
1492  members.push_back(fItr->second);
1493 
1494  for (auto cur : members) {
1495  if (cur == nullptr)
1496  continue;
1497  PySafeIncRef(payload);
1498  cur->SendNotification(notifyType, "*fleetid", payload, true); // this sends "*fleetid" update to all fleet members and is sequenced
1499  }
1500 }
1501 
1502 void FleetService::GetFleetMembersOnGrid(Client* pClient, std::vector< uint32 >& data)
1503 {
1504  std::vector<Client*> members;
1505  uint16 scopeID = pClient->GetShipSE()->SysBubble()->GetID();
1506  auto range = m_fleetMembers.equal_range(pClient->GetFleetID());
1507  for (auto fItr = range.first; fItr != range.second; ++fItr)
1508  members.push_back(fItr->second);
1509 
1510  for (auto cur : members) {
1511  if (cur == nullptr)
1512  continue;
1513  if (cur->GetShipSE()->SysBubble()->GetID() == scopeID)
1514  data.push_back(cur->GetCharacterID());
1515  }
1516 }
1517 
1518 void FleetService::GetFleetMembersInSystem(Client* pClient, std::vector< uint32 >& data)
1519 {
1520  std::vector<Client*> members;
1521  uint16 scopeID = pClient->GetShipSE()->SystemMgr()->GetID();
1522  auto range = m_fleetMembers.equal_range(pClient->GetFleetID());
1523  for (auto fItr = range.first; fItr != range.second; ++fItr)
1524  members.push_back(fItr->second);
1525 
1526  for (auto cur : members) {
1527  if (cur == nullptr)
1528  continue;
1529  if (cur->GetShipSE()->SystemMgr()->GetID() == scopeID)
1530  data.push_back(cur->GetCharacterID());
1531  }
1532 }
1533 
1534 void FleetService::GetFleetClientsInSystem(Client* pClient, std::vector< Client* >& data)
1535 {
1536  std::vector<Client*> members;
1537  uint32 scopeID = pClient->GetShipSE()->SystemMgr()->GetID();
1538  auto range = m_fleetMembers.equal_range(pClient->GetFleetID());
1539  for (auto fItr = range.first; fItr != range.second; ++fItr)
1540  members.push_back(fItr->second);
1541 
1542  for (auto cur : members) {
1543  if (cur == nullptr)
1544  continue;
1545  if (cur->GetShipSE()->SystemMgr()->GetID() == scopeID)
1546  data.push_back(cur);
1547  }
1548 }
1549 
1550 std::vector<Client *> FleetService::GetFleetClients(uint32 fleetID) {
1551  std::vector<Client*> members;
1552  auto range = m_fleetMembers.equal_range(fleetID);
1553  for (auto fItr = range.first; fItr != range.second; ++fItr)
1554  members.push_back(fItr->second);
1555 
1556  return members;
1557 }
1558 
1559 void FleetService::SendActiveStatus(uint32 fleetID, int32 wingID, int32 squadID)
1560 {
1561  PyTuple* count = new PyTuple(1);
1562  count->SetItem(0, new PyInt((255 - m_fleetMembers.count(fleetID)))); // this is slots left from 255 (256 - leader)
1563  SendFleetUpdate(fleetID, "OnFleetActive", count);
1564 
1565  if (wingID > 0) {
1566  WingData wData = WingData();
1567  GetWingData(wingID, wData);
1568  PyTuple* count = new PyTuple(2);
1569  count->SetItem(0, new PyInt(wingID));
1570  count->SetItem(1, new PyInt(IsWingActive(wingID) ? 1 : 0));
1571  SendFleetUpdate(fleetID, "OnWingActive", count);
1572  }
1573 
1574  if (squadID > 0) {
1575  SquadData sData = SquadData();
1576  GetSquadData(squadID, sData);
1577  PyTuple* count = new PyTuple(2);
1578  count->SetItem(0, new PyInt(squadID));
1579  count->SetItem(1, new PyInt(sData.members.size()? 1 : 0));
1580  SendFleetUpdate(fleetID, "OnSquadActive", count);
1581  }
1582 }
1583 
1585 {
1586  std::map<uint32, InviteData>::iterator itr = m_inviteData.find(charID);
1587  if (itr != m_inviteData.end()) {
1588  data = itr->second;
1589  return true;
1590  }
1591  return false;
1592 }
1593 
1595 {
1596  std::map<uint32, InviteData>::iterator itr = m_inviteData.find(charID);
1597  if (itr != m_inviteData.end())
1598  return false;
1599 
1600  m_inviteData.emplace(charID, data); // map of invites by invitedCharID
1601  return true;
1602 }
1603 
1605 {
1606  m_inviteData.erase(charID); // remove invite data
1607 }
1608 
1610 {
1611  // ensure only one request per client
1612  auto range = m_joinReq.equal_range(fleetID);
1613  for (auto itr = range.first; itr != range.second; ++itr)
1614  if (itr->second == pClient)
1615  return false;
1616  m_joinReq.emplace(fleetID, pClient);
1617  return true;
1618 }
1619 
1620 void FleetService::GetJoinRequests(uint32 fleetID, std::vector< Client* >& data)
1621 {
1622  auto range = m_joinReq.equal_range(fleetID);
1623  for (auto itr = range.first; itr != range.second; ++itr)
1624  data.push_back(itr->second);
1625 }
1626 
1628 {
1629  auto range = m_joinReq.equal_range(fleetID);
1630  for (auto itr = range.first; itr != range.second; ++itr)
1631  if (itr->second == pClient) {
1632  m_joinReq.erase(itr);
1633  return;
1634  }
1635 }
1636 
1638 {
1639  switch (job) {
1640  case 0: return "None";
1641  case 1: return "Scout";
1642  case 2: return "Creator";
1643  default: return "Invalid Job";
1644  }
1645 }
1646 
1648 {
1649  switch (role) {
1650  case 1: return "FleetLeader";
1651  case 2: return "WingLeader";
1652  case 3: return "SquadLeader";
1653  case 4: return "Member";
1654  default: return "Invalid Role";
1655  }
1656 }
1657 
1659 {
1660  switch (booster) {
1661  case 0: return "No";
1662  case 1: return "Fleet";
1663  case 2: return "Wing";
1664  case 3: return "Squad";
1665  default: return "Invalid Booster";
1666  }
1667 }
1668 
1670 {
1671  switch (scope) {
1672  case 0: return "Universe";
1673  case 1: return "System";
1674  case 2: return "Bubble";
1675  default: return "Invalid Scope";
1676  }
1677 
1678 }
1679 
1681 {
1682  switch (group) {
1683  case 0: return "No";
1684  case 1: return "Subordinate";
1685  case 2: return "Superior";
1686  case 3: return "All";
1687  default: return "Invalid Group";
1688  }
1689 
1690 }
1691 
1692 std::string FleetService::GetBoosterData(uint32 fleetID, uint16& length)
1693 {
1694  if (!IsFleetID(fleetID) or (fleetID > m_fleetID))
1695  return "Invalid Data";
1696 
1698  Character* pChar(nullptr);
1699  std::ostringstream str;
1700  str.clear();
1701 
1702  bool fboost(false);
1703  FleetData fData = FleetData();
1704  GetFleetData(fleetID, fData);
1705  str << "<color=teal>" << fData.name << " Created By: " << fData.creator->GetChar()->itemName();
1706  str << " Members: " << std::to_string(m_fleetMembers.count(fleetID)) << "</color><br>"; //54
1707  length += 54;
1708  length += fData.name.size();
1709  length += fData.creator->GetChar()->itemName().size();
1710 
1711  if ((fData.leader != nullptr) and (fData.leader->IsInSpace()) and (pChar = fData.leader->GetChar().get()) != nullptr) {
1712  if (m_fleetWings.count(fleetID) > pChar->GetSkillLevel(EvESkill::FleetCommand)) {
1713  str << "<color=red>";
1714  fboost = false;
1715  } else {
1716  str << "<color=green>";
1717  fboost = true;
1718  }
1719  length += 13;
1720  str << "Fleet Cmdr: " << pChar->itemName(); //12
1721  length += pChar->itemName().size();
1722 
1723  str << " " << std::to_string(pChar->GetSkillLevel(EvESkill::FleetCommand)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::WingCommand)) << "/";
1724  str << std::to_string(pChar->GetSkillLevel(EvESkill::Leadership)) << "</color><br>";//15
1725  length += 30;
1726  } else {
1727  str << "<color=red>No Fleet Cmdr</color><br>";
1728  length += 37;
1729  }
1730 
1731  if ((fData.booster != nullptr) and (fData.booster->IsInSpace()) and (pChar = fData.booster->GetChar().get()) != nullptr) {
1732  if (fData.leader->GetSystemID() == fData.booster->GetSystemID()) {
1736  if (fboost) {
1737  str << "<color=green>";
1738  } else {
1739  str << "<color=yellow>";
1740  }
1741  } else {
1742  if (fboost) {
1743  str << "<color=yellow>";
1744  } else {
1745  str << "<color=red>";
1746  }
1747  fboost = false;
1748  }
1749  length += 14;
1750  } else {
1751  str << "<color=red> (Not In System)";
1752  fboost = false;
1753  length += 30;
1754  }
1755  str << "Fleet Booster: " << pChar->itemName();//15
1756  length += pChar->itemName().size();
1757  str << " " << std::to_string(pChar->GetSkillLevel(EvESkill::ArmoredWarfare)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::InformationWarfare)) << "/";
1758  str << std::to_string(pChar->GetSkillLevel(EvESkill::SiegeWarfare)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::SkirmishWarfare)) << "/";
1759  str << std::to_string(pChar->GetSkillLevel(EvESkill::MiningForeman)) << "</color><br>";//30
1760  length += 50;
1761  } else {
1762  str << "<color=red>No Fleet Booster</color><br>";
1763  length += 40;
1764  fboost = false;
1765  }
1766 
1767  std::vector< uint32 > wingIDs, squadIDs;
1768  wingIDs.clear();
1769  GetWingIDs(fleetID, wingIDs);
1770  for (auto wingID : wingIDs) {
1771  if (!IsWingID(wingID))
1772  continue;
1773  bool wboost(false);
1774  WingData wData = WingData();
1775  GetWingData(wingID, wData);
1776  if ((wData.leader != nullptr) and (wData.leader->IsInSpace()) and (pChar = wData.leader->GetChar().get()) != nullptr) {
1777  if (m_wingSquads.count(wingID) > pChar->GetSkillLevel(EvESkill::WingCommand)) {
1778  str << "<color=red>";
1779  } else {
1780  if (fboost) {
1781  str << "<color=green>";
1782  } else {
1783  str << "<color=yellow>";
1784  }
1785  wboost = true;
1786  }
1787  length += 13;
1788  str << " " << wData.name.c_str() << " Cmdr: " << pChar->itemName(); //10
1789  length += wData.name.size();
1790  length += pChar->itemName().size();
1791  str << " " << std::to_string(pChar->GetSkillLevel(EvESkill::FleetCommand)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::WingCommand)) << "/";
1792  str << std::to_string(pChar->GetSkillLevel(EvESkill::Leadership)) << "</color><br>";//15
1793  length += 30;
1794  } else {
1795  str << " <color=red>" << wData.name.c_str() << " No Cmdr</color><br>";//33
1796  length += wData.name.size();
1797  length += 35;
1798  }
1799  if ((wData.booster != nullptr) and (wData.booster->IsInSpace()) and (pChar = wData.booster->GetChar().get()) != nullptr) {
1800  if (wData.leader->GetSystemID() == wData.booster->GetSystemID()) {
1804  if (wboost) {
1805  str << "<color=green>";
1806  } else {
1807  str << "<color=yellow>";
1808  }
1809  } else {
1810  if (wboost) {
1811  str << "<color=yellow>";
1812  } else {
1813  str << "<color=red>";
1814  }
1815  wboost = false;
1816  }
1817  length += 14;
1818  } else {
1819  str << "<color=red> (Not In System)";
1820  wboost = false;
1821  length += 30;
1822  }
1823  str << " " << "Booster: " << pChar->itemName();//11
1824  length += pChar->itemName().size();
1825  str << " " << std::to_string(pChar->GetSkillLevel(EvESkill::ArmoredWarfare)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::InformationWarfare));
1826  str << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::SiegeWarfare)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::SkirmishWarfare)) << "/";
1827  str << std::to_string(pChar->GetSkillLevel(EvESkill::MiningForeman)) << "</color><br>";//32
1828  length += 38;
1829  } else {
1830  str << " <color=red>" << wData.name.c_str() << " No Booster</color><br>";//43
1831  length += wData.name.size();
1832  length += 45;
1833  wboost = false;
1834  }
1835 
1836  squadIDs.clear();
1837  GetSquadIDs(wingID, squadIDs);
1838  for (auto squadID : squadIDs) {
1839  if (!IsSquadID(squadID))
1840  continue;
1841  bool sboost(false);
1842  SquadData sData = SquadData();
1843  GetSquadData(squadID, sData);
1844  if ((sData.leader != nullptr) and (sData.leader->IsInSpace()) and (pChar = sData.leader->GetChar().get()) != nullptr) {
1845  if (sData.members.size() > (pChar->GetSkillLevel(EvESkill::Leadership) * 2)) {
1846  str << "<color=red>";
1847  } else {
1848  if (wboost) {
1849  str << "<color=green>";
1850  } else {
1851  str << "<color=yellow>";
1852  }
1853  sboost = true;
1854  }
1855  length += 13;
1856  str << " " << sData.name.c_str() << " Cmdr: " << pChar->itemName(); //11
1857  length += sData.name.size();
1858  length += pChar->itemName().size();
1859  str << " " << std::to_string(pChar->GetSkillLevel(EvESkill::FleetCommand)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::WingCommand)) << "/";
1860  str << std::to_string(pChar->GetSkillLevel(EvESkill::Leadership)) << "</color><br>";//21
1861  length += 22;
1862  } else {
1863  str << " <color=red>" << sData.name.c_str() << " No Cmdr</color><br>";
1864  length += sData.name.size();
1865  length += 37;
1866  }
1867  if ((sData.booster != nullptr) and (sData.booster->IsInSpace()) and (pChar = sData.booster->GetChar().get()) != nullptr) {
1868  if (sData.leader->GetSystemID() == sData.booster->GetSystemID()) {
1872  if (sboost) {
1873  str << "<color=green>";
1874  } else {
1875  str << "<color=yellow>";
1876  }
1877  } else {
1878  if (sboost) {
1879  str << "<color=yellow>";
1880  } else {
1881  str << "<color=red>";
1882  }
1883  sboost = false;
1884  }
1885  length += 14;
1886  } else {
1887  str << "<color=red> (Not In System)";
1888  sboost = false;
1889  length += 30;
1890  }
1891  str << " Booster: " << pChar->itemName();//13
1892  length += pChar->itemName().size();
1893  str << " " << std::to_string(pChar->GetSkillLevel(EvESkill::ArmoredWarfare)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::InformationWarfare));
1894  str << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::SiegeWarfare)) << "/" << std::to_string(pChar->GetSkillLevel(EvESkill::SkirmishWarfare)) << "/";
1895  str << std::to_string(pChar->GetSkillLevel(EvESkill::MiningForeman)) << "</color><br>";//25
1896  length += 40;
1897  } else {
1898  str << " <color=red>" << sData.name.c_str() << " No Booster</color><br>";//45
1899  length += sData.name.size();
1900  length += 43;
1901  sboost = false;
1902  }
1903  if (sboost) {
1904  str << " <color=green>";
1905  } else {
1906  str << " <color=red>";
1907  }
1908  str << "Members: " << std::to_string(sData.members.size()) << " Effective: ";
1909  length += 40;
1910  std::string bdata;
1911  if (sboost) { // this is the only way i could get these working right...dunno why
1912  bdata = std::to_string(sData.boost.leader);
1913  bdata += "/";
1914  bdata += std::to_string(sData.boost.armored);
1915  bdata += "/";
1916  bdata += std::to_string(sData.boost.info);
1917  bdata += "/";
1918  bdata += std::to_string(sData.boost.siege);
1919  bdata += "/";
1920  bdata += std::to_string(sData.boost.skirmish);
1921  bdata += "/";
1922  bdata += std::to_string(sData.boost.mining);
1923  length += 11;
1924  } else {
1925  bdata = "0/0/0/0/0/0 (";
1926  bdata += std::to_string(sData.boost.leader);
1927  bdata += "/";
1928  bdata += std::to_string(sData.boost.armored);
1929  bdata += "/";
1930  bdata += std::to_string(sData.boost.info);
1931  bdata += "/";
1932  bdata += std::to_string(sData.boost.siege);
1933  bdata += "/";
1934  bdata += std::to_string(sData.boost.skirmish);
1935  bdata += "/";
1936  bdata += std::to_string(sData.boost.mining);
1937  bdata += ")";
1938  length += 26;
1939  }
1940  str << bdata.c_str();
1941  str << "</color><br>";//12
1942  length += 12;
1943  }
1944  if (squadIDs.empty()) {
1945  str << " <color=fuchsia>No Squads</color><br><br>";
1946  length += 45;
1947  }
1948  }
1949  if (wingIDs.empty()) {
1950  str << " <color=fuchsia>No Wings</color><br><br>";
1951  length += 45;
1952  }
1953 
1954  return str.str();
1955 }
std::multimap< uint32, Client * > m_fleetMembers
Definition: FleetService.h:141
Base Python wire object.
Definition: PyRep.h:66
#define sConfig
A macro for easier access to the singleton.
void GetSquadData(uint32 squadID, SquadData &data)
uint32 CreateFleet(Client *pClient)
unsigned __int8 uint8
Definition: eve-compat.h:46
int64 fleetJoinTime()
Definition: Character.h:317
void SendNotification(const PyAddress &dest, EVENotificationStream &noti, bool seq=true)
Definition: Client.cpp:2245
bool isRegistered
Definition: FleetData.h:101
void SendFleetUpdate(uint32 fleetID, const char *notifyType, PyTuple *payload)
void FleetBroadcast(Client *pFrom, uint32 itemID, int8 scope, int8 group, std::string msg)
std::map< uint32, InviteData > m_inviteData
Definition: FleetService.h:132
bool SaveInviteData(uint32 charID, InviteData &data)
void GetRandUnitIDs(uint32 fleetID, int32 &wingID, int32 &squadID)
void SendErrorMsg(const char *fmt,...)
Definition: Client.cpp:2719
uint32 GetSystemID() const
Definition: Client.h:152
#define _log(type, fmt,...)
Definition: logsys.h:124
int8 fleetRole() const
Definition: Character.h:321
Python string.
Definition: PyRep.h:430
#define PySafeIncRef(op)
Definition: PyRep.h:60
float GetSecurityRating() const
Definition: Client.h:172
Python's dictionary.
Definition: PyRep.h:719
std::multimap< uint32, uint32 > m_wingSquads
Definition: FleetService.h:143
std::multimap< uint32, uint32 > isExcludedFromMuting
Definition: FleetData.h:112
std::multimap< uint32, uint32 > m_fleetWings
Definition: FleetService.h:142
void SetWingBoostData(uint32 wingID, BoostData &bData)
SystemBubble * SysBubble()
Definition: SystemEntity.h:195
void RemoveJoinRequest(uint32 fleetID, Client *pClient)
uint32 GetFleetLeaderID(uint32 fleetID)
void SetSquadBoostData(uint32 squadID, BoostData bData, bool &sboost)
void UpdateBoost(uint32 fleetID, bool fleet, std::list< int32 > &wing, std::list< int32 > &squad)
Client * leader
Definition: FleetData.h:129
bool AddJoinRequest(uint32 fleetID, Client *pClient)
void DeleteFleet(uint32 fleetID)
PyRep * GetAvailableFleets()
std::vector< Client * > GetFleetClients(uint32 fleetID)
int8 squads
Definition: FleetData.h:104
bool isVoiceEnabled
Definition: FleetData.h:102
std::string name
Definition: FleetData.h:109
int32 GetCharacterID() const
Definition: Client.h:113
void GetWingData(uint32 wingID, WingData &data)
int32 GetWarFactionID() const
Definition: Client.h:126
bool isLootLogging
Definition: FleetData.h:103
PyRep * GetMOTD(uint32 fleetID)
int32 GetCorporationID() const
Definition: Client.h:123
int8 leader
Definition: FleetData.h:71
#define sEntityList
Definition: EntityList.h:208
uint32 GetID() const
Definition: SystemManager.h:80
int64 GetClientID() const
Definition: Client.h:119
bool isFreeMove
Definition: FleetData.h:100
bool IsWingActive(int32 wingID)
int8 siege
Definition: FleetData.h:74
bool IsInSpace()
Definition: Client.h:228
CharacterRef GetChar() const
Definition: Client.h:164
std::multimap< uint32, Client * > m_joinReq
Definition: FleetService.h:140
Python tuple.
Definition: PyRep.h:567
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
void CreateFleetAdvert(uint32 fleetID, FleetAdvert data)
signed __int8 int8
Definition: eve-compat.h:45
int32 GetAllianceID() const
Definition: Client.h:125
std::map< uint32, FleetData > m_fleetDataMap
Definition: FleetService.h:136
Client * GetSquadLeader(uint32 squadID)
uint32 wingID
Definition: FleetData.h:127
signed __int32 int32
Definition: eve-compat.h:49
std::string GetBoosterName(int8 booster)
Python boolean.
Definition: PyRep.h:323
void GetFleetData(uint32 fleetID, FleetData &data)
void GetMemeberVec(uint32 fleetID, std::vector< Client * > &data)
#define is_log_enabled(type)
Definition: logsys.h:78
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
std::string GetWingName(uint32 wingID)
bool GetInviteData(uint32 charID, InviteData &data)
void CreateSystemChannel(int32 channelID)
Definition: LSCService.cpp:951
void RemoveInviteData(uint32 charID)
SystemManager * SystemMgr()
Definition: SystemEntity.h:196
PyRep * GetFleetAdvert(uint32 fleetID)
PyRep * CreateWing(uint32 fleetID)
Python extended object.
Definition: PyRep.h:861
double GetTimeUSeconds()
Definition: utils_time.cpp:116
void SetFleetData(CharFleetData &fleet)
Definition: Character.cpp:462
PyServiceMgr * m_services
Definition: FleetService.h:129
Python object.
Definition: PyRep.h:826
bool UpdateMember(uint32 charID, uint32 fleetID, int32 newWingID, int32 newSquadID, int8 newJob, int8 newRole, int8 newBooster)
void SendActiveStatus(uint32 fleetID, int32 wingID, int32 squadID)
void DecFleetSquads(uint32 fleetID, uint32 wingID)
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
#define WING_ID
Definition: EVE_Defines.h:184
Client * GetFleetLeader(uint32 fleetID)
std::map< uint32, FleetAdvert > m_fleetAdvertMap
Definition: FleetService.h:134
uint16 GetID()
Definition: SystemBubble.h:91
int32 wingID() const
Definition: Character.h:319
int64 dateCreated
Definition: FleetData.h:105
Python integer.
Definition: PyRep.h:231
std::string GetJobName(int8 job)
int8 info
Definition: FleetData.h:72
int8 fleetBooster() const
Definition: Character.h:322
void LeaveFleet(Client *pClient)
void GetFleetClientsInSystem(Client *pClient, std::vector< Client * > &data)
#define PyStatic
Definition: PyRep.h:1209
uint32 GetFleetID() const
Definition: Client.h:146
X * get() const
Definition: RefPtr.h:213
void AddItemInt(int32 intval)
Definition: PyRep.h:702
int32 squadID() const
Definition: Character.h:320
ShipItemRef GetShip() const
Definition: Client.h:167
std::string GetBCastScopeName(int8 scope)
const char * GetName() const
Definition: Client.h:94
std::string GetFleetDescription(uint32 fleetID)
std::string motd
Definition: FleetData.h:110
Client * GetWingLeader(uint32 wingID)
std::string GetRoleName(int8 role)
void Initialize(PyServiceMgr *svc)
void RenameWing(uint32 wingID, std::string name)
std::string name
Definition: FleetData.h:131
#define IsSquadID(itemID)
Definition: EVE_Defines.h:231
Client * booster
Definition: FleetData.h:130
Definition: Client.h:66
LSCService * lsc_service
Definition: PyServiceMgr.h:77
unsigned __int32 uint32
Definition: eve-compat.h:50
if(sConfig.world.saveOnMove)
#define PyIncRef(op)
Definition: PyRep.h:56
int8 armored
Definition: FleetData.h:70
void RemoveMember(Client *pClient)
void UpdateOptions(uint32 fleetID, bool isFreeMove, bool isRegistered, bool isVoiceEnabled)
uint32 fleetID
Definition: FleetData.h:117
void CreateSquad(uint32 fleetID, uint32 wingID)
void RemoveFleetAdvert(uint32 fleetID)
std::map< uint32, SquadData > m_squadDataMap
Definition: FleetService.h:138
int8 skirmish
Definition: FleetData.h:75
void GetFleetMembersInSystem(Client *pClient, std::vector< uint32 > &data)
Python token (eg. class name).
Definition: PyRep.h:522
bool HasSkillTrainedToLevel(uint16 skillTypeID, uint8 skillLevel) const
Definition: Character.cpp:584
double GetFileTimeNow()
Definition: utils_time.cpp:84
uint32 m_fleetID
Definition: FleetService.h:124
Client * creator
Definition: FleetData.h:106
void DeleteWing(uint32 wingID)
int64 MakeRandomInt(int64 low, int64 high)
Generates random integer from interval [low; high].
Definition: misc.cpp:109
#define FLEET_ID
Definition: EVE_Defines.h:183
ShipSE * GetShipSE()
Definition: Client.h:168
#define IsWingID(itemID)
Definition: EVE_Defines.h:228
const std::string & itemName() const
std::string GetBoosterData(uint32 fleetID, uint16 &length)
void GetFleetMembersOnGrid(Client *pClient, std::vector< uint32 > &data)
uint32 m_wingID
Definition: FleetService.h:125
#define IsFleetID(itemID)
Definition: EVE_Defines.h:225
void GetSquadIDs(uint32 wingID, std::vector< uint32 > &squadIDs)
Client * leader
Definition: FleetData.h:107
void IncFleetSquads(uint32 fleetID, uint32 wingID)
int8 mining
Definition: FleetData.h:73
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
uint8 inviteScope
Definition: FleetData.h:83
std::map< uint32, Client * > members
Definition: FleetData.h:132
std::multimap< uint32, uint32 > isMutedByLeader
Definition: FleetData.h:111
int8 GetSkillLevel(uint16 skillTypeID, bool zeroForNotInjected=true) const
Definition: Character.cpp:575
int8 fleetJob() const
Definition: Character.h:323
Client * booster
Definition: FleetData.h:120
std::string GetFleetName(uint32 fleetID)
void DeleteSquad(uint32 squadID)
uint32 GetWingLeaderID(uint32 wingID)
uint32 fleetID
Definition: FleetData.h:126
uint32 GetSquadLeaderID(uint32 squadID)
PyRep * GetWings(uint32 fleetID)
std::string name
Definition: FleetData.h:121
uint32 m_squadID
Definition: FleetService.h:126
int32 fleetID() const
Definition: Character.h:318
BoostData boost
Definition: FleetData.h:128
void GetJoinRequests(uint32 fleetID, std::vector< Client * > &data)
void SetMOTD(uint32 fleetID, std::string motd)
Client * booster
Definition: FleetData.h:108
Client * leader
Definition: FleetData.h:119
unsigned __int16 uint16
Definition: eve-compat.h:48
std::string GetBCastGroupName(int8 group)
std::map< uint32, WingData > m_wingDataMap
Definition: FleetService.h:137
void SetItem(PyRep *key, PyRep *value)
SetItem adds or sets a database entry.
Definition: PyRep.cpp:713
bool AddMember(Client *pClient, uint32 fleetID, int32 wingID, int32 squadID, int8 job, int8 role, int8 booster)
uint16 typeID() const
Python list.
Definition: PyRep.h:639
#define SQUAD_ID
Definition: EVE_Defines.h:185
std::string GetSquadName(uint32 squadID)
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
void RenameSquad(uint32 squadID, std::string name)
Python long integer.
Definition: PyRep.h:261
void GetWingIDs(uint32 fleetID, std::vector< uint32 > &wingIDs)