UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
inv_shared.cpp
Go to the documentation of this file.
1 
8 /*
9 Copyright (C) 2002-2020 UFO: Alien Invasion.
10 
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 See the GNU General Public License for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 
26 */
27 
28 #include "q_shared.h"
29 
30 static const csi_t* CSI;
31 
39 void INVSH_InitCSI (const csi_t* import)
40 {
41  CSI = import;
42 }
43 
48 bool invDef_t::isFloorDef () const
49 {
50  return id == CID_FLOOR;
51 }
52 
57 bool invDef_t::isRightDef () const
58 {
59  return id == CID_RIGHT;
60 }
61 
66 bool invDef_t::isLeftDef () const
67 {
68  return id == CID_LEFT;
69 }
70 
75 bool invDef_t::isEquipDef () const
76 {
77  return id == CID_EQUIP;
78 }
79 
84 bool invDef_t::isArmourDef () const
85 {
86  return id == CID_ARMOUR;
87 }
88 
90 
99 static bool INVSH_CheckShapeCollision (const uint32_t* shape, const uint32_t itemShape, const int x, const int y)
100 {
101  /* Negative positions not allowed (all items are supposed to have at least one bit set in the first row and column) */
102  if (x < 0 || y < 0) {
103  Com_DPrintf(DEBUG_SHARED, "INVSH_CheckShapeCollision: x or y value negative: x=%i y=%i!\n", x, y);
104  return true;
105  }
106 
107  for (int i = 0; i < SHAPE_SMALL_MAX_HEIGHT; i++) {
108  /* 0xFF is the length of one row in a "small shape" i.e. SHAPE_SMALL_MAX_WIDTH */
109  const int itemRow = (itemShape >> (i * SHAPE_SMALL_MAX_WIDTH)) & 0xFF;
110  /* Result has to be limited to 32bit (SHAPE_BIG_MAX_WIDTH) */
111  const uint32_t itemRowShifted = itemRow << x;
112 
113  /* Check x maximum. */
114  if (itemRowShifted >> x != itemRow)
115  /* Out of bounds (32bit; a few bits of this row in itemShape were truncated) */
116  return true;
117 
118  /* Check y maximum. */
119  if (y + i >= SHAPE_BIG_MAX_HEIGHT && itemRow)
120  /* This row (row "i" in itemShape) is outside of the max. bound and has bits in it. */
121  return true;
122 
123  /* Check for collisions of the item with the big mask. */
124  if (itemRowShifted & shape[y + i])
125  return true;
126  }
127 
128  return false;
129 }
130 
142 static bool INVSH_CheckToInventory_shape (const Inventory* const inv, const invDef_t* container, const uint32_t itemShape, const int x, const int y, const Item* ignoredItem)
143 {
144  static uint32_t mask[SHAPE_BIG_MAX_HEIGHT];
145 
146  assert(container);
147 
148  if (container->scroll)
149  Sys_Error("INVSH_CheckToInventory_shape: No scrollable container will ever use this. This type does not support grid-packing!");
150 
151  /* check bounds */
152  if (x < 0 || y < 0 || x >= SHAPE_BIG_MAX_WIDTH || y >= SHAPE_BIG_MAX_HEIGHT)
153  return false;
154 
155  if (!cacheCheckToInventory) {
156  /* extract shape info */
157  for (int j = 0; j < SHAPE_BIG_MAX_HEIGHT; j++)
158  mask[j] = ~container->shape[j];
159 
160  /* Add other items to mask. (i.e. merge their shapes at their location into the generated mask) */
161  const Container& cont = inv->getContainer(container->id);
162  Item* item = nullptr;
163  while ((item = cont.getNextItem(item))) {
164  if (ignoredItem == item)
165  continue;
166 
167  if (item->rotated)
168  INVSH_MergeShapes(mask, item->def()->getShapeRotated(), item->getX(), item->getY());
169  else
170  INVSH_MergeShapes(mask, item->def()->shape, item->getX(), item->getY());
171  }
172  }
173 
174  /* Test for collisions with newly generated mask. */
175  if (INVSH_CheckShapeCollision(mask, itemShape, x, y))
176  return false;
177 
178  /* Everything ok. */
179  return true;
180 }
181 
188 static bool INVSH_CheckShapeSmall (const uint32_t shape, const int x, const int y)
189 {
190  if (y >= SHAPE_SMALL_MAX_HEIGHT || x >= SHAPE_SMALL_MAX_WIDTH|| x < 0 || y < 0) {
191  return false;
192  }
193 
194  return shape & (0x01 << (y * SHAPE_SMALL_MAX_WIDTH + x));
195 }
196 
203 static bool INVSH_ShapeCheckPosition (const Item* item, const int x, const int y)
204 {
205  assert(item);
206 
207  /* Check if the position is inside the shape (depending on rotation value) of the item. */
208  uint32_t shape;
209  if (item->rotated) {
210  shape = item->def()->getShapeRotated();
211  } else {
212  shape = item->def()->shape;
213  }
214 
215  return INVSH_CheckShapeSmall(shape, x - item->getX(), y - item->getY());
216 }
217 
227 {
228  return craftitem.type != MAX_ACITEMS && !isDummy;
229 }
230 
240 {
241  return craftitem.type != MAX_ACITEMS && isDummy;
242 }
243 
249 const objDef_t* INVSH_GetItemByIDSilent (const char* id)
250 {
251  if (!id)
252  return nullptr;
253 
254  for (int i = 0; i < CSI->numODs; ++i) { /* i = item index */
255  const objDef_t* item = &CSI->ods[i];
256  if (Q_streq(id, item->id)) {
257  return item;
258  }
259  }
260  return nullptr;
261 }
262 
267 {
268  if (index == NONE)
269  return nullptr;
270 
271  if (index < 0 || index >= CSI->numODs)
272  Sys_Error("Invalid object index given: %i", index);
273 
274  return &CSI->ods[index];
275 }
276 
282 const objDef_t* INVSH_GetItemByID (const char* id)
283 {
284  const objDef_t* od = INVSH_GetItemByIDSilent(id);
285  if (!od)
286  Com_Printf("INVSH_GetItemByID: Item \"%s\" not found.\n", id);
287 
288  return od;
289 }
290 
292 {
293  for (int i = 0; i < CSI->numImplants; i++) {
294  const implantDef_t* id = &CSI->implants[i];
295  if (id->item == od)
296  return id;
297  }
298  Com_Printf("INVSH_GetImplantForObjDef: could not get implant for %s\n", od->id);
299  return nullptr;
300 }
301 
308 {
309  if (!id)
310  return nullptr;
311 
312  for (int i = 0; i < CSI->numImplants; ++i) {
313  const implantDef_t* item = &CSI->implants[i];
314  if (Q_streq(id, item->id)) {
315  return item;
316  }
317  }
318  return nullptr;
319 }
320 
326 const implantDef_t* INVSH_GetImplantByID (const char* id)
327 {
328  const implantDef_t* implantDef = INVSH_GetImplantByIDSilent(id);
329  if (!implantDef)
330  Com_Printf("INVSH_GetImplantByID: Implant \"%s\" not found.\n", id);
331 
332  return implantDef;
333 }
334 
341 {
342  const invDef_t* container = CSI->ids;
343 
344  for (containerIndex_t i = 0; i < CID_MAX; ++container, ++i)
345  if (Q_streq(id, container->name))
346  return container;
347 
348  return nullptr;
349 }
350 
356 bool objDef_t::isLoadableInWeapon (const objDef_t* weapon) const
357 {
358  assert(weapon);
359 
360  /* check whether the weapon is only linked to itself. */
361  if (this->numWeapons == 1 && this->weapons[0] == this)
362  return false;
363 
364  for (int i = 0; i < this->numWeapons; i++)
365  if (weapon == this->weapons[i])
366  return true;
367 
368  return false;
369 }
370 
371 /*
372 ===============================
373 FIREMODE MANAGEMENT FUNCTIONS
374 ===============================
375 */
376 
385 const fireDef_t* FIRESH_GetFiredef (const objDef_t* obj, const weaponFireDefIndex_t weapFdsIdx, const fireDefIndex_t fdIdx)
386 {
387  if (weapFdsIdx < 0 || weapFdsIdx >= MAX_WEAPONS_PER_OBJDEF)
388  Sys_Error("FIRESH_GetFiredef: weapFdsIdx out of bounds [%i] for item '%s'", weapFdsIdx, obj->id);
389  if (fdIdx < 0 || fdIdx >= MAX_FIREDEFS_PER_WEAPON)
390  Sys_Error("FIRESH_GetFiredef: fdIdx out of bounds [%i] for item '%s'", fdIdx, obj->id);
391  return &obj->fd[weapFdsIdx & (MAX_WEAPONS_PER_OBJDEF - 1)][fdIdx & (MAX_FIREDEFS_PER_WEAPON - 1)];
392 }
393 
402 void INVSH_MergeShapes (uint32_t* shape, const uint32_t itemShape, const int x, const int y)
403 {
404  for (int i = 0; (i < SHAPE_SMALL_MAX_HEIGHT) && (y + i < SHAPE_BIG_MAX_HEIGHT); ++i)
405  shape[y + i] |= ((itemShape >> i * SHAPE_SMALL_MAX_WIDTH) & 0xFF) << x;
406 }
407 
414 bool INVSH_CheckShape (const uint32_t* shape, const int x, const int y)
415 {
416  if (y >= SHAPE_BIG_MAX_HEIGHT || x >= SHAPE_BIG_MAX_WIDTH || x < 0 || y < 0) {
417  Com_Printf("INVSH_CheckShape: Bad x or y value: (x=%i, y=%i)\n", x, y);
418  return false;
419  }
420 
421  const uint32_t row = shape[y];
422  const int position = powf(2.0f, (float)x);
423  if ((row & position) == 0)
424  return false;
425 
426  return true;
427 }
428 
435 int INVSH_ShapeSize (const uint32_t shape)
436 {
437  int bitCounter = 0;
438 
439  for (int i = 0; i < SHAPE_SMALL_MAX_HEIGHT * SHAPE_SMALL_MAX_WIDTH; ++i)
440  if (shape & (1 << i))
441  ++bitCounter;
442 
443  return bitCounter;
444 }
445 
455 static uint32_t INVSH_ShapeSetBit (uint32_t shape, const int x, const int y)
456 {
457  if (x >= SHAPE_SMALL_MAX_WIDTH || y >= SHAPE_SMALL_MAX_HEIGHT || x < 0 || y < 0) {
458  Com_Printf("INVSH_ShapeSetBit: Bad x or y value: (x=%i, y=%i)\n", x,y);
459  return shape;
460  }
461 
462  shape |= 0x01 << (y * SHAPE_SMALL_MAX_WIDTH + x);
463  return shape;
464 }
465 
466 
472 uint32_t objDef_t::getShapeRotated () const
473 {
474  uint32_t shapeNew = 0;
475  int maxWidth = -1;
476 
477  for (int w = SHAPE_SMALL_MAX_WIDTH - 1; w >= 0; w--) {
478  for (int h = 0; h < SHAPE_SMALL_MAX_HEIGHT; h++) {
479  if (!INVSH_CheckShapeSmall(shape, w, h))
480  continue;
481  if (w >= SHAPE_SMALL_MAX_HEIGHT) {
482  /* Object can't be rotated (code-wise), it is longer than SHAPE_SMALL_MAX_HEIGHT allows. */
483  return shape;
484  }
485 
486  if (maxWidth < 0)
487  maxWidth = w;
488 
489  shapeNew = INVSH_ShapeSetBit(shapeNew, h, maxWidth - w);
490  }
491  }
492 
493  return shapeNew;
494 }
495 
498 {
500  setAmount(0);
501  setAmmoDef(nullptr);
502  _itemDef = nullptr;
503  _x = _y = rotated = 0;
504  _next = nullptr;
505 }
506 
508 Item::Item (const objDef_t* itemDef, const objDef_t* ammo, int ammoLeft)
509 {
510  setAmmoLeft(ammoLeft);
511  setAmount(0);
512  setAmmoDef(ammo);
513  _itemDef = itemDef;
514  _x = _y = rotated = 0;
515  _next = nullptr;
516 }
517 
522 int Item::getWeight () const
523 {
524  int weight = def()->weight;
525  if (ammoDef() && ammoDef() != def() && getAmmoLeft() > 0) {
526  weight += ammoDef()->weight;
527  }
528  return weight;
529 }
530 
536 bool Item::isSameAs (const Item* const other) const
537 {
538  if (this == other)
539  return true;
540 
541  if (other == nullptr)
542  return false;
543 
544  if (this->def() == other->def() && this->ammoDef() == other->ammoDef() && this->getAmmoLeft() == other->getAmmoLeft())
545  return true;
546 
547  return false;
548 }
549 
557 void Item::getFirstShapePosition (int* const x, int* const y) const
558 {
559  for (int tempX = 0; tempX < SHAPE_SMALL_MAX_HEIGHT; tempX++)
560  for (int tempY = 0; tempY < SHAPE_SMALL_MAX_HEIGHT; tempY++)
561  if (INVSH_ShapeCheckPosition(this, this->getX() + tempX, this->getY() + tempY)) {
562  *x = tempX;
563  *y = tempY;
564  return;
565  }
566 
567  *x = *y = NONE;
568 }
569 
577 {
578  const objDef_t* ammodef = ammoDef();
579  const objDef_t* weapon = def();
580 
581  /* this weapon does not use ammo, check for
582  * existing firedefs in the weapon. */
583  if (weapon->numWeapons > 0)
584  ammodef = def();
585 
586  if (!ammodef)
587  return nullptr;
588 
589  for (int i = 0; i < ammodef->numWeapons; ++i) { /* search the weapons that this ammo supports */
590  if (weapon == ammodef->weapons[i]) /* found it ! */
591  return &ammodef->fd[i][0]; /* return the relevant part of the ammo's fireDef table */
592  }
593 
594  return nullptr;
595 }
596 
598 {
599  const fireDef_t* fdArray = getFiredefs();
600  if (!fdArray)
601  return 0;
602  const objDef_t* ammodef = this->def()->numWeapons > 0 ? def() : ammoDef();
603  return ammodef->numFiredefs[fdArray->weapFdsIdx];
604 }
605 
611 {
612  const fireDef_t* fdArray = getFiredefs();
613  int slowest = 0;
614 
615  if (fdArray == nullptr)
616  return nullptr;
617 
618  for (int i = 0; i < MAX_FIREDEFS_PER_WEAPON; ++i)
619  if (fdArray[i].time > fdArray[slowest].time)
620  slowest = i;
621 
622  return &fdArray[slowest];
623 }
625 {
626  const fireDef_t* fdArray = getFiredefs();
627  const int fdCount = getNumFiredefs();
628  int fastestTime = 999;
629  int fastest = -1;
630 
631  if (fdArray == nullptr)
632  return nullptr;
633 
634  for (int i = 0; i < fdCount; ++i)
635  if (fastestTime > fdArray[i].time) {
636  fastestTime = fdArray[i].time;
637  fastest = i;
638  }
639 
640  return fastest == -1 ? nullptr : &fdArray[fastest];
641 }
642 
650 {
651  if (def()) {
652  const fireDef_t* fd = getFiredefs();
653  if (fd && fd->reaction)
654  return def();
655  }
656 
657  return nullptr;
658 }
659 
661 {
662  _def = nullptr;
663  _invList = nullptr;
664  id = 0;
665 }
666 
667 const invDef_t* Container::def () const
668 {
669  return &CSI->ids[id];
670 }
671 Item* Container::getNextItem (const Item* prev) const
672 {
673  if (!prev)
674  return _invList; /* the first one */
675 
676  return prev->getNext();
677 }
678 
682 {
683  int nr = 0;
684  Item* item = nullptr;
685  while ((item = getNextItem(item))) {
687  ++nr;
688  }
689  return nr;
690 }
691 
693 {
694  /* This (prototype-)constructor does not work as intended. Seems like the first inventory is created before CSI is set.
695  * There is the static game_inventory, static character_t, static le_t ...
696  * containers[CID_LEFT]._invList = nullptr;
697  * containers[CID_LEFT]._def = &CSI->ids[CID_LEFT]; */
698 
699  /* Plan B: add an 'id' member to class Container and init it here */
700  init();
701 }
702 
704 {
706  for (int i = 0; i < CID_MAX; ++i)
707  _containers[i].id = i;
708 }
709 
710 const Container* Inventory::_getNextCont (const Container* prev) const
711 {
712  if (!prev)
713  /* the first one */
714  return &_containers[0];
715  if (prev >= &_containers[CID_MAX - 1])
716  /* prev was the last one */
717  return nullptr;
718 
719  return ++prev;
720 }
721 
722 const Container* Inventory::getNextCont (const Container* prev, bool inclTemp) const
723 {
724  const Container* cont = prev;
725 
726  while ((cont = _getNextCont(cont))) {
727  /* if we don't want to include the temp containers ... */
728  if (!inclTemp) {
729  /* ...skip them ! */
730  if (cont == &_containers[CID_FLOOR])
731  continue;
732  if (cont == &_containers[CID_EQUIP])
733  continue;
734  }
735  break;
736  }
737  return cont;
738 }
739 
742 {
743  int nr = 0;
744  const Container* cont = nullptr;
745  while ((cont = getNextCont(cont))) { /* skips the temp containers */
746  nr += cont->countItems();
747  }
748  return nr;
749 }
761 int Inventory::canHoldItem (const invDef_t* container, const objDef_t* od, const int x, const int y, const Item* ignoredItem) const
762 {
763  assert(container);
764  assert(od);
765 
766  /* armour vs item */
767  if (od->isArmour()) {
768  if (!container->armour && !container->all) {
769  return INV_DOES_NOT_FIT;
770  }
771  } else if (!od->implant && container->implant) {
772  return INV_DOES_NOT_FIT;
773  } else if (!od->headgear && container->headgear) {
774  return INV_DOES_NOT_FIT;
775  } else if (container->armour) {
776  return INV_DOES_NOT_FIT;
777  }
778 
779  /* twohanded item */
780  if (od->holdTwoHanded) {
781  if ((container->isRightDef() && getContainer2(CID_LEFT)) || container->isLeftDef())
782  return INV_DOES_NOT_FIT;
783  }
784 
785  /* left hand is busy if right wields twohanded */
786  if (container->isLeftDef()) {
788  return INV_DOES_NOT_FIT;
789 
790  /* can't put an item that is 'fireTwoHanded' into the left hand */
791  if (od->fireTwoHanded)
792  return INV_DOES_NOT_FIT;
793  }
794 
795  if (container->unique) {
796  const Item item(od);
797  if (containsItem(container->id, &item))
798  return INV_DOES_NOT_FIT;
799  }
800 
801  /* Single item containers, e.g. hands or headgear. */
802  if (container->single) {
803  if (getContainer2(container->id)) {
804  /* There is already an item. */
805  return INV_DOES_NOT_FIT;
806  } else {
807  int fits = INV_DOES_NOT_FIT; /* equals 0 */
808 
809  if (INVSH_CheckToInventory_shape(this, container, od->shape, x, y, ignoredItem))
810  fits |= INV_FITS;
811  if (INVSH_CheckToInventory_shape(this, container, od->getShapeRotated(), x, y, ignoredItem))
812  fits |= INV_FITS_ONLY_ROTATED;
813 
814  if (fits != INV_DOES_NOT_FIT)
815  return fits;
817  Com_DPrintf(DEBUG_SHARED, "canHoldItem: INFO: Moving to 'single' container but item would not fit normally.\n");
818  return INV_FITS;
819  }
820  }
821 
822  /* Scrolling container have endless room, the item always fits. */
823  if (container->scroll)
824  return INV_FITS;
825 
826  /* Check 'grid' containers. */
827  int fits = INV_DOES_NOT_FIT; /* equals 0 */
828  if (INVSH_CheckToInventory_shape(this, container, od->shape, x, y, ignoredItem))
829  fits |= INV_FITS;
831  if (!container->isEquipDef() && !container->isFloorDef()
832  && INVSH_CheckToInventory_shape(this, container, od->getShapeRotated(), x, y, ignoredItem))
833  fits |= INV_FITS_ONLY_ROTATED;
834 
835  return fits;
836 }
837 
844 Item* Inventory::getItemAtPos (const invDef_t* container, const int x, const int y) const
845 {
846  assert(container);
847 
848  /* Only a single item. */
849  if (container->single)
850  return getContainer2(container->id);
851 
852  if (container->scroll)
853  Sys_Error("getItemAtPos: Scrollable containers (%i:%s) are not supported by this function.", container->id, container->name);
854 
855  /* More than one item - search for the item that is located at location x/y in this container. */
856  const Container& cont = getContainer(container->id);
857  Item* item = nullptr;
858  while ((item = cont.getNextItem(item)))
859  if (INVSH_ShapeCheckPosition(item, x, y))
860  return item;
861 
862  /* Found nothing. */
863  return nullptr;
864 }
865 
876 void Inventory::findSpace (const invDef_t* container, const Item* item, int* const px, int* const py, const Item* ignoredItem) const
877 {
878  assert(container);
879  assert(!cacheCheckToInventory);
880 
881  /* Scrollable container always have room. We return a dummy location. */
882  if (container->scroll) {
883  *px = *py = 0;
884  return;
885  }
886 
889  for (int y = 0; y < SHAPE_BIG_MAX_HEIGHT; ++y) {
890  for (int x = 0; x < SHAPE_BIG_MAX_WIDTH; ++x) {
891  const int checkedTo = canHoldItem(container, item->def(), x, y, ignoredItem);
892  if (checkedTo) {
894  *px = x;
895  *py = y;
896  return;
897  } else {
899  }
900  }
901  }
903 
904 #ifdef PARANOID
905  Com_DPrintf(DEBUG_SHARED, "findSpace: no space for %s: %s in %s\n",
906  item->def()->type, item->def()->id, container->name);
907 #endif
908  *px = *py = NONE;
909 }
910 
919 bool Inventory::canHoldItemWeight (containerIndex_t from, containerIndex_t to, const Item& item, int maxWeight) const
920 {
921  if (CSI->ids[to].temp || !CSI->ids[from].temp)
922  return true;
923 
924  const int itemWeight = item.getWeight();
925  if (itemWeight < 1)
926  return true;
927  const bool swapArmour = item.isArmour() && getArmour();
928  const int invWeight = getWeight() - (swapArmour ? getArmour()->getWeight() : 0);
929 
930  return (maxWeight < 0 || maxWeight * WEIGHT_FACTOR >= invWeight + itemWeight);
931 }
932 
938 {
939  int weight = 0;
940  const Container* cont = nullptr;
941  while ((cont = getNextCont(cont))) {
942  Item* item = nullptr;
943  while ((item = cont->getNextItem(item))) {
944  weight += item->getWeight();
945  }
946  }
947  return weight;
948 }
949 
951 {
952  setContainer(CID_FLOOR, cont);
953 }
954 
956 {
957  return getContainer2(CID_RIGHT);
958 }
959 
961 {
962  return getContainer2(CID_LEFT);
963 }
964 
966 {
967  return getContainer2(CID_HEADGEAR);
968 }
969 
971 {
972  return getContainer2(CID_HOLSTER);
973 }
974 
976 {
977  return getContainer2(CID_FLOOR);
978 }
979 
981 {
982  return getContainer2(CID_EQUIP);
983 }
984 
986 {
987  return getContainer2(CID_IMPLANT);
988 }
989 
991 {
992  return getContainer2(CID_ARMOUR);
993 }
994 
1001 Item* Inventory::findInContainer (const containerIndex_t contId, const Item* const searchItem) const
1002 {
1003  const Container& cont = getContainer(contId);
1004  Item* item = nullptr;
1005  while ((item = cont.getNextItem(item)))
1006  if (item->isSameAs(searchItem)) {
1007  return item;
1008  }
1009 
1010  return nullptr;
1011 }
1012 
1017 {
1018  if (getRightHandContainer() != nullptr && getRightHandContainer()->getReactionFireWeaponType())
1019  return true;
1020  if (getLeftHandContainer() != nullptr && getLeftHandContainer()->getReactionFireWeaponType())
1021  return true;
1022  return false;
1023 }
1024 
1028 void equipDef_t::addClip (const Item* item)
1029 {
1030  const int ammoIdx = item->ammoDef()->idx;
1031  numItemsLoose[ammoIdx] += item->getAmmoLeft();
1032  /* Accumulate loose ammo into clips */
1033  if (numItemsLoose[ammoIdx] >= item->def()->ammo) {
1034  numItemsLoose[ammoIdx] -= item->def()->ammo;
1035  numItems[ammoIdx]++;
1036  }
1037 }
1038 
1039 void fireDef_t::getShotOrigin (const vec3_t from, const vec3_t dir, bool crouching, vec3_t shotOrigin) const
1040 {
1041  const int dv = AngleToDir((int) (atan2(dir[1], dir[0]) * todeg));
1042  vec3_t dvec;
1043  VectorCopy(dvecs[dv], dvec);
1044  /* get weapon position */
1045  VectorCopy(from, shotOrigin);
1046  /* adjust height: */
1047  if (shotOrg[1] != 0) {
1048  shotOrigin[2] += shotOrg[1];
1049  if (crouching)
1050  shotOrigin[2] -= EYE_STAND - PLAYER_CROUCH - 1;
1051  }
1052  /* adjust horizontal: */
1053  if (shotOrg[0] != 0) {
1054  /* get "right" and "left" of a unit(rotate dir 90 on the x-y plane): */
1055  const float x = dvec[1];
1056  const float y = -dvec[0];
1057  const float length = sqrt(dvec[0] * dvec[0] + dvec[1] * dvec[1]);
1058  /* assign adjustments: */
1059  shotOrigin[0] += x * shotOrg[0] / length;
1060  shotOrigin[1] += y * shotOrg[0] / length;
1061  }
1062 }
static uint32_t INVSH_ShapeSetBit(uint32_t shape, const int x, const int y)
Sets one bit in a shape to true/1.
Definition: inv_shared.cpp:455
#define SHAPE_BIG_MAX_HEIGHT
defines the max height of an inventory container
Definition: inv_shared.h:188
const objDef_t * INVSH_GetItemByIDSilent(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
Definition: inv_shared.cpp:249
#define VectorCopy(src, dest)
Definition: vector.h:51
const objDef_t * _itemDef
Definition: inv_shared.h:403
Item()
Item constructor with all default values.
Definition: inv_shared.cpp:497
const objDef_t * getReactionFireWeaponType() const
Checks whether this item is a reaction fire enabled weapon.
Definition: inv_shared.cpp:649
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
#define CID_EQUIP
Definition: inv_shared.h:56
void setAmmoLeft(int value)
Definition: inv_shared.h:441
const implantDef_t * INVSH_GetImplantByIDSilent(const char *id)
Returns the implant that belongs to the given id or nullptr if it wasn't found.
Definition: inv_shared.cpp:307
bool implant
Definition: inv_shared.h:282
const objDef_t * INVSH_GetItemByID(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
Definition: inv_shared.cpp:282
bool isCraftItem() const
Checks whether a given item is an aircraftitem item.
Definition: inv_shared.cpp:226
void getShotOrigin(const vec3_t from, const vec3_t dir, bool crouching, vec3_t shotOrigin) const
int _y
Definition: inv_shared.h:406
bool isArmour() const
Definition: inv_shared.h:489
const fireDef_t * getFastestFireDef() const
Definition: inv_shared.cpp:624
bool isBaseDefenceItem() const
Checks whether the item is a basedefence item.
Definition: inv_shared.cpp:239
this is a fire definition for our weapons/ammo
Definition: inv_shared.h:110
int INVSH_ShapeSize(const uint32_t shape)
Counts the used bits in a shape (item shape).
Definition: inv_shared.cpp:435
static bool INVSH_CheckShapeCollision(const uint32_t *shape, const uint32_t itemShape, const int x, const int y)
Will check if the item-shape is colliding with something else in the container-shape at position x/y...
Definition: inv_shared.cpp:99
int getAmmoLeft() const
Definition: inv_shared.h:466
Common header file.
int _x
Definition: inv_shared.h:406
weaponFireDefIndex_t weapFdsIdx
Definition: inv_shared.h:126
Item * getContainer2(const containerIndex_t idx) const
Definition: inv_shared.h:546
void addClip(const Item *item)
Combine the rounds of partially used clips.
const fireDef_t * getFiredefs() const
Returns the firedefinitions for a given weapon/ammo.
Definition: inv_shared.cpp:576
bool holdTwoHanded
Definition: inv_shared.h:278
Item * getLeftHandContainer() const
Definition: inv_shared.cpp:960
bool isRightDef() const
Checks whether the inventory definition is the right Hand.
Definition: inv_shared.cpp:57
const objDef_t * def(void) const
Definition: inv_shared.h:469
#define CID_ARMOUR
Definition: inv_shared.h:54
const vec4_t dvecs[PATHFINDING_DIRECTIONS]
Definition: mathlib.cpp:58
bool unique
Definition: inv_shared.h:380
invDef_t ids[MAX_INVDEFS]
Definition: q_shared.h:524
bool isLeftDef() const
Checks whether a given inventory definition is of special type.
Definition: inv_shared.cpp:66
fireDef_t fd[MAX_WEAPONS_PER_OBJDEF][MAX_FIREDEFS_PER_WEAPON]
Definition: inv_shared.h:314
int countItems() const
Count the number of items in the inventory (without temp containers)
Definition: inv_shared.cpp:741
static int cacheCheckToInventory
Definition: inv_shared.cpp:89
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
int numODs
Definition: q_shared.h:518
Item * getHeadgear() const
Definition: inv_shared.cpp:965
bool isSameAs(const Item *const other) const
Check if the (physical) information of 2 items is exactly the same.
Definition: inv_shared.cpp:536
Item * getArmour() const
Definition: inv_shared.cpp:990
Item * getNext() const
Definition: inv_shared.h:451
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
char name[MAX_VAR]
Definition: inv_shared.h:372
bool holdsReactionFireWeapon() const
Checks if there is a weapon in the hands that can be used for reaction fire.
const char * type
Definition: inv_shared.h:271
int getWeight() const
Return the weight of an item.
Definition: inv_shared.cpp:522
implantDef_t implants[MAX_IMPLANTS]
Definition: q_shared.h:520
Item * getFloorContainer() const
Definition: inv_shared.cpp:975
bool containsItem(const containerIndex_t contId, const Item *const item) const
Searches if there is a specific item already in the inventory&container.
Definition: inv_shared.h:572
bool headgear
Definition: inv_shared.h:280
bool scroll
Definition: inv_shared.h:383
int AngleToDir(int angle)
Returns the index of array directionAngles[DIRECTIONS] whose value is the closest to angle...
Definition: mathlib.cpp:130
Item * findInContainer(const containerIndex_t contId, const Item *const item) const
Searches a specific item in the inventory&container.
vec2_t shotOrg
Definition: inv_shared.h:145
#define CID_LEFT
Definition: inv_shared.h:48
bool fireTwoHanded
Definition: inv_shared.h:279
item instance data, with linked list capability
Definition: inv_shared.h:402
void getFirstShapePosition(int *const x, int *const y) const
Calculates the first "true" bit in the shape and returns its position in the item.
Definition: inv_shared.cpp:557
#define todeg
Definition: mathlib.h:51
GLuint * id
Definition: r_gl.h:149
Item * getHolsterContainer() const
Definition: inv_shared.cpp:970
inventory definition with all its containers
Definition: inv_shared.h:525
void INVSH_MergeShapes(uint32_t *shape, const uint32_t itemShape, const int x, const int y)
Will merge the second shape (=itemShape) into the first one (=big container shape) on the position x/...
Definition: inv_shared.cpp:402
const fireDef_t * FIRESH_GetFiredef(const objDef_t *obj, const weaponFireDefIndex_t weapFdsIdx, const fireDefIndex_t fdIdx)
Get the fire definitions for a given object.
Definition: inv_shared.cpp:385
#define CID_HEADGEAR
Definition: inv_shared.h:50
#define CID_RIGHT
Definition: inv_shared.h:47
fireDefIndex_t numFiredefs[MAX_WEAPONS_PER_OBJDEF]
Definition: inv_shared.h:315
#define SHAPE_BIG_MAX_WIDTH
32 bit mask
Definition: inv_shared.h:190
#define OBJZERO(obj)
Definition: shared.h:178
uint32_t shape
Definition: inv_shared.h:273
static const csi_t * CSI
Definition: inv_shared.cpp:30
void findSpace(const invDef_t *container, const Item *item, int *const px, int *const py, const Item *ignoredItem) const
Finds space for item in inv at container.
Definition: inv_shared.cpp:876
Item * getRightHandContainer() const
Definition: inv_shared.cpp:955
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition: r_gl.h:110
bool single
Definition: inv_shared.h:375
The csi structure is the client-server-information structure which contains all the static data neede...
Definition: q_shared.h:515
int getWeight() const
Get the weight of the items in the given inventory (excluding those in temp containers).
Definition: inv_shared.cpp:937
int numWeapons
Definition: inv_shared.h:317
bool armour
Definition: inv_shared.h:376
#define MAX_WEAPONS_PER_OBJDEF
Definition: inv_shared.h:40
const invDef_t * INVSH_GetInventoryDefinitionByID(const char *id)
Definition: inv_shared.cpp:340
int32_t fireDefIndex_t
Definition: inv_shared.h:78
#define MAX_FIREDEFS_PER_WEAPON
Definition: inv_shared.h:42
#define CID_IMPLANT
Definition: inv_shared.h:49
#define SHAPE_SMALL_MAX_WIDTH
The max width and height of an item-shape.
Definition: inv_shared.h:176
#define CID_FLOOR
Definition: inv_shared.h:55
int canHoldItem(const invDef_t *container, const objDef_t *od, const int x, const int y, const Item *ignoredItem) const
Definition: inv_shared.cpp:761
uint32_t getShapeRotated() const
Rotates a shape definition 90 degree to the left (CCW)
Definition: inv_shared.cpp:472
const implantDef_t * INVSH_GetImplantByID(const char *id)
Returns the implant that belongs to the given id or nullptr if it wasn't found.
Definition: inv_shared.cpp:326
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
const invDef_t * def() const
Definition: inv_shared.cpp:667
int countItems() const
Count the number of items in the Container.
Definition: inv_shared.cpp:681
Item * getEquipContainer() const
Definition: inv_shared.cpp:980
int numImplants
Definition: q_shared.h:521
Item * getNextItem(const Item *prev) const
Definition: inv_shared.cpp:671
Item * _invList
Definition: inv_shared.h:516
void init()
Definition: inv_shared.cpp:703
#define CID_HOLSTER
Definition: inv_shared.h:53
QGL_EXTERN GLuint index
Definition: r_gl.h:110
const implantDef_t * INVSH_GetImplantForObjDef(const objDef_t *od)
Definition: inv_shared.cpp:291
const Container & getContainer(const containerIndex_t idx) const
Definition: inv_shared.h:537
const char * id
Definition: inv_shared.h:102
bool canHoldItemWeight(containerIndex_t from, containerIndex_t to, const Item &item, int maxWeight) const
Check that adding an item to the inventory won't exceed the max permitted weight. ...
Definition: inv_shared.cpp:919
int32_t weaponFireDefIndex_t
Definition: inv_shared.h:77
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
int32_t containerIndex_t
Definition: inv_shared.h:46
Container _containers[MAX_CONTAINERS]
Definition: inv_shared.h:527
uint32_t shape[SHAPE_BIG_MAX_HEIGHT]
Definition: inv_shared.h:384
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.
Definition: inv_shared.cpp:356
bool isFloorDef() const
Checks whether the inventory definition is the floor.
Definition: inv_shared.cpp:48
int weight
Definition: inv_shared.h:335
QGL_EXTERN GLint i
Definition: r_gl.h:113
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
Definition: inv_shared.cpp:722
int numItems[MAX_OBJDEFS]
Definition: inv_shared.h:608
bool isDummy
Definition: inv_shared.h:290
void setAmmoDef(const objDef_t *od)
Definition: inv_shared.h:435
int getNumFiredefs() const
Definition: inv_shared.cpp:597
bool temp
Definition: inv_shared.h:381
int ammo
Definition: inv_shared.h:293
#define EYE_STAND
Definition: q_sizes.h:4
#define CID_MAX
Definition: inv_shared.h:57
void setFloorContainer(Item *cont)
Definition: inv_shared.cpp:950
aircraftItemType_t type
Definition: inv_shared.h:247
Item * getItemAtPos(const invDef_t *container, const int x, const int y) const
Searches if there is an item at location (x,y) in a container.
Definition: inv_shared.cpp:844
Item * getImplantContainer() const
Definition: inv_shared.cpp:985
bool isArmour() const
Definition: inv_shared.h:346
bool isHeldTwoHanded() const
Definition: inv_shared.h:476
#define NONE_AMMO
Definition: defines.h:69
bool isArmourDef() const
Checks whether a given inventory definition is of special type.
Definition: inv_shared.cpp:84
static bool INVSH_ShapeCheckPosition(const Item *item, const int x, const int y)
Check if a position in a container is used by an item (i.e. collides with the shape).
Definition: inv_shared.cpp:203
const objDef_t * ammoDef(void) const
Definition: inv_shared.h:460
Item * _next
Definition: inv_shared.h:405
vec_t vec3_t[3]
Definition: ufotypes.h:39
inventory definition for our menus
Definition: inv_shared.h:371
bool reaction
Definition: inv_shared.h:139
void setAmount(int value)
Definition: inv_shared.h:438
byte numItemsLoose[MAX_OBJDEFS]
Definition: inv_shared.h:609
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
Definition: inv_shared.cpp:266
int getX() const
Definition: inv_shared.h:454
bool INVSH_CheckShape(const uint32_t *shape, const int x, const int y)
Checks the shape if there is a 1-bit on the position x/y.
Definition: inv_shared.cpp:414
containerIndex_t id
Definition: inv_shared.h:373
objDef_t ods[MAX_OBJDEFS]
Definition: q_shared.h:517
bool isEquipDef() const
Checks whether a given inventory definition is of special type.
Definition: inv_shared.cpp:75
const fireDef_t * getSlowestFireDef() const
Get the firedef that uses the most TU for this item.
Definition: inv_shared.cpp:610
const Container * _getNextCont(const Container *prev) const
Definition: inv_shared.cpp:710
const invDef_t * _def
Definition: inv_shared.h:513
int rotated
Definition: inv_shared.h:412
bool all
Definition: inv_shared.h:379
#define NONE
Definition: defines.h:68
#define Q_streq(a, b)
Definition: shared.h:136
void INVSH_InitCSI(const csi_t *import)
Initializes client server shared data pointer. This works because the client and the server are both ...
Definition: inv_shared.cpp:39
#define DEBUG_SHARED
Definition: defines.h:55
const struct objDef_s * item
Definition: inv_shared.h:104
#define SHAPE_SMALL_MAX_HEIGHT
Definition: inv_shared.h:177
craftItem craftitem
Definition: inv_shared.h:331
#define PLAYER_CROUCH
Definition: q_sizes.h:7
void setContainer(const containerIndex_t idx, Item *cont)
Definition: inv_shared.h:550
static bool INVSH_CheckShapeSmall(const uint32_t shape, const int x, const int y)
Checks the shape if there is a 1-bit on the position x/y.
Definition: inv_shared.cpp:188
const char * id
Definition: inv_shared.h:268
int getY() const
Definition: inv_shared.h:457
const struct objDef_s * weapons[MAX_WEAPONS_PER_OBJDEF]
Definition: inv_shared.h:311
static bool INVSH_CheckToInventory_shape(const Inventory *const inv, const invDef_t *container, const uint32_t itemShape, const int x, const int y, const Item *ignoredItem)
Checks if an item-shape can be put into a container at a certain position... ignores any 'special' ty...
Definition: inv_shared.cpp:142
bool headgear
Definition: inv_shared.h:378
bool implant
Definition: inv_shared.h:377