TombEngine/TR5Main/Game/Lara/lara_objects.cpp

1183 lines
26 KiB
C++
Raw Normal View History

#include "framework.h"
#include "lara.h"
#include "input.h"
2021-09-19 18:29:25 +03:00
#include "level.h"
#include "Sound/sound.h"
#include "animation.h"
#include "rope.h"
#include "camera.h"
#include "collide.h"
2021-09-19 23:41:26 +03:00
#include "items.h"
#include "control/control.h"
#include "Objects/Generic/Object/rope.h"
using namespace TEN::Entities::Generic;
2021-09-09 11:10:25 +03:00
2021-11-21 20:50:17 +11:00
// -----------------------------------
// MISCELLANEOUS INTERACTABLE OBJECTS
// State Control & Collision Functions
// -----------------------------------
// ------
// PICKUP
// ------
2021-02-03 01:50:59 -03:00
void lara_as_pickup(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 39, 98*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = -ANGLE(130.0f);
Camera.targetElevation = -ANGLE(15.0f);
2021-11-22 22:47:34 +11:00
Camera.targetDistance = WALL_SIZE;
}
2021-02-03 01:50:59 -03:00
void lara_as_pickupflare(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 67*/
/*collison: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = ANGLE(130.0f);
Camera.targetElevation = -ANGLE(15.0f);
2021-11-22 22:47:34 +11:00
Camera.targetDistance = WALL_SIZE;
if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd - 1)
2021-11-22 22:47:34 +11:00
info->gunStatus = LG_NO_ARMS;
}
2021-11-21 20:50:17 +11:00
// ------
// SWITCH
// ------
2021-02-03 01:50:59 -03:00
void lara_as_switchon(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*states 40, 126*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
2021-11-22 22:47:34 +11:00
Camera.targetDistance = WALL_SIZE;
Camera.speed = 6;
}
2021-02-03 01:50:59 -03:00
void lara_as_switchoff(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 41*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
2021-11-22 22:47:34 +11:00
Camera.targetDistance = WALL_SIZE;
Camera.speed = 6;
}
2021-02-03 01:50:59 -03:00
void lara_col_turnswitch(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 95*/
/*state code: lara_as_controlledl*/
2021-09-10 00:20:59 +03:00
if (coll->Setup.OldPosition.x != item->pos.xPos || coll->Setup.OldPosition.z != item->pos.zPos)
{
if (item->animNumber == LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_CONTINUE)
{
item->pos.yRot -= ANGLE(90.0f);
item->animNumber = LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
}
if (item->animNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_CONTINUE)
{
item->pos.yRot += ANGLE(90.0f);
item->animNumber = LA_TURNSWITCH_PUSH_CLOCKWISE_END;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
}
}
}
2021-11-21 20:50:17 +11:00
// ----------
// RECEPTACLE
// ----------
2021-02-03 01:50:59 -03:00
void lara_as_usekey(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 42*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = -ANGLE(80.0f);
2021-11-22 22:47:34 +11:00
Camera.targetElevation = -ANGLE(25.0f);
Camera.targetDistance = WALL_SIZE;
}
2021-02-03 01:50:59 -03:00
void lara_as_usepuzzle(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 43*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = -ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
2021-11-22 22:47:34 +11:00
Camera.targetDistance = WALL_SIZE;
if (TestLastFrame(item))
{
if (item->itemFlags[0])
{
item->animNumber = item->itemFlags[0];
item->currentAnimState = LS_MISC_CONTROL;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
}
}
}
2021-11-21 20:50:17 +11:00
// --------
// PUSHABLE
// --------
2021-02-03 01:50:59 -03:00
void lara_as_pushblock(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 36*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.flags = CF_FOLLOW_CENTER;
Camera.targetAngle = ANGLE(35.0f);
Camera.targetElevation = -ANGLE(25.0f);
Camera.laraNode = LM_TORSO;
}
2021-02-03 01:50:59 -03:00
void lara_as_pullblock(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 37*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.flags = CF_FOLLOW_CENTER;
Camera.targetAngle = ANGLE(35.0f);
Camera.targetElevation = -ANGLE(25.0f);
Camera.laraNode = LM_TORSO;
}
2021-02-03 01:50:59 -03:00
void lara_as_ppready(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 38*/
/*collision: lara_default_col*/
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.targetAngle = ANGLE(75.0f);
2021-11-22 22:47:34 +11:00
if (!(TrInput & IN_ACTION))
item->goalAnimState = LS_STOP;
}
2021-11-21 20:50:17 +11:00
// ------
// PULLEY
// ------
2021-02-03 01:50:59 -03:00
void lara_as_pulley(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 104*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
ITEM_INFO* pulley = &g_Level.Items[info->interactedItem];
2021-11-22 22:47:34 +11:00
info->look = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableSpaz = false;
coll->Setup.EnableObjectPush = false;
2021-06-08 06:32:51 +02:00
if (TrInput & IN_ACTION && pulley->triggerFlags)
item->goalAnimState = LS_PULLEY;
else
item->goalAnimState = LS_STOP;
2021-11-22 22:47:34 +11:00
if (item->animNumber == LA_PULLEY_PULL &&
item->frameNumber == g_Level.Anims[item->animNumber].frameBase + 44)
{
2021-06-08 06:32:51 +02:00
if (pulley->triggerFlags)
{
2021-06-08 06:32:51 +02:00
if (!pulley->itemFlags[1])
{
2021-06-08 06:32:51 +02:00
pulley->triggerFlags--;
if (pulley->triggerFlags)
{
2021-06-08 06:32:51 +02:00
if (pulley->itemFlags[2])
{
pulley->itemFlags[2] = 0;
pulley->status = ITEM_DEACTIVATED;
}
}
else
2021-06-08 06:32:51 +02:00
{
pulley->status = ITEM_DEACTIVATED;
pulley->itemFlags[2] = 1;
2021-11-22 22:47:34 +11:00
2021-06-08 06:32:51 +02:00
if (pulley->itemFlags[3] >= 0)
pulley->triggerFlags = abs(pulley->itemFlags[3]);
else
pulley->itemFlags[0] = 1;
}
}
}
}
2021-11-22 22:47:34 +11:00
if (item->animNumber == LA_PULLEY_RELEASE &&
item->frameNumber == g_Level.Anims[item->animNumber].frameEnd - 1)
{
info->gunStatus = LG_NO_ARMS;
}
}
2021-11-21 20:50:17 +11:00
// --------------
// HORIZONTAL BAR
// --------------
void lara_as_parallelbars(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 128*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
if (!(TrInput & IN_ACTION) || TrInput & IN_JUMP)
item->goalAnimState = LS_BARS_JUMP;
}
2021-02-03 01:50:59 -03:00
void lara_as_pbleapoff(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 129*/
/*collision: lara_default_col*/
2021-11-22 22:47:34 +11:00
ITEM_INFO* barItem = &g_Level.Items[Lara.interactedItem];
item->gravityStatus = true;
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase)
{
int dist;
2021-11-22 22:47:34 +11:00
if (item->pos.yRot == barItem->pos.yRot)
dist = barItem->triggerFlags / 100 - 2;
else
2021-11-22 22:47:34 +11:00
dist = barItem->triggerFlags % 100 - 2;
item->fallspeed = -(20 * dist + 64);
item->speed = 20 * dist + 58;
}
if (TestLastFrame(item))
{
2021-11-22 22:47:34 +11:00
SetAnimation(item, LA_REACH);
2020-10-05 22:24:57 -03:00
item->pos.xPos += 700 * phd_sin(item->pos.yRot);
item->pos.yPos -= 361;
2020-10-05 22:24:57 -03:00
item->pos.zPos += 700 * phd_cos(item->pos.yRot);
}
}
2021-11-21 20:50:17 +11:00
// ---------
// TIGHTROPE
// ---------
#ifdef NEW_TIGHTROPE
2021-11-21 00:04:28 +11:00
void lara_trbalance_mesh(ITEM_INFO* item)
{
LaraInfo*& info = item->data;
item->pos.zRot = info->tightrope.balance / 4;
info->torsoZrot = -info->tightrope.balance;
}
2021-11-21 00:04:28 +11:00
void lara_trbalance_regen(ITEM_INFO* item)
{
LaraInfo*& info = item->data;
if (info->tightrope.timeOnTightrope <= 32)
info->tightrope.timeOnTightrope = 0;
else
2021-11-21 00:04:28 +11:00
info->tightrope.timeOnTightrope -= 32;
if (info->tightrope.balance > 0)
{
2021-11-22 22:47:34 +11:00
if (info->tightrope.balance <= ANGLE(0.75f))
2021-11-21 00:04:28 +11:00
info->tightrope.balance = 0;
else
2021-11-22 22:47:34 +11:00
info->tightrope.balance -= ANGLE(0.75f);
}
2021-11-21 00:04:28 +11:00
if (info->tightrope.balance < 0)
{
2021-11-22 22:47:34 +11:00
if (info->tightrope.balance >= -ANGLE(0.75f))
2021-11-21 00:04:28 +11:00
info->tightrope.balance = 0;
else
2021-11-22 22:47:34 +11:00
info->tightrope.balance += ANGLE(0.75f);
}
}
2021-11-21 00:04:28 +11:00
void lara_trbalance(ITEM_INFO* item)
{
LaraInfo*& info = item->data;
const int factor = ((info->tightrope.timeOnTightrope >> 7) & 0xFF) * 128;
if (TrInput & IN_LEFT)
2021-11-22 22:47:34 +11:00
info->tightrope.balance += ANGLE(1.4f);
2021-11-21 00:04:28 +11:00
if (TrInput & IN_RIGHT)
2021-11-22 22:47:34 +11:00
info->tightrope.balance -= ANGLE(1.4f);
2021-11-21 00:04:28 +11:00
if (info->tightrope.balance < 0)
{
2021-11-21 00:04:28 +11:00
info->tightrope.balance -= factor;
2021-11-22 22:47:34 +11:00
if (info->tightrope.balance <= -ANGLE(45.0f))
info->tightrope.balance = ANGLE(45.0f);
2021-11-21 00:04:28 +11:00
}
else if (info->tightrope.balance > 0)
{
info->tightrope.balance += factor;
2021-11-22 22:47:34 +11:00
if (info->tightrope.balance >= ANGLE(45.0f))
info->tightrope.balance = ANGLE(45.0f);
2021-11-21 00:04:28 +11:00
}
else
info->tightrope.balance = GetRandomControl() & 1 ? -1 : 1;
}
void lara_as_trpose(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 00:04:28 +11:00
if (TrInput & IN_LOOK)
LookUpDown();
2021-11-21 00:04:28 +11:00
lara_trbalance_regen(item);
lara_trbalance_mesh(item);
if (TrInput & IN_FORWARD)
item->goalAnimState = LS_TIGHTROPE_FORWARD;
2021-11-21 00:04:28 +11:00
else if (TrInput & (IN_ROLL | IN_BACK))
{
2021-11-21 00:04:28 +11:00
if (item->animNumber == LA_TIGHTROPE_IDLE)
{
item->currentAnimState = LS_TIGHTROPE_TURN_180;
item->animNumber = LA_TIGHTROPE_TURN_180;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
}
}
}
2021-11-21 00:04:28 +11:00
void lara_as_trexit(ITEM_INFO* item, COLL_INFO* coll)
{
LaraInfo*& info = item->data;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
2021-11-21 00:04:28 +11:00
lara_trbalance_regen(item);
lara_trbalance_mesh(item);
if (item->animNumber == LA_TIGHTROPE_END &&
TestLastFrame(item))
{
2021-11-21 00:04:28 +11:00
info->torsoZrot = 0;
item->pos.zRot = 0;
}
}
2021-11-21 00:04:28 +11:00
void lara_as_trwalk(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 00:04:28 +11:00
LaraInfo*& info = item->data;
auto probe = GetCollisionResult(item);
if (probe.Position.Floor == item->pos.yPos &&
info->tightrope.canGoOff)
{
2021-11-21 00:04:28 +11:00
lara_trbalance_regen(item);
item->goalAnimState = LS_TIGHTROPE_EXIT;
}
2021-11-21 00:04:28 +11:00
if (item->goalAnimState != LS_TIGHTROPE_EXIT &&
(TrInput & (IN_BACK | IN_ROLL) || !(TrInput & IN_FORWARD)))
{
item->goalAnimState = LS_TIGHTROPE_IDLE;
}
2021-11-21 00:04:28 +11:00
info->tightrope.timeOnTightrope++;
lara_trbalance(item);
lara_trbalance_mesh(item);
if (info->tightrope.balance >= 8000)
SetAnimation(item, LA_TIGHTROPE_FALL_RIGHT);
else if (info->tightrope.balance <= -8000)
SetAnimation(item, LA_TIGHTROPE_FALL_LEFT);
}
2021-11-21 00:04:28 +11:00
void lara_as_trfall(ITEM_INFO* item, COLL_INFO* coll)
{
/*states 122, 123*/
/*collision: lara_default_col*/
2021-11-21 00:04:28 +11:00
lara_trbalance_regen(item);
lara_trbalance_mesh(item);
if (TestLastFrame(item))
2021-11-21 00:04:28 +11:00
{
PHD_VECTOR pos{ 0, 75, 0 };
GetLaraJointPosition(&pos, LM_RFOOT);
item->pos.xPos = pos.x;
2021-11-21 00:04:28 +11:00
item->pos.yPos = pos.y;
item->pos.zPos = pos.z;
item->goalAnimState = LS_FREEFALL;
item->currentAnimState = LS_FREEFALL;
item->animNumber = LA_FREEFALL;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->fallspeed = 81;
Camera.targetspeed = 16;
}
}
#else
void lara_as_trpose(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 119*/
/*collision: lara_default_col*/
if (TrInput & IN_LOOK)
LookUpDown();
GetTighRopeFallOff(127);
2021-11-22 22:47:34 +11:00
if (LaraItem->currentAnimState != LS_TIGHTROPE_UNBALANCE_LEFT)
{
if (Lara.tightRopeFall)
{
if (GetRandomControl() & 1)
item->goalAnimState = LS_TIGHTROPE_UNBALANCE_RIGHT;
else
item->goalAnimState = LS_TIGHTROPE_UNBALANCE_LEFT;
}
else
{
if (TrInput & IN_FORWARD)
item->goalAnimState = LS_TIGHTROPE_FORWARD;
2021-11-22 22:47:34 +11:00
else if (TrInput & (IN_ROLL | IN_BACK))
{
if (item->animNumber == LA_TIGHTROPE_IDLE)
{
item->currentAnimState = LS_TIGHTROPE_TURN_180;
item->animNumber = LA_TIGHTROPE_TURN_180;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
GetTighRopeFallOff(1);
}
}
}
}
}
void lara_as_trwalk(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 121*/
/*collision: lara_default_col*/
if (Lara.tightRopeOnCount)
Lara.tightRopeOnCount--;
else if (Lara.tightRopeOff)
{
short roomNumber = item->roomNumber;
if (GetFloorHeight(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber),
item->pos.xPos, item->pos.yPos, item->pos.zPos) == item->pos.yPos)
{
Lara.tightRopeOff = 0;
item->goalAnimState = LS_TIGHTROPE_EXIT;
}
}
else
GetTighRopeFallOff(127);
2021-11-22 22:47:34 +11:00
if (item->currentAnimState != LS_TIGHTROPE_UNBALANCE_LEFT)
{
if (TrInput & IN_LOOK)
LookUpDown();
2021-11-22 22:47:34 +11:00
if ((Lara.tightRopeFall || (TrInput & (IN_BACK | IN_ROLL) || !(TrInput & IN_FORWARD)) && !Lara.tightRopeOnCount && !Lara.tightRopeOff) &&
item->goalAnimState != LS_TIGHTROPE_EXIT)
{
item->goalAnimState = LS_TIGHTROPE_IDLE;
}
}
}
void lara_as_trfall(ITEM_INFO* item, COLL_INFO* coll)
{
/*states 122, 123*/
/*collision: lara_default_col*/
if (item->animNumber == LA_TIGHTROPE_FALL_LEFT || item->animNumber == LA_TIGHTROPE_FALL_RIGHT)
{
if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd)
{
PHD_VECTOR pos;
pos.x = 0;
pos.y = 0;
pos.z = 0;
GetLaraJointPosition(&pos, LM_RFOOT);
item->pos.xPos = pos.x;
item->pos.yPos = pos.y + 75;
item->pos.zPos = pos.z;
item->goalAnimState = LS_FREEFALL;
item->currentAnimState = LS_FREEFALL;
item->animNumber = LA_FREEFALL;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->fallspeed = 81;
Camera.targetspeed = 16;
}
}
else
{
int undoInp, wrongInput;
int undoAnim, undoFrame;
if (Lara.tightRopeOnCount > 0)
Lara.tightRopeOnCount--;
if (item->animNumber == LA_TIGHTROPE_UNBALANCE_LEFT)
{
undoInp = IN_RIGHT;
wrongInput = IN_LEFT;
undoAnim = LA_TIGHTROPE_RECOVER_LEFT;
}
else if (item->animNumber == LA_TIGHTROPE_UNBALANCE_RIGHT)
{
undoInp = IN_LEFT;
wrongInput = IN_RIGHT;
undoAnim = LA_TIGHTROPE_RECOVER_RIGHT;
}
else
return;
undoFrame = g_Level.Anims[item->animNumber].frameEnd + g_Level.Anims[undoAnim].frameBase - item->frameNumber;
if (TrInput & undoInp && Lara.tightRopeOnCount == 0)
{
item->currentAnimState = LS_TIGHTROPE_RECOVER_BALANCE;
item->goalAnimState = LS_TIGHTROPE_IDLE;
item->animNumber = undoAnim;
item->frameNumber = undoFrame;
Lara.tightRopeFall--;
}
else
{
if (TrInput & wrongInput)
{
if (Lara.tightRopeOnCount < 10)
Lara.tightRopeOnCount += (GetRandomControl() & 3) + 2;
}
}
}
}
2021-11-21 20:50:17 +11:00
#endif
// ----
// ROPE
// ----
2021-02-03 01:50:59 -03:00
void lara_as_ropel(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 90*/
/*collision: lara_void_func*/
if (TrInput & IN_ACTION)
{
if (TrInput & IN_LEFT)
2021-11-22 22:47:34 +11:00
Lara.ropeY += ANGLE(1.4f);
else
item->goalAnimState = LS_ROPE_IDLE;
}
else
FallFromRope(item);
}
2021-02-03 01:50:59 -03:00
void lara_as_roper(ITEM_INFO* item, COLL_INFO* coll)
{
if (TrInput & IN_ACTION)
{
if (TrInput & IN_RIGHT)
2021-11-22 22:47:34 +11:00
Lara.ropeY -= ANGLE(1.4f);
else
item->goalAnimState = LS_ROPE_IDLE;
}
else
FallFromRope(item);
}
2021-02-03 01:50:59 -03:00
void lara_as_rope(ITEM_INFO* item, COLL_INFO* coll)
{
/*states 111, 114, 115*/
/*collison: lara_col_rope(111), lara_col_ropefwd(114, 115)*/
if (!(TrInput & IN_ACTION))
FallFromRope(item);
if (TrInput & IN_LOOK)
LookUpDown();
}
2021-02-03 01:50:59 -03:00
void lara_col_rope(ITEM_INFO* item, COLL_INFO* coll)
{
/*state: 111*/
/*state code: lara_as_rope*/
if (TrInput & IN_ACTION)
{
UpdateRopeSwing(item);
if (TrInput & IN_SPRINT)
{
Lara.ropeDFrame = (g_Level.Anims[LA_ROPE_SWING].frameBase + 32) << 8;
Lara.ropeFrame = Lara.ropeDFrame;
item->goalAnimState = LS_ROPE_SWING;
}
else if (TrInput & IN_FORWARD && Lara.ropeSegment > 4)
item->goalAnimState = LS_ROPE_UP;
else if (TrInput & IN_BACK && Lara.ropeSegment < 21)
{
item->goalAnimState = LS_ROPE_DOWN;
Lara.ropeFlag = 0;
Lara.ropeCount = 0;
}
else if (TrInput & IN_LEFT)
item->goalAnimState = LS_ROPE_TURN_CLOCKWISE;
else if (TrInput & IN_RIGHT)
item->goalAnimState = LS_ROPE_TURN_COUNTER_CLOCKWISE;
}
else
FallFromRope(item);
}
2021-02-03 01:50:59 -03:00
void lara_col_ropefwd(ITEM_INFO* item, COLL_INFO* coll)
{
/*states 114, 115*/
/*state code: lara_as_rope(for both)*/
Camera.targetDistance = SECTOR(2);
UpdateRopeSwing(item);
if (item->animNumber == LA_ROPE_SWING)
{
if (TrInput & IN_SPRINT)
{
int vel;
if (abs(Lara.ropeLastX) < 9000)
vel = 192 * (9000 - abs(Lara.ropeLastX)) / 9000;
else
vel = 0;
ApplyVelocityToRope(Lara.ropeSegment - 2,
item->pos.yRot + (Lara.ropeDirection ? ANGLE(0.0f) : ANGLE(180.0f)),
vel >> 5);
}
if (Lara.ropeFrame > Lara.ropeDFrame)
{
Lara.ropeFrame -= (unsigned short)Lara.ropeFrameRate;
if (Lara.ropeFrame < Lara.ropeDFrame)
Lara.ropeFrame = Lara.ropeDFrame;
}
else if (Lara.ropeFrame < Lara.ropeDFrame)
{
Lara.ropeFrame += (unsigned short)Lara.ropeFrameRate;
if (Lara.ropeFrame > Lara.ropeDFrame)
Lara.ropeFrame = Lara.ropeDFrame;
}
item->frameNumber = Lara.ropeFrame >> 8;
if (!(TrInput & IN_SPRINT) &&
item->frameNumber == g_Level.Anims[LA_ROPE_SWING].frameBase + 32 &&
Lara.ropeMaxXBackward < 6750 &&
Lara.ropeMaxXForward < 6750)
{
item->animNumber = LA_JUMP_UP_TO_ROPE_END;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_ROPE_IDLE;
item->goalAnimState = LS_ROPE_IDLE;
}
if (TrInput & IN_JUMP)
JumpOffRope(item);
}
else if (item->frameNumber == g_Level.Anims[LA_ROPE_IDLE_TO_SWING].frameBase + 15)
ApplyVelocityToRope(Lara.ropeSegment, item->pos.yRot, 128);
}
2021-02-03 01:50:59 -03:00
void lara_as_climbrope(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 112*/
/*collision: lara_void_func*/
if (TrInput & IN_ROLL)
FallFromRope(item);
else
{
Camera.targetAngle = ANGLE(30.0f);
if (g_Level.Anims[item->animNumber].frameEnd == item->frameNumber)
{
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
Lara.ropeSegment -= 2;
}
if (!(TrInput & IN_FORWARD) || Lara.ropeSegment <= 4)
item->goalAnimState = LS_ROPE_IDLE;
}
}
2021-02-03 01:50:59 -03:00
void lara_as_climbroped(ITEM_INFO* item, COLL_INFO* coll)
{
/*state 113*/
/*collision: lara_void_func*/
LaraClimbRope(item, coll);
}
2021-11-21 20:50:17 +11:00
// -------------
// VERTICAL POLE
// -------------
// TODO: Move test functions to lara_tests.cpp when lara_state_cleaning_etc branch is merged.
bool TestLaraPoleUp(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 20:50:17 +11:00
// TODO: Accuracy.
return (coll->Middle.Ceiling < -STEP_SIZE);
}
bool TestLaraPoleDown(ITEM_INFO* item, COLL_INFO* coll)
{
return (coll->Middle.Floor > 0);
}
// State: LS_POLE_IDLE (99)
// Collision: lara_col_pole_idle()
void lara_as_pole_idle(ITEM_INFO* item, COLL_INFO* coll)
{
LaraInfo*& info = item->data;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableSpaz = false;
coll->Setup.EnableObjectPush = false;
2021-11-21 20:50:17 +11:00
if (item->hitPoints <= 0)
{
2021-11-21 20:50:17 +11:00
item->goalAnimState = LS_FREEFALL; // TODO: Death state dispatch.
2021-11-21 20:50:17 +11:00
return;
}
2021-11-21 20:50:17 +11:00
if (TrInput & IN_LOOK)
LookUpDown();
2021-11-21 20:50:17 +11:00
if (TrInput & IN_ACTION)
{
if (item->currentAnimState == LA_POLE_IDLE) // Hack.
{
if (TrInput & IN_LEFT)
{
2021-11-21 20:50:17 +11:00
info->turnRate += LARA_TURN_RATE;
if (info->turnRate > LARA_SLOW_TURN)
info->turnRate = LARA_SLOW_TURN;
}
else if (TrInput & IN_RIGHT)
{
2021-11-21 20:50:17 +11:00
info->turnRate -= LARA_TURN_RATE;
if (info->turnRate < -LARA_SLOW_TURN)
info->turnRate = -LARA_SLOW_TURN;
}
2021-11-21 20:50:17 +11:00
}
2021-11-21 20:50:17 +11:00
// TODO: Add forward jump.
if (TrInput & IN_JUMP)
{
item->goalAnimState = LS_JUMP_BACK;
2021-11-21 20:50:17 +11:00
return;
}
2021-11-21 20:50:17 +11:00
if (TrInput & IN_FORWARD &&
TestLaraPoleUp(item, coll))
{
item->goalAnimState = LS_POLE_UP;
2021-11-21 20:50:17 +11:00
return;
}
2021-11-21 20:50:17 +11:00
else if (TrInput & IN_BACK &&
TestLaraPoleDown(item, coll))
{
2021-11-21 20:50:17 +11:00
item->itemFlags[2] = 0; // Doesn't seem necessary?
item->goalAnimState = LS_POLE_DOWN;
return;
}
2021-11-21 20:50:17 +11:00
if (TrInput & IN_LEFT)
{
2021-11-21 20:50:17 +11:00
item->goalAnimState = LS_POLE_TURN_CLOCKWISE;
return;
}
else if (TrInput & IN_RIGHT)
{
item->goalAnimState = LS_POLE_TURN_COUNTER_CLOCKWISE;
return;
}
2021-11-21 20:50:17 +11:00
item->goalAnimState = LS_POLE_IDLE;
return;
}
2021-11-21 20:50:17 +11:00
if (coll->Middle.Floor <= 0)
{
item->goalAnimState = LS_STOP;
return;
}
// TODO: This should not be required. Update anim's root displacement + set position distance.
//item->pos.xPos -= phd_sin(item->pos.yRot) * 64;
//item->pos.zPos -= phd_cos(item->pos.yRot) * 64;
item->goalAnimState = LS_FREEFALL;
}
2021-11-21 20:50:17 +11:00
// State: LS_POLE_IDLE (99)
// Control: lara_as_pole_idle()
void lara_col_pole_idle(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 20:50:17 +11:00
LaraInfo*& info = item->data;
info->moveAngle = item->pos.yRot;
coll->Setup.BadHeightDown = NO_BAD_POS;
coll->Setup.BadHeightUp = -STEPUP_HEIGHT;
coll->Setup.BadCeilingHeight = BAD_JUMP_CEILING;
coll->Setup.ForwardAngle = info->moveAngle;
coll->Setup.Radius = LARA_RAD;
coll->Setup.SlopesAreWalls = true;
GetCollisionInfo(coll, item);
if (coll->Middle.Floor < 0)
item->pos.yPos += coll->Middle.Floor;
}
// State: LS_POLE_UP (100)
// Collision: lara_col_pole_up()
void lara_as_pole_up(ITEM_INFO* item, COLL_INFO* coll)
{
LaraInfo*& info = item->data;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
2021-11-21 20:50:17 +11:00
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Death state dispatch.
2021-11-21 20:50:17 +11:00
return;
}
2021-11-21 20:50:17 +11:00
if (TrInput & IN_ACTION)
{
if (TrInput & IN_LEFT)
{
info->turnRate += LARA_TURN_RATE;
if (info->turnRate > LARA_SLOW_TURN)
info->turnRate = LARA_SLOW_TURN;
}
else if (TrInput & IN_RIGHT)
{
info->turnRate -= LARA_TURN_RATE;
if (info->turnRate < -LARA_SLOW_TURN)
info->turnRate = -LARA_SLOW_TURN;
}
if (TrInput & IN_FORWARD &&
TestLaraPoleUp(item, coll))
{
item->goalAnimState = LS_POLE_UP;
return;
}
item->goalAnimState = LS_POLE_IDLE;
2021-11-21 20:50:17 +11:00
return;
}
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to freefall?
}
2021-11-21 20:50:17 +11:00
// State: LS_POLE_UP (100)
// Control: lara_as_pole_up()
void lara_col_pole_up(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 20:50:17 +11:00
lara_col_pole_idle(item, coll);
2021-11-21 20:50:17 +11:00
// TODO: Stop at top of pole.
}
2021-11-21 20:50:17 +11:00
// State: LS_POLE_DOWN (101)
// Collision: lara_col_pole_down()
void lara_as_pole_down(ITEM_INFO* item, COLL_INFO* coll)
{
LaraInfo*& info = item->data;
2021-11-21 20:50:17 +11:00
coll->Setup.EnableSpaz = false;
coll->Setup.EnableObjectPush = false;
2021-11-21 20:50:17 +11:00
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Death state dispatch.
2021-11-21 20:50:17 +11:00
return;
}
2021-11-21 20:50:17 +11:00
// TODO: In WAD.
SoundEffect(SFX_TR4_LARA_POLE_LOOP, &item->pos, 0);
2021-11-21 20:50:17 +11:00
if (TrInput & IN_ACTION)
{
2021-11-21 20:50:17 +11:00
if (TrInput & IN_LEFT)
{
info->turnRate += LARA_TURN_RATE;
if (info->turnRate > LARA_SLOW_TURN)
info->turnRate = LARA_SLOW_TURN;
}
else if (TrInput & IN_RIGHT)
{
info->turnRate -= LARA_TURN_RATE;
if (info->turnRate < -LARA_SLOW_TURN)
info->turnRate = -LARA_SLOW_TURN;
}
2021-11-21 20:50:17 +11:00
if (TrInput & IN_BACK &&
TestLaraPoleDown(item, coll))
{
item->goalAnimState = LS_POLE_DOWN;
return;
}
item->itemFlags[2] = 0; // ??
item->goalAnimState = LS_POLE_IDLE;
2021-11-21 20:50:17 +11:00
return;
}
2021-11-21 20:50:17 +11:00
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to freefall?
}
// State: LS_POLE_DOWN (101)
// Control: lara_as_pole_down()
void lara_col_pole_down(ITEM_INFO* item, COLL_INFO* coll)
{
LaraInfo*& info = item->data;
info->moveAngle = item->pos.yRot;
coll->Setup.BadHeightDown = NO_BAD_POS;
coll->Setup.BadHeightUp = -STEPUP_HEIGHT;
coll->Setup.BadCeilingHeight = 0;
coll->Setup.SlopesAreWalls = true;
coll->Setup.ForwardAngle = info->moveAngle;
coll->Setup.Radius = LARA_RAD;
GetCollisionInfo(coll, item);
// Translate Lara down.
if (item->animNumber == LA_POLE_DOWN_END)
2021-11-21 20:50:17 +11:00
item->itemFlags[2] -= WALL_SIZE;
else
2021-11-21 20:50:17 +11:00
item->itemFlags[2] += STEP_SIZE;
2021-11-21 20:50:17 +11:00
// Clamp speed.
2020-09-29 11:27:09 -03:00
if (item->itemFlags[2] < 0)
item->itemFlags[2] = 0;
2021-11-21 20:50:17 +11:00
else if (item->itemFlags[2] > SHRT_MAX / 2)
item->itemFlags[2] = SHRT_MAX / 2;
item->pos.yPos += item->itemFlags[2] >> 8;
2021-11-21 20:50:17 +11:00
if (coll->Middle.Floor < 0)
item->pos.yPos += coll->Middle.Floor;
}
2021-11-21 20:50:17 +11:00
// State: LS_POLE_TURN_CLOCKWISE (102)
// Collision: lara_col_pole_turn_clockwise()
void lara_as_pole_turn_clockwise(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 20:50:17 +11:00
LaraInfo*& info = item->data;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
2021-11-21 20:50:17 +11:00
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Death state dispatch.
return;
}
if (TrInput & IN_LOOK)
LookUpDown();
if (TrInput & IN_ACTION)
{
if (TrInput & IN_FORWARD &&
TestLaraPoleUp(item, coll))
2021-11-21 20:50:17 +11:00
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to climp up.
return;
}
else if (TrInput & IN_BACK &&
TestLaraPoleDown(item, coll))
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to climb down.
return;
}
if (TrInput & IN_LEFT)
{
info->turnRate += LARA_TURN_RATE;
if (info->turnRate > LARA_SLOW_TURN + ANGLE(0.5f))
info->turnRate = LARA_SLOW_TURN + ANGLE(0.5f);
item->goalAnimState = LS_POLE_TURN_CLOCKWISE;
return;
}
item->goalAnimState = LS_POLE_IDLE;
2021-11-21 20:50:17 +11:00
return;
}
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to freefall.
}
2021-11-21 20:50:17 +11:00
// State: LS_POLE_TURN_CLOCKWISE (102)
// Control: lara_as_pole_turn_clockwise()
void lara_col_pole_turn_clockwise(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-21 20:50:17 +11:00
lara_col_pole_idle(item, coll);
}
// State: LS_POLE_TURN_COUNTER_CLOCKWISE (103)
// Collision: lara_col_pole_turn_counter_clockwise()
void lara_as_pole_turn_counter_clockwise(ITEM_INFO* item, COLL_INFO* coll)
{
LaraInfo*& info = item->data;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
2021-11-21 20:50:17 +11:00
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Death state dispatch.
return;
}
if (TrInput & IN_LOOK)
LookUpDown();
if (TrInput & IN_ACTION)
{
if (TrInput & IN_FORWARD &&
TestLaraPoleUp(item, coll))
2021-11-21 20:50:17 +11:00
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to climb up.
return;
}
else if (TrInput & IN_BACK &&
TestLaraPoleDown(item, coll))
{
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to climb down.
return;
}
if (TrInput & IN_RIGHT)
{
info->turnRate -= LARA_TURN_RATE;
if (info->turnRate < -(LARA_SLOW_TURN + ANGLE(0.5f)))
info->turnRate = -(LARA_SLOW_TURN + ANGLE(0.5f));
item->goalAnimState = LS_POLE_TURN_COUNTER_CLOCKWISE;
return;
}
item->goalAnimState = LS_POLE_IDLE;
2021-11-21 20:50:17 +11:00
return;
}
item->goalAnimState = LS_POLE_IDLE; // TODO: Dispatch to freefall.
}
// State: LS_POLE_TURN_COUNTER_CLOCKWISE (103)
// Control: lara_col_pole_turn_counter_clockwise()
void lara_col_pole_turn_counter_clockwise(ITEM_INFO* item, COLL_INFO* coll)
{
lara_col_pole_idle(item, coll);
}
2021-11-21 20:50:17 +11:00
// --------
// ZIP-LINE
// --------
2021-02-03 01:50:59 -03:00
void lara_as_deathslide(ITEM_INFO* item, COLL_INFO* coll)
{
2021-11-22 22:47:34 +11:00
LaraInfo*& info = item->data;
/*state 70*/
/*collision: lara_void_func*/
Camera.targetAngle = ANGLE(70.0f);
if (!(TrInput & IN_ACTION))
{
item->goalAnimState = LS_JUMP_FORWARD;
AnimateLara(item);
2021-11-22 22:47:34 +11:00
item->gravityStatus = true;
item->speed = 100;
item->fallspeed = 40;
info->moveAngle = item->pos.yRot;
}
}