2019-12-22 00:20:10 +01:00
|
|
|
#include "tomb4fx.h"
|
|
|
|
#include "../Global/global.h"
|
|
|
|
#include "lara.h"
|
|
|
|
#include "effect2.h"
|
|
|
|
#include "draw.h"
|
|
|
|
#include "items.h"
|
|
|
|
|
|
|
|
char FlareTable[121] =
|
|
|
|
{
|
|
|
|
0x60, 0x50, 0x00, 0x06, 0x00, 0x1F, 0x30, 0x20, 0x20, 0x0A, 0xFA, 0x1F, 0x20, 0x18,
|
|
|
|
0x18, 0x12, 0xFF, 0x1F, 0x50, 0x68, 0x40, 0x05, 0xFD, 0x1E, 0x40, 0x40, 0x40, 0x14,
|
|
|
|
0x00, 0x20, 0x60, 0x38, 0x38, 0x0E, 0x00, 0x0B, 0x50, 0x28, 0x20, 0x09, 0x00, 0x1D,
|
|
|
|
0x10, 0x18, 0x28, 0x02, 0x05, 0x1F, 0x08, 0x08, 0x18, 0x07, 0x08, 0x1F, 0x08, 0x10,
|
|
|
|
0x20, 0x04, 0x0A, 0x1F, 0x30, 0x18, 0x00, 0x02, 0x0D, 0x1F, 0x28, 0x60, 0x48, 0x01,
|
|
|
|
0x10, 0x0B, 0x28, 0x60, 0x48, 0x03, 0x14, 0x0B, 0x20, 0x10, 0x00, 0x06, 0x16, 0x1F,
|
|
|
|
0x20, 0x10, 0x00, 0x09, 0x17, 0x1E, 0x20, 0x10, 0x00, 0x03, 0x18, 0x1F, 0x20, 0x30,
|
|
|
|
0x18, 0x04, 0x1A, 0x1F, 0x08, 0x28, 0x70, 0x03, 0x1B, 0x0B, 0x08, 0x10, 0x00, 0x0A,
|
|
|
|
0x1D, 0x1E, 0x10, 0x10, 0x18, 0x11, 0x1F, 0x1D, 0xFF
|
|
|
|
};
|
|
|
|
|
|
|
|
char LaserSightActive = 0;
|
|
|
|
char LaserSightCol = 0;
|
|
|
|
int NextGunshell = 0;
|
|
|
|
|
|
|
|
NODEOFFSET_INFO NodeOffsets[16] = // offset 0xA0A24
|
|
|
|
{
|
|
|
|
{ -0x10, 0x28, 0xA0, -0xE, 0 },
|
|
|
|
{ -0x10, -8, 0xA0, 0, 0 },
|
|
|
|
{ 0, 0, 0x100, 8, 0 },
|
|
|
|
{ 0, 0, 0x100, 0x11, 0 },
|
|
|
|
{ 0, 0, 0x100, 0x1A, 0 },
|
|
|
|
{ 0, 0x90, 0x28, 0xA, 0 },
|
|
|
|
{ -0x28, 0x40, 0x168, 0xE, 0 },
|
|
|
|
{ 0, -0x258, -0x28, 0, 0 },
|
|
|
|
{ 0, 0x20, 0x10, 9, 0 },
|
|
|
|
{ 0 },
|
|
|
|
{ 0 },
|
|
|
|
{ 0 },
|
|
|
|
{ 0 },
|
|
|
|
{ 0 },
|
|
|
|
{ 0 },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
int LaserSightX;
|
|
|
|
int LaserSightY;
|
|
|
|
int LaserSightZ;
|
|
|
|
|
|
|
|
int NextFireSpark = 1;
|
|
|
|
int NextSmokeSpark = 0;
|
|
|
|
int NextBubble = 0;
|
|
|
|
int NextDrip = 0;
|
|
|
|
int NextBlood = 0;
|
|
|
|
int NextSpider = 0;
|
|
|
|
int NextGunShell = 0;
|
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
GUNFLASH_STRUCT Gunflashes[MAX_GUNFLASH];
|
|
|
|
PHD_VECTOR NodeVectors[16];
|
|
|
|
FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE];
|
|
|
|
SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE];
|
|
|
|
GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL];
|
|
|
|
BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD];
|
|
|
|
BUBBLE_STRUCT Bubbles[MAX_BUBBLES];
|
|
|
|
DRIP_STRUCT Drips[MAX_DRIPS];
|
|
|
|
SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE];
|
|
|
|
FIRE_LIST Fires[MAX_FIRE_LIST];
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
extern int NextSpark;
|
2019-12-26 19:19:20 +01:00
|
|
|
extern SPARKS Sparks[MAX_SPARKS];
|
2019-12-26 08:00:45 +01:00
|
|
|
extern Renderer11* g_Renderer;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
int GetFreeFireSpark()
|
|
|
|
{
|
|
|
|
int sparkNum = NextFireSpark;
|
|
|
|
int minIndex = 0;
|
|
|
|
int minLife = 4095;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
FIRE_SPARKS* spark = &FireSparks[NextFireSpark];
|
|
|
|
while (spark->on)
|
|
|
|
{
|
|
|
|
if (spark->life < minLife)
|
|
|
|
{
|
|
|
|
minIndex = sparkNum;
|
|
|
|
minLife = spark->life;
|
|
|
|
}
|
2019-12-27 10:50:59 +01:00
|
|
|
if (sparkNum == MAX_SPARKS_FIRE - 1)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
spark = &FireSparks[1];
|
|
|
|
sparkNum = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sparkNum++;
|
|
|
|
spark++;
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++i >= MAX_SPARKS_FIRE)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
NextFireSpark = minIndex + 1;
|
2019-12-26 19:19:20 +01:00
|
|
|
if (NextFireSpark >= MAX_SPARKS_FIRE)
|
2019-12-22 00:20:10 +01:00
|
|
|
NextFireSpark = 1;
|
|
|
|
return minIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NextFireSpark = sparkNum + 1;
|
2019-12-26 19:19:20 +01:00
|
|
|
if (sparkNum + 1 >= MAX_SPARKS_FIRE)
|
2019-12-22 00:20:10 +01:00
|
|
|
NextFireSpark = 1;
|
|
|
|
|
|
|
|
return sparkNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerGlobalStaticFlame()
|
|
|
|
{
|
2019-12-22 07:35:22 +01:00
|
|
|
FIRE_SPARKS* spark = &FireSparks[0];
|
|
|
|
|
|
|
|
spark->on = true;
|
|
|
|
spark->dR = spark->sR = (GetRandomControl() & 0x3F) - 64;
|
|
|
|
spark->dB = 64;
|
|
|
|
spark->sB = 64;
|
|
|
|
spark->dG = (GetRandomControl() & 0x3F) + 96;
|
|
|
|
spark->sG = (GetRandomControl() & 0x3F) + 96;
|
|
|
|
spark->colFadeSpeed = 1;
|
|
|
|
spark->fadeToBlack = 0;
|
|
|
|
spark->life = 8;
|
|
|
|
spark->sLife = 8;
|
|
|
|
spark->y = 0;
|
|
|
|
spark->x = (GetRandomControl() & 7) - 4;
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
spark->gravity = 0;
|
|
|
|
spark->z = (GetRandomControl() & 7) - 4;
|
|
|
|
spark->friction = 0;
|
|
|
|
spark->xVel = 0;
|
|
|
|
spark->yVel = 0;
|
|
|
|
spark->zVel = 0;
|
|
|
|
spark->flags = 0;
|
|
|
|
spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 0x1F) + -128;
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerGlobalFireSmoke()
|
|
|
|
{
|
|
|
|
FIRE_SPARKS* spark = &FireSparks[GetFreeFireSpark()];
|
|
|
|
|
|
|
|
spark->on = 1;
|
|
|
|
spark->sR = 0;
|
|
|
|
spark->sG = 0;
|
|
|
|
spark->sB = 0;
|
|
|
|
spark->dR = 32;
|
|
|
|
spark->dG = 32;
|
|
|
|
spark->dB = 32;
|
|
|
|
spark->fadeToBlack = 16;
|
|
|
|
spark->colFadeSpeed = (GetRandomControl() & 7) + 32;
|
|
|
|
spark->life = spark->sLife = (GetRandomControl() & 0xF) + 57;
|
|
|
|
spark->x = (GetRandomControl() & 0xF) - 8;
|
|
|
|
spark->y = -256 - (GetRandomControl() & 0x7F);
|
|
|
|
spark->z = (GetRandomControl() & 0xF) - 8;
|
2019-12-22 07:35:22 +01:00
|
|
|
spark->xVel = (GetRandomControl() & 0xFF) - 128;
|
2019-12-22 00:20:10 +01:00
|
|
|
spark->yVel = -16 - (GetRandomControl() & 0xF);
|
2019-12-22 07:35:22 +01:00
|
|
|
spark->zVel = (GetRandomControl() & 0xFF) - 128;
|
2019-12-22 00:20:10 +01:00
|
|
|
spark->friction = 4;
|
|
|
|
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
{
|
|
|
|
spark->flags = 16;
|
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
spark->rotAdd = -16 - (GetRandomControl() & 0xF);
|
|
|
|
else
|
|
|
|
spark->rotAdd = (GetRandomControl() & 0xF) + 16;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->flags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
spark->gravity = -16 - (GetRandomControl() & 0xF);
|
|
|
|
spark->maxYvel = -8 - (GetRandomControl() & 7);
|
|
|
|
spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 0x7F) + 128;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerGlobalFireFlame()
|
|
|
|
{
|
|
|
|
FIRE_SPARKS* spark = &FireSparks[GetFreeFireSpark()];
|
|
|
|
|
2019-12-22 07:35:22 +01:00
|
|
|
spark->on = true;
|
|
|
|
spark->sR = 255;
|
2019-12-22 00:20:10 +01:00
|
|
|
spark->sB = 48;
|
|
|
|
spark->sG = (GetRandomControl() & 0x1F) + 48;
|
|
|
|
spark->dR = (GetRandomControl() & 0x3F) - 64;
|
|
|
|
spark->dB = 32;
|
|
|
|
spark->dG = (GetRandomControl() & 0x3F) + -128;
|
|
|
|
spark->fadeToBlack = 8;
|
|
|
|
spark->colFadeSpeed = (GetRandomControl() & 3) + 8;
|
|
|
|
spark->life = spark->sLife = (GetRandomControl() & 7) + 32;
|
|
|
|
spark->y = 0;
|
|
|
|
spark->x = 4 * (GetRandomControl() & 0x1F) - 64;
|
|
|
|
spark->z = 4 * (GetRandomControl() & 0x1F) - 64;
|
2019-12-22 07:35:22 +01:00
|
|
|
spark->xVel = 2 * (GetRandomControl() & 0xFF) - 256;
|
2019-12-22 00:20:10 +01:00
|
|
|
spark->yVel = -16 - (GetRandomControl() & 0xF);
|
2019-12-22 07:35:22 +01:00
|
|
|
spark->zVel = 2 * (GetRandomControl() & 0xFF) - 256;
|
2019-12-22 00:20:10 +01:00
|
|
|
spark->friction = 5;
|
|
|
|
spark->gravity = -32 - (GetRandomControl() & 0x1F);
|
|
|
|
spark->maxYvel = -16 - (GetRandomControl() & 7);
|
|
|
|
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
{
|
|
|
|
spark->flags = 16;
|
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
spark->rotAdd = -16 - (GetRandomControl() & 0xF);
|
|
|
|
else
|
|
|
|
spark->rotAdd = (GetRandomControl() & 0xF) + 16;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->flags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
spark->sSize = spark->size = (GetRandomControl() & 0x1F) + 128;
|
|
|
|
spark->dSize = spark->size >> 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
void keep_those_fires_burning()
|
|
|
|
{
|
|
|
|
TriggerGlobalStaticFlame();
|
|
|
|
if (!(Wibble & 0xF))
|
|
|
|
{
|
|
|
|
TriggerGlobalFireFlame();
|
|
|
|
if (!(Wibble & 0x1F))
|
|
|
|
TriggerGlobalFireSmoke();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddFire(int x, int y, int z, char size, short roomNum, short on)
|
|
|
|
{
|
|
|
|
FIRE_LIST* fptr = &Fires[0];
|
|
|
|
int i = 0;
|
|
|
|
while (fptr->on)
|
|
|
|
{
|
|
|
|
fptr++;
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++i >= MAX_FIRE_LIST)
|
2019-12-22 00:20:10 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (on)
|
|
|
|
fptr->on = on;
|
|
|
|
else
|
|
|
|
fptr->on = true;
|
|
|
|
|
|
|
|
fptr->x = x;
|
|
|
|
fptr->y = y;
|
|
|
|
fptr->z = z;
|
|
|
|
fptr->size = size;
|
|
|
|
fptr->roomNumber = roomNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearFires()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_FIRE_LIST; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
Fires[i].on = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateFireSparks()
|
|
|
|
{
|
|
|
|
keep_those_fires_burning();
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_SPARKS_FIRE; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
FIRE_SPARKS* spark = &FireSparks[i];
|
|
|
|
|
|
|
|
if (spark->on)
|
|
|
|
{
|
|
|
|
spark->life--;
|
|
|
|
|
|
|
|
if (!spark->life)
|
|
|
|
{
|
|
|
|
spark->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spark->sLife - spark->life < spark->colFadeSpeed)
|
|
|
|
{
|
|
|
|
int dl = ((spark->sLife - spark->life) << 16) / spark->colFadeSpeed;
|
|
|
|
|
|
|
|
spark->r = spark->sR + (dl * (spark->dR - spark->sR) >> 16);
|
|
|
|
spark->g = spark->sG + (dl * (spark->dG - spark->sG) >> 16);
|
|
|
|
spark->b = spark->sB + (dl * (spark->dB - spark->sB) >> 16);
|
|
|
|
}
|
|
|
|
else if (spark->life >= spark->fadeToBlack)
|
|
|
|
{
|
|
|
|
spark->r = spark->dR;
|
|
|
|
spark->g = spark->dG;
|
|
|
|
spark->b = spark->dB;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int dl = ((spark->life - spark->fadeToBlack) << 16) / spark->fadeToBlack + 0x10000;
|
|
|
|
|
|
|
|
spark->r = dl * spark->dR >> 16;
|
|
|
|
spark->g = dl * spark->dG >> 16;
|
|
|
|
spark->b = dl * spark->dB >> 16;
|
|
|
|
|
2019-12-22 07:35:22 +01:00
|
|
|
if (spark->r < 8 && spark->g < 8 && spark->b < 8)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
spark->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spark->flags & SP_ROTATE)
|
|
|
|
spark->rotAng = (spark->rotAng + spark->rotAdd) & 0xFFF;
|
|
|
|
|
|
|
|
if (spark->r >= 24 || spark->g >= 24 || spark->b >= 24)
|
|
|
|
{
|
|
|
|
if (spark->r >= 80 || spark->g >= 80 || spark->b >= 80)
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex;
|
|
|
|
else
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dl = ((spark->sLife - spark->life) << 16) / spark->sLife;
|
|
|
|
spark->yVel += spark->gravity;
|
|
|
|
if (spark->maxYvel)
|
|
|
|
{
|
|
|
|
if ((spark->yVel < 0 && spark->yVel < (spark->maxYvel << 5)) ||
|
|
|
|
(spark->yVel > 0 && spark->yVel > (spark->maxYvel << 5)))
|
|
|
|
spark->yVel = spark->maxYvel << 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spark->friction)
|
|
|
|
{
|
|
|
|
spark->xVel -= spark->xVel >> spark->friction;
|
|
|
|
spark->zVel -= spark->zVel >> spark->friction;
|
|
|
|
}
|
|
|
|
|
|
|
|
spark->x += spark->xVel >> 5;
|
|
|
|
spark->y += spark->yVel >> 5;
|
|
|
|
spark->z += spark->zVel >> 5;
|
|
|
|
|
|
|
|
spark->size = spark->sSize + (dl * (spark->dSize - spark->sSize) >> 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
int GetFreeSmokeSpark()
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
SMOKE_SPARKS* spark = &SmokeSparks[NextSmokeSpark];
|
|
|
|
int sparkNum = NextSmokeSpark;
|
|
|
|
short minLife = 4095;
|
|
|
|
short minIndex = 0;
|
|
|
|
short count = 0;
|
|
|
|
while (spark->on)
|
|
|
|
{
|
|
|
|
if (spark->life < minLife)
|
|
|
|
{
|
|
|
|
minIndex = sparkNum;
|
|
|
|
minLife = spark->life;
|
|
|
|
}
|
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
if (sparkNum == MAX_SPARKS_SMOKE - 1)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
spark = &SmokeSparks[0];
|
|
|
|
sparkNum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sparkNum++;
|
|
|
|
spark++;
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++count >= MAX_SPARKS_SMOKE)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
NextSmokeSpark = (minIndex + 1) % MAX_SPARKS_SMOKE;
|
2019-12-22 00:20:10 +01:00
|
|
|
return minIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
NextSmokeSpark = (sparkNum + 1) % MAX_SPARKS_SMOKE;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
return sparkNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateSmoke()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_SPARKS_SMOKE; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
SMOKE_SPARKS* spark = &SmokeSparks[i];
|
|
|
|
|
|
|
|
if (spark->on)
|
|
|
|
{
|
2019-12-27 10:50:59 +01:00
|
|
|
spark->life -= 2;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
if (spark->life <= 0)
|
|
|
|
{
|
|
|
|
spark->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spark->sLife - spark->life >= spark->colFadeSpeed)
|
|
|
|
{
|
|
|
|
if (spark->life >= spark->fadeToBlack)
|
|
|
|
{
|
|
|
|
spark->shade = spark->dShade;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->shade = spark->dShade * (((spark->life - spark->fadeToBlack) << 16) / spark->fadeToBlack + 0x10000) >> 16;
|
|
|
|
if (spark->shade < 8)
|
|
|
|
{
|
|
|
|
spark->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->shade = spark->sShade + ((spark->dShade - spark->sShade) * (((spark->sLife - spark->life) << 16) / spark->colFadeSpeed) >> 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spark->shade >= 24)
|
|
|
|
{
|
|
|
|
if (spark->shade >= 80)
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex;
|
|
|
|
else
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spark->flags & SP_ROTATE)
|
|
|
|
spark->rotAng = (spark->rotAng + spark->rotAdd) & 0xFFF;
|
|
|
|
|
|
|
|
int dl = ((spark->sLife - spark->life) << 16) / spark->sLife;
|
|
|
|
|
2019-12-28 00:12:38 +01:00
|
|
|
spark->yVel -= spark->gravity.to_float();
|
|
|
|
|
|
|
|
if (spark->maxYvel != 0)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
2019-12-28 00:12:38 +01:00
|
|
|
if (spark->yVel < 0) {
|
|
|
|
if (-spark->yVel.to_float() > (spark->maxYvel)) {
|
|
|
|
spark->yVel = -spark->maxYvel.to_float();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (spark->yVel.to_float() > (spark->maxYvel)) {
|
|
|
|
spark->yVel = spark->maxYvel.to_float();
|
|
|
|
}
|
|
|
|
}
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
|
2019-12-28 00:12:38 +01:00
|
|
|
spark->xVel -= spark->xVel * spark->friction.to_float();
|
|
|
|
spark->zVel -= spark->zVel * spark->friction.to_float();
|
|
|
|
spark->yVel -= spark->yVel * spark->friction.to_float();
|
|
|
|
spark->x += spark->xVel.to_float();
|
|
|
|
spark->y += spark->yVel.to_float();
|
|
|
|
spark->z += spark->zVel.to_float();
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
if (spark->flags & SP_WIND)
|
|
|
|
{
|
|
|
|
spark->x += SmokeWindX >> 1;
|
2019-12-29 14:23:39 +01:00
|
|
|
spark->z += SmokeWindZ>>1;
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
spark->size = spark->sSize + (dl * (spark->dSize - spark->sSize) >> 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
byte TriggerGunSmoke_SubFunction(int weaponType)
|
|
|
|
{
|
|
|
|
switch (weaponType)
|
|
|
|
{
|
|
|
|
case WEAPON_HK:
|
|
|
|
case WEAPON_ROCKET_LAUNCHER:
|
|
|
|
case WEAPON_GRENADE_LAUNCHER:
|
|
|
|
return 0x18; //(12) Rocket and Grenade value for TriggerGunSmoke in TR3 have the value 12 ! (the HK is not included there)
|
|
|
|
|
|
|
|
// other weapon
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte initial, int weaponType, byte count)
|
|
|
|
{
|
|
|
|
SMOKE_SPARKS* spark;
|
2019-12-27 10:50:59 +01:00
|
|
|
|
2019-12-22 00:20:10 +01:00
|
|
|
spark = &SmokeSparks[GetFreeSmokeSpark()];
|
|
|
|
spark->on = true;
|
|
|
|
spark->sShade = 0;
|
|
|
|
spark->dShade = (count << 2);
|
|
|
|
spark->colFadeSpeed = 4;
|
|
|
|
spark->fadeToBlack = 32 - (initial << 4);
|
|
|
|
spark->life = (GetRandomControl() & 3) + 40;
|
|
|
|
spark->sLife = spark->life;
|
|
|
|
|
|
|
|
if (weaponType == WEAPON_PISTOLS || weaponType == WEAPON_REVOLVER || weaponType == WEAPON_UZI)
|
|
|
|
{
|
|
|
|
if (spark->dShade > 64)
|
|
|
|
spark->dShade = 64;
|
|
|
|
}
|
|
|
|
|
|
|
|
spark->transType = 2;
|
|
|
|
spark->x = x + (GetRandomControl() & 31) - 16;
|
|
|
|
spark->y = y + (GetRandomControl() & 31) - 16;
|
|
|
|
spark->z = z + (GetRandomControl() & 31) - 16;
|
|
|
|
|
|
|
|
if (initial)
|
|
|
|
{
|
|
|
|
spark->xVel = ((GetRandomControl() & 1023) - 512) + xv;
|
|
|
|
spark->yVel = ((GetRandomControl() & 1023) - 512) + yv;
|
|
|
|
spark->zVel = ((GetRandomControl() & 1023) - 512) + zv;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-28 00:12:38 +01:00
|
|
|
float f = (frand() * 6) - 3;
|
|
|
|
spark->xVel = (frand() * 6) - 3;
|
|
|
|
spark->yVel = (frand() * 6) - 3;
|
|
|
|
spark->zVel = (frand() * 6) - 3;
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
spark->friction = 4;
|
|
|
|
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
{
|
|
|
|
if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
|
|
|
|
spark->flags = SP_ROTATE | SP_WIND;
|
|
|
|
else
|
|
|
|
spark->flags = SP_ROTATE;
|
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
if (GetRandomControl() & 1)
|
2019-12-27 10:50:59 +01:00
|
|
|
spark->rotAdd = -(GetRandomControl() & 0x0F) - 16;
|
2019-12-22 00:20:10 +01:00
|
|
|
else
|
2019-12-27 10:50:59 +01:00
|
|
|
spark->rotAdd = (GetRandomControl() & 0x0F) + 16;
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
else if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
|
|
|
|
{
|
|
|
|
spark->flags = SP_WIND;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->flags = 0;
|
|
|
|
}
|
2019-12-28 00:12:38 +01:00
|
|
|
float gravity = frand() * 1.25f;
|
|
|
|
spark->gravity = gravity;
|
|
|
|
spark->maxYvel = frand() * 16;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
byte size = ((GetRandomControl() & 0x0F) + 24); // -TriggerGunSmoke_SubFunction(weaponType);
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
if (initial)
|
|
|
|
{
|
|
|
|
spark->sSize = size >> 1;
|
|
|
|
spark->size = size >> 1;
|
|
|
|
spark->dSize = (size << 1) + 8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->sSize = size >> 2;
|
|
|
|
spark->size = size >> 2;
|
|
|
|
spark->dSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*if (gfLevelFlags & 0x20 && LaraItem->room_number == gfMirrorRoom) // 0x20 = GF_MIRROR_ENABLED
|
|
|
|
{
|
|
|
|
spark->mirror = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->mirror = 0;
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerShatterSmoke(int x, int y, int z)
|
|
|
|
{
|
|
|
|
SMOKE_SPARKS* spark = &SmokeSparks[GetFreeSmokeSpark()];
|
|
|
|
|
|
|
|
spark->on = true;
|
|
|
|
spark->sShade = 0;
|
|
|
|
spark->colFadeSpeed = 4;
|
|
|
|
spark->dShade = (GetRandomControl() & 0x1F) + 64;
|
|
|
|
spark->fadeToBlack = 24 - (GetRandomControl() & 7);
|
|
|
|
spark->transType = 2;
|
|
|
|
spark->life = spark->sLife = (GetRandomControl() & 7) + 48;
|
|
|
|
spark->x = (GetRandomControl() & 0x1F) + x - 16;
|
|
|
|
spark->y = (GetRandomControl() & 0x1F) + y - 16;
|
|
|
|
spark->z = (GetRandomControl() & 0x1F) + z - 16;
|
|
|
|
spark->xVel = 2 * (GetRandomControl() & 0x1FF) - 512;
|
|
|
|
spark->yVel = 2 * (GetRandomControl() & 0x1FF) - 512;
|
|
|
|
spark->zVel = 2 * (GetRandomControl() & 0x1FF) - 512;
|
|
|
|
spark->friction = 7;
|
|
|
|
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
{
|
|
|
|
spark->flags = SP_ROTATE;
|
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
spark->rotAdd = -64 - (GetRandomControl() & 0x3F);
|
|
|
|
else
|
|
|
|
spark->rotAdd = (GetRandomControl() & 0x3F) + 64;
|
|
|
|
}
|
|
|
|
else if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
|
|
|
|
{
|
|
|
|
spark->flags = SP_WIND;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->flags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
spark->gravity = -4 - (GetRandomControl() & 3);
|
|
|
|
spark->maxYvel = -4 - (GetRandomControl() & 3);
|
|
|
|
spark->dSize = (GetRandomControl() & 0x3F) + 64;
|
|
|
|
spark->sSize = spark->dSize >> 3;
|
|
|
|
spark->size = spark->dSize >> 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetFreeBlood()// (F)
|
|
|
|
{
|
|
|
|
BLOOD_STRUCT* blood = &Blood[NextBlood];
|
|
|
|
int bloodNum = NextBlood;
|
|
|
|
int minLife = 4095;
|
|
|
|
int minIndex = 0;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
while (blood->on)
|
|
|
|
{
|
|
|
|
if (blood->life < minLife)
|
|
|
|
{
|
|
|
|
minIndex = bloodNum;
|
|
|
|
minLife = blood->life;
|
|
|
|
}
|
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
if (bloodNum == MAX_SPARKS_BLOOD - 1)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
blood = &Blood[0];
|
|
|
|
bloodNum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
blood++;
|
|
|
|
bloodNum++;
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++count >= MAX_SPARKS_BLOOD)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
NextBlood = (minIndex + 1) & 31;
|
|
|
|
return minIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NextBlood = (bloodNum + 1) & 31;
|
|
|
|
return bloodNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerBlood(int x, int y, int z, int unk, int num)// (F)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
BLOOD_STRUCT* blood = &Blood[GetFreeBlood()];
|
|
|
|
blood->on = 1;
|
|
|
|
blood->sShade = 0;
|
|
|
|
blood->colFadeSpeed = 4;
|
|
|
|
blood->fadeToBlack = 8;
|
|
|
|
blood->dShade = (GetRandomControl() & 0x3F) + 48;
|
|
|
|
blood->life = blood->sLife = (GetRandomControl() & 7) + 24;
|
|
|
|
blood->x = (GetRandomControl() & 0x1F) + x - 16;
|
|
|
|
blood->y = (GetRandomControl() & 0x1F) + y - 16;
|
|
|
|
blood->z = (GetRandomControl() & 0x1F) + z - 16;
|
|
|
|
int a = (unk == -1
|
|
|
|
? GetRandomControl() & 0xFFFF
|
|
|
|
: (GetRandomControl() & 0x1F) + unk - 16) & 0xFFF;
|
|
|
|
int b = GetRandomControl() & 0xF;
|
|
|
|
blood->zVel = b * rcossin_tbl[2 * a + 1] >> 7;
|
|
|
|
blood->xVel = -(b * rcossin_tbl[2 * a]) >> 7;
|
|
|
|
blood->friction = 4;
|
|
|
|
blood->yVel = -((GetRandomControl() & 0xFF) + 128);
|
|
|
|
blood->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
blood->rotAdd = (GetRandomControl() & 0x3F) + 64;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
blood->rotAdd = -blood->rotAdd;
|
|
|
|
blood->gravity = (GetRandomControl() & 0x1F) + 31;
|
|
|
|
int size = (GetRandomControl() & 7) + 8;
|
|
|
|
blood->sSize = blood->size = size;
|
|
|
|
blood->dSize = size >> 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateBlood()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_SPARKS_BLOOD; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
BLOOD_STRUCT* blood = &Blood[i];
|
|
|
|
|
|
|
|
if (blood->on)
|
|
|
|
{
|
|
|
|
blood->life--;
|
|
|
|
|
|
|
|
if (blood->life <= 0)
|
|
|
|
{
|
|
|
|
blood->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (blood->sLife - blood->life >= blood->colFadeSpeed)
|
|
|
|
{
|
|
|
|
if (blood->life >= blood->fadeToBlack)
|
|
|
|
{
|
|
|
|
blood->shade = blood->dShade;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
blood->shade = blood->dShade * (((blood->life - blood->fadeToBlack) << 16) / blood->fadeToBlack + 0x10000) >> 16;
|
|
|
|
if (blood->shade < 8)
|
|
|
|
{
|
|
|
|
blood->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
blood->shade = blood->sShade + ((blood->dShade - blood->sShade) * (((blood->sLife - blood->life) << 16) / blood->colFadeSpeed) >> 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
blood->rotAng = (blood->rotAng + blood->rotAdd) & 0xFFF;
|
|
|
|
blood->yVel += blood->gravity;
|
|
|
|
|
|
|
|
if (blood->friction & 0xF)
|
|
|
|
{
|
|
|
|
blood->xVel -= blood->xVel >> (blood->friction & 0xF);
|
|
|
|
blood->zVel -= blood->zVel >> (blood->friction & 0xF);
|
|
|
|
}
|
|
|
|
|
|
|
|
int dl = ((blood->sLife - blood->life) << 16) / blood->sLife;
|
|
|
|
|
|
|
|
blood->x += blood->xVel >> 5;
|
|
|
|
blood->y += blood->yVel >> 5;
|
|
|
|
blood->z += blood->zVel >> 5;
|
|
|
|
|
|
|
|
blood->size = blood->sSize + (dl * (blood->dSize - blood->sSize) >> 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetFreeGunshell()
|
|
|
|
{
|
|
|
|
int gsNum = NextGunShell;
|
|
|
|
int minLife = 4095;
|
|
|
|
int minIndex = 0;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
GUNSHELL_STRUCT* gs = &Gunshells[NextGunShell];
|
|
|
|
|
|
|
|
if (!gs->counter)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (gs->counter < minLife)
|
|
|
|
{
|
|
|
|
minLife = gs->counter;
|
|
|
|
minIndex = gsNum;
|
|
|
|
}
|
2019-12-27 10:50:59 +01:00
|
|
|
if (gsNum == MAX_GUNSHELL - 1)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
gs = &Gunshells[0];
|
|
|
|
gsNum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gsNum++;
|
|
|
|
gs++;
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++i >= MAX_GUNSHELL)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
NextGunShell = minIndex + 1;
|
2019-12-26 19:19:20 +01:00
|
|
|
if (minIndex + 1 >= MAX_GUNSHELL)
|
2019-12-22 00:20:10 +01:00
|
|
|
NextGunShell = 0;
|
|
|
|
return minIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NextGunShell = gsNum + 1;
|
2019-12-26 19:19:20 +01:00
|
|
|
if (gsNum + 1 >= MAX_GUNSHELL)
|
2019-12-22 00:20:10 +01:00
|
|
|
NextGunShell = 0;
|
|
|
|
|
|
|
|
return gsNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerGunShell(short hand, short objNum, int weaponType)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
|
|
|
|
if (hand)
|
|
|
|
{
|
|
|
|
switch (weaponType)
|
|
|
|
{
|
|
|
|
case WEAPON_PISTOLS:
|
|
|
|
pos.x = 8;
|
|
|
|
pos.y = 48;
|
|
|
|
pos.z = 40;
|
|
|
|
break;
|
|
|
|
case WEAPON_UZI:
|
|
|
|
pos.x = 8;
|
|
|
|
pos.y = 35;
|
|
|
|
pos.z = 48;
|
|
|
|
break;
|
|
|
|
case WEAPON_SHOTGUN:
|
|
|
|
pos.x = 16;
|
|
|
|
pos.y = 114;
|
|
|
|
pos.z = 32;
|
|
|
|
break;
|
|
|
|
case WEAPON_HK:
|
|
|
|
pos.x = 16;
|
|
|
|
pos.y = 114;
|
|
|
|
pos.z = 96;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetLaraJointPosition(&pos, LJ_RHAND);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (weaponType == WEAPON_PISTOLS)
|
|
|
|
{
|
|
|
|
pos.x = -12;
|
|
|
|
pos.y = 48;
|
|
|
|
pos.z = 40;
|
|
|
|
|
|
|
|
GetLaraJointPosition(&pos, LJ_LHAND);
|
|
|
|
}
|
|
|
|
else if (weaponType == WEAPON_UZI)
|
|
|
|
{
|
|
|
|
pos.x = -16;
|
|
|
|
pos.y = 35;
|
|
|
|
pos.z = 48;
|
|
|
|
|
|
|
|
GetLaraJointPosition(&pos, LJ_LHAND);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GUNSHELL_STRUCT* gshell = &Gunshells[GetFreeGunshell()];
|
|
|
|
|
|
|
|
gshell->pos.xPos = pos.x;
|
|
|
|
gshell->pos.yPos = pos.y;
|
|
|
|
gshell->pos.zPos = pos.z;
|
|
|
|
gshell->pos.xRot = 0;
|
|
|
|
gshell->pos.yRot = 0;
|
|
|
|
gshell->pos.zRot = GetRandomControl();
|
|
|
|
gshell->roomNumber = LaraItem->roomNumber;
|
|
|
|
gshell->speed = (GetRandomControl() & 0x1F) + 16;
|
|
|
|
gshell->fallspeed = -48 - (GetRandomControl() & 7);
|
|
|
|
gshell->objectNumber = objNum;
|
|
|
|
gshell->counter = (GetRandomControl() & 0x1F) + 60;
|
|
|
|
if (hand)
|
|
|
|
{
|
|
|
|
if (weaponType == WEAPON_SHOTGUN)
|
|
|
|
{
|
|
|
|
gshell->dirXrot = Lara.leftArm.yRot
|
|
|
|
+ Lara.torsoYrot
|
|
|
|
+ LaraItem->pos.yRot
|
|
|
|
- (GetRandomControl() & 0xFFF)
|
|
|
|
+ 10240;
|
|
|
|
gshell->pos.yRot += Lara.leftArm.yRot
|
|
|
|
+ Lara.torsoYrot
|
|
|
|
+ LaraItem->pos.yRot;
|
|
|
|
if (gshell->speed < 24)
|
|
|
|
gshell->speed += 24;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gshell->dirXrot = Lara.leftArm.yRot
|
|
|
|
+ LaraItem->pos.yRot
|
|
|
|
- (GetRandomControl() & 0xFFF)
|
|
|
|
+ 18432;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gshell->dirXrot = Lara.leftArm.yRot
|
|
|
|
+ LaraItem->pos.yRot
|
|
|
|
+ (GetRandomControl() & 0xFFF)
|
|
|
|
- 18432;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LaraItem->meshBits)
|
|
|
|
{
|
|
|
|
if (weaponType == WEAPON_SHOTGUN)
|
|
|
|
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, WEAPON_SHOTGUN, 24);
|
|
|
|
else
|
|
|
|
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, weaponType, 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateGunShells()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_GUNSHELL; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
GUNSHELL_STRUCT* gs = &Gunshells[i];
|
|
|
|
|
|
|
|
if (gs->counter)
|
|
|
|
{
|
|
|
|
int oldX = gs->pos.xPos;
|
|
|
|
int oldY = gs->pos.yPos;
|
|
|
|
int oldZ = gs->pos.zPos;
|
|
|
|
|
|
|
|
gs->counter--;
|
|
|
|
|
|
|
|
short oldRoomNumber = gs->roomNumber;
|
|
|
|
|
|
|
|
if (Rooms[gs->roomNumber].flags & ENV_FLAG_WATER)
|
|
|
|
{
|
|
|
|
gs->fallspeed++;
|
|
|
|
|
|
|
|
if (gs->fallspeed <= 8)
|
|
|
|
{
|
|
|
|
if (gs->fallspeed < 0)
|
|
|
|
gs->fallspeed = gs->fallspeed >> 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gs->fallspeed = 8;
|
|
|
|
}
|
|
|
|
gs->speed -= gs->speed >> 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gs->fallspeed += 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
gs->pos.xRot += (gs->speed >> 1 + 7) * ANGLE(1);
|
|
|
|
gs->pos.yRot += gs->speed * ANGLE(1);
|
|
|
|
gs->pos.zRot += ANGLE(23);
|
|
|
|
|
2019-12-28 09:30:40 +01:00
|
|
|
gs->pos.xPos += gs->speed * SIN(gs->dirXrot) >> W2V_SHIFT;
|
2019-12-22 00:20:10 +01:00
|
|
|
gs->pos.yPos += gs->fallspeed;
|
2019-12-28 09:30:40 +01:00
|
|
|
gs->pos.zPos += gs->speed * COS(gs->dirXrot) >> W2V_SHIFT;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
FLOOR_INFO* floor = GetFloor(gs->pos.xPos, gs->pos.yPos, gs->pos.zPos, &gs->roomNumber);
|
|
|
|
if (Rooms[gs->roomNumber].flags & ENV_FLAG_WATER
|
|
|
|
&& !(Rooms[oldRoomNumber].flags & ENV_FLAG_WATER))
|
|
|
|
{
|
|
|
|
AddWaterSparks(gs->pos.xPos, Rooms[gs->roomNumber].maxceiling, gs->pos.zPos, 8);
|
|
|
|
SetupRipple(gs->pos.xPos, Rooms[gs->roomNumber].maxceiling, gs->pos.zPos, (GetRandomControl() & 3) + 8, 2);
|
|
|
|
gs->fallspeed >>= 5;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ceiling = GetCeiling(floor, gs->pos.xPos, gs->pos.yPos, gs->pos.zPos);
|
|
|
|
if (gs->pos.yPos < ceiling)
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_LARA_SHOTGUN_SHELL, &gs->pos, 0);
|
|
|
|
gs->speed -= 4;
|
|
|
|
|
|
|
|
if (gs->speed < 8)
|
|
|
|
{
|
|
|
|
gs->counter = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
gs->pos.yPos = ceiling;
|
|
|
|
gs->fallspeed = -gs->fallspeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
int height = GetFloorHeight(floor, gs->pos.xPos, gs->pos.yPos, gs->pos.zPos);
|
|
|
|
if (gs->pos.yPos >= height)
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_LARA_SHOTGUN_SHELL, &gs->pos, 0);
|
|
|
|
gs->speed -= 8;
|
|
|
|
if (gs->speed >= 8)
|
|
|
|
{
|
|
|
|
if (oldY <= height)
|
|
|
|
{
|
|
|
|
gs->fallspeed = -gs->fallspeed >> 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gs->dirXrot += -ANGLE(180);
|
|
|
|
gs->pos.xPos = oldX;
|
|
|
|
gs->pos.zPos = oldZ;
|
|
|
|
}
|
|
|
|
gs->pos.yPos = oldY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gs->counter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddWaterSparks(int x, int y, int z, int num)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
SPARKS* spark = &Sparks[GetFreeSpark()];
|
|
|
|
|
|
|
|
spark->on = 1;
|
|
|
|
spark->sR = 64;
|
|
|
|
spark->sG = 64;
|
|
|
|
spark->sB = 64;
|
|
|
|
spark->dR = 32;
|
|
|
|
spark->dG = 32;
|
|
|
|
spark->dB = 32;
|
|
|
|
spark->colFadeSpeed = 4;
|
|
|
|
spark->fadeToBlack = 8;
|
|
|
|
spark->life = 24;
|
|
|
|
spark->sLife = 24;
|
|
|
|
spark->transType = 2;
|
|
|
|
int random = GetRandomControl();
|
|
|
|
spark->xVel = -rcossin_tbl[2 * random] >> 5;
|
|
|
|
spark->yVel = -640 - GetRandomControl();
|
|
|
|
spark->zVel = rcossin_tbl[2 * random & 0xFFF + 1] >> 5;
|
|
|
|
spark->friction = 5;
|
|
|
|
spark->flags = 0;
|
|
|
|
spark->x = x + (spark->xVel >> 3);
|
|
|
|
spark->y = y - (spark->yVel >> 5);
|
|
|
|
spark->z = z + (spark->zVel >> 3);
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
spark->gravity = (GetRandomControl() & 0xF) + 64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetFreeBubble()//8BEAC(<), 8DEF0(<) (F)
|
|
|
|
{
|
|
|
|
BUBBLE_STRUCT* bub = &Bubbles[NextBubble];
|
|
|
|
int bubNum = NextBubble;
|
|
|
|
|
|
|
|
while (bub->size != 0)
|
|
|
|
{
|
2019-12-27 10:50:59 +01:00
|
|
|
if (bubNum == MAX_BUBBLES - 1)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
bub = &Bubbles[0];
|
|
|
|
bubNum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bubNum++;
|
|
|
|
bub++;
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++bubNum >= MAX_BUBBLES)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NextBubble = bubNum + 1;
|
2019-12-26 19:19:20 +01:00
|
|
|
if (bubNum + 1 >= MAX_BUBBLES)
|
2019-12-22 00:20:10 +01:00
|
|
|
NextBubble = 0;
|
|
|
|
|
|
|
|
return bubNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateBubble(PHD_VECTOR * pos, short roomNum, int unk1, int unk2, int flags, int xv, int yv, int zv)//8BF14(<), 8DF58(<) (F)
|
|
|
|
{
|
|
|
|
GetFloor(pos->x, pos->y, pos->z, &roomNum);
|
|
|
|
|
|
|
|
if (Rooms[roomNum].flags & ENV_FLAG_WATER)
|
|
|
|
{
|
|
|
|
BUBBLE_STRUCT* bubble = &Bubbles[GetFreeBubble()];
|
|
|
|
bubble->pos = *pos;
|
|
|
|
bubble->roomNumber = roomNum;
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->speed = frand();
|
2019-12-22 00:20:10 +01:00
|
|
|
bubble->shade = 0;
|
2019-12-28 09:30:40 +01:00
|
|
|
int size = rand() % 4 + 6;
|
2019-12-22 00:20:10 +01:00
|
|
|
bubble->size = size;
|
|
|
|
bubble->dsize = 16 * size;
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->vel = (frand()*0.8f)+0.2f;
|
2019-12-22 00:20:10 +01:00
|
|
|
bubble->flags = flags;
|
|
|
|
bubble->xVel = xv;
|
|
|
|
bubble->yVel = yv;
|
|
|
|
bubble->zVel = zv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LaraBubbles(ITEM_INFO* item)// (F)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
int num, i;
|
|
|
|
|
|
|
|
SoundEffect(SFX_LARA_BUBBLES, &item->pos, 1);
|
|
|
|
|
|
|
|
pos.x = 0;
|
|
|
|
|
|
|
|
if (LaraDrawType == LARA_DIVESUIT)
|
|
|
|
{
|
|
|
|
pos.y = -192;
|
|
|
|
pos.z = -160;
|
|
|
|
|
|
|
|
GetLaraJointPosition(&pos, LJ_TORSO);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos.y = -4;
|
|
|
|
pos.z = 64;
|
|
|
|
|
|
|
|
GetLaraJointPosition(&pos, LJ_HEAD);
|
|
|
|
}
|
|
|
|
|
|
|
|
num = (GetRandomControl() & 1) + 2;
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
CreateBubble(&pos, item->roomNumber, 8, 7, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateBubbles()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_BUBBLES; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
BUBBLE_STRUCT* bubble = &Bubbles[i];
|
|
|
|
|
|
|
|
if (bubble->size)
|
|
|
|
{
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->speed += bubble->vel.to_float();
|
2019-12-22 00:20:10 +01:00
|
|
|
bubble->yRot += 6;
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->pos.y -= bubble->speed.to_float();
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
if (bubble->flags & 1)
|
|
|
|
{
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->pos.x += bubble->xVel.to_float();
|
|
|
|
bubble->pos.y += bubble->yVel.to_float();
|
|
|
|
bubble->pos.z += bubble->zVel.to_float();
|
2019-12-22 00:20:10 +01:00
|
|
|
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->xVel -= (bubble->xVel.to_float()/2.0f);
|
|
|
|
bubble->yVel -= (bubble->yVel.to_float()/2.0f);
|
|
|
|
bubble->zVel -= (bubble->zVel.to_float()/2.0f);
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-28 09:30:40 +01:00
|
|
|
bubble->pos.x += sin(bubble->yRot)*5;
|
|
|
|
bubble->pos.z += cos(bubble->yRot)*5;
|
2019-12-22 00:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
short roomNumber = bubble->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(bubble->pos.x, bubble->pos.y, bubble->pos.z, &roomNumber);
|
|
|
|
int height = GetFloorHeight(floor, bubble->pos.x, bubble->pos.y, bubble->pos.z);
|
|
|
|
|
|
|
|
if (bubble->pos.y > height || !floor)
|
|
|
|
{
|
|
|
|
bubble->size = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(Rooms[roomNumber].flags & ENV_FLAG_WATER))
|
|
|
|
{
|
|
|
|
SetupRipple(bubble->pos.x, Rooms[bubble->roomNumber].maxceiling, bubble->pos.z, (GetRandomControl() & 0xF) + 48, 2);
|
|
|
|
bubble->size = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ceiling = GetCeiling(floor, bubble->pos.x, bubble->pos.y, bubble->pos.z);
|
|
|
|
if (ceiling == NO_HEIGHT || bubble->pos.y <= ceiling)
|
|
|
|
{
|
|
|
|
bubble->size = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bubble->size < bubble->dsize)
|
|
|
|
bubble->size++;
|
|
|
|
|
|
|
|
if (bubble->flags & 1)
|
|
|
|
{
|
|
|
|
if (bubble->shade < 96)
|
|
|
|
{
|
|
|
|
bubble->shade += 16;
|
|
|
|
bubble->roomNumber = roomNumber;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bubble->shade < 144)
|
|
|
|
{
|
|
|
|
bubble->shade += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
bubble->roomNumber = roomNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetFreeDrip()
|
|
|
|
{
|
|
|
|
DRIP_STRUCT* drip = &Drips[NextDrip];
|
|
|
|
int dripNum = NextDrip;
|
|
|
|
short minLife = 4095;
|
|
|
|
short minIndex = 0;
|
|
|
|
short count = 0;
|
|
|
|
|
|
|
|
while (drip->on)
|
|
|
|
{
|
|
|
|
if (drip->life < minLife)
|
|
|
|
{
|
|
|
|
minIndex = dripNum;
|
|
|
|
minLife = drip->life;
|
|
|
|
}
|
|
|
|
|
2019-12-27 10:50:59 +01:00
|
|
|
if (dripNum == MAX_DRIPS - 1)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
drip = &Drips[0];
|
|
|
|
dripNum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dripNum++;
|
|
|
|
drip++;
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
if (++count >= MAX_DRIPS)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
NextDrip = (minIndex + 1) % MAX_DRIPS;
|
2019-12-22 00:20:10 +01:00
|
|
|
return minIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 19:19:20 +01:00
|
|
|
NextDrip = (dripNum + 1) % MAX_DRIPS;
|
2019-12-22 00:20:10 +01:00
|
|
|
|
|
|
|
return dripNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateDrips()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_DRIPS; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
DRIP_STRUCT* drip = &Drips[i];
|
|
|
|
|
|
|
|
if (drip->on)
|
|
|
|
{
|
|
|
|
drip->life--;
|
|
|
|
if (!drip->life)
|
|
|
|
{
|
|
|
|
drip->on = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drip->life < 16)
|
|
|
|
{
|
|
|
|
drip->r -= drip->r >> 3;
|
|
|
|
drip->g -= drip->g >> 3;
|
|
|
|
drip->b -= drip->b >> 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
drip->yVel += drip->gravity;
|
|
|
|
|
|
|
|
if (Rooms[drip->roomNumber].flags & ENV_FLAG_WIND)
|
|
|
|
{
|
|
|
|
drip->x += SmokeWindX >> 1;
|
|
|
|
drip->z += SmokeWindZ >> 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
drip->y += drip->yVel >> 5;
|
|
|
|
|
|
|
|
FLOOR_INFO* floor = GetFloor(drip->x, drip->y, drip->z, &drip->roomNumber);
|
|
|
|
if (Rooms[drip->roomNumber].flags & ENV_FLAG_WATER)
|
|
|
|
drip->on = false;
|
|
|
|
|
|
|
|
int height = GetFloorHeight(floor, drip->x, drip->y, drip->z);
|
|
|
|
if (drip->y > height)
|
|
|
|
{
|
|
|
|
if (i % 2 == 0)
|
|
|
|
AddWaterSparks(drip->x, drip->y, drip->z, 1);
|
|
|
|
drip->on = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerLaraDrips()// (F)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
|
|
|
|
if (!(Wibble & 0xF))
|
|
|
|
{
|
|
|
|
for (int i = 14; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (Lara.wet[i]
|
|
|
|
&& !LaraNodeUnderwater[14 - i]
|
|
|
|
&& (GetRandomControl() & 0x1FF) < Lara.wet[i])
|
|
|
|
{
|
|
|
|
|
|
|
|
pos.x = (GetRandomControl() & 0x1F) - 16;
|
|
|
|
pos.y = (GetRandomControl() & 0xF) + 16;
|
|
|
|
pos.z = (GetRandomControl() & 0x1F) - 16;
|
|
|
|
|
|
|
|
DRIP_STRUCT* dptr = &Drips[GetFreeDrip()];
|
|
|
|
GetLaraJointPosition(&pos, i);
|
|
|
|
dptr->x = pos.x;
|
|
|
|
dptr->y = pos.y;
|
|
|
|
dptr->z = pos.z;
|
|
|
|
dptr->on = 1;
|
|
|
|
dptr->r = (GetRandomControl() & 7) + 16;
|
|
|
|
dptr->g = (GetRandomControl() & 7) + 24;
|
|
|
|
dptr->b = (GetRandomControl() & 7) + 32;
|
|
|
|
dptr->yVel = (GetRandomControl() & 0x1F) + 32;
|
|
|
|
dptr->gravity = (GetRandomControl() & 0x1F) + 32;
|
|
|
|
dptr->life = (GetRandomControl() & 0x1F) + 8;
|
|
|
|
dptr->roomNumber = LaraItem->roomNumber;
|
|
|
|
|
|
|
|
Lara.wet[i] -= 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int ExplodingDeath2(short itemNumber, int meshBits, short damage)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &Items[itemNumber];
|
|
|
|
OBJECT_INFO* obj = &Objects[item->objectNumber];
|
|
|
|
|
|
|
|
short* frame = GetBestFrame(item);
|
|
|
|
|
|
|
|
phd_PushUnitMatrix();
|
|
|
|
|
|
|
|
MatrixPtr[M03] = 0;
|
|
|
|
MatrixPtr[M13] = 0;
|
|
|
|
MatrixPtr[M23] = 0;
|
|
|
|
|
|
|
|
phd_RotYXZ(item->pos.yPos, item->pos.xRot, item->pos.zRot);
|
|
|
|
phd_TranslateRel(frame[6], frame[7], frame[8]);
|
|
|
|
|
|
|
|
short* rotation = &frame[9];
|
|
|
|
gar_RotYXZsuperpack(&rotation, 0);
|
|
|
|
|
|
|
|
short* extraRotation = (short*)item->data;
|
|
|
|
|
|
|
|
int* bone = &Bones[obj->boneIndex];
|
|
|
|
|
|
|
|
int bits = 1;
|
|
|
|
if (meshBits & 1 && item->meshBits & 1)
|
|
|
|
{
|
|
|
|
if (damage & 0x100 || !(GetRandomControl() & 3))
|
|
|
|
{
|
|
|
|
int fxNumber = CreateNewEffect(item->roomNumber);
|
|
|
|
if (fxNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
FX_INFO* fx = &Effects[fxNumber];
|
|
|
|
fx->pos.xPos = item->pos.xPos + (MatrixPtr[M03] >> W2V_SHIFT);
|
|
|
|
fx->pos.yPos = item->pos.yPos + (MatrixPtr[M13] >> W2V_SHIFT);
|
|
|
|
fx->pos.zPos = item->pos.zPos + (MatrixPtr[M23] >> W2V_SHIFT);
|
|
|
|
fx->roomNumber = item->roomNumber;
|
|
|
|
fx->pos.yRot = 0;
|
|
|
|
fx->pos.zRot = 0;
|
|
|
|
fx->pos.xRot = 0;
|
|
|
|
|
|
|
|
if (damage & 0x10)
|
|
|
|
{
|
|
|
|
fx->speed = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (damage & 0x20)
|
|
|
|
fx->speed = GetRandomControl() >> 12;
|
|
|
|
else
|
|
|
|
fx->speed = GetRandomControl() >> 8;
|
|
|
|
}
|
|
|
|
if (damage & 0x40)
|
|
|
|
{
|
|
|
|
fx->fallspeed = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((damage & 0x80u) == 0)
|
|
|
|
fx->fallspeed = -(GetRandomControl() >> 8);
|
|
|
|
else
|
|
|
|
fx->fallspeed = -(GetRandomControl() >> 12);
|
|
|
|
}
|
|
|
|
fx->frameNumber = obj->meshIndex;
|
|
|
|
fx->objectNumber = ID_BODY_PART;
|
|
|
|
fx->shade = 16912;
|
|
|
|
fx->flag2 = damage;
|
|
|
|
|
|
|
|
if (item->objectNumber == ID_CRUMBLING_FLOOR)
|
|
|
|
{
|
|
|
|
fx->speed = 0;
|
|
|
|
fx->fallspeed = 0;
|
|
|
|
fx->counter = 61;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fx->counter = 0;
|
|
|
|
}
|
|
|
|
fx->flag1 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->meshBits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < obj->nmeshes; i++, bone += 3)
|
|
|
|
{
|
|
|
|
short popPush = *(bone++);
|
|
|
|
|
|
|
|
if (popPush & 1)
|
|
|
|
{
|
|
|
|
MatrixPtr -= 12;
|
|
|
|
DxMatrixPtr -= 48;
|
|
|
|
}
|
|
|
|
else if (popPush & 2)
|
|
|
|
{
|
|
|
|
phd_PushMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
phd_TranslateRel(bone[0], bone[1], bone[2]);
|
|
|
|
gar_RotYXZsuperpack(&rotation, 0);
|
|
|
|
|
|
|
|
if (popPush & (ROT_X | ROT_Y | ROT_Z))
|
|
|
|
{
|
|
|
|
if (popPush & ROT_Y)
|
|
|
|
phd_RotY(*(extraRotation++));
|
|
|
|
if (popPush & ROT_X)
|
|
|
|
phd_RotX(*(extraRotation++));
|
|
|
|
if (popPush & ROT_Z)
|
|
|
|
phd_RotZ(*(extraRotation++));
|
|
|
|
}
|
|
|
|
|
|
|
|
bits <<= 1;
|
|
|
|
|
|
|
|
if (bits & meshBits && bits & item->meshBits && (damage & 0x100 || !(GetRandomControl() & 3)))
|
|
|
|
{
|
|
|
|
int fxNumber = CreateNewEffect(item->roomNumber);
|
|
|
|
if (fxNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
FX_INFO* fx = &Effects[fxNumber];
|
|
|
|
fx->pos.xPos = item->pos.xPos + (MatrixPtr[3] >> 14);
|
|
|
|
fx->pos.yPos = item->pos.yPos + (MatrixPtr[7] >> 14);
|
|
|
|
fx->pos.zPos = item->pos.zPos + (MatrixPtr[11] >> 14);
|
|
|
|
fx->roomNumber = item->roomNumber;
|
|
|
|
fx->pos.yRot = 0;
|
|
|
|
fx->pos.zRot = 0;
|
|
|
|
fx->pos.xRot = 0;
|
|
|
|
if (damage & 0x10)
|
|
|
|
{
|
|
|
|
fx->speed = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (damage & 0x20)
|
|
|
|
fx->speed = GetRandomControl() >> 12;
|
|
|
|
else
|
|
|
|
fx->speed = GetRandomControl() >> 8;
|
|
|
|
}
|
|
|
|
if (damage & 0x40)
|
|
|
|
{
|
|
|
|
fx->fallspeed = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((damage & 0x80u) == 0)
|
|
|
|
fx->fallspeed = -(GetRandomControl() >> 8);
|
|
|
|
else
|
|
|
|
fx->fallspeed = -(GetRandomControl() >> 12);
|
|
|
|
}
|
|
|
|
fx->objectNumber = ID_BODY_PART;
|
|
|
|
fx->shade = 16912;
|
|
|
|
fx->flag2 = damage;
|
|
|
|
fx->frameNumber = obj->meshIndex + 2 * i;
|
|
|
|
|
|
|
|
if (item->objectNumber == ID_CRUMBLING_FLOOR)
|
|
|
|
{
|
|
|
|
fx->speed = 0;
|
|
|
|
fx->fallspeed = 0;
|
|
|
|
fx->counter = 61;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fx->counter = 0;
|
|
|
|
}
|
|
|
|
fx->flag1 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->meshBits -= bits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixPtr -= 12;
|
|
|
|
DxMatrixPtr = (DxMatrixPtr - 48);
|
|
|
|
|
|
|
|
return (item->meshBits == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetFreeShockwave()// (F)
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_SHOCKWAVE; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
if (!ShockWaves[i].life)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerShockwave(PHD_3DPOS* pos, short innerRad, short outerRad, int speed, char r, char g, char b, char life, short angle, short flags)// (F)
|
|
|
|
{
|
|
|
|
int s = GetFreeShockwave();
|
|
|
|
SHOCKWAVE_STRUCT* sptr;
|
|
|
|
|
|
|
|
if (s != -1)
|
|
|
|
{
|
|
|
|
sptr = &ShockWaves[s];
|
|
|
|
|
|
|
|
sptr->x = pos->xPos;
|
|
|
|
sptr->y = pos->yPos;
|
|
|
|
sptr->z = pos->zPos;
|
|
|
|
sptr->innerRad = innerRad;
|
|
|
|
sptr->outerRad = outerRad;
|
|
|
|
sptr->xRot = angle;
|
|
|
|
sptr->flags = flags;
|
|
|
|
sptr->speed = speed;
|
|
|
|
sptr->r = r;
|
|
|
|
sptr->g = g;
|
|
|
|
sptr->b = b;
|
|
|
|
sptr->life = life;
|
|
|
|
|
|
|
|
SoundEffect(SFX_IMP_STONE_HIT, pos, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerShockwaveHitEffect(int x, int y, int z, int color, short rot, int vel)
|
|
|
|
{
|
|
|
|
int dx = LaraItem->pos.xPos - x;
|
|
|
|
int dz = LaraItem->pos.zPos - z;
|
|
|
|
|
|
|
|
if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
|
|
|
|
{
|
|
|
|
SPARKS* spark = &Sparks[GetFreeSpark()];
|
|
|
|
spark->dB = color & 0xFF;
|
|
|
|
spark->on = true;
|
|
|
|
spark->sR = 0;
|
|
|
|
spark->sG = 0;
|
|
|
|
spark->sB = 0;
|
|
|
|
spark->dG = color >> 8;
|
|
|
|
spark->dR = color >> 16;
|
|
|
|
spark->colFadeSpeed = 4;
|
|
|
|
spark->fadeToBlack = 8;
|
|
|
|
spark->transType = 2;
|
|
|
|
spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
|
|
|
|
|
|
|
|
int speed = (GetRandomControl() & 0xF) + vel;
|
|
|
|
spark->xVel = speed * 16 * SIN(rot) >> W2V_SHIFT;
|
|
|
|
spark->yVel = -512 - (GetRandomControl() & 0x1FF);
|
|
|
|
spark->zVel = speed * 16 * COS(rot) >> W2V_SHIFT;
|
|
|
|
|
|
|
|
short angle;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
angle = rot + ANGLE(90);
|
|
|
|
else
|
|
|
|
angle = rot - ANGLE(90);
|
|
|
|
|
|
|
|
int shift = (GetRandomControl() & 0x1FF) - 256;
|
|
|
|
x += (shift * SIN(angle) >> W2V_SHIFT);
|
|
|
|
z += (shift * COS(angle) >> W2V_SHIFT);
|
|
|
|
|
|
|
|
spark->x = (GetRandomControl() & 0x1F) + x - 16;
|
|
|
|
spark->y = (GetRandomControl() & 0x1F) + y - 16;
|
|
|
|
spark->z = (GetRandomControl() & 0x1F) + z - 16;
|
|
|
|
|
|
|
|
spark->friction = 3;
|
|
|
|
spark->flags = 538;
|
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
spark->rotAdd = -16 - (GetRandomControl() & 0xF);
|
|
|
|
else
|
|
|
|
spark->rotAdd = (GetRandomControl() & 0xF) + 16;
|
|
|
|
|
|
|
|
spark->scalar = 1;
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 14;
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
spark->gravity = (GetRandomControl() & 0x3F) + 64;
|
|
|
|
spark->sSize = spark->size = (GetRandomControl() & 0x1F) + 32;
|
|
|
|
spark->dSize = spark->size >> 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateShockwaves()
|
|
|
|
{
|
2019-12-26 19:19:20 +01:00
|
|
|
for (int i = 0; i < MAX_SHOCKWAVE; i++)
|
2019-12-22 00:20:10 +01:00
|
|
|
{
|
|
|
|
SHOCKWAVE_STRUCT* sw = &ShockWaves[i];
|
|
|
|
|
|
|
|
if (sw->life)
|
|
|
|
{
|
|
|
|
sw->life--;
|
|
|
|
|
|
|
|
if (sw->life)
|
|
|
|
{
|
|
|
|
sw->outerRad += sw->speed;
|
|
|
|
sw->speed -= (sw->speed >> 4);
|
|
|
|
|
|
|
|
if (LaraItem->hitPoints > 0)
|
|
|
|
{
|
|
|
|
if (sw->flags & 3)
|
|
|
|
{
|
|
|
|
short* frame = GetBestFrame(LaraItem);
|
|
|
|
|
|
|
|
int dx = LaraItem->pos.xPos - sw->x;
|
|
|
|
int dz = LaraItem->pos.zPos - sw->z;
|
|
|
|
int distance = SQRT_ASM(SQUARE(dx) + SQUARE(dz));
|
|
|
|
|
|
|
|
if (sw->y <= LaraItem->pos.yPos + frame[2]
|
|
|
|
|| sw->y >= LaraItem->pos.yPos + frame[3] + 256
|
|
|
|
|| distance <= sw->innerRad
|
|
|
|
|| distance >= sw->outerRad)
|
|
|
|
{
|
|
|
|
sw->temp = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
short angle = ATAN(dz, dx);
|
|
|
|
TriggerShockwaveHitEffect(LaraItem->pos.xPos,
|
|
|
|
sw->y,
|
|
|
|
LaraItem->pos.zPos,
|
|
|
|
(sw->r << 16) | (sw->g << 8) | sw->b,
|
|
|
|
angle,
|
|
|
|
sw->speed);
|
|
|
|
LaraItem->hitPoints -= sw->speed >> (((sw->flags >> 1) & 1) + 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerExplosionBubble(int x, int y, int z, short roomNum)// (F)
|
|
|
|
{
|
|
|
|
int dx = LaraItem->pos.xPos - x;
|
|
|
|
int dz = LaraItem->pos.zPos - z;
|
|
|
|
|
|
|
|
if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
|
|
|
|
{
|
|
|
|
SPARKS* spark = &Sparks[GetFreeSpark()];
|
|
|
|
spark->sR = 128;
|
|
|
|
spark->dR = 128;
|
|
|
|
spark->dG = 128;
|
|
|
|
spark->dB = 128;
|
|
|
|
spark->on = 1;
|
|
|
|
spark->life = 24;
|
|
|
|
spark->sLife = 24;
|
|
|
|
spark->sG = 64;
|
|
|
|
spark->sB = 0;
|
|
|
|
spark->colFadeSpeed = 8;
|
|
|
|
spark->fadeToBlack = 12;
|
|
|
|
spark->transType = 2;
|
|
|
|
spark->x = x;
|
|
|
|
spark->y = y;
|
|
|
|
spark->z = z;
|
|
|
|
spark->xVel = 0;
|
|
|
|
spark->yVel = 0;
|
|
|
|
spark->zVel = 0;
|
|
|
|
spark->friction = 0;
|
|
|
|
spark->flags = 2058;
|
|
|
|
spark->scalar = 3;
|
|
|
|
spark->gravity = 0;
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 13;
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
int size = (GetRandomControl() & 7) + 63;
|
|
|
|
spark->sSize = size >> 1;
|
|
|
|
spark->size = size >> 1;
|
|
|
|
spark->dSize = 2 * size;
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
pos.x = (GetRandomControl() & 0x1FF) + x - 256;
|
|
|
|
pos.y = (GetRandomControl() & 0x7F) + y - 64;
|
|
|
|
pos.z = (GetRandomControl() & 0x1FF) + z - 256;
|
|
|
|
CreateBubble(&pos, roomNum, 6, 15, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*void TriggerExplosionSmokeEnd(int x, int y, int z, int unk)// (F)
|
|
|
|
{
|
|
|
|
SPARKS* spark = &Sparks[GetFreeSpark()];
|
|
|
|
|
|
|
|
spark->on = 1;
|
|
|
|
if (unk)
|
|
|
|
{
|
|
|
|
spark->sR = 0;
|
|
|
|
spark->sG = 0;
|
|
|
|
spark->sB = 0;
|
|
|
|
spark->dR = 192;
|
|
|
|
spark->dG = 192;
|
|
|
|
spark->dB = 208;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->dR = 64;
|
|
|
|
spark->sR = 144;
|
|
|
|
spark->sG = 144;
|
|
|
|
spark->sB = 144;
|
|
|
|
spark->dG = 64;
|
|
|
|
spark->dB = 64;
|
|
|
|
}
|
|
|
|
|
|
|
|
spark->colFadeSpeed = 8;
|
|
|
|
spark->fadeToBlack = 64;
|
|
|
|
spark->life = spark->sLife = (GetRandomControl() & 0x1F) + 96;
|
|
|
|
if (unk)
|
|
|
|
spark->transType = 2;
|
|
|
|
else
|
|
|
|
spark->transType = 3;
|
|
|
|
spark->x = (GetRandomControl() & 0x1F) + x - 16;
|
|
|
|
spark->y = (GetRandomControl() & 0x1F) + y - 16;
|
|
|
|
spark->z = (GetRandomControl() & 0x1F) + z - 16;
|
|
|
|
spark->xVel = ((GetRandomControl() & 0xFFF) - 2048) >> 2;
|
|
|
|
spark->yVel = (GetRandomControl() & 0xFF) - 128;
|
|
|
|
spark->zVel = ((GetRandomControl() & 0xFFF) - 2048) >> 2;
|
|
|
|
if (unk)
|
|
|
|
{
|
|
|
|
spark->friction = 20;
|
|
|
|
spark->yVel >>= 4;
|
|
|
|
spark->y += 32;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->friction = 6;
|
|
|
|
}
|
|
|
|
spark->flags = 538;
|
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
if (GetRandomControl() & 1)
|
|
|
|
spark->rotAdd = -((GetRandomControl() & 0xF) + 16);
|
|
|
|
else
|
|
|
|
spark->rotAdd = (GetRandomControl() & 0xF) + 16;
|
|
|
|
spark->scalar = 3;
|
|
|
|
if (unk)
|
|
|
|
{
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
spark->gravity = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->gravity = -3 - (GetRandomControl() & 3);
|
|
|
|
spark->maxYvel = -4 - (GetRandomControl() & 3);
|
|
|
|
}
|
|
|
|
int size = (GetRandomControl() & 0x1F) + 128;
|
|
|
|
spark->dSize = size;
|
|
|
|
spark->sSize = size >> 2;
|
|
|
|
spark->size = size >> 2;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*void DrawLensFlares(ITEM_INFO* item)// (F)
|
|
|
|
{
|
|
|
|
GAME_VECTOR pos;
|
|
|
|
|
|
|
|
pos.x = item->pos.x_pos;
|
|
|
|
pos.y = item->pos.y_pos;
|
|
|
|
pos.z = item->pos.z_pos;
|
|
|
|
pos.room_number = item->room_number;
|
|
|
|
|
|
|
|
SetUpLensFlare(0, 0, 0, &pos);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
void TriggerLightningGlow(int x, int y, int z, int rgb)// (F)
|
|
|
|
{
|
|
|
|
SPARKS* spark = &Sparks[GetFreeSpark()];
|
|
|
|
|
|
|
|
spark->dG = GREEN(rgb);
|
|
|
|
spark->sG = GREEN(rgb);
|
|
|
|
spark->life = 4;
|
|
|
|
spark->sLife = 4;
|
|
|
|
spark->dR = RED(rgb);
|
|
|
|
spark->sR = RED(rgb);
|
|
|
|
spark->colFadeSpeed = 2;
|
|
|
|
spark->transType = 2;
|
|
|
|
spark->x = x;
|
|
|
|
spark->on = 1;
|
|
|
|
spark->dB = BLUE(rgb);
|
|
|
|
spark->sB = BLUE(rgb);
|
|
|
|
spark->fadeToBlack = 0;
|
|
|
|
spark->y = y;
|
|
|
|
spark->z = z;
|
|
|
|
spark->zVel = 0;
|
|
|
|
spark->yVel = 0;
|
|
|
|
spark->xVel = 0;
|
|
|
|
spark->flags = 10;
|
|
|
|
spark->scalar = 3;
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 11;
|
|
|
|
spark->gravity = 0;
|
|
|
|
int size = ALPHA(rgb) + (GetRandomControl() & 3);
|
|
|
|
spark->dSize = size;
|
|
|
|
spark->sSize = size;
|
|
|
|
spark->size = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerFenceSparks(int x, int y, int z, int kill, int crane)//(F)
|
|
|
|
{
|
|
|
|
SPARKS* spark = &Sparks[GetFreeSpark()];
|
|
|
|
spark->on = 1;
|
|
|
|
spark->sR = (GetRandomControl() & 0x3F) - 0x40;
|
|
|
|
spark->sG = (GetRandomControl() & 0x3F) - 0x40;
|
|
|
|
spark->sB = (GetRandomControl() & 0x3F) - 0x40;
|
|
|
|
|
|
|
|
spark->dR = GetRandomControl() | 0xC0;
|
|
|
|
spark->colFadeSpeed = 16;
|
|
|
|
spark->g = 8;
|
|
|
|
spark->dG = spark->sR >> 1;
|
|
|
|
spark->dB = spark->sR >> 2;
|
|
|
|
|
|
|
|
spark->life = (GetRandomControl() & 7) + 24;
|
|
|
|
spark->sLife = (GetRandomControl() & 7) + 24;
|
|
|
|
spark->transType = 2;
|
|
|
|
spark->dynamic = -1;
|
|
|
|
|
|
|
|
spark->x = x;
|
|
|
|
spark->y = y;
|
|
|
|
spark->z = z;
|
|
|
|
|
|
|
|
spark->xVel = ((GetRandomControl() & 0xFF) - 128) << 2;
|
|
|
|
spark->yVel = (GetRandomControl() & 0xF) - ((kill << 5) + 8) + (crane << 4);
|
|
|
|
spark->zVel = ((GetRandomControl() & 0xFF) - 128) << 2;
|
|
|
|
|
|
|
|
if (crane != 0)
|
|
|
|
{
|
|
|
|
spark->friction = 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
spark->friction = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
//loc_365C4
|
|
|
|
spark->flags = 0;
|
|
|
|
spark->gravity = (GetRandomControl() & 0xF) + ((crane << 4) + 16);
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetFreeSpider()// (F)
|
|
|
|
{
|
|
|
|
SPIDER_STRUCT* peter = &Spiders[NextSpider];
|
|
|
|
int peter_num = NextSpider;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
while (peter->on)
|
|
|
|
{
|
|
|
|
if (peter_num == 63)
|
|
|
|
{
|
|
|
|
peter = &Spiders[0];
|
|
|
|
peter_num = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
peter++;
|
|
|
|
peter_num++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (++count >= 64)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
NextSpider = (peter_num + 1) & 63;
|
|
|
|
return peter_num;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerSmallSplash(int x, int y, int z, int num)// (F)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int angle;
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
SPARKS* sptr = &Sparks[GetFreeSpark()];
|
|
|
|
|
|
|
|
sptr->on = 1;
|
|
|
|
|
|
|
|
sptr->sR = 64;
|
|
|
|
sptr->sG = 64;
|
|
|
|
sptr->sB = 64;
|
|
|
|
|
|
|
|
sptr->dR = 32;
|
|
|
|
sptr->dG = 32;
|
|
|
|
sptr->dB = 32;
|
|
|
|
|
|
|
|
sptr->colFadeSpeed = 4;
|
|
|
|
sptr->fadeToBlack = 8;
|
|
|
|
|
|
|
|
sptr->life = 24;
|
|
|
|
sptr->sLife = 24;
|
|
|
|
|
|
|
|
sptr->transType = 2;
|
|
|
|
|
|
|
|
angle = GetRandomControl() << 3;
|
|
|
|
|
|
|
|
sptr->xVel = -SIN(angle) >> 5;
|
|
|
|
sptr->yVel = -640 - (GetRandomControl() & 0xFF);
|
|
|
|
sptr->zVel = COS(angle) >> 5;
|
|
|
|
|
|
|
|
sptr->friction = 5;
|
|
|
|
sptr->flags = 0;
|
|
|
|
|
|
|
|
sptr->x = x + (sptr->xVel >> 3);
|
|
|
|
sptr->y = y - (sptr->yVel >> 5);
|
|
|
|
sptr->z = z + (sptr->zVel >> 3);
|
|
|
|
|
|
|
|
sptr->maxYvel = 0;
|
|
|
|
sptr->gravity = (GetRandomControl() & 0xF) + 64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Inject_Tomb4FX()
|
|
|
|
{
|
|
|
|
INJECT(0x004827E0, TriggerBlood);
|
|
|
|
INJECT(0x00431070, TriggerExplosionBubble);
|
|
|
|
INJECT(0x004812B0, GetFreeFireSpark);
|
|
|
|
INJECT(0x00481A00, TriggerGlobalStaticFlame);
|
|
|
|
INJECT(0x004816B0, TriggerGlobalFireSmoke);
|
|
|
|
INJECT(0x00481840, TriggerGlobalFireFlame);
|
|
|
|
INJECT(0x00481370, keep_those_fires_burning);
|
|
|
|
INJECT(0x00481B10, ClearFires);
|
|
|
|
INJECT(0x00481B10, AddFire);
|
|
|
|
INJECT(0x004813B0, UpdateFireSparks);
|
|
|
|
INJECT(0x00481D40, GetFreeSmokeSpark);
|
|
|
|
INJECT(0x00481DD0, UpdateSmoke);
|
|
|
|
INJECT(0x004820A0, TriggerGunSmoke);
|
|
|
|
INJECT(0x004823A0, TriggerShatterSmoke);
|
|
|
|
INJECT(0x00482580, GetFreeBlood);
|
|
|
|
INJECT(0x00482610, UpdateBlood);
|
|
|
|
INJECT(0x004829A0, GetFreeGunshell);
|
|
|
|
INJECT(0x00482A60, TriggerGunShell);
|
|
|
|
INJECT(0x00482D80, UpdateGunShells);
|
|
|
|
INJECT(0x00483180, AddWaterSparks);
|
|
|
|
INJECT(0x004832C0, GetFreeBubble);
|
|
|
|
INJECT(0x00483350, CreateBubble);
|
|
|
|
INJECT(0x00483470, LaraBubbles);
|
|
|
|
INJECT(0x00483540, UpdateBubbles);
|
|
|
|
INJECT(0x00483D00, GetFreeDrip);
|
|
|
|
INJECT(0x00483D90, UpdateDrips);
|
|
|
|
INJECT(0x00483F00, TriggerLaraDrips);
|
|
|
|
INJECT(0x00484080, ExplodingDeath2);
|
|
|
|
INJECT(0x00484640, GetFreeShockwave);
|
|
|
|
INJECT(0x00484670, TriggerShockwave);
|
|
|
|
INJECT(0x004849A0, UpdateShockwaves);
|
|
|
|
}
|