World of Might and Magic  0.2.0
Open reimplementation of Might and Magic 6 7 8 game engine
Chest.cpp
См. документацию.
1 #include "Engine/Objects/Chest.h"
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 
6 #include "Engine/Engine.h"
7 #include "Engine/LOD.h"
8 #include "Engine/Localization.h"
9 #include "Engine/MapInfo.h"
10 #include "Engine/OurMath.h"
11 #include "Engine/Party.h"
12 #include "Engine/Time.h"
13 
14 #include "IO/Mouse.h"
15 
16 #include "GUI/UI/UIChest.h"
17 #include "GUI/UI/UIStatusBar.h"
18 
20 
25 
27 
28 #include "Engine/Objects/Actor.h"
29 #include "Engine/Objects/Items.h"
32 
34 
35 // should be injected in Chest but struct size cant be altered
37 
39 std::vector<Chest> vChests;
40 
41 bool Chest::Open(int uChestID) {
42  ODMFace *pODMFace; // eax@19
43  BLVFace *pBLVFace; // eax@20
44  int pObjectX; // ebx@21
45  int pObjectZ; // edi@21
46  double dir_x; // st7@23
47  double dir_y; // st6@23
48  double length_vector; // st7@23
49  int pDepth; // ecx@26
50  Vec3_int_ v; // ST4C_12@28
51  bool flag_shout; // edi@28
52  SPRITE_OBJECT_TYPE pSpriteID[4]; // [sp+84h] [bp-40h]@16
53  Vec3_int_ pOut; // [sp+A0h] [bp-24h]@28
54  int pObjectY; // [sp+B0h] [bp-14h]@21
55  int sRotX; // [sp+B4h] [bp-10h]@23
56  float dir_z; // [sp+BCh] [bp-8h]@23
57  int sRotY; // [sp+C0h] [bp-4h]@8
58  SpriteObject pSpellObject; // [sp+14h] [bp-B0h]@28
59 
60  assert(uChestID < 20);
61  if ((uChestID < 0) && (uChestID >= 20)) return false;
62  Chest *chest = &vChests[uChestID];
63 
64  if (!chest->Initialized()) Chest::PlaceItems(uChestID);
65 
66  if (!uActiveCharacter) return false;
67  flag_shout = false;
68  unsigned int pMapID = pMapStats->GetMapInfo(pCurrentMapName);
69  if (chest->Trapped() && pMapID) {
70  if (pPlayers[uActiveCharacter]->GetDisarmTrap() <
71  2 * pMapStats->pInfos[pMapID].LockX5) {
72  pSpriteID[0] = SPRITE_811;
73  pSpriteID[1] = SPRITE_812;
74  pSpriteID[2] = SPRITE_813;
75  pSpriteID[3] = SPRITE_814;
76  int pRandom = rand() % 4;
77  int v6 = PID_ID(EvtTargetObj);
78  if (PID_TYPE(EvtTargetObj) == OBJECT_Decoration) {
79  pObjectX = pLevelDecorations[v6].vPosition.x;
80  pObjectY = pLevelDecorations[v6].vPosition.y;
81  pObjectZ = pLevelDecorations[v6].vPosition.z +
83  }
84  if (PID_TYPE(EvtTargetObj) == OBJECT_BModel) {
86  pODMFace = &pOutdoor->pBModels[EvtTargetObj >> 9]
87  .pFaces[(EvtTargetObj >> 3) & 0x3F];
88  pObjectX = (pODMFace->pBoundingBox.x1 +
89  pODMFace->pBoundingBox.x2) /
90  2;
91  pObjectY = (pODMFace->pBoundingBox.y1 +
92  pODMFace->pBoundingBox.y2) /
93  2;
94  pObjectZ = (pODMFace->pBoundingBox.z1 +
95  pODMFace->pBoundingBox.z2) /
96  2;
97  } else { // Indoor
98  pBLVFace = &pIndoor->pFaces[v6];
99  pObjectX =
100  (pBLVFace->pBounding.x1 + pBLVFace->pBounding.x2) / 2;
101  pObjectY =
102  (pBLVFace->pBounding.y1 + pBLVFace->pBounding.y2) / 2;
103  pObjectZ =
104  (pBLVFace->pBounding.z1 + pBLVFace->pBounding.z2) / 2;
105  }
106  }
107  dir_x = (double)pParty->vPosition.x - (double)pObjectX;
108  dir_y = (double)pParty->vPosition.y - (double)pObjectY;
109  dir_z = ((double)pParty->sEyelevel + (double)pParty->vPosition.z) - (double)pObjectZ;
110  length_vector = sqrt((dir_x * dir_x) + (dir_y * dir_y) + (dir_z * dir_z));
111  if (length_vector <= 1.0) {
112  *(float*)&sRotX = 0.0;
113  *(float*)&sRotY = 0.0;
114  } else {
115  sRotY = (int64_t)sqrt(dir_x * dir_x + dir_y * dir_y);
116  sRotX = stru_5C6E00->Atan2((int64_t)dir_x, (int64_t)dir_y);
117  sRotY =
118  stru_5C6E00->Atan2(dir_y * dir_y, (int64_t)dir_z);
119  }
120  pDepth = 256;
121  if (length_vector < 256.0)
122  pDepth = (int64_t)length_vector / 4;
123  v.x = pObjectX;
124  v.y = pObjectY;
125  v.z = pObjectZ;
126  Vec3_int_::Rotate(pDepth, sRotX, sRotY, v, &pOut.x, &pOut.z,
127  &pOut.y);
128  SpriteObject::sub_42F7EB_DropItemAt(pSpriteID[pRandom], pOut.x,
129  pOut.z, pOut.y, 0, 1, 0, 48, 0);
130 
131  pSpellObject.containing_item.Reset();
132  pSpellObject.spell_skill = 0;
133  pSpellObject.spell_level = 0;
134  pSpellObject.spell_id = 0;
135  pSpellObject.field_54 = 0;
136  pSpellObject.uType = pSpriteID[pRandom];
137  pSpellObject.uObjectDescID = pObjectList->ObjectIDByItemID(pSpellObject.uType);
138  pSpellObject.vPosition.y = pOut.z;
139  pSpellObject.vPosition.x = pOut.x;
140  pSpellObject.vPosition.z = pOut.y;
141  pSpellObject.uSoundID = 0;
142  pSpellObject.uAttributes = 48;
143  pSpellObject.uSectorID = pIndoor->GetSector(pOut.x, pOut.z, pOut.y);
144  pSpellObject.uSpriteFrameID = 0;
145  pSpellObject.spell_caster_pid = 0;
146  pSpellObject.spell_target_pid = 0;
147  pSpellObject.uFacing = 0;
148  pSpellObject.Create(0, 0, 0, 0);
149  pAudioPlayer->PlaySound(SOUND_fireBall, 0, 0, -1, 0, 0);
150  pSpellObject.ExplosionTraps();
151  chest->uFlags &= 0xFEu;
157  }
158  OpenedTelekinesis = false;
159  return false;
160  }
161  chest->uFlags &= 0xFEu;
162  flag_shout = true;
163  }
164  pAudioPlayer->StopChannels(-1, -1);
165  pAudioPlayer->PlaySound(SOUND_openchest0101, 0, 0, -1, 0, 0);
166  if (flag_shout == true) {
167  if (!OpenedTelekinesis)
168  pPlayers[uActiveCharacter]->PlaySound(SPEECH_4, 0);
169  }
170  OpenedTelekinesis = false;
172  return true;
173 }
174 
176  Point pt = mouse->GetCursorPos();
177  unsigned int pX = pt.x;
178  unsigned int pY = pt.y;
179 
180  Chest *chest = &vChests[(int)pGUIWindow_CurrentMenu->par1C];
181 
182  int chestheight = pChestHeightsByType[chest->uChestBitmapID];
183  int chestwidth = pChestWidthsByType[chest->uChestBitmapID];
184 
185  int inventoryYCoord = (pY - (pChestPixelOffsetY[chest->uChestBitmapID])) / 32;
186  int inventoryXCoord = (pX - (pChestPixelOffsetX[chest->uChestBitmapID])) / 32;
187  int invMatrixIndex = inventoryXCoord + (chestheight * inventoryYCoord);
188 
189  if (inventoryYCoord >= 0 && inventoryYCoord < chestheight &&
190  inventoryXCoord >= 0 && inventoryXCoord < chestwidth) {
191  int chestindex = chest->pInventoryIndices[invMatrixIndex];
192  if (chestindex < 0) {
193  invMatrixIndex = (-(chestindex + 1));
194  chestindex = chest->pInventoryIndices[invMatrixIndex];
195  }
196 
197  if (chestindex) {
198  int itemindex = chestindex - 1;
199  ItemGen *item = &chest->igChestItems[itemindex];
200 
202  // normal picking
203 
206  return 1;
207 
209 
210  // per pixel transparency check tests
211  /*
212 
213  auto img = assets->GetImage_16BitColorKey(item->GetIconName(),
214  0x7FF);
215 
216  int imgwidth = img->GetWidth();
217  int imgheight = img->GetHeight();
218  auto pixels = (signed __int32
219  *)img->GetPixels(IMAGE_FORMAT_A8R8G8B8);
220 
221  Assert(pixels != nullptr, "Cannot get pixels");
222 
223  if (imgwidth < 14)
224  imgwidth = 14;
225 
226  int v12 = imgwidth - 14;
227  v12 = v12 & 0xFFFFFFE0;
228  int v13 = v12 + 32;
229 
230  if (imgheight < 14)
231  imgheight = 14;
232 
233  int chest_offs_x =
234  42;//pChestPixelOffsetX[(int)pGUIWindow_CurrentMenu->par1C].uChestBitmapID];
235  int chest_offs_y = 34; //
236  pChestPixelOffsetY[(int)pGUIWindow_CurrentMenu->par1C].uChestBitmapID];
237 
238  int imgX = chest_offs_x + 32 * (invMatrixIndex % chestwidth) +
239  ((signed int)(v13 - imgwidth) / 2);
240 
241  int imgY = chest_offs_y + 32 * (invMatrixIndex / chestheight) +
242  ((signed int)(((imgheight - 14) & 0xFFFFFFE0) + 32 -
243  imgheight) / 2);
244 
245  int pix_chk_x = pX-imgX;
246  int pix_chk_y = pY-imgY;
247 
248  if (pix_chk_x > 0 && pix_chk_x <= imgwidth && pix_chk_y > 0 &&
249  pix_chk_y <= imgheight) {
250 
251  pixels += pix_chk_x + pix_chk_y*imgwidth;
252 
253  if (*pixels & 0xFF000000) {
254  GameUI_StatusBar_Set(item->GetDisplayName());
255  uLastPointedObjectID = 1;
256  return 1;
257  }
258  }
259 
260  */
261  }
262  }
263  return 0;
264 }
265 
266 bool Chest::CanPlaceItemAt(int test_cell_position, int item_id, int uChestID) {
267  int chest_cell_heght = pChestHeightsByType[vChests[uChestID].uChestBitmapID];
268  int chest_cell_width = pChestWidthsByType[vChests[uChestID].uChestBitmapID];
269 
270  auto img = assets->GetImage_ColorKey(pItemsTable->pItems[item_id].pIconName, 0x7FF);
271  unsigned int slot_width = GetSizeInInventorySlots(img->GetWidth());
272  unsigned int slot_height = GetSizeInInventorySlots(img->GetHeight());
273 
274  Assert(slot_height > 0 && slot_width > 0, "Items should have nonzero dimensions");
275  if ((slot_width + test_cell_position % chest_cell_width <= chest_cell_width) &&
276  (slot_height + test_cell_position / chest_cell_width <= chest_cell_heght)) {
277  for (unsigned int x = 0; x < slot_width; x++) {
278  for (unsigned int y = 0; y < slot_height; y++) {
279  if (vChests[uChestID].pInventoryIndices[y * chest_cell_width + x + test_cell_position] != 0) {
280  return false;
281  }
282  }
283  }
284  return true;
285  }
286  return false;
287 }
288 
289 int Chest::CountChestItems(int uChestID) {
290  // this returns first free slot rather than an actual count
291  int item_count = 0;
292  int max_items = pChestWidthsByType[vChests[uChestID].uChestBitmapID] *
293  pChestHeightsByType[vChests[uChestID].uChestBitmapID];
294 
295  if (max_items <= 0) {
296  item_count = -1;
297  } else {
298  while (vChests[uChestID].igChestItems[item_count].uItemID) {
299  ++item_count;
300  if (item_count >= max_items) {
301  item_count = -1;
302  break;
303  }
304  }
305  }
306  return item_count;
307 }
308 
309 int Chest::PutItemInChest(int position, ItemGen *put_item, int uChestID) {
310  int item_in_chest_count = CountChestItems(uChestID);
311  int test_pos = 0;
312 
313  int max_size = pChestWidthsByType[vChests[uChestID].uChestBitmapID] *
314  pChestHeightsByType[vChests[uChestID].uChestBitmapID];
315  int chest_width = pChestWidthsByType[vChests[uChestID].uChestBitmapID];
316 
317  if (item_in_chest_count == -1) return 0;
318 
319  if (position != -1) {
320  if (CanPlaceItemAt(position, put_item->uItemID, uChestID)) {
321  test_pos = position;
322  } else {
323  position = -1; // try another position?? is this the right behavior
324  }
325  }
326 
327  if (position == -1) { // no position specified
328  for (int _i = 0; _i < max_size; _i++) {
329  if (Chest::CanPlaceItemAt(_i, put_item->uItemID, pChestWindow->par1C)) {
330  test_pos = _i; // found somewhere to place item
331  break;
332  }
333  }
334 
335  if (test_pos == max_size) { // limits check no room
336  if (uActiveCharacter) {
337  pPlayers[uActiveCharacter]->PlaySound(SPEECH_NoRoom, 0);
338  }
339  return 0;
340  }
341  }
342 
343  Image *texture = assets->GetImage_ColorKey(put_item->GetIconName(), 0x7FF);
344  unsigned int slot_width = GetSizeInInventorySlots(texture->GetWidth());
345  unsigned int slot_height = GetSizeInInventorySlots(texture->GetHeight());
346 
347  Assert(slot_height > 0 && slot_width > 0, "Items should have nonzero dimensions");
348 
349  // set inventory indices - memset was eratic??
350  for (unsigned int x = 0; x < slot_width; x++) {
351  for (unsigned int y = 0; y < slot_height; y++) {
352  vChests[uChestID].pInventoryIndices[y * chest_width + x + test_pos] = (-1 - test_pos);
353  }
354  }
355 
356  vChests[uChestID].pInventoryIndices[test_pos] = item_in_chest_count + 1;
357  memcpy(&vChests[uChestID].igChestItems[item_in_chest_count], put_item, sizeof(ItemGen));
358 
359  return (test_pos + 1);
360 }
361 
362 void Chest::PlaceItemAt(unsigned int put_cell_pos, unsigned int item_at_cell, int uChestID) { // only used for setup?
363  int uItemID = vChests[uChestID].igChestItems[item_at_cell].uItemID;
364  pItemsTable->SetSpecialBonus(&vChests[uChestID].igChestItems[item_at_cell]);
365  if (uItemID >= 135 && uItemID <= 159 &&
366  !vChests[uChestID].igChestItems[item_at_cell].uNumCharges) {
367  int v6 = rand() % 21 + 10;
368  vChests[uChestID].igChestItems[item_at_cell].uNumCharges = v6;
369  vChests[uChestID].igChestItems[item_at_cell].uMaxCharges = v6;
370  }
371 
372  auto img = assets->GetImage_Alpha(pItemsTable->pItems[uItemID].pIconName);
373 
374  int v9 = img->GetWidth();
375  if (v9 < 14) v9 = 14;
376  unsigned int texture_cell_width = ((v9 - 14) >> 5) + 1;
377  int v10 = img->GetHeight();
378  if (v10 < 14) v10 = 14;
379  int textute_cell_height = ((v10 - 14) >> 5) + 1;
380 
381  int chest_cell_width = pChestWidthsByType[vChests[uChestID].uChestBitmapID];
382  int chest_cell_row_pos = 0;
383  for (int i = 0; i < textute_cell_height; ++i) {
384  for (int j = 0; j < texture_cell_width; ++j)
385  vChests[uChestID].pInventoryIndices[put_cell_pos + chest_cell_row_pos + j] = (int16_t)-(put_cell_pos + 1);
386  chest_cell_row_pos += chest_cell_width;
387  }
388  vChests[uChestID].pInventoryIndices[put_cell_pos] = item_at_cell + 1;
389 }
390 
391 void Chest::PlaceItems(int uChestID) { // only sued for setup
392  char chest_cells_map[144]; // [sp+Ch] [bp-A0h]@1
393 
394  render->ClearZBuffer(0, 479);
395  int uChestArea = pChestWidthsByType[vChests[uChestID].uChestBitmapID] *
396  pChestHeightsByType[vChests[uChestID].uChestBitmapID];
397  memset(chest_cells_map, 0, 144);
398  // fill cell map at random positions
399  for (int items_counter = 0; items_counter < uChestArea; ++items_counter) {
400  // get random position in chest
401  int random_chest_pos = 0;
402  do {
403  random_chest_pos = (uint8_t)rand();
404  } while (random_chest_pos >= uChestArea);
405  // if this pos occupied move to next
406  while (chest_cells_map[random_chest_pos]) {
407  ++random_chest_pos;
408  if (random_chest_pos == uChestArea) random_chest_pos = 0;
409  }
410  chest_cells_map[random_chest_pos] = items_counter;
411  }
412 
413  for (int items_counter = 0; items_counter < uChestArea; ++items_counter) {
414  int chest_item_id = vChests[uChestID].igChestItems[items_counter].uItemID;
415  if (chest_item_id) {
416  int test_position = 0;
417  while (!Chest::CanPlaceItemAt((uint8_t)chest_cells_map[test_position], chest_item_id, uChestID)) {
418  ++test_position;
419  if (test_position >= uChestArea) break;
420  }
421  if (test_position < uChestArea) {
422  Chest::PlaceItemAt((uint8_t)chest_cells_map[test_position], items_counter, uChestID);
423  if (vChests[uChestID].uFlags & CHEST_OPENED) {
424  vChests[uChestID].igChestItems[items_counter].SetIdentified();
425  }
426  }
427  }
428  }
429  vChests[uChestID].SetInitialized(true);
430 }
431 
432 void Chest::ToggleFlag(int uChestID, uint16_t uFlag, unsigned int bToggle) {
433  if (uChestID >= 0 && uChestID <= 19) {
434  if (bToggle)
435  vChests[uChestID].uFlags |= uFlag;
436  else
437  vChests[uChestID].uFlags &= ~uFlag;
438  }
439 }
440 
441 #pragma pack(push, 1)
443  char pName[32];
444  char uWidth;
445  char uHeight;
447 };
448 #pragma pack(pop)
449 
451  sName = pChest->pName;
452  uWidth = pChest->uWidth;
453  uHeight = pChest->uHeight;
454  uTextureID = pChest->uTextureID;
455 }
456 
457 void ChestList::FromFile(void *data_mm6, void *data_mm7, void *data_mm8) {
458  static_assert(sizeof(ChestDesc_mm7) == 36, "Wrong type size");
459 
460  unsigned int num_mm6_chests = data_mm6 ? *(uint32_t*)data_mm6 : 0;
461  unsigned int num_mm7_chests = data_mm7 ? *(uint32_t*)data_mm7 : 0;
462  unsigned int num_mm8_chests = data_mm8 ? *(uint32_t*)data_mm8 : 0;
463 
464  assert(num_mm7_chests);
465  assert(!num_mm8_chests);
466 
467  ChestDesc_mm7 *pChests = (ChestDesc_mm7*)((char*)data_mm7 + 4);
468  for (int i = 0; i < num_mm7_chests; i++) {
469  ChestDesc chest(pChests + i);
470  vChests.push_back(chest);
471  }
472 
473  pChests = (ChestDesc_mm7*)((char*)data_mm6 + 4);
474  for (int i = 0; i < num_mm6_chests; i++) {
475  ChestDesc chest(pChests + i);
476  vChests.push_back(chest);
477  }
478 
479  pChests = (ChestDesc_mm7*)((char*)data_mm8 + 4);
480  for (int i = 0; i < num_mm8_chests; i++) {
481  ChestDesc chest(pChests + i);
482  vChests.push_back(chest);
483  }
484 }
485 
486 char *ChestsSerialize(char *pData) {
487  static_assert(sizeof(Chest) == 5324, "Wrong type size");
488 
489  uint32_t uNumChests = vChests.size();
490  memcpy(pData, &uNumChests, 4);
491  pData += 4;
492  Chest *pChests = (Chest*)pData;
493  for (int i = 0; i < uNumChests; i++) {
494  memcpy(pChests + i, &vChests[i], sizeof(Chest));
495  }
496  pData += sizeof(Chest) * uNumChests;
497  return pData;
498 }
499 
500 char *ChestsDeserialize(char *pData) {
501  vChests.clear();
502  uint32_t uNumChests = 0;
503  memcpy(&uNumChests, pData, 4);
504  pData += 4;
505  Chest *pChests = (Chest*)pData;
506  for (int i = 0; i < uNumChests; i++) {
507  vChests.push_back(pChests[i]);
508  }
509  pData += uNumChests * sizeof(Chest);
510  return pData;
511 }
512 
515 
516  int chestindex = chest->pInventoryIndices[index];
517  ItemGen *item_in_slot = &chest->igChestItems[chestindex - 1];
518 
519  auto img = assets->GetImage_ColorKey(item_in_slot->GetIconName(), 0x7FF);
520  unsigned int slot_width = GetSizeInInventorySlots(img->GetWidth());
521  unsigned int slot_height = GetSizeInInventorySlots(img->GetHeight());
522 
523  int chestwidth = pChestWidthsByType[chest->uChestBitmapID];
524 
525  item_in_slot->Reset();
526 
527  if (slot_width > 0) {
528  // blank inventory indices - memset was eratic??
529  for (unsigned int x = 0; x < slot_width; x++) {
530  for (unsigned int y = 0; y < slot_height; y++) {
531  chest->pInventoryIndices[y * chestwidth + x + index] = 0;
532  }
533  }
534  }
535 }
536 
539 
540  int chestheight = pChestHeightsByType[chest->uChestBitmapID];
541  int chestwidth = pChestWidthsByType[chest->uChestBitmapID];
542 
543  unsigned int pX;
544  unsigned int pY;
545  mouse->GetClickPos(&pX, &pY);
546  int inventoryYCoord = (pY - (pChestPixelOffsetY[chest->uChestBitmapID])) / 32;
547  int inventoryXCoord = (pX - (pChestPixelOffsetX[chest->uChestBitmapID])) / 32;
548 
549  int invMatrixIndex = inventoryXCoord + (chestheight * inventoryYCoord);
550 
551  if (inventoryYCoord >= 0 && inventoryYCoord < chestheight &&
552  inventoryXCoord >= 0 && inventoryXCoord < chestwidth) {
553  if (pParty->pPickedItem.uItemID) { // item held
556  }
557  } else {
558  int chestindex = chest->pInventoryIndices[invMatrixIndex];
559  if (chestindex < 0) {
560  invMatrixIndex = (-(chestindex + 1));
561  chestindex = chest->pInventoryIndices[invMatrixIndex];
562  }
563 
564  if (chestindex) {
565  int itemindex = chestindex - 1;
566 
567  if (chest->igChestItems[itemindex].GetItemEquipType() == EQUIP_GOLD) {
568  pParty->PartyFindsGold(chest->igChestItems[itemindex].special_enchantment, 0);
570  } else {
571  pParty->SetHoldingItem(&chest->igChestItems[itemindex]);
572  }
573 
574  RemoveItemAtChestIndex(invMatrixIndex);
575  }
576  }
577  }
578 }
579 
580 void Chest::GrabItem(bool all) { // new fucntion to grab items from chest using spacebar
582  return;
583  }
584 
585  int InventSlot;
586  int grabcount = 0;
587  int goldcount = 0;
588  int goldamount = 0;
589 
591 
592  // loop through chest pInvetoryIndices
593  for (int loop = 0; loop < 140; loop++) {
594  int chestindex = chest->pInventoryIndices[loop];
595  if (chestindex <= 0) continue; // no item here
596 
597  int itemindex = chestindex - 1;
598  ItemGen chestitem = chest->igChestItems[itemindex];
599  if (chestitem.GetItemEquipType() == EQUIP_GOLD) {
602  goldamount += chestitem.special_enchantment;
603  goldcount++;
604  } else { // this should add item to invetory of active char - if that fails set as holding item and break
605  if (uActiveCharacter && (InventSlot = pPlayers[uActiveCharacter]->AddItem(-1, chestitem.uItemID)) != 0) { // can place
606  memcpy(&pPlayers[uActiveCharacter]->pInventoryItemList[InventSlot - 1], &chestitem, 0x24u);
607  grabcount++;
608  GameUI_StatusBar_OnEvent(localization->FormatString(471, pItemsTable->pItems[chestitem.uItemID].pUnidentifiedName)); // You found an item (%s)!
609  } else { // no room so set as holding item
610  pParty->SetHoldingItem(&chestitem);
612  pPlayers[uActiveCharacter]->PlaySound(SPEECH_NoRoom, 0);
613  break;
614  }
615  }
617  if (all == false) // only grab 1 item
618  break;
619  }
620 
621  if (grabcount > 1 || goldcount > 1) { // found items
622  char out[200];
623  sprintf(out, "You found %d item(s) and %d Gold!", grabcount, goldamount);
625  }
626  if (grabcount == 0 && goldcount == 0) { // nothing here
628  }
629 }
630 
632  unsigned int mapType = pMapStats->GetMapInfo(pCurrentMapName);
633  MapInfo *currMapInfo = &pMapStats->pInfos[mapType];
634  for (int i = 1; i < 20; ++i) {
635  for (int j = 0; j < 140; ++j) {
636  ItemGen *currItem = &vChests[i].igChestItems[j];
637  if (currItem->uItemID < 0) {
638  int additionaItemCount = rand() % 5; // additional items in chect
639  additionaItemCount++; // + 1 because it's the item at pChests[i].igChestItems[j] and the additional ones
640  int treasureLevelBot = byte_4E8168[abs(currItem->uItemID) - 1][2 * currMapInfo->Treasure_prob];
641  int treasureLevelTop = byte_4E8168[abs(currItem->uItemID) - 1][2 * currMapInfo->Treasure_prob + 1];
642  int treasureLevelRange = treasureLevelTop - treasureLevelBot + 1;
643  int resultTreasureLevel = treasureLevelBot + rand() % treasureLevelRange; // treasure level
644  if (resultTreasureLevel < 7) {
645  for (int k = 0; k < additionaItemCount; k++) {
646  int whatToGenerateProb = rand() % 100;
647  if (whatToGenerateProb < 20) {
648  currItem->Reset();
649  } else if (whatToGenerateProb < 60) { // generate gold
650  int goldAmount = 0;
651  currItem->Reset();
652  switch (resultTreasureLevel) {
653  case 1:
654  goldAmount = rand() % 51 + 50;
655  currItem->uItemID = ITEM_GOLD_SMALL;
656  break;
657  case 2:
658  goldAmount = rand() % 101 + 100;
659  currItem->uItemID = ITEM_GOLD_SMALL;
660  break;
661  case 3:
662  goldAmount = rand() % 301 + 200;
663  currItem->uItemID = ITEM_GOLD_MEDIUM;
664  break;
665  case 4:
666  goldAmount = rand() % 501 + 500;
667  currItem->uItemID = ITEM_GOLD_MEDIUM;
668  break;
669  case 5:
670  goldAmount = rand() % 1001 + 1000;
671  currItem->uItemID = ITEM_GOLD_LARGE;
672  break;
673  case 6:
674  goldAmount = rand() % 3001 + 2000;
675  currItem->uItemID = ITEM_GOLD_LARGE;
676  break;
677  }
678  currItem->SetIdentified();
679  currItem->special_enchantment = (ITEM_ENCHANTMENT)goldAmount;
680  } else {
681  pItemsTable->GenerateItem(resultTreasureLevel, 0, currItem);
682  }
683 
684  for (int m = 0; m < 140; m++) {
685  if (vChests[i].igChestItems[m].uItemID == ITEM_NULL) {
686  currItem = &vChests[i].igChestItems[m];
687  break;
688  }
689  }
690  }
691  } else {
692  currItem->GenerateArtifact();
693  }
694  }
695  }
696  }
697 }
Party::pPickedItem
ItemGen pPickedItem
Definition: Party.h:312
uint16_t
unsigned __int16 uint16_t
Definition: SDL_config.h:37
SpriteObject
Definition: SpriteObject.h:189
Party::vPosition
Vec3_int_ vPosition
Definition: Party.h:250
Engine_::IocContainer
Definition: IocContainer.h:15
pChestList
ChestList * pChestList
Definition: Chest.cpp:38
ChestDesc::ChestDesc
ChestDesc(struct ChestDesc_mm7 *pChest)
Definition: Chest.cpp:450
Localization::GetString
const char * GetString(unsigned int index) const
Definition: Localization.cpp:13
pChestPixelOffsetY
int pChestPixelOffsetY[8]
Definition: UIChest.cpp:16
pLevelDecorations
std::array< LevelDecoration, 3000 > pLevelDecorations
Definition: Decoration.cpp:8
Chest::GrabItem
static void GrabItem(bool all=false)
Definition: Chest.cpp:580
uSpeakingCharacter
int uSpeakingCharacter
Definition: mm7_data.cpp:764
int16_t
signed __int16 int16_t
Definition: SDL_config.h:36
SOUND_fireBall
@ SOUND_fireBall
Definition: AudioPlayer.h:14
Viewport.h
Chest::Initialized
bool Initialized() const
Definition: Chest.h:36
SpriteObject::uFacing
unsigned __int16 uFacing
Definition: SpriteObject.h:220
v
const GLdouble * v
Definition: SDL_opengl.h:2064
MapStats::pInfos
MapInfo pInfos[77]
Definition: MapInfo.h:79
LOD.h
DecorationList::GetDecoration
DecorationDesc * GetDecoration(unsigned int index)
Definition: DecorationList.h:65
Mouse::GetCursorPos
Point GetCursorPos()
Definition: Mouse.cpp:108
GenerateItemsInChest
void GenerateItemsInChest()
Definition: Chest.cpp:631
Chest::igChestItems
struct ItemGen igChestItems[140]
Definition: Chest.h:60
DecorationList.h
Mouse
Definition: Mouse.h:279
Items.h
Chest::CountChestItems
static int CountChestItems(int uChestID)
Definition: Chest.cpp:289
OutdoorLocation::pBModels
BSPModelList pBModels
Definition: Outdoor.h:119
Chest::PlaceItems
static void PlaceItems(int uChestID)
Definition: Chest.cpp:391
ChestDesc_mm7::pName
char pName[32]
Definition: Chest.cpp:443
ItemsTable::SetSpecialBonus
void SetSpecialBonus(ItemGen *pItem)
Definition: Items.cpp:472
ItemGen::GetItemEquipType
ITEM_EQUIP_TYPE GetItemEquipType()
Definition: Items.cpp:1504
ItemGen::SetIdentified
void SetIdentified()
Definition: Items.h:307
pGUIWindow_CurrentMenu
GUIWindow * pGUIWindow_CurrentMenu
Definition: GUIWindow.cpp:54
Chest::uFlags
uint16_t uFlags
Definition: Chest.h:59
PlayerSpeechID
enum PlayerSpeech PlayerSpeechID
Definition: Player.cpp:48
MapStats::GetMapInfo
MAP_TYPE GetMapInfo(const String &Str2)
Definition: MapInfo.cpp:225
Party::sEyelevel
int sEyelevel
Definition: Party.h:239
SpriteObject::uSectorID
__int16 uSectorID
Definition: SpriteObject.h:223
UIChest.h
AudioPlayer::PlaySound
void PlaySound(SoundID eSoundID, int pid, unsigned int uNumRepeats, int x, int y, int a7)
Definition: AudioPlayer.cpp:195
pChestPixelOffsetX
int pChestPixelOffsetX[8]
Definition: UIChest.cpp:15
BBox_short_::x1
int16_t x1
Definition: VectorTypes.h:114
SpriteObject.h
EvtTargetObj
int EvtTargetObj
Definition: mm7_data.cpp:620
GetSizeInInventorySlots
unsigned int GetSizeInInventorySlots(unsigned int uNumPixels)
Definition: UICharacter.cpp:919
ChestDesc_mm7::uTextureID
int16_t uTextureID
Definition: Chest.cpp:446
localization
Localization * localization
Definition: Localization.cpp:11
Point::x
unsigned int x
Definition: Point.h:7
ChestDesc_mm7
Definition: Chest.cpp:442
ObjectList::ObjectIDByItemID
unsigned int ObjectIDByItemID(unsigned int uItemID)
Definition: ObjectList.cpp:7
BBox_short_::y1
int16_t y1
Definition: VectorTypes.h:116
GameUI_StatusBar_Set
void GameUI_StatusBar_Set(const String &str)
Definition: UIStatusBar.cpp:15
int64_t
__int64 int64_t
Definition: alext.h:31
EQUIP_GOLD
@ EQUIP_GOLD
Definition: Items.h:246
SpriteObject::uType
SPRITE_OBJECT_TYPE uType
Definition: SpriteObject.h:215
texture
GLenum GLenum GLuint texture
Definition: SDL_opengl_glext.h:1181
OBJECT_Decoration
@ OBJECT_Decoration
Definition: Actor.h:69
Chest::PlaceItemAt
static void PlaceItemAt(unsigned int put_cell_pos, unsigned int uItemIdx, int uChestID)
Definition: Chest.cpp:362
Chest::OnChestLeftClick
static void OnChestLeftClick()
Definition: Chest.cpp:537
ItemGen::Reset
void Reset()
Definition: Items.cpp:133
Chest::PutItemInChest
static int PutItemInChest(int a1, struct ItemGen *a2, int uChestID)
Definition: Chest.cpp:309
index
GLuint index
Definition: SDL_opengl_glext.h:663
pChestWidthsByType
int pChestWidthsByType[8]
Definition: UIChest.cpp:17
pPlayers
NZIArray< struct Player *, 5 > pPlayers
Definition: Player.cpp:46
SpriteObject::uSpriteFrameID
unsigned __int16 uSpriteFrameID
Definition: SpriteObject.h:224
BBox_short_::z2
int16_t z2
Definition: VectorTypes.h:119
pIndoor
IndoorLocation * pIndoor
Definition: Indoor.cpp:49
Chest.h
Engine.h
ChestDesc_mm7::uHeight
char uHeight
Definition: Chest.cpp:445
ChestDesc::uHeight
unsigned int uHeight
Definition: Chest.h:19
Chest::ToggleFlag
static void ToggleFlag(int uChestID, uint16_t uFlag, unsigned int bToggle)
Definition: Chest.cpp:432
pMapStats
struct MapStats * pMapStats
Definition: mm7_data.cpp:20
SpriteObject::uObjectDescID
unsigned __int16 uObjectDescID
Definition: SpriteObject.h:217
MapInfo::LockX5
char LockX5
Definition: MapInfo.h:50
Actor.h
ODMFace::pBoundingBox
struct BBox_short_ pBoundingBox
Definition: BSPModel.h:145
pItemsTable
struct ItemsTable * pItemsTable
Definition: Items.cpp:37
Party::PartyFindsGold
void PartyFindsGold(unsigned int uNumGold, int _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal)
Definition: Party.cpp:976
Localization.h
y
EGLSurface EGLint EGLint y
Definition: SDL_egl.h:1596
ItemGen::special_enchantment
ITEM_ENCHANTMENT special_enchantment
Definition: Items.h:330
Image::GetWidth
unsigned int GetWidth()
Definition: Image.cpp:217
SpriteObject::vPosition
struct Vec3_int_ vPosition
Definition: SpriteObject.h:218
pParty
Party * pParty
Definition: Party.cpp:30
Image
Definition: Image.h:19
GUIWindow_Chest
Definition: UIChest.h:10
SpriteObject::field_54
int field_54
Definition: SpriteObject.h:231
ItemGen::GetDisplayName
String GetDisplayName()
Definition: Items.cpp:610
OBJECT_BModel
@ OBJECT_BModel
Definition: Actor.h:70
x
EGLSurface EGLint x
Definition: SDL_egl.h:1596
viewparams
struct ViewingParams * viewparams
Definition: mm7_data.cpp:22
ItemsTable::GenerateItem
void GenerateItem(int treasure_level, unsigned int uTreasureType, ItemGen *pItem)
Definition: Items.cpp:680
SpriteObject::ExplosionTraps
void ExplosionTraps()
Definition: SpriteObject.cpp:788
ITEM_GOLD_LARGE
@ ITEM_GOLD_LARGE
Definition: Items.h:99
BBox_short_::y2
int16_t y2
Definition: VectorTypes.h:117
ItemGen::GetIconName
char * GetIconName()
Definition: Items.cpp:1521
mouse
static Mouse * mouse
Definition: Chest.cpp:36
BLVFace
Definition: Indoor.h:424
ItemGen::uItemID
int uItemID
Definition: Items.h:326
AssetsManager::GetImage_ColorKey
Texture * GetImage_ColorKey(const String &name, uint16_t colorkey)
Definition: AssetsManager.cpp:34
SpriteObject::spell_id
int spell_id
Definition: SpriteObject.h:228
Engine_::IocContainer::ResolveMouse
static Mouse * ResolveMouse()
Definition: IocContainer.cpp:88
ChestDesc
Definition: Chest.h:14
SPRITE_813
@ SPRITE_813
Definition: SpriteObject.h:39
AudioPlayer::StopChannels
void StopChannels(int uStartChannel, int uEndChannel)
Definition: AudioPlayer.cpp:331
ChestDesc::sName
String sName
Definition: Chest.h:17
Party.h
ChestsSerialize
char * ChestsSerialize(char *pData)
Definition: Chest.cpp:486
Mouse::GetClickPos
void GetClickPos(unsigned int *pX, unsigned int *pY)
Definition: Mouse.cpp:20
LEVEL_Outdoor
@ LEVEL_Outdoor
Definition: Indoor.h:287
ITEM_GOLD_SMALL
@ ITEM_GOLD_SMALL
Definition: Items.h:97
Chest::uChestBitmapID
uint16_t uChestBitmapID
Definition: Chest.h:58
OpenedTelekinesis
bool OpenedTelekinesis
Definition: mm7_data.cpp:561
MapInfo
Definition: MapInfo.h:35
ITEM_ENCHANTMENT
ITEM_ENCHANTMENT
Definition: Items.h:38
pCurrentMapName
String pCurrentMapName
Definition: mm7_data.cpp:712
Chest::Trapped
bool Trapped() const
Definition: Chest.h:45
SPRITE_811
@ SPRITE_811
Definition: SpriteObject.h:37
ChestDesc::uTextureID
unsigned int uTextureID
Definition: Chest.h:20
RemoveItemAtChestIndex
void RemoveItemAtChestIndex(int index)
Definition: Chest.cpp:513
BLVFace::pBounding
struct BBox_short_ pBounding
Definition: Indoor.h:486
Outdoor.h
Chest::Open
static bool Open(int uChestID)
Definition: Chest.cpp:41
SpriteObject::Create
int Create(int yaw, int pitch, int a4, int a5)
Definition: SpriteObject.cpp:56
SpriteObject::containing_item
struct ItemGen containing_item
Definition: SpriteObject.h:227
byte_4E8168
std::array< std::array< char, 14 >, 7 > byte_4E8168
Definition: Items.cpp:25
SPRITE_OBJECT_TYPE
SPRITE_OBJECT_TYPE
Definition: SpriteObject.h:5
AudioPlayer.h
vChests
std::vector< Chest > vChests
Definition: Chest.cpp:39
SpriteObject::uSoundID
unsigned __int16 uSoundID
Definition: SpriteObject.h:221
MapInfo.h
uint8_t
unsigned __int8 uint8_t
Definition: SDL_config.h:35
FrameTableInc.h
uLastPointedObjectID
int uLastPointedObjectID
Definition: mm7_data.cpp:534
Point::y
unsigned int y
Definition: Point.h:8
stru193_math::Atan2
unsigned int Atan2(int x, int y)
Definition: OurMath.cpp:46
ChestList
Definition: Chest.h:23
SpriteObject::spell_level
int spell_level
Definition: SpriteObject.h:229
SPRITE_814
@ SPRITE_814
Definition: SpriteObject.h:40
ITEM_NULL
@ ITEM_NULL
Definition: Items.h:74
UIStatusBar.h
SpriteObject::spell_target_pid
int spell_target_pid
Definition: SpriteObject.h:233
Chest::ChestUI_WritePointedObjectStatusString
static bool ChestUI_WritePointedObjectStatusString()
Definition: Chest.cpp:175
assets
AssetsManager * assets
Definition: AssetsManager.cpp:12
uActiveCharacter
unsigned int uActiveCharacter
Definition: mm7_data.cpp:555
Localization::FormatString
String FormatString(unsigned int index,...) const
Definition: Localization.cpp:17
pChestHeightsByType
int pChestHeightsByType[8]
Definition: UIChest.cpp:18
DecorationDesc_mm6::uDecorationHeight
uint16_t uDecorationHeight
Definition: DecorationList.h:40
SOUND_openchest0101
@ SOUND_openchest0101
Definition: AudioPlayer.h:78
GUIWindow::par1C
unsigned int par1C
Definition: GUIWindow.h:477
SpriteObject::sub_42F7EB_DropItemAt
static bool sub_42F7EB_DropItemAt(SPRITE_OBJECT_TYPE sprite, int x, int y, int z, int a4, int count, int a7, unsigned __int16 attributes, ItemGen *a9)
Definition: SpriteObject.cpp:937
GameUI_StatusBar_OnEvent
void GameUI_StatusBar_OnEvent(const String &str, unsigned int num_seconds)
Definition: UIStatusBar.cpp:33
ODMFace
Definition: BSPModel.h:93
Party::SetHoldingItem
void SetHoldingItem(ItemGen *pItem)
Definition: Party.cpp:150
Chest::CanPlaceItemAt
static bool CanPlaceItemAt(int a1, int a2, int uChestID)
Definition: Chest.cpp:266
SpriteObject::spell_skill
int spell_skill
Definition: SpriteObject.h:230
ChestsDeserialize
char * ChestsDeserialize(char *pData)
Definition: Chest.cpp:500
Decoration.h
stru_5C6E00
struct stru193_math * stru_5C6E00
Definition: mm7_data.cpp:19
ItemGen::GenerateArtifact
bool GenerateArtifact()
Definition: Items.cpp:978
SPRITE_812
@ SPRITE_812
Definition: SpriteObject.h:38
m
const GLfloat * m
Definition: SDL_opengl_glext.h:6095
ViewingParams::bRedrawGameUI
int bRedrawGameUI
Definition: Viewport.h:74
AssetsManager::GetImage_Alpha
Texture * GetImage_Alpha(const String &name)
Definition: AssetsManager.cpp:66
OurMath.h
uCurrentlyLoadedLevelType
LEVEL_TYPE uCurrentlyLoadedLevelType
Definition: Indoor.cpp:52
IndoorLocation::GetSector
int GetSector(int sX, int sY, int sZ)
Definition: Indoor.cpp:1279
IndoorLocation::pFaces
struct BLVFace * pFaces
Definition: Indoor.h:630
ChestList::FromFile
void FromFile(void *data_mm6, void *data_mm7, void *data_mm8)
Definition: Chest.cpp:457
SPEECH_4
@ SPEECH_4
Definition: Player.h:50
pAudioPlayer
AudioPlayer * pAudioPlayer
Definition: AudioPlayer.cpp:20
BBox_short_::x2
int16_t x2
Definition: VectorTypes.h:115
Chest
Definition: Chest.h:35
Chest::pInventoryIndices
int16_t pInventoryIndices[140]
Definition: Chest.h:61
Point
Definition: Point.h:3
ItemGen
Definition: Items.h:263
CHEST_OPENED
@ CHEST_OPENED
Definition: Chest.h:11
ObjectList.h
ChestDesc::uWidth
unsigned int uWidth
Definition: Chest.h:18
ChestDesc_mm7::uWidth
char uWidth
Definition: Chest.cpp:444
pOutdoor
OutdoorLocation * pOutdoor
Definition: Outdoor.cpp:48
MapInfo::Treasure_prob
char Treasure_prob
Definition: MapInfo.h:52
_A750D8_player_speech_timer
int64_t _A750D8_player_speech_timer
Definition: mm7_data.cpp:763
SpriteObject::uAttributes
unsigned __int16 uAttributes
Definition: SpriteObject.h:222
BBox_short_::z1
int16_t z1
Definition: VectorTypes.h:118
uint32_t
unsigned __int32 uint32_t
Definition: SDL_config.h:39
pChestWindow
GUIWindow * pChestWindow
Definition: GUIWindow.cpp:49
ITEM_GOLD_MEDIUM
@ ITEM_GOLD_MEDIUM
Definition: Items.h:98
SPEECH_5
@ SPEECH_5
Definition: Player.h:51
Mouse::RemoveHoldingItem
void RemoveHoldingItem()
Definition: Mouse.cpp:25
pObjectList
struct ObjectList * pObjectList
Definition: ObjectList.cpp:5
ItemsTable::pItems
NZIArray< ItemDesc, 800 > pItems
Definition: Items.h:460
Mouse.h
img
GLint GLvoid * img
Definition: SDL_opengl.h:1980
pDecorationList
struct DecorationList * pDecorationList
Definition: DecorationList.cpp:11
SpriteObject::spell_caster_pid
int spell_caster_pid
Definition: SpriteObject.h:232
SPEECH_NoRoom
@ SPEECH_NoRoom
Definition: Player.h:61
Time.h
ChestList::vChests
std::vector< ChestDesc > vChests
Definition: Chest.h:30
render
std::shared_ptr< IRender > render
Definition: RenderOpenGL.cpp:52