Merge branch 'DiagonalCollisions' into NoShifts

This commit is contained in:
asasas9500 2020-08-07 16:43:29 -03:00
commit 671d59e1c8
304 changed files with 15655 additions and 17021 deletions

View file

@ -1,3 +1,4 @@
#include "./../VertexInput.hlsli"
cbuffer HUDBarBuffer : register(b0) cbuffer HUDBarBuffer : register(b0)
{ {
float Percent; float Percent;

View file

@ -1,18 +1,10 @@
#include "./../VertexInput.hlsli"
cbuffer HUDBuffer : register(b0) cbuffer HUDBuffer : register(b0)
{ {
float4x4 View; float4x4 View;
float4x4 Projection; float4x4 Projection;
}; };
struct VertexShaderInput
{
float3 Position: POSITION;
float3 Normal: NORMAL;
float2 UV: TEXCOORD;
float4 Color: COLOR;
float Bone : BLENDINDICES;
};
struct PixelShaderInput struct PixelShaderInput
{ {
float4 Position: SV_POSITION; float4 Position: SV_POSITION;

View file

@ -36,14 +36,14 @@ typedef enum ZoneType
ZONE_APE, // only 2 click climb ZONE_APE, // only 2 click climb
}; };
typedef struct OBJECT_BONES typedef struct OBJECT_Bones
{ {
short bone0; short bone0;
short bone1; short bone1;
short bone2; short bone2;
short bone3; short bone3;
OBJECT_BONES() OBJECT_Bones()
{ {
this->bone0 = 0; this->bone0 = 0;
this->bone1 = 0; this->bone1 = 0;
@ -51,7 +51,7 @@ typedef struct OBJECT_BONES
this->bone3 = 0; this->bone3 = 0;
} }
OBJECT_BONES(short all) OBJECT_Bones(short all)
{ {
this->bone0 = all; this->bone0 = all;
this->bone1 = all; this->bone1 = all;
@ -59,7 +59,7 @@ typedef struct OBJECT_BONES
this->bone3 = all; this->bone3 = all;
} }
OBJECT_BONES(short angleY, short angleX) OBJECT_Bones(short angleY, short angleX)
{ {
this->bone0 = angleY; this->bone0 = angleY;
this->bone1 = angleX; this->bone1 = angleX;
@ -67,7 +67,7 @@ typedef struct OBJECT_BONES
this->bone3 = angleX; this->bone3 = angleX;
} }
OBJECT_BONES(short angleY, short angleX, bool total) OBJECT_Bones(short angleY, short angleX, bool total)
{ {
this->bone0 = angleY; this->bone0 = angleY;
this->bone1 = angleX; this->bone1 = angleX;
@ -84,28 +84,18 @@ typedef struct OBJECT_BONES
} }
}; };
typedef struct BOX_NODE struct BOX_NODE
{ {
short exitBox; int exitBox;
unsigned short searchNumber; int searchNumber;
short nextExpansion; int nextExpansion;
short boxNumber; int boxNumber;
}; };
typedef struct BOX_INFO struct AI_INFO
{ {
unsigned char left; int zoneNumber;
unsigned char right; int enemyZone;
unsigned char top;
unsigned char bottom;
short height;
short overlapIndex;
};
typedef struct AI_INFO
{
short zoneNumber;
short enemyZone;
int distance; int distance;
int ahead; int ahead;
int bite; int bite;
@ -114,7 +104,24 @@ typedef struct AI_INFO
short enemyFacing; short enemyFacing;
}; };
typedef struct BITE_INFO struct BOX_INFO
{
unsigned int left;
unsigned int right;
unsigned int top;
unsigned int bottom;
int height;
int overlapIndex;
int flags;
};
struct OVERLAP
{
int box;
int flags;
};
struct BITE_INFO
{ {
int x; int x;
int y; int y;
@ -138,18 +145,18 @@ typedef struct BITE_INFO
} }
}; };
typedef struct LOT_INFO struct LOT_INFO
{ {
BOX_NODE* node; std::vector<BOX_NODE> node;
short head; int head;
short tail; int tail;
unsigned short searchNumber; int searchNumber;
unsigned short blockMask; int blockMask;
short step; short step;
short drop; short drop;
short zoneCount; short zoneCount;
short targetBox; int targetBox;
short requiredBox; int requiredBox;
short fly; short fly;
bool canJump; bool canJump;
bool canMonkey; bool canMonkey;
@ -160,7 +167,7 @@ typedef struct LOT_INFO
ZoneType zone; ZoneType zone;
}; };
typedef struct CREATURE_INFO struct CREATURE_INFO
{ {
short jointRotation[4]; short jointRotation[4];
short maximumTurn; short maximumTurn;
@ -249,7 +256,7 @@ constexpr auto BLOCKED = 0x4000;
constexpr auto OVERLAP_INDEX = 0x3FFF; constexpr auto OVERLAP_INDEX = 0x3FFF;
constexpr auto SEARCH_NUMBER = 0x7FFF; constexpr auto SEARCH_NUMBER = 0x7FFF;
constexpr auto BLOCKED_SEARCH = 0x8000; constexpr auto BLOCKED_SEARCH = 0x8000;
constexpr auto NO_BOX = 0x7FF; constexpr auto NO_BOX = -1;
constexpr auto BOX_JUMP = 0x800; constexpr auto BOX_JUMP = 0x800;
constexpr auto BOX_MONKEY = 0x2000; constexpr auto BOX_MONKEY = 0x2000;
constexpr auto BOX_NUMBER = 0x7FF; constexpr auto BOX_NUMBER = 0x7FF;
@ -268,12 +275,6 @@ constexpr auto SECONDARY_CLIP = 0x10;
constexpr auto ALL_CLIP = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM); constexpr auto ALL_CLIP = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM);
constexpr auto SLOPE_DIF = 60; constexpr auto SLOPE_DIF = 60;
extern int NumberBoxes;
extern BOX_INFO* Boxes;
extern int NumberOverlaps;
extern short* Overlaps;
extern short* Zones[ZONE_MAX][2];
void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int violent); void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int violent);
void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent); void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent);
void FindAITargetObject(CREATURE_INFO* creature, short objectNumber); void FindAITargetObject(CREATURE_INFO* creature, short objectNumber);
@ -299,13 +300,13 @@ void CreatureDie(short itemNumber, int explode);
int BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumber, LOT_INFO* LOT); int BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumber, LOT_INFO* LOT);
int CreatureCreature(short itemNumber); int CreatureCreature(short itemNumber);
int ValidBox(ITEM_INFO* item, short zoneNumber, short boxNumber); int ValidBox(ITEM_INFO* item, short zoneNumber, short boxNumber);
int EscapeBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber); int EscapeBox(ITEM_INFO* item, ITEM_INFO* enemy, int boxNumber);
void TargetBox(LOT_INFO* LOT, short boxNumber); void TargetBox(LOT_INFO* LOT, int boxNumber);
int UpdateLOT(LOT_INFO* LOT, int expansion); int UpdateLOT(LOT_INFO* LOT, int expansion);
int SearchLOT(LOT_INFO* LOT, int expansion); int SearchLOT(LOT_INFO* LOT, int expansion);
int CreatureActive(short itemNumber); int CreatureActive(short itemNumber);
void InitialiseCreature(short itemNumber); void InitialiseCreature(short itemNumber);
int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber); int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, int boxNumber);
void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info); void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info);
TARGET_TYPE CalculateTarget(PHD_VECTOR* target, ITEM_INFO* item, LOT_INFO* LOT); TARGET_TYPE CalculateTarget(PHD_VECTOR* target, ITEM_INFO* item, LOT_INFO* LOT);
int CreatureAnimation(short itemNumber, short angle, short tilt); int CreatureAnimation(short itemNumber, short angle, short tilt);

View file

@ -12,12 +12,6 @@
#include "trmath.h" #include "trmath.h"
#include "objectslist.h" #include "objectslist.h"
int NumberBoxes;
BOX_INFO* Boxes;
int NumberOverlaps;
short* Overlaps;
short* Zones[ZONE_MAX][2];
#define CHECK_CLICK(x) CLICK(x) / 2 #define CHECK_CLICK(x) CLICK(x) / 2
#define ESCAPE_DIST SECTOR(5) #define ESCAPE_DIST SECTOR(5)
#define STALK_DIST SECTOR(3) #define STALK_DIST SECTOR(3)
@ -34,11 +28,11 @@ void DropBaddyPickups(ITEM_INFO* item)
ITEM_INFO* pickup = NULL; ITEM_INFO* pickup = NULL;
FLOOR_INFO* floor; FLOOR_INFO* floor;
short roomNumber; short roomNumber;
short* bounds; BOUNDING_BOX* bounds;
for (short pickupNumber = item->carriedItem; pickupNumber != NO_ITEM; pickupNumber = pickup->carriedItem) for (short pickupNumber = item->carriedItem; pickupNumber != NO_ITEM; pickupNumber = pickup->carriedItem)
{ {
pickup = &Items[pickupNumber]; pickup = &g_Level.Items[pickupNumber];
pickup->pos.xPos = (item->pos.xPos & -CLICK(2)) | CLICK(2); pickup->pos.xPos = (item->pos.xPos & -CLICK(2)) | CLICK(2);
pickup->pos.zPos = (item->pos.zPos & -CLICK(2)) | CLICK(2); pickup->pos.zPos = (item->pos.zPos & -CLICK(2)) | CLICK(2);
@ -46,7 +40,7 @@ void DropBaddyPickups(ITEM_INFO* item)
floor = GetFloor(pickup->pos.xPos, item->pos.yPos, pickup->pos.zPos, &roomNumber); floor = GetFloor(pickup->pos.xPos, item->pos.yPos, pickup->pos.zPos, &roomNumber);
pickup->pos.yPos = GetFloorHeight(floor, pickup->pos.xPos, item->pos.yPos, pickup->pos.zPos); pickup->pos.yPos = GetFloorHeight(floor, pickup->pos.xPos, item->pos.yPos, pickup->pos.zPos);
bounds = GetBoundsAccurate(pickup); bounds = GetBoundsAccurate(pickup);
pickup->pos.yPos -= bounds[3]; pickup->pos.yPos -= bounds->Y2;
ItemNewRoom(pickupNumber, item->roomNumber); ItemNewRoom(pickupNumber, item->roomNumber);
pickup->flags |= 32; pickup->flags |= 32;
@ -112,17 +106,17 @@ void CreatureYRot2(PHD_3DPOS* srcpos, short angle, short angadd)
short SameZone(CREATURE_INFO* creature, ITEM_INFO* targetItem) short SameZone(CREATURE_INFO* creature, ITEM_INFO* targetItem)
{ {
ITEM_INFO* item = &Items[creature->itemNum]; ITEM_INFO* item = &g_Level.Items[creature->itemNum];
ROOM_INFO* r; ROOM_INFO* r;
short* zone; int* zone;
r = &Rooms[item->roomNumber]; r = &g_Level.Rooms[item->roomNumber];
item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box; item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box;
r = &Rooms[targetItem->roomNumber]; r = &g_Level.Rooms[targetItem->roomNumber];
targetItem->boxNumber = XZ_GET_SECTOR(r, targetItem->pos.xPos - r->x, targetItem->pos.zPos - r->z).box; targetItem->boxNumber = XZ_GET_SECTOR(r, targetItem->pos.xPos - r->x, targetItem->pos.zPos - r->z).box;
zone = Zones[creature->LOT.zone][FlipStatus]; zone = g_Level.Zones[creature->LOT.zone][FlipStatus].data();
return zone[item->boxNumber] == zone[targetItem->boxNumber]; return zone[item->boxNumber] == zone[targetItem->boxNumber];
} }
@ -131,7 +125,7 @@ short AIGuard(CREATURE_INFO* creature)
ITEM_INFO* item; ITEM_INFO* item;
int random; int random;
item = &Items[creature->itemNum]; item = &g_Level.Items[creature->itemNum];
if (item->aiBits & (GUARD | PATROL1)) if (item->aiBits & (GUARD | PATROL1))
return 0; return 0;
@ -175,7 +169,7 @@ void AlertNearbyGuards(ITEM_INFO* item)
if (creature->itemNum == NO_ITEM) if (creature->itemNum == NO_ITEM)
continue; continue;
target = &Items[creature->itemNum + i]; target = &g_Level.Items[creature->itemNum + i];
if (item->roomNumber == target->roomNumber) if (item->roomNumber == target->roomNumber)
{ {
creature->alerted = true; creature->alerted = true;
@ -204,8 +198,8 @@ void AlertAllGuards(short itemNumber)
if (creature->itemNum == NO_ITEM) if (creature->itemNum == NO_ITEM)
continue; continue;
target = &Items[creature->itemNum]; target = &g_Level.Items[creature->itemNum];
objNumber = Items[itemNumber].objectNumber; objNumber = g_Level.Items[itemNumber].objectNumber;
if (objNumber == target->objectNumber) if (objNumber == target->objectNumber)
{ {
if (target->status == ITEM_ACTIVE) if (target->status == ITEM_ACTIVE)
@ -217,11 +211,11 @@ void AlertAllGuards(short itemNumber)
void CreatureKill(ITEM_INFO* item, int killAnim, int killState, short laraKillState) void CreatureKill(ITEM_INFO* item, int killAnim, int killState, short laraKillState)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + killAnim; item->animNumber = Objects[item->objectNumber].animIndex + killAnim;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = killState; item->currentAnimState = killState;
LaraItem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex; LaraItem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex;
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
LaraItem->currentAnimState = 0; LaraItem->currentAnimState = 0;
LaraItem->goalAnimState = laraKillState; LaraItem->goalAnimState = laraKillState;
@ -330,7 +324,7 @@ void CreatureFloat(short itemNumber)
int y; int y;
short roomNumber; short roomNumber;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
item->hitPoints = NOT_TARGETABLE; item->hitPoints = NOT_TARGETABLE;
item->pos.xRot = 0; item->pos.xRot = 0;
@ -353,7 +347,7 @@ void CreatureFloat(short itemNumber)
if (item->pos.yPos <= waterLevel) if (item->pos.yPos <= waterLevel)
{ {
if (item->frameNumber == Anims[item->animNumber].frameBase) if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase)
{ {
item->pos.yPos = waterLevel; item->pos.yPos = waterLevel;
item->collidable = false; item->collidable = false;
@ -432,72 +426,6 @@ short CreatureTurn(ITEM_INFO* item, short maximumTurn)
item->pos.yRot += angle; item->pos.yRot += angle;
/*
ROOM_INFO* r;
CREATURE_INFO* creature;
int range, distance;
short angle;
short xAngle1, zAngle1;
short xAngle2, zAngle2;
short xAngle3, zAngle3;
int xDist, zDist;
unsigned short floorIndex1, floorIndex2, floorIndex3;
r = &Rooms[item->roomNumber];
creature = (CREATURE_INFO*)item->data;
// "<< 11" is really needed ? it can cause problem i think since it TR3 code the "<< 11" is not there !
xAngle1 = item->pos.xPos + phd_sin(item->pos.yRot + ANGLE(45)) << 11 >> W2V_SHIFT;
zAngle1 = item->pos.zPos + phd_cos(item->pos.yRot + ANGLE(45)) << 11 >> W2V_SHIFT;
floorIndex1 = XZ_GET_SECTOR(r, xAngle1 - r->x, zAngle1 - r->z).index;
xAngle2 = item->pos.xPos + phd_sin(item->pos.yRot - ANGLE(45)) << 11 >> W2V_SHIFT;
zAngle2 = item->pos.zPos + phd_cos(item->pos.yRot - ANGLE(45)) << 11 >> W2V_SHIFT;
floorIndex2 = XZ_GET_SECTOR(r, xAngle2 - r->x, zAngle2 - r->z).index;
xAngle3 = item->pos.xPos + phd_sin(item->pos.yRot) << 11 >> W2V_SHIFT;
zAngle3 = item->pos.zPos + phd_cos(item->pos.yRot) << 11 >> W2V_SHIFT;
floorIndex3 = XZ_GET_SECTOR(r, xAngle3 - r->x, zAngle3 - r->z).index;
if (floorIndex1 && !floorIndex2 && !floorIndex3)
{
creature = (CREATURE_INFO*)item->data;
creature->target.x = xAngle1;
creature->target.z = zAngle1;
}
else if (floorIndex2 && !floorIndex1 && !floorIndex3)
{
creature = (CREATURE_INFO*)item->data;
creature->target.x = xAngle2;
creature->target.z = zAngle2;
}
else if (floorIndex3 && !floorIndex1 && !floorIndex2)
{
creature = (CREATURE_INFO*)item->data;
creature->target.x = xAngle3;
creature->target.z = zAngle3;
}
xDist = creature->target.x - item->pos.xPos;
zDist = creature->target.z - item->pos.zPos;
angle = phd_atan(zDist, xDist) - item->pos.yRot;
if (angle > FRONT_ARC || angle < -FRONT_ARC)
{
range = (item->speed << W2V_SHIFT) / maximumTurn;
distance = SQUARE(zDist) + SQUARE(xDist);
if (distance < SQUARE(range))
maximumTurn >>= 1;
}
if (angle > maximumTurn)
angle = maximumTurn;
else if (angle < -maximumTurn)
angle = -maximumTurn;
item->pos.yRot += (angle + maximumTurn);
*/
return angle; return angle;
} }
@ -509,17 +437,19 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
FLOOR_INFO* floor; FLOOR_INFO* floor;
PHD_VECTOR old; PHD_VECTOR old;
int xPos, zPos, x, y, z, ceiling, shiftX, shiftZ, dy; int xPos, zPos, x, y, z, ceiling, shiftX, shiftZ, dy;
short* zone, *bounds; BOUNDING_BOX* bounds;
short roomNumber, boxHeight, height, nextHeight, nextBox, radius, biffAngle, top; int* zone;
short roomNumber, radius, biffAngle, top;
int boxHeight, height, nextHeight, nextBox;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (item->data == NULL) if (item->data == NULL)
return FALSE; return false;
creature = (CREATURE_INFO*)item->data; creature = (CREATURE_INFO*)item->data;
LOT = &creature->LOT; LOT = &creature->LOT;
zone = Zones[LOT->zone][FlipStatus]; zone = g_Level.Zones[LOT->zone][FlipStatus].data();
boxHeight = Boxes[item->boxNumber].height; boxHeight = g_Level.Boxes[item->boxNumber].height;
old.x = item->pos.xPos; old.x = item->pos.xPos;
old.y = item->pos.yPos; old.y = item->pos.yPos;
old.z = item->pos.zPos; old.z = item->pos.zPos;
@ -536,16 +466,16 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
if (item->status == ITEM_DEACTIVATED) if (item->status == ITEM_DEACTIVATED)
{ {
CreatureDie(itemNumber, FALSE); CreatureDie(itemNumber, FALSE);
return FALSE; return false;
} }
bounds = GetBoundsAccurate(item); bounds = GetBoundsAccurate(item);
y = item->pos.yPos + bounds[2]; y = item->pos.yPos + bounds->Y1;
roomNumber = item->roomNumber; roomNumber = item->roomNumber;
GetFloor(old.x, y, old.z, &roomNumber); GetFloor(old.x, y, old.z, &roomNumber);
floor = GetFloor(item->pos.xPos, y, item->pos.zPos, &roomNumber); floor = GetFloor(item->pos.xPos, y, item->pos.zPos, &roomNumber);
height = Boxes[floor->box].height; height = g_Level.Boxes[floor->box].height;
nextHeight = 0; nextHeight = 0;
if (!Objects[item->objectNumber].nonLot) if (!Objects[item->objectNumber].nonLot)
@ -555,14 +485,14 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
else else
{ {
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
height = Boxes[floor->box].height; height = g_Level.Boxes[floor->box].height;
nextBox = floor->box; nextBox = floor->box;
} }
if (nextBox == NO_BOX) if (nextBox == NO_BOX)
nextHeight = height; nextHeight = height;
else else
nextHeight = Boxes[nextBox].height; nextHeight = g_Level.Boxes[nextBox].height;
if (floor->box == NO_BOX || !LOT->isJumping && (LOT->fly == NO_FLYING && zone[item->boxNumber] != zone[floor->box] || boxHeight - height > LOT->step || boxHeight - height < LOT->drop)) if (floor->box == NO_BOX || !LOT->isJumping && (LOT->fly == NO_FLYING && zone[item->boxNumber] != zone[floor->box] || boxHeight - height > LOT->step || boxHeight - height < LOT->drop))
{ {
@ -582,7 +512,7 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
item->pos.zPos = old.z | (WALL_SIZE - 1); item->pos.zPos = old.z | (WALL_SIZE - 1);
floor = GetFloor(item->pos.xPos, y, item->pos.zPos, &roomNumber); floor = GetFloor(item->pos.xPos, y, item->pos.zPos, &roomNumber);
height = Boxes[floor->box].height; height = g_Level.Boxes[floor->box].height;
if (!Objects[item->objectNumber].nonLot) if (!Objects[item->objectNumber].nonLot)
{ {
nextHeight = LOT->node[floor->box].exitBox; nextHeight = LOT->node[floor->box].exitBox;
@ -590,14 +520,14 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
else else
{ {
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
height = Boxes[floor->box].height; height = g_Level.Boxes[floor->box].height;
nextBox = floor->box; nextBox = floor->box;
} }
if (nextBox == NO_BOX) if (nextBox == NO_BOX)
nextHeight = height; nextHeight = height;
else else
nextHeight = Boxes[nextBox].height; nextHeight = g_Level.Boxes[nextBox].height;
} }
x = item->pos.xPos; x = item->pos.xPos;
@ -714,7 +644,7 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
item->pos.yRot -= BIFF_AVOID_TURN; item->pos.yRot -= BIFF_AVOID_TURN;
else else
item->pos.yRot += BIFF_AVOID_TURN; item->pos.yRot += BIFF_AVOID_TURN;
return TRUE; return true;
} }
if (LOT->fly != NO_FLYING && item->hitPoints > 0) if (LOT->fly != NO_FLYING && item->hitPoints > 0)
@ -735,7 +665,7 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
if (item->objectNumber == ID_WHALE) if (item->objectNumber == ID_WHALE)
top = STEP_SIZE / 2; top = STEP_SIZE / 2;
else else
top = bounds[2]; top = bounds->Y1;
if (item->pos.yPos + top + dy < ceiling) if (item->pos.yPos + top + dy < ceiling)
{ {
@ -752,7 +682,7 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
else else
{ {
floor = GetFloor(item->pos.xPos, y + STEP_SIZE, item->pos.zPos, &roomNumber); floor = GetFloor(item->pos.xPos, y + STEP_SIZE, item->pos.zPos, &roomNumber);
if (Rooms[roomNumber].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP)) if (g_Level.Rooms[roomNumber].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
{ {
dy = -LOT->fly; dy = -LOT->fly;
} }
@ -796,7 +726,7 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
if (LOT->isMonkeying) if (LOT->isMonkeying)
{ {
ceiling = GetCeiling(floor, item->pos.xPos, y, item->pos.zPos); ceiling = GetCeiling(floor, item->pos.xPos, y, item->pos.zPos);
item->pos.yPos = ceiling - bounds[2]; item->pos.yPos = ceiling - bounds->Y1;
} }
else else
{ {
@ -823,7 +753,7 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
if (item->objectNumber == ID_TYRANNOSAUR || item->objectNumber == ID_SHIVA || item->objectNumber == ID_MUTANT2) if (item->objectNumber == ID_TYRANNOSAUR || item->objectNumber == ID_SHIVA || item->objectNumber == ID_MUTANT2)
top = STEP_SIZE*3; top = STEP_SIZE*3;
else else
top = bounds[2]; top = bounds->Y1; // TODO: check if Y1 or Y2
if (item->pos.yPos + top < ceiling) if (item->pos.yPos + top < ceiling)
{ {
@ -850,19 +780,19 @@ int CreatureAnimation(short itemNumber, short angle, short tilt)
{ {
GetFloor(item->pos.xPos, item->pos.yPos - STEP_SIZE*2, item->pos.zPos, &roomNumber); GetFloor(item->pos.xPos, item->pos.yPos - STEP_SIZE*2, item->pos.zPos, &roomNumber);
if (Rooms[roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_WATER)
item->hitPoints = 0; item->hitPoints = 0;
} }
if (item->roomNumber != roomNumber) if (item->roomNumber != roomNumber)
ItemNewRoom(itemNumber, roomNumber); ItemNewRoom(itemNumber, roomNumber);
return TRUE; return true;
} }
void CreatureDie(short itemNumber, int explode) void CreatureDie(short itemNumber, int explode)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->hitPoints = -16384; item->hitPoints = -16384;
item->collidable = false; item->collidable = false;
@ -897,10 +827,10 @@ int BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumbe
if (LOT->isJumping) if (LOT->isJumping)
return false; return false;
if (Boxes[floor->box].overlapIndex & LOT->blockMask) if (g_Level.Boxes[floor->box].flags & LOT->blockMask)
return true; return true;
height = Boxes[floor->box].height; height = g_Level.Boxes[floor->box].height;
if (boxHeight - height > LOT->step || boxHeight - height < LOT->drop) if (boxHeight - height > LOT->step || boxHeight - height < LOT->drop)
return true; return true;
@ -916,22 +846,22 @@ int BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumbe
int CreatureCreature(short itemNumber) int CreatureCreature(short itemNumber)
{ {
ITEM_INFO* item, *linked; ITEM_INFO* item, *linked;
ObjectInfo* obj; OBJECT_INFO* obj;
ROOM_INFO* r; ROOM_INFO* r;
int x, z, xDistance, zDistance, distance = 0; int x, z, xDistance, zDistance, distance = 0;
short link, radius; short link, radius;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
obj = &Objects[item->objectNumber]; obj = &Objects[item->objectNumber];
x = item->pos.xPos; x = item->pos.xPos;
z = item->pos.zPos; z = item->pos.zPos;
radius = obj->radius; radius = obj->radius;
r = &Rooms[item->roomNumber]; r = &g_Level.Rooms[item->roomNumber];
link = r->itemNumber; link = r->itemNumber;
do do
{ {
linked = &Items[link]; linked = &g_Level.Items[link];
if (link != itemNumber && linked != LaraItem && linked->status == ITEM_ACTIVE && linked->hitPoints > 0) if (link != itemNumber && linked != LaraItem && linked->status == ITEM_ACTIVE && linked->hitPoints > 0)
{ {
@ -957,15 +887,15 @@ int ValidBox(ITEM_INFO* item, short zoneNumber, short boxNumber)
{ {
CREATURE_INFO* creature; CREATURE_INFO* creature;
BOX_INFO* box; BOX_INFO* box;
short* zone; int* zone;
creature = (CREATURE_INFO*)item->data; creature = (CREATURE_INFO*)item->data;
zone = Zones[creature->LOT.zone][FlipStatus]; zone = g_Level.Zones[creature->LOT.zone][FlipStatus].data();
if (creature->LOT.fly == NO_FLYING && zone[boxNumber] != zoneNumber) if (creature->LOT.fly == NO_FLYING && zone[boxNumber] != zoneNumber)
return false; return false;
box = &Boxes[boxNumber]; box = &g_Level.Boxes[boxNumber];
if (box->overlapIndex & creature->LOT.blockMask) if (box->flags & creature->LOT.blockMask)
return false; return false;
if ((item->pos.zPos > (box->left << WALL_SHIFT)) && item->pos.zPos < ((box->right << WALL_SHIFT)) && if ((item->pos.zPos > (box->left << WALL_SHIFT)) && item->pos.zPos < ((box->right << WALL_SHIFT)) &&
@ -975,9 +905,9 @@ int ValidBox(ITEM_INFO* item, short zoneNumber, short boxNumber)
return true; return true;
} }
int EscapeBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber) int EscapeBox(ITEM_INFO* item, ITEM_INFO* enemy, int boxNumber)
{ {
BOX_INFO* box = &Boxes[boxNumber]; BOX_INFO* box = &g_Level.Boxes[boxNumber];
int x, z; int x, z;
x = (int(box->top + box->bottom) << (WALL_SHIFT - 1)) - enemy->pos.xPos; x = (int(box->top + box->bottom) << (WALL_SHIFT - 1)) - enemy->pos.xPos;
@ -992,15 +922,13 @@ int EscapeBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber)
return true; return true;
} }
void TargetBox(LOT_INFO* LOT, short boxNumber) void TargetBox(LOT_INFO* LOT, int boxNumber)
{ {
BOX_INFO* box; BOX_INFO* box;
boxNumber &= NO_BOX; boxNumber &= NO_BOX;
box = &Boxes[boxNumber]; box = &g_Level.Boxes[boxNumber];
//LOT->target.x = (((((box->bottom - box->top) - 1) * GetRandomControl()) / 32) + (box->top * 1024)) + 512;
//LOT->target.z = (((((box->right - box->left) - 1) * GetRandomControl()) / 32) + (box->left * 1024)) + 512;
LOT->target.x = ((box->top << WALL_SHIFT) + GetRandomControl() * ((box->bottom - box->top) - 1) >> 5) + WALL_SIZE / 2; LOT->target.x = ((box->top << WALL_SHIFT) + GetRandomControl() * ((box->bottom - box->top) - 1) >> 5) + WALL_SIZE / 2;
LOT->target.z = ((box->left << WALL_SHIFT) + GetRandomControl() * ((box->right - box->left) - 1) >> 5) + WALL_SIZE / 2; LOT->target.z = ((box->left << WALL_SHIFT) + GetRandomControl() * ((box->right - box->left) - 1) >> 5) + WALL_SIZE / 2;
LOT->requiredBox = boxNumber; LOT->requiredBox = boxNumber;
@ -1015,6 +943,8 @@ int UpdateLOT(LOT_INFO* LOT, int depth)
{ {
BOX_NODE* node; BOX_NODE* node;
//printf("LOT->head: %d, LOT->tail: %d\n", LOT->head, LOT->tail);
if (LOT->requiredBox != NO_BOX && LOT->requiredBox != LOT->targetBox) if (LOT->requiredBox != NO_BOX && LOT->requiredBox != LOT->targetBox)
{ {
LOT->targetBox = LOT->requiredBox; LOT->targetBox = LOT->requiredBox;
@ -1041,41 +971,44 @@ int SearchLOT(LOT_INFO* LOT, int depth)
{ {
BOX_NODE* node, *expand; BOX_NODE* node, *expand;
BOX_INFO* box; BOX_INFO* box;
short* zone, index, searchZone, boxNumber, delta; int* zone, index, searchZone, boxNumber, delta, flags;
bool done; bool done;
zone = Zones[LOT->zone][FlipStatus]; zone = g_Level.Zones[LOT->zone][FlipStatus].data();
searchZone = zone[LOT->head]; searchZone = zone[LOT->head];
if (depth <= 0) if (depth <= 0)
return 1; return true;
for (int i = 0; i < depth; i++) for (int i = 0; i < depth; i++)
{ {
if (LOT->head == NO_BOX) if (LOT->head == NO_BOX)
{ {
LOT->tail = NO_BOX; LOT->tail = NO_BOX;
return FALSE; return false;
} }
node = &LOT->node[LOT->head]; node = &LOT->node[LOT->head];
box = &Boxes[LOT->head]; box = &g_Level.Boxes[LOT->head];
index = box->overlapIndex & OVERLAP_INDEX; index = box->overlapIndex;
done = false; done = false;
if (index >= 0)
{
do do
{ {
boxNumber = Overlaps[index++]; boxNumber = g_Level.Overlaps[index].box;
if (boxNumber & BOX_END_BIT) flags = g_Level.Overlaps[index++].flags;
if (flags & BOX_END_BIT)
{ {
done = TRUE; done = true;
boxNumber &= BOX_NUMBER;
} }
if (LOT->fly == NO_FLYING && searchZone != zone[boxNumber]) if (LOT->fly == NO_FLYING && searchZone != zone[boxNumber])
continue; continue;
delta = Boxes[boxNumber].height - box->height; delta = g_Level.Boxes[boxNumber].height - box->height;
if (delta > LOT->step || delta < LOT->drop) if (delta > LOT->step || delta < LOT->drop)
continue; continue;
@ -1095,7 +1028,7 @@ int SearchLOT(LOT_INFO* LOT, int depth)
if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & BLOCKED_SEARCH)) if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & BLOCKED_SEARCH))
continue; continue;
if (Boxes[boxNumber].overlapIndex & LOT->blockMask) if (g_Level.Boxes[boxNumber].flags & LOT->blockMask)
{ {
expand->searchNumber = node->searchNumber | BLOCKED_SEARCH; expand->searchNumber = node->searchNumber | BLOCKED_SEARCH;
} }
@ -1112,26 +1045,28 @@ int SearchLOT(LOT_INFO* LOT, int depth)
LOT->tail = boxNumber; LOT->tail = boxNumber;
} }
} while (!done); } while (!done);
}
LOT->head = node->nextExpansion; LOT->head = node->nextExpansion;
node->nextExpansion = NO_BOX; node->nextExpansion = NO_BOX;
} }
return TRUE; return true;
} }
int CreatureActive(short itemNumber) int CreatureActive(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (!(item->flags & IFLAG_KILLED) && item->status & ITEM_INVISIBLE) if (!(item->flags & IFLAG_KILLED)
&& item->status & ITEM_INVISIBLE)
{ {
if (!EnableBaddieAI(itemNumber, FALSE)) if (!EnableBaddieAI(itemNumber, false))
return FALSE; return false;
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
} }
return TRUE; return true;
} }
void InitialiseCreature(short itemNumber) void InitialiseCreature(short itemNumber)
@ -1139,16 +1074,16 @@ void InitialiseCreature(short itemNumber)
ClearItem(itemNumber); ClearItem(itemNumber);
} }
int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber) int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, int boxNumber)
{ {
if (enemy == NULL) if (enemy == NULL)
return FALSE; return false;
BOX_INFO* box; BOX_INFO* box;
int x, z, xrange, zrange; int x, z, xrange, zrange;
int enemyQuad, boxQuad, baddieQuad; int enemyQuad, boxQuad, baddieQuad;
box = &Boxes[boxNumber]; box = &g_Level.Boxes[boxNumber];
xrange = STALK_DIST + ((box->bottom - box->top + 3) << WALL_SHIFT); xrange = STALK_DIST + ((box->bottom - box->top + 3) << WALL_SHIFT);
zrange = STALK_DIST + ((box->right - box->left + 3) << WALL_SHIFT); zrange = STALK_DIST + ((box->right - box->left + 3) << WALL_SHIFT);
@ -1156,7 +1091,7 @@ int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber)
z = ((box->left + box->right) << (WALL_SHIFT - 1)) - enemy->pos.zPos; z = ((box->left + box->right) << (WALL_SHIFT - 1)) - enemy->pos.zPos;
if (x > xrange || x < -xrange || z > zrange || z < -zrange) if (x > xrange || x < -xrange || z > zrange || z < -zrange)
return FALSE; return false;
enemyQuad = (enemy->pos.yRot >> W2V_SHIFT) + 2; enemyQuad = (enemy->pos.yRot >> W2V_SHIFT) + 2;
@ -1167,7 +1102,7 @@ int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber)
boxQuad = (x > 0) ? 3 : 0; boxQuad = (x > 0) ? 3 : 0;
if (enemyQuad == boxQuad) if (enemyQuad == boxQuad)
return FALSE; return false;
baddieQuad = 0; baddieQuad = 0;
if (item->pos.zPos > enemy->pos.zPos) if (item->pos.zPos > enemy->pos.zPos)
@ -1176,14 +1111,14 @@ int StalkBox(ITEM_INFO* item, ITEM_INFO* enemy, short boxNumber)
baddieQuad = (item->pos.xPos > enemy->pos.xPos) ? 3 : 0; baddieQuad = (item->pos.xPos > enemy->pos.xPos) ? 3 : 0;
if (enemyQuad == baddieQuad && abs(enemyQuad - boxQuad) == 2) if (enemyQuad == baddieQuad && abs(enemyQuad - boxQuad) == 2)
return FALSE; return false;
return TRUE; return true;
} }
int CreatureVault(short itemNum, short angle, int vault, int shift) int CreatureVault(short itemNum, short angle, int vault, int shift)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
int xBlock, zBlock, y, newXblock, newZblock; int xBlock, zBlock, y, newXblock, newZblock;
short roomNumber; short roomNumber;
@ -1269,7 +1204,7 @@ void GetAITarget(CREATURE_INFO* creature)
else else
enemyObjectNumber = NO_ITEM; enemyObjectNumber = NO_ITEM;
item = &Items[creature->itemNum]; item = &g_Level.Items[creature->itemNum];
if (item->aiBits & GUARD) if (item->aiBits & GUARD)
{ {
@ -1381,11 +1316,11 @@ void GetAITarget(CREATURE_INFO* creature)
// tr3 old way.. // tr3 old way..
void FindAITarget(CREATURE_INFO* creature, short objectNumber) void FindAITarget(CREATURE_INFO* creature, short objectNumber)
{ {
ITEM_INFO* item = &Items[creature->itemNum]; ITEM_INFO* item = &g_Level.Items[creature->itemNum];
ITEM_INFO* targetItem; ITEM_INFO* targetItem;
int i; int i;
for (i = 0, targetItem = &Items[0]; i < LevelItems; i++, targetItem++) for (i = 0, targetItem = &g_Level.Items[0]; i < g_Level.NumItems; i++, targetItem++)
{ {
if (targetItem->objectNumber == objectNumber && targetItem->roomNumber != NO_ROOM) if (targetItem->objectNumber == objectNumber && targetItem->roomNumber != NO_ROOM)
{ {
@ -1400,25 +1335,25 @@ void FindAITarget(CREATURE_INFO* creature, short objectNumber)
void FindAITargetObject(CREATURE_INFO* creature, short objectNumber) void FindAITargetObject(CREATURE_INFO* creature, short objectNumber)
{ {
ITEM_INFO* item = &Items[creature->itemNum]; ITEM_INFO* item = &g_Level.Items[creature->itemNum];
if (nAIObjects > 0) if (g_Level.AIObjects.size() > 0)
{ {
AIOBJECT* foundObject = NULL; AIOBJECT* foundObject = NULL;
for (int i = 0; i < nAIObjects; i++) for (int i = 0; i < g_Level.AIObjects.size(); i++)
{ {
AIOBJECT* aiObject = &AIObjects[i]; AIOBJECT* aiObject = &g_Level.AIObjects[i];
if (aiObject->objectNumber == objectNumber && aiObject->triggerFlags == item->itemFlags[3] && aiObject->roomNumber != 255) if (aiObject->objectNumber == objectNumber && aiObject->triggerFlags == item->itemFlags[3] && aiObject->roomNumber != NO_ROOM)
{ {
short* zone = Zones[creature->LOT.zone][FlipStatus]; int* zone = g_Level.Zones[creature->LOT.zone][FlipStatus].data();
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box & 0x7FF; item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box;
r = &Rooms[aiObject->roomNumber]; r = &g_Level.Rooms[aiObject->roomNumber];
aiObject->boxNumber = XZ_GET_SECTOR(r, aiObject->x - r->x, aiObject->z - r->z).box & 0x7FF; aiObject->boxNumber = XZ_GET_SECTOR(r, aiObject->x - r->x, aiObject->z - r->z).box;
if (zone[item->boxNumber] == zone[aiObject->boxNumber]) if (zone[item->boxNumber] == zone[aiObject->boxNumber])
{ {
@ -1458,11 +1393,12 @@ void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info)
if (item->data == NULL) if (item->data == NULL)
return; return;
CREATURE_INFO* creature; CREATURE_INFO * creature;
ITEM_INFO* enemy; ITEM_INFO * enemy;
ObjectInfo* obj; OBJECT_INFO * obj;
ROOM_INFO* r; ROOM_INFO * r;
short* zone, angle; short angle;
int* zone;
int x, y, z; int x, y, z;
creature = (CREATURE_INFO*)item->data; creature = (CREATURE_INFO*)item->data;
@ -1475,19 +1411,19 @@ void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info)
creature->enemy = LaraItem; creature->enemy = LaraItem;
} }
zone = Zones[creature->LOT.zone][FlipStatus]; zone = g_Level.Zones[creature->LOT.zone][FlipStatus].data();
r = &Rooms[item->roomNumber]; r = &g_Level.Rooms[item->roomNumber];
item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box & BOX_NUMBER; item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box;
info->zoneNumber = zone[item->boxNumber]; info->zoneNumber = zone[item->boxNumber];
r = &Rooms[enemy->roomNumber]; r = &g_Level.Rooms[enemy->roomNumber];
enemy->boxNumber = XZ_GET_SECTOR(r, enemy->pos.xPos - r->x, enemy->pos.zPos - r->z).box & BOX_NUMBER; enemy->boxNumber = XZ_GET_SECTOR(r, enemy->pos.xPos - r->x, enemy->pos.zPos - r->z).box;
info->enemyZone = zone[enemy->boxNumber]; info->enemyZone = zone[enemy->boxNumber];
if (!obj->nonLot) if (!obj->nonLot)
{ {
if (Boxes[enemy->boxNumber].overlapIndex & creature->LOT.blockMask) if (g_Level.Boxes[enemy->boxNumber].flags & creature->LOT.blockMask)
info->enemyZone |= BLOCKED; info->enemyZone |= BLOCKED;
else if (creature->LOT.node[item->boxNumber].searchNumber == (creature->LOT.searchNumber | BLOCKED_SEARCH)) else if (creature->LOT.node[item->boxNumber].searchNumber == (creature->LOT.searchNumber | BLOCKED_SEARCH))
info->enemyZone |= BLOCKED; info->enemyZone |= BLOCKED;
@ -1520,7 +1456,7 @@ void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info)
} }
info->angle = angle - item->pos.yRot; info->angle = angle - item->pos.yRot;
info->enemyFacing = ANGLE(180) + angle - enemy->pos.yRot; info->enemyFacing = -ANGLE(180) + angle - enemy->pos.yRot;
x = abs(x); x = abs(x);
z = abs(z); z = abs(z);
@ -1528,12 +1464,12 @@ void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info)
if (enemy == LaraItem) if (enemy == LaraItem)
{ {
short laraState = LaraItem->currentAnimState; short laraState = LaraItem->currentAnimState;
if (laraState == STATE_LARA_CROUCH_IDLE || if (laraState == LS_CROUCH_IDLE ||
laraState == STATE_LARA_CROUCH_TURN_LEFT || laraState == LS_CROUCH_TURN_LEFT ||
laraState == STATE_LARA_CROUCH_TURN_RIGHT || laraState == LS_CROUCH_TURN_RIGHT ||
laraState == STATE_LARA_CROUCH_ROLL || laraState == LS_CROUCH_ROLL ||
laraState <= STATE_LARA_MONKEYSWING_TURNAROUND || laraState <= LS_MONKEYSWING_TURN_180 ||
laraState >= STATE_LARA_CLIMB_TO_CRAWL) laraState >= LS_HANG_TO_CRAWL)
{ {
y -= STEPUP_HEIGHT; y -= STEPUP_HEIGHT;
} }
@ -1545,7 +1481,7 @@ void CreatureAIInfo(ITEM_INFO* item, AI_INFO* info)
info->xAngle = phd_atan(z + (x >> 1), y); info->xAngle = phd_atan(z + (x >> 1), y);
info->ahead = (info->angle > -FRONT_ARC && info->angle < FRONT_ARC); info->ahead = (info->angle > -FRONT_ARC && info->angle < FRONT_ARC);
info->bite = (info->ahead && enemy->hitPoints > 0 && abs(enemy->pos.yPos - item->pos.yPos) <= (STEP_SIZE*2)); info->bite = (info->ahead && enemy->hitPoints > 0 && abs(enemy->pos.yPos - item->pos.yPos) <= (STEP_SIZE * 2));
} }
void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent) void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent)
@ -1556,8 +1492,8 @@ void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent)
CREATURE_INFO* creature; CREATURE_INFO* creature;
ITEM_INFO* enemy; ITEM_INFO* enemy;
LOT_INFO* LOT; LOT_INFO* LOT;
short boxNumber, startBox, overlapIndex, nextBox; int boxNumber, startBox, overlapIndex, nextBox, flags;
short* bounds; BOUNDING_BOX* bounds;
creature = (CREATURE_INFO*)item->data; creature = (CREATURE_INFO*)item->data;
enemy = creature->enemy; enemy = creature->enemy;
@ -1567,7 +1503,8 @@ void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent)
{ {
case BORED_MOOD: case BORED_MOOD:
boxNumber = LOT->node[GetRandomControl() * LOT->zoneCount >> NODE_SHIFT].boxNumber; boxNumber = LOT->node[GetRandomControl() * LOT->zoneCount >> NODE_SHIFT].boxNumber;
if (ValidBox(item, info->zoneNumber, boxNumber)) if (ValidBox(item, info->zoneNumber, boxNumber)
&& !(GetRandomControl() & 0x0F))
{ {
if (StalkBox(item, enemy, boxNumber) && enemy->hitPoints > 0 && creature->enemy) if (StalkBox(item, enemy, boxNumber) && enemy->hitPoints > 0 && creature->enemy)
{ {
@ -1589,14 +1526,14 @@ void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent)
if (LOT->fly != NO_FLYING && Lara.waterStatus == LW_ABOVE_WATER) if (LOT->fly != NO_FLYING && Lara.waterStatus == LW_ABOVE_WATER)
{ {
bounds = GetBestFrame(enemy); bounds = (BOUNDING_BOX*)GetBestFrame(enemy);
LOT->target.y += bounds[2]; LOT->target.y += bounds->Y1;
} }
break; break;
case ESCAPE_MOOD: case ESCAPE_MOOD:
boxNumber = LOT->node[GetRandomControl() * LOT->zoneCount >> NODE_SHIFT].boxNumber; boxNumber = LOT->node[GetRandomControl() * LOT->zoneCount >> NODE_SHIFT].boxNumber;
if (ValidBox(item, info->zoneNumber, boxNumber)) if (ValidBox(item, info->zoneNumber, boxNumber) && LOT->requiredBox == NO_BOX)
{ {
if (EscapeBox(item, enemy, boxNumber)) if (EscapeBox(item, enemy, boxNumber))
{ {
@ -1634,30 +1571,35 @@ void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent)
if (LOT->targetBox == NO_BOX) if (LOT->targetBox == NO_BOX)
TargetBox(LOT, item->boxNumber); TargetBox(LOT, item->boxNumber);
CalculateTarget(&creature->target, item, &creature->LOT);
creature->jumpAhead = false; creature->jumpAhead = false;
creature->monkeyAhead = false; creature->monkeyAhead = false;
startBox = LOT->node[item->boxNumber].exitBox; startBox = LOT->node[item->boxNumber].exitBox;
if (startBox != NO_BOX) if (startBox != NO_BOX)
{ {
overlapIndex = Boxes[startBox].overlapIndex & OVERLAP_INDEX; overlapIndex = g_Level.Boxes[startBox].overlapIndex;
nextBox = 0; nextBox = 0;
flags = 0;
if (overlapIndex >= 0)
{
do do
{ {
overlapIndex++; overlapIndex++;
nextBox = Overlaps[overlapIndex]; nextBox = g_Level.Overlaps[overlapIndex].box;
} while (nextBox != NO_BOX && ((nextBox & BOX_END_BIT) == FALSE) && ((nextBox & BOX_NUMBER) != startBox)); flags = g_Level.Overlaps[overlapIndex].flags;
} while (nextBox != NO_BOX && ((flags & BOX_END_BIT) == FALSE) && (nextBox != startBox));
}
if ((nextBox & BOX_NUMBER) == startBox) if (nextBox == startBox)
{ {
if (nextBox & BOX_JUMP) if (flags & BOX_JUMP)
creature->jumpAhead = true; creature->jumpAhead = true;
if (nextBox & BOX_MONKEY) if (flags & BOX_MONKEY)
creature->monkeyAhead = true; creature->monkeyAhead = true;
} }
} }
/*Unk_00EEFB6C =*/ CalculateTarget(&creature->target, item, &creature->LOT);
} }
void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int isViolent) void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int isViolent)
@ -1677,7 +1619,8 @@ void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int isViolent)
if (creature->LOT.node[item->boxNumber].searchNumber == (creature->LOT.searchNumber | BLOCKED_SEARCH)) if (creature->LOT.node[item->boxNumber].searchNumber == (creature->LOT.searchNumber | BLOCKED_SEARCH))
creature->LOT.requiredBox = NO_BOX; creature->LOT.requiredBox = NO_BOX;
if (creature->mood != ATTACK_MOOD && creature->LOT.requiredBox != NO_BOX) if (creature->mood != ATTACK_MOOD
&& creature->LOT.requiredBox != NO_BOX)
{ {
if (!ValidBox(item, info->zoneNumber, creature->LOT.targetBox)) if (!ValidBox(item, info->zoneNumber, creature->LOT.targetBox))
{ {
@ -1720,13 +1663,14 @@ void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int isViolent)
break; break;
} }
} }
else if (!isViolent) else
{ {
switch (creature->mood) switch (creature->mood)
{ {
case BORED_MOOD: case BORED_MOOD:
case STALK_MOOD: case STALK_MOOD:
if (creature->alerted && info->zoneNumber != info->enemyZone) if (creature->alerted
&& info->zoneNumber != info->enemyZone)
{ {
if (info->distance > 3072) if (info->distance > 3072)
creature->mood = STALK_MOOD; creature->mood = STALK_MOOD;
@ -1735,7 +1679,9 @@ void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int isViolent)
} }
else if (info->zoneNumber == info->enemyZone) else if (info->zoneNumber == info->enemyZone)
{ {
if (info->distance < ATTACK_RANGE || (creature->mood == STALK_MOOD && LOT->requiredBox == NO_BOX)) if (info->distance < ATTACK_RANGE
|| (creature->mood == STALK_MOOD
&& LOT->requiredBox == NO_BOX))
creature->mood = ATTACK_MOOD; creature->mood = ATTACK_MOOD;
else else
creature->mood = STALK_MOOD; creature->mood = STALK_MOOD;
@ -1743,14 +1689,17 @@ void GetCreatureMood(ITEM_INFO* item, AI_INFO* info, int isViolent)
break; break;
case ATTACK_MOOD: case ATTACK_MOOD:
if (item->hitStatus && (GetRandomControl() < ESCAPE_CHANCE || info->zoneNumber != info->enemyZone)) if (item->hitStatus
&& (GetRandomControl() < ESCAPE_CHANCE
|| info->zoneNumber != info->enemyZone))
creature->mood = STALK_MOOD; creature->mood = STALK_MOOD;
else if (info->zoneNumber != info->enemyZone && info->distance > (WALL_SIZE*6)) else if (info->zoneNumber != info->enemyZone && info->distance > (WALL_SIZE*6))
creature->mood = BORED_MOOD; creature->mood = BORED_MOOD;
break; break;
case ESCAPE_MOOD: case ESCAPE_MOOD:
if (info->zoneNumber == info->enemyZone && GetRandomControl() < RECOVER_CHANCE) if (info->zoneNumber == info->enemyZone
&& GetRandomControl() < RECOVER_CHANCE)
creature->mood = STALK_MOOD; creature->mood = STALK_MOOD;
break; break;
} }
@ -1770,7 +1719,7 @@ TARGET_TYPE CalculateTarget(PHD_VECTOR* target, ITEM_INFO* item, LOT_INFO* LOT)
int boxLeft, boxRight, boxTop, boxBottom; int boxLeft, boxRight, boxTop, boxBottom;
int left, top, right, bottom; int left, top, right, bottom;
int direction; int direction;
short boxNumber; int boxNumber;
UpdateLOT(LOT, 5); UpdateLOT(LOT, 5);
@ -1782,7 +1731,7 @@ TARGET_TYPE CalculateTarget(PHD_VECTOR* target, ITEM_INFO* item, LOT_INFO* LOT)
if (boxNumber == NO_BOX) if (boxNumber == NO_BOX)
return TARGET_TYPE::NO_TARGET; return TARGET_TYPE::NO_TARGET;
box = &Boxes[boxNumber]; box = &g_Level.Boxes[boxNumber];
boxLeft = ((int)box->left << WALL_SHIFT); boxLeft = ((int)box->left << WALL_SHIFT);
boxRight = ((int)box->right << WALL_SHIFT) - 1; boxRight = ((int)box->right << WALL_SHIFT) - 1;
boxTop = ((int)box->top << WALL_SHIFT); boxTop = ((int)box->top << WALL_SHIFT);
@ -1795,7 +1744,7 @@ TARGET_TYPE CalculateTarget(PHD_VECTOR* target, ITEM_INFO* item, LOT_INFO* LOT)
do do
{ {
box = &Boxes[boxNumber]; box = &g_Level.Boxes[boxNumber];
if (LOT->fly == NO_FLYING) if (LOT->fly == NO_FLYING)
{ {
@ -1958,7 +1907,7 @@ TARGET_TYPE CalculateTarget(PHD_VECTOR* target, ITEM_INFO* item, LOT_INFO* LOT)
} }
boxNumber = LOT->node[boxNumber].exitBox; boxNumber = LOT->node[boxNumber].exitBox;
if (boxNumber != NO_BOX && (Boxes[boxNumber].overlapIndex & LOT->blockMask)) if (boxNumber != NO_BOX && (g_Level.Boxes[boxNumber].flags & LOT->blockMask))
break; break;
} while (boxNumber != NO_BOX); } while (boxNumber != NO_BOX);
@ -1999,7 +1948,7 @@ void AdjustStopperFlag(ITEM_INFO* item, int dir, int set)
int x = item->pos.xPos; int x = item->pos.xPos;
int z = item->pos.zPos; int z = item->pos.zPos;
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
FLOOR_INFO* floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); FLOOR_INFO* floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
floor->stopper = set; floor->stopper = set;
@ -2009,7 +1958,7 @@ void AdjustStopperFlag(ITEM_INFO* item, int dir, int set)
short roomNumber = item->roomNumber; short roomNumber = item->roomNumber;
GetFloor(x, item->pos.yPos, z, &roomNumber); GetFloor(x, item->pos.yPos, z, &roomNumber);
r = &Rooms[roomNumber]; r = &g_Level.Rooms[roomNumber];
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
floor->stopper = set; floor->stopper = set;

View file

@ -21,7 +21,7 @@ void UpdateBubbles()
bubble->size = lerp(0, bubble->destinationSize, alpha); bubble->size = lerp(0, bubble->destinationSize, alpha);
bubble->color = Vector4::Lerp(bubble->sourceColor, bubble->destinationColor, alpha); bubble->color = Vector4::Lerp(bubble->sourceColor, bubble->destinationColor, alpha);
int ceilingHeight = Rooms[bubble->roomNumber].maxceiling; int ceilingHeight = g_Level.Rooms[bubble->roomNumber].maxceiling;
short roomNumber = bubble->roomNumber; short roomNumber = bubble->roomNumber;
@ -34,9 +34,9 @@ void UpdateBubbles()
continue; continue;
} }
if (!(Rooms[roomNumber].flags & ENV_FLAG_WATER)) if (!(g_Level.Rooms[roomNumber].flags & ENV_FLAG_WATER))
{ {
SetupRipple(bubble->worldPosition.x, Rooms[bubble->roomNumber].maxceiling, bubble->worldPosition.z, (GetRandomControl() & 0xF) + 48, RIPPLE_FLAG_SHORT_LIFE + RIPPLE_FLAG_RAND_ROT); SetupRipple(bubble->worldPosition.x, g_Level.Rooms[bubble->roomNumber].maxceiling, bubble->worldPosition.z, (GetRandomControl() & 0xF) + 48, RIPPLE_FLAG_SHORT_LIFE + RIPPLE_FLAG_RAND_ROT);
bubble->active = false; bubble->active = false;
continue; continue;
} }
@ -77,7 +77,7 @@ int GetFreeBubble() //8BEAC(<), 8DEF0(<) (F)
void CreateBubble(PHD_VECTOR* pos, short roomNum, int unk1, int unk2, int flags, int xv, int yv, int zv) //8BF14(<), 8DF58(<) (F) void CreateBubble(PHD_VECTOR* pos, short roomNum, int unk1, int unk2, int flags, int xv, int yv, int zv) //8BF14(<), 8DF58(<) (F)
{ {
if (Rooms[roomNum].flags & ENV_FLAG_WATER) if (g_Level.Rooms[roomNum].flags & ENV_FLAG_WATER)
{ {
BUBBLE_STRUCT* bubble = &Bubbles[GetFreeBubble()]; BUBBLE_STRUCT* bubble = &Bubbles[GetFreeBubble()];
bubble->active = true; bubble->active = true;

View file

@ -14,7 +14,7 @@
#include "sound.h" #include "sound.h"
#include "savegame.h" #include "savegame.h"
#include "input.h" #include "input.h"
using T5M::Renderer::g_Renderer;
struct OLD_CAMERA struct OLD_CAMERA
{ {
short currentAnimState; short currentAnimState;
@ -63,26 +63,23 @@ int PhdPerspective;
short CurrentFOV; short CurrentFOV;
int GetLaraOnLOS; int GetLaraOnLOS;
int SniperOverlay; int SniperOverlay;
std::vector<OBJECT_VECTOR> FixedCameras;
void LookAt(int posX, int posY, int posZ, int targetX, int targetY, int targetZ, short roll) void LookAt(CAMERA_INFO* cam, short roll)
{ {
Vector3 position = Vector3(posX, posY, posZ); Vector3 position = Vector3(cam->pos.x, cam->pos.y, cam->pos.z);
Vector3 target = Vector3(targetX, targetY, targetZ); Vector3 target = Vector3(cam->target.x, cam->target.y, cam->target.z);
Vector3 up = Vector3(0.0f, -1.0f, 0.0f); Vector3 up = Vector3(0.0f, -1.0f, 0.0f);
float fov = TO_RAD(CurrentFOV / 1.333333f); float fov = TO_RAD(CurrentFOV / 1.333333f);
float r = TO_RAD(roll); float r = 0; TO_RAD(roll);
// This should not be needed but it seems to solve our issues g_Renderer.UpdateCameraMatrices(cam, r, fov);
if (posX == targetX && posY == targetY && posZ == targetZ)
return;
g_Renderer->UpdateCameraMatrices(posX, posY, posZ, targetX, targetY, targetZ, r, fov);
} }
void AlterFOV(int value) void AlterFOV(int value)
{ {
CurrentFOV = value; CurrentFOV = value;
PhdPerspective = g_Renderer->ScreenWidth / 2 * phd_cos(CurrentFOV / 2) / phd_sin(CurrentFOV / 2); PhdPerspective = g_Renderer.ScreenWidth / 2 * phd_cos(CurrentFOV / 2) / phd_sin(CurrentFOV / 2);
} }
int mgLOS(GAME_VECTOR* start, GAME_VECTOR* target, int push) int mgLOS(GAME_VECTOR* start, GAME_VECTOR* target, int push)
@ -331,7 +328,7 @@ void MoveCamera(GAME_VECTOR* ideal, int speed)
} }
GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber); GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber);
LookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.target.x, Camera.target.y, Camera.target.z, 0); LookAt(&Camera, 0);
if (Camera.mikeAtLara) if (Camera.mikeAtLara)
{ {
@ -369,8 +366,8 @@ void ChaseCamera(ITEM_INFO* item)
int distance = Camera.targetDistance * phd_cos(Camera.actualElevation) >> W2V_SHIFT; int distance = Camera.targetDistance * phd_cos(Camera.actualElevation) >> W2V_SHIFT;
GetFloor(Camera.target.x, Camera.target.y, Camera.target.z, &Camera.target.roomNumber); GetFloor(Camera.target.x, Camera.target.y, Camera.target.z, &Camera.target.roomNumber);
if (Rooms[Camera.target.roomNumber].flags & ENV_FLAG_SWAMP) if (g_Level.Rooms[Camera.target.roomNumber].flags & ENV_FLAG_SWAMP)
Camera.target.y = Rooms[Camera.target.roomNumber].y - 256; Camera.target.y = g_Level.Rooms[Camera.target.roomNumber].y - 256;
int x = Camera.target.x; int x = Camera.target.x;
int y = Camera.target.y; int y = Camera.target.y;
@ -779,7 +776,7 @@ void FixedCamera(ITEM_INFO* item)
} }
else else
{ {
OBJECT_VECTOR* camera = &Camera.fixed[Camera.number]; OBJECT_VECTOR* camera = &FixedCameras[Camera.number];
from.x = camera->x; from.x = camera->x;
from.y = camera->y; from.y = camera->y;
@ -814,7 +811,7 @@ void FixedCamera(ITEM_INFO* item)
PHD_VECTOR pos; PHD_VECTOR pos;
int objLos = ObjectOnLOS2(&from, &to, &pos, &CollidedMeshes[0]); int objLos = ObjectOnLOS2(&from, &to, &pos, &CollidedMeshes[0]);
objLos = (objLos != 999 && objLos >= 0 && Items[objLos].objectNumber != ID_LARA); objLos = (objLos != 999 && objLos >= 0 && g_Level.Items[objLos].objectNumber != ID_LARA);
if (!(GetRandomControl() & 0x3F) if (!(GetRandomControl() & 0x3F)
|| !(GlobalCounter & 0x3F) || !(GlobalCounter & 0x3F)
@ -920,9 +917,9 @@ void LookCamera(ITEM_INFO* item)
roomNumber = LaraItem->roomNumber; roomNumber = LaraItem->roomNumber;
floor = GetFloor(pos.x, pos.y + 256, pos.z, &roomNumber); floor = GetFloor(pos.x, pos.y + 256, pos.z, &roomNumber);
if (Rooms[roomNumber].flags & ENV_FLAG_SWAMP) if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_SWAMP)
{ {
pos.y = Rooms[roomNumber].y - 256; pos.y = g_Level.Rooms[roomNumber].y - 256;
floor = GetFloor(pos.x, pos.y, pos.z, &roomNumber); floor = GetFloor(pos.x, pos.y, pos.z, &roomNumber);
} }
else else
@ -964,9 +961,9 @@ void LookCamera(ITEM_INFO* item)
{ {
roomNumber = roomNumber2; roomNumber = roomNumber2;
floor = GetFloor(x, y + 256, z, &roomNumber2); floor = GetFloor(x, y + 256, z, &roomNumber2);
if (Rooms[roomNumber2].flags & ENV_FLAG_SWAMP) if (g_Level.Rooms[roomNumber2].flags & ENV_FLAG_SWAMP)
{ {
y = Rooms[roomNumber2].y - 256; y = g_Level.Rooms[roomNumber2].y - 256;
break; break;
} }
else else
@ -1090,8 +1087,8 @@ void LookCamera(ITEM_INFO* item)
floor = GetFloor(x, y, z, &roomNumber); floor = GetFloor(x, y, z, &roomNumber);
h = GetFloorHeight(floor, x, y, z); h = GetFloorHeight(floor, x, y, z);
c = GetCeiling(floor, x, y, z); c = GetCeiling(floor, x, y, z);
if ((Rooms[roomNumber].flags & ENV_FLAG_SWAMP)) if ((g_Level.Rooms[roomNumber].flags & ENV_FLAG_SWAMP))
Camera.pos.y = Rooms[roomNumber].y - 256; Camera.pos.y = g_Level.Rooms[roomNumber].y - 256;
else if (y < c || y > h || c >= h || h == NO_HEIGHT || c == NO_HEIGHT) else if (y < c || y > h || c >= h || h == NO_HEIGHT || c == NO_HEIGHT)
mgLOS(&Camera.target, &Camera.pos, 0); mgLOS(&Camera.target, &Camera.pos, 0);
@ -1102,7 +1099,7 @@ void LookCamera(ITEM_INFO* item)
floor = GetFloor(x, y, z, &roomNumber); floor = GetFloor(x, y, z, &roomNumber);
h = GetFloorHeight(floor, x, y, z); h = GetFloorHeight(floor, x, y, z);
c = GetCeiling(floor, x, y, z); c = GetCeiling(floor, x, y, z);
if (y < c || y > h || c >= h || h == NO_HEIGHT || c == NO_HEIGHT || (Rooms[roomNumber].flags & ENV_FLAG_SWAMP)) if (y < c || y > h || c >= h || h == NO_HEIGHT || c == NO_HEIGHT || (g_Level.Rooms[roomNumber].flags & ENV_FLAG_SWAMP))
{ {
Camera.pos.x = pos.x; Camera.pos.x = pos.x;
Camera.pos.y = pos.y; Camera.pos.y = pos.y;
@ -1111,7 +1108,7 @@ void LookCamera(ITEM_INFO* item)
} }
GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber); GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber);
LookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.target.x, Camera.target.y, Camera.target.z, 0); LookAt(&Camera, 0);
if (Camera.mikeAtLara) if (Camera.mikeAtLara)
{ {
@ -1180,7 +1177,6 @@ void BinocularCamera(ITEM_INFO* item)
Lara.headXrot = 0; Lara.headXrot = 0;
Lara.torsoYrot = 0; Lara.torsoYrot = 0;
Lara.torsoXrot = 0; Lara.torsoXrot = 0;
//dword_87B0F8 = 0;
Camera.type = BinocularOldCamera; Camera.type = BinocularOldCamera;
return; return;
} }
@ -1257,7 +1253,7 @@ void BinocularCamera(ITEM_INFO* item)
} }
GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber); GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber);
LookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.target.x, Camera.target.y, Camera.target.z, 0); LookAt(&Camera, 0);
if (Camera.mikeAtLara) if (Camera.mikeAtLara)
{ {
@ -1444,7 +1440,6 @@ void BinocularCamera(ITEM_INFO* item)
if (!(InputBusy & IN_ACTION) || Infrared) if (!(InputBusy & IN_ACTION) || Infrared)
{ {
//dword_87B0F8 = 0;
} }
else else
{ {
@ -1559,20 +1554,12 @@ void CalculateCamera()
Camera.underwater = 0; Camera.underwater = 0;
} }
TLFlag = 0; TLFlag = 0;
//if (gfCurrentLevel != LVL5_DEEPSEA_DIVE)
//{
//Camera is in a water room, play water sound effect. //Camera is in a water room, play water sound effect.
if ((Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER)) if ((g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER))
{ {
SoundEffect(SFX_UNDERWATER, NULL, SFX_ALWAYS); SoundEffect(SFX_UNDERWATER, NULL, SFX_ALWAYS);
if (Camera.underwater == 0) if (Camera.underwater == 0)
{ {
/*if (GLOBAL_playing_cutseq == 0 && TLFlag == 0)
{
CDDA_SetMasterVolume(savegame.VolumeCD >> 2);
}*/
Camera.underwater = 1; Camera.underwater = 1;
} }
} }
@ -1580,15 +1567,9 @@ void CalculateCamera()
{ {
if (Camera.underwater != 0) if (Camera.underwater != 0)
{ {
/*if (GLOBAL_playing_cutseq == 0 && TLFlag == 0 && savegame.VolumeCD > 0)
{
CDDA_SetMasterVolume(savegame.VolumeCD);
}*/
Camera.underwater = 0; Camera.underwater = 0;
} }
} }
//}
if (Camera.type == CINEMATIC_CAMERA) if (Camera.type == CINEMATIC_CAMERA)
{ {
@ -1609,10 +1590,10 @@ void CalculateCamera()
fixedCamera = 0; fixedCamera = 0;
} }
short* bounds = GetBoundsAccurate(item); BOUNDING_BOX* bounds = GetBoundsAccurate(item);
int x; int x;
int y = ((bounds[2] + bounds[3]) >> 1) + item->pos.yPos - 256; int y = ((bounds->Y1 + bounds->Y2) / 2) + item->pos.yPos - 256;
int z; int z;
if (Camera.item) if (Camera.item)
@ -1623,7 +1604,7 @@ void CalculateCamera()
int dz = Camera.item->pos.zPos - item->pos.zPos; int dz = Camera.item->pos.zPos - item->pos.zPos;
int shift = sqrt(SQUARE(dx) + SQUARE(dz)); int shift = sqrt(SQUARE(dx) + SQUARE(dz));
short angle = phd_atan(dz, dx) - item->pos.yRot; short angle = phd_atan(dz, dx) - item->pos.yRot;
short tilt = phd_atan(shift, y - (bounds[2] + bounds[3]) / 2 - Camera.item->pos.yPos); short tilt = phd_atan(shift, y - (bounds->Y1 + bounds->Y2) / 2 - Camera.item->pos.yPos);
bounds = GetBoundsAccurate(Camera.item); bounds = GetBoundsAccurate(Camera.item);
angle >>= 1; angle >>= 1;
tilt >>= 1; tilt >>= 1;
@ -1695,7 +1676,7 @@ void CalculateCamera()
if (Camera.type if (Camera.type
&& Camera.flags != CF_CHASE_OBJECT && Camera.flags != CF_CHASE_OBJECT
&& (Camera.number != -1 &&(SniperCamActive = Camera.fixed[Camera.number].flags & 3, Camera.fixed[Camera.number].flags & 2))) && (Camera.number != -1 &&(SniperCamActive = FixedCameras[Camera.number].flags & 3, FixedCameras[Camera.number].flags & 2)))
{ {
PHD_VECTOR pos; PHD_VECTOR pos;
pos.x = 0; pos.x = 0;
@ -1713,7 +1694,7 @@ void CalculateCamera()
} }
else else
{ {
int shift = (bounds[0] + bounds[1] + bounds[4] + bounds[5]) >> 2; int shift = (bounds->X1 + bounds->X2 + bounds->Z1 + bounds->Z2) / 4;
x = item->pos.xPos + (shift * phd_sin(item->pos.yRot) >> W2V_SHIFT); x = item->pos.xPos + (shift * phd_sin(item->pos.yRot) >> W2V_SHIFT);
z = item->pos.zPos + (shift * phd_cos(item->pos.yRot) >> W2V_SHIFT); z = item->pos.zPos + (shift * phd_cos(item->pos.yRot) >> W2V_SHIFT);

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "phd_global.h" #include "phd_global.h"
#include "items.h" #include "items.h"
#include <Specific\setup.h>
typedef enum CAMERA_TYPE typedef enum CAMERA_TYPE
{ {
@ -38,7 +39,6 @@ typedef struct CAMERA_INFO
short targetspeed; // size=0, offset=88 short targetspeed; // size=0, offset=88
ITEM_INFO* item; // size=144, offset=92 ITEM_INFO* item; // size=144, offset=92
ITEM_INFO* lastItem; // size=144, offset=96 ITEM_INFO* lastItem; // size=144, offset=96
OBJECT_VECTOR* fixed; // size=16, offset=100
int mikeAtLara; // size=0, offset=104 int mikeAtLara; // size=0, offset=104
PHD_VECTOR mikePos; // size=12, offset=108 PHD_VECTOR mikePos; // size=12, offset=108
}; };
@ -69,8 +69,9 @@ extern int PhdPerspective;
extern short CurrentFOV; extern short CurrentFOV;
extern int GetLaraOnLOS; extern int GetLaraOnLOS;
extern int SniperOverlay; extern int SniperOverlay;
extern std::vector<OBJECT_VECTOR> FixedCameras;
void LookAt(int posX, int posY, int posZ, int targetX, int targetY, int targetZ, short roll); void LookAt(CAMERA_INFO* cam, short roll);
void AlterFOV(int value); void AlterFOV(int value);
int mgLOS(GAME_VECTOR* start, GAME_VECTOR* target, int push); int mgLOS(GAME_VECTOR* start, GAME_VECTOR* target, int push);
void InitialiseCamera(); void InitialiseCamera();

View file

@ -33,7 +33,7 @@ void TriggerChaffEffects(int flareAge)
vel.y = vect.y - pos.y; vel.y = vect.y - pos.y;
vel.z = vect.z - pos.z; vel.z = vect.z - pos.z;
TriggerChaffEffects(LaraItem, &pos, &vel, LaraItem->speed, (bool)(Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WATER),flareAge); TriggerChaffEffects(LaraItem, &pos, &vel, LaraItem->speed, (bool)(g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WATER),flareAge);
} }
void TriggerChaffEffects(ITEM_INFO* Item,int age) void TriggerChaffEffects(ITEM_INFO* Item,int age)
@ -57,7 +57,7 @@ void TriggerChaffEffects(ITEM_INFO* Item,int age)
vel.y = world.Translation().y; vel.y = world.Translation().y;
vel.z = world.Translation().z; vel.z = world.Translation().z;
TriggerChaffEffects(Item, &pos, &vel, Item->speed, (bool)(Rooms[Item->roomNumber].flags & ENV_FLAG_WATER),age); TriggerChaffEffects(Item, &pos, &vel, Item->speed, (bool)(g_Level.Rooms[Item->roomNumber].flags & ENV_FLAG_WATER),age);
} }
void TriggerChaffEffects(ITEM_INFO* item, PHD_VECTOR* pos, PHD_VECTOR* vel, int speed, bool isUnderwater,int age) void TriggerChaffEffects(ITEM_INFO* item, PHD_VECTOR* pos, PHD_VECTOR* vel, int speed, bool isUnderwater,int age)

View file

@ -31,6 +31,7 @@ char LM[] =
}; };
extern int SplitFloor, SplitCeiling; extern int SplitFloor, SplitCeiling;
int hitSoundTimer;
int XFront, ZFront; int XFront, ZFront;
BOUNDING_BOX GlobalCollisionBounds; BOUNDING_BOX GlobalCollisionBounds;
ITEM_INFO* CollidedItems[1024]; ITEM_INFO* CollidedItems[1024];
@ -58,17 +59,18 @@ int CollideStaticObjects(COLL_INFO* coll, int x, int y, int z, short roomNumber,
for (int i = 0; i < numRooms; i++) for (int i = 0; i < numRooms; i++)
{ {
room = &Rooms[roomList[i]]; room = &g_Level.Rooms[roomList[i]];
for (int j = room->mesh.size(); j > 0; j--, mesh++) for (int j = room->mesh.size(); j > 0; j--, mesh++)
{ {
mesh = &room->mesh[j]; mesh = &room->mesh[j];
StaticInfo* sInfo = &StaticObjects[mesh->staticNumber]; STATIC_INFO* sInfo = &StaticObjects[mesh->staticNumber];
if ((sInfo->flags & 1)) // No collision if ((sInfo->flags & 1)) // No collision
continue; continue;
int yMin = mesh->y + sInfo->xMinc; int yMin = mesh->y + sInfo->xMinc;
int yMax = mesh->y + sInfo->yMaxc; int yMax = mesh->y + sInfo->yMaxc;
short yRot = mesh->yRot;
std::array<float, 4> box{sInfo->xMinc, sInfo->zMinc, sInfo->xMaxc, sInfo->zMaxc}; std::array<float, 4> box{sInfo->xMinc, sInfo->zMinc, sInfo->xMaxc, sInfo->zMaxc};
RotateBoundingBox(box, mesh->yRot); RotateBoundingBox(box, mesh->yRot);
@ -78,6 +80,37 @@ int CollideStaticObjects(COLL_INFO* coll, int x, int y, int z, short roomNumber,
xMax = box[2]; xMax = box[2];
zMax = box[3]; zMax = box[3];
if (yRot == ANGLE(180))
{
xMin = mesh->x - sInfo->collisionBox.X2;
xMax = mesh->x - sInfo->collisionBox.X1;
zMin = mesh->z - sInfo->collisionBox.Z2;
zMax = mesh->z - sInfo->collisionBox.Z1;
}
else if (yRot == -ANGLE(90))
{
xMin = mesh->x - sInfo->collisionBox.Z2;
xMax = mesh->x - sInfo->collisionBox.Z1;
zMin = mesh->z + sInfo->collisionBox.X1;
zMax = mesh->z + sInfo->collisionBox.X2;
}
else if (yRot == ANGLE(90))
{
xMin = mesh->x + sInfo->collisionBox.Z1;
xMax = mesh->x + sInfo->collisionBox.Z2;
zMin = mesh->z - sInfo->collisionBox.X2;
zMax = mesh->z - sInfo->collisionBox.X1;
}
else
{
xMin = mesh->x + sInfo->collisionBox.X1;
xMax = mesh->x + sInfo->collisionBox.X2;
zMin = mesh->z + sInfo->collisionBox.Z1;
zMax = mesh->z + sInfo->collisionBox.Z2;
}
if (inXmax <= xMin if (inXmax <= xMin
|| inXmin >= xMax || inXmin >= xMax
|| y <= yMin || y <= yMin
@ -110,27 +143,27 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT
{ {
for (int i = 0; i < numRooms; i++) for (int i = 0; i < numRooms; i++)
{ {
room = &Rooms[roomsArray[i]]; room = &g_Level.Rooms[roomsArray[i]];
for (int j = 0; j < room->mesh.size(); j++) for (int j = 0; j < room->mesh.size(); j++)
{ {
MESH_INFO* mesh = &room->mesh[j]; MESH_INFO* mesh = &room->mesh[j];
StaticInfo* staticMesh = &StaticObjects[mesh->staticNumber]; STATIC_INFO* staticMesh = &StaticObjects[mesh->staticNumber];
if (mesh->flags & 1) if (mesh->flags & 1)
{ {
if (collidingItem->pos.yPos + radius + STEP_SIZE/2 >= mesh->y + staticMesh->yMinc) if (collidingItem->pos.yPos + radius + STEP_SIZE/2 >= mesh->y + staticMesh->collisionBox.Y1)
{ {
if (collidingItem->pos.yPos <= mesh->y + staticMesh->yMaxc) if (collidingItem->pos.yPos <= mesh->y + staticMesh->collisionBox.Y2)
{ {
s = phd_sin(mesh->yRot); s = phd_sin(mesh->yRot);
c = phd_cos(mesh->yRot); c = phd_cos(mesh->yRot);
rx = ((collidingItem->pos.xPos - mesh->x) * c - s * (collidingItem->pos.zPos - mesh->z)) >> W2V_SHIFT; rx = ((collidingItem->pos.xPos - mesh->x) * c - s * (collidingItem->pos.zPos - mesh->z)) >> W2V_SHIFT;
rz = ((collidingItem->pos.zPos - mesh->z) * c + s * (collidingItem->pos.xPos - mesh->x)) >> W2V_SHIFT; rz = ((collidingItem->pos.zPos - mesh->z) * c + s * (collidingItem->pos.xPos - mesh->x)) >> W2V_SHIFT;
if (radius + rx + STEP_SIZE/2 >= staticMesh->xMinc && rx - radius - STEP_SIZE/2 <= staticMesh->xMaxc) if (radius + rx + STEP_SIZE/2 >= staticMesh->collisionBox.X1 && rx - radius - STEP_SIZE/2 <= staticMesh->collisionBox.X2)
{ {
if (radius + rz + STEP_SIZE/2 >= staticMesh->zMinc && rz - radius - STEP_SIZE/2 <= staticMesh->zMaxc) if (radius + rz + STEP_SIZE/2 >= staticMesh->collisionBox.Z1 && rz - radius - STEP_SIZE/2 <= staticMesh->collisionBox.Z2)
{ {
collidedMeshes[numMeshes++] = mesh; collidedMeshes[numMeshes++] = mesh;
if (!radius) if (!radius)
@ -153,14 +186,14 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT
{ {
for (int i = 0; i < numRooms; i++) for (int i = 0; i < numRooms; i++)
{ {
ROOM_INFO* room = &Rooms[roomsArray[i]]; ROOM_INFO* room = &g_Level.Rooms[roomsArray[i]];
int itemNumber = room->itemNumber; int itemNumber = room->itemNumber;
if (itemNumber != NO_ITEM) if (itemNumber != NO_ITEM)
{ {
do do
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item == collidingItem || !ignoreLara && item == LaraItem) if (item == collidingItem || !ignoreLara && item == LaraItem)
{ {
@ -184,7 +217,7 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT
int dy = collidingItem->pos.yPos - item->pos.yPos; int dy = collidingItem->pos.yPos - item->pos.yPos;
int dz = collidingItem->pos.zPos - item->pos.zPos; int dz = collidingItem->pos.zPos - item->pos.zPos;
short* framePtr = GetBestFrame(item); ANIM_FRAME* framePtr = GetBestFrame(item);
if (Objects[item->objectNumber].drawRoutine if (Objects[item->objectNumber].drawRoutine
&& item->meshBits && item->meshBits
@ -195,8 +228,8 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT
&& dy <= 2048 && dy <= 2048
&& dz >= -2048 && dz >= -2048
&& dz <= 2048 && dz <= 2048
&& collidingItem->pos.yPos + radius + 128 >= item->pos.yPos + framePtr[2] && collidingItem->pos.yPos + radius + 128 >= item->pos.yPos + framePtr->boundingBox.Y1
&& collidingItem->pos.yPos - radius - 128 <= item->pos.yPos + framePtr[3]) && collidingItem->pos.yPos - radius - 128 <= item->pos.yPos + framePtr->boundingBox.Y2)
{ {
int s = phd_sin(item->pos.yRot); int s = phd_sin(item->pos.yRot);
int c = phd_cos(item->pos.yRot); int c = phd_cos(item->pos.yRot);
@ -214,9 +247,9 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT
bounds = &v57;*/ bounds = &v57;*/
} }
if (radius + rx + 128 >= framePtr[0] && rx - radius - 128 <= framePtr[1]) if (radius + rx + 128 >= framePtr->boundingBox.X1 && rx - radius - 128 <= framePtr->boundingBox.X2)
{ {
if (radius + rz + 128 >= framePtr[4] && rz - radius - 128 <= framePtr[5]) if (radius + rz + 128 >= framePtr->boundingBox.Z1 && rz - radius - 128 <= framePtr->boundingBox.Z2)
{ {
collidedItems[numItems++] = item; collidedItems[numItems++] = item;
if (!radius) if (!radius)
@ -234,17 +267,17 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT
collidedItems[numItems] = NULL; collidedItems[numItems] = NULL;
} }
return (numItems | numMeshes); return (numItems || numMeshes);
} }
int TestWithGlobalCollisionBounds(ITEM_INFO* item, ITEM_INFO* lara, COLL_INFO* coll) int TestWithGlobalCollisionBounds(ITEM_INFO* item, ITEM_INFO* lara, COLL_INFO* coll)
{ {
short* framePtr = GetBestFrame(lara); ANIM_FRAME* framePtr = GetBestFrame(lara);
if (item->pos.yPos + GlobalCollisionBounds.Y2 <= lara->pos.yPos + framePtr[3]) if (item->pos.yPos + GlobalCollisionBounds.Y2 <= lara->pos.yPos + framePtr->boundingBox.Y1)
return false; return false;
if (item->pos.yPos + GlobalCollisionBounds.Y1 >= framePtr[4]) if (item->pos.yPos + GlobalCollisionBounds.Y1 >= framePtr->boundingBox.Y2)
return false; return false;
int s = phd_sin(item->pos.yRot); int s = phd_sin(item->pos.yRot);
@ -267,7 +300,7 @@ int TestWithGlobalCollisionBounds(ITEM_INFO* item, ITEM_INFO* lara, COLL_INFO* c
void TrapCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c) void TrapCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->status == ITEM_ACTIVE) if (item->status == ITEM_ACTIVE)
{ {
@ -275,9 +308,6 @@ void TrapCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
return; return;
TestCollision(item, LaraItem); TestCollision(item, LaraItem);
/*if (item->object_number == FAN && item->currentAnimState == 1) // Is the fan moving slow ?
ObjectCollision(item_num, laraitem, coll);*/
} }
else if (item->status != ITEM_INVISIBLE) else if (item->status != ITEM_INVISIBLE)
ObjectCollision(itemNumber, l, c); ObjectCollision(itemNumber, l, c);
@ -349,7 +379,7 @@ short GetTiltType(FLOOR_INFO* floor, int x, int y, int z)
{ {
if (CheckNoColFloorTriangle(floor, x, z) == TRUE) if (CheckNoColFloorTriangle(floor, x, z) == TRUE)
break; break;
r = &Rooms[floor->pitRoom]; r = &g_Level.Rooms[floor->pitRoom];
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
} }
@ -359,7 +389,7 @@ short GetTiltType(FLOOR_INFO* floor, int x, int y, int z)
if (!floor->index) if (!floor->index)
return FLOOR_TYPE; return FLOOR_TYPE;
data = &FloorData[floor->index]; data = &g_Level.FloorData[floor->index];
func = *data & DATA_TYPE; func = *data & DATA_TYPE;
if (func == TILT_TYPE) if (func == TILT_TYPE)
@ -423,17 +453,17 @@ int FindGridShift(int x, int z)
return ((WALL_SIZE + 1) - (x & (WALL_SIZE - 1))); return ((WALL_SIZE + 1) - (x & (WALL_SIZE - 1)));
} }
int TestBoundsCollideStatic(short* bounds, PHD_3DPOS* pos, int radius) int TestBoundsCollideStatic(BOUNDING_BOX* bounds, PHD_3DPOS* pos, int radius)
{ {
if (!(bounds[5] | bounds[4] | bounds[0] | bounds[1] | bounds[2] | bounds[3])) if (!(bounds->Z2 != 0 || bounds->Z1 != 0 || bounds->X1 != 0 || bounds->X2 != 0 || bounds->Y1 != 0 || bounds->Y2 != 0))
return FALSE; return false;
short* frame = GetBestFrame(LaraItem); ANIM_FRAME* frame = GetBestFrame(LaraItem);
if (pos->yPos + bounds[3] <= LaraItem->pos.yPos + frame[2]) if (pos->yPos + bounds->Y2 <= LaraItem->pos.yPos + frame->boundingBox.Y1)
return FALSE; return false;
if (pos->yPos + bounds[2] >= LaraItem->pos.yPos + frame[3]) if (pos->yPos + bounds->Y1 >= LaraItem->pos.yPos + frame->boundingBox.Y2)
return FALSE; return false;
int c, s; int c, s;
int x, z, dx, dz; int x, z, dx, dz;
@ -445,20 +475,20 @@ int TestBoundsCollideStatic(short* bounds, PHD_3DPOS* pos, int radius)
dx = (c * x - s * z) >> W2V_SHIFT; dx = (c * x - s * z) >> W2V_SHIFT;
dz = (c * z + s * x) >> W2V_SHIFT; dz = (c * z + s * x) >> W2V_SHIFT;
if (dx <= radius + bounds[1] if (dx <= radius + bounds->X2
&& dx >= bounds[0] - radius && dx >= bounds->X1 - radius
&& dz <= radius + bounds[5] && dz <= radius + bounds->Z2
&& dz >= bounds[4] - radius) && dz >= bounds->Z1 - radius)
{ {
return TRUE; return true;
} }
else else
{ {
return FALSE; return false;
} }
} }
int ItemPushLaraStatic(ITEM_INFO* item, short* bounds, PHD_3DPOS* pos, COLL_INFO* coll) int ItemPushLaraStatic(ITEM_INFO* item, BOUNDING_BOX* bounds, PHD_3DPOS* pos, COLL_INFO* coll)
{ {
int c, s; int c, s;
int dx, dz, rx, rz, minX, maxX, minZ, maxZ; int dx, dz, rx, rz, minX, maxX, minZ, maxZ;
@ -471,10 +501,10 @@ int ItemPushLaraStatic(ITEM_INFO* item, short* bounds, PHD_3DPOS* pos, COLL_INFO
dz = LaraItem->pos.zPos - pos->zPos; dz = LaraItem->pos.zPos - pos->zPos;
rx = (c * dx - s * dz) >> W2V_SHIFT; rx = (c * dx - s * dz) >> W2V_SHIFT;
rz = (c * dz + s * dx) >> W2V_SHIFT; rz = (c * dz + s * dx) >> W2V_SHIFT;
minX = bounds[0] - coll->radius; minX = bounds->X1 - coll->radius;
maxX = bounds[1] + coll->radius; maxX = bounds->X2 + coll->radius;
minZ = bounds[4] - coll->radius; minZ = bounds->Z1 - coll->radius;
maxZ = bounds[5] + coll->radius; maxZ = bounds->Z2 + coll->radius;
if (abs(dx) > 4608 if (abs(dx) > 4608
|| abs(dz) > 4608 || abs(dz) > 4608
@ -482,7 +512,7 @@ int ItemPushLaraStatic(ITEM_INFO* item, short* bounds, PHD_3DPOS* pos, COLL_INFO
|| rx >= maxX || rx >= maxX
|| rz <= minZ || rz <= minZ
|| rz >= maxZ) || rz >= maxZ)
return FALSE; return false;
left = rx - minX; left = rx - minX;
top = maxZ - rz; top = maxZ - rz;
@ -530,7 +560,7 @@ int ItemPushLaraStatic(ITEM_INFO* item, short* bounds, PHD_3DPOS* pos, COLL_INFO
Lara.gunStatus = LG_NO_ARMS; Lara.gunStatus = LG_NO_ARMS;
} }
return TRUE; return true;
} }
int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, char bigpush) int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, char bigpush)
@ -538,7 +568,7 @@ int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, cha
int c, s; int c, s;
int dx, dz, rx, rz, minX, maxX, minZ, maxZ; int dx, dz, rx, rz, minX, maxX, minZ, maxZ;
int left, right, bottom, top; int left, right, bottom, top;
short* bounds; BOUNDING_BOX* bounds;
short facing; short facing;
c = phd_cos(item->pos.yRot); c = phd_cos(item->pos.yRot);
@ -549,14 +579,14 @@ int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, cha
rz = (c * dz + s * dx) >> W2V_SHIFT; rz = (c * dz + s * dx) >> W2V_SHIFT;
if (bigpush & 2) if (bigpush & 2)
bounds = (short*)&GlobalCollisionBounds; bounds = &GlobalCollisionBounds;
else else
bounds = GetBestFrame(item); bounds = (BOUNDING_BOX*)GetBestFrame(item);
minX = bounds[0]; minX = bounds->X1;
maxX = bounds[1]; maxX = bounds->X2;
minZ = bounds[4]; minZ = bounds->Z1;
maxZ = bounds[5]; maxZ = bounds->Z2;
if (bigpush & 1) if (bigpush & 1)
{ {
@ -572,7 +602,7 @@ int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, cha
|| rx >= maxX || rx >= maxX
|| rz <= minZ || rz <= minZ
|| rz >= maxZ) || rz >= maxZ)
return FALSE; return false;
left = rx - minX; left = rx - minX;
top = maxZ - rz; top = maxZ - rz;
@ -591,18 +621,24 @@ int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, cha
l->pos.xPos = item->pos.xPos + ((c * rx + s * rz) >> W2V_SHIFT); l->pos.xPos = item->pos.xPos + ((c * rx + s * rz) >> W2V_SHIFT);
l->pos.zPos = item->pos.zPos + ((c * rz - s * rx) >> W2V_SHIFT); l->pos.zPos = item->pos.zPos + ((c * rz - s * rx) >> W2V_SHIFT);
if (spazon && bounds[3] - bounds[2] > STEP_SIZE) if (spazon && bounds->Y2 - bounds->Y1 > STEP_SIZE)
{ {
rx = (bounds[0] + bounds[1]) / 2; rx = (bounds->X1 + bounds->X2) / 2;
rz = (bounds[4] + bounds[5]) / 2; rz = (bounds->Z1 + bounds->Z2) / 2;
dx -= (c * rx + s * rz) >> W2V_SHIFT; dx -= (c * rx + s * rz) >> W2V_SHIFT;
dz -= (c * rz - s * rx) >> W2V_SHIFT; dz -= (c * rz - s * rx) >> W2V_SHIFT;
Lara.hitDirection = (l->pos.yRot - phd_atan(dz, dz) - ANGLE(135)) >> W2V_SHIFT; Lara.hitDirection = (l->pos.yRot - phd_atan(dz, dz) - ANGLE(135)) >> W2V_SHIFT;
if (!Lara.hitFrame) if ((!Lara.hitFrame) && (!hitSoundTimer > 0))
{
SoundEffect(SFX_LARA_INJURY_RND, &l->pos, 0); SoundEffect(SFX_LARA_INJURY_RND, &l->pos, 0);
hitSoundTimer = frandMinMax(5, 15);
}
if (hitSoundTimer > 0)
hitSoundTimer--;
Lara.hitFrame++; Lara.hitFrame++;
if (Lara.hitFrame > 34) if (Lara.hitFrame > 34)
@ -638,19 +674,19 @@ int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, cha
Lara.gunStatus = LG_NO_ARMS; Lara.gunStatus = LG_NO_ARMS;
} }
return TRUE; return true;
} }
void AIPickupCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c) void AIPickupCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->objectNumber == ID_SHOOT_SWITCH1 && !(item->meshBits & 1)) if (item->objectNumber == ID_SHOOT_SWITCH1 && !(item->meshBits & 1))
item->status = ITEM_INVISIBLE; item->status = ITEM_INVISIBLE;
} }
void ObjectCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c) void ObjectCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TestBoundsCollide(item, l, c->radius)) if (TestBoundsCollide(item, l, c->radius))
{ {
@ -705,7 +741,7 @@ void TriggerLaraBlood()
} }
} }
int TestLaraPosition(short* bounds, ITEM_INFO* item, ITEM_INFO* l) int TestLaraPosition(OBJECT_COLLISION_BOUNDS* bounds, ITEM_INFO* item, ITEM_INFO* l)
{ {
int x, y, z, rx, ry, rz; int x, y, z, rx, ry, rz;
short xRotRel, yRotRel, zRotRel; short xRotRel, yRotRel, zRotRel;
@ -714,23 +750,25 @@ int TestLaraPosition(short* bounds, ITEM_INFO* item, ITEM_INFO* l)
yRotRel = l->pos.yRot - item->pos.yRot; yRotRel = l->pos.yRot - item->pos.yRot;
zRotRel = l->pos.zRot - item->pos.zRot; zRotRel = l->pos.zRot - item->pos.zRot;
if (xRotRel < bounds[6]) if (xRotRel < bounds->rotX1)
return FALSE; return false;
if (xRotRel > bounds[7]) if (xRotRel > bounds->rotX2)
return FALSE; return false;
if (yRotRel < bounds[8]) if (yRotRel < bounds->rotY1)
return FALSE; return false;
if (yRotRel > bounds[9]) if (yRotRel > bounds->rotY2)
return FALSE; return false;
if (zRotRel < bounds[10]) if (zRotRel < bounds->rotZ1)
return FALSE; return false;
if (zRotRel > bounds[11]) if (zRotRel > bounds->rotX2)
return FALSE; return false;
Vector3 pos = Vector3(l->pos.xPos - item->pos.xPos, l->pos.yPos - item->pos.yPos, l->pos.zPos - item->pos.zPos); Vector3 pos = Vector3(l->pos.xPos - item->pos.xPos, l->pos.yPos - item->pos.yPos, l->pos.zPos - item->pos.zPos);
// HACK: it seems that a minus sign is required here. I don't know why, but it just works (tm) but we must
// do more tests
Matrix matrix = Matrix::CreateFromYawPitchRoll( Matrix matrix = Matrix::CreateFromYawPitchRoll(
TO_RAD(item->pos.yRot), TO_RAD(-(item->pos.yRot)),
TO_RAD(item->pos.xRot), TO_RAD(item->pos.xRot),
TO_RAD(item->pos.zRot) TO_RAD(item->pos.zRot)
); );
@ -741,10 +779,13 @@ int TestLaraPosition(short* bounds, ITEM_INFO* item, ITEM_INFO* l)
ry = pos.y; ry = pos.y;
rz = pos.z; rz = pos.z;
if (rx < bounds[0] || rx > bounds[1] || ry < bounds[2] || ry > bounds[3] || rz < bounds[4] || rz > bounds[5])
return FALSE;
return TRUE; if (rx < bounds->boundingBox.X1 || rx > bounds->boundingBox.X2
|| ry < bounds->boundingBox.Y1 || ry > bounds->boundingBox.Y2
|| rz < bounds->boundingBox.Z1 || rz > bounds->boundingBox.Z2)
return false;
return true;
} }
int Move3DPosTo3DPos(PHD_3DPOS* src, PHD_3DPOS* dest, int velocity, short angAdd) int Move3DPosTo3DPos(PHD_3DPOS* src, PHD_3DPOS* dest, int velocity, short angAdd)
@ -781,35 +822,35 @@ int Move3DPosTo3DPos(PHD_3DPOS* src, PHD_3DPOS* dest, int velocity, short angAdd
switch (direction) switch (direction)
{ {
case 0: case 0:
LaraItem->animNumber = ANIMATION_LARA_WALK_LEFT; LaraItem->animNumber = LA_SIDESTEP_LEFT;
LaraItem->frameNumber = GF(ANIMATION_LARA_WALK_LEFT, 0); LaraItem->frameNumber = GF(LA_SIDESTEP_LEFT, 0);
LaraItem->goalAnimState = STATE_LARA_WALK_LEFT; LaraItem->goalAnimState = LS_STEP_LEFT;
LaraItem->currentAnimState = STATE_LARA_WALK_LEFT; LaraItem->currentAnimState = LS_STEP_LEFT;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
break; break;
case 1: case 1:
LaraItem->animNumber = ANIMATION_LARA_WALK_FORWARD; LaraItem->animNumber = LA_WALK;
LaraItem->frameNumber = GF(ANIMATION_LARA_WALK_FORWARD, 0); LaraItem->frameNumber = GF(LA_WALK, 0);
LaraItem->goalAnimState = STATE_LARA_WALK_FORWARD; LaraItem->goalAnimState = LS_WALK_FORWARD;
LaraItem->currentAnimState = STATE_LARA_WALK_FORWARD; LaraItem->currentAnimState = LS_WALK_FORWARD;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
break; break;
case 2: case 2:
LaraItem->animNumber = ANIMATION_LARA_WALK_RIGHT; LaraItem->animNumber = LA_WALK;
LaraItem->frameNumber = GF(ANIMATION_LARA_WALK_RIGHT, 0); LaraItem->frameNumber = GF(LA_SIDESTEP_RIGHT, 0);
LaraItem->goalAnimState = STATE_LARA_WALK_RIGHT; LaraItem->goalAnimState = LS_STEP_RIGHT;
LaraItem->currentAnimState = STATE_LARA_WALK_RIGHT; LaraItem->currentAnimState = LS_STEP_RIGHT;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
break; break;
case 3: case 3:
default: default:
LaraItem->animNumber = ANIMATION_LARA_WALK_BACK; LaraItem->animNumber = LA_WALK_BACK;
LaraItem->frameNumber = GF(ANIMATION_LARA_WALK_BACK, 0); LaraItem->frameNumber = GF(LA_WALK_BACK, 0);
LaraItem->goalAnimState = STATE_LARA_WALK_BACK; LaraItem->goalAnimState = LS_WALK_BACK;
LaraItem->currentAnimState = STATE_LARA_WALK_BACK; LaraItem->currentAnimState = LS_WALK_BACK;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
break; break;
@ -899,7 +940,7 @@ int MoveLaraPosition(PHD_VECTOR* vec, ITEM_INFO* item, ITEM_INFO* l)
if (abs(height - l->pos.yPos) <= CLICK(2)) if (abs(height - l->pos.yPos) <= CLICK(2))
{ {
if (sqrt(SQUARE(dest.xPos - l->pos.xPos) + SQUARE(dest.yPos - l->pos.yPos) + SQUARE(dest.zPos - l->pos.zPos)) < (STEP_SIZE/2)) if (sqrt(SQUARE(dest.xPos - l->pos.xPos) + SQUARE(dest.yPos - l->pos.yPos) + SQUARE(dest.zPos - l->pos.zPos)) < (STEP_SIZE/2))
return TRUE; return true;
return Move3DPosTo3DPos(&l->pos, &dest, LARA_VELOCITY, ANGLE(2)); return Move3DPosTo3DPos(&l->pos, &dest, LARA_VELOCITY, ANGLE(2));
} }
@ -910,23 +951,23 @@ int MoveLaraPosition(PHD_VECTOR* vec, ITEM_INFO* item, ITEM_INFO* l)
Lara.gunStatus = LG_NO_ARMS; Lara.gunStatus = LG_NO_ARMS;
} }
return FALSE; return false;
} }
int TestBoundsCollide(ITEM_INFO* item, ITEM_INFO* l, int radius) int TestBoundsCollide(ITEM_INFO* item, ITEM_INFO* l, int radius)
{ {
short* bounds; BOUNDING_BOX* bounds;
short* laraBounds; BOUNDING_BOX* laraBounds;
int c, s; int c, s;
int x, z; int x, z;
int dx, dz; int dx, dz;
bounds = GetBestFrame(item); bounds = (BOUNDING_BOX*)GetBestFrame(item);
laraBounds = GetBestFrame(l); laraBounds = (BOUNDING_BOX*)GetBestFrame(l);
if (item->pos.yPos + bounds[3] > l->pos.yPos + laraBounds[2]) if (item->pos.yPos + bounds->Y2 > l->pos.yPos + laraBounds->Y1)
{ {
if (item->pos.yPos + bounds[2] < l->pos.yPos + laraBounds[3]) if (item->pos.yPos + bounds->Y1 < l->pos.yPos + laraBounds->Y2)
{ {
c = phd_cos(item->pos.yRot); c = phd_cos(item->pos.yRot);
s = phd_sin(item->pos.yRot); s = phd_sin(item->pos.yRot);
@ -935,27 +976,27 @@ int TestBoundsCollide(ITEM_INFO* item, ITEM_INFO* l, int radius)
dx = (c * x - s * z) >> W2V_SHIFT; dx = (c * x - s * z) >> W2V_SHIFT;
dz = (c * z + s * x) >> W2V_SHIFT; dz = (c * z + s * x) >> W2V_SHIFT;
if (dx >= bounds[0] - radius if (dx >= bounds->X1 - radius
&& dx <= radius + bounds[1] && dx <= radius + bounds->X2
&& dz >= bounds[4] - radius && dz >= bounds->Z1 - radius
&& dz <= radius + bounds[5]) && dz <= radius + bounds->Z2)
{ {
return TRUE; return true;
} }
} }
} }
return FALSE; return false;
} }
void CreatureCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void CreatureCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
int c, s; int c, s;
int x, z, rx, rz; int x, z, rx, rz;
short* frame; ANIM_FRAME* frame;
if (item->objectNumber != ID_HITMAN || item->currentAnimState != STATE_LARA_INSERT_PUZZLE) if (item->objectNumber != ID_HITMAN || item->currentAnimState != LS_INSERT_PUZZLE)
{ {
if (TestBoundsCollide(item, l, coll->radius)) if (TestBoundsCollide(item, l, coll->radius))
{ {
@ -972,10 +1013,10 @@ void CreatureCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
c = phd_cos(item->pos.yRot); c = phd_cos(item->pos.yRot);
s = phd_sin(item->pos.yRot); s = phd_sin(item->pos.yRot);
frame = GetBestFrame(item); frame = GetBestFrame(item);
rx = (frame[0] + frame[1]) / 2; rx = (frame->boundingBox.X1 + frame->boundingBox.X2) / 2;
rz = (frame[4] + frame[5]) / 2; rz = (frame->boundingBox.X2 + frame->boundingBox.Z2) / 2;
if (frame[3] - frame[2] > STEP_SIZE) if (frame->boundingBox.Y2 - frame->boundingBox.Y1 > STEP_SIZE)
{ {
int angle = (l->pos.yRot - phd_atan(z - ((c * rx - s * rz) >> W2V_SHIFT), x - ((c * rx + s * rz) >> W2V_SHIFT)) - ANGLE(135)) >> W2V_SHIFT; int angle = (l->pos.yRot - phd_atan(z - ((c * rx - s * rz) >> W2V_SHIFT), x - ((c * rx + s * rz) >> W2V_SHIFT)) - ANGLE(135)) >> W2V_SHIFT;
Lara.hitDirection = (short)angle; Lara.hitDirection = (short)angle;
@ -1419,31 +1460,30 @@ void GetCollisionInfo(COLL_INFO* coll, int xPos, int yPos, int zPos, int roomNum
void LaraBaddieCollision(ITEM_INFO* l, COLL_INFO* coll) void LaraBaddieCollision(ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item; ITEM_INFO* item;
ObjectInfo* obj; OBJECT_INFO* obj;
l->hitStatus = false; l->hitStatus = false;
Lara.hitDirection = -1; Lara.hitDirection = -1;
if (l->hitPoints > 0) if (l->hitPoints > 0)
{ {
// Crash when using GetRoomList() with vector there but work without :x
vector<short> roomsList;
short* door, numDoors; short* door, numDoors;
short roomsToCheck[128];
short numRoomsToCheck = 0;
roomsToCheck[numRoomsToCheck++] = l->roomNumber;
roomsList.push_back(l->roomNumber); ROOM_INFO* room = &g_Level.Rooms[l->roomNumber];
for (int i = 0; i < room->doors.size(); i++)
ROOM_INFO room = Rooms[l->roomNumber];
for (int i = 0; i < room.doors.size(); i++)
{ {
roomsList.push_back(room.doors[i].room); roomsToCheck[numRoomsToCheck++] = room->doors[i].room;
} }
for (int i = 0; i < roomsList.size(); i++) for (int i = 0; i < numRoomsToCheck; i++)
{ {
short itemNumber = Rooms[roomsList[i]].itemNumber; short itemNumber = g_Level.Rooms[roomsToCheck[i]].itemNumber;
while (itemNumber != NO_ITEM) while (itemNumber != NO_ITEM)
{ {
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (item->collidable && item->status != ITEM_INVISIBLE) if (item->collidable && item->status != ITEM_INVISIBLE)
{ {
obj = &Objects[item->objectNumber]; obj = &Objects[item->objectNumber];
@ -1462,9 +1502,9 @@ void LaraBaddieCollision(ITEM_INFO* l, COLL_INFO* coll)
if (coll->enableSpaz) if (coll->enableSpaz)
{ {
for (int j = 0; j < Rooms[roomsList[i]].mesh.size(); j++) for (int j = 0; j < g_Level.Rooms[roomsToCheck[i]].mesh.size(); j++)
{ {
MESH_INFO* mesh = &Rooms[roomsList[i]].mesh[j]; MESH_INFO* mesh = &g_Level.Rooms[roomsToCheck[i]].mesh[j];
if (mesh->flags & 1) if (mesh->flags & 1)
{ {
@ -1480,8 +1520,8 @@ void LaraBaddieCollision(ITEM_INFO* l, COLL_INFO* coll)
pos.zPos = mesh->z; pos.zPos = mesh->z;
pos.yRot = mesh->yRot; pos.yRot = mesh->yRot;
if (TestBoundsCollideStatic(&StaticObjects[mesh->staticNumber].xMinc, &pos, coll->radius)) if (TestBoundsCollideStatic(&StaticObjects[mesh->staticNumber].collisionBox, &pos, coll->radius))
ItemPushLaraStatic(l, &StaticObjects[mesh->staticNumber].xMinc, &pos, coll); ItemPushLaraStatic(l, &StaticObjects[mesh->staticNumber].collisionBox, &pos, coll);
} }
} }
@ -1497,7 +1537,7 @@ void LaraBaddieCollision(ITEM_INFO* l, COLL_INFO* coll)
void GenericSphereBoxCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void GenericSphereBoxCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (item->status != ITEM_INVISIBLE) if (item->status != ITEM_INVISIBLE)
{ {
@ -1562,20 +1602,20 @@ void GenericSphereBoxCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void CalcItemToFloorRotation(ITEM_INFO* item, int radiusDivide) void CalcItemToFloorRotation(ITEM_INFO* item, int radiusDivide)
{ {
FLOOR_INFO* floor; FLOOR_INFO* floor;
ANIM_FRAME* bounds; BOUNDING_BOX* bounds;
GAME_VECTOR pos; GAME_VECTOR pos;
int ratioXZ, frontHDif, sideHDif; int ratioXZ, frontHDif, sideHDif;
int frontX, frontZ, leftX, leftZ, rightX, rightZ; int frontX, frontZ, leftX, leftZ, rightX, rightZ;
int frontHeight, backHeight, leftHeight, rightHeight; int frontHeight, backHeight, leftHeight, rightHeight;
int radiusZ, radiusX; int radiusZ, radiusX;
bounds = (ANIM_FRAME*)GetBoundsAccurate(item); bounds = GetBoundsAccurate(item);
pos.x = item->pos.xPos; pos.x = item->pos.xPos;
pos.y = item->pos.yPos; pos.y = item->pos.yPos;
pos.z = item->pos.zPos; pos.z = item->pos.zPos;
pos.roomNumber = item->roomNumber; pos.roomNumber = item->roomNumber;
radiusX = bounds->MaxX; radiusX = bounds->X2;
radiusZ = bounds->MaxZ / radiusDivide; // need divide in any case else it's too much ! radiusZ = bounds->Z2 / radiusDivide; // need divide in any case else it's too much !
ratioXZ = radiusZ / radiusX; ratioXZ = radiusZ / radiusX;
frontX = (phd_sin(item->pos.yRot) * radiusZ) >> W2V_SHIFT; frontX = (phd_sin(item->pos.yRot) * radiusZ) >> W2V_SHIFT;

View file

@ -7,16 +7,6 @@
// used by coll->badNeg // used by coll->badNeg
#define NO_BAD_NEG NO_HEIGHT #define NO_BAD_NEG NO_HEIGHT
struct BOUNDING_BOX
{
short X1;
short X2;
short Y1;
short Y2;
short Z1;
short Z2;
};
struct COLL_FLOOR struct COLL_FLOOR
{ {
int floor; int floor;
@ -98,6 +88,17 @@ struct COLL_INFO
bool hitCeiling; bool hitCeiling;
}; };
struct OBJECT_COLLISION_BOUNDS
{
BOUNDING_BOX boundingBox;
short rotX1;
short rotX2;
short rotY1;
short rotY2;
short rotZ1;
short rotZ2;
};
extern BOUNDING_BOX GlobalCollisionBounds; extern BOUNDING_BOX GlobalCollisionBounds;
constexpr auto MAX_ITEMS = 1024; constexpr auto MAX_ITEMS = 1024;
extern ITEM_INFO* CollidedItems[MAX_ITEMS]; extern ITEM_INFO* CollidedItems[MAX_ITEMS];
@ -113,14 +114,14 @@ void ShiftItem(ITEM_INFO* item, COLL_INFO* coll);
void UpdateLaraRoom(ITEM_INFO* item, int height); void UpdateLaraRoom(ITEM_INFO* item, int height);
short GetTiltType(FLOOR_INFO* floor, int x, int y, int z); short GetTiltType(FLOOR_INFO* floor, int x, int y, int z);
int FindGridShift(int x, int z); int FindGridShift(int x, int z);
int TestBoundsCollideStatic(short* bounds, PHD_3DPOS* pos, int radius); int TestBoundsCollideStatic(BOUNDING_BOX* bounds, PHD_3DPOS* pos, int radius);
int ItemPushLaraStatic(ITEM_INFO* item, short* bounds, PHD_3DPOS* pos, COLL_INFO* coll); int ItemPushLaraStatic(ITEM_INFO* item, BOUNDING_BOX* bounds, PHD_3DPOS* pos, COLL_INFO* coll);
void AIPickupCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c); void AIPickupCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c);
void ObjectCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c); void ObjectCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c);
void AlignLaraPosition(PHD_VECTOR* vec, ITEM_INFO* item, ITEM_INFO* l); void AlignLaraPosition(PHD_VECTOR* vec, ITEM_INFO* item, ITEM_INFO* l);
void TriggerLaraBlood(); void TriggerLaraBlood();
int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, char bigpush); int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, char bigpush);
int TestLaraPosition(short* bounds, ITEM_INFO* item, ITEM_INFO* l); int TestLaraPosition(OBJECT_COLLISION_BOUNDS* bounds, ITEM_INFO* item, ITEM_INFO* l);
int Move3DPosTo3DPos(PHD_3DPOS* src, PHD_3DPOS* dest, int velocity, short angAdd); int Move3DPosTo3DPos(PHD_3DPOS* src, PHD_3DPOS* dest, int velocity, short angAdd);
int MoveLaraPosition(PHD_VECTOR* pos, ITEM_INFO* item, ITEM_INFO* l); int MoveLaraPosition(PHD_VECTOR* pos, ITEM_INFO* item, ITEM_INFO* l);
int TestBoundsCollide(ITEM_INFO* item, ITEM_INFO* l, int radius); int TestBoundsCollide(ITEM_INFO* item, ITEM_INFO* l, int radius);

View file

@ -41,12 +41,16 @@
#include "tr4_locusts.h" #include "tr4_locusts.h"
#include "smoke.h" #include "smoke.h"
#include "spark.h" #include "spark.h"
#include <tr4_littlebeetle.h>
#include "explosion.h" #include "explosion.h"
#include "drip.h" #include "drip.h"
using std::vector; using std::vector;
using namespace T5M::Effects::Explosion; using namespace T5M::Effects::Explosion;
using namespace T5M::Effects::Spark; using namespace T5M::Effects::Spark;
using namespace T5M::Effects::Smoke; using namespace T5M::Effects::Smoke;
using T5M::Renderer::g_Renderer;
short ShatterSounds[18][10] = short ShatterSounds[18][10] =
{ {
{SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS}, {SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS, SFX_SMASH_GLASS},
@ -146,7 +150,6 @@ short FlashFadeR;
short FlashFadeG; short FlashFadeG;
short FlashFadeB; short FlashFadeB;
short FlashFader; short FlashFader;
short IsRoomOutsideNo;
int SplitFloor; int SplitFloor;
int SplitCeiling; int SplitCeiling;
@ -154,6 +157,9 @@ int TiltXOffset;
int TiltYOffset; int TiltYOffset;
int FramesCount; int FramesCount;
std::vector<short> OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE];
short IsRoomOutsideNo;
extern GameFlow *g_GameFlow; extern GameFlow *g_GameFlow;
extern GameScript *g_GameScript; extern GameScript *g_GameScript;
extern Inventory g_Inventory; extern Inventory g_Inventory;
@ -248,7 +254,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
// Does the player want to enter inventory? // Does the player want to enter inventory?
SetDebounce = false; SetDebounce = false;
if (CurrentLevel != 0 && !g_Renderer->IsFading()) if (CurrentLevel != 0 && !g_Renderer.IsFading())
{ {
if ((DbInput & IN_DESELECT || g_Inventory.GetEnterObject() != NO_ITEM) && !CutSeqTriggered && LaraItem->hitPoints > 0) if ((DbInput & IN_DESELECT || g_Inventory.GetEnterObject() != NO_ITEM) && !CutSeqTriggered && LaraItem->hitPoints > 0)
{ {
@ -299,7 +305,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
if (CurrentLevel != 0) if (CurrentLevel != 0)
{ {
if (!(TrInput & IN_LOOK) || SniperCameraActive || UseSpotCam || TrackCameraInit || if (!(TrInput & IN_LOOK) || SniperCameraActive || UseSpotCam || TrackCameraInit ||
((LaraItem->currentAnimState != STATE_LARA_STOP || LaraItem->animNumber != ANIMATION_LARA_STAY_IDLE) && (!Lara.isDucked || TrInput & IN_DUCK || LaraItem->animNumber != ANIMATION_LARA_CROUCH_IDLE || LaraItem->goalAnimState != STATE_LARA_CROUCH_IDLE))) ((LaraItem->currentAnimState != LS_STOP || LaraItem->animNumber != LA_STAND_IDLE) && (!Lara.isDucked || TrInput & IN_DUCK || LaraItem->animNumber != LA_CROUCH_IDLE || LaraItem->goalAnimState != LS_CROUCH_IDLE)))
{ {
if (BinocularRange == 0) if (BinocularRange == 0)
{ {
@ -345,11 +351,6 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
Lara.busy = true; Lara.busy = true;
LaserSight = true; LaserSight = true;
/*if (!(gfLevelFlags & GF_LVOP_TRAIN))
InfraRed = TRUE;
else*
InfraRed = false;*/
Infrared = true; Infrared = true;
} }
else else
@ -359,18 +360,10 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
{ {
if (LaserSight) if (LaserSight)
{ {
/*if (!(gfLevelFlags & GF_LVOP_TRAIN))
InfraRed = TRUE;
else
InfraRed = false;*/
Infrared = true; Infrared = true;
} }
else else
{ {
/*if ((gfLevelFlags & GF_LVOP_TRAIN) && (inputBusy & IN_ACTION))
InfraRed = TRUE;
else
InfraRed = false;*/
Infrared = false; Infrared = false;
} }
} }
@ -379,7 +372,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
// Clear dynamic lights // Clear dynamic lights
ClearDynamicLights(); ClearDynamicLights();
ClearFires(); ClearFires();
g_Renderer->ClearDynamicLights(); g_Renderer.ClearDynamicLights();
GotLaraSpheres = false; GotLaraSpheres = false;
@ -389,7 +382,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
short itemNum = NextItemActive; short itemNum = NextItemActive;
while (itemNum != NO_ITEM) while (itemNum != NO_ITEM)
{ {
ITEM_INFO *item = &Items[itemNum]; ITEM_INFO *item = &g_Level.Items[itemNum];
short nextItem = item->nextActive; short nextItem = item->nextActive;
if (item->afterDeath <= 128) if (item->afterDeath <= 128)
@ -419,8 +412,8 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
short fxNum = NextFxActive; short fxNum = NextFxActive;
while (fxNum != NO_ITEM) while (fxNum != NO_ITEM)
{ {
short nextFx = Effects[fxNum].nextActive; short nextFx = EffectList[fxNum].nextActive;
FX_INFO *fx = &Effects[fxNum]; FX_INFO *fx = &EffectList[fxNum];
if (Objects[fx->objectNumber].control) if (Objects[fx->objectNumber].control)
Objects[fx->objectNumber].control(fxNum); Objects[fx->objectNumber].control(fxNum);
fxNum = nextFx; fxNum = nextFx;
@ -461,7 +454,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
{ {
Lara.poisoned = 4096; Lara.poisoned = 4096;
} }
if (/*(gfLevelFlags & 0x80u) != 0 &&*/ !Lara.gassed) if (!Lara.gassed)
{ {
if (Lara.dpoisoned) if (Lara.dpoisoned)
{ {
@ -484,6 +477,8 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
InItemControlLoop = false; InItemControlLoop = false;
KillMoveItems(); KillMoveItems();
g_Renderer.UpdateLaraAnimations(true);
// Update Lara's ponytails // Update Lara's ponytails
HairControl(0, 0, 0); HairControl(0, 0, 0);
if (level->LaraType == LARA_YOUNG) if (level->LaraType == LARA_YOUNG)
@ -550,12 +545,14 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
UpdateRats(); UpdateRats();
UpdateBats(); UpdateBats();
UpdateSpiders(); UpdateSpiders();
UpdateLittleBeetles();
UpdateSparkParticles(); UpdateSparkParticles();
UpdateSmokeParticles(); UpdateSmokeParticles();
T5M::Effects::Drip::UpdateDrips(); T5M::Effects::Drip::UpdateDrips();
UpdateExplosionParticles(); UpdateExplosionParticles();
UpdateShockwaves(); UpdateShockwaves();
UpdateLocusts(); UpdateLocusts();
UpdateLittleBeetles();
//Legacy_UpdateLightning(); //Legacy_UpdateLightning();
AnimateWaterfalls(); AnimateWaterfalls();
@ -564,7 +561,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
//SoundEffects(); //SoundEffects();
HealtBarTimer--; HealthBarTimer--;
GameTimer++; GameTimer++;
} }
@ -587,7 +584,7 @@ unsigned CALLBACK GameMain(void *)
TIME_Init(); TIME_Init();
// Do a fixed time title image // Do a fixed time title image
g_Renderer->DoTitleImage(); g_Renderer.DoTitleImage();
// Execute the LUA gameflow and play the game // Execute the LUA gameflow and play the game
g_GameFlow->DoGameflow(); g_GameFlow->DoGameflow();
@ -598,7 +595,7 @@ unsigned CALLBACK GameMain(void *)
PostMessage(WindowsHandle, WM_CLOSE, NULL, NULL); PostMessage(WindowsHandle, WM_CLOSE, NULL, NULL);
EndThread(); EndThread();
return TRUE; return true;
} }
GAME_STATUS DoTitle(int index) GAME_STATUS DoTitle(int index)
@ -750,18 +747,18 @@ GAME_STATUS DoLevel(int index, int ambient, bool loadFromSavegame)
int nframes = 2; int nframes = 2;
// First control phase // First control phase
g_Renderer->ResetAnimations(); g_Renderer.ResetAnimations();
GAME_STATUS result = ControlPhase(nframes, 0); GAME_STATUS result = ControlPhase(nframes, 0);
// Fade in screen // Fade in screen
g_Renderer->FadeIn(); g_Renderer.FadeIn();
// The game loop, finally! // The game loop, finally!
while (true) while (true)
{ {
nframes = DrawPhaseGame(); nframes = DrawPhaseGame();
g_Renderer->ResetAnimations(); g_Renderer.ResetAnimations();
result = ControlPhase(nframes, 0); result = ControlPhase(nframes, 0);
if (result == GAME_STATUS_EXIT_TO_TITLE || if (result == GAME_STATUS_EXIT_TO_TITLE ||
result == GAME_STATUS_LOAD_GAME || result == GAME_STATUS_LOAD_GAME ||
@ -897,16 +894,16 @@ void TestTriggers(short *data, int heavy, int HeavyFlags)
value = *(data++) & 0x3FF; value = *(data++) & 0x3FF;
if (flags & 0x100) if (flags & 0x100)
Items[value].itemFlags[0] = 1; g_Level.Items[value].itemFlags[0] = 1;
if (!SwitchTrigger(value, timer)) if (!SwitchTrigger(value, timer))
return; return;
objectNumber = Items[value].objectNumber; objectNumber = g_Level.Items[value].objectNumber;
if (objectNumber >= ID_SWITCH_TYPE1 && objectNumber <= ID_SWITCH_TYPE6 && Items[value].triggerFlags == 5) if (objectNumber >= ID_SWITCH_TYPE1 && objectNumber <= ID_SWITCH_TYPE6 && g_Level.Items[value].triggerFlags == 5)
switchFlag = 1; switchFlag = 1;
switchOff = (Items[value].currentAnimState == 1); switchOff = (g_Level.Items[value].currentAnimState == 1);
break; break;
@ -1003,7 +1000,7 @@ void TestTriggers(short *data, int heavy, int HeavyFlags)
switch (targetType) switch (targetType)
{ {
case TO_OBJECT: case TO_OBJECT:
item = &Items[value]; item = &g_Level.Items[value];
if (keyResult >= 2 || if (keyResult >= 2 ||
(triggerType == TRIGGER_TYPES::ANTIPAD || (triggerType == TRIGGER_TYPES::ANTIPAD ||
@ -1127,12 +1124,12 @@ void TestTriggers(short *data, int heavy, int HeavyFlags)
if (keyResult == 1) if (keyResult == 1)
break; break;
if (Camera.fixed[value].flags & 0x100) if (FixedCameras[value].flags & 0x100)
break; break;
Camera.number = value; Camera.number = value;
if (Camera.type == LOOK_CAMERA || Camera.type == COMBAT_CAMERA && !(Camera.fixed[value].flags & 3)) if (Camera.type == LOOK_CAMERA || Camera.type == COMBAT_CAMERA && !(FixedCameras[value].flags & 3))
break; break;
if (triggerType == TRIGGER_TYPES::COMBAT) if (triggerType == TRIGGER_TYPES::COMBAT)
@ -1146,7 +1143,7 @@ void TestTriggers(short *data, int heavy, int HeavyFlags)
Camera.timer = (trigger & 0xFF) * 30; Camera.timer = (trigger & 0xFF) * 30;
if (trigger & 0x100) if (trigger & 0x100)
Camera.fixed[Camera.number].flags |= 0x100; FixedCameras[Camera.number].flags |= 0x100;
Camera.speed = ((trigger & CODE_BITS) >> 6) + 1; Camera.speed = ((trigger & CODE_BITS) >> 6) + 1;
Camera.type = heavy ? HEAVY_CAMERA : FIXED_CAMERA; Camera.type = heavy ? HEAVY_CAMERA : FIXED_CAMERA;
@ -1191,7 +1188,7 @@ void TestTriggers(short *data, int heavy, int HeavyFlags)
break; break;
case TO_TARGET: case TO_TARGET:
cameraItem = &Items[value]; cameraItem = &g_Level.Items[value];
break; break;
case TO_SINK: case TO_SINK:
@ -1316,7 +1313,7 @@ short GetDoor(FLOOR_INFO *floor)
if (!floor->index) if (!floor->index)
return NO_ROOM; return NO_ROOM;
short *data = &FloorData[floor->index]; short *data = &g_Level.FloorData[floor->index];
short type = *(data++); short type = *(data++);
if (((type & DATA_TYPE) == TILT_TYPE) || ((type & DATA_TYPE) == SPLIT1) || ((type & DATA_TYPE) == SPLIT2) || ((type & DATA_TYPE) == NOCOLF1B) || ((type & DATA_TYPE) == NOCOLF1T) || ((type & DATA_TYPE) == NOCOLF2B) || ((type & DATA_TYPE) == NOCOLF2T)) if (((type & DATA_TYPE) == TILT_TYPE) || ((type & DATA_TYPE) == SPLIT1) || ((type & DATA_TYPE) == SPLIT2) || ((type & DATA_TYPE) == NOCOLF1B) || ((type & DATA_TYPE) == NOCOLF1T) || ((type & DATA_TYPE) == NOCOLF2B) || ((type & DATA_TYPE) == NOCOLF2T))
@ -1355,14 +1352,14 @@ void TranslateItem(ITEM_INFO *item, int x, int y, int z)
int GetWaterSurface(int x, int y, int z, short roomNumber) int GetWaterSurface(int x, int y, int z, short roomNumber)
{ {
ROOM_INFO *room = &Rooms[roomNumber]; ROOM_INFO *room = &g_Level.Rooms[roomNumber];
FLOOR_INFO *floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z); FLOOR_INFO *floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z);
if (room->flags & ENV_FLAG_WATER) if (room->flags & ENV_FLAG_WATER)
{ {
while (floor->skyRoom != NO_ROOM) while (floor->skyRoom != NO_ROOM)
{ {
room = &Rooms[floor->skyRoom]; room = &g_Level.Rooms[floor->skyRoom];
if (!(room->flags & ENV_FLAG_WATER)) if (!(room->flags & ENV_FLAG_WATER))
return (floor->ceiling << 8); return (floor->ceiling << 8);
floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z); floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z);
@ -1373,7 +1370,7 @@ int GetWaterSurface(int x, int y, int z, short roomNumber)
{ {
while (floor->pitRoom != NO_ROOM) while (floor->pitRoom != NO_ROOM)
{ {
room = &Rooms[floor->pitRoom]; room = &g_Level.Rooms[floor->pitRoom];
if (room->flags & ENV_FLAG_WATER) if (room->flags & ENV_FLAG_WATER)
return (floor->floor << 8); return (floor->floor << 8);
floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z); floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z);
@ -1427,12 +1424,12 @@ int GetChange(ITEM_INFO *item, ANIM_STRUCT *anim)
for (int i = 0; i < anim->numberChanges; i++) for (int i = 0; i < anim->numberChanges; i++)
{ {
CHANGE_STRUCT *change = &Changes[anim->changeIndex + i]; CHANGE_STRUCT *change = &g_Level.Changes[anim->changeIndex + i];
if (change->goalAnimState == item->goalAnimState) if (change->goalAnimState == item->goalAnimState)
{ {
for (int j = 0; j < change->numberRanges; j++) for (int j = 0; j < change->numberRanges; j++)
{ {
RANGE_STRUCT *range = &Ranges[change->rangeIndex + j]; RANGE_STRUCT *range = &g_Level.Ranges[change->rangeIndex + j];
if (item->frameNumber >= range->startFrame && item->frameNumber <= range->endFrame) if (item->frameNumber >= range->startFrame && item->frameNumber <= range->endFrame)
{ {
item->animNumber = range->linkAnimNum; item->animNumber = range->linkAnimNum;
@ -1479,13 +1476,13 @@ void AlterFloorHeight(ITEM_INFO *item, int height)
floor->floor = NO_HEIGHT / STEP_SIZE; floor->floor = NO_HEIGHT / STEP_SIZE;
} }
box = &Boxes[floor->box]; box = &g_Level.Boxes[floor->box];
if (box->overlapIndex & BLOCKABLE) if (box->flags & BLOCKABLE)
{ {
if (height >= 0) if (height >= 0)
box->overlapIndex &= ~BLOCKED; box->flags &= ~BLOCKED;
else else
box->overlapIndex |= BLOCKED; box->flags |= BLOCKED;
} }
} }
@ -1499,7 +1496,7 @@ FLOOR_INFO *GetFloor(int x, int y, int z, short *roomNumber)
short roomDoor = 0; short roomDoor = 0;
int retval; int retval;
r = &Rooms[*roomNumber]; r = &g_Level.Rooms[*roomNumber];
do do
{ {
xFloor = (z - r->z) >> WALL_SHIFT; xFloor = (z - r->z) >> WALL_SHIFT;
@ -1536,7 +1533,7 @@ FLOOR_INFO *GetFloor(int x, int y, int z, short *roomNumber)
if (data != NO_ROOM) if (data != NO_ROOM)
{ {
*roomNumber = data; *roomNumber = data;
r = &Rooms[data]; r = &g_Level.Rooms[data];
} }
} while (data != NO_ROOM); } while (data != NO_ROOM);
@ -1551,7 +1548,7 @@ FLOOR_INFO *GetFloor(int x, int y, int z, short *roomNumber)
break; break;
*roomNumber = floor->skyRoom; *roomNumber = floor->skyRoom;
r = &Rooms[floor->skyRoom]; r = &g_Level.Rooms[floor->skyRoom];
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
if (y >= floor->ceiling * 256) if (y >= floor->ceiling * 256)
break; break;
@ -1567,7 +1564,7 @@ FLOOR_INFO *GetFloor(int x, int y, int z, short *roomNumber)
break; break;
*roomNumber = floor->pitRoom; *roomNumber = floor->pitRoom;
r = &Rooms[floor->pitRoom]; r = &g_Level.Rooms[floor->pitRoom];
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
if (y < floor->floor * 256) if (y < floor->floor * 256)
break; break;
@ -1582,7 +1579,7 @@ int CheckNoColFloorTriangle(FLOOR_INFO *floor, int x, int z)
if (!floor->index) if (!floor->index)
return 0; return 0;
short *data = &FloorData[floor->index]; short *data = &g_Level.FloorData[floor->index];
short type = *(data)&DATA_TYPE; short type = *(data)&DATA_TYPE;
if (type == NOCOLF1T || type == NOCOLF1B || type == NOCOLF2T || type == NOCOLF2B) if (type == NOCOLF1T || type == NOCOLF1B || type == NOCOLF2T || type == NOCOLF2B)
@ -1610,7 +1607,7 @@ int CheckNoColCeilingTriangle(FLOOR_INFO *floor, int x, int z)
if (!floor->index) if (!floor->index)
return 0; return 0;
short *data = &FloorData[floor->index]; short *data = &g_Level.FloorData[floor->index];
short type = *(data)&DATA_TYPE; short type = *(data)&DATA_TYPE;
if (type == TILT_TYPE || type == SPLIT1 || type == SPLIT2 || type == NOCOLF1T || type == NOCOLF1B || type == NOCOLF2T || type == NOCOLF2B) // gibby if (type == TILT_TYPE || type == SPLIT1 || type == SPLIT2 || type == NOCOLF1T || type == NOCOLF1B || type == NOCOLF2T || type == NOCOLF2B) // gibby
@ -1653,7 +1650,7 @@ int GetFloorHeight(FLOOR_INFO *floor, int x, int y, int z)
{ {
if (CheckNoColFloorTriangle(floor, x, z) == 1) if (CheckNoColFloorTriangle(floor, x, z) == 1)
break; break;
r = &Rooms[floor->pitRoom]; r = &g_Level.Rooms[floor->pitRoom];
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
} }
@ -1666,12 +1663,12 @@ int GetFloorHeight(FLOOR_INFO *floor, int x, int y, int z)
if (floor->index == 0) if (floor->index == 0)
return height; return height;
short *data = &FloorData[floor->index]; short *data = &g_Level.FloorData[floor->index];
short type, hadj; short type, hadj;
int xOff, yOff, trigger; int xOff, yOff, trigger;
ITEM_INFO *item; ITEM_INFO *item;
ObjectInfo *obj; OBJECT_INFO *obj;
int tilts, t0, t1, t2, t3, t4, dx, dz, h1, h2; int tilts, t0, t1, t2, t3, t4, dx, dz, h1, h2;
do do
@ -1733,7 +1730,7 @@ int GetFloorHeight(FLOOR_INFO *floor, int x, int y, int z)
} }
else else
{ {
item = &Items[trigger & VALUE_BITS]; item = &g_Level.Items[trigger & VALUE_BITS];
obj = &Objects[item->objectNumber]; obj = &Objects[item->objectNumber];
if (obj->floor && !(item->flags & 0x8000)) if (obj->floor && !(item->flags & 0x8000))
@ -2174,8 +2171,8 @@ int GetTargetOnLOS(GAME_VECTOR *src, GAME_VECTOR *dest, int DrawTarget, int firi
GetFloor(target.x, target.y, target.z, &target.roomNumber); GetFloor(target.x, target.y, target.z, &target.roomNumber);
if (itemNumber >= 0) if ((itemNumber >= 0) && (BaddieSlots[itemNumber].itemNum != NO_ITEM)) // BUGFIX: ensure target has AI. No more pistol desync and camera wobble when shooting non-AI movable objects.
Lara.target = &Items[itemNumber]; Lara.target = &g_Level.Items[itemNumber];
if (firing) if (firing)
{ {
@ -2200,7 +2197,7 @@ int GetTargetOnLOS(GAME_VECTOR *src, GAME_VECTOR *dest, int DrawTarget, int firi
} }
else else
{ {
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (item->objectNumber != ID_SHOOT_SWITCH1 && item->objectNumber != ID_SHOOT_SWITCH2) if (item->objectNumber != ID_SHOOT_SWITCH1 && item->objectNumber != ID_SHOOT_SWITCH2)
{ {
if (Objects[item->objectNumber].explodableMeshbits & ShatterItem.bit && LaserSight) if (Objects[item->objectNumber].explodableMeshbits & ShatterItem.bit && LaserSight)
@ -2301,8 +2298,8 @@ int GetTargetOnLOS(GAME_VECTOR *src, GAME_VECTOR *dest, int DrawTarget, int firi
for (count = GetSwitchTrigger(item, triggerItems, 1); count > 0; --count) for (count = GetSwitchTrigger(item, triggerItems, 1); count > 0; --count)
{ {
AddActiveItem(triggerItems[count - 1]); AddActiveItem(triggerItems[count - 1]);
Items[triggerItems[count - 1]].status = ITEM_ACTIVE; g_Level.Items[triggerItems[count - 1]].status = ITEM_ACTIVE;
Items[triggerItems[count - 1]].flags |= IFLAG_ACTIVATION_MASK; g_Level.Items[triggerItems[count - 1]].flags |= IFLAG_ACTIVATION_MASK;
} }
} }
} }
@ -2322,7 +2319,7 @@ int GetTargetOnLOS(GAME_VECTOR *src, GAME_VECTOR *dest, int DrawTarget, int firi
{ {
if (LaserSight && itemNumber >= 0) if (LaserSight && itemNumber >= 0)
{ {
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (item->objectNumber == ID_ENEMY_JEEP && item->meshBits & 1) if (item->objectNumber == ID_ENEMY_JEEP && item->meshBits & 1)
{ {
/* @FIXME This turns the LaserSight sprite of the Grappling Gun green and calls FireGrapplingBoltFromLasersight() */ /* @FIXME This turns the LaserSight sprite of the Grappling Gun green and calls FireGrapplingBoltFromLasersight() */
@ -2334,7 +2331,7 @@ int GetTargetOnLOS(GAME_VECTOR *src, GAME_VECTOR *dest, int DrawTarget, int firi
{ {
if (itemNumber >= 0) if (itemNumber >= 0)
{ {
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (item->objectNumber == ID_ENEMY_JEEP && Lara.gunType == WEAPON_CROSSBOW && item->meshBits & 1) if (item->objectNumber == ID_ENEMY_JEEP && Lara.gunType == WEAPON_CROSSBOW && item->meshBits & 1)
{ {
/* @FIXME This turns the LaserSight sprite of the Grappling Gun green */ /* @FIXME This turns the LaserSight sprite of the Grappling Gun green */
@ -2378,17 +2375,18 @@ int ObjectOnLOS2(GAME_VECTOR *start, GAME_VECTOR *end, PHD_VECTOR *vec, MESH_INF
{ {
int r, m; int r, m;
ROOM_INFO *room; ROOM_INFO *room;
short linknum, *box; short linknum;
ITEM_INFO *item; ITEM_INFO *item;
PHD_3DPOS pos; PHD_3DPOS pos;
MESH_INFO *meshp; MESH_INFO *meshp;
BOUNDING_BOX* box;
ClosestItem = 999; ClosestItem = 999;
ClosestDist = SQUARE(end->x - start->x) + SQUARE(end->y - start->y) + SQUARE(end->z - start->z); ClosestDist = SQUARE(end->x - start->x) + SQUARE(end->y - start->y) + SQUARE(end->z - start->z);
for (r = 0; r < number_los_rooms; ++r) for (r = 0; r < number_los_rooms; ++r)
{ {
room = &Rooms[los_rooms[r]]; room = &g_Level.Rooms[los_rooms[r]];
for (m = 0; m < room->mesh.size(); m++) for (m = 0; m < room->mesh.size(); m++)
{ {
@ -2401,7 +2399,7 @@ int ObjectOnLOS2(GAME_VECTOR *start, GAME_VECTOR *end, PHD_VECTOR *vec, MESH_INF
pos.zPos = meshp->z; pos.zPos = meshp->z;
pos.yRot = meshp->yRot; pos.yRot = meshp->yRot;
if (DoRayBox(start, end, &StaticObjects[meshp->staticNumber].xMinc, &pos, vec, -1 - meshp->staticNumber)) if (DoRayBox(start, end, &StaticObjects[meshp->staticNumber].collisionBox, &pos, vec, -1 - meshp->staticNumber))
{ {
*mesh = meshp; *mesh = meshp;
end->roomNumber = los_rooms[r]; end->roomNumber = los_rooms[r];
@ -2409,11 +2407,15 @@ int ObjectOnLOS2(GAME_VECTOR *start, GAME_VECTOR *end, PHD_VECTOR *vec, MESH_INF
} }
} }
for (linknum = room->itemNumber; linknum != NO_ITEM; linknum = Items[linknum].nextItem) for (linknum = room->itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextItem)
{ {
item = &Items[linknum]; item = &g_Level.Items[linknum];
if (item->status != ITEM_DEACTIVATED && item->status != ITEM_INVISIBLE && (item->objectNumber != ID_LARA && Objects[item->objectNumber].collision != NULL || item->objectNumber == ID_LARA && GetLaraOnLOS)) if (item->status != ITEM_DEACTIVATED && item->status != ITEM_INVISIBLE
&& (item->objectNumber != ID_LARA
&& Objects[item->objectNumber].collision != NULL
|| item->objectNumber == ID_LARA
&& GetLaraOnLOS))
{ {
box = GetBoundsAccurate(item); box = GetBoundsAccurate(item);
@ -2474,7 +2476,7 @@ int GetCeiling(FLOOR_INFO *floor, int x, int y, int z) // (F) (D)
{ {
if (CheckNoColCeilingTriangle(floor, x, z) == 1) /* @ORIGINAL_BUG: the call is made with floor (which is constant in the while loop) instead of floor2 */ if (CheckNoColCeilingTriangle(floor, x, z) == 1) /* @ORIGINAL_BUG: the call is made with floor (which is constant in the while loop) instead of floor2 */
break; break;
room = &Rooms[floor2->skyRoom]; room = &g_Level.Rooms[floor2->skyRoom];
floor2 = &XZ_GET_SECTOR(room, x - room->x, z - room->z); floor2 = &XZ_GET_SECTOR(room, x - room->x, z - room->z);
} }
ceiling = 256 * floor2->ceiling; ceiling = 256 * floor2->ceiling;
@ -2482,7 +2484,7 @@ int GetCeiling(FLOOR_INFO *floor, int x, int y, int z) // (F) (D)
{ {
if (floor2->index) if (floor2->index)
{ {
data = &FloorData[floor2->index]; data = &g_Level.FloorData[floor2->index];
type = *data; type = *data;
function = type & DATA_TYPE; function = type & DATA_TYPE;
++data; ++data;
@ -2582,12 +2584,12 @@ int GetCeiling(FLOOR_INFO *floor, int x, int y, int z) // (F) (D)
{ {
if (CheckNoColFloorTriangle(floor, x, z) == 1) if (CheckNoColFloorTriangle(floor, x, z) == 1)
break; break;
room = &Rooms[floor->pitRoom]; room = &g_Level.Rooms[floor->pitRoom];
floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z); floor = &XZ_GET_SECTOR(room, x - room->x, z - room->z);
} }
if (floor->index) if (floor->index)
{ {
data = &FloorData[floor->index]; data = &g_Level.FloorData[floor->index];
do do
{ {
type = *data; type = *data;
@ -2629,7 +2631,7 @@ int GetCeiling(FLOOR_INFO *floor, int x, int y, int z) // (F) (D)
} }
else else
{ {
item = &Items[type2 & VALUE_BITS]; item = &g_Level.Items[type2 & VALUE_BITS];
if (Objects[item->objectNumber].ceiling && !(item->flags & 0x8000)) if (Objects[item->objectNumber].ceiling && !(item->flags & 0x8000))
{ {
Objects[item->objectNumber].ceiling(item, x, y, z, &ceiling); Objects[item->objectNumber].ceiling(item, x, y, z, &ceiling);
@ -2643,7 +2645,7 @@ int GetCeiling(FLOOR_INFO *floor, int x, int y, int z) // (F) (D)
return ceiling; return ceiling;
} }
int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOrStaticPos, PHD_VECTOR *hitPos, short closesItemNumber) int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, BOUNDING_BOX *box, PHD_3DPOS *itemOrStaticPos, PHD_VECTOR *hitPos, short closesItemNumber)
{ {
// Ray // Ray
FXMVECTOR rayStart = {start->x, start->y, start->z}; FXMVECTOR rayStart = {start->x, start->y, start->z};
@ -2652,8 +2654,8 @@ int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOr
XMVECTOR rayDirNormalized = XMVector3Normalize(rayDir); XMVECTOR rayDirNormalized = XMVector3Normalize(rayDir);
// Create the bounding box for raw collision detection // Create the bounding box for raw collision detection
Vector3 boxCentre = Vector3(itemOrStaticPos->xPos + (box[1] + box[0]) / 2.0f, itemOrStaticPos->yPos + (box[3] + box[2]) / 2.0f, itemOrStaticPos->zPos + (box[5] + box[4]) / 2.0f); Vector3 boxCentre = Vector3(itemOrStaticPos->xPos + (box->X2 + box->X1) / 2.0f, itemOrStaticPos->yPos + (box->Y2 + box->Y1) / 2.0f, itemOrStaticPos->zPos + (box->Z2 + box->Z1) / 2.0f);
Vector3 boxExtent = Vector3((box[1] - box[0]) / 2.0f, (box[3] - box[2]) / 2.0f, (box[5] - box[4]) / 2.0f); Vector3 boxExtent = Vector3((box->X2 - box->X1) / 2.0f, (box->Y2 - box->Y1) / 2.0f, (box->Z2 - box->Z1) / 2.0f);
Quaternion rotation = Quaternion::CreateFromAxisAngle(Vector3::UnitY, TO_RAD(itemOrStaticPos->yRot)); Quaternion rotation = Quaternion::CreateFromAxisAngle(Vector3::UnitY, TO_RAD(itemOrStaticPos->yRot));
BoundingOrientedBox obox = BoundingOrientedBox(boxCentre, boxExtent, rotation); BoundingOrientedBox obox = BoundingOrientedBox(boxCentre, boxExtent, rotation);
@ -2672,7 +2674,7 @@ int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOr
hitPos->z = collidedPoint.z - itemOrStaticPos->zPos; hitPos->z = collidedPoint.z - itemOrStaticPos->zPos;
// Now in the case of items we need to test single spheres // Now in the case of items we need to test single spheres
short *meshPtr = NULL; MESH* meshPtr = NULL;
int bit = 0; int bit = 0;
int sp = -2; int sp = -2;
float minDistance = SECTOR(1024); float minDistance = SECTOR(1024);
@ -2688,8 +2690,8 @@ int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOr
else else
{ {
// For items instead we need to test spheres // For items instead we need to test spheres
ITEM_INFO *item = &Items[closesItemNumber]; ITEM_INFO *item = &g_Level.Items[closesItemNumber];
ObjectInfo *obj = &Objects[item->objectNumber]; OBJECT_INFO *obj = &Objects[item->objectNumber];
// Get the ransformed sphere of meshes // Get the ransformed sphere of meshes
GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity);
@ -2698,7 +2700,7 @@ int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOr
if (obj->nmeshes <= 0) if (obj->nmeshes <= 0)
return 0; return 0;
meshPtr = Meshes[obj->meshIndex]; meshPtr = &g_Level.Meshes[obj->meshIndex];
for (int i = 0; i < obj->nmeshes; i++) for (int i = 0; i < obj->nmeshes; i++)
{ {
@ -2721,7 +2723,7 @@ int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOr
if (newDist < minDistance) if (newDist < minDistance)
{ {
minDistance = newDist; minDistance = newDist;
meshPtr = Meshes[obj->meshIndex + i]; meshPtr = &g_Level.Meshes[obj->meshIndex + i];
bit = 1 << i; bit = 1 << i;
sp = i; sp = i;
} }
@ -2746,7 +2748,7 @@ int DoRayBox(GAME_VECTOR *start, GAME_VECTOR *end, short *box, PHD_3DPOS *itemOr
// If collided object is an item, then setup the shatter item data struct // If collided object is an item, then setup the shatter item data struct
if (sp >= 0) if (sp >= 0)
{ {
ITEM_INFO *item = &Items[closesItemNumber]; ITEM_INFO *item = &g_Level.Items[closesItemNumber];
GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity); GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity);
@ -2769,10 +2771,10 @@ void AnimateItem(ITEM_INFO *item)
item->frameNumber++; item->frameNumber++;
ANIM_STRUCT *anim = &Anims[item->animNumber]; ANIM_STRUCT *anim = &g_Level.Anims[item->animNumber];
if (anim->numberChanges > 0 && GetChange(item, anim)) if (anim->numberChanges > 0 && GetChange(item, anim))
{ {
anim = &Anims[item->animNumber]; anim = &g_Level.Anims[item->animNumber];
item->currentAnimState = anim->currentAnimState; item->currentAnimState = anim->currentAnimState;
@ -2784,7 +2786,7 @@ void AnimateItem(ITEM_INFO *item)
{ {
if (anim->numberCommands > 0) if (anim->numberCommands > 0)
{ {
short *cmd = &Commands[anim->commandIndex]; short *cmd = &g_Level.Commands[anim->commandIndex];
for (int i = anim->numberCommands; i > 0; i--) for (int i = anim->numberCommands; i > 0; i--)
{ {
switch (*(cmd++)) switch (*(cmd++))
@ -2819,7 +2821,7 @@ void AnimateItem(ITEM_INFO *item)
item->animNumber = anim->jumpAnimNum; item->animNumber = anim->jumpAnimNum;
item->frameNumber = anim->jumpFrameNum; item->frameNumber = anim->jumpFrameNum;
anim = &Anims[item->animNumber]; anim = &g_Level.Anims[item->animNumber];
if (item->currentAnimState != anim->currentAnimState) if (item->currentAnimState != anim->currentAnimState)
{ {
@ -2833,7 +2835,7 @@ void AnimateItem(ITEM_INFO *item)
if (anim->numberCommands > 0) if (anim->numberCommands > 0)
{ {
short *cmd = &Commands[anim->commandIndex]; short *cmd = &g_Level.Commands[anim->commandIndex];
int flags; int flags;
int effectID = 0; int effectID = 0;
@ -2868,21 +2870,21 @@ void AnimateItem(ITEM_INFO *item)
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2); SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
} }
else if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
if (!flags || flags == SFX_WATERONLY && (Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER || Objects[item->objectNumber].intelligent)) if (!flags || flags == SFX_WATERONLY && (g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER || Objects[item->objectNumber].intelligent))
{ {
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2); SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
} }
} }
else if (!flags || flags == SFX_LANDONLY && !(Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER)) else if (!flags || flags == SFX_LANDONLY && !(g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER))
{ {
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2); SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
} }
} }
else else
{ {
if (Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER)
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 1); SoundEffect(cmd[1] & 0x3FFF, &item->pos, 1);
else else
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 0); SoundEffect(cmd[1] & 0x3FFF, &item->pos, 0);
@ -2937,23 +2939,23 @@ void AnimateItem(ITEM_INFO *item)
item->pos.zPos += lateral * phd_cos(item->pos.yRot + ANGLE(90)) >> W2V_SHIFT; item->pos.zPos += lateral * phd_cos(item->pos.yRot + ANGLE(90)) >> W2V_SHIFT;
// Update matrices // Update matrices
short itemNumber = item - Items; short itemNumber = item - g_Level.Items.data();
g_Renderer->UpdateItemAnimations(itemNumber, true); g_Renderer.UpdateItemAnimations(itemNumber, true);
} }
void DoFlipMap(short group) void DoFlipMap(short group)
{ {
ROOM_INFO temp; ROOM_INFO temp;
for (int i = 0; i < Rooms.size(); i++) for (int i = 0; i < g_Level.Rooms.size(); i++)
{ {
ROOM_INFO *r = &Rooms[i]; ROOM_INFO *r = &g_Level.Rooms[i];
if (r->flippedRoom >= 0 && r->flipNumber == group) if (r->flippedRoom >= 0 && r->flipNumber == group)
{ {
RemoveRoomFlipItems(r); RemoveRoomFlipItems(r);
ROOM_INFO *flipped = &Rooms[r->flippedRoom]; ROOM_INFO *flipped = &g_Level.Rooms[r->flippedRoom];
memcpy(&temp, r, sizeof(temp)); memcpy(&temp, r, sizeof(temp));
memcpy(r, flipped, sizeof(ROOM_INFO)); memcpy(r, flipped, sizeof(ROOM_INFO));
@ -2967,7 +2969,7 @@ void DoFlipMap(short group)
AddRoomFlipItems(r); AddRoomFlipItems(r);
g_Renderer->FlipRooms(i, r->flippedRoom); g_Renderer.FlipRooms(i, r->flippedRoom);
} }
} }
@ -2983,9 +2985,9 @@ void DoFlipMap(short group)
void AddRoomFlipItems(ROOM_INFO *r) void AddRoomFlipItems(ROOM_INFO *r)
{ {
for (short linkNum = r->itemNumber; linkNum != NO_ITEM; linkNum = Items[linkNum].nextItem) for (short linkNum = r->itemNumber; linkNum != NO_ITEM; linkNum = g_Level.Items[linkNum].nextItem)
{ {
ITEM_INFO *item = &Items[linkNum]; ITEM_INFO *item = &g_Level.Items[linkNum];
if (item->objectNumber == ID_RAISING_BLOCK1 && item->itemFlags[1]) if (item->objectNumber == ID_RAISING_BLOCK1 && item->itemFlags[1])
AlterFloorHeight(item, -1024); AlterFloorHeight(item, -1024);
@ -3000,9 +3002,9 @@ void AddRoomFlipItems(ROOM_INFO *r)
void RemoveRoomFlipItems(ROOM_INFO *r) void RemoveRoomFlipItems(ROOM_INFO *r)
{ {
for (short linkNum = r->itemNumber; linkNum != NO_ITEM; linkNum = Items[linkNum].nextItem) for (short linkNum = r->itemNumber; linkNum != NO_ITEM; linkNum = g_Level.Items[linkNum].nextItem)
{ {
ITEM_INFO *item = &Items[linkNum]; ITEM_INFO *item = &g_Level.Items[linkNum];
if (item->flags & 0x100 && Objects[item->objectNumber].intelligent && item->hitPoints <= 0 && item->hitPoints != NOT_TARGETABLE) if (item->flags & 0x100 && Objects[item->objectNumber].intelligent && item->hitPoints <= 0 && item->hitPoints != NOT_TARGETABLE)
{ {
@ -3086,7 +3088,7 @@ void RefreshCamera(short type, short *data)
if (Camera.type == LOOK_CAMERA || Camera.type == COMBAT_CAMERA) if (Camera.type == LOOK_CAMERA || Camera.type == COMBAT_CAMERA)
break; break;
Camera.item = &Items[value]; Camera.item = &g_Level.Items[value];
break; break;
} }
} while (!(trigger & END_BIT)); } while (!(trigger & END_BIT));
@ -3117,11 +3119,10 @@ int ExplodeItemNode(ITEM_INFO *item, int Node, int NoXZVel, int bits)
GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity); GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity);
ShatterItem.yRot = item->pos.yRot; ShatterItem.yRot = item->pos.yRot;
ShatterItem.bit = 1 << Node; ShatterItem.bit = 1 << Node;
ShatterItem.meshp = Meshes[Objects[item->objectNumber].meshIndex + Node]; ShatterItem.meshp = &g_Level.Meshes[Objects[item->objectNumber].meshIndex + Node];
ShatterItem.sphere.x = CreatureSpheres[Node].x; ShatterItem.sphere.x = CreatureSpheres[Node].x;
ShatterItem.sphere.y = CreatureSpheres[Node].y; ShatterItem.sphere.y = CreatureSpheres[Node].y;
ShatterItem.sphere.z = CreatureSpheres[Node].z; ShatterItem.sphere.z = CreatureSpheres[Node].z;
ShatterItem.il = (ITEM_LIGHT *)&item->legacyLightData; // TODO: remove it or at last change it with the new renderer light...
ShatterItem.flags = item->objectNumber == ID_CROSSBOW_BOLT ? 0x400 : 0; ShatterItem.flags = item->objectNumber == ID_CROSSBOW_BOLT ? 0x400 : 0;
ShatterImpactData.impactDirection = Vector3(0, -1, 0); ShatterImpactData.impactDirection = Vector3(0, -1, 0);
ShatterImpactData.impactLocation = {(float)ShatterItem.sphere.x, (float)ShatterItem.sphere.y, (float)ShatterItem.sphere.z}; ShatterImpactData.impactLocation = {(float)ShatterItem.sphere.x, (float)ShatterItem.sphere.y, (float)ShatterItem.sphere.z};
@ -3166,7 +3167,7 @@ int TriggerActive(ITEM_INFO *item)
int GetWaterHeight(int x, int y, int z, short roomNumber) int GetWaterHeight(int x, int y, int z, short roomNumber)
{ {
ROOM_INFO *r = &Rooms[roomNumber]; ROOM_INFO *r = &g_Level.Rooms[roomNumber];
FLOOR_INFO *floor; FLOOR_INFO *floor;
short adjoiningRoom = NO_ROOM; short adjoiningRoom = NO_ROOM;
@ -3202,7 +3203,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber)
if (adjoiningRoom != NO_ROOM) if (adjoiningRoom != NO_ROOM)
{ {
roomNumber = adjoiningRoom; roomNumber = adjoiningRoom;
r = &Rooms[adjoiningRoom]; r = &g_Level.Rooms[adjoiningRoom];
} }
} while (adjoiningRoom != NO_ROOM); } while (adjoiningRoom != NO_ROOM);
@ -3212,7 +3213,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber)
{ {
if (CheckNoColCeilingTriangle(floor, x, z) == 1) if (CheckNoColCeilingTriangle(floor, x, z) == 1)
break; break;
r = &Rooms[floor->skyRoom]; r = &g_Level.Rooms[floor->skyRoom];
if (!(r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))) if (!(r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP)))
return r->minfloor; return r->minfloor;
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
@ -3228,7 +3229,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber)
{ {
if (CheckNoColFloorTriangle(floor, x, z) == 1) if (CheckNoColFloorTriangle(floor, x, z) == 1)
break; break;
r = &Rooms[floor->pitRoom]; r = &g_Level.Rooms[floor->pitRoom];
if (r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP)) if (r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
return r->maxceiling; return r->maxceiling;
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z); floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
@ -3242,14 +3243,14 @@ int GetWaterHeight(int x, int y, int z, short roomNumber)
int is_object_in_room(short roomNumber, short objectNumber) int is_object_in_room(short roomNumber, short objectNumber)
{ {
short itemNumber = Rooms[roomNumber].itemNumber; short itemNumber = g_Level.Rooms[roomNumber].itemNumber;
if (itemNumber == NO_ITEM) if (itemNumber == NO_ITEM)
return 0; return 0;
while (true) while (true)
{ {
ITEM_INFO *item = &Items[itemNumber]; ITEM_INFO *item = &g_Level.Items[itemNumber];
if (item->objectNumber == objectNumber) if (item->objectNumber == objectNumber)
break; break;
@ -3280,21 +3281,26 @@ void InterpolateAngle(short angle, short *rotation, short *outAngle, int shift)
int IsRoomOutside(int x, int y, int z) int IsRoomOutside(int x, int y, int z)
{ {
return 0; if (x < 0 || z < 0)
/*
short offset = OutsideRoomOffsets[((x >> 12) * 27) + (z >> 12)];
if (offset == -1)
return -2; return -2;
if (offset < 0) int xTable = x / 1024;
int zTable = z / 1024;
if (OutsideRoomTable[xTable][zTable].size() == 0)
return -2;
for (int i = 0; i < OutsideRoomTable[xTable][zTable].size(); i++)
{ {
ROOM_INFO* r = &Rooms[(offset & 0x7FFF)]; short roomNumber = OutsideRoomTable[xTable][zTable][i];
ROOM_INFO* r = &g_Level.Rooms[roomNumber];
if ((y > r->maxceiling) && (y < r->minfloor) if ((y > r->maxceiling) && (y < r->minfloor)
&& ((z > (r->z + 1024)) && (z < (r->z + ((r->xSize - 1) * 1024)))) && ((z > (r->z + 1024)) && (z < (r->z + ((r->xSize - 1) * 1024))))
&& ((x > (r->x + 1024)) && (x < (r->x + ((r->ySize - 1) * 1024))))) && ((x > (r->x + 1024)) && (x < (r->x + ((r->ySize - 1) * 1024)))))
{ {
short roomNumber = offset & 0x7fff; IsRoomOutsideNo = roomNumber;
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber); FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber);
int height = GetFloorHeight(floor, x, y, z); int height = GetFloorHeight(floor, x, y, z);
if (height == NO_HEIGHT || y > height) if (height == NO_HEIGHT || y > height)
@ -3303,44 +3309,9 @@ int IsRoomOutside(int x, int y, int z)
if (y < height) if (y < height)
return -2; return -2;
if (!(r->flags & (ENV_FLAG_WIND | ENV_FLAG_WATER))) return ((r->flags & (ENV_FLAG_WIND | ENV_FLAG_WATER)) != 0 ? 1 : -3);
return -3;
IsRoomOutsideNo = offset & 0x7FFF;
return 1;
} }
else
return -2;
} }
else
{
unsigned char* s = &OutsideRoomTable[offset];
while (*s != 0xFF)
{
ROOM_INFO* r = &Rooms[*s];
if ((y > r->maxceiling && y < r->minfloor)
&& ((z > (r->z + 1024)) && (z < (r->z + ((r->xSize - 1) * 1024))))
&& ((x > (r->x + 1024)) && (x < (r->x + ((r->ySize - 1) * 1024)))))
{
short roomNumber = *s;
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber);
int height = GetFloorHeight(floor, x, y, z);
if (height == NO_HEIGHT || y > height)
return -2; return -2;
height = GetCeiling(floor, x, y, z);
if (y < height)
return -2;
if (!(r->flags & (ENV_FLAG_WIND | ENV_FLAG_WATER)))
return -3;
IsRoomOutsideNo = *s;
return 1;
}
s++;
}
return -2;
}*/
} }

View file

@ -3,6 +3,8 @@
#include "items.h" #include "items.h"
#include "room.h" #include "room.h"
struct BOUNDING_BOX;
enum GAME_STATUS enum GAME_STATUS
{ {
GAME_STATUS_NONE, GAME_STATUS_NONE,
@ -68,6 +70,9 @@ enum COMMAND_TYPES
#define TRIG_BITS(T) ((T & 0x3FFF) >> 10) #define TRIG_BITS(T) ((T & 0x3FFF) >> 10)
#define OUTSIDE_Z 64
#define OUTSIDE_SIZE 108
extern int KeyTriggerActive; extern int KeyTriggerActive;
extern byte IsAtmospherePlaying; extern byte IsAtmospherePlaying;
extern byte FlipStatus; extern byte FlipStatus;
@ -140,9 +145,10 @@ extern short FlashFadeR;
extern short FlashFadeG; extern short FlashFadeG;
extern short FlashFadeB; extern short FlashFadeB;
extern short FlashFader; extern short FlashFader;
extern short IsRoomOutsideNo;
extern int TiltXOffset; extern int TiltXOffset;
extern int TiltYOffset; extern int TiltYOffset;
extern std::vector<short> OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE];
extern short IsRoomOutsideNo;
GAME_STATUS DoTitle(int index); GAME_STATUS DoTitle(int index);
GAME_STATUS DoLevel(int index, int ambient, bool loadFromSavegame); GAME_STATUS DoLevel(int index, int ambient, bool loadFromSavegame);
@ -173,7 +179,7 @@ void SeedRandomControl(int seed);
int GetRandomDraw(); int GetRandomDraw();
void SeedRandomDraw(int seed); void SeedRandomDraw(int seed);
int GetCeiling(FLOOR_INFO* floor, int x, int y, int z); int GetCeiling(FLOOR_INFO* floor, int x, int y, int z);
int DoRayBox(GAME_VECTOR* start, GAME_VECTOR* end, short* box, PHD_3DPOS* itemOrStaticPos, PHD_VECTOR* hitPos, short closesItemNumber); int DoRayBox(GAME_VECTOR* start, GAME_VECTOR* end, BOUNDING_BOX* box, PHD_3DPOS* itemOrStaticPos, PHD_VECTOR* hitPos, short closesItemNumber);
void AnimateItem(ITEM_INFO* item); void AnimateItem(ITEM_INFO* item);
void DoFlipMap(short group); void DoFlipMap(short group);
void AddRoomFlipItems(ROOM_INFO* r); void AddRoomFlipItems(ROOM_INFO* r);

View file

@ -11,7 +11,7 @@ short SmashedMeshCount;
MESH_INFO* SmashedMesh[32]; MESH_INFO* SmashedMesh[32];
short SmashedMeshRoom[32]; short SmashedMeshRoom[32];
vector<DebrisFragment> DebrisFragments = vector<DebrisFragment>(MAX_DEBRIS); vector<DebrisFragment> DebrisFragments = vector<DebrisFragment>(MAX_DEBRIS);
using namespace T5M::Renderer;
DebrisFragment* GetFreeDebrisFragment() DebrisFragment* GetFreeDebrisFragment()
{ {
for (auto frag = DebrisFragments.begin(); frag != DebrisFragments.end(); frag++) { for (auto frag = DebrisFragments.begin(); frag != DebrisFragments.end(); frag++) {
@ -24,13 +24,12 @@ DebrisFragment* GetFreeDebrisFragment()
void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num,short roomNumber,int noZXVel) void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num,short roomNumber,int noZXVel)
{ {
extern Renderer11* g_Renderer; MESH* meshPtr = nullptr;
short* meshPtr = nullptr;
RendererMesh* fragmentsMesh; RendererMesh* fragmentsMesh;
short yRot = 0; short yRot = 0;
Vector3 pos; Vector3 pos;
if (mesh) { if (mesh) {
meshPtr = Meshes[StaticObjects[mesh->staticNumber].meshNumber]; meshPtr = &g_Level.Meshes[StaticObjects[mesh->staticNumber].meshNumber];
yRot = mesh->yRot; yRot = mesh->yRot;
pos = Vector3(mesh->x, mesh->y, mesh->z); pos = Vector3(mesh->x, mesh->y, mesh->z);
} }
@ -39,8 +38,8 @@ void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num,short roomNumber
yRot = item->yRot; yRot = item->yRot;
pos = Vector3(item->sphere.x, item->sphere.y, item->sphere.z); pos = Vector3(item->sphere.x, item->sphere.y, item->sphere.z);
} }
fragmentsMesh = g_Renderer->getMeshFromMeshPtr(reinterpret_cast<unsigned int>(meshPtr)); fragmentsMesh = g_Renderer.getMesh(0);
for (int bucket = RENDERER_BUCKET_SOLID; bucket <= RENDERER_BUCKET_TRANSPARENT_DS; bucket++) { for (int bucket = RENDERER_BUCKET_SOLID; bucket <= RENDERER_BUCKET_TRANSPARENT; bucket++) {
RendererBucket renderBucket = fragmentsMesh->Buckets[bucket]; RendererBucket renderBucket = fragmentsMesh->Buckets[bucket];
vector<RendererVertex>* meshVertices = &renderBucket.Vertices; vector<RendererVertex>* meshVertices = &renderBucket.Vertices;
for (int i = 0; i < renderBucket.Indices.size(); i += 3) for (int i = 0; i < renderBucket.Indices.size(); i += 3)

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "sphere.h" #include <sphere.h>
#include "Renderer11.h" #include <Renderer11.h>
#include <newtypes.h>
#include <level.h>
#define MAX_DEBRIS 256 #define MAX_DEBRIS 256
@ -25,7 +27,7 @@ typedef struct SHATTER_ITEM
{ {
SPHERE sphere; SPHERE sphere;
ITEM_LIGHT* il; ITEM_LIGHT* il;
short* meshp; MESH* meshp;
int bit; int bit;
short yRot; short yRot;
short flags; short flags;
@ -40,7 +42,7 @@ typedef struct ShatterImpactInfo
typedef struct DebrisMesh typedef struct DebrisMesh
{ {
RENDERER_BUCKETS bucket; RENDERER_BUCKETS bucket;
std::array<RendererVertex, 3> vertices; std::array<T5M::Renderer::RendererVertex, 3> vertices;
}; };
typedef struct DebrisFragment typedef struct DebrisFragment

View file

@ -0,0 +1,26 @@
#pragma once
#if _DEBUG
constexpr bool DebugBuild = true;
#else
constexpr bool DebugBuild = false;
#endif
#include <stdexcept>
inline void assertion(const bool& expr,const char* msg) noexcept {
if constexpr (DebugBuild) {
if (!expr) throw std::runtime_error(msg);
}
};
template <typename ...T>
inline void logD(const T&... x) {
if constexpr (DebugBuild) {
(std::cout << ... << x) << std::endl;
}
};
template <typename ...T>
inline void logE(const T&... x) {
if constexpr (DebugBuild) {
(std::cerr << ... << x) << std::endl;
}
};

View file

@ -22,17 +22,17 @@ PHD_VECTOR KickDoorPos(0, 0, -917);
PHD_VECTOR UnderwaterDoorPos(-251, -540, -46); PHD_VECTOR UnderwaterDoorPos(-251, -540, -46);
PHD_VECTOR CrowbarDoorPos(-412, 0, 256); PHD_VECTOR CrowbarDoorPos(-412, 0, 256);
static short PushPullKickDoorBounds[12] = OBJECT_COLLISION_BOUNDS PushPullKickDoorBounds =
{ {
0xFE80, 0x0180, 0x0000, 0x0000, 0xFC00, 0x0200, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C 0xFE80, 0x0180, 0x0000, 0x0000, 0xFC00, 0x0200, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C
}; };
static short UnderwaterDoorBounds[12] = OBJECT_COLLISION_BOUNDS UnderwaterDoorBounds =
{ {
0xFF00, 0x0100, 0xFC00, 0x0000, 0xFC00, 0x0000, 0xC720, 0x38E0, 0xC720, 0x38E0, 0xC720, 0x38E0 0xFF00, 0x0100, 0xFC00, 0x0000, 0xFC00, 0x0000, 0xC720, 0x38E0, 0xC720, 0x38E0, 0xC720, 0x38E0
}; };
static short CrowbarDoorBounds[12] = OBJECT_COLLISION_BOUNDS CrowbarDoorBounds =
{ {
0xFE00, 0x0200, 0xFC00, 0x0000, 0x0000, 0x0200, 0xC720, 0x38E0, 0xC720, 0x38E0, 0xC720, 0x38E0 0xFE00, 0x0200, 0xFC00, 0x0000, 0x0000, 0x0200, 0xC720, 0x38E0, 0xC720, 0x38E0, 0xC720, 0x38E0
}; };
@ -50,7 +50,7 @@ extern Inventory g_Inventory;
void SequenceDoorControl(short itemNumber) void SequenceDoorControl(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
DOOR_DATA* door = (DOOR_DATA*)item->data; DOOR_DATA* door = (DOOR_DATA*)item->data;
if (CurrentSequence == 3) if (CurrentSequence == 3)
@ -78,7 +78,7 @@ void SequenceDoorControl(short itemNumber)
OpenThatDoor(&door->d2, door); OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door); OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door); OpenThatDoor(&door->d2flip, door);
door->opened = TRUE; door->opened = true;
item->flags |= 0x3E; item->flags |= 0x3E;
} }
} }
@ -90,7 +90,7 @@ void SequenceDoorControl(short itemNumber)
ShutThatDoor(&door->d2, door); ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d1flip, door); ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&door->d2flip, door); ShutThatDoor(&door->d2flip, door);
door->opened = FALSE; door->opened = false;
item->flags &= 0xC1; item->flags &= 0xC1;
} }
} }
@ -101,10 +101,10 @@ void SequenceDoorControl(short itemNumber)
void UnderwaterDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void UnderwaterDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (TrInput & IN_ACTION if (TrInput & IN_ACTION
&& l->currentAnimState == STATE_LARA_UNDERWATER_STOP && l->currentAnimState == LS_UNDERWATER_STOP
&& !(item->status && item->gravityStatus) && !(item->status && item->gravityStatus)
&& Lara.waterStatus == LW_UNDERWATER && Lara.waterStatus == LW_UNDERWATER
&& !Lara.gunStatus && !Lara.gunStatus
@ -112,17 +112,17 @@ void UnderwaterDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
l->pos.yRot ^= ANGLE(180.0f); l->pos.yRot ^= ANGLE(180.0f);
if (TestLaraPosition(UnderwaterDoorBounds, item, l)) if (TestLaraPosition(&UnderwaterDoorBounds, item, l))
{ {
if (MoveLaraPosition(&UnderwaterDoorPos, item, l)) if (MoveLaraPosition(&UnderwaterDoorPos, item, l))
{ {
l->animNumber = ANIMATION_LARA_UNDERWATER_DOOR_OPEN; l->animNumber = LA_UNDERWATER_DOOR_OPEN;
l->frameNumber = GF(ANIMATION_LARA_UNDERWATER_DOOR_OPEN, 0); l->frameNumber = GF(LA_UNDERWATER_DOOR_OPEN, 0);
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->fallspeed = 0; l->fallspeed = 0;
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
AddActiveItem(itemNum); AddActiveItem(itemNum);
item->goalAnimState = STATE_LARA_RUN_FORWARD; item->goalAnimState = LS_RUN_FORWARD;
AnimateItem(item); AnimateItem(item);
Lara.isMoving = false; Lara.isMoving = false;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
@ -151,24 +151,24 @@ void UnderwaterDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void DoubleDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void DoubleDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (TrInput & IN_ACTION if (TrInput & IN_ACTION
&& l->currentAnimState == STATE_LARA_STOP && l->currentAnimState == LS_STOP
&& l->animNumber == ANIMATION_LARA_STAY_IDLE && l->animNumber == LA_STAND_IDLE
&& !(item->status && item->gravityStatus) && !(item->status && item->gravityStatus)
&& !(l->hitStatus) && !(l->hitStatus)
&& !Lara.gunStatus && !Lara.gunStatus
|| Lara.isMoving && Lara.generalPtr == (void*)itemNum) || Lara.isMoving && Lara.generalPtr == (void*)itemNum)
{ {
item->pos.yRot ^= ANGLE(180); item->pos.yRot ^= ANGLE(180);
if (TestLaraPosition(PushPullKickDoorBounds, item, l)) if (TestLaraPosition(&PushPullKickDoorBounds, item, l))
{ {
if (MoveLaraPosition(&DoubleDoorPos, item, l)) if (MoveLaraPosition(&DoubleDoorPos, item, l))
{ {
l->animNumber = ANIMATION_LARA_DOUBLEDOORS_PUSH; l->animNumber = LA_DOUBLEDOOR_OPEN_PUSH;
l->frameNumber = GF(ANIMATION_LARA_DOUBLEDOORS_PUSH, 0); l->frameNumber = GF(LA_DOUBLEDOOR_OPEN_PUSH, 0);
l->currentAnimState = STATE_LARA_DOUBLEDOORS_PUSH; l->currentAnimState = LS_DOUBLEDOOR_PUSH;
AddActiveItem(itemNum); AddActiveItem(itemNum);
@ -200,10 +200,10 @@ void DoubleDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (TrInput & IN_ACTION if (TrInput & IN_ACTION
&& l->currentAnimState == STATE_LARA_STOP && l->currentAnimState == LS_STOP
&& l->animNumber == ANIMATION_LARA_STAY_IDLE && l->animNumber == LA_STAND_IDLE
&& item->status != ITEM_ACTIVE && item->status != ITEM_ACTIVE
&& !(l->hitStatus) && !(l->hitStatus)
&& !Lara.gunStatus && !Lara.gunStatus
@ -217,7 +217,7 @@ void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
applyRot = true; applyRot = true;
} }
if (!TestLaraPosition(PushPullKickDoorBounds, item, l)) if (!TestLaraPosition(&PushPullKickDoorBounds, item, l))
{ {
if (Lara.isMoving && Lara.generalPtr == (void*)itemNum) if (Lara.isMoving && Lara.generalPtr == (void*)itemNum)
{ {
@ -238,15 +238,15 @@ void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
return; return;
} }
l->animNumber = ANIMATION_LARA_DOOR_OPEN_BACK; l->animNumber = LA_DOOR_OPEN_PULL;
l->frameNumber = GF(ANIMATION_LARA_DOOR_OPEN_BACK, 0); l->frameNumber = GF(LA_DOOR_OPEN_PULL, 0);
item->goalAnimState = 3; item->goalAnimState = 3;
AddActiveItem(itemNum); AddActiveItem(itemNum);
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->goalAnimState = STATE_LARA_STOP; l->goalAnimState = LS_STOP;
Lara.isMoving = false; Lara.isMoving = false;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
@ -259,15 +259,15 @@ void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
if (MoveLaraPosition(&KickDoorPos, item, l)) if (MoveLaraPosition(&KickDoorPos, item, l))
{ {
l->animNumber = ANIMATION_LARA_DOOR_KICK; l->animNumber = LA_DOOR_OPEN_KICK;
l->frameNumber = GF(ANIMATION_LARA_DOOR_KICK, 0); l->frameNumber = GF(LA_DOOR_OPEN_KICK, 0);
item->goalAnimState = 2; item->goalAnimState = 2;
AddActiveItem(itemNum); AddActiveItem(itemNum);
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->goalAnimState = STATE_LARA_STOP; l->goalAnimState = LS_STOP;
Lara.isMoving = false; Lara.isMoving = false;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
@ -280,15 +280,15 @@ void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
if (MoveLaraPosition(&PushDoorPos, item, l)) if (MoveLaraPosition(&PushDoorPos, item, l))
{ {
l->animNumber = ANIMATION_LARA_DOOR_OPEN_FORWARD; l->animNumber = LA_DOOR_OPEN_PUSH;
l->frameNumber = GF(ANIMATION_LARA_DOOR_OPEN_FORWARD, 0); l->frameNumber = GF(LA_DOOR_OPEN_PUSH, 0);
item->goalAnimState = 2; item->goalAnimState = 2;
AddActiveItem(itemNum); AddActiveItem(itemNum);
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->goalAnimState = STATE_LARA_STOP; l->goalAnimState = LS_STOP;
Lara.isMoving = false; Lara.isMoving = false;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
@ -311,7 +311,7 @@ void PushPullKickDoorControl(short itemNumber)
ITEM_INFO* item; ITEM_INFO* item;
DOOR_DATA* door; DOOR_DATA* door;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
door = (DOOR_DATA*)item->data; door = (DOOR_DATA*)item->data;
if (!door->opened) if (!door->opened)
@ -320,7 +320,7 @@ void PushPullKickDoorControl(short itemNumber)
OpenThatDoor(&door->d2, door); OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door); OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door); OpenThatDoor(&door->d2flip, door);
door->opened = TRUE; door->opened = true;
} }
AnimateItem(item); AnimateItem(item);
@ -328,19 +328,19 @@ void PushPullKickDoorControl(short itemNumber)
void DoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void DoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (item->triggerFlags == 2 if (item->triggerFlags == 2
&& item->status == ITEM_NOT_ACTIVE && !item->gravityStatus // CHECK && item->status == ITEM_NOT_ACTIVE && !item->gravityStatus // CHECK
&& ((TrInput & IN_ACTION || g_Inventory.GetSelectedObject() == ID_CROWBAR_ITEM) && ((TrInput & IN_ACTION || g_Inventory.GetSelectedObject() == ID_CROWBAR_ITEM)
&& l->currentAnimState == STATE_LARA_STOP && l->currentAnimState == LS_STOP
&& l->animNumber == ANIMATION_LARA_STAY_IDLE && l->animNumber == LA_STAND_IDLE
&& !l->hitStatus && !l->hitStatus
&& Lara.gunStatus == LG_NO_ARMS && Lara.gunStatus == LG_NO_ARMS
|| Lara.isMoving && Lara.generalPtr == (void*)itemNum)) || Lara.isMoving && Lara.generalPtr == (void*)itemNum))
{ {
item->pos.yRot ^= ANGLE(180); item->pos.yRot ^= ANGLE(180);
if (TestLaraPosition(CrowbarDoorBounds, item, l)) if (TestLaraPosition(&CrowbarDoorBounds, item, l))
{ {
if (!Lara.isMoving) if (!Lara.isMoving)
{ {
@ -374,16 +374,16 @@ void DoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
g_Inventory.SetSelectedObject(NO_ITEM); g_Inventory.SetSelectedObject(NO_ITEM);
if (MoveLaraPosition(&CrowbarDoorPos, item, l)) if (MoveLaraPosition(&CrowbarDoorPos, item, l))
{ {
l->animNumber = ANIMATION_LARA_DOOR_OPEN_CROWBAR; l->animNumber = LA_DOOR_OPEN_CROWBAR;
l->frameNumber = GF(ANIMATION_LARA_DOOR_OPEN_CROWBAR, 0); l->frameNumber = GF(LA_DOOR_OPEN_CROWBAR, 0);
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
item->pos.yRot ^= ANGLE(180); item->pos.yRot ^= ANGLE(180);
AddActiveItem(itemNum); AddActiveItem(itemNum);
item->flags |= IFLAG_ACTIVATION_MASK; item->flags |= IFLAG_ACTIVATION_MASK;
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
item->goalAnimState = STATE_LARA_RUN_FORWARD; item->goalAnimState = LS_RUN_FORWARD;
Lara.isMoving = 0; Lara.isMoving = 0;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
@ -418,17 +418,17 @@ void DoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void DoorControl(short itemNumber) void DoorControl(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
DOOR_DATA* door = (DOOR_DATA*)item->data; DOOR_DATA* door = (DOOR_DATA*)item->data;
if (item->triggerFlags == 1) if (item->triggerFlags == 1)
{ {
if (item->itemFlags[0]) if (item->itemFlags[0])
{ {
short* bounds = GetBoundsAccurate(item); BOUNDING_BOX* bounds = GetBoundsAccurate(item);
--item->itemFlags[0]; --item->itemFlags[0];
item->pos.yPos -= 12; item->pos.yPos -= 12;
int y = bounds[2] + item->itemFlags[2] - STEP_SIZE; int y = bounds->Y1 + item->itemFlags[2] - STEP_SIZE;
if (item->pos.yPos < y) if (item->pos.yPos < y)
{ {
item->pos.yPos = y; item->pos.yPos = y;
@ -440,7 +440,7 @@ void DoorControl(short itemNumber)
OpenThatDoor(&door->d2, door); OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door); OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door); OpenThatDoor(&door->d2flip, door);
door->opened = TRUE; door->opened = true;
} }
} }
else else
@ -456,7 +456,7 @@ void DoorControl(short itemNumber)
ShutThatDoor(&door->d2, door); ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d1flip, door); ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&door->d2flip, door); ShutThatDoor(&door->d2flip, door);
door->opened = FALSE; door->opened = false;
} }
} }
} }
@ -479,28 +479,8 @@ void DoorControl(short itemNumber)
OpenThatDoor(&door->d2, door); OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door); OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door); OpenThatDoor(&door->d2flip, door);
door->opened = TRUE; door->opened = true;
} }
/*if (item->frameNumber == Anims[item->animNumber].frameEnd)
{
if (gfCurrentLevel == 11)
{
v9 = item->object_number;
if (v9 != 302 && v9 != 304)
{
LOBYTE(v5) = AnimateItem((int)item);
return v5;
}
LABEL_40:
v10 = item->_bf15ea;
LOBYTE(v10) = v10 | 6;
item->_bf15ea = v10;
LOBYTE(v5) = AnimateItem((int)item);
return v5;
}
if (gfCurrentLevel >= 0xCu && gfCurrentLevel <= 0xEu && item->object_number == 300)
goto LABEL_40;
}*/
} }
else else
{ {
@ -536,7 +516,7 @@ void DoorControl(short itemNumber)
ShutThatDoor(&door->d2, door); ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d1flip, door); ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&door->d2flip, door); ShutThatDoor(&door->d2flip, door);
door->opened = FALSE; door->opened = false;
} }
} }
else else
@ -579,7 +559,7 @@ void OpenThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd)
if (boxIndex != NO_BOX) if (boxIndex != NO_BOX)
{ {
if (!DontUnlockBox) if (!DontUnlockBox)
Boxes[boxIndex].overlapIndex &= ~BLOCKED; g_Level.Boxes[boxIndex].flags &= ~BLOCKED;
for (int i = 0; i < NUM_SLOTS; i++) for (int i = 0; i < NUM_SLOTS; i++)
{ {
@ -670,7 +650,7 @@ void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd)
short boxIndex = doorPos->block; short boxIndex = doorPos->block;
if (boxIndex != NO_BOX) if (boxIndex != NO_BOX)
{ {
Boxes[boxIndex].overlapIndex |= BLOCKED; g_Level.Boxes[boxIndex].flags |= BLOCKED;
for (int i = 0; i < NUM_SLOTS; i++) for (int i = 0; i < NUM_SLOTS; i++)
{ {
BaddieSlots[i].LOT.targetBox = NO_BOX; BaddieSlots[i].LOT.targetBox = NO_BOX;
@ -706,7 +686,7 @@ void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd)
void InitialiseDoor(short itemNumber) void InitialiseDoor(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->objectNumber == ID_SEQUENCE_DOOR1) if (item->objectNumber == ID_SEQUENCE_DOOR1)
item->flags &= 0xBFFFu; item->flags &= 0xBFFFu;
@ -714,7 +694,7 @@ void InitialiseDoor(short itemNumber)
if (item->objectNumber == ID_LIFT_DOORS1 || item->objectNumber == ID_LIFT_DOORS2) if (item->objectNumber == ID_LIFT_DOORS1 || item->objectNumber == ID_LIFT_DOORS2)
item->itemFlags[0] = 4096; item->itemFlags[0] = 4096;
DOOR_DATA * door = (DOOR_DATA*)game_malloc(sizeof(DOOR_DATA)); DOOR_DATA * door = game_malloc<DOOR_DATA>();
item->data = door; item->data = door;
door->opened = false; door->opened = false;
@ -739,7 +719,7 @@ void InitialiseDoor(short itemNumber)
else else
dx++; dx++;
r = &Rooms[item->roomNumber]; r = &g_Level.Rooms[item->roomNumber];
door->d1.floor = &r->floor[(((item->pos.zPos - r->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - r->x) >> WALL_SHIFT) + dx) * r->xSize]; door->d1.floor = &r->floor[(((item->pos.zPos - r->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - r->x) >> WALL_SHIFT) + dx) * r->xSize];
roomNumber = GetDoor(door->d1.floor); roomNumber = GetDoor(door->d1.floor);
@ -747,16 +727,16 @@ void InitialiseDoor(short itemNumber)
boxNumber = door->d1.floor->box; boxNumber = door->d1.floor->box;
else else
{ {
b = &Rooms[roomNumber]; b = &g_Level.Rooms[roomNumber];
boxNumber = b->floor[(((item->pos.zPos - b->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - b->x) >> WALL_SHIFT) + dx) * b->xSize].box; boxNumber = b->floor[(((item->pos.zPos - b->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - b->x) >> WALL_SHIFT) + dx) * b->xSize].box;
} }
door->d1.block = (Boxes[boxNumber].overlapIndex & BLOCKABLE) ? boxNumber : NO_BOX; door->d1.block = (g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
memcpy(&door->d1.data, door->d1.floor, sizeof(FLOOR_INFO)); memcpy(&door->d1.data, door->d1.floor, sizeof(FLOOR_INFO));
if (r->flippedRoom != -1) if (r->flippedRoom != -1)
{ {
r = &Rooms[r->flippedRoom]; r = &g_Level.Rooms[r->flippedRoom];
door->d1flip.floor = &r->floor[(((item->pos.zPos - r->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - r->x) >> WALL_SHIFT) + dx) * r->xSize]; door->d1flip.floor = &r->floor[(((item->pos.zPos - r->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - r->x) >> WALL_SHIFT) + dx) * r->xSize];
roomNumber = GetDoor(door->d1flip.floor); roomNumber = GetDoor(door->d1flip.floor);
@ -764,10 +744,10 @@ void InitialiseDoor(short itemNumber)
boxNumber = door->d1flip.floor->box; boxNumber = door->d1flip.floor->box;
else else
{ {
b = &Rooms[roomNumber]; b = &g_Level.Rooms[roomNumber];
boxNumber = b->floor[(((item->pos.zPos - b->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - b->x) >> WALL_SHIFT) + dx) * b->xSize].box; boxNumber = b->floor[(((item->pos.zPos - b->z) >> WALL_SHIFT) + dz) + (((item->pos.xPos - b->x) >> WALL_SHIFT) + dx) * b->xSize].box;
} }
door->d1flip.block = (Boxes[boxNumber].overlapIndex & BLOCKABLE) ? boxNumber : NO_BOX; door->d1flip.block = (g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
memcpy(&door->d1flip.data, door->d1flip.floor, sizeof(FLOOR_INFO)); memcpy(&door->d1flip.data, door->d1flip.floor, sizeof(FLOOR_INFO));
} }
@ -786,7 +766,7 @@ void InitialiseDoor(short itemNumber)
} }
else else
{ {
r = &Rooms[twoRoom]; r = &g_Level.Rooms[twoRoom];
door->d2.floor = &r->floor[((item->pos.zPos - r->z) >> WALL_SHIFT) + ((item->pos.xPos - r->x) >> WALL_SHIFT) * r->xSize]; door->d2.floor = &r->floor[((item->pos.zPos - r->z) >> WALL_SHIFT) + ((item->pos.xPos - r->x) >> WALL_SHIFT) * r->xSize];
roomNumber = GetDoor(door->d2.floor); roomNumber = GetDoor(door->d2.floor);
@ -794,16 +774,16 @@ void InitialiseDoor(short itemNumber)
boxNumber = door->d2.floor->box; boxNumber = door->d2.floor->box;
else else
{ {
b = &Rooms[roomNumber]; b = &g_Level.Rooms[roomNumber];
boxNumber = b->floor[((item->pos.zPos - b->z) >> WALL_SHIFT) + ((item->pos.xPos - b->x) >> WALL_SHIFT) * b->xSize].box; boxNumber = b->floor[((item->pos.zPos - b->z) >> WALL_SHIFT) + ((item->pos.xPos - b->x) >> WALL_SHIFT) * b->xSize].box;
} }
door->d2.block = (Boxes[boxNumber].overlapIndex & BLOCKABLE) ? boxNumber : NO_BOX; door->d2.block = (g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
memcpy(&door->d2.data, door->d2.floor, sizeof(FLOOR_INFO)); memcpy(&door->d2.data, door->d2.floor, sizeof(FLOOR_INFO));
if (r->flippedRoom != -1) if (r->flippedRoom != -1)
{ {
r = &Rooms[r->flippedRoom]; r = &g_Level.Rooms[r->flippedRoom];
door->d2flip.floor = &r->floor[((item->pos.zPos - r->z) >> WALL_SHIFT) + ((item->pos.xPos - r->x) >> WALL_SHIFT) * r->xSize]; door->d2flip.floor = &r->floor[((item->pos.zPos - r->z) >> WALL_SHIFT) + ((item->pos.xPos - r->x) >> WALL_SHIFT) * r->xSize];
roomNumber = GetDoor(door->d2flip.floor); roomNumber = GetDoor(door->d2flip.floor);
@ -811,10 +791,10 @@ void InitialiseDoor(short itemNumber)
boxNumber = door->d2flip.floor->box; boxNumber = door->d2flip.floor->box;
else else
{ {
b = &Rooms[roomNumber]; b = &g_Level.Rooms[roomNumber];
boxNumber = b->floor[((item->pos.zPos - b->z) >> WALL_SHIFT) + ((item->pos.xPos - b->x) >> WALL_SHIFT) * b->xSize].box; boxNumber = b->floor[((item->pos.zPos - b->z) >> WALL_SHIFT) + ((item->pos.xPos - b->x) >> WALL_SHIFT) * b->xSize].box;
} }
door->d2flip.block = (Boxes[boxNumber].overlapIndex & BLOCKABLE) ? boxNumber : NO_BOX; door->d2flip.block = (g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
memcpy(&door->d2flip.data, door->d2flip.floor, sizeof(FLOOR_INFO)); memcpy(&door->d2flip.data, door->d2flip.floor, sizeof(FLOOR_INFO));
} }
@ -829,43 +809,6 @@ void InitialiseDoor(short itemNumber)
item->roomNumber = roomNumber; item->roomNumber = roomNumber;
item->inDrawRoom = true; item->inDrawRoom = true;
} }
/*if (twoRoom != NO_ROOM && item->objectNumber >= ID_CLOSED_DOOR1 && item->objectNumber <= ID_LIFT_DOORS2)
{
FillDoorPointers(door, item, twoRoom, dz, dx);
door->dptr1[0] = 0;
door->dptr1[1] = 0;
door->dptr1[2] = 0;
door->dptr3[0] = 0;
door->dptr3[1] = 0;
door->dptr3[2] = 0;
if (Rooms[item->roomNumber].flippedRoom != -1)
{
//if (!door->dptr2)
// MEMORY[1] = 1;
door->dptr2[0] = 0;
door->dptr2[1] = 0;
door->dptr2[2] = 0;
}
if (Rooms[item->drawRoom].flippedRoom != -1)
{
//if (!door->dptr4)
// MEMORY[1] = 1;
door->dptr4[0] = 0;
door->dptr4[1] = 0;
door->dptr4[2] = 0;
}
door->item = item;
AssignClosedDoor(item);
}*/
} }
void InitialiseClosedDoors() void InitialiseClosedDoors()
@ -881,17 +824,17 @@ void FillDoorPointers(DOOR_DATA* doorData, ITEM_INFO* item, short roomNumber, in
dx <<= WALL_SHIFT; dx <<= WALL_SHIFT;
dz <<= WALL_SHIFT; dz <<= WALL_SHIFT;
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
GetClosedDoorNormal(r, &doorData->dptr1, &doorData->dn1, dz, dx, absX, absZ); GetClosedDoorNormal(r, &doorData->dptr1, &doorData->dn1, dz, dx, absX, absZ);
if (r->flippedRoom != -1) if (r->flippedRoom != -1)
GetClosedDoorNormal(&Rooms[r->flippedRoom], &doorData->dptr2, &doorData->dn2, dz, dx, absX, absZ); GetClosedDoorNormal(&g_Level.Rooms[r->flippedRoom], &doorData->dptr2, &doorData->dn2, dz, dx, absX, absZ);
r = &Rooms[roomNumber]; r = &g_Level.Rooms[roomNumber];
GetClosedDoorNormal(r, &doorData->dptr3, &doorData->dn3, dz, dx, absX, absZ); GetClosedDoorNormal(r, &doorData->dptr3, &doorData->dn3, dz, dx, absX, absZ);
if (r->flippedRoom != -1) if (r->flippedRoom != -1)
GetClosedDoorNormal(&Rooms[r->flippedRoom], &doorData->dptr4, &doorData->dn4, dz, dx, absX, absZ); GetClosedDoorNormal(&g_Level.Rooms[r->flippedRoom], &doorData->dptr4, &doorData->dn4, dz, dx, absX, absZ);
} }
void GetClosedDoorNormal(ROOM_INFO* room, short** dptr, byte* n, int z, int x, int absX, int absZ) void GetClosedDoorNormal(ROOM_INFO* room, short** dptr, byte* n, int z, int x, int absX, int absZ)
@ -955,10 +898,10 @@ void ProcessClosedDoors()
break; break;
short roomNumber = item->roomNumber; short roomNumber = item->roomNumber;
if (!Rooms[roomNumber].boundActive && !Rooms[item->drawRoom].boundActive) if (!g_Level.Rooms[roomNumber].boundActive && !g_Level.Rooms[item->drawRoom].boundActive)
continue; continue;
if (Rooms[item->drawRoom].boundActive) if (g_Level.Rooms[item->drawRoom].boundActive)
{ {
if (!(item->inDrawRoom)) if (!(item->inDrawRoom))
{ {
@ -975,6 +918,7 @@ void ProcessClosedDoors()
} }
}*/ }*/
} }
// keeping these cocmments for now in case they're actually needed?
void AssignClosedDoor(ITEM_INFO* item) void AssignClosedDoor(ITEM_INFO* item)
{ {
@ -990,7 +934,7 @@ void AssignClosedDoor(ITEM_INFO* item)
void InitialiseSteelDoor(short itemNumber) void InitialiseSteelDoor(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->meshBits = 1; item->meshBits = 1;
item->pos.yPos -= 1024; item->pos.yPos -= 1024;
@ -998,7 +942,7 @@ void InitialiseSteelDoor(short itemNumber)
void SteelDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) void SteelDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->itemFlags[0] != 3) if (item->itemFlags[0] != 3)
{ {

View file

@ -4,7 +4,7 @@
#include "camera.h" #include "camera.h"
#include "level.h" #include "level.h"
#include "Renderer11.h" #include "Renderer11.h"
using T5M::Renderer::g_Renderer;
BITE_INFO EnemyBites[9] = BITE_INFO EnemyBites[9] =
{ {
{ 20, -95, 240, 13 }, { 20, -95, 240, 13 },
@ -24,7 +24,7 @@ int StormTimer;
int dLightningRand; int dLightningRand;
byte SkyStormColor[3]; byte SkyStormColor[3];
byte SkyStormColor2[3]; byte SkyStormColor2[3];
short InterpolatedBounds[6]; BOUNDING_BOX InterpolatedBounds;
LARGE_INTEGER PerformanceCount; LARGE_INTEGER PerformanceCount;
double LdFreq; double LdFreq;
double LdSync; double LdSync;
@ -32,8 +32,8 @@ int GnFrameCounter;
int DrawPhaseGame() int DrawPhaseGame()
{ {
g_Renderer->Draw(); g_Renderer.Draw();
Camera.numberFrames = g_Renderer->SyncRenderer(); Camera.numberFrames = g_Renderer.SyncRenderer();
return Camera.numberFrames; return Camera.numberFrames;
} }
@ -66,30 +66,31 @@ void UpdateStorm()
} }
} }
short* GetBoundsAccurate(ITEM_INFO* item) BOUNDING_BOX* GetBoundsAccurate(ITEM_INFO* item)
{ {
int rate = 0; int rate = 0;
short* framePtr[2]; ANIM_FRAME* framePtr[2];
int frac = GetFrame_D2(item, framePtr, &rate); int frac = GetFrame_D2(item, framePtr, &rate);
if (frac == 0) if (frac == 0)
return framePtr[0]; return &framePtr[0]->boundingBox;
else else
{ {
for (int i = 0; i < 6; i++) InterpolatedBounds.X1 = framePtr[0]->boundingBox.X1 + (framePtr[1]->boundingBox.X1 - framePtr[0]->boundingBox.X1) / rate;
{ InterpolatedBounds.X2 = framePtr[0]->boundingBox.X2 + (framePtr[1]->boundingBox.X2 - framePtr[0]->boundingBox.X2) / rate;
InterpolatedBounds[i] = *(framePtr[0]) + ((*(framePtr[1]) - *(framePtr[0])) * frac) / rate; InterpolatedBounds.Y1 = framePtr[0]->boundingBox.Y1 + (framePtr[1]->boundingBox.Y1 - framePtr[0]->boundingBox.Y1) / rate;
framePtr[0]++; InterpolatedBounds.Y2 = framePtr[0]->boundingBox.Y2 + (framePtr[1]->boundingBox.Y2 - framePtr[0]->boundingBox.Y2) / rate;
framePtr[1]++; InterpolatedBounds.Z1 = framePtr[0]->boundingBox.Z1 + (framePtr[1]->boundingBox.Z1 - framePtr[0]->boundingBox.Z1) / rate;
} InterpolatedBounds.Z2 = framePtr[0]->boundingBox.Z2 + (framePtr[1]->boundingBox.Z2 - framePtr[0]->boundingBox.Z2) / rate;
return InterpolatedBounds;
return &InterpolatedBounds;
} }
} }
short* GetBestFrame(ITEM_INFO* item) ANIM_FRAME* GetBestFrame(ITEM_INFO* item)
{ {
int rate = 0; int rate = 0;
short* framePtr[2]; ANIM_FRAME* framePtr[2];
int frac = GetFrame_D2(item, framePtr, &rate); int frac = GetFrame_D2(item, framePtr, &rate);
@ -99,24 +100,22 @@ short* GetBestFrame(ITEM_INFO* item)
return framePtr[1]; return framePtr[1];
} }
int GetFrame_D2(ITEM_INFO* item, short* framePtr[], int* rate) int GetFrame_D2(ITEM_INFO* item, ANIM_FRAME* framePtr[], int* rate)
{ {
ANIM_STRUCT *anim; ANIM_STRUCT *anim;
int frm; int frm;
int first, second; int first, second;
int frame_size;
int interp, rat; int interp, rat;
frm = item->frameNumber; frm = item->frameNumber;
anim = &Anims[item->animNumber]; anim = &g_Level.Anims[item->animNumber];
framePtr[0] = framePtr[1] = anim->framePtr; framePtr[0] = framePtr[1] = &g_Level.Frames[anim->framePtr];
rat = *rate = anim->interpolation & 0x00ff; rat = *rate = anim->interpolation & 0x00ff;
frame_size = anim->interpolation >> 8;
frm -= anim->frameBase; frm -= anim->frameBase;
first = frm / rat; first = frm / rat;
interp = frm % rat; interp = frm % rat;
framePtr[0] += first * frame_size; // Get Frame pointers framePtr[0] += first; // Get Frame pointers
framePtr[1] = framePtr[0] + frame_size; // and store away framePtr[1] = framePtr[0] + 1; // and store away
if (interp == 0) if (interp == 0)
return(0); return(0);
second = first * rat + rat; second = first * rat + rat;
@ -160,7 +159,7 @@ int Sync()
void DrawAnimatingItem(ITEM_INFO* item) void DrawAnimatingItem(ITEM_INFO* item)
{ {
// TODO: to refactor // TODO: to refactor
// Empty stub because actually we disable items drawing when drawRoutine pointer is NULL in ObjectInfo // Empty stub because actually we disable items drawing when drawRoutine pointer is NULL in OBJECT_INFO
} }
void GetLaraJointPosition(PHD_VECTOR* pos, int LM_enum) void GetLaraJointPosition(PHD_VECTOR* pos, int LM_enum)
@ -169,7 +168,7 @@ void GetLaraJointPosition(PHD_VECTOR* pos, int LM_enum)
LM_enum = LM_HEAD; LM_enum = LM_HEAD;
Vector3 p = Vector3(pos->x, pos->y, pos->z); Vector3 p = Vector3(pos->x, pos->y, pos->z);
g_Renderer->GetLaraAbsBonePosition(&p, LM_enum); g_Renderer.GetLaraAbsBonePosition(&p, LM_enum);
pos->x = p.x; pos->x = p.x;
pos->y = p.y; pos->y = p.y;

View file

@ -1,20 +1,6 @@
#pragma once #pragma once
#include "box.h" #include "box.h"
struct ANIM_FRAME
{
short MinX;
short MaxX;
short MinY;
short MaxY;
short MinZ;
short MaxZ;
short OffsetX;
short OffsetY;
short OffsetZ;
unsigned short AngleSets[]; // Variable size
};
extern BITE_INFO EnemyBites[9]; extern BITE_INFO EnemyBites[9];
extern int LightningCount; extern int LightningCount;
extern int LightningRand; extern int LightningRand;
@ -25,10 +11,10 @@ extern byte SkyStormColor2[3];
extern int GnFrameCounter; extern int GnFrameCounter;
int DrawPhaseGame(); int DrawPhaseGame();
int GetFrame_D2(ITEM_INFO* item, short* framePtr[], int* rate); int GetFrame_D2(ITEM_INFO* item, ANIM_FRAME* framePtr[], int* rate);
void UpdateStorm(); void UpdateStorm();
short* GetBoundsAccurate(ITEM_INFO* item); BOUNDING_BOX* GetBoundsAccurate(ITEM_INFO* item);
short* GetBestFrame(ITEM_INFO* item); ANIM_FRAME* GetBestFrame(ITEM_INFO* item);
int Sync(); int Sync();
bool TIME_Init(); bool TIME_Init();
bool TIME_Reset(); bool TIME_Reset();

View file

@ -23,7 +23,7 @@ namespace T5M {
if (d.age > d.life) if (d.age > d.life)
d.active = false; d.active = false;
d.velocity.y += d.gravity; d.velocity.y += d.gravity;
if (Rooms[d.room].flags & ENV_FLAG_WIND) { if (g_Level.Rooms[d.room].flags & ENV_FLAG_WIND) {
d.velocity.x = SmokeWindX / 2; d.velocity.x = SmokeWindX / 2;
d.velocity.z = SmokeWindZ / 2; d.velocity.z = SmokeWindZ / 2;
} }

View file

@ -18,13 +18,15 @@
#include "tr5_bats_emitter.h" #include "tr5_bats_emitter.h"
#include "tr5_spider_emitter.h" #include "tr5_spider_emitter.h"
#include "pickup.h" #include "pickup.h"
#include "larafire.h"
using std::function; using std::function;
constexpr auto ITEM_RADIUS_YMAX = SECTOR(3); constexpr auto ITEM_RADIUS_YMAX = SECTOR(3);
int wf = 256; int wf = 256;
using namespace T5M::Effects::Footprints; using namespace T5M::Effects::Footprints;
short FXType; short FXType;
FX_INFO* Effects; FX_INFO* EffectList;
function<EffectFunction> effect_routines[59] = function<EffectFunction> effect_routines[59] =
{ {
@ -41,9 +43,9 @@ function<EffectFunction> effect_routines[59] =
SoundFlipEffect, SoundFlipEffect,
ExplosionFX, ExplosionFX,
lara_hands_free, lara_hands_free,
void_effect, puzzle,
void_effect, draw_right_pistol,
void_effect, draw_left_pistol,
shoot_right_gun, shoot_right_gun,
shoot_left_gun, shoot_left_gun,
void_effect, void_effect,
@ -74,36 +76,19 @@ function<EffectFunction> effect_routines[59] =
void_effect, void_effect,
void_effect, void_effect,
LaraLocationPad, LaraLocationPad,
KillActiveBaddies, KillActiveBaddies
TL_1,
TL_2,
TL_3,
TL_4,
TL_5,
TL_6,
TL_7,
TL_8,
TL_9,
TL_10,
TL_11,
TL_12,
}; };
void TL_1(ITEM_INFO* item)
{
if (!Savegame.TLCount)
{
IsAtmospherePlaying = 0;
S_CDPlay(9, 0);
Savegame.TLCount = 1;
}
}
void pickup(ITEM_INFO* item) void pickup(ITEM_INFO* item)
{ {
do_pickup(); do_pickup();
} }
void puzzle(ITEM_INFO* item)
{
do_puzzle();
}
// TODO: here are sound for lara footstep too ! // TODO: here are sound for lara footstep too !
void AddFootprint(ITEM_INFO* item) void AddFootprint(ITEM_INFO* item)
{ {
@ -142,116 +127,6 @@ void AddFootprint(ITEM_INFO* item)
} }
} }
void TL_2(ITEM_INFO* item)
{
if (Savegame.TLCount <= 1u)
{
IsAtmospherePlaying = 0;
S_CDPlay(7, 0);
Savegame.TLCount = 2;
}
}
void TL_3(ITEM_INFO* item)
{
if (Savegame.TLCount <= 2u)
{
IsAtmospherePlaying = 0;
S_CDPlay(23, 0);
Savegame.TLCount = 3;
}
}
void TL_4(ITEM_INFO* item)
{
if (Savegame.TLCount <= 3u)
{
IsAtmospherePlaying = 0;
S_CDPlay(39, 0);
Savegame.TLCount = 4;
}
}
void TL_5(ITEM_INFO* item)
{
if (Savegame.TLCount <= 4u)
{
IsAtmospherePlaying = 0;
S_CDPlay(2, 0);
Savegame.TLCount = 5;
}
}
void TL_6(ITEM_INFO* item)
{
if (Savegame.TLCount <= 5u)
{
IsAtmospherePlaying = 0;
S_CDPlay(22, 0);
Savegame.TLCount = 6;
}
}
void TL_7(ITEM_INFO* item)
{
if (Savegame.TLCount <= 6u)
{
IsAtmospherePlaying = 0;
S_CDPlay(51, 0);
Savegame.TLCount = 7;
}
}
void TL_8(ITEM_INFO* item)
{
if (Savegame.TLCount <= 7u)
{
IsAtmospherePlaying = 0;
S_CDPlay(3, 0);
Savegame.TLCount = 8;
}
}
void TL_9(ITEM_INFO* item)
{
if (Savegame.TLCount <= 8u)
{
IsAtmospherePlaying = 0;
S_CDPlay(4, 0);
Savegame.TLCount = 9;
}
}
void TL_10(ITEM_INFO* item)
{
if (Savegame.TLCount == 9)
{
IsAtmospherePlaying = 0;
S_CDPlay(13, 0);
Savegame.TLCount = 10;
}
}
void TL_11(ITEM_INFO* item)
{
if (Savegame.TLCount == 10)
{
IsAtmospherePlaying = 0;
S_CDPlay(0, 0);
Savegame.TLCount = 11;
}
}
void TL_12(ITEM_INFO* item)
{
if (Savegame.TLCount == 11)
{
IsAtmospherePlaying = 0;
S_CDPlay(35, 0);
Savegame.TLCount = 12;
}
}
void reset_hair(ITEM_INFO* item) void reset_hair(ITEM_INFO* item)
{ {
InitialiseHair(); InitialiseHair();
@ -267,48 +142,39 @@ void invisibility_on(ITEM_INFO* item)
item->status = ITEM_INVISIBLE; item->status = ITEM_INVISIBLE;
} }
/*void SetFog()
{
FlipEffect = -1;
unsigned __int16 v0; // si
int v1; // eax
int v2; // eax
char v3; // bl
char v4; // ST14_1
char v5; // ST18_1
dword_51CE04 = 0;
v0 = TriggerTimer;
v1 = CheckVolumetric();
if (!v1)
goto LABEL_5;
if (v0 == 100)
{
dword_51CE04 = 1;
LABEL_5:
FlipEffect = -1;
return v1;
}
v2 = FogTable[v0];
v3 = FogTable[v0] >> 16;
v4 = BYTE1(v2);
v5 = FogTable[v0];
SomeDxFunctionToRemove1(BYTE2(v2), BYTE1(v2), v2);
LOBYTE(v1) = v4;
byte_51CE32 = v3;
byte_51CE31 = v4;
byte_51CE30 = v5;
FlipEffect = -1;
return v1;
}*/
void SetFog(ITEM_INFO* item)//39A44(<), 39F44(<) (F) void SetFog(ITEM_INFO* item)//39A44(<), 39F44(<) (F)
{ {
FlipEffect = -1; FlipEffect = -1;
} }
void draw_left_pistol(ITEM_INFO* item)
{
if (Lara.meshPtrs[LM_LHAND] == Objects[ID_LARA_SKIN].meshIndex + LM_LHAND)
{
Lara.meshPtrs[LM_LHAND] = Objects[WeaponObjectMesh(WEAPON_PISTOLS)].meshIndex + LM_LHAND;
Lara.holsterInfo.leftHolster = HOLSTER_SLOT::Empty;
}
else
{
Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND;
Lara.holsterInfo.leftHolster = HolsterSlotForWeapon(static_cast<LARA_WEAPON_TYPE>(WEAPON_PISTOLS));
}
}
void draw_right_pistol(ITEM_INFO* item)
{
if (Lara.meshPtrs[LM_RHAND] == Objects[ID_LARA_SKIN].meshIndex + LM_RHAND)
{
Lara.meshPtrs[LM_RHAND] = Objects[WeaponObjectMesh(WEAPON_PISTOLS)].meshIndex + LM_RHAND;
Lara.holsterInfo.rightHolster = HOLSTER_SLOT::Empty;
}
else
{
Lara.meshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND;
Lara.holsterInfo.rightHolster = HolsterSlotForWeapon(static_cast<LARA_WEAPON_TYPE>(WEAPON_PISTOLS));
}
}
void shoot_left_gun(ITEM_INFO* item)//39A34(<), 39F34(<) (F) void shoot_left_gun(ITEM_INFO* item)//39A34(<), 39F34(<) (F)
{ {
Lara.leftArm.flash_gun = 3; Lara.leftArm.flash_gun = 3;
@ -333,7 +199,7 @@ void KillActiveBaddies(ITEM_INFO* item)//39938(<), 39E38(<) (F)
do do
{ {
targetItem = &Items[itemNum]; targetItem = &g_Level.Items[itemNum];
if (Objects[targetItem->objectNumber].intelligent) if (Objects[targetItem->objectNumber].intelligent)
{ {
@ -380,12 +246,10 @@ void ExplosionFX(ITEM_INFO* item)//39694(<), 39B94(<) (F)
void SwapCrowbar(ITEM_INFO* item)//39638(<), 39B38(<) (F) void SwapCrowbar(ITEM_INFO* item)//39638(<), 39B38(<) (F)
{ {
short* tmp = Meshes[Objects[ID_LARA].meshIndex + LM_RHAND]; if (Lara.meshPtrs[LM_RHAND] == Objects[ID_LARA].meshIndex + LM_RHAND)
Lara.meshPtrs[LM_RHAND] = Objects[ID_LARA_CROWBAR_ANIM].meshIndex + LM_RHAND;
if (Lara.meshPtrs[LM_RHAND] == tmp)
Lara.meshPtrs[LM_RHAND] = Meshes[Objects[ID_LARA_CROWBAR_ANIM].meshIndex + LM_RHAND];
else else
Lara.meshPtrs[LM_RHAND] = tmp; Lara.meshPtrs[LM_RHAND] = Objects[ID_LARA].meshIndex + LM_RHAND;
} }
void ActivateKey(ITEM_INFO* item)//39624(<), 39B24(<) (F) void ActivateKey(ITEM_INFO* item)//39624(<), 39B24(<) (F)
@ -410,7 +274,7 @@ void RubbleFX(ITEM_INFO* item)//39534(<), 39A34(<) (F)
if (itemNumber != NO_ITEM) if (itemNumber != NO_ITEM)
{ {
ITEM_INFO* eq = &Items[itemNumber]; ITEM_INFO* eq = &g_Level.Items[itemNumber];
AddActiveItem(itemNumber); AddActiveItem(itemNumber);
eq->status = ITEM_ACTIVE; eq->status = ITEM_ACTIVE;
@ -460,7 +324,7 @@ void void_effect(ITEM_INFO* item)//393CC(<), 398CC(<) (F)
void ControlWaterfallMist(short itemNumber) // ControlWaterfallMist void ControlWaterfallMist(short itemNumber) // ControlWaterfallMist
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
int x, z; int x, z;
if (item->pos.yRot == -ANGLE(180)) if (item->pos.yRot == -ANGLE(180))
@ -484,7 +348,7 @@ short DoBloodSplat(int x, int y, int z, short a4, short a5, short roomNumber)
{ {
short roomNum = roomNumber; short roomNum = roomNumber;
GetFloor(x, y, z, &roomNum); GetFloor(x, y, z, &roomNum);
if (Rooms[roomNum].flags & ENV_FLAG_WATER) if (g_Level.Rooms[roomNum].flags & ENV_FLAG_WATER)
TriggerUnderwaterBlood(x, y, z, a4); TriggerUnderwaterBlood(x, y, z, a4);
else else
TriggerBlood(x, y, z, a5 >> 4, a4); TriggerBlood(x, y, z, a5 >> 4, a4);
@ -503,7 +367,7 @@ static bool ItemInRange(int x, int z, int radius)
bool ItemNearLara(PHD_3DPOS* pos, int radius) bool ItemNearLara(PHD_3DPOS* pos, int radius)
{ {
ANIM_FRAME* bounds; BOUNDING_BOX* bounds;
GAME_VECTOR target; GAME_VECTOR target;
target.x = pos->xPos - LaraItem->pos.xPos; target.x = pos->xPos - LaraItem->pos.xPos;
target.y = pos->yPos - LaraItem->pos.yPos; target.y = pos->yPos - LaraItem->pos.yPos;
@ -515,8 +379,8 @@ bool ItemNearLara(PHD_3DPOS* pos, int radius)
if (!ItemInRange(target.x, target.z, radius)) if (!ItemInRange(target.x, target.z, radius))
return false; return false;
bounds = (ANIM_FRAME*)GetBoundsAccurate(LaraItem); bounds = GetBoundsAccurate(LaraItem);
if (target.y >= bounds->MinY && target.y <= (bounds->MaxY + LARA_RAD)) if (target.y >= bounds->Y1 && target.y <= (bounds->Y2 + LARA_RAD))
return true; return true;
return false; return false;
@ -524,7 +388,7 @@ bool ItemNearLara(PHD_3DPOS* pos, int radius)
bool ItemNearTarget(PHD_3DPOS* src, ITEM_INFO* target, int radius) bool ItemNearTarget(PHD_3DPOS* src, ITEM_INFO* target, int radius)
{ {
ANIM_FRAME* bounds; BOUNDING_BOX* bounds;
PHD_VECTOR pos; PHD_VECTOR pos;
pos.x = src->xPos - target->pos.xPos; pos.x = src->xPos - target->pos.xPos;
pos.y = src->yPos - target->pos.yPos; pos.y = src->yPos - target->pos.yPos;
@ -536,8 +400,8 @@ bool ItemNearTarget(PHD_3DPOS* src, ITEM_INFO* target, int radius)
if (!ItemInRange(pos.x, pos.z, radius)) if (!ItemInRange(pos.x, pos.z, radius))
return false; return false;
bounds = (ANIM_FRAME*)GetBoundsAccurate(target); bounds = GetBoundsAccurate(target);
if (pos.y >= bounds->MinY && pos.y <= bounds->MaxY) if (pos.y >= bounds->Y1 && pos.y <= bounds->Y2)
return true; return true;
return false; return false;

View file

@ -21,13 +21,12 @@ struct FX_INFO
}; };
extern std::function<EffectFunction> effect_routines[]; extern std::function<EffectFunction> effect_routines[];
extern FX_INFO* Effects; extern FX_INFO* EffectList;
bool ItemNearLara(PHD_3DPOS* pos, int radius); bool ItemNearLara(PHD_3DPOS* pos, int radius);
bool ItemNearTarget(PHD_3DPOS* src, ITEM_INFO* target, int radius); bool ItemNearTarget(PHD_3DPOS* src, ITEM_INFO* target, int radius);
void StopSoundEffect(short sampleIndex); void StopSoundEffect(short sampleIndex);
short DoBloodSplat(int x, int y, int z, short speed, short yRot, short roomNumber); short DoBloodSplat(int x, int y, int z, short speed, short yRot, short roomNumber);
//void SoundEffects();
void AddFootprint(ITEM_INFO* item); void AddFootprint(ITEM_INFO* item);
void ControlWaterfallMist(short itemNumber); void ControlWaterfallMist(short itemNumber);
void void_effect(ITEM_INFO* item); void void_effect(ITEM_INFO* item);
@ -52,18 +51,9 @@ void SetFog(ITEM_INFO* item);
void invisibility_on(ITEM_INFO* item); void invisibility_on(ITEM_INFO* item);
void invisibility_off(ITEM_INFO* item); void invisibility_off(ITEM_INFO* item);
void reset_hair(ITEM_INFO* item); void reset_hair(ITEM_INFO* item);
void TL_1(ITEM_INFO* item);
void TL_2(ITEM_INFO* item);
void TL_3(ITEM_INFO* item);
void TL_4(ITEM_INFO* item);
void TL_5(ITEM_INFO* item);
void TL_6(ITEM_INFO* item);
void TL_7(ITEM_INFO* item);
void TL_8(ITEM_INFO* item);
void TL_9(ITEM_INFO* item);
void TL_10(ITEM_INFO* item);
void TL_11(ITEM_INFO* item);
void TL_12(ITEM_INFO* item);
void Richochet(PHD_3DPOS* pos); void Richochet(PHD_3DPOS* pos);
void DoLotsOfBlood(int x, int y, int z, int speed, short direction, short roomNumber, int count); void DoLotsOfBlood(int x, int y, int z, int speed, short direction, short roomNumber, int count);
void pickup(ITEM_INFO* item); void pickup(ITEM_INFO* item);
void puzzle(ITEM_INFO* item);
void draw_right_pistol(ITEM_INFO* item);
void draw_left_pistol(ITEM_INFO* item);

View file

@ -14,6 +14,7 @@
#include "spark.h" #include "spark.h"
#include "explosion.h" #include "explosion.h"
#include <Game\drip.h> #include <Game\drip.h>
using T5M::Renderer::g_Renderer;
using T5M::Effects::Explosion::TriggerExplosion; using T5M::Effects::Explosion::TriggerExplosion;
using namespace T5M::Effects::Spark; using namespace T5M::Effects::Spark;
@ -81,11 +82,11 @@ void DetatchSpark(int num, SpriteEnumFlag type)// (F) (D)
case SP_FX: case SP_FX:
if (sptr->flags & SP_USEFXOBJPOS) if (sptr->flags & SP_USEFXOBJPOS)
{ {
sptr->on = FALSE; sptr->on = false;
} }
else else
{ {
fx = &Effects[num]; fx = &EffectList[num];
sptr->x += fx->pos.xPos; sptr->x += fx->pos.xPos;
sptr->y += fx->pos.yPos; sptr->y += fx->pos.yPos;
sptr->z += fx->pos.zPos; sptr->z += fx->pos.zPos;
@ -95,11 +96,11 @@ void DetatchSpark(int num, SpriteEnumFlag type)// (F) (D)
case SP_ITEM: case SP_ITEM:
if (sptr->flags & SP_USEFXOBJPOS) if (sptr->flags & SP_USEFXOBJPOS)
{ {
sptr->on = FALSE; sptr->on = false;
} }
else else
{ {
item = &Items[num]; item = &g_Level.Items[num];
sptr->x += item->pos.xPos; sptr->x += item->pos.xPos;
sptr->y += item->pos.yPos; sptr->y += item->pos.yPos;
sptr->z += item->pos.zPos; sptr->z += item->pos.zPos;
@ -164,14 +165,14 @@ int GetFreeSpark()
void UpdateSparks() void UpdateSparks()
{ {
short* bounds = GetBoundsAccurate(LaraItem); BOUNDING_BOX* bounds = GetBoundsAccurate(LaraItem);
DeadlyBounds[0] = LaraItem->pos.xPos + bounds[0]; DeadlyBounds[0] = LaraItem->pos.xPos + bounds->X1;
DeadlyBounds[1] = LaraItem->pos.xPos + bounds[1]; DeadlyBounds[1] = LaraItem->pos.xPos + bounds->X2;
DeadlyBounds[2] = LaraItem->pos.yPos + bounds[2]; DeadlyBounds[2] = LaraItem->pos.yPos + bounds->Y1;
DeadlyBounds[3] = LaraItem->pos.yPos + bounds[3]; DeadlyBounds[3] = LaraItem->pos.yPos + bounds->Y2;
DeadlyBounds[4] = LaraItem->pos.zPos + bounds[4]; DeadlyBounds[4] = LaraItem->pos.zPos + bounds->Z1;
DeadlyBounds[5] = LaraItem->pos.zPos + bounds[5]; DeadlyBounds[5] = LaraItem->pos.zPos + bounds->Z2;
for (int i = 0; i < MAX_SPARKS; i++) for (int i = 0; i < MAX_SPARKS; i++)
{ {
@ -387,128 +388,6 @@ void UpdateSparks()
void TriggerRicochetSpark(GAME_VECTOR* pos, short angle, int num, int unk) void TriggerRicochetSpark(GAME_VECTOR* pos, short angle, int num, int unk)
{ {
/*int random;
SPARKS* spark;
if (!unk)
{
for (int i = 0; i < num; i++)
{
spark = &Sparks[GetFreeSpark()];
random = GetRandomControl();
spark->on = true;
spark->sR = -128;
spark->sG = (random & 0xF) + 16;
spark->sB = 0;
spark->dR = 96;
spark->dG = ((random >> 4) & 0x1F) + 48;
spark->dB = 0;
spark->colFadeSpeed = 2;
spark->fadeToBlack = 4;
spark->life = 9;
spark->sLife = 9;
spark->transType = COLADD;
spark->x = pos->x;
spark->y = pos->y;
spark->z = pos->z;
short ang = (((random >> 3) & 0x7FF) + angle - WALL_SIZE) & 0xFFF;
spark->xVel = -rcossin_tbl[2 * ang] >> 2;
spark->yVel = (random & 0xFFF) - 2048;
spark->zVel = rcossin_tbl[2 * ang + 1] >> 2;
spark->gravity = (random >> 7) & 0x1F;
spark->friction = 34;
spark->flags = SP_NONE;
spark->maxYvel = 0;
}
spark = &Sparks[GetFreeSpark()];
random = GetRandomControl();
spark->on = true;
spark->sR = 48;
spark->sG = (random & 0xF) + 32;
spark->sB = 0;
spark->dR = 0;
spark->dG = 0;
spark->dB = 0;
spark->colFadeSpeed = 4;
spark->fadeToBlack = 0;
spark->life = 4;
spark->sLife = 4;
spark->transType = COLADD;
spark->x = pos->x;
spark->y = pos->y;
spark->z = pos->z;
spark->xVel = 0;
spark->yVel = 0;
spark->zVel = 0;
spark->flags = 26;
spark->rotAng = (random >> 2) & 0xFFF;
if (random & 1)
spark->rotAdd = -64 - ((random >> 1) & 0x3F);
else
spark->rotAdd = ((random >> 1) & 0x3F) + 64;
spark->scalar = 3;
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 12;
spark->sSize = spark->size = ((random >> 10) & 7) + 8;
spark->dSize = 1;
spark->maxYvel = 0;
spark->gravity = 0;
}
if (1 - unk > 0)
{
num = (1 - unk);
for (int i = 0; i < num; i++)
{
spark = &Sparks[GetFreeSpark()];
int random = GetRandomControl();
spark->on = true;
spark->sR = 0;
spark->sG = 0;
spark->sB = 0;
spark->dR = 40;
spark->dG = 40;
spark->dB = 40;
spark->colFadeSpeed = (random & 3) + 4;
spark->fadeToBlack = 8;
spark->life =spark->sLife= ((random >> 2) & 7) + 16;
spark->x = pos->x;
spark->y = pos->y;
spark->z = pos->z;
if (unk)
{
spark->colFadeSpeed >>= 1;
spark->fadeToBlack = 4;
spark->sLife >>= 1;
spark->life >>= 1;
spark->xVel = (random & 0x1FF) - 256;
spark->yVel = ((random >> 2) & 0x1FF) - 256;
spark->zVel = ((random >> 4) & 0x1FF) - 256;
}
else
{
spark->yVel = 0;
spark->xVel = 0;
spark->zVel = 0;
}
spark->transType = COLADD;
spark->friction = 0;
spark->flags = 26;
spark->rotAng = random >> 3;
if (random & 1)
spark->rotAdd = -random - (random & 0xF);
else
spark->rotAdd = (random & 0xF) + 16;
spark->scalar = 2;
spark->gravity = -4 - ((random >> 9) & 3);
spark->sSize = spark->size= ((random >> 5) & 7) + 4;
spark->maxYvel = -4 - ((random >> 6) & 3);
spark->dSize = spark->size;
}
}*/
TriggerRicochetSpark(pos, angle, num); TriggerRicochetSpark(pos, angle, num);
} }
@ -552,137 +431,7 @@ void TriggerCyborgSpark(int x, int y, int z, short xv, short yv, short zv)
void TriggerExplosionSparks(int x, int y, int z, int extraTrig, int dynamic, int uw, int roomNumber) void TriggerExplosionSparks(int x, int y, int z, int extraTrig, int dynamic, int uw, int roomNumber)
{ {
/*int shift = 0;
if ((roomNumber & 0x8000) != 0)
{
//v7 = -roomNumber;
roomNumber = -roomNumber;
shift = 1;
}
/ *if (v7 == gfMirrorRoom && gfLevelFlags & 0x2000)
v27 = 1;
z_bis = z;
do
{* /
SPARKS* spark = &Sparks[GetFreeSpark()];
spark->on = 1;
spark->sR = -1;
if (uw == 1)
{
spark->sB = 32;
spark->dR = -64;
spark->sG = (GetRandomControl() & 0x3F) + -128;
spark->dB = 0;
spark->colFadeSpeed = 7;
spark->dG = (GetRandomControl() & 0x1F) + 64;
spark->fadeToBlack = 8;
spark->transType = COLADD;
spark->life = spark->sLife = (GetRandomControl() & 7) + 16;
spark->roomNumber = roomNumber;
}
else
{
spark->sB = 0;
spark->sG = (GetRandomControl() & 0xF) + 32;
spark->dR = (GetRandomControl() & 0x3F) - 64;
spark->dB = 32;
spark->colFadeSpeed = 8;
spark->dG = (GetRandomControl() & 0x3F) + -128;
spark->fadeToBlack = 16;
spark->transType = COLADD;
spark->life = spark->sLife = (GetRandomControl() & 7) + 24;
}
spark->extras = extraTrig | 8 * (TES_extra_tab[extraTrig] + (GetRandomControl() & 7) + 28);
spark->dynamic = dynamic;
if (dynamic == -2)
{
int j;
for (j = 0; j < 8; j++)
{
SP_DYNAMIC* spdyn = &SparkDynamics[j];
if (!spdyn->On)
{
spdyn->On = 1;
spdyn->Falloff = 4;
if (uw == 1)
spdyn->Flags = SD_UWEXPLOSION;
else
spdyn->Flags = SD_EXPLOSION;
spark->dynamic = j;
break;
}
}
if (j == 8)
{
spark->dynamic = -1;
}
}
spark->xVel = (GetRandomControl() & 0xFFF) - 2048;
spark->yVel = (GetRandomControl() & 0xFFF) - 2048;
spark->zVel = (GetRandomControl() & 0xFFF) - 2048;
if (dynamic != -2 || uw == 1)
{
spark->x = (GetRandomControl() & 0x1F) + x - 16;
spark->y = (GetRandomControl() & 0x1F) + y - 16;
spark->z = (GetRandomControl() & 0x1F) + z - 16;
}
else
{
spark->x = (GetRandomControl() & 0x1FF) + x - 256;
spark->y = (GetRandomControl() & 0x1FF) + y - 256;
spark->z = (GetRandomControl() & 0x1FF) + z - 256;
}
if (uw == 1)
spark->friction = 17;
else
spark->friction = 51;
if (GetRandomControl() & 1)
{
if (uw == 1)
spark->flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF | SP_UNDERWEXP;
else
spark->flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
spark->rotAng = GetRandomControl() & 0xFFF;
spark->rotAdd = GetRandomControl() + -128;
}
else if (uw == 1)
{
spark->flags = SP_SCALE | SP_DEF | SP_EXPDEF | SP_UNDERWEXP;
}
else
{
spark->flags = SP_SCALE | SP_DEF | SP_EXPDEF;
}
spark->scalar = 3;
spark->gravity = 0;
int size = (GetRandomControl() & 0xF) + 40;
spark->maxYvel = 0;
spark->sSize = size << shift;
spark->size = size << shift;
spark->dSize = size << (shift + 1);
if (uw == 2)
{
spark->sG = spark->sR;
spark->sB = spark->sG;
spark->flags |= SP_PLASMAEXP;
spark->sR = spark->sB;
spark->dR = spark->dB;
spark->dG = spark->dR;
spark->dB = spark->dG;
}
else if (extraTrig)
{
TriggerExplosionSmoke(x, y, z, uw);
}
else
{
TriggerExplosionSmokeEnd(x, y, z, uw);
}*/
TriggerExplosion(Vector3(x, y, z), 512, true, false, true, roomNumber); TriggerExplosion(Vector3(x, y, z), 512, true, false, true, roomNumber);
//} while (!v24);
} }
void TriggerExplosionSmokeEnd(int x, int y, int z, int uw) void TriggerExplosionSmokeEnd(int x, int y, int z, int uw)
@ -1414,7 +1163,7 @@ void KillAllCurrentItems(short itemNumber)
void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b) void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b)
{ {
g_Renderer->AddDynamicLight(x, y, z, falloff, r, g, b); g_Renderer.AddDynamicLight(x, y, z, falloff, r, g, b);
} }
// Really needed? // Really needed?
@ -1431,27 +1180,27 @@ void WadeSplash(ITEM_INFO* item, int wh, int wd)
short roomNumber = item->roomNumber; short roomNumber = item->roomNumber;
GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
ROOM_INFO* room = &Rooms[roomNumber]; ROOM_INFO* room = &g_Level.Rooms[roomNumber];
if (room->flags & ENV_FLAG_WATER) if (room->flags & ENV_FLAG_WATER)
{ {
short roomNumber2 = item->roomNumber; short roomNumber2 = item->roomNumber;
GetFloor(item->pos.xPos, room->y - 128, item->pos.zPos, &roomNumber2); GetFloor(item->pos.xPos, room->y - 128, item->pos.zPos, &roomNumber2);
ROOM_INFO* room2 = &Rooms[roomNumber2]; ROOM_INFO* room2 = &g_Level.Rooms[roomNumber2];
if (!(room2->flags & ENV_FLAG_WATER)) if (!(room2->flags & ENV_FLAG_WATER))
{ {
short* frame = GetBestFrame(item); ANIM_FRAME* frame = GetBestFrame(item);
if (item->pos.yPos + frame[2] <= wh) if (item->pos.yPos + frame->boundingBox.Y1 <= wh)
{ {
if (item->pos.yPos + frame[3] >= wh) if (item->pos.yPos + frame->boundingBox.Y2 >= wh)
{ {
if (item->fallspeed <= 0 || wd >= 474 || SplashCount != 0) if (item->fallspeed <= 0 || wd >= 474 || SplashCount != 0)
{ {
if (!(Wibble & 0xF)) if (!(Wibble & 0xF))
{ {
if (!(GetRandomControl() & 0xF) || item->currentAnimState != STATE_LARA_STOP) if (!(GetRandomControl() & 0xF) || item->currentAnimState != LS_STOP)
{ {
if (item->currentAnimState == STATE_LARA_STOP) if (item->currentAnimState == LS_STOP)
{ {
SetupRipple(item->pos.xPos, wh, item->pos.zPos, (GetRandomControl() & 0xF) + 112, RIPPLE_FLAG_RAND_ROT | RIPPLE_FLAG_RAND_POS); SetupRipple(item->pos.xPos, wh, item->pos.zPos, (GetRandomControl() & 0xF) + 112, RIPPLE_FLAG_RAND_ROT | RIPPLE_FLAG_RAND_POS);
} }
@ -1483,7 +1232,7 @@ void Splash(ITEM_INFO* item)
short roomNumber = item->roomNumber; short roomNumber = item->roomNumber;
GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
ROOM_INFO* room = &Rooms[roomNumber]; ROOM_INFO* room = &g_Level.Rooms[roomNumber];
if (room->flags & ENV_FLAG_WATER) if (room->flags & ENV_FLAG_WATER)
{ {
int wh = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, roomNumber); int wh = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, roomNumber);
@ -1604,7 +1353,7 @@ void TriggerRocketSmoke(int x, int y, int z, int bodyPart)
void GrenadeExplosionEffects(int x, int y, int z, short roomNumber) void GrenadeExplosionEffects(int x, int y, int z, short roomNumber)
{ {
ROOM_INFO* room = &Rooms[roomNumber]; ROOM_INFO* room = &g_Level.Rooms[roomNumber];
bool mirror = (roomNumber == g_GameFlow->GetLevel(CurrentLevel)->Mirror.Room); bool mirror = (roomNumber == g_GameFlow->GetLevel(CurrentLevel)->Mirror.Room);
@ -1867,30 +1616,6 @@ void GrenadeLauncherSpecialEffect1(int x, int y, int z, int flag1, int flag2)
return; return;
} }
/*if (flag2 && flag2 != 1)
{
if (flag2 < -2)
{
spark->y = y;
spark->x = (GetRandomControl() & 0xF) + x - 8;
spark->z = (GetRandomControl() & 0xF) + z - 8;
}
else
{
spark->x = (GetRandomControl() & 0x3F) + x - 32;
spark->y = y;
spark->z = (GetRandomControl() & 0x3F) + z - 32;
}
}
else
{
spark->y = y;
spark->x = (GetRandomControl() & 0x1F) + x - 16;
spark->z = (GetRandomControl() & 0x1F) + z - 16;
}
goto LABEL_POS_1;*/
} }
} }

View file

@ -15,10 +15,7 @@
#include "sound.h" #include "sound.h"
#include "snowmobile.h" #include "snowmobile.h"
short FireBounds[12] = extern OBJECT_COLLISION_BOUNDS FireBounds;
{
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C
};
void TriggerTorchFlame(char fxObj, char node) void TriggerTorchFlame(char fxObj, char node)
{ {
@ -72,12 +69,12 @@ void DoFlameTorch() // (F) (D)
if (TrInput & IN_DRAW if (TrInput & IN_DRAW
&& !(LaraItem->gravityStatus) && !(LaraItem->gravityStatus)
&& !LaraItem->fallspeed && !LaraItem->fallspeed
&& LaraItem->currentAnimState != STATE_LARA_JUMP_PREPARE && LaraItem->currentAnimState != LS_JUMP_PREPARE
&& LaraItem->currentAnimState != STATE_LARA_JUMP_UP && LaraItem->currentAnimState != LS_JUMP_UP
&& LaraItem->currentAnimState != STATE_LARA_JUMP_FORWARD && LaraItem->currentAnimState != LS_JUMP_FORWARD
&& LaraItem->currentAnimState != STATE_LARA_JUMP_BACK && LaraItem->currentAnimState != LS_JUMP_BACK
&& LaraItem->currentAnimState != STATE_LARA_JUMP_LEFT && LaraItem->currentAnimState != LS_JUMP_LEFT
&& LaraItem->currentAnimState != STATE_LARA_JUMP_RIGHT && LaraItem->currentAnimState != LS_JUMP_RIGHT
|| Lara.waterStatus == LW_UNDERWATER) || Lara.waterStatus == LW_UNDERWATER)
{ {
Lara.leftArm.lock = true; Lara.leftArm.lock = true;
@ -110,7 +107,7 @@ void DoFlameTorch() // (F) (D)
} }
else if (Lara.leftArm.frameNumber == 12) else if (Lara.leftArm.frameNumber == 12)
{ {
LARA_MESHES(ID_LARA, LM_LHAND); Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND;
CreateFlare(ID_BURNING_TORCH_ITEM, 1); CreateFlare(ID_BURNING_TORCH_ITEM, 1);
} }
} }
@ -130,12 +127,12 @@ void DoFlameTorch() // (F) (D)
} }
else if (Lara.leftArm.frameNumber == 36) else if (Lara.leftArm.frameNumber == 36)
{ {
LARA_MESHES(ID_LARA, LM_LHAND); Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND;
CreateFlare(ID_BURNING_TORCH_ITEM, 0); CreateFlare(ID_BURNING_TORCH_ITEM, 0);
} }
break; break;
case 3: case 3:
if (LaraItem->currentAnimState != STATE_LARA_MISC_CONTROL) if (LaraItem->currentAnimState != LS_MISC_CONTROL)
{ {
Lara.leftArm.lock = false; Lara.leftArm.lock = false;
Lara.leftArm.frameNumber = 0; Lara.leftArm.frameNumber = 0;
@ -151,7 +148,7 @@ void DoFlameTorch() // (F) (D)
if (Lara.flareControlLeft) if (Lara.flareControlLeft)
Lara.gunStatus = LG_READY; Lara.gunStatus = LG_READY;
Lara.leftArm.frameBase = Anims[Lara.leftArm.animNumber].framePtr; Lara.leftArm.frameBase = g_Level.Anims[Lara.leftArm.animNumber].framePtr;
if (Lara.litTorch) if (Lara.litTorch)
{ {
@ -166,7 +163,7 @@ void DoFlameTorch() // (F) (D)
TriggerDynamicLight(pos.x, pos.y, pos.z, 12 - (GetRandomControl() & 1), (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 96, 0); TriggerDynamicLight(pos.x, pos.y, pos.z, 12 - (GetRandomControl() & 1), (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 96, 0);
if (!(Wibble & 7)) if (!(Wibble & 7))
TriggerTorchFlame(LaraItem - Items, 0); TriggerTorchFlame(LaraItem - g_Level.Items.data(), 0);
SoundEffect(SFX_LOOP_FOR_SMALL_FIRES, (PHD_3DPOS*)&pos, 0); SoundEffect(SFX_LOOP_FOR_SMALL_FIRES, (PHD_3DPOS*)&pos, 0);
@ -186,13 +183,14 @@ void GetFlameTorch() // (F) (D)
Lara.gunStatus = LG_READY; Lara.gunStatus = LG_READY;
Lara.leftArm.lock = false; Lara.leftArm.lock = false;
Lara.leftArm.frameNumber = 0; Lara.leftArm.frameNumber = 0;
Lara.leftArm.frameBase = Anims[Lara.leftArm.animNumber].framePtr; Lara.leftArm.frameBase = g_Level.Anims[Lara.leftArm.animNumber].framePtr;
LARA_MESHES(ID_LARA_TORCH_ANIM, LM_LHAND);
Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_TORCH_ANIM].meshIndex + LM_LHAND;
} }
void TorchControl(short itemNumber) // (F) (D) void TorchControl(short itemNumber) // (F) (D)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
int oldX = item->pos.xPos; int oldX = item->pos.xPos;
int oldY = item->pos.yPos; int oldY = item->pos.yPos;
@ -212,7 +210,7 @@ void TorchControl(short itemNumber) // (F) (D)
item->pos.xPos += xv; item->pos.xPos += xv;
item->pos.zPos += zv; item->pos.zPos += zv;
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
item->fallspeed += (5 - item->fallspeed) / 2; item->fallspeed += (5 - item->fallspeed) / 2;
item->speed += (5 - item->speed) / 2; item->speed += (5 - item->speed) / 2;
@ -233,17 +231,17 @@ void TorchControl(short itemNumber) // (F) (D)
if (CollidedItems) if (CollidedItems)
{ {
if (!Objects[CollidedItems[0]->objectNumber].intelligent) if (!Objects[CollidedItems[0]->objectNumber].intelligent)
ObjectCollision(CollidedItems[0] - Items, item, &lara_coll); ObjectCollision(CollidedItems[0] - g_Level.Items.data(), item, &lara_coll);
} }
else else
{ {
StaticInfo* sobj = &StaticObjects[CollidedMeshes[0]->staticNumber]; STATIC_INFO* sobj = &StaticObjects[CollidedMeshes[0]->staticNumber];
PHD_3DPOS pos; PHD_3DPOS pos;
pos.xPos = CollidedMeshes[0]->x; pos.xPos = CollidedMeshes[0]->x;
pos.yPos = CollidedMeshes[0]->y; pos.yPos = CollidedMeshes[0]->y;
pos.zPos = CollidedMeshes[0]->z; pos.zPos = CollidedMeshes[0]->z;
pos.yRot = CollidedMeshes[0]->yRot; pos.yRot = CollidedMeshes[0]->yRot;
ItemPushLaraStatic(item, &sobj->xMinc, &pos, &lara_coll); ItemPushLaraStatic(item, &sobj->collisionBox, &pos, &lara_coll);
} }
item->speed >>= 1; item->speed >>= 1;
} }
@ -259,7 +257,7 @@ void TorchControl(short itemNumber) // (F) (D)
void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (Lara.gunType != WEAPON_TORCH if (Lara.gunType != WEAPON_TORCH
|| Lara.gunStatus != LG_READY || Lara.gunStatus != LG_READY
@ -267,8 +265,8 @@ void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
|| Lara.litTorch == (item->status == ITEM_ACTIVE) || Lara.litTorch == (item->status == ITEM_ACTIVE)
|| item->timer == -1 || item->timer == -1
|| !(TrInput & IN_ACTION) || !(TrInput & IN_ACTION)
|| l->currentAnimState != STATE_LARA_STOP || l->currentAnimState != LS_STOP
|| l->animNumber != ANIMATION_LARA_STAY_IDLE || l->animNumber != LA_STAND_IDLE
|| l->gravityStatus) || l->gravityStatus)
{ {
if (item->objectNumber == ID_BURNING_ROOTS) if (item->objectNumber == ID_BURNING_ROOTS)
@ -281,47 +279,47 @@ void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
switch (item->objectNumber) switch (item->objectNumber)
{ {
case ID_FLAME_EMITTER: case ID_FLAME_EMITTER:
FireBounds[0] = -256; FireBounds.boundingBox.X1 = -256;
FireBounds[1] = 256; FireBounds.boundingBox.X2 = 256;
FireBounds[2] = 0; FireBounds.boundingBox.Y1 = 0;
FireBounds[3] = 1024; FireBounds.boundingBox.Y2 = 1024;
FireBounds[4] = -800; FireBounds.boundingBox.Z1 = -800;
FireBounds[5] = 800; FireBounds.boundingBox.Z2 = 800;
break; break;
case ID_FLAME_EMITTER2: case ID_FLAME_EMITTER2:
FireBounds[1] = -256; FireBounds.boundingBox.X1 = -256;
FireBounds[2] = 256; FireBounds.boundingBox.X2 = 256;
FireBounds[3] = 0; FireBounds.boundingBox.Y1 = 0;
FireBounds[4] = 1024; FireBounds.boundingBox.Y2 = 1024;
FireBounds[5] = -600; FireBounds.boundingBox.Z1 = -600;
FireBounds[6] = 600; FireBounds.boundingBox.Z2 = 600;
break; break;
case ID_BURNING_ROOTS: case ID_BURNING_ROOTS:
FireBounds[0] = -384; FireBounds.boundingBox.X1 = -384;
FireBounds[1] = 384; FireBounds.boundingBox.X2 = 384;
FireBounds[2] = 0; FireBounds.boundingBox.Y1 = 0;
FireBounds[3] = 2048; FireBounds.boundingBox.Y2 = 2048;
FireBounds[4] = -384; FireBounds.boundingBox.Z1 = -384;
FireBounds[5] = 384; FireBounds.boundingBox.Z2 = 384;
break; break;
} }
item->pos.yRot = l->pos.yRot; item->pos.yRot = l->pos.yRot;
if (TestLaraPosition(FireBounds, item, l)) if (TestLaraPosition(&FireBounds, item, l))
{ {
if (item->objectNumber == ID_BURNING_ROOTS) if (item->objectNumber == ID_BURNING_ROOTS)
{ {
l->animNumber = ANIMATION_LARA_TORCH_LIGHT_5; l->animNumber = LA_TORCH_LIGHT_5;
} }
else else
{ {
int dy = abs(l->pos.yPos - item->pos.yPos); int dy = abs(l->pos.yPos - item->pos.yPos);
l->itemFlags[3] = 1; l->itemFlags[3] = 1;
l->animNumber = (dy >> 8) + ANIMATION_LARA_TORCH_LIGHT_1; l->animNumber = (dy >> 8) + LA_TORCH_LIGHT_1;
} }
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
Lara.flareControlLeft = false; Lara.flareControlLeft = false;
Lara.leftArm.lock = 3; Lara.leftArm.lock = 3;
Lara.generalPtr = (void*)itemNumber; Lara.generalPtr = (void*)itemNumber;
@ -329,11 +327,11 @@ void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
item->pos.yRot = rot; item->pos.yRot = rot;
} }
if ((short)Lara.generalPtr == itemNumber && item->status != ITEM_ACTIVE && l->currentAnimState == STATE_LARA_MISC_CONTROL) if ((short)Lara.generalPtr == itemNumber && item->status != ITEM_ACTIVE && l->currentAnimState == LS_MISC_CONTROL)
{ {
if (l->animNumber >= ANIMATION_LARA_TORCH_LIGHT_1 && l->animNumber <= ANIMATION_LARA_TORCH_LIGHT_5) if (l->animNumber >= LA_TORCH_LIGHT_1 && l->animNumber <= LA_TORCH_LIGHT_5)
{ {
if (l->frameNumber - Anims[l->animNumber].frameBase == 40) if (l->frameNumber - g_Level.Anims[l->animNumber].frameBase == 40)
{ {
TestTriggersAtXYZ(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 1, item->flags & 0x3E00); TestTriggersAtXYZ(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 1, item->flags & 0x3E00);
item->flags |= 0x3E00; item->flags |= 0x3E00;

View file

@ -9,9 +9,9 @@
#include "setup.h" #include "setup.h"
#include "sphere.h" #include "sphere.h"
#include "level.h" #include "level.h"
using T5M::Renderer::g_Renderer;
int FirstHair[HAIR_MAX]; int FirstHair[HAIR_MAX];
HAIR_STRUCT Hairs[HAIR_MAX][HAIR_SEGMENTS]; HAIR_STRUCT Hairs[HAIR_MAX][HAIR_SEGMENTS + 1];
int WindAngle; int WindAngle;
int DWindAngle; int DWindAngle;
int Wind; int Wind;
@ -24,12 +24,12 @@ void InitialiseHair()
{ {
FirstHair[h] = 1; FirstHair[h] = 1;
int* bone = &Bones[Objects[ID_LARA_HAIR].boneIndex]; int* bone = &g_Level.Bones[Objects[ID_LARA_HAIR].boneIndex];
Hairs[h][0].pos.yRot = 0; Hairs[h][0].pos.yRot = 0;
Hairs[h][0].pos.xRot = -0x4000; Hairs[h][0].pos.xRot = -0x4000;
for (int i = 1; i < HAIR_SEGMENTS; i++, bone += 4) for (int i = 1; i < HAIR_SEGMENTS + 1; i++, bone += 4)
{ {
Hairs[h][i].pos.xPos = *(bone + 1); Hairs[h][i].pos.xPos = *(bone + 1);
Hairs[h][i].pos.yPos = *(bone + 2); Hairs[h][i].pos.yPos = *(bone + 2);
@ -43,11 +43,11 @@ void InitialiseHair()
} }
void HairControl(int cutscene, int ponytail, short* framePtr) void HairControl(int cutscene, int ponytail, ANIM_FRAME* framePtr)
{ {
SPHERE sphere[HAIR_SPHERE]; SPHERE sphere[HAIR_SPHERE];
ObjectInfo* object = &Objects[ID_LARA]; OBJECT_INFO* object = &Objects[ID_LARA];
short* frame; ANIM_FRAME* frame;
int spaz; int spaz;
bool youngLara = g_GameFlow->GetLevel(CurrentLevel)->LaraType == LARA_YOUNG; bool youngLara = g_GameFlow->GetLevel(CurrentLevel)->LaraType == LARA_YOUNG;
@ -86,10 +86,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
break; break;
} }
frame = Anims[spaz].framePtr; frame = &g_Level.Frames[g_Level.Anims[spaz].framePtr + Lara.hitFrame];
int size = Anims[spaz].interpolation >> 8;
frame += (int)(Lara.hitFrame * size);
} }
else else
frame = GetBestFrame(LaraItem); frame = GetBestFrame(LaraItem);
@ -100,47 +97,47 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
} }
// Get Lara's spheres in absolute coords, for head, torso, hips and upper arms // Get Lara's spheres in absolute coords, for head, torso, hips and upper arms
short* objptr = Lara.meshPtrs[LM_HIPS]; MESH* mesh = &g_Level.Meshes[Lara.meshPtrs[LM_HIPS]];
PHD_VECTOR pos = { objptr[0], objptr[1], objptr[2] }; PHD_VECTOR pos = { (int)mesh->sphere.Center.x, (int)mesh->sphere.Center.y, (int)mesh->sphere.Center.z };
GetLaraJointPosition(&pos, LM_HIPS); GetLaraJointPosition(&pos, LM_HIPS);
sphere[0].x = pos.x; sphere[0].x = pos.x;
sphere[0].y = pos.y; sphere[0].y = pos.y;
sphere[0].z = pos.z; sphere[0].z = pos.z;
sphere[0].r = (int) * (objptr + 3); sphere[0].r = (int)mesh->sphere.Radius;
objptr = Lara.meshPtrs[LM_TORSO]; mesh = &g_Level.Meshes[Lara.meshPtrs[LM_TORSO]];
pos = { objptr[0], objptr[1], objptr[2] }; pos = { (int)mesh->sphere.Center.x, (int)mesh->sphere.Center.y, (int)mesh->sphere.Center.z };
GetLaraJointPosition(&pos, LM_TORSO); GetLaraJointPosition(&pos, LM_TORSO);
sphere[1].x = pos.x; sphere[1].x = pos.x;
sphere[1].y = pos.y; sphere[1].y = pos.y;
sphere[1].z = pos.z; sphere[1].z = pos.z;
sphere[1].r = (int) * (objptr + 3); sphere[1].r = (int)mesh->sphere.Radius;
if (youngLara) if (youngLara)
sphere[1].r = sphere[1].r - ((sphere[1].r >> 2) + (sphere[1].r >> 3)); sphere[1].r = sphere[1].r - ((sphere[1].r >> 2) + (sphere[1].r >> 3));
objptr = Lara.meshPtrs[LM_HEAD]; mesh = &g_Level.Meshes[Lara.meshPtrs[LM_HEAD]];
pos = { objptr[0], objptr[1], objptr[2] }; pos = { (int)mesh->sphere.Center.x, (int)mesh->sphere.Center.y, (int)mesh->sphere.Center.z };
GetLaraJointPosition(&pos, LM_HEAD); GetLaraJointPosition(&pos, LM_HEAD);
sphere[2].x = pos.x; sphere[2].x = pos.x;
sphere[2].y = pos.y; sphere[2].y = pos.y;
sphere[2].z = pos.z; sphere[2].z = pos.z;
sphere[2].r = (int) * (objptr + 3); sphere[2].r = (int)mesh->sphere.Radius;
objptr = Lara.meshPtrs[LM_RINARM]; mesh = &g_Level.Meshes[Lara.meshPtrs[LM_RINARM]];
pos = { objptr[0], objptr[1], objptr[2] }; pos = { (int)mesh->sphere.Center.x, (int)mesh->sphere.Center.y, (int)mesh->sphere.Center.z };
GetLaraJointPosition(&pos, LM_RINARM); GetLaraJointPosition(&pos, LM_RINARM);
sphere[3].x = pos.x; sphere[3].x = pos.x;
sphere[3].y = pos.y; sphere[3].y = pos.y;
sphere[3].z = pos.z; sphere[3].z = pos.z;
sphere[3].r = (int) * (objptr + 3) * 3 / 2; sphere[3].r = (int)mesh->sphere.Radius * 3 / 2;
objptr = Lara.meshPtrs[LM_LINARM]; mesh = &g_Level.Meshes[Lara.meshPtrs[LM_LINARM]];
pos = { objptr[0], objptr[1], objptr[2] }; pos = { (int)mesh->sphere.Center.x, (int)mesh->sphere.Center.y, (int)mesh->sphere.Center.z };
GetLaraJointPosition(&pos, LM_LINARM); GetLaraJointPosition(&pos, LM_LINARM);
sphere[4].x = pos.x; sphere[4].x = pos.x;
sphere[4].y = pos.y; sphere[4].y = pos.y;
sphere[4].z = pos.z; sphere[4].z = pos.z;
sphere[4].r = (int) * (objptr + 3) * 3 / 2; sphere[4].r = (int)mesh->sphere.Radius * 3 / 2;
if (youngLara) if (youngLara)
{ {
@ -150,7 +147,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
} }
Matrix world; Matrix world;
g_Renderer->GetBoneMatrix(Lara.itemNumber, LM_HEAD, &world); g_Renderer.GetBoneMatrix(Lara.itemNumber, LM_HEAD, &world);
if (ponytail) if (ponytail)
{ {
@ -169,7 +166,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
pos.y = world.Translation().y; pos.y = world.Translation().y;
pos.z = world.Translation().z; pos.z = world.Translation().z;
int* bone = &Bones[Objects[ID_LARA_HAIR].boneIndex]; int* bone = &g_Level.Bones[Objects[ID_LARA_HAIR].boneIndex];
if (FirstHair[ponytail]) if (FirstHair[ponytail])
{ {
@ -179,7 +176,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
Hairs[ponytail][0].pos.yPos = pos.y; Hairs[ponytail][0].pos.yPos = pos.y;
Hairs[ponytail][0].pos.zPos = pos.z; Hairs[ponytail][0].pos.zPos = pos.z;
for (int i = 0; i < HAIR_SEGMENTS - 1; i++, bone += 4) for (int i = 0; i < HAIR_SEGMENTS; i++, bone += 4)
{ {
world = Matrix::CreateTranslation(Hairs[ponytail][i].pos.xPos, Hairs[ponytail][i].pos.yPos, Hairs[ponytail][i].pos.zPos); world = Matrix::CreateTranslation(Hairs[ponytail][i].pos.xPos, Hairs[ponytail][i].pos.yPos, Hairs[ponytail][i].pos.zPos);
world = Matrix::CreateFromYawPitchRoll(TO_RAD(Hairs[ponytail][i].pos.yRot), TO_RAD(Hairs[ponytail][i].pos.xRot), 0) * world; world = Matrix::CreateFromYawPitchRoll(TO_RAD(Hairs[ponytail][i].pos.yRot), TO_RAD(Hairs[ponytail][i].pos.xRot), 0) * world;
@ -208,9 +205,9 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
} }
else else
{ {
int x = LaraItem->pos.xPos + (frame[0] + frame[1]) / 2; int x = LaraItem->pos.xPos + (frame->boundingBox.X1 + frame->boundingBox.X2) / 2;
int y = LaraItem->pos.yPos + (frame[2] + frame[3]) / 2; int y = LaraItem->pos.yPos + (frame->boundingBox.Y1 + frame->boundingBox.Y2) / 2;
int z = LaraItem->pos.zPos + (frame[4] + frame[5]) / 2; int z = LaraItem->pos.zPos + (frame->boundingBox.Z1 + frame->boundingBox.Z2) / 2;
wh = GetWaterHeight(x, y, z, roomNumber); wh = GetWaterHeight(x, y, z, roomNumber);
} }
@ -235,7 +232,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
SmokeWindX = (((rcossin_tbl[WindAngle]) * Wind) >> 12); SmokeWindX = (((rcossin_tbl[WindAngle]) * Wind) >> 12);
SmokeWindZ = (((rcossin_tbl[WindAngle + 1]) * Wind) >> 12); SmokeWindZ = (((rcossin_tbl[WindAngle + 1]) * Wind) >> 12);
for (int i = 1; i < HAIR_SEGMENTS; i++, bone += 4) for (int i = 1; i < HAIR_SEGMENTS + 1; i++, bone += 4)
{ {
Hairs[ponytail][0].hvel.x = Hairs[ponytail][i].pos.xPos; Hairs[ponytail][0].hvel.x = Hairs[ponytail][i].pos.xPos;
Hairs[ponytail][0].hvel.y = Hairs[ponytail][i].pos.yPos; Hairs[ponytail][0].hvel.y = Hairs[ponytail][i].pos.yPos;
@ -257,7 +254,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
Hairs[ponytail][i].pos.yPos += Hairs[ponytail][i].hvel.y * 3 / 4; Hairs[ponytail][i].pos.yPos += Hairs[ponytail][i].hvel.y * 3 / 4;
Hairs[ponytail][i].pos.zPos += Hairs[ponytail][i].hvel.z * 3 / 4; Hairs[ponytail][i].pos.zPos += Hairs[ponytail][i].hvel.z * 3 / 4;
if (Lara.waterStatus == LW_ABOVE_WATER && Rooms[roomNumber].flags & ENV_FLAG_WIND) if (Lara.waterStatus == LW_ABOVE_WATER && g_Level.Rooms[roomNumber].flags & ENV_FLAG_WIND)
{ {
Hairs[ponytail][i].pos.xPos += SmokeWindX; Hairs[ponytail][i].pos.xPos += SmokeWindX;
Hairs[ponytail][i].pos.zPos += SmokeWindZ; Hairs[ponytail][i].pos.zPos += SmokeWindZ;
@ -316,7 +313,7 @@ void HairControl(int cutscene, int ponytail, short* framePtr)
world = Matrix::CreateTranslation(Hairs[ponytail][i - 1].pos.xPos, Hairs[ponytail][i - 1].pos.yPos, Hairs[ponytail][i - 1].pos.zPos); world = Matrix::CreateTranslation(Hairs[ponytail][i - 1].pos.xPos, Hairs[ponytail][i - 1].pos.yPos, Hairs[ponytail][i - 1].pos.zPos);
world = Matrix::CreateFromYawPitchRoll(TO_RAD(Hairs[ponytail][i - 1].pos.yRot), TO_RAD(Hairs[ponytail][i - 1].pos.xRot), 0) * world; world = Matrix::CreateFromYawPitchRoll(TO_RAD(Hairs[ponytail][i - 1].pos.yRot), TO_RAD(Hairs[ponytail][i - 1].pos.xRot), 0) * world;
if (i == HAIR_SEGMENTS - 1) if (i == HAIR_SEGMENTS)
world = Matrix::CreateTranslation(*(bone - 3), *(bone - 2), *(bone - 1)) * world; world = Matrix::CreateTranslation(*(bone - 3), *(bone - 2), *(bone - 1)) * world;
else else
world = Matrix::CreateTranslation(*(bone + 1), *(bone + 2), *(bone + 3)) * world; world = Matrix::CreateTranslation(*(bone + 1), *(bone + 2), *(bone + 3)) * world;

View file

@ -3,16 +3,18 @@
#include "phd_global.h" #include "phd_global.h"
constexpr auto HAIR_MAX = 2; // HAIR_NORMAL = 0, HAIR_YOUNG = 1 constexpr auto HAIR_MAX = 2; // HAIR_NORMAL = 0, HAIR_YOUNG = 1
constexpr auto HAIR_SEGMENTS = 7; // classic = 7, young = 14 constexpr auto HAIR_SEGMENTS = 6; // classic = 7, young = 14
constexpr auto HAIR_SPHERE = 5; // current hair max collision constexpr auto HAIR_SPHERE = 5; // current hair max collision
struct ANIM_FRAME;
struct HAIR_STRUCT struct HAIR_STRUCT
{ {
PHD_3DPOS pos; PHD_3DPOS pos;
PHD_VECTOR hvel; PHD_VECTOR hvel;
PHD_VECTOR unknown; PHD_VECTOR unknown;
}; };
extern HAIR_STRUCT Hairs[HAIR_MAX][HAIR_SEGMENTS]; extern HAIR_STRUCT Hairs[HAIR_MAX][HAIR_SEGMENTS + 1];
void InitialiseHair(); void InitialiseHair();
void HairControl(int cutscene, int ponytail, short* framePtr); void HairControl(int cutscene, int ponytail, ANIM_FRAME* framePtr);

View file

@ -7,13 +7,16 @@
#include "level.h" #include "level.h"
#include "control.h" #include "control.h"
using namespace T5M::Renderer;
short PickupX; short PickupX;
short PickupY; short PickupY;
short CurrentPickup; short CurrentPickup;
DISPLAY_PICKUP Pickups[MAX_COLLECTED_PICKUPS]; DISPLAY_PICKUP Pickups[MAX_COLLECTED_PICKUPS];
short PickupVel; short PickupVel;
int OldHitPoints = 1000; int OldHitPoints = 1000;
int HealtBarTimer = 40; int HealthBarTimer = 40;
float HealthBar = OldHitPoints;
float MutateAmount = 0;
int FlashState = 0; int FlashState = 0;
int FlashCount = 0; int FlashCount = 0;
int PoisonFlag = 0; int PoisonFlag = 0;
@ -22,6 +25,8 @@ extern RendererHUDBar* g_HealthBar;
extern RendererHUDBar* g_DashBar; extern RendererHUDBar* g_DashBar;
extern RendererHUDBar* g_AirBar; extern RendererHUDBar* g_AirBar;
bool EnableSmoothHealthBar = true;
void DrawHealthBarOverlay(int value) void DrawHealthBarOverlay(int value)
{ {
if (CurrentLevel) if (CurrentLevel)
@ -31,7 +36,7 @@ void DrawHealthBarOverlay(int value)
color2 = 0xA0A000; color2 = 0xA0A000;
else else
color2 = 0xA00000; color2 = 0xA00000;
g_Renderer->DrawBar(value, g_HealthBar); g_Renderer.DrawBar(value, ::g_HealthBar);
} }
} }
@ -39,16 +44,11 @@ void DrawHealthBar(float value)
{ {
if (CurrentLevel) if (CurrentLevel)
{ {
//int color2; g_Renderer.DrawBar(value, ::g_HealthBar);
//if (Lara.poisoned || Lara.gassed)
// color2 = 0xA0A000;
//else
// color2 = 0xA00000;
g_Renderer->DrawBar(value,g_HealthBar);
} }
} }
void UpdateHealtBar(int flash) void UpdateHealthBar(int flash)
{ {
int hitPoints = LaraItem->hitPoints; int hitPoints = LaraItem->hitPoints;
@ -57,44 +57,75 @@ void UpdateHealtBar(int flash)
else if (hitPoints > 1000) else if (hitPoints > 1000)
hitPoints = 1000; hitPoints = 1000;
// OPT: smoothly transition health bar display.
if (EnableSmoothHealthBar)
{
if (OldHitPoints != hitPoints)
{
MutateAmount += OldHitPoints - hitPoints;
OldHitPoints = hitPoints;
HealthBarTimer = 40;
}
if (HealthBar - MutateAmount < 0)
MutateAmount = HealthBar;
else if (HealthBar - MutateAmount > 1000)
MutateAmount = HealthBar - 1000;
HealthBar -= MutateAmount / 3;
MutateAmount -= MutateAmount / 3;
if (MutateAmount > -0.5f && MutateAmount < 0.5f)
{
MutateAmount = 0;
HealthBar = hitPoints;
}
}
// OG: discretely transition health bar display.
else
{
if (OldHitPoints != hitPoints) if (OldHitPoints != hitPoints)
{ {
OldHitPoints = hitPoints; OldHitPoints = hitPoints;
HealtBarTimer = 40; HealthBar = hitPoints;
HealthBarTimer = 40;
}
} }
if (HealtBarTimer < 0) if (HealthBarTimer < 0)
HealtBarTimer = 0; HealthBarTimer = 0;
if (hitPoints <= 1000 / 4) // Flash when at 1/4 capacity AND HP bar is not transitioning.
if (HealthBar <= 1000 / 4 && MutateAmount == 0)
{ {
if (!BinocularRange) if (!BinocularRange)
{ {
if (flash) if (flash)
DrawHealthBar(hitPoints / 1000.0f); DrawHealthBar(HealthBar / 1000.0f);
else else
DrawHealthBar(0); DrawHealthBar(0);
} }
else else
{ {
if (flash) if (flash)
DrawHealthBarOverlay(hitPoints / 1000.0f); DrawHealthBarOverlay(HealthBar / 1000.0f);
else else
DrawHealthBarOverlay(0); DrawHealthBarOverlay(0);
} }
} }
else if ((HealtBarTimer > 0) else if ((HealthBarTimer > 0)
|| (hitPoints <= 0) || (HealthBar <= 0)
|| (Lara.gunStatus == LG_READY && Lara.gunType != WEAPON_TORCH) || (Lara.gunStatus == LG_READY && Lara.gunType != WEAPON_TORCH)
|| (Lara.poisoned >= 256)) || (Lara.poisoned >= 256))
{ {
if (!BinocularRange && !SniperOverlay) if (!BinocularRange && !SniperOverlay)
{ {
DrawHealthBar(hitPoints / 1000.0f); DrawHealthBar(HealthBar / 1000.0f);
} }
else else
{ {
DrawHealthBarOverlay(hitPoints / 1000.0f); DrawHealthBarOverlay(HealthBar / 1000.0f);
} }
} }
@ -106,7 +137,7 @@ void DrawAirBar(float value)
{ {
if (CurrentLevel) if (CurrentLevel)
{ {
g_Renderer->DrawBar(value, g_AirBar); g_Renderer.DrawBar(value, ::g_AirBar);
} }
} }
@ -116,11 +147,11 @@ void UpdateAirBar(int flash)
return; return;
if ((Lara.Vehicle == NO_ITEM) if ((Lara.Vehicle == NO_ITEM)
|| (Items[Lara.Vehicle].objectNumber != ID_UPV)) || (g_Level.Items[Lara.Vehicle].objectNumber != ID_UPV))
{ {
if ((Lara.waterStatus != LW_UNDERWATER) if ((Lara.waterStatus != LW_UNDERWATER)
&& (Lara.waterStatus != LW_SURFACE) && (Lara.waterStatus != LW_SURFACE)
&& (!((Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP) && (!((g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP)
&& (Lara.waterSurfaceDist < -775)))) && (Lara.waterSurfaceDist < -775))))
return; return;
} }
@ -133,7 +164,7 @@ void UpdateAirBar(int flash)
if (air <= 450) if (air <= 450)
{ {
if (flash) if (flash)
DrawAirBar(air/ 1800.0f); DrawAirBar(air / 1800.0f);
else else
DrawAirBar(0); DrawAirBar(0);
} }
@ -152,7 +183,7 @@ void DrawDashBar(int value)
{ {
if (CurrentLevel) if (CurrentLevel)
{ {
g_Renderer->DrawBar(value, g_DashBar); g_Renderer.DrawBar(value, ::g_DashBar);
} }
} }
@ -163,12 +194,12 @@ int DrawAllPickups()
if (PickupX > 0) if (PickupX > 0)
{ {
PickupX += -PickupX >> 5; PickupX += -PickupX >> 5;
return g_Renderer->DrawPickup(Pickups[CurrentPickup].objectNumber); return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber);
} }
else else
{ {
Pickups[CurrentPickup].life--; Pickups[CurrentPickup].life--;
return g_Renderer->DrawPickup(Pickups[CurrentPickup].objectNumber); return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber);
} }
} }
else if (Pickups[CurrentPickup].life == 0) else if (Pickups[CurrentPickup].life == 0)
@ -178,13 +209,13 @@ int DrawAllPickups()
if (PickupVel < 16) if (PickupVel < 16)
PickupVel++; PickupVel++;
PickupX += PickupVel >> 2; PickupX += PickupVel >> 2;
return g_Renderer->DrawPickup(Pickups[CurrentPickup].objectNumber); return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber);
} }
else else
{ {
Pickups[CurrentPickup].life = -1; Pickups[CurrentPickup].life = -1;
PickupVel = 0; PickupVel = 0;
return g_Renderer->DrawPickup(Pickups[CurrentPickup].objectNumber); return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber);
} }
} }
@ -199,7 +230,7 @@ int DrawAllPickups()
CurrentPickup = pickupIndex; CurrentPickup = pickupIndex;
if (i != MAX_COLLECTED_PICKUPS) if (i != MAX_COLLECTED_PICKUPS)
return g_Renderer->DrawPickup(Pickups[CurrentPickup].objectNumber); return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber);
CurrentPickup = 0; CurrentPickup = 0;

View file

@ -9,7 +9,7 @@ typedef struct DISPLAY_PICKUP
void DrawHealthBarOverlay(int value); void DrawHealthBarOverlay(int value);
void DrawHealthBar(float value); void DrawHealthBar(float value);
void UpdateHealtBar(int flash); void UpdateHealthBar(int flash);
void DrawAirBar(float value); void DrawAirBar(float value);
void UpdateAirBar(int flash); void UpdateAirBar(int flash);
void DrawDashBar(int value); void DrawDashBar(int value);
@ -24,7 +24,11 @@ extern short CurrentPickup;
extern DISPLAY_PICKUP Pickups[MAX_COLLECTED_PICKUPS]; extern DISPLAY_PICKUP Pickups[MAX_COLLECTED_PICKUPS];
extern short PickupVel; extern short PickupVel;
extern int OldHitPoints; extern int OldHitPoints;
extern int HealtBarTimer; extern int HealthBarTimer;
extern float HealthBar;
extern float MutateAmount;
extern int FlashState; extern int FlashState;
extern int PoisonFlag; extern int PoisonFlag;
extern int DashTimer; extern int DashTimer;
extern bool EnableSmoothHealthBar;

View file

@ -16,6 +16,7 @@
#include "lara2gun.h" #include "lara2gun.h"
#include "level.h" #include "level.h"
#include "input.h" #include "input.h"
using namespace T5M::Renderer;
using std::vector; using std::vector;
Inventory g_Inventory; Inventory g_Inventory;
extern GameFlow* g_GameFlow; extern GameFlow* g_GameFlow;
@ -571,18 +572,18 @@ int Inventory::DoInventory()
m_activeRing = INV_RING_OPTIONS; m_activeRing = INV_RING_OPTIONS;
m_rings[m_activeRing].currentObject = 0; m_rings[m_activeRing].currentObject = 0;
g_Renderer->DumpGameScene(); g_Renderer.DumpGameScene();
OpenRing(m_activeRing, true); OpenRing(m_activeRing, true);
int passportResult = DoPassport(); int passportResult = DoPassport();
// Fade out // Fade out
g_Renderer->FadeOut(); //g_Renderer.FadeOut();
for (int i = 0; i < FADE_FRAMES_COUNT; i++) //for (int i = 0; i < FADE_FRAMES_COUNT; i++)
{ //{
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
} //}
return passportResult; return passportResult;
} }
@ -614,7 +615,7 @@ int Inventory::DoInventory()
int result = INV_RESULT_NONE; int result = INV_RESULT_NONE;
g_Renderer->DumpGameScene(); g_Renderer.DumpGameScene();
SoundEffect(SFX_TR3_MENU_SPININ, NULL, 0); SoundEffect(SFX_TR3_MENU_SPININ, NULL, 0);
@ -725,7 +726,7 @@ int Inventory::DoInventory()
passportResult == INV_RESULT_LOAD_GAME) passportResult == INV_RESULT_LOAD_GAME)
{ {
// Fade out // Fade out
g_Renderer->FadeOut(); g_Renderer.FadeOut();
for (int i = 0; i < FADE_FRAMES_COUNT; i++) for (int i = 0; i < FADE_FRAMES_COUNT; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
@ -823,7 +824,7 @@ bool Inventory::IsCurrentObjectExamine()
int Inventory::DoPuzzle() int Inventory::DoPuzzle()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
ring->selectedIndex = 0; ring->selectedIndex = 0;
ring->numActions = 0; ring->numActions = 0;
@ -913,7 +914,7 @@ int Inventory::DoPuzzle()
int Inventory::DoWeapon() int Inventory::DoWeapon()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
ring->selectedIndex = 0; ring->selectedIndex = 0;
ring->numActions = 0; ring->numActions = 0;
@ -1060,7 +1061,7 @@ void Inventory::AddCombination(short piece1, short piece2, short combinedObject,
int Inventory::DoGenericObject() int Inventory::DoGenericObject()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
return INV_RESULT_USE_ITEM; return INV_RESULT_USE_ITEM;
} }
@ -1068,14 +1069,14 @@ int Inventory::DoGenericObject()
void Inventory::DoStatistics() void Inventory::DoStatistics()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
} }
void Inventory::DoExamine() void Inventory::DoExamine()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
} }
@ -1501,7 +1502,7 @@ void Inventory::UseCurrentItem()
// Binoculars // Binoculars
if (objectNumber == ID_BINOCULARS_ITEM) if (objectNumber == ID_BINOCULARS_ITEM)
{ {
if (LaraItem->currentAnimState == STATE_LARA_STOP && LaraItem->animNumber == ANIMATION_LARA_STAY_IDLE || Lara.isDucked && !(TrInput & 0x20000000)) if (LaraItem->currentAnimState == LS_STOP && LaraItem->animNumber == LA_STAND_IDLE || Lara.isDucked && !(TrInput & 0x20000000))
{ {
if (!SniperCameraActive && !UseSpotCam && !TrackCameraInit) if (!SniperCameraActive && !UseSpotCam && !TrackCameraInit)
{ {
@ -1564,15 +1565,15 @@ void Inventory::UseCurrentItem()
} }
// TODO: can cause problem with harpoongun in underwater and wading ! // TODO: can cause problem with harpoongun in underwater and wading !
bool canUseWeapons = !(LaraItem->currentAnimState == STATE_LARA_CRAWL_IDLE || bool canUseWeapons = !(LaraItem->currentAnimState == LS_CRAWL_IDLE ||
LaraItem->currentAnimState == STATE_LARA_CRAWL_FORWARD || LaraItem->currentAnimState == LS_CRAWL_FORWARD ||
LaraItem->currentAnimState == STATE_LARA_CRAWL_TURN_LEFT || LaraItem->currentAnimState == LS_CRAWL_TURN_LEFT ||
LaraItem->currentAnimState == STATE_LARA_CRAWL_TURN_RIGHT || LaraItem->currentAnimState == LS_CRAWL_TURN_RIGHT ||
LaraItem->currentAnimState == STATE_LARA_CRAWL_BACK || LaraItem->currentAnimState == LS_CRAWL_BACK ||
LaraItem->currentAnimState == STATE_LARA_CRAWL_TO_CLIMB || LaraItem->currentAnimState == LS_CRAWL_TO_HANG ||
LaraItem->currentAnimState == STATE_LARA_CROUCH_IDLE || LaraItem->currentAnimState == LS_CROUCH_IDLE ||
LaraItem->currentAnimState == STATE_LARA_CROUCH_TURN_LEFT || LaraItem->currentAnimState == LS_CROUCH_TURN_LEFT ||
LaraItem->currentAnimState == STATE_LARA_CROUCH_TURN_RIGHT || LaraItem->currentAnimState == LS_CROUCH_TURN_RIGHT ||
Lara.waterStatus != LW_ABOVE_WATER); Lara.waterStatus != LW_ABOVE_WATER);
// Pistols // Pistols
@ -1732,12 +1733,12 @@ void Inventory::UseCurrentItem()
{ {
if (!Lara.gunStatus) if (!Lara.gunStatus)
{ {
if (LaraItem->currentAnimState != STATE_LARA_CRAWL_IDLE && if (LaraItem->currentAnimState != LS_CRAWL_IDLE &&
LaraItem->currentAnimState != STATE_LARA_CRAWL_FORWARD && LaraItem->currentAnimState != LS_CRAWL_FORWARD &&
LaraItem->currentAnimState != STATE_LARA_CRAWL_TURN_LEFT && LaraItem->currentAnimState != LS_CRAWL_TURN_LEFT &&
LaraItem->currentAnimState != STATE_LARA_CRAWL_TURN_RIGHT && LaraItem->currentAnimState != LS_CRAWL_TURN_RIGHT &&
LaraItem->currentAnimState != STATE_LARA_CRAWL_BACK && LaraItem->currentAnimState != LS_CRAWL_BACK &&
LaraItem->currentAnimState != STATE_LARA_CRAWL_TO_CLIMB && LaraItem->currentAnimState != LS_CRAWL_TO_HANG &&
Lara.waterStatus == LW_ABOVE_WATER) Lara.waterStatus == LW_ABOVE_WATER)
{ {
if (Lara.gunType != WEAPON_FLARE) if (Lara.gunType != WEAPON_FLARE)
@ -1803,17 +1804,16 @@ bool Inventory::UpdateSceneAndDrawInventory()
if (CurrentLevel == 0 && g_GameFlow->TitleType == TITLE_FLYBY) if (CurrentLevel == 0 && g_GameFlow->TitleType == TITLE_FLYBY)
{ {
g_Renderer->DumpGameScene(); g_Renderer.DrawTitle();
g_Renderer->DrawInventory(); Camera.numberFrames = g_Renderer.SyncRenderer();
Camera.numberFrames = g_Renderer->SyncRenderer();
nframes = Camera.numberFrames; nframes = Camera.numberFrames;
ControlPhase(nframes, 0); ControlPhase(nframes, 0);
} }
else else
{ {
g_Renderer->DrawInventory(); g_Renderer.DrawInventory();
g_Renderer->SyncRenderer(); g_Renderer.SyncRenderer();
} }
return true; return true;
@ -1831,7 +1831,7 @@ int Inventory::DoTitleInventory()
m_activeRing = INV_RING_OPTIONS; m_activeRing = INV_RING_OPTIONS;
// Fade in // Fade in
g_Renderer->FadeIn(); g_Renderer.FadeIn();
for (int i = 0; i < FADE_FRAMES_COUNT; i++) for (int i = 0; i < FADE_FRAMES_COUNT; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
@ -1931,7 +1931,7 @@ int Inventory::DoTitleInventory()
CloseRing(INV_RING_OPTIONS, true); CloseRing(INV_RING_OPTIONS, true);
// Fade out // Fade out
g_Renderer->FadeOut(); g_Renderer.FadeOut();
for (int i = 0; i < FADE_FRAMES_COUNT; i++) for (int i = 0; i < FADE_FRAMES_COUNT; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
@ -1948,7 +1948,7 @@ InventoryObjectDefinition* Inventory::GetInventoryObject(int index)
int Inventory::DoPassport() int Inventory::DoPassport()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
short choice = 0; short choice = 0;
@ -1978,7 +1978,7 @@ int Inventory::DoPassport()
for (int i = 0; i < 14; i++) for (int i = 0; i < 14; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
ring->frameIndex++; ring->framePtr++;
} }
bool moveLeft = false; bool moveLeft = false;
@ -2016,11 +2016,11 @@ int Inventory::DoPassport()
if (choice > 0) if (choice > 0)
{ {
ring->frameIndex = 19; ring->framePtr = 19;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
ring->frameIndex--; ring->framePtr--;
} }
choice--; choice--;
@ -2036,11 +2036,11 @@ int Inventory::DoPassport()
if (choice < choices.size() - 1) if (choice < choices.size() - 1)
{ {
ring->frameIndex = 14; ring->framePtr = 14;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
ring->frameIndex++; ring->framePtr++;
} }
choice++; choice++;
@ -2433,14 +2433,14 @@ int Inventory::DoPassport()
} }
// Close the passport // Close the passport
ring->frameIndex = 24; ring->framePtr = 24;
for (int i = 24; i < 30; i++) for (int i = 24; i < 30; i++)
{ {
UpdateSceneAndDrawInventory(); UpdateSceneAndDrawInventory();
ring->frameIndex++; ring->framePtr++;
} }
ring->frameIndex = 0; ring->framePtr = 0;
PopoverObject(); PopoverObject();
@ -2505,7 +2505,7 @@ int Inventory::GetType()
void Inventory::DoControlsSettings() void Inventory::DoControlsSettings()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
ring->selectedIndex = 0; ring->selectedIndex = 0;
ring->waitingForKey = false; ring->waitingForKey = false;
@ -2642,7 +2642,7 @@ void Inventory::DoControlsSettings()
void Inventory::DoGraphicsSettings() void Inventory::DoGraphicsSettings()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
ring->selectedIndex = 0; ring->selectedIndex = 0;
PopupObject(); PopupObject();
@ -2651,7 +2651,7 @@ void Inventory::DoGraphicsSettings()
memcpy(&ring->Configuration, &g_Configuration, sizeof(GameConfiguration)); memcpy(&ring->Configuration, &g_Configuration, sizeof(GameConfiguration));
// Get current display mode // Get current display mode
vector<RendererVideoAdapter>* adapters = g_Renderer->GetAdapters(); vector<RendererVideoAdapter>* adapters = g_Renderer.GetAdapters();
RendererVideoAdapter* adapter = &(*adapters)[ring->Configuration.Adapter]; RendererVideoAdapter* adapter = &(*adapters)[ring->Configuration.Adapter];
ring->SelectedVideoMode = 0; ring->SelectedVideoMode = 0;
for (int i = 0; i < adapter->DisplayModes.size(); i++) for (int i = 0; i < adapter->DisplayModes.size(); i++)
@ -2782,7 +2782,7 @@ void Inventory::DoGraphicsSettings()
SaveConfiguration(); SaveConfiguration();
// Reset screen and go back // Reset screen and go back
g_Renderer->ChangeScreenResolution(ring->Configuration.Width, ring->Configuration.Height, g_Renderer.ChangeScreenResolution(ring->Configuration.Width, ring->Configuration.Height,
ring->Configuration.RefreshRate, ring->Configuration.Windowed); ring->Configuration.RefreshRate, ring->Configuration.Windowed);
closeObject = true; closeObject = true;
@ -2810,7 +2810,7 @@ void Inventory::DoGraphicsSettings()
void Inventory::DoSoundSettings() void Inventory::DoSoundSettings()
{ {
InventoryRing* ring = &m_rings[m_activeRing]; InventoryRing* ring = &m_rings[m_activeRing];
ring->frameIndex = 0; ring->framePtr = 0;
ring->selectedIndex = 0; ring->selectedIndex = 0;
PopupObject(); PopupObject();

View file

@ -271,7 +271,7 @@ struct InventoryRing
int rotation; int rotation;
int distance; int distance;
int focusState; int focusState;
int frameIndex; int framePtr;
bool draw; bool draw;
int y; int y;
int titleStringIndex; int titleStringIndex;

View file

@ -8,8 +8,8 @@
void ClearItem(short itemNum) void ClearItem(short itemNum)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
ROOM_INFO* room = &Rooms[item->roomNumber]; ROOM_INFO* room = &g_Level.Rooms[item->roomNumber];
item->collidable = true; item->collidable = true;
item->data = NULL; item->data = NULL;
@ -27,7 +27,7 @@ void KillItem(short itemNum)
} }
else else
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
DetatchSpark(itemNum, SP_ITEM); DetatchSpark(itemNum, SP_ITEM);
@ -41,11 +41,11 @@ void KillItem(short itemNum)
else else
{ {
short linknum; short linknum;
for (linknum = NextItemActive; linknum != NO_ITEM; linknum = Items[linknum].nextActive) for (linknum = NextItemActive; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextActive)
{ {
if (Items[linknum].nextActive == itemNum) if (g_Level.Items[linknum].nextActive == itemNum)
{ {
Items[linknum].nextActive = item->nextActive; g_Level.Items[linknum].nextActive = item->nextActive;
break; break;
} }
} }
@ -53,18 +53,18 @@ void KillItem(short itemNum)
if (item->roomNumber != NO_ROOM) if (item->roomNumber != NO_ROOM)
{ {
if (Rooms[item->roomNumber].itemNumber == itemNum) if (g_Level.Rooms[item->roomNumber].itemNumber == itemNum)
{ {
Rooms[item->roomNumber].itemNumber = item->nextItem; g_Level.Rooms[item->roomNumber].itemNumber = item->nextItem;
} }
else else
{ {
short linknum; short linknum;
for (linknum = Rooms[item->roomNumber].itemNumber; linknum != NO_ITEM; linknum = Items[linknum].nextItem) for (linknum = g_Level.Rooms[item->roomNumber].itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextItem)
{ {
if (Items[linknum].nextItem == itemNum) if (g_Level.Items[linknum].nextItem == itemNum)
{ {
Items[linknum].nextItem = item->nextItem; g_Level.Items[linknum].nextItem = item->nextItem;
break; break;
} }
} }
@ -74,7 +74,7 @@ void KillItem(short itemNum)
if (item == Lara.target) if (item == Lara.target)
Lara.target = NULL; Lara.target = NULL;
if (itemNum >= LevelItems) if (itemNum >= g_Level.NumItems)
{ {
item->nextItem = NextItemFree; item->nextItem = NextItemFree;
NextItemFree = itemNum; NextItemFree = itemNum;
@ -88,12 +88,12 @@ void KillItem(short itemNum)
void RemoveAllItemsInRoom(short roomNumber, short objectNumber) void RemoveAllItemsInRoom(short roomNumber, short objectNumber)
{ {
ROOM_INFO* room = &Rooms[roomNumber]; ROOM_INFO* room = &g_Level.Rooms[roomNumber];
short currentItemNum = room->itemNumber; short currentItemNum = room->itemNumber;
while (currentItemNum != NO_ITEM) while (currentItemNum != NO_ITEM)
{ {
ITEM_INFO* item = &Items[currentItemNum]; ITEM_INFO* item = &g_Level.Items[currentItemNum];
if (item->objectNumber == objectNumber) if (item->objectNumber == objectNumber)
{ {
@ -108,7 +108,7 @@ void RemoveAllItemsInRoom(short roomNumber, short objectNumber)
void AddActiveItem(short itemNumber) void AddActiveItem(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->flags |= 0x20; item->flags |= 0x20;
@ -136,11 +136,11 @@ void ItemNewRoom(short itemNumber, short roomNumber)
} }
else else
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->roomNumber != 255) if (item->roomNumber != 255)
{ {
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
if (r->itemNumber == itemNumber) if (r->itemNumber == itemNumber)
{ {
@ -148,11 +148,11 @@ void ItemNewRoom(short itemNumber, short roomNumber)
} }
else else
{ {
for (short linknum = r->itemNumber; linknum != -1; linknum = Items[linknum].nextItem) for (short linknum = r->itemNumber; linknum != -1; linknum = g_Level.Items[linknum].nextItem)
{ {
if (Items[linknum].nextItem == itemNumber) if (g_Level.Items[linknum].nextItem == itemNumber)
{ {
Items[linknum].nextItem = item->nextItem; g_Level.Items[linknum].nextItem = item->nextItem;
break; break;
} }
} }
@ -160,8 +160,8 @@ void ItemNewRoom(short itemNumber, short roomNumber)
} }
item->roomNumber = roomNumber; item->roomNumber = roomNumber;
item->nextItem = Rooms[roomNumber].itemNumber; item->nextItem = g_Level.Rooms[roomNumber].itemNumber;
Rooms[roomNumber].itemNumber = itemNumber; g_Level.Rooms[roomNumber].itemNumber = itemNumber;
} }
} }
@ -175,8 +175,8 @@ void EffectNewRoom(short fxNumber, short roomNumber)
} }
else else
{ {
FX_INFO* fx = &Effects[fxNumber]; FX_INFO* fx = &EffectList[fxNumber];
ROOM_INFO* r = &Rooms[fx->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[fx->roomNumber];
if (r->fxNumber == fxNumber) if (r->fxNumber == fxNumber)
{ {
@ -185,19 +185,19 @@ void EffectNewRoom(short fxNumber, short roomNumber)
else else
{ {
short linknum; short linknum;
for (linknum = r->fxNumber; linknum != -1; linknum = Effects[linknum].nextFx) for (linknum = r->fxNumber; linknum != -1; linknum = EffectList[linknum].nextFx)
{ {
if (Effects[linknum].nextFx == fxNumber) if (EffectList[linknum].nextFx == fxNumber)
{ {
Effects[linknum].nextFx = fx->nextFx; EffectList[linknum].nextFx = fx->nextFx;
break; break;
} }
} }
} }
fx->roomNumber = roomNumber; fx->roomNumber = roomNumber;
fx->nextFx = Rooms[roomNumber].fxNumber; fx->nextFx = g_Level.Rooms[roomNumber].fxNumber;
Rooms[roomNumber].fxNumber = fxNumber; g_Level.Rooms[roomNumber].fxNumber = fxNumber;
} }
} }
@ -210,7 +210,7 @@ void KillEffect(short fxNumber)
} }
else else
{ {
FX_INFO* fx = &Effects[fxNumber]; FX_INFO* fx = &EffectList[fxNumber];
DetatchSpark(fxNumber, SP_FX); DetatchSpark(fxNumber, SP_FX);
if (NextFxActive == fxNumber) if (NextFxActive == fxNumber)
@ -219,27 +219,27 @@ void KillEffect(short fxNumber)
} }
else else
{ {
for (short linknum = NextFxActive; linknum != NO_ITEM; linknum = Effects[linknum].nextActive) for (short linknum = NextFxActive; linknum != NO_ITEM; linknum = EffectList[linknum].nextActive)
{ {
if (Effects[linknum].nextActive == fxNumber) if (EffectList[linknum].nextActive == fxNumber)
{ {
Effects[linknum].nextActive = fx->nextActive; EffectList[linknum].nextActive = fx->nextActive;
break; break;
} }
} }
} }
if (Rooms[fx->roomNumber].fxNumber == fxNumber) if (g_Level.Rooms[fx->roomNumber].fxNumber == fxNumber)
{ {
Rooms[fx->roomNumber].fxNumber = fx->nextFx; g_Level.Rooms[fx->roomNumber].fxNumber = fx->nextFx;
} }
else else
{ {
for (short linknum = Rooms[fx->roomNumber].fxNumber; linknum != NO_ITEM; linknum = Effects[linknum].nextFx) for (short linknum = g_Level.Rooms[fx->roomNumber].fxNumber; linknum != NO_ITEM; linknum = EffectList[linknum].nextFx)
{ {
if (Effects[linknum].nextFx == fxNumber) if (EffectList[linknum].nextFx == fxNumber)
{ {
Effects[linknum].nextFx = fx->nextFx; EffectList[linknum].nextFx = fx->nextFx;
break; break;
} }
} }
@ -256,9 +256,9 @@ short CreateNewEffect(short roomNum)
if (NextFxFree != NO_ITEM) if (NextFxFree != NO_ITEM)
{ {
FX_INFO* fx = &Effects[NextFxFree]; FX_INFO* fx = &EffectList[NextFxFree];
NextFxFree = fx->nextFx; NextFxFree = fx->nextFx;
ROOM_INFO* r = &Rooms[roomNum]; ROOM_INFO* r = &g_Level.Rooms[roomNum];
fx->roomNumber = roomNum; fx->roomNumber = roomNum;
fx->nextFx = r->fxNumber; fx->nextFx = r->fxNumber;
r->fxNumber = fxNumber; r->fxNumber = fxNumber;
@ -273,13 +273,15 @@ short CreateNewEffect(short roomNum)
void InitialiseFXArray(int allocmem) void InitialiseFXArray(int allocmem)
{ {
if (allocmem) if (allocmem)
Effects = (FX_INFO*)game_malloc(NUM_EFFECTS * sizeof(FX_INFO)); EffectList = game_malloc<FX_INFO>(NUM_EFFECTS);
FX_INFO* fx;
FX_INFO* fx = Effects;
NextFxActive = NO_ITEM; NextFxActive = NO_ITEM;
NextFxFree = 0; NextFxFree = 0;
for (int i = 1; i < NUM_EFFECTS; i++, fx++) for (int i = 1; i < NUM_EFFECTS; i++, fx++)
{ {
fx = &EffectList[i];
fx->nextFx = i; fx->nextFx = i;
} }
fx->nextFx = -1; fx->nextFx = -1;
@ -287,19 +289,19 @@ void InitialiseFXArray(int allocmem)
void RemoveDrawnItem(short itemNum) void RemoveDrawnItem(short itemNum)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (Rooms[item->roomNumber].itemNumber == itemNum) if (g_Level.Rooms[item->roomNumber].itemNumber == itemNum)
{ {
Rooms[item->roomNumber].itemNumber = item->nextItem; g_Level.Rooms[item->roomNumber].itemNumber = item->nextItem;
} }
else else
{ {
for (short linknum = Rooms[item->roomNumber].itemNumber; linknum != NO_ITEM; linknum = Items[linknum].nextItem) for (short linknum = g_Level.Rooms[item->roomNumber].itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextItem)
{ {
if (Items[linknum].nextItem == itemNum) if (g_Level.Items[linknum].nextItem == itemNum)
{ {
Items[linknum].nextItem = item->nextItem; g_Level.Items[linknum].nextItem = item->nextItem;
break; break;
} }
} }
@ -308,21 +310,21 @@ void RemoveDrawnItem(short itemNum)
void RemoveActiveItem(short itemNum) void RemoveActiveItem(short itemNum)
{ {
if (Items[itemNum].active) if (g_Level.Items[itemNum].active)
{ {
Items[itemNum].active = false; g_Level.Items[itemNum].active = false;
if (NextItemActive == itemNum) if (NextItemActive == itemNum)
{ {
NextItemActive = Items[itemNum].nextActive; NextItemActive = g_Level.Items[itemNum].nextActive;
} }
else else
{ {
for (short linknum = NextItemActive; linknum != NO_ITEM; linknum = Items[linknum].nextActive) for (short linknum = NextItemActive; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextActive)
{ {
if (Items[linknum].nextActive == itemNum) if (g_Level.Items[linknum].nextActive == itemNum)
{ {
Items[linknum].nextActive = Items[itemNum].nextActive; g_Level.Items[linknum].nextActive = g_Level.Items[itemNum].nextActive;
break; break;
} }
} }
@ -332,14 +334,14 @@ void RemoveActiveItem(short itemNum)
void InitialiseItem(short itemNum) void InitialiseItem(short itemNum)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
item->animNumber = Objects[item->objectNumber].animIndex; item->animNumber = Objects[item->objectNumber].animIndex;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->requiredAnimState = 0; item->requiredAnimState = 0;
item->goalAnimState = Anims[item->animNumber].currentAnimState; item->goalAnimState = g_Level.Anims[item->animNumber].currentAnimState;
item->currentAnimState = Anims[item->animNumber].currentAnimState; item->currentAnimState = g_Level.Anims[item->animNumber].currentAnimState;
item->pos.zRot = 0; item->pos.zRot = 0;
item->pos.xRot = 0; item->pos.xRot = 0;
@ -403,7 +405,7 @@ void InitialiseItem(short itemNum)
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
} }
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
item->nextItem = r->itemNumber; item->nextItem = r->itemNumber;
r->itemNumber = itemNum; r->itemNumber = itemNum;
@ -416,8 +418,6 @@ void InitialiseItem(short itemNum)
{ {
Objects[item->objectNumber].initialise(itemNum); Objects[item->objectNumber].initialise(itemNum);
} }
//item->unk_thing = 0;
} }
short CreateItem() short CreateItem()
@ -427,22 +427,22 @@ short CreateItem()
if (NextItemFree == -1) return NO_ITEM; if (NextItemFree == -1) return NO_ITEM;
itemNum = NextItemFree; itemNum = NextItemFree;
Items[NextItemFree].flags = 0; g_Level.Items[NextItemFree].flags = 0;
NextItemFree = Items[NextItemFree].nextItem; NextItemFree = g_Level.Items[NextItemFree].nextItem;
return itemNum; return itemNum;
} }
void InitialiseItemArray(int numitems) void InitialiseItemArray(int numitems)
{ {
ITEM_INFO* item = &Items[LevelItems]; ITEM_INFO* item = &g_Level.Items[g_Level.NumItems];
NextItemActive = NO_ITEM; NextItemActive = NO_ITEM;
NextItemFree = LevelItems; NextItemFree = g_Level.NumItems;
if (LevelItems + 1 < numitems) if (g_Level.NumItems + 1 < numitems)
{ {
for (int i = LevelItems + 1; i < numitems; i++, item++) for (int i = g_Level.NumItems + 1; i < numitems; i++, item++)
{ {
item->nextItem = i; item->nextItem = i;
item->active = false; item->active = false;
@ -457,7 +457,7 @@ short SpawnItem(ITEM_INFO* item, short objectNumber)
short itemNumber = CreateItem(); short itemNumber = CreateItem();
if (itemNumber != NO_ITEM) if (itemNumber != NO_ITEM)
{ {
ITEM_INFO* spawn = &Items[itemNumber]; ITEM_INFO* spawn = &g_Level.Items[itemNumber];
spawn->objectNumber = objectNumber; spawn->objectNumber = objectNumber;
spawn->roomNumber = item->roomNumber; spawn->roomNumber = item->roomNumber;
@ -475,14 +475,14 @@ short SpawnItem(ITEM_INFO* item, short objectNumber)
int GlobalItemReplace(short search, short replace) int GlobalItemReplace(short search, short replace)
{ {
int changed = 0; int changed = 0;
for (int i = 0; i < Rooms.size(); i++) for (int i = 0; i < g_Level.Rooms.size(); i++)
{ {
ROOM_INFO* room = &Rooms[i]; ROOM_INFO* room = &g_Level.Rooms[i];
for (short itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = Items[itemNumber].nextItem) for (short itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].nextItem)
{ {
if (Items[itemNumber].objectNumber == search) if (g_Level.Items[itemNumber].objectNumber == search)
{ {
Items[itemNumber].objectNumber = replace; g_Level.Items[itemNumber].objectNumber = replace;
changed++; changed++;
} }
} }
@ -494,14 +494,14 @@ int GlobalItemReplace(short search, short replace)
ITEM_INFO* find_a_fucking_item(short objectNum) ITEM_INFO* find_a_fucking_item(short objectNum)
{ {
int itemNumber = FindItemNumber(objectNum); int itemNumber = FindItemNumber(objectNum);
return (itemNumber != NO_ITEM ? &Items[itemNumber] : NULL); return (itemNumber != NO_ITEM ? &g_Level.Items[itemNumber] : NULL);
} }
int FindItemNumber(short objectNum) int FindItemNumber(short objectNum)
{ {
for (int i = 0; i < LevelItems; i++) for (int i = 0; i < g_Level.NumItems; i++)
{ {
ITEM_INFO* item = &Items[i]; ITEM_INFO* item = &g_Level.Items[i];
if (item->objectNumber == objectNum) if (item->objectNumber == objectNum)
return i; return i;
} }
@ -515,12 +515,12 @@ ITEM_INFO* FindItem(short objectNumber)
printf("Called FindItem()\n"); printf("Called FindItem()\n");
#endif #endif
if (LevelItems > 0) if (g_Level.NumItems > 0)
{ {
for (int i = 0; i < LevelItems; i++) for (int i = 0; i < g_Level.NumItems; i++)
{ {
if (Items[i].objectNumber == objectNumber) if (g_Level.Items[i].objectNumber == objectNumber)
return &Items[i]; return &g_Level.Items[i];
} }
} }

View file

@ -47,7 +47,7 @@ typedef struct ITEM_INFO
short speed; short speed;
short fallspeed; short fallspeed;
short hitPoints; short hitPoints;
unsigned short boxNumber; int boxNumber;
short timer; short timer;
unsigned short flags; // ItemFlags enum unsigned short flags; // ItemFlags enum
short shade; short shade;
@ -55,10 +55,9 @@ typedef struct ITEM_INFO
short carriedItem; short carriedItem;
short afterDeath; short afterDeath;
short firedWeapon; short firedWeapon;
short itemFlags[4]; short itemFlags[8];
void* data; void* data;
PHD_3DPOS pos; PHD_3DPOS pos;
byte legacyLightData[5528];
bool active; bool active;
short status; // ItemStatus enum short status; // ItemStatus enum
bool gravityStatus; bool gravityStatus;
@ -73,6 +72,7 @@ typedef struct ITEM_INFO
int swapMeshFlags; int swapMeshFlags;
short drawRoom; short drawRoom;
short TOSSPAD; short TOSSPAD;
PHD_3DPOS startPos;
}; };
// used by fx->shade ! // used by fx->shade !
@ -99,7 +99,7 @@ void InitialiseFXArray(int allocmem);
short CreateNewEffect(short roomNum); short CreateNewEffect(short roomNum);
void KillEffect(short fxNumber); void KillEffect(short fxNumber);
void InitialiseItem(short itemNum); void InitialiseItem(short itemNum);
void InitialiseItemArray(int numitems); void InitialiseItemArray(int numItems);
void KillItem(short itemNum); void KillItem(short itemNum);
ITEM_INFO* find_a_fucking_item(short objectNum); ITEM_INFO* find_a_fucking_item(short objectNum);
int FindItemNumber(short objectNumber); int FindItemNumber(short objectNumber);

File diff suppressed because it is too large Load diff

View file

@ -45,7 +45,7 @@ void FireHarpoon()
{ {
GAME_VECTOR pos; GAME_VECTOR pos;
PHD_VECTOR handr; PHD_VECTOR handr;
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->shade = 0x4210 | 0x8000; item->shade = 0x4210 | 0x8000;
item->objectNumber = ID_HARPOON; item->objectNumber = ID_HARPOON;
@ -92,7 +92,7 @@ void FireHarpoon()
void ControlHarpoonBolt(short itemNumber) void ControlHarpoonBolt(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
int oldX = item->pos.xPos; int oldX = item->pos.xPos;
int oldY = item->pos.yPos; int oldY = item->pos.yPos;
int oldZ = item->pos.zPos; int oldZ = item->pos.zPos;
@ -112,23 +112,17 @@ void ControlHarpoonBolt(short itemNumber)
// First check if the harpoon has it an item // First check if the harpoon has it an item
short targetItemNumber = 0; short targetItemNumber = 0;
ITEM_INFO* target; ITEM_INFO* target;
for (targetItemNumber = Rooms[item->roomNumber].itemNumber; targetItemNumber != NO_ITEM; targetItemNumber = target->nextItem) for (targetItemNumber = g_Level.Rooms[item->roomNumber].itemNumber; targetItemNumber != NO_ITEM; targetItemNumber = target->nextItem)
{ {
target = &Items[targetItemNumber]; target = &g_Level.Items[targetItemNumber];
if (target == LaraItem || !target->collidable) if (target == LaraItem || !target->collidable)
continue; continue;
if (/*target->objectNumber == SMASH_WINDOW || if (target->status != ITEM_INVISIBLE && Objects[target->objectNumber].collision)
target->objectNumber == SMASH_OBJECT1 ||
target->objectNumber == SMASH_OBJECT2 ||
target->objectNumber == SMASH_OBJECT3 ||
target->objectNumber == CARCASS ||
target->objectNumber == EXTRAFX6 ||*/
(target->status != ITEM_INVISIBLE && Objects[target->objectNumber].collision))
{ {
// check against bounds of target for collision // check against bounds of target for collision
short* bounds = GetBestFrame(target); BOUNDING_BOX* bounds = (BOUNDING_BOX*)GetBestFrame(target);
if (item->pos.yPos < target->pos.yPos + bounds[2] || item->pos.yPos > target->pos.yPos + bounds[3]) if (item->pos.yPos < target->pos.yPos + bounds->Y1 || item->pos.yPos > target->pos.yPos + bounds->Y2)
continue; continue;
// get vector from target to bolt and check against x,z bounds // get vector from target to bolt and check against x,z bounds
@ -143,13 +137,13 @@ void ControlHarpoonBolt(short itemNumber)
int oz = oldZ - target->pos.zPos; int oz = oldZ - target->pos.zPos;
int sx = (c * ox - s * oz) >> W2V_SHIFT; int sx = (c * ox - s * oz) >> W2V_SHIFT;
if ((rx < bounds[0] && sx < bounds[0]) || (rx > bounds[1] && sx > bounds[1])) if ((rx < bounds->X1 && sx < bounds->X1) || (rx > bounds->X2 && sx > bounds->X2))
continue; continue;
int rz = (c * z + s * x) >> W2V_SHIFT; int rz = (c * z + s * x) >> W2V_SHIFT;
int sz = (c * oz + s * ox) >> W2V_SHIFT; int sz = (c * oz + s * ox) >> W2V_SHIFT;
if ((rz < bounds[4] && sz < bounds[4]) || (rz > bounds[5] && sz > bounds[5])) if ((rz < bounds->Z1 && sz < bounds->Z1) || (rz > bounds->Z2 && sz > bounds->Z2))
continue; continue;
// TODO: // TODO:
@ -213,7 +207,7 @@ void ControlHarpoonBolt(short itemNumber)
else else
{ {
item->pos.zRot += ANGLE(35); item->pos.zRot += ANGLE(35);
if (!(Rooms[item->roomNumber].flags & 1)) if (!(g_Level.Rooms[item->roomNumber].flags & 1))
{ {
item->pos.xRot -= ANGLE(1); item->pos.xRot -= ANGLE(1);
if (item->pos.xRot < -16384) if (item->pos.xRot < -16384)
@ -256,7 +250,7 @@ void FireGrenade()
short itemNumber = CreateItem(); short itemNumber = CreateItem();
if (itemNumber != NO_ITEM) if (itemNumber != NO_ITEM)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->shade = 0xC210; item->shade = 0xC210;
item->objectNumber = ID_GRENADE; item->objectNumber = ID_GRENADE;
@ -343,7 +337,7 @@ enum GRENADE_TYPE
void ControlGrenade(short itemNumber) void ControlGrenade(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->itemFlags[1]) if (item->itemFlags[1])
{ {
@ -370,12 +364,6 @@ void ControlGrenade(short itemNumber)
FlashFader = 32; FlashFader = 32;
// if Volumetric then FlashFader = 0?
/*if (sub_47F960())
{
FlashFader = 0;
}*/
GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
} }
@ -385,7 +373,7 @@ void ControlGrenade(short itemNumber)
if (newGrenadeItemNumber != NO_ITEM) if (newGrenadeItemNumber != NO_ITEM)
{ {
ITEM_INFO* newGrenade = &Items[newGrenadeItemNumber]; ITEM_INFO* newGrenade = &g_Level.Items[newGrenadeItemNumber];
newGrenade->shade = 0xC210; newGrenade->shade = 0xC210;
newGrenade->objectNumber = ID_GRENADE; newGrenade->objectNumber = ID_GRENADE;
@ -411,7 +399,7 @@ void ControlGrenade(short itemNumber)
newGrenade->itemFlags[2] = item->itemFlags[2]; newGrenade->itemFlags[2] = item->itemFlags[2];
newGrenade->hitPoints = 3000; newGrenade->hitPoints = 3000;
if (Rooms[newGrenade->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[newGrenade->roomNumber].flags & ENV_FLAG_WATER)
newGrenade->hitPoints = 1; newGrenade->hitPoints = 1;
} }
} }
@ -434,7 +422,7 @@ void ControlGrenade(short itemNumber)
item->shade = 0xC210; item->shade = 0xC210;
bool aboveWater = false; bool aboveWater = false;
if (Rooms[item->roomNumber].flags & 1) if (g_Level.Rooms[item->roomNumber].flags & 1)
{ {
aboveWater = false; aboveWater = false;
item->fallspeed += (5 - item->fallspeed) >> 1; item->fallspeed += (5 - item->fallspeed) >> 1;
@ -475,43 +463,9 @@ void ControlGrenade(short itemNumber)
int wy = world.Translation().y; int wy = world.Translation().y;
int wz = world.Translation().z; int wz = world.Translation().z;
// For now keep this legacy math
// PHD_MATH
/*phd_PushUnitMatrix();
MatrixPtr[M03] = 0;
MatrixPtr[M13] = 0;
MatrixPtr[M23] = 0;
phd_RotYXZ(item->pos.yRot - ANGLE(180), item->pos.xRot, item->pos.zRot);
phd_TranslateRel(0, 0, -64);
int wx = (MatrixPtr[M03] >> W2V_SHIFT);
int wy = (MatrixPtr[M13] >> W2V_SHIFT);
int wz = (MatrixPtr[M23] >> W2V_SHIFT);
phd_PopMatrix();*/
TriggerRocketSmoke(wx + item->pos.xPos, wy + item->pos.yPos, wz + item->pos.zPos, -1); TriggerRocketSmoke(wx + item->pos.xPos, wy + item->pos.yPos, wz + item->pos.zPos, -1);
} }
/*XMMATRIX transform;
XMMATRIX translation;
XMMATRIX rotation;
XMMATRIXRotationYawPitchRoll(&rotation, TO_RAD(item->pos.yRot), TO_RAD(item->pos.xRot),
TO_RAD(item->pos.zRot));
XMMATRIXTranslation(&translation, 0, 0, -64);
XMMATRIXMultiply(&transform, &rotation, &translation);
int wx = transform._14;
int wy = transform._24;
int wz = transform._34;
if (item->speed && aboveWater)
TriggerRocketSmoke(wx + item->pos.xPos, wy + item->pos.yPos, wz + item->pos.zPos, -1);
*/
xv = ((item->speed * phd_sin(item->goalAnimState)) >> W2V_SHIFT); xv = ((item->speed * phd_sin(item->goalAnimState)) >> W2V_SHIFT);
yv = item->fallspeed; yv = item->fallspeed;
zv = ((item->speed * phd_cos(item->goalAnimState)) >> W2V_SHIFT); zv = ((item->speed * phd_cos(item->goalAnimState)) >> W2V_SHIFT);
@ -550,7 +504,7 @@ void ControlGrenade(short itemNumber)
roomNumber = item->roomNumber; roomNumber = item->roomNumber;
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
if ((Rooms[roomNumber].flags & ENV_FLAG_WATER) && aboveWater) if ((g_Level.Rooms[roomNumber].flags & ENV_FLAG_WATER) && aboveWater)
{ {
// Setup splash // Setup splash
/*dword_804E20 = item->pos.xPos; /*dword_804E20 = item->pos.xPos;
@ -574,6 +528,7 @@ void ControlGrenade(short itemNumber)
goto LABEL_35; goto LABEL_35;
} }
item->hitPoints = 1;*/ item->hitPoints = 1;*/
// what is this lol
} }
if (item->itemFlags[0] == GRENADE_ULTRA) if (item->itemFlags[0] == GRENADE_ULTRA)
@ -657,8 +612,8 @@ void ControlGrenade(short itemNumber)
for (int i = 0; i < sw; i++) for (int i = 0; i < sw; i++)
{ {
AddActiveItem(itemNos[i]); AddActiveItem(itemNos[i]);
Items[itemNos[i]].status = ITEM_ACTIVE; g_Level.Items[itemNos[i]].status = ITEM_ACTIVE;
Items[itemNos[i]].triggerFlags |= 0x3E00; g_Level.Items[itemNos[i]].triggerFlags |= 0x3E00;
} }
} }
} }
@ -669,7 +624,7 @@ void ControlGrenade(short itemNumber)
ExplodeItemNode(currentItem, Objects[ID_SHOOT_SWITCH1].nmeshes - 1, 0, 64); ExplodeItemNode(currentItem, Objects[ID_SHOOT_SWITCH1].nmeshes - 1, 0, 64);
} }
AddActiveItem((currentItem - Items)); AddActiveItem((currentItem - g_Level.Items.data()));
currentItem->status = ITEM_ACTIVE; currentItem->status = ITEM_ACTIVE;
currentItem->triggerFlags |= 0x3E40; currentItem->triggerFlags |= 0x3E40;
} }
@ -680,7 +635,7 @@ void ControlGrenade(short itemNumber)
//TriggerShockwave(&currentItem->pos, 48, 304, 64, 0, 96, 128, 24, 0, 0); // CHECK //TriggerShockwave(&currentItem->pos, 48, 304, 64, 0, 96, 128, 24, 0, 0); // CHECK
currentItem->pos.yPos += 128; currentItem->pos.yPos += 128;
ExplodeItemNode(currentItem, 0, 0, 128); ExplodeItemNode(currentItem, 0, 0, 128);
short currentItemNumber = (currentItem - Items); short currentItemNumber = (currentItem - g_Level.Items.data());
SmashObject(currentItemNumber); SmashObject(currentItemNumber);
KillItem(currentItemNumber); KillItem(currentItemNumber);
} }
@ -734,18 +689,10 @@ void ControlGrenade(short itemNumber)
FlashFadeG = 255; FlashFadeG = 255;
FlashFadeB = 255; FlashFadeB = 255;
/*
if ( sub_47F960() )
{
FlashFader = 0;
sub_47F880(item->pos.xPos, item->pos.yPos, item->pos.zPos, 4096, 255, 255, 255, 255, item->roomNumber);
}
*/
GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); GrenadeExplosionEffects(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
} }
else if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
TriggerUnderwaterExplosion(item); TriggerUnderwaterExplosion(item);
} }
@ -783,7 +730,7 @@ void draw_shotgun(int weaponType)
{ {
Lara.weaponItem = CreateItem(); Lara.weaponItem = CreateItem();
item = &Items[Lara.weaponItem]; item = &g_Level.Items[Lara.weaponItem];
item->objectNumber = WeaponObject(weaponType); item->objectNumber = WeaponObject(weaponType);
@ -794,7 +741,7 @@ void draw_shotgun(int weaponType)
else else
item->animNumber = Objects[item->objectNumber].animIndex + HARPOON_DRAW_ANIM; // M16 too item->animNumber = Objects[item->objectNumber].animIndex + HARPOON_DRAW_ANIM; // M16 too
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = 1; item->goalAnimState = 1;
item->currentAnimState = 1; item->currentAnimState = 1;
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
@ -805,14 +752,14 @@ void draw_shotgun(int weaponType)
} }
else else
{ {
item = &Items[Lara.weaponItem]; item = &g_Level.Items[Lara.weaponItem];
} }
AnimateItem(item); AnimateItem(item);
if (item->currentAnimState != 0 && item->currentAnimState != 6) if (item->currentAnimState != 0 && item->currentAnimState != 6)
{ {
if (item->frameNumber - Anims[item->animNumber].frameBase == Weapons[weaponType].drawFrame) if (item->frameNumber - g_Level.Anims[item->animNumber].frameBase == Weapons[weaponType].drawFrame)
draw_shotgun_meshes(weaponType); draw_shotgun_meshes(weaponType);
else if (Lara.waterStatus == 1) else if (Lara.waterStatus == 1)
item->goalAnimState = 6; item->goalAnimState = 6;
@ -822,8 +769,8 @@ void draw_shotgun(int weaponType)
ready_shotgun(weaponType); ready_shotgun(weaponType);
} }
Lara.leftArm.frameBase = Lara.rightArm.frameBase = Anims[item->animNumber].framePtr; Lara.leftArm.frameBase = Lara.rightArm.frameBase = g_Level.Anims[item->animNumber].framePtr;
Lara.leftArm.frameNumber = Lara.rightArm.frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; Lara.leftArm.frameNumber = Lara.rightArm.frameNumber = item->frameNumber - g_Level.Anims[item->animNumber].frameBase;
Lara.leftArm.animNumber = Lara.rightArm.animNumber = item->animNumber; Lara.leftArm.animNumber = Lara.rightArm.animNumber = item->animNumber;
} }
@ -870,7 +817,7 @@ void AnimateShotgun(int weaponType)
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, SmokeWeapon, SmokeCountL); TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, SmokeWeapon, SmokeCountL);
} }
ITEM_INFO* item = &Items[Lara.weaponItem]; ITEM_INFO* item = &g_Level.Items[Lara.weaponItem];
bool running = (weaponType == WEAPON_HK && LaraItem->speed != 0); bool running = (weaponType == WEAPON_HK && LaraItem->speed != 0);
bool harpoonFired = false; bool harpoonFired = false;
@ -908,7 +855,7 @@ void AnimateShotgun(int weaponType)
break; break;
case 2: case 2:
if (item->frameNumber == Anims[item->animNumber].frameBase) if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase)
{ {
item->goalAnimState = 4; item->goalAnimState = 4;
@ -982,12 +929,12 @@ void AnimateShotgun(int weaponType)
item->goalAnimState = 4; item->goalAnimState = 4;
} }
if (item->frameNumber - Anims[item->animNumber].frameBase == 12 && weaponType == WEAPON_SHOTGUN) if (item->frameNumber - g_Level.Anims[item->animNumber].frameBase == 12 && weaponType == WEAPON_SHOTGUN)
TriggerGunShell(1, ID_SHOTGUNSHELL, 4); TriggerGunShell(1, ID_SHOTGUNSHELL, 4);
break; break;
case 8: case 8:
if (item->frameNumber - Anims[item->animNumber].frameBase == 0) if (item->frameNumber - g_Level.Anims[item->animNumber].frameBase == 0)
{ {
item->goalAnimState = 7; item->goalAnimState = 7;
@ -1054,8 +1001,8 @@ void AnimateShotgun(int weaponType)
AnimateItem(item); AnimateItem(item);
Lara.leftArm.frameBase = Lara.rightArm.frameBase = Anims[item->animNumber].framePtr; Lara.leftArm.frameBase = Lara.rightArm.frameBase = g_Level.Anims[item->animNumber].framePtr;
Lara.leftArm.frameNumber = Lara.rightArm.frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; Lara.leftArm.frameNumber = Lara.rightArm.frameNumber = item->frameNumber - g_Level.Anims[item->animNumber].frameBase;
Lara.leftArm.animNumber = Lara.rightArm.animNumber = item->animNumber; Lara.leftArm.animNumber = Lara.rightArm.animNumber = item->animNumber;
} }
@ -1068,7 +1015,7 @@ enum CROSSBOW_TYPE
void ControlCrossbowBolt(short itemNumber) void ControlCrossbowBolt(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
int oldX = item->pos.xPos; int oldX = item->pos.xPos;
int oldY = item->pos.yPos; int oldY = item->pos.yPos;
@ -1078,7 +1025,7 @@ void ControlCrossbowBolt(short itemNumber)
bool land = false; bool land = false;
bool explode = false; bool explode = false;
if (Rooms[roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_WATER)
{ {
PHD_VECTOR bubblePos(item->pos.xPos, item->pos.yPos, item->pos.zPos); PHD_VECTOR bubblePos(item->pos.xPos, item->pos.yPos, item->pos.zPos);
if (item->speed > 64) if (item->speed > 64)
@ -1125,9 +1072,9 @@ void ControlCrossbowBolt(short itemNumber)
ItemNewRoom(itemNumber, roomNumber); ItemNewRoom(itemNumber, roomNumber);
// If now in water and before in land, add a ripple // If now in water and before in land, add a ripple
if ((Rooms[item->roomNumber].flags & ENV_FLAG_WATER) && land) if ((g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER) && land)
{ {
SetupRipple(item->pos.xPos, Rooms[item->roomNumber].minfloor, item->pos.zPos, (GetRandomControl() & 7) + 8, 0); SetupRipple(item->pos.xPos, g_Level.Rooms[item->roomNumber].minfloor, item->pos.zPos, (GetRandomControl() & 7) + 8, 0);
} }
int radius = (explode ? CROSSBOW_EXPLODE_RADIUS : CROSSBOW_HIT_RADIUS); int radius = (explode ? CROSSBOW_EXPLODE_RADIUS : CROSSBOW_HIT_RADIUS);
@ -1242,7 +1189,7 @@ void ControlCrossbowBolt(short itemNumber)
} }
// At this point, for sure bolt must explode // At this point, for sure bolt must explode
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
TriggerUnderwaterExplosion(item); TriggerUnderwaterExplosion(item);
} }
@ -1299,11 +1246,6 @@ void RifleHandler(int weaponType)
if (weaponType == WEAPON_SHOTGUN || weaponType == WEAPON_HK) if (weaponType == WEAPON_SHOTGUN || weaponType == WEAPON_HK)
{ {
PHD_VECTOR pos = {}; PHD_VECTOR pos = {};
/*
pos.x = GetRandomControl() - 128;
pos.y = (GetRandomControl() & 0x7F) - 63;
pos.z = GetRandomControl() - 128;
*/
pos.y = -64; pos.y = -64;
GetLaraJointPosition(&pos, LM_RHAND); GetLaraJointPosition(&pos, LM_RHAND);
TriggerDynamicLight( TriggerDynamicLight(
@ -1319,11 +1261,6 @@ void RifleHandler(int weaponType)
else if (weaponType == WEAPON_REVOLVER) else if (weaponType == WEAPON_REVOLVER)
{ {
PHD_VECTOR pos = {}; PHD_VECTOR pos = {};
/*
pos.x = GetRandomControl() - 128;
pos.y = (GetRandomControl() & 0x7F) - 63;
pos.z = GetRandomControl() - 128;
*/
pos.y = -32; pos.y = -32;
GetLaraJointPosition(&pos, LM_RHAND); GetLaraJointPosition(&pos, LM_RHAND);
TriggerDynamicLight(pos.x, pos.y, pos.z, 12, (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 128, (GetRandomControl() & 0x3F)); TriggerDynamicLight(pos.x, pos.y, pos.z, 12, (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 128, (GetRandomControl() & 0x3F));
@ -1342,7 +1279,7 @@ void FireCrossbow(PHD_3DPOS* pos)
short itemNumber = CreateItem(); short itemNumber = CreateItem();
if (itemNumber != NO_ITEM) if (itemNumber != NO_ITEM)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = ID_CROSSBOW_BOLT; item->objectNumber = ID_CROSSBOW_BOLT;
item->shade = 0xC210; item->shade = 0xC210;
if (pos) if (pos)
@ -1425,7 +1362,7 @@ void DoGrenadeDamageOnBaddie(ITEM_INFO* dest, ITEM_INFO* src)
{ {
dest->hitStatus = true; dest->hitStatus = true;
ObjectInfo* obj = &Objects[dest->objectNumber]; OBJECT_INFO* obj = &Objects[dest->objectNumber];
if (!obj->undead) if (!obj->undead)
{ {
HitTarget(dest, 0, 30, 1); HitTarget(dest, 0, 30, 1);
@ -1435,7 +1372,7 @@ void DoGrenadeDamageOnBaddie(ITEM_INFO* dest, ITEM_INFO* src)
if (src->hitPoints <= 0) if (src->hitPoints <= 0)
{ {
++Savegame.Level.Kills; ++Savegame.Level.Kills;
CreatureDie((dest - Items), 1); CreatureDie((dest - g_Level.Items.data()), 1);
} }
} }
} }
@ -1444,7 +1381,7 @@ void DoGrenadeDamageOnBaddie(ITEM_INFO* dest, ITEM_INFO* src)
else else
{ {
LaraItem->hitPoints -= 50; LaraItem->hitPoints -= 50;
if (!(Rooms[dest->roomNumber].flags & ENV_FLAG_WATER) && LaraItem->hitPoints <= 50) if (!(g_Level.Rooms[dest->roomNumber].flags & ENV_FLAG_WATER) && LaraItem->hitPoints <= 50)
LaraBurn(); LaraBurn();
} }
} }
@ -1479,7 +1416,7 @@ void TriggerUnderwaterExplosion(ITEM_INFO* item)
void undraw_shotgun(int weapon) void undraw_shotgun(int weapon)
{ {
ITEM_INFO* item = &Items[Lara.weaponItem]; ITEM_INFO* item = &g_Level.Items[Lara.weaponItem];
item->goalAnimState = 3; item->goalAnimState = 3;
AnimateItem(item); AnimateItem(item);
@ -1495,29 +1432,31 @@ void undraw_shotgun(int weapon)
Lara.rightArm.frameNumber = 0; Lara.rightArm.frameNumber = 0;
Lara.leftArm.frameNumber = 0; Lara.leftArm.frameNumber = 0;
} }
else if (item->currentAnimState == 3 && item->frameNumber - Anims[item->animNumber].frameBase == 21) else if (item->currentAnimState == 3 && item->frameNumber - g_Level.Anims[item->animNumber].frameBase == 21)
{ {
undraw_shotgun_meshes(weapon); undraw_shotgun_meshes(weapon);
} }
Lara.rightArm.frameBase = Anims[item->animNumber].framePtr; Lara.rightArm.frameBase = g_Level.Anims[item->animNumber].framePtr;
Lara.leftArm.frameBase = Anims[item->animNumber].framePtr; Lara.leftArm.frameBase = g_Level.Anims[item->animNumber].framePtr;
Lara.rightArm.frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; Lara.rightArm.frameNumber = item->frameNumber - g_Level.Anims[item->animNumber].frameBase;
Lara.leftArm.frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; Lara.leftArm.frameNumber = item->frameNumber - g_Level.Anims[item->animNumber].frameBase;
Lara.rightArm.animNumber = item->animNumber; Lara.rightArm.animNumber = item->animNumber;
Lara.leftArm.animNumber = Lara.rightArm.animNumber; Lara.leftArm.animNumber = Lara.rightArm.animNumber;
} }
void undraw_shotgun_meshes(int weapon) void undraw_shotgun_meshes(int weapon)
{ {
Lara.backGun = WeaponObject(weapon); Lara.holsterInfo.backHolster = HolsterSlotForWeapon(static_cast<LARA_WEAPON_TYPE>(weapon));
LARA_MESHES(ID_LARA, LM_RHAND); //LARA_MESHES(ID_LARA, LM_RHAND);
Lara.meshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND;
} }
void draw_shotgun_meshes(int weaponType) void draw_shotgun_meshes(int weaponType)
{ {
Lara.backGun = WEAPON_NONE; Lara.holsterInfo.backHolster = HOLSTER_SLOT::Empty;
LARA_MESHES(WeaponObjectMesh(weaponType), LM_RHAND); //LARA_MESHES(WeaponObjectMesh(weaponType), LM_RHAND);
Lara.meshPtrs[LM_RHAND] = Objects[WeaponObjectMesh(weaponType)].meshIndex + LM_RHAND;
} }
void DoCrossbowDamage(ITEM_INFO* item1, ITEM_INFO* item2, signed int search) void DoCrossbowDamage(ITEM_INFO* item1, ITEM_INFO* item2, signed int search)
@ -1597,8 +1536,8 @@ void DoCrossbowDamage(ITEM_INFO* item1, ITEM_INFO* item2, signed int search)
AddActiveItem(*v16); AddActiveItem(*v16);
v17 = *v16; v17 = *v16;
--v16; --v16;
Items[v17]._bf15ea = Items[v17]._bf15ea & 0xFFFFFFFB | 2; Items[v17]._bf15ea = g_Level.Items[v17]._bf15ea & 0xFFFFFFFB | 2;
HIBYTE(Items[v16[1]].flags) |= 0x3Eu; HIBYTE(g_Level.Items[v16[1]].flags) |= 0x3Eu;
--v15; --v15;
} while (v15); } while (v15);
} }
@ -1612,6 +1551,7 @@ void DoCrossbowDamage(ITEM_INFO* item1, ITEM_INFO* item2, signed int search)
item2->status = ITEM_ACTIVE; item2->status = ITEM_ACTIVE;
} }
}*/ }*/
// what is this 2.0
} }
void FireHK(int mode) void FireHK(int mode)

View file

@ -11,7 +11,6 @@
#include "input.h" #include "input.h"
#include "sound.h" #include "sound.h"
#include "savegame.h" #include "savegame.h"
struct PISTOL_DEF struct PISTOL_DEF
{ {
short objectNum; short objectNum;
@ -33,7 +32,7 @@ bool UziRight;
void AnimatePistols(int weaponType) void AnimatePistols(int weaponType)
{ {
PISTOL_DEF* p = &PistolsTable[Lara.gunType]; PISTOL_DEF* p = &PistolsTable[static_cast<int>(Lara.gunType)];
WEAPON_INFO* weapon = &Weapons[weaponType]; WEAPON_INFO* weapon = &Weapons[weaponType];
int soundPlayed = false; int soundPlayed = false;
short angleLeft[2], angleRight[2]; short angleLeft[2], angleRight[2];
@ -44,19 +43,19 @@ void AnimatePistols(int weaponType)
{ {
PHD_VECTOR pos; PHD_VECTOR pos;
switch (SmokeWeapon) switch (static_cast<LARA_WEAPON_TYPE>(SmokeWeapon))
{ {
case WEAPON_PISTOLS: case LARA_WEAPON_TYPE::WEAPON_PISTOLS:
pos.x = 4; pos.x = 4;
pos.y = 128; pos.y = 128;
pos.z = 40; pos.z = 40;
break; break;
case WEAPON_REVOLVER: case LARA_WEAPON_TYPE::WEAPON_REVOLVER:
pos.x = 16; pos.x = 16;
pos.y = 160; pos.y = 160;
pos.z = 56; pos.z = 56;
break; break;
case WEAPON_UZI: case LARA_WEAPON_TYPE::WEAPON_UZI:
pos.x = 8; pos.x = 8;
pos.y = 140; pos.y = 140;
pos.z = 48; pos.z = 48;
@ -71,19 +70,19 @@ void AnimatePistols(int weaponType)
{ {
PHD_VECTOR pos; PHD_VECTOR pos;
switch (SmokeWeapon) switch (static_cast<LARA_WEAPON_TYPE>(SmokeWeapon))
{ {
case WEAPON_PISTOLS: case LARA_WEAPON_TYPE::WEAPON_PISTOLS:
pos.x = -16; pos.x = -16;
pos.y = 128; pos.y = 128;
pos.z = 40; pos.z = 40;
break; break;
case WEAPON_REVOLVER: case LARA_WEAPON_TYPE::WEAPON_REVOLVER:
pos.x = -32; pos.x = -32;
pos.y = 160; pos.y = 160;
pos.z = 56; pos.z = 56;
break; break;
case WEAPON_UZI: case LARA_WEAPON_TYPE::WEAPON_UZI:
pos.x = -16; pos.x = -16;
pos.y = 140; pos.y = 140;
pos.z = 48; pos.z = 48;
@ -112,7 +111,7 @@ void AnimatePistols(int weaponType)
// actually shoot, bang bang // actually shoot, bang bang
if (TrInput & IN_ACTION) if (TrInput & IN_ACTION)
{ {
if (weaponType != WEAPON_REVOLVER) if (static_cast<LARA_WEAPON_TYPE>(weaponType) != LARA_WEAPON_TYPE::WEAPON_REVOLVER)
{ {
angleRight[0] = Lara.rightArm.yRot + LaraItem->pos.yRot; angleRight[0] = Lara.rightArm.yRot + LaraItem->pos.yRot;
angleRight[1] = Lara.rightArm.xRot; angleRight[1] = Lara.rightArm.xRot;
@ -129,7 +128,7 @@ void AnimatePistols(int weaponType)
SoundEffect(weapon->sampleNum, &LaraItem->pos, 0); SoundEffect(weapon->sampleNum, &LaraItem->pos, 0);
soundPlayed = true; soundPlayed = true;
if (weaponType == WEAPON_UZI) if (static_cast<LARA_WEAPON_TYPE>(weaponType) == LARA_WEAPON_TYPE::WEAPON_UZI)
UziRight = true; UziRight = true;
Savegame.Game.AmmoUsed++; Savegame.Game.AmmoUsed++;
@ -148,7 +147,7 @@ void AnimatePistols(int weaponType)
// at or beyond (3) SHOOT_CONTINUE start frame // at or beyond (3) SHOOT_CONTINUE start frame
else if (frameRight >= p->recoilAnim) else if (frameRight >= p->recoilAnim)
{ {
if (weaponType == WEAPON_UZI) if (static_cast<LARA_WEAPON_TYPE>(weaponType) == LARA_WEAPON_TYPE::WEAPON_UZI)
{ {
SoundEffect(weapon->sampleNum, &LaraItem->pos, 0); SoundEffect(weapon->sampleNum, &LaraItem->pos, 0);
UziRight = true; UziRight = true;
@ -207,10 +206,10 @@ void AnimatePistols(int weaponType)
if (FireWeapon(weaponType, Lara.target, LaraItem, angleLeft)) if (FireWeapon(weaponType, Lara.target, LaraItem, angleLeft))
{ {
if (weaponType == WEAPON_REVOLVER) if (static_cast<LARA_WEAPON_TYPE>(weaponType) == LARA_WEAPON_TYPE::WEAPON_REVOLVER)
{ {
SmokeCountR = 28; SmokeCountR = 28;
SmokeWeapon = WEAPON_REVOLVER; SmokeWeapon = static_cast<int>(LARA_WEAPON_TYPE::WEAPON_REVOLVER);
Lara.rightArm.flash_gun = weapon->flashTime; Lara.rightArm.flash_gun = weapon->flashTime;
} }
else else
@ -227,7 +226,7 @@ void AnimatePistols(int weaponType)
SoundEffect(weapon->sampleNum, &LaraItem->pos, 0); SoundEffect(weapon->sampleNum, &LaraItem->pos, 0);
} }
if (weaponType == WEAPON_UZI) if (static_cast<LARA_WEAPON_TYPE>(weaponType) == LARA_WEAPON_TYPE::WEAPON_UZI)
UziLeft = true; UziLeft = true;
Savegame.Game.AmmoUsed++; Savegame.Game.AmmoUsed++;
@ -243,7 +242,7 @@ void AnimatePistols(int weaponType)
} }
else if (frameLeft >= p->recoilAnim) else if (frameLeft >= p->recoilAnim)
{ {
if (weaponType == WEAPON_UZI) if (static_cast<LARA_WEAPON_TYPE>(weaponType) == LARA_WEAPON_TYPE::WEAPON_UZI)
{ {
SoundEffect(weapon->sampleNum, &LaraItem->pos, 0); SoundEffect(weapon->sampleNum, &LaraItem->pos, 0);
UziLeft = true; UziLeft = true;
@ -335,64 +334,38 @@ void PistolHandler(int weaponType)
pos.z = (byte)GetRandomControl() - 128; pos.z = (byte)GetRandomControl() - 128;
GetLaraJointPosition(&pos, Lara.leftArm.flash_gun != 0 ? LM_LHAND : LM_RHAND); GetLaraJointPosition(&pos, Lara.leftArm.flash_gun != 0 ? LM_LHAND : LM_RHAND);
/*if (gfLevelFlags & 0x2000 && LaraItem->roomNumber == gfMirrorRoom)
{
v8 = GetRandomControl() & 0x3F;
v9 = (GetRandomControl() & 0x1F) + 128;
v10 = GetRandomControl();
sub_4015A5(v14, v15, v16, 10, (v10 & 0x3F) + 192, v9, v8); // TODO: TriggerDynamicLightMirror !
}
else
{*/
TriggerDynamicLight(pos.x+frandMinMax(-128,128), pos.y + frandMinMax(-128, 128), pos.z + frandMinMax(-128, 128), frandMinMax(8,11), (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 128, GetRandomControl() & 0x3F); TriggerDynamicLight(pos.x+frandMinMax(-128,128), pos.y + frandMinMax(-128, 128), pos.z + frandMinMax(-128, 128), frandMinMax(8,11), (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 128, GetRandomControl() & 0x3F);
//}
} }
} }
void undraw_pistol_mesh_right(int weaponType) void undraw_pistol_mesh_right(int weaponType)
{ {
LARA_MESHES(ID_LARA, LM_RHAND); Lara.meshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND;
switch (weaponType) Lara.holsterInfo.rightHolster = HolsterSlotForWeapon(static_cast<LARA_WEAPON_TYPE>(weaponType));
{
case WEAPON_PISTOLS:
Lara.holster = ID_LARA_HOLSTERS_PISTOLS;
break;
case WEAPON_UZI:
Lara.holster = ID_LARA_HOLSTERS_UZIS;
break;
case WEAPON_REVOLVER:
Lara.holster = ID_LARA_HOLSTERS_REVOLVER;
break;
}
} }
void undraw_pistol_mesh_left(int weaponType) void undraw_pistol_mesh_left(int weaponType)
{ {
if (weaponType != WEAPON_REVOLVER) if (static_cast<LARA_WEAPON_TYPE>(weaponType) != LARA_WEAPON_TYPE::WEAPON_REVOLVER)
{ {
LARA_MESHES(ID_LARA, LM_LHAND); Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND;
switch (weaponType) Lara.holsterInfo.leftHolster = HolsterSlotForWeapon(static_cast<LARA_WEAPON_TYPE>(weaponType));
{
case WEAPON_PISTOLS:
Lara.holster = ID_LARA_HOLSTERS_PISTOLS;
break;
case WEAPON_UZI:
Lara.holster = ID_LARA_HOLSTERS_UZIS;
break;
}
} }
} }
void draw_pistol_meshes(int weaponType) void draw_pistol_meshes(int weaponType)
{ {
Lara.holster = ID_LARA_HOLSTERS; if(static_cast<LARA_WEAPON_TYPE>(weaponType) != LARA_WEAPON_TYPE::WEAPON_REVOLVER){
Lara.holsterInfo.leftHolster = HOLSTER_SLOT::Empty;
}
Lara.holsterInfo.rightHolster = HOLSTER_SLOT::Empty;
LARA_MESHES(WeaponObjectMesh(weaponType), LM_RHAND); Lara.meshPtrs[LM_RHAND] = Objects[WeaponObjectMesh(weaponType)].meshIndex + LM_RHAND;
if (weaponType != WEAPON_REVOLVER) if (static_cast<LARA_WEAPON_TYPE>(weaponType) != LARA_WEAPON_TYPE::WEAPON_REVOLVER)
LARA_MESHES(WeaponObjectMesh(weaponType), LM_LHAND); Lara.meshPtrs[LM_LHAND] = Objects[WeaponObjectMesh(weaponType)].meshIndex + LM_LHAND;
} }
void ready_pistols(int weaponType) void ready_pistols(int weaponType)
@ -415,7 +388,7 @@ void ready_pistols(int weaponType)
void undraw_pistols(int weaponType) void undraw_pistols(int weaponType)
{ {
PISTOL_DEF* p = &PistolsTable[Lara.gunType]; PISTOL_DEF* p = &PistolsTable[static_cast<int>(Lara.gunType)];
WEAPON_INFO* weapon = &Weapons[weaponType]; WEAPON_INFO* weapon = &Weapons[weaponType];
short frameLeft = Lara.leftArm.frameNumber; short frameLeft = Lara.leftArm.frameNumber;
@ -514,7 +487,7 @@ void undraw_pistols(int weaponType)
void set_arm_info(LARA_ARM* arm, int frame) void set_arm_info(LARA_ARM* arm, int frame)
{ {
PISTOL_DEF* p = &PistolsTable[Lara.gunType]; PISTOL_DEF* p = &PistolsTable[static_cast<int>(Lara.gunType)];
short animBase = Objects[p->objectNum].animIndex; short animBase = Objects[p->objectNum].animIndex;
if (frame < p->draw1Anim) if (frame < p->draw1Anim)
@ -527,13 +500,13 @@ void set_arm_info(LARA_ARM* arm, int frame)
arm->animNumber = animBase + 3; arm->animNumber = animBase + 3;
arm->frameNumber = frame; arm->frameNumber = frame;
arm->frameBase = Anims[arm->animNumber].framePtr; arm->frameBase = g_Level.Anims[arm->animNumber].framePtr;
} }
void draw_pistols(int weaponType) void draw_pistols(int weaponType)
{ {
short frame = Lara.leftArm.frameNumber + 1; short frame = Lara.leftArm.frameNumber + 1;
PISTOL_DEF* p = &PistolsTable[Lara.gunType]; PISTOL_DEF* p = &PistolsTable[static_cast<int>(Lara.gunType)];
if (frame < p->draw1Anim || frame > p->recoilAnim - 1) if (frame < p->draw1Anim || frame > p->recoilAnim - 1)
{ {

File diff suppressed because it is too large Load diff

View file

@ -55,10 +55,10 @@ void lara_as_climbend(ITEM_INFO* item, COLL_INFO* coll)//46DF8(<), 4725C(<) (F)
void lara_col_climbdown(ITEM_INFO* item, COLL_INFO* coll)//46BD0, 47034 (F) void lara_col_climbdown(ITEM_INFO* item, COLL_INFO* coll)//46BD0, 47034 (F)
{ {
if (LaraCheckForLetGo(item, coll) if (LaraCheckForLetGo(item, coll)
|| item->animNumber != ANIMATION_LARA_LADDER_DOWN) || item->animNumber != LA_LADDER_DOWN)
return; return;
int frame = item->frameNumber - Anims[ANIMATION_LARA_LADDER_DOWN].frameBase; int frame = item->frameNumber - g_Level.Anims[LA_LADDER_DOWN].frameBase;
int xShift; int xShift;
int yShift; int yShift;
@ -98,7 +98,7 @@ void lara_col_climbdown(ITEM_INFO* item, COLL_INFO* coll)//46BD0, 47034 (F)
{ {
if (shiftRight < 0 != shiftLeft < 0) if (shiftRight < 0 != shiftLeft < 0)
{ {
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
AnimateLara(item); AnimateLara(item);
return; return;
} }
@ -112,22 +112,22 @@ void lara_col_climbdown(ITEM_INFO* item, COLL_INFO* coll)//46BD0, 47034 (F)
if (resultRight == -1 || resultLeft == -1) if (resultRight == -1 || resultLeft == -1)
{ {
item->animNumber = ANIMATION_LARA_LADDER_IDLE; item->animNumber = LA_LADDER_IDLE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = STATE_LARA_LADDER_IDLE; item->currentAnimState = LS_LADDER_IDLE;
item->goalAnimState = STATE_LARA_HANG; item->goalAnimState = LS_HANG;
AnimateLara(item); AnimateLara(item);
} }
else else
{ {
item->goalAnimState = STATE_LARA_LADDER_DOWN; item->goalAnimState = LS_LADDER_DOWN;
item->pos.yPos -= yShift; item->pos.yPos -= yShift;
} }
return; return;
} }
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
if (yShift != 0) if (yShift != 0)
AnimateLara(item); AnimateLara(item);
@ -144,9 +144,9 @@ void lara_as_climbdown(ITEM_INFO* item, COLL_INFO* coll)//46BA4(<), 47008(<) (F)
void lara_col_climbing(ITEM_INFO* item, COLL_INFO* coll)//469B0, 46E14 (F) void lara_col_climbing(ITEM_INFO* item, COLL_INFO* coll)//469B0, 46E14 (F)
{ {
if (!LaraCheckForLetGo(item, coll) if (!LaraCheckForLetGo(item, coll)
&& item->animNumber == ANIMATION_LARA_LADDER_UP) && item->animNumber == LA_LADDER_UP)
{ {
int frame = item->frameNumber - Anims[ANIMATION_LARA_LADDER_UP].frameBase; int frame = item->frameNumber - g_Level.Anims[LA_LADDER_UP].frameBase;
int yShift; int yShift;
int resultRight, resultLeft; int resultRight, resultLeft;
int shiftRight, shiftLeft; int shiftRight, shiftLeft;
@ -180,7 +180,7 @@ void lara_col_climbing(ITEM_INFO* item, COLL_INFO* coll)//469B0, 46E14 (F)
{ {
if (resultRight < 0 || resultLeft < 0) if (resultRight < 0 || resultLeft < 0)
{ {
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
AnimateLara(item); AnimateLara(item);
@ -188,25 +188,25 @@ void lara_col_climbing(ITEM_INFO* item, COLL_INFO* coll)//469B0, 46E14 (F)
{ {
if (resultRight != -1 || resultLeft != -1) if (resultRight != -1 || resultLeft != -1)
{ {
item->goalAnimState = STATE_LARA_UNKNOWN_138; item->goalAnimState = LS_UNKNOWN_6;
item->requiredAnimState = STATE_LARA_CROUCH_IDLE; item->requiredAnimState = LS_CROUCH_IDLE;
} }
else else
{ {
item->goalAnimState = STATE_LARA_GRABBING; item->goalAnimState = LS_GRABBING;
item->pos.yPos += (ledgeRight + ledgeLeft) / 2 - 256; item->pos.yPos += (ledgeRight + ledgeLeft) / 2 - 256;
} }
} }
} }
else else
{ {
item->goalAnimState = STATE_LARA_LADDER_UP; item->goalAnimState = LS_LADDER_UP;
item->pos.yPos -= yShift; item->pos.yPos -= yShift;
} }
} }
else else
{ {
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
if (yShift != 0) if (yShift != 0)
AnimateLara(item); AnimateLara(item);
@ -241,7 +241,7 @@ void lara_as_climbright(ITEM_INFO* item, COLL_INFO* coll)//468B8(<), 46D1C(<) (F
Camera.targetElevation = -ANGLE(15); Camera.targetElevation = -ANGLE(15);
if (!(TrInput & (IN_RIGHT | IN_RSTEP))) if (!(TrInput & (IN_RIGHT | IN_RSTEP)))
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
} }
void lara_col_climbleft(ITEM_INFO* item, COLL_INFO* coll)//46834(<), 46C98(<) (F) void lara_col_climbleft(ITEM_INFO* item, COLL_INFO* coll)//46834(<), 46C98(<) (F)
@ -263,7 +263,7 @@ void lara_as_climbleft(ITEM_INFO* item, COLL_INFO* coll)//467E4(<), 46C48(<) (F)
Camera.targetElevation = -ANGLE(15); Camera.targetElevation = -ANGLE(15);
if (!(TrInput & (IN_LEFT | IN_LSTEP))) if (!(TrInput & (IN_LEFT | IN_LSTEP)))
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
} }
void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
@ -274,7 +274,7 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
int ledgeRight, ledgeLeft; int ledgeRight, ledgeLeft;
if (LaraCheckForLetGo(item, coll) if (LaraCheckForLetGo(item, coll)
|| item->animNumber != ANIMATION_LARA_LADDER_IDLE) || item->animNumber != LA_LADDER_IDLE)
return; return;
if (!(TrInput & IN_FORWARD)) if (!(TrInput & IN_FORWARD))
@ -282,10 +282,10 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
if (!(TrInput & IN_BACK)) if (!(TrInput & IN_BACK))
return; return;
if (item->goalAnimState == STATE_LARA_HANG) if (item->goalAnimState == LS_HANG)
return; return;
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
item->pos.yPos += 256; item->pos.yPos += 256;
resultRight = LaraTestClimbPos(item, coll->radius, coll->radius + 120, -512, 512, &ledgeRight); resultRight = LaraTestClimbPos(item, coll->radius, coll->radius + 120, -512, 512, &ledgeRight);
@ -308,17 +308,17 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
if (resultRight == 1 && resultLeft == 1) if (resultRight == 1 && resultLeft == 1)
{ {
item->goalAnimState = STATE_LARA_LADDER_DOWN; item->goalAnimState = LS_LADDER_DOWN;
item->pos.yPos += yShift; item->pos.yPos += yShift;
} }
else else
{ {
item->goalAnimState = STATE_LARA_HANG; item->goalAnimState = LS_HANG;
} }
} }
else if (item->goalAnimState != STATE_LARA_GRABBING) else if (item->goalAnimState != LS_GRABBING)
{ {
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
resultRight = LaraTestClimbUpPos(item, coll->radius, coll->radius + 120, &shiftRight, &ledgeRight); resultRight = LaraTestClimbUpPos(item, coll->radius, coll->radius + 120, &shiftRight, &ledgeRight);
resultLeft = LaraTestClimbUpPos(item, coll->radius, -120 - coll->radius, &shiftLeft, &ledgeLeft); resultLeft = LaraTestClimbUpPos(item, coll->radius, -120 - coll->radius, &shiftLeft, &ledgeLeft);
@ -344,20 +344,20 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
} }
} }
item->goalAnimState = STATE_LARA_LADDER_UP; item->goalAnimState = LS_LADDER_UP;
item->pos.yPos += yShift; item->pos.yPos += yShift;
} }
else if (abs(ledgeLeft - ledgeRight) <= 120) else if (abs(ledgeLeft - ledgeRight) <= 120)
{ {
if (resultRight == -1 && resultLeft == -1) if (resultRight == -1 && resultLeft == -1)
{ {
item->goalAnimState = STATE_LARA_GRABBING; item->goalAnimState = LS_GRABBING;
item->pos.yPos += (ledgeRight + ledgeLeft) / 2 - 256; item->pos.yPos += (ledgeRight + ledgeLeft) / 2 - 256;
} }
else else
{ {
item->goalAnimState = STATE_LARA_UNKNOWN_138; item->goalAnimState = LS_UNKNOWN_6;
item->requiredAnimState = STATE_LARA_CROUCH_IDLE; item->requiredAnimState = LS_CROUCH_IDLE;
} }
} }
} }
@ -372,6 +372,11 @@ void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll)//463F0, 46854 (F)
Camera.targetElevation = -ANGLE(20); Camera.targetElevation = -ANGLE(20);
if (item->animNumber == LA_LADDER_DISMOUNT_LEFT_START)
Camera.targetAngle = -ANGLE(60.0f);
if (item->animNumber == LA_LADDER_DISMOUNT_RIGHT_START)
Camera.targetAngle = ANGLE(60.0f);
if (TrInput & IN_LOOK) if (TrInput & IN_LOOK)
{ {
LookUpDown(); LookUpDown();
@ -379,25 +384,47 @@ void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll)//463F0, 46854 (F)
if (TrInput & IN_LEFT || TrInput & IN_LSTEP) if (TrInput & IN_LEFT || TrInput & IN_LSTEP)
{ {
item->goalAnimState = STATE_LARA_LADDER_LEFT; item->goalAnimState = LS_LADDER_LEFT;
Lara.moveAngle = -ANGLE(90); Lara.moveAngle = -ANGLE(90);
} }
else if (TrInput & IN_RIGHT || TrInput & IN_RSTEP) else if (TrInput & IN_RIGHT || TrInput & IN_RSTEP)
{ {
item->goalAnimState = STATE_LARA_LADDER_RIGHT; item->goalAnimState = LS_LADDER_RIGHT;
Lara.moveAngle = ANGLE(90); Lara.moveAngle = ANGLE(90);
} }
else if (TrInput & IN_JUMP) else if (TrInput & IN_JUMP)
{ {
if (item->animNumber == ANIMATION_LARA_LADDER_IDLE) if (item->animNumber == LA_LADDER_IDLE)
{ {
item->goalAnimState = STATE_LARA_JUMP_BACK; item->goalAnimState = LS_JUMP_BACK;
Lara.gunStatus = LG_NO_ARMS; Lara.gunStatus = LG_NO_ARMS;
Lara.moveAngle = ANGLE(180); Lara.moveAngle = ANGLE(180);
} }
} }
} }
void lara_as_stepoff_left(ITEM_INFO* item, COLL_INFO* coll)
{
coll->enableBaddiePush = false;
coll->enableSpaz = false;
Camera.targetAngle = -ANGLE(60.0f);
Camera.targetElevation = -ANGLE(15.0f);
item->pos.yRot -= ANGLE(90.0f);
}
void lara_as_stepoff_right(ITEM_INFO* item, COLL_INFO* coll)
{
coll->enableBaddiePush = false;
coll->enableSpaz = false;
Camera.targetAngle = ANGLE(60.0f);
Camera.targetElevation = -ANGLE(15.0f);
item->pos.yRot += ANGLE(90.0f);
}
int LaraTestClimbPos(ITEM_INFO* item, int front, int right, int origin, int height, int* shift) // (F) (D) int LaraTestClimbPos(ITEM_INFO* item, int front, int right, int origin, int height, int* shift) // (F) (D)
{ {
int x; int x;
@ -442,15 +469,15 @@ void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shif
{ {
if (TrInput & IN_LEFT) if (TrInput & IN_LEFT)
{ {
item->goalAnimState = STATE_LARA_LADDER_LEFT; item->goalAnimState = LS_LADDER_LEFT;
} }
else if (TrInput & IN_RIGHT) else if (TrInput & IN_RIGHT)
{ {
item->goalAnimState = STATE_LARA_LADDER_RIGHT; item->goalAnimState = LS_LADDER_RIGHT;
} }
else else
{ {
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
} }
item->pos.yPos += shift; item->pos.yPos += shift;
@ -460,12 +487,12 @@ void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shif
if (result != 0) if (result != 0)
{ {
item->goalAnimState = STATE_LARA_HANG; item->goalAnimState = LS_HANG;
do do
{ {
AnimateItem(item); AnimateItem(item);
} while (item->currentAnimState != STATE_LARA_HANG); } while (item->currentAnimState != LS_HANG);
item->pos.xPos = coll->old.x; item->pos.xPos = coll->old.x;
item->pos.zPos = coll->old.z; item->pos.zPos = coll->old.z;
@ -476,16 +503,43 @@ void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shif
item->pos.xPos = coll->old.x; item->pos.xPos = coll->old.x;
item->pos.zPos = coll->old.z; item->pos.zPos = coll->old.z;
item->goalAnimState = STATE_LARA_LADDER_IDLE; item->goalAnimState = LS_LADDER_IDLE;
item->currentAnimState = STATE_LARA_LADDER_IDLE; item->currentAnimState = LS_LADDER_IDLE;
if (coll->oldAnimState != STATE_LARA_LADDER_IDLE) if (coll->oldAnimState != LS_LADDER_IDLE)
{ {
item->animNumber = ANIMATION_LARA_LADDER_IDLE; item->animNumber = LA_LADDER_IDLE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
return; return;
} }
if (TrInput & IN_LEFT)
{
short troomnumber = item->roomNumber;
int dx = int(sin(TO_RAD(item->pos.yRot - ANGLE(90.0f))) * 10);
int dz = int(cos(TO_RAD(item->pos.yRot - ANGLE(90.0f))) * 10);
int height = GetFloorHeight(GetFloor(item->pos.xPos + dx, item->pos.yPos, item->pos.zPos + dz, &troomnumber),
item->pos.xPos, item->pos.yPos, item->pos.zPos) - item->pos.yPos;
if (height < 3 * STEP_SIZE / 2) // LADDER dismounts (left/right)
{
item->goalAnimState = LS_LADDER_DISMOUNT_LEFT;
item->currentAnimState = LS_MISC_CONTROL;
}
}
else if (TrInput & IN_RIGHT)
{
short troomnumber = item->roomNumber;
int dx = int(sin(TO_RAD(item->pos.yRot + ANGLE(90.0f))) * 10);
int dz = int(cos(TO_RAD(item->pos.yRot + ANGLE(90.0f))) * 10);
int height = GetFloorHeight(GetFloor(item->pos.xPos + dx, item->pos.yPos, item->pos.zPos + dz, &troomnumber),
item->pos.xPos, item->pos.yPos, item->pos.zPos) - item->pos.yPos;
if (height < 3 * STEP_SIZE / 2) // LADDER dismounts (left/right)
{
item->goalAnimState = LS_LADDER_DISMOUNT_RIGHT;
item->currentAnimState = LS_MISC_CONTROL;
}
}
if (TrInput & IN_LEFT) if (TrInput & IN_LEFT)
{ {
int flag = LaraClimbLeftCornerTest(item, coll); int flag = LaraClimbLeftCornerTest(item, coll);
@ -494,17 +548,17 @@ void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shif
{ {
if (flag <= 0) if (flag <= 0)
{ {
item->animNumber = ANIMATION_LARA_LADDER_AROUND_LEFT_INNER_BEGIN; item->animNumber = LA_LADDER_LEFT_CORNER_INNER_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_CLIMB_CORNER_LEFT_INNER; item->goalAnimState = LS_SHIMMY_INNER_LEFT;
item->currentAnimState = STATE_LARA_CLIMB_CORNER_LEFT_INNER; item->currentAnimState = LS_SHIMMY_INNER_LEFT;
} }
else else
{ {
item->animNumber = ANIMATION_LARA_LADDER_AROUND_LEFT_OUTER_BEGIN; item->animNumber = LA_LADDER_LEFT_CORNER_OUTER_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_CLIMB_CORNER_LEFT_OUTER; item->goalAnimState = LS_SHIMMY_OUTER_LEFT;
item->currentAnimState = STATE_LARA_CLIMB_CORNER_LEFT_OUTER; item->currentAnimState = LS_SHIMMY_OUTER_LEFT;
} }
return; return;
@ -518,17 +572,17 @@ void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shif
{ {
if (flag <= 0) if (flag <= 0)
{ {
item->animNumber = ANIMATION_LARA_LADDER_AROUND_RIGHT_INNER_BEGIN; item->animNumber = LA_LADDER_RIGHT_CORNER_INNER_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_CLIMB_CORNER_RIGHT_INNER; item->goalAnimState = LS_SHIMMY_INNER_RIGHT;
item->currentAnimState = STATE_LARA_CLIMB_CORNER_RIGHT_INNER; item->currentAnimState = LS_SHIMMY_INNER_RIGHT;
} }
else else
{ {
item->animNumber = ANIMATION_LARA_LADDER_AROUND_RIGHT_OUTER_BEGIN; item->animNumber = LA_LADDER_RIGHT_CORNER_OUTER_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_CLIMB_CORNER_RIGHT_OUTER; item->goalAnimState = LS_SHIMMY_OUTER_RIGHT;
item->currentAnimState = STATE_LARA_CLIMB_CORNER_RIGHT_OUTER; item->currentAnimState = LS_SHIMMY_OUTER_RIGHT;
} }
return; return;
@ -545,7 +599,7 @@ int LaraClimbRightCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45DE4, 46248
{ {
int result = 0; int result = 0;
if (item->animNumber != ANIMATION_LARA_LADDER_RIGHT) if (item->animNumber != LA_LADDER_RIGHT)
return 0; return 0;
int oldYrot = item->pos.yRot; int oldYrot = item->pos.yRot;
@ -643,7 +697,7 @@ int LaraClimbLeftCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45ABC, 45F20
{ {
int result = 0; int result = 0;
if (item->animNumber != ANIMATION_LARA_LADDER_LEFT) if (item->animNumber != LA_LADDER_LEFT)
return 0; return 0;
int oldYrot = item->pos.yRot; int oldYrot = item->pos.yRot;
@ -957,10 +1011,10 @@ int LaraCheckForLetGo(ITEM_INFO* item, COLL_INFO* coll)//45434, 45898 (F)
Lara.headYrot = 0; Lara.headYrot = 0;
Lara.headXrot = 0; Lara.headXrot = 0;
item->goalAnimState = STATE_LARA_JUMP_FORWARD; item->goalAnimState = LS_JUMP_FORWARD;
item->currentAnimState = STATE_LARA_JUMP_FORWARD; item->currentAnimState = LS_JUMP_FORWARD;
item->animNumber = ANIMATION_LARA_FREE_FALL_FORWARD; item->animNumber = LA_FALL_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->speed = 2; item->speed = 2;
item->gravityStatus = true; item->gravityStatus = true;

View file

@ -15,6 +15,8 @@ void lara_col_climbleft(ITEM_INFO* item, COLL_INFO* coll);
void lara_as_climbleft(ITEM_INFO* item, COLL_INFO* coll); void lara_as_climbleft(ITEM_INFO* item, COLL_INFO* coll);
void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll); void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll);
void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll); void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll);
void lara_as_stepoff_left(ITEM_INFO* item, COLL_INFO* coll);
void lara_as_stepoff_right(ITEM_INFO* item, COLL_INFO* coll);
int LaraTestClimbPos(ITEM_INFO* item, int front, int right, int origin, int height, int* shift); int LaraTestClimbPos(ITEM_INFO* item, int front, int right, int origin, int height, int* shift);
void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shift); void LaraDoClimbLeftRight(ITEM_INFO* item, COLL_INFO* coll, int result, int shift);

View file

@ -18,6 +18,7 @@
#include "sound.h" #include "sound.h"
#include "savegame.h" #include "savegame.h"
#include "GameFlowScript.h" #include "GameFlowScript.h"
#include "lara_struct.h"
WEAPON_INFO Weapons[NUM_WEAPONS] = WEAPON_INFO Weapons[NUM_WEAPONS] =
{ {
@ -219,23 +220,23 @@ WEAPON_INFO Weapons[NUM_WEAPONS] =
}; };
short HoldStates[] = { short HoldStates[] = {
STATE_LARA_WALK_FORWARD, LS_WALK_FORWARD,
STATE_LARA_RUN_FORWARD, LS_RUN_FORWARD,
STATE_LARA_STOP, LS_STOP,
STATE_LARA_POSE, LS_POSE,
STATE_LARA_TURN_RIGHT_SLOW, LS_TURN_RIGHT_SLOW,
STATE_LARA_TURN_LEFT_SLOW, LS_TURN_LEFT_SLOW,
STATE_LARA_WALK_BACK, LS_WALK_BACK,
STATE_LARA_TURN_FAST, LS_TURN_FAST,
STATE_LARA_WALK_RIGHT, LS_STEP_RIGHT,
STATE_LARA_WALK_LEFT, LS_STEP_LEFT,
STATE_LARA_PICKUP, LS_PICKUP,
STATE_LARA_SWITCH_DOWN, LS_SWITCH_DOWN,
STATE_LARA_SWITCH_UP, LS_SWITCH_UP,
STATE_LARA_WADE_FORWARD, LS_WADE_FORWARD,
STATE_LARA_CROUCH_IDLE, LS_CROUCH_IDLE,
STATE_LARA_CROUCH_TURN_LEFT, LS_CROUCH_TURN_LEFT,
STATE_LARA_CROUCH_TURN_RIGHT, LS_CROUCH_TURN_RIGHT,
-1 -1
}; };
@ -310,13 +311,13 @@ void AimWeapon(WEAPON_INFO* winfo, LARA_ARM* arm) // (F) (D)
rotX -= speed; rotX -= speed;
arm->xRot = rotX; arm->xRot = rotX;
// TODO: set arm rotations to inherit rotations of parent bones. -Sezz // TODO: set arm rotations to inherit rotations of parent Bones. -Sezz
arm->zRot = 0; arm->zRot = 0;
} }
void SmashItem(short itemNum) // (F) (D) void SmashItem(short itemNum) // (F) (D)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (item->objectNumber >= ID_SMASH_OBJECT1 && item->objectNumber <= ID_SMASH_OBJECT8) if (item->objectNumber >= ID_SMASH_OBJECT1 && item->objectNumber <= ID_SMASH_OBJECT8)
SmashObject(itemNum); SmashObject(itemNum);
} }
@ -346,7 +347,7 @@ void LaraGun() // (F) (D)
} }
else if (TrInput & IN_FLARE && (g_GameFlow->GetLevel(CurrentLevel)->LaraType != LARA_YOUNG)) else if (TrInput & IN_FLARE && (g_GameFlow->GetLevel(CurrentLevel)->LaraType != LARA_YOUNG))
{ {
if (LaraItem->currentAnimState == STATE_LARA_CROUCH_IDLE && LaraItem->animNumber != ANIMATION_LARA_CROUCH_IDLE) if (LaraItem->currentAnimState == LS_CROUCH_IDLE && LaraItem->animNumber != LA_CROUCH_IDLE)
return; return;
if (Lara.gunType == WEAPON_FLARE) if (Lara.gunType == WEAPON_FLARE)
@ -366,9 +367,9 @@ void LaraGun() // (F) (D)
if ((Lara.requestGunType != Lara.gunType) || (TrInput & IN_DRAW)) if ((Lara.requestGunType != Lara.gunType) || (TrInput & IN_DRAW))
{ {
if ((LaraItem->currentAnimState == STATE_LARA_CROUCH_IDLE if ((LaraItem->currentAnimState == LS_CROUCH_IDLE
|| LaraItem->currentAnimState == STATE_LARA_CROUCH_TURN_LEFT || LaraItem->currentAnimState == LS_CROUCH_TURN_LEFT
|| LaraItem->currentAnimState == STATE_LARA_CROUCH_TURN_RIGHT) || LaraItem->currentAnimState == LS_CROUCH_TURN_RIGHT)
&& (Lara.requestGunType == WEAPON_HK && (Lara.requestGunType == WEAPON_HK
|| Lara.requestGunType == WEAPON_CROSSBOW || Lara.requestGunType == WEAPON_CROSSBOW
#if 1 #if 1
@ -423,7 +424,7 @@ void LaraGun() // (F) (D)
#endif #endif
Lara.gunStatus = LG_UNDRAW_GUNS; Lara.gunStatus = LG_UNDRAW_GUNS;
} }
else if (Lara.gunStatus == LG_HANDS_BUSY && (TrInput & IN_FLARE) && LaraItem->currentAnimState == STATE_LARA_CRAWL_IDLE && LaraItem->animNumber == ANIMATION_LARA_CRAWL_IDLE) else if (Lara.gunStatus == LG_HANDS_BUSY && (TrInput & IN_FLARE) && LaraItem->currentAnimState == LS_CRAWL_IDLE && LaraItem->animNumber == LA_CRAWL_IDLE)
{ {
Lara.requestGunType = WEAPON_FLARE; Lara.requestGunType = WEAPON_FLARE;
} }
@ -472,7 +473,8 @@ void LaraGun() // (F) (D)
break; break;
case LG_UNDRAW_GUNS: case LG_UNDRAW_GUNS:
LARA_MESHES(ID_LARA, LM_HEAD); //LARA_MESHES(ID_LARA, LM_HEAD);
Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD;
switch (Lara.gunType) switch (Lara.gunType)
{ {
@ -504,9 +506,11 @@ void LaraGun() // (F) (D)
case LG_READY: case LG_READY:
if (!(TrInput & IN_ACTION)) if (!(TrInput & IN_ACTION))
LARA_MESHES(ID_LARA, LM_HEAD); //LARA_MESHES(ID_LARA, LM_HEAD);
Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD;
else else
LARA_MESHES(ID_LARA_SCREAM, LM_HEAD); //LARA_MESHES(ID_LARA_SCREAM, LM_HEAD);
Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD;
if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA)
Camera.type = COMBAT_CAMERA; Camera.type = COMBAT_CAMERA;
@ -580,7 +584,7 @@ void LaraGun() // (F) (D)
case LG_HANDS_BUSY: case LG_HANDS_BUSY:
if (Lara.gunType == WEAPON_FLARE) if (Lara.gunType == WEAPON_FLARE)
{ {
if (CHECK_LARA_MESHES(ID_LARA_FLARE_ANIM, LM_LHAND)) if (Lara.meshPtrs[LM_LHAND] == Objects[ID_LARA_FLARE_ANIM].meshIndex + LM_LHAND)
{ {
#if 0 #if 0
Lara.flareControlLeft = (Lara.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState)); Lara.flareControlLeft = (Lara.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState));
@ -646,8 +650,8 @@ void InitialiseNewWeapon()
break; break;
default: default:
Lara.rightArm.frameBase = Anims[LaraItem->animNumber].framePtr; Lara.rightArm.frameBase = g_Level.Anims[LaraItem->animNumber].framePtr;
Lara.leftArm.frameBase = Anims[LaraItem->animNumber].framePtr; Lara.leftArm.frameBase = g_Level.Anims[LaraItem->animNumber].framePtr;
break; break;
} }
} }
@ -689,7 +693,7 @@ int WeaponObjectMesh(int weaponType)
void HitTarget(ITEM_INFO* item, GAME_VECTOR* hitPos, int damage, int flag) void HitTarget(ITEM_INFO* item, GAME_VECTOR* hitPos, int damage, int flag)
{ {
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
item->hitStatus = true; item->hitStatus = true;
if (creature != nullptr && item != LaraItem) if (creature != nullptr && item != LaraItem)
@ -850,13 +854,13 @@ FireWeaponType FireWeapon(int weaponType, ITEM_INFO* target, ITEM_INFO* src, sho
void find_target_point(ITEM_INFO* item, GAME_VECTOR* target) // (F) (D) void find_target_point(ITEM_INFO* item, GAME_VECTOR* target) // (F) (D)
{ {
ANIM_FRAME* bounds; BOUNDING_BOX* bounds;
int x, y, z, c, s; int x, y, z, c, s;
bounds = (ANIM_FRAME*)GetBestFrame(item); bounds = (BOUNDING_BOX*)GetBestFrame(item);
x = (int)(bounds->MinX + bounds->MaxX) / 2; x = (int)(bounds->X1 + bounds->X2) / 2;
y = (int) bounds->MinY + (bounds->MaxY - bounds->MinY) / 3; y = (int) bounds->Y1 + (bounds->Y2 - bounds->Y1) / 3;
z = (int)(bounds->MinZ + bounds->MaxZ) / 2; z = (int)(bounds->Z1 + bounds->Z2) / 2;
c = phd_cos(item->pos.yRot); c = phd_cos(item->pos.yRot);
s = phd_sin(item->pos.yRot); s = phd_sin(item->pos.yRot);
@ -982,7 +986,7 @@ void LaraGetNewTarget(WEAPON_INFO* weapon) // (F) (D)
{ {
if (BaddieSlots[slot].itemNum != NO_ITEM) if (BaddieSlots[slot].itemNum != NO_ITEM)
{ {
item = &Items[BaddieSlots[slot].itemNum]; item = &g_Level.Items[BaddieSlots[slot].itemNum];
if (item->hitPoints > 0) if (item->hitPoints > 0)
{ {
x = item->pos.xPos - src.x; x = item->pos.xPos - src.x;
@ -1086,7 +1090,7 @@ void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, in
int ceiling, height, oldonobj, oldheight; int ceiling, height, oldonobj, oldheight;
int bs, yang; int bs, yang;
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
short roomNumber = item->roomNumber; short roomNumber = item->roomNumber;
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber); FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber);
@ -1578,3 +1582,29 @@ void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, in
if (roomNumber != item->roomNumber) if (roomNumber != item->roomNumber)
ItemNewRoom(itemNumber, roomNumber); ItemNewRoom(itemNumber, roomNumber);
} }
HOLSTER_SLOT HolsterSlotForWeapon(LARA_WEAPON_TYPE weapon)
{
switch(weapon){
case WEAPON_PISTOLS:
return HOLSTER_SLOT::Pistols;
case WEAPON_UZI:
return HOLSTER_SLOT::Uzis;
case WEAPON_REVOLVER:
return HOLSTER_SLOT::Revolver;
case WEAPON_SHOTGUN:
return HOLSTER_SLOT::Shotgun;
case WEAPON_HK:
return HOLSTER_SLOT::HK;
case WEAPON_HARPOON_GUN:
return HOLSTER_SLOT::Harpoon;
case WEAPON_CROSSBOW:
return HOLSTER_SLOT::Crowssbow;
case WEAPON_GRENADE_LAUNCHER:
return HOLSTER_SLOT::GrenadeLauncher;
case WEAPON_ROCKET_LAUNCHER:
return HOLSTER_SLOT::RocketLauncher;
default:
return HOLSTER_SLOT::Empty;
}
}

View file

@ -23,7 +23,7 @@ typedef struct WEAPON_INFO
byte drawFrame; byte drawFrame;
short sampleNum; short sampleNum;
}; };
extern WEAPON_INFO Weapons[NUM_WEAPONS]; extern WEAPON_INFO Weapons[static_cast<int>(LARA_WEAPON_TYPE::NUM_WEAPONS)];
void SmashItem(short itemNum); void SmashItem(short itemNum);
int WeaponObject(int weaponType); int WeaponObject(int weaponType);
@ -39,3 +39,4 @@ void LaraTargetInfo(WEAPON_INFO* weapon);
bool CheckForHoldingState(int state); bool CheckForHoldingState(int state);
void LaraGetNewTarget(WEAPON_INFO* weapon); void LaraGetNewTarget(WEAPON_INFO* weapon);
void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, int zv); void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, int zv);
HOLSTER_SLOT HolsterSlotForWeapon(LARA_WEAPON_TYPE weapon);

View file

@ -21,9 +21,9 @@ constexpr std::array<float, 28> FlareFlickerTableLow = { 0.7590,0.1880,0.0790,0.
void FlareControl(short itemNumber) // (AF) (D) void FlareControl(short itemNumber) // (AF) (D)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)
{ {
KillItem(itemNumber); KillItem(itemNumber);
return; return;
@ -51,7 +51,7 @@ void FlareControl(short itemNumber) // (AF) (D)
item->pos.zPos += zv; item->pos.zPos += zv;
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
item->fallspeed += (5 - item->fallspeed) / 2; item->fallspeed += (5 - item->fallspeed) / 2;
item->speed += (5 - item->speed) / 2; item->speed += (5 - item->speed) / 2;
@ -104,12 +104,12 @@ void ready_flare() // (F) (D)
void undraw_flare_meshes() // (F) (D) void undraw_flare_meshes() // (F) (D)
{ {
LARA_MESHES(ID_LARA, LM_LHAND); Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND;
} }
void draw_flare_meshes() // (F) (D) void draw_flare_meshes() // (F) (D)
{ {
LARA_MESHES(ID_LARA_FLARE_ANIM, LM_LHAND); Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_FLARE_ANIM].meshIndex + LM_LHAND;
} }
void undraw_flare() // (F) (D) void undraw_flare() // (F) (D)
@ -120,25 +120,25 @@ void undraw_flare() // (F) (D)
short frame2 = Lara.leftArm.frameNumber; short frame2 = Lara.leftArm.frameNumber;
#if 0 #if 0
if (LaraItem->goalAnimState == STATE_LARA_STOP && if (LaraItem->goalAnimState == LS_STOP &&
Lara.Vehicle == NO_ITEM) Lara.Vehicle == NO_ITEM)
#else #else
if (LaraItem->goalAnimState == STATE_LARA_STOP) if (LaraItem->goalAnimState == LS_STOP)
#endif #endif
{ {
if (LaraItem->animNumber == ANIMATION_LARA_STAY_IDLE) if (LaraItem->animNumber == LA_STAND_IDLE)
{ {
LaraItem->animNumber = ANIMATION_LARA_FLARE_THROW; LaraItem->animNumber = LA_DISCARD_FLARE;
frame1 = frame2 + Anims[LaraItem->animNumber].frameBase; frame1 = frame2 + g_Level.Anims[LaraItem->animNumber].frameBase;
Lara.flareFrame = frame1; Lara.flareFrame = frame1;
LaraItem->frameNumber = frame1; LaraItem->frameNumber = frame1;
} }
if (LaraItem->animNumber == ANIMATION_LARA_FLARE_THROW) if (LaraItem->animNumber == LA_DISCARD_FLARE)
{ {
Lara.flareControlLeft = false; Lara.flareControlLeft = false;
if (frame1 >= Anims[LaraItem->animNumber].frameBase + 31) if (frame1 >= g_Level.Anims[LaraItem->animNumber].frameBase + 31)
{ {
Lara.requestGunType = Lara.lastGunType; Lara.requestGunType = Lara.lastGunType;
Lara.gunType = Lara.lastGunType; Lara.gunType = Lara.lastGunType;
@ -149,21 +149,21 @@ void undraw_flare() // (F) (D)
Lara.target = NULL; Lara.target = NULL;
Lara.rightArm.lock = false; Lara.rightArm.lock = false;
Lara.leftArm.lock = false; Lara.leftArm.lock = false;
LaraItem->animNumber = ANIMATION_LARA_STAY_SOLID; LaraItem->animNumber = LA_STAND_SOLID;
Lara.flareFrame = Anims[LaraItem->animNumber].frameBase; Lara.flareFrame = g_Level.Anims[LaraItem->animNumber].frameBase;
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
LaraItem->currentAnimState = STATE_LARA_STOP; LaraItem->currentAnimState = LS_STOP;
LaraItem->goalAnimState = STATE_LARA_STOP; LaraItem->goalAnimState = LS_STOP;
return; return;
} }
Lara.flareFrame++; Lara.flareFrame++;
} }
} }
else if (LaraItem->currentAnimState == STATE_LARA_STOP) /* @ORIGINAL_BUG: this code block makes flare cancels possible */ else if (LaraItem->currentAnimState == LS_STOP) /* @ORIGINAL_BUG: this code block makes flare cancels possible */
{ {
LaraItem->animNumber = ANIMATION_LARA_STAY_SOLID; LaraItem->animNumber = LA_STAND_SOLID;
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
} }
if (frame2 >= 33 && frame2 < 72) if (frame2 >= 33 && frame2 < 72)
@ -232,8 +232,8 @@ void draw_flare() // (F) (D)
{ {
short frame; short frame;
if (LaraItem->currentAnimState == STATE_LARA_FLARE_PICKUP || if (LaraItem->currentAnimState == LS_PICKUP_FLARE ||
LaraItem->currentAnimState == STATE_LARA_PICKUP) LaraItem->currentAnimState == LS_PICKUP)
{ {
DoFlareInHand(Lara.flareAge); DoFlareInHand(Lara.flareAge);
Lara.flareControlLeft = false; Lara.flareControlLeft = false;
@ -257,7 +257,7 @@ void draw_flare() // (F) (D)
{ {
if (frame == 72) if (frame == 72)
{ {
SoundEffect(SFX_RAVESTICK, &LaraItem->pos, Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WATER); SoundEffect(SFX_RAVESTICK, &LaraItem->pos, g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WATER);
Lara.flareAge = 1; Lara.flareAge = 1;
} }
@ -300,7 +300,7 @@ void set_flare_arm(int frame) // (F) (D)
} }
Lara.leftArm.animNumber = anim; Lara.leftArm.animNumber = anim;
Lara.leftArm.frameBase = Anims[anim].framePtr; Lara.leftArm.frameBase = g_Level.Anims[anim].framePtr;
} }
void CreateFlare(short objectNum, int thrown) // (F) (D) void CreateFlare(short objectNum, int thrown) // (F) (D)
@ -309,7 +309,7 @@ void CreateFlare(short objectNum, int thrown) // (F) (D)
if (itemNum != NO_ITEM) if (itemNum != NO_ITEM)
{ {
bool flag = false; bool flag = false;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
item->objectNumber = objectNum; item->objectNumber = objectNum;
item->roomNumber = LaraItem->roomNumber; item->roomNumber = LaraItem->roomNumber;

View file

@ -18,7 +18,7 @@
#include "camera.h" #include "camera.h"
#include "input.h" #include "input.h"
#include "sound.h" #include "sound.h"
using T5M::Renderer::g_Renderer;
extern GameFlow* g_GameFlow; extern GameFlow* g_GameFlow;
extern short FXType; extern short FXType;
COLL_INFO lara_coll; COLL_INFO lara_coll;
@ -27,45 +27,45 @@ short cheatHitPoints;
void GetLaraDeadlyBounds() // (F) (D) void GetLaraDeadlyBounds() // (F) (D)
{ {
short* bounds; BOUNDING_BOX* bounds;
short tbounds[6]; BOUNDING_BOX tbounds;
bounds = GetBoundsAccurate(LaraItem); bounds = GetBoundsAccurate(LaraItem);
phd_RotBoundingBoxNoPersp(&LaraItem->pos, bounds, tbounds); phd_RotBoundingBoxNoPersp(&LaraItem->pos, bounds, &tbounds);
DeadlyBounds[0] = LaraItem->pos.xPos + tbounds[0]; DeadlyBounds[0] = LaraItem->pos.xPos + tbounds.X1;
DeadlyBounds[1] = LaraItem->pos.xPos + tbounds[1]; DeadlyBounds[1] = LaraItem->pos.xPos + tbounds.X2;
DeadlyBounds[2] = LaraItem->pos.yPos + tbounds[2]; DeadlyBounds[2] = LaraItem->pos.yPos + tbounds.Y1;
DeadlyBounds[3] = LaraItem->pos.yPos + tbounds[3]; DeadlyBounds[3] = LaraItem->pos.yPos + tbounds.Y2;
DeadlyBounds[4] = LaraItem->pos.zPos + tbounds[4]; DeadlyBounds[4] = LaraItem->pos.zPos + tbounds.Z1;
DeadlyBounds[5] = LaraItem->pos.zPos + tbounds[5]; DeadlyBounds[5] = LaraItem->pos.zPos + tbounds.Z2;
} }
void InitialiseLaraAnims(ITEM_INFO* item) // (F) (D) void InitialiseLaraAnims(ITEM_INFO* item) // (F) (D)
{ {
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
Lara.waterStatus = LW_UNDERWATER; Lara.waterStatus = LW_UNDERWATER;
item->goalAnimState = STATE_LARA_UNDERWATER_STOP; item->goalAnimState = LS_UNDERWATER_STOP;
item->currentAnimState = STATE_LARA_UNDERWATER_STOP; item->currentAnimState = LS_UNDERWATER_STOP;
item->fallspeed = 0; item->fallspeed = 0;
item->animNumber = ANIMATION_LARA_UNDERWATER_IDLE; item->animNumber = LA_UNDERWATER_IDLE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
} }
else else
{ {
Lara.waterStatus = LW_ABOVE_WATER; Lara.waterStatus = LW_ABOVE_WATER;
item->goalAnimState = STATE_LARA_STOP; item->goalAnimState = LS_STOP;
item->currentAnimState = STATE_LARA_STOP; item->currentAnimState = LS_STOP;
item->animNumber = ANIMATION_LARA_STAY_SOLID; item->animNumber = LA_STAND_SOLID;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
} }
} }
void InitialiseLaraLoad(short itemNum) // (F) (D) void InitialiseLaraLoad(short itemNum) // (F) (D)
{ {
Lara.itemNumber = itemNum; Lara.itemNumber = itemNum;
LaraItem = &Items[itemNum]; LaraItem = &g_Level.Items[itemNum];
} }
void DelsGiveLaraItemsCheat() // (AF) (D) void DelsGiveLaraItemsCheat() // (AF) (D)
@ -216,10 +216,10 @@ void LaraCheatyBits() // (F) (D)
if (Lara.waterStatus != LW_FLYCHEAT) if (Lara.waterStatus != LW_FLYCHEAT)
{ {
Lara.waterStatus = LW_FLYCHEAT; Lara.waterStatus = LW_FLYCHEAT;
LaraItem->animNumber = ANIMATION_LARA_DOZY; LaraItem->animNumber = LA_DOZY;
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
LaraItem->currentAnimState = ANIMATION_LARA_ONWATER_IDLE_TO_SWIM; LaraItem->currentAnimState = LA_ONWATER_IDLE_TO_SWIM;
LaraItem->goalAnimState = ANIMATION_LARA_ONWATER_IDLE_TO_SWIM; LaraItem->goalAnimState = LA_ONWATER_IDLE_TO_SWIM;
LaraItem->gravityStatus = false; LaraItem->gravityStatus = false;
LaraItem->pos.xRot = ANGLE(30); LaraItem->pos.xRot = ANGLE(30);
LaraItem->fallspeed = 30; LaraItem->fallspeed = 30;
@ -259,23 +259,23 @@ void LaraControl(short itemNumber) // (AF) (D)
int oldZ = LaraItem->pos.zPos; int oldZ = LaraItem->pos.zPos;
if (Lara.gunStatus == LG_HANDS_BUSY && if (Lara.gunStatus == LG_HANDS_BUSY &&
LaraItem->currentAnimState == STATE_LARA_STOP && LaraItem->currentAnimState == LS_STOP &&
LaraItem->goalAnimState == STATE_LARA_STOP && LaraItem->goalAnimState == LS_STOP &&
LaraItem->animNumber == ANIMATION_LARA_STAY_IDLE && LaraItem->animNumber == LA_STAND_IDLE &&
!LaraItem->gravityStatus) !LaraItem->gravityStatus)
{ {
Lara.gunStatus = LG_NO_ARMS; Lara.gunStatus = LG_NO_ARMS;
} }
if (item->currentAnimState != STATE_LARA_SPRINT && DashTimer < 120) if (item->currentAnimState != LS_SPRINT && DashTimer < 120)
DashTimer++; DashTimer++;
Lara.isDucked = false; Lara.isDucked = false;
#if 1 #if 1
bool isWater = Rooms[item->roomNumber].flags & ENV_FLAG_WATER; bool isWater = g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER;
#else #else
bool isWater = Rooms[item->roomNumber].flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP); bool isWater = g_Level.Rooms[item->roomNumber].flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP);
#endif #endif
int wd = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); int wd = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
@ -311,18 +311,18 @@ void LaraControl(short itemNumber) // (AF) (D)
Lara.waterStatus = LW_WADE; Lara.waterStatus = LW_WADE;
if (!(item->gravityStatus)) if (!(item->gravityStatus))
{ {
item->goalAnimState = STATE_LARA_STOP; item->goalAnimState = LS_STOP;
} }
#if 0 #if 0
else if (isWater & ENV_FLAG_SWAMP) else if (isWater & ENV_FLAG_SWAMP)
{ {
if (item->currentAnimState == STATE_LARA_SWANDIVE_BEGIN || item->currentAnimState == STATE_LARA_SWANDIVE_END) // Is Lara swan-diving? if (item->currentAnimState == LS_SWANDIVE_BEGIN || item->currentAnimState == LS_SWANDIVE_END) // Is Lara swan-diving?
item->pos.yPos = wh + 1000; item->pos.yPos = wh + 1000;
item->goalAnimState = STATE_LARA_WADE_FORWARD; item->goalAnimState = LS_WADE_FORWARD;
item->currentAnimState = STATE_LARA_WADE_FORWARD; item->currentAnimState = LS_WADE_FORWARD;
item->animNumber = ANIMATION_LARA_WADE; item->animNumber = LA_WADE;
item->frameNumber = GF(ANIMATION_LARA_WADE, 0); item->frameNumber = GF(LA_WADE, 0);
} }
#endif #endif
} }
@ -341,27 +341,27 @@ void LaraControl(short itemNumber) // (AF) (D)
UpdateLaraRoom(LaraItem, 0); UpdateLaraRoom(LaraItem, 0);
StopSoundEffect(SFX_LARA_FALL); StopSoundEffect(SFX_LARA_FALL);
if (item->currentAnimState == STATE_LARA_SWANDIVE_BEGIN) if (item->currentAnimState == LS_SWANDIVE_START)
{ {
item->pos.xRot = -ANGLE(45); item->pos.xRot = -ANGLE(45);
item->goalAnimState = STATE_LARA_UNDERWATER_DIVING; item->goalAnimState = LS_DIVE;
AnimateLara(item); AnimateLara(item);
item->fallspeed *= 2; item->fallspeed *= 2;
} }
else if (item->currentAnimState == STATE_LARA_SWANDIVE_END) else if (item->currentAnimState == LS_SWANDIVE_END)
{ {
item->pos.xRot = -ANGLE(85); item->pos.xRot = -ANGLE(85);
item->goalAnimState = STATE_LARA_UNDERWATER_DIVING; item->goalAnimState = LS_DIVE;
AnimateLara(item); AnimateLara(item);
item->fallspeed *= 2; item->fallspeed *= 2;
} }
else else
{ {
item->pos.xRot = -ANGLE(45); item->pos.xRot = -ANGLE(45);
item->animNumber = ANIMATION_LARA_FREE_FALL_TO_UNDERWATER; item->animNumber = LA_FREEFALL_DIVE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = STATE_LARA_UNDERWATER_DIVING; item->currentAnimState = LS_DIVE;
item->goalAnimState = STATE_LARA_UNDERWATER_FORWARD; item->goalAnimState = LS_UNDERWATER_FORWARD;
item->fallspeed = 3 * item->fallspeed / 2; item->fallspeed = 3 * item->fallspeed / 2;
} }
@ -383,32 +383,32 @@ void LaraControl(short itemNumber) // (AF) (D)
switch (item->currentAnimState) switch (item->currentAnimState)
{ {
case STATE_LARA_WALK_BACK: case LS_WALK_BACK:
item->animNumber = ANIMATION_LARA_ONWATER_IDLE_TO_SWIM_BACK; item->animNumber = LA_ONWATER_IDLE_TO_SWIM_BACK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_BACK; item->goalAnimState = LS_ONWATER_BACK;
item->currentAnimState = STATE_LARA_ONWATER_BACK; item->currentAnimState = LS_ONWATER_BACK;
break; break;
case STATE_LARA_WALK_RIGHT: case LS_STEP_RIGHT:
item->animNumber = ANIMATION_LARA_ONWATER_SWIM_RIGHT; item->animNumber = LA_ONWATER_SWIM_RIGHT;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_RIGHT; item->goalAnimState = LS_ONWATER_RIGHT;
item->currentAnimState = STATE_LARA_ONWATER_RIGHT; item->currentAnimState = LS_ONWATER_RIGHT;
break; break;
case STATE_LARA_WALK_LEFT: case LS_STEP_LEFT:
item->animNumber = ANIMATION_LARA_ONWATER_SWIM_LEFT; item->animNumber = LA_ONWATER_SWIM_LEFT;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_LEFT; item->goalAnimState = LS_ONWATER_LEFT;
item->currentAnimState = STATE_LARA_ONWATER_LEFT; item->currentAnimState = LS_ONWATER_LEFT;
break; break;
default: default:
item->animNumber = ANIMATION_LARA_ONWATER_SWIM_FORWARD; item->animNumber = LA_ONWATER_SWIM;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_FORWARD; item->goalAnimState = LS_ONWATER_FORWARD;
item->currentAnimState = STATE_LARA_ONWATER_FORWARD; item->currentAnimState = LS_ONWATER_FORWARD;
break; break;
} }
@ -428,8 +428,8 @@ void LaraControl(short itemNumber) // (AF) (D)
else else
{ {
Lara.waterStatus = LW_ABOVE_WATER; Lara.waterStatus = LW_ABOVE_WATER;
if (item->currentAnimState == STATE_LARA_WADE_FORWARD) if (item->currentAnimState == LS_WADE_FORWARD)
item->goalAnimState = STATE_LARA_RUN_FORWARD; item->goalAnimState = LS_RUN_FORWARD;
} }
} }
@ -441,19 +441,19 @@ void LaraControl(short itemNumber) // (AF) (D)
if (wd == NO_HEIGHT if (wd == NO_HEIGHT
|| abs(hfw) >= 256 || abs(hfw) >= 256
|| Rooms[roomNumber].flags & ENV_FLAG_WATER || g_Level.Rooms[roomNumber].flags & ENV_FLAG_WATER
|| item->animNumber == ANIMATION_LARA_UNDERWATER_TO_ONWATER || item->animNumber == LA_UNDERWATER_RESURFACE
|| item->animNumber == ANIMATION_LARA_FREE_FALL_TO_UNDERWATER_ALTERNATE) || item->animNumber == LA_ONWATER_DIVE)
{ {
if (!isWater) if (!isWater)
{ {
if (wd == NO_HEIGHT || abs(hfw) >= 256) if (wd == NO_HEIGHT || abs(hfw) >= 256)
{ {
Lara.waterStatus = LW_ABOVE_WATER; Lara.waterStatus = LW_ABOVE_WATER;
item->animNumber = ANIMATION_LARA_FREE_FALL_FORWARD; item->animNumber = LA_FALL_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_JUMP_FORWARD; item->goalAnimState = LS_JUMP_FORWARD;
item->currentAnimState = STATE_LARA_JUMP_FORWARD; item->currentAnimState = LS_JUMP_FORWARD;
item->speed = item->fallspeed / 4; item->speed = item->fallspeed / 4;
item->gravityStatus = true; item->gravityStatus = true;
@ -469,10 +469,10 @@ void LaraControl(short itemNumber) // (AF) (D)
{ {
Lara.waterStatus = LW_SURFACE; Lara.waterStatus = LW_SURFACE;
item->pos.yPos = wh; item->pos.yPos = wh;
item->animNumber = ANIMATION_LARA_UNDERWATER_TO_ONWATER; item->animNumber = LA_UNDERWATER_RESURFACE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
item->currentAnimState = STATE_LARA_ONWATER_STOP; item->currentAnimState = LS_ONWATER_STOP;
item->fallspeed = 0; item->fallspeed = 0;
Lara.diveCount = 11; Lara.diveCount = 11;
LaraItem->pos.zRot = 0; LaraItem->pos.zRot = 0;
@ -491,10 +491,10 @@ void LaraControl(short itemNumber) // (AF) (D)
{ {
Lara.waterStatus = LW_SURFACE; Lara.waterStatus = LW_SURFACE;
item->pos.yPos = wh + 1; item->pos.yPos = wh + 1;
item->animNumber = ANIMATION_LARA_UNDERWATER_TO_ONWATER; item->animNumber = LA_UNDERWATER_RESURFACE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
item->currentAnimState = STATE_LARA_ONWATER_STOP; item->currentAnimState = LS_ONWATER_STOP;
item->fallspeed = 0; item->fallspeed = 0;
Lara.diveCount = 11; Lara.diveCount = 11;
LaraItem->pos.zRot = 0; LaraItem->pos.zRot = 0;
@ -515,20 +515,20 @@ void LaraControl(short itemNumber) // (AF) (D)
if (hfw <= 256) if (hfw <= 256)
{ {
Lara.waterStatus = LW_ABOVE_WATER; Lara.waterStatus = LW_ABOVE_WATER;
item->animNumber = ANIMATION_LARA_FREE_FALL_FORWARD; item->animNumber = LA_FALL_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_JUMP_FORWARD; item->goalAnimState = LS_JUMP_FORWARD;
item->currentAnimState = STATE_LARA_JUMP_FORWARD; item->currentAnimState = LS_JUMP_FORWARD;
item->speed = item->fallspeed / 4; item->speed = item->fallspeed / 4;
item->gravityStatus = true; item->gravityStatus = true;
} }
else else
{ {
Lara.waterStatus = LW_WADE; /* @DEAD_CODE: Lara has to reach a room without water while in the surface but then GetWaterHeight() return value never will make hfw > 256 */ Lara.waterStatus = LW_WADE; /* @DEAD_CODE: Lara has to reach a room without water while in the surface but then GetWaterHeight() return value never will make hfw > 256 */
item->animNumber = ANIMATION_LARA_STAY_IDLE; item->animNumber = LA_STAND_IDLE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_WADE_FORWARD; item->goalAnimState = LS_WADE_FORWARD;
item->currentAnimState = STATE_LARA_STOP; item->currentAnimState = LS_STOP;
AnimateItem(item); AnimateItem(item);
} }
@ -558,32 +558,32 @@ void LaraControl(short itemNumber) // (AF) (D)
switch (item->currentAnimState) switch (item->currentAnimState)
{ {
case STATE_LARA_WALK_BACK: case LS_WALK_BACK:
item->animNumber = ANIMATION_LARA_ONWATER_IDLE_TO_SWIM_BACK; item->animNumber = LA_ONWATER_IDLE_TO_SWIM_BACK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_BACK; item->goalAnimState = LS_ONWATER_BACK;
item->currentAnimState = STATE_LARA_ONWATER_BACK; item->currentAnimState = LS_ONWATER_BACK;
break; break;
case STATE_LARA_WALK_RIGHT: case LS_STEP_RIGHT:
item->animNumber = ANIMATION_LARA_ONWATER_SWIM_RIGHT; item->animNumber = LA_ONWATER_SWIM_RIGHT;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_RIGHT; item->goalAnimState = LS_ONWATER_RIGHT;
item->currentAnimState = STATE_LARA_ONWATER_RIGHT; item->currentAnimState = LS_ONWATER_RIGHT;
break; break;
case STATE_LARA_WALK_LEFT: case LS_STEP_LEFT:
item->animNumber = ANIMATION_LARA_ONWATER_SWIM_LEFT; item->animNumber = LA_ONWATER_SWIM_LEFT;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_LEFT; item->goalAnimState = LS_ONWATER_LEFT;
item->currentAnimState = STATE_LARA_ONWATER_LEFT; item->currentAnimState = LS_ONWATER_LEFT;
break; break;
default: default:
item->animNumber = ANIMATION_LARA_ONWATER_SWIM_FORWARD; item->animNumber = LA_ONWATER_SWIM;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_ONWATER_FORWARD; item->goalAnimState = LS_ONWATER_FORWARD;
item->currentAnimState = STATE_LARA_ONWATER_FORWARD; item->currentAnimState = LS_ONWATER_FORWARD;
break; break;
} }
@ -603,8 +603,8 @@ void LaraControl(short itemNumber) // (AF) (D)
else else
{ {
Lara.waterStatus = LW_ABOVE_WATER; Lara.waterStatus = LW_ABOVE_WATER;
if (item->currentAnimState == STATE_LARA_WADE_FORWARD) if (item->currentAnimState == LS_WADE_FORWARD)
item->goalAnimState = STATE_LARA_RUN_FORWARD; item->goalAnimState = LS_RUN_FORWARD;
} }
break; break;
} }
@ -632,7 +632,7 @@ void LaraControl(short itemNumber) // (AF) (D)
case LW_ABOVE_WATER: case LW_ABOVE_WATER:
case LW_WADE: case LW_WADE:
#if 0 #if 0
if (Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -775) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -775)
{ {
if (item->hitPoints >= 0) if (item->hitPoints >= 0)
{ {
@ -723,8 +723,8 @@ void LaraCheat(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
if (TrInput & IN_WALK && !(TrInput & IN_LOOK)) if (TrInput & IN_WALK && !(TrInput & IN_LOOK))
{ {
Lara.waterStatus = LW_ABOVE_WATER; Lara.waterStatus = LW_ABOVE_WATER;
item->animNumber = ANIMATION_LARA_STAY_SOLID; item->animNumber = LA_STAND_SOLID;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->pos.zRot = 0; item->pos.zRot = 0;
item->pos.xRot = 0; item->pos.xRot = 0;
Lara.torsoYrot = 0; Lara.torsoYrot = 0;
@ -742,24 +742,25 @@ void LaraInitialiseMeshes() // (AF) (D)
{ {
for (int i = 0; i < NUM_LARA_MESHES; i++) for (int i = 0; i < NUM_LARA_MESHES; i++)
{ {
MESHES(ID_LARA, i) = MESHES(ID_LARA_SKIN, i); //Meshes[i] = Meshes[MESHES(ID_LARA_SKIN, i)];
LARA_MESHES(ID_LARA, i); //LARA_MESHES(ID_LARA, MESHES(ID_LARA_SKIN, i));
Lara.meshPtrs[i] = Objects[ID_LARA_SKIN].meshIndex + i;
} }
/* Hardcoded code */ /* Hardcoded code */
if (Lara.gunType == WEAPON_HK) if (Lara.gunType == WEAPON_HK)
{ {
Lara.backGun = WEAPON_HK; Lara.holsterInfo.backHolster = HOLSTER_SLOT::HK;
} }
else if (!Lara.Weapons[WEAPON_SHOTGUN].Present) else if (!Lara.Weapons[WEAPON_SHOTGUN].Present)
{ {
if (Lara.Weapons[WEAPON_HK].Present) if (Lara.Weapons[WEAPON_HK].Present)
Lara.backGun = WEAPON_HK; Lara.holsterInfo.backHolster = HOLSTER_SLOT::HK;
} }
else else
{ {
Lara.backGun = WEAPON_UZI; Lara.holsterInfo.backHolster = HOLSTER_SLOT::Uzis;
} }
Lara.gunStatus = LG_NO_ARMS; Lara.gunStatus = LG_NO_ARMS;
@ -802,7 +803,20 @@ void InitialiseLara(int restore)
Lara.dpoisoned = 0; Lara.dpoisoned = 0;
Lara.poisoned = 0; Lara.poisoned = 0;
Lara.waterSurfaceDist = 100; Lara.waterSurfaceDist = 100;
Lara.holster = ID_LARA_HOLSTERS_PISTOLS; if(Lara.Weapons[static_cast<int>(LARA_WEAPON_TYPE::WEAPON_PISTOLS)].Present){
Lara.holsterInfo.leftHolster = HOLSTER_SLOT::Pistols;
Lara.holsterInfo.rightHolster = HOLSTER_SLOT::Pistols;
} else{
Lara.holsterInfo.leftHolster = HOLSTER_SLOT::Empty;
Lara.holsterInfo.rightHolster = HOLSTER_SLOT::Empty;
}
if(Lara.Weapons[static_cast<int>(LARA_WEAPON_TYPE::WEAPON_SHOTGUN)].Present){
Lara.holsterInfo.backHolster = HOLSTER_SLOT::Shotgun;
} else{
Lara.holsterInfo.backHolster = HOLSTER_SLOT::Empty;
}
Lara.location = -1; Lara.location = -1;
Lara.highestLocation = -1; Lara.highestLocation = -1;
Lara.ropePtr = -1; Lara.ropePtr = -1;
@ -856,10 +870,10 @@ void AnimateLara(ITEM_INFO* item)
{ {
item->frameNumber++; item->frameNumber++;
ANIM_STRUCT* anim = &Anims[item->animNumber]; ANIM_STRUCT* anim = &g_Level.Anims[item->animNumber];
if (anim->numberChanges > 0 && GetChange(item, anim)) if (anim->numberChanges > 0 && GetChange(item, anim))
{ {
anim = &Anims[item->animNumber]; anim = &g_Level.Anims[item->animNumber];
item->currentAnimState = anim->currentAnimState; item->currentAnimState = anim->currentAnimState;
} }
@ -867,7 +881,7 @@ void AnimateLara(ITEM_INFO* item)
{ {
if (anim->numberCommands > 0) if (anim->numberCommands > 0)
{ {
short* cmd = &Commands[anim->commandIndex]; short* cmd = &g_Level.Commands[anim->commandIndex];
for (int i = anim->numberCommands; i > 0; i--) for (int i = anim->numberCommands; i > 0; i--)
{ {
switch (*(cmd++)) switch (*(cmd++))
@ -908,13 +922,13 @@ void AnimateLara(ITEM_INFO* item)
item->animNumber = anim->jumpAnimNum; item->animNumber = anim->jumpAnimNum;
item->frameNumber = anim->jumpFrameNum; item->frameNumber = anim->jumpFrameNum;
anim = &Anims[item->animNumber]; anim = &g_Level.Anims[item->animNumber];
item->currentAnimState = anim->currentAnimState; item->currentAnimState = anim->currentAnimState;
} }
if (anim->numberCommands > 0) if (anim->numberCommands > 0)
{ {
short* cmd = &Commands[anim->commandIndex]; short* cmd = &g_Level.Commands[anim->commandIndex];
int flags; int flags;
int effectID = 0; int effectID = 0;
@ -940,7 +954,7 @@ void AnimateLara(ITEM_INFO* item)
flags = cmd[1] & 0xC000; flags = cmd[1] & 0xC000;
if (flags == SFX_LANDANDWATER || if (flags == SFX_LANDANDWATER ||
(flags == SFX_LANDONLY && (Lara.waterSurfaceDist >= 0 || Lara.waterSurfaceDist == NO_HEIGHT)) || (flags == SFX_LANDONLY && (Lara.waterSurfaceDist >= 0 || Lara.waterSurfaceDist == NO_HEIGHT)) ||
(flags == SFX_WATERONLY && Lara.waterSurfaceDist < 0 && Lara.waterSurfaceDist != NO_HEIGHT && !(Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP))) (flags == SFX_WATERONLY && Lara.waterSurfaceDist < 0 && Lara.waterSurfaceDist != NO_HEIGHT && !(g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP)))
{ {
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2); SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
} }
@ -976,7 +990,7 @@ void AnimateLara(ITEM_INFO* item)
if (item->gravityStatus) // If gravity ON (Do Up/Down movement) if (item->gravityStatus) // If gravity ON (Do Up/Down movement)
{ {
if (Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)
{ {
item->speed -= item->speed >> 3; item->speed -= item->speed >> 3;
if (abs(item->speed) < 8) if (abs(item->speed) < 8)
@ -1004,7 +1018,7 @@ void AnimateLara(ITEM_INFO* item)
{ {
int velocity; int velocity;
if (Lara.waterStatus == LW_WADE && Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) if (Lara.waterStatus == LW_WADE && g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)
{ {
velocity = (anim->velocity >> 1); velocity = (anim->velocity >> 1);
if (anim->acceleration) if (anim->acceleration)
@ -1033,7 +1047,7 @@ void AnimateLara(ITEM_INFO* item)
} }
// Update matrices // Update matrices
g_Renderer->UpdateLaraAnimations(true); g_Renderer.UpdateLaraAnimations(true);
} }
void DelAlignLaraToRope(ITEM_INFO* item) // (F) (D) void DelAlignLaraToRope(ITEM_INFO* item) // (F) (D)
@ -1051,8 +1065,8 @@ void DelAlignLaraToRope(ITEM_INFO* item) // (F) (D)
frame = (ANIM_FRAME*) GetBestFrame(item); frame = (ANIM_FRAME*) GetBestFrame(item);
ropeY = Lara.ropeY - ANGLE(90); ropeY = Lara.ropeY - ANGLE(90);
rope = &Ropes[Lara.ropePtr]; rope = &Ropes[Lara.ropePtr];
_0x0046D130(rope, (Lara.ropeSegment - 1 << 7) + frame->OffsetY, &pos.x, &pos.y, &pos.z); _0x0046D130(rope, (Lara.ropeSegment - 1 << 7) + frame->offsetY, &pos.x, &pos.y, &pos.z);
_0x0046D130(rope, (Lara.ropeSegment - 1 << 7) + frame->OffsetY - 192, &pos2.x, &pos2.y, &pos2.z); _0x0046D130(rope, (Lara.ropeSegment - 1 << 7) + frame->offsetY - 192, &pos2.x, &pos2.y, &pos2.z);
diff.x = pos.x - pos2.x << 16; diff.x = pos.x - pos2.x << 16;
diff.y = pos.y - pos2.y << 16; diff.y = pos.y - pos2.y << 16;
diff.z = pos.z - pos2.z << 16; diff.z = pos.z - pos2.z << 16;

View file

@ -16,12 +16,12 @@ bool EnableCrawlFlexWaterPullUp, EnableCrawlFlexSubmerged;
void lara_col_surftread(ITEM_INFO* item, COLL_INFO* coll) void lara_col_surftread(ITEM_INFO* item, COLL_INFO* coll)
{ {
if (item->goalAnimState == STATE_LARA_UNDERWATER_FORWARD) if (item->goalAnimState == LS_UNDERWATER_FORWARD)
{ {
item->currentAnimState = STATE_LARA_UNDERWATER_DIVING; item->currentAnimState = LS_DIVE;
item->animNumber = ANIMATION_LARA_FREE_FALL_TO_UNDERWATER_ALTERNATE; item->animNumber = LA_ONWATER_DIVE;
item->pos.xRot = -8190; item->pos.xRot = -8190;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->fallspeed = 80; item->fallspeed = 80;
Lara.waterStatus = LW_UNDERWATER; Lara.waterStatus = LW_UNDERWATER;
} }
@ -53,6 +53,7 @@ void lara_col_surfswim(ITEM_INFO* item, COLL_INFO* coll)//4DCE8(<), 4E14C(<) (F)
Lara.moveAngle = 0; Lara.moveAngle = 0;
LaraSurfaceCollision(item, coll); LaraSurfaceCollision(item, coll);
LaraTestWaterClimbOut(item, coll); LaraTestWaterClimbOut(item, coll);
LaraTestLadderClimbOut(item, coll);
} }
void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F) void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F)
@ -63,7 +64,7 @@ void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F)
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -84,27 +85,27 @@ void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F)
if (TrInput & IN_FORWARD) if (TrInput & IN_FORWARD)
{ {
item->goalAnimState = STATE_LARA_ONWATER_FORWARD; item->goalAnimState = LS_ONWATER_FORWARD;
} }
else if (TrInput & IN_BACK) else if (TrInput & IN_BACK)
{ {
item->goalAnimState = STATE_LARA_ONWATER_BACK; item->goalAnimState = LS_ONWATER_BACK;
} }
if (TrInput & IN_LSTEP) if (TrInput & IN_LSTEP)
{ {
item->goalAnimState = STATE_LARA_ONWATER_LEFT; item->goalAnimState = LS_ONWATER_LEFT;
} }
else if (TrInput & IN_RSTEP) else if (TrInput & IN_RSTEP)
{ {
item->goalAnimState = STATE_LARA_ONWATER_RIGHT; item->goalAnimState = LS_ONWATER_RIGHT;
} }
if (TrInput & IN_JUMP) if (TrInput & IN_JUMP)
{ {
Lara.diveCount++; Lara.diveCount++;
if (Lara.diveCount == 10) if (Lara.diveCount == 10)
item->goalAnimState = STATE_LARA_UNDERWATER_FORWARD; item->goalAnimState = LS_UNDERWATER_FORWARD;
} }
else else
{ {
@ -116,7 +117,7 @@ void lara_as_surfright(ITEM_INFO* item, COLL_INFO* coll)//4DAF8, 4DF5C (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -133,7 +134,7 @@ void lara_as_surfright(ITEM_INFO* item, COLL_INFO* coll)//4DAF8, 4DF5C (F)
if (!(TrInput & IN_RSTEP)) if (!(TrInput & IN_RSTEP))
{ {
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
} }
item->fallspeed += 8; item->fallspeed += 8;
@ -145,7 +146,7 @@ void lara_as_surfleft(ITEM_INFO* item, COLL_INFO* coll)//4DA50(<), 4DEB4(<) (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -162,7 +163,7 @@ void lara_as_surfleft(ITEM_INFO* item, COLL_INFO* coll)//4DA50(<), 4DEB4(<) (F)
if (!(TrInput & IN_LSTEP)) if (!(TrInput & IN_LSTEP))
{ {
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
} }
item->fallspeed += 8; item->fallspeed += 8;
@ -174,7 +175,7 @@ void lara_as_surfback(ITEM_INFO* item, COLL_INFO* coll)//4D9A8(<), 4DE0C(<) (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -191,7 +192,7 @@ void lara_as_surfback(ITEM_INFO* item, COLL_INFO* coll)//4D9A8(<), 4DE0C(<) (F)
if (!(TrInput & IN_BACK)) if (!(TrInput & IN_BACK))
{ {
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
} }
item->fallspeed += 8; item->fallspeed += 8;
@ -203,7 +204,7 @@ void lara_as_surfswim(ITEM_INFO* item, COLL_INFO* coll)//4D8E4(<), 4DD48(<) (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -219,9 +220,9 @@ void lara_as_surfswim(ITEM_INFO* item, COLL_INFO* coll)//4D8E4(<), 4DD48(<) (F)
} }
if (!(TrInput & IN_FORWARD)) if (!(TrInput & IN_FORWARD))
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
if (TrInput & IN_JUMP) if (TrInput & IN_JUMP)
item->goalAnimState = STATE_LARA_ONWATER_STOP; item->goalAnimState = LS_ONWATER_STOP;
item->fallspeed += 8; item->fallspeed += 8;
if (item->fallspeed > 60) if (item->fallspeed > 60)
@ -314,11 +315,11 @@ void LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll)//4D4F0(<), 4D954(<)
} }
else else
{ {
item->goalAnimState = STATE_LARA_UNDERWATER_FORWARD; item->goalAnimState = LS_UNDERWATER_FORWARD;
item->currentAnimState = STATE_LARA_UNDERWATER_DIVING; item->currentAnimState = LS_DIVE;
item->animNumber = ANIMATION_LARA_FREE_FALL_TO_UNDERWATER_ALTERNATE; item->animNumber = LA_ONWATER_DIVE;
item->pos.xRot = -8190; item->pos.xRot = -8190;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->fallspeed = 80; item->fallspeed = 80;
Lara.waterStatus = LW_UNDERWATER; Lara.waterStatus = LW_UNDERWATER;
} }
@ -388,49 +389,49 @@ int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)//4D22C, 4D690
{ {
if ((LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512) && EnableCrawlFlexWaterPullUp == true) if ((LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512) && EnableCrawlFlexWaterPullUp == true)
{ {
item->animNumber = ANIMATION_LARA_CLIMB_OUT_OF_WATER_TO_2CLICK; item->animNumber = LA_ONWATER_TO_CROUCH_1CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = ANIMATION_LARA_CROUCH_IDLE; item->goalAnimState = LA_CROUCH_IDLE;
} }
else else
{ {
item->animNumber = ANIMATION_LARA_CLIMB_OUT_OF_WATER; item->animNumber = LA_ONWATER_TO_STAND_1CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_STOP; item->goalAnimState = LS_STOP;
} }
} }
else if (frontFloor > 128) else if (frontFloor > 128)
{ {
if ((LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512) && EnableCrawlFlexSubmerged == true) if ((LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512) && EnableCrawlFlexSubmerged == true)
{ {
item->animNumber = ANIMATION_LARA_WATER_TO_SUBMERGED_CRAWL; item->animNumber = LA_ONWATER_TO_CROUCH_M1CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = ANIMATION_LARA_CROUCH_IDLE; item->goalAnimState = LA_CROUCH_IDLE;
} }
else else
item->animNumber = ANIMATION_LARA_ONWATER_TO_WADE; item->animNumber = LA_ONWATER_TO_STAND_M1CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
} }
else else
{ {
if ((LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512) && EnableCrawlFlexWaterPullUp == true) if ((LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512) && EnableCrawlFlexWaterPullUp == true)
{ {
item->animNumber = ANIMATION_LARA_ONWATER_TO_LAND_LOW_TO_2CLICK; item->animNumber = LA_ONWATER_TO_CROUCH_0CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = ANIMATION_LARA_CROUCH_IDLE; item->goalAnimState = LA_CROUCH_IDLE;
} }
else else
{ {
item->animNumber = ANIMATION_LARA_ONWATER_TO_LAND_LOW; item->animNumber = LA_ONWATER_TO_STAND_0CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_STOP; item->goalAnimState = LS_STOP;
} }
} }
item->currentAnimState = STATE_LARA_ONWATER_EXIT; item->currentAnimState = LS_ONWATER_EXIT;
item->pos.yRot = rot; item->pos.yRot = rot;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
item->pos.zRot = 0; item->pos.zRot = 0;
@ -455,28 +456,28 @@ int LaraTestWaterStepOut(ITEM_INFO* item, COLL_INFO* coll)//4D100, 4D564 (F)
if (coll->midFloor >= -128) if (coll->midFloor >= -128)
{ {
if (item->goalAnimState == STATE_LARA_ONWATER_LEFT) if (item->goalAnimState == LS_ONWATER_LEFT)
{ {
item->goalAnimState = STATE_LARA_WALK_LEFT; item->goalAnimState = LS_STEP_LEFT;
} }
else if (item->goalAnimState == STATE_LARA_ONWATER_RIGHT) else if (item->goalAnimState == LS_ONWATER_RIGHT)
{ {
item->goalAnimState = STATE_LARA_WALK_RIGHT; item->goalAnimState = LS_STEP_RIGHT;
} }
else else
{ {
item->animNumber = ANIMATION_LARA_WADE; item->animNumber = LA_WADE;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_LARA_WADE_FORWARD; item->goalAnimState = LS_WADE_FORWARD;
item->currentAnimState = STATE_LARA_WADE_FORWARD; item->currentAnimState = LS_WADE_FORWARD;
} }
} }
else else
{ {
item->animNumber = ANIMATION_LARA_ONWATER_TO_WADE_DEEP; item->animNumber = LA_ONWATER_TO_WADE_1CLICK;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = STATE_LARA_ONWATER_EXIT; item->currentAnimState = LS_ONWATER_EXIT;
item->goalAnimState = STATE_LARA_STOP; item->goalAnimState = LS_STOP;
} }
item->pos.yPos += coll->frontFloor + 695; item->pos.yPos += coll->frontFloor + 695;
@ -493,3 +494,65 @@ int LaraTestWaterStepOut(ITEM_INFO* item, COLL_INFO* coll)//4D100, 4D564 (F)
return 1; return 1;
} }
int LaraTestLadderClimbOut(ITEM_INFO* item, COLL_INFO* coll) // NEW function for water to ladder move
{
if (!Lara.climbStatus || coll->collType != CT_FRONT || !(TrInput & IN_ACTION))
return 0;
if (Lara.gunStatus && (Lara.gunStatus != LG_READY || Lara.gunType != WEAPON_FLARE))
return 0;
if (!LaraTestClimbStance(item, coll))
return 0;
short rot = item->pos.yRot;
if (rot >= -ANGLE(35.0f) && rot <= ANGLE(35.0f))
rot = 0;
else if (rot >= ANGLE(55.0f) && rot <= ANGLE(125.0f))
rot = ANGLE(90.0f);
else if (rot >= ANGLE(145.0f) || rot <= -ANGLE(145.0f))
rot = ANGLE(180.0f);
else if (rot >= -ANGLE(125.0f) && rot <= -ANGLE(55.0f))
rot = -ANGLE(90.0f);
if (rot & 0x3FFF)
return 0;
switch ((unsigned short)rot / ANGLE(90.0f))
{
case NORTH:
item->pos.zPos = (item->pos.zPos | (WALL_SIZE - 1)) - LARA_RAD - 1;
break;
case EAST:
item->pos.xPos = (item->pos.xPos | (WALL_SIZE - 1)) - LARA_RAD - 1;
break;
case SOUTH:
item->pos.zPos = (item->pos.zPos & -WALL_SIZE) + LARA_RAD + 1;
break;
case WEST:
item->pos.xPos = (item->pos.xPos & -WALL_SIZE) + LARA_RAD + 1;
break;
}
item->animNumber = LA_ONWATER_IDLE;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_ONWATER_STOP;
item->goalAnimState = LS_LADDER_IDLE;
AnimateLara(item);
item->pos.yRot = rot;
Lara.gunStatus = LG_HANDS_BUSY;
item->pos.zRot = 0;
item->pos.xRot = 0;
item->gravityStatus = false;
item->speed = 0;
item->fallspeed = 0;
Lara.waterStatus = LW_ABOVE_WATER;
return 1;
}

View file

@ -17,3 +17,4 @@ void _cdecl LaraSurface(ITEM_INFO* item, COLL_INFO* coll);
void _cdecl LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll); void _cdecl LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll);
int _cdecl LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll); int _cdecl LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll);
int _cdecl LaraTestWaterStepOut(ITEM_INFO* item, COLL_INFO* coll); int _cdecl LaraTestWaterStepOut(ITEM_INFO* item, COLL_INFO* coll);
int _cdecl LaraTestLadderClimbOut(ITEM_INFO* item, COLL_INFO* coll); // NEW function for water to ladder move

View file

@ -32,7 +32,7 @@ void LaraWaterCurrent(COLL_INFO* coll) // (F) (D)
{ {
if (Lara.currentActive) if (Lara.currentActive)
{ {
OBJECT_VECTOR* sink = &Camera.fixed[Lara.currentActive - 1]; OBJECT_VECTOR* sink = &FixedCameras[Lara.currentActive - 1];
short angle = mGetAngle(sink->x, sink->z, LaraItem->pos.xPos, LaraItem->pos.zPos); short angle = mGetAngle(sink->x, sink->z, LaraItem->pos.xPos, LaraItem->pos.zPos);
Lara.currentXvel += ((sink->data * (phd_sin(angle - ANGLE(90)) / 4) >> 2) - Lara.currentXvel) >> 4; Lara.currentXvel += ((sink->data * (phd_sin(angle - ANGLE(90)) / 4) >> 2) - Lara.currentXvel) >> 4;
@ -113,7 +113,7 @@ void LaraWaterCurrent(COLL_INFO* coll) // (F) (D)
int GetWaterDepth(int x, int y, int z, short roomNumber)//4CA38, 4CE9C int GetWaterDepth(int x, int y, int z, short roomNumber)//4CA38, 4CE9C
{ {
FLOOR_INFO* floor; FLOOR_INFO* floor;
ROOM_INFO* r = &Rooms[roomNumber]; ROOM_INFO* r = &g_Level.Rooms[roomNumber];
short roomIndex = NO_ROOM; short roomIndex = NO_ROOM;
do do
@ -147,7 +147,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber)//4CA38, 4CE9C
if (roomIndex != NO_ROOM) if (roomIndex != NO_ROOM)
{ {
roomNumber = roomIndex; roomNumber = roomIndex;
r = &Rooms[roomIndex]; r = &g_Level.Rooms[roomIndex];
} }
} while (roomIndex != NO_ROOM); } while (roomIndex != NO_ROOM);
@ -155,7 +155,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber)//4CA38, 4CE9C
{ {
while (floor->skyRoom != NO_ROOM) while (floor->skyRoom != NO_ROOM)
{ {
r = &Rooms[floor->skyRoom]; r = &g_Level.Rooms[floor->skyRoom];
if (!(r->flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP))) if (!(r->flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP)))
{ {
int wh = floor->ceiling << 8; int wh = floor->ceiling << 8;
@ -170,7 +170,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber)//4CA38, 4CE9C
{ {
while (floor->pitRoom != NO_ROOM) while (floor->pitRoom != NO_ROOM)
{ {
r = &Rooms[floor->pitRoom]; r = &g_Level.Rooms[floor->pitRoom];
if (r->flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP)) if (r->flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP))
{ {
int wh = floor->floor << 8; int wh = floor->floor << 8;
@ -260,15 +260,15 @@ void lara_as_tread(ITEM_INFO* item, COLL_INFO* coll)//4C730, 4CB94 (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
if (TrInput & IN_ROLL && LaraDrawType != LARA_DIVESUIT) if (TrInput & IN_ROLL && LaraDrawType != LARA_DIVESUIT)
{ {
item->currentAnimState = STATE_LARA_UNDERWATER_TURNAROUND; item->currentAnimState = LS_UNDERWATER_ROLL;
item->animNumber = ANIMATION_LARA_UNDERWATER_ROLL_BEGIN; item->animNumber = LA_UNDERWATER_ROLL_180_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
} }
else else
{ {
@ -281,7 +281,7 @@ void lara_as_tread(ITEM_INFO* item, COLL_INFO* coll)//4C730, 4CB94 (F)
SwimTurn(item); SwimTurn(item);
if (TrInput & IN_JUMP) if (TrInput & IN_JUMP)
item->goalAnimState = STATE_LARA_UNDERWATER_FORWARD; item->goalAnimState = LS_UNDERWATER_FORWARD;
item->fallspeed -= 6; item->fallspeed -= 6;
@ -297,7 +297,7 @@ void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll)//4C634(<), 4CA98(<) (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -305,9 +305,9 @@ void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll)//4C634(<), 4CA98(<) (F)
{ {
if (LaraDrawType != LARA_DIVESUIT) if (LaraDrawType != LARA_DIVESUIT)
{ {
item->currentAnimState = STATE_LARA_UNDERWATER_TURNAROUND; item->currentAnimState = LS_UNDERWATER_ROLL;
item->animNumber = ANIMATION_LARA_UNDERWATER_ROLL_BEGIN; item->animNumber = LA_UNDERWATER_ROLL_180_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
return; return;
} }
} }
@ -321,21 +321,21 @@ void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll)//4C634(<), 4CA98(<) (F)
} }
if (TrInput & IN_JUMP) if (TrInput & IN_JUMP)
item->goalAnimState = STATE_LARA_UNDERWATER_FORWARD; item->goalAnimState = LS_UNDERWATER_FORWARD;
item->fallspeed -= 6; item->fallspeed -= 6;
if (item->fallspeed < 0) if (item->fallspeed < 0)
item->fallspeed = 0; item->fallspeed = 0;
if (item->fallspeed <= 133) if (item->fallspeed <= 133)
item->goalAnimState = STATE_LARA_UNDERWATER_STOP; item->goalAnimState = LS_UNDERWATER_STOP;
} }
void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll)//4C548(<), 4C9AC(<) (F) void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll)//4C548(<), 4C9AC(<) (F)
{ {
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = STATE_LARA_WATER_DEATH; item->goalAnimState = LS_WATER_DEATH;
return; return;
} }
@ -343,9 +343,9 @@ void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll)//4C548(<), 4C9AC(<) (F)
{ {
if (LaraDrawType != LARA_DIVESUIT) if (LaraDrawType != LARA_DIVESUIT)
{ {
item->currentAnimState = STATE_LARA_UNDERWATER_TURNAROUND; item->currentAnimState = LS_UNDERWATER_ROLL;
item->animNumber = ANIMATION_LARA_UNDERWATER_ROLL_BEGIN; item->animNumber = LA_UNDERWATER_ROLL_180_START;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
return; return;
} }
} }
@ -364,7 +364,7 @@ void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll)//4C548(<), 4C9AC(<) (F)
item->fallspeed = 200; item->fallspeed = 200;
if (!(TrInput & IN_JUMP)) if (!(TrInput & IN_JUMP))
item->goalAnimState = STATE_LARA_UNDERWATER_INERTIA; item->goalAnimState = LS_UNDERWATER_INERTIA;
} }
void lara_as_swimcheat(ITEM_INFO* item, COLL_INFO* coll)//4C3A8, 4C80C (F) void lara_as_swimcheat(ITEM_INFO* item, COLL_INFO* coll)//4C3A8, 4C80C (F)
@ -806,7 +806,6 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C
&& oldZ == item->pos.zPos && oldZ == item->pos.zPos
&& oldXrot == item->pos.xRot && oldXrot == item->pos.xRot
&& oldYrot == item->pos.yRot && oldYrot == item->pos.yRot
/*|| (LOBYTE(v21) = byte_51CEE4) != 0*/
|| flag != 1) || flag != 1)
{ {
if (flag == 2) if (flag == 2)
@ -819,8 +818,6 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C
SoundEffect(SFX_SWIMSUIT_METAL_CLASH, &LaraItem->pos, ((2 * GetRandomControl() + 0x8000) << 8) | 6); SoundEffect(SFX_SWIMSUIT_METAL_CLASH, &LaraItem->pos, ((2 * GetRandomControl() + 0x8000) << 8) | 6);
} }
// CHECK related to cutscene?
//byte_51CEE4 = 30;
if (Lara.anxiety < 96) if (Lara.anxiety < 96)
{ {
Lara.anxiety += 16; Lara.anxiety += 16;
@ -846,15 +843,15 @@ void LaraTestWaterDepth(ITEM_INFO* item, COLL_INFO* coll)//4B4F8(<), 4B95C(<) (F
} }
else if (wd <= 512) else if (wd <= 512)
{ {
item->animNumber = ANIMATION_LARA_UNDERWATER_TO_WADE; item->animNumber = LA_UNDERWATER_TO_STAND;
item->currentAnimState = STATE_LARA_ONWATER_EXIT; item->currentAnimState = LS_ONWATER_EXIT;
item->goalAnimState = STATE_LARA_STOP; item->goalAnimState = LS_STOP;
item->pos.zRot = 0; item->pos.zRot = 0;
item->pos.xRot = 0; item->pos.xRot = 0;
item->speed = 0; item->speed = 0;
item->fallspeed = 0; item->fallspeed = 0;
item->gravityStatus = false; item->gravityStatus = false;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
Lara.waterStatus = LW_WADE; Lara.waterStatus = LW_WADE;
item->pos.yPos = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); item->pos.yPos = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
} }

View file

@ -10,18 +10,29 @@
#define DEFAULT_SWIM_UPDOWN_SPEED 32 #define DEFAULT_SWIM_UPDOWN_SPEED 32
int SlotsUsed; int SlotsUsed;
CREATURE_INFO* BaddieSlots; std::vector<CREATURE_INFO> BaddieSlots;
void InitialiseLOTarray(int allocMem) void InitialiseLOTarray(int allocMem)
{ {
if (allocMem) if (allocMem)
BaddieSlots = (CREATURE_INFO*)game_malloc(sizeof(CREATURE_INFO) * NUM_SLOTS); {
BaddieSlots.clear();
BaddieSlots.resize(NUM_SLOTS);
}
CREATURE_INFO* creature = BaddieSlots; CREATURE_INFO* creature = BaddieSlots.data();
for (int i = 0; i < NUM_SLOTS; i++, creature++) for (int i = 0; i < NUM_SLOTS; i++, creature++)
{ {
creature->itemNum = NO_ITEM; creature->itemNum = NO_ITEM;
creature->LOT.node = (BOX_NODE*)game_malloc(sizeof(BOX_NODE) * NumberBoxes); if (allocMem)
{
creature->LOT.node.clear();
creature->LOT.node.resize(g_Level.Boxes.size());
for (int j = 0; j < g_Level.Boxes.size(); j++)
{
creature->LOT.node.emplace_back(BOX_NODE());
}
}
} }
SlotsUsed = 0; SlotsUsed = 0;
@ -29,7 +40,7 @@ void InitialiseLOTarray(int allocMem)
int EnableBaddieAI(short itemNum, int always) int EnableBaddieAI(short itemNum, int always)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (item->data != NULL) if (item->data != NULL)
return true; return true;
@ -46,10 +57,10 @@ int EnableBaddieAI(short itemNum, int always)
} }
int slotToDisable = -1; int slotToDisable = -1;
CREATURE_INFO* creature = BaddieSlots; CREATURE_INFO* creature = BaddieSlots.data();
for (int slot = 0; slot < NUM_SLOTS; slot++, creature++) for (int slot = 0; slot < NUM_SLOTS; slot++, creature++)
{ {
item = &Items[creature->itemNum]; item = &g_Level.Items[creature->itemNum];
int deltaX = (item->pos.xPos - Camera.pos.x) >> 8; int deltaX = (item->pos.xPos - Camera.pos.x) >> 8;
int deltaY = (item->pos.yPos - Camera.pos.y) >> 8; int deltaY = (item->pos.yPos - Camera.pos.y) >> 8;
@ -66,7 +77,7 @@ int EnableBaddieAI(short itemNum, int always)
if (slotToDisable < 0 || slotToDisable > NUM_SLOTS) if (slotToDisable < 0 || slotToDisable > NUM_SLOTS)
return false; return false;
ITEM_INFO* itemToDisable = &Items[BaddieSlots[slotToDisable].itemNum]; ITEM_INFO* itemToDisable = &g_Level.Items[BaddieSlots[slotToDisable].itemNum];
CREATURE_INFO* creatureToDisable = &BaddieSlots[slotToDisable]; CREATURE_INFO* creatureToDisable = &BaddieSlots[slotToDisable];
itemToDisable->status = ITEM_INVISIBLE; itemToDisable->status = ITEM_INVISIBLE;
@ -76,7 +87,7 @@ int EnableBaddieAI(short itemNum, int always)
} }
else else
{ {
CREATURE_INFO* creature = BaddieSlots; CREATURE_INFO* creature = BaddieSlots.data();
for (int slot = 0; slot < NUM_SLOTS; slot++, creature++) for (int slot = 0; slot < NUM_SLOTS; slot++, creature++)
{ {
if (creature->itemNum == NO_ITEM) if (creature->itemNum == NO_ITEM)
@ -92,7 +103,7 @@ int EnableBaddieAI(short itemNum, int always)
void DisableBaddieAI(short itemNumber) void DisableBaddieAI(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
item->data = NULL; item->data = NULL;
@ -105,8 +116,8 @@ void DisableBaddieAI(short itemNumber)
void InitialiseSlot(short itemNum, short slot) void InitialiseSlot(short itemNum, short slot)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
CREATURE_INFO* creature = &BaddieSlots[slot]; CREATURE_INFO* creature = &BaddieSlots[slot];
item->data = creature; item->data = creature;
@ -261,8 +272,8 @@ void ClearLOT(LOT_INFO* LOT)
LOT->targetBox = NO_BOX; LOT->targetBox = NO_BOX;
LOT->requiredBox = NO_BOX; LOT->requiredBox = NO_BOX;
BOX_NODE* node = LOT->node; BOX_NODE* node = LOT->node.data();
for (int i = 0; i < NumberBoxes; i++) for (int i = 0; i < g_Level.Boxes.size(); i++)
{ {
node->exitBox = NO_BOX; node->exitBox = NO_BOX;
node->nextExpansion = NO_BOX; node->nextExpansion = NO_BOX;
@ -274,16 +285,16 @@ void ClearLOT(LOT_INFO* LOT)
void CreateZone(ITEM_INFO* item) void CreateZone(ITEM_INFO* item)
{ {
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box; item->boxNumber = XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z).box;
if (creature->LOT.fly) if (creature->LOT.fly)
{ {
BOX_NODE* node = creature->LOT.node; BOX_NODE* node = creature->LOT.node.data();
creature->LOT.zoneCount = 0; creature->LOT.zoneCount = 0;
for (int i = 0; i < NumberBoxes; i++) for (int i = 0; i < g_Level.Boxes.size(); i++)
{ {
node->boxNumber = i; node->boxNumber = i;
node++; node++;
@ -292,16 +303,16 @@ void CreateZone(ITEM_INFO* item)
} }
else else
{ {
short* zone = Zones[creature->LOT.zone][FALSE]; int* zone = g_Level.Zones[creature->LOT.zone][0].data();
short* flippedZone = Zones[creature->LOT.zone][TRUE]; int* flippedZone = g_Level.Zones[creature->LOT.zone][1].data();
short zoneNumber = zone[item->boxNumber]; int zoneNumber = zone[item->boxNumber];
short flippedZoneNumber = flippedZone[item->boxNumber]; int flippedZoneNumber = flippedZone[item->boxNumber];
BOX_NODE* node = creature->LOT.node; BOX_NODE* node = creature->LOT.node.data();
creature->LOT.zoneCount = 0; creature->LOT.zoneCount = 0;
for (int i = 0; i < NumberBoxes; i++) for (int i = 0; i < g_Level.Boxes.size(); i++)
{ {
if (*zone == zoneNumber || *flippedZone == flippedZoneNumber) if (*zone == zoneNumber || *flippedZone == flippedZoneNumber)
{ {

View file

@ -3,7 +3,7 @@
constexpr auto NUM_SLOTS = 32; constexpr auto NUM_SLOTS = 32;
extern int SlotsUsed; extern int SlotsUsed;
extern CREATURE_INFO* BaddieSlots; extern std::vector<CREATURE_INFO> BaddieSlots;
void InitialiseLOTarray(int allocMem); void InitialiseLOTarray(int allocMem);
int EnableBaddieAI(short itemNum, int always); int EnableBaddieAI(short itemNum, int always);

View file

@ -1,43 +0,0 @@
#include "framework.h"
#include "malloc.h"
char* malloc_buffer;
int malloc_size;
char* malloc_ptr;
int malloc_free;
int malloc_used;
char* game_malloc(int size)
{
char* ptr;
size = (size + 3) & 0xfffffffc;
if (size <= malloc_free)
{
ptr = malloc_ptr;
malloc_free -= size;
malloc_used += size;
malloc_ptr += size;
return ptr;
}
return 0;
}
void init_game_malloc()
{
malloc_size = 1048576 * 128;
malloc_buffer = (char*)malloc(malloc_size);
malloc_ptr = malloc_buffer;
malloc_free = malloc_size;
malloc_used = 0;
}
void game_free(int size, int type)
{
size = (size + 3) & (~3);
malloc_ptr -= size;
malloc_free += size;
malloc_used -= size;
}

View file

@ -1,11 +0,0 @@
#pragma once
extern char* malloc_buffer;
extern int malloc_size;
extern char* malloc_ptr;
extern int malloc_free;
extern int malloc_used;
char* game_malloc(int size);
void init_game_malloc();
void game_free(int size, int type);

View file

@ -0,0 +1,48 @@
#pragma once
#include <cstdint>
#include <iterator>
#include <vector>
#include <iostream>
#include "pool.h"
#include <limits>
namespace T5M::Memory {
template <typename T,typename Pool>
class PoolAllocator {
public:
Pool* pool;
typedef std::size_t size_type;
typedef T* pointer;
typedef T value_type;
PoolAllocator(Pool* pool) : pool(pool) {}
PoolAllocator(const PoolAllocator& other) throw() : pool(other.pool) {};
template<typename U>
PoolAllocator(const PoolAllocator<U,Pool>& other) throw() : pool(other.pool) {};
template<typename U>
PoolAllocator& operator = (const PoolAllocator<U,Pool>& other) {
return *this;
}
PoolAllocator<T,Pool>& operator = (const PoolAllocator& other) {
return *this;
}
~PoolAllocator() {}
pointer allocate(size_type n, const void* hint = 0) {
return (pool)->malloc<value_type>(n);
}
void deallocate(T* ptr, size_type n) {
(pool)->free(ptr);
}
size_type max_size() const {
#pragma push_macro("max") //thanks Microsoft
#undef max
return std::numeric_limits<size_type>::max();
#pragma pop_macro("max")
}
};
}

View file

@ -0,0 +1,43 @@
#pragma once
#include <memory>
#include "Game/debug/assert.h"
#include "Game/debug/log.h"
namespace T5M::Memory {
enum class MemoryUnit : size_t {
Byte = 1,
KByte = Byte*1024,
MByte = KByte*1024,
GByte = MByte*1024,
};
class LinearPool {
private:
const size_t allocatedBytes;
const std::unique_ptr<uint8_t> bytes;
size_t offset;
public:
LinearPool(size_t amount, MemoryUnit unit) : allocatedBytes(amount* static_cast<size_t>(unit)), bytes(new uint8_t[allocatedBytes]) {
offset = 0;
}
template<typename T>
[[nodiscard]]T* malloc(size_t count = 1) noexcept {
assertm(sizeof(T) * count >= 1, "Requested memory needs to be greater than 0!");
size_t requestedBytes = sizeof(T) * count;
Log("LinearPool - Malloc :" << requestedBytes << " Bytes")
assertm(offset + requestedBytes > allocatedBytes, "Memory must not overflow linear pool!");
T* returnValue = reinterpret_cast<T*>(bytes.get()[offset]);
offset += requestedBytes;
Log("LinearPool - Malloc : New Offset at " << offset)
return returnValue;
}
void flush() noexcept {
std::memset(bytes.get(), 0, allocatedBytes);
offset = 0;
}
public:
size_t size() const {
return allocatedBytes;
}
};
}

View file

@ -0,0 +1,41 @@
#pragma once
#include <cstdint>
#include <iterator>
#include <vector>
#include <iostream>
#include "linearPool.h"
template <typename T>
class LinearPoolAllocator {
private:
LinearPool* pool;
public:
typedef std::size_t size_type;
typedef T* pointer;
typedef T value_type;
LinearPoolAllocator(LinearPool* pool) : pool(pool){}
LinearPoolAllocator(const LinearPoolAllocator& other) throw() : pool(other.pool) {};
template<typename U>
LinearPoolAllocator(const LinearPoolAllocator<U>& other) throw() : pool(other.pool) {};
template<typename U>
LinearPoolAllocator& operator = (const LinearPoolAllocator<U>& other) {
return *this;
}
LinearPoolAllocator<T>& operator = (const LinearPoolAllocator& other) {
return *this;
}
~LinearPoolAllocator() {}
pointer allocate(size_type n, const void* hint = 0) {
return pool->malloc<value_type>(n);
}
void deallocate(T* ptr, size_type n) {}
size_type max_size() const {
return pool->size();
}
};

View file

@ -0,0 +1,20 @@
#include "framework.h"
#include "malloc.h"
#include "door.h"
#include "PoolAllocator.h"
using namespace T5M::Memory;
char* malloc_buffer;
int malloc_size;
char* malloc_ptr;
int malloc_free;
int malloc_used;
TGPool* gameMemory;
void init_game_malloc() noexcept
{
gameMemory = new TGPool(8 * 1024 * 1024);
}
void game_free(void* ptr) noexcept
{
gameMemory->free(ptr);
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "pool.h"
#include <utility>
#include "memory/memory.h"
extern char* malloc_buffer;
extern int malloc_size;
extern char* malloc_ptr;
extern int malloc_free;
extern int malloc_used;
extern T5M::Memory::TGPool* gameMemory;
template <typename T,typename ... Args>
[[nodiscard]] T* game_malloc(size_t count = 1,Args&&...args) noexcept {
return gameMemory->malloc<T>(count,std::forward<Args>(args)...);
}
void init_game_malloc() noexcept;
void game_free(void* ptr) noexcept;

View file

@ -0,0 +1,8 @@
#pragma once
#include "pool.h"
#include "PoolAllocator.h"
#include <vector>
namespace T5M::Memory {
using TGPool = Pool<BlockSize::Medium>;
template<typename T> using vector = std::vector <T, PoolAllocator<T, TGPool>>;
}

202
TR5Main/Game/memory/pool.h Normal file
View file

@ -0,0 +1,202 @@
#pragma once
#include <stdint.h>
#include <memory>
#include <iostream>
#include "../debug/debug.h"
#include <type_traits>
namespace T5M::Memory {
//Block Size suggestions
enum class BlockSize : size_t {
Minimal = 4,
Tiny = 8,
Small = 16,
Medium = 32,
Big = 64,
Huge = 128,
};
//A multi purpose Memory pool
template<BlockSize BlkSz>
class Pool {
static constexpr char MAGIC[] = "Everything's okay";
using Size = size_t;
using Byte = uint8_t;
using Magic = uint32_t;
//Block representation
struct Block {
Byte data[static_cast<Size>(BlkSz)];
};
// Block Header Data. Contains either Data about Free Blocks in the case of Free
// Or Number of Blocks that were allocated in the case of Used
union BlockHeader;
struct BlockHeaderData {
const char* magic;
//pointer to the next BlockHeader, nullptr if tail
BlockHeader* nextFreeBlock;
//pointer to the previous BlockHeader, nullptr if head
BlockHeader* previousFreeBlock;
//number of Free Blocks / Used Blocks
Size managedBlocks;
//whether this Header is Free or Used
bool isFree;
//pointer to the next physical block header
BlockHeader* nextPhysicalBlock;
//pointer to the previous physical block header
BlockHeader* previousPhysicalBlock;
//pointer to first physical block header
BlockHeaderData() : magic(MAGIC), nextFreeBlock(nullptr), previousFreeBlock(nullptr), managedBlocks(0), nextPhysicalBlock(nullptr), previousPhysicalBlock(nullptr), isFree(false) {}
BlockHeaderData(BlockHeaderData&&) = default;
BlockHeaderData(const BlockHeaderData&) = default;
};
union BlockHeader {
BlockHeaderData data;
//Padding to ensure BlockHeader is always the next multiple of BlkSz blocks large
Block padding[getBlockCount(sizeof(BlockHeaderData))];
BlockHeader() : data(BlockHeaderData()) {};
BlockHeader(BlockHeader&&) = default;
BlockHeader(const BlockHeader&) = default;
};
private:
Size allocatedBlockCount;
Size allocatedBytesCount;
const std::unique_ptr<Block> allocatedBlocks;
BlockHeader* head;
BlockHeader* firstPhysicalBlock;
void initialize() {
std::memset(allocatedBlocks.get(), 0, allocatedBytesCount);
// Place initial BlockHeader at the beginning of all blocks
head = new(allocatedBlocks.get())BlockHeader();
head->data.nextFreeBlock = nullptr;
head->data.managedBlocks = allocatedBlockCount - getHeaderBlockCount();
head->data.previousFreeBlock = nullptr;
head->data.nextPhysicalBlock = nullptr;
head->data.previousPhysicalBlock = nullptr;
this->firstPhysicalBlock = head;
}
public:
Pool(Size numBlocks) : allocatedBlockCount(numBlocks), allocatedBytesCount(sizeof(Block)* numBlocks) , allocatedBlocks(new Block[numBlocks]) {
initialize();
logD("Pool Init: Initialized Pool with ", numBlocks ," Blocks");
logD("Pool Init: Free Blocks :" , head->data.managedBlocks);
}
Pool(Pool&&) = delete;
Pool(const Pool&) = delete;
~Pool() = default;
private:
static constexpr Size getBlockCount(Size bytes) {
return (bytes + (static_cast<Size>(BlkSz) - 1)) / static_cast<Size>(BlkSz);
}
constexpr Size getHeaderBlockCount() const {
return getBlockCount(sizeof(BlockHeader));
};
BlockHeader*& getFreeListHead() {
return head;
}
void tryCoalesce(BlockHeader* origin) {
BlockHeader* left = origin->data.previousPhysicalBlock;
BlockHeader* right = origin->data.nextPhysicalBlock;
if (right != nullptr && right->data.isFree)
coalesce(origin, right);
if (left != nullptr && left->data.isFree)
coalesce(left, origin);
}
void coalesce(BlockHeader* left, BlockHeader* right) {
logD("Coalescing BlockHeader at " , left , " & " , right);
left->data.managedBlocks += right->data.managedBlocks;
left->data.managedBlocks += getHeaderBlockCount();
left->data.nextFreeBlock = right->data.nextFreeBlock;
left->data.nextPhysicalBlock = right->data.nextPhysicalBlock;
if (right->data.nextFreeBlock != nullptr) {
right->data.nextFreeBlock->data.previousFreeBlock = left;
right->data.nextPhysicalBlock->data.previousPhysicalBlock = left;
}
}
void splitBlocks(BlockHeader*& nodeToSplit, size_t& requestedBlocks, Block* whereToSplit) {
Size numFreeBlocksAfterSplit = nodeToSplit->data.managedBlocks - getHeaderBlockCount();
nodeToSplit->data.managedBlocks = requestedBlocks;
nodeToSplit->data.isFree = false;
Block* splitBlock = whereToSplit;
placeNewFreeHead(splitBlock, nodeToSplit, numFreeBlocksAfterSplit);
logD("Malloc: New Free Blocks : ", numFreeBlocksAfterSplit);
}
void placeNewFreeHead(Block*& position, BlockHeader*& oldFreeBlock, size_t& numManagedBlocks) {
BlockHeader* newHead = new(position)BlockHeader();
logD("Malloc: New Head at ", newHead);
newHead->data.previousPhysicalBlock = oldFreeBlock;
BlockHeader* physicalRightBlock = oldFreeBlock->data.nextPhysicalBlock;
newHead->data.nextPhysicalBlock = physicalRightBlock;
if (physicalRightBlock != nullptr)
physicalRightBlock->data.previousPhysicalBlock = newHead;
oldFreeBlock->data.nextPhysicalBlock = newHead;
newHead->data.isFree = true;
head = newHead;
head->data.nextFreeBlock = oldFreeBlock->data.nextFreeBlock;
head->data.managedBlocks = numManagedBlocks;
}
Block* getFirstManagedBlock(BlockHeader* header) const {
return reinterpret_cast<Block*>(header + 1);
}
BlockHeader* getBlockHeaderFromBlock(Block* block) const {
return (reinterpret_cast<BlockHeader*>(block)) - 1;
}
public:
template <typename T>
void free(T* ptr) noexcept {
assertion((static_cast<void*>(ptr) >= allocatedBlocks.get() && static_cast<void*>(ptr) < (allocatedBlocks.get() + allocatedBlockCount)), "memory must be in Pool range!");
ptr->~T();
Block* block = reinterpret_cast<Block*>(ptr);
BlockHeader* blockHead = getBlockHeaderFromBlock(block);
if (blockHead->data.magic == MAGIC) {
logD("Free: BlockHeader at ", blockHead);
BlockHeader* oldHead = head;
BlockHeader* newHead = blockHead;
head = newHead;
head->data.isFree = true;
head->data.nextFreeBlock = oldHead;
oldHead->data.previousFreeBlock = head;
tryCoalesce(blockHead);
tryCoalesce(oldHead);
}
}
template <typename T,typename ... Args>
[[nodiscard]]T* malloc(Size count = 1,Args&&...args) noexcept {
if (count < 1) return nullptr;
Size requestedBlocks = getBlockCount(sizeof(T) * count);
logD("Malloc: Requested Blocks for " , typeid(T).name() , " x " , count , ": " , requestedBlocks);
BlockHeader* currentFreeNode = getFreeListHead();
while (currentFreeNode != nullptr && currentFreeNode->data.isFree && currentFreeNode->data.managedBlocks < requestedBlocks+getHeaderBlockCount()) {
assertion(currentFreeNode->data.magic == MAGIC, "Pool is corrupt");
currentFreeNode = currentFreeNode->data.nextFreeBlock;
}
assertion(currentFreeNode != nullptr, "Pool is full");
Block* blockToReturn = getFirstManagedBlock(currentFreeNode);
logD("Malloc: Return block at " , blockToReturn);
splitBlocks(currentFreeNode, requestedBlocks, blockToReturn + requestedBlocks + 1);
return new(blockToReturn)T(std::forward<Args>(args)...);
}
void reset() {
initialize();
}
};
}

View file

@ -7,12 +7,12 @@
using std::vector; using std::vector;
short GF(short animIndex, short frameToStart) short GF(short animIndex, short frameToStart)
{ {
return Anims[animIndex].frameBase + frameToStart; return g_Level.Anims[animIndex].frameBase + frameToStart;
} }
short GF2(short objectID, short animIndex, short frameToStart) short GF2(short objectID, short animIndex, short frameToStart)
{ {
return Anims[Objects[objectID].animIndex + animIndex].frameBase + frameToStart; return g_Level.Anims[Objects[objectID].animIndex + animIndex].frameBase + frameToStart;
} }
CREATURE_INFO* GetCreatureInfo(ITEM_INFO* item) CREATURE_INFO* GetCreatureInfo(ITEM_INFO* item)
@ -28,9 +28,9 @@ void TargetNearestEntity(ITEM_INFO* item, CREATURE_INFO* creature)
int x, z; int x, z;
bestdistance = MAXINT; bestdistance = MAXINT;
for (int i = 0; i < LevelItems; i++) for (int i = 0; i < g_Level.NumItems; i++)
{ {
target = &Items[i]; target = &g_Level.Items[i];
if (target != nullptr) if (target != nullptr)
{ {
if (target != item && target->hitPoints > 0 && target->status != ITEM_INVISIBLE) if (target != item && target->hitPoints > 0 && target->status != ITEM_INVISIBLE)
@ -50,12 +50,14 @@ void TargetNearestEntity(ITEM_INFO* item, CREATURE_INFO* creature)
void GetRoomList(short roomNumber, short* roomArray, short* numRooms) void GetRoomList(short roomNumber, short* roomArray, short* numRooms)
{ {
if (*numRooms <= 0)
return;
short numDoors, * door, adjoiningRoom; short numDoors, * door, adjoiningRoom;
int i, j; int i, j;
bool adjoiningRoomFound; bool adjoiningRoomFound;
roomArray[0] = roomNumber; roomArray[0] = roomNumber;
ROOM_INFO* room = &Rooms[roomNumber]; ROOM_INFO* room = &g_Level.Rooms[roomNumber];
for (i = 0; i < room->doors.size(); i++) for (i = 0; i < room->doors.size(); i++)
{ {
@ -84,7 +86,7 @@ void GetRoomList(short roomNumber, vector<short>* destRoomList)
bool adjoiningRoomFound; bool adjoiningRoomFound;
roomList.push_back(roomNumber); roomList.push_back(roomNumber);
ROOM_INFO* room = &Rooms[roomNumber]; ROOM_INFO* room = &g_Level.Rooms[roomNumber];
for (i = 0; i < room->doors.size(); i++) for (i = 0; i < room->doors.size(); i++)
{ {

View file

@ -20,14 +20,14 @@
void ShootAtLara(FX_INFO *fx) void ShootAtLara(FX_INFO *fx)
{ {
int x, y, z, distance; int x, y, z, distance;
short* bounds; BOUNDING_BOX* bounds;
x = LaraItem->pos.xPos - fx->pos.xPos; x = LaraItem->pos.xPos - fx->pos.xPos;
y = LaraItem->pos.yPos - fx->pos.yPos; y = LaraItem->pos.yPos - fx->pos.yPos;
z = LaraItem->pos.zPos - fx->pos.zPos; z = LaraItem->pos.zPos - fx->pos.zPos;
bounds = GetBoundsAccurate(LaraItem); bounds = GetBoundsAccurate(LaraItem);
y += bounds[3] + (bounds[2] - bounds[3]) * 3 / 4; y += bounds->Y2 + (bounds->Y1 - bounds->Y2) * 3 / 4;
distance = sqrt(SQUARE(x) + SQUARE(z)); distance = sqrt(SQUARE(x) + SQUARE(z));
fx->pos.xRot = -phd_atan(distance, y); fx->pos.xRot = -phd_atan(distance, y);
@ -45,10 +45,10 @@ void ControlMissile(short fxNumber)
short roomNumber; short roomNumber;
int speed; int speed;
fx = &Effects[fxNumber]; fx = &EffectList[fxNumber];
printf("ControlMissile\n"); printf("ControlMissile\n");
if (fx->objectNumber == ID_SCUBA_HARPOON && !(Rooms[fx->roomNumber].flags & 1) && fx->pos.xRot > -0x3000) if (fx->objectNumber == ID_SCUBA_HARPOON && !(g_Level.Rooms[fx->roomNumber].flags & 1) && fx->pos.xRot > -0x3000)
fx->pos.xRot -= ONE_DEGREE; fx->pos.xRot -= ONE_DEGREE;
fx->pos.yPos += (fx->speed * phd_sin(-fx->pos.xRot) >> W2V_SHIFT); fx->pos.yPos += (fx->speed * phd_sin(-fx->pos.xRot) >> W2V_SHIFT);
@ -115,7 +115,7 @@ void ControlMissile(short fxNumber)
} }
/* Create bubbles in wake of harpoon bolt */ /* Create bubbles in wake of harpoon bolt */
//if (fx->objectNumber == ID_SCUBA_HARPOON && Rooms[fx->roomNumber].flags & 1) //if (fx->objectNumber == ID_SCUBA_HARPOON && g_Level.Rooms[fx->roomNumber].flags & 1)
// CreateBubble(&fx->pos, fx->roomNumber, 1, 0); // CreateBubble(&fx->pos, fx->roomNumber, 1, 0);
/*else if (fx->objectNumber == DRAGON_FIRE && !fx->counter--) /*else if (fx->objectNumber == DRAGON_FIRE && !fx->counter--)
{ {
@ -130,12 +130,12 @@ void ControlMissile(short fxNumber)
void ControlNatlaGun(short fx_number) void ControlNatlaGun(short fx_number)
{ {
FX_INFO* fx, *newfx; FX_INFO* fx, *newfx;
ObjectInfo* object; OBJECT_INFO* object;
FLOOR_INFO* floor; FLOOR_INFO* floor;
short roomNumber; short roomNumber;
int x, y, z; int x, y, z;
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
object = &Objects[fx->objectNumber]; object = &Objects[fx->objectNumber];
fx->frameNumber--; fx->frameNumber--;
if (fx->frameNumber <= Objects[fx->objectNumber].nmeshes) if (fx->frameNumber <= Objects[fx->objectNumber].nmeshes)
@ -157,7 +157,7 @@ void ControlNatlaGun(short fx_number)
fx_number = CreateNewEffect(roomNumber); fx_number = CreateNewEffect(roomNumber);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
newfx = &Effects[fx_number]; newfx = &EffectList[fx_number];
newfx->pos.xPos = x; newfx->pos.xPos = x;
newfx->pos.yPos = y; newfx->pos.yPos = y;
newfx->pos.zPos = z; newfx->pos.zPos = z;
@ -178,7 +178,7 @@ short ShardGun(int x, int y, int z, short speed, short yrot, short roomNumber)
fx_number = CreateNewEffect(roomNumber); fx_number = CreateNewEffect(roomNumber);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
fx->pos.xPos = x; fx->pos.xPos = x;
fx->pos.yPos = y; fx->pos.yPos = y;
fx->pos.zPos = z; fx->pos.zPos = z;
@ -203,7 +203,7 @@ short BombGun(int x, int y, int z, short speed, short yrot, short roomNumber)
fx_number = CreateNewEffect(roomNumber); fx_number = CreateNewEffect(roomNumber);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
fx->pos.xPos = x; fx->pos.xPos = x;
fx->pos.yPos = y; fx->pos.yPos = y;
fx->pos.zPos = z; fx->pos.zPos = z;
@ -228,7 +228,7 @@ short NatlaGun(int x, int y, int z, short speed, short yrot, short roomNumber)
fx_number = CreateNewEffect(roomNumber); fx_number = CreateNewEffect(roomNumber);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
fx->pos.xPos = x; fx->pos.xPos = x;
fx->pos.yPos = y; fx->pos.yPos = y;
fx->pos.zPos = z; fx->pos.zPos = z;

View file

@ -19,30 +19,26 @@
OBJECT_TEXTURE* WaterfallTextures[6]; OBJECT_TEXTURE* WaterfallTextures[6];
float WaterfallY[6]; float WaterfallY[6];
int lastWaterfallY = 0; int lastWaterfallY = 0;
short TightRopeBounds[12] = OBJECT_COLLISION_BOUNDS TightRopeBounds =
{ {
0xFF00, 0x0100, 0x0000, 0x0000, 0xFF00, 0x0100, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xFF00, 0x0100, 0x0000, 0x0000, 0xFF00, 0x0100, 0xF8E4, 0x071C, 0xEAAC, 0x1554,
0xF8E4, 0x071C 0xF8E4, 0x071C
}; };
PHD_VECTOR TightRopePos = { 0, 0, 0 }; PHD_VECTOR TightRopePos = { 0, 0, 0 };
short ParallelBarsBounds[12] = OBJECT_COLLISION_BOUNDS ParallelBarsBounds =
{ {
0xFD80, 0x0280, 0x02C0, 0x0340, 0xFFA0, 0x0060, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C 0xFD80, 0x0280, 0x02C0, 0x0340, 0xFFA0, 0x0060, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xF8E4, 0x071C
}; };
PHD_VECTOR PolePos = { 0, 0, -208 }; PHD_VECTOR PolePos = { 0, 0, -208 };
PHD_VECTOR PolePosR = { 0, 0, 0 }; PHD_VECTOR PolePosR = { 0, 0, 0 };
short PoleBounds[12] = // offset 0xA1250 OBJECT_COLLISION_BOUNDS PoleBounds = // offset 0xA1250
{ {
0xFF00, 0x0100, 0x0000, 0x0000, 0xFE00, 0x0200, 0xF8E4, 0x071C, 0xEAAC, 0x1554, 0xFF00, 0x0100, 0x0000, 0x0000, 0xFE00, 0x0200, 0xF8E4, 0x071C, 0xEAAC, 0x1554,
0xF8E4, 0x071C 0xF8E4, 0x071C
}; };
void BridgeFlatFloor(ITEM_INFO* item, int x, int y, int z, int* height) void BridgeFlatFloor(ITEM_INFO* item, int x, int y, int z, int* height)
{ {
if (item->pos.yPos >= y) if (item->pos.yPos >= y)
@ -128,7 +124,7 @@ void BridgeTilt2Ceiling(ITEM_INFO* item, int x, int y, int z, int* height)
void ControlAnimatingSlots(short itemNumber) void ControlAnimatingSlots(short itemNumber)
{ {
// TODO: TR5 has here a series of hardcoded OCB codes, this function actually is just a placeholder // TODO: TR5 has here a series of hardcoded OCB codes, this function actually is just a placeholder
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item)) if (TriggerActive(item))
AnimateItem(item); AnimateItem(item);
@ -136,21 +132,21 @@ void ControlAnimatingSlots(short itemNumber)
void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if ((TrInput & IN_ACTION) && !Lara.gunStatus && l->currentAnimState == STATE_LARA_STOP && if ((TrInput & IN_ACTION) && !Lara.gunStatus && l->currentAnimState == LS_STOP &&
l->animNumber == ANIMATION_LARA_STAY_IDLE l->animNumber == LA_STAND_IDLE
|| Lara.isMoving && Lara.generalPtr == (void*)itemNumber) || Lara.isMoving && Lara.generalPtr == (void*)itemNumber)
{ {
short rot = item->pos.yRot; short rot = item->pos.yRot;
item->pos.yRot = l->pos.yRot; item->pos.yRot = l->pos.yRot;
if (TestLaraPosition(PoleBounds, item, l)) if (TestLaraPosition(&PoleBounds, item, l))
{ {
if (MoveLaraPosition(&PolePos, item, l)) if (MoveLaraPosition(&PolePos, item, l))
{ {
l->animNumber = ANIMATION_LARA_STAY_TO_POLE_GRAB; l->animNumber = LA_STAND_TO_POLE;
l->currentAnimState = STATE_LARA_POLE_IDLE; l->currentAnimState = LS_POLE_IDLE;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
Lara.isMoving = false; Lara.isMoving = false;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
} }
@ -174,7 +170,7 @@ void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
&& !Lara.gunStatus && !Lara.gunStatus
&& l->gravityStatus && l->gravityStatus
&& l->fallspeed > Lara.gunStatus && l->fallspeed > Lara.gunStatus
&& (l->currentAnimState == STATE_LARA_REACH || l->currentAnimState == STATE_LARA_JUMP_UP)) && (l->currentAnimState == LS_REACH || l->currentAnimState == LS_JUMP_UP))
{ {
if (TestBoundsCollide(item, l, 100)) if (TestBoundsCollide(item, l, 100))
{ {
@ -182,23 +178,23 @@ void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{ {
short rot = item->pos.yRot; short rot = item->pos.yRot;
item->pos.yRot = l->pos.yRot; item->pos.yRot = l->pos.yRot;
if (l->currentAnimState == STATE_LARA_REACH) if (l->currentAnimState == LS_REACH)
{ {
PolePosR.y = l->pos.yPos - item->pos.yPos + 10; PolePosR.y = l->pos.yPos - item->pos.yPos + 10;
AlignLaraPosition(&PolePosR, item, l); AlignLaraPosition(&PolePosR, item, l);
l->animNumber = ANIMATION_LARA_JUMP_FORWARD_TO_POLE_GRAB; l->animNumber = LA_REACH_TO_POLE;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
} }
else else
{ {
PolePosR.y = l->pos.yPos - item->pos.yPos + 66; PolePosR.y = l->pos.yPos - item->pos.yPos + 66;
AlignLaraPosition(&PolePosR, item, l); AlignLaraPosition(&PolePosR, item, l);
l->animNumber = ANIMATION_LARA_JUMP_UP_TO_POLE_GRAB; l->animNumber = LA_JUMP_UP_TO_POLE;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
} }
l->gravityStatus = false; l->gravityStatus = false;
l->fallspeed = false; l->fallspeed = false;
l->currentAnimState = STATE_LARA_POLE_IDLE; l->currentAnimState = LS_POLE_IDLE;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
item->pos.yRot = rot; item->pos.yRot = rot;
} }
@ -206,15 +202,15 @@ void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
} }
else else
{ {
if ((l->currentAnimState < STATE_LARA_POLE_IDLE || l->currentAnimState > STATE_LARA_POLE_TURN_RIGHT) && if ((l->currentAnimState < LS_POLE_IDLE || l->currentAnimState > LS_POLE_TURN_COUNTER_CLOCKWISE) &&
l->currentAnimState != STATE_LARA_JUMP_BACK) l->currentAnimState != LS_JUMP_BACK)
ObjectCollision(itemNumber, l, coll); ObjectCollision(itemNumber, l, coll);
} }
} }
void ControlTriggerTriggerer(short itemNumber) void ControlTriggerTriggerer(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &item->roomNumber); FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &item->roomNumber);
int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
@ -285,7 +281,7 @@ void AnimateWaterfalls()
void ControlWaterfall(short itemNumber) void ControlWaterfall(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
TriggerActive(item); TriggerActive(item);
if (itemNumber != 0) if (itemNumber != 0)
@ -312,17 +308,17 @@ void ControlWaterfall(short itemNumber)
void TightRopeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void TightRopeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (((TrInput & IN_ACTION) == 0 if (((TrInput & IN_ACTION) == 0
|| l->currentAnimState != STATE_LARA_STOP || l->currentAnimState != LS_STOP
|| l->animNumber != ANIMATION_LARA_STAY_IDLE || l->animNumber != LA_STAND_IDLE
|| l->status == ITEM_INVISIBLE || l->status == ITEM_INVISIBLE
|| Lara.gunStatus) || Lara.gunStatus)
&& (!Lara.isMoving || Lara.generalPtr != (void*)itemNum)) && (!Lara.isMoving || Lara.generalPtr != (void*)itemNum))
{ {
if (l->currentAnimState == STATE_LARA_TIGHTROPE_FORWARD && if (l->currentAnimState == LS_TIGHTROPE_FORWARD &&
l->goalAnimState != STATE_LARA_TIGHTROPE_EXIT && l->goalAnimState != LS_TIGHTROPE_EXIT &&
!Lara.tightRopeOff) !Lara.tightRopeOff)
{ {
if (item->pos.yRot == l->pos.yRot) if (item->pos.yRot == l->pos.yRot)
@ -335,13 +331,13 @@ void TightRopeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
else else
{ {
item->pos.yRot += -ANGLE(180); item->pos.yRot += -ANGLE(180);
if (TestLaraPosition(TightRopeBounds, item, l)) if (TestLaraPosition(&TightRopeBounds, item, l))
{ {
if (MoveLaraPosition(&TightRopePos, item, l)) if (MoveLaraPosition(&TightRopePos, item, l))
{ {
l->currentAnimState = STATE_LARA_TIGHTROPE_ENTER; l->currentAnimState = LS_TIGHTROPE_ENTER;
l->animNumber = ANIMATION_LARA_TIGHTROPE_START; l->animNumber = LA_TIGHTROPE_START;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
Lara.isMoving = false; Lara.isMoving = false;
Lara.headYrot = 0; Lara.headYrot = 0;
Lara.headXrot = 0; Lara.headXrot = 0;
@ -368,23 +364,23 @@ void TightRopeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void ParallelBarsCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) void ParallelBarsCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION && l->currentAnimState == STATE_LARA_REACH && l->animNumber == ANIMATION_LARA_TRY_HANG_SOLID) if (TrInput & IN_ACTION && l->currentAnimState == LS_REACH && l->animNumber == LA_REACH)
{ {
int test1 = TestLaraPosition(ParallelBarsBounds, item, l); int test1 = TestLaraPosition(&ParallelBarsBounds, item, l);
int test2 = 0; int test2 = 0;
if (!test1) if (!test1)
{ {
item->pos.yRot += -ANGLE(180); item->pos.yRot += -ANGLE(180);
test2 = TestLaraPosition(ParallelBarsBounds, item, l); test2 = TestLaraPosition(&ParallelBarsBounds, item, l);
item->pos.yRot += -ANGLE(180); item->pos.yRot += -ANGLE(180);
} }
if (test1 || test2) if (test1 || test2)
{ {
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->animNumber = ANIMATION_LARA_BARS_GRAB; l->animNumber = LA_SWINGBAR_GRAB;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
l->fallspeed = false; l->fallspeed = false;
l->gravityStatus = false; l->gravityStatus = false;
@ -424,7 +420,7 @@ void ParallelBarsCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
ObjectCollision(itemNumber, l, coll); ObjectCollision(itemNumber, l, coll);
} }
} }
else if (l->currentAnimState != STATE_LARA_BARS_SWING) else if (l->currentAnimState != LS_BARS_SWING)
{ {
ObjectCollision(itemNumber, l, coll); ObjectCollision(itemNumber, l, coll);
} }
@ -432,7 +428,7 @@ void ParallelBarsCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void ControlXRayMachine(short itemNumber) void ControlXRayMachine(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (!TriggerActive(item)) if (!TriggerActive(item))
return; return;
@ -497,7 +493,7 @@ void ControlXRayMachine(short itemNumber)
if (item->itemFlags[1] < 128) if (item->itemFlags[1] < 128)
{ {
SoundEffect(SFX_LOOP_FOR_SMALL_FIRES, &item->pos, 0); SoundEffect(SFX_LOOP_FOR_SMALL_FIRES, &item->pos, 0);
TriggerFontFire(&Items[item->itemFlags[0]], item->itemFlags[1], item->itemFlags[1] == 0 ? 16 : 1); TriggerFontFire(&g_Level.Items[item->itemFlags[0]], item->itemFlags[1], item->itemFlags[1] == 0 ? 16 : 1);
} }
++item->itemFlags[1]; ++item->itemFlags[1];
@ -505,7 +501,7 @@ void ControlXRayMachine(short itemNumber)
case 333: case 333:
{ {
ROOM_INFO* r = &Rooms[item->roomNumber]; ROOM_INFO* r = &g_Level.Rooms[item->roomNumber];
MESH_INFO* mesh = r->mesh; MESH_INFO* mesh = r->mesh;
int j; int j;
@ -545,17 +541,17 @@ void CutsceneRopeControl(short itemNumber)
int dy; int dy;
int dz; int dz;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
pos1.x = -128; pos1.x = -128;
pos1.y = -72; pos1.y = -72;
pos1.z = -16; pos1.z = -16;
GetJointAbsPosition(&Items[item->itemFlags[2]], &pos1, 0); GetJointAbsPosition(&g_Level.Items[item->itemFlags[2]], &pos1, 0);
pos2.x = 830; pos2.x = 830;
pos2.z = -12; pos2.z = -12;
pos2.y = 0; pos2.y = 0;
GetJointAbsPosition(&Items[item->itemFlags[3]], &pos2, 0); GetJointAbsPosition(&g_Level.Items[item->itemFlags[3]], &pos2, 0);
item->pos.xPos = pos2.x; item->pos.xPos = pos2.x;
item->pos.yPos = pos2.y; item->pos.yPos = pos2.y;
@ -573,11 +569,11 @@ void HybridCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
/*if (gfCurrentLevel == LVL5_SINKING_SUBMARINE) /*if (gfCurrentLevel == LVL5_SINKING_SUBMARINE)
{ {
if (item->frameNumber < Anims[item->animNumber].frame_end) if (item->frameNumber < g_Level.Anims[item->animNumber].frame_end)
{ {
ObjectCollision(itemNum, laraitem, coll); ObjectCollision(itemNum, laraitem, coll);
} }
@ -586,7 +582,7 @@ void HybridCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
void InitialiseTightRope(short itemNumber) void InitialiseTightRope(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->pos.yRot > 0) if (item->pos.yRot > 0)
{ {
@ -612,35 +608,35 @@ void InitialiseTightRope(short itemNumber)
void InitialiseAnimating(short itemNumber) void InitialiseAnimating(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; /*ITEM_INFO* item = &g_Level.Items[itemNumber];
item->currentAnimState = 0; item->currentAnimState = 0;
item->animNumber = Objects[item->objectNumber].animIndex; item->animNumber = Objects[item->objectNumber].animIndex;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;*/
} }
void AnimatingControl(short itemNumber) void AnimatingControl(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (!TriggerActive(item)) if (!TriggerActive(item))
return; return;
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
AnimateItem(item); AnimateItem(item);
if (item->frameNumber >= Anims[item->animNumber].frameEnd) // TODO: ID_SHOOT_SWITCH2 probably the bell in Trajan Markets, use LUA for that
/*if (item->frameNumber >= g_Level.Anims[item->animNumber].frameEnd)
{ {
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
RemoveActiveItem(itemNumber); RemoveActiveItem(itemNumber);
item->aiBits = 0; item->aiBits = 0;
item->status = ITEM_NOT_ACTIVE; item->status = ITEM_NOT_ACTIVE;
} }*/
} }
void HighObject2Control(short itemNumber) void HighObject2Control(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (!TriggerActive(item)) if (!TriggerActive(item))
return; return;

View file

@ -125,20 +125,20 @@ int Targetable(ITEM_INFO* item, AI_INFO* info)
{ {
GAME_VECTOR start, target; GAME_VECTOR start, target;
short* bounds = GetBestFrame(item); BOUNDING_BOX* bounds = (BOUNDING_BOX*)GetBestFrame(item);
start.x = item->pos.xPos; start.x = item->pos.xPos;
if (item->objectNumber == ID_SNIPER) if (item->objectNumber == ID_SNIPER)
start.y = item->pos.yPos - 768; start.y = item->pos.yPos - 768;
else else
start.y = item->pos.yPos + ((bounds[3] + 3 * bounds[2]) >> 2); start.y = item->pos.yPos + ((bounds->Y2 + 3 * bounds->Y1) / 4);
start.z = item->pos.zPos; start.z = item->pos.zPos;
start.roomNumber = item->roomNumber; start.roomNumber = item->roomNumber;
bounds = GetBestFrame(enemy); bounds = (BOUNDING_BOX*)GetBestFrame(enemy);
target.x = enemy->pos.xPos; target.x = enemy->pos.xPos;
target.y = enemy->pos.yPos + ((bounds[3] + 3 * bounds[2]) >> 2); target.y = enemy->pos.yPos + ((bounds->Y2 + 3 * bounds->Y1) / 4);
target.z = enemy->pos.zPos; target.z = enemy->pos.zPos;
return LOS(&start, &target); return LOS(&start, &target);
@ -165,8 +165,8 @@ int TargetVisible(ITEM_INFO* item, AI_INFO* info)
GAME_VECTOR target; GAME_VECTOR target;
target.x = enemy->pos.xPos; target.x = enemy->pos.xPos;
short* bounds = GetBestFrame(enemy); BOUNDING_BOX* bounds = (BOUNDING_BOX*)GetBestFrame(enemy);
target.y = enemy->pos.yPos + ((((bounds[2] << 1) + bounds[2]) + bounds[3]) >> 2); target.y = enemy->pos.yPos + ((((bounds->Y1 * 2) + bounds->Y1) + bounds->Y2) / 4);
target.z = enemy->pos.zPos; target.z = enemy->pos.zPos;
return LOS(&start, &target); return LOS(&start, &target);

View file

@ -76,8 +76,8 @@ typedef struct GAME_VECTOR
int x; int x;
int y; int y;
int z; int z;
int boxNumber;
short roomNumber; short roomNumber;
short boxNumber;
GAME_VECTOR() GAME_VECTOR()
{ {
@ -121,8 +121,8 @@ typedef struct OBJECT_VECTOR
int x; int x;
int y; int y;
int z; int z;
short data; int data;
short flags; int flags;
OBJECT_VECTOR() OBJECT_VECTOR()
{ {
@ -225,3 +225,13 @@ typedef struct MATRIX3D
int ty; int ty;
int tz; int tz;
}; };
struct BOUNDING_BOX
{
short X1;
short X2;
short Y1;
short Y2;
short Z1;
short Z2;
};

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,7 @@ void PuzzleDoneCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void KeyHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll); void KeyHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll); void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void RegeneratePickups(); void RegeneratePickups();
short* FindPlinth(ITEM_INFO* item); BOUNDING_BOX* FindPlinth(ITEM_INFO* item);
void PuzzleDone(ITEM_INFO* item, short itemNum); void PuzzleDone(ITEM_INFO* item, short itemNum);
void PickupControl(short itemNum); void PickupControl(short itemNum);
@ -21,3 +21,4 @@ void InitialiseSearchObject(short itemNumber);
void SearchObjectCollision(short itemNumber, ITEM_INFO* laraitem, COLL_INFO* laracoll); void SearchObjectCollision(short itemNumber, ITEM_INFO* laraitem, COLL_INFO* laracoll);
void SearchObjectControl(short itemNumber); void SearchObjectControl(short itemNumber);
void do_pickup(); void do_pickup();
void do_puzzle();

View file

@ -1,40 +1,17 @@
#pragma once #pragma once
#include <framework.h> #include <framework.h>
#include <newtypes.h>
typedef struct tr5_room_layer struct ANIM_FRAME;
{
unsigned int NumLayerVertices; // Number of vertices in this layer (4 bytes)
unsigned short UnknownL1;
unsigned short NumLayerRectangles; // Number of rectangles in this layer (2 bytes)
unsigned short NumLayerTriangles; // Number of triangles in this layer (2 bytes)
unsigned short UnknownL2;
unsigned short Filler; // Always 0
unsigned short Filler2; // Always 0
/// The following 6 floats define the bounding box for the layer
float LayerBoundingBoxX1;
float LayerBoundingBoxY1;
float LayerBoundingBoxZ1;
float LayerBoundingBoxX2;
float LayerBoundingBoxY2;
float LayerBoundingBoxZ2;
unsigned int Filler3; // Always 0 (4 bytes)
void* VerticesOffset;
void* PolyOffset;
void* PolyOffset2;
};
typedef struct tr5_vertex struct ROOM_VERTEX
{ {
float x; Vector3 position;
float y; Vector3 normal;
float z; Vector2 textureCoordinates;
}; Vector3 color;
int effects;
typedef struct tr5_room_vertex int index;
{
tr5_vertex Vertex; // Vertex is now floating-point
tr5_vertex Normal;
DWORD Colour; // 32-bit colour
}; };
struct ROOM_DOOR struct ROOM_DOOR
@ -44,48 +21,18 @@ struct ROOM_DOOR
Vector3 vertices[4]; Vector3 vertices[4];
}; };
typedef struct tr4_mesh_face3 // 10 bytes
{
short Vertices[3];
short Texture;
short Effects; // TR4-5 ONLY: alpha blending and environment mapping strength
};
typedef struct tr4_mesh_face4 // 12 bytes
{
short Vertices[4];
short Texture;
short Effects;
};
typedef struct tr_ROOM_DOOR // 32 bytes
{
short AdjoiningRoom; // Which room this portal leads to
TR_VERTEX Normal;
TR_VERTEX Vertices[4];
};
typedef struct tr_room_sector // 8 bytes
{
unsigned short FDindex; // Index into FloorData[]
unsigned short BoxIndex; // Index into Boxes[] (-1 if none)
unsigned char RoomBelow; // 255 is none
signed char Floor; // Absolute height of floor
unsigned char RoomAbove; // 255 if none
signed char Ceiling; // Absolute height of ceiling
};
typedef struct ROOM_LIGHT typedef struct ROOM_LIGHT
{ {
float x, y, z; // Position of light, in world coordinates int x, y, z; // Position of light, in world coordinates
float r, g, b; // Colour of the light float r, g, b; // Colour of the light
float intensity;
float in; // Cosine of the IN value for light / size of IN value float in; // Cosine of the IN value for light / size of IN value
float out; // Cosine of the OUT value for light / size of OUT value float out; // Cosine of the OUT value for light / size of OUT value
float radIn; // (IN radians) * 2 float length; // Range of light
float radOut; // (OUT radians) * 2 float cutoff; // Range of light
float range; // Range of light
float dx, dy, dz; // Direction - used only by sun and spot lights float dx, dy, dz; // Direction - used only by sun and spot lights
byte type; byte type;
bool castShadows;
}; };
typedef struct MESH_INFO typedef struct MESH_INFO
@ -147,7 +94,7 @@ struct SECTOR_COLLISION_INFO
SECTOR_PLANE planes[2]; SECTOR_PLANE planes[2];
}; };
typedef struct FLOOR_INFO struct FLOOR_INFO
{ {
int index; int index;
int box; int box;
@ -161,7 +108,7 @@ typedef struct FLOOR_INFO
SECTOR_COLLISION_INFO ceilingCollision; SECTOR_COLLISION_INFO ceilingCollision;
}; };
typedef enum RoomEnumFlag enum RoomEnumFlag
{ {
ENV_FLAG_WATER = 0x0001, ENV_FLAG_WATER = 0x0001,
ENV_FLAG_SWAMP = 0x0004, ENV_FLAG_SWAMP = 0x0004,
@ -175,36 +122,37 @@ typedef enum RoomEnumFlag
ENV_FLAG_UNKNOWN3 = 0x0400 ENV_FLAG_UNKNOWN3 = 0x0400
}; };
typedef struct ROOM_INFO struct ROOM_INFO
{ {
int x; int x;
int y; int y;
int z; int z;
int minfloor; int minfloor;
int maxceiling; int maxceiling;
std::vector<tr5_room_vertex> vertices; std::vector<Vector3> positions;
std::vector<tr4_mesh_face4> quads; std::vector<Vector3> normals;
std::vector<tr4_mesh_face3> triangles; std::vector<Vector3> colors;
std::vector<BUCKET> buckets;
std::vector<ROOM_DOOR> doors; std::vector<ROOM_DOOR> doors;
short xSize; int xSize;
short ySize; int ySize;
std::vector<FLOOR_INFO> floor; std::vector<FLOOR_INFO> floor;
Vector3 ambient; Vector3 ambient;
std::vector<ROOM_LIGHT> lights; std::vector<ROOM_LIGHT> lights;
std::vector<MESH_INFO> mesh; std::vector<MESH_INFO> mesh;
short flippedRoom; int flippedRoom;
unsigned short flags; int flags;
byte meshEffect; int meshEffect;
unsigned char reverbType; int reverbType;
unsigned char flipNumber; int flipNumber;
short itemNumber; short itemNumber;
short fxNumber; short fxNumber;
bool boundActive; bool boundActive;
}; };
typedef struct ANIM_STRUCT struct ANIM_STRUCT
{ {
short* framePtr; int framePtr;
short interpolation; short interpolation;
short currentAnimState; short currentAnimState;
int velocity; int velocity;
@ -222,5 +170,5 @@ typedef struct ANIM_STRUCT
}; };
constexpr auto NUM_ROOMS = 1024; constexpr auto NUM_ROOMS = 1024;
constexpr auto NO_ROOM = 0xFF; constexpr auto NO_ROOM = -1;
constexpr auto NO_HEIGHT = (-0x7F00); constexpr auto NO_HEIGHT = (-0x7F00);

View file

@ -16,7 +16,7 @@ void InitialiseRope(short itemNumber) // (F) (D)
{ {
PHD_VECTOR itemPos; PHD_VECTOR itemPos;
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
short roomNumber = item->roomNumber; short roomNumber = item->roomNumber;
itemPos.x = item->pos.xPos; itemPos.x = item->pos.xPos;
@ -153,7 +153,7 @@ void RopeControl(short itemNumber) // (F) (D)
ITEM_INFO* item; ITEM_INFO* item;
ROPE_STRUCT* rope; ROPE_STRUCT* rope;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
rope = &Ropes[item->triggerFlags]; rope = &Ropes[item->triggerFlags];
if (TriggerActive(item)) if (TriggerActive(item))
{ {
@ -170,30 +170,30 @@ void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (F) (D)
{ {
ITEM_INFO* item; ITEM_INFO* item;
ROPE_STRUCT* rope; ROPE_STRUCT* rope;
ANIM_FRAME* frame; BOUNDING_BOX* frame;
int segment; int segment;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
rope = &Ropes[item->triggerFlags]; rope = &Ropes[item->triggerFlags];
if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && (l->currentAnimState == STATE_LARA_REACH || l->currentAnimState == STATE_LARA_JUMP_UP) && l->gravityStatus && l->fallspeed > 0 && rope->active) if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && (l->currentAnimState == LS_REACH || l->currentAnimState == LS_JUMP_UP) && l->gravityStatus && l->fallspeed > 0 && rope->active)
{ {
frame = (ANIM_FRAME*) GetBoundsAccurate(l); frame = GetBoundsAccurate(l);
segment = _0x0046D200(rope, l->pos.xPos, l->pos.yPos + frame->MinY + 512, l->pos.zPos + (frame->MaxZ * phd_cos(l->pos.yRot) >> W2V_SHIFT), l->currentAnimState == STATE_LARA_REACH ? 128 : 320); segment = _0x0046D200(rope, l->pos.xPos, l->pos.yPos + frame->Y1 + 512, l->pos.zPos + ((int)(frame->Z2 * phd_cos(l->pos.yRot)) >> W2V_SHIFT), l->currentAnimState == LS_REACH ? 128 : 320);
if (segment >= 0) if (segment >= 0)
{ {
if (l->currentAnimState == STATE_LARA_REACH) if (l->currentAnimState == LS_REACH)
{ {
l->animNumber = ANIMATION_LARA_ROPE_JUMP_TO_GRAB; l->animNumber = LA_REACH_TO_ROPE_SWING;
l->currentAnimState = STATE_LARA_ROPE_SWING; l->currentAnimState = LS_ROPE_SWING;
Lara.ropeFrame = Anims[ANIMATION_LARA_ROPE_SWING_FORWARD_SEMIHARD].frameBase + 32 << 8; Lara.ropeFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 32 << 8;
Lara.ropeDFrame = Anims[ANIMATION_LARA_ROPE_SWING_FORWARD_SEMIHARD].frameBase + 60 << 8; Lara.ropeDFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 60 << 8;
} }
else else
{ {
l->animNumber = ANIMATION_LARA_MONKEY_TO_ROPE_BEGIN; l->animNumber = LA_JUMP_UP_TO_ROPE_START;
l->currentAnimState = STATE_LARA_ROPE_IDLE; l->currentAnimState = LS_ROPE_IDLE;
} }
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
l->gravityStatus = false; l->gravityStatus = false;
l->fallspeed = 0; l->fallspeed = 0;
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;

View file

@ -77,13 +77,13 @@ extern byte CurrentSequence;
void SaveGame::saveItems() void SaveGame::saveItems()
{ {
// Save level items // Save level items
for (int i = 0; i < NumItems; i++) for (int i = 0; i < g_Level.NumItems; i++)
m_writer->WriteChunkWithChildren(m_chunkItem, &saveItem, i, 0); m_writer->WriteChunkWithChildren(m_chunkItem, &saveItem, i, 0);
// Save items created at runtime (flares, missiles...) // Save items created at runtime (flares, missiles...)
for (int i = NumItems; i < NUM_ITEMS; i++) for (int i = g_Level.NumItems; i < NUM_ITEMS; i++)
{ {
ITEM_INFO* item = &Items[i]; ITEM_INFO* item = &g_Level.Items[i];
if (item->active) if (item->active)
{ {
// Some items are very special and are saved in specific functions, all the others use the general function // Some items are very special and are saved in specific functions, all the others use the general function
@ -121,8 +121,8 @@ void SaveGame::saveItems()
void SaveGame::saveItem(int itemNumber, int runtimeItem) void SaveGame::saveItem(int itemNumber, int runtimeItem)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
LEB128::Write(m_stream, itemNumber); LEB128::Write(m_stream, itemNumber);
LEB128::Write(m_stream, runtimeItem); LEB128::Write(m_stream, runtimeItem);
@ -186,8 +186,8 @@ void SaveGame::saveGameStatus(int arg1, int arg2)
LEB128::Write(m_stream, CurrentSequence); LEB128::Write(m_stream, CurrentSequence);
// Now the sub-chunks // Now the sub-chunks
for (int i = 0; i < Rooms.size(); i++) for (int i = 0; i < g_Level.Rooms.size(); i++)
for (int j = 0; j < Rooms[i].mesh.size(); j++) for (int j = 0; j < g_Level.Rooms[i].mesh.size(); j++)
m_writer->WriteChunk(m_chunkStaticFlags, &saveStaticFlag, i, j); m_writer->WriteChunk(m_chunkStaticFlags, &saveStaticFlag, i, j);
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@ -200,7 +200,7 @@ void SaveGame::saveGameStatus(int arg1, int arg2)
m_writer->WriteChunk(m_chunkCdFlags, &saveCdFlags, i, g_AudioTracks[i].Mask); m_writer->WriteChunk(m_chunkCdFlags, &saveCdFlags, i, g_AudioTracks[i].Mask);
for (int i = 0; i < NumberCameras; i++) for (int i = 0; i < NumberCameras; i++)
m_writer->WriteChunk(m_chunkCamera, &saveCamera, i, Camera.fixed[i].flags); m_writer->WriteChunk(m_chunkCamera, &saveCamera, i, FixedCameras[i].flags);
for (int i = 0; i < 255; i++) for (int i = 0; i < 255; i++)
m_writer->WriteChunk(m_chunkFlipStats, &saveFlipStats, i, FlipStats[i]); m_writer->WriteChunk(m_chunkFlipStats, &saveFlipStats, i, FlipStats[i]);
@ -215,11 +215,8 @@ void SaveGame::saveLara(int arg1, int arg2)
LaraInfo lara; LaraInfo lara;
memcpy(&lara, &Lara, sizeof(Lara)); memcpy(&lara, &Lara, sizeof(Lara));
for (int i = 0; i < 15; i++) //lara.leftArm.frameBase = (short*)((char *)lara.leftArm.frameBase - (ptrdiff_t)Objects[ID_LARA].frameBase);
lara.meshPtrs[i] = (short*)((char*)lara.meshPtrs[i] - (ptrdiff_t)MeshBase); //lara.rightArm.frameBase = (short*)((char *)lara.rightArm.frameBase - (ptrdiff_t)Objects[ID_LARA].frameBase);
lara.leftArm.frameBase = (short*)((char *)lara.leftArm.frameBase - (ptrdiff_t)Objects[ID_LARA].frameBase);
lara.rightArm.frameBase = (short*)((char *)lara.rightArm.frameBase - (ptrdiff_t)Objects[ID_LARA].frameBase);
lara.generalPtr = (char *)lara.generalPtr - (ptrdiff_t)malloc_buffer; lara.generalPtr = (char *)lara.generalPtr - (ptrdiff_t)malloc_buffer;
m_stream->Write(reinterpret_cast<char*>(&lara), sizeof(Lara)); m_stream->Write(reinterpret_cast<char*>(&lara), sizeof(Lara));
@ -289,7 +286,7 @@ void SaveGame::saveLara(int arg1, int arg2)
void SaveGame::saveWeaponItem(int arg1, int arg2) void SaveGame::saveWeaponItem(int arg1, int arg2)
{ {
ITEM_INFO* weaponItem = &Items[arg1]; ITEM_INFO* weaponItem = &g_Level.Items[arg1];
LEB128::Write(m_stream, weaponItem->objectNumber); LEB128::Write(m_stream, weaponItem->objectNumber);
LEB128::Write(m_stream, weaponItem->animNumber); LEB128::Write(m_stream, weaponItem->animNumber);
@ -512,13 +509,8 @@ bool SaveGame::readLara()
memcpy(&Lara, lara, sizeof(LaraInfo)); memcpy(&Lara, lara, sizeof(LaraInfo));
free(buffer); free(buffer);
for (int i = 0; i < NUM_LARA_MESHES; i++) //Lara.leftArm.frameBase = AddPtr(Lara.leftArm.frameBase, short, Objects[ID_LARA].frameBase);
{ //Lara.rightArm.frameBase = AddPtr(Lara.rightArm.frameBase, short, Objects[ID_LARA].frameBase);
Lara.meshPtrs[i] = AddPtr(Lara.meshPtrs[i], short, MeshBase);
}
Lara.leftArm.frameBase = AddPtr(Lara.leftArm.frameBase, short, Objects[ID_LARA].frameBase);
Lara.rightArm.frameBase = AddPtr(Lara.rightArm.frameBase, short, Objects[ID_LARA].frameBase);
Lara.target = NULL; Lara.target = NULL;
Lara.spazEffect = NULL; Lara.spazEffect = NULL;
@ -555,10 +547,10 @@ bool SaveGame::readItem()
if (runtimeItem) if (runtimeItem)
itemNumber = CreateItem(); itemNumber = CreateItem();
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = LEB128::ReadInt16(m_stream); item->objectNumber = LEB128::ReadInt16(m_stream);
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
// Runtime items must be initialised // Runtime items must be initialised
// TODO: test test test!!! // TODO: test test test!!!
@ -739,7 +731,7 @@ void SaveGame::saveStaticFlag(int arg1, int arg2)
{ {
LEB128::Write(m_stream, arg1); LEB128::Write(m_stream, arg1);
LEB128::Write(m_stream, arg2); LEB128::Write(m_stream, arg2);
LEB128::Write(m_stream, Rooms[arg1].mesh[arg2].flags); LEB128::Write(m_stream, g_Level.Rooms[arg1].mesh[arg2].flags);
} }
bool SaveGame::readLaraChunks(ChunkId* chunkId, int maxSize, int arg) bool SaveGame::readLaraChunks(ChunkId* chunkId, int maxSize, int arg)
@ -828,7 +820,7 @@ bool SaveGame::readLaraChunks(ChunkId* chunkId, int maxSize, int arg)
short weaponItemNum = CreateItem(); short weaponItemNum = CreateItem();
Lara.weaponItem = weaponItemNum; Lara.weaponItem = weaponItemNum;
ITEM_INFO* weaponItem = &Items[Lara.weaponItem]; ITEM_INFO* weaponItem = &g_Level.Items[Lara.weaponItem];
weaponItem->objectNumber = LEB128::ReadInt16(m_stream); weaponItem->objectNumber = LEB128::ReadInt16(m_stream);
weaponItem->animNumber = LEB128::ReadInt16(m_stream); weaponItem->animNumber = LEB128::ReadInt16(m_stream);
@ -849,17 +841,17 @@ bool SaveGame::readGameStatusChunks(ChunkId* chunkId, int maxSize, int arg)
short roomIndex = LEB128::ReadInt16(m_stream); short roomIndex = LEB128::ReadInt16(m_stream);
short staticIndex = LEB128::ReadInt16(m_stream); short staticIndex = LEB128::ReadInt16(m_stream);
short flags = LEB128::ReadInt16(m_stream); short flags = LEB128::ReadInt16(m_stream);
Rooms[roomIndex].mesh[staticIndex].flags = flags; g_Level.Rooms[roomIndex].mesh[staticIndex].flags = flags;
if (!flags) if (!flags)
{ {
FLOOR_INFO* floor = GetFloor(Rooms[roomIndex].mesh[staticIndex].x, FLOOR_INFO* floor = GetFloor(g_Level.Rooms[roomIndex].mesh[staticIndex].x,
Rooms[roomIndex].mesh[staticIndex].y, g_Level.Rooms[roomIndex].mesh[staticIndex].y,
Rooms[roomIndex].mesh[staticIndex].z, g_Level.Rooms[roomIndex].mesh[staticIndex].z,
&roomIndex); &roomIndex);
int height = GetFloorHeight(floor, Rooms[roomIndex].mesh[staticIndex].x, int height = GetFloorHeight(floor, g_Level.Rooms[roomIndex].mesh[staticIndex].x,
Rooms[roomIndex].mesh[staticIndex].y, g_Level.Rooms[roomIndex].mesh[staticIndex].y,
Rooms[roomIndex].mesh[staticIndex].z); g_Level.Rooms[roomIndex].mesh[staticIndex].z);
TestTriggers(TriggerIndex, 1, 0); TestTriggers(TriggerIndex, 1, 0);
floor->stopper = false; floor->stopper = false;
} }
@ -895,7 +887,7 @@ bool SaveGame::readGameStatusChunks(ChunkId* chunkId, int maxSize, int arg)
{ {
short index = LEB128::ReadInt16(m_stream); short index = LEB128::ReadInt16(m_stream);
short value = LEB128::ReadInt16(m_stream); short value = LEB128::ReadInt16(m_stream);
Camera.fixed[index].flags = value; FixedCameras[index].flags = value;
return true; return true;
} }
else if (chunkId->EqualsTo(m_chunkSequenceSwitch)) else if (chunkId->EqualsTo(m_chunkSequenceSwitch))
@ -953,7 +945,7 @@ void SaveGame::saveCdFlags(int arg1, int arg2)
bool SaveGame::readItemChunks(ChunkId* chunkId, int maxSize, int itemNumber) bool SaveGame::readItemChunks(ChunkId* chunkId, int maxSize, int itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (chunkId->EqualsTo(m_chunkItemDummy)) if (chunkId->EqualsTo(m_chunkItemDummy))
return m_reader->ReadChunkInt32(maxSize); return m_reader->ReadChunkInt32(maxSize);
@ -1020,7 +1012,7 @@ bool SaveGame::readItemChunks(ChunkId* chunkId, int maxSize, int itemNumber)
{ {
EnableBaddieAI(itemNumber, 1); EnableBaddieAI(itemNumber, 1);
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
creature->jointRotation[0] = LEB128::ReadInt16(m_stream); creature->jointRotation[0] = LEB128::ReadInt16(m_stream);
@ -1063,7 +1055,7 @@ bool SaveGame::readItemChunks(ChunkId* chunkId, int maxSize, int itemNumber)
} }
else if (chunkId->EqualsTo(m_chunkItemQuadInfo)) else if (chunkId->EqualsTo(m_chunkItemQuadInfo))
{ {
QUAD_INFO* quadInfo = (QUAD_INFO*)game_malloc(sizeof(QUAD_INFO)); QUAD_INFO* quadInfo = game_malloc<QUAD_INFO>();
m_stream->ReadBytes(reinterpret_cast<byte*>(quadInfo), sizeof(QUAD_INFO)); m_stream->ReadBytes(reinterpret_cast<byte*>(quadInfo), sizeof(QUAD_INFO));
if (item->objectNumber == ID_QUAD) if (item->objectNumber == ID_QUAD)
item->data = (void*)quadInfo; item->data = (void*)quadInfo;
@ -1123,8 +1115,8 @@ bool SaveGame::readStatistics()
void SaveGame::saveItemFlags(int arg1, int arg2) void SaveGame::saveItemFlags(int arg1, int arg2)
{ {
ITEM_INFO* item = &Items[arg1]; ITEM_INFO* item = &g_Level.Items[arg1];
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
LEB128::Write(m_stream, item->flags); LEB128::Write(m_stream, item->flags);
LEB128::Write(m_stream, item->active); LEB128::Write(m_stream, item->active);
@ -1147,8 +1139,8 @@ void SaveGame::saveItemFlags(int arg1, int arg2)
void SaveGame::saveItemIntelligentData(int arg1, int arg2) void SaveGame::saveItemIntelligentData(int arg1, int arg2)
{ {
ITEM_INFO* item = &Items[arg1]; ITEM_INFO* item = &g_Level.Items[arg1];
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
ITEM_INFO* enemy = (ITEM_INFO*)((char*)creature->enemy - (ptrdiff_t)malloc_buffer); ITEM_INFO* enemy = (ITEM_INFO*)((char*)creature->enemy - (ptrdiff_t)malloc_buffer);
@ -1190,14 +1182,14 @@ void SaveGame::saveItemIntelligentData(int arg1, int arg2)
void SaveGame::saveItemHitPoints(int arg1, int arg2) void SaveGame::saveItemHitPoints(int arg1, int arg2)
{ {
ITEM_INFO* item = &Items[arg1]; ITEM_INFO* item = &g_Level.Items[arg1];
LEB128::Write(m_stream, item->hitPoints); LEB128::Write(m_stream, item->hitPoints);
} }
void SaveGame::saveItemPosition(int arg1, int arg2) void SaveGame::saveItemPosition(int arg1, int arg2)
{ {
ITEM_INFO* item = &Items[arg1]; ITEM_INFO* item = &g_Level.Items[arg1];
LEB128::Write(m_stream, item->pos.xPos); LEB128::Write(m_stream, item->pos.xPos);
LEB128::Write(m_stream, item->pos.yPos); LEB128::Write(m_stream, item->pos.yPos);
@ -1212,7 +1204,7 @@ void SaveGame::saveItemPosition(int arg1, int arg2)
void SaveGame::saveItemMesh(int arg1, int arg2) void SaveGame::saveItemMesh(int arg1, int arg2)
{ {
ITEM_INFO* item = &Items[arg1]; ITEM_INFO* item = &g_Level.Items[arg1];
LEB128::Write(m_stream, item->meshBits); LEB128::Write(m_stream, item->meshBits);
LEB128::Write(m_stream, item->swapMeshFlags); LEB128::Write(m_stream, item->swapMeshFlags);
@ -1220,7 +1212,7 @@ void SaveGame::saveItemMesh(int arg1, int arg2)
void SaveGame::saveItemAnims(int arg1, int arg2) void SaveGame::saveItemAnims(int arg1, int arg2)
{ {
ITEM_INFO* item = &Items[arg1]; ITEM_INFO* item = &g_Level.Items[arg1];
LEB128::Write(m_stream, item->currentAnimState); LEB128::Write(m_stream, item->currentAnimState);
LEB128::Write(m_stream, item->goalAnimState); LEB128::Write(m_stream, item->goalAnimState);
@ -1231,7 +1223,7 @@ void SaveGame::saveItemAnims(int arg1, int arg2)
void SaveGame::saveBurningTorch(int itemNumber, int arg2) void SaveGame::saveBurningTorch(int itemNumber, int arg2)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
LEB128::Write(m_stream, itemNumber); LEB128::Write(m_stream, itemNumber);
LEB128::Write(m_stream, item->pos.xPos); LEB128::Write(m_stream, item->pos.xPos);
@ -1249,7 +1241,7 @@ void SaveGame::saveBurningTorch(int itemNumber, int arg2)
void SaveGame::saveChaff(int itemNumber, int arg2) void SaveGame::saveChaff(int itemNumber, int arg2)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
LEB128::Write(m_stream, itemNumber); LEB128::Write(m_stream, itemNumber);
LEB128::Write(m_stream, item->pos.xPos); LEB128::Write(m_stream, item->pos.xPos);
@ -1268,7 +1260,7 @@ void SaveGame::saveChaff(int itemNumber, int arg2)
void SaveGame::saveTorpedo(int itemNumber, int arg2) void SaveGame::saveTorpedo(int itemNumber, int arg2)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
LEB128::Write(m_stream, itemNumber); LEB128::Write(m_stream, itemNumber);
LEB128::Write(m_stream, item->pos.xPos); LEB128::Write(m_stream, item->pos.xPos);
@ -1290,7 +1282,7 @@ void SaveGame::saveTorpedo(int itemNumber, int arg2)
void SaveGame::saveCrossbowBolt(int itemNumber, int arg2) void SaveGame::saveCrossbowBolt(int itemNumber, int arg2)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
LEB128::Write(m_stream, itemNumber); LEB128::Write(m_stream, itemNumber);
LEB128::Write(m_stream, item->pos.xPos); LEB128::Write(m_stream, item->pos.xPos);
@ -1306,7 +1298,7 @@ void SaveGame::saveCrossbowBolt(int itemNumber, int arg2)
void SaveGame::saveFlare(int itemNumber, int arg2) void SaveGame::saveFlare(int itemNumber, int arg2)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
LEB128::Write(m_stream, itemNumber); LEB128::Write(m_stream, itemNumber);
LEB128::Write(m_stream, item->pos.xPos); LEB128::Write(m_stream, item->pos.xPos);
@ -1328,7 +1320,7 @@ bool SaveGame::readBurningTorch()
LEB128::ReadInt16(m_stream); LEB128::ReadInt16(m_stream);
short itemNumber = CreateItem(); short itemNumber = CreateItem();
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = ID_BURNING_TORCH_ITEM; item->objectNumber = ID_BURNING_TORCH_ITEM;
item->pos.xPos = LEB128::ReadInt32(m_stream); item->pos.xPos = LEB128::ReadInt32(m_stream);
@ -1364,7 +1356,7 @@ bool SaveGame::readChaff()
LEB128::ReadInt16(m_stream); LEB128::ReadInt16(m_stream);
short itemNumber = CreateItem(); short itemNumber = CreateItem();
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = ID_CHAFF; item->objectNumber = ID_CHAFF;
item->pos.xPos = LEB128::ReadInt32(m_stream); item->pos.xPos = LEB128::ReadInt32(m_stream);
@ -1401,7 +1393,7 @@ bool SaveGame::readCrossbowBolt()
LEB128::ReadInt16(m_stream); LEB128::ReadInt16(m_stream);
short itemNumber = CreateItem(); short itemNumber = CreateItem();
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = ID_CROSSBOW_BOLT; item->objectNumber = ID_CROSSBOW_BOLT;
item->pos.xPos = LEB128::ReadInt32(m_stream); item->pos.xPos = LEB128::ReadInt32(m_stream);
@ -1435,7 +1427,7 @@ bool SaveGame::readFlare()
LEB128::ReadInt16(m_stream); LEB128::ReadInt16(m_stream);
short itemNumber = CreateItem(); short itemNumber = CreateItem();
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = ID_FLARE_ITEM; item->objectNumber = ID_FLARE_ITEM;
item->pos.xPos = LEB128::ReadInt32(m_stream); item->pos.xPos = LEB128::ReadInt32(m_stream);
@ -1472,7 +1464,7 @@ bool SaveGame::readTorpedo()
LEB128::ReadInt16(m_stream); LEB128::ReadInt16(m_stream);
short itemNumber = CreateItem(); short itemNumber = CreateItem();
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->objectNumber = ID_TORPEDO; item->objectNumber = ID_TORPEDO;
item->pos.xPos = LEB128::ReadInt32(m_stream); item->pos.xPos = LEB128::ReadInt32(m_stream);
@ -1509,7 +1501,7 @@ bool SaveGame::readTorpedo()
void SaveGame::saveItemQuadInfo(int itemNumber, int arg2) void SaveGame::saveItemQuadInfo(int itemNumber, int arg2)
{ {
m_stream->WriteBytes(reinterpret_cast<byte*>(Items[itemNumber].data), sizeof(QUAD_INFO)); m_stream->WriteBytes(reinterpret_cast<byte*>(g_Level.Items[itemNumber].data), sizeof(QUAD_INFO));
} }
void SaveGame::saveRats(int arg1, int arg2) void SaveGame::saveRats(int arg1, int arg2)

View file

@ -30,7 +30,7 @@ namespace T5M {
} }
s.position += s.velocity; s.position += s.velocity;
if (s.affectedByWind) { if (s.affectedByWind) {
if (Rooms[s.room].flags & ENV_FLAG_WIND) { if (g_Level.Rooms[s.room].flags & ENV_FLAG_WIND) {
s.position.x += SmokeWindX / 2; s.position.x += SmokeWindX / 2;
s.position.z += SmokeWindZ / 2; s.position.z += SmokeWindZ / 2;
} }
@ -88,29 +88,38 @@ namespace T5M {
Vector3(xv, yv, zv).Normalize(s.velocity); Vector3(xv, yv, zv).Normalize(s.velocity);
s.velocity *= frand() * 24 + 16; s.velocity *= frand() * 24 + 16;
s.gravity = -.1f; s.gravity = -.1f;
s.affectedByWind = Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND; s.affectedByWind = g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND;
s.sourceColor = Vector4(.4, .4, .4, 1); s.sourceColor = Vector4(.4, .4, .4, 1);
s.destinationColor = Vector4(0, 0, 0, 0); s.destinationColor = Vector4(0, 0, 0, 0);
float size = (float)((GetRandomControl() & 0x0F) + 48); // -TriggerGunSmoke_SubFunction(weaponType);
if (initial) if (initial)
{ {
s.sourceSize = size; float size = (frand() * 25) + 48;
s.destinationSize = (size * 8) + 8; s.sourceSize = size *2;
s.destinationSize = size * 8;
s.terminalVelocity = 0;
s.friction = 0.90f;
s.life = frand() * 30 + 60;
} }
else else
{ {
float size = (float)((GetRandomControl() & 0x0F) + 48); // -TriggerGunSmoke_SubFunction(weaponType);
s.sourceSize = size / 2; s.sourceSize = size / 2;
s.destinationSize = size * 2; s.destinationSize = size * 4;
}
s.terminalVelocity = 0; s.terminalVelocity = 0;
s.friction = 0.89f; s.friction = 0.97f;
s.life = frand() * 10 + 35; s.life = frand() * 20 + 42;
}
s.position = Vector3(x, y, z); s.position = Vector3(x, y, z);
s.position += Vector3(frandMinMax(-8, 8), frandMinMax(-8, 8), frandMinMax(-8, 8)); s.position += Vector3(frandMinMax(-8, 8), frandMinMax(-8, 8), frandMinMax(-8, 8));
s.angularVelocity = frandMinMax(-PI, PI); s.angularVelocity = frandMinMax(-PI / 4, PI / 4);
s.angularDrag = 0.8f; s.angularDrag = 0.8f;
s.room = LaraItem->roomNumber; s.room = LaraItem->roomNumber;
} }
} }

View file

@ -24,10 +24,6 @@ const BASS_BFX_FREEVERB BASS_ReverbTypes[NUM_REVERB_TYPES] = // Reverb preset
}; };
vector<AudioTrack> g_AudioTracks; vector<AudioTrack> g_AudioTracks;
short SampleLUT[SOUND_NEW_SOUNDMAP_MAX_SIZE];
short SoundMapSize;
int NumSamplesInfos;
SAMPLE_INFO* SampleInfo;
int GlobalMusicVolume; int GlobalMusicVolume;
int GlobalFXVolume; int GlobalFXVolume;
@ -112,7 +108,7 @@ bool Sound_LoadSample(char *pointer, int compSize, int uncompSize, int index) //
long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags) long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags)
{ {
if (effectID >= SoundMapSize) if (effectID >= g_Level.SoundMap.size())
return 0; return 0;
if (BASS_GetDevice() == -1) if (BASS_GetDevice() == -1)
@ -121,25 +117,25 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags)
if (!(env_flags & SFX_ALWAYS)) if (!(env_flags & SFX_ALWAYS))
{ {
// Don't play effect if effect's environment isn't the same as camera position's environment // Don't play effect if effect's environment isn't the same as camera position's environment
if ((env_flags & ENV_FLAG_WATER) != (Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER)) if ((env_flags & ENV_FLAG_WATER) != (g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER))
return 0; return 0;
} }
// Get actual sample index from SoundMap // Get actual sample index from SoundMap
int sampleIndex = SampleLUT[effectID]; int sampleIndex = g_Level.SoundMap[effectID];
// -1 means no such effect exists in level file. // -1 means no such effect exists in level file.
// We set it to -2 afterwards to prevent further debug message firings. // We set it to -2 afterwards to prevent further debug message firings.
if (sampleIndex == -1) if (sampleIndex == -1)
{ {
printf("Non present effect %d \n", effectID); printf("Non present effect %d \n", effectID);
SampleLUT[effectID] = -2; g_Level.SoundMap[effectID] = -2;
return 0; return 0;
} }
else if (sampleIndex == -2) else if (sampleIndex == -2)
return 0; return 0;
SAMPLE_INFO *sampleInfo = &SampleInfo[sampleIndex]; SAMPLE_INFO *sampleInfo = &g_Level.SoundDetails[sampleIndex];
if (sampleInfo->number < 0) if (sampleInfo->number < 0)
{ {
@ -184,7 +180,7 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags)
float distance = Sound_DistanceToListener(position); float distance = Sound_DistanceToListener(position);
// Don't play sound if it's too far from listener's position. // Don't play sound if it's too far from listener's position.
if (distance > radius) if (distance > radius && false)
return 0; return 0;
// Set and randomize volume (if needed) // Set and randomize volume (if needed)
@ -561,9 +557,9 @@ void Sound_UpdateScene()
static int currentReverb = -1; static int currentReverb = -1;
if (currentReverb == -1 || Rooms[Camera.pos.roomNumber].reverbType != currentReverb) if (currentReverb == -1 || g_Level.Rooms[Camera.pos.roomNumber].reverbType != currentReverb)
{ {
currentReverb = Rooms[Camera.pos.roomNumber].reverbType; currentReverb = g_Level.Rooms[Camera.pos.roomNumber].reverbType;
if (currentReverb < NUM_REVERB_TYPES) if (currentReverb < NUM_REVERB_TYPES)
BASS_FXSetParameters(BASS_FXHandler[SOUND_FILTER_REVERB], &BASS_ReverbTypes[currentReverb]); BASS_FXSetParameters(BASS_FXHandler[SOUND_FILTER_REVERB], &BASS_ReverbTypes[currentReverb]);
} }
@ -572,7 +568,7 @@ void Sound_UpdateScene()
{ {
if ((SoundSlot[i].channel != NULL) && (BASS_ChannelIsActive(SoundSlot[i].channel) == BASS_ACTIVE_PLAYING)) if ((SoundSlot[i].channel != NULL) && (BASS_ChannelIsActive(SoundSlot[i].channel) == BASS_ACTIVE_PLAYING))
{ {
SAMPLE_INFO *sampleInfo = &SampleInfo[SampleLUT[SoundSlot[i].effectID]]; SAMPLE_INFO *sampleInfo = &g_Level.SoundDetails[g_Level.SoundMap[SoundSlot[i].effectID]];
// Stop and clean up sounds which were in ending state in previous frame. // Stop and clean up sounds which were in ending state in previous frame.
// In case sound is looping, make it ending unless they are re-fired in next frame. // In case sound is looping, make it ending unless they are re-fired in next frame.

View file

@ -619,7 +619,7 @@ typedef enum sound_effects
SFX_TR1_BULLET_HITTING_LARA = 500, SFX_TR1_BULLET_HITTING_LARA = 500,
SFX_TR1_LARA_HEH_STARTING_TO_PULL_BLOCK = 501, SFX_TR1_LARA_HEH_STARTING_TO_PULL_BLOCK = 501,
SFX_TR1_LARA_TREADING_WATER = 502, SFX_TR1_LARA_TREADING_WATER = 502,
SFX_TR1_LARA_S_BONES_BREAKING_DYING = 503, SFX_TR1_LARA_S_Bones_BREAKING_DYING = 503,
SFX_TR1_LEDGE_GRAB_BY_LARA = 504, SFX_TR1_LEDGE_GRAB_BY_LARA = 504,
SFX_TR1_LARA_OOMPH_HITTING_WALL_AFTER_GRABBING_LEDGE = 505, SFX_TR1_LARA_OOMPH_HITTING_WALL_AFTER_GRABBING_LEDGE = 505,
SFX_TR1_FOOTSTEP_LEDGE_SHIMMY_BY_LARA = 506, SFX_TR1_FOOTSTEP_LEDGE_SHIMMY_BY_LARA = 506,
@ -877,7 +877,7 @@ typedef enum sound_effects
SFX_TR2_BULLET_HITTING_LARA = 756, SFX_TR2_BULLET_HITTING_LARA = 756,
SFX_TR2_LARA_HEH_PULLING_UP = 757, SFX_TR2_LARA_HEH_PULLING_UP = 757,
SFX_TR2_LARA_TREADING_WATER1 = 758, SFX_TR2_LARA_TREADING_WATER1 = 758,
SFX_TR2_LARA_S_BONES_BREAKING_DYING = 759, SFX_TR2_LARA_S_Bones_BREAKING_DYING = 759,
SFX_TR2_LEDGE_GRAB_BY_LARA = 760, SFX_TR2_LEDGE_GRAB_BY_LARA = 760,
SFX_TR2_LARA_OOMPH_HITTING_WALL_AFTER_GRABBING_LEDGE = 761, SFX_TR2_LARA_OOMPH_HITTING_WALL_AFTER_GRABBING_LEDGE = 761,
SFX_TR2_FOOTSTEP_LEDGE_SHIMMY_BY_LARA = 762, SFX_TR2_FOOTSTEP_LEDGE_SHIMMY_BY_LARA = 762,
@ -2042,10 +2042,6 @@ typedef struct AudioTrack
}; };
extern std::vector<AudioTrack> g_AudioTracks; extern std::vector<AudioTrack> g_AudioTracks;
extern short SampleLUT[SOUND_NEW_SOUNDMAP_MAX_SIZE];
extern short SoundMapSize;
extern int NumSamplesInfos;
extern SAMPLE_INFO* SampleInfo;
extern int GlobalMusicVolume; extern int GlobalMusicVolume;
extern int GlobalFXVolume; extern int GlobalFXVolume;

View file

@ -6,7 +6,7 @@
#include "setup.h" #include "setup.h"
#include "Renderer11.h" #include "Renderer11.h"
#include "trmath.h" #include "trmath.h"
using namespace T5M::Renderer;
int NumLaraSpheres; int NumLaraSpheres;
bool GotLaraSpheres; bool GotLaraSpheres;
SPHERE LaraSpheres[MAX_SPHERES]; SPHERE LaraSpheres[MAX_SPHERES];
@ -18,9 +18,9 @@ int GetSpheres(ITEM_INFO* item, SPHERE* ptr, int worldSpace, Matrix local)
return 0; return 0;
BoundingSphere spheres[MAX_SPHERES]; BoundingSphere spheres[MAX_SPHERES];
short itemNumber = (item - Items); short itemNumber = (item - g_Level.Items.data());
int num = g_Renderer->GetSpheres(itemNumber, spheres, worldSpace, local); int num = g_Renderer.GetSpheres(itemNumber, spheres, worldSpace, local);
for (int i = 0; i < MAX_SPHERES; i++) for (int i = 0; i < MAX_SPHERES; i++)
{ {
@ -164,11 +164,11 @@ void GetMatrixFromTrAngle(Matrix* matrix, short* frameptr, int index)
void GetJointAbsPosition(ITEM_INFO* item, PHD_VECTOR* vec, int joint) void GetJointAbsPosition(ITEM_INFO* item, PHD_VECTOR* vec, int joint)
{ {
// Get the real item number // Get the real item number
short itemNumber = item - Items; short itemNumber = item - g_Level.Items.data();
// Use matrices done in the renderer and transform the input vector // Use matrices done in the renderer and transform the input vector
Vector3 p = Vector3(vec->x, vec->y, vec->z); Vector3 p = Vector3(vec->x, vec->y, vec->z);
g_Renderer->GetItemAbsBonePosition(itemNumber, &p, joint); g_Renderer.GetItemAbsBonePosition(itemNumber, &p, joint);
// Store the result // Store the result
vec->x = p.x; vec->x = p.x;

View file

@ -7,7 +7,7 @@
#include "switch.h" #include "switch.h"
#include "lara.h" #include "lara.h"
#include "input.h" #include "input.h"
using namespace T5M::Renderer;
int LastSequence; int LastSequence;
int SpotcamTimer; int SpotcamTimer;
int SpotcamLoopCnt; int SpotcamLoopCnt;
@ -162,10 +162,10 @@ void InitialiseSpotCam(short Sequence)
LastCamera = CurrentSplineCamera + (CameraCnt[SpotCamRemap[Sequence]] - 1); LastCamera = CurrentSplineCamera + (CameraCnt[SpotCamRemap[Sequence]] - 1);
CurrentCameraCnt = CameraCnt[SpotCamRemap[Sequence]]; CurrentCameraCnt = CameraCnt[SpotCamRemap[Sequence]];
if ((s->flags & SCF_DISABLE_LARA_CONTROLS) /*|| gfGameMode == 1*/) if ((s->flags & SCF_DISABLE_LARA_CONTROLS))
{ {
DisableLaraControl = 1; DisableLaraControl = 1;
g_Renderer->EnableCinematicBars(true); g_Renderer.EnableCinematicBars(true);
//SetFadeClip(16, 1); //SetFadeClip(16, 1);
} }
@ -266,14 +266,7 @@ void InitialiseSpotCam(short Sequence)
if (s->flags & SCF_VIGNETTE) if (s->flags & SCF_VIGNETTE)
{ {
/*if (s->timer < 0) /*Hardcoded code*/
{
SCOverlay = 1;
}//loc_37C8C
else if (SlowMotion == 0)
{
SlowMotion = s->timer;
}*/
} }
if (s->flags & SCF_HIDE_LARA) if (s->flags & SCF_HIDE_LARA)
@ -421,28 +414,12 @@ void CalculateSpotCameras()
&& CameraFade != CurrentSplineCamera) && CameraFade != CurrentSplineCamera)
{ {
CameraFade = CurrentSplineCamera; CameraFade = CurrentSplineCamera;
/*if (gfCurrentLevel != LVL5_TITLE)
{
ScreenFadedOut = 0;
ScreenFade = 255;
dScreenFade = 0;
SetScreenFadeIn(16);
}*/
} }
if ((SpotCam[CurrentSplineCamera].flags & SCF_SCREEN_FADE_OUT) if ((SpotCam[CurrentSplineCamera].flags & SCF_SCREEN_FADE_OUT)
&& CameraFade != CurrentSplineCamera) && CameraFade != CurrentSplineCamera)
{ {
CameraFade = CurrentSplineCamera; CameraFade = CurrentSplineCamera;
/*if (gfCurrentLevel != LVL5_TITLE)
{
ScreenFadedOut = 0;
ScreenFade = 0;
dScreenFade = 255;
SetScreenFadeOut(16, 0);
}*/
} }
sp = 0; sp = 0;
@ -516,7 +493,7 @@ void CalculateSpotCameras()
} }
if (s->flags & SCF_DISABLE_BREAKOUT if (s->flags & SCF_DISABLE_BREAKOUT
|| !(TrInput & IN_LOOK) /*&& gfGameMode != 1*/) || !(TrInput & IN_LOOK))
{ {
Camera.pos.x = cpx; Camera.pos.x = cpx;
Camera.pos.y = cpy; Camera.pos.y = cpy;
@ -570,7 +547,7 @@ void CalculateSpotCameras()
} }
} }
LookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.target.x, Camera.target.y, Camera.target.z, 0); LookAt(&Camera, 0);
if (CheckTrigger) if (CheckTrigger)
{ {
@ -682,7 +659,7 @@ void CalculateSpotCameras()
{ {
//SetFadeClip(16, 1); //SetFadeClip(16, 1);
if (CurrentLevel) if (CurrentLevel)
g_Renderer->EnableCinematicBars(true); g_Renderer.EnableCinematicBars(true);
DisableLaraControl = true; DisableLaraControl = true;
} }
@ -783,7 +760,7 @@ void CalculateSpotCameras()
} }
//SetFadeClip(0, 1); //SetFadeClip(0, 1);
g_Renderer->EnableCinematicBars(false); g_Renderer.EnableCinematicBars(false);
UseSpotCam = 0; UseSpotCam = 0;
DisableLaraControl = 0; DisableLaraControl = 0;
@ -874,7 +851,7 @@ void CalculateSpotCameras()
Camera.targetElevation = elevation; Camera.targetElevation = elevation;
LookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.target.x, Camera.target.y, Camera.target.z, croll); LookAt(&Camera, croll);
SplineToCamera = 1; SplineToCamera = 1;
} }
@ -893,7 +870,7 @@ void CalculateSpotCameras()
} }
else else
{ {
g_Renderer->EnableCinematicBars(false); g_Renderer.EnableCinematicBars(false);
UseSpotCam = false; UseSpotCam = false;
DisableLaraControl = false; DisableLaraControl = false;
Camera.speed = 1; Camera.speed = 1;

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
#include "text.h" #include "text.h"
#include "draw.h" #include "draw.h"
#include "Renderer11.h" #include "Renderer11.h"
namespace T5M::Renderer {
void PrintString(int x, int y, int unk1, char* string, int unk2) void PrintString(int x, int y, int unk1, char* string, int unk2) {
{ g_Renderer.PrintString(x, y, string, D3DCOLOR_RGBA(0xFF, 0xFF, 0xFF, 255), 0);
g_Renderer->PrintString(x, y, string, D3DCOLOR_RGBA(0xFF, 0xFF, 0xFF, 255), 0); }
} }

View file

@ -528,7 +528,7 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini
if (GetRandomControl() & 1) if (GetRandomControl() & 1)
{ {
if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND) if (g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
spark->flags = SP_ROTATE | SP_WIND; spark->flags = SP_ROTATE | SP_WIND;
else else
spark->flags = SP_ROTATE; spark->flags = SP_ROTATE;
@ -540,7 +540,7 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini
else else
spark->rotAdd = (GetRandomControl() & 0x0F) + 16; spark->rotAdd = (GetRandomControl() & 0x0F) + 16;
} }
else if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND) else if (g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
{ {
spark->flags = SP_WIND; spark->flags = SP_WIND;
} }
@ -607,7 +607,7 @@ void TriggerShatterSmoke(int x, int y, int z)
else else
spark->rotAdd = (GetRandomControl() & 0x3F) + 64; spark->rotAdd = (GetRandomControl() & 0x3F) + 64;
} }
else if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND) else if (g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
{ {
spark->flags = SP_WIND; spark->flags = SP_WIND;
} }
@ -920,7 +920,7 @@ void UpdateGunShells()
short oldRoomNumber = gs->roomNumber; short oldRoomNumber = gs->roomNumber;
if (Rooms[gs->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[gs->roomNumber].flags & ENV_FLAG_WATER)
{ {
gs->fallspeed++; gs->fallspeed++;
@ -949,13 +949,13 @@ void UpdateGunShells()
gs->pos.zPos += gs->speed * phd_cos(gs->dirXrot) >> W2V_SHIFT; gs->pos.zPos += gs->speed * phd_cos(gs->dirXrot) >> W2V_SHIFT;
FLOOR_INFO* floor = GetFloor(gs->pos.xPos, gs->pos.yPos, gs->pos.zPos, &gs->roomNumber); FLOOR_INFO* floor = GetFloor(gs->pos.xPos, gs->pos.yPos, gs->pos.zPos, &gs->roomNumber);
if (Rooms[gs->roomNumber].flags & ENV_FLAG_WATER if (g_Level.Rooms[gs->roomNumber].flags & ENV_FLAG_WATER
&& !(Rooms[oldRoomNumber].flags & ENV_FLAG_WATER)) && !(g_Level.Rooms[oldRoomNumber].flags & ENV_FLAG_WATER))
{ {
T5M::Effects::Drip::SpawnGunshellDrips(Vector3(gs->pos.xPos, Rooms[gs->roomNumber].maxceiling, gs->pos.zPos), gs->roomNumber); T5M::Effects::Drip::SpawnGunshellDrips(Vector3(gs->pos.xPos, g_Level.Rooms[gs->roomNumber].maxceiling, gs->pos.zPos), gs->roomNumber);
//AddWaterSparks(gs->pos.xPos, Rooms[gs->roomNumber].maxceiling, gs->pos.zPos, 8); //AddWaterSparks(gs->pos.xPos, g_Level.Rooms[gs->roomNumber].maxceiling, gs->pos.zPos, 8);
SetupRipple(gs->pos.xPos, Rooms[gs->roomNumber].maxceiling, gs->pos.zPos, (GetRandomControl() & 3) + 8, 2); SetupRipple(gs->pos.xPos, g_Level.Rooms[gs->roomNumber].maxceiling, gs->pos.zPos, (GetRandomControl() & 3) + 8, 2);
gs->fallspeed >>= 5; gs->fallspeed >>= 5;
continue; continue;
} }
@ -1132,7 +1132,7 @@ void UpdateDrips()
drip->yVel += drip->gravity; drip->yVel += drip->gravity;
if (Rooms[drip->roomNumber].flags & ENV_FLAG_WIND) if (g_Level.Rooms[drip->roomNumber].flags & ENV_FLAG_WIND)
{ {
drip->x += SmokeWindX >> 1; drip->x += SmokeWindX >> 1;
drip->z += SmokeWindZ >> 1; drip->z += SmokeWindZ >> 1;
@ -1141,7 +1141,7 @@ void UpdateDrips()
drip->y += drip->yVel >> 5; drip->y += drip->yVel >> 5;
FLOOR_INFO* floor = GetFloor(drip->x, drip->y, drip->z, &drip->roomNumber); FLOOR_INFO* floor = GetFloor(drip->x, drip->y, drip->z, &drip->roomNumber);
if (Rooms[drip->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[drip->roomNumber].flags & ENV_FLAG_WATER)
drip->on = false; drip->on = false;
int height = GetFloorHeight(floor, drip->x, drip->y, drip->z); int height = GetFloorHeight(floor, drip->x, drip->y, drip->z);
@ -1194,10 +1194,10 @@ void TriggerLaraDrips()// (F)
int ExplodingDeath(short itemNumber, int meshBits, short flags) int ExplodingDeath(short itemNumber, int meshBits, short flags)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
ObjectInfo* obj = &Objects[item->objectNumber]; OBJECT_INFO* obj = &Objects[item->objectNumber];
short* frame = GetBestFrame(item); ANIM_FRAME* frame = GetBestFrame(item);
Matrix world = Matrix::CreateFromYawPitchRoll( Matrix world = Matrix::CreateFromYawPitchRoll(
TO_RAD(item->pos.yRot), TO_RAD(item->pos.yRot),
@ -1464,14 +1464,14 @@ void UpdateShockwaves()
{ {
if (sw->flags & 3) if (sw->flags & 3)
{ {
short* frame = GetBestFrame(LaraItem); ANIM_FRAME* frame = GetBestFrame(LaraItem);
int dx = LaraItem->pos.xPos - sw->x; int dx = LaraItem->pos.xPos - sw->x;
int dz = LaraItem->pos.zPos - sw->z; int dz = LaraItem->pos.zPos - sw->z;
int distance = sqrt(SQUARE(dx) + SQUARE(dz)); int distance = sqrt(SQUARE(dx) + SQUARE(dz));
if (sw->y <= LaraItem->pos.yPos + frame[2] if (sw->y <= LaraItem->pos.yPos + frame->boundingBox.Y1
|| sw->y >= LaraItem->pos.yPos + frame[3] + 256 || sw->y >= LaraItem->pos.yPos + frame->boundingBox.Y2 + 256
|| distance <= sw->innerRad || distance <= sw->innerRad
|| distance >= sw->outerRad) || distance >= sw->outerRad)
{ {

View file

@ -16,9 +16,9 @@
#include "input.h" #include "input.h"
#include "sound.h" #include "sound.h"
static short CeilingTrapDoorBounds[12] = {-256, 256, 0, 900, -768, -256, -1820, 1820, -5460, 5460, -1820, 1820}; OBJECT_COLLISION_BOUNDS CeilingTrapDoorBounds = {-256, 256, 0, 900, -768, -256, -1820, 1820, -5460, 5460, -1820, 1820};
static PHD_VECTOR CeilingTrapDoorPos = {0, 1056, -480}; static PHD_VECTOR CeilingTrapDoorPos = {0, 1056, -480};
static short FloorTrapDoorBounds[12] = {-256, 256, 0, 0, -1024, -256, -1820, 1820, -5460, 5460, -1820, 1820}; OBJECT_COLLISION_BOUNDS FloorTrapDoorBounds = {-256, 256, 0, 0, -1024, -256, -1820, 1820, -5460, 5460, -1820, 1820};
static PHD_VECTOR FloorTrapDoorPos = {0, 0, -655}; static PHD_VECTOR FloorTrapDoorPos = {0, 0, -655};
static short WreckingBallData[2] = {0, 0}; static short WreckingBallData[2] = {0, 0};
ITEM_INFO* WBItem; ITEM_INFO* WBItem;
@ -43,7 +43,7 @@ byte Flame3xzoffs[16][2] =
{ 0x28, 0x37 }, { 0x28, 0x37 },
{ 0x37, 0x37 } { 0x37, 0x37 }
}; };
static short FireBounds[12] = {0, 0, 0, 0, 0, 0, -1820, 1820, -5460, 5460, -1820, 1820}; OBJECT_COLLISION_BOUNDS FireBounds = {0, 0, 0, 0, 0, 0, -1820, 1820, -5460, 5460, -1820, 1820};
void LaraBurn() void LaraBurn()
{ {
@ -52,7 +52,7 @@ void LaraBurn()
short fxNum = CreateNewEffect(LaraItem->roomNumber); short fxNum = CreateNewEffect(LaraItem->roomNumber);
if (fxNum != NO_ITEM) if (fxNum != NO_ITEM)
{ {
Effects[fxNum].objectNumber = ID_FLAME; EffectList[fxNum].objectNumber = ID_FLAME;
Lara.burn = true; Lara.burn = true;
} }
} }
@ -63,7 +63,7 @@ void FlameEmitterControl(short itemNumber)
byte r, g, b; byte r, g, b;
int falloff; int falloff;
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item)) if (TriggerActive(item))
{ {
if (item->triggerFlags < 0) if (item->triggerFlags < 0)
@ -151,7 +151,8 @@ void FlameEmitterControl(short itemNumber)
if (!Lara.burn if (!Lara.burn
&& item->triggerFlags != 33 && item->triggerFlags != 33
&& ItemNearLara(&item->pos, 600) && ItemNearLara(&item->pos, 600)
&& (SQUARE(LaraItem->pos.xPos - item->pos.xPos) + SQUARE(LaraItem->pos.zPos - item->pos.zPos) < 0x40000)) && (SQUARE(LaraItem->pos.xPos - item->pos.xPos) + SQUARE(LaraItem->pos.zPos - item->pos.zPos) < 0x40000)
&& Lara.waterStatus != LW_FLYCHEAT)
{ {
LaraBurn(); LaraBurn();
} }
@ -160,7 +161,7 @@ void FlameEmitterControl(short itemNumber)
void FlameEmitter2Control(short itemNumber)//5A1BC, 5A638 (F) void FlameEmitter2Control(short itemNumber)//5A1BC, 5A638 (F)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item)) if (TriggerActive(item))
{ {
@ -214,7 +215,7 @@ void FlameEmitter2Control(short itemNumber)//5A1BC, 5A638 (F)
void FlameControl(short fxNumber) void FlameControl(short fxNumber)
{ {
FX_INFO* fx = &Effects[fxNumber]; FX_INFO* fx = &EffectList[fxNumber];
for (int i = 0; i < 14; i++) for (int i = 0; i < 14; i++)
{ {
@ -279,6 +280,12 @@ void FlameControl(short fxNumber)
KillEffect(fxNumber); KillEffect(fxNumber);
Lara.burn = false; Lara.burn = false;
} }
if (Lara.waterStatus == LW_FLYCHEAT)
{
KillEffect(fxNumber);
Lara.burn = false;
}
} }
void LavaBurn(ITEM_INFO* item) void LavaBurn(ITEM_INFO* item)
@ -300,7 +307,7 @@ void InitialiseTrapDoor(short itemNumber) // (F) (D)
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
CloseTrapDoor(item); CloseTrapDoor(item);
} }
@ -308,8 +315,8 @@ void TrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (F) (
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (item->currentAnimState == 1 && item->frameNumber == Anims[item->animNumber].frameEnd) if (item->currentAnimState == 1 && item->frameNumber == g_Level.Anims[item->animNumber].frameEnd)
ObjectCollision(itemNumber, l, coll); ObjectCollision(itemNumber, l, coll);
} }
@ -318,12 +325,12 @@ void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) /
ITEM_INFO* item; ITEM_INFO* item;
int result, result2; int result, result2;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
result = TestLaraPosition(CeilingTrapDoorBounds, item, l); result = TestLaraPosition(&CeilingTrapDoorBounds, item, l);
l->pos.yRot += ANGLE(180); l->pos.yRot += ANGLE(180);
result2 = TestLaraPosition(CeilingTrapDoorBounds, item, l); result2 = TestLaraPosition(&CeilingTrapDoorBounds, item, l);
l->pos.yRot += ANGLE(180); l->pos.yRot += ANGLE(180);
if (TrInput & IN_ACTION && item->status != ITEM_DEACTIVATED && l->currentAnimState == STATE_LARA_JUMP_UP && l->gravityStatus && Lara.gunStatus == LG_NO_ARMS && (result || result2)) if (TrInput & IN_ACTION && item->status != ITEM_DEACTIVATED && l->currentAnimState == LS_JUMP_UP && l->gravityStatus && Lara.gunStatus == LG_NO_ARMS && (result || result2))
{ {
AlignLaraPosition(&CeilingTrapDoorPos, item, l); AlignLaraPosition(&CeilingTrapDoorPos, item, l);
if (result2) if (result2)
@ -335,9 +342,9 @@ void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) /
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
l->gravityStatus = false; l->gravityStatus = false;
l->fallspeed = 0; l->fallspeed = 0;
l->animNumber = ANIMATION_LARA_CEILING_TRAPDOOR_OPEN; l->animNumber = LA_TRAPDOOR_CEILING_OPEN;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
l->currentAnimState = STATE_LARA_FREEFALL_BIS; l->currentAnimState = LS_FREEFALL_BIS;
AddActiveItem(itemNumber); AddActiveItem(itemNumber);
item->status = ITEM_ACTIVE; item->status = ITEM_ACTIVE;
item->goalAnimState = 1; item->goalAnimState = 1;
@ -354,7 +361,7 @@ void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) /
UseForcedFixedCamera = 0; UseForcedFixedCamera = 0;
} }
if (item->currentAnimState == 1 && item->frameNumber == Anims[item->animNumber].frameEnd) if (item->currentAnimState == 1 && item->frameNumber == g_Level.Anims[item->animNumber].frameEnd)
ObjectCollision(itemNumber, l, coll); ObjectCollision(itemNumber, l, coll);
} }
@ -362,17 +369,17 @@ void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) //
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION && item->status != ITEM_DEACTIVATED && l->currentAnimState == STATE_LARA_STOP && l->animNumber == ANIMATION_LARA_STAY_IDLE && Lara.gunStatus == LG_NO_ARMS if (TrInput & IN_ACTION && item->status != ITEM_DEACTIVATED && l->currentAnimState == LS_STOP && l->animNumber == LA_STAND_IDLE && Lara.gunStatus == LG_NO_ARMS
|| Lara.isMoving && Lara.generalPtr == (void *) itemNumber) || Lara.isMoving && Lara.generalPtr == (void *) itemNumber)
{ {
if (TestLaraPosition(FloorTrapDoorBounds, item, l)) if (TestLaraPosition(&FloorTrapDoorBounds, item, l))
{ {
if (MoveLaraPosition(&FloorTrapDoorPos, item, l)) if (MoveLaraPosition(&FloorTrapDoorPos, item, l))
{ {
l->animNumber = ANIMATION_LARA_FLOOR_TRAPDOOR_OPEN; l->animNumber = LA_TRAPDOOR_FLOOR_OPEN;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
l->currentAnimState = STATE_LARA_TRAPDOOR_FLOOR_OPEN; l->currentAnimState = LS_TRAPDOOR_FLOOR_OPEN;
Lara.isMoving = false; Lara.isMoving = false;
Lara.headYrot = 0; Lara.headYrot = 0;
Lara.headXrot = 0; Lara.headXrot = 0;
@ -386,8 +393,8 @@ void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) //
UseForcedFixedCamera = 1; UseForcedFixedCamera = 1;
ForcedFixedCamera.x = item->pos.xPos - phd_sin(item->pos.yRot) / 8; ForcedFixedCamera.x = item->pos.xPos - phd_sin(item->pos.yRot) / 8;
ForcedFixedCamera.y = item->pos.yPos - 2048; ForcedFixedCamera.y = item->pos.yPos - 2048;
if (ForcedFixedCamera.y < Rooms[item->roomNumber].maxceiling) if (ForcedFixedCamera.y < g_Level.Rooms[item->roomNumber].maxceiling)
ForcedFixedCamera.y = Rooms[item->roomNumber].maxceiling; ForcedFixedCamera.y = g_Level.Rooms[item->roomNumber].maxceiling;
ForcedFixedCamera.z = item->pos.zPos - phd_cos(item->pos.yRot) / 8; ForcedFixedCamera.z = item->pos.zPos - phd_cos(item->pos.yRot) / 8;
ForcedFixedCamera.roomNumber = item->roomNumber; ForcedFixedCamera.roomNumber = item->roomNumber;
} }
@ -403,7 +410,7 @@ void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) //
UseForcedFixedCamera = 0; UseForcedFixedCamera = 0;
} }
if (item->currentAnimState == 1 && item->frameNumber == Anims[item->animNumber].frameEnd) if (item->currentAnimState == 1 && item->frameNumber == g_Level.Anims[item->animNumber].frameEnd)
ObjectCollision(itemNumber, l, coll); ObjectCollision(itemNumber, l, coll);
} }
@ -411,14 +418,14 @@ void TrapDoorControl(short itemNumber) // (F) (D)
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (TriggerActive(item)) if (TriggerActive(item))
{ {
if (!item->currentAnimState && item->triggerFlags >= 0) if (!item->currentAnimState && item->triggerFlags >= 0)
{ {
item->goalAnimState = 1; item->goalAnimState = 1;
} }
else if (item->frameNumber == Anims[item->animNumber].frameEnd && CurrentLevel == 14 && item->objectNumber == ID_TRAPDOOR1) else if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd && CurrentLevel == 14 && item->objectNumber == ID_TRAPDOOR1)
{ {
item->status = ITEM_INVISIBLE; item->status = ITEM_INVISIBLE;
} }
@ -451,7 +458,7 @@ void CloseTrapDoor(ITEM_INFO* item) // (F) (D)
FLOOR_INFO* floor; FLOOR_INFO* floor;
unsigned short pitsky; unsigned short pitsky;
r = &Rooms[item->roomNumber]; r = &g_Level.Rooms[item->roomNumber];
floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z); floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z);
pitsky = 0; pitsky = 0;
@ -459,7 +466,7 @@ void CloseTrapDoor(ITEM_INFO* item) // (F) (D)
{ {
pitsky = floor->pitRoom; pitsky = floor->pitRoom;
floor->pitRoom = NO_ROOM; floor->pitRoom = NO_ROOM;
r = &Rooms[pitsky]; r = &g_Level.Rooms[pitsky];
floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z); floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z);
pitsky |= floor->skyRoom << 8; pitsky |= floor->skyRoom << 8;
floor->skyRoom = NO_ROOM; floor->skyRoom = NO_ROOM;
@ -468,7 +475,7 @@ void CloseTrapDoor(ITEM_INFO* item) // (F) (D)
{ {
pitsky = floor->skyRoom; pitsky = floor->skyRoom;
floor->skyRoom = NO_ROOM; floor->skyRoom = NO_ROOM;
r = &Rooms[pitsky]; r = &g_Level.Rooms[pitsky];
floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z); floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z);
pitsky = pitsky << 8 | floor->pitRoom; pitsky = pitsky << 8 | floor->pitRoom;
floor->pitRoom = NO_ROOM; floor->pitRoom = NO_ROOM;
@ -484,21 +491,21 @@ void OpenTrapDoor(ITEM_INFO* item) // (F) (D)
FLOOR_INFO* floor; FLOOR_INFO* floor;
unsigned short pitsky; unsigned short pitsky;
r = &Rooms[item->roomNumber]; r = &g_Level.Rooms[item->roomNumber];
floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z); floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z);
pitsky = item->itemFlags[3]; pitsky = item->itemFlags[3];
if (item->pos.yPos == r->minfloor) if (item->pos.yPos == r->minfloor)
{ {
floor->pitRoom = (unsigned char) pitsky; floor->pitRoom = (unsigned char) pitsky;
r = &Rooms[floor->pitRoom]; r = &g_Level.Rooms[floor->pitRoom];
floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z); floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z);
floor->skyRoom = pitsky >> 8; floor->skyRoom = pitsky >> 8;
} }
else else
{ {
floor->skyRoom = pitsky >> 8; floor->skyRoom = pitsky >> 8;
r = &Rooms[floor->skyRoom]; r = &g_Level.Rooms[floor->skyRoom];
floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z); floor = &XZ_GET_SECTOR(r, item->pos.xPos - r->x, item->pos.zPos - r->z);
floor->pitRoom = (unsigned char) pitsky; floor->pitRoom = (unsigned char) pitsky;
} }
@ -508,12 +515,12 @@ void OpenTrapDoor(ITEM_INFO* item) // (F) (D)
void InitialiseFallingBlock(short itemNumber) void InitialiseFallingBlock(short itemNumber)
{ {
Items[itemNumber].meshBits = 1; g_Level.Items[itemNumber].meshBits = 1;
} }
void FallingBlockCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) void FallingBlockCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
if (!item->itemFlags[0] && !item->triggerFlags && item->pos.yPos == l->pos.yPos) if (!item->itemFlags[0] && !item->triggerFlags && item->pos.yPos == l->pos.yPos)
{ {
if (!((item->pos.xPos ^ l->pos.xPos) & 0xFFFFFC00) && !((l->pos.zPos ^ item->pos.zPos) & 0xFFFFFC00)) if (!((item->pos.xPos ^ l->pos.xPos) & 0xFFFFFC00) && !((l->pos.zPos ^ item->pos.zPos) & 0xFFFFFC00))
@ -530,7 +537,7 @@ void FallingBlockCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void FallingBlockControl(short itemNumber) void FallingBlockControl(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->triggerFlags) if (item->triggerFlags)
{ {
@ -598,8 +605,8 @@ void InitialiseWreckingBall(short itemNumber)
ITEM_INFO* item; ITEM_INFO* item;
short room; short room;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
item->itemFlags[3] = find_a_fucking_item(ID_ANIMATING16) - Items; item->itemFlags[3] = find_a_fucking_item(ID_ANIMATING16) - g_Level.Items.data();
room = item->roomNumber; room = item->roomNumber;
item->pos.yPos = GetCeiling(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &room), item->pos.xPos, item->pos.yPos, item->pos.zPos) + 1644; item->pos.yPos = GetCeiling(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &room), item->pos.xPos, item->pos.yPos, item->pos.zPos) + 1644;
GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &room); GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &room);
@ -613,7 +620,7 @@ void WreckingBallCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
int x, y, z, test; int x, y, z, test;
short damage; short damage;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
if (TestBoundsCollide(item, l, coll->radius)) if (TestBoundsCollide(item, l, coll->radius))
{ {
x = l->pos.xPos; x = l->pos.xPos;
@ -654,9 +661,9 @@ void WreckingBallControl(short itemNumber)
int test, x, z, oldX, oldZ, wx, wz, flagX, flagZ, height, dx, dz, ceilingX, ceilingZ, adx, adz; int test, x, z, oldX, oldZ, wx, wz, flagX, flagZ, height, dx, dz, ceilingX, ceilingZ, adx, adz;
short room; short room;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
test = 1; test = 1;
item2 = &Items[item->itemFlags[3]]; item2 = &g_Level.Items[item->itemFlags[3]];
if (LaraItem->pos.xPos >= 45056 && LaraItem->pos.xPos <= 57344 && LaraItem->pos.zPos >= 26624 && LaraItem->pos.zPos <= 43008 if (LaraItem->pos.xPos >= 45056 && LaraItem->pos.xPos <= 57344 && LaraItem->pos.zPos >= 26624 && LaraItem->pos.zPos <= 43008
|| item->itemFlags[2] < 900) || item->itemFlags[2] < 900)
{ {
@ -800,7 +807,7 @@ void WreckingBallControl(short itemNumber)
{ {
item->goalAnimState = 1; item->goalAnimState = 1;
} }
else if (item->frameNumber == Anims[item->animNumber].frameEnd) else if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd)
{ {
SoundEffect(SFX_GRAB_DROP, &item->pos, 0); SoundEffect(SFX_GRAB_DROP, &item->pos, 0);
++item->itemFlags[1]; ++item->itemFlags[1];
@ -880,7 +887,7 @@ void WreckingBallControl(short itemNumber)
void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (F) (D) void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (F) (D)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (Lara.gunType != WEAPON_TORCH if (Lara.gunType != WEAPON_TORCH
|| Lara.gunStatus != LG_READY || Lara.gunStatus != LG_READY
@ -888,8 +895,8 @@ void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (
|| Lara.litTorch == (item->status & 1) || Lara.litTorch == (item->status & 1)
|| item->timer == -1 || item->timer == -1
|| !(TrInput & IN_ACTION) || !(TrInput & IN_ACTION)
|| l->currentAnimState != STATE_LARA_STOP || l->currentAnimState != LS_STOP
|| l->animNumber != ANIMATION_LARA_STAY_IDLE || l->animNumber != LA_STAND_IDLE
|| l->gravityStatus) || l->gravityStatus)
{ {
if (item->objectNumber == ID_BURNING_ROOTS) if (item->objectNumber == ID_BURNING_ROOTS)
@ -900,30 +907,30 @@ void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (
switch (item->objectNumber) switch (item->objectNumber)
{ {
case ID_FLAME_EMITTER: case ID_FLAME_EMITTER:
FireBounds[0] = -256; FireBounds.boundingBox.X1 = -256;
FireBounds[1] = 256; FireBounds.boundingBox.X2 = 256;
FireBounds[2] = 0; FireBounds.boundingBox.Y1 = 0;
FireBounds[3] = 1024; FireBounds.boundingBox.Y2 = 1024;
FireBounds[4] = -800; FireBounds.boundingBox.Z1 = -800;
FireBounds[5] = 800; FireBounds.boundingBox.Z2 = 800;
break; break;
case ID_FLAME_EMITTER2: case ID_FLAME_EMITTER2:
FireBounds[0] = -256; FireBounds.boundingBox.X1 = -256;
FireBounds[1] = 256; FireBounds.boundingBox.X2 = 256;
FireBounds[2] = 0; FireBounds.boundingBox.Y1 = 0;
FireBounds[3] = 1024; FireBounds.boundingBox.Y2 = 1024;
FireBounds[4] = -600; FireBounds.boundingBox.Z1 = -600;
FireBounds[5] = 600; FireBounds.boundingBox.Z2 = 600;
break; break;
case ID_BURNING_ROOTS: case ID_BURNING_ROOTS:
FireBounds[0] = -384; FireBounds.boundingBox.X1 = -384;
FireBounds[1] = 384; FireBounds.boundingBox.X2 = 384;
FireBounds[2] = 0; FireBounds.boundingBox.Y1 = 0;
FireBounds[3] = 2048; FireBounds.boundingBox.Y2 = 2048;
FireBounds[4] = -384; FireBounds.boundingBox.Z1 = -384;
FireBounds[5] = 384; FireBounds.boundingBox.Z2 = 384;
break; break;
} }
@ -931,21 +938,21 @@ void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (
short oldYrot = item->pos.yRot; short oldYrot = item->pos.yRot;
item->pos.yRot = l->pos.yRot; item->pos.yRot = l->pos.yRot;
if (TestLaraPosition(FireBounds, item, l)) if (TestLaraPosition(&FireBounds, item, l))
{ {
if (item->objectNumber == ID_BURNING_ROOTS) if (item->objectNumber == ID_BURNING_ROOTS)
{ {
l->animNumber = ANIMATION_LARA_TORCH_LIGHT_5; l->animNumber = LA_TORCH_LIGHT_5;
} }
else else
{ {
int dy = abs(l->pos.yPos - item->pos.yPos); int dy = abs(l->pos.yPos - item->pos.yPos);
l->itemFlags[3] = 1; l->itemFlags[3] = 1;
l->animNumber = (dy >> 8) + ANIMATION_LARA_TORCH_LIGHT_1; l->animNumber = (dy >> 8) + LA_TORCH_LIGHT_1;
} }
l->currentAnimState = STATE_LARA_MISC_CONTROL; l->currentAnimState = LS_MISC_CONTROL;
l->frameNumber = Anims[l->animNumber].frameBase; l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
Lara.flareControlLeft = false; Lara.flareControlLeft = false;
Lara.leftArm.lock = 3; Lara.leftArm.lock = 3;
Lara.generalPtr = (void*)itemNumber; Lara.generalPtr = (void*)itemNumber;
@ -956,11 +963,11 @@ void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (
if (Lara.generalPtr == (void*)itemNumber if (Lara.generalPtr == (void*)itemNumber
&& item->status != ITEM_ACTIVE && item->status != ITEM_ACTIVE
&& l->currentAnimState == STATE_LARA_MISC_CONTROL) && l->currentAnimState == LS_MISC_CONTROL)
{ {
if (l->animNumber >= ANIMATION_LARA_TORCH_LIGHT_1 && l->animNumber <= ANIMATION_LARA_TORCH_LIGHT_5) if (l->animNumber >= LA_TORCH_LIGHT_1 && l->animNumber <= LA_TORCH_LIGHT_5)
{ {
if (l->frameNumber - Anims[l->animNumber].frameBase == 40) if (l->frameNumber - g_Level.Anims[l->animNumber].frameBase == 40)
{ {
TestTriggersAtXYZ(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 1, item->flags & 0x3E00); TestTriggersAtXYZ(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 1, item->flags & 0x3E00);
@ -976,7 +983,7 @@ void FlameEmitterCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) // (
void InitialiseFlameEmitter2(short itemNumber) void InitialiseFlameEmitter2(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
item->pos.yPos -= 64; item->pos.yPos -= 64;
@ -1021,7 +1028,7 @@ void InitialiseFlameEmitter2(short itemNumber)
void InitialiseFlameEmitter(short itemNumber) void InitialiseFlameEmitter(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->triggerFlags > 0) if (item->triggerFlags > 0)
{ {
@ -1093,7 +1100,7 @@ void InitialiseFlameEmitter(short itemNumber)
void FlameEmitter3Control(short itemNumber) void FlameEmitter3Control(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item)) if (TriggerActive(item))
{ {
@ -1137,7 +1144,7 @@ void FlameEmitter3Control(short itemNumber)
if (item->triggerFlags >= 3 && !(GlobalCounter & 1)) if (item->triggerFlags >= 3 && !(GlobalCounter & 1))
{ {
short targetItemNumber = item->itemFlags[((GlobalCounter >> 2) & 1) + 2]; short targetItemNumber = item->itemFlags[((GlobalCounter >> 2) & 1) + 2];
ITEM_INFO* targetItem = &Items[targetItemNumber]; ITEM_INFO* targetItem = &g_Level.Items[targetItemNumber];
dest.x = 0; dest.x = 0;
dest.y = -64; dest.y = -64;
@ -1218,7 +1225,7 @@ void FlameEmitter3Control(short itemNumber)
if (ItemNearLara(&pos, 600)) if (ItemNearLara(&pos, 600))
{ {
if (!Lara.burn) if ((!Lara.burn) && Lara.waterStatus != LW_FLYCHEAT)
{ {
LaraItem->hitPoints -= 5; LaraItem->hitPoints -= 5;
LaraItem->hitStatus = true; LaraItem->hitStatus = true;

View file

@ -1464,7 +1464,7 @@ void phd_GetVectorAngles(int x, int y, int z, short* angles)
angles[1] = angle; angles[1] = angle;
} }
void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, short* bounds, short* tbounds) void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, BOUNDING_BOX* bounds, BOUNDING_BOX* tbounds)
{ {
Matrix world = Matrix::CreateFromYawPitchRoll( Matrix world = Matrix::CreateFromYawPitchRoll(
TO_RAD(pos->yRot), TO_RAD(pos->yRot),
@ -1472,16 +1472,16 @@ void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, short* bounds, short* tbounds)
TO_RAD(pos->zRot) TO_RAD(pos->zRot)
); );
Vector3 bMin = Vector3(bounds[0], bounds[2], bounds[4]); Vector3 bMin = Vector3(bounds->X1, bounds->Y1, bounds->Z1);
Vector3 bMax = Vector3(bounds[1], bounds[3], bounds[5]); Vector3 bMax = Vector3(bounds->X2, bounds->Y2, bounds->Z2);
bMin = Vector3::Transform(bMin, world); bMin = Vector3::Transform(bMin, world);
bMax = Vector3::Transform(bMax, world); bMax = Vector3::Transform(bMax, world);
tbounds[0] = bMin.x; tbounds->X1 = bMin.x;
tbounds[1] = bMax.x; tbounds->X2 = bMax.x;
tbounds[2] = bMin.y; tbounds->Y1 = bMin.y;
tbounds[3] = bMax.y; tbounds->Y2 = bMax.y;
tbounds[4] = bMin.z; tbounds->Z1 = bMin.z;
tbounds[5] = bMax.z; tbounds->Z2 = bMax.z;
} }

View file

@ -38,4 +38,4 @@ const float lerp(float v0, float v1, float t);
int mGetAngle(int x1, int y1, int x2, int y2); int mGetAngle(int x1, int y1, int x2, int y2);
int phd_atan(int dz, int dx); int phd_atan(int dz, int dx);
void phd_GetVectorAngles(int x, int y, int z, short* angles); void phd_GetVectorAngles(int x, int y, int z, short* angles);
void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, short* bounds, short* tbounds); void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, BOUNDING_BOX* bounds, BOUNDING_BOX* tbounds);

View file

@ -13,7 +13,7 @@
void BubblesEffect1(short fxNum, short xVel, short yVel, short zVel) void BubblesEffect1(short fxNum, short xVel, short yVel, short zVel)
{ {
FX_INFO* fx = &Effects[fxNum]; FX_INFO* fx = &EffectList[fxNum];
int dx = LaraItem->pos.xPos - fx->pos.xPos; int dx = LaraItem->pos.xPos - fx->pos.xPos;
int dz = LaraItem->pos.zPos - fx->pos.zPos; int dz = LaraItem->pos.zPos - fx->pos.zPos;
@ -68,7 +68,7 @@ void BubblesEffect1(short fxNum, short xVel, short yVel, short zVel)
void BubblesEffect2(short fxNum, short xVel, short yVel, short zVel) void BubblesEffect2(short fxNum, short xVel, short yVel, short zVel)
{ {
FX_INFO* fx = &Effects[fxNum]; FX_INFO* fx = &EffectList[fxNum];
int dx = LaraItem->pos.xPos - fx->pos.xPos; int dx = LaraItem->pos.xPos - fx->pos.xPos;
int dz = LaraItem->pos.zPos - fx->pos.zPos; int dz = LaraItem->pos.zPos - fx->pos.zPos;
@ -115,7 +115,7 @@ void BubblesEffect2(short fxNum, short xVel, short yVel, short zVel)
void BubblesEffect4(short fxNum, short xVel, short yVel, short zVel) void BubblesEffect4(short fxNum, short xVel, short yVel, short zVel)
{ {
FX_INFO* fx = &Effects[fxNum]; FX_INFO* fx = &EffectList[fxNum];
int dx = LaraItem->pos.xPos - fx->pos.xPos; int dx = LaraItem->pos.xPos - fx->pos.xPos;
int dz = LaraItem->pos.zPos - fx->pos.zPos; int dz = LaraItem->pos.zPos - fx->pos.zPos;
@ -176,7 +176,7 @@ void BubblesEffect4(short fxNum, short xVel, short yVel, short zVel)
void BubblesShatterFunction(FX_INFO* fx, int param1, int param2) void BubblesShatterFunction(FX_INFO* fx, int param1, int param2)
{ {
ShatterItem.yRot = fx->pos.yRot; ShatterItem.yRot = fx->pos.yRot;
ShatterItem.meshp = Meshes[fx->frameNumber]; ShatterItem.meshp = &g_Level.Meshes[fx->frameNumber];
ShatterItem.sphere.x = fx->pos.xPos; ShatterItem.sphere.x = fx->pos.xPos;
ShatterItem.sphere.y = fx->pos.yPos; ShatterItem.sphere.y = fx->pos.yPos;
ShatterItem.sphere.z = fx->pos.zPos; ShatterItem.sphere.z = fx->pos.zPos;
@ -187,7 +187,7 @@ void BubblesShatterFunction(FX_INFO* fx, int param1, int param2)
void BubblesControl(short fxNum) void BubblesControl(short fxNum)
{ {
FX_INFO* fx = &Effects[fxNum]; FX_INFO* fx = &EffectList[fxNum];
short angles[2]; short angles[2];
phd_GetVectorAngles( phd_GetVectorAngles(
@ -291,7 +291,7 @@ void BubblesControl(short fxNum)
if (fx->flag1 == 1) if (fx->flag1 == 1)
{ {
TriggerShockwave(&fx->pos, 32, 160, 64, 64, 128, 00, 24, (((~Rooms[fx->roomNumber].flags) >> 4) & 2) << 16, 0); TriggerShockwave(&fx->pos, 32, 160, 64, 64, 128, 00, 24, (((~g_Level.Rooms[fx->roomNumber].flags) >> 4) & 2) << 16, 0);
TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 2, fx->roomNumber); TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 2, fx->roomNumber);
} }
else else
@ -400,7 +400,7 @@ void BubblesControl(short fxNum)
} }
else else
{ {
TriggerShockwave( &fx->pos, 24, 88, 48, 64, 128, 0, 16, (((~Rooms[fx->roomNumber].flags) >> 4) & 2) << 16, 0); TriggerShockwave( &fx->pos, 24, 88, 48, 64, 128, 0, 16, (((~g_Level.Rooms[fx->roomNumber].flags) >> 4) & 2) << 16, 0);
} }
} }
else else

View file

@ -92,7 +92,7 @@ void SpawnLocust(ITEM_INFO* item)
void InitialiseLocust(short itemNumber) void InitialiseLocust(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->pos.yRot > 0) if (item->pos.yRot > 0)
{ {
@ -114,7 +114,7 @@ void InitialiseLocust(short itemNumber)
void LocustControl(short itemNumber) void LocustControl(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item)) if (TriggerActive(item))
{ {
@ -152,7 +152,7 @@ void UpdateLocusts(void)
locust->counter--; locust->counter--;
if (locust->counter == 0) if (locust->counter == 0)
{ {
locust->on = FALSE; locust->on = false;
break; break;
} }

View file

@ -129,7 +129,7 @@ void ElectricityWiresControl(short itemNumber)
bool flag = false; bool flag = false;
int counter = 3; int counter = 3;
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->itemFlags[0] > 2) if (item->itemFlags[0] > 2)
{ {
@ -224,7 +224,7 @@ void ElectricityWiresControl(short itemNumber)
roomNumber = item->roomNumber; roomNumber = item->roomNumber;
GetFloor(pos.x, pos.y, pos.z, &roomNumber); GetFloor(pos.x, pos.y, pos.z, &roomNumber);
ROOM_INFO* r = &Rooms[roomNumber]; ROOM_INFO* r = &g_Level.Rooms[roomNumber];
if (r->flags & ENV_FLAG_WATER) if (r->flags & ENV_FLAG_WATER)
{ {
@ -241,7 +241,7 @@ void ElectricityWiresControl(short itemNumber)
{ {
if (water) if (water)
{ {
int flipNumber = Rooms[roomNumber].flipNumber; int flipNumber = g_Level.Rooms[roomNumber].flipNumber;
PHD_VECTOR pos1; PHD_VECTOR pos1;
pos1.x = 0; pos1.x = 0;
@ -261,7 +261,7 @@ void ElectricityWiresControl(short itemNumber)
short roomNumber2 = LaraItem->roomNumber; short roomNumber2 = LaraItem->roomNumber;
GetFloor(pos2.x, pos2.y, pos2.z, &roomNumber2); GetFloor(pos2.x, pos2.y, pos2.z, &roomNumber2);
if (Rooms[roomNumber1].flipNumber == flipNumber || Rooms[roomNumber2].flipNumber == flipNumber) if (g_Level.Rooms[roomNumber1].flipNumber == flipNumber || g_Level.Rooms[roomNumber2].flipNumber == flipNumber)
{ {
if (LaraItem->hitPoints > 32) if (LaraItem->hitPoints > 32)
{ {

View file

@ -13,7 +13,7 @@ void ApeControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short head = 0; short head = 0;
@ -25,7 +25,7 @@ void ApeControl(short itemNum)
if (item->currentAnimState != 5) if (item->currentAnimState != 5)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 7 + (short)(GetRandomControl() / 0x4000); item->animNumber = Objects[item->objectNumber].animIndex + 7 + (short)(GetRandomControl() / 0x4000);
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 5; item->currentAnimState = 5;
} }
} }
@ -174,7 +174,7 @@ void ApeControl(short itemNum)
creature->maximumTurn = 0; creature->maximumTurn = 0;
item->animNumber = Objects[item->objectNumber].animIndex + 19; item->animNumber = Objects[item->objectNumber].animIndex + 19;
item->currentAnimState = 11; item->currentAnimState = 11;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
break; break;
default: default:

View file

@ -13,7 +13,7 @@ void BearControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short head = 0; short head = 0;
@ -54,7 +54,7 @@ void BearControl(short itemNum)
} }
item->animNumber = Objects[item->objectNumber].animIndex + 20; item->animNumber = Objects[item->objectNumber].animIndex + 20;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 9; item->currentAnimState = 9;
break; break;
} }

View file

@ -85,14 +85,14 @@ static bool RatIsInWater(ITEM_INFO* item, CREATURE_INFO* big_rat)
// initialised at loading level // initialised at loading level
void InitialiseBigRat(short itemNumber) void InitialiseBigRat(short itemNumber)
{ {
ITEM_INFO* item = &Items[itemNumber]; ITEM_INFO* item = &g_Level.Items[itemNumber];
InitialiseCreature(itemNumber); InitialiseCreature(itemNumber);
// if the room is a "water room" // if the room is a "water room"
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + BIG_RAT_ANIM_SWIM; item->animNumber = Objects[item->objectNumber].animIndex + BIG_RAT_ANIM_SWIM;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = BIG_RAT_SWIM; item->currentAnimState = BIG_RAT_SWIM;
item->goalAnimState = BIG_RAT_SWIM; item->goalAnimState = BIG_RAT_SWIM;
} }
@ -100,7 +100,7 @@ void InitialiseBigRat(short itemNumber)
else else
{ {
item->animNumber = Objects[item->objectNumber].animIndex + BIG_RAT_ANIM_EMPTY; item->animNumber = Objects[item->objectNumber].animIndex + BIG_RAT_ANIM_EMPTY;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = BIG_RAT_STOP; item->currentAnimState = BIG_RAT_STOP;
item->goalAnimState = BIG_RAT_STOP; item->goalAnimState = BIG_RAT_STOP;
} }
@ -113,13 +113,13 @@ void BigRatControl(short itemNumber)
return; return;
ITEM_INFO* item; ITEM_INFO* item;
ObjectInfo* obj; OBJECT_INFO* obj;
CREATURE_INFO* big_rat; CREATURE_INFO* big_rat;
AI_INFO info; AI_INFO info;
short head, angle; short head, angle;
int WaterHeight; int WaterHeight;
item = &Items[itemNumber]; item = &g_Level.Items[itemNumber];
obj = &Objects[item->objectNumber]; obj = &Objects[item->objectNumber];
big_rat = GetCreatureInfo(item); big_rat = GetCreatureInfo(item);
head = angle = 0; head = angle = 0;
@ -130,10 +130,10 @@ void BigRatControl(short itemNumber)
if (item->currentAnimState != BIG_RAT_LAND_DEATH && item->currentAnimState != BIG_RAT_WATER_DEATH) if (item->currentAnimState != BIG_RAT_LAND_DEATH && item->currentAnimState != BIG_RAT_WATER_DEATH)
{ {
// water // water
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
{ {
item->animNumber = obj->animIndex + BIG_RAT_ANIM_WATER_DEATH; item->animNumber = obj->animIndex + BIG_RAT_ANIM_WATER_DEATH;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = BIG_RAT_WATER_DEATH; item->currentAnimState = BIG_RAT_WATER_DEATH;
item->goalAnimState = BIG_RAT_WATER_DEATH; item->goalAnimState = BIG_RAT_WATER_DEATH;
} }
@ -141,14 +141,14 @@ void BigRatControl(short itemNumber)
else else
{ {
item->animNumber = obj->animIndex + BIG_RAT_ANIM_LAND_DEATH; item->animNumber = obj->animIndex + BIG_RAT_ANIM_LAND_DEATH;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = BIG_RAT_LAND_DEATH; item->currentAnimState = BIG_RAT_LAND_DEATH;
item->goalAnimState = BIG_RAT_LAND_DEATH; item->goalAnimState = BIG_RAT_LAND_DEATH;
} }
} }
// creatures in water are floating after death. // creatures in water are floating after death.
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
CreatureFloat(itemNumber); CreatureFloat(itemNumber);
} }
else else
@ -171,7 +171,7 @@ void BigRatControl(short itemNumber)
if ((item->hitStatus || info.distance < BIG_RAT_ALERT_RANGE) || (TargetVisible(item, &info) && info.distance < BIG_RAT_VISIBILITY_RANGE)) if ((item->hitStatus || info.distance < BIG_RAT_ALERT_RANGE) || (TargetVisible(item, &info) && info.distance < BIG_RAT_VISIBILITY_RANGE))
{ {
if (!big_rat->alerted) if (!big_rat->alerted)
big_rat->alerted = TRUE; big_rat->alerted = true;
AlertAllGuards(itemNumber); AlertAllGuards(itemNumber);
} }
@ -213,7 +213,7 @@ void BigRatControl(short itemNumber)
{ {
CreatureEffect(item, &big_ratBite, DoBloodSplat); CreatureEffect(item, &big_ratBite, DoBloodSplat);
LaraItem->hitPoints -= BIG_RAT_BITE_DAMAGE; LaraItem->hitPoints -= BIG_RAT_BITE_DAMAGE;
LaraItem->hitStatus = TRUE; LaraItem->hitStatus = true;
item->requiredAnimState = BIG_RAT_STOP; item->requiredAnimState = BIG_RAT_STOP;
} }
break; break;
@ -223,7 +223,7 @@ void BigRatControl(short itemNumber)
{ {
CreatureEffect(item, &big_ratBite, DoBloodSplat); CreatureEffect(item, &big_ratBite, DoBloodSplat);
LaraItem->hitPoints -= BIG_RAT_CHARGE_DAMAGE; LaraItem->hitPoints -= BIG_RAT_CHARGE_DAMAGE;
LaraItem->hitStatus = TRUE; LaraItem->hitStatus = true;
item->requiredAnimState = BIG_RAT_RUN; item->requiredAnimState = BIG_RAT_RUN;
} }
break; break;
@ -253,7 +253,7 @@ void BigRatControl(short itemNumber)
{ {
CreatureEffect(item, &big_ratBite, DoBloodSplat); CreatureEffect(item, &big_ratBite, DoBloodSplat);
LaraItem->hitPoints -= BIG_RAT_BITE_DAMAGE; LaraItem->hitPoints -= BIG_RAT_BITE_DAMAGE;
LaraItem->hitStatus = TRUE; LaraItem->hitStatus = true;
} }
item->goalAnimState = BIG_RAT_SWIM; item->goalAnimState = BIG_RAT_SWIM;

View file

@ -29,7 +29,7 @@ void DoppelgangerControl(short itemNum)
int x, y, z; int x, y, z;
short room_num; short room_num;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
if (item->hitPoints < 1000) // If Evil Lara being Injured if (item->hitPoints < 1000) // If Evil Lara being Injured
{ // then take the hits off Lara instead... { // then take the hits off Lara instead...
@ -62,10 +62,10 @@ void DoppelgangerControl(short itemNum)
if (h >= lh + WALL_SIZE && !LaraItem->gravityStatus) if (h >= lh + WALL_SIZE && !LaraItem->gravityStatus)
{ {
item->goalAnimState = STATE_LARA_FREEFALL; // Make Player Stop Immediately item->goalAnimState = LS_FREEFALL; // Make Player Stop Immediately
item->currentAnimState = STATE_LARA_FREEFALL; // and Skip directly into fastfall item->currentAnimState = LS_FREEFALL; // and Skip directly into fastfall
item->frameNumber = GF(ANIMATION_LARA_SMASH_JUMP, 0); item->frameNumber = GF(LA_JUMP_WALL_SMASH_START, 0);
item->animNumber = ANIMATION_LARA_SMASH_JUMP; item->animNumber = LA_JUMP_WALL_SMASH_START;
item->gravityStatus = true; item->gravityStatus = true;
item->fallspeed = 0; item->fallspeed = 0;
item->speed = 0; item->speed = 0;
@ -93,8 +93,8 @@ void DoppelgangerControl(short itemNum)
TestTriggers(TriggerIndex, TRUE, 0); TestTriggers(TriggerIndex, TRUE, 0);
item->gravityStatus = false; item->gravityStatus = false;
item->fallspeed = 0; item->fallspeed = 0;
item->goalAnimState = STATE_LARA_DEATH; item->goalAnimState = LS_DEATH;
item->requiredAnimState = STATE_LARA_DEATH; item->requiredAnimState = LS_DEATH;
} }
} }
} }

View file

@ -42,7 +42,7 @@ void NatlaControl(short itemNum)
short facing = 0; short facing = 0;
short fx_number, timer; short fx_number, timer;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
natla = (CREATURE_INFO*)item->data; natla = (CREATURE_INFO*)item->data;
head = angle = tilt = 0; head = angle = tilt = 0;
gun = natla->jointRotation[0] * 7 / 8; gun = natla->jointRotation[0] * 7 / 8;
@ -101,7 +101,7 @@ void NatlaControl(short itemNum)
fx_number = CreatureEffect(item, &natla_gun, ShardGun); fx_number = CreatureEffect(item, &natla_gun, ShardGun);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
gun = fx->pos.xRot; gun = fx->pos.xRot;
SoundEffect(123, &fx->pos, NULL); SoundEffect(123, &fx->pos, NULL);
} }
@ -117,7 +117,7 @@ void NatlaControl(short itemNum)
fx_number = CreatureEffect(item, &natla_gun, ShardGun); fx_number = CreatureEffect(item, &natla_gun, ShardGun);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
gun = fx->pos.xRot; gun = fx->pos.xRot;
SoundEffect(123, &fx->pos, NULL); SoundEffect(123, &fx->pos, NULL);
} }
@ -225,7 +225,7 @@ void NatlaControl(short itemNum)
fx_number = CreatureEffect(item, &natla_gun, BombGun); fx_number = CreatureEffect(item, &natla_gun, BombGun);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
{ {
fx = &Effects[fx_number]; fx = &EffectList[fx_number];
gun = fx->pos.xRot; gun = fx->pos.xRot;
SoundEffect(123, &fx->pos, NULL); SoundEffect(123, &fx->pos, NULL);
} }
@ -248,13 +248,13 @@ void NatlaControl(short itemNum)
/* Eat this ... */ /* Eat this ... */
fx_number = CreatureEffect(item, &natla_gun, BombGun); fx_number = CreatureEffect(item, &natla_gun, BombGun);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
gun = Effects[fx_number].pos.xRot; gun = EffectList[fx_number].pos.xRot;
fx_number = CreatureEffect(item, &natla_gun, BombGun); fx_number = CreatureEffect(item, &natla_gun, BombGun);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
Effects[fx_number].pos.yRot += (short)((GetRandomControl() - 0x4000) / 4); EffectList[fx_number].pos.yRot += (short)((GetRandomControl() - 0x4000) / 4);
fx_number = CreatureEffect(item, &natla_gun, BombGun); fx_number = CreatureEffect(item, &natla_gun, BombGun);
if (fx_number != NO_ITEM) if (fx_number != NO_ITEM)
Effects[fx_number].pos.yRot += (short)((GetRandomControl() - 0x4000) / 4); EffectList[fx_number].pos.yRot += (short)((GetRandomControl() - 0x4000) / 4);
item->requiredAnimState = NATLA_STOP; item->requiredAnimState = NATLA_STOP;
} }

View file

@ -40,7 +40,7 @@ void NatlaEvilControl(short itemNum)
FLOOR_INFO* floor; FLOOR_INFO* floor;
short head, angle; short head, angle;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
abort = (CREATURE_INFO*)item->data; abort = (CREATURE_INFO*)item->data;
head = angle = 0; head = angle = 0;
@ -50,7 +50,7 @@ void NatlaEvilControl(short itemNum)
if (item->currentAnimState != ABORT_DEATH) if (item->currentAnimState != ABORT_DEATH)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + ABORT_DIE_ANIM; item->animNumber = Objects[item->objectNumber].animIndex + ABORT_DIE_ANIM;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = ABORT_DEATH; item->currentAnimState = ABORT_DEATH;
} }
} }
@ -169,7 +169,7 @@ void NatlaEvilControl(short itemNum)
item->goalAnimState = ABORT_KILL; item->goalAnimState = ABORT_KILL;
LaraItem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex; LaraItem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex;
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
LaraItem->currentAnimState = LaraItem->goalAnimState = 46; LaraItem->currentAnimState = LaraItem->goalAnimState = 46;
LaraItem->roomNumber = item->roomNumber; LaraItem->roomNumber = item->roomNumber;
LaraItem->pos.xPos = item->pos.xPos; LaraItem->pos.xPos = item->pos.xPos;

View file

@ -11,7 +11,7 @@ BITE_INFO wolfBite = { 0, -14, 174, 6 };
void InitialiseWolf(short itemNum) void InitialiseWolf(short itemNum)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
ClearItem(itemNum); ClearItem(itemNum);
item->frameNumber = 96; item->frameNumber = 96;
} }
@ -21,7 +21,7 @@ void WolfControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short head = 0; short head = 0;
@ -33,7 +33,7 @@ void WolfControl(short itemNum)
if (item->currentAnimState != 11) if (item->currentAnimState != 11)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 20 + (short)(GetRandomControl() / 11000); item->animNumber = Objects[item->objectNumber].animIndex + 20 + (short)(GetRandomControl() / 11000);
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 11; item->currentAnimState = 11;
} }
} }

View file

@ -18,7 +18,7 @@
#include "setup.h" #include "setup.h"
#include "level.h" #include "level.h"
static void StartBaddy(ObjectInfo* obj) static void StartBaddy(OBJECT_INFO* obj)
{ {
obj = &Objects[ID_WOLF]; obj = &Objects[ID_WOLF];
if (obj->loaded) if (obj->loaded)
@ -36,7 +36,7 @@ static void StartBaddy(ObjectInfo* obj)
obj->saveAnim = true; obj->saveAnim = true;
obj->saveFlags = true; obj->saveFlags = true;
Bones[obj->boneIndex + 2 * 4] |= ROT_Y; g_Level.Bones[obj->boneIndex + 2 * 4] |= ROT_Y;
} }
obj = &Objects[ID_BEAR]; obj = &Objects[ID_BEAR];
@ -55,7 +55,7 @@ static void StartBaddy(ObjectInfo* obj)
obj->saveAnim = true; obj->saveAnim = true;
obj->saveFlags = true; obj->saveFlags = true;
Bones[obj->boneIndex + 13 * 4] |= ROT_Y; g_Level.Bones[obj->boneIndex + 13 * 4] |= ROT_Y;
} }
obj = &Objects[ID_APE]; obj = &Objects[ID_APE];
@ -92,7 +92,7 @@ static void StartBaddy(ObjectInfo* obj)
obj->saveFlags = true; obj->saveFlags = true;
obj->waterCreature = true; // dont want the rat to be killed when going in water ! obj->waterCreature = true; // dont want the rat to be killed when going in water !
obj->zoneType = ZONE_WATER; obj->zoneType = ZONE_WATER;
Bones[obj->boneIndex + 4] |= ROT_Y; g_Level.Bones[obj->boneIndex + 4] |= ROT_Y;
} }
obj = &Objects[ID_NATLA]; obj = &Objects[ID_NATLA];
@ -109,7 +109,7 @@ static void StartBaddy(ObjectInfo* obj)
obj->saveFlags = true; obj->saveFlags = true;
obj->savePosition = true; obj->savePosition = true;
obj->saveHitpoints = true; obj->saveHitpoints = true;
Bones[obj->boneIndex + 2 * 4] |= (ROT_Z | ROT_X); g_Level.Bones[obj->boneIndex + 2 * 4] |= (ROT_Z | ROT_X);
} }
obj = &Objects[ID_WINGED_NATLA]; obj = &Objects[ID_WINGED_NATLA];
@ -126,7 +126,7 @@ static void StartBaddy(ObjectInfo* obj)
obj->saveFlags = true; obj->saveFlags = true;
obj->savePosition = true; obj->savePosition = true;
obj->saveHitpoints = true; obj->saveHitpoints = true;
Bones[obj->boneIndex + 1 * 4] |= ROT_Y; g_Level.Bones[obj->boneIndex + 1 * 4] |= ROT_Y;
} }
obj = &Objects[ID_LARA_DOPPELGANGER]; obj = &Objects[ID_LARA_DOPPELGANGER];
@ -150,17 +150,17 @@ static void StartBaddy(ObjectInfo* obj)
} }
} }
static void StartObject(ObjectInfo* obj) static void StartObject(OBJECT_INFO* obj)
{ {
} }
static void StartTrap(ObjectInfo* obj) static void StartTrap(OBJECT_INFO* obj)
{ {
} }
static ObjectInfo* objToInit; static OBJECT_INFO* objToInit;
void InitialiseTR1Objects() void InitialiseTR1Objects()
{ {
StartBaddy(objToInit); StartBaddy(objToInit);

View file

@ -13,7 +13,7 @@ void BarracudaControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short angle = 0; short angle = 0;
short head = 0; short head = 0;
@ -23,7 +23,7 @@ void BarracudaControl(short itemNum)
if (item->currentAnimState != 6) if (item->currentAnimState != 6)
{ {
item->animNumber = Objects[ID_BARRACUDA].animIndex + 6; item->animNumber = Objects[ID_BARRACUDA].animIndex + 6;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 6; item->currentAnimState = 6;
} }

View file

@ -19,7 +19,7 @@ void BirdMonsterControl(short itemNum)
AI_INFO info; AI_INFO info;
short angle, head; short angle, head;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
monster = (CREATURE_INFO*)item->data; monster = (CREATURE_INFO*)item->data;
angle = head = 0; angle = head = 0;
@ -28,7 +28,7 @@ void BirdMonsterControl(short itemNum)
if (item->currentAnimState != 9) if (item->currentAnimState != 9)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 20; item->animNumber = Objects[item->objectNumber].animIndex + 20;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 9; item->currentAnimState = 9;
} }
} }

View file

@ -61,7 +61,7 @@ enum DRAGON_STATE {
static void createBartoliLight(short ItemIndex, int type) static void createBartoliLight(short ItemIndex, int type)
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[ItemIndex]; item = &g_Level.Items[ItemIndex];
if (type == 0) if (type == 0)
TriggerDynamicLight(item->pos.xPos, item->pos.yPos - STEP_SIZE, item->pos.zPos, (GetRandomControl() & 150) + 25, (GetRandomControl() & 30) + 200, (GetRandomControl() & 25) + 200, (GetRandomControl() & 20) + 200); TriggerDynamicLight(item->pos.xPos, item->pos.yPos - STEP_SIZE, item->pos.zPos, (GetRandomControl() & 150) + 25, (GetRandomControl() & 30) + 200, (GetRandomControl() & 25) + 200, (GetRandomControl() & 20) + 200);
@ -106,7 +106,7 @@ static void createExplosion(ITEM_INFO* item)
ExplIndex = CreateItem(); ExplIndex = CreateItem();
if (ExplIndex != NO_ITEM) if (ExplIndex != NO_ITEM)
{ {
itemExplo = &Items[ExplIndex]; itemExplo = &g_Level.Items[ExplIndex];
if (item->timer == BOOM_TIME) if (item->timer == BOOM_TIME)
itemExplo->objectNumber = ID_SPHERE_OF_DOOM; itemExplo->objectNumber = ID_SPHERE_OF_DOOM;
@ -134,7 +134,7 @@ static void createExplosion(ITEM_INFO* item)
static void createDragonBone(short front_number) static void createDragonBone(short front_number)
{ {
/* Create the bones of the dragon */ /* Create the Bones of the dragon */
short bone_back, bone_front; short bone_back, bone_front;
ITEM_INFO* back_dragon, *front_dragon, *item; ITEM_INFO* back_dragon, *front_dragon, *item;
@ -143,9 +143,9 @@ static void createDragonBone(short front_number)
if (bone_back != NO_ITEM && bone_front != NO_ITEM) if (bone_back != NO_ITEM && bone_front != NO_ITEM)
{ {
item = &Items[front_number]; item = &g_Level.Items[front_number];
back_dragon = &Items[bone_back]; back_dragon = &g_Level.Items[bone_back];
back_dragon->objectNumber = ID_DRAGON_BONE_BACK; back_dragon->objectNumber = ID_DRAGON_BONE_BACK;
back_dragon->pos.xPos = item->pos.xPos; back_dragon->pos.xPos = item->pos.xPos;
back_dragon->pos.yPos = item->pos.yPos; back_dragon->pos.yPos = item->pos.yPos;
@ -156,7 +156,7 @@ static void createDragonBone(short front_number)
InitialiseItem(bone_back); InitialiseItem(bone_back);
front_dragon = &Items[bone_front]; front_dragon = &g_Level.Items[bone_front];
front_dragon->objectNumber = ID_DRAGON_BONE_FRONT; front_dragon->objectNumber = ID_DRAGON_BONE_FRONT;
front_dragon->pos.xPos = item->pos.xPos; front_dragon->pos.xPos = item->pos.xPos;
front_dragon->pos.yPos = item->pos.yPos; front_dragon->pos.yPos = item->pos.yPos;
@ -178,7 +178,7 @@ void DragonCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
int anim, frame; int anim, frame;
/* If Lara has collided with correct bit of dragon, then start him up */ /* If Lara has collided with correct bit of dragon, then start him up */
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
if (!TestBoundsCollide(item, laraitem, coll->radius)) if (!TestBoundsCollide(item, laraitem, coll->radius))
return; return;
@ -205,7 +205,7 @@ void DragonCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
/* Check if in a position to pull dagger from dragon */ /* Check if in a position to pull dagger from dragon */
anim = item->animNumber - Objects[ID_DRAGON_BACK].animIndex; anim = item->animNumber - Objects[ID_DRAGON_BACK].animIndex;
frame = item->frameNumber - Anims[item->animNumber].frameBase; frame = item->frameNumber - g_Level.Anims[item->animNumber].frameBase;
if ((anim == DRAGON_DEAD_ANIM || (anim == DRAGON_DEAD_ANIM + 1 && frame <= DRAGON_ALMOST_LIVE)) && if ((anim == DRAGON_DEAD_ANIM || (anim == DRAGON_DEAD_ANIM + 1 && frame <= DRAGON_ALMOST_LIVE)) &&
(TrInput & IN_ACTION) && item->objectNumber == ID_DRAGON_BACK && !laraitem->gravityStatus && (TrInput & IN_ACTION) && item->objectNumber == ID_DRAGON_BACK && !laraitem->gravityStatus &&
shift <= DRAGON_MID && shift > DRAGON_CLOSE - 350 && side_shift > -350 && side_shift < 350 && shift <= DRAGON_MID && shift > DRAGON_CLOSE - 350 && side_shift > -350 && side_shift < 350 &&
@ -213,7 +213,7 @@ void DragonCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
{ {
/* Jump to animation state in LARA_EXTRA */ /* Jump to animation state in LARA_EXTRA */
laraitem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex; laraitem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex;
laraitem->frameNumber = Anims[laraitem->animNumber].frameBase; laraitem->frameNumber = g_Level.Anims[laraitem->animNumber].frameBase;
laraitem->currentAnimState = 0; laraitem->currentAnimState = 0;
laraitem->goalAnimState = 7; laraitem->goalAnimState = 7;
@ -239,7 +239,8 @@ void DragonCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
Lara.gunStatus = LG_HANDS_BUSY; Lara.gunStatus = LG_HANDS_BUSY;
Lara.hitDirection = -1; Lara.hitDirection = -1;
LARA_MESHES(ID_LARA_EXTRA_ANIMS, LM_RHAND); //LARA_MESHES(ID_LARA_EXTRA_ANIMS, LM_RHAND);
Lara.meshPtrs[LM_RHAND] = Objects[ID_LARA_EXTRA_ANIMS].meshIndex + LM_RHAND;
/* Do cinematic camera */ /* Do cinematic camera */
Camera.type = CINEMATIC_CAMERA; Camera.type = CINEMATIC_CAMERA;
@ -247,7 +248,7 @@ void DragonCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
//memcpy(&CinematicPos, &laraitem->pos, sizeof(PHD_3DPOS)); //memcpy(&CinematicPos, &laraitem->pos, sizeof(PHD_3DPOS));
/* Flag dragon is dead forever */ /* Flag dragon is dead forever */
((CREATURE_INFO*)Items[(short)item->data].data)->flags = -1; ((CREATURE_INFO*)g_Level.Items[(short)item->data].data)->flags = -1;
return; return;
} }
@ -277,7 +278,7 @@ void DragonControl(short backNum)
short head, angle; short head, angle;
short itemNum; short itemNum;
back = &Items[backNum]; back = &g_Level.Items[backNum];
if (back->data != NULL && back->objectNumber == ID_DRAGON_FRONT) // check if data is not null and back is front if (back->data != NULL && back->objectNumber == ID_DRAGON_FRONT) // check if data is not null and back is front
return; return;
@ -285,7 +286,7 @@ void DragonControl(short backNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
dragon = (CREATURE_INFO*)item->data; dragon = (CREATURE_INFO*)item->data;
head = angle = 0; head = angle = 0;
@ -294,7 +295,7 @@ void DragonControl(short backNum)
if (item->currentAnimState != DRAGON_DEATH) if (item->currentAnimState != DRAGON_DEATH)
{ {
item->animNumber = Objects[ID_DRAGON_FRONT].animIndex + 21; item->animNumber = Objects[ID_DRAGON_FRONT].animIndex + 21;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = item->goalAnimState = DRAGON_DEATH; item->currentAnimState = item->goalAnimState = DRAGON_DEATH;
dragon->flags = 0; dragon->flags = 0;
} }
@ -481,7 +482,7 @@ void DragonControl(short backNum)
/* Set back end to same frame */ /* Set back end to same frame */
back->currentAnimState = item->currentAnimState; back->currentAnimState = item->currentAnimState;
back->animNumber = Objects[ID_DRAGON_BACK].animIndex + (item->animNumber - Objects[ID_DRAGON_FRONT].animIndex); back->animNumber = Objects[ID_DRAGON_BACK].animIndex + (item->animNumber - Objects[ID_DRAGON_FRONT].animIndex);
back->frameNumber = Anims[back->animNumber].frameBase + (item->frameNumber - Anims[item->animNumber].frameBase); back->frameNumber = g_Level.Anims[back->animNumber].frameBase + (item->frameNumber - g_Level.Anims[item->animNumber].frameBase);
back->pos.xPos = item->pos.xPos; back->pos.xPos = item->pos.xPos;
back->pos.yPos = item->pos.yPos; back->pos.yPos = item->pos.yPos;
back->pos.zPos = item->pos.zPos; back->pos.zPos = item->pos.zPos;
@ -497,7 +498,7 @@ void InitialiseBartoli(short itemNum)
ITEM_INFO* item, *back, *front; ITEM_INFO* item, *back, *front;
short back_item, front_item; short back_item, front_item;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
item->pos.xPos -= STEP_SIZE * 2; item->pos.xPos -= STEP_SIZE * 2;
item->pos.zPos -= STEP_SIZE * 2; item->pos.zPos -= STEP_SIZE * 2;
@ -506,7 +507,7 @@ void InitialiseBartoli(short itemNum)
front_item = CreateItem(); front_item = CreateItem();
if (back_item != NO_ITEM && front_item != NO_ITEM) if (back_item != NO_ITEM && front_item != NO_ITEM)
{ {
back = &Items[back_item]; back = &g_Level.Items[back_item];
back->objectNumber = ID_DRAGON_BACK; back->objectNumber = ID_DRAGON_BACK;
back->pos.xPos = item->pos.xPos; back->pos.xPos = item->pos.xPos;
back->pos.yPos = item->pos.yPos; back->pos.yPos = item->pos.yPos;
@ -521,7 +522,7 @@ void InitialiseBartoli(short itemNum)
item->data = (void*)back_item; // Bartoli points at back of dragon item->data = (void*)back_item; // Bartoli points at back of dragon
front = &Items[front_item]; front = &g_Level.Items[front_item];
front->objectNumber = ID_DRAGON_FRONT; front->objectNumber = ID_DRAGON_FRONT;
front->pos.xPos = item->pos.xPos; front->pos.xPos = item->pos.xPos;
front->pos.yPos = item->pos.yPos; front->pos.yPos = item->pos.yPos;
@ -535,7 +536,7 @@ void InitialiseBartoli(short itemNum)
back->data = (void*)front_item; // back of dragon points at front back->data = (void*)front_item; // back of dragon points at front
LevelItems += 2; g_Level.NumItems += 2;
} }
} }
@ -544,7 +545,7 @@ void BartoliControl(short itemNum)
ITEM_INFO* item, *back, *front; ITEM_INFO* item, *back, *front;
short front_item, back_item; short front_item, back_item;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
if (item->timer) if (item->timer)
{ {
@ -561,7 +562,7 @@ void BartoliControl(short itemNum)
front_item = CreateItem(); front_item = CreateItem();
if (front_item != NO_ITEM) if (front_item != NO_ITEM)
{ {
front = &Items[front_item]; front = &g_Level.Items[front_item];
if (item->timer == BOOM_TIME) if (item->timer == BOOM_TIME)
front->objectNumber = ID_SPHERE_OF_DOOM; front->objectNumber = ID_SPHERE_OF_DOOM;
else if (item->timer == BOOM_TIME + 10) else if (item->timer == BOOM_TIME + 10)
@ -582,10 +583,10 @@ void BartoliControl(short itemNum)
{ {
/* Convert Bartoli into a dragon */ /* Convert Bartoli into a dragon */
back_item = (short)item->data; back_item = (short)item->data;
back = &Items[back_item]; back = &g_Level.Items[back_item];
front_item = (short)back->data; front_item = (short)back->data;
front = &Items[front_item]; front = &g_Level.Items[front_item];
front->touchBits = back->touchBits = 0; front->touchBits = back->touchBits = 0;
EnableBaddieAI(front_item, 1); EnableBaddieAI(front_item, 1);

View file

@ -12,19 +12,19 @@ BITE_INFO crowBite = { 2, 10, 60, 14 };
void InitialiseEagle(short itemNum) void InitialiseEagle(short itemNum)
{ {
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
ClearItem(itemNum); ClearItem(itemNum);
if (item->objectNumber == ID_CROW) if (item->objectNumber == ID_CROW)
{ {
item->animNumber = Objects[ID_CROW].animIndex + 14; item->animNumber = Objects[ID_CROW].animIndex + 14;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = item->goalAnimState = 7; item->currentAnimState = item->goalAnimState = 7;
} }
else else
{ {
item->animNumber = Objects[ID_EAGLE].animIndex + 5; item->animNumber = Objects[ID_EAGLE].animIndex + 5;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = item->goalAnimState = 2; item->currentAnimState = item->goalAnimState = 2;
} }
} }
@ -34,7 +34,7 @@ void EagleControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short angle = 0; short angle = 0;
@ -63,7 +63,7 @@ void EagleControl(short itemNum)
else else
item->animNumber = Objects[ID_EAGLE].animIndex + 8; item->animNumber = Objects[ID_EAGLE].animIndex + 8;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 4; item->currentAnimState = 4;
item->gravityStatus = 1; item->gravityStatus = 1;
item->speed = 0; item->speed = 0;

View file

@ -19,7 +19,7 @@ void KnifeControl(short fxNum)
short roomNumber; short roomNumber;
FLOOR_INFO* floor; FLOOR_INFO* floor;
fx = &Effects[fxNum]; fx = &EffectList[fxNum];
if (fx->counter <= 0) if (fx->counter <= 0)
{ {
@ -107,7 +107,7 @@ void KnifethrowerControl(short itemNum)
AI_INFO info; AI_INFO info;
short angle, torso, head, tilt; short angle, torso, head, tilt;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
knife = (CREATURE_INFO*)item->data; knife = (CREATURE_INFO*)item->data;
angle = torso = head = tilt = 0; angle = torso = head = tilt = 0;
@ -116,7 +116,7 @@ void KnifethrowerControl(short itemNum)
if (item->currentAnimState != 10) if (item->currentAnimState != 10)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 23; item->animNumber = Objects[item->objectNumber].animIndex + 23;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 10; item->currentAnimState = 10;
} }
} }

View file

@ -20,7 +20,7 @@ void MercenaryUziControl(short itemNum)
AI_INFO info; AI_INFO info;
short angle, head_y, head_x, torso_y, torso_x, tilt; short angle, head_y, head_x, torso_y, torso_x, tilt;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
mc1 = (CREATURE_INFO*)item->data; mc1 = (CREATURE_INFO*)item->data;
angle = head_y = head_x = torso_y = torso_x = tilt = 0; angle = head_y = head_x = torso_y = torso_x = tilt = 0;
@ -29,7 +29,7 @@ void MercenaryUziControl(short itemNum)
if (item->currentAnimState != 13) if (item->currentAnimState != 13)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 14; item->animNumber = Objects[item->objectNumber].animIndex + 14;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 13; item->currentAnimState = 13;
} }
} }
@ -209,7 +209,7 @@ void MercenaryAutoPistolControl(short itemNum)
AI_INFO info; AI_INFO info;
short angle, head_y, head_x, torso_y, torso_x, tilt; short angle, head_y, head_x, torso_y, torso_x, tilt;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
mc2 = (CREATURE_INFO*)item->data; mc2 = (CREATURE_INFO*)item->data;
angle = head_y = head_x = torso_y = torso_x = tilt = 0; angle = head_y = head_x = torso_y = torso_x = tilt = 0;
@ -218,7 +218,7 @@ void MercenaryAutoPistolControl(short itemNum)
if (item->currentAnimState != 11) if (item->currentAnimState != 11)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 9; item->animNumber = Objects[item->objectNumber].animIndex + 9;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 11; item->currentAnimState = 11;
} }
} }

View file

@ -22,7 +22,7 @@ void MonkControl(short itemNum)
AI_INFO info; AI_INFO info;
int random; int random;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
monk = (CREATURE_INFO*)item->data; monk = (CREATURE_INFO*)item->data;
torso = angle = tilt = 0; torso = angle = tilt = 0;
@ -31,7 +31,7 @@ void MonkControl(short itemNum)
if (item->currentAnimState != 9) if (item->currentAnimState != 9)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 20 + (GetRandomControl() / 0x4000); item->animNumber = Objects[item->objectNumber].animIndex + 20 + (GetRandomControl() / 0x4000);
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 9; item->currentAnimState = 9;
} }
} }

View file

@ -13,7 +13,7 @@ void RatControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short head = 0; short head = 0;
short angle = 0; short angle = 0;
@ -24,7 +24,7 @@ void RatControl(short itemNum)
if (item->currentAnimState != 6) if (item->currentAnimState != 6)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 9; item->animNumber = Objects[item->objectNumber].animIndex + 9;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 6; item->currentAnimState = 6;
} }
} }

View file

@ -13,7 +13,7 @@ void SharkControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data; CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short angle = 0; short angle = 0;
short head = 0; short head = 0;
@ -23,7 +23,7 @@ void SharkControl(short itemNum)
if (item->currentAnimState != 5) if (item->currentAnimState != 5)
{ {
item->animNumber = Objects[ID_SHARK].animIndex + 4; item->animNumber = Objects[ID_SHARK].animIndex + 4;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 5; item->currentAnimState = 5;
} }
CreatureFloat(itemNum); CreatureFloat(itemNum);

View file

@ -13,7 +13,7 @@ void SilencerControl(short itemNum)
if (!CreatureActive(itemNum)) if (!CreatureActive(itemNum))
return; return;
ITEM_INFO* item = &Items[itemNum]; ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* silencer = (CREATURE_INFO*)item->data; CREATURE_INFO* silencer = (CREATURE_INFO*)item->data;
AI_INFO info; AI_INFO info;
short angle = 0, torso_y = 0, torso_x = 0, head_y = 0, tilt = 0; short angle = 0, torso_y = 0, torso_x = 0, head_y = 0, tilt = 0;
@ -23,7 +23,7 @@ void SilencerControl(short itemNum)
if (item->currentAnimState != 12 && item->currentAnimState != 13) if (item->currentAnimState != 12 && item->currentAnimState != 13)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 20; // die 21 is for heavy weapon. item->animNumber = Objects[item->objectNumber].animIndex + 20; // die 21 is for heavy weapon.
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 13; item->currentAnimState = 13;
} }
} }

View file

@ -30,8 +30,8 @@ void InitialiseSkidman(short itemNum)
skidoo_item = CreateItem(); skidoo_item = CreateItem();
if (skidoo_item != NO_ITEM) if (skidoo_item != NO_ITEM)
{ {
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
skidoo = &Items[skidoo_item]; skidoo = &g_Level.Items[skidoo_item];
skidoo->objectNumber = ID_SNOWMOBILE_GUN; skidoo->objectNumber = ID_SNOWMOBILE_GUN;
skidoo->pos.xPos = item->pos.xPos; skidoo->pos.xPos = item->pos.xPos;
skidoo->pos.yPos = item->pos.yPos; skidoo->pos.yPos = item->pos.yPos;
@ -46,7 +46,7 @@ void InitialiseSkidman(short itemNum)
// The skidman remembers his skidoo // The skidman remembers his skidoo
item->data = (void*)skidoo_item; item->data = (void*)skidoo_item;
LevelItems++; g_Level.NumItems++;
} }
else else
{ {
@ -58,7 +58,7 @@ void SkidManCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
{ {
ITEM_INFO* item; ITEM_INFO* item;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
if (!TestBoundsCollide(item, laraitem, coll->radius)) if (!TestBoundsCollide(item, laraitem, coll->radius))
return; return;
if (!TestCollision(item, laraitem)) if (!TestCollision(item, laraitem))
@ -88,7 +88,7 @@ void SkidManControl(short riderNum)
short angle, item_number; short angle, item_number;
int damage; int damage;
rider = &Items[riderNum]; rider = &g_Level.Items[riderNum];
if (rider->data == NULL) if (rider->data == NULL)
{ {
printf("FATAL: rider data not contains the skidoo itemNumber !"); printf("FATAL: rider data not contains the skidoo itemNumber !");
@ -96,7 +96,7 @@ void SkidManControl(short riderNum)
} }
item_number = (short)rider->data; item_number = (short)rider->data;
item = &Items[item_number]; item = &g_Level.Items[item_number];
/* Need to activate AI for skidoo (it's the skidoo that holds the brain) if not done yet */ /* Need to activate AI for skidoo (it's the skidoo that holds the brain) if not done yet */
if (!item->data) if (!item->data)
@ -120,7 +120,7 @@ void SkidManControl(short riderNum)
rider->roomNumber = item->roomNumber; rider->roomNumber = item->roomNumber;
rider->animNumber = Objects[ID_SNOWMOBILE_DRIVER].animIndex + SMAN_DEATH_ANIM; rider->animNumber = Objects[ID_SNOWMOBILE_DRIVER].animIndex + SMAN_DEATH_ANIM;
rider->frameNumber = Anims[rider->animNumber].frameBase; rider->frameNumber = g_Level.Anims[rider->animNumber].frameBase;
rider->currentAnimState = SMAN_DEATH; rider->currentAnimState = SMAN_DEATH;
/* Break Lara's lock */ /* Break Lara's lock */
@ -230,7 +230,7 @@ void SkidManControl(short riderNum)
ItemNewRoom(riderNum, item->roomNumber); ItemNewRoom(riderNum, item->roomNumber);
rider->animNumber = item->animNumber + (Objects[ID_SNOWMOBILE_DRIVER].animIndex - Objects[ID_SNOWMOBILE_GUN].animIndex); rider->animNumber = item->animNumber + (Objects[ID_SNOWMOBILE_DRIVER].animIndex - Objects[ID_SNOWMOBILE_GUN].animIndex);
rider->frameNumber = item->frameNumber + (Anims[rider->animNumber].frameBase - Anims[item->animNumber].frameBase); rider->frameNumber = item->frameNumber + (g_Level.Anims[rider->animNumber].frameBase - g_Level.Anims[item->animNumber].frameBase);
} }
else if (rider->status == ITEM_DEACTIVATED && item->speed == 0 && item->fallspeed == 0) else if (rider->status == ITEM_DEACTIVATED && item->speed == 0 && item->fallspeed == 0)
{ {

View file

@ -39,10 +39,10 @@ void InitialiseSpearGuardian(short itemNum)
ClearItem(itemNum); ClearItem(itemNum);
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
item->animNumber = Objects[item->objectNumber].animIndex + 48; item->animNumber = Objects[item->objectNumber].animIndex + 48;
anim = &Anims[item->animNumber]; anim = &g_Level.Anims[item->animNumber];
item->frameNumber = anim->frameBase; item->frameNumber = anim->frameBase;
item->currentAnimState = anim->currentAnimState; item->currentAnimState = anim->currentAnimState;
@ -62,7 +62,7 @@ void SpearGuardianControl(short itemNum)
int random, lara_alive; int random, lara_alive;
AI_INFO info; AI_INFO info;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
xian = (CREATURE_INFO*)item->data; xian = (CREATURE_INFO*)item->data;
head = neck = angle = tilt = 0; head = neck = angle = tilt = 0;
lara_alive = (LaraItem->hitPoints > 0); lara_alive = (LaraItem->hitPoints > 0);

View file

@ -47,7 +47,7 @@ static void SpiderLeap(short itemNum, ITEM_INFO* item, short angle)
ItemNewRoom(item->roomNumber, vec.roomNumber); ItemNewRoom(item->roomNumber, vec.roomNumber);
item->animNumber = Objects[item->objectNumber].animIndex + 2; item->animNumber = Objects[item->objectNumber].animIndex + 2;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 5; item->currentAnimState = 5;
CreatureAnimation(itemNum, angle, 0); CreatureAnimation(itemNum, angle, 0);
@ -63,7 +63,7 @@ void SmallSpiderControl(short itemNum)
AI_INFO info; AI_INFO info;
short angle; short angle;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
spider = (CREATURE_INFO*)item->data; spider = (CREATURE_INFO*)item->data;
angle = 0; angle = 0;
@ -168,7 +168,7 @@ void BigSpiderControl(short itemNum)
AI_INFO info; AI_INFO info;
short angle; short angle;
item = &Items[itemNum]; item = &g_Level.Items[itemNum];
spider = (CREATURE_INFO*)item->data; spider = (CREATURE_INFO*)item->data;
angle = 0; angle = 0;
@ -177,7 +177,7 @@ void BigSpiderControl(short itemNum)
if (item->currentAnimState != 7) if (item->currentAnimState != 7)
{ {
item->animNumber = Objects[item->objectNumber].animIndex + 2; item->animNumber = Objects[item->objectNumber].animIndex + 2;
item->frameNumber = Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = 7; item->currentAnimState = 7;
} }
} }

Some files were not shown because too many files have changed in this diff Show more