2020-05-27 09:21:20 +02:00
|
|
|
#include "framework.h"
|
|
|
|
#include "minecart.h"
|
|
|
|
#include "lara.h"
|
|
|
|
#include "collide.h"
|
|
|
|
#include "effect.h"
|
2020-08-09 22:09:14 -03:00
|
|
|
#include "lara_flare.h"
|
2020-05-27 09:21:20 +02:00
|
|
|
#include "items.h"
|
|
|
|
#include "sphere.h"
|
|
|
|
#include "draw.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "camera.h"
|
|
|
|
#include "level.h"
|
|
|
|
#include "setup.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "sound.h"
|
2020-06-20 23:39:08 +02:00
|
|
|
using std::vector;
|
2021-07-18 15:22:15 +01:00
|
|
|
enum MINECART_STATE {
|
2019-11-30 13:51:37 +01:00
|
|
|
CART_GETIN,
|
|
|
|
CART_GETOUT,
|
|
|
|
CART_GETOUTL,
|
|
|
|
CART_GETOUTR,
|
|
|
|
CART_STILL,
|
|
|
|
CART_DUCK,
|
|
|
|
CART_MOVE,
|
|
|
|
CART_RIGHT,
|
|
|
|
CART_HARDLEFT,
|
|
|
|
CART_LEFT,
|
|
|
|
CART_HARDRIGHT,
|
|
|
|
CART_BRAKE,
|
|
|
|
CART_FWD,
|
|
|
|
CART_BACK,
|
|
|
|
CART_TURNDEATH,
|
|
|
|
CART_FALLDEATH,
|
|
|
|
CART_WALLDEATH,
|
|
|
|
CART_HIT,
|
|
|
|
CART_USE,
|
|
|
|
CART_BRAKING
|
|
|
|
};
|
|
|
|
|
2021-07-18 15:22:15 +01:00
|
|
|
enum MINECART_FLAGS
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
CF_MESH = 1,
|
|
|
|
CF_TURNINGL = 2,
|
|
|
|
CF_TURNINGR = 4,
|
|
|
|
CF_RDIR = 8,
|
|
|
|
CF_CONTROL = 16,
|
|
|
|
CF_STOPPED = 32,
|
|
|
|
CF_NOANIM = 64,
|
|
|
|
CF_DEAD = 128
|
|
|
|
};
|
|
|
|
|
|
|
|
#define GETOFF_DIST 330
|
|
|
|
#define CART_DEC -1536
|
|
|
|
#define CART_MIN_SPEED 2560
|
|
|
|
#define CART_MIN_VEL 32
|
|
|
|
#define TURN_DEATH_VEL 128
|
|
|
|
#define CART_FWD_GRAD -128
|
|
|
|
#define CART_BACK_GRAD 128
|
|
|
|
#define CART_JUMP_VEL 64512
|
|
|
|
#define CART_GRAVITY (WALL_SIZE + 1)
|
|
|
|
#define MAX_CART_YVEL 16128
|
|
|
|
#define TERMINAL_ANGLE (WALL_SIZE * 4)
|
|
|
|
#define CART_RADIUS 100
|
|
|
|
#define CART_HEIGHT (STEP_SIZE * 3)
|
|
|
|
#define CART_NHITS 25
|
|
|
|
#define CART_BADDIE_RADIUS STEP_SIZE
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
static int TestMinecartHeight(ITEM_INFO* v, int x, int z)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
FLOOR_INFO* floor;
|
2020-10-05 22:24:57 -03:00
|
|
|
float s, c;
|
2020-04-09 14:19:18 +02:00
|
|
|
short roomNumber;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-04-25 16:23:53 +02:00
|
|
|
c = phd_cos(v->pos.yRot);
|
|
|
|
s = phd_sin(v->pos.yRot);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
pos.x = v->pos.xPos + z * s + x * c;
|
|
|
|
pos.y = v->pos.yPos - z * phd_sin(v->pos.xRot) + x * phd_sin(v->pos.zRot);
|
|
|
|
pos.z = v->pos.zPos + z * c - x * s;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
roomNumber = v->roomNumber;
|
|
|
|
floor = GetFloor(pos.x, pos.y, pos.z, &roomNumber);
|
2019-11-30 13:51:37 +01:00
|
|
|
return GetFloorHeight(floor, pos.x, pos.y, pos.z);
|
|
|
|
}
|
|
|
|
|
|
|
|
static short GetCollision(ITEM_INFO* v, short ang, int dist, short* ceiling)
|
|
|
|
{
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
int x, y, z, height, cheight;
|
2020-04-09 14:19:18 +02:00
|
|
|
short roomNumber;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
x = v->pos.xPos + phd_sin(ang) * dist;
|
2019-11-30 13:51:37 +01:00
|
|
|
y = v->pos.yPos - LARA_HITE;
|
2020-10-05 22:24:57 -03:00
|
|
|
z = v->pos.zPos + phd_cos(ang) * dist;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
roomNumber = v->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
2019-11-30 13:51:37 +01:00
|
|
|
height = GetFloorHeight(floor, x, y, z);
|
|
|
|
cheight = GetCeiling(floor, x, y, z);
|
|
|
|
|
|
|
|
*ceiling = ((short)cheight);
|
|
|
|
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= v->pos.yPos;
|
|
|
|
|
|
|
|
return short(height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool GetInMineCart(ITEM_INFO* v, ITEM_INFO* l, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
int dist;
|
|
|
|
int x, z;
|
|
|
|
FLOOR_INFO* floor;
|
2020-04-09 14:19:18 +02:00
|
|
|
short roomNumber;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if (!(TrInput & IN_ACTION) || Lara.gunStatus != LG_NO_ARMS || l->gravityStatus)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!TestBoundsCollide(v, l, coll->radius))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!TestCollision(v, l))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
x = l->pos.xPos - v->pos.xPos;
|
|
|
|
z = l->pos.zPos - v->pos.zPos;
|
|
|
|
|
|
|
|
dist = SQUARE(x) + SQUARE(z);
|
|
|
|
|
|
|
|
if (dist > SQUARE(WALL_SIZE/2))
|
|
|
|
return false;
|
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
roomNumber = v->roomNumber;
|
|
|
|
floor = GetFloor(v->pos.xPos, v->pos.yPos, v->pos.zPos, &roomNumber);
|
2019-11-30 13:51:37 +01:00
|
|
|
if (GetFloorHeight(floor, v->pos.xPos, v->pos.yPos, v->pos.zPos) < -32000)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CanGetOut(int direction)
|
|
|
|
{
|
|
|
|
ITEM_INFO* v;
|
|
|
|
FLOOR_INFO* floor;
|
2020-04-09 14:19:18 +02:00
|
|
|
short roomNumber, angle;
|
2019-11-30 13:51:37 +01:00
|
|
|
int x, y, z, height, ceiling;
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
v = &g_Level.Items[Lara.Vehicle];
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if (direction < 0)
|
|
|
|
angle = v->pos.yRot + 0x4000;
|
|
|
|
else
|
|
|
|
angle = v->pos.yRot - 0x4000;
|
|
|
|
|
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
x = v->pos.xPos - GETOFF_DIST * phd_sin(angle);
|
2019-11-30 13:51:37 +01:00
|
|
|
y = v->pos.yPos;
|
2020-10-05 22:24:57 -03:00
|
|
|
z = v->pos.zPos - GETOFF_DIST * phd_cos(angle);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
roomNumber = v->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
2019-11-30 13:51:37 +01:00
|
|
|
height = GetFloorHeight(floor, x, y, z);
|
|
|
|
|
|
|
|
if ((HeightType == BIG_SLOPE) || (HeightType == DIAGONAL) || (height == NO_HEIGHT))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (abs(height - v->pos.yPos) > WALL_SIZE / 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ceiling = GetCeiling(floor, x, y, z);
|
|
|
|
if ((ceiling - v->pos.yPos > -LARA_HITE) || (height - ceiling < LARA_HITE))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CartToBaddieCollision(ITEM_INFO* v)
|
|
|
|
{
|
|
|
|
vector<short> roomsList;
|
|
|
|
short* door, numDoors;
|
|
|
|
|
|
|
|
roomsList.push_back(v->roomNumber);
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
ROOM_INFO* room = &g_Level.Rooms[v->roomNumber];
|
2020-06-26 07:06:18 +02:00
|
|
|
for (int i = 0; i < room->doors.size(); i++)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
2020-06-26 07:06:18 +02:00
|
|
|
roomsList.push_back(room->doors[i].room);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < roomsList.size(); i++)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
short itemNum = g_Level.Rooms[roomsList[i]].itemNumber;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
while (itemNum != NO_ITEM)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2019-11-30 13:51:37 +01:00
|
|
|
if (item->collidable && item->status != ITEM_INVISIBLE && item != LaraItem && item != v)
|
|
|
|
{
|
2020-07-07 07:32:33 +02:00
|
|
|
OBJECT_INFO* object = &Objects[item->objectNumber];
|
2019-11-30 13:51:37 +01:00
|
|
|
if (object->collision && (object->intelligent || item->objectNumber == ID_ROLLINGBALL || item->objectNumber == ID_ANIMATING2))
|
|
|
|
{
|
|
|
|
int x = v->pos.xPos - item->pos.xPos;
|
|
|
|
int y = v->pos.yPos - item->pos.yPos;
|
|
|
|
int z = v->pos.zPos - item->pos.zPos;
|
|
|
|
if (x > -2048 && x < 2048 && z > -2048 && z < 2048 && y > -2048 && y < 2048)
|
|
|
|
{
|
|
|
|
if (TestBoundsCollide(item, LaraItem, CART_BADDIE_RADIUS))
|
|
|
|
{
|
|
|
|
if (item->objectNumber == ID_ANIMATING2)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if ((item->frameNumber == g_Level.Anims[item->animNumber].frameBase) && (LaraItem->currentAnimState == CART_USE) && (LaraItem->animNumber == Objects[ID_MINECART_LARA_ANIMS].animIndex + 6))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
FLOOR_INFO* floor;
|
2020-04-09 14:19:18 +02:00
|
|
|
short frame, roomNumber;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
frame = LaraItem->frameNumber - g_Level.Anims[LaraItem->animNumber].frameBase;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if ((frame >= 12) && (frame <= 22))
|
|
|
|
{
|
|
|
|
SoundEffect(220, &item->pos, 2);
|
2021-08-20 14:13:06 +03:00
|
|
|
TestTriggersAtXYZ(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, false, NULL);
|
2019-11-30 13:51:37 +01:00
|
|
|
item->frameNumber++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (item->objectNumber == ID_ROLLINGBALL)
|
|
|
|
{
|
2021-03-24 12:49:36 -05:00
|
|
|
/*code, kill lara and stop both the boulder and the minecart*/
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DoLotsOfBlood(item->pos.xPos, v->pos.yPos - STEP_SIZE, item->pos.zPos, GetRandomControl() & 3, v->pos.yRot, item->roomNumber, 3);
|
|
|
|
item->hitPoints = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
itemNum = item->nextItem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MoveCart(ITEM_INFO* v, ITEM_INFO* l, CART_INFO* cart)
|
|
|
|
{
|
|
|
|
short val;
|
|
|
|
if (cart->StopDelay)
|
|
|
|
cart->StopDelay--;
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
if (((Lara.mineL) && (Lara.mineR) && (!cart->StopDelay)) && (((v->pos.xPos & 0x380) == 512) || ((v->pos.zRot & 0x380) == 512)))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
2021-03-24 12:49:36 -05:00
|
|
|
if (cart->Speed < 0xf000)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
cart->Flags |= CF_STOPPED | CF_CONTROL;
|
|
|
|
cart->Speed = v->speed = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cart->StopDelay = 16;
|
|
|
|
}
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
if ((Lara.mineL || Lara.mineR) && (!(Lara.mineL && Lara.mineR)) && (!cart->StopDelay) && (!(cart->Flags & (CF_TURNINGL | CF_TURNINGR))))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
short ang;
|
2020-10-06 10:36:30 -05:00
|
|
|
unsigned short rot = (((unsigned short)v->pos.yRot) / 16384) | (Lara.mineL * 4);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
switch (rot)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
cart->TurnX = (v->pos.xPos + 4096) & ~1023;
|
|
|
|
cart->TurnZ = v->pos.zPos & ~1023;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
cart->TurnX = v->pos.xPos & ~1023;
|
|
|
|
cart->TurnZ = (v->pos.zPos - 4096) | 1023;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
cart->TurnX = (v->pos.xPos - 4096) | 1023;
|
|
|
|
cart->TurnZ = v->pos.zPos | 1023;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
cart->TurnX = v->pos.xPos | 1023;
|
|
|
|
cart->TurnZ = (v->pos.zPos + 4096) & ~1023;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
cart->TurnX = (v->pos.xPos - 4096) | 1023;
|
|
|
|
cart->TurnZ = v->pos.zPos & ~1023;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
cart->TurnX = v->pos.xPos & ~1023;
|
|
|
|
cart->TurnZ = (v->pos.zPos + 4096) & ~1023;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
cart->TurnX = (v->pos.xPos + 4096) & ~1023;
|
|
|
|
cart->TurnZ = v->pos.zPos | 1023;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
cart->TurnX = v->pos.xPos | 1023;
|
|
|
|
cart->TurnZ = (v->pos.zPos - 4096) | 1023;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ang = mGetAngle(v->pos.xPos, v->pos.zPos, cart->TurnX, cart->TurnZ) & 0x3fff;
|
|
|
|
|
|
|
|
if (rot < 4)
|
|
|
|
{
|
|
|
|
cart->TurnRot = v->pos.yRot;
|
|
|
|
cart->TurnLen = ang;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cart->TurnRot = v->pos.yRot;
|
|
|
|
|
|
|
|
if (ang)
|
|
|
|
ang = 16384 - ang;
|
|
|
|
|
|
|
|
cart->TurnLen = ang;
|
|
|
|
}
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
cart->Flags |= (Lara.mineL) ? CF_TURNINGL : CF_TURNINGR;
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cart->Speed < CART_MIN_SPEED)
|
|
|
|
cart->Speed = CART_MIN_SPEED;
|
|
|
|
|
2020-10-06 10:36:30 -05:00
|
|
|
cart->Speed += (-cart->Gradient * 4);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-10-06 10:36:30 -05:00
|
|
|
if ((v->speed = cart->Speed / 256) < CART_MIN_VEL)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
v->speed = CART_MIN_VEL;
|
|
|
|
|
|
|
|
StopSoundEffect(209);
|
|
|
|
|
|
|
|
if (cart->YVel)
|
|
|
|
StopSoundEffect(210);
|
|
|
|
else
|
|
|
|
SoundEffect(210, &v->pos, 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StopSoundEffect(210);
|
|
|
|
|
|
|
|
if (cart->YVel)
|
|
|
|
StopSoundEffect(209);
|
|
|
|
else
|
2020-10-06 10:36:30 -05:00
|
|
|
SoundEffect(209, &v->pos, (2 | 4) + 0x1000000 + (v->speed * 32768));
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cart->Flags & (CF_TURNINGL | CF_TURNINGR))
|
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
float x, z;
|
2019-11-30 13:51:37 +01:00
|
|
|
unsigned short quad, deg;
|
|
|
|
|
|
|
|
if ((cart->TurnLen += (v->speed * 3)) > ANGLE(90))
|
|
|
|
{
|
|
|
|
if (cart->Flags & CF_TURNINGL)
|
|
|
|
v->pos.yRot = cart->TurnRot - 16384;
|
|
|
|
else
|
|
|
|
v->pos.yRot = cart->TurnRot + 16384;
|
|
|
|
|
|
|
|
cart->Flags &= ~(CF_TURNINGL | CF_TURNINGR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cart->Flags & CF_TURNINGL)
|
|
|
|
v->pos.yRot = cart->TurnRot - cart->TurnLen;
|
|
|
|
else
|
|
|
|
v->pos.yRot = cart->TurnRot + cart->TurnLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cart->Flags & (CF_TURNINGL | CF_TURNINGR))
|
|
|
|
{
|
2020-10-06 10:36:30 -05:00
|
|
|
quad = ((unsigned short)v->pos.yRot) / 16384;
|
2019-11-30 13:51:37 +01:00
|
|
|
deg = v->pos.yRot & 16383;
|
|
|
|
|
|
|
|
switch (quad)
|
|
|
|
{
|
|
|
|
case 0:
|
2020-04-25 16:23:53 +02:00
|
|
|
x = -phd_cos(deg);
|
|
|
|
z = phd_sin(deg);
|
2019-11-30 13:51:37 +01:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-25 16:23:53 +02:00
|
|
|
x = phd_sin(deg);
|
|
|
|
z = phd_cos(deg);
|
2019-11-30 13:51:37 +01:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-25 16:23:53 +02:00
|
|
|
x = phd_cos(deg);
|
|
|
|
z = -phd_sin(deg);
|
2019-11-30 13:51:37 +01:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-25 16:23:53 +02:00
|
|
|
x = -phd_sin(deg);
|
|
|
|
z = -phd_cos(deg);
|
2019-11-30 13:51:37 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cart->Flags & CF_TURNINGL)
|
|
|
|
{
|
|
|
|
x = -x;
|
|
|
|
z = -z;
|
|
|
|
}
|
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
v->pos.xPos = cart->TurnX + x * 3584;
|
|
|
|
v->pos.zPos = cart->TurnZ + z * 3584;
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
v->pos.xPos += v->speed * phd_sin(v->pos.yRot);
|
|
|
|
v->pos.zPos += v->speed * phd_cos(v->pos.yRot);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
cart->MidPos = TestMinecartHeight(v, 0, 0);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if (!cart->YVel)
|
|
|
|
{
|
2020-05-27 09:21:20 +02:00
|
|
|
cart->FrontPos = TestMinecartHeight(v, 0, 256);
|
2019-11-30 13:51:37 +01:00
|
|
|
cart->Gradient = cart->MidPos - cart->FrontPos;
|
|
|
|
v->pos.yPos = cart->MidPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (v->pos.yPos > cart->MidPos)
|
|
|
|
{
|
|
|
|
if (cart->YVel > 0)
|
|
|
|
SoundEffect(202, &v->pos, 2);
|
|
|
|
|
|
|
|
v->pos.yPos = cart->MidPos;
|
|
|
|
cart->YVel = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cart->YVel += CART_GRAVITY;
|
|
|
|
|
|
|
|
if (cart->YVel > MAX_CART_YVEL)
|
|
|
|
cart->YVel = MAX_CART_YVEL;
|
|
|
|
|
2020-10-06 10:36:30 -05:00
|
|
|
v->pos.yPos += (cart->YVel / 256);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-06 10:36:30 -05:00
|
|
|
v->pos.xRot = cart->Gradient * 32;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
val = v->pos.yRot & 16383;
|
|
|
|
if (cart->Flags & (CF_TURNINGL | CF_TURNINGR))
|
|
|
|
{
|
|
|
|
if (cart->Flags & CF_TURNINGR)
|
2020-10-06 10:36:30 -05:00
|
|
|
v->pos.zRot = -(val * v->speed) / 512;
|
2019-11-30 13:51:37 +01:00
|
|
|
else
|
2020-10-06 10:36:30 -05:00
|
|
|
v->pos.zRot = ((0x4000 - val) * v->speed) / 512;
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-06 10:36:30 -05:00
|
|
|
v->pos.zRot -= (v->pos.zRot / 8);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DoUserInput(ITEM_INFO* v, ITEM_INFO* l, CART_INFO* cart)
|
|
|
|
{
|
|
|
|
short fh, ch;
|
|
|
|
|
|
|
|
switch (l->currentAnimState)
|
|
|
|
{
|
|
|
|
case CART_MOVE:
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
l->goalAnimState = CART_USE;
|
|
|
|
else if (TrInput & IN_DUCK)
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
l->goalAnimState = CART_BRAKE;
|
|
|
|
else if ((cart->Speed == CART_MIN_VEL) || (cart->Flags & CF_STOPPED))
|
|
|
|
l->goalAnimState = CART_STILL;
|
|
|
|
else if (cart->Gradient < CART_FWD_GRAD)
|
|
|
|
l->goalAnimState = CART_FWD;
|
|
|
|
else if (cart->Gradient > CART_BACK_GRAD)
|
|
|
|
l->goalAnimState = CART_BACK;
|
|
|
|
else if (TrInput & IN_LEFT)
|
|
|
|
l->goalAnimState = CART_LEFT;
|
|
|
|
else if (TrInput & IN_RIGHT)
|
|
|
|
l->goalAnimState = CART_RIGHT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_FWD:
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
l->goalAnimState = CART_USE;
|
|
|
|
else if (TrInput & IN_DUCK)
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
l->goalAnimState = CART_BRAKE;
|
|
|
|
else if (cart->Gradient > CART_FWD_GRAD)
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_BACK:
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
l->goalAnimState = CART_USE;
|
|
|
|
else if (TrInput & IN_DUCK)
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
l->goalAnimState = CART_BRAKE;
|
|
|
|
else if (cart->Gradient < CART_BACK_GRAD)
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_LEFT:
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
l->goalAnimState = CART_USE;
|
|
|
|
else if (TrInput & IN_DUCK)
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
l->goalAnimState = CART_BRAKE;
|
|
|
|
|
|
|
|
if (!(TrInput & IN_LEFT))
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_RIGHT:
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
l->goalAnimState = CART_USE;
|
|
|
|
else if (TrInput & IN_DUCK)
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
l->goalAnimState = CART_BRAKE;
|
|
|
|
|
|
|
|
if (!(TrInput & IN_RIGHT))
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_STILL:
|
|
|
|
if (!(cart->Flags & CF_CONTROL))
|
|
|
|
{
|
|
|
|
SoundEffect(211, &v->pos, 2);
|
|
|
|
cart->Flags |= CF_CONTROL;
|
|
|
|
cart->StopDelay = 64;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TrInput & IN_ROLL && (cart->Flags & CF_STOPPED))
|
|
|
|
{
|
|
|
|
if ((TrInput & IN_LEFT) && (CanGetOut(-1)))
|
|
|
|
{
|
|
|
|
l->goalAnimState = CART_GETOUT;
|
|
|
|
cart->Flags &= ~CF_RDIR;
|
|
|
|
}
|
|
|
|
else if ((TrInput & IN_RIGHT) && (CanGetOut(1)))
|
|
|
|
{
|
|
|
|
l->goalAnimState = CART_GETOUT;
|
|
|
|
cart->Flags |= CF_RDIR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TrInput & IN_DUCK)
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
else if (cart->Speed > CART_MIN_VEL)
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_DUCK:
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
l->goalAnimState = CART_USE;
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
l->goalAnimState = CART_BRAKE;
|
|
|
|
else if (!(TrInput & IN_DUCK))
|
|
|
|
l->goalAnimState = CART_STILL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_USE:
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_BRAKING:
|
|
|
|
if (TrInput & IN_DUCK)
|
|
|
|
{
|
|
|
|
l->goalAnimState = CART_DUCK;
|
|
|
|
StopSoundEffect(219);
|
|
|
|
}
|
|
|
|
else if ((!(TrInput & IN_JUMP)) || (cart->Flags & CF_STOPPED))
|
|
|
|
{
|
|
|
|
l->goalAnimState = CART_MOVE;
|
|
|
|
StopSoundEffect(219);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cart->Speed += CART_DEC;
|
|
|
|
SoundEffect(219, &l->pos, 2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_BRAKE:
|
|
|
|
l->goalAnimState = CART_BRAKING;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_GETOUT:
|
2019-12-31 14:56:02 +01:00
|
|
|
if (l->animNumber == Objects[ID_MINECART_LARA_ANIMS].animIndex + 7)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
if ((l->frameNumber == GF2(ID_MINECART, 7, 0) + 20) && (cart->Flags & CF_MESH))
|
|
|
|
{
|
2020-07-03 07:05:33 +02:00
|
|
|
Lara.meshPtrs[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
cart->Flags &= ~CF_MESH;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cart->Flags & CF_RDIR)
|
|
|
|
l->goalAnimState = CART_GETOUTR;
|
|
|
|
else
|
|
|
|
l->goalAnimState = CART_GETOUTL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_GETOUTL:
|
2020-07-21 09:56:47 +02:00
|
|
|
if ((l->animNumber == Objects[ID_MINECART_LARA_ANIMS].animIndex + 1) && (l->frameNumber == g_Level.Anims[l->animNumber].frameEnd))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR vec = { 0, 640, 0 };
|
|
|
|
|
2019-12-15 16:19:01 +01:00
|
|
|
GetLaraJointPosition(&vec, LM_HIPS);
|
2019-11-30 13:51:37 +01:00
|
|
|
l->pos.xPos = vec.x;
|
|
|
|
l->pos.yPos = vec.y;
|
|
|
|
l->pos.zPos = vec.z;
|
|
|
|
l->pos.xRot = 0;
|
|
|
|
l->pos.yRot = v->pos.yRot + 0x4000;
|
|
|
|
l->pos.zRot = 0;
|
|
|
|
|
|
|
|
l->animNumber = 13;
|
|
|
|
l->frameNumber = GF(11, 0);
|
|
|
|
l->currentAnimState = l->goalAnimState = 2;
|
2020-04-27 14:01:00 +02:00
|
|
|
Lara.Vehicle = NO_ITEM;
|
2019-11-30 13:51:37 +01:00
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_GETOUTR:
|
2020-07-21 09:56:47 +02:00
|
|
|
if ((l->animNumber == Objects[ID_MINECART_LARA_ANIMS].animIndex + 47) && (l->frameNumber == g_Level.Anims[l->animNumber].frameEnd))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR vec = { 0, 640, 0 };
|
|
|
|
|
2019-12-15 16:19:01 +01:00
|
|
|
GetLaraJointPosition(&vec, LM_HIPS);
|
2019-11-30 13:51:37 +01:00
|
|
|
l->pos.xPos = vec.x;
|
|
|
|
l->pos.yPos = vec.y;
|
|
|
|
l->pos.zPos = vec.z;
|
|
|
|
l->pos.xRot = 0;
|
|
|
|
l->pos.yRot = v->pos.yRot - 0x4000;
|
|
|
|
l->pos.zRot = 0;
|
|
|
|
|
|
|
|
l->animNumber = 11;
|
|
|
|
l->frameNumber = GF(11, 0);
|
|
|
|
l->currentAnimState = l->goalAnimState = 2;
|
2020-04-27 14:01:00 +02:00
|
|
|
Lara.Vehicle = NO_ITEM;
|
2019-11-30 13:51:37 +01:00
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_GETIN:
|
2019-12-31 14:56:02 +01:00
|
|
|
if ((l->animNumber == Objects[ID_MINECART_LARA_ANIMS].animIndex + 5) && (l->frameNumber == GF2(ID_MINECART, 5, 0) + 20) && (!cart->Flags & CF_MESH))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
MESH tmp = g_Level.Meshes[Lara.meshPtrs[LM_RHAND]];
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-07-03 07:05:33 +02:00
|
|
|
Lara.meshPtrs[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND;
|
2020-07-21 09:56:47 +02:00
|
|
|
g_Level.Meshes[Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND] = tmp;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
cart->Flags |= CF_MESH;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_WALLDEATH:
|
|
|
|
Camera.targetElevation = -ANGLE(25);
|
|
|
|
Camera.targetDistance = WALL_SIZE * 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_TURNDEATH:
|
|
|
|
Camera.targetElevation = -ANGLE(45);
|
|
|
|
Camera.targetDistance = WALL_SIZE * 2;
|
|
|
|
|
|
|
|
fh = GetCollision(v, v->pos.yRot, 512, &ch);
|
|
|
|
|
|
|
|
if ((fh > -STEP_SIZE) && (fh < STEP_SIZE))
|
|
|
|
{
|
|
|
|
if ((Wibble & 7) == 0)
|
2020-03-02 09:49:11 +01:00
|
|
|
SoundEffect(SFX_TR3_QUAD_FRONT_IMPACT, &v->pos, 2);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
v->pos.xPos += TURN_DEATH_VEL * phd_sin(v->pos.yRot);
|
|
|
|
v->pos.zPos += TURN_DEATH_VEL * phd_cos(v->pos.yRot);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-31 14:56:02 +01:00
|
|
|
if (l->animNumber == Objects[ID_MINECART_LARA_ANIMS].animIndex + 30)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
cart->Flags |= CF_NOANIM;
|
|
|
|
l->hitPoints = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CART_HIT:
|
|
|
|
if ((l->hitPoints <= 0) && (l->frameNumber == GF2(ID_MINECART, 34, 0) + 28))
|
|
|
|
{
|
|
|
|
l->frameNumber = GF2(ID_MINECART, 34, 0) + 28;
|
|
|
|
cart->Flags = (cart->Flags & ~CF_CONTROL) | (CF_NOANIM);
|
|
|
|
cart->Speed = v->speed = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
if ((Lara.Vehicle != NO_ITEM) && (!(cart->Flags & CF_NOANIM)))
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
AnimateItem(l);
|
|
|
|
|
2019-12-31 14:56:02 +01:00
|
|
|
v->animNumber = Objects[ID_MINECART].animIndex + (l->animNumber - Objects[ID_MINECART_LARA_ANIMS].animIndex);
|
2020-07-21 09:56:47 +02:00
|
|
|
v->frameNumber = g_Level.Anims[v->animNumber].frameBase + (l->frameNumber - g_Level.Anims[l->animNumber].frameBase);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
if ((l->currentAnimState != CART_TURNDEATH) && (l->currentAnimState != CART_WALLDEATH) && (l->hitPoints > 0))
|
|
|
|
{
|
|
|
|
if ((v->pos.zRot > TERMINAL_ANGLE) || (v->pos.zRot < -TERMINAL_ANGLE))
|
|
|
|
{
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_MINECART_LARA_ANIMS].animIndex + 31;
|
2020-07-21 09:56:47 +02:00
|
|
|
l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
|
2019-11-30 13:51:37 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = CART_TURNDEATH;
|
|
|
|
cart->Flags = (cart->Flags & ~CF_CONTROL) | CF_STOPPED | CF_DEAD;
|
|
|
|
cart->Speed = v->speed = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fh = GetCollision(v, v->pos.yRot, 512, &ch);
|
|
|
|
if (fh < -(STEP_SIZE * 2))
|
|
|
|
{
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_MINECART_LARA_ANIMS].animIndex + 23;
|
2020-07-21 09:56:47 +02:00
|
|
|
l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
|
2019-11-30 13:51:37 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = CART_WALLDEATH;
|
|
|
|
cart->Flags = (cart->Flags & ~CF_CONTROL) | (CF_STOPPED | CF_DEAD);
|
|
|
|
cart->Speed = v->speed = 0;
|
|
|
|
l->hitPoints = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((l->currentAnimState != CART_DUCK) && (l->currentAnimState != CART_HIT))
|
|
|
|
{
|
|
|
|
COLL_INFO coll;
|
|
|
|
|
|
|
|
coll.quadrant = short((v->pos.yRot + 0x2000) / 0x4000);
|
|
|
|
coll.radius = CART_RADIUS;
|
|
|
|
|
|
|
|
if (CollideStaticObjects(&coll, v->pos.xPos, v->pos.yPos, v->pos.zPos, v->roomNumber, CART_HEIGHT))
|
|
|
|
{
|
|
|
|
int hits;
|
|
|
|
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_MINECART_LARA_ANIMS].animIndex + 34;
|
2020-07-21 09:56:47 +02:00
|
|
|
l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
|
2019-11-30 13:51:37 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = CART_HIT;
|
|
|
|
DoLotsOfBlood(l->pos.xPos, l->pos.yPos - 768, l->pos.zPos, v->speed, v->pos.yRot, l->roomNumber, 3);
|
|
|
|
|
2020-10-06 10:36:30 -05:00
|
|
|
hits = (CART_NHITS * short((cart->Speed) / 2048));
|
2019-11-30 13:51:37 +01:00
|
|
|
if (hits < 20)
|
|
|
|
hits = 20;
|
|
|
|
|
|
|
|
l->hitPoints -= hits;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fh > 512 + 64) && (!cart->YVel))
|
|
|
|
cart->YVel = CART_JUMP_VEL;
|
|
|
|
|
|
|
|
CartToBaddieCollision(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitialiseMineCart(short itemNum)
|
|
|
|
{
|
|
|
|
ITEM_INFO* v;
|
|
|
|
CART_INFO* cart;
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
v = &g_Level.Items[itemNum];
|
2020-07-05 22:19:06 +02:00
|
|
|
cart = game_malloc<CART_INFO>();
|
2019-11-30 13:51:37 +01:00
|
|
|
v->data = (void*)cart;
|
|
|
|
cart->Flags = NULL;
|
|
|
|
cart->Speed = 0;
|
|
|
|
cart->YVel = 0;
|
|
|
|
cart->Gradient = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MineCartCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
ITEM_INFO* v;
|
|
|
|
CART_INFO* cart;
|
|
|
|
int geton;
|
|
|
|
short ang;
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
if ((l->hitPoints < 0) || (Lara.Vehicle != NO_ITEM))
|
2019-11-30 13:51:37 +01:00
|
|
|
return;
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
v = &g_Level.Items[itemNum];
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if ((geton = GetInMineCart(v, l, coll)))
|
|
|
|
{
|
2020-04-27 14:01:00 +02:00
|
|
|
Lara.Vehicle = itemNum;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if (Lara.gunType == WEAPON_FLARE)
|
|
|
|
{
|
|
|
|
CreateFlare(ID_FLARE_ITEM, FALSE);
|
2019-12-02 09:11:21 +01:00
|
|
|
undraw_flare_meshes();
|
2019-11-30 13:51:37 +01:00
|
|
|
Lara.flareControlLeft = false;
|
2020-06-05 14:01:22 +02:00
|
|
|
Lara.requestGunType = Lara.gunType = WEAPON_NONE;
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
|
|
|
|
ang = short(mGetAngle(v->pos.xPos, v->pos.zPos, l->pos.xPos, l->pos.zPos) - v->pos.yRot);
|
|
|
|
|
|
|
|
if ((ang > -ANGLE(45)) && (ang < ANGLE(135)))
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_MINECART_LARA_ANIMS].animIndex + 46;
|
2019-11-30 13:51:37 +01:00
|
|
|
else
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_MINECART_LARA_ANIMS].animIndex + 0;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
|
2019-11-30 13:51:37 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = CART_GETIN;
|
|
|
|
|
|
|
|
l->pos.xPos = v->pos.xPos;
|
|
|
|
l->pos.yPos = v->pos.yPos;
|
|
|
|
l->pos.zPos = v->pos.zPos;
|
|
|
|
l->pos.xRot = v->pos.xRot;
|
|
|
|
l->pos.yRot = v->pos.yRot;
|
|
|
|
l->pos.zRot = v->pos.zRot;
|
|
|
|
|
2021-06-26 07:36:54 +02:00
|
|
|
//S_CDPlay(12, 0);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ObjectCollision(itemNum, l, coll);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
int MineCartControl(void)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
CART_INFO* cart;
|
|
|
|
ITEM_INFO* v;
|
|
|
|
FLOOR_INFO* floor;
|
2020-04-09 14:19:18 +02:00
|
|
|
short roomNumber;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
v = &g_Level.Items[Lara.Vehicle];
|
2019-11-30 13:51:37 +01:00
|
|
|
if (v->data == NULL) { printf("v->data is nullptr !"); return 0; }
|
|
|
|
cart = (CART_INFO*)v->data;
|
|
|
|
|
|
|
|
DoUserInput(v, LaraItem, cart);
|
|
|
|
|
|
|
|
if (cart->Flags & CF_CONTROL)
|
|
|
|
MoveCart(v, LaraItem, cart);
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
if (Lara.Vehicle != NO_ITEM)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
|
|
|
LaraItem->pos.xPos = v->pos.xPos;
|
|
|
|
LaraItem->pos.yPos = v->pos.yPos;
|
|
|
|
LaraItem->pos.zPos = v->pos.zPos;
|
|
|
|
LaraItem->pos.xRot = v->pos.xRot;
|
|
|
|
LaraItem->pos.yRot = v->pos.yRot;
|
|
|
|
LaraItem->pos.zRot = v->pos.zRot;
|
|
|
|
}
|
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
roomNumber = v->roomNumber;
|
|
|
|
floor = GetFloor(v->pos.xPos, v->pos.yPos, v->pos.zPos, &roomNumber);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
if (roomNumber != v->roomNumber)
|
2019-11-30 13:51:37 +01:00
|
|
|
{
|
2020-04-27 14:01:00 +02:00
|
|
|
ItemNewRoom(Lara.Vehicle, roomNumber);
|
2020-04-09 14:19:18 +02:00
|
|
|
ItemNewRoom(Lara.itemNumber, roomNumber);
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|
|
|
|
|
2021-08-20 14:13:06 +03:00
|
|
|
TestTriggersAtXYZ(v->pos.xPos, v->pos.yPos, v->pos.zPos, roomNumber, false, NULL);
|
2019-11-30 13:51:37 +01:00
|
|
|
|
|
|
|
if (!(cart->Flags & CF_DEAD))
|
|
|
|
{
|
|
|
|
Camera.targetElevation = -ANGLE(45);
|
|
|
|
Camera.targetDistance = WALL_SIZE * 2;
|
|
|
|
}
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
return (Lara.Vehicle == NO_ITEM) ? 0 : 1;
|
2019-11-30 13:51:37 +01:00
|
|
|
}
|