EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
AttributeMap.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Update: Captnoord - Juni 2010
25  Rewrite: Allan - 6Feb17
26 */
27 
28 #include "eve-server.h"
29 
30 #include "Client.h"
31 #include "EntityList.h"
32 #include "StaticDataMgr.h"
33 #include "inventory/AttributeMap.h"
35 
36 
37 /*
38  * ATTRIBUTE__ADD
39  * ATTRIBUTE__CHANGE
40  * ATTRIBUTE__DELETE
41  * ATTRIBUTE__MISSING
42  * ATTRIBUTE__ERROR
43  * ATTRIBUTE__WARNING
44  * ATTRIBUTE__INFO
45  */
46 
47 
49 : mItem(item)
50 {
51  mAttributes.clear();
52 }
53 
55 {
56  //mAttributes.clear();
57 }
58 
59 
60 bool AttributeMap::Load(bool reset/*false*/) {
61  if (reset) {
62  // this will allow total clearing of attribs to eliminate the necessity of 'removing' effects
63  mAttributes.clear();
64  }
65  /* First, we copy default attributes values from our itemType, loaded into memObj when type is loaded */
66  // (except char ability scores...dunno why yet)
68 
69  // check for temp items. they arent saved to db
70  if (!IsTempItem(mItem.itemID()) and !IsNPC(mItem.itemID())) {
71  /* load saved attribs from the db, if any, to update the defaults with items current (saved) values*/
72  DBQueryResult res;
73  if (IsCharacterID(mItem.itemID())) {
74  if (!sDatabase.RunQuery(res, "SELECT attributeID, valueInt, valueFloat FROM chrCharacterAttributes WHERE charID=%u", mItem.itemID()))
75  _log(DATABASE__ERROR, "AttributeMap", "Error in db load query: %s", res.error.c_str());
76  } else {
77  if (!sDatabase.RunQuery(res, "SELECT attributeID, valueInt, valueFloat FROM entity_attributes WHERE itemID=%u", mItem.itemID()))
78  _log(DATABASE__ERROR, "AttributeMap", "Error in db load query: %s", res.error.c_str());
79  }
80 
81  DBResultRow row;
82  EvilNumber value;
83  while (res.GetRow(row)) {
84  if (row.IsNull(1)) {
85  if (row.IsNull(2)) {
86  value = EvilZero;
87  } else {
88  value = row.GetDouble(2);
89  }
90  } else {
91  value = row.GetInt64(1);
92  }
93  SetAttribute(row.GetUInt(0), value, false);
94  }
95  }
96  /* item now has it's own attribute map, and is deleted when item object is destroyed or reset */
97  if (is_log_enabled(ATTRIBUTE__INFO))
98  _log(ATTRIBUTE__INFO, "AttributeMap::Load() Loaded %u attribs for %s.", mAttributes.size(), mItem.name());
99  return true;
100 }
101 
103  return Save();
104 }
105 
117  if (IsStaticItem(mItem.itemID()))
118  return true;
119 
120  bool save(false);
121  std::vector<Inv::AttrData> attribs;
122  attribs.clear();
123  AttrMapItr itr = mAttributes.begin(), end = mAttributes.end();
124  if (IsCharacterID(mItem.itemID())) {
125  for (; itr != end; ++itr) {
126  switch (itr->first) {
127  case AttrCharisma:
128  case AttrIntelligence:
129  case AttrMemory:
130  case AttrPerception:
131  case AttrWillpower:
137  case AttrCharismaBonus:
139  case AttrMemoryBonus:
140  case AttrPerceptionBonus:
141  case AttrWillpowerBonus: {
142  if (itr->second == EvilZero)
143  continue;
144  Inv::AttrData data = Inv::AttrData();
145  data.itemID = mItem.itemID();
146  data.attrID = itr->first;
147  data.type = false;
148  data.valueInt = itr->second.get_int();
149  attribs.push_back(data);
150  }
151  }
152  }
153  } else {
154  bool skill(false), damage(false), owner(false), module(false);
155  switch (mItem.categoryID()) {
156  case EVEDB::invCategories::Asteroid: // asteroids and blueprints are NOT saved here
158  return false;
159  } break;
160  case EVEDB::invCategories::Ship: { // ship attribs saved in shipItem, not here.
161  return true;
162  } break;
163  case EVEDB::invCategories::Skill: { // save SP, Level and times for skills
164  skill = true;
165  } break;
166  case EVEDB::invCategories::Celestial: // save all attribs for these
172  owner = true;
173  } break;
174  case EVEDB::invCategories::Module: // save online state for modules
175  module = true; // we're falling thru on purpose here to save module damage
176  case EVEDB::invCategories::Charge: // remember, crystals and lenses are charges, too.
177  case EVEDB::invCategories::Drone: // this may need more. check once system is working
179  damage = true;
180  } break;
181  }
182 
183  for (; itr != end; ++itr) {
184  save = false;
185  if (skill)
186  if ((itr->first == AttrSkillPoints)
187  or (itr->first == AttrSkillLevel))
188  save = true;
189  if (damage)
190  if (itr->first == AttrDamage)
191  save = true;
192  if (module)
193  if (itr->first == AttrOnline)
194  save = true;
195  if (save or owner) {
196  Inv::AttrData data = Inv::AttrData();
197  data.itemID = mItem.itemID();
198  data.attrID = itr->first;
199  if (itr->second.isInt()) {
200  data.type = false;
201  data.valueInt = itr->second.get_int();
202  } else {
203  data.type = true;
204  data.valueFloat = itr->second.get_double();
205  }
206  attribs.push_back(data);
207  }
208  }
209  }
210 
211  if (!attribs.empty())
213  return true;
214 }
215 
216 
217 void AttributeMap::SetAttribute(uint16 attrID, EvilNumber& num, bool notify/*true*/)
218 {
219  if (num.isNaN() or num.isInf()) {
220  _log(ATTRIBUTE__ERROR, "AttributeMap::SetAttribute() - Something sent NaN or Inf for Attr %u on %s(%u). Returning without modifying.",\
221  attrID, mItem.name(), mItem.itemID());
222  EvE::traceStack();
223  //ResetAttribute(attrID, notify);
224  return;
225  }
226  AttrMapItr itr = mAttributes.find(attrID);
227  if (itr == mAttributes.end()) {
228  mAttributes.emplace(attrID, num);
229  if (notify) {
230  Add(attrID, num);
231  } else if (is_log_enabled(ATTRIBUTE__MISSING)) {
232  if (num.isFloat()) {
233  _log(ATTRIBUTE__MISSING, "Attribute %u not in map. Adding as %.2f for %s(%u)", \
234  attrID, num.get_float(), mItem.name(), mItem.itemID());
235  } else {
236  _log(ATTRIBUTE__MISSING, "Attribute %u not in map. Adding as %li for %s(%u)", \
237  attrID, num.get_int(), mItem.name(), mItem.itemID());
238  }
239  } else if (is_log_enabled(ATTRIBUTE__ADD)) {
240  if (num.isFloat()) {
241  _log(ATTRIBUTE__ADD, "Attribute %u not in map. Adding as %.2f for %s(%u)", \
242  attrID, num.get_float(), mItem.name(), mItem.itemID());
243  } else {
244  _log(ATTRIBUTE__ADD, "Attribute %u not in map. Adding as %li for %s(%u)", \
245  attrID, num.get_int(), mItem.name(), mItem.itemID());
246  }
247  }
248 
249  return;
250  }
251 
252  if (itr->second == num)
253  return;
254 
255  if (notify) {
256  Change(attrID, itr->second, num);
257  } else if (is_log_enabled(ATTRIBUTE__CHANGE)) {
258  if (itr->second.isFloat()) {
259  if (num.isFloat()) {
260  _log(ATTRIBUTE__CHANGE, "Changing Attribute %u from %.2f to %.2f for %s(%u)", \
261  attrID, itr->second.get_float(), num.get_float(), mItem.name(), mItem.itemID());
262  } else {
263  _log(ATTRIBUTE__CHANGE, "Changing Attribute %u from %.2f to %li for %s(%u)", \
264  attrID, itr->second.get_float(), num.get_int(), mItem.name(), mItem.itemID());
265  }
266  } else {
267  if (num.isFloat()) {
268  _log(ATTRIBUTE__CHANGE, "Changing Attribute %u from %li to %.2f for %s(%u)", \
269  attrID, itr->second.get_int(), num.get_float(), mItem.name(), mItem.itemID());
270  } else {
271  _log(ATTRIBUTE__CHANGE, "Changing Attribute %u from %li to %li for %s(%u)", \
272  attrID, itr->second.get_int(), num.get_int(), mItem.name(), mItem.itemID());
273  }
274  }
275  }
276 
277  itr->second = num;
278 }
279 
280 void AttributeMap::MultiplyAttribute(uint16 attrID, EvilNumber& num, bool notify/*false*/)
281 {
282  if (num.isNaN() or num.isInf()) {
283  _log(ATTRIBUTE__ERROR, "AttributeMap::MultiplyAttribute() - Something sent NaN or Inf for %u on %s(%u). Returning without modifying.", \
284  attrID, mItem.name(), mItem.itemID());
285  EvE::traceStack();
286  //ResetAttribute(attrID, notify);
287  return;
288  }
289  if (num == EvilZero) {
290  // could this be on purpose?
291  //ResetAttribute(attrID, notify);
292  _log(ATTRIBUTE__WARNING, "AttributeMap::MultiplyAttribute() - Something sent 0 for %u on %s(%u). Returning without modifying.", \
293  attrID, mItem.name(), mItem.itemID());
294  EvE::traceStack();
295  return;
296  }
297  AttrMapItr itr = mAttributes.find(attrID);
298  if (itr == mAttributes.end())
299  return; // it doesnt exist...nothing to do.
300 
301  EvilNumber oldValue(itr->second);
302  itr->second *= num;
303 
304  if (notify)
305  Change(attrID, oldValue, itr->second);
306 }
307 
308 
310 {
311  AttrMapConstItr itr = mAttributes.find(attrID);
312  if (itr != mAttributes.end())
313  return itr->second;
314  return EvilZero;
315 }
316 
317 bool AttributeMap::HasAttribute(const uint16 attrID) const
318 {
319  AttrMapConstItr itr = mAttributes.find(attrID);
320  if (itr != mAttributes.end())
321  return true;
322  return false;
323 }
324 
325 bool AttributeMap::HasAttribute(const uint16 attrID, EvilNumber &value) const
326 {
327  AttrMapConstItr itr = mAttributes.find(attrID);
328  if (itr != mAttributes.end()) {
329  value = itr->second;
330  return true;
331  }
332  value = EvilZero;
333  return false;
334 }
335 
336 // [eventName,] ownerID, itemID, attributeID, time, newValue, oldValue = change (unless attrib = quantity)
337 bool AttributeMap::Change(uint16 attrID, EvilNumber& old_val, EvilNumber& new_val) {
338  // check for internal skill time data
339  if (attrID == AttrStartTime)
340  return true;
341  // check for changes
342  if (old_val == new_val)
343  return true;
344  // check owner
345  if ((mItem.ownerID() == 1)
346  and (!IsCharacterID(mItem.itemID())))
347  return true;
348 
349  // i dunno wtf i put this here....modules maybe?
350  /*
351  if (IsCharacterID(mItem.ownerID())) {
352  Client* pClient = sEntityList.FindClientByCharID(mItem.ownerID());
353  if (pClient->IsDocked())
354  return true;
355  } */
356 
357  Notify_OnModuleAttributeChange modChange;
358  modChange.ownerID = mItem.ownerID();
359 
361  // locationID, flag, typeID = itemKey
362  PyTuple* itemKey = new PyTuple(3);
363  itemKey->SetItem(0, new PyInt(mItem.locationID()));
364  itemKey->SetItem(1, new PyInt(mItem.flag()));
365  itemKey->SetItem(2, new PyInt(mItem.typeID()));
366  modChange.itemKey = itemKey;
367  } else {
368  modChange.itemKey = new PyInt(mItem.itemID());
369  }
370 
371  modChange.attributeID = attrID;
372  modChange.time = GetFileTimeNow();
373  modChange.newValue = new_val.GetPyObject();
374  modChange.oldValue = old_val.GetPyObject();
375  /* not sure about this one yet, used in cap charge (more?)....oldValue is list for this server rsp
376  *
377  [PyTuple 7 items]
378  [PyString "OnModuleAttributeChange"]
379  [PyInt 649670823]
380  [PyIntegerVar 1005885567714]
381  [PyInt 18]
382  [PyIntegerVar 129756563388570240]
383  [PyFloat 680.554999862301]
384  [PyList 4 items]
385  [PyFloat 526.692785423517] <<- old value
386  [PyIntegerVar 129756563391382864] <<- old time?
387  [PyFloat 104400] <<- recharge time ??
388  [PyFloat 4860] <<- ??
389  */
390  return SendChanges(modChange.Encode());
391 }
392 
393 bool AttributeMap::Add(uint16 attrID, EvilNumber& num) {
394  if (attrID == AttrStartTime)
395  return true;
396 
397  if ((mItem.ownerID() == 1)
398  and (!IsCharacterID(mItem.itemID())))
399  return true;
400 /*
401  if (IsCharacterID(mItem.ownerID())) {
402  Client* pClient = sEntityList.FindClientByCharID(mItem.ownerID());
403  if (pClient->IsDocked())
404  return true;
405  }
406  */
407 
408  Notify_OnModuleAttributeChange modChange;
409  modChange.ownerID = mItem.ownerID();
411  // locationID, flag, typeID = itemKey
412  PyTuple* itemKey = new PyTuple(3);
413  itemKey->SetItem(0, new PyInt(mItem.locationID()));
414  itemKey->SetItem(1, new PyInt(mItem.flag()));
415  itemKey->SetItem(2, new PyInt(mItem.typeID()));
416  modChange.itemKey = itemKey;
417  } else {
418  modChange.itemKey = new PyInt(mItem.itemID());
419  }
420 
421  modChange.attributeID = attrID;
422  modChange.time = GetFileTimeNow();
423  modChange.newValue = num.GetPyObject();
424  modChange.oldValue = PyStatic.NewNone();
425  return SendChanges(modChange.Encode());
426 }
427 
429  if (attrChange == nullptr)
430  return true;
431 
432  if (IsPlayerCorp(mItem.ownerID())) {
433  // there is no code to get corp AND loc in multicast. it sends to both
434  MulticastTarget mct;
435  mct.corporations.insert(mItem.ownerID());
436  if (sDataMgr.IsStation(mItem.locationID())) {
437  mct.locations.insert(mItem.locationID());
438  sEntityList.Multicast("OnItemChange", "*stationid&corpid", &attrChange, mct);
439  } else {
440  sEntityList.Multicast("OnItemChange", "corpid", &attrChange, mct);
441  }
442  }
443 
444  if (IsCorp(mItem.ownerID()))
445  return true;
446 
447  Client* pClient(nullptr);
448  if (IsCharacterID(mItem.itemID())) {
449  pClient = sEntityList.FindClientByCharID(mItem.itemID());
450  } else {
451  pClient = sEntityList.FindClientByCharID(mItem.ownerID());
452  }
453 
454  if (pClient == nullptr) {
455  _log(PLAYER__WARNING, "AttributeMap::SendChanges() - ownerID for %u not found", mItem.itemID() );
456  return false;
457  }
458 
459  // avoid flooding the client on login
460  if (pClient->IsLogin())
461  return true;
462 
463  if (is_log_enabled(ATTRIBUTE__CHANGE)) {
464  _log(ATTRIBUTE__CHANGE, "Sending Attribute changes for %s(%u)", mItem.name(), mItem.itemID());
465  attrChange->Dump(ATTRIBUTE__CHANGE, "");
466  }
467 
468  pClient->QueueDestinyEvent(&attrChange);
469 
470  //Save();
471 
472  return true;
473 }
474 
475 void AttributeMap::ResetAttribute(uint16 attrID, bool notify/*false*/) {
476  EvilNumber value(mItem.GetDefaultAttribute(attrID));
477  SetAttribute(attrID, value, notify);
478 }
479 
480 void AttributeMap::CopyAttributes(std::map< uint16, EvilNumber >& attrMap)
481 {
482  for (auto cur : mAttributes)
483  attrMap[cur.first] = cur.second;
484 }
485 
487 {
488  std::ostringstream Inserts;
489  // start the insert into command.
490  Inserts << "REPLACE INTO entity_attributes ";
491  Inserts << " (itemID, attributeID, valueInt, valueFloat) VALUES";
492  bool save(false);
493  AttrMap::iterator cur = mAttributes.find(AttrShieldCharge);
494  if (cur != mAttributes.end()) {
495  save = true;
496  Inserts << "(" << mItem.itemID() << ", " << cur->first << ", ";
497  if ( cur->second.get_type() == evil_number_int ) {
498  Inserts << cur->second.get_int() << ", NULL)";
499  } else {
500  Inserts << " NULL, " << cur->second.get_double() << ")";
501  }
502  }
503  cur = mAttributes.find(AttrArmorDamage);
504  if (cur != mAttributes.end()) {
505  if (save)
506  Inserts << ",";
507  save = true;
508  Inserts << "(" << mItem.itemID() << ", " << cur->first << ", ";
509  if ( cur->second.get_type() == evil_number_int ) {
510  Inserts << cur->second.get_int() << ", NULL)";
511  } else {
512  Inserts << " NULL, " << cur->second.get_double() << ")";
513  }
514  }
515  cur = mAttributes.find(AttrDamage);
516  if (cur != mAttributes.end()) {
517  if (save)
518  Inserts << ",";
519  save = true;
520  Inserts << "(" << mItem.itemID() << ", " << cur->first << ", ";
521  if ( cur->second.get_type() == evil_number_int ) {
522  Inserts << cur->second.get_int() << ", NULL)";
523  } else {
524  Inserts << " NULL, " << cur->second.get_double() << ")";
525  }
526  }
527  cur = mAttributes.find(AttrHeatHi);
528  if (cur != mAttributes.end()) {
529  if (save)
530  Inserts << ",";
531  save = true;
532  Inserts << "(" << mItem.itemID() << ", " << cur->first << ", ";
533  if ( cur->second.get_type() == evil_number_int ) {
534  Inserts << cur->second.get_int() << ", NULL)";
535  } else {
536  Inserts << " NULL, " << cur->second.get_double() << ")";
537  }
538  }
539  cur = mAttributes.find(AttrHeatMed);
540  if (cur != mAttributes.end()) {
541  if (save)
542  Inserts << ",";
543  save = true;
544  Inserts << "(" << mItem.itemID() << ", " << cur->first << ", ";
545  if ( cur->second.get_type() == evil_number_int ) {
546  Inserts << cur->second.get_int() << ", NULL)";
547  } else {
548  Inserts << " NULL, " << cur->second.get_double() << ")";
549  }
550  }
551  cur = mAttributes.find(AttrHeatLow);
552  if (cur != mAttributes.end()) {
553  if (save)
554  Inserts << ",";
555  save = true;
556  Inserts << "(" << mItem.itemID() << ", " << cur->first << ", ";
557  if ( cur->second.get_type() == evil_number_int ) {
558  Inserts << cur->second.get_int() << ", NULL)";
559  } else {
560  Inserts << " NULL, " << cur->second.get_double() << ")";
561  }
562  }
563 
564  if (save) {
565  DBerror err;
566  if (!sDatabase.RunQuery(err, Inserts.str().c_str())) {
567  _log(DATABASE__ERROR, "SaveShipState - unable to save attributes for %u - %s", mItem.itemID(), err.c_str());
568  }
569  }
570 }
571 
572 // Delete() only called from InventoryItem::Delete()
574  mAttributes.clear();
575 }
576 
578  _log(ATTRIBUTE__DELETE, "Delete Attribute %u for %s(%u)", attrID, mItem.name(), mItem.itemID());
579  AttrMapItr itr = mAttributes.find(attrID);
580  if (itr != mAttributes.end()) {
581  mAttributes.erase(itr);
582  // if it's not in the map, it's not in db, either...
583  DBerror err;
584  if (IsCharacterID(mItem.itemID())) {
585  if (!sDatabase.RunQuery(err, "DELETE FROM chrCharacterAttributes WHERE charID = %u AND attributeID = %u", mItem.itemID(), attrID)) {
586  _log(DATABASE__ERROR, "DeleteAttribute - unable to delete attribute %u for %u - %s", attrID, mItem.itemID(), err.c_str());
587  }
588  } else {
589  if (!sDatabase.RunQuery(err, "DELETE FROM entity_attributes WHERE itemID = %u AND attributeID = %u", mItem.itemID(), attrID)) {
590  _log(DATABASE__ERROR, "DeleteAttribute - unable to delete attribute %u for %u - %s", attrID, mItem.itemID(), err.c_str());
591  }
592  }
593  } else {
594  _log(ATTRIBUTE__WARNING, "Attribute %u not found in %s(%u) when calling delete ", attrID, mItem.name(), mItem.itemID());
595  }
596 }
597 
599  return mAttributes.begin();
600 }
601 
603  return mAttributes.end();
604 }
#define IsStaticItem(itemID)
Definition: EVE_Defines.h:266
bool IsLogin()
Definition: Client.h:235
bool Change(uint16 attrID, EvilNumber &old_val, EvilNumber &new_val)
internal function to handle the change.
InventoryItem & mItem
Definition: AttributeMap.h:117
void SetAttribute(uint16 attrID, EvilNumber &num, bool notify=true)
#define sDatabase
Definition: dbcore.h:199
void SaveShipState()
std::set< uint32 > corporations
Definition: EntityList.h:60
#define _log(type, fmt,...)
Definition: logsys.h:124
PyRep * GetPyObject()
converts the EvilNumber into a python object.
Definition: EvilNumber.cpp:109
uint32 ownerID() const
Definition: InventoryItem.h:99
uint32 GetUInt(uint32 index) const
Definition: dbcore.cpp:658
double GetDouble(uint32 index) const
Definition: dbcore.cpp:693
void MultiplyAttribute(uint16 attrID, EvilNumber &num, bool notify=false)
void QueueDestinyEvent(PyTuple **multiEvent)
Definition: Client.cpp:2124
bool Add(uint16 attrID, EvilNumber &num)
internal function to handle adding attributes.
EvilNumber GetDefaultAttribute(const uint16 attrID) const
#define sEntityList
Definition: EntityList.h:208
bool isNaN()
Definition: EvilNumber.cpp:139
AttrMapItr begin()
return the begin iterator of the AttributeMap
this is a class that kinda mimics how python polymorph's numbers.
Definition: EvilNumber.h:59
const char * name()
void DeleteAttribute(uint16 attrID)
Python tuple.
Definition: PyRep.h:567
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
itemID[count] Create count or of the specified item(from Insider)" ) COMMAND( goto
EvilNumber EvilZero
Definition: EvilNumber.cpp:32
EvilNumber GetAttribute(const uint16 attrID) const
bool GetRow(DBResultRow &into)
Definition: dbcore.cpp:552
const ItemType & type() const
#define is_log_enabled(type)
Definition: logsys.h:78
const char * c_str() const
Definition: dbcore.h:48
int64 get_int()
Definition: EvilNumber.cpp:166
void ResetAttribute(uint16 attrID, bool notify=false)
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
AttrMap::iterator AttrMapItr
Definition: AttributeMap.h:35
uint32 locationID() const
Python integer.
Definition: PyRep.h:231
AttrMap mAttributes
Definition: AttributeMap.h:119
~AttributeMap() noexcept
bool HasAttribute(const uint16 attrID) const
#define PyStatic
Definition: PyRep.h:1209
bool IsNull(uint32 index) const
Definition: dbcore.h:102
#define IsFittingSlot(flag)
Definition: EVE_Defines.h:355
#define IsPlayerCorp(itemID)
Definition: EVE_Defines.h:241
AttrMap::const_iterator AttrMapConstItr
Definition: AttributeMap.h:36
#define IsCharacterID(itemID)
Definition: EVE_Defines.h:206
const void CopyAttributes(InventoryItem &itemRef) const
Definition: ItemType.cpp:153
bool Load(bool reset=false)
Definition: Client.h:66
EVEItemFlags flag() const
static void SaveAttributes(bool isChar, std::vector< Inv::AttrData > &data)
Definition: ItemDB.cpp:310
#define IsCorp(itemID)
Definition: EVE_Defines.h:234
double GetFileTimeNow()
Definition: utils_time.cpp:84
bool SaveAttributes()
#define IsTempItem(itemID)
Definition: EVE_Defines.h:333
DBerror error
Definition: dbcore.h:69
AttributeMap(InventoryItem &item)
void traceStack(void)
Definition: misc.cpp:169
float get_float()
Definition: EvilNumber.cpp:184
AttrMapItr end()
return the end iterator of the AttributeMap
int64 GetInt64(uint32 index) const
Definition: dbcore.cpp:670
std::set< uint32 > locations
Definition: EntityList.h:59
unsigned __int16 uint16
Definition: eve-compat.h:48
bool isInf()
Definition: EvilNumber.cpp:148
#define IsNPC(itemID)
Definition: EVE_Defines.h:300
void CopyAttributes(std::map< uint16, EvilNumber > &attrMap)
uint16 typeID() const
uint8 categoryID() const
Definition: dbcore.h:39
uint32 itemID() const
Definition: InventoryItem.h:98
bool SendChanges(PyTuple *attrChange)
queue the attribute changes into the QueueDestinyEvent system.
#define sDataMgr
bool isFloat()
Definition: EvilNumber.h:382