TombEngine/TR5Main/Game/larafire.cpp

925 lines
22 KiB
C++
Raw Normal View History

2018-08-19 09:46:58 +02:00
#include "larafire.h"
2018-08-19 09:46:58 +02:00
#include "items.h"
2019-11-21 07:43:34 +01:00
#include "Lara.h"
#include "laraflar.h"
#include "lara1gun.h"
#include "lara2gun.h"
#include "..\Scripting\GameFlowScript.h"
2018-08-19 09:46:58 +02:00
#include <stdio.h>
2019-12-01 08:13:19 +01:00
#include "objects.h"
#include "effects.h"
#include "sphere.h"
#include "draw.h"
#include "effect2.h"
2018-08-19 09:46:58 +02:00
WEAPON_INFO Weapons[NUM_WEAPONS] =
{
/* No weapons */
2019-11-12 12:28:54 +01:00
{
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
0,
0,
0,
0,
0,
0,
0,
0,
0
},
/* Pistols */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(60), ANGLE(60) },
{ -ANGLE(170), ANGLE(60), -ANGLE(80), ANGLE(80) },
{ -ANGLE(60), ANGLE(170), -ANGLE(80), ANGLE(80) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
650,
8 * WALL_SIZE,
1,
9,
3,
0,
SFX_LARA_FIRE
2019-11-12 12:28:54 +01:00
},
/* Revolver */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(60), ANGLE(60) },
{ -ANGLE(10), ANGLE(10), -ANGLE(80), ANGLE(80) },
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(4),
650,
8 * WALL_SIZE,
21,
16,
3,
0,
SFX_REVOLVER
2019-11-12 12:28:54 +01:00
},
/* Uzis */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(60), ANGLE(60) },
{ -ANGLE(170), ANGLE(60), -ANGLE(80), ANGLE(80) },
{ -ANGLE(60), ANGLE(170), -ANGLE(80), ANGLE(80) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
650,
8 * WALL_SIZE,
1,
3,
3,
0,
SFX_LARA_UZI_FIRE
2019-11-12 12:28:54 +01:00
},
/* Shotgun */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(55), ANGLE(55) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
0,
500,
8 * WALL_SIZE,
3,
9,
3,
10,
SFX_LARA_SHOTGUN
2019-11-12 12:28:54 +01:00
},
/* HK */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(55), ANGLE(55) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(4),
500,
12 * WALL_SIZE,
4,
0,
3,
10,
0 // FIRE/SILENCER_FIRE
2019-11-12 12:28:54 +01:00
},
/* Crossbow */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(55), ANGLE(55) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
500,
8 * WALL_SIZE,
5,
0,
2,
10,
SFX_LARA_CROSSBOW
2019-11-12 12:28:54 +01:00
},
/* Flare */
2019-11-12 12:28:54 +01:00
{
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
{ ANGLE(0), ANGLE(0), ANGLE(0), ANGLE(0) },
0,
0,
0,
0,
0,
0,
0,
0,
0
},
/* Flare 2 */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(30), ANGLE(30), -ANGLE(55), ANGLE(55) },
{ -ANGLE(30), ANGLE(30), -ANGLE(55), ANGLE(55) },
{ -ANGLE(30), ANGLE(30), -ANGLE(55), ANGLE(55) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
400,
8 * WALL_SIZE,
3,
0,
2,
0,
SFX_LARA_UZI_FIRE
2019-11-12 12:28:54 +01:00
},
/* Grenade launcher */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(55), ANGLE(55) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
500,
8 * WALL_SIZE,
20,
0,
2,
10,
0
},
/* Harpoon gun */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(65), ANGLE(65) },
{ -ANGLE(20), ANGLE(20), -ANGLE(75), ANGLE(75) },
{ -ANGLE(80), ANGLE(80), -ANGLE(75), ANGLE(75) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
500,
8 * WALL_SIZE,
6,
0,
2,
10,
0
},
/* Rocket launcher */
2019-11-12 12:28:54 +01:00
{
{ -ANGLE(60), ANGLE(60), -ANGLE(55), ANGLE(55) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
{ -ANGLE(80), ANGLE(80), -ANGLE(65), ANGLE(65) },
2019-11-12 12:28:54 +01:00
ANGLE(10),
ANGLE(8),
500,
8 * WALL_SIZE,
30,
0,
2,
12,
77
},
/* Snowmobile */
{
{ -ANGLE(30), ANGLE(30), -ANGLE(55), ANGLE(55) },
{ -ANGLE(30), ANGLE(30), -ANGLE(55), ANGLE(55) },
{ -ANGLE(30), ANGLE(30), -ANGLE(55), ANGLE(55) },
ANGLE(10),
ANGLE(8),
400,
8 * WALL_SIZE,
3,
0,
0,
0,
SFX_LARA_UZI_FIRE
2019-11-12 12:28:54 +01:00
}
};
extern GameFlow* g_GameFlow;
2018-11-21 09:34:01 +01:00
extern LaraExtraInfo g_LaraExtra;
bool MonksAttackLara;
int WeaponObject(int weaponType)
{
switch (weaponType)
{
case WEAPON_UZI:
return ID_UZI_ANIM;
case WEAPON_SHOTGUN:
return ID_SHOTGUN_ANIM;
case WEAPON_REVOLVER:
return ID_REVOLVER_ANIM;
case WEAPON_CROSSBOW:
return ID_CROSSBOW_ANIM;
case WEAPON_HK:
return ID_HK_ANIM;
case WEAPON_FLARE:
return ID_FLARE_ANIM;
2018-11-21 09:34:01 +01:00
case WEAPON_GRENADE_LAUNCHER:
return ID_GRENADE_ANIM;
2018-11-21 09:34:01 +01:00
case WEAPON_ROCKET_LAUNCHER:
return ID_ROCKET_ANIM;
2018-11-21 09:34:01 +01:00
case WEAPON_HARPOON_GUN:
return ID_HARPOON_ANIM;
default:
return ID_PISTOLS_ANIM;
}
}
void AimWeapon(WEAPON_INFO* winfo, LARA_ARM* arm)
2019-11-12 12:28:54 +01:00
{
2019-12-02 09:11:21 +01:00
short rotY, rotX, speed = 0, x = 0, y = 0;
2019-11-12 12:28:54 +01:00
speed = winfo->aimSpeed;
if (arm->lock)
{
y = Lara.targetAngles[0];
x = Lara.targetAngles[1];
}
else
{
y = 0;
x = 0;
}
/* move y axis */
rotY = arm->yRot;
if ((rotY >= (y - speed)) && (rotY <= (y + speed)))
2019-11-12 12:28:54 +01:00
rotY = y;
else if (rotY < speed)
rotY += speed;
else
rotY -= speed;
arm->yRot = rotY;
2019-11-12 12:28:54 +01:00
/* move x axis */
rotX = arm->xRot;
if ((rotX >= (x - speed)) && (rotX <= (x + speed)))
2019-11-12 12:28:54 +01:00
rotX = x;
else if (rotX < x)
rotX += speed;
else
rotX -= speed;
arm->xRot = rotX;
/* move z axis */
2019-11-12 12:28:54 +01:00
arm->zRot = 0;
}
void SmashItem(short itemNum)
2018-08-19 09:46:58 +02:00
{
2019-12-01 08:13:19 +01:00
ITEM_INFO* item = &Items[itemNum];
2019-12-02 09:11:21 +01:00
short objectNumber = item->objectNumber;
2019-12-01 08:13:19 +01:00
if (objectNumber >= ID_SMASH_OBJECT1 && objectNumber <= ID_SMASH_OBJECT8)
SmashObject(itemNum);
/*ITEM_INFO* item = &Items[itemNum];
2019-12-02 09:11:21 +01:00
short objectNumber = item->objectNumber;
2018-08-19 09:46:58 +02:00
printf("SmashItem\n");
if (objectNumber >= ID_SMASH_OBJECT1 && objectNumber <= ID_SMASH_OBJECT8)
SmashObject(itemNum);
else if (objectNumber == ID_BELL_SWITCH)
{
if (item->status != ITEM_ACTIVE)
{
item->status = ITEM_ACTIVE;
AddActiveItem(itemNum);
}
}*/
2018-08-19 09:46:58 +02:00
}
void LaraGun()
{
2019-12-02 09:11:21 +01:00
int meshIndex;
if (Lara.leftArm.flash_gun > 0)
--Lara.leftArm.flash_gun;
if (Lara.rightArm.flash_gun > 0)
--Lara.rightArm.flash_gun;
if (Lara.gunType == WEAPON_TORCH)
{
DoFlameTorch();
return;
}
2019-12-02 09:11:21 +01:00
int gunStatus = Lara.gunStatus;
if (LaraItem->hitPoints <= 0)
{
gunStatus = LG_NO_ARMS;
Lara.gunStatus = LG_NO_ARMS;
}
else if (!Lara.gunStatus)
{
if (TrInput & IN_DRAW)
Lara.requestGunType = Lara.lastGunType;
else if ((TrInput & IN_FLARE) && (g_GameFlow->GetLevel(CurrentLevel)->LaraType != LARA_YOUNG))
{
if (LaraItem->currentAnimState == 71 && LaraItem->animNumber != 222)
return;
if (Lara.gunType == WEAPON_FLARE && !Lara.leftArm.frameNumber)
Lara.gunStatus = LG_UNDRAW_GUNS;
else if (Lara.numFlares)
{
if (Lara.numFlares != -1)
Lara.numFlares--;
Lara.requestGunType = WEAPON_FLARE;
}
}
if ((Lara.requestGunType != Lara.gunType) || (TrInput & IN_DRAW))
{
2019-12-01 08:13:19 +01:00
if ((LaraItem->currentAnimState == STATE_LARA_CROUCH_IDLE
|| LaraItem->currentAnimState == STATE_LARA_CROUCH_TURN_LEFT
|| LaraItem->currentAnimState == STATE_LARA_CROUCH_TURN_RIGHT) &&
(Lara.requestGunType == WEAPON_HK || Lara.requestGunType == WEAPON_CROSSBOW || Lara.requestGunType == WEAPON_FLARE))
{
if (Lara.gunType != WEAPON_FLARE)
Lara.requestGunType = WEAPON_FLARE;
}
else if (Lara.requestGunType != WEAPON_FLARE)
{
if (Lara.waterStatus)
{
2019-12-01 08:13:19 +01:00
if (Lara.waterStatus != LW_WADE || Lara.waterSurfaceDist <= -Weapons[Lara.gunType].gunHeight)
{
Lara.lastGunType = Lara.requestGunType;
if (Lara.gunType != WEAPON_FLARE)
Lara.gunType = Lara.requestGunType;
else
Lara.requestGunType = WEAPON_FLARE;
}
}
}
else if (Lara.gunType == WEAPON_FLARE)
{
CreateFlare(ID_FLARE_ITEM, 0);
2019-12-01 08:13:19 +01:00
undraw_flare_meshes();
Lara.flareControlLeft;
Lara.flareAge = 0;
}
Lara.gunType = Lara.requestGunType;
InitialiseNewWeapon();
Lara.rightArm.frameNumber = 0;
Lara.leftArm.frameNumber = 0;
Lara.gunStatus = LG_DRAW_GUNS;
}
}
else if (Lara.gunStatus == LG_READY)
{
if ((TrInput & IN_DRAW) || Lara.requestGunType != Lara.gunType)
Lara.gunStatus = LG_UNDRAW_GUNS;
2018-11-21 09:34:01 +01:00
else if (Lara.gunType != WEAPON_HARPOON_GUN && Lara.waterStatus != LW_ABOVE_WATER &&
(Lara.waterStatus != LW_WADE || Lara.waterSurfaceDist < -Weapons[Lara.gunType].gunHeight))
Lara.gunStatus = LG_UNDRAW_GUNS;
}
else if (Lara.gunStatus == LG_HANDS_BUSY
&& TrInput & IN_FLARE
&& LaraItem->currentAnimState == 80
&& LaraItem->animNumber == 263)
Lara.requestGunType = WEAPON_FLARE;
switch (Lara.gunStatus)
{
case LG_DRAW_GUNS:
if (Lara.gunType != WEAPON_FLARE && Lara.gunType)
Lara.lastGunType = Lara.gunType;
switch (Lara.gunType)
{
case WEAPON_PISTOLS:
case WEAPON_REVOLVER:
case WEAPON_UZI:
if (Camera.type != CAMERA_TYPE::CINEMATIC_CAMERA && Camera.type != CAMERA_TYPE::LOOK_CAMERA &&
Camera.type != CAMERA_TYPE::HEAVY_CAMERA)
Camera.type = CAMERA_TYPE::COMBAT_CAMERA;
2019-12-01 08:13:19 +01:00
draw_pistols(Lara.gunType);
break;
case WEAPON_SHOTGUN:
case WEAPON_CROSSBOW:
case WEAPON_HK:
2018-11-21 09:34:01 +01:00
case WEAPON_GRENADE_LAUNCHER:
case WEAPON_ROCKET_LAUNCHER:
case WEAPON_HARPOON_GUN:
if (Camera.type != CAMERA_TYPE::CINEMATIC_CAMERA && Camera.type != CAMERA_TYPE::LOOK_CAMERA &&
Camera.type != CAMERA_TYPE::HEAVY_CAMERA)
Camera.type = CAMERA_TYPE::COMBAT_CAMERA;
DrawShotgun(Lara.gunType);
break;
case WEAPON_FLARE:
2019-12-01 08:13:19 +01:00
draw_flare();
break;
default:
Lara.gunStatus = LG_NO_ARMS;
break;
}
break;
case LG_SPECIAL:
2019-12-01 08:13:19 +01:00
draw_flare();
break;
case LG_UNDRAW_GUNS:
Lara.meshPtrs[HEAD] = Meshes[Objects[ID_LARA].meshIndex + 14 * 2];
switch (Lara.gunType)
{
case WEAPON_PISTOLS:
case WEAPON_REVOLVER:
case WEAPON_UZI:
2019-12-01 08:13:19 +01:00
undraw_pistols(Lara.gunType);
break;
case WEAPON_SHOTGUN:
case WEAPON_CROSSBOW:
case WEAPON_HK:
2018-11-21 09:34:01 +01:00
case WEAPON_GRENADE_LAUNCHER:
case WEAPON_ROCKET_LAUNCHER:
case WEAPON_HARPOON_GUN:
2019-12-01 08:13:19 +01:00
undraw_shotgun(Lara.gunType);
break;
case WEAPON_FLARE:
2019-12-01 08:13:19 +01:00
undraw_flare();
break;
default:
return;
}
break;
case LG_READY:
if (!(TrInput & IN_ACTION))
meshIndex = Objects[ID_LARA].meshIndex;
else
meshIndex = Objects[ID_LARA_SCREAM].meshIndex;
Lara.meshPtrs[HEAD] = Meshes[meshIndex + 14 * 2];
if (Camera.type != CAMERA_TYPE::CINEMATIC_CAMERA && Camera.type != CAMERA_TYPE::LOOK_CAMERA &&
Camera.type != CAMERA_TYPE::HEAVY_CAMERA)
Camera.type = CAMERA_TYPE::COMBAT_CAMERA;
if (TrInput & IN_ACTION)
{
if (!GetAmmo(Lara.gunType))
{
Lara.requestGunType = Objects[ID_PISTOLS_ITEM].loaded;
return;
}
}
switch (Lara.gunType)
{
case WEAPON_PISTOLS:
case WEAPON_UZI:
2019-12-01 08:13:19 +01:00
PistolHandler(Lara.gunType);
break;
case WEAPON_SHOTGUN:
case WEAPON_CROSSBOW:
case WEAPON_HK:
2018-11-21 09:34:01 +01:00
case WEAPON_GRENADE_LAUNCHER:
case WEAPON_ROCKET_LAUNCHER:
case WEAPON_HARPOON_GUN:
case WEAPON_REVOLVER:
RifleHandler(Lara.gunType);
break;
default:
return;
}
break;
case LG_NO_ARMS:
if (Lara.gunType == WEAPON_FLARE)
{
2018-11-21 09:34:01 +01:00
if (g_LaraExtra.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState))
{
if (Lara.flareControlLeft)
{
if (Lara.leftArm.frameNumber)
{
if (++Lara.leftArm.frameNumber == 110)
Lara.leftArm.frameNumber = 0;
}
}
else
{
Lara.leftArm.frameNumber = 95;
Lara.flareControlLeft = true;
}
}
else
{
Lara.flareControlLeft = false;
}
DoFlareInHand(Lara.flareAge);
2019-12-01 08:13:19 +01:00
set_flare_arm(Lara.leftArm.frameNumber);
}
break;
case LG_HANDS_BUSY:
if (Lara.gunType == WEAPON_FLARE)
{
if (Lara.meshPtrs[HAND_L] == Meshes[Objects[ID_FLARE_ANIM].meshIndex + 26])
{
2018-11-21 09:34:01 +01:00
Lara.flareControlLeft = (g_LaraExtra.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState));
DoFlareInHand(Lara.flareAge);
2019-12-01 08:13:19 +01:00
set_flare_arm(Lara.leftArm.frameNumber);
}
}
break;
}
}
short* GetAmmo(int weaponType)
{
2018-11-21 09:34:01 +01:00
return &g_LaraExtra.Weapons[weaponType].Ammo[g_LaraExtra.Weapons[weaponType].SelectedAmmo];
}
void InitialiseNewWeapon()
{
Lara.rightArm.frameNumber = 0;
Lara.leftArm.frameNumber = 0;
Lara.leftArm.zRot = 0;
Lara.leftArm.yRot = 0;
Lara.leftArm.xRot = 0;
Lara.rightArm.zRot = 0;
Lara.rightArm.yRot = 0;
Lara.rightArm.xRot = 0;
Lara.target = 0;
Lara.rightArm.lock = 0;
Lara.leftArm.lock = 0;
Lara.rightArm.flash_gun = 0;
Lara.leftArm.flash_gun = 0;
switch (Lara.gunType)
{
case WEAPON_PISTOLS:
case WEAPON_UZI:
Lara.rightArm.frameBase = Objects[ID_PISTOLS_ANIM].frameBase;
Lara.leftArm.frameBase = Objects[ID_PISTOLS_ANIM].frameBase;
if (Lara.gunStatus)
2019-12-01 08:13:19 +01:00
draw_pistol_meshes(Lara.gunType);
break;
case WEAPON_SHOTGUN:
case WEAPON_REVOLVER:
case WEAPON_HK:
2018-11-21 09:34:01 +01:00
case WEAPON_GRENADE_LAUNCHER:
case WEAPON_HARPOON_GUN:
case WEAPON_ROCKET_LAUNCHER:
Lara.rightArm.frameBase = Objects[WeaponObject(Lara.gunType)].frameBase;
Lara.leftArm.frameBase = Lara.rightArm.frameBase;
if (Lara.gunStatus)
2019-12-01 08:13:19 +01:00
undraw_shotgun_meshes(Lara.gunType);
break;
case WEAPON_FLARE:
Lara.rightArm.frameBase = Objects[ID_FLARE_ANIM].frameBase;
Lara.leftArm.frameBase = Objects[ID_FLARE_ANIM].frameBase;
if (Lara.gunStatus)
2019-12-01 08:13:19 +01:00
draw_flare_meshes();
break;
default:
Lara.rightArm.frameBase = Anims[LaraItem->animNumber].framePtr;
Lara.leftArm.frameBase = Anims[LaraItem->animNumber].framePtr;
break;
}
}
int WeaponObjectMesh(int weaponType)
{
switch (weaponType)
{
case WEAPON_REVOLVER:
2018-11-21 09:34:01 +01:00
return ((g_LaraExtra.Weapons[WEAPON_REVOLVER].HasLasersight) != 0 ? ID_LARA_REVOLVER_LASER : ID_REVOLVER_ANIM);
case WEAPON_UZI:
return ID_UZI_ANIM;
case WEAPON_SHOTGUN:
return ID_SHOTGUN_ANIM;
case WEAPON_HK:
return ID_HK_ANIM;
case WEAPON_CROSSBOW:
2018-11-21 09:34:01 +01:00
return ((g_LaraExtra.Weapons[WEAPON_CROSSBOW].HasLasersight) != 0 ? ID_LARA_CROSSBOW_LASER : ID_CROSSBOW_ANIM);
2018-11-21 09:34:01 +01:00
case WEAPON_GRENADE_LAUNCHER:
return ID_GRENADE_ANIM;
2018-11-21 09:34:01 +01:00
case WEAPON_HARPOON_GUN:
return ID_HARPOON_ANIM;
2018-11-21 09:34:01 +01:00
case WEAPON_ROCKET_LAUNCHER:
return ID_ROCKET_ANIM;
default:
return ID_PISTOLS_ANIM;
}
}
void HitTarget(ITEM_INFO* item, GAME_VECTOR* hitPos, int damage, int flag)
2019-12-01 08:13:19 +01:00
{
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
OBJECT_INFO* obj = &Objects[item->objectNumber];
item->hitStatus = true;
if (creature && item != LaraItem)
creature->hurtByLara = true;
if (hitPos)
{
if (obj->hitEffect)
{
switch (obj->hitEffect)
{
case 1:
DoBloodSplat(hitPos->x, hitPos->y, hitPos->z, (GetRandomControl() & 3) + 3, item->pos.yRot, item->roomNumber);
break;
case 3:
TriggerRicochetSparks(hitPos, LaraItem->pos.yRot, 3, 0);
break;
case 2:
TriggerRicochetSparks(hitPos, LaraItem->pos.yRot, 3, -5);
SoundEffect(SFX_SWORD_GOD_HITMET, &item->pos, 0);
break;
}
}
}
if (!obj->undead || flag || item->hitPoints == -16384)
{
if (item->hitPoints > 0 && item->hitPoints <= damage)
++Savegame.Level.Kills;
item->hitPoints -= damage;
}
}
int FireWeapon(int weaponType, ITEM_INFO* target, ITEM_INFO* src, short* angles)
2019-12-01 08:13:19 +01:00
{
PHD_3DPOS pos;
pos.xPos = 0;
pos.yPos = 0;
pos.zPos = 0;
GetLaraJointPosition((PHD_VECTOR*)&pos, 11);
2019-12-02 09:11:21 +01:00
short* ammo = GetAmmo(weaponType);
2019-12-01 08:13:19 +01:00
if (!*ammo)
return 0;
if (*ammo != -1)
(*ammo)--;
WEAPON_INFO* weapon = &Weapons[weaponType];
pos.xPos = src->pos.xPos;
pos.yPos = src->pos.yPos - weapon->gunHeight;
pos.zPos = src->pos.zPos;
2019-12-02 09:11:21 +01:00
int r = (int)((GetRandomControl() - 16384) * weapon->shotAccuracy) / 65536;
pos.xRot = angles[1] + (short)r;
r = (int)((GetRandomControl() - 16384) * weapon->shotAccuracy) / 65536;
pos.yRot = angles[0] + (short)r;
2019-12-01 08:13:19 +01:00
pos.zRot = 0;
phd_GenerateW2V(&pos);
2019-12-02 09:11:21 +01:00
int num = GetSpheres(target, SphereList, 0);
int best = -1;
int bestDistance = 0x7FFFFFFF;
2019-12-01 08:13:19 +01:00
2019-12-02 09:11:21 +01:00
for (int i = 0; i < num; i++)
2019-12-01 08:13:19 +01:00
{
SPHERE* sphere = &SphereList[i];
r = sphere->r;
if ((abs(sphere->x)) < r && (abs(sphere->y)) < r && sphere->z > r && SQUARE(sphere->x) + SQUARE(sphere->y) <= SQUARE(r))
{
if (sphere->z - r < bestDistance)
{
bestDistance = sphere->z - r;
best = i;
}
}
}
Lara.hasFired = true;
Lara.fired = true;
GAME_VECTOR vSrc;
vSrc.x = pos.xPos;
vSrc.y = pos.yPos;
vSrc.z = pos.zPos;
2019-12-02 09:11:21 +01:00
short roomNumber = src->roomNumber;
2019-12-01 08:13:19 +01:00
FLOOR_INFO* floor = GetFloor(pos.xPos, pos.yPos, pos.zPos, &roomNumber);
vSrc.roomNumber = roomNumber;
if (best < 0)
{
GAME_VECTOR vDest;
vDest.x = vSrc.x + ((*(MatrixPtr + M20) * weapon->targetDist) >> W2V_SHIFT);
vDest.y = vSrc.y + ((*(MatrixPtr + M21) * weapon->targetDist) >> W2V_SHIFT);
vDest.z = vSrc.z + ((*(MatrixPtr + M22) * weapon->targetDist) >> W2V_SHIFT);
GetTargetOnLOS(&vSrc, &vDest, 0, 1);
return -1;
}
else
{
Savegame.Game.AmmoHits++;
GAME_VECTOR vDest;
vDest.x = vSrc.x + ((*(MatrixPtr + M20) * bestDistance) >> W2V_SHIFT);
vDest.y = vSrc.y + ((*(MatrixPtr + M21) * bestDistance) >> W2V_SHIFT);
vDest.z = vSrc.z + ((*(MatrixPtr + M22) * bestDistance) >> W2V_SHIFT);
// TODO: enable it when the slot is created !
/*if (target->objectNumber != ID_SHIVA && target->objectNumber != ID_ARMY_WINSTON && target->objectNumber != ID_LONDONBOSS && (target->objectNumber != ID_TRIBEBOSS || TribeBossShieldOn == false)) // Hit TRIBEBOSS's shield if on.
{
2019-12-01 08:13:19 +01:00
HitTarget(target, &vDest, weapon->damage, 0);
}
else if (target->objectNumber == ID_TRIBEBOSS)
{
long dx, dy, dz;
dx = (vDest.x - vSrc.x) >> 5;
dy = (vDest.y - vSrc.y) >> 5;
dz = (vDest.z - vSrc.z) >> 5;
FindClosestShieldPoint(vDest.x - dx, vDest.y - dy, vDest.z - dz, target);
}
else if (target->objectNumber == ID_ARMY_WINSTON || target->objectNumber == ID_LONDONBOSS) //Don't want blood on Winston - never get the stains out
{
short ricochet_angle;
target->hitStatus = true; //need to do this to maintain defence state
target->hitPoints--;
ricochet_angle = (mGetAngle(LaraItem->pos.zPos, LaraItem->pos.xPos, target->pos.zPos, target->pos.xPos) >> 4) & 4095;
TriggerRicochetSparks(&vDest, ricochet_angle, 16, 0);
SoundEffect(SFX_LARA_RICOCHET, &target->pos, 0); // play RICOCHET Sample
}
else if (target->objectNumber == ID_SHIVA) //So must be Shiva
{
z = target->pos.zPos - lara_item->pos.zPos;
x = target->pos.xPos - lara_item->pos.xPos;
angle = 0x8000 + ATAN(z, x) - target->pos.yRot;
if ((target->currentAnimState > 1 && target->currentAnimState < 5) && angle < 0x4000 && angle > -0x4000)
{
target->hitStatus = true; //need to do this to maintain defence state
ricochet_angle = (mGetAngle(LaraItem->pos.zPos, LaraItem->pos.xPos, target->pos.zPos, target->pos.xPos) >> 4) & 4095;
TriggerRicochetSparks(&vDest, ricochet_angle, 16, 0);
SoundEffect(SFX_LARA_RICOCHET, &target->pos, 0); // play RICOCHET Sample
}
else //Shiva's not in defence mode or has its back to Lara
HitTarget(target, &vDest, weapon->damage, 0);
}
else
{*/
if (!GetTargetOnLOS(&vSrc, &vDest, 0, 1))
HitTarget(target, &vDest, weapon->damage, 0);
//}
2019-12-01 08:13:19 +01:00
return 1;
}
}
void find_target_point(ITEM_INFO* item, GAME_VECTOR* target)
2019-12-01 08:13:19 +01:00
{
2019-12-02 09:11:21 +01:00
short* bounds = GetBestFrame(item);
2019-12-01 08:13:19 +01:00
2019-12-02 09:11:21 +01:00
int x = (int)((*(bounds + 0) + *(bounds + 1)) / 2);
int y = (int)(*(bounds + 2) + (*(bounds + 3) - *(bounds + 2)) / 3);
int z = (int)((*(bounds + 4) + *(bounds + 5)) / 2);
2019-12-01 08:13:19 +01:00
2019-12-02 09:11:21 +01:00
int c = COS(item->pos.yRot);
int s = SIN(item->pos.yRot);
2019-12-01 08:13:19 +01:00
target->x = item->pos.xPos + ((c * x + s * z) >> W2V_SHIFT);
target->y = item->pos.yPos + y;
target->z = item->pos.zPos + ((c * z - s * x) >> W2V_SHIFT);
target->roomNumber = item->roomNumber;
}
void LaraTargetInfo(WEAPON_INFO* weapon)
2019-12-01 08:13:19 +01:00
{
if (!Lara.target)
{
Lara.rightArm.lock = 0;
Lara.leftArm.lock = 0;
Lara.targetAngles[1] = 0;
Lara.targetAngles[0] = 0;
return;
}
GAME_VECTOR pos;
pos.x = 0;
pos.y = 0;
pos.z = 0;
GetLaraJointPosition((PHD_VECTOR*)&pos, LJ_RHAND);
pos.x = LaraItem->pos.xPos;
pos.z = LaraItem->pos.zPos;
pos.roomNumber = LaraItem->roomNumber;
GAME_VECTOR targetPoint;
find_target_point(Lara.target, &targetPoint);
2019-12-02 09:11:21 +01:00
short angles[2];
2019-12-01 08:13:19 +01:00
phd_GetVectorAngles(targetPoint.x - pos.x, targetPoint.y - pos.y, targetPoint.z - pos.z, angles);
angles[0] -= LaraItem->pos.yRot;
angles[1] -= LaraItem->pos.xRot;
if (LOS(&pos, &targetPoint))
{
if (angles[0] >= weapon->lockAngles[0]
&& angles[0] <= weapon->lockAngles[1]
&& angles[1] >= weapon->lockAngles[2]
&& angles[1] <= weapon->lockAngles[3])
{
Lara.rightArm.lock = 1;
Lara.leftArm.lock = 1;
Lara.targetAngles[0] = angles[0];
Lara.targetAngles[1] = angles[1];
return;
}
if (Lara.leftArm.lock
&& (angles[0] < weapon->leftAngles[0]
|| angles[0] > weapon->leftAngles[1]
|| angles[1] < weapon->leftAngles[2]
|| angles[1] > weapon->leftAngles[3]))
{
Lara.leftArm.lock = 0;
}
if (Lara.rightArm.lock
&& (angles[0] < weapon->rightAngles[0]
|| angles[0] > weapon->rightAngles[1]
|| angles[1] < weapon->rightAngles[2]
|| angles[1] > weapon->rightAngles[3]))
{
Lara.rightArm.lock = 0;
Lara.targetAngles[0] = angles[0];
Lara.targetAngles[1] = angles[1];
return;
}
}
else
{
Lara.rightArm.lock = 0;
Lara.leftArm.lock = 0;
}
Lara.targetAngles[0] = angles[0];
Lara.targetAngles[1] = angles[1];
}
2018-08-19 09:46:58 +02:00
void Inject_LaraFire()
{
2019-11-12 12:28:54 +01:00
INJECT(0x00453490, AimWeapon);
INJECT(0x00453AE0, WeaponObject);
INJECT(0x00452430, LaraGun);
INJECT(0x004546C0, GetAmmo);
INJECT(0x00452B30, InitialiseNewWeapon);
INJECT(0x00453B50, WeaponObjectMesh);
//INJECT(0x00453A90, SmashItem);
2018-08-19 09:46:58 +02:00
}