mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-12 21:47:03 +03:00
Finished decompiling WRAITH
This commit is contained in:
parent
7adfdbc8f6
commit
2f93e8598c
3 changed files with 334 additions and 66 deletions
|
@ -7,24 +7,13 @@
|
|||
#include "trmath.h"
|
||||
#include <sound.h>
|
||||
#include <lara.h>
|
||||
#include <traps.h>
|
||||
#include <tomb4fx.h>
|
||||
|
||||
constexpr auto WRAITH_COUNT = 8;
|
||||
|
||||
short WraithSpeed = 64;
|
||||
|
||||
struct WRAITH_INFO
|
||||
{
|
||||
int xPos;
|
||||
int yPos;
|
||||
int zPos;
|
||||
short xRot;
|
||||
short yRot;
|
||||
short zRot;
|
||||
unsigned char unknown01;
|
||||
unsigned char unknown02;
|
||||
unsigned char unknown03;
|
||||
};
|
||||
|
||||
void InitialiseWraith(short itemNumber)
|
||||
{
|
||||
ITEM_INFO* item;
|
||||
|
@ -46,9 +35,9 @@ void InitialiseWraith(short itemNumber)
|
|||
wraithData->zRot = 0;
|
||||
wraithData->yPos = 0;
|
||||
wraithData->xPos = 0;
|
||||
wraithData->unknown01 = 0;
|
||||
wraithData->unknown02 = 0;
|
||||
wraithData->unknown03 = 0;
|
||||
wraithData->r = 0;
|
||||
wraithData->g = 0;
|
||||
wraithData->b = 0;
|
||||
|
||||
wraithData++;
|
||||
}
|
||||
|
@ -66,7 +55,7 @@ void WraithControl(short itemNumber)
|
|||
else
|
||||
target = LaraItem;
|
||||
|
||||
int x, y, z, distance, dx, dy, dz;
|
||||
int x, y, z, distance, dx, dy, dz, oldX, oldY, oldZ;
|
||||
|
||||
if (target == LaraItem || target->objectNumber == 445)
|
||||
{
|
||||
|
@ -163,11 +152,13 @@ void WraithControl(short itemNumber)
|
|||
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
||||
int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
||||
int ceiling = GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
||||
int doEffect = 0;
|
||||
bool hitWall = false;
|
||||
if (height < item->pos.yPos || ceiling > item->pos.yPos)
|
||||
{
|
||||
doEffect = 1;
|
||||
}
|
||||
hitWall = true;
|
||||
|
||||
oldX = item->pos.xPos;
|
||||
oldY = item->pos.yPos;
|
||||
oldZ = item->pos.zPos;
|
||||
|
||||
item->pos.xPos += item->speed * phd_sin(item->pos.yRot) >> W2V_SHIFT;
|
||||
item->pos.yPos += item->speed * phd_sin(item->pos.xRot) >> W2V_SHIFT;
|
||||
|
@ -200,9 +191,244 @@ void WraithControl(short itemNumber)
|
|||
item->hitPoints = linkNum;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->objectNumber != ID_WRAITH3)
|
||||
{
|
||||
// WRAITH1 AND WRAITH2 can die on contact with water
|
||||
// WRAITH1 dies because it's fire and it dies on contact with water, WRAITH2 instead triggers a flipmap for making icy water
|
||||
if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
|
||||
{
|
||||
TriggerExplosionSparks(item->pos.xPos, item->pos.yPos, item->pos.zPos, 2, -2, 1, item->roomNumber);
|
||||
item->itemFlags[1]--;
|
||||
if (item->itemFlags[1] < -1)
|
||||
{
|
||||
if (item->itemFlags[1] < 30)
|
||||
{
|
||||
if (item->objectNumber == ID_WRAITH2)
|
||||
{
|
||||
if (item->triggerFlags)
|
||||
{
|
||||
if (!FlipStats[item->triggerFlags])
|
||||
{
|
||||
DoFlipMap(item->triggerFlags);
|
||||
FlipStats[item->triggerFlags] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
KillItem(itemNumber);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->itemFlags[1] = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->itemFlags[1]--;
|
||||
if (item->itemFlags[1] < 0)
|
||||
{
|
||||
item->itemFlags[1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distance >= 28900 || abs(item->pos.yPos - target->pos.yPos + 384) >= 256)
|
||||
{
|
||||
if (Wibble & 16)
|
||||
{
|
||||
if (item->speed < WraithSpeed)
|
||||
{
|
||||
item->speed++;
|
||||
}
|
||||
if (item->hitPoints)
|
||||
{
|
||||
if (item->TOSSPAD & 0x3E00)
|
||||
{
|
||||
item->TOSSPAD = ((item->TOSSPAD & 0xFE00) - 1) & 0x3E00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->speed > 32)
|
||||
{
|
||||
item->speed -= 12;
|
||||
}
|
||||
if (target == LaraItem)
|
||||
{
|
||||
target->hitPoints -= distance / 1024;
|
||||
|
||||
// WRAITH1 can burn Lara
|
||||
if (item->objectNumber == ID_WRAITH1)
|
||||
{
|
||||
item->itemFlags[1] += 400;
|
||||
if (item->itemFlags[1] > 8000)
|
||||
{
|
||||
LaraBurn();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (target->objectNumber == ID_ANIMATING10)
|
||||
{
|
||||
// ANIMATING10 is the sacred pedistal that can kill WRAITH
|
||||
item->TOSSPAD = ((item->TOSSPAD & 0xFE00) + 512) & 0x3E00; // HACK: maybe create new var for this
|
||||
if (item->TOSSPAD & 0x3E00 > 12800)
|
||||
{
|
||||
item->pos.xPos = target->pos.xPos;
|
||||
item->pos.yPos = target->pos.yPos - 384;
|
||||
item->pos.zPos = target->pos.zPos;
|
||||
WraithExplosionEffect(item, 96, 96, 96, -32);
|
||||
WraithExplosionEffect(item, 48, 48, 48, 48);
|
||||
target->triggerFlags--;
|
||||
target->hitPoints = 0;
|
||||
if (target->triggerFlags > 0)
|
||||
{
|
||||
target->frameNumber = g_Level.Anims[target->animNumber].frameBase;
|
||||
}
|
||||
KillItem(itemNumber);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Target is another WRAITH (fire vs ice), they kill both themselves
|
||||
item->TOSSPAD = item->TOSSPAD & 0xD5FF | 0x1400;
|
||||
if (item->TOSSPAD & 0x3E00)
|
||||
{
|
||||
TriggerExplosionSparks(item->pos.xPos, item->pos.yPos, item->pos.zPos, 2, -2, 1, item->roomNumber);
|
||||
target->hitPoints = 0;
|
||||
KillItem(item->hitPoints);
|
||||
KillItem(itemNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if WRAITH is going below floor or above ceiling and trigger sparks
|
||||
roomNumber = item->roomNumber;
|
||||
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
||||
if (GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) < item->pos.yPos
|
||||
|| GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) > item->pos.yPos)
|
||||
{
|
||||
if (!hitWall)
|
||||
{
|
||||
WraithWallsEffect(oldX, oldY, oldZ, item->pos.yRot + -ANGLE(180), item->objectNumber);
|
||||
}
|
||||
}
|
||||
else if (hitWall)
|
||||
{
|
||||
WraithWallsEffect(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->pos.yRot, item->objectNumber);
|
||||
}
|
||||
|
||||
// Update WRAITH nodes
|
||||
WRAITH_INFO* creature = (WRAITH_INFO*)item->data;
|
||||
int j = 0;
|
||||
for (int i = WRAITH_COUNT - 1; i > 0; i--)
|
||||
{
|
||||
creature[i - 1].xPos += (creature[i - 1].xRot / 16);
|
||||
creature[i - 1].yPos += (creature[i - 1].yRot / 16);
|
||||
creature[i - 1].zPos += (creature[i - 1].zRot / 16);
|
||||
|
||||
creature[i - 1].xRot -= (creature[i - 1].xRot / 16);
|
||||
creature[i - 1].yRot -= (creature[i - 1].yRot / 16);
|
||||
creature[i - 1].zRot -= (creature[i - 1].zRot / 16);
|
||||
|
||||
creature[i].xPos = creature[i - 1].xPos;
|
||||
creature[i].yPos = creature[i - 1].yPos;
|
||||
creature[i].zPos = creature[i - 1].zPos;
|
||||
|
||||
creature[i].xRot = creature[i - 1].xRot;
|
||||
creature[i].yRot = creature[i - 1].yRot;
|
||||
creature[i].zRot = creature[i - 1].zRot;
|
||||
|
||||
if (item->objectNumber == ID_WRAITH1)
|
||||
{
|
||||
creature[i].r = (GetRandomControl() & 0x3F) - 64;
|
||||
creature[i].g = 16 * (j + 1) + (GetRandomControl() & 0x3F);
|
||||
creature[i].b = GetRandomControl() & 0xF;
|
||||
}
|
||||
else if (item->objectNumber == ID_WRAITH2)
|
||||
{
|
||||
creature[i].r = GetRandomControl() & 0xF;
|
||||
creature[i].g = 16 * (j + 1) + (GetRandomControl() & 0x3F);
|
||||
creature[i].b = (GetRandomControl() & 0x3F) - 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
creature[i].r = 8 * (j + 2) + (GetRandomControl() & 0x3F);
|
||||
creature[i].g = creature[i].r;
|
||||
creature[i].b = creature[i].r + (GetRandomControl() & 0xF);
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
creature[0].xPos = item->pos.xPos;
|
||||
creature[0].yPos = item->pos.yPos;
|
||||
creature[0].zPos = item->pos.zPos;
|
||||
|
||||
creature[0].xRot = (item->pos.xPos - oldX);
|
||||
creature[0].yRot = (item->pos.yPos - oldY);
|
||||
creature[0].zRot = (item->pos.zPos - oldZ);
|
||||
|
||||
// Standard WRAITH drawing code
|
||||
DrawWraith(
|
||||
item->pos.xPos,
|
||||
item->pos.yPos,
|
||||
item->pos.zPos,
|
||||
creature[0].xRot,
|
||||
creature[0].yRot,
|
||||
creature[0].zRot,
|
||||
item->objectNumber);
|
||||
|
||||
DrawWraith(
|
||||
(oldX + item->pos.xPos) / 2,
|
||||
(oldY + item->pos.yPos) / 2,
|
||||
(oldZ + item->pos.zPos) / 2,
|
||||
creature[0].xRot,
|
||||
creature[0].yRot,
|
||||
creature[0].zRot,
|
||||
item->objectNumber);
|
||||
|
||||
// Lighting for WRAITH
|
||||
byte r, g, b;
|
||||
if (item->objectNumber == ID_WRAITH3)
|
||||
{
|
||||
r = creature[5].r;
|
||||
g = creature[5].g;
|
||||
b = creature[5].b;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = creature[1].r;
|
||||
g = creature[1].g;
|
||||
b = creature[1].b;
|
||||
}
|
||||
|
||||
TriggerDynamicLight(
|
||||
creature[0].xPos,
|
||||
creature[0].yPos,
|
||||
creature[0].zPos,
|
||||
16,
|
||||
r, g, b);
|
||||
}
|
||||
|
||||
void WraithEffects(int x, int y, int z, short xVel, short yVel, short zVel, int objNumber)
|
||||
void WraithExplosionEffect(ITEM_INFO* item, byte r, byte g, byte b, int speed)
|
||||
{
|
||||
short inner = speed >= 0 ? 32 : 640;
|
||||
short outer = speed >= 0 ? 160 : 512;
|
||||
|
||||
item->pos.yPos -= 384;
|
||||
|
||||
TriggerShockwave(&item->pos, inner, outer, speed, r, g, b, 24, 0, 0);
|
||||
TriggerShockwave(&item->pos, inner, outer, speed, r, g, b, 24, ANGLE(45), 0);
|
||||
TriggerShockwave(&item->pos, inner, outer, speed, r, g, b, 24, ANGLE(90), 0);
|
||||
TriggerShockwave(&item->pos, inner, outer, speed, r, g, b, 24, ANGLE(135), 0);
|
||||
|
||||
item->pos.yPos += 384;
|
||||
}
|
||||
|
||||
void DrawWraith(int x, int y, int z, short xVel, short yVel, short zVel, int objNumber)
|
||||
{
|
||||
unsigned char size, life;
|
||||
BYTE color;
|
||||
|
@ -227,7 +453,6 @@ void WraithEffects(int x, int y, int z, short xVel, short yVel, short zVel, int
|
|||
spark->dR = 24;
|
||||
spark->dG = (GetRandomControl() & 0x1F) + 64;
|
||||
}
|
||||
|
||||
else {
|
||||
color = (GetRandomControl() & 0x1F) + 64;
|
||||
spark->dG = color;
|
||||
|
@ -247,7 +472,7 @@ void WraithEffects(int x, int y, int z, short xVel, short yVel, short zVel, int
|
|||
spark->x = (GetRandomControl() & 0x1F) + x - 16;
|
||||
spark->y = y;
|
||||
spark->friction = 85;
|
||||
spark->flags = 522;
|
||||
spark->flags = SP_EXPDEF | SP_DEF | SP_SCALE;
|
||||
spark->z = (GetRandomControl() & 0x1F) + z - 16;
|
||||
spark->xVel = xVel;
|
||||
spark->yVel = yVel;
|
||||
|
@ -261,70 +486,73 @@ void WraithEffects(int x, int y, int z, short xVel, short yVel, short zVel, int
|
|||
spark->size = size;
|
||||
}
|
||||
|
||||
/*
|
||||
void DrawWraithEffect(int x, int y, int z, short yrot, short objNumber)
|
||||
void WraithWallsEffect(int x, int y, int z, short yrot, short objNumber)
|
||||
{
|
||||
BYTE life;
|
||||
unsigned char size;
|
||||
signed int i;
|
||||
int objNumbera,v5,v6,v7,v8,v9,v10,v11,v13;
|
||||
SPARKS* spark;
|
||||
spark = &Sparks[GetFreeSpark()];
|
||||
|
||||
byte sR, sG, sB, dR, dG, dB;
|
||||
short color;
|
||||
|
||||
if (objNumber == ID_WRAITH1)
|
||||
{
|
||||
v5 = GetRandomControl() << 8;
|
||||
v6 = ((GetRandomControl() | v5) << 32) | 0x18000001;
|
||||
v7 = ((GetRandomControl() & 0x1F) + 48) << 8;
|
||||
v8 = (((GetRandomControl() & 0x1F) + 128) << 16) | v7 | 0x18;
|
||||
sR = (GetRandomControl() & 0x1F) + -128;
|
||||
sB = 24;
|
||||
sG = (GetRandomControl() & 0x1F) + 48;
|
||||
dR = (GetRandomControl() & 0x1F) + -128;
|
||||
dB = 24;
|
||||
dG = (GetRandomControl() & 0x1F) + 64;
|
||||
}
|
||||
else if (objNumber == ID_WRAITH2) {
|
||||
v9 = ((GetRandomControl() & 0x1F) << 24) - 0x7FFFFFFF;
|
||||
v6 = (GetRandomControl() << 32) | v9 | 1;
|
||||
v10 = ((GetRandomControl() & 0x1F) + 48) << 8;
|
||||
v8 = ((GetRandomControl() & 0x1F) + 128) | v10 | 0x180000;
|
||||
sB = (GetRandomControl() & 0x1F) + -128;
|
||||
sR = 24;
|
||||
sG = (GetRandomControl() & 0x1F) + -128;
|
||||
dB = (GetRandomControl() & 0x1F) + -128;
|
||||
dR = 24;
|
||||
dG = (GetRandomControl() & 0x1F) + 64;
|
||||
}
|
||||
else {
|
||||
v11 = (GetRandomControl() & 0xF) + 64;
|
||||
v6 = ((v11 | ((v11 | (v11 << 8)) << 8)) << 24) | 1;
|
||||
v8 = ((v11 | (v11 << 8)) << 8) | (v11 + (GetRandomControl() & 0xF));
|
||||
color = (GetRandomControl() & 0x1F) + 64;
|
||||
dG = color;
|
||||
dR = color;
|
||||
sB = color;
|
||||
sG = color;
|
||||
sR = color;
|
||||
dB = sB + (GetRandomControl() & 0x1F);
|
||||
}
|
||||
|
||||
objNumbera = (v8 & 0xFF00) | (v8 << 16) | BYTE2(v8);
|
||||
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
*&spark->on = v6;
|
||||
*&spark->dR = objNumbera;
|
||||
*&spark->colFadeSpeed = 1796;
|
||||
v13 = GetRandomControl();
|
||||
SPARKS* spark = &Sparks[GetFreeSpark()];
|
||||
spark->on = true;
|
||||
spark->sR = dR;
|
||||
spark->sG = dG;
|
||||
spark->sB = dB;
|
||||
spark->dR = dR;
|
||||
spark->dG = dG;
|
||||
spark->dB = dB;
|
||||
spark->colFadeSpeed = 4;
|
||||
spark->fadeToBlack = 7;
|
||||
spark->transType = COLADD;
|
||||
life = (v13 & 7) + 32;
|
||||
short life = (GetRandomControl() & 7) + 32;
|
||||
spark->life = life;
|
||||
spark->sLife = life;
|
||||
spark->x = (GetRandomControl() & 0x1F) + x - 16;
|
||||
spark->y = (GetRandomControl() & 0x1F) + y - 16;
|
||||
spark->z = (GetRandomControl() & 0x1F) + z - 16;
|
||||
v15 = GetRandomControl() - 0x4000;
|
||||
v16 = (GetRandomControl() & 0x3FF) + 1024;
|
||||
v17 = ((yrot + v15) >> 3) & 0x1FFE;
|
||||
spark->xVel = v16 * 4 * rcossin_tbl[v17] >> 14;
|
||||
short rot = yrot + GetRandomControl() - ANGLE(90);
|
||||
short velocity = ((GetRandomControl() & 0x3FF) + 1024);
|
||||
spark->xVel = velocity * phd_sin(rot) >> W2V_SHIFT;
|
||||
spark->yVel = (GetRandomControl() & 0x7F) - 64;
|
||||
spark->zVel = v16 * 4 * rcossin_tbl[v17 + 1] >> 14;
|
||||
spark->zVel = velocity * phd_cos(rot) >> W2V_SHIFT;
|
||||
spark->friction = 4;
|
||||
spark->flags = 522;
|
||||
v18 = GetRandomControl();
|
||||
spark->flags = SP_EXPDEF | SP_DEF | SP_SCALE;
|
||||
spark->maxYvel = 0;
|
||||
spark->scalar = 3;
|
||||
spark->gravity = (v18 & 0x7F) - 64;
|
||||
size = (GetRandomControl() & 0x1F) + 48;
|
||||
spark->gravity = (GetRandomControl() & 0x7F) - 64;
|
||||
short size = (GetRandomControl() & 0x1F) + 48;
|
||||
spark->sSize = size;
|
||||
spark->size = size;
|
||||
spark->dSize = size >> 2;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void DrawWraith(ITEM_INFO* item)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,23 @@
|
|||
#pragma once
|
||||
#include "items.h"
|
||||
|
||||
struct WRAITH_INFO
|
||||
{
|
||||
int xPos;
|
||||
int yPos;
|
||||
int zPos;
|
||||
short xRot;
|
||||
short yRot;
|
||||
short zRot;
|
||||
byte r;
|
||||
byte g;
|
||||
byte b;
|
||||
};
|
||||
|
||||
void InitialiseWraith(short itemNumber);
|
||||
void WraithControl(short itemNumber);
|
||||
void WraithEffects(int x, int y, int z, short xVel, short yVel, short zVel, int objNumber);
|
||||
void DrawWraithEffect(int x, int y, int z, short yrot, short objNumber);
|
||||
void WraithWallsEffect(int x, int y, int z, short yrot, short objNumber);
|
||||
void DrawWraith(int x, int y, int z, short xVel, short yVel, short zVel, int objNumber);
|
||||
void DrawWraith(ITEM_INFO* item);
|
||||
void KillWraith(ITEM_INFO* item);
|
||||
void WraithExplosionEffect(ITEM_INFO* item, byte r, byte g, byte b, int speed);
|
|
@ -580,11 +580,38 @@ static void StartBaddy(OBJECT_INFO* obj)
|
|||
obj->zoneType = ZONE_BASIC;
|
||||
}
|
||||
|
||||
obj = &Objects[ID_WRAITH1];
|
||||
if (obj->loaded)
|
||||
{
|
||||
obj->initialise = InitialiseWraith;
|
||||
obj->control = WraithControl;
|
||||
obj->savePosition = true;
|
||||
obj->saveHitpoints = true;
|
||||
obj->saveFlags = true;
|
||||
obj->saveAnim = true;
|
||||
}
|
||||
|
||||
obj = &Objects[ID_WRAITH2];
|
||||
if (obj->loaded)
|
||||
{
|
||||
obj->initialise = InitialiseWraith;
|
||||
obj->control = WraithControl;
|
||||
obj->savePosition = true;
|
||||
obj->saveHitpoints = true;
|
||||
obj->saveFlags = true;
|
||||
obj->saveAnim = true;
|
||||
}
|
||||
|
||||
obj = &Objects[ID_WRAITH3];
|
||||
if (obj->loaded)
|
||||
{
|
||||
//not decompiled yet and multiple versions of wraiths exist
|
||||
}
|
||||
obj->initialise = InitialiseWraith;
|
||||
obj->control = WraithControl;
|
||||
obj->savePosition = true;
|
||||
obj->saveHitpoints = true;
|
||||
obj->saveFlags = true;
|
||||
obj->saveAnim = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void StartObject(OBJECT_INFO* obj)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue