mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-02 09:47:58 +03:00
241 lines
4.9 KiB
C++
241 lines
4.9 KiB
C++
#include "framework.h"
|
|
#include "tr5_missile.h"
|
|
#include "items.h"
|
|
#include "box.h"
|
|
#include "people.h"
|
|
#include "sphere.h"
|
|
#include "tomb4fx.h"
|
|
#include "effect2.h"
|
|
#include "draw.h"
|
|
#include "effect.h"
|
|
#include "traps.h"
|
|
#include "level.h"
|
|
#include "debris.h"
|
|
#include "lara.h"
|
|
#include "sound.h"
|
|
#include "tr5_roman_statue.h"
|
|
#include "tr5_hydra.h"
|
|
|
|
int DebrisFlags;
|
|
|
|
void MissileControl(short itemNumber)
|
|
{
|
|
FX_INFO* fx = &EffectList[itemNumber];
|
|
if (fx->flag1 == 2)
|
|
{
|
|
fx->pos.zRot += 16 * fx->speed;
|
|
|
|
if (fx->speed > 64)
|
|
fx->speed -= 4;
|
|
|
|
if (fx->pos.xRot > -12288)
|
|
{
|
|
if (fx->fallspeed < 512)
|
|
fx->fallspeed += 36;
|
|
fx->pos.xRot -= fx->fallspeed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
short angles[2];
|
|
phd_GetVectorAngles(
|
|
LaraItem->pos.xPos - fx->pos.xPos,
|
|
LaraItem->pos.yPos - fx->pos.yPos - 256,
|
|
LaraItem->pos.zPos - fx->pos.zPos,
|
|
angles);
|
|
|
|
int dh;
|
|
if (fx->flag1)
|
|
{
|
|
dh = fx->flag1 != 1 ? 768 : 384;
|
|
}
|
|
else
|
|
{
|
|
if (fx->counter)
|
|
fx->counter--;
|
|
dh = 256;
|
|
}
|
|
|
|
if (fx->speed < 192)
|
|
{
|
|
if (fx->flag1 == 0 || fx->flag1 == 1)
|
|
fx->speed++;
|
|
|
|
int dy = angles[0] - fx->pos.yRot;
|
|
if (abs(dy) > 0x8000)
|
|
dy = -dy;
|
|
dy /= 8;
|
|
|
|
int dx = angles[1] - fx->pos.xRot;
|
|
if (abs(dx) > 0x8000)
|
|
dx = -dx;
|
|
dx /= 8;
|
|
|
|
if (dy <= dh)
|
|
{
|
|
if (dy < -dh)
|
|
dy = -dh;
|
|
}
|
|
else
|
|
{
|
|
dy = dh;
|
|
}
|
|
|
|
if (dx <= dh)
|
|
{
|
|
if (dx < -dh)
|
|
dx = -dh;
|
|
}
|
|
else
|
|
{
|
|
dx = dh;
|
|
}
|
|
|
|
fx->pos.yRot += dy;
|
|
fx->pos.xRot += dx;
|
|
}
|
|
|
|
fx->pos.zRot += 16 * fx->speed;
|
|
|
|
if (!fx->flag1)
|
|
fx->pos.zRot += 16 * fx->speed;
|
|
}
|
|
|
|
int x = fx->pos.xPos;
|
|
int y = fx->pos.yPos;
|
|
int z = fx->pos.zPos;
|
|
|
|
int c = fx->speed * phd_cos(fx->pos.xRot);
|
|
|
|
fx->pos.xPos += c * phd_sin(fx->pos.yRot);
|
|
fx->pos.yPos += fx->speed * phd_sin(-fx->pos.xRot);
|
|
fx->pos.zPos += c * phd_cos(fx->pos.yRot);
|
|
|
|
short roomNumber = fx->roomNumber;
|
|
FLOOR_INFO* floor = GetFloor(fx->pos.xPos, fx->pos.yPos, fx->pos.zPos, &roomNumber);
|
|
int fh = GetFloorHeight(floor, fx->pos.xPos, fx->pos.yPos, fx->pos.zPos);
|
|
int ch = GetCeiling(floor, fx->pos.xPos, fx->pos.yPos, fx->pos.zPos);
|
|
|
|
if (fx->pos.yPos >= fh || fx->pos.yPos <= ch)
|
|
{
|
|
fx->pos.xPos = x;
|
|
fx->pos.yPos = y;
|
|
fx->pos.zPos = z;
|
|
|
|
if (fx->flag1)
|
|
{
|
|
if (fx->flag1 == 1)
|
|
{
|
|
TriggerExplosionSparks(x, y, z, 3, -2, 2, fx->roomNumber);
|
|
fx->pos.yPos -= 64;
|
|
TriggerShockwave((PHD_3DPOS*)fx, 48, 256, 64, 64, 128, 0, 24, 0, 1);
|
|
fx->pos.yPos -= 128;
|
|
TriggerShockwave((PHD_3DPOS*)fx, 48, 256, 48, 64, 128, 0, 24, 0, 1);
|
|
}
|
|
else if (fx->flag1 == 2)
|
|
{
|
|
ExplodeFX(fx, 0, 32);
|
|
SoundEffect(251, &fx->pos, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TriggerExplosionSparks(x, y, z, 3, -2, 0, fx->roomNumber);
|
|
TriggerShockwave((PHD_3DPOS*)fx, 48, 240, 48, 0, 96, 128, 24, 0, 2);
|
|
}
|
|
|
|
KillEffect(itemNumber);
|
|
}
|
|
else if (ItemNearLara((PHD_3DPOS*)fx, 200))
|
|
{
|
|
LaraItem->hitStatus = true;
|
|
|
|
if (fx->flag1)
|
|
{
|
|
if (fx->flag1 == 1)
|
|
{
|
|
// ROMAN_GOD hit effect
|
|
TriggerExplosionSparks(x, y, z, 3, -2, 2, fx->roomNumber);
|
|
fx->pos.yPos -= 64;
|
|
TriggerShockwave((PHD_3DPOS*)fx, 48, 256, 64, 0, 128, 64, 24, 0, 1);
|
|
fx->pos.yPos -= 128;
|
|
TriggerShockwave((PHD_3DPOS*)fx, 48, 256, 48, 0, 128, 64, 24, 0, 1);
|
|
LaraItem->hitPoints -= 200;
|
|
KillEffect(itemNumber);
|
|
}
|
|
else
|
|
{
|
|
if (fx->flag1 == 2)
|
|
{
|
|
// IMP hit effect
|
|
ExplodeFX(fx, 0, 32);
|
|
LaraItem->hitPoints -= 50;
|
|
DoBloodSplat(fx->pos.xPos, fx->pos.yPos, fx->pos.zPos, (GetRandomControl() & 3) + 2, LaraItem->pos.yRot, LaraItem->roomNumber);
|
|
SoundEffect(SFX_IMP_STONE_HIT, &fx->pos, 0);
|
|
SoundEffect(SFX_LARA_INJURY_RND, &LaraItem->pos, 0);
|
|
}
|
|
|
|
KillEffect(itemNumber);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// HYDRA hit effect
|
|
TriggerExplosionSparks(x, y, z, 3, -2, 0, fx->roomNumber);
|
|
TriggerShockwave((PHD_3DPOS*)fx, 48, 240, 48, 0, 96, 128, 24, 0, 0);
|
|
if (LaraItem->hitPoints >= 500)
|
|
LaraItem->hitPoints -= 300;
|
|
else
|
|
LaraBurn();
|
|
KillEffect(itemNumber);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (roomNumber != fx->roomNumber)
|
|
EffectNewRoom(itemNumber, roomNumber);
|
|
|
|
if (GlobalCounter & 1)
|
|
{
|
|
PHD_VECTOR pos;
|
|
pos.x = x;
|
|
pos.y = y;
|
|
pos.z = z;
|
|
|
|
int xv = x - fx->pos.xPos;
|
|
int yv = y - fx->pos.yPos;
|
|
int zv = z - fx->pos.zPos;
|
|
|
|
if (fx->flag1 == 1)
|
|
{
|
|
TriggerRomanStatueMissileSparks(&pos, itemNumber);
|
|
}
|
|
else
|
|
{
|
|
TriggerHydraMissileSparks(&pos, 4 * xv, 4 * yv, 4 * zv);
|
|
TriggerHydraMissileSparks((PHD_VECTOR*)&fx, 4 * xv, 4 * yv, 4 * zv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExplodeFX(FX_INFO* fx, int noXZVel, int bits)
|
|
{
|
|
MESH* meshpp = &g_Level.Meshes[fx->frameNumber];
|
|
|
|
ShatterItem.yRot = fx->pos.yRot;
|
|
ShatterItem.meshp = meshpp;
|
|
ShatterItem.sphere.x = fx->pos.xPos;
|
|
ShatterItem.sphere.y = fx->pos.yPos;
|
|
ShatterItem.sphere.z = fx->pos.zPos;
|
|
ShatterItem.bit = 0;
|
|
ShatterItem.flags = fx->flag2 & 0x1400;
|
|
|
|
if (fx->flag2 & 0x2000)
|
|
DebrisFlags = 1;
|
|
|
|
ShatterObject(&ShatterItem, 0, bits, fx->roomNumber, noXZVel);
|
|
|
|
DebrisFlags = 0;
|
|
}
|
|
|