From b57d97aa4763092f9c4823113bdaa2a838dbfd5c Mon Sep 17 00:00:00 2001 From: Lwmte Date: Fri, 10 Dec 2021 11:04:28 +0300 Subject: [PATCH] Refactor pickup system to actually use dispatches (except stupid standing pickup) --- TR5Main/Game/Lara/lara_objects.cpp | 3 + TR5Main/Game/Lara/lara_struct.h | 4 +- TR5Main/Game/Lara/lara_tests.cpp | 2 +- TR5Main/Game/animation.cpp | 10 ++ TR5Main/Game/animation.h | 2 + TR5Main/Game/flipeffect.cpp | 2 +- TR5Main/Game/pickup/pickup.cpp | 228 ++++++++++++++++------------- TR5Main/Game/pickup/pickup.h | 2 +- 8 files changed, 145 insertions(+), 108 deletions(-) diff --git a/TR5Main/Game/Lara/lara_objects.cpp b/TR5Main/Game/Lara/lara_objects.cpp index 343dfb6fe..e97f00b6e 100644 --- a/TR5Main/Game/Lara/lara_objects.cpp +++ b/TR5Main/Game/Lara/lara_objects.cpp @@ -35,6 +35,9 @@ void lara_as_pickup(ITEM_INFO* item, COLL_INFO* coll) Camera.targetAngle = -ANGLE(130.0f); Camera.targetElevation = -ANGLE(15.0f); Camera.targetDistance = WALL_SIZE; + + if (TestLastFrame(item)) + item->goalAnimState = GetNextAnimState(item); } void lara_as_pickupflare(ITEM_INFO* item, COLL_INFO* coll) diff --git a/TR5Main/Game/Lara/lara_struct.h b/TR5Main/Game/Lara/lara_struct.h index 93cf7da71..5d02e9490 100644 --- a/TR5Main/Game/Lara/lara_struct.h +++ b/TR5Main/Game/Lara/lara_struct.h @@ -88,13 +88,13 @@ enum LARA_STATE LS_LADDER_STOP = 59, LS_LADDER_RIGHT = 60, LS_LADDER_DOWN = 61, - LS_TEST_1 = 62, // Used for auto monkey up jump. + LS_MONKEY_VAULT = 62, // Used for auto monkey up jump. LS_TEST_2 = 63, LS_TEST_3 = 64, LS_WADE_FORWARD = 65, LS_UNDERWATER_ROLL = 66, LS_PICKUP_FLARE = 67, - LS_JUMP_ROLL_180 = 68, // Hm? Was SWANDIVE_ROLL in WT. + LS_JUMP_ROLL_180 = 68, LS_KICK = 69, LS_ZIPLINE_RIDE = 70, diff --git a/TR5Main/Game/Lara/lara_tests.cpp b/TR5Main/Game/Lara/lara_tests.cpp index 223ee6658..ded2c0794 100644 --- a/TR5Main/Game/Lara/lara_tests.cpp +++ b/TR5Main/Game/Lara/lara_tests.cpp @@ -223,7 +223,7 @@ bool TestLaraVault(ITEM_INFO* item, COLL_INFO* coll) item->animNumber = LA_STAND_IDLE; item->frameNumber = g_Level.Anims[LA_STAND_IDLE].frameBase; item->goalAnimState = LS_JUMP_UP; - item->currentAnimState = LS_TEST_1; + item->currentAnimState = LS_MONKEY_VAULT; return true; } diff --git a/TR5Main/Game/animation.cpp b/TR5Main/Game/animation.cpp index 2c93ebf5f..76f22228a 100644 --- a/TR5Main/Game/animation.cpp +++ b/TR5Main/Game/animation.cpp @@ -304,6 +304,16 @@ int GetFrameCount(short animNumber) return &g_Level.Anims[animNumber].frameEnd - &g_Level.Anims[animNumber].frameBase; } +int GetNextAnimState(ITEM_INFO* item) +{ + return GetNextAnimState(item->objectNumber, item->animNumber); +} + +int GetNextAnimState(short objectID, short animNumber) +{ + auto nextAnim = g_Level.Anims[Objects[objectID].animIndex + animNumber].jumpAnimNum; + return g_Level.Anims[Objects[objectID].animIndex + nextAnim].currentAnimState; +} void SetAnimation(ITEM_INFO* item, short animIndex, short frameToStart) { diff --git a/TR5Main/Game/animation.h b/TR5Main/Game/animation.h index c895d823e..3f4629e15 100644 --- a/TR5Main/Game/animation.h +++ b/TR5Main/Game/animation.h @@ -59,6 +59,8 @@ void SetAnimation(ITEM_INFO* item, short animIndex, short frameToStart = 0); short GetFrameNumber(ITEM_INFO* item, short frameToStart); short GetFrameNumber(short objectID, short animNumber, short frameToStart); int GetFrameCount(short animNumber); +int GetNextAnimState(ITEM_INFO* item); +int GetNextAnimState(short objectID, short animNumber); int GetChange(ITEM_INFO* item, ANIM_STRUCT* anim); int GetFrame(ITEM_INFO* item, ANIM_FRAME* framePtr[], int* rate); ANIM_FRAME* GetBestFrame(ITEM_INFO* item); diff --git a/TR5Main/Game/flipeffect.cpp b/TR5Main/Game/flipeffect.cpp index fe5efa590..0b0075e5e 100644 --- a/TR5Main/Game/flipeffect.cpp +++ b/TR5Main/Game/flipeffect.cpp @@ -94,7 +94,7 @@ void MeshSwapFromPour(ITEM_INFO* item) void Pickup(ITEM_INFO* item) { - DoPickup(); + DoPickup(item); } void Puzzle(ITEM_INFO* item) diff --git a/TR5Main/Game/pickup/pickup.cpp b/TR5Main/Game/pickup/pickup.cpp index 404d25838..ce26c70ec 100644 --- a/TR5Main/Game/pickup/pickup.cpp +++ b/TR5Main/Game/pickup/pickup.cpp @@ -118,11 +118,11 @@ int GetInventoryCount(GAME_OBJECT_ID objID) void RemoveObjectFromInventory(GAME_OBJECT_ID objID, int count) { // see if the items fit into one of these easy groups - if (!TryRemoveWeapon(Lara, objID, count) - && !TryRemoveAmmo(Lara, objID, count) - && !TryRemoveKeyItem(Lara, objID, count) - && !TryRemoveConsumable(Lara, objID, count) - && !TryRemoveMiscItem(Lara, objID)) + if (!TryRemoveWeapon(Lara, objID, count) && + !TryRemoveAmmo(Lara, objID, count) && + !TryRemoveKeyItem(Lara, objID, count) && + !TryRemoveConsumable(Lara, objID, count) && + !TryRemoveMiscItem(Lara, objID)) { // item isn't any of the above; do nothing } @@ -143,11 +143,13 @@ void CollectCarriedItems(ITEM_INFO* item) item->carriedItem = NO_ITEM; } -void DoPickup() +void DoPickup(ITEM_INFO* character) { if (getThisItemPlease == NO_ITEM) return; + auto lara = (LaraInfo*&)character->data; + short pickupitem = getThisItemPlease; ITEM_INFO* item = &g_Level.Items[pickupitem]; short oldXrot = item->pos.xRot; @@ -158,7 +160,7 @@ void DoPickup() { AddDisplayPickup(ID_BURNING_TORCH_ITEM); GetFlameTorch(); - Lara.litTorch = (item->itemFlags[3] & 1); + lara->litTorch = (item->itemFlags[3] & 1); KillItem(pickupitem); item->pos.xRot = oldXrot; @@ -169,14 +171,14 @@ void DoPickup() } else if (item->objectNumber == ID_FLARE_ITEM) { - if (LaraItem->currentAnimState == LA_UNDERWATER_PICKUP_FLARE) + if (character->currentAnimState == LA_UNDERWATER_PICKUP_FLARE) { - Lara.requestGunType = WEAPON_FLARE; - Lara.gunType = WEAPON_FLARE; - InitialiseNewWeapon(LaraItem); - Lara.gunStatus = LG_SPECIAL; - Lara.flareAge = (int)(item->data) & 0x7FFF; - DrawFlareMeshes(LaraItem); + lara->requestGunType = WEAPON_FLARE; + lara->gunType = WEAPON_FLARE; + InitialiseNewWeapon(character); + lara->gunStatus = LG_SPECIAL; + lara->flareAge = (int)(item->data) & 0x7FFF; + DrawFlareMeshes(character); KillItem(pickupitem); item->pos.xRot = oldXrot; @@ -185,22 +187,21 @@ void DoPickup() getThisItemPlease = NO_ITEM; return; } - else - if (LaraItem->currentAnimState == LS_PICKUP_FLARE) - { - Lara.requestGunType = WEAPON_FLARE; - Lara.gunType = WEAPON_FLARE; - InitialiseNewWeapon(LaraItem); - Lara.gunStatus = LG_SPECIAL; - Lara.flareAge = (short)(item->data) & 0x7FFF; - KillItem(pickupitem); - getThisItemPlease = NO_ITEM; - return; - } + else if (character->currentAnimState == LS_PICKUP_FLARE) + { + lara->requestGunType = WEAPON_FLARE; + lara->gunType = WEAPON_FLARE; + InitialiseNewWeapon(character); + lara->gunStatus = LG_SPECIAL; + lara->flareAge = (short)(item->data) & 0x7FFF; + KillItem(pickupitem); + getThisItemPlease = NO_ITEM; + return; + } } else { - if (LaraItem->animNumber == LA_UNDERWATER_PICKUP) //dirty but what can I do, it uses the same state + if (character->animNumber == LA_UNDERWATER_PICKUP) //dirty but what can I do, it uses the same state { AddDisplayPickup(item->objectNumber); if (!(item->triggerFlags & 0xC0)) @@ -221,13 +222,13 @@ void DoPickup() } else { - if (LaraItem->animNumber == LA_CROWBAR_PRY_WALL_SLOW) + if (character->animNumber == LA_CROWBAR_PRY_WALL_SLOW) { AddDisplayPickup(ID_CROWBAR_ITEM); Lara.Crowbar = true; KillItem(pickupitem); } - else if (LaraItem->currentAnimState == LS_PICKUP || LaraItem->currentAnimState == LS_PICKUP_FROM_CHEST || LaraItem->currentAnimState == LS_HOLE) + else if (character->currentAnimState == LS_PICKUP || character->currentAnimState == LS_PICKUP_FROM_CHEST || character->currentAnimState == LS_HOLE) { AddDisplayPickup(item->objectNumber); if (item->triggerFlags & 0x100) @@ -247,7 +248,7 @@ void DoPickup() item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; item->pos.zRot = oldZrot; - KillItem(pickupitem);//? + KillItem(pickupitem); getThisItemPlease = NO_ITEM; return; } @@ -271,23 +272,25 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) if (triggerFlags == 5 || triggerFlags == 10) return; - if (item->objectNumber == ID_FLARE_ITEM && Lara.gunType == WEAPON_FLARE) + auto lara = (LaraInfo*&)l->data; + + 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 && lara->waterStatus != LW_WADE) { - if (Lara.waterStatus == LW_UNDERWATER) + if (lara->waterStatus == LW_UNDERWATER) { item->pos.xRot = -ANGLE(25); - if (TrInput & IN_ACTION - && item->objectNumber != ID_BURNING_TORCH_ITEM - && l->currentAnimState == LS_UNDERWATER_STOP - && !Lara.gunStatus - && TestLaraPosition(&PickUpBoundsUW, item, l) - || Lara.isMoving && Lara.interactedItem == itemNum) + + if (TrInput & IN_ACTION && + item->objectNumber != ID_BURNING_TORCH_ITEM && + l->currentAnimState == LS_UNDERWATER_STOP && + !lara->gunStatus && + TestLaraPosition(&PickUpBoundsUW, item, l) || lara->isMoving && lara->interactedItem == itemNum) { if (TestLaraPosition(&PickUpBoundsUW, item, l)) { @@ -308,20 +311,20 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) } l->goalAnimState = LS_UNDERWATER_STOP; l->frameNumber = g_Level.Anims[l->animNumber].frameBase; - Lara.isMoving = false; - Lara.gunStatus = LG_HANDS_BUSY; + lara->isMoving = false; + lara->gunStatus = LG_HANDS_BUSY; } - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; } else { - if (Lara.isMoving) + if (lara->isMoving) { - if (Lara.interactedItem == itemNum) + if (lara->interactedItem == itemNum) { getThisItemPlease = itemNum; - Lara.isMoving = false; - Lara.gunStatus = LG_NO_ARMS; + lara->isMoving = false; + lara->gunStatus = LG_NO_ARMS; } } } @@ -340,15 +343,15 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) } if (!(TrInput & IN_ACTION) && - (g_Gui.GetInventoryItemChosen() == NO_ITEM || triggerFlags != 2) - || BinocularRange - || (l->currentAnimState != LS_STOP || l->animNumber != LA_STAND_IDLE || Lara.gunStatus) - && (l->currentAnimState != LS_CROUCH_IDLE || l->animNumber != LA_CROUCH_IDLE || Lara.gunStatus) - && (l->currentAnimState != LS_CRAWL_IDLE || l->animNumber != LA_CRAWL_IDLE)) + (g_Gui.GetInventoryItemChosen() == NO_ITEM || triggerFlags != 2) || + BinocularRange || + (l->currentAnimState != LS_STOP || l->animNumber != LA_STAND_IDLE || lara->gunStatus) && + (l->currentAnimState != LS_CROUCH_IDLE || l->animNumber != LA_CROUCH_IDLE || lara->gunStatus) && + (l->currentAnimState != LS_CRAWL_IDLE || l->animNumber != LA_CRAWL_IDLE)) { - if (!Lara.isMoving) + if (!lara->isMoving) { - if (Lara.interactedItem == itemNum) + if (lara->interactedItem == itemNum) { if (l->currentAnimState != LS_PICKUP && l->currentAnimState != LS_HOLE) { @@ -369,7 +372,7 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) } } - if (Lara.interactedItem != itemNum) + if (lara->interactedItem != itemNum) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; @@ -384,14 +387,14 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) switch (triggerFlags) { case 1: // Pickup from wall hole - if (Lara.isDucked || !TestLaraPosition(&HiddenPickUpBounds, item, l)) + if (lara->isDucked || !TestLaraPosition(&HiddenPickUpBounds, item, l)) { - if(Lara.isMoving) + if (lara->isMoving) { - if (Lara.interactedItem == itemNum) + if (lara->interactedItem == itemNum) { - Lara.isMoving = false; - Lara.gunStatus = LG_NO_ARMS; + lara->isMoving = false; + lara->gunStatus = LG_NO_ARMS; } } @@ -407,14 +410,14 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) l->currentAnimState = LS_HOLE; flag = 1; } - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; break; case 2: // Pickup with crowbar item->pos.yRot = oldYrot; - if (Lara.isDucked || !TestLaraPosition(&CrowbarPickUpBounds, item, l)) + if (lara->isDucked || !TestLaraPosition(&CrowbarPickUpBounds, item, l)) { - if (!Lara.isMoving) + if (!lara->isMoving) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; @@ -422,10 +425,10 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) return; } - if (Lara.interactedItem == itemNum) + if (lara->interactedItem == itemNum) { - Lara.isMoving = false; - Lara.gunStatus = LG_NO_ARMS; + lara->isMoving = false; + lara->gunStatus = LG_NO_ARMS; } item->pos.xRot = oldXrot; @@ -433,7 +436,7 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) item->pos.zRot = oldZrot; return; } - if (!Lara.isMoving) + if (!lara->isMoving) { if (g_Gui.GetInventoryItemChosen() == NO_ITEM) { @@ -467,7 +470,7 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) flag = 1; } - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; break; case 3: @@ -489,7 +492,7 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) PlinthPickUpBounds.boundingBox.Z2 = plinth->Z2 + 320; PlinthPickUpPosition.z = -200 - plinth->Z2; - if (TestLaraPosition(&PlinthPickUpBounds, item, l) && !Lara.isDucked) + if (TestLaraPosition(&PlinthPickUpBounds, item, l) && !lara->isDucked) { if (item->pos.yPos == l->pos.yPos) PlinthPickUpPosition.y = 0; @@ -511,11 +514,11 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) } flag = 1; } - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; break; } - if (!Lara.isMoving) + if (!lara->isMoving) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; @@ -523,10 +526,10 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) return; } - if (Lara.interactedItem == itemNum) + if (lara->interactedItem == itemNum) { - Lara.isMoving = false; - Lara.gunStatus = LG_NO_ARMS; + lara->isMoving = false; + lara->gunStatus = LG_NO_ARMS; } item->pos.xRot = oldXrot; @@ -552,13 +555,13 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) AddActiveItem(itemNum); flag = 1; } - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; break; default: if (!TestLaraPosition(&PickUpBounds, item, l)) { - if (!Lara.isMoving) + if (!lara->isMoving) { item->pos.xRot = oldXrot; item->pos.yRot = oldYrot; @@ -566,10 +569,10 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) return; } - if (Lara.interactedItem == itemNum) + if (lara->interactedItem == itemNum) { - Lara.isMoving = false; - Lara.gunStatus = LG_NO_ARMS; + lara->isMoving = false; + lara->gunStatus = LG_NO_ARMS; } item->pos.xRot = oldXrot; @@ -591,11 +594,11 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) l->animNumber = LA_CROUCH_PICKUP_FLARE; l->currentAnimState = LS_PICKUP_FLARE; flag = 1; - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; break; } getThisItemPlease = itemNum; - l->animNumber = LA_CROUCH_PICKUP; + l->goalAnimState = LS_PICKUP; } else { @@ -603,41 +606,60 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { if (item->objectNumber == ID_BURNING_TORCH_ITEM) break; - l->goalAnimState = LS_CROUCH_IDLE; - Lara.interactedItem = itemNum; + + AlignLaraPosition(&PickUpPosition, item, l); + + if (item->objectNumber == ID_FLARE_ITEM) + { + l->goalAnimState = LS_CROUCH_IDLE; + lara->interactedItem = itemNum; + } + else + { + getThisItemPlease = itemNum; + l->goalAnimState = LS_PICKUP; + } break; } - if (!MoveLaraPosition(&PickUpPosition, item, l)) - { - Lara.interactedItem = itemNum; - break; - } - if (item->objectNumber == ID_FLARE_ITEM) + else { + if (!MoveLaraPosition(&PickUpPosition, item, l)) + { + lara->interactedItem = itemNum; + break; + } + getThisItemPlease = itemNum; - l->animNumber = LA_PICKUP; - l->currentAnimState = LS_PICKUP_FLARE; - flag = 1; - Lara.interactedItem = itemNum; - break; + + if (item->objectNumber == ID_FLARE_ITEM) + { + l->animNumber = LA_PICKUP; + l->currentAnimState = LS_PICKUP_FLARE; + flag = 1; + lara->interactedItem = itemNum; + break; + } + else + { + // HACK: because of MoveLaraPosition(), we can't properly dispatch. Must be fixed later. + l->animNumber = LA_PICKUP; + l->currentAnimState = LS_PICKUP; + } } - getThisItemPlease = itemNum; - l->animNumber = LA_PICKUP; } - l->currentAnimState = LS_PICKUP; flag = 1; - Lara.interactedItem = itemNum; + lara->interactedItem = itemNum; } if (flag) { - Lara.headYrot = 0; - Lara.headXrot = 0; - Lara.torsoYrot = 0; - Lara.torsoXrot = 0; + lara->headYrot = 0; + lara->headXrot = 0; + lara->torsoYrot = 0; + lara->torsoXrot = 0; l->frameNumber = g_Level.Anims[l->animNumber].frameBase; - Lara.isMoving = false; - Lara.gunStatus = LG_HANDS_BUSY; + lara->isMoving = false; + lara->gunStatus = LG_HANDS_BUSY; } item->pos.xRot = oldXrot; diff --git a/TR5Main/Game/pickup/pickup.h b/TR5Main/Game/pickup/pickup.h index 1e88164e5..4d187bb3d 100644 --- a/TR5Main/Game/pickup/pickup.h +++ b/TR5Main/Game/pickup/pickup.h @@ -24,5 +24,5 @@ void PickupControl(short itemNum); void InitialiseSearchObject(short itemNumber); void SearchObjectCollision(short itemNumber, ITEM_INFO* laraitem, COLL_INFO* laracoll); void SearchObjectControl(short itemNumber); -void DoPickup(); +void DoPickup(ITEM_INFO* character); int UseSpecialItem(ITEM_INFO* item); \ No newline at end of file