EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Agent.cpp
Go to the documentation of this file.
1 
13 /*
14  * # Agent Logging:
15  * AGENT__ERROR
16  * AGENT__WARNING
17  * AGENT__MESSAGE
18  * AGENT__DEBUG
19  * AGENT__INFO
20  * AGENT__TRACE
21  * AGENT__DUMP
22  * AGENT__RSP_DUMP
23  */
24 
25 #include "../eve-server.h"
26 #include "../StaticDataMgr.h"
27 #include "../station/StationDataMgr.h"
28 #include "../map/MapData.h"
29 
30 #include "agents/Agent.h"
31 #include "agents/AgentDB.h"
32 #include "../Client.h"
33 #include "../fleet/FleetService.h"
34 #include "../system/SystemManager.h"
35 #include "../standing/StandingMgr.h"
36 
37 
39 : m_agentID(id)
40 {
41  m_important = false;
42  m_buttonID = 1;
43 
44  m_actions.clear();
45  m_offers.clear();
46 
47  _log(AGENT__TRACE, "Agent created for AgentID %u", id);
48 }
49 
50 
51 bool Agent::Load() {
53  sMissionDataMgr.LoadAgentOffers(m_agentID, m_offers);
54 
57 
58  _log(AGENT__TRACE, "Data Loaded for Agent %u - bl: %u, level: %u, locationID: %u, systemID: %u", \
60  return true;
61 }
62 
63 void Agent::MakeOffer(uint32 charID, MissionOffer& offer)
64 {
65  // this will be based on agent type eventually
66  uint8 misionType = Mission::Type::Courier;
67 
68  sMissionDataMgr.CreateMissionOffer(misionType, m_agentData.level, m_agentData.raceID, m_important, offer);
69 
70  /* static mission data from db
71  offer.name = cData.name;
72  offer.typeID = cData.typeID;
73  offer.bonusISK = cData.bonusISK;
74  offer.rewardISK = cData.rewardISK;
75  offer.bonusTime = cData.bonusTime;
76  offer.important = cData.important;
77  offer.storyline = cData.storyline;
78  offer.missionID = cData.missionID;
79  offer.briefingID = cData.briefingID;
80  offer.rewardItemID = cData.rewardItemID;
81  offer.rewardItemQty = cData.rewardItemQty;
82  offer.courierTypeID = cData.itemTypeID;
83  offer.courierAmount = cData.itemQty;
84 
85  offer.stateID = Mission::State::Allocated;
86  offer.dateIssued = GetFileTimeNow();
87  */
88 
89  offer.characterID = charID;
90 
91  // variable mission data based on agent
92  offer.agentID = m_agentID;
97 
98  // make function to determine destination based on mission type, agent level, agent location, and some other shit.
99  //offer.destinationID = 0;
100  //offer.destinationOwnerID = 0;
101  //offer.destinationSystemID = 0;
102  //offer.destinationTypeID = 0;
103  //offer.dungeonLocationID = 0;
104  //offer.dungeonSolarSystemID = 0;
105  sMapData.GetMissionDestination(this, misionType, offer);
106  if (offer.destinationID == 0) {
107  // make error here and reset
108  sEntityList.FindClientByCharID(charID)->SendErrorMsg("Internal Server Error. Ref: ServerError 07208.");
109  //return;
110  }
111 
112  // not sure how this is checked/set
113  offer.remoteOfferable = false;
114  offer.remoteCompletable = false;
115  // same with these
116  offer.rewardLP = 0;
117  offer.acceptFee = 0;
118 
119  // create and save bookmarks for this offer.... not sure how yet.
120  offer.bookmarks = new PyList();
121 
122  //offer.dateAccepted = 0; //not set here
123  //offer.dateCompleted = 0; //not set here
124 
126  //offer.offerID = 0; //created when saving offer in db
127 
128  // update mission data as needed....
129  if (offer.typeID == Mission::Type::Courier) {
130  if ((offer.briefingID == 145156) or (offer.briefingID == 14515)) {
131  // the destination and origin need to be reversed on this mission.
132  offer.originID = offer.destinationID;
133  offer.originOwnerID = offer.destinationOwnerID;
134  offer.originSystemID = offer.destinationSystemID;
135 
139  }
140 
141  }
143 
144  // keep local copy and also add to mission data mgr
145  m_offers.emplace(charID, offer);
146  sMissionDataMgr.AddMissionOffer(charID, offer);
147 }
148 
150 {
151  std::map<uint32, MissionOffer>::iterator itr = m_offers.find(charID);
152  if (itr != m_offers.end())
153  return true;
154  return false;
155 }
156 
158 {
159  std::map<uint32, MissionOffer>::iterator itr = m_offers.find(charID);
160  if (itr != m_offers.end()) {
161  offer = itr->second;
162  return true;
163  }
164  return false;
165 }
166 
167 void Agent::GetOffer(uint32 charID, MissionOffer& offer)
168 {
169  std::map<uint32, MissionOffer>::iterator itr = m_offers.find(charID);
170  if (itr != m_offers.end()) {
171  offer = itr->second;
172  } else {
173  _log(AGENT__WARNING, "Agent::GetOffer() - offer not found for characterID %u", charID);
174  }
175 }
176 
177 /*{'FullPath': u'UI/Messages', 'messageID': 259310, 'label': u'MisMissionExpiredBody'}(u'This mission has already expired.', None, None)
178  {'FullPath': u'UI/Messages', 'messageID': 259311, 'label': u'MisNoItemsTitle'}(u'No items available', None, None)
179  {'FullPath': u'UI/Messages', 'messageID': 259312, 'label': u'MisNoItemsBody'}(u"There's nothing available at this station.", None, None)
180  {'FullPath': u'UI/Messages', 'messageID': 259313, 'label': u'MisNoShipsInCourierTitle'}(u'Cannot create courier mission', None, None)
181  {'FullPath': u'UI/Messages', 'messageID': 259314, 'label': u'MisNoShipsInCourierBody'}(u'Only packaged ships can be couriered.', None, None)
182  {'FullPath': u'UI/Messages', 'messageID': 259315, 'label': u'MisNoSuchMissionTitle'}(u'Mission not found', None, None)
183  {'FullPath': u'UI/Messages', 'messageID': 259316, 'label': u'MisNoSuchMissionBody'}(u'This mission is no longer available.', None, None)
184  {'FullPath': u'UI/Messages', 'messageID': 259317, 'label': u'MisNotAvailableBody'}(u'"This mission is no longer available"', None, None)
185  {'FullPath': u'UI/Messages', 'messageID': 259318, 'label': u'MisPackageNotHereTitle'}(u"Can't deliver package", None, None)
186  {'FullPath': u'UI/Messages', 'messageID': 259319, 'label': u'MisPackageNotHereBody'}(u'The package is not on your hangar floor.', None, None)
187  {'FullPath': u'UI/Messages', 'messageID': 259320, 'label': u'MisPilotOnBoardBody'}(u"Can't add ships with people in it in a courier mission.", None, None)
188  {'FullPath': u'UI/Messages', 'messageID': 259321, 'label': u'MisRewardLessAcceptTitle'}(u'Too unfair', None, None)
189  {'FullPath': u'UI/Messages', 'messageID': 259322, 'label': u'MisRewardLessAcceptBody'}(u'Please make the reward higher than the accept fee.', None, None)
190  {'FullPath': u'UI/Messages', 'messageID': 259323, 'label': u'MissMissionAcceptedHelpTitle'}(u'Mission Accepted', None, None)
191  {'FullPath': u'UI/Messages', 'messageID': 259325, 'label': u'MissionItemAlreadyThereTitle'}(u'Create the Mission', None, None)
192  {'FullPath': u'UI/Messages', 'messageID': 259326, 'label': u'MissionItemAlreadyThereBody'}(u'The item is already here. Are you sure you want to continue?', None, None)
193  {'FullPath': u'UI/Messages', 'messageID': 259327, 'label': u'MissionNotIssuedBody'}(u'This mission cannot be accepted.', None, None)
194  */
196 {
197  std::map<uint32, MissionOffer>::iterator itr = m_offers.find(charID);
198  if (itr != m_offers.end()) {
199  itr->second = offer;
200  MissionDB::UpdateMissionOffer(itr->second);
201  sMissionDataMgr.UpdateMissionData(charID, itr->second);
202  } else {
203  _log(AGENT__WARNING, "Agent::UpdateOffer() - offer not found for character %u", charID);
204  }
205 }
206 
208 {
209  std::map<uint32, MissionOffer>::iterator itr = m_offers.find(charID);
210  if (itr != m_offers.end()) {
211  m_offers.erase(itr);
212  } else {
213  _log(AGENT__WARNING, "Agent::RemoveOffer() - offer not found for character %u", charID);
214  }
215 }
216 
218 {
219  std::map<uint32, MissionOffer>::iterator itr = m_offers.find(charID);
220  if (itr != m_offers.end()) {
221  itr->second.stateID = Mission::State::Rejected;
222  MissionDB::UpdateMissionOffer(itr->second);
223  sMissionDataMgr.RemoveMissionOffer(charID, itr->second);
224  m_offers.erase(itr);
225  } else {
226  _log(AGENT__WARNING, "Agent::DeleteOffer() - offer not found for character %u", charID);
227  }
228 }
229 
230 
232  PyDict *res = new PyDict();
233  res->SetItemString("typeID", new PyInt(m_agentData.locationTypeID) );
234  res->SetItemString("locationID", new PyInt(m_agentData.locationID) );
235  res->SetItemString("solarsystemID", new PyInt(m_agentData.solarSystemID) );
236  return res;
237 
238  /* other location data types to put in dict for agents in space
239  * locationType
240  * coords
241  * referringAgentID
242  * shipTypeID
243  *
244  */
245 
246  /*
247  * def LocationWrapper(location, locationType = None):
248  * if locationType is None and 'locationType' in location:
249  * locationType = location['locationType']
250  * pseudoSecurityRating = cfg.solarsystems.Get(location['solarsystemID']).pseudoSecurity
251  * if pseudoSecurityRating <= 0:
252  * securityKey = '0.0'
253  * else:
254  * securityKey = str(round(pseudoSecurityRating, 1))
255  * secColor = SECURITY_COLORS[securityKey]
256  * secColorAsHtml = '#%02X%02X%02X' % (secColor[0], secColor[1], secColor[2])
257  * secWarning = '<font color=#E3170D>'
258  * secClass = util.SecurityClassFromLevel(pseudoSecurityRating)
259  * standingSvc = sm.GetService('standing')
260  * if secClass <= const.securityClassLowSec:
261  * secWarning += localization.GetByLabel('UI/Agents/LowSecWarning')
262  * elif standingSvc.GetMySecurityRating() <= -5:
263  * secWarning += localization.GetByLabel('UI/Agents/HighSecWarning')
264  * secWarning += '</font>'
265  * if 'coords' in location:
266  * x, y, z = location['coords']
267  * refAgentString = str(location['agentID'])
268  * if 'referringAgentID' in location:
269  * refAgentString += ',' + str(location['referringAgentID'])
270  * infoLinkData = ['showinfo',
271  * location['typeID'],
272  * location['locationID'],
273  * x,
274  * y,
275  * z,
276  * refAgentString,
277  * 0,
278  * locationType]
279  * else:
280  * infoLinkData = ['showinfo', location['typeID'], location['locationID']]
281  * spacePigShipType = location.get('shipTypeID', None)
282  * if spacePigShipType is not None:
283  * locationName = localization.GetByLabel('UI/Agents/Items/ItemLocation', typeID=spacePigShipType, locationID=location['locationID'])
284  * else:
285  * locationName = cfg.evelocations.Get(location['locationID']).locationName
286  * return localization.GetByLabel('UI/Agents/LocationWrapper', startFontTag='<font color=%s>' % secColorAsHtml, endFontTag='</font>', securityRating=pseudoSecurityRating, locationName=locationName, linkdata=infoLinkData, securityWarning=secWarning)
287  */
288 }
289 
291 {
292  // can this be static data created when agent is loaded? avoid creating this everytime it's called.
293  PyDict* res = new PyDict();
294  res->SetItemString("stationID", new PyInt(m_agentData.stationID) );
295  res->SetItemString("level", new PyInt(m_agentData.level) );
296 
297  // 'services' is a tuple of dicts containing data for [research], [locate], and [mission] services this agent offers
298 
299  /* for research agents....
300  * skillTypeID, skillLevel in data.skills:
301  * researchData = data.researchData
302  * researchData['rpMultiplier']
303  * researchData['skillTypeID']
304  * researchData['points'] -- current points
305  * researchData['pointsPerDay']
306  * skillTypeID, blueprintTypeID in data.researchSummary: -- for predictablePatentNames
307  */
308 
310  PyDict* research = new PyDict();
311  if (m_agentData.research) {
312  PyTuple* skill1 = new PyTuple(2);
313  skill1->SetItem(0, new PyInt(11452)); // Mechanical Engineering
314  skill1->SetItem(1, new PyInt(4));
315  PyTuple* skill2 = new PyTuple(2);
316  skill2->SetItem(0, new PyInt(11453)); //Electronic Engineering
317  skill2->SetItem(1, new PyInt(3));
318  PyList* skillList = new PyList();
319  skillList->AddItem(skill1);
320  skillList->AddItem(skill2);
321  PyDict* researchData = new PyDict();
322  researchData->SetItemString("rpMultiplier", new PyInt(2));
323  researchData->SetItemString("skillTypeID", new PyInt(11452)); // this is player research field with this agent. not sure how to make "none" yet
324  researchData->SetItemString("points", new PyInt(150));
325  researchData->SetItemString("pointsPerDay", new PyInt(30));
326  PyTuple* patent1 = new PyTuple(2);
327  patent1->SetItem(0, new PyInt(11452));
328  PyList* patentlist1 = new PyList();
329  patentlist1->AddItem(new PyInt(692));
330  patent1->SetItem(1, patentlist1);
331  PyTuple* patent2 = new PyTuple(2);
332  patent2->SetItem(0, new PyInt(11453));
333  PyList* patentlist2 = new PyList();
334  patentlist2->AddItem(new PyInt(1196));
335  patent2->SetItem(1, patentlist2);
336  PyList* patentList = new PyList();
337  patentList->AddItem(patent1);
338  patentList->AddItem(patent2);
339 
340  research->SetItemString("agentServiceType", new PyString("research"));
341  research->SetItemString("skills", skillList);
342  research->SetItemString("researchSummary", patentList);
343  research->SetItemString("researchData", researchData);
344  } else {
345  research->SetItemString("agentServiceType", PyStatic.NewNone());
346  }
347 
348  /* for location agents....
349  *
350  level Standings Time to Run Cooldown Cost Range
351  1 Any Instant/1 minute 5 minutes 1k/5k Constellation
352  2 1.0 Instant/1 minute/8 minutes 5 minutes 5k/10k/25k Region
353  3 3.0 Instant/30 seconds/4 minutes/8 minutes 15 minutes 10k/25k/50k/100k Unlimited
354  4 5.0 Instant/20 seconds/2 minutes/4 minutes 30 minutes 25k/50k/100k/250k Unlimited
355 
356  * data.frequency
357  *delayRange, delay, cost in data.delays: -- (tuple) range (system, const, region, other region), responseTime (in sec), cost
358  * data.callbackID -- bool for agent locator services being used (locator unavailable)
359  * OR
360  * data.lastUsed -- blue time?
361 
362  Once done the locator agent will send you a Notification with the location of the target when you started the search which will include the system, constellation and region as well as the station the player might be docked at. If the target is in space, no station will be listed. E.g. "The sleazebag is currently in the Bukah system, Nohshayess constellation of the Khanid region."
363  If the target is logged off, the locator agent will tell you the last known position. If the target is in Anoikis (wormhole space), the locator agent will tell you "I'm sorry, but I just can't help you with that one. I'm pretty sure O'b Haru Sen is well out of my zone of influence." - even if the agent can locate anyone in known space.
364 
365  (235843, `{[character]charID.gender -> "He", "She"} is in the {systemName} system of the {constellationName} constellation.`)
366  (235844, `{[character]charID.gender -> "He", "She"} is in the {systemName} system, {constellationName} constellation of the {regionName} region.`)
367  (235845, `{[character]charID.gender -> "He", "She"} is in your solar system.`)
368  (235846, `{[character]charID.gender -> "He", "She"} is at your station.`)
369  (235847, `{[character]charID.gender -> "He", "She"} is at {stationName} station in your solar system.`)
370  (235848, `{[character]charID.gender -> "He", "She"} is at {stationName} station in the {systemName} system.`)
371  (235849, `{[character]charID.gender -> "He", "She"} is at{stationName} station in the {systemName} system of the {constellationName} constellation.`)
372  (235850, `{[character]charID.gender -> "He", "She"} is at {stationName} station in the {systemName} system, {constellationName} constellation of {regionName} region.`)
373  (235851, `{[character]charID.gender -> "He", "She"} is in the {systemName} system.`)
374  */
375  PyDict* locate = new PyDict();
376  if (m_agentData.locator) {
377  PyTuple* sameSystem = new PyTuple(3);
378  sameSystem->SetItem(0, new PyInt(0));
379  sameSystem->SetItem(1, new PyInt(10));
380  sameSystem->SetItem(2, new PyInt(20000));
381  PyTuple* sameConst = new PyTuple(3);
382  sameConst->SetItem(0, PyStatic.NewOne());
383  sameConst->SetItem(1, new PyInt(30));
384  sameConst->SetItem(2, new PyInt(200000));
385  PyTuple* sameRegion = new PyTuple(3);
386  sameRegion->SetItem(0, new PyInt(2));
387  sameRegion->SetItem(1, new PyInt(60));
388  sameRegion->SetItem(2, new PyInt(2000000));
389  PyTuple* otherRegion = new PyTuple(3);
390  otherRegion->SetItem(0, new PyInt(3));
391  otherRegion->SetItem(1, new PyInt(120));
392  otherRegion->SetItem(2, new PyInt(20000000));
393  PyTuple* delays = new PyTuple(4);
394  delays->SetItem(0, sameSystem);
395  delays->SetItem(1, sameConst);
396  delays->SetItem(2, sameRegion);
397  delays->SetItem(3, otherRegion);
398 
399  locate->SetItemString("agentServiceType", new PyString("locate"));
400  locate->SetItemString("frequency", new PyInt(1200)); // if this is PyNone (or 0?) agent location isnt avalible (client parsed msg)
401  locate->SetItemString("delays", delays);
402  locate->SetItemString("callbackID", new PyInt(2));
403  locate->SetItemString("lastUsed", new PyInt(0));
404  } else {
405  locate->SetItemString("agentServiceType", PyStatic.NewNone());
406  }
407 
408  // for mission agents....
409  PyDict* mission = new PyDict();
410  mission->SetItemString("agentServiceType", new PyString("mission"));
411  // will need to check standings vs agent level to determine this boolean
412  mission->SetItemString("available", new PyBool(true));
413 
414  PyTuple* services = new PyTuple(3);
415  services->SetItem(0, new PyObject("util.KeyVal", research));
416  services->SetItem(1, new PyObject("util.KeyVal", locate));
417  services->SetItem(2, new PyObject("util.KeyVal", mission));
418  res->SetItemString("services", services);
419 
420  // standings info for this agent.
422  std::string msg = "Your personal standings must be ";
424  msg += " or higher toward this agent, its faction, or its corporation in order to use this agent's services.";
425  res->SetItemString("incompatible", new PyString(msg));
426 
427  /* can also use locale labelIDs for this using a tuple to define minStandings, minEffective, corpMinStandings, mainEffective, effectiveMinStandings in other msgIDs
428  * this will take char, corp, faction, agent, and some other shit into account to determine msg and data sent using the tuple system
429  // note: this is kinda hacked right now.
430  PyDict* dict = new PyDict();
431  dict->SetItemString("minStandings", new PyFloat(GetMinReqStanding(m_agentData.level)));
432  // dict->SetItemString("mainEffective", new PyFloat(GetMinReqStanding(m_agentData.level +10)));
433  PyTuple* tuple = new PyTuple(2);
434  tuple->SetItem(0, new PyInt(235465));
435  tuple->SetItem(1, dict);
436  res->SetItemString("incompatible", tuple);
437  */
438 
439  if (is_log_enabled(AGENT__RSP_DUMP)) {
440  _log(AGENT__RSP_DUMP, "Agent::GetInfoServiceDetails() Dump:" );
441  res->Dump(AGENT__RSP_DUMP, " ");
442  }
443 
444  return new PyObject("util.KeyVal", res);
445 }
446 
447 std::string Agent::GetMinReqStanding(uint8 level)
448 {
449  switch(level) {
450  // these are agentCorp -> char
451  case 1: return "-2.0";
452  case 2: return "1.0";
453  case 3: return "3.0";
454  case 4: return "5.0";
455  case 5: return "7.0";
456  //these are agent/corp/faction -> char
457  case 11: return "-1.0";
458  case 12: return "1.5";
459  case 13: return "3.5";
460  case 14: return "5.5";
461  case 15: return "7.5";
462  };
463 
464  return "-0.5";
465 }
466 
467 
469 {
470  //(130431, 'Thank you. Be careful out there, those logs must <b>not</b> fall into the wrong hands.')
471 
472  switch (MakeRandomInt(1, 13)) {
473  case 1: return 236738; // `Very well then, get going.`)
474  case 2: return 236739; // `Ok, hurry up will you.`)
475  case 3: return 236740; // `Good good, now get out there and give me some results.`)
476  case 4: return 236741; // `Thank you, and good luck.`)
477  case 5: return 236742; // `Thanks, I really appreciate it.`)
478  case 6: return 236743; // `Have fun!`)
479  case 7: return 236744; // `Now be careful out there, you hear me?`)
480  case 8: return 236745; // `Stay alive, friend.`)
481  case 9: return 236721; // `You have a long and prosperous future within {[npcOrganization]agentFactionID.name}, {[character]player.name}.`)
482  case 10: return 236746; // `I knew I could count on you.`)
483  case 11: return 236747; // `Great. I know I can trust you with this, mate.`)
484  case 12: return 236749; // `Wonderful. I expect a quick result with you on the job.`)
485  case 13: return 135877; // `I knew we could count on you, {[character]player.name}. Please hurry. ')
486  }
487  return 236745; // `Stay alive, friend.`)
488 }
489 
491 {
492  switch (MakeRandomInt(1, 14)) {
493  case 1: return 236693; // `It's your loss.`)
494  case 2: return 236695; // `Son, I am disappoint.`)
495  case 3: return 236793; // `Too bad, I'll try to find someone else then for that job.`)
496  case 4: return 236794; // `Bah, that mission wasn't that bad. Oh well, wait a bit and I'll come up with something else.`)
497  case 5: return 236796; // `Well, don't expect me to come up with something as good later on.`)
498  case 6: return 236797; // `Your wayward ways displease me.`)
499  case 7: return 236801; // `It's your loss.`)
500  case 8: return 236802; // `Your wayward ways displease me, young one.`)
501  case 9: return 236843; // `See if I offer this to you again... seriously try it.`)
502  case 10: return 130895; // 'Fine. Be that way. Asshole.')
503  case 11: return 133432; // 'Too bad, {[character]player.name}. You could have made some serious points with the powers-that-be on this one. ')
504  case 12: return 135858; // 'I'm sorry to hear that, {[character]player.name}. I'll find someone else, I suppose.')
505  case 13: return 135895; // 'Lollygagger')
506  case 14: return 136322; // 'I see. Easy money's not good enough, eh? Huh. ')
507  }
508  //(137499, 'Fine, I’ll get someone more capable. A word of advice: don’t repeat this display of cowardice and uselessness. We don’t tolerate such things in the Republic. ')
509  return 137499;
510 }
511 
513 {
514  switch (MakeRandomInt(1, 20)) {
515  case 1: return 236750; // `Fabulous. I couldn't have asked for a better man for the job.`)
516  case 2: return 236751; // `Not bad. Get back to me later for another assignment will you?`)
517  case 3: return 236752; // `Nice work. I'm starting to like your style.`)
518  case 4: return 236753; // `Thanks, your services to {[npcOrganization]agentCorpID.name} is duly appreciated.`)
519  case 5: return 236754; // `Thank you. Your accomplishment has been noted and saved into our database.`)
520  case 6: return 236755; // `Excellent job!`)
521  case 7: return 236756; // `Thanks, I really appreciate your help.`)
522  case 8: return 236757; // `I won't forget this.`)
523  case 9: return 236758; // `I'm grateful for your assistance.`)
524  case 10: return 236759; // `You have my gratitude.`)
525  case 11: return 236760; // `Thank you very much, I really appreciate it.`)
526  case 12: return 236761; // `Well done! Take this reward and my gratitude as well.`)
527  case 13: return 236762; // `It's a pleasure doing business with you.`)
528  case 14: return 236763; // `Excellent work! Care for another assignment?`)
529  case 15: return 236764; // `I look forward to your next visit.`)
530  case 16: return 236765; // `Again you finish the job right on time. Keep this up and I'll probably get a promotion.`)
531  case 17: return 236766; // `I thank you from the bottom of my heart.`)
532  case 18: return 236767; // `If only I had more excellent pilots like you, {[character]player.name} ...`)
533  case 19: return 236768; // `Your talents as a pilot never cease to amaze me. Keep up the good work!`)
534  case 20: return 139398; // 'I knew you were the right pilot for the job.')
535  }
536  return 236758; // `I'm grateful for your assistance.`)
537 }
538 
539 //(235999, `You have failed the mission I gave you. I am disappointed in you. I was hoping for a little more competence.`)
540 
542 {
543  //(236846, `Quitters never win.`)
544  return 236846;
545 }
546 
548 {
549  switch (MakeRandomInt(1, 6)) {
550  case 1: return 236682; // `I’m sorry pilot, but you do not have the required standings to receive any missions from me. You will need to raise your standings by doing missions for lower-ranked agents. Use the Agent Finder to locate agents that are available to you.`)
551  case 2: return 236691; // `I’m sorry pilot, but you do not have the required standings to receive any missions from me. You will need to raise your standings by doing missions for lower-ranked agents. Use the Agent Finder to locate agents that are available to you.`)
552  //case 1: return 236708; // `Trial account users cannot access agents of level 3 or higher. Either use your map settings to find a level 1 or level 2 agent, or consider purchasing an EVE subscription if you wish to access higher-level content.`)
553  case 3: return 236785; // `What planet were you born on? Check your standings next time or I'll drill a hole in you.`)
554  case 4: return 236787; // `Have you even bothered to check your standings.`)
555  case 5: return 236775; // `Hello, {[character]player.name}. I was given the assignment of handing out a valuable item to loyal supporters of {[npcOrganization]agentFactionID.name}. If you know of someone who has proven him or herself time and time again for {[npcOrganization]agentFactionID.nameWithArticle} then point that person to me and perhaps we can come to an 'arrangement' ...<br><br>You on the other hand do not meet my requirements or have already received my offer.`)
556  case 6: return 236853; // `I’m sorry pilot, but you do not have the required standings to receive any missions from me. You will need to raise your standings by doing missions for lower-ranked agents. Use the Agent Finder to locate agents that are available to you.`)
557  }
558  return 236853; // `I’m sorry pilot, but you do not have the required standings to receive any missions from me. You will need to raise your standings by doing missions for lower-ranked agents. Use the Agent Finder to locate agents that are available to you.`)
559 }
560 
561 
562 void Agent::UpdateStandings(Client* pClient, uint8 eventID, bool important/*false*/)
563 {
564  /*
565  [PyAddress Broadcast: broadcastType='charid', idType='OnStandingsModified']
566  Payload:
567  [NotificationStream Tuple01]
568  [PyTuple 1 items]
569  [PyList 2 items]
570  [PyList 5 items]
571  [PyInt 3013251] fromID
572  [PyInt 91576239] toID
573  [PyFloat 0,00768598434114595] change
574  [PyFloat -1] minAbs
575  [PyFloat 1] maxAbs
576  */
577  Character* pChar = pClient->GetChar().get();
578  uint32 charID = pChar->itemID();
579 
580  float charStanding = StandingDB::GetStanding(m_agentID, charID);
582  float standing = EvEMath::Agent::EffectiveStanding(charStanding, bonus);
584  float newStanding = EvEMath::Agent::Efficiency(m_agentData.level, quality); // 0.018 to 0.38
585  SystemManager* pSysMgr = sEntityList.FindOrBootSystem(m_agentData.solarSystemID);
586  if (pSysMgr != nullptr)
587  newStanding *= pSysMgr->GetSecValue(); // 0.0018 to .76
588 
589  //newStanding = EvEMath::Agent::AgentStandingIncrease(standing, (newStanding /10)); -- this isnt used.
590  newStanding = EvEMath::Agent::MissionStandingIncrease(newStanding, pChar->GetSkillLevel(EvESkill::Social));
591  newStanding /= 8;
592 
593  newStanding *= sConfig.standings.BaseMissionMultiplier;
594 
595  if (important)
596  newStanding *= sConfig.standings.ImportantMissionBonus;
597 
598  std::string msg = "Status Change for Mission ";
599  switch (eventID) {
601  msg += "failed ";
602  newStanding *= sConfig.standings.MissionFailedRollback;
603  } break;
605  msg += "expired ";
606  newStanding *= sConfig.standings.MissionOfferExpired;
607  } break;
609  msg += "completion bonus ";
610  newStanding *= sConfig.standings.MissionBonus;
611  } break;
613  msg += "completion ";
614  newStanding *= sConfig.standings.MissionCompleted;
615  } break;
617  msg += "decline ";
618  // test for mission declined in last 4 hours
619  //newStanding *= sConfig.standings.MissionDeclined;
620  } break;
622  msg += "failure ";
623  newStanding *= sConfig.standings.MissionFailure;
624  } break;
625 
626  msg += "from ";
627  msg += m_agentData.name;
628  }
629 
630  if (pClient->InFleet() and (newStanding > 0)) {
631  float fleetStanding = newStanding * sConfig.standings.FleetMissionMultiplier;
632  newStanding -= (fleetStanding /2); // live does half, but mission acceptor will get more here.
633  // shared mission standings are from agent to character only.
634  std::vector<Client*> clientVec;
635  sFltSvc.GetFleetClientsInSystem(pClient, clientVec);
636  for (auto cur : clientVec) {
637  sStandingMgr.UpdateStandings(m_agentID, cur->GetCharacterID(), eventID, fleetStanding, msg);
638  PyTuple* agent = new PyTuple(5);
639  agent->SetItem(0, new PyInt(m_agentID));
640  agent->SetItem(1, new PyInt(cur->GetCharacterID()));
641  agent->SetItem(2, new PyFloat(fleetStanding));
642  agent->SetItem(3, new PyInt(-1));
643  agent->SetItem(4, PyStatic.NewOne());
644  PyList* list = new PyList();
645  list->AddItem(agent);
646  PyTuple* payload = new PyTuple(1);
647  payload->SetItem(0, list);
648  cur->SendNotification("OnStandingsModified", "charid", payload, false);
649  // fleet will share corp standings on some missions. fix later.
650  }
651  }
652 
653  sStandingMgr.UpdateStandings(m_agentID, charID, eventID, newStanding, msg);
654  sStandingMgr.UpdateStandings(m_agentData.corporationID, charID, eventID, newStanding * sConfig.standings.ACorp2CharMissionMultiplier, msg);
655  sStandingMgr.UpdateStandings(m_agentData.factionID, charID, eventID, newStanding * sConfig.standings.AFaction2CharMissionMultiplier, msg);
656 
657  if (IsPlayerCorp(pClient->GetCorporationID())) {
658  sStandingMgr.UpdateStandings(m_agentID, pClient->GetCorporationID(), eventID, newStanding * sConfig.standings.Agent2PCorpMissionMultiplier, msg);
659  sStandingMgr.UpdateStandings(m_agentData.corporationID, pClient->GetCorporationID(), eventID, newStanding * sConfig.standings.ACorp2PCorpMissionMultiplier, msg);
660  sStandingMgr.UpdateStandings(m_agentData.factionID, pClient->GetCorporationID(), eventID, newStanding * sConfig.standings.AFaction2PCorpMissionMultiplier, msg);
661  }
662 
663  PyTuple* agent = new PyTuple(5);
664  agent->SetItem(0, new PyInt(m_agentID));
665  agent->SetItem(1, new PyInt(charID));
666  agent->SetItem(2, new PyFloat(newStanding));
667  agent->SetItem(3, new PyInt(-1));
668  agent->SetItem(4, PyStatic.NewOne());
669  PyTuple* corp = new PyTuple(5);
670  corp->SetItem(0, new PyInt(m_agentData.corporationID));
671  corp->SetItem(1, new PyInt(charID));
672  corp->SetItem(2, new PyFloat(newStanding /4));
673  corp->SetItem(3, new PyInt(-1));
674  corp->SetItem(4, PyStatic.NewOne());
675  PyTuple* faction = new PyTuple(5);
676  faction->SetItem(0, new PyInt(m_agentData.factionID));
677  faction->SetItem(1, new PyInt(charID));
678  faction->SetItem(2, new PyFloat(newStanding /8));
679  faction->SetItem(3, new PyInt(-1));
680  faction->SetItem(4, PyStatic.NewOne());
681  PyList* list = new PyList();
682  list->AddItem(agent);
683  list->AddItem(corp);
684  list->AddItem(faction);
685  PyTuple* payload = new PyTuple(1);
686  payload->SetItem(0, list);
687 
688  if (is_log_enabled(STANDING__RSPDUMP)) {
689  _log(STANDING__RSPDUMP, "Agent::UpdateStandings RSP:" );
690  payload->Dump(STANDING__RSPDUMP, " ");
691  }
692 
693  pClient->SendNotification("OnStandingsModified", "charid", payload, false); // i *think* this is unsequenced
694 }
695 
696 void Agent::SendMissionUpdate(Client* pClient, std::string action)
697 {
698  if (pClient == nullptr)
699  return;
700  //OnAgentMissionChange(action, agentID, tutorialID)
701  /*
702  agentMissionOffered = 'offered'
703  agentMissionOfferAccepted = 'offer_accepted'
704  agentMissionOfferDeclined = 'offer_declined'
705  agentMissionOfferExpired = 'offer_expired'
706  agentMissionOfferRemoved = 'offer_removed'
707  agentMissionAccepted = 'accepted'
708  agentMissionDeclined = 'declined'
709  agentMissionCompleted = 'completed'
710  agentTalkToMissionCompleted = 'talk_to_completed'
711  agentMissionQuit = 'quit'
712  agentMissionResearchUpdatePPD = 'research_update_ppd'
713  agentMissionResearchStarted = 'research_started'
714  agentMissionProlonged = 'prolong'
715  agentMissionReset = 'reset'
716  agentMissionModified = 'modified' - force agent convo
717  agentMissionFailed = 'failed'
718  */
719 
720  PyTuple* payload = new PyTuple(3);
721  payload->SetItem(0, new PyString(action));
722  payload->SetItem(1, new PyInt(m_agentID));
723  payload->SetItem(2, PyStatic.NewNone()); // NOTE if we ever get tutorials working, this will need to be fixed.
724  pClient->SendNotification("OnAgentMissionChange", "charid", payload, false); // i *think* this is unsequenced
725 }
726  //specific to the calling action
727  //OnInteractWith(agentID) (force agent convo)
728 
729  /*
730  * Level 1 = always available
731  * Level 2 = +1.00 standing
732  * Level 3 = +3.00 standing
733  * Level 4 = +5.00 standing
734  * Level 5 = +7.00 standing
735  * (235462, 'Your personal standings must be -1.9 or higher toward this agent, its faction, or its corporation in order to use this agent's services.')
736  * (235463, 'Your personal standings must be -1.9 or higher toward this agent, its faction, and its corporation in order to use this agent's services. Additionally, you need a minimum effective standing to this agent's corp of at least {[numeric]corpMinStandings, decimalPlaces=1} , as well as personal standing of at least {[numeric]effectiveMinStandings, decimalPlaces=1} to this agent's faction, corp, or to the agent in order to use this agent's services.')
737  * (235464, 'Your personal standings must be -1.9 or higher toward this agent, its faction, and its corporation in order to use this agent's services. Additionally, you need a minimum effective standing of at least {[numeric]minStandings, decimalPlaces=1} to this agent's faction, corp, or to the agent in order to use this agent's services.')
738  * (235465, 'Your effective personal standings must be {[numeric]minStandings, decimalPlaces=1} or higher toward this agent, its faction, or its corporation in order to use this agent's services')
739  * (235466*, 'Your effective personal standings must be {[numeric]minEffective, decimalPlaces=1} or higher toward this agent's corporation in order to use this agent, as well as an effective personal standing of {[numeric]mainEffective, decimalPlaces=1} or higher toward this agent, its faction, or its corporation in order to use this agent's services.')
740  * (235467, 'This agent can only be used through a direct referral.')
741  */
742 
744 {
746  return true;
747  if (m_agentData.level == 1)
749  return true;
750 
751  Character* pChar = pClient->GetChar().get();
752  uint32 charID = pChar->itemID();
753  uint8 sConn = pChar->GetSkillLevel(EvESkill::Connections);
754  uint8 sDiplo = pChar->GetSkillLevel(EvESkill::Diplomacy);
756  float charStanding = StandingDB::GetStanding(m_agentID, charID);
757  float bonus = EvEMath::Agent::GetStandingBonus(charStanding, m_agentData.factionID, sConn, sDiplo, sCrim);
758  float standing = EvEMath::Agent::EffectiveStanding(charStanding, bonus);
759 
760  float facChr = StandingDB::GetStanding(m_agentData.factionID, charID);
761  float corpChr = StandingDB::GetStanding(m_agentData.corporationID, charID);
762  float charChr = StandingDB::GetStanding(m_agentID, charID);
763  float facBonus = EvEMath::Agent::GetStandingBonus(facChr, m_agentData.factionID, sConn, sDiplo, sCrim);
764  float corpBonus = EvEMath::Agent::GetStandingBonus(corpChr, m_agentData.factionID, sConn, sDiplo, sCrim);
765  float charBonus = EvEMath::Agent::GetStandingBonus(charChr, m_agentData.factionID, sConn, sDiplo, sCrim);
766 
767  if (facBonus > 0.0f)
768  facChr = (1.0 - (1.0 - facChr / 10.0) * (1.0 - facBonus / 10.0)) * 10.0;
769  if (corpBonus > 0.0f)
770  corpChr = (1.0 - (1.0 - corpChr / 10.0) * (1.0 - corpBonus / 10.0)) * 10.0;
771  if (charBonus > 0.0f)
772  charChr = (1.0 - (1.0 - charChr / 10.0) * (1.0 - charBonus / 10.0)) * 10.0;
773 
774  float m = (m_agentData.level - 1) * 2.0f - 1.0f;
775 
776  _log(AGENT__DEBUG, "%s(%u) CanUseAgent() - charSkills(con:%u,dip:%u,cri:%u), stand(%f, %f, %f)",\
777  m_agentData.name.c_str(), m_agentID, sConn, sDiplo, sCrim, charStanding, bonus, standing);
778  _log(AGENT__DEBUG, "%s(%u) CanUseAgent() - standings(fac:%u,crp:%u,chr:%u), bonus(%f, %f, %f) - m=%f", \
779  m_agentData.name.c_str(), m_agentID, facChr, corpChr, charChr, facBonus, corpBonus, charBonus, m);
780 
781  if ((EvE::max(facChr, corpChr, charChr) >= m ) and (EvE::min(facChr, corpChr, charChr) > -2.0f)) {
782  if ((m_agentData.typeID == Agents::Type::Research) and (corpChr < m - 2.0f))
783  return false;
784  return true;
785  }
786 
787  return false;
788 }
789 
790 
791 
792 /* mission errata....
793  *
794  * courier missions:
795  * L1 missions will keep you within the agent's constellation, up to 450 m3
796  * L2/L3 will possibly send you to a neighboring constellation,4-6km3
797  * L4 missions will always send you to a neighboring constellation. 8km3
798  * If a Distribution mission has an item as a reward instead of ISK, then the item will appear in your personal hangar at the agent's station
799  *
800  * mining missions:
801  * Mining missions require you to mine an asteroid or set of asteroids in a mission space, usually until the asteroids are depleted, and bring the ore back to the agent's station.
802  * There is a risk of combat in mining missions, though the hostiles that show up tend to be much weaker than hostiles found in security missions.
803  * It is advisable to have some offensive capability (like a set of combat drones) or have a strong enough tank that you can ignore any hostiles that show up and start shooting at you.
804  * The mission may require you to mine more ore than can fit in your cargohold; this is typical of mining missions.
805  * L1 missions will require mining up to 2km3 of ore,
806  * L2 up to 6km3 of ore,
807  * L3 up to 9km3 of ore or 10km3 of ice,
808  * L4 up to 45km3 of ore, 20km3 of ice or 5km3 gas.
809  *
810  * encounter missions:
811  * Level 1 is where most new players start. Most, if not all, level 1 missions can be done in a basic frigate, Only the most basic piloting skills are required.
812  * Level 2 mining missions can be done in a cruiser or in a destroyer piloted by a more skilled pilot. These missions generally expect that you are continually improving your piloting skills and learning how to fit out new ships.
813  * Level 3 missions require a battlecruiser. These missions go faster if you have trained for better ships and at least some Tech 2 fittings.
814  * Level 4 missions require a Battleship with full T2 tank fitted. These missions can be time-consuming, but they offer large rewards.
815  * Level 5 missions are designed for groups of players or capital ship and are exclusively located in Low Security space.
816  */
817 
818 
819 /* agent errata...
820  *
821  * char mission history and current offers in agtOffers
822  * notify:OnIncomingAgentMessage(agentID, message)
823  * OnIncomingTransmission(self, transmission, isAgentMission = 0, *args)
824  * transmission.header, transmission.text, transmission.icon
825  * if transmission.header.startswith('[d]'):
826  * transmission.header = transmission.header[3:]
827  * self.delayedTransmission = transmission
828  *
829  * (237604, `You can only do this on MASTER or LOCAL server`)
830  * (235975, `I am in need of your services, {[character]notification_receiverID.name, linkify}, for a very special mission.`)
831  * (235976, `I found {[character]charID.name, linkify} for you`)
832  *
833  * The forumla for LP reward is:
834  * LP reward = (1.6288 - System security) × Base LP
835  *
836  *
837  **** see also shit in common/utils/evemath.* *******
838  * Agent_Effective_Quality = Agent_Quality + (5 * Negotiation_Skill_Level) + Round_Down(AgentPersonalStanding)
839  *
840  * Research_Points_Per_Day = Multiplier * ((1 + (Agent_Effective_Quality / 100)) * ((Core_Skill + Agent_Skill) ^ 2))
841  *
842  * RP/Day = ((Agent Level + Your Skill)^2 * (1 + (20 + 5 * Negotiation Skill + Agent Effective Standing) / 100)) * Multiplier
843  * ((Agent Skill + Your Skill)^2 * (1 + Effective Quality / 100)) * Area Bonus
844  */
static float GetStanding(uint32 fromID, uint32 toID)
Definition: StandingDB.cpp:142
uint16 m_buttonID
Definition: Agent.h:79
uint16 locationTypeID
Definition: EVE_Agent.h:21
#define sConfig
A macro for easier access to the singleton.
unsigned __int8 uint8
Definition: eve-compat.h:46
void SendNotification(const PyAddress &dest, EVENotificationStream &noti, bool seq=true)
Definition: Client.cpp:2245
bool m_important
Definition: Agent.h:77
void RemoveOffer(uint32 charID)
Definition: Agent.cpp:207
std::string GetMinReqStanding(uint8 level)
Definition: Agent.cpp:447
#define _log(type, fmt,...)
Definition: logsys.h:124
uint32 locationID
Definition: EVE_Agent.h:25
Python string.
Definition: PyRep.h:430
uint32 agentID
Definition: EVE_Missions.h:42
Python's dictionary.
Definition: PyRep.h:719
uint32 GetStandingsRsp(uint32 charID)
Definition: Agent.cpp:547
std::string name
Definition: EVE_Agent.h:29
double min(double x, double y)
Definition: misc.h:95
PyObject * GetInfoServiceDetails()
Definition: Agent.cpp:290
float EffectiveQuality(int8 AgentQuality, uint8 NegotiationSkillLevel, float AgentPersonalStanding)
Definition: EvEMath.cpp:150
uint32 GetDeclineRsp(uint32 charID)
Definition: Agent.cpp:490
std::map< uint32, MissionOffer > m_offers
Definition: Agent.h:73
std::map< uint16, AgentActions > m_actions
Definition: Agent.h:74
Python floating point number.
Definition: PyRep.h:292
int32 GetCorporationID() const
Definition: Client.h:123
uint32 stationID
Definition: EVE_Agent.h:24
#define sEntityList
Definition: EntityList.h:208
int8 quality
Definition: EVE_Agent.h:15
uint32 characterID
Definition: EVE_Missions.h:45
static void LoadAgentSkills(uint32 agentID, std::map< uint16, uint8 > &data)
Definition: AgentDB.cpp:80
uint8 level
Definition: EVE_Agent.h:16
#define sStandingMgr
Definition: StandingMgr.h:52
uint16 rewardLP
Definition: EVE_Missions.h:35
CharacterRef GetChar() const
Definition: Client.h:164
Python tuple.
Definition: PyRep.h:567
void MakeOffer(uint32 charID, MissionOffer &offer)
Definition: Agent.cpp:63
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
bool HasMission(uint32 charID)
Definition: Agent.cpp:149
uint16 typeID
Definition: EVE_Agent.h:20
void AddItem(PyRep *i)
Definition: PyRep.h:701
bool locator
Definition: EVE_Agent.h:13
Python boolean.
Definition: PyRep.h:323
#define is_log_enabled(type)
Definition: logsys.h:78
uint32 originSystemID
Definition: EVE_Missions.h:50
#define sFltSvc
Definition: FleetService.h:147
uint32 destinationSystemID
Definition: EVE_Missions.h:53
uint32 briefingID
Definition: EVE_Missions.h:43
bool InFleet()
Definition: Client.h:142
float MissionStandingIncrease(float BaseMissionIncrease, uint8 YourSocialSkillLevel)
Definition: EvEMath.cpp:165
Python object.
Definition: PyRep.h:826
bool research
Definition: EVE_Agent.h:14
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
Python integer.
Definition: PyRep.h:231
float Efficiency(uint8 AgentLevel, int8 AgentQuality)
Definition: EvEMath.cpp:170
float GetSecValue()
uint32 factionID
Definition: EVE_Agent.h:28
void UpdateStandings(Client *pClient, uint8 eventID, bool important=false)
Definition: Agent.cpp:562
#define PyStatic
Definition: PyRep.h:1209
X * get() const
Definition: RefPtr.h:213
double expiryTime
Definition: EVE_Missions.h:58
uint32 corporationID
Definition: EVE_Agent.h:22
#define IsPlayerCorp(itemID)
Definition: EVE_Defines.h:241
#define sMissionDataMgr
Definition: Client.h:66
bool CanUseAgent(Client *pClient)
Definition: Agent.cpp:743
uint32 GetCompleteRsp(uint32 charID)
Definition: Agent.cpp:512
unsigned __int32 uint32
Definition: eve-compat.h:50
bool remoteOfferable
Definition: EVE_Missions.h:28
double GetFileTimeNow()
Definition: utils_time.cpp:84
uint32 destinationOwnerID
Definition: EVE_Missions.h:52
static void LoadAgentData(uint32 agentID, AgentData &data)
Definition: AgentDB.cpp:20
void GetOffer(uint32 charID, MissionOffer &offer)
Definition: Agent.cpp:167
PyDict * GetLocationWrap()
Definition: Agent.cpp:231
int64 MakeRandomInt(int64 low, int64 high)
Generates random integer from interval [low; high].
Definition: misc.cpp:109
int64 max(int64 x, int64 y=0)
Definition: misc.h:103
float GetStandingBonus(float fromStanding, uint32 fromFactionID, uint8 ConnectionsSkillLevel, uint8 DiplomacySkillLevel, uint8 CriminalConnectionsSkillLevel)
Definition: EvEMath.cpp:180
void DeleteOffer(uint32 charID)
Definition: Agent.cpp:217
uint32 GetQuitRsp(uint32 charID)
Definition: Agent.cpp:541
int8 GetSkillLevel(uint16 skillTypeID, bool zeroForNotInjected=true) const
Definition: Character.cpp:575
float EffectiveStanding(float YourStanding, double standingBonus)
Definition: EvEMath.cpp:155
uint8 raceID
Definition: EVE_Agent.h:17
uint32 solarSystemID
Definition: EVE_Agent.h:23
bool Load()
Definition: Agent.cpp:51
static void CreateOfferID(MissionOffer &data)
Definition: MissionDB.cpp:42
uint32 GetAcceptRsp(uint32 charID)
Definition: Agent.cpp:468
Agent(uint32 id)
Definition: Agent.cpp:38
void SendMissionUpdate(Client *pClient, std::string action)
Definition: Agent.cpp:696
bool remoteCompletable
Definition: EVE_Missions.h:29
uint32 destinationID
Definition: EVE_Missions.h:51
void UpdateOffer(uint32 charID, MissionOffer &offer)
Definition: Agent.cpp:195
std::map< uint16, uint8 > m_skills
Definition: Agent.h:72
uint32 acceptFee
Definition: EVE_Missions.h:56
AgentData m_agentData
Definition: Agent.h:70
uint8 bloodlineID
Definition: EVE_Agent.h:19
uint32 originID
Definition: EVE_Missions.h:48
Python list.
Definition: PyRep.h:639
static void UpdateMissionOffer(MissionOffer &data)
Definition: MissionDB.cpp:76
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
PyList * bookmarks
Definition: EVE_Missions.h:63
uint32 originOwnerID
Definition: EVE_Missions.h:49
const uint32 m_agentID
Definition: Agent.h:69
#define sMapData
Definition: MapData.h:54