2020-08-25 18:14:18 -05:00
|
|
|
#include "framework.h"
|
|
|
|
#include "biggun.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "level.h"
|
|
|
|
#include "collide.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "lara.h"
|
2020-08-29 22:20:52 -03:00
|
|
|
#include "lara_flare.h"
|
2021-09-25 16:00:30 +03:00
|
|
|
#include "Sound/sound.h"
|
|
|
|
#include "effects/effects.h"
|
2020-08-25 18:14:18 -05:00
|
|
|
#include "lara_struct.h"
|
2021-09-25 16:00:30 +03:00
|
|
|
#include "effects/tomb4fx.h"
|
2021-09-16 05:06:03 +03:00
|
|
|
#include "animation.h"
|
2021-08-28 13:27:58 +02:00
|
|
|
#include "setup.h"
|
|
|
|
#include "camera.h"
|
2021-08-29 10:19:47 +02:00
|
|
|
#include "biggun_info.h"
|
2021-09-25 11:27:47 +02:00
|
|
|
|
2020-10-25 00:35:31 -05:00
|
|
|
#define RECOIL_TIME 26
|
|
|
|
#define RECOIL_Z 25
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
// Frames
|
|
|
|
#define BGUN_STATE_UP_DOWN_FRAMES 59
|
|
|
|
#define BGUN_DISMOUNT_FRAME 30
|
|
|
|
|
|
|
|
#define BGUN_IN_FIRE IN_ACTION
|
|
|
|
#define BGUN_IN_DISMOUNT (IN_ROLL | IN_JUMP)
|
|
|
|
#define BGUN_IN_UP IN_FORWARD
|
|
|
|
#define BGUN_IN_DOWN IN_BACK
|
|
|
|
#define BGUN_IN_LEFT IN_LEFT
|
|
|
|
#define BGUN_IN_RIGHT IN_RIGHT
|
|
|
|
|
|
|
|
enum BigGunState {
|
|
|
|
BGUN_STATE_MOUNT = 0,
|
|
|
|
BGUN_STATE_DISMOUNT = 1,
|
|
|
|
BGUN_STATE_UP_DOWN = 2,
|
|
|
|
BGUN_STATE_RECOIL = 3
|
2020-10-25 00:35:31 -05:00
|
|
|
};
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
enum BigGunAnim {
|
|
|
|
BGUN_ANIM_MOUNT = 0,
|
|
|
|
BGUN_ANIM_DISMOUNT = 1,
|
|
|
|
BGUN_ANIM_UP_DOWN = 2,
|
|
|
|
BGUN_ANIM_RECOIL = 3
|
|
|
|
};
|
2020-09-11 12:54:30 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
enum BigGunFlags {
|
|
|
|
BGUN_FLAG_UP_DOWN = 1,
|
|
|
|
BGUN_FLAG_AUTO_ROT = 2,
|
|
|
|
BGUN_FLAG_DISMOUNT = 4,
|
|
|
|
BGUN_FLAG_FIRE = 8
|
|
|
|
};
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
static long GunRotYAdd = 0;
|
|
|
|
bool barrelRotating;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
void FireBigGun(ITEM_INFO* bigGun)
|
|
|
|
{
|
|
|
|
auto bigGunInfo = (BIGGUNINFO*)bigGun->data;
|
|
|
|
auto itemNumber = CreateItem();
|
|
|
|
ITEM_INFO* projectile = &g_Level.Items[itemNumber];
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (itemNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
projectile->objectNumber = ID_ROCKET;
|
|
|
|
projectile->roomNumber = LaraItem->roomNumber;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
PHD_VECTOR pos = { 0, 0, 256 }; // 256 or 520?
|
|
|
|
GetJointAbsPosition(bigGun, &pos, 2);
|
2020-09-11 12:54:30 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
projectile->pos.xPos = pos.x;
|
|
|
|
projectile->pos.yPos = pos.y;
|
|
|
|
projectile->pos.zPos = pos.z;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
InitialiseItem(itemNumber);
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
projectile->pos.xRot = -((bigGunInfo->xRot - 32) * ANGLE(1.0f));
|
|
|
|
projectile->pos.yRot = bigGun->pos.yRot;
|
|
|
|
projectile->pos.zRot = 0;
|
|
|
|
projectile->speed = 16;
|
|
|
|
projectile->itemFlags[0] = 1;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
AddActiveItem(itemNumber);
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
SmokeCountL = 32;
|
|
|
|
SmokeWeapon = WEAPON_ROCKET_LAUNCHER;
|
2020-09-11 12:54:30 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
for (int i = 0; i < 5; i++)
|
|
|
|
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 1, WEAPON_ROCKET_LAUNCHER, 32);
|
2020-08-25 22:55:23 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
SoundEffect(SFX_TR4_EXPLOSION1, 0, 0);
|
|
|
|
}
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
static bool CanUseGun(ITEM_INFO* lara, ITEM_INFO* bigGun)
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
//LaraInfo*& laraInfo = lara->data; // This function is presumably called before Lara is initialised, so global must be used. @Sezz 2021.11.16
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (!(TrInput & IN_ACTION) ||
|
|
|
|
Lara.gunStatus != LG_NO_ARMS ||
|
|
|
|
lara->gravityStatus) // BUG: Lara can still mount when jumping up. @Sezz 2021.11.16
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
auto dist = pow(lara->pos.xPos - bigGun->pos.xPos, 2) + pow(lara->pos.zPos - bigGun->pos.zPos, 2);
|
2020-08-25 18:14:18 -05:00
|
|
|
if (dist > 30000)
|
2021-11-16 22:30:37 +11:00
|
|
|
return false;
|
2020-10-25 00:35:31 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
short angle = abs(lara->pos.yRot - bigGun->pos.yRot);
|
|
|
|
if (angle > ANGLE(35.0f) || angle < -ANGLE(35.0f))
|
|
|
|
return false;
|
2020-10-25 00:35:31 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
return true;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void BigGunInitialise(short itemNum)
|
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
ITEM_INFO* bigGun = &g_Level.Items[itemNum];
|
|
|
|
bigGun->data = BIGGUNINFO();
|
|
|
|
auto bigGunInfo = (BIGGUNINFO*)bigGun->data;
|
|
|
|
|
|
|
|
bigGunInfo->flags = 0;
|
|
|
|
bigGunInfo->fireCount = 0;
|
|
|
|
bigGunInfo->xRot = BGUN_DISMOUNT_FRAME;
|
|
|
|
bigGunInfo->yRot = 0;
|
|
|
|
bigGunInfo->startYRot = bigGun->pos.yRot;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void BigGunCollision(short itemNum, ITEM_INFO* lara, COLL_INFO* coll)
|
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
LaraInfo*& laraInfo = lara->data;
|
|
|
|
ITEM_INFO* bigGun = &g_Level.Items[itemNum];
|
|
|
|
auto bigGunInfo = (BIGGUNINFO*)bigGun->data;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (lara->hitPoints <= 0 || laraInfo->Vehicle != NO_ITEM)
|
2020-08-25 18:14:18 -05:00
|
|
|
return;
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (CanUseGun(bigGun, lara))
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
laraInfo->Vehicle = itemNum;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (laraInfo->gunType == WEAPON_FLARE)
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-20 13:18:59 +11:00
|
|
|
CreateFlare(lara, ID_FLARE_ITEM, 0);
|
|
|
|
undraw_flare_meshes(lara);
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
laraInfo->flareControlLeft = false;
|
|
|
|
laraInfo->requestGunType = WEAPON_NONE;
|
|
|
|
laraInfo->gunType = WEAPON_NONE;
|
|
|
|
}
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
lara->animNumber = Objects[ID_BIGGUN_ANIMS].animIndex + BGUN_ANIM_MOUNT;
|
|
|
|
lara->frameNumber = g_Level.Anims[Objects[ID_BIGGUN_ANIMS].animIndex + BGUN_ANIM_MOUNT].frameBase;
|
|
|
|
lara->currentAnimState = BGUN_STATE_MOUNT;
|
|
|
|
lara->goalAnimState = BGUN_STATE_MOUNT;
|
|
|
|
lara->pos = bigGun->pos;
|
|
|
|
laraInfo->gunStatus = LG_HANDS_BUSY;
|
|
|
|
bigGun->hitPoints = 1;
|
|
|
|
bigGunInfo->flags = 0;
|
|
|
|
bigGunInfo->xRot = BGUN_DISMOUNT_FRAME;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ObjectCollision(itemNum, lara, coll);
|
|
|
|
}
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
bool BigGunControl(ITEM_INFO* lara, COLL_INFO* coll)
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
LaraInfo*& laraInfo = lara->data;
|
|
|
|
ITEM_INFO* bigGun = &g_Level.Items[laraInfo->Vehicle];
|
|
|
|
auto bigGunInfo = (BIGGUNINFO*)bigGun->data;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (bigGunInfo->flags & BGUN_FLAG_UP_DOWN)
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2020-10-25 00:35:31 -05:00
|
|
|
if (barrelRotating)
|
2021-11-16 22:30:37 +11:00
|
|
|
bigGunInfo->barrelZ--;
|
2020-10-25 00:35:31 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (!bigGunInfo->barrelZ)
|
2020-10-25 00:35:31 -05:00
|
|
|
barrelRotating = false;
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (TrInput & BGUN_IN_DISMOUNT || lara->hitPoints <= 0)
|
|
|
|
bigGunInfo->flags = BGUN_FLAG_AUTO_ROT;
|
2020-08-25 18:14:18 -05:00
|
|
|
else
|
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
if (TrInput & BGUN_IN_FIRE && bigGunInfo->fireCount == 0)
|
2020-10-25 00:35:31 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
FireBigGun(bigGun);
|
|
|
|
bigGunInfo->fireCount = RECOIL_TIME;
|
|
|
|
bigGunInfo->barrelZ = RECOIL_Z;
|
2020-10-25 00:35:31 -05:00
|
|
|
barrelRotating = true;
|
|
|
|
}
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (TrInput & BGUN_IN_LEFT)
|
2020-10-25 00:35:31 -05:00
|
|
|
{
|
|
|
|
if (GunRotYAdd > 0)
|
|
|
|
GunRotYAdd /= 2;
|
|
|
|
|
|
|
|
GunRotYAdd -= 8;
|
|
|
|
|
|
|
|
if (GunRotYAdd < -64)
|
|
|
|
GunRotYAdd = -64;
|
|
|
|
}
|
|
|
|
else
|
2021-11-16 22:30:37 +11:00
|
|
|
if (TrInput & BGUN_IN_RIGHT)
|
2020-10-25 00:35:31 -05:00
|
|
|
{
|
|
|
|
if (GunRotYAdd < 0)
|
|
|
|
GunRotYAdd /= 2;
|
2020-08-25 22:55:23 -05:00
|
|
|
|
2020-10-25 00:35:31 -05:00
|
|
|
GunRotYAdd += 8;
|
|
|
|
|
|
|
|
if (GunRotYAdd > 64)
|
|
|
|
GunRotYAdd = 64;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GunRotYAdd -= GunRotYAdd / 4;
|
|
|
|
if (abs(GunRotYAdd) < 8)
|
|
|
|
GunRotYAdd = 0;
|
|
|
|
}
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
bigGunInfo->yRot += GunRotYAdd / 4;
|
2020-10-25 00:35:31 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (TrInput & BGUN_IN_UP && bigGunInfo->xRot < BGUN_STATE_UP_DOWN_FRAMES)
|
|
|
|
bigGunInfo->xRot++;
|
|
|
|
else if (TrInput & BGUN_IN_DOWN && bigGunInfo->xRot)
|
|
|
|
bigGunInfo->xRot--;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
|
|
|
}
|
2020-09-11 00:44:48 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (bigGunInfo->flags & BGUN_FLAG_AUTO_ROT)
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
if (bigGunInfo->xRot == BGUN_DISMOUNT_FRAME)
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
lara->animNumber = Objects[ID_BIGGUN_ANIMS].animIndex + BGUN_ANIM_DISMOUNT;
|
|
|
|
lara->frameNumber = g_Level.Anims[Objects[ID_BIGGUN].animIndex + BGUN_ANIM_DISMOUNT].frameBase;
|
|
|
|
lara->currentAnimState = BGUN_STATE_DISMOUNT;
|
|
|
|
lara->goalAnimState = BGUN_STATE_DISMOUNT;
|
|
|
|
bigGunInfo->flags = BGUN_FLAG_DISMOUNT;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
2021-11-16 22:30:37 +11:00
|
|
|
else if (bigGunInfo->xRot > BGUN_DISMOUNT_FRAME)
|
|
|
|
bigGunInfo->xRot--;
|
|
|
|
else if (bigGunInfo->xRot < BGUN_DISMOUNT_FRAME)
|
|
|
|
bigGunInfo->xRot++;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (lara->currentAnimState)
|
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
case BGUN_STATE_MOUNT:
|
|
|
|
case BGUN_STATE_DISMOUNT:
|
2020-08-25 18:14:18 -05:00
|
|
|
AnimateItem(lara);
|
2021-11-16 22:30:37 +11:00
|
|
|
bigGun->animNumber = Objects[ID_BIGGUN].animIndex + (lara->animNumber - Objects[ID_BIGGUN_ANIMS].animIndex);
|
|
|
|
bigGun->frameNumber = g_Level.Anims[bigGun->animNumber].frameBase + (lara->frameNumber - g_Level.Anims[lara->animNumber].frameBase);
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (bigGunInfo->flags & BGUN_FLAG_DISMOUNT && TestLastFrame(lara, lara->animNumber))
|
2020-08-25 18:14:18 -05:00
|
|
|
{
|
2021-11-16 22:30:37 +11:00
|
|
|
SetAnimation(lara, LA_STAND_IDLE);
|
|
|
|
laraInfo->Vehicle = NO_ITEM;
|
|
|
|
laraInfo->gunStatus = LG_NO_ARMS;
|
|
|
|
bigGun->hitPoints = 0;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|
2021-11-16 22:30:37 +11:00
|
|
|
|
2020-08-25 18:14:18 -05:00
|
|
|
break;
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
case BGUN_STATE_UP_DOWN:
|
|
|
|
lara->animNumber = Objects[ID_BIGGUN_ANIMS].animIndex + BGUN_ANIM_UP_DOWN;
|
|
|
|
lara->frameNumber = g_Level.Anims[Objects[ID_BIGGUN].animIndex + BGUN_ANIM_UP_DOWN].frameBase + bigGunInfo->xRot;
|
|
|
|
bigGun->animNumber = Objects[ID_BIGGUN].animIndex + (lara->animNumber - Objects[ID_BIGGUN_ANIMS].animIndex);
|
|
|
|
bigGun->frameNumber = g_Level.Anims[bigGun->animNumber].frameBase + (lara->frameNumber - g_Level.Anims[lara->animNumber].frameBase);
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
if (bigGunInfo->fireCount > 0)
|
|
|
|
bigGunInfo->fireCount--;
|
|
|
|
else if (bigGunInfo->fireCount <= 0)
|
|
|
|
bigGunInfo->fireCount = 0;
|
|
|
|
|
|
|
|
bigGunInfo->flags = BGUN_FLAG_UP_DOWN;
|
2020-08-25 18:14:18 -05:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
Camera.targetElevation = -ANGLE(15.0f);
|
|
|
|
lara->pos.yRot = bigGunInfo->startYRot + bigGunInfo->yRot * (ANGLE(1.0f) / 4);
|
2021-09-10 00:20:59 +03:00
|
|
|
coll->Setup.EnableSpaz = false;
|
|
|
|
coll->Setup.EnableObjectPush = false;
|
2021-11-16 22:30:37 +11:00
|
|
|
bigGun->pos.yRot = bigGunInfo->startYRot + bigGunInfo->yRot * (ANGLE(1.0f) / 4);
|
2021-09-02 11:20:41 +03:00
|
|
|
DoObjectCollision(lara, coll);
|
2020-08-25 18:14:18 -05:00
|
|
|
|
2021-11-16 22:30:37 +11:00
|
|
|
return true;
|
2020-08-25 18:14:18 -05:00
|
|
|
}
|