mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-08 03:28:03 +03:00
240 lines
No EOL
5 KiB
C++
240 lines
No EOL
5 KiB
C++
#include "framework.h"
|
|
#include "tr4_littlebeetle.h"
|
|
#include "level.h"
|
|
#include "control.h"
|
|
#include "trmath.h"
|
|
#include "lara.h"
|
|
|
|
namespace TEN::Entities::TR4
|
|
{
|
|
SCARAB_INFO* Scarabs;
|
|
int NextScarab;
|
|
|
|
void InitialiseScarabs(short itemNumber)
|
|
{
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
item->itemFlags[0] = (item->triggerFlags / 1000) & 1;
|
|
item->itemFlags[1] = (item->triggerFlags / 1000) & 2;
|
|
item->itemFlags[2] = (item->triggerFlags / 1000) & 4;
|
|
|
|
item->triggerFlags = item->triggerFlags % 1000;
|
|
|
|
if (!item->itemFlags[1])
|
|
{
|
|
if (item->pos.yRot <= 4096 || item->pos.yRot >= 28672)
|
|
{
|
|
if (!(item->pos.yRot >= -4096 || item->pos.yRot <= -28672))
|
|
item->pos.xPos += 512;
|
|
}
|
|
else
|
|
{
|
|
item->pos.xPos -= 512;
|
|
}
|
|
|
|
if (item->pos.yRot <= -8192 || item->pos.yRot >= 0x2000)
|
|
{
|
|
if (item->pos.yRot < -20480 || item->pos.yRot > 20480)
|
|
{
|
|
item->pos.zPos += 512;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->pos.zPos -= 512;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScarabsControl(short itemNumber)
|
|
{
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
if (item->triggerFlags)
|
|
{
|
|
if (!item->itemFlags[2] || !(GetRandomControl() & 0xF))
|
|
{
|
|
item->triggerFlags--;
|
|
if (item->itemFlags[2])
|
|
{
|
|
if (GetRandomControl() & 1)
|
|
{
|
|
item->itemFlags[2]--;
|
|
}
|
|
}
|
|
|
|
short beetleNum = GetFreeScarab();
|
|
if (beetleNum != NO_ITEM)
|
|
{
|
|
SCARAB_INFO* beetle = &Scarabs[beetleNum];
|
|
beetle->pos.xPos = item->pos.xPos;
|
|
beetle->pos.yPos = item->pos.yPos;
|
|
beetle->pos.zPos = item->pos.zPos;
|
|
beetle->roomNumber = item->roomNumber;
|
|
if (item->itemFlags[0])
|
|
{
|
|
beetle->pos.yRot = 2 * GetRandomControl();
|
|
beetle->fallspeed = -16 - (GetRandomControl() & 0x1F);
|
|
}
|
|
else
|
|
{
|
|
beetle->pos.yRot = item->pos.yRot + (GetRandomControl() & 0x3FFF) - ANGLE(45);
|
|
beetle->fallspeed = 0;
|
|
}
|
|
beetle->pos.xRot = 0;
|
|
beetle->pos.zRot = 0;
|
|
beetle->on = true;
|
|
beetle->flags = 0;
|
|
beetle->speed = (GetRandomControl() & 0x1F) + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClearScarabs()
|
|
{
|
|
if (Objects[ID_LITTLE_BEETLE].loaded)
|
|
{
|
|
ZeroMemory(Scarabs, NUM_LITTLE_BETTLES * sizeof(SCARAB_INFO));
|
|
NextScarab = 0;
|
|
FlipEffect = -1;
|
|
}
|
|
}
|
|
|
|
short GetFreeScarab()
|
|
{
|
|
short result = NextScarab;
|
|
SCARAB_INFO* beetle = &Scarabs[NextScarab];
|
|
|
|
int i = 0;
|
|
while (beetle->on)
|
|
{
|
|
if (result == NUM_LITTLE_BETTLES - 1)
|
|
{
|
|
beetle = &Scarabs[0];
|
|
result = 0;
|
|
}
|
|
else
|
|
{
|
|
result++;
|
|
beetle++;
|
|
}
|
|
if (++i >= NUM_LITTLE_BETTLES)
|
|
{
|
|
return NO_ITEM;
|
|
}
|
|
}
|
|
|
|
NextScarab = (result + 1) & (NUM_LITTLE_BETTLES - 1);
|
|
|
|
return result;
|
|
}
|
|
|
|
void UpdateScarabs()
|
|
{
|
|
for (int i = 0; i < NUM_LITTLE_BETTLES; i++)
|
|
{
|
|
SCARAB_INFO* beetle = &Scarabs[i];
|
|
|
|
if (beetle->on)
|
|
{
|
|
int oldx = beetle->pos.xPos;
|
|
int oldy = beetle->pos.yPos;
|
|
int oldz = beetle->pos.zPos;
|
|
|
|
beetle->pos.xPos += beetle->speed * phd_sin(beetle->pos.yRot);
|
|
beetle->pos.yPos += beetle->fallspeed;
|
|
beetle->pos.zPos += beetle->speed * phd_cos(beetle->pos.yRot);
|
|
|
|
beetle->fallspeed += GRAVITY;
|
|
|
|
int dx = LaraItem->pos.xPos - beetle->pos.xPos;
|
|
int dy = LaraItem->pos.yPos - beetle->pos.yPos;
|
|
int dz = LaraItem->pos.zPos - beetle->pos.zPos;
|
|
|
|
short angle = phd_atan(dz, dx) - beetle->pos.yRot;
|
|
|
|
if (abs(dx) < 85 && abs(dy) < 85 && abs(dz) < 85)
|
|
{
|
|
LaraItem->hitPoints--;
|
|
LaraItem->hitStatus = true;
|
|
}
|
|
|
|
if (beetle->flags)
|
|
{
|
|
if (abs(dx) + abs(dz) <= 1024)
|
|
{
|
|
if (beetle->speed & 1)
|
|
beetle->pos.yRot += 512;
|
|
else
|
|
beetle->pos.yRot -= 512;
|
|
|
|
beetle->speed = 48 - Lara.litTorch * 64 - (abs(angle) / 128);
|
|
if (beetle->speed < -16)
|
|
{
|
|
beetle->speed = i & 0xF;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (beetle->speed < (i & 0x1F) + 24)
|
|
{
|
|
beetle->speed++;
|
|
}
|
|
if (abs(angle) >= 4096)
|
|
{
|
|
if (angle >= 0)
|
|
beetle->pos.yRot += 1024;
|
|
else
|
|
beetle->pos.yRot -= 1024;
|
|
}
|
|
else
|
|
{
|
|
beetle->pos.yRot += 8 * (Wibble - i);
|
|
}
|
|
}
|
|
}
|
|
|
|
FLOOR_INFO* floor = GetFloor(beetle->pos.xPos, beetle->pos.yPos, beetle->pos.zPos, &beetle->roomNumber);
|
|
int height = GetFloorHeight(floor, beetle->pos.xPos, beetle->pos.yPos, beetle->pos.zPos);
|
|
if (height < beetle->pos.yPos - 1280 || height == NO_HEIGHT)
|
|
{
|
|
// If beetle has hit a wall or a too high step
|
|
if (angle <= 0)
|
|
beetle->pos.yRot -= ANGLE(90);
|
|
else
|
|
beetle->pos.yRot += ANGLE(90);
|
|
|
|
beetle->pos.xPos = oldx;
|
|
beetle->pos.yPos = oldy;
|
|
beetle->pos.zPos = oldz;
|
|
beetle->pos.xRot = 0;
|
|
beetle->pos.zRot = 0;
|
|
beetle->fallspeed = 0;
|
|
}
|
|
else
|
|
{
|
|
// If beetle is below the floor
|
|
if (beetle->pos.yPos > height)
|
|
{
|
|
beetle->pos.yPos = height;
|
|
beetle->flags = 1;
|
|
beetle->fallspeed = 0;
|
|
beetle->pos.xRot = 0;
|
|
beetle->pos.zRot = 0;
|
|
}
|
|
}
|
|
|
|
if (beetle->fallspeed >= 500)
|
|
{
|
|
beetle->on = false;
|
|
NextScarab = 0;
|
|
}
|
|
else
|
|
{
|
|
beetle->pos.xRot = -64 * beetle->fallspeed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |