mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-02 09:47:58 +03:00
695 lines
No EOL
14 KiB
C++
695 lines
No EOL
14 KiB
C++
#include "newobjects.h"
|
|
#include "..\Global\global.h"
|
|
#include "..\Game\Box.h"
|
|
#include "..\Game\items.h"
|
|
#include "..\Game\lot.h"
|
|
#include "..\Game\control.h"
|
|
#include "..\Game\effects.h"
|
|
#include "..\Game\draw.h"
|
|
#include "..\Game\sphere.h"
|
|
#include "..\Game\effect2.h"
|
|
#include "..\Game\people.h"
|
|
#include "..\Game\lara.h"
|
|
|
|
void __cdecl InitialiseDemigod(__int16 itemNum)
|
|
{
|
|
ITEM_INFO* item = &Items[itemNum];
|
|
|
|
ClearItem(itemNum);
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex;
|
|
item->goalAnimState = 0;
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
item->currentAnimState = 0;
|
|
|
|
/*if (LevelItems > 0)
|
|
{
|
|
ITEM_INFO* currentItem = &Items[0];
|
|
__int32 k = 0;
|
|
|
|
while (item == currentItem || currentItem->objectNumber != ID_DEMIGOD3 || currentItem->itemFlags[0])
|
|
{
|
|
k++;
|
|
currentItem++;
|
|
if (k >= LevelItems)
|
|
return;
|
|
}
|
|
|
|
item->itemFlags[0] = k;
|
|
}*/
|
|
}
|
|
|
|
void __cdecl DemigodControl(__int16 itemNum)
|
|
{
|
|
ITEM_INFO* item = &Items[itemNum];
|
|
|
|
__int32 someItemNum = item->itemFlags[0];
|
|
|
|
if (someItemNum && Items[someItemNum].status == ITEM_ACTIVE && Items[someItemNum].active)
|
|
{
|
|
item->hitPoints = Objects[item->objectNumber].hitPoints;
|
|
return;
|
|
}
|
|
|
|
if (!CreatureActive(itemNum))
|
|
return;
|
|
|
|
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
|
|
|
__int16 tilt = 0;
|
|
__int16 angle = 0;
|
|
__int16 joint0 = 0;
|
|
__int16 joint1 = 0;
|
|
__int16 joint2 = 0;
|
|
__int16 joint3 = 0;
|
|
|
|
/*if (CurrentLevel == 24)
|
|
{
|
|
ROOM_INFO* room = &Rooms[item->roomNumber];
|
|
|
|
__int16* zone = GroundZones[FlipStatus * 2 + creature->LOT.zone];
|
|
|
|
LaraItem->boxNumber = room->floor[((LaraItem->pos.zPos - room->z) >> WALL_SHIFT) +
|
|
((LaraItem->pos.xPos - room->x) >> WALL_SHIFT) * room->xSize].box;
|
|
|
|
if (zone[item->boxNumber] == zone[LaraItem->boxNumber])
|
|
{
|
|
item->aiBits = 0;
|
|
creature->enemy = LaraItem;
|
|
}
|
|
else
|
|
{
|
|
item->aiBits = FOLLOW;
|
|
item->itemFlags[3] = Lara.location;
|
|
creature->enemy = NULL;
|
|
}
|
|
}*/
|
|
|
|
if (item->hitPoints <= 0)
|
|
{
|
|
item->hitPoints = 0;
|
|
if (item->currentAnimState != 8 && item->currentAnimState != 15)
|
|
{
|
|
if (item->currentAnimState == 1 || item->currentAnimState == 2)
|
|
{
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 27;
|
|
item->currentAnimState = 15;
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
}
|
|
else
|
|
{
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 12;
|
|
item->currentAnimState = 8;
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (item->aiBits)
|
|
GetAITarget(creature);
|
|
|
|
AI_INFO info;
|
|
AI_INFO laraInfo;
|
|
|
|
__int32 dx = 0;
|
|
__int32 dy = 0;
|
|
__int32 dz = 0;
|
|
|
|
CreatureAIInfo(item, &info);
|
|
|
|
if (creature->enemy == LaraItem)
|
|
{
|
|
laraInfo.ahead = info.ahead;
|
|
laraInfo.angle = info.angle;
|
|
laraInfo.xAngle = 0;
|
|
}
|
|
else
|
|
{
|
|
dx = LaraItem->pos.xPos - item->pos.xPos;
|
|
dz = LaraItem->pos.zPos - item->pos.zPos;
|
|
laraInfo.angle = ATAN(dz, dx) - item->pos.yRot;
|
|
laraInfo.xAngle = 0;
|
|
|
|
laraInfo.ahead = true;
|
|
if (laraInfo.angle <= -ANGLE(90) || laraInfo.angle >= ANGLE(90))
|
|
laraInfo.ahead = false;
|
|
|
|
dx = abs(dx);
|
|
dy = item->pos.yPos - LaraItem->pos.yPos;
|
|
dz = abs(dz);
|
|
|
|
if (dx <= dz)
|
|
laraInfo.xAngle = ATAN(dz + (dx >> 1), dy);
|
|
else
|
|
laraInfo.xAngle = ATAN(dx + (dz >> 1), dy);
|
|
}
|
|
|
|
GetCreatureMood(item, &info, VIOLENT);
|
|
CreatureMood(item, &info, VIOLENT);
|
|
|
|
angle = CreatureTurn(item, creature->maximumTurn);
|
|
|
|
if (laraInfo.ahead)
|
|
{
|
|
joint0 = laraInfo.angle >> 1;
|
|
joint1 = -laraInfo.xAngle;
|
|
joint2 = laraInfo.angle >> 1;
|
|
joint3 = laraInfo.angle >> 1;
|
|
}
|
|
else if (info.ahead)
|
|
{
|
|
joint0 = info.angle >> 1;
|
|
joint1 = -info.xAngle;
|
|
joint2 = info.angle >> 1;
|
|
joint3 = info.angle >> 1;
|
|
}
|
|
|
|
switch (item->currentAnimState)
|
|
{
|
|
case 0:
|
|
creature->maximumTurn = 0;
|
|
if (info.ahead)
|
|
joint1 = -info.xAngle;
|
|
|
|
if (item->objectNumber == ID_DEMIGOD1)
|
|
{
|
|
if (info.distance >= SQUARE(3072))
|
|
{
|
|
item->goalAnimState = 1;
|
|
break;
|
|
}
|
|
if (info.bite
|
|
|| LaraItem->currentAnimState >= 56
|
|
&& LaraItem->currentAnimState <= 61
|
|
&& !Lara.location)
|
|
{
|
|
item->goalAnimState = 13;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Targetable(item, &info))
|
|
{
|
|
creature->flags = 1;
|
|
if (item->objectNumber == ID_DEMIGOD2)
|
|
item->goalAnimState = 3;
|
|
else
|
|
item->goalAnimState = 11;
|
|
break;
|
|
}
|
|
|
|
if (item->objectNumber == ID_DEMIGOD3)
|
|
{
|
|
if (info.distance <= SQUARE(2048) || info.distance >= SQUARE(5120))
|
|
{
|
|
item->goalAnimState = 1;
|
|
break;
|
|
}
|
|
if (!(GetRandomControl() & 3))
|
|
{
|
|
item->goalAnimState = 9;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (info.distance <= SQUARE(3072) || item->objectNumber != ID_DEMIGOD2)
|
|
{
|
|
item->goalAnimState = 1;
|
|
break;
|
|
}
|
|
|
|
item->goalAnimState = 5;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
creature->maximumTurn = 1274;
|
|
|
|
if (info.distance < SQUARE(2048))
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
|
|
if (item->objectNumber == ID_DEMIGOD1)
|
|
{
|
|
if (info.distance < SQUARE(3072))
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Targetable(item, &info))
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (info.distance > SQUARE(3072))
|
|
{
|
|
if (item->objectNumber == ID_DEMIGOD2)
|
|
{
|
|
item->goalAnimState = 5;
|
|
}
|
|
else
|
|
{
|
|
item->goalAnimState = 2;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
creature->maximumTurn = 1274;
|
|
|
|
if (info.distance < SQUARE(2048))
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
if (item->objectNumber == ID_DEMIGOD1)
|
|
{
|
|
if (info.distance < SQUARE(3072))
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Targetable(item, &info) || item->objectNumber == ID_DEMIGOD3 && info.distance > SQUARE(2048))
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
|
|
if (info.distance < SQUARE(3072))
|
|
{
|
|
item->goalAnimState = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
if (info.ahead)
|
|
{
|
|
joint1 = -info.xAngle;
|
|
}
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (item->animNumber == Objects[item->objectNumber].animIndex + 6)
|
|
{
|
|
if (abs(info.angle) >= ANGLE(7))
|
|
{
|
|
if (info.angle >= 0)
|
|
{
|
|
item->pos.yRot += ANGLE(7);
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot -= ANGLE(7);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot += info.angle;
|
|
}
|
|
}
|
|
|
|
if (Targetable(item, &info) || creature->flags)
|
|
{
|
|
item->goalAnimState = 4;
|
|
creature->flags = 0;
|
|
}
|
|
else
|
|
{
|
|
item->goalAnimState = 0;
|
|
creature->flags = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
|
case 12:
|
|
DemigodEnergyAttack(itemNum);
|
|
break;
|
|
|
|
case 6:
|
|
creature->maximumTurn = ANGLE(7);
|
|
if (Targetable(item, &info))
|
|
{
|
|
item->goalAnimState = 7;
|
|
}
|
|
|
|
break;
|
|
|
|
case 9:
|
|
creature->maximumTurn = ANGLE(7);
|
|
if (!Targetable(item, &info) && info.distance < SQUARE(5120))
|
|
{
|
|
item->goalAnimState = 10;
|
|
}
|
|
|
|
break;
|
|
|
|
case 10:
|
|
creature->maximumTurn = ANGLE(7);
|
|
|
|
DemigodEnergyAttack(itemNum);
|
|
|
|
if (!Targetable(item, &info) || info.distance < SQUARE(5120) || !GetRandomControl())
|
|
{
|
|
item->goalAnimState = 0;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case 11:
|
|
joint2 = joint0;
|
|
joint0 = 0;
|
|
|
|
if (info.ahead)
|
|
{
|
|
joint1 = -info.xAngle;
|
|
}
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (item->animNumber == Objects[(signed __int16)item->objectNumber].animIndex + 6)
|
|
{
|
|
if (abs(info.angle) >= ANGLE(7))
|
|
{
|
|
if (info.angle >= 0)
|
|
{
|
|
item->pos.yRot += ANGLE(7);
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot -= ANGLE(7);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot += info.angle;
|
|
}
|
|
}
|
|
if (Targetable(item, &info) || creature->flags)
|
|
{
|
|
item->goalAnimState = 12;
|
|
creature->flags = 0;
|
|
}
|
|
else
|
|
{
|
|
item->goalAnimState = 0;
|
|
creature->flags = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case 13:
|
|
// Aiming
|
|
creature->maximumTurn = 0;
|
|
joint2 = joint0;
|
|
joint0 = 0;
|
|
if (abs(info.angle) >= ANGLE(7))
|
|
{
|
|
if (info.angle >= 0)
|
|
{
|
|
item->pos.yRot += ANGLE(7);
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot -= ANGLE(7);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot += info.angle;
|
|
}
|
|
if (info.distance >= SQUARE(3072)
|
|
|| !info.bite
|
|
&& (LaraItem->currentAnimState < 56 || LaraItem->currentAnimState > 61 || Lara.location))
|
|
{
|
|
item->goalAnimState = 0;
|
|
}
|
|
else
|
|
{
|
|
item->goalAnimState = 14;
|
|
}
|
|
|
|
break;
|
|
|
|
case 14:
|
|
// Hammer attack
|
|
if (item->frameNumber - Anims[item->animNumber].frameBase == 26)
|
|
{
|
|
PHD_VECTOR pos;
|
|
|
|
pos.x = 80;
|
|
pos.y = -8;
|
|
pos.z = -40;
|
|
|
|
GetJointAbsPosition(item, &pos, 17);
|
|
|
|
__int16 roomNumber = item->roomNumber;
|
|
FLOOR_INFO* floor = GetFloor(pos.x, pos.y, pos.z, &roomNumber);
|
|
__int32 height = GetFloorHeight(floor, pos.x, pos.y, pos.z);
|
|
if (height == -32512)
|
|
{
|
|
pos.y = pos.y - 128;
|
|
}
|
|
else
|
|
{
|
|
pos.y = height - 128;
|
|
}
|
|
|
|
TriggerShockwave((PHD_3DPOS *)&pos, 0x00580018, 256, 545292416, 0x20000, 0);
|
|
DemigodHammerAttack(pos.x, pos.y + 128, pos.z, 8);
|
|
|
|
Camera.bounce = -128;
|
|
|
|
if (LaraItem->currentAnimState >= 56 && LaraItem->currentAnimState <= 61 && !Lara.location)
|
|
{
|
|
Lara.torsoXrot = 0; // dword_80DF6C
|
|
Lara.torsoYrot = 0; // dword_80DF6C
|
|
Lara.headXrot = 0;
|
|
Lara.headYrot = 0;
|
|
LaraItem->goalAnimState = 3;
|
|
LaraItem->currentAnimState = 3;
|
|
LaraItem->animNumber = 34;
|
|
LaraItem->frameNumber = Anims[item->animNumber].frameBase;
|
|
LaraItem->hitStatus = true;
|
|
LaraItem->speed = 2;
|
|
LaraItem->fallspeed = 1;
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
}
|
|
}
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
CreatureTilt(item, 0);
|
|
|
|
CreatureJoint(item, 0, joint0);
|
|
CreatureJoint(item, 1, joint1);
|
|
CreatureJoint(item, 2, joint2);
|
|
CreatureJoint(item, 3, joint3);
|
|
|
|
CreatureAnimation(itemNum, angle, 0);
|
|
}
|
|
|
|
void __cdecl DemigodThrowEnergyAttack(PHD_3DPOS* pos, __int16 roomNumber, __int32 something)
|
|
{
|
|
return;
|
|
__int16 fxNum = CreateNewEffect(roomNumber);
|
|
if (fxNum != -1)
|
|
{
|
|
FX_INFO* fx = &Effects[fxNum];
|
|
|
|
fx->pos.xPos = pos->xPos;
|
|
fx->pos.yPos = pos->yPos - (GetRandomControl() & 0x3F) - 32;
|
|
fx->pos.zPos = pos->zPos;
|
|
fx->pos.xRot = pos->xRot;
|
|
if (something < 4)
|
|
{
|
|
fx->pos.yRot = pos->yRot;
|
|
}
|
|
else
|
|
{
|
|
fx->pos.yRot = pos->yRot + (GetRandomControl() & 0x7FF) - 1024;
|
|
}
|
|
fx->pos.zRot = 0;
|
|
fx->roomNumber = roomNumber;
|
|
fx->counter = 2 * GetRandomControl() + -ANGLE(180);
|
|
fx->flag1 = something;
|
|
fx->speed = (GetRandomControl() & 0x1F) + 96;
|
|
fx->objectNumber = ID_BUBBLES;
|
|
if (something >= 4)
|
|
something--;
|
|
fx->frameNumber = Objects[ID_BUBBLES].meshIndex + 2 * something;
|
|
}
|
|
}
|
|
|
|
void __cdecl DemigodEnergyAttack(__int16 itemNum)
|
|
{
|
|
ITEM_INFO* item = &Items[itemNum];
|
|
|
|
__int16 animIndex = item->animNumber - Objects[item->objectNumber].animIndex;
|
|
|
|
if (animIndex != 8 && animIndex != 16 && animIndex != 19)
|
|
return;
|
|
|
|
if (animIndex == 8)
|
|
{
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase)
|
|
{
|
|
PHD_VECTOR pos1;
|
|
PHD_VECTOR pos2;
|
|
|
|
pos1.x = -544;
|
|
pos1.y = 96;
|
|
pos1.z = 0;
|
|
|
|
GetJointAbsPosition(item, &pos1, 16);
|
|
|
|
pos2.x = -900;
|
|
pos2.y = 96;
|
|
pos2.z = 0;
|
|
|
|
GetJointAbsPosition(item, &pos2, 16);
|
|
|
|
__int16 angles[2];
|
|
phd_GetVectorAngles(pos2.x - pos1.x, pos2.y - pos1.y, pos2.z - pos1.z, angles);
|
|
|
|
PHD_3DPOS pos;
|
|
pos.xPos = pos1.x;
|
|
pos.yPos = pos1.y;
|
|
pos.zPos = pos1.z;
|
|
pos.xRot = angles[0];
|
|
pos.yRot = angles[1];
|
|
pos.zRot = 0;
|
|
|
|
if (item->objectNumber == ID_DEMIGOD3)
|
|
{
|
|
DemigodThrowEnergyAttack(&pos, item->roomNumber, 3);
|
|
}
|
|
else
|
|
{
|
|
DemigodThrowEnergyAttack(&pos, item->roomNumber, 5);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__int32 frameNumber = item->frameNumber - Anims[item->animNumber].frameBase;
|
|
|
|
if (frameNumber >= 8 && frameNumber <= 64)
|
|
{
|
|
PHD_VECTOR pos1;
|
|
PHD_VECTOR pos2;
|
|
|
|
pos1.x = 0;
|
|
pos1.y = 0;
|
|
pos1.z = 192;
|
|
|
|
pos2.x = 0;
|
|
pos2.y = 0;
|
|
pos2.z = 384;
|
|
|
|
if (GlobalCounter & 1)
|
|
{
|
|
GetJointAbsPosition(item, &pos1, 18);
|
|
GetJointAbsPosition(item, &pos2, 18);
|
|
}
|
|
else
|
|
{
|
|
GetJointAbsPosition(item, &pos1, 17);
|
|
GetJointAbsPosition(item, &pos2, 17);
|
|
}
|
|
|
|
__int16 angles[2];
|
|
phd_GetVectorAngles(pos2.x - pos1.x, pos2.y - pos1.y, pos2.z - pos1.z, angles);
|
|
|
|
PHD_3DPOS pos;
|
|
pos.xPos = pos1.x;
|
|
pos.yPos = pos1.y;
|
|
pos.zPos = pos1.z;
|
|
pos.xRot = angles[0];
|
|
pos.yRot = angles[1];
|
|
pos.zRot = 0;
|
|
|
|
DemigodThrowEnergyAttack(&pos, item->roomNumber, 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void __cdecl DemigodHammerAttack(__int32 x, __int32 y, __int32 z, __int32 something)
|
|
{
|
|
__int32 angle = 2 * GetRandomControl();
|
|
__int32 deltaAngle = 0x10000 / something;
|
|
|
|
if (something > 0)
|
|
{
|
|
for (__int32 i = 0; i < something; i++)
|
|
{
|
|
SMOKE_SPARKS* spark = &SmokeSparks[GetFreeSmokeSpark()];
|
|
|
|
spark->On = true;
|
|
spark->sShade = 0;
|
|
spark->ColFadeSpeed = 4;
|
|
spark->dShade = (GetRandomControl() & 0x1F) + 96;
|
|
spark->FadeToBlack = 24 - (GetRandomControl() & 7);
|
|
spark->TransType = 2;
|
|
spark->Life = spark->sLife = (GetRandomControl() & 7) + 48;
|
|
spark->x = (GetRandomControl() & 0x1F) + x - 16;
|
|
spark->y = (GetRandomControl() & 0x1F) + y - 16;
|
|
spark->z = (GetRandomControl() & 0x1F) + z - 16;
|
|
spark->Xvel = (byte)(GetRandomControl() + 256) * SIN(angle) >> W2V_SHIFT;
|
|
spark->Yvel = -32 - (GetRandomControl() & 0x3F);
|
|
spark->Zvel = (byte)(GetRandomControl() + 256) * COS(angle) >> W2V_SHIFT;
|
|
spark->Friction = 9;
|
|
|
|
if (GetRandomControl() & 1)
|
|
{
|
|
spark->Flags = 16;
|
|
spark->RotAng = GetRandomControl() & 0xFFF;
|
|
if (GetRandomControl() & 1)
|
|
{
|
|
spark->RotAdd = -64 - (GetRandomControl() & 0x3F);
|
|
}
|
|
else
|
|
{
|
|
spark->RotAdd = (GetRandomControl() & 0x3F) + 64;
|
|
}
|
|
}
|
|
else if (Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND)
|
|
{
|
|
spark->Flags = 256;
|
|
}
|
|
else
|
|
{
|
|
spark->Flags = 0;
|
|
}
|
|
spark->Gravity = -4 - (GetRandomControl() & 3);
|
|
spark->MaxYvel = -4 - (GetRandomControl() & 3);
|
|
spark->dSize = ((GetRandomControl() & 0x3F) + 64);
|
|
spark->sSize = spark->dSize >> 3;
|
|
spark->Size = spark->dSize >> 3;
|
|
|
|
angle += deltaAngle;
|
|
}
|
|
}
|
|
} |