#include "pickup.h" #include "lara.h" #include "draw.h" #include "inventory.h" #include "effects.h" #include "effect2.h" #include "control.h" #include "sphere.h" #include "debris.h" #include "box.h" #include "healt.h" #include "items.h" #include "collide.h" #include "switch.h" #include "larafire.h" #include "laraflar.h" #include "lara1gun.h" #include "lara2gun.h" #include "..\Global\global.h" static short PickUpBounds[12] = // offset 0xA1338 { 0xFF00, 0x0100, 0xFF38, 0x00C8, 0xFF00, 0x0100, 0xF8E4, 0x071C, 0x0000, 0x0000, 0x0000, 0x0000 }; static PHD_VECTOR PickUpPosition = { 0, 0, 0xFFFFFF9C }; // offset 0xA1350 static short HiddenPickUpBounds[12] = // offset 0xA135C { 0xFF00, 0x0100, 0xFF9C, 0x0064, 0xFCE0, 0xFF00, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0x0000, 0x0000 }; static PHD_VECTOR HiddenPickUpPosition = { 0, 0, 0xFFFFFD4E }; // offset 0xA1374 static short CrowbarPickUpBounds[12] = // offset 0xA1380 { 0xFF00, 0x0100, 0xFF9C, 0x0064, 0x00C8, 0x0200, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0x0000, 0x0000 }; static PHD_VECTOR CrowbarPickUpPosition = { 0, 0, 0xD7 }; // offset 0xA1398 static short JobyCrowPickUpBounds[12] = // offset 0xA13A4 { 0xFE00, 0x0000, 0xFF9C, 0x0064, 0x0000, 0x0200, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0x0000, 0x0000 }; static PHD_VECTOR JobyCrowPickUpPosition = { 0xFFFFFF20, 0, 0xF0 }; // offset 0xA13BC static short PlinthPickUpBounds[12] = // offset 0xA13C8 { 0xFF00, 0x0100, 0xFD80, 0x0280, 0xFE01, 0x0000, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0x0000, 0x0000 }; static PHD_VECTOR PlinthPickUpPosition = { 0, 0, 0xFFFFFE34 }; // offset 0xA13E0 static short PickUpBoundsUW[12] = // offset 0xA13EC { 0xFE00, 0x0200, 0xFE00, 0x0200, 0xFE00, 0x0200, 0xE002, 0x1FFE, 0xE002, 0x1FFE, 0xE002, 0x1FFE }; static PHD_VECTOR PickUpPositionUW = { 0, 0xFFFFFF38, 0xFFFFFEA2 }; // offset 0xA1404 static short KeyHoleBounds[12] = // offset 0xA1410 { 0xFF00, 0x0100, 0x0000, 0x0000, 0x0000, 0x019C, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C }; static PHD_VECTOR KeyHolePosition = { 0, 0, 0x138 }; // offset 0xA1428 static short PuzzleBounds[12] = // offset 0xA1434 { 0x0000, 0x0000, 0xFF00, 0x0100, 0x0000, 0x0000, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C }; static short SOBounds[12] = // offset 0xA144C { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C }; static PHD_VECTOR SOPos = { 0, 0, 0 }; // offset 0xA1464 short SearchCollectFrames[4] = { 0x00B4, 0x0064, 0x0099, 0x0053 }; short SearchAnims[4] = { 0x01D0, 0x01D1, 0x01D2, 0x01D8 }; short SearchOffsets[4] = { 0x00A0, 0x0060, 0x00A0, 0x0070 }; static short MSBounds[12] = // offset 0xA1488 { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C }; int NumRPickups; short RPickups[16]; PHD_VECTOR OldPickupPos; extern int KeyTriggerActive; extern LaraExtraInfo g_LaraExtra; extern Inventory* g_Inventory; void PickedUpObject(short objectNumber) { switch (objectNumber) { case ID_UZI_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_UZI].Present)) { g_LaraExtra.Weapons[WEAPON_UZI].Present = true; g_LaraExtra.Weapons[WEAPON_UZI].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_UZI].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_UZI].Ammo[0] += 30; break; case ID_PISTOLS_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_PISTOLS].Present)) { g_LaraExtra.Weapons[WEAPON_PISTOLS].Present = true; g_LaraExtra.Weapons[WEAPON_PISTOLS].SelectedAmmo = 0; } g_LaraExtra.Weapons[WEAPON_PISTOLS].Ammo[0] = -1; break; case ID_SHOTGUN_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_SHOTGUN].Present)) { g_LaraExtra.Weapons[WEAPON_SHOTGUN].Present = true; g_LaraExtra.Weapons[WEAPON_SHOTGUN].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[0] += 36; break; case ID_REVOLVER_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_REVOLVER].Present)) { g_LaraExtra.Weapons[WEAPON_REVOLVER].Present = true; g_LaraExtra.Weapons[WEAPON_REVOLVER].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_REVOLVER].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_REVOLVER].Ammo[0] += 6; break; case ID_CROSSBOW_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_CROSSBOW].Present)) { g_LaraExtra.Weapons[WEAPON_CROSSBOW].Present = true; g_LaraExtra.Weapons[WEAPON_CROSSBOW].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[0] += 10; break; case ID_HK_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_CROSSBOW].Present)) { g_LaraExtra.Weapons[WEAPON_HK].Present = true; g_LaraExtra.Weapons[WEAPON_HK].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_HK].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_HK].Ammo[0] += 30; break; case ID_HARPOON_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Present)) { g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Present = true; g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[0] += 10; break; case ID_GRENADE_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Present)) { g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Present = true; g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[0] += 10; break; case ID_ROCKET_LAUNCHER_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Present)) { g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Present = true; g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].SelectedAmmo = 0; } if (g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Ammo[0] += 10; break; case ID_SHOTGUN_AMMO1_ITEM: if (g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[0] += 36; break; case ID_SHOTGUN_AMMO2_ITEM: if (g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[1] != -1) g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[1] += 36; break; case ID_HK_AMMO_ITEM: if (g_LaraExtra.Weapons[WEAPON_HK].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_HK].Ammo[0] += 30; break; case ID_CROSSBOW_AMMO1_ITEM: if (g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[0] += 10; break; case ID_CROSSBOW_AMMO2_ITEM: if (g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[1] != -1) g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[1] += 10; break; case ID_CROSSBOW_AMMO3_ITEM: if (g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[2] != -1) g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[2] += 10; break; case ID_GRENADE_AMMO1_ITEM: if (g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[0] += 10; break; case ID_GRENADE_AMMO2_ITEM: if (g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[1] != -1) g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[1] += 10; break; case ID_GRENADE_AMMO3_ITEM: if (g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[2] != -1) g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[2] += 10; break; case ID_REVOLVER_AMMO_ITEM: if (g_LaraExtra.Weapons[WEAPON_REVOLVER].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_REVOLVER].Ammo[0] += 6; break; case ID_ROCKET_LAUNCHER_AMMO_ITEM: if (g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Ammo[0] += 10; break; case ID_HARPOON_AMMO_ITEM: if (g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[0] += 10; break; case ID_UZI_AMMO_ITEM: if (g_LaraExtra.Weapons[WEAPON_UZI].Ammo[0] != -1) g_LaraExtra.Weapons[WEAPON_UZI].Ammo[0] += 30; break; case ID_FLARE_INV_ITEM: if (Lara.numFlares != -1) Lara.numFlares += 12; break; case ID_SILENCER_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_UZI].HasSilencer || g_LaraExtra.Weapons[WEAPON_PISTOLS].HasSilencer || g_LaraExtra.Weapons[WEAPON_SHOTGUN].HasSilencer || g_LaraExtra.Weapons[WEAPON_REVOLVER].HasSilencer || g_LaraExtra.Weapons[WEAPON_CROSSBOW].HasSilencer || g_LaraExtra.Weapons[WEAPON_HK].HasSilencer)) Lara.silencer = true; break; case ID_LASERSIGHT_ITEM: if (!(g_LaraExtra.Weapons[WEAPON_UZI].HasSilencer || g_LaraExtra.Weapons[WEAPON_PISTOLS].HasSilencer || g_LaraExtra.Weapons[WEAPON_SHOTGUN].HasSilencer || g_LaraExtra.Weapons[WEAPON_REVOLVER].HasSilencer || g_LaraExtra.Weapons[WEAPON_CROSSBOW].HasSilencer || g_LaraExtra.Weapons[WEAPON_HK].HasSilencer)) Lara.laserSight = true; break; case ID_BIGMEDI_ITEM: if (Lara.numLargeMedipack != -1) Lara.numLargeMedipack++; break; case ID_SMALLMEDI_ITEM: if (Lara.numSmallMedipack != -1) Lara.numSmallMedipack++; break; case ID_BINOCULARS_ITEM: Lara.binoculars = 1; break; case ID_WATERSKIN1_EMPTY: g_LaraExtra.Waterskin1.Present = true; g_LaraExtra.Waterskin1.Quantity = 0; break; case ID_WATERSKIN2_EMPTY: g_LaraExtra.Waterskin2.Present = true; g_LaraExtra.Waterskin2.Quantity = 0; break; default: if (objectNumber >= ID_PUZZLE_ITEM1 && objectNumber <= ID_PUZZLE_ITEM8) Lara.puzzleItems[objectNumber - ID_PUZZLE_ITEM1]++; else if (objectNumber >= ID_PUZZLE_ITEM1_COMBO1 && objectNumber <= ID_PUZZLE_ITEM8_COMBO2) Lara.puzzleItemsCombo |= 1 << (objectNumber - ID_PUZZLE_ITEM1_COMBO1); else if (objectNumber >= ID_KEY_ITEM1 && objectNumber <= ID_KEY_ITEM8) Lara.keyItems |= 1 << (objectNumber - ID_KEY_ITEM1); else if (objectNumber >= ID_KEY_ITEM1_COMBO1 && objectNumber <= ID_KEY_ITEM8_COMBO2) Lara.keyItemsCombo |= 1 << (objectNumber - ID_KEY_ITEM1_COMBO1); else if (objectNumber >= ID_PICKUP_ITEM1 && objectNumber <= ID_PICKUP_ITEM4) Lara.pickupItems |= 1 << (objectNumber - ID_PICKUP_ITEM1); else if (objectNumber >= ID_PICKUP_ITEM1_COMBO1 && objectNumber <= ID_PICKUP_ITEM4_COMBO2) Lara.pickupItemsCombo |= 1 << (objectNumber - ID_PICKUP_ITEM1_COMBO1); else if (objectNumber == ID_GOLDROSE_ITEM) { IsAtmospherePlaying = 0; S_CDPlay(6, 0); Lara.pickupItems |= 8; Savegame.Level.Secrets++; Savegame.Game.Secrets++; } else if (objectNumber == ID_CROWBAR_ITEM) Lara.crowbar = true; else if (objectNumber == ID_EXAMINE1) Lara.examine1 = true; else if (objectNumber == ID_EXAMINE2) Lara.examine2 = true; else if (objectNumber == ID_EXAMINE3) Lara.examine3 = true; else if (objectNumber == ID_DIARY) g_LaraExtra.Diary.Present = true; break; } g_Inventory->LoadObjects(false); } void RemoveObjectFromInventory(short objectNumber) { if (objectNumber >= ID_PUZZLE_ITEM1 && objectNumber <= ID_PUZZLE_ITEM8) Lara.puzzleItems[objectNumber - ID_PUZZLE_ITEM1]--; else if (objectNumber >= ID_PUZZLE_ITEM1_COMBO1 && objectNumber <= ID_PUZZLE_ITEM8_COMBO2) Lara.puzzleItemsCombo &= ~(1 << (objectNumber - ID_PUZZLE_ITEM1_COMBO1)); else if (objectNumber >= ID_KEY_ITEM1 && objectNumber <= ID_KEY_ITEM8) Lara.keyItems &= ~(1 << (objectNumber - ID_KEY_ITEM1)); else if (objectNumber >= ID_KEY_ITEM1_COMBO1 && objectNumber <= ID_KEY_ITEM8_COMBO2) Lara.keyItemsCombo &= ~(1 << (objectNumber - ID_KEY_ITEM1_COMBO1)); else if (objectNumber >= ID_PICKUP_ITEM1 && objectNumber <= ID_PICKUP_ITEM4) Lara.pickupItems &= ~(1 << (objectNumber - ID_PICKUP_ITEM1)); else if (objectNumber >= ID_PICKUP_ITEM1_COMBO1 && objectNumber <= ID_PICKUP_ITEM4_COMBO2) Lara.pickupItemsCombo &= ~(1 << (objectNumber - ID_PICKUP_ITEM1_COMBO1)); g_Inventory->LoadObjects(false); } void CollectCarriedItems(ITEM_INFO* item) { short pickupNumber = item->carriedItem; if (pickupNumber != NO_ITEM) { while (pickupNumber != NO_ITEM) { ITEM_INFO* pickup = &Items[pickupNumber]; AddDisplayPickup(pickup->objectNumber); KillItem(pickupNumber); pickupNumber = pickup->carriedItem; } } } /*void SearchObjectCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { UNIMPLEMENTED(); } void SearchObjectControl(short itemNumber)//52D54, 531B8 { UNIMPLEMENTED(); }*/ int PickupTrigger(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (item->flags & IFLAG_KILLED || ( item->status != ITEM_INVISIBLE || item->itemFlags[3] != 1 || item->triggerFlags & 0x80)) { return 0; } KillItem(itemNum); return 1; } int KeyTrigger(short itemNum) { ITEM_INFO* item = &Items[itemNum]; int oldkey; if ((item->status != ITEM_ACTIVE || Lara.gunStatus == LG_HANDS_BUSY) && (!KeyTriggerActive || Lara.gunStatus != LG_HANDS_BUSY)) return -1; oldkey = KeyTriggerActive; if (!oldkey) item->status = ITEM_DEACTIVATED; KeyTriggerActive = false; return oldkey; } void PuzzleHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item = &Items[itemNum]; int flag = 0; if (item->triggerFlags >= 0) { if (item->triggerFlags <= 1024) { if (item->triggerFlags && item->triggerFlags != 999 && item->triggerFlags != 998) flag = 3; } else flag = 2; } else flag = 1; printf("BinocularRange: %d\n", BinocularRange); printf("Lara.gunStatus: %d\n", Lara.gunStatus); printf("GetKeyTrigger(): %d\n", GetKeyTrigger(&Items[itemNum])); if (!((TrInput & IN_ACTION || g_Inventory->GetSelectedObject() != NO_ITEM) && !BinocularRange && !Lara.gunStatus && l->currentAnimState == STATE_LARA_STOP && l->animNumber == ANIMATION_LARA_STAY_IDLE && GetKeyTrigger(&Items[itemNum]))) { if (!Lara.isMoving && (short)Lara.generalPtr == itemNum || (short)Lara.generalPtr != itemNum) { if ((short)Lara.generalPtr == itemNum && l->currentAnimState == STATE_LARA_INSERT_PUZZLE) { if (l->frameNumber == Anims[ANIMATION_LARA_USE_PUZZLE].frameBase + 80 && item->itemFlags[0]) { if (flag == 3) l->itemFlags[0] = item->triggerFlags; else l->itemFlags[0] = 0; PuzzleDone(item, itemNum); item->itemFlags[0] = 0; return; } } if ((short)Lara.generalPtr == itemNum) { if (l->currentAnimState != STATE_LARA_MISC_CONTROL) { if (flag != 2) ObjectCollision(itemNum, l, coll); return; } if (l->animNumber == ANIMATION_LARA_PUT_TRIDENT) { if (l->frameNumber == Anims[l->animNumber].frameBase + 180) { PuzzleDone(item, itemNum); return; } } } if (l->currentAnimState == STATE_LARA_MISC_CONTROL) return; if (flag != 2) ObjectCollision(itemNum, l, coll); return; } } short oldYrot = item->pos.yRot; short* bounds = GetBoundsAccurate(item); PuzzleBounds[0] = bounds[0] - 256; PuzzleBounds[1] = bounds[1] + 256; PuzzleBounds[4] = bounds[4] - 256; PuzzleBounds[5] = bounds[5] + 256; if (item->triggerFlags == 1058) { PuzzleBounds[0] = bounds[0] - 256 - 300; PuzzleBounds[1] = bounds[1] + 256 + 300; PuzzleBounds[4] = bounds[4] - 256 - 300; PuzzleBounds[5] = bounds[5] + 256 + 300; item->pos.yRot = l->pos.yRot; /*v13 = word_509C0E; v12 = word_509C0C; v11 = word_509C06; v10 = word_509C04;*/ } /*if (v20 == 7 && gfCurrentLevel >= 0xBu && gfCurrentLevel <= 0xCu) { word_509C0C = v12 - 512; word_509C04 = v10 - 512; word_509C06 = v11 + 512; word_509C0E = v13 + 512; v19 = 0; }*/ if (TestLaraPosition(PuzzleBounds, item, l)) { PHD_VECTOR pos; pos.x = 0; pos.y = 0; pos.z = 0; /*if (item->objectNumber == ID_PUZZLE_HOLE8 && gfCurrentLevel >= 0xBu && gfCurrentLevel <= 0xCu) { pos.z = coll->midType - 100; if (MoveLaraPosition(&pos, item, l)) { Lara.isMoving = false; l->animNumber = ANIMATION_LARA_STAY_IDLE; l->currentAnimState = STATE_LARA_STOP; l->frameNumber = Anims[l->animNumber].frameBase; //GLOBAL_invkeypadcombination = item->triggerFlags; //GLOBAL_enterinventory = -559038737; } else { Lara.generalPtr = (void*)itemNum; InventoryItemChosen = NO_ITEM } return; }*/ if (!Lara.isMoving) { if (g_Inventory->GetSelectedObject() == NO_ITEM) { if (g_Inventory->IsObjectPresentInInventory(item->objectNumber - 70)) g_Inventory->SetEnterObject(item->objectNumber - 70); item->pos.yRot = oldYrot; return; } if (g_Inventory->GetSelectedObject() != item->objectNumber - 70) { item->pos.yRot = oldYrot; return; } } pos.z = bounds[4] - 100; if (flag != 2 || item->triggerFlags == 1036) { if (!MoveLaraPosition(&pos, item, l)) { Lara.generalPtr = (void*)itemNum; g_Inventory->SetSelectedObject(NO_ITEM); item->pos.yRot = oldYrot; return; } } RemoveObjectFromInventory(item->objectNumber - 70); if (flag == 1) { l->currentAnimState = STATE_LARA_MISC_CONTROL; l->animNumber = -item->triggerFlags; if (l->animNumber != ANIMATION_LARA_PUT_TRIDENT) PuzzleDone(item, itemNum); } else { l->animNumber = ANIMATION_LARA_USE_PUZZLE; l->currentAnimState = STATE_LARA_INSERT_PUZZLE; item->itemFlags[0] = 1; } l->frameNumber = Anims[l->animNumber].frameBase; Lara.isMoving = false; Lara.headYrot = 0; Lara.headXrot = 0; Lara.torsoYrot = 0; Lara.torsoXrot = 0; Lara.gunStatus = 1; item->flags |= 0x20; Lara.generalPtr = (void*)itemNum; g_Inventory->SetSelectedObject(NO_ITEM); item->pos.yRot = oldYrot; return; } if (Lara.isMoving) { if ((short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } } item->pos.yRot = oldYrot; } void PuzzleDoneCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { if (Items[itemNum].triggerFlags - 998 > 1) { ObjectCollision(itemNum, l, coll); } } void KeyHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item = &Items[itemNum]; if (Items[itemNum].triggerFlags == 1 && item->objectNumber == ID_KEY_HOLE8) { if (item->itemFlags[3]) { item->itemFlags[3]--; if (!item->itemFlags[3]) item->meshBits = 2; } } if ((!(TrInput & IN_ACTION) && g_Inventory->GetSelectedObject() == NO_ITEM || BinocularRange || Lara.gunStatus || l->currentAnimState != STATE_LARA_STOP || l->animNumber != ANIMATION_LARA_STAY_IDLE) && (!Lara.isMoving || (short)Lara.generalPtr != itemNum)) { if (item->objectNumber < ID_KEY_HOLE6) ObjectCollision(itemNum, l, coll); } else { if (TestLaraPosition(KeyHoleBounds, item, l)) { if (!Lara.isMoving) { if (item->status != ITEM_INACTIVE) return; if (g_Inventory->GetSelectedObject() == NO_ITEM) { if (g_Inventory->IsObjectPresentInInventory(item->objectNumber - 62)) g_Inventory->SetEnterObject(item->objectNumber - 62); return; } if (g_Inventory->GetSelectedObject() != item->objectNumber - 62) return; } if (MoveLaraPosition(&KeyHolePosition, item, l)) { if (item->objectNumber == ID_KEY_HOLE8) l->animNumber = ANIMATION_LARA_USE_KEYCARD; else { RemoveObjectFromInventory(item->objectNumber - 62); l->animNumber = ANIMATION_LARA_USE_KEY; } l->currentAnimState = STATE_LARA_INSERT_KEY; l->frameNumber = Anims[l->animNumber].frameBase; Lara.isMoving = false; Lara.headYrot = 0; Lara.headXrot = 0; Lara.torsoYrot = 0; Lara.torsoXrot = 0; Lara.gunStatus = LG_HANDS_BUSY; item->flags |= 0x20; item->status = ITEM_ACTIVE; if (item->triggerFlags == 1 && item->objectNumber == ID_KEY_HOLE8) { item->itemFlags[3] = 92; g_Inventory->SetSelectedObject(NO_ITEM); return; } } else { Lara.generalPtr = (void*)itemNum; } g_Inventory->SetSelectedObject(NO_ITEM); return; } if (Lara.isMoving && (short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } } return; } void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item = &Items[itemNum]; short oldXrot = item->pos.xRot; short oldYrot = item->pos.yRot; short oldZrot = item->pos.zRot; if (item->status == ITEM_INVISIBLE) return; short triggerFlags = item->triggerFlags & 0x3F; if (triggerFlags == 5 || triggerFlags == 10) return; if (item->objectNumber == ID_FLARE_ITEM && Lara.gunType == WEAPON_FLARE) return; item->pos.yRot = l->pos.yRot; item->pos.zRot = 0; if (Lara.waterStatus && Lara.waterStatus != LW_WADE) { if (Lara.waterStatus == LW_UNDERWATER) { item->pos.xRot = -ANGLE(25); if (TrInput & IN_ACTION && item->objectNumber != ID_BURNING_TORCH_ITEM && l->currentAnimState == STATE_LARA_UNDERWATER_STOP && !Lara.gunStatus && TestLaraPosition(PickUpBoundsUW, item, l) || Lara.isMoving && (short)Lara.generalPtr == itemNum) { if (TestLaraPosition(PickUpBoundsUW, item, l)) { if (MoveLaraPosition(&PickUpPositionUW, item, l)) { if (item->objectNumber == ID_FLARE_ITEM) { l->animNumber = ANIMATION_LARA_UNDERWATER_FLARE_PICKUP; l->currentAnimState = STATE_LARA_FLARE_PICKUP; l->fallspeed = 0; } else { l->animNumber = ANIMATION_LARA_UNDERWATER_PICKUP; l->currentAnimState = STATE_LARA_PICKUP; } l->goalAnimState = STATE_LARA_UNDERWATER_STOP; l->frameNumber = Anims[l->animNumber].frameBase; Lara.isMoving = false; Lara.gunStatus = LG_HANDS_BUSY; } Lara.generalPtr = (void*)itemNum; } else { if (Lara.isMoving) { if ((short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } } } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if ((short)Lara.generalPtr != itemNum || l->currentAnimState != STATE_LARA_PICKUP || l->frameNumber != Anims[ANIMATION_LARA_UNDERWATER_PICKUP].frameBase + 18) { if ((short)Lara.generalPtr == itemNum && l->currentAnimState == STATE_LARA_FLARE_PICKUP && l->frameNumber == Anims[ANIMATION_LARA_UNDERWATER_FLARE_PICKUP].frameBase + 20) { Lara.requestGunType = WEAPON_FLARE; Lara.gunType = WEAPON_FLARE; InitialiseNewWeapon(); Lara.gunStatus = LG_SPECIAL; Lara.flareAge = (int)(item->data) & 0x7FFF; draw_flare_meshes(); KillItem(itemNum); } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } AddDisplayPickup(item->objectNumber); if (!(item->triggerFlags & 0xC0)) { KillItem(itemNum); } else { item->itemFlags[3] = 1; item->flags |= 0x20; item->status = ITEM_INVISIBLE; } } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if (!(TrInput & IN_ACTION) && (g_Inventory->GetSelectedObject() == NO_ITEM || triggerFlags != 2) || BinocularRange || (l->currentAnimState != STATE_LARA_STOP || l->animNumber != ANIMATION_LARA_STAY_IDLE || Lara.gunStatus) && (l->currentAnimState != STATE_LARA_CROUCH_IDLE || l->animNumber != ANIMATION_LARA_CROUCH_IDLE || Lara.gunStatus) && (l->currentAnimState != STATE_LARA_CRAWL_IDLE || l->animNumber != ANIMATION_LARA_CRAWL_IDLE)) { if (!Lara.isMoving) { if ((short)Lara.generalPtr == itemNum) { if (l->currentAnimState != STATE_LARA_PICKUP && l->currentAnimState != STATE_LARA_HOLE) { if ((short)Lara.generalPtr == itemNum && l->currentAnimState == STATE_LARA_FLARE_PICKUP && (l->animNumber == ANIMATION_LARA_CROUCH_PICKUP_FLARE && l->frameNumber == Anims[ANIMATION_LARA_CROUCH_PICKUP_FLARE].frameBase + 22) || l->frameNumber == Anims[ANIMATION_LARA_FLARE_PICKUP].frameBase + 58) { Lara.requestGunType = WEAPON_FLARE; Lara.gunType = WEAPON_FLARE; InitialiseNewWeapon(); Lara.gunStatus = LG_SPECIAL; Lara.flareAge = (short)(item->data) & 0x7FFF; } else { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } } else { printf("Frame: %d\n", Anims[ANIMATION_LARA_PICKUP].frameBase); if (l->frameNumber == Anims[ANIMATION_LARA_PICKUP].frameBase + 15 || l->frameNumber == Anims[ANIMATION_LARA_CROUCH_PICKUP].frameBase + 22 || l->frameNumber == Anims[ANIMATION_LARA_CROUCH_PICKUP].frameBase + 20 || l->frameNumber == Anims[ANIMATION_LARA_PICKUP_PEDESTAL_LOW].frameBase + 29 || l->frameNumber == Anims[ANIMATION_LARA_PICKUP_PEDESTAL_HIGH].frameBase + 45 || l->frameNumber == Anims[ANIMATION_LARA_HOLE_GRAB].frameBase + 42 || l->frameNumber == Anims[ANIMATION_LARA_CROWBAR_USE_ON_WALL2].frameBase + 183 || (l->animNumber == ANIMATION_LARA_CROWBAR_USE_ON_WALL && l->frameNumber != Anims[ANIMATION_LARA_CROWBAR_USE_ON_WALL].frameBase + 123)) { if (item->objectNumber == ID_BURNING_TORCH_ITEM) { AddDisplayPickup(ID_BURNING_TORCH_ITEM); //sub_402FC7(); Lara.litTorch = (item->itemFlags[3] & 1); KillItem(itemNum); item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } else { if (item->objectNumber != ID_FLARE_ITEM) { AddDisplayPickup(item->objectNumber); if (item->triggerFlags & 0x100) { for (int i = 0; i < LevelItems; i++) { if (Items[i].objectNumber == item->objectNumber) KillItem(i); } } } if (item->triggerFlags & 0xC0) { item->itemFlags[3] = 1; item->flags |= 0x20; item->status = ITEM_INVISIBLE; } } } else { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } } KillItem(itemNum); item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } } if ((short)Lara.generalPtr != itemNum) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } } int flag = 0; short* plinth = NULL; item->pos.xRot = 0; switch (triggerFlags) { case 1: // Pickup from wall hole if (Lara.isDucked || !TestLaraPosition(HiddenPickUpBounds, item, l)) { if(Lara.isMoving) { if ((short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } else if (MoveLaraPosition(&HiddenPickUpPosition, item, l)) { l->animNumber = ANIMATION_LARA_HOLE_GRAB; l->currentAnimState = STATE_LARA_HOLE; flag = 1; } Lara.generalPtr = (void*)itemNum; break; case 2: // Pickup with crowbar item->pos.yRot = oldYrot; if (Lara.isDucked || !TestLaraPosition(CrowbarPickUpBounds, item, l)) { if (!Lara.isMoving) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if ((short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if (!Lara.isMoving) { if (g_Inventory->GetSelectedObject() == NO_ITEM) { if (g_Inventory->IsObjectPresentInInventory(ID_CROWBAR_ITEM)) g_Inventory->SetEnterObject(ID_CROWBAR_ITEM); item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if (g_Inventory->GetSelectedObject() != ID_CROWBAR_ITEM) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } g_Inventory->SetSelectedObject(NO_ITEM); } if (MoveLaraPosition(&CrowbarPickUpPosition, item, l)) { l->animNumber = ANIMATION_LARA_CROWBAR_USE_ON_WALL; l->currentAnimState = STATE_LARA_PICKUP; item->status = ITEM_ACTIVE; AddActiveItem(itemNum); AnimateItem(item); flag = 1; } Lara.generalPtr = (void*)itemNum; break; case 3: case 4: case 7: case 8: plinth = FindPlinth(item); if (!plinth) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } PlinthPickUpBounds[0] = plinth[0]; PlinthPickUpBounds[1] = plinth[1]; PlinthPickUpBounds[3] = l->pos.yPos - item->pos.yPos + 100; PlinthPickUpBounds[5] = plinth[5] + 320; PlinthPickUpPosition.z = -200 - plinth[5]; if (TestLaraPosition(PlinthPickUpBounds, item, l) && !Lara.isDucked) { if (item->pos.yPos == l->pos.yPos) PlinthPickUpPosition.y = 0; else PlinthPickUpPosition.y = l->pos.yPos - item->pos.yPos; if (MoveLaraPosition(&PlinthPickUpPosition, item, l)) { if (triggerFlags == 3 || triggerFlags == 7) { l->animNumber = ANIMATION_LARA_PICKUP_PEDESTAL_HIGH; l->currentAnimState = STATE_LARA_PICKUP; } else { l->animNumber = ANIMATION_LARA_PICKUP_PEDESTAL_LOW; l->currentAnimState = STATE_LARA_PICKUP; } flag = 1; } Lara.generalPtr = (void*)itemNum; break; } if (!Lara.isMoving) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if ((short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; case 9: // Pickup object and conver it to crowbar (like submarine level) item->pos.yRot = oldYrot; if (!TestLaraPosition(JobyCrowPickUpBounds, item, l)) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if (MoveLaraPosition(&JobyCrowPickUpPosition, item, l)) { l->animNumber = ANIMATION_LARA_CROWBAR_USE_ON_WALL2; l->currentAnimState = STATE_LARA_PICKUP; item->status = ITEM_ACTIVE; AddActiveItem(itemNum); flag = 1; } Lara.generalPtr = (void*)itemNum; break; default: if (!TestLaraPosition(PickUpBounds, item, l)) { if (!Lara.isMoving) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } if ((short)Lara.generalPtr == itemNum) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; return; } PickUpPosition.y = l->pos.yPos - item->pos.yPos; if (l->currentAnimState == STATE_LARA_CROUCH_IDLE) { AlignLaraPosition(&PickUpPosition, item, l); if (item->objectNumber == ID_FLARE_ITEM) { l->animNumber = ANIMATION_LARA_CROUCH_PICKUP_FLARE; l->currentAnimState = STATE_LARA_FLARE_PICKUP; flag = 1; Lara.generalPtr = (void*)itemNum; break; } l->animNumber = ANIMATION_LARA_CROUCH_PICKUP; } else { if (l->currentAnimState == STATE_LARA_CRAWL_IDLE) { l->goalAnimState = STATE_LARA_CROUCH_IDLE; Lara.generalPtr = (void*)itemNum; break;; } if (!MoveLaraPosition(&PickUpPosition, item, l)) { Lara.generalPtr = (void*)itemNum; break; } if (item->objectNumber == ID_FLARE_ITEM) { l->animNumber = ANIMATION_LARA_FLARE_PICKUP; l->currentAnimState = STATE_LARA_FLARE_PICKUP; flag = 1; Lara.generalPtr = (void*)itemNum; break; } l->animNumber = ANIMATION_LARA_PICKUP; } l->currentAnimState = STATE_LARA_PICKUP; flag = 1; Lara.generalPtr = (void*)itemNum; } if (flag) { Lara.headYrot = 0; Lara.headXrot = 0; Lara.torsoYrot = 0; Lara.torsoXrot = 0; l->frameNumber = Anims[l->animNumber].frameBase; Lara.isMoving = FAILED_ACCESS_ACE_FLAG; Lara.gunStatus = LG_HANDS_BUSY; } item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; } void RegeneratePickups() { for (int i = 0; i < NumRPickups; i++) { ITEM_INFO* item = &Items[RPickups[i]]; if (item->status == ITEM_INVISIBLE) { short ammo = 0; if (item->objectNumber == ID_CROSSBOW_AMMO1_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_CROSSBOW_AMMO2_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[WEAPON_AMMO2]; else if (item->objectNumber == ID_CROSSBOW_AMMO3_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_CROSSBOW].Ammo[WEAPON_AMMO3]; else if(item->objectNumber == ID_GRENADE_AMMO1_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_GRENADE_AMMO2_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[WEAPON_AMMO2]; else if (item->objectNumber == ID_GRENADE_AMMO3_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_GRENADE_LAUNCHER].Ammo[WEAPON_AMMO3]; else if (item->objectNumber == ID_HK_AMMO_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_HK].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_UZI_AMMO_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_UZI].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_HARPOON_AMMO_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_ROCKET_LAUNCHER_AMMO_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_ROCKET_LAUNCHER].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_REVOLVER_AMMO_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_REVOLVER].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_SHOTGUN_AMMO1_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[WEAPON_AMMO1]; else if (item->objectNumber == ID_SHOTGUN_AMMO1_ITEM) ammo = g_LaraExtra.Weapons[WEAPON_SHOTGUN].Ammo[WEAPON_AMMO2]; if (ammo == 0) { item->status = ITEM_INACTIVE; } } } } void PickupControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; short roomNumber; short triggerFlags = item->triggerFlags & 0x3F; switch (triggerFlags) { case 5: item->fallspeed += 6; item->pos.yPos += item->fallspeed; roomNumber = item->roomNumber; GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); if (item->pos.yPos > item->itemFlags[0]) { item->pos.yPos = item->itemFlags[0]; if (item->fallspeed <= 64) item->triggerFlags &= 0xC0; else item->fallspeed = -item->fallspeed >> 2; } if (item->roomNumber != roomNumber) ItemNewRoom(itemNum, roomNumber); break; case 2: case 6: case 7: case 8: case 9: AnimateItem(item); break; case 11: //sub_401014(itemNum); break; } } short* FindPlinth(ITEM_INFO* item) { ROOM_INFO* room = &Rooms[item->roomNumber]; MESH_INFO* mesh = room->mesh; int found = -1; for (int i = 0; i < room->numMeshes; i++) { MESH_INFO* mesh = &room->mesh[i]; if (mesh->Flags & 1) { if (item->pos.xPos == mesh->x && item->pos.yPos == mesh->y && item->pos.zPos == mesh->z) { short* frame = GetBestFrame(item); STATIC_INFO* s = &StaticObjects[mesh->staticNumber]; if (frame[0] <= s->xMaxc && frame[1] >= s->xMinc && frame[4] <= s->zMaxc && frame[5] >= s->zMinc && (s->xMinc || s->xMaxc)) { found = i; break; } } } } if (found != -1) return &StaticObjects[found].xMinc; if (room->itemNumber == NO_ITEM) return NULL; short itemNumber = room->itemNumber; for (itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = Items[itemNumber].nextItem) { ITEM_INFO* current = &Items[itemNumber]; if (Objects[current->objectNumber].collision != PickupCollision && item->pos.xPos == current->pos.xPos && item->pos.yPos <= current->pos.yPos && item->pos.zPos == current->pos.zPos && (current->objectNumber != ID_HIGH_OBJECT1 || current->itemFlags[0] == 5)) { break; } } if (itemNumber == NO_ITEM) return NULL; else return GetBestFrame(&Items[itemNumber]); } void PuzzleDone(ITEM_INFO* item, short itemNum) { item->objectNumber += 8; item->animNumber = Objects[item->objectNumber].animIndex; item->frameNumber = Anims[item->animNumber].frameBase; item->requiredAnimState = 0; item->goalAnimState = Anims[item->animNumber].currentAnimState; item->currentAnimState = Anims[item->animNumber].currentAnimState; AddActiveItem(itemNum); item->flags |= IFLAG_ACTIVATION_MASK; item->status = ITEM_ACTIVE; /*if (item->triggerFlags == 0x3E6 && LevelItems > 0) { int i; for (i = 0; i < level_items; i++) { if (Items[i].objectNumber == AIRLOCK_SWITCH && Items[i].pos.xPos == item->pos.xPos && Items[i].pos.zPos == item->pos.zPos) { FlipMap(Items[i].triggerFlags - 7); flipmap[Items[i].triggerFlags - 7] ^= IFLAG_ACTIVATION_MASK; Items[i].status = ITEM_INACTIVE; Items[i].flags |= 0x20; } } }*/ } void InitialisePickup(short itemNumber) { ITEM_INFO* item = &Items[itemNumber]; short* bounds = GetBoundsAccurate(item); short triggerFlags = item->triggerFlags & 0x3F; if (triggerFlags == 5) { item->itemFlags[0] = item->pos.yPos - bounds[3]; item->status = ITEM_INVISIBLE; } else { if (triggerFlags == 0 || triggerFlags == 3 || triggerFlags == 4 || triggerFlags == 7 || triggerFlags == 8 || triggerFlags == 11) item->pos.yPos -= bounds[3]; if ((item->triggerFlags & 0x80) != 0) { RPickups[NumRPickups] = itemNumber; NumRPickups++; } if (item->triggerFlags & 0x100) item->meshBits = 0; if (item->status == ITEM_INVISIBLE) item->flags |= 0x20; } } void InitialiseSearchObject(short itemNumber) { ITEM_INFO* item, *item2; short itemNumber2; item = &Items[itemNumber]; if (item->objectNumber == ID_SEARCH_OBJECT1) { item->swapMeshFlags = -1; item->meshBits = 7; } else if (item->objectNumber == ID_SEARCH_OBJECT2) { item->meshBits = 2; } else if (item->objectNumber == ID_SEARCH_OBJECT4) { item->itemFlags[1] = -1; item->meshBits = 9; for (itemNumber2 = 0; itemNumber2 < LevelItems; ++itemNumber2) { item2 = &Items[itemNumber2]; if (item2->objectNumber == 149) /* @FIXME In TRC OBJECTS.H this is the EXPLOSION slot */ { if (item->pos.xPos == item2->pos.xPos && item->pos.yPos == item2->pos.yPos && item->pos.zPos == item2->pos.zPos) { item->itemFlags[1] = itemNumber2; break; } } else if (Objects[item2->objectNumber].collision == PickupCollision && item->pos.xPos == item2->pos.xPos && item->pos.yPos == item2->pos.yPos && item->pos.zPos == item2->pos.zPos) { item->itemFlags[1] = itemNumber2; break; } } AddActiveItem(itemNumber); item->flags |= IFLAG_ACTIVATION_MASK; item->status = ITEM_ACTIVE; } } void SearchObjectCollision(short itemNumber, ITEM_INFO* laraitem, COLL_INFO* laracoll) { ITEM_INFO* item; int objNumber; short* bounds; item = &Items[itemNumber]; objNumber = (item->objectNumber - ID_SEARCH_OBJECT1) / 2; if (TrInput & IN_ACTION && laraitem->currentAnimState == STATE_LARA_STOP && laraitem->animNumber == ANIMATION_LARA_STAY_IDLE && Lara.gunStatus == LG_NO_ARMS && (item->status == ITEM_INACTIVE && item->objectNumber != ID_SEARCH_OBJECT4 || !item->itemFlags[0]) || Lara.isMoving && Lara.generalPtr == (void *) itemNumber) { bounds = GetBoundsAccurate(item); if (item->objectNumber != ID_SEARCH_OBJECT1) { SOBounds[0] = bounds[0] - 128; SOBounds[1] = bounds[1] + 128; } else { SOBounds[0] = bounds[0] + 64; SOBounds[1] = bounds[1] - 64; } SOBounds[4] = bounds[4] - 200; SOBounds[5] = bounds[5] + 200; SOPos.z = bounds[4] - SearchOffsets[objNumber]; if (TestLaraPosition(SOBounds, item, laraitem)) { if (MoveLaraPosition(&SOPos, item, laraitem)) { laraitem->currentAnimState = STATE_LARA_MISC_CONTROL; laraitem->animNumber = SearchAnims[objNumber]; laraitem->frameNumber = Anims[laraitem->animNumber].frameBase; Lara.isMoving = false; Lara.headYrot = 0; Lara.headXrot = 0; Lara.torsoYrot = 0; Lara.torsoXrot = 0; Lara.gunStatus = LG_HANDS_BUSY; if (item->objectNumber == ID_SEARCH_OBJECT4) { item->itemFlags[0] = 1; } else { AddActiveItem(itemNumber); item->status = ITEM_ACTIVE; } item->animNumber = Objects[item->objectNumber].animIndex + 1; item->frameNumber = Anims[item->animNumber].frameBase; AnimateItem(item); } else { Lara.generalPtr = (void *) itemNumber; } } else if (Lara.isMoving && Lara.generalPtr == (void *) itemNumber) { Lara.isMoving = false; Lara.gunStatus = LG_NO_ARMS; } } else if (laraitem->currentAnimState != STATE_LARA_MISC_CONTROL) { ObjectCollision(itemNumber, laraitem, laracoll); } } void SearchObjectControl(short itemNumber) { ITEM_INFO* item, *item2; int objNumber; short frameNumber; item = &Items[itemNumber]; objNumber = (item->objectNumber - ID_SEARCH_OBJECT1) / 2; if (item->objectNumber != ID_SEARCH_OBJECT4 || item->itemFlags[0] == 1) AnimateItem(item); frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if (item->objectNumber == ID_SEARCH_OBJECT1) { if (frameNumber > 0) { item->swapMeshFlags = 0; item->meshBits = -1; } else { item->swapMeshFlags = -1; item->meshBits = 7; } } else if (item->objectNumber == ID_SEARCH_OBJECT2) { if (frameNumber == 18) item->meshBits = 1; else if (frameNumber == 172) item->meshBits = 2; } else if (item->objectNumber == ID_SEARCH_OBJECT4) { item->meshBits = FlipStats[0] != 0 ? 48 : 9; if (frameNumber >= 45 && frameNumber <= 131) item->meshBits |= FlipStats[0] != 0 ? 4 : 2; if (item->itemFlags[1] != -1) { item2 = &Items[item->itemFlags[1]]; if (Objects[item2->objectNumber].collision == PickupCollision) { if (FlipStats[0]) item2->status = ITEM_INACTIVE; else item2->status = ITEM_INVISIBLE; } } } if (frameNumber == SearchCollectFrames[objNumber]) { if (item->objectNumber == ID_SEARCH_OBJECT4) { if (item->itemFlags[1] != -1) { item2 = &Items[item->itemFlags[1]]; if (Objects[item2->objectNumber].collision == PickupCollision) { AddDisplayPickup(item2->objectNumber); KillItem(item->itemFlags[1]); } else { AddActiveItem(item->itemFlags[1]); item2->flags |= IFLAG_ACTIVATION_MASK; item2->status = ITEM_ACTIVE; LaraItem->hitPoints = 640; } item->itemFlags[1] = -1; } } else { CollectCarriedItems(item); } } if (item->status == ITEM_DEACTIVATED) { if (item->objectNumber == ID_SEARCH_OBJECT4) { item->itemFlags[0] = 0; item->status = ITEM_ACTIVE; } else { RemoveActiveItem(itemNumber); item->status = ITEM_INACTIVE; } } } void Inject_Pickup() { INJECT(0x0043A130, DrawAllPickups); INJECT(0x00463B60, PickedUpObject); INJECT(0x0043E260, InitialisePickup); INJECT(0x004679D0, PickupControl); INJECT(0x00467AF0, RegeneratePickups); INJECT(0x00467C00, PickupCollision); INJECT(0x00468770, FindPlinth); INJECT(0x00468930, KeyHoleCollision); INJECT(0x00468C00, PuzzleDoneCollision); INJECT(0x00468C70, PuzzleHoleCollision); INJECT(0x004693A0, PuzzleDone); INJECT(0x00469550, KeyTrigger); INJECT(0x004695E0, PickupTrigger); }