diff --git a/TR5Main/Game/Box.h b/TR5Main/Game/Box.h
index b1b7134f5..17b1c7eec 100644
--- a/TR5Main/Game/Box.h
+++ b/TR5Main/Game/Box.h
@@ -38,14 +38,14 @@ enum ZoneType
ZONE_HUMAN_LONGJUMP_AND_MONKEY,
};
-struct OBJECT_Bones
+struct OBJECT_BONES
{
short bone0;
short bone1;
short bone2;
short bone3;
- OBJECT_Bones()
+ OBJECT_BONES()
{
this->bone0 = 0;
this->bone1 = 0;
@@ -53,7 +53,7 @@ struct OBJECT_Bones
this->bone3 = 0;
}
- OBJECT_Bones(short all)
+ OBJECT_BONES(short all)
{
this->bone0 = all;
this->bone1 = all;
@@ -61,7 +61,7 @@ struct OBJECT_Bones
this->bone3 = all;
}
- OBJECT_Bones(short angleY, short angleX)
+ OBJECT_BONES(short angleY, short angleX)
{
this->bone0 = angleY;
this->bone1 = angleX;
@@ -69,7 +69,7 @@ struct OBJECT_Bones
this->bone3 = angleX;
}
- OBJECT_Bones(short angleY, short angleX, bool total)
+ OBJECT_BONES(short angleY, short angleX, bool total)
{
this->bone0 = angleY;
this->bone1 = angleX;
diff --git a/TR5Main/Objects/Effects/tr4_bubbles.cpp b/TR5Main/Objects/Effects/tr4_bubbles.cpp
index 17813106e..d3bad2128 100644
--- a/TR5Main/Objects/Effects/tr4_bubbles.cpp
+++ b/TR5Main/Objects/Effects/tr4_bubbles.cpp
@@ -11,426 +11,429 @@
#include "lara.h"
#include "tr4_mutant.h"
-void BubblesEffect1(short fxNum, short xVel, short yVel, short zVel)
+namespace ten::entities::all
{
- FX_INFO* fx = &EffectList[fxNum];
-
- int dx = LaraItem->pos.xPos - fx->pos.xPos;
- int dz = LaraItem->pos.zPos - fx->pos.zPos;
-
- if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
+ void TriggerSethMissileFlame(short fxNum, short xVel, short yVel, short zVel)
{
- SPARKS* spark = &Sparks[GetFreeSpark()];
+ FX_INFO* fx = &EffectList[fxNum];
- spark->on = 1;
- spark->sR = 0;
- spark->dR = 0;
- spark->sG = (GetRandomControl() & 0x7F) + 32;
- spark->sB = spark->dG + 64;
- spark->dB = (GetRandomControl() & 0x7F) + 32;
- spark->dG = spark->dB + 64;
- spark->fadeToBlack = 8;
- spark->colFadeSpeed = (GetRandomControl() & 3) + 4;
- spark->transType = COLADD;
- spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
- spark->y = 0;
- spark->x = (GetRandomControl() & 0xF) - 8;
- spark->xVel = xVel;
- spark->yVel = yVel;
- spark->z = (GetRandomControl() & 0xF) - 8;
- spark->zVel = zVel;
- spark->friction = 68;
- spark->flags = 602;
- spark->rotAng = GetRandomControl() & 0xFFF;
- if (GetRandomControl() & 1)
+ int dx = LaraItem->pos.xPos - fx->pos.xPos;
+ int dz = LaraItem->pos.zPos - fx->pos.zPos;
+
+ if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
{
- spark->rotAdd = -32 - (GetRandomControl() & 0x1F);
- }
- else
- {
- spark->rotAdd = (GetRandomControl() & 0x1F) + 32;
- }
- spark->gravity = 0;
- spark->maxYvel = 0;
- spark->fxObj = fxNum;
- if (fx->flag1 == 1)
- {
- spark->scalar = 3;
- }
- else
- {
- spark->scalar = 2;
- }
- spark->sSize = spark->size = (GetRandomControl() & 7) + 64;
- spark->dSize = spark->size / 32;
- }
-}
+ SPARKS* spark = &Sparks[GetFreeSpark()];
-void BubblesEffect2(short fxNum, short xVel, short yVel, short zVel)
-{
- FX_INFO* fx = &EffectList[fxNum];
-
- int dx = LaraItem->pos.xPos - fx->pos.xPos;
- int dz = LaraItem->pos.zPos - fx->pos.zPos;
-
- if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
- {
- SPARKS* spark = &Sparks[GetFreeSpark()];
-
- spark->on = 1;
- spark->sR = 0;
- spark->sG = (GetRandomControl() & 0x7F) + 32;
- spark->sB = spark->dG + 64;
- spark->dB = 0;
- spark->dG = spark->dR = (GetRandomControl() & 0x7F) + 32;
- spark->fadeToBlack = 8;
- spark->colFadeSpeed = (GetRandomControl() & 3) + 4;
- spark->transType = COLADD;
- spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
- spark->y = 0;
- spark->x = (GetRandomControl() & 0xF) - 8;
- spark->xVel = xVel;
- spark->zVel = zVel;
- spark->z = (GetRandomControl() & 0xF) - 8;
- spark->yVel = yVel;
- spark->friction = 68;
- spark->flags = 602;
- spark->rotAng = GetRandomControl() & 0xFFF;
- if (GetRandomControl() & 1)
- {
- spark->rotAdd = -32 - (GetRandomControl() & 0x1F);
- }
- else
- {
- spark->rotAdd = (GetRandomControl() & 0x1F) + 32;
- }
- spark->gravity = 0;
- spark->maxYvel = 0;
- spark->fxObj = fxNum;
- spark->scalar = 2;
- spark->sSize = spark->size = (GetRandomControl() & 7) + 64;
- spark->dSize = spark->size / 32;
- }
-}
-
-void BubblesEffect4(short fxNum, short xVel, short yVel, short zVel)
-{
- FX_INFO* fx = &EffectList[fxNum];
-
- int dx = LaraItem->pos.xPos - fx->pos.xPos;
- int dz = LaraItem->pos.zPos - fx->pos.zPos;
-
- if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
- {
- SPARKS* spark = &Sparks[GetFreeSpark()];
-
- spark->on = 1;
- if (fx->flag1 == 3 || fx->flag1 == 4)
- {
+ spark->on = 1;
spark->sR = 0;
spark->dR = 0;
- spark->sB = (GetRandomControl() & 0x7F) + 32;
- spark->sG = spark->sB + 64;
- spark->dG = (GetRandomControl() & 0x7F) + 32;
- spark->dB = spark->dG + 64;
- }
- else
- {
- spark->sR = (GetRandomControl() & 0x7F) + 32;
- spark->sG = spark->sR - (GetRandomControl() & 0x1F);
- spark->sB = 0;
- spark->dR = (GetRandomControl() & 0x7F) + 32;
- spark->dB = 0;
- spark->dG = spark->dR - (GetRandomControl() & 0x1F);
- }
- spark->fadeToBlack = 8;
- spark->colFadeSpeed = (GetRandomControl() & 3) + 4;
- spark->transType = COLADD;
- spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
- spark->y = 0;
- spark->x = (GetRandomControl() & 0xF) - 8;
- spark->yVel = yVel;
- spark->zVel = zVel;
- spark->z = (GetRandomControl() & 0xF) - 8;
- spark->xVel = xVel;
- spark->friction = 68;
- spark->flags = 602;
- spark->rotAng = GetRandomControl() & 0xFFF;
- if (GetRandomControl() & 1)
- {
- spark->rotAdd = -32 - (GetRandomControl() & 0x1F);
- }
- else
- {
- spark->rotAdd = (GetRandomControl() & 0x1F) + 32;
- }
- spark->gravity = 0;
- spark->maxYvel = 0;
- spark->fxObj = fxNum;
- spark->scalar = 2;
- spark->sSize = spark->size = (GetRandomControl() & 7) + 64;
- spark->dSize = spark->size / 32;
- }
-}
-
-void BubblesShatterFunction(FX_INFO* fx, int param1, int param2)
-{
- ShatterItem.yRot = fx->pos.yRot;
- ShatterItem.meshp = &g_Level.Meshes[fx->frameNumber];
- 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 & 0x400;
- ShatterObject(&ShatterItem, 0, param2, fx->roomNumber, param1);
-}
-
-void BubblesControl(short fxNum)
-{
- FX_INFO* fx = &EffectList[fxNum];
-
- short angles[2];
- phd_GetVectorAngles(
- LaraItem->pos.xPos - fx->pos.xPos,
- LaraItem->pos.yPos - fx->pos.yPos - STEP_SIZE,
- LaraItem->pos.zPos - fx->pos.zPos,
- angles);
-
- int maxRotation = 0;
- int maxSpeed = 0;
-
- if (fx->flag1 == 1)
- {
- maxRotation = 512;
- maxSpeed = 256;
- }
- else
- {
- if (fx->flag1 == 6)
- {
- if (fx->counter)
+ spark->sG = (GetRandomControl() & 0x7F) + 32;
+ spark->sB = spark->dG + 64;
+ spark->dB = (GetRandomControl() & 0x7F) + 32;
+ spark->dG = spark->dB + 64;
+ spark->fadeToBlack = 8;
+ spark->colFadeSpeed = (GetRandomControl() & 3) + 4;
+ spark->transType = TransTypeEnum::COLADD;
+ spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
+ spark->y = 0;
+ spark->x = (GetRandomControl() & 0xF) - 8;
+ spark->xVel = xVel;
+ spark->yVel = yVel;
+ spark->z = (GetRandomControl() & 0xF) - 8;
+ spark->zVel = zVel;
+ spark->friction = 68;
+ spark->flags = 602;
+ spark->rotAng = GetRandomControl() & 0xFFF;
+ if (GetRandomControl() & 1)
{
- fx->counter--;
+ spark->rotAdd = -32 - (GetRandomControl() & 0x1F);
}
- maxRotation = 256;
+ else
+ {
+ spark->rotAdd = (GetRandomControl() & 0x1F) + 32;
+ }
+ spark->gravity = 0;
+ spark->maxYvel = 0;
+ spark->fxObj = fxNum;
+ if (fx->flag1 == 1)
+ {
+ spark->scalar = 3;
+ }
+ else
+ {
+ spark->scalar = 2;
+ }
+ spark->sSize = spark->size = (GetRandomControl() & 7) + 64;
+ spark->dSize = spark->size / 32;
}
- else
- {
- maxRotation = 768;
- }
- maxSpeed = 192;
}
- if (fx->speed < maxSpeed)
+ void TriggerHarpyFlameFlame(short fxNum, short xVel, short yVel, short zVel)
{
- if (fx->flag1 == 6)
+ FX_INFO* fx = &EffectList[fxNum];
+
+ int dx = LaraItem->pos.xPos - fx->pos.xPos;
+ int dz = LaraItem->pos.zPos - fx->pos.zPos;
+
+ if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
{
- fx->speed++;
+ SPARKS* spark = &Sparks[GetFreeSpark()];
+
+ spark->on = 1;
+ spark->sR = 0;
+ spark->sG = (GetRandomControl() & 0x7F) + 32;
+ spark->sB = spark->dG + 64;
+ spark->dB = 0;
+ spark->dG = spark->dR = (GetRandomControl() & 0x7F) + 32;
+ spark->fadeToBlack = 8;
+ spark->colFadeSpeed = (GetRandomControl() & 3) + 4;
+ spark->transType = COLADD;
+ spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
+ spark->y = 0;
+ spark->x = (GetRandomControl() & 0xF) - 8;
+ spark->xVel = xVel;
+ spark->zVel = zVel;
+ spark->z = (GetRandomControl() & 0xF) - 8;
+ spark->yVel = yVel;
+ spark->friction = 68;
+ spark->flags = 602;
+ spark->rotAng = GetRandomControl() & 0xFFF;
+ if (GetRandomControl() & 1)
+ {
+ spark->rotAdd = -32 - (GetRandomControl() & 0x1F);
+ }
+ else
+ {
+ spark->rotAdd = (GetRandomControl() & 0x1F) + 32;
+ }
+ spark->gravity = 0;
+ spark->maxYvel = 0;
+ spark->fxObj = fxNum;
+ spark->scalar = 2;
+ spark->sSize = spark->size = (GetRandomControl() & 7) + 64;
+ spark->dSize = spark->size / 32;
}
- else
- {
- fx->speed += 3;
- }
-
- int dy = angles[0] - fx->pos.yRot;
- if (abs(dy) <= ANGLE(180.0f))
- {
- dy = -dy;
- }
-
- int dx = angles[1] - fx->pos.xRot;
- if (abs(dx) <= ANGLE(180.0f))
- dx = -dx;
-
- dy /= 8;
- dx /= 8;
-
- if (dy < -maxRotation)
- dy = -maxRotation;
- else if (dy > maxRotation)
- dy = maxRotation;
-
- if (dx < -maxRotation)
- dx = -maxRotation;
- else if (dx > maxRotation)
- dx = maxRotation;
-
- if (fx->flag1 != 4 && (fx->flag1 != 6 || !fx->counter))
- {
- fx->pos.yRot += dy;
- }
- fx->pos.xRot += dx;
}
- fx->pos.zRot += 16 * fx->speed;
- if (fx->flag1 == 6)
- fx->pos.zRot += 16 * fx->speed;
-
- int oldX = fx->pos.xPos;
- int oldY = fx->pos.yPos;
- int oldZ = fx->pos.zPos;
-
- int speed = (fx->speed * phd_cos(fx->pos.xRot));
- fx->pos.zPos += (speed * phd_cos(fx->pos.yRot));
- fx->pos.xPos += (speed * phd_sin(fx->pos.yRot));
- fx->pos.yPos += -((fx->speed * phd_sin(fx->pos.xRot))) + fx->fallspeed;
-
- short roomNumber = fx->roomNumber;
- FLOOR_INFO* floor = GetFloor(fx->pos.xPos, fx->pos.yPos, fx->pos.zPos, &roomNumber);
- int floorHeight = GetFloorHeight(floor, fx->pos.xPos, fx->pos.yPos, fx->pos.zPos);
- int ceilingHeight = GetCeiling(floor, fx->pos.xPos, fx->pos.yPos, fx->pos.zPos);
-
- if (fx->pos.yPos >= floorHeight || fx->pos.yPos <= ceilingHeight)
+ void TriggerDemigodMissileFlame(short fxNum, short xVel, short yVel, short zVel)
{
- fx->pos.xPos = oldX;
- fx->pos.yPos = oldY;
- fx->pos.zPos = oldZ;
+ FX_INFO* fx = &EffectList[fxNum];
+
+ int dx = LaraItem->pos.xPos - fx->pos.xPos;
+ int dz = LaraItem->pos.zPos - fx->pos.zPos;
+
+ if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
+ {
+ SPARKS* spark = &Sparks[GetFreeSpark()];
+
+ spark->on = 1;
+ if (fx->flag1 == 3 || fx->flag1 == 4)
+ {
+ spark->sR = 0;
+ spark->dR = 0;
+ spark->sB = (GetRandomControl() & 0x7F) + 32;
+ spark->sG = spark->sB + 64;
+ spark->dG = (GetRandomControl() & 0x7F) + 32;
+ spark->dB = spark->dG + 64;
+ }
+ else
+ {
+ spark->sR = (GetRandomControl() & 0x7F) + 32;
+ spark->sG = spark->sR - (GetRandomControl() & 0x1F);
+ spark->sB = 0;
+ spark->dR = (GetRandomControl() & 0x7F) + 32;
+ spark->dB = 0;
+ spark->dG = spark->dR - (GetRandomControl() & 0x1F);
+ }
+ spark->fadeToBlack = 8;
+ spark->colFadeSpeed = (GetRandomControl() & 3) + 4;
+ spark->transType = COLADD;
+ spark->life = spark->sLife = (GetRandomControl() & 3) + 16;
+ spark->y = 0;
+ spark->x = (GetRandomControl() & 0xF) - 8;
+ spark->yVel = yVel;
+ spark->zVel = zVel;
+ spark->z = (GetRandomControl() & 0xF) - 8;
+ spark->xVel = xVel;
+ spark->friction = 68;
+ spark->flags = 602;
+ spark->rotAng = GetRandomControl() & 0xFFF;
+ if (GetRandomControl() & 1)
+ {
+ spark->rotAdd = -32 - (GetRandomControl() & 0x1F);
+ }
+ else
+ {
+ spark->rotAdd = (GetRandomControl() & 0x1F) + 32;
+ }
+ spark->gravity = 0;
+ spark->maxYvel = 0;
+ spark->fxObj = fxNum;
+ spark->scalar = 2;
+ spark->sSize = spark->size = (GetRandomControl() & 7) + 64;
+ spark->dSize = spark->size / 32;
+ }
+ }
+
+ void BubblesShatterFunction(FX_INFO* fx, int param1, int param2)
+ {
+ ShatterItem.yRot = fx->pos.yRot;
+ ShatterItem.meshp = &g_Level.Meshes[fx->frameNumber];
+ 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 & 0x400;
+ ShatterObject(&ShatterItem, 0, param2, fx->roomNumber, param1);
+ }
+
+ void ControlEnemyMissile(short fxNum)
+ {
+ FX_INFO* fx = &EffectList[fxNum];
+
+ short angles[2];
+ phd_GetVectorAngles(
+ LaraItem->pos.xPos - fx->pos.xPos,
+ LaraItem->pos.yPos - fx->pos.yPos - STEP_SIZE,
+ LaraItem->pos.zPos - fx->pos.zPos,
+ angles);
+
+ int maxRotation = 0;
+ int maxSpeed = 0;
- if (fx->flag1 != 6)
- BubblesShatterFunction(fx, 0, -32);
-
if (fx->flag1 == 1)
{
- TriggerShockwave(&fx->pos, 32, 160, 64, 64, 128, 00, 24, (((~g_Level.Rooms[fx->roomNumber].flags) / 16) & 2) * 65536, 0);
- TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 2, fx->roomNumber);
+ maxRotation = 512;
+ maxSpeed = 256;
}
else
{
- int shockwaveValue = 0;
- byte r, g, b, life;
-
- if (fx->flag1)
+ if (fx->flag1 == 6)
{
- if (fx->flag1 == 3 || fx->flag1 == 4)
+ if (fx->counter)
{
- shockwaveValue = 268451968;
- r = 128;
- g = 64;
- b = 0;
- life = 16;
+ fx->counter--;
}
- else if (fx->flag1 == 5)
+ maxRotation = 256;
+ }
+ else
+ {
+ maxRotation = 768;
+ }
+ maxSpeed = 192;
+ }
+
+ if (fx->speed < maxSpeed)
+ {
+ if (fx->flag1 == 6)
+ {
+ fx->speed++;
+ }
+ else
+ {
+ fx->speed += 3;
+ }
+
+ int dy = angles[0] - fx->pos.yRot;
+ if (abs(dy) <= ANGLE(180.0f))
+ {
+ dy = -dy;
+ }
+
+ int dx = angles[1] - fx->pos.xRot;
+ if (abs(dx) <= ANGLE(180.0f))
+ dx = -dx;
+
+ dy /= 8;
+ dx /= 8;
+
+ if (dy < -maxRotation)
+ dy = -maxRotation;
+ else if (dy > maxRotation)
+ dy = maxRotation;
+
+ if (dx < -maxRotation)
+ dx = -maxRotation;
+ else if (dx > maxRotation)
+ dx = maxRotation;
+
+ if (fx->flag1 != 4 && (fx->flag1 != 6 || !fx->counter))
+ {
+ fx->pos.yRot += dy;
+ }
+ fx->pos.xRot += dx;
+ }
+
+ fx->pos.zRot += 16 * fx->speed;
+ if (fx->flag1 == 6)
+ fx->pos.zRot += 16 * fx->speed;
+
+ int oldX = fx->pos.xPos;
+ int oldY = fx->pos.yPos;
+ int oldZ = fx->pos.zPos;
+
+ int speed = (fx->speed * phd_cos(fx->pos.xRot));
+ fx->pos.zPos += (speed * phd_cos(fx->pos.yRot));
+ fx->pos.xPos += (speed * phd_sin(fx->pos.yRot));
+ fx->pos.yPos += -((fx->speed * phd_sin(fx->pos.xRot))) + fx->fallspeed;
+
+ short roomNumber = fx->roomNumber;
+ FLOOR_INFO* floor = GetFloor(fx->pos.xPos, fx->pos.yPos, fx->pos.zPos, &roomNumber);
+ int floorHeight = GetFloorHeight(floor, fx->pos.xPos, fx->pos.yPos, fx->pos.zPos);
+ int ceilingHeight = GetCeiling(floor, fx->pos.xPos, fx->pos.yPos, fx->pos.zPos);
+
+ if (fx->pos.yPos >= floorHeight || fx->pos.yPos <= ceilingHeight)
+ {
+ fx->pos.xPos = oldX;
+ fx->pos.yPos = oldY;
+ fx->pos.zPos = oldZ;
+
+ if (fx->flag1 != 6)
+ BubblesShatterFunction(fx, 0, -32);
+
+ if (fx->flag1 == 1)
+ {
+ TriggerShockwave(&fx->pos, 32, 160, 64, 64, 128, 00, 24, (((~g_Level.Rooms[fx->roomNumber].flags) / 16) & 2) * 65536, 0);
+ TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 2, fx->roomNumber);
+ }
+ else
+ {
+ int shockwaveValue = 0;
+ byte r, g, b, life;
+
+ if (fx->flag1)
{
- shockwaveValue = 276848640;
- r = 0;
- g = 96;
- b = 128;
- life = 16;
- }
- else
- {
- if (fx->flag1 != 2)
+ if (fx->flag1 == 3 || fx->flag1 == 4)
{
- if (fx->flag1 == 6)
- {
- TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 0, fx->roomNumber);
- TriggerShockwave(&fx->pos, 48, 240, 64, 0, 96, 128, 24, 0, 2);
- fx->pos.yPos -= 128;
- TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 2);
- fx->pos.yPos += 256;
- TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 2);
- }
+ shockwaveValue = 268451968;
+ r = 128;
+ g = 64;
+ b = 0;
+ life = 16;
}
- else
+ else if (fx->flag1 == 5)
{
- shockwaveValue = 276856832;
+ shockwaveValue = 276848640;
r = 0;
- g = 128;
+ g = 96;
b = 128;
life = 16;
}
+ else
+ {
+ if (fx->flag1 != 2)
+ {
+ if (fx->flag1 == 6)
+ {
+ TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 0, fx->roomNumber);
+ TriggerShockwave(&fx->pos, 48, 240, 64, 0, 96, 128, 24, 0, 2);
+ fx->pos.yPos -= 128;
+ TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 2);
+ fx->pos.yPos += 256;
+ TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 2);
+ }
+ }
+ else
+ {
+ shockwaveValue = 276856832;
+ r = 0;
+ g = 128;
+ b = 128;
+ life = 16;
+ }
+ }
+ }
+ else
+ {
+ shockwaveValue = 268468288;
+ r = 64;
+ g = 128;
+ b = 0;
+ life = 16;
+ }
+
+ TriggerShockwave(&fx->pos, 32, 160, 64, r, g, b, life, 0, 0);
+ }
+
+ KillEffect(fxNum);
+ return;
+ }
+
+ if (ItemNearLara(&fx->pos, 200))
+ {
+ LaraItem->hitStatus = true;
+ if (fx->flag1 != 6)
+ {
+ BubblesShatterFunction(fx, 0, -32);
+ }
+
+ KillEffect(fxNum);
+
+ if (fx->flag1 == 1)
+ {
+ TriggerShockwave(&fx->pos, 48, 240, 64, 64, 128, 0, 24, 0, 0);
+ TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 2, fx->roomNumber);
+ LaraBurn();
+ }
+ else if (fx->flag1)
+ {
+ switch (fx->flag1)
+ {
+ case 3:
+ case 4:
+ TriggerShockwave(&fx->pos, 32, 160, 64, 128, 64, 0, 16, 0, 1);
+ break;
+ case 5:
+ TriggerShockwave(&fx->pos, 32, 160, 64, 0, 96, 128, 16, 0, 2);
+ break;
+ case 2:
+ TriggerShockwave(&fx->pos, 32, 160, 64, 0, 128, 128, 16, 0, 2);
+ break;
+ case 6:
+ TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 0, fx->roomNumber);
+ TriggerShockwave(&fx->pos, 48, 240, 64, 0, 96, 128, 24, 0, 0);
+ fx->pos.yPos -= 128;
+ TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 0);
+ fx->pos.yPos += 256;
+ TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 0);
+ LaraBurn();
+ break;
}
}
else
{
- shockwaveValue = 268468288;
- r = 64;
- g = 128;
- b = 0;
- life = 16;
- }
-
- TriggerShockwave(&fx->pos, 32, 160, 64, r, g, b, life, 0, 0);
- }
-
- KillEffect(fxNum);
- return;
- }
-
- if (ItemNearLara(&fx->pos, 200))
- {
- LaraItem->hitStatus = true;
- if (fx->flag1 != 6)
- {
- BubblesShatterFunction(fx, 0, -32);
- }
-
- KillEffect(fxNum);
-
- if (fx->flag1 == 1)
- {
- TriggerShockwave(&fx->pos, 48, 240, 64, 64, 128, 0, 24, 0, 0);
- TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 2, fx->roomNumber);
- LaraBurn();
- }
- else if (fx->flag1)
- {
- switch (fx->flag1)
- {
- case 3:
- case 4:
- TriggerShockwave(&fx->pos, 32, 160, 64, 128, 64, 0, 16, 0, 1);
- break;
- case 5:
- TriggerShockwave(&fx->pos, 32, 160, 64, 0, 96, 128, 16, 0, 2);
- break;
- case 2:
- TriggerShockwave(&fx->pos, 32, 160, 64, 0, 128, 128, 16, 0, 2);
- break;
- case 6:
- TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 0, fx->roomNumber);
- TriggerShockwave(&fx->pos, 48, 240, 64, 0, 96, 128, 24, 0, 0);
- fx->pos.yPos -= 128;
- TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 0);
- fx->pos.yPos += 256;
- TriggerShockwave(&fx->pos, 48, 240, 48, 0, 112, 128, 16, 0, 0);
- LaraBurn();
- break;
+ TriggerShockwave(&fx->pos, 24, 88, 48, 64, 128, 0, 16, (((~g_Level.Rooms[fx->roomNumber].flags) / 16) & 2) * 65536, 0);
}
}
else
{
- TriggerShockwave( &fx->pos, 24, 88, 48, 64, 128, 0, 16, (((~g_Level.Rooms[fx->roomNumber].flags) / 16) & 2) * 65536, 0);
- }
- }
- else
- {
- if (roomNumber != fx->roomNumber)
- EffectNewRoom(fxNum, roomNumber);
+ if (roomNumber != fx->roomNumber)
+ EffectNewRoom(fxNum, roomNumber);
- int dx = oldX - fx->pos.xPos;
- int dy = oldY - fx->pos.yPos;
- int dz = oldZ - fx->pos.zPos;
+ int dx = oldX - fx->pos.xPos;
+ int dy = oldY - fx->pos.yPos;
+ int dz = oldZ - fx->pos.zPos;
- if (Wibble & 4)
- {
- switch (fx->flag1)
+ if (Wibble & 4)
{
+ switch (fx->flag1)
+ {
default:
case 1:
- BubblesEffect1(fxNum, 32 * dx, 32 * dy, 32 * dz);
+ TriggerSethMissileFlame(fxNum, 32 * dx, 32 * dy, 32 * dz);
break;
case 2:
- BubblesEffect2(fxNum, 16 * dx, 16 * dy, 16 * dz);
+ TriggerHarpyFlameFlame(fxNum, 16 * dx, 16 * dy, 16 * dz);
break;
case 3:
case 4:
case 5:
- BubblesEffect4(fxNum, 16 * dx, 16 * dy, 16 * dz);
+ TriggerDemigodMissileFlame(fxNum, 16 * dx, 16 * dy, 16 * dz);
break;
case 6:
- TriggerMutantRocketEffects(fxNum, 16 * dx, 16 * dy, 16 * dz);
+ ten::entities::tr4::TriggerCrocgodMissileFlame(fxNum, 16 * dx, 16 * dy, 16 * dz);
break;
+ }
}
}
}
diff --git a/TR5Main/Objects/Effects/tr4_bubbles.h b/TR5Main/Objects/Effects/tr4_bubbles.h
index 33fcd8772..c0bbefb80 100644
--- a/TR5Main/Objects/Effects/tr4_bubbles.h
+++ b/TR5Main/Objects/Effects/tr4_bubbles.h
@@ -1,3 +1,6 @@
#pragma once
-void BubblesControl(short fxNum);
\ No newline at end of file
+namespace ten::entities::all
+{
+ void ControlEnemyMissile(short fxNum);
+}
\ No newline at end of file
diff --git a/TR5Main/Objects/TR4/Entity/tr4_crocodile.cpp b/TR5Main/Objects/TR4/Entity/tr4_crocodile.cpp
index 9a0e0ec2e..77df24059 100644
--- a/TR5Main/Objects/TR4/Entity/tr4_crocodile.cpp
+++ b/TR5Main/Objects/TR4/Entity/tr4_crocodile.cpp
@@ -104,7 +104,7 @@ void CrocodileControl(short itemNumber)
OBJECT_INFO* obj;
CREATURE_INFO* crocodile;
AI_INFO info;
- OBJECT_Bones boneRot;
+ OBJECT_BONES boneRot;
short angle;
short boneAngle;
diff --git a/TR5Main/Objects/TR4/Entity/tr4_mutant.cpp b/TR5Main/Objects/TR4/Entity/tr4_mutant.cpp
index 8b8c83d49..5f9a32e7a 100644
--- a/TR5Main/Objects/TR4/Entity/tr4_mutant.cpp
+++ b/TR5Main/Objects/TR4/Entity/tr4_mutant.cpp
@@ -10,341 +10,324 @@
#include "objectslist.h"
#include "trmath.h"
-enum MUTANT_STATE
+namespace ten::entities::tr4
{
- MUTANT_EMPTY,
- MUTANT_APPEAR,
- MUTANT_IDLE,
- MUTANT_SHOOT,
- MUTANT_LOCUST1,
- MUTANT_LOCUST2,
-};
-
-enum class MissileRotationType
-{
- M_FRONT,
- M_LEFT,
- M_RIGHT
-};
-
-constexpr auto MUTANT_ANIM_APPEAR = 0;
-constexpr auto MUTANT_SHOOT_RANGE = SQUARE(SECTOR(10));
-constexpr auto MUTANT_LOCUST1_RANGE = SQUARE(SECTOR(15));
-constexpr auto MUTANT_LOCUST2_RANGE = SQUARE(SECTOR(30));
-
-static void TriggerMutantRocket(PHD_3DPOS* src, short roomNumber, short counter)
-{
- FX_INFO* fx;
- short fxNumber = NO_ITEM;
-
- fxNumber = CreateNewEffect(roomNumber);
- if (fxNumber != NO_ITEM)
+ void TriggerCrocgodMissile(PHD_3DPOS* src, short roomNumber, short counter)
{
+ FX_INFO* fx;
+ short fxNumber = NO_ITEM;
+
+ fxNumber = CreateNewEffect(roomNumber);
+ if (fxNumber != NO_ITEM)
+ {
+ fx = &EffectList[fxNumber];
+ fx->pos.xPos = src->xPos;
+ fx->pos.yPos = src->yPos - (GetRandomControl() & 0x3F) - 32;
+ fx->pos.zPos = src->zPos;
+ fx->pos.xRot = src->xRot;
+ fx->pos.yRot = src->yRot;
+ fx->pos.zRot = 0;
+ fx->roomNumber = roomNumber;
+ fx->counter = 16 * counter + 15;
+ fx->objectNumber = ID_ENERGY_BUBBLES;
+ fx->frameNumber = Objects[fx->objectNumber].meshIndex + 5 * 2;
+ fx->speed = (GetRandomControl() & 0x1F) + 96;
+ fx->flag1 = 6;
+ }
+ }
+
+ void TriggerCrocgodMissileFlame(short fxNumber, short xVel, short yVel, short zVel)
+ {
+ FX_INFO* fx;
+ SPARKS* sptr;
+ BYTE color, life, size;
+
+ //x = LaraItem->pos.xPos - Effects[m_fxNumber].pos.xPos;
+ //z = LaraItem->pos.zPos - Effects[m_fxNumber].pos.zPos;
+ //if (x >= -0x4000u && x <= 0x4000 && z >= -0x4000u && z <= 0x4000)
+
fx = &EffectList[fxNumber];
- fx->pos.xPos = src->xPos;
- fx->pos.yPos = src->yPos - (GetRandomControl() & 0x3F) - 32;
- fx->pos.zPos = src->zPos;
- fx->pos.xRot = src->xRot;
- fx->pos.yRot = src->yRot;
- fx->pos.zRot = 0;
- fx->roomNumber = roomNumber;
- fx->counter = 16 * counter + 15;
- fx->objectNumber = ID_ENERGY_BUBBLES;
- fx->frameNumber = Objects[fx->objectNumber].meshIndex + 5 * 2;
- fx->speed = (GetRandomControl() & 0x1F) + 96;
- fx->flag1 = 6;
- }
-}
-
-void TriggerMutantRocketEffects(short fxNumber, short xVel, short yVel, short zVel)
-{
- FX_INFO* fx;
- SPARKS* sptr;
- BYTE color, life, size;
-
- //x = LaraItem->pos.xPos - Effects[m_fxNumber].pos.xPos;
- //z = LaraItem->pos.zPos - Effects[m_fxNumber].pos.zPos;
- //if (x >= -0x4000u && x <= 0x4000 && z >= -0x4000u && z <= 0x4000)
-
- fx = &EffectList[fxNumber];
- sptr = &Sparks[GetFreeSpark()];
- sptr->on = true;
- color = (GetRandomControl() & 0x3F) - 128;
- sptr->sB = 0;
- sptr->sR = color;
- sptr->sG = color / 2;
- color = (GetRandomControl() & 0x3F) - 128;
- sptr->dB = 0;
- sptr->dR = color;
- sptr->dG = color / 2;
- sptr->fadeToBlack = 8;
- sptr->colFadeSpeed = (GetRandomControl() & 3) + 8;
- sptr->transType = COLADD;
- sptr->dynamic = -1;
- life = (GetRandomControl() & 7) + 32;
- sptr->life = life;
- sptr->sLife = life;
- sptr->x = (GetRandomControl() & 0xF) - 8;
- sptr->y = 0;
- sptr->z = (GetRandomControl() & 0xF) - 8;
- sptr->x += fx->pos.xPos;
- sptr->y += fx->pos.yPos;
- sptr->z += fx->pos.zPos;
- sptr->xVel = xVel;
- sptr->yVel = yVel;
- sptr->zVel = zVel;
- sptr->friction = 34;
- sptr->flags = SP_EXPDEF | SP_ROTATE | SP_DEF | SP_SCALE;
- sptr->rotAng = GetRandomControl() & 0xFFF;
- if (GetRandomControl() & 1)
- sptr->rotAdd = (GetRandomControl() & 0x1F) - 32;
- else
- sptr->rotAdd = (GetRandomControl() & 0x1F) + 32;
- sptr->gravity = 0;
- sptr->maxYvel = 0;
- sptr->fxObj = byte(fxNumber);
- sptr->scalar = 2;
- size = (GetRandomControl() & 0xF) + 128;
- sptr->size = size;
- sptr->sSize = size;
- sptr->dSize = size / 4;
-}
-
-static void ShootFireball(PHD_3DPOS* src, MissileRotationType rotation, short roomNumber, int timer)
-{
- switch (rotation)
- {
- case MissileRotationType::M_LEFT:
- src->yRot -= GetRandomControl() % 0x2000;
- break;
- case MissileRotationType::M_RIGHT:
- src->yRot += GetRandomControl() % 0x2000;
- break;
+ sptr = &Sparks[GetFreeSpark()];
+ sptr->on = true;
+ color = (GetRandomControl() & 0x3F) - 128;
+ sptr->sB = 0;
+ sptr->sR = color;
+ sptr->sG = color / 2;
+ color = (GetRandomControl() & 0x3F) - 128;
+ sptr->dB = 0;
+ sptr->dR = color;
+ sptr->dG = color / 2;
+ sptr->fadeToBlack = 8;
+ sptr->colFadeSpeed = (GetRandomControl() & 3) + 8;
+ sptr->transType = TransTypeEnum::COLADD;
+ sptr->dynamic = -1;
+ life = (GetRandomControl() & 7) + 32;
+ sptr->life = life;
+ sptr->sLife = life;
+ sptr->x = (GetRandomControl() & 0xF) - 8;
+ sptr->y = 0;
+ sptr->z = (GetRandomControl() & 0xF) - 8;
+ sptr->x += fx->pos.xPos;
+ sptr->y += fx->pos.yPos;
+ sptr->z += fx->pos.zPos;
+ sptr->xVel = xVel;
+ sptr->yVel = yVel;
+ sptr->zVel = zVel;
+ sptr->friction = 34;
+ sptr->flags = SP_EXPDEF | SP_ROTATE | SP_DEF | SP_SCALE;
+ sptr->rotAng = GetRandomControl() & 0xFFF;
+ if (GetRandomControl() & 1)
+ sptr->rotAdd = (GetRandomControl() & 0x1F) - 32;
+ else
+ sptr->rotAdd = (GetRandomControl() & 0x1F) + 32;
+ sptr->gravity = 0;
+ sptr->maxYvel = 0;
+ sptr->fxObj = byte(fxNumber);
+ sptr->scalar = 2;
+ size = (GetRandomControl() & 0xF) + 128;
+ sptr->size = size;
+ sptr->sSize = size;
+ sptr->dSize = size / 4;
}
- TriggerMutantRocket(src, roomNumber, timer);
-}
-
-static bool ShootFrame(ITEM_INFO* item)
-{
- short frameNumber = (item->frameNumber - g_Level.Anims[item->objectNumber].frameBase);
- if (frameNumber == 45
- //|| frameNumber == 50
- //|| frameNumber == 55
- || frameNumber == 60
- //|| frameNumber == 65
- //|| frameNumber == 70
- || frameNumber == 75)
- return true;
- else
- return false;
-}
-
-static void RotateHeadToTarget(ITEM_INFO* item, CREATURE_INFO* creature, int joint, short& headAngle)
-{
- if (creature->enemy == nullptr)
+ static void ShootFireball(PHD_3DPOS* src, MissileRotationType rotation, short roomNumber, int timer)
{
- headAngle = item->pos.yRot;
- return;
- }
- ITEM_INFO* enemy = creature->enemy;
- PHD_VECTOR pos;
- int x, z;
- pos.x = 0;
- pos.y = 0;
- pos.z = 0;
- GetJointAbsPosition(item, &pos, joint);
- x = enemy->pos.xPos - pos.x;
- z = enemy->pos.zPos - pos.z;
- headAngle = (short)(phd_atan(z, x) - item->pos.yRot) / 2;
-}
-
-static void GetTargetPosition(ITEM_INFO* item, PHD_3DPOS* target)
-{
- PHD_VECTOR start, end;
- short angles[2];
- start.x = 0;
- start.y = -96;
- start.z = 144;
- GetJointAbsPosition(item, &start, 9);
- end.x = 0;
- end.y = -128;
- end.z = 288;
- GetJointAbsPosition(item, &end, 9);
- phd_GetVectorAngles(end.x - start.x, end.y - start.y, end.z - start.z, angles);
- target->xPos = end.x;
- target->yPos = end.y;
- target->zPos = end.z;
- target->yRot = angles[0];
- target->xRot = angles[1];
- target->zRot = 0;
-}
-
-enum CARDINAL_POINT
-{
- C_NORTH = 0,
- C_NORTH_EAST = 45,
- C_EAST = 90,
- C_EAST_SOUTH = 135,
- C_SOUTH = 180,
- C_SOUTH_WEST = 225,
- C_WEST = 270,
- C_WEST_NORTH = 315
-};
-
-static void MoveItemFront(ITEM_INFO* item, int distance)
-{
- short degree = short(TO_DEGREES(item->pos.yRot));
- switch (degree)
- {
- case C_NORTH:
- item->pos.zPos += distance;
- break;
- case C_EAST:
- item->pos.xPos += distance;
- break;
- case C_SOUTH:
- item->pos.zPos -= distance;
- break;
- case C_WEST:
- item->pos.xPos -= distance;
- break;
- }
-}
-
-static void MoveItemBack(ITEM_INFO* item, int distance)
-{
- short degree = short(TO_DEGREES(item->pos.yRot));
- switch (degree)
- {
- case C_NORTH:
- item->pos.zPos -= distance;
- break;
- case C_EAST:
- item->pos.xPos -= distance;
- break;
- case C_SOUTH:
- item->pos.zPos += distance;
- break;
- case C_WEST:
- item->pos.xPos += distance;
- break;
- }
-}
-
-static void MutantAIFix(ITEM_INFO* item, AI_INFO* info)
-{
- MoveItemFront(item, SECTOR(2));
- item->pos.yPos -= CLICK(3);
- CreatureAIInfo(item, info);
- item->pos.yPos += CLICK(3);
- MoveItemBack(item, SECTOR(2));
-}
-
-void InitialiseMutant(short itemNumber)
-{
- ITEM_INFO* item;
- InitialiseCreature(itemNumber);
-
- item = &g_Level.Items[itemNumber];
- item->animNumber = Objects[item->objectNumber].animIndex + MUTANT_ANIM_APPEAR;
- item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
- item->currentAnimState = MUTANT_APPEAR;
- item->goalAnimState = MUTANT_APPEAR;
-}
-
-void MutantControl(short itemNumber)
-{
- if (!CreatureActive(itemNumber))
- return;
-
- ITEM_INFO* item;
- CREATURE_INFO* mutant;
- AI_INFO info;
- OBJECT_Bones mutant_joint;
- short frameNumber;
- short headY;
- short angle;
-
- item = &g_Level.Items[itemNumber];
- mutant = GetCreatureInfo(item);
- angle = 0;
- headY = 0;
-
- if (item->aiBits & ALL_AIOBJ)
- GetAITarget(mutant);
- else if (mutant->hurtByLara)
- mutant->enemy = LaraItem;
- else
- TargetNearestEntity(item, mutant);
-
- MutantAIFix(item, &info);
- RotateHeadToTarget(item, mutant, 9, headY);
- GetCreatureMood(item, &info, VIOLENT);
- CreatureMood(item, &info, VIOLENT);
- mutant->maximumTurn = 0;
- angle = CreatureTurn(item, 0);
-
- switch (item->currentAnimState)
- {
- case MUTANT_IDLE:
- if (info.ahead)
+ switch (rotation)
{
- int random = GetRandomControl() & 31;
- if ((random > 0 && random < 10) && info.distance <= MUTANT_SHOOT_RANGE)
- item->goalAnimState = MUTANT_SHOOT;
- else if ((random > 10 && random < 20) && info.distance <= MUTANT_LOCUST1_RANGE)
- item->goalAnimState = MUTANT_LOCUST1;
- else if ((random > 20 && random < 30) && info.distance <= MUTANT_LOCUST2_RANGE)
- item->goalAnimState = MUTANT_LOCUST2;
+ case MissileRotationType::M_LEFT:
+ src->yRot -= GetRandomControl() % 0x2000;
+ break;
+ case MissileRotationType::M_RIGHT:
+ src->yRot += GetRandomControl() % 0x2000;
+ break;
}
- break;
- case MUTANT_SHOOT:
- frameNumber = (item->frameNumber - g_Level.Anims[item->objectNumber].frameBase);
- if (frameNumber >= 94 && frameNumber <= 96)
- {
- PHD_3DPOS src;
- GetTargetPosition(item, &src);
- if (frameNumber == 94)
- {
- ShootFireball(&src, MissileRotationType::M_FRONT, item->roomNumber, 0);
- }
- else if (frameNumber == 95)
- {
- ShootFireball(&src, MissileRotationType::M_LEFT, item->roomNumber, 1);
- //ShootFireball(&src, MissileRotationType::M_LEFT, item->roomNumber, 1);
- }
- else if (frameNumber == 96)
- {
- ShootFireball(&src, MissileRotationType::M_RIGHT, item->roomNumber, 1);
- //ShootFireball(&src, MissileRotationType::M_RIGHT, item->roomNumber, 1);
- }
- }
- break;
- case MUTANT_LOCUST1:
- frameNumber = (item->frameNumber - g_Level.Anims[item->objectNumber].frameBase);
- if (frameNumber >= 60 && frameNumber <= 120)
- ten::entities::tr4::SpawnLocust(item);
- break;
- case MUTANT_LOCUST2:
- if (ShootFrame(item))
- {
- PHD_3DPOS src;
- GetTargetPosition(item, &src);
- ShootFireball(&src, MissileRotationType::M_FRONT, item->roomNumber, 1);
- }
- break;
+
+ TriggerCrocgodMissile(src, roomNumber, timer);
}
- if (item->currentAnimState != MUTANT_LOCUST1)
- mutant_joint = OBJECT_Bones(headY, info.xAngle, true);
- else
- mutant_joint = OBJECT_Bones(0);
+ static bool ShootFrame(ITEM_INFO* item)
+ {
+ short frameNumber = (item->frameNumber - g_Level.Anims[item->objectNumber].frameBase);
+ if (frameNumber == 45
+ //|| frameNumber == 50
+ //|| frameNumber == 55
+ || frameNumber == 60
+ //|| frameNumber == 65
+ //|| frameNumber == 70
+ || frameNumber == 75)
+ return true;
+ else
+ return false;
+ }
- CreatureJoint(item, 0, mutant_joint.bone0);
- CreatureJoint(item, 1, mutant_joint.bone1);
- CreatureJoint(item, 2, mutant_joint.bone2);
- CreatureJoint(item, 3, mutant_joint.bone3);
- CreatureAnimation(itemNumber, angle, 0);
-}
+ static void RotateHeadToTarget(ITEM_INFO* item, CREATURE_INFO* creature, int joint, short& headAngle)
+ {
+ if (creature->enemy == nullptr)
+ {
+ headAngle = item->pos.yRot;
+ return;
+ }
+ ITEM_INFO* enemy = creature->enemy;
+ PHD_VECTOR pos;
+ int x, z;
+ pos.x = 0;
+ pos.y = 0;
+ pos.z = 0;
+ GetJointAbsPosition(item, &pos, joint);
+ x = enemy->pos.xPos - pos.x;
+ z = enemy->pos.zPos - pos.z;
+ headAngle = (short)(phd_atan(z, x) - item->pos.yRot) / 2;
+ }
+ static void GetTargetPosition(ITEM_INFO* item, PHD_3DPOS* target)
+ {
+ PHD_VECTOR start, end;
+ short angles[2];
+ start.x = 0;
+ start.y = -96;
+ start.z = 144;
+ GetJointAbsPosition(item, &start, 9);
+ end.x = 0;
+ end.y = -128;
+ end.z = 288;
+ GetJointAbsPosition(item, &end, 9);
+ phd_GetVectorAngles(end.x - start.x, end.y - start.y, end.z - start.z, angles);
+ target->xPos = end.x;
+ target->yPos = end.y;
+ target->zPos = end.z;
+ target->yRot = angles[0];
+ target->xRot = angles[1];
+ target->zRot = 0;
+ }
+
+ enum CARDINAL_POINT
+ {
+ C_NORTH = 0,
+ C_NORTH_EAST = 45,
+ C_EAST = 90,
+ C_EAST_SOUTH = 135,
+ C_SOUTH = 180,
+ C_SOUTH_WEST = 225,
+ C_WEST = 270,
+ C_WEST_NORTH = 315
+ };
+
+ static void MoveItemFront(ITEM_INFO* item, int distance)
+ {
+ short degree = short(TO_DEGREES(item->pos.yRot));
+ switch (degree)
+ {
+ case C_NORTH:
+ item->pos.zPos += distance;
+ break;
+ case C_EAST:
+ item->pos.xPos += distance;
+ break;
+ case C_SOUTH:
+ item->pos.zPos -= distance;
+ break;
+ case C_WEST:
+ item->pos.xPos -= distance;
+ break;
+ }
+ }
+
+ static void MoveItemBack(ITEM_INFO* item, int distance)
+ {
+ short degree = short(TO_DEGREES(item->pos.yRot));
+ switch (degree)
+ {
+ case C_NORTH:
+ item->pos.zPos -= distance;
+ break;
+ case C_EAST:
+ item->pos.xPos -= distance;
+ break;
+ case C_SOUTH:
+ item->pos.zPos += distance;
+ break;
+ case C_WEST:
+ item->pos.xPos += distance;
+ break;
+ }
+ }
+
+ static void MutantAIFix(ITEM_INFO* item, AI_INFO* info)
+ {
+ MoveItemFront(item, SECTOR(2));
+ item->pos.yPos -= CLICK(3);
+ CreatureAIInfo(item, info);
+ item->pos.yPos += CLICK(3);
+ MoveItemBack(item, SECTOR(2));
+ }
+
+ void InitialiseCrocgod(short itemNumber)
+ {
+ ITEM_INFO* item;
+ InitialiseCreature(itemNumber);
+
+ item = &g_Level.Items[itemNumber];
+ item->animNumber = Objects[item->objectNumber].animIndex + MUTANT_ANIM_APPEAR;
+ item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
+ item->currentAnimState = STATE_MUTANT_APPEAR;
+ item->goalAnimState = STATE_MUTANT_APPEAR;
+ }
+
+ void CrocgodControl(short itemNumber)
+ {
+ if (!CreatureActive(itemNumber))
+ return;
+
+ ITEM_INFO* item;
+ CREATURE_INFO* mutant;
+ AI_INFO info;
+ OBJECT_BONES mutant_joint;
+ short frameNumber;
+ short headY;
+ short angle;
+
+ item = &g_Level.Items[itemNumber];
+ mutant = GetCreatureInfo(item);
+ angle = 0;
+ headY = 0;
+
+ if (item->aiBits & ALL_AIOBJ)
+ GetAITarget(mutant);
+ else if (mutant->hurtByLara)
+ mutant->enemy = LaraItem;
+ else
+ TargetNearestEntity(item, mutant);
+
+ MutantAIFix(item, &info);
+ RotateHeadToTarget(item, mutant, 9, headY);
+ GetCreatureMood(item, &info, VIOLENT);
+ CreatureMood(item, &info, VIOLENT);
+ mutant->maximumTurn = 0;
+ angle = CreatureTurn(item, 0);
+
+ switch (item->currentAnimState)
+ {
+ case STATE_MUTANT_IDLE:
+ if (info.ahead)
+ {
+ int random = GetRandomControl() & 31;
+ if ((random > 0 && random < 10) && info.distance <= MUTANT_SHOOT_RANGE)
+ item->goalAnimState = STATE_MUTANT_SHOOT;
+ else if ((random > 10 && random < 20) && info.distance <= MUTANT_LOCUST1_RANGE)
+ item->goalAnimState = STATE_MUTANT_LOCUST1;
+ else if ((random > 20 && random < 30) && info.distance <= MUTANT_LOCUST2_RANGE)
+ item->goalAnimState = STATE_MUTANT_LOCUST2;
+ }
+ break;
+
+ case STATE_MUTANT_SHOOT:
+ frameNumber = (item->frameNumber - g_Level.Anims[item->objectNumber].frameBase);
+ if (frameNumber >= 94 && frameNumber <= 96)
+ {
+ PHD_3DPOS src;
+ GetTargetPosition(item, &src);
+ if (frameNumber == 94)
+ {
+ ShootFireball(&src, MissileRotationType::M_FRONT, item->roomNumber, 0);
+ }
+ else if (frameNumber == 95)
+ {
+ ShootFireball(&src, MissileRotationType::M_LEFT, item->roomNumber, 1);
+ //ShootFireball(&src, MissileRotationType::M_LEFT, item->roomNumber, 1);
+ }
+ else if (frameNumber == 96)
+ {
+ ShootFireball(&src, MissileRotationType::M_RIGHT, item->roomNumber, 1);
+ //ShootFireball(&src, MissileRotationType::M_RIGHT, item->roomNumber, 1);
+ }
+ }
+ break;
+
+ case STATE_MUTANT_LOCUST1:
+ frameNumber = (item->frameNumber - g_Level.Anims[item->objectNumber].frameBase);
+ if (frameNumber >= 60 && frameNumber <= 120)
+ ten::entities::tr4::SpawnLocust(item);
+ break;
+
+ case STATE_MUTANT_LOCUST2:
+ if (ShootFrame(item))
+ {
+ PHD_3DPOS src;
+ GetTargetPosition(item, &src);
+ ShootFireball(&src, MissileRotationType::M_FRONT, item->roomNumber, 1);
+ }
+ break;
+ }
+
+ if (item->currentAnimState != STATE_MUTANT_LOCUST1)
+ mutant_joint = OBJECT_BONES(headY, info.xAngle, true);
+ else
+ mutant_joint = OBJECT_BONES(0);
+
+ CreatureJoint(item, 0, mutant_joint.bone0);
+ CreatureJoint(item, 1, mutant_joint.bone1);
+ CreatureJoint(item, 2, mutant_joint.bone2);
+ CreatureJoint(item, 3, mutant_joint.bone3);
+ CreatureAnimation(itemNumber, angle, 0);
+ }
+}
\ No newline at end of file
diff --git a/TR5Main/Objects/TR4/Entity/tr4_mutant.h b/TR5Main/Objects/TR4/Entity/tr4_mutant.h
index b32827a5c..33a4140f1 100644
--- a/TR5Main/Objects/TR4/Entity/tr4_mutant.h
+++ b/TR5Main/Objects/TR4/Entity/tr4_mutant.h
@@ -1,5 +1,33 @@
#pragma once
-void InitialiseMutant(short itemNumber);
-void MutantControl(short itemNumber);
-void TriggerMutantRocketEffects(short fxNumber, short xVel, short yVel, short zVel);
\ No newline at end of file
+#include "framework.h"
+#include "trmath.h"
+
+namespace ten::entities::tr4
+{
+ enum MUTANT_STATE
+ {
+ STATE_MUTANT_EMPTY,
+ STATE_MUTANT_APPEAR,
+ STATE_MUTANT_IDLE,
+ STATE_MUTANT_SHOOT,
+ STATE_MUTANT_LOCUST1,
+ STATE_MUTANT_LOCUST2,
+ };
+
+ enum class MissileRotationType
+ {
+ M_FRONT,
+ M_LEFT,
+ M_RIGHT
+ };
+
+ constexpr auto MUTANT_ANIM_APPEAR = 0;
+ constexpr auto MUTANT_SHOOT_RANGE = SQUARE(SECTOR(10));
+ constexpr auto MUTANT_LOCUST1_RANGE = SQUARE(SECTOR(15));
+ constexpr auto MUTANT_LOCUST2_RANGE = SQUARE(SECTOR(30));
+
+ void InitialiseCrocgod(short itemNumber);
+ void CrocgodControl(short itemNumber);
+ void TriggerCrocgodMissileFlame(short fxNumber, short xVel, short yVel, short zVel);
+}
\ No newline at end of file
diff --git a/TR5Main/Objects/TR4/tr4_objects.cpp b/TR5Main/Objects/TR4/tr4_objects.cpp
index ccd586050..46e0ce7b5 100644
--- a/TR5Main/Objects/TR4/tr4_objects.cpp
+++ b/TR5Main/Objects/TR4/tr4_objects.cpp
@@ -664,8 +664,8 @@ static void StartBaddy(OBJECT_INFO* obj)
obj = &Objects[ID_CROCODILE_GOD];
if (obj->loaded)
{
- obj->initialise = InitialiseMutant;
- obj->control = MutantControl;
+ obj->initialise = ten::entities::tr4::InitialiseCrocgod;
+ obj->control = ten::entities::tr4::CrocgodControl;
obj->collision = CreatureCollision;
obj->shadowSize = UNIT_SHADOW / 2;
obj->hitPoints = NOT_TARGETABLE;
diff --git a/TR5Main/Objects/TR5/tr5_objects.cpp b/TR5Main/Objects/TR5/tr5_objects.cpp
index 4861ca73e..ef6cf0862 100644
--- a/TR5Main/Objects/TR5/tr5_objects.cpp
+++ b/TR5Main/Objects/TR5/tr5_objects.cpp
@@ -1241,7 +1241,7 @@ static void StartShatter(OBJECT_INFO *obj)
static void StartProjectiles(OBJECT_INFO *obj)
{
- InitProjectile(obj, BubblesControl, ID_ENERGY_BUBBLES, true);
+ InitProjectile(obj, ten::entities::all::ControlEnemyMissile, ID_ENERGY_BUBBLES, true);
InitProjectile(obj, MissileControl, ID_BUBBLES, true);
InitProjectile(obj, MissileControl, ID_IMP_ROCK, true);
InitProjectile(obj, TorpedoControl, ID_TORPEDO);
diff --git a/TR5Main/Objects/objectslist.h b/TR5Main/Objects/objectslist.h
index c4995b9f8..ca4046fa1 100644
--- a/TR5Main/Objects/objectslist.h
+++ b/TR5Main/Objects/objectslist.h
@@ -110,7 +110,7 @@ enum GAME_OBJECT_ID : short
ID_DOBERMAN,
ID_HAMMERHEAD, // TR4 - OK
ID_CROCODILE_GOD, // TR4 Citadel Gate Mutant
- ID_LOCUSTS_EMITTER,
+ ID_LOCUSTS_EMITTER, // TR4 - OK
/* Humans */
ID_SCUBA_HARPOON = 150,
diff --git a/TR5Main/TR5Main.vcxproj b/TR5Main/TR5Main.vcxproj
index 963ed4372..e256f21e6 100644
--- a/TR5Main/TR5Main.vcxproj
+++ b/TR5Main/TR5Main.vcxproj
@@ -711,7 +711,6 @@ xcopy /Y "$(ProjectDir)Shaders\HUD\*.hlsl" "$(TargetDir)\Shaders\HUD\"
-