Finished ID_RATS, ID_BATS, ID_SPIDERS

This commit is contained in:
Montagna Marco 2020-02-14 07:42:20 +01:00
parent 9b6040a3dd
commit 5c7aada97a
11 changed files with 688 additions and 560 deletions

View file

@ -1735,129 +1735,6 @@ int GetFloorHeight(FLOOR_INFO* floor, int x, int y, int z)
return height;
}
void UpdateBats()
{
if (!Objects[ID_BATS].loaded)
return;
short* bounds = GetBoundsAccurate(LaraItem);
int x1 = LaraItem->pos.xPos + bounds[0] - (bounds[0] >> 2);
int x2 = LaraItem->pos.xPos + bounds[1] - (bounds[1] >> 2);
int y1 = LaraItem->pos.yPos + bounds[2] - (bounds[2] >> 2);
int y2 = LaraItem->pos.yPos + bounds[3] - (bounds[3] >> 2);
int z1 = LaraItem->pos.zPos + bounds[4] - (bounds[4] >> 2);
int z2 = LaraItem->pos.zPos + bounds[5] - (bounds[5] >> 2);
int minDistance = 0xFFFFFFF; // v40
int minIndex = -1;
for (int i = 0; i < NUM_BATS; i++)
{
BAT_STRUCT* bat = &Bats[i];
if (!bat->on)
continue;
if ((Lara.burn || LaraItem->hitPoints <= 0)
&& bat->counter > 90
&& !(GetRandomControl() & 7))
bat->counter = 90;
if (!(--bat->counter))
{
bat->on = 0;
continue;
}
if (!(GetRandomControl() & 7))
{
bat->laraTarget = GetRandomControl() % 640 + 128;
bat->xTarget = (GetRandomControl() & 0x7F) - 64;
bat->zTarget = (GetRandomControl() & 0x7F) - 64;
}
short angles[2];
phd_GetVectorAngles(
LaraItem->pos.xPos + 8 * bat->xTarget - bat->pos.xPos,
LaraItem->pos.yPos - bat->laraTarget - bat->pos.yPos,
LaraItem->pos.zPos + 8 * bat->zTarget - bat->pos.zPos,
angles);
int distance = SQUARE(LaraItem->pos.zPos - bat->pos.zPos) + SQUARE(LaraItem->pos.xPos - bat->pos.xPos);
if (distance < minDistance)
{
minDistance = distance;
minIndex = i;
}
distance = SQRT_ASM(distance) / 8;
if (distance <= 128)
{
if (distance < 48)
distance = 48;
}
else
{
distance = 128;
}
if (bat->speed < distance)
bat->speed++;
else if (bat->speed > distance)
bat->speed--;
if (bat->counter > 90)
{
int speed = bat->speed * 128;
short xAngle = abs(angles[1] - bat->pos.yRot) >> 3;
short yAngle = abs(angles[0] - bat->pos.yRot) >> 3;
if (xAngle <= -speed)
xAngle = -speed;
else if (xAngle >= speed)
xAngle = speed;
if (yAngle <= -speed)
yAngle = -speed;
else if (yAngle >= speed)
yAngle = speed;
bat->pos.yRot += yAngle;
bat->pos.xRot += xAngle;
}
int sp = bat->speed * SIN(bat->pos.xRot) >> W2V_SHIFT;
bat->pos.xPos += sp * SIN(bat->pos.yRot) >> W2V_SHIFT;
bat->pos.yPos += bat->speed * SIN(-bat->pos.xRot) >> W2V_SHIFT;
bat->pos.zPos += sp * COS(bat->pos.yRot) >> W2V_SHIFT;
if ((i % 2 == 0)
&& bat->pos.xPos > x1
&& bat->pos.xPos < x2
&& bat->pos.yPos > y1
&& bat->pos.yPos < y2
&& bat->pos.zPos > z1
&& bat->pos.zPos < z2)
{
TriggerBlood(bat->pos.xPos, bat->pos.yPos, bat->pos.zPos, 2 * GetRandomControl(), 2);
if (LaraItem->hitPoints > 0)
LaraItem->hitPoints -= 2;
}
}
if (minIndex != -1)
{
BAT_STRUCT* bat = &Bats[minIndex];
if (!(GetRandomControl() & 4))
SoundEffect(SFX_BATS_1, &bat->pos, 0);
}
}
void UpdateDebris()
{
for (int i = 0; i < 256; i++)
@ -1896,305 +1773,6 @@ void UpdateDebris()
}
}
void UpdateRats()
{
if (Objects[ID_RATS].loaded)
{
for (int i = 0; i < 32; i++)
{
RAT_STRUCT* rat = &Rats[i];
if (rat->on)
{
int oldX = rat->pos.xPos;
int oldY = rat->pos.yPos;
int oldZ = rat->pos.zPos;
rat->pos.xPos += rat->speed * SIN(rat->pos.yRot) >> W2V_SHIFT;
rat->pos.yPos += rat->fallspeed;
rat->pos.zPos += rat->speed * COS(rat->pos.yRot) >> W2V_SHIFT;
rat->fallspeed += 6;
int dx = LaraItem->pos.xPos - rat->pos.xPos;
int dy = LaraItem->pos.yPos - rat->pos.yPos;
int dz = LaraItem->pos.zPos - rat->pos.zPos;
short angle;
if (rat->flags >= 170)
angle = rat->pos.yRot - ATAN(dz, dx);
else
angle = ATAN(dz, dx) - rat->pos.yRot;
if (abs(dx) < 85 && abs(dy) < 85 && abs(dz) < 85)
{
LaraItem->hitPoints--;
LaraItem->hitStatus = true;
}
if (rat->flags & 1)
{
if (abs(dz) + abs(dx) <= 1024)
{
if (rat->speed & 1)
rat->pos.yRot += 512;
else
rat->pos.yRot -= 512;
rat->speed = 48 - (abs(angle) >> 10);
}
else
{
if (rat->speed < (i & 0x1F) + 24)
rat->speed++;
if (abs(angle) >= 2048)
{
if (angle >= 0)
rat->pos.yRot += 1024;
else
rat->pos.yRot -= 1024;
}
else
{
rat->pos.yRot += 8 * (Wibble - i);
}
}
}
__int16 oldRoomNumber = rat->roomNumber;
FLOOR_INFO* floor = GetFloor(rat->pos.xPos, rat->pos.yPos, rat->pos.zPos, &rat->roomNumber);
int height = GetFloorHeight(floor, rat->pos.xPos, rat->pos.yPos, rat->pos.zPos);
if (height < rat->pos.yPos - 1280 || height == NO_HEIGHT)
{
if (rat->flags > 170)
{
rat->on = false;
NextRat = 0;
}
if (angle <= 0)
rat->pos.yRot -= ANGLE(90);
else
rat->pos.yRot += ANGLE(90);
rat->pos.xPos = oldX;
rat->pos.yPos = oldY;
rat->pos.zPos = oldZ;
rat->fallspeed = 0;
}
else
{
if (height >= rat->pos.yPos - 64)
{
if (rat->pos.yPos <= height)
{
if (rat->fallspeed >= 500 || rat->flags >= 200)
{
rat->on = 0;
NextRat = 0;
}
else
{
rat->pos.xRot = -128 * rat->fallspeed;
}
}
else
{
rat->pos.yPos = height;
rat->fallspeed = 0;
rat->flags |= 1;
}
}
else
{
rat->pos.xRot = 14336;
rat->pos.xPos = oldX;
rat->pos.yPos = oldY - 24;
rat->pos.zPos = oldZ;
rat->fallspeed = 0;
}
}
if (!(Wibble & 0x3C))
rat->flags += 2;
ROOM_INFO* r = &Rooms[rat->roomNumber];
if (r->flags & ENV_FLAG_WATER)
{
rat->fallspeed = 0;
rat->speed = 16;
rat->pos.yPos = r->maxceiling + 50;
if (Rooms[oldRoomNumber].flags & ENV_FLAG_WATER)
{
if (!(GetRandomControl() & 0xF))
{
SetupRipple(rat->pos.xPos, r->maxceiling, rat->pos.zPos, (GetRandomControl() & 3) + 48, 2);
}
}
else
{
AddWaterSparks(rat->pos.xPos, r->maxceiling, rat->pos.zPos, 16);
SetupRipple(rat->pos.xPos, r->maxceiling, rat->pos.zPos, (GetRandomControl() & 3) + 48, 2);
SoundEffect(SFX_RATSPLASH, &rat->pos, 0);
}
}
if (!i && !(GetRandomControl() & 4))
SoundEffect(SFX_RATS_1, &rat->pos, 0);
}
}
}
}
/*char __usercall UpdateSpiders@<al > (signed int a1@<eax > )
{
if (Objects[ID_SPIDER].loaded)
{
for (int i = 0; i < 64; i++)
{
SPIDER_STRUCT* spider = &Spiders[i];
if (spider->on)
{
}
}
}
LOBYTE(a1) = *(&objects[95] + 50);
if (*(&objects[95] + 50) & 1)
{
v1 = Spiders;
v23 = 0;
do
{
if (BYTE2(v1[1].yPos))
{
LOWORD(a1) = v1->yRot;
v2 = SHIWORD(v1[1].xPos);
v3 = v1->yPos;
v4 = (a1 >> 3) & 0x1FFE;
v25 = v1->xPos;
v5 = v1->zPos;
v6 = v1[1].yPos;
v1->xPos += v2 * 4 * rcossin_tbl[v4] >> 14;
v26 = v3;
v1->yPos = v3 + v6;
v27 = v5;
v7 = v5 + (v2 * 4 * rcossin_tbl[v4 + 1] >> 14);
LOWORD(v1[1].yPos) = v6 + 6;
v1->zPos = v7;
v8 = v3 + v6;
v9 = LaraItem->pos.zPos - v1->zPos;
v10 = LaraItem->pos.xPos - v1->xPos;
v11 = LaraItem->pos.yPos - v8;
v12 = phd_atan(v9, v10) - v1->yRot;
v24 = v12;
v13 = abs(v9);
if (v13 < 85 && abs(v11) < 85 && abs(v10) < 85)
{
LaraItem->hit_points -= 3;
LaraItem->_bf15ea |= 0x10u;
TriggerBlood(v1->xPos, v1->yPos, v1->zPos, v1->yRot, 1);
v12 = v24;
}
if (HIBYTE(v1[1].yPos))
{
if (v13 + abs(v10) <= 768)
{
if (v1[1].xPos & 0x10000)
v1->yRot += 512;
else
v1->yRot -= 512;
HIWORD(v1[1].xPos) = 48 - (abs(v12) >> 10);
}
else
{
v14 = HIWORD(v1[1].xPos);
if (v14 < (v23 & 0x1F) + 24)
HIWORD(v1[1].xPos) = v14 + 1;
if (abs(v12) >= 2048)
{
if (v12 >= 0)
v1->yRot += 1024;
else
v1->yRot -= 1024;
}
else
{
v1->yRot += 8 * (wibble - v23);
}
}
}
v15 = v1 + 1;
v16 = GetFloor(v1->xPos, v1->yPos, v1->zPos, &v1[1]);
v17 = GetHeight(v16, v1->xPos, v1->yPos, v1->zPos);
v18 = v1->yPos;
if (v17 >= v18 - 1280 || v17 == -32512)
{
if (v17 >= v18 - 64)
{
if (v18 <= v17)
{
if (SLOWORD(v1[1].yPos) >= 500)
{
BYTE2(v1[1].yPos) = 0;
NextSpider = 0;
}
else
{
v1->xRot = -128 * LOWORD(v1[1].yPos);
}
}
else
{
v1->yPos = v17;
LOWORD(v1[1].yPos) = 0;
HIBYTE(v1[1].yPos) = 1;
}
}
else
{
v1->xRot = 14336;
v1->xPos = v25;
v1->yPos = v26 - 8;
if (!(GetRandomControl() & 0x1F))
v1->yRot += -32768;
LOWORD(v1[1].yPos) = 0;
v1->zPos = v27;
}
}
else
{
if (v24 <= 0)
v1->yRot -= 0x4000;
else
v1->yRot += 0x4000;
v1->xPos = v25;
v1->yPos = v26;
v1->zPos = v27;
LOWORD(v1[1].yPos) = 0;
}
if (v1->yPos < room[SLOWORD(v15->xPos)].maxceiling + 50)
{
v19 = room[SLOWORD(v15->xPos)].maxceiling;
LOWORD(v1[1].yPos) = 1;
v1->yRot += -32768;
v1->yPos = v19 + 50;
}
if (!v23 && !(GetRandomControl() & 4))
SoundEffect(276, v1, 0);
}
v1 = (v1 + 26);
a1 = v23 + 1;
v21 = __OFSUB__(v23 + 1, 64);
v20 = v23++ - 63 < 0;
} while (v20 ^ v21);
}
return a1;
}*/
int LOS(GAME_VECTOR* start, GAME_VECTOR* end)
{
int result1, result2;

View file

@ -2,7 +2,7 @@
#include "..\Global\global.h"
#define UpdateSpiders ((void (__cdecl*)()) 0x0047A340)
//#define UpdateSpiders ((void (__cdecl*)()) 0x0047A340)
#define UpdateLightning ((void (__cdecl*)()) 0x00484CB0)
#define UpdatePulseColor ((void (__cdecl*)()) 0x00480830)
#define DoRayBox_sub_401523 ((int (__cdecl*)(PHD_VECTOR*, PHD_VECTOR*, PHD_VECTOR*, PHD_VECTOR*, PHD_VECTOR*)) 0x00401523)
@ -40,9 +40,7 @@ int CheckNoColCeilingTriangle(FLOOR_INFO* floor, int x, int z);
int CheckNoColFloorTriangle(FLOOR_INFO* floor, int x, int z);
int GetFloorHeight(FLOOR_INFO* floor, int x, int y, int z);
FLOOR_INFO* GetFloor(int x, int y, int z, short* roomNumber);
void UpdateRats();
void UpdateDebris();
void UpdateBats();
int LOS(GAME_VECTOR* start, GAME_VECTOR* end);
int xLOS(GAME_VECTOR* start, GAME_VECTOR* end);
int zLOS(GAME_VECTOR* start, GAME_VECTOR* end);

View file

@ -9,6 +9,8 @@
#include "draw.h"
#include "sphere.h"
#include "footprint.h"
#include "..\Objects\oldobjects.h"
int wf = 256;
extern std::deque<FOOTPRINT_STRUCT> footprints;
@ -244,21 +246,6 @@ void invisibility_on(ITEM_INFO* item)
item->status = ITEM_INVISIBLE;
}
void ClearSpiders()// (F)
{
/*if (Objects[ID_SPIDER].loaded)
{
memset((char*)&Spiders, 0, 64 * sizeof(SPIDER_STRUCT));
NextSpider = 0;
FlipEffect = -1;
}*/
}
void ClearSpidersPatch(ITEM_INFO* item)//39AA4(<), 39FA4(<) (F)
{
ClearSpiders();
}
/*void SetFog()
{
FlipEffect = -1;

View file

@ -31,8 +31,6 @@ void lara_hands_free(ITEM_INFO* item);
void shoot_right_gun(ITEM_INFO* item);
void shoot_left_gun(ITEM_INFO* item);
void SetFog(ITEM_INFO* item);
void ClearSpidersPatch(ITEM_INFO* item);
void ClearSpiders();
void invisibility_on(ITEM_INFO* item);
void invisibility_off(ITEM_INFO* item);
void reset_hair(ITEM_INFO* item);

View file

@ -2,5 +2,5 @@
#include "..\Global\global.h"
#define InitialiseLittleRats ((void (__cdecl*)(short)) 0x0046B220)
//#define InitialiseLittleRats ((void (__cdecl*)(short)) 0x0046B220)
//#define ControlLittleRats ((void (__cdecl*)(short)) 0x0046AB30)

View file

@ -31,7 +31,6 @@ int NextSmokeSpark = 0;
int NextBubble = 0;
int NextDrip = 0;
int NextBlood = 0;
int NextSpider = 0;
int NextGunShell = 0;
GUNFLASH_STRUCT Gunflashes[MAX_GUNFLASH];
@ -1813,40 +1812,12 @@ void TriggerFenceSparks(int x, int y, int z, int kill, int crane)//(F)
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)
void TriggerSmallSplash(int x, int y, int z, int num)
{
int i;
int angle;

View file

@ -71,7 +71,6 @@ void TriggerShockwave(PHD_3DPOS* pos, short innerRad, short outerRad, int speed,
void TriggerShockwaveHitEffect(int x, int y, int z, int color, short rot, int vel);
void UpdateShockwaves();
void TriggerSmallSplash(int x, int y, int z, int num);
int GetFreeSpider();
void SetFadeClip(short height, short speed);
void TriggerLightningGlow(int x, int y, int z, int rgb);

View file

@ -213,8 +213,8 @@
#define PhdHeight VAR_U_(0x0055D164, int)
#define PhdPerspective VAR_U_(0x0055D208, int)
//#define Bats VAR_U_(0x00EEEFE8, BAT_STRUCT*)
#define Rats VAR_U_(0x00EEEFEC, RAT_STRUCT*)
#define Spiders VAR_U_(0x00EEF45C, SPIDER_STRUCT*)
//#define Rats VAR_U_(0x00EEEFEC, RAT_STRUCT*)
//#define Spiders VAR_U_(0x00EEF45C, SPIDER_STRUCT*)
#define PoisonFlags VAR_U_(0x00E5BF3E, byte)
#define SmashedMeshCount VAR_U_(0x0051CA5C, short)
#define SmashedMesh ARRAY_(0x00EEF8C0, MESH_INFO*, [16])
@ -307,7 +307,7 @@
#define KillEverythingFlag VAR_U_(0x0051CDF4, int)
#define SmokeWindX VAR_U_(0x00E6C9E0, int)
#define SmokeWindZ VAR_U_(0x00E6C9E4, int)
#define NextRat VAR_U_(0x0051CF94, int)
//#define NextRat VAR_U_(0x0051CF94, int)
//#define NextFireSpark VAR_U_(0x0050A17C, int)
#define LaraNodeUnderwater ARRAY_(0x00E862FE, byte, [15])
#define OnFloor VAR_U_(0x00EEEAC8, int)

View file

@ -10,9 +10,15 @@
#include "../../Game/control.h"
#include "../../Game/effects.h"
int NumBats;
int NextBat;
BAT_STRUCT* Bats;
int NextSpider;
SPIDER_STRUCT* Spiders;
int NextRat;
RAT_STRUCT* Rats;
void InitialiseLittleBats(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
@ -58,11 +64,11 @@ void ControlLittleBats(short itemNumber)
}
}
short GetFreeBat()
short GetNextBat()
{
short batNumber = NumBats;
short batNumber = NextBat;
int index = 0;
BAT_STRUCT* bat = &Bats[NumBats];
BAT_STRUCT* bat = &Bats[NextBat];
while (bat->on)
{
@ -83,14 +89,14 @@ short GetFreeBat()
return NO_ITEM;
}
NumBats = (batNumber + 1) & (NUM_BATS - 1);
NextBat = (batNumber + 1) & (NUM_BATS - 1);
return batNumber;
}
void TriggerLittleBat(ITEM_INFO* item)
{
short batNumber = GetFreeBat();
short batNumber = GetNextBat();
if (batNumber != NO_ITEM)
{
@ -108,4 +114,651 @@ void TriggerLittleBat(ITEM_INFO* item)
bat->laraTarget = GetRandomControl() & 0x1FF;
bat->counter = 20 * ((GetRandomControl() & 7) + 15);
}
}
short GetNextSpider()
{
short spiderNum = NextSpider;
int i = 0;
SPIDER_STRUCT* spider = &Spiders[NextSpider];
while (spider->on)
{
if (spiderNum == NUM_SPIDERS - 1)
{
spider = &Spiders[0];
spiderNum = 0;
}
else
{
++spiderNum;
++spider;
}
if (++i >= NUM_SPIDERS)
return -1;
}
NextSpider = (spiderNum + 1) & 0x3F;
return spiderNum;
}
void ClearSpiders()
{
if (Objects[ID_SPIDER].loaded)
{
ZeroMemory(Spiders, NUM_SPIDERS * sizeof(SPIDER_STRUCT));
NextSpider = 0;
FlipEffect = -1;
}
}
void ClearSpidersPatch(ITEM_INFO* item)
{
ClearSpiders();
}
void InitialiseSpiders(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
short flags = item->triggerFlags / -24;
item->pos.xRot = ANGLE(45);
item->itemFlags[1] = flags & 2;
item->itemFlags[2] = flags & 4;
item->itemFlags[0] = flags & 1;
item->triggerFlags = flags % 1000;
if (flags & 1)
{
ClearSpiders();
return;
}
if (item->pos.yRot > -28672 && item->pos.yRot < -4096)
{
item->pos.xPos += 512;
}
else if(item->pos.yRot > 4096 && item->pos.yRot < 28672)
{
item->pos.xPos -= 512;
}
if (item->pos.yRot > -8192 && item->pos.yRot < 8192)
{
item->pos.zPos -= 512;
}
else if (item->pos.yRot < -20480 || item->pos.yRot > 20480)
{
item->pos.zPos += 512;
}
ClearSpiders();
}
void ControlSpiders(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
if (item->triggerFlags)
{
if (!item->itemFlags[2] || !(GetRandomControl() & 0xF))
{
item->triggerFlags--;
if (item->itemFlags[2] && GetRandomControl() & 1)
item->itemFlags[2]--;
short spiderNum = GetNextSpider();
if (spiderNum != -1)
{
SPIDER_STRUCT* spider = &Spiders[spiderNum];
spider->pos.xPos = item->pos.xPos;
spider->pos.yPos = item->pos.yPos;
spider->pos.zPos = item->pos.zPos;
spider->roomNumber = item->roomNumber;
if (item->itemFlags[0])
{
spider->pos.yRot = 2 * GetRandomControl();
spider->fallspeed = -16 - (GetRandomControl() & 0x1F);
}
else
{
spider->fallspeed = 0;
spider->pos.yRot = item->pos.yRot + (GetRandomControl() & 0x3FFF) - ANGLE(45);
}
spider->pos.xRot = 0;
spider->pos.zRot = 0;
spider->on = true;
spider->flags = 0;
spider->speed = (GetRandomControl() & 0x1F) + 1;
}
}
}
}
short GetNextRat()
{
short ratNum = NextRat;
int i = 0;
RAT_STRUCT* rat = &Rats[NextRat];
while (rat->on)
{
if (ratNum == NUM_RATS - 1)
{
rat = &Rats[0];
ratNum = 0;
}
else
{
ratNum++;
rat++;
}
i++;
if (i >= NUM_RATS)
return NO_ITEM;
}
NextRat = (ratNum + 1) & 0x1F;
return ratNum;
}
void ControlLittleRats(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
if (item->triggerFlags)
{
if (!item->itemFlags[2] || !(GetRandomControl() & 0xF))
{
item->triggerFlags--;
if (item->itemFlags[2] && GetRandomControl() & 1)
item->itemFlags[2]--;
short ratNum = GetNextRat();
if (ratNum != -1)
{
RAT_STRUCT* rat = &Rats[ratNum];
rat->pos.xPos = item->pos.xPos;
rat->pos.yPos = item->pos.yPos;
rat->pos.zPos = item->pos.zPos;
rat->roomNumber = item->roomNumber;
if (item->itemFlags[0])
{
rat->pos.yRot = 2 * GetRandomControl();
rat->fallspeed = -16 - (GetRandomControl() & 0x1F);
}
else
{
rat->fallspeed = 0;
rat->pos.yRot = item->pos.yRot + (GetRandomControl() & 0x3FFF) - ANGLE(45);
}
rat->pos.xRot = 0;
rat->pos.zRot = 0;
rat->on = 1;
rat->flags = GetRandomControl() & 0x1E;
rat->speed = (GetRandomControl() & 0x1F) + 1;
}
}
}
}
void ClearRats()
{
if (Objects[ID_RATS].loaded)
{
ZeroMemory(Rats, NUM_RATS * sizeof(RAT_STRUCT));
NextRat = 0;
FlipEffect = -1;
}
}
void InitialiseLittleRats(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
short flags = item->triggerFlags / -24;
item->pos.xRot = ANGLE(45);
item->itemFlags[1] = flags & 2;
item->itemFlags[2] = flags & 4;
item->itemFlags[0] = flags & 1;
item->triggerFlags = flags % 1000;
if (flags & 1)
{
ClearRats();
return;
}
if (item->pos.yRot > -28672 && item->pos.yRot < -4096)
{
item->pos.xPos += 512;
}
else if (item->pos.yRot > 4096 && item->pos.yRot < 28672)
{
item->pos.xPos -= 512;
}
if (item->pos.yRot > -8192 && item->pos.yRot < 8192)
{
item->pos.zPos -= 512;
}
else if (item->pos.yRot < -20480 || item->pos.yRot > 20480)
{
item->pos.zPos += 512;
}
ClearRats();
}
void UpdateBats()
{
if (!Objects[ID_BATS].loaded)
return;
short* bounds = GetBoundsAccurate(LaraItem);
int x1 = LaraItem->pos.xPos + bounds[0] - (bounds[0] >> 2);
int x2 = LaraItem->pos.xPos + bounds[1] - (bounds[1] >> 2);
int y1 = LaraItem->pos.yPos + bounds[2] - (bounds[2] >> 2);
int y2 = LaraItem->pos.yPos + bounds[3] - (bounds[3] >> 2);
int z1 = LaraItem->pos.zPos + bounds[4] - (bounds[4] >> 2);
int z2 = LaraItem->pos.zPos + bounds[5] - (bounds[5] >> 2);
int minDistance = 0xFFFFFFF; // v40
int minIndex = -1;
for (int i = 0; i < NUM_BATS; i++)
{
BAT_STRUCT* bat = &Bats[i];
if (!bat->on)
continue;
if ((Lara.burn || LaraItem->hitPoints <= 0)
&& bat->counter > 90
&& !(GetRandomControl() & 7))
bat->counter = 90;
if (!(--bat->counter))
{
bat->on = 0;
continue;
}
if (!(GetRandomControl() & 7))
{
bat->laraTarget = GetRandomControl() % 640 + 128;
bat->xTarget = (GetRandomControl() & 0x7F) - 64;
bat->zTarget = (GetRandomControl() & 0x7F) - 64;
}
short angles[2];
phd_GetVectorAngles(
LaraItem->pos.xPos + 8 * bat->xTarget - bat->pos.xPos,
LaraItem->pos.yPos - bat->laraTarget - bat->pos.yPos,
LaraItem->pos.zPos + 8 * bat->zTarget - bat->pos.zPos,
angles);
int distance = SQUARE(LaraItem->pos.zPos - bat->pos.zPos) + SQUARE(LaraItem->pos.xPos - bat->pos.xPos);
if (distance < minDistance)
{
minDistance = distance;
minIndex = i;
}
distance = SQRT_ASM(distance) / 8;
if (distance <= 128)
{
if (distance < 48)
distance = 48;
}
else
{
distance = 128;
}
if (bat->speed < distance)
bat->speed++;
else if (bat->speed > distance)
bat->speed--;
if (bat->counter > 90)
{
int speed = bat->speed * 128;
short xAngle = abs(angles[1] - bat->pos.yRot) >> 3;
short yAngle = abs(angles[0] - bat->pos.yRot) >> 3;
if (xAngle <= -speed)
xAngle = -speed;
else if (xAngle >= speed)
xAngle = speed;
if (yAngle <= -speed)
yAngle = -speed;
else if (yAngle >= speed)
yAngle = speed;
bat->pos.yRot += yAngle;
bat->pos.xRot += xAngle;
}
int sp = bat->speed * SIN(bat->pos.xRot) >> W2V_SHIFT;
bat->pos.xPos += sp * SIN(bat->pos.yRot) >> W2V_SHIFT;
bat->pos.yPos += bat->speed * SIN(-bat->pos.xRot) >> W2V_SHIFT;
bat->pos.zPos += sp * COS(bat->pos.yRot) >> W2V_SHIFT;
if ((i % 2 == 0)
&& bat->pos.xPos > x1
&& bat->pos.xPos < x2
&& bat->pos.yPos > y1
&& bat->pos.yPos < y2
&& bat->pos.zPos > z1
&& bat->pos.zPos < z2)
{
TriggerBlood(bat->pos.xPos, bat->pos.yPos, bat->pos.zPos, 2 * GetRandomControl(), 2);
if (LaraItem->hitPoints > 0)
LaraItem->hitPoints -= 2;
}
}
if (minIndex != -1)
{
BAT_STRUCT* bat = &Bats[minIndex];
if (!(GetRandomControl() & 4))
SoundEffect(SFX_BATS_1, &bat->pos, 0);
}
}
void UpdateRats()
{
if (Objects[ID_RATS].loaded)
{
for (int i = 0; i < NUM_RATS; i++)
{
RAT_STRUCT* rat = &Rats[i];
if (rat->on)
{
int oldX = rat->pos.xPos;
int oldY = rat->pos.yPos;
int oldZ = rat->pos.zPos;
rat->pos.xPos += rat->speed * SIN(rat->pos.yRot) >> W2V_SHIFT;
rat->pos.yPos += rat->fallspeed;
rat->pos.zPos += rat->speed * COS(rat->pos.yRot) >> W2V_SHIFT;
rat->fallspeed += 6;
int dx = LaraItem->pos.xPos - rat->pos.xPos;
int dy = LaraItem->pos.yPos - rat->pos.yPos;
int dz = LaraItem->pos.zPos - rat->pos.zPos;
short angle;
if (rat->flags >= 170)
angle = rat->pos.yRot - ATAN(dz, dx);
else
angle = ATAN(dz, dx) - rat->pos.yRot;
if (abs(dx) < 85 && abs(dy) < 85 && abs(dz) < 85)
{
LaraItem->hitPoints--;
LaraItem->hitStatus = true;
}
if (rat->flags & 1)
{
if (abs(dz) + abs(dx) <= 1024)
{
if (rat->speed & 1)
rat->pos.yRot += 512;
else
rat->pos.yRot -= 512;
rat->speed = 48 - (abs(angle) >> 10);
}
else
{
if (rat->speed < (i & 0x1F) + 24)
rat->speed++;
if (abs(angle) >= 2048)
{
if (angle >= 0)
rat->pos.yRot += 1024;
else
rat->pos.yRot -= 1024;
}
else
{
rat->pos.yRot += 8 * (Wibble - i);
}
}
}
__int16 oldRoomNumber = rat->roomNumber;
FLOOR_INFO* floor = GetFloor(rat->pos.xPos, rat->pos.yPos, rat->pos.zPos, &rat->roomNumber);
int height = GetFloorHeight(floor, rat->pos.xPos, rat->pos.yPos, rat->pos.zPos);
if (height < rat->pos.yPos - 1280 || height == NO_HEIGHT)
{
if (rat->flags > 170)
{
rat->on = false;
NextRat = 0;
}
if (angle <= 0)
rat->pos.yRot -= ANGLE(90);
else
rat->pos.yRot += ANGLE(90);
rat->pos.xPos = oldX;
rat->pos.yPos = oldY;
rat->pos.zPos = oldZ;
rat->fallspeed = 0;
}
else
{
if (height >= rat->pos.yPos - 64)
{
if (rat->pos.yPos <= height)
{
if (rat->fallspeed >= 500 || rat->flags >= 200)
{
rat->on = 0;
NextRat = 0;
}
else
{
rat->pos.xRot = -128 * rat->fallspeed;
}
}
else
{
rat->pos.yPos = height;
rat->fallspeed = 0;
rat->flags |= 1;
}
}
else
{
rat->pos.xRot = 14336;
rat->pos.xPos = oldX;
rat->pos.yPos = oldY - 24;
rat->pos.zPos = oldZ;
rat->fallspeed = 0;
}
}
if (!(Wibble & 0x3C))
rat->flags += 2;
ROOM_INFO* r = &Rooms[rat->roomNumber];
if (r->flags & ENV_FLAG_WATER)
{
rat->fallspeed = 0;
rat->speed = 16;
rat->pos.yPos = r->maxceiling + 50;
if (Rooms[oldRoomNumber].flags & ENV_FLAG_WATER)
{
if (!(GetRandomControl() & 0xF))
{
SetupRipple(rat->pos.xPos, r->maxceiling, rat->pos.zPos, (GetRandomControl() & 3) + 48, 2);
}
}
else
{
AddWaterSparks(rat->pos.xPos, r->maxceiling, rat->pos.zPos, 16);
SetupRipple(rat->pos.xPos, r->maxceiling, rat->pos.zPos, (GetRandomControl() & 3) + 48, 2);
SoundEffect(SFX_RATSPLASH, &rat->pos, 0);
}
}
if (!i && !(GetRandomControl() & 4))
SoundEffect(SFX_RATS_1, &rat->pos, 0);
}
}
}
}
void UpdateSpiders()
{
if (Objects[ID_SPIDER].loaded)
{
for (int i = 0; i < NUM_SPIDERS; i++)
{
SPIDER_STRUCT* spider = &Spiders[i];
if (spider->on)
{
int x = spider->pos.xPos;
int y = spider->pos.yPos;
int z = spider->pos.zPos;
spider->pos.xPos += spider->speed * SIN(spider->pos.yRot) >> W2V_SHIFT;
spider->pos.yPos += spider->fallspeed;
spider->pos.zPos += spider->speed * COS(spider->pos.yRot) >> W2V_SHIFT;
spider->fallspeed += GRAVITY;
int dx = LaraItem->pos.xPos - spider->pos.xPos;
int dy = LaraItem->pos.yPos - spider->pos.yPos;
int dz = LaraItem->pos.zPos - spider->pos.zPos;
short angle = ATAN(dz, dx) - spider->pos.yRot;
if (abs(dx) < 85 && abs(dy) < 85 && abs(dz) < 85)
{
LaraItem->hitPoints -= 3;
LaraItem->hitStatus = true;
TriggerBlood(spider->pos.xPos, spider->pos.yPos, spider->pos.zPos, spider->pos.yRot, 1);
}
if (spider->flags)
{
if (abs(dx) + abs(dz) <= 768)
{
if (spider->speed & 1)
spider->pos.yRot += 512;
else
spider->pos.yRot -= 512;
spider->speed = 48 - (abs(angle) >> 10);
}
else
{
if (spider->speed < (i & 0x1F) + 24)
spider->speed++;
if (abs(angle) >= 2048)
{
if (angle >= 0)
spider->pos.yRot += 1024;
else
spider->pos.yRot -= 1024;
}
else
{
spider->pos.yRot += 8 * (Wibble - i);
}
}
}
FLOOR_INFO* floor = GetFloor(spider->pos.xPos, spider->pos.yPos, spider->pos.zPos, &spider->roomNumber);
int height = GetFloorHeight(floor, spider->pos.xPos, spider->pos.yPos, spider->pos.zPos);
if (height >= spider->pos.yPos - 1280 || height == -32512)
{
if (height >= spider->pos.yPos - 64)
{
if (spider->pos.yPos <= height)
{
if (spider->fallspeed >= 500)
{
spider->on = false;
NextSpider = 0;
}
else
{
spider->pos.xRot = -128 * spider->fallspeed;
}
}
else
{
spider->pos.yPos = height;
spider->fallspeed = 0;
spider->flags = 1;
}
}
else
{
spider->pos.xRot = 14336;
spider->pos.xPos = x;
spider->pos.yPos = y - 8;
spider->pos.zPos = z;
spider->fallspeed = 0;
if (!(GetRandomControl() & 0x1F))
spider->pos.yRot += -ANGLE(180);
}
}
else
{
if (angle <= 0)
spider->pos.yRot -= ANGLE(90);
else
spider->pos.yRot += ANGLE(90);
spider->pos.xPos = x;
spider->pos.yPos = y;
spider->pos.zPos = z;
spider->fallspeed = 0;
}
if (spider->pos.yPos < Rooms[spider->roomNumber].maxceiling + 50)
{
spider->fallspeed = 1;
spider->pos.yRot += -32768;
spider->pos.yPos = Rooms[spider->roomNumber].maxceiling + 50;
}
if (!i && !(GetRandomControl() & 4))
SoundEffect(SFX_BEETLES, &spider->pos, 0);
}
}
}
}

View file

@ -1,74 +1,2 @@
#include "..\newobjects.h"
short GetNextRat()
{
short ratNum = NextRat;
int i = 0;
RAT_STRUCT* rat = &Rats[NextRat];
while (rat->on)
{
if (ratNum == 31)
{
rat = &Rats[0];
ratNum = 0;
}
else
{
ratNum++;
rat++;
}
i++;
if (i >= 32)
return NO_ITEM;
}
NextRat = (ratNum + 1) & 0x1F;
return ratNum;
}
void ControlLittleRats(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
if (item->triggerFlags)
{
if (!item->itemFlags[2] || !(GetRandomControl() & 0xF))
{
item->triggerFlags--;
if (item->itemFlags[2] && GetRandomControl() & 1)
item->itemFlags[2]--;
short ratNum = GetNextRat();
if (ratNum != -1)
{
RAT_STRUCT* rat = &Rats[ratNum];
rat->pos.xPos = item->pos.xPos;
rat->pos.yPos = item->pos.yPos;
rat->pos.zPos = item->pos.zPos;
rat->roomNumber = item->roomNumber;
if (item->itemFlags[0])
{
rat->pos.yRot = 2 * GetRandomControl();
rat->fallspeed = -16 - (GetRandomControl() & 0x1F);
}
else
{
rat->fallspeed = 0;
rat->pos.yRot = item->pos.yRot + (GetRandomControl() & 0x3FFF) - ANGLE(45);
}
rat->pos.xRot = 0;
rat->pos.zRot = 0;
rat->on = 1;
rat->flags = GetRandomControl() & 0x1E;
rat->speed = (GetRandomControl() & 0x1F) + 1;
}
}
}
}

View file

@ -21,8 +21,8 @@
//#define ControlInvisibleGhost ((void (__cdecl*)(short)) 0x00477AB0)
//#define InitialiseLittleBats ((void (__cdecl*)(short)) 0x00407EC0)
//#define ControlLittleBats ((void (__cdecl*)(short)) 0x00407F50)
#define InitialiseSpiders ((void (__cdecl*)(short)) 0x0043F2B0)
#define ControlSpiders ((void (__cdecl*)(short)) 0x0047A200)
//#define InitialiseSpiders ((void (__cdecl*)(short)) 0x0043F2B0)
//#define ControlSpiders ((void (__cdecl*)(short)) 0x0047A200)
//#define ControlGladiator ((void (__cdecl*)(short)) 0x00436700)
//#define ControlRomanStatue ((void (__cdecl*)(short)) 0x0046BC10)
//#define ControlAutoGuns ((void (__cdecl*)(short)) 0x004078A0)
@ -30,9 +30,15 @@
//#define InitialiseRomanStatue ((void (__cdecl*)(short)) 0x0046BB00) // need to check a dword_ variable before decompiling
extern int NumBats;
extern int NextBat;
extern BAT_STRUCT* Bats;
extern int NextSpider;
extern SPIDER_STRUCT* Spiders;
extern int NextRat;
extern RAT_STRUCT* Rats;
void InitialiseGuard(short itemNum);
void InitialiseGuardM16(short itemNum);
void InitialiseGuardLaser(short itemNum);
@ -130,7 +136,7 @@ void ChaffFlareControl(short itemNumber);
void TorpedoControl(short itemNumber);
void InitialiseLittleBats(short itemNumber);
void ControlLittleBats(short itemNumber);
short GetFreeBat();
short GetNextBat();
void TriggerLittleBat(ITEM_INFO* item);
void TriggerCyborgSparks(int x, int y, int z, short xv, short yv, short zv);
void ControlCyborg(short itemNumber);
@ -141,4 +147,14 @@ void HydraBubblesAttack(PHD_3DPOS* pos, short roomNumber, int count);
void TriggerAutoGunSmoke(PHD_VECTOR* pos, char shade);
void ControlAutoGuns(short itemNumber);
void TriggerLaserHeadSparks1(PHD_VECTOR* pos, int count, CVECTOR* color, int unk);
void LaserHeadCharge(ITEM_INFO* item);
void LaserHeadCharge(ITEM_INFO* item);
short GetNextSpider();
void ControlSpiders(short itemNumber);
void InitialiseSpiders(short itemNumber);
void ClearSpidersPatch(ITEM_INFO* item);
void ClearSpiders();
void InitialiseLittleRats(short itemNumber);
void ClearRats();
void UpdateSpiders();
void UpdateRats();
void UpdateBats();