This commit is contained in:
Montagna Marco 2019-12-29 20:16:04 +01:00
commit c03760d123
14 changed files with 895 additions and 379 deletions

View file

@ -2,7 +2,7 @@
#include "draw.h"
#include "tomb4fx.h"
#include "traps.h"
#include "math.h"
#include "..\Scripting\GameFlowScript.h"
//long wibble;
@ -1001,37 +1001,68 @@ void TriggerSuperJetFlame(ITEM_INFO* item, int yvel, int deadly)//32EAC, 333AC (
}
}
void SetupSplash(SPLASH_SETUP* setup)
void SetupSplash(const SPLASH_SETUP* const setup)
{
constexpr size_t NUM_SPLASHES = 4;
int numSplashesSetup = 0;
float splashVelocity;
for (int i = 0; i < MAX_SPLASH; i++)
{
SPLASH_STRUCT* splash = &Splashes[i];
if (!(splash->flags & 1))
SPLASH_STRUCT& splash = Splashes[i];
if (!splash.isActive)
{
splash->flags = 1;
splash->x = setup->x;
splash->y = setup->y;
splash->z = setup->z;
splash->life = 62;
splash->innerRad = setup->innerRad;
splash->innerSize = setup->innerSize;
splash->innerRadVel = setup->innerRadVel;
splash->innerYVel = setup->innerYVel;
splash->innerY = setup->innerYVel >> 2;
splash->middleRad = setup->middleRad;
splash->middleSize = setup->middleSize;
splash->middleRadVel = setup->middleRadVel;
splash->middleYVel = setup->middleYVel;
splash->middleY = setup->middleYVel >> 2;
splash->outerRad = setup->outerRad;
splash->outerSize = setup->outerSize;
splash->outerRadVel = setup->outerRadVel;
if (numSplashesSetup == 0) {
splash.isActive = true;
splash.x = setup->x;
splash.y = setup->y;
splash.z = setup->z;
splash.life = 62;
splash.isRipple = false;
splash.innerRad = setup->innerRadius;
splashVelocity = setup->splashPower / 16;
splash.innerRadVel = splashVelocity;
splash.heightSpeed = setup->splashPower * 1.5f;
splash.height = 0;
splash.heightVel = -16;
splash.outerRad = setup->innerRadius / 6;
splash.outerRadVel = splashVelocity *2;
splash.spriteSequenceStart = 8; //Splash Texture
numSplashesSetup++;
}
else {
float thickness = frandMinMax(128,256);
splash.isActive = true;
splash.x = setup->x;
splash.y = setup->y;
splash.z = setup->z;
splash.isRipple = true;
float vel = (splashVelocity/2) + frandMinMax(3,16);
float innerRadius = 0;
splash.innerRad = innerRadius;
splash.innerRadVel = vel;
splash.outerRad = innerRadius + thickness;
splash.outerRadVel = vel;
splash.heightSpeed = 128;
splash.height = 0;
splash.heightVel = -16;
float t = vel / (splashVelocity / 2) + 16;
t = fmax(0, fmin(t, 1));
splash.life = lerp(48, 70, t);
splash.spriteSequenceStart = 4; //Splash Texture
splash.spriteSequenceEnd = 7; //Splash Texture
splash.animationSpeed = frandMinMax(0.05f, 0.15f);
break;
numSplashesSetup++;
}
if (numSplashesSetup == NUM_SPLASHES) {
break;
}
continue;
}
}
SoundEffect(SFX_LARA_SPLASH, (PHD_3DPOS*)setup, 0);
}
@ -1039,60 +1070,30 @@ void UpdateSplashes()
{
for (int i = 0; i < MAX_SPLASH; i++)
{
SPLASH_STRUCT* splash = &Splashes[i];
if (splash->flags & 1)
{
splash->innerRad += splash->innerRadVel >> 5;
splash->innerSize += splash->innerRadVel >> 6;
splash->innerRadVel -= (splash->innerRadVel >> 6);
splash->middleRad += splash->middleRadVel >> 5;
splash->middleSize += splash->middleRadVel >> 6;
splash->middleRadVel -= splash->middleRadVel >> 6;
splash->outerRad += splash->outerRadVel >> 5;
splash->outerSize += splash->outerRadVel >> 6;
splash->outerRadVel -= splash->outerRadVel >> 6;
splash->innerY += splash->innerYVel >> 4;
splash->innerYVel += 1024;
if (splash->innerYVel > 16384)
splash->innerYVel = 16384;
if (splash->innerY < 0)
{
if (splash->innerY < -28672)
splash->innerY = -28672;
SPLASH_STRUCT& splash = Splashes[i];
if (splash.isActive) {
splash.life--;
if (splash.life <= 0) {
splash.isActive = false;
}
else
{
splash->innerY = 0;
splash->flags |= 4;
splash->life -= 2;
if (splash->life == 0)
splash->flags = 0;
splash.heightSpeed += splash.heightVel;
splash.height += splash.heightSpeed;
if (splash.height < 0) {
splash.height = 0;
if (!splash.isRipple) {
splash.isActive = false;
}
}
splash->middleY += splash->middleYVel >> 4;
splash->middleYVel += 896;
if (splash->middleYVel > 16384)
splash->middleYVel = 16384;
if (splash->middleY < 0)
{
if (splash->middleY < -28672)
splash->middleY = -28672;
}
else
{
splash->middleY = 0;
splash->flags |= 8;
splash.innerRad += splash.innerRadVel;
splash.outerRad += splash.outerRadVel;
splash.animationPhase += splash.animationSpeed;
short sequenceLength = splash.spriteSequenceEnd - splash.spriteSequenceStart;
if (splash.animationPhase > sequenceLength) {
splash.animationPhase = fmod(splash.animationPhase, sequenceLength);
}
}
}
for (int i = 0; i < MAX_RIPPLES; i++)
@ -1389,17 +1390,8 @@ void WadeSplash(ITEM_INFO* item, int wh, int wd)
SplashSetup.y = wh;
SplashSetup.x = item->pos.xPos;
SplashSetup.z = item->pos.zPos;
SplashSetup.innerRad = 16;
SplashSetup.innerSize = 12;
SplashSetup.innerRadVel = 160;
SplashSetup.innerYVel = -72 * item->fallspeed;
SplashSetup.middleRad = 24;
SplashSetup.middleSize = 24;
SplashSetup.middleRadVel = 224;
SplashSetup.middleYVel = -36 * item->fallspeed;
SplashSetup.outerRad = 32;
SplashSetup.outerSize = 32;
SplashSetup.outerRadVel = 272;
SplashSetup.innerRadius = 16;
SplashSetup.splashPower = item->speed;
SetupSplash(&SplashSetup);
SplashCount = 16;
}
@ -1421,17 +1413,8 @@ void Splash(ITEM_INFO* item)
SplashSetup.y = wh;
SplashSetup.x = item->pos.xPos;
SplashSetup.z = item->pos.zPos;
SplashSetup.innerRad = 32;
SplashSetup.innerSize = 8;
SplashSetup.innerRadVel = 320;
SplashSetup.innerYVel = -40 * item->fallspeed;
SplashSetup.middleRad = 48;
SplashSetup.middleSize = 32;
SplashSetup.middleRadVel = 480;
SplashSetup.middleYVel = -20 * item->fallspeed;
SplashSetup.outerRad = 32;
SplashSetup.outerSize = 128;
SplashSetup.outerRadVel = 544;
SplashSetup.splashPower = item->fallspeed;
SplashSetup.innerRadius = 64;
SetupSplash(&SplashSetup);
}
}
@ -1952,5 +1935,4 @@ void Inject_Effect2()
INJECT(0x00431530, ClearDynamicLights);
INJECT(0x00432A30, WadeSplash);
INJECT(0x00432900, Splash);
INJECT(0x00430620, SetupSplash);
}

View file

@ -23,7 +23,7 @@
//#define ControlWaterfallMist ((void (__cdecl*)(short)) 0x00432CA0)
//#define TriggerRicochetSparks ((void (__cdecl*)(GAME_VECTOR*, short, int, int)) 0x0042F060)
extern SPLASH_STRUCT Splashes[4];
extern SPLASH_STRUCT Splashes[MAX_SPLASH];
extern RIPPLE_STRUCT Ripples[32];
extern int DeadlyBounds[6];
extern SPARKS Sparks[1024];
@ -43,7 +43,7 @@ void TriggerExplosionSmokeEnd(int x, int y, int z, int uw);
void TriggerExplosionSmoke(int x, int y, int z, int uw);
void TriggerFireFlame(int x, int y, int z, int fxObj, int type);
void TriggerSuperJetFlame(ITEM_INFO* item, int yvel, int deadly);
void SetupSplash(SPLASH_SETUP* setup);
void SetupSplash(const SPLASH_SETUP* const setup);
void UpdateSplashes();
void SetupRipple(int x, int y, int z, char size, char flags);
void TriggerUnderwaterBlood(int x, int y, int z, int sizeme);
@ -59,6 +59,4 @@ void GrenadeExplosionEffects(int x, int y, int z, short roomNumber);
void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, int additional);
void WadeSplash(ITEM_INFO* item, int wh, int wd);
void Splash(ITEM_INFO* item);
void SetupSplash(SPLASH_SETUP* setup);
void Inject_Effect2();

View file

@ -1442,18 +1442,8 @@ void TriggerUnderwaterExplosion(ITEM_INFO* item)
SplashSetup.y = wh;
SplashSetup.x = item->pos.xPos;
SplashSetup.z = item->pos.zPos;
SplashSetup.innerRadVel = 160;
SplashSetup.middleRadVel = 224;
SplashSetup.outerRadVel = 272;
SplashSetup.innerRad = (2048 - dy) >> 6 + 16;
SplashSetup.innerSize = (2048 - dy) >> 6 + 12;
SplashSetup.innerYVel = 8 * (-512 - (2048 - dy));
SplashSetup.middleRad = (2048 - dy) >> 6 + 24;
SplashSetup.middleSize = (2048 - dy) >> 6 + 24;
SplashSetup.middleYVel = 4 * (-768 - (2048 - dy));
SplashSetup.outerRad = (2048 - dy) >> 6 + 32;
SplashSetup.outerSize = (2048 - dy) >> 6 + 32;
SplashSetup.innerRadius = 160;
SplashSetup.splashPower = 2048 - dy;
SetupSplash(&SplashSetup);
}
}

View file

@ -7,6 +7,7 @@
#include "laraswim.h"
#include "larasurf.h"
#include "effect2.h"
#include "misc.h"
extern LaraExtraInfo g_LaraExtra;
extern GameFlow* g_GameFlow;
@ -137,7 +138,7 @@ void LaraControl(short itemNumber)//4A838, 4AC9C
Lara.isDucked = 0;
bool isWater = Rooms[item->roomNumber].flags & ENV_FLAG_WATER;
bool isWater = Rooms[item->roomNumber].flags & (ENV_FLAG_WATER|ENV_FLAG_SWAMP);
int wd = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
int wh = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
@ -162,10 +163,22 @@ void LaraControl(short itemNumber)//4A838, 4AC9C
{
Lara.waterStatus = LW_WADE;
if (!(item->gravityStatus))
{
item->goalAnimState = STATE_LARA_STOP;
}
else if (isWater & ENV_FLAG_SWAMP)
{
if (item->currentAnimState == STATE_LARA_SWANDIVE_BEGIN || item->currentAnimState == STATE_LARA_SWANDIVE_END) // Is Lara swan-diving?
item->pos.yPos = wh + 1000;
item->goalAnimState = STATE_LARA_WADE_FORWARD;
item->currentAnimState = STATE_LARA_WADE_FORWARD;
item->animNumber = ANIMATION_LARA_WADE;
item->frameNumber = GF(ANIMATION_LARA_WADE, 0);
}
}
}
else if (isWater)
else if (!(isWater & ENV_FLAG_SWAMP))
{
Lara.air = 1800;
Lara.waterStatus = LW_UNDERWATER;
@ -388,7 +401,7 @@ void LaraControl(short itemNumber)//4A838, 4AC9C
Camera.targetElevation = -ANGLE(22);
if (hfw >= 256)
{
if (hfw > 730)
if (hfw > 730 && !(isWater & ENV_FLAG_SWAMP))
{
Lara.waterStatus = LW_SURFACE;
item->pos.yPos += 1 - hfw;
@ -471,7 +484,20 @@ void LaraControl(short itemNumber)//4A838, 4AC9C
{
case LW_ABOVE_WATER:
case LW_WADE:
if (Lara.gassed)
if (Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -775)
{
if (item->hitPoints >= 0)
{
Lara.air -= 6;
if (Lara.air < 0)
{
Lara.air = -1;
item->hitPoints -= 10;
}
}
}
else if (Lara.gassed)
{
if (item->hitPoints >= 0 && --Lara.air < 0)
{
@ -483,10 +509,14 @@ void LaraControl(short itemNumber)//4A838, 4AC9C
}
else if (Lara.air < 1800 && item->hitPoints >= 0)
{
Lara.air += 10;
if (Lara.air > 1800)
Lara.air = 1800;
}
/* lara is not equipped with any vehicle */
if (g_LaraExtra.Vehicle == NO_ITEM) // only for the upv !!
{
Lara.air += 10;
if (Lara.air > 1800)
Lara.air = 1800;
}
}
LaraAboveWater(item, &coll);
break;
@ -832,8 +862,8 @@ void AnimateLara(ITEM_INFO* item)
flags = cmd[1] & 0xC000;
if (flags == SFX_LANDANDWATER ||
(flags == SFX_LANDONLY && (Lara.waterSurfaceDist >= 0 || Lara.waterSurfaceDist == NO_HEIGHT)) ||
(flags == SFX_WATERONLY && Lara.waterSurfaceDist < 0 && Lara.waterSurfaceDist != NO_HEIGHT /*&& !(Rooms[lara_item->room_number].flags & SWAMP)*/))
(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)))
{
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
}
@ -864,75 +894,57 @@ void AnimateLara(ITEM_INFO* item)
int lateral = anim->Xvelocity;
if (anim->Xacceleration)
lateral += anim->Xacceleration * (item->frameNumber - anim->frameBase);
lateral >>= 16;
if (item->gravityStatus)
if (item->gravityStatus) // If gravity ON (Do Up/Down movement)
{
int velocity = (anim->velocity + anim->acceleration * (item->frameNumber - anim->frameBase - 1));
item->speed -= velocity >> 16;
item->speed += (velocity + anim->acceleration) >> 16;
item->fallspeed += (item->fallspeed >= 128 ? 1 : 6);
item->pos.yPos += item->fallspeed;
if (Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)
{
item->speed -= item->speed >> 3;
if (abs(item->speed) < 8)
{
item->speed = 0;
item->gravityStatus = false;
}
if (item->fallspeed > 128)
item->fallspeed >>= 1;
item->fallspeed -= item->fallspeed >> 2;
if (item->fallspeed < 4)
item->fallspeed = 4;
item->pos.yPos += item->fallspeed;
}
else
{
int velocity = (anim->velocity + anim->acceleration * (item->frameNumber - anim->frameBase - 1));
item->speed -= velocity >> 16;
item->speed += (velocity + anim->acceleration) >> 16;
item->fallspeed += (item->fallspeed >= 128 ? 1 : GRAVITY);
item->pos.yPos += item->fallspeed;
}
}
else
else // if on the Ground...
{
int velocity = anim->velocity;
if (anim->acceleration)
velocity += anim->acceleration * (item->frameNumber - anim->frameBase);
int velocity;
if (Lara.waterStatus == LW_WADE && Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)
{
velocity = anim->velocity >> 1;
if (anim->acceleration)
velocity += anim->acceleration * (item->frameNumber - anim->frameBase) >> 2;
}
else
{
velocity = anim->velocity;
if (anim->acceleration)
velocity += anim->acceleration * (item->frameNumber - anim->frameBase);
}
item->speed = velocity >> 16;
}
/*if (lara.RopePtr != -1)
result = j_SomeRopeCollisionFunc(item);*/
/*
if ( !item->gravity_status ) // Calculate absolute new velocities
{ // if on the Ground...
if (lara.water_status==LARA_WADE && (room[item->room_number].flags & SWAMP))
{
speed = anim->velocity>>1;
if ( anim->acceleration )
speed += (anim->acceleration * (item->frame_number - anim->frame_base))>>2;
item->speed = (sint16)(speed >> 16);
}
else
{
speed = anim->velocity;
if ( anim->acceleration )
speed += anim->acceleration * (item->frame_number - anim->frame_base);
item->speed = (sint16)(speed >> 16);
}
}
else // If gravity ON
{ // do Up/down movement
if (room[item->room_number].flags & SWAMP)
{
item->speed -= item->speed>>3;
if (abs(item->speed)<8)
{
item->speed = 0;
item->gravity_status = 0;
}
if (item->fallspeed > 128)
item->fallspeed >>= 1;
item->fallspeed -= item->fallspeed>>2;
if (item->fallspeed < 4)
item->fallspeed = 4;
item->pos.y_pos += item->fallspeed;
}
else
{
speed = anim->velocity + anim->acceleration * (item->frame_number - anim->frame_base - 1);
item->speed -= (sint16)(speed>>16);
speed += anim->acceleration;
item->speed += (sint16)(speed>>16);
item->fallspeed += (item->fallspeed<FASTFALL_SPEED) ? GRAVITY : 1;
item->pos.y_pos += item->fallspeed;
}
}
*/
if (!Lara.isMoving)
{
item->pos.xPos += item->speed * SIN(Lara.moveAngle) >> W2V_SHIFT;

View file

@ -439,32 +439,33 @@ void UpdateSmoke()
int dl = ((spark->sLife - spark->life) << 16) / spark->sLife;
spark->yVel += spark->gravity;
if (spark->maxYvel)
spark->yVel -= spark->gravity.to_float();
if (spark->maxYvel != 0)
{
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 & 0xF)
{
spark->xVel -= spark->xVel >> (spark->friction & 0xF);
spark->zVel -= spark->zVel >> (spark->friction & 0xF);
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();
}
}
}
if (spark->friction & 0xF0)
spark->yVel -= spark->yVel >> (spark->friction >> 4);
spark->x += spark->xVel >> 5;
spark->y += spark->yVel >> 5;
spark->z += spark->zVel >> 5;
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();
if (spark->flags & SP_WIND)
{
spark->x += SmokeWindX >> 1;
spark->z += SmokeWindZ >> 1;
spark->z += SmokeWindZ>>1;
}
spark->size = spark->sSize + (dl * (spark->dSize - spark->sSize) >> 16);
@ -519,9 +520,10 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini
}
else
{
spark->xVel = ((GetRandomControl() & 511) - 256) >> 1;
spark->yVel = ((GetRandomControl() & 511) - 256) >> 1;
spark->zVel = ((GetRandomControl() & 511) - 256) >> 1;
float f = (frand() * 6) - 3;
spark->xVel = (frand() * 6) - 3;
spark->yVel = (frand() * 6) - 3;
spark->zVel = (frand() * 6) - 3;
}
spark->friction = 4;
@ -548,9 +550,9 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini
{
spark->flags = 0;
}
spark->gravity = -(GetRandomControl() & 1) - 2;
spark->maxYvel = -(GetRandomControl() & 1) - 2;
float gravity = frand() * 1.25f;
spark->gravity = gravity;
spark->maxYvel = frand() * 16;
byte size = ((GetRandomControl() & 0x0F) + 24); // -TriggerGunSmoke_SubFunction(weaponType);
@ -942,9 +944,9 @@ void UpdateGunShells()
gs->pos.yRot += gs->speed * ANGLE(1);
gs->pos.zRot += ANGLE(23);
gs->pos.xPos += gs->speed * 2 * SIN(gs->dirXrot) >> W2V_SHIFT;
gs->pos.xPos += gs->speed * SIN(gs->dirXrot) >> W2V_SHIFT;
gs->pos.yPos += gs->fallspeed;
gs->pos.zPos += gs->speed * 2 * COS(gs->dirXrot) >> W2V_SHIFT;
gs->pos.zPos += gs->speed * COS(gs->dirXrot) >> W2V_SHIFT;
FLOOR_INFO* floor = GetFloor(gs->pos.xPos, gs->pos.yPos, gs->pos.zPos, &gs->roomNumber);
if (Rooms[gs->roomNumber].flags & ENV_FLAG_WATER
@ -1072,12 +1074,12 @@ void CreateBubble(PHD_VECTOR * pos, short roomNum, int unk1, int unk2, int flags
BUBBLE_STRUCT* bubble = &Bubbles[GetFreeBubble()];
bubble->pos = *pos;
bubble->roomNumber = roomNum;
bubble->speed = GetRandomControl() + 64;
bubble->speed = frand();
bubble->shade = 0;
int size = 2 * (unk1 + (unk2 & GetRandomControl()));
int size = rand() % 4 + 6;
bubble->size = size;
bubble->dsize = 16 * size;
bubble->vel = (GetRandomControl() & 0x1F) + 32;
bubble->vel = (frand()*0.8f)+0.2f;
bubble->flags = flags;
bubble->xVel = xv;
bubble->yVel = yv;
@ -1125,24 +1127,24 @@ void UpdateBubbles()
if (bubble->size)
{
bubble->speed += bubble->vel;
bubble->speed += bubble->vel.to_float();
bubble->yRot += 6;
bubble->pos.y -= bubble->speed >> 8;
bubble->pos.y -= bubble->speed.to_float();
if (bubble->flags & 1)
{
bubble->pos.x += bubble->xVel >> 4;
bubble->pos.y += bubble->yVel >> 4;
bubble->pos.z += bubble->zVel >> 4;
bubble->pos.x += bubble->xVel.to_float();
bubble->pos.y += bubble->yVel.to_float();
bubble->pos.z += bubble->zVel.to_float();
bubble->xVel -= (bubble->xVel >> 3);
bubble->yVel -= (bubble->yVel >> 3);
bubble->zVel -= (bubble->zVel >> 3);
bubble->xVel -= (bubble->xVel.to_float()/2.0f);
bubble->yVel -= (bubble->yVel.to_float()/2.0f);
bubble->zVel -= (bubble->zVel.to_float()/2.0f);
}
else
{
bubble->pos.x += SIN(bubble->yRot) >> W2V_SHIFT;
bubble->pos.z += COS(bubble->yRot) >> W2V_SHIFT;
bubble->pos.x += sin(bubble->yRot)*5;
bubble->pos.z += cos(bubble->yRot)*5;
}
short roomNumber = bubble->roomNumber;
@ -1910,16 +1912,6 @@ void TriggerSmallSplash(int x, int y, int z, int num)// (F)
}
}
void SetFadeClip(short height, short speed)
{
/*__int16 result; // ax
result = a1;
DestFadeScreenHeight = a1;
FadeClipSpeed = a2;
return result;*/
}
void Inject_Tomb4FX()
{
INJECT(0x004827E0, TriggerBlood);

View file

@ -69,7 +69,7 @@
#define MAX_DRIPS 32
#define MAX_BUBBLES 40
#define MAX_DYNAMICS 64
#define MAX_SPLASH 4
constexpr auto MAX_SPLASH = 8;
#define MAX_RIPPLES 32
#define MAX_CAMERA 18
#define MAX_SHOCKWAVE 16

View file

@ -12,3 +12,19 @@ float ANGLEF(short angle)
{
return TR_ANGLE_TO_DEGREES(angle);
}
const float frand() {
int randValue = rand();
float result = randValue / (float)RAND_MAX;
return result;
}
const float frandMinMax(float min, float max)
{
return frand()* (max - min) + min;
}
const float lerp(float v0, float v1, float t) {
return (1 - t) * v0 + t * v1;
}

View file

@ -24,4 +24,10 @@
#define COS(x) (4 * rcossin_tbl[((int(x) >> 3) & 8190) + 1])
short ANGLE(double angle);
float ANGLEF(short angle);
float ANGLEF(short angle);
// returns a float between 0-1
const float frand();
const float frandMinMax(float min, float max);
const float lerp(float v0, float v1, float t);

View file

@ -2,6 +2,7 @@
#include <Windows.h>
#include "enums.h"
#include <fixed_point.h>
#pragma pack(push, 1)
typedef enum TYPE_ZONE
{
@ -1012,39 +1013,38 @@ struct BUBBLE_STRUCT
{
PHD_VECTOR pos; // size=12, offset=0
short roomNumber; // size=0, offset=12
short speed; // size=0, offset=14
numeric::Fixed<9, 7> speed; // size=0, offset=14
short size; // size=0, offset=16
short dsize; // size=0, offset=18
unsigned char shade; // size=0, offset=20
unsigned char vel; // size=0, offset=21
numeric::Fixed<4, 4> vel; // size=0, offset=21
unsigned char yRot; // size=0, offset=22
byte flags; // size=0, offset=23
short xVel; // size=0, offset=24
short yVel; // size=0, offset=26
short zVel; // size=0, offset=28
numeric::Fixed<6,2> xVel; // size=0, offset=24
numeric::Fixed<6, 2> yVel; // size=0, offset=26
numeric::Fixed<6, 2> zVel; // size=0, offset=28
short pad; // size=0, offset=30
};
struct SPLASH_STRUCT
{
int x; // size=0, offset=0
int y; // size=0, offset=4
int z; // size=0, offset=8
short innerRad; // size=0, offset=12
short innerSize; // size=0, offset=14
short innerRadVel; // size=0, offset=16
short innerYVel; // size=0, offset=18
short innerY; // size=0, offset=20
short middleRad; // size=0, offset=22
short middleSize; // size=0, offset=24
short middleRadVel; // size=0, offset=26
short middleYVel; // size=0, offset=28
short middleY; // size=0, offset=30
short outerRad; // size=0, offset=32
short outerSize; // size=0, offset=34
short outerRadVel; // size=0, offset=36
byte flags; // size=0, offset=38
unsigned char life; // size=0, offset=39
float x;
float y;
float z;
float innerRad;
float innerRadVel;
float heightVel;
float heightSpeed;
float height;
float outerRad;
float outerRadVel;
float animationSpeed;
float animationPhase;
short spriteSequenceStart;
short spriteSequenceEnd;
unsigned short life;
bool isRipple;
bool isActive;
};
struct DRIP_STRUCT
@ -1077,23 +1077,11 @@ struct RIPPLE_STRUCT
struct SPLASH_SETUP
{
int x; // size=0, offset=0
int y; // size=0, offset=4
int z; // size=0, offset=8
short innerRad; // size=0, offset=12
short innerSize; // size=0, offset=14
short innerRadVel; // size=0, offset=16
short innerYVel; // size=0, offset=18
short pad1; // size=0, offset=20
short middleRad; // size=0, offset=22
short middleSize; // size=0, offset=24
short middleRadVel; // size=0, offset=26
short middleYVel; // size=0, offset=28
short pad2; // size=0, offset=30
short outerRad; // size=0, offset=32
short outerSize; // size=0, offset=34
short outerRadVel; // size=0, offset=36
short pad3; // size=0, offset=38
float x;
float y;
float z;
float splashPower;
float innerRadius;
};
struct FIRE_LIST
@ -1146,20 +1134,20 @@ struct SMOKE_SPARKS
int x; // size=0, offset=0
int y; // size=0, offset=4
int z; // size=0, offset=8
short xVel; // size=0, offset=12
short yVel; // size=0, offset=14
short zVel; // size=0, offset=16
short gravity; // size=0, offset=18
numeric::Fixed<12 ,4> xVel; // size=0, offset=12
numeric::Fixed<12, 4> yVel; // size=0, offset=14
numeric::Fixed<12, 4> zVel; // size=0, offset=16
numeric::Fixed<8, 8> gravity; // size=0, offset=18
short rotAng; // size=0, offset=20
short flags; // size=0, offset=22
byte sSize; // size=0, offset=24
byte dSize; // size=0, offset=25
byte size; // size=0, offset=26
byte friction; // size=0, offset=27
numeric::Fixed<2,6> friction; // size=0, offset=27
byte scalar; // size=0, offset=28
byte def; // size=0, offset=29
byte rotAdd; // size=0, offset=30
byte maxYvel; // size=0, offset=31
numeric::Fixed<4, 4> maxYvel; // size=0, offset=31
byte on; // size=0, offset=32
byte sShade; // size=0, offset=33
byte dShade; // size=0, offset=34

View file

@ -0,0 +1,574 @@
// From: https://github.com/eteran/cpp-utilities/blob/master/fixed/include/eteran/cpp-utilities/Fixed.h
// See also: http://stackoverflow.com/questions/79677/whats-the-best-way-to-do-fixed-point-math
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Evan Teran
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef FIXED_H_
#define FIXED_H_
#if __cplusplus >= 201402L
#define CONSTEXPR14 constexpr
#else
#define CONSTEXPR14
#endif
#include <ostream>
#include <exception>
#include <cstddef> // for size_t
#include <cstdint>
#include <type_traits>
namespace numeric {
template <size_t I, size_t F>
class Fixed;
namespace detail {
// helper templates to make magic with types :)
// these allow us to determine resonable types from
// a desired size, they also let us infer the next largest type
// from a type which is nice for the division op
template <size_t T>
struct type_from_size {
static constexpr bool is_specialized = false;
};
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
template <>
struct type_from_size<128> {
static constexpr bool is_specialized = true;
static constexpr size_t size = 128;
using value_type = __int128;
using unsigned_type = unsigned __int128;
using signed_type = __int128;
using next_size = type_from_size<256>;
};
#endif
template <>
struct type_from_size<64> {
static constexpr bool is_specialized = true;
static constexpr size_t size = 64;
using value_type = int64_t;
using unsigned_type = std::make_unsigned<value_type>::type;
using signed_type = std::make_signed<value_type>::type;
using next_size = type_from_size<128>;
};
template <>
struct type_from_size<32> {
static constexpr bool is_specialized = true;
static constexpr size_t size = 32;
using value_type = int32_t;
using unsigned_type = std::make_unsigned<value_type>::type;
using signed_type = std::make_signed<value_type>::type;
using next_size = type_from_size<64>;
};
template <>
struct type_from_size<16> {
static constexpr bool is_specialized = true;
static constexpr size_t size = 16;
using value_type = int16_t;
using unsigned_type = std::make_unsigned<value_type>::type;
using signed_type = std::make_signed<value_type>::type;
using next_size = type_from_size<32>;
};
template <>
struct type_from_size<8> {
static constexpr bool is_specialized = true;
static constexpr size_t size = 8;
using value_type = int8_t;
using unsigned_type = std::make_unsigned<value_type>::type;
using signed_type = std::make_signed<value_type>::type;
using next_size = type_from_size<16>;
};
// this is to assist in adding support for non-native base
// types (for adding big-int support), this should be fine
// unless your bit-int class doesn't nicely support casting
template <class B, class N>
constexpr B next_to_base(N rhs) {
return static_cast<B>(rhs);
}
struct divide_by_zero : std::exception {
};
template <size_t I, size_t F>
CONSTEXPR14 Fixed<I, F> divide(Fixed<I, F> numerator, Fixed<I, F> denominator, Fixed<I, F>& remainder, typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type * = nullptr) {
using next_type = typename Fixed<I, F>::next_type;
using base_type = typename Fixed<I, F>::base_type;
constexpr size_t fractional_bits = Fixed<I, F>::fractional_bits;
next_type t(numerator.to_raw());
t <<= fractional_bits;
Fixed<I, F> quotient;
quotient = Fixed<I, F>::from_base(next_to_base<base_type>(t / denominator.to_raw()));
remainder = Fixed<I, F>::from_base(next_to_base<base_type>(t % denominator.to_raw()));
return quotient;
}
template <size_t I, size_t F>
CONSTEXPR14 Fixed<I, F> divide(Fixed<I, F> numerator, Fixed<I, F> denominator, Fixed<I, F> & remainder, typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type * = nullptr) {
// NOTE(eteran): division is broken for large types :-(
// especially when dealing with negative quantities
using base_type = typename Fixed<I, F>::base_type;
using unsigned_type = typename Fixed<I, F>::unsigned_type;
constexpr int bits = Fixed<I, F>::total_bits;
if (denominator == 0) {
throw divide_by_zero();
}
else {
int sign = 0;
Fixed<I, F> quotient;
if (numerator < 0) {
sign ^= 1;
numerator = -numerator;
}
if (denominator < 0) {
sign ^= 1;
denominator = -denominator;
}
base_type n = numerator.to_raw();
base_type d = denominator.to_raw();
base_type x = 1;
base_type answer = 0;
// egyptian division algorithm
while ((n >= d) && (((d >> (bits - 1)) & 1) == 0)) {
x <<= 1;
d <<= 1;
}
while (x != 0) {
if (n >= d) {
n -= d;
answer += x;
}
x >>= 1;
d >>= 1;
}
unsigned_type l1 = n;
unsigned_type l2 = denominator.to_raw();
// calculate the lower bits (needs to be unsigned)
// unfortunately for many fractions this overflows the type still :-/
const unsigned_type lo = (static_cast<unsigned_type>(n) << F) / denominator.to_raw();
quotient = Fixed<I, F>::from_base((answer << F) | lo);
remainder = n;
if (sign) {
quotient = -quotient;
}
return quotient;
}
}
// this is the usual implementation of multiplication
template <size_t I, size_t F>
CONSTEXPR14 Fixed<I, F> multiply(Fixed<I, F> lhs, Fixed<I, F> rhs, typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type * = nullptr) {
using next_type = typename Fixed<I, F>::next_type;
using base_type = typename Fixed<I, F>::base_type;
constexpr size_t fractional_bits = Fixed<I, F>::fractional_bits;
next_type t(static_cast<next_type>(lhs.to_raw()) * static_cast<next_type>(rhs.to_raw()));
t >>= fractional_bits;
return Fixed<I, F>::from_base(next_to_base<base_type>(t));
}
// this is the fall back version we use when we don't have a next size
// it is slightly slower, but is more robust since it doesn't
// require and upgraded type
template <size_t I, size_t F>
CONSTEXPR14 Fixed<I, F> multiply(Fixed<I, F> lhs, Fixed<I, F> rhs, typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type * = nullptr) {
using base_type = typename Fixed<I, F>::base_type;
constexpr size_t fractional_bits = Fixed<I, F>::fractional_bits;
constexpr base_type integer_mask = Fixed<I, F>::integer_mask;
constexpr base_type fractional_mask = Fixed<I, F>::fractional_mask;
// more costly but doesn't need a larger type
constexpr base_type a_hi = (lhs.to_raw() & integer_mask) >> fractional_bits;
constexpr base_type b_hi = (rhs.to_raw() & integer_mask) >> fractional_bits;
constexpr base_type a_lo = (lhs.to_raw() & fractional_mask);
constexpr base_type b_lo = (rhs.to_raw() & fractional_mask);
constexpr base_type x1 = a_hi * b_hi;
constexpr base_type x2 = a_hi * b_lo;
constexpr base_type x3 = a_lo * b_hi;
constexpr base_type x4 = a_lo * b_lo;
return Fixed<I, F>::from_base((x1 << fractional_bits) + (x3 + x2) + (x4 >> fractional_bits));
}
}
template <size_t I, size_t F>
class Fixed {
static_assert(detail::type_from_size<I + F>::is_specialized, "invalid combination of sizes");
public:
static constexpr size_t fractional_bits = F;
static constexpr size_t integer_bits = I;
static constexpr size_t total_bits = I + F;
using base_type_info = detail::type_from_size<total_bits>;
using base_type = typename base_type_info::value_type;
using next_type = typename base_type_info::next_size::value_type;
using unsigned_type = typename base_type_info::unsigned_type;
public:
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverflow"
#endif
static constexpr base_type fractional_mask = ~(static_cast<unsigned_type>(~base_type(0)) << fractional_bits);
static constexpr base_type integer_mask = ~fractional_mask;
#ifdef __GNUC__
#pragma GCC diagnostic push
#endif
public:
static constexpr base_type one = base_type(1) << fractional_bits;
public: // constructors
Fixed() = default;
Fixed(const Fixed&) = default;
Fixed & operator=(const Fixed&) = default;
template <class Number>
constexpr Fixed(Number n, typename std::enable_if<std::is_arithmetic<Number>::value>::type * = nullptr) : data_(static_cast<base_type>(n * one)) {
}
public: // conversion
template <size_t I2, size_t F2>
CONSTEXPR14 explicit Fixed(Fixed<I2, F2> other) {
static_assert(I2 <= I && F2 <= F, "Scaling conversion can only upgrade types");
using T = Fixed<I2, F2>;
const base_type fractional = (other.data_ & T::fractional_mask);
const base_type integer = (other.data_ & T::integer_mask) >> T::fractional_bits;
data_ = (integer << fractional_bits) | (fractional << (fractional_bits - T::fractional_bits));
}
private:
// this makes it simpler to create a fixed point object from
// a native type without scaling
// use "Fixed::from_base" in order to perform this.
struct NoScale {};
constexpr Fixed(base_type n, const NoScale&) : data_(n) {
}
public:
constexpr static Fixed from_base(base_type n) {
return Fixed(n, NoScale());
}
public: // comparison operators
constexpr bool operator==(Fixed rhs) const {
return data_ == rhs.data_;
}
constexpr bool operator!=(Fixed rhs) const {
return data_ != rhs.data_;
}
constexpr bool operator<(Fixed rhs) const {
return data_ < rhs.data_;
}
constexpr bool operator>(Fixed rhs) const {
return data_ > rhs.data_;
}
constexpr bool operator<=(Fixed rhs) const {
return data_ <= rhs.data_;
}
constexpr bool operator>=(Fixed rhs) const {
return data_ >= rhs.data_;
}
public: // unary operators
constexpr bool operator!() const {
return !data_;
}
constexpr Fixed operator~() const {
// NOTE(eteran): this will often appear to "just negate" the value
// that is not an error, it is because -x == (~x+1)
// and that "+1" is adding an infinitesimally small fraction to the
// complimented value
return Fixed::from_base(~data_);
}
constexpr Fixed operator-() const {
return Fixed::from_base(-data_);
}
constexpr Fixed operator+() const {
return Fixed::from_base(+data_);
}
CONSTEXPR14 Fixed& operator++() {
data_ += one;
return *this;
}
CONSTEXPR14 Fixed& operator--() {
data_ -= one;
return *this;
}
CONSTEXPR14 Fixed operator++(int) {
Fixed tmp(*this);
data_ += one;
return tmp;
}
CONSTEXPR14 Fixed operator--(int) {
Fixed tmp(*this);
data_ -= one;
return tmp;
}
public: // basic math operators
CONSTEXPR14 Fixed& operator+=(Fixed n) {
data_ += n.data_;
return *this;
}
CONSTEXPR14 Fixed& operator-=(Fixed n) {
data_ -= n.data_;
return *this;
}
CONSTEXPR14 Fixed& operator*=(Fixed n) {
return assign(detail::multiply(*this, n));
}
CONSTEXPR14 Fixed& operator/=(Fixed n) {
Fixed temp;
return assign(detail::divide(*this, n, temp));
}
private:
CONSTEXPR14 Fixed& assign(Fixed rhs) {
data_ = rhs.data_;
return *this;
}
public: // binary math operators, effects underlying bit pattern since these
// don't really typically make sense for non-integer values
CONSTEXPR14 Fixed& operator&=(Fixed n) {
data_ &= n.data_;
return *this;
}
CONSTEXPR14 Fixed& operator|=(Fixed n) {
data_ |= n.data_;
return *this;
}
CONSTEXPR14 Fixed& operator^=(Fixed n) {
data_ ^= n.data_;
return *this;
}
template <class Integer, class = typename std::enable_if<std::is_integral<Integer>::value>::type>
CONSTEXPR14 Fixed & operator>>=(Integer n) {
data_ >>= n;
return *this;
}
template <class Integer, class = typename std::enable_if<std::is_integral<Integer>::value>::type>
CONSTEXPR14 Fixed & operator<<=(Integer n) {
data_ <<= n;
return *this;
}
public: // conversion to basic types
constexpr int to_int() const {
return (data_ & integer_mask) >> fractional_bits;
}
constexpr unsigned int to_uint() const {
return (data_ & integer_mask) >> fractional_bits;
}
constexpr float to_float() const {
return static_cast<float>(data_) / Fixed::one;
}
constexpr double to_double() const {
return static_cast<double>(data_) / Fixed::one;
}
constexpr base_type to_raw() const {
return data_;
}
public:
CONSTEXPR14 void swap(Fixed & rhs) {
using std::swap;
swap(data_, rhs.data_);
}
public:
base_type data_ = 0;
};
// if we have the same fractional portion, but differing integer portions, we trivially upgrade the smaller type
template <size_t I1, size_t I2, size_t F>
CONSTEXPR14 typename std::conditional<I1 >= I2, Fixed<I1, F>, Fixed<I2, F>>::type operator+(Fixed<I1, F> lhs, Fixed<I2, F> rhs) {
using T = typename std::conditional<
I1 >= I2,
Fixed<I1, F>,
Fixed<I2, F>
>::type;
const T l = T::from_base(lhs.to_raw());
const T r = T::from_base(rhs.to_raw());
return l + r;
}
template <size_t I1, size_t I2, size_t F>
CONSTEXPR14 typename std::conditional<I1 >= I2, Fixed<I1, F>, Fixed<I2, F>>::type operator-(Fixed<I1, F> lhs, Fixed<I2, F> rhs) {
using T = typename std::conditional<
I1 >= I2,
Fixed<I1, F>,
Fixed<I2, F>
>::type;
const T l = T::from_base(lhs.to_raw());
const T r = T::from_base(rhs.to_raw());
return l - r;
}
template <size_t I1, size_t I2, size_t F>
CONSTEXPR14 typename std::conditional<I1 >= I2, Fixed<I1, F>, Fixed<I2, F>>::type operator*(Fixed<I1, F> lhs, Fixed<I2, F> rhs) {
using T = typename std::conditional<
I1 >= I2,
Fixed<I1, F>,
Fixed<I2, F>
>::type;
const T l = T::from_base(lhs.to_raw());
const T r = T::from_base(rhs.to_raw());
return l * r;
}
template <size_t I1, size_t I2, size_t F>
CONSTEXPR14 typename std::conditional<I1 >= I2, Fixed<I1, F>, Fixed<I2, F>>::type operator/(Fixed<I1, F> lhs, Fixed<I2, F> rhs) {
using T = typename std::conditional<
I1 >= I2,
Fixed<I1, F>,
Fixed<I2, F>
>::type;
const T l = T::from_base(lhs.to_raw());
const T r = T::from_base(rhs.to_raw());
return l / r;
}
template <size_t I, size_t F>
std::ostream& operator<<(std::ostream & os, Fixed<I, F> f) {
os << f.to_double();
return os;
}
// basic math operators
template <size_t I, size_t F> CONSTEXPR14 Fixed<I, F> operator+(Fixed<I, F> lhs, Fixed<I, F> rhs) { lhs += rhs; return lhs; }
template <size_t I, size_t F> CONSTEXPR14 Fixed<I, F> operator-(Fixed<I, F> lhs, Fixed<I, F> rhs) { lhs -= rhs; return lhs; }
template <size_t I, size_t F> CONSTEXPR14 Fixed<I, F> operator*(Fixed<I, F> lhs, Fixed<I, F> rhs) { lhs *= rhs; return lhs; }
template <size_t I, size_t F> CONSTEXPR14 Fixed<I, F> operator/(Fixed<I, F> lhs, Fixed<I, F> rhs) { lhs /= rhs; return lhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator+(Fixed<I, F> lhs, Number rhs) { lhs += Fixed<I, F>(rhs); return lhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator-(Fixed<I, F> lhs, Number rhs) { lhs -= Fixed<I, F>(rhs); return lhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator*(Fixed<I, F> lhs, Number rhs) { lhs *= Fixed<I, F>(rhs); return lhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator/(Fixed<I, F> lhs, Number rhs) { lhs /= Fixed<I, F>(rhs); return lhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator+(Number lhs, Fixed<I, F> rhs) { Fixed<I, F> tmp(lhs); tmp += rhs; return tmp; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator-(Number lhs, Fixed<I, F> rhs) { Fixed<I, F> tmp(lhs); tmp -= rhs; return tmp; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator*(Number lhs, Fixed<I, F> rhs) { Fixed<I, F> tmp(lhs); tmp *= rhs; return tmp; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> CONSTEXPR14 Fixed<I, F> operator/(Number lhs, Fixed<I, F> rhs) { Fixed<I, F> tmp(lhs); tmp /= rhs; return tmp; }
// shift operators
template <size_t I, size_t F, class Integer, class = typename std::enable_if<std::is_integral<Integer>::value>::type> CONSTEXPR14 Fixed<I, F> operator<<(Fixed<I, F> lhs, Integer rhs) { lhs <<= rhs; return lhs; }
template <size_t I, size_t F, class Integer, class = typename std::enable_if<std::is_integral<Integer>::value>::type> CONSTEXPR14 Fixed<I, F> operator>>(Fixed<I, F> lhs, Integer rhs) { lhs >>= rhs; return lhs; }
// comparison operators
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator>(Fixed<I, F> lhs, Number rhs) { return lhs > Fixed<I, F>(rhs); }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator<(Fixed<I, F> lhs, Number rhs) { return lhs < Fixed<I, F>(rhs); }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator>=(Fixed<I, F> lhs, Number rhs) { return lhs >= Fixed<I, F>(rhs); }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator<=(Fixed<I, F> lhs, Number rhs) { return lhs <= Fixed<I, F>(rhs); }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator==(Fixed<I, F> lhs, Number rhs) { return lhs == Fixed<I, F>(rhs); }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator!=(Fixed<I, F> lhs, Number rhs) { return lhs != Fixed<I, F>(rhs); }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator>(Number lhs, Fixed<I, F> rhs) { return Fixed<I, F>(lhs) > rhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator<(Number lhs, Fixed<I, F> rhs) { return Fixed<I, F>(lhs) < rhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator>=(Number lhs, Fixed<I, F> rhs) { return Fixed<I, F>(lhs) >= rhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator<=(Number lhs, Fixed<I, F> rhs) { return Fixed<I, F>(lhs) <= rhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator==(Number lhs, Fixed<I, F> rhs) { return Fixed<I, F>(lhs) == rhs; }
template <size_t I, size_t F, class Number, class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> constexpr bool operator!=(Number lhs, Fixed<I, F> rhs) { return Fixed<I, F>(lhs) != rhs; }
}
#undef CONSTEXPR14
#endif

View file

@ -922,7 +922,7 @@ void AnimateQuadBike(ITEM_INFO* item, int collide, int dead)
break;
}
if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
if (Rooms[item->roomNumber].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
{
LaraItem->goalAnimState = QUAD_STATE_FALLOFF;
LaraItem->hitPoints = 0;

View file

@ -2706,15 +2706,19 @@ void Renderer11::DrawDashBar()
void Renderer11::DrawHealthBar(int percentual)
{
int color2 = 0xA00000;
int color2;
if (Lara.poisoned || Lara.gassed)
color2 = 0xA0A000;
else
color2 = 0xA00000;
drawBar(20, 32, 150, 12, percentual, 0xA00000, color2);
}
void Renderer11::DrawAirBar(int percentual)
{
drawBar(20, 10, 150, 12, percentual, 0x0000A0, 0x0050A0);
/* Draw the air bar only if lara is not one a swamp room */
if (!(Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP))
drawBar(20, 10, 150, 12, percentual, 0x0000A0, 0x0050A0);
}
void Renderer11::ClearDynamicLights()
@ -4916,104 +4920,51 @@ void Renderer11::drawBubbles()
void Renderer11::drawSplahes()
{
constexpr size_t NUM_POINTS = 12;
for (int i = 0; i < MAX_SPLASH; i++)
{
SPLASH_STRUCT* splash = &Splashes[i];
if (splash->flags & 1)
SPLASH_STRUCT& splash = Splashes[i];
if (splash.isActive)
{
byte color = (splash->life >= 32 ? 255 : splash->life << 5);
// Inner circle
float angle = PI / 16.0f;
float c = cos(angle);
float s = sin(angle);
float dx = splash->innerRad * c;
float dz = splash->innerRad * s;
float x1 = splash->x + dx;
float z1 = splash->z + dz;
angle -= PI / 4.0f;
for (int j = 0; j < 8; j++)
{
c = cos(angle);
s = sin(angle);
dx = splash->innerRad * c;
dz = splash->innerRad * s;
float x2 = splash->x + dx;
float z2 = splash->z + dz;
angle -= PI / 4.0f;
addSprite3D(m_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_SPLASH1],
x1, splash->y + splash->innerY, z1,
x2, splash->y + splash->innerY, z2,
x2, splash->y, z2,
x1, splash->y, z1,
color, color, color, 0, 1, 0, 0, BLENDMODE_ALPHABLEND);
x1 = x2;
z1 = z2;
constexpr float alpha = 360 / NUM_POINTS;
byte color = (splash.life >= 32 ? 255 : (byte)((splash.life / 32.0f) * 255));
if (!splash.isRipple) {
if (splash.heightSpeed < 0 && splash.height < 1024) {
float multiplier = splash.height / 1024.0f;
color = (float)color*multiplier;
}
}
// Medium circle
angle = PI / 16.0f;
c = cos(angle);
s = sin(angle);
dx = splash->middleRad * c;
dz = splash->middleRad * s;
x1 = splash->x + dx;
z1 = splash->z + dz;
angle -= PI / 4.0f;
for (int j = 0; j < 8; j++)
{
c = cos(angle);
s = sin(angle);
dx = splash->middleRad * c;
dz = splash->middleRad * s;
float x2 = splash->x + dx;
float z2 = splash->z + dz;
angle -= PI / 4.0f;
addSprite3D(m_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_SPLASH],
x1, splash->y + splash->middleY, z1,
x2, splash->y + splash->middleY, z2,
x2, splash->y, z2,
x1, splash->y, z1,
color, color, color, 0, 1, 0, 0, BLENDMODE_ALPHABLEND);
x1 = x2;
z1 = z2;
}
// Large circle
angle = PI / 16.0f;
c = cos(angle);
s = sin(angle);
dx = splash->outerRad * c;
dz = splash->outerRad * s;
x1 = splash->x + dx;
z1 = splash->z + dz;
angle -= PI / 4.0f;
for (int j = 0; j < 8; j++)
{
c = cos(angle);
s = sin(angle);
dx = splash->outerRad * c;
dz = splash->outerRad * s;
float x2 = splash->x + dx;
float z2 = splash->z + dz;
angle -= PI / 4.0f;
addSprite3D(m_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_SPLASH],
x1, splash->y - splash->outerSize, z1,
x2, splash->y - splash->outerSize, z2,
x2, splash->y, z2,
x1, splash->y, z1,
color, color, color, 0, 1, 0, 0, BLENDMODE_ALPHABLEND);
x1 = x2;
z1 = z2;
float innerRadius = splash.innerRad;
float outerRadius = splash.outerRad;
float xInner;
float zInner;
float xOuter;
float zOuter;
float x2Inner;
float z2Inner;
float x2Outer;
float z2Outer;
float yInner = splash.y;
float yOuter = splash.y - splash.height;
for (int i = 0; i < NUM_POINTS; i++) {
xInner = innerRadius * sin(alpha * i * PI / 180);
zInner = innerRadius * cos(alpha * i * PI / 180);
xOuter = outerRadius * sin(alpha * i * PI / 180);
zOuter = outerRadius * cos(alpha * i * PI / 180);
xInner += splash.x;
zInner += splash.z;
xOuter += splash.x;
zOuter += splash.z;
int j = (i + 1) % NUM_POINTS;
x2Inner = innerRadius * sin(alpha * j * PI / 180);
x2Inner += splash.x;
z2Inner = innerRadius * cos(alpha * j * PI / 180);
z2Inner += splash.z;
x2Outer = outerRadius * sin(alpha * j * PI / 180);
x2Outer += splash.x;
z2Outer = outerRadius * cos(alpha * j * PI / 180);
z2Outer += splash.z;
addSprite3D(m_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + splash.spriteSequenceStart + (int)splash.animationPhase], xOuter, yOuter, zOuter, x2Outer, yOuter, z2Outer, x2Inner, yInner, z2Inner, xInner, yInner, zInner, color, color, color, 0, 1, 0, 0, BLENDMODE_ALPHABLEND);
}
}
}
@ -7006,7 +6957,7 @@ void Renderer11::drawUnderwaterDust()
dust->Life++;
byte color = (dust->Life > 16 ? 32 - dust->Life : dust->Life) * 4;
addSpriteBillboard(m_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], dust->X, dust->Y, dust->Z, color, color, color, 0.0f, 1.0f, UNDERWATER_DUST_PARTICLES_SIZE, UNDERWATER_DUST_PARTICLES_SIZE, BLENDMODE_ALPHABLEND);
addSpriteBillboard(m_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], dust->X, dust->Y, dust->Z, color, color, color, 0.0f, 1.0f, 12, 12, BLENDMODE_ALPHABLEND);
if (dust->Life >= 32)
dust->Reset = true;

View file

@ -65,9 +65,11 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;TR5MAIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)TR5Main\Libs\sol2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)TR5Main\Libs\fixedpoint;$(SolutionDir)TR5Main\Libs\sol2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -94,7 +96,8 @@ xcopy /Y "$(ProjectDir)Scripting\Scripts\*.lua" "$(TargetDir)\Scripts"</Command>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_RELEASE;TR5MAIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)TR5Main\Libs\fixedpoint;$(SolutionDir)TR5Main\Libs\sol2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -115,6 +118,7 @@ xcopy /Y "$(ProjectDir)Scripting\Scripts\*.lua" "$(TargetDir)\Scripts"</Command>
<ItemGroup>
<ClInclude Include="Game\swat.h" />
<ClInclude Include="Game\lion.h" />
<ClInclude Include="Libs\fixedpoint\fixed_point.hpp" />
<ClInclude Include="Objects\oldobjects.h" />
<ClInclude Include="Scripting\LanguageScript.h" />
<ClInclude Include="Renderer\Renderer11.h" />

View file

@ -300,6 +300,9 @@
<ClInclude Include="Objects\oldobjects.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="Libs\fixedpoint\fixed_point.hpp">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="TR5Main.cpp">