2020-02-01 07:54:26 +01:00
|
|
|
#include "../oldobjects.h"
|
2019-12-20 11:23:03 +01:00
|
|
|
#include "../../Game/items.h"
|
2019-12-24 08:51:54 +01:00
|
|
|
#include "../../Game/sphere.h"
|
|
|
|
#include "../../Game/Box.h"
|
|
|
|
#include "../../Game/effect2.h"
|
|
|
|
#include "../../Game/people.h"
|
2020-03-16 12:36:29 +01:00
|
|
|
#include "../../Game/tomb4fx.h"
|
2019-12-24 08:51:54 +01:00
|
|
|
#include "../../Game/draw.h"
|
2019-12-30 00:01:00 +01:00
|
|
|
BITE_INFO SwatGun = { 80, 200, 13, 0 };
|
|
|
|
BITE_INFO SniperGun = { 0, 480, 110, 13 };
|
|
|
|
BITE_INFO ArmedBaddy2Gun = { -50, 220, 60, 13 };
|
2020-03-13 06:56:09 +01:00
|
|
|
#define STATE_GUARD_STOP 1
|
|
|
|
#define STATE_GUARD_TURN180 2
|
2020-03-15 09:05:43 +01:00
|
|
|
#define STATE_GUARD_FIRE_SINGLE 3
|
2020-03-13 06:56:09 +01:00
|
|
|
#define STATE_GUARD_AIM 4
|
|
|
|
#define STATE_GUARD_WALK 5
|
|
|
|
#define STATE_GUARD_RUN 7
|
|
|
|
#define STATE_GUARD_DEATH1 6
|
|
|
|
#define STATE_GUARD_DEATH2 8
|
2020-03-15 09:05:43 +01:00
|
|
|
#define STATE_GUARD_RECOIL 11
|
|
|
|
#define STATE_GUARD_CROUCH 13
|
|
|
|
#define STATE_GUARD_ROPE_DOWN 14
|
|
|
|
#define STATE_GUARD_SITTING 15
|
|
|
|
#define STATE_GUARD_STAND_UP 16
|
|
|
|
#define STATE_GUARD_WAITING_ON_WALL 19
|
|
|
|
#define STATE_GUARD_STOP_START_JUMP 26
|
|
|
|
#define STATE_GUARD_JUMPING_1BLOCK 27
|
|
|
|
#define STATE_GUARD_JUMPING_2BLOCKS 28
|
|
|
|
#define STATE_GUARD_LANDING 29
|
|
|
|
#define STATE_GUARD_HUNTING 30
|
|
|
|
#define STATE_GUARD_HUNTING_IDLE 31
|
|
|
|
#define STATE_GUARD_FIRE_FAST 35
|
|
|
|
#define STATE_GUARD_INSERT_CODE 36
|
|
|
|
#define STATE_GUARD_START_USE_COMPUTER 37
|
|
|
|
#define STATE_GUARD_USE_COMPUTER 38
|
|
|
|
#define STATE_GUARD_SURREND 39
|
2020-03-13 06:56:09 +01:00
|
|
|
#define ANIMATION_GUARD_DEATH1 11
|
|
|
|
#define ANIMATION_GUARD_DEATH2 16
|
|
|
|
#define ANIMATION_GUARD_START_JUMP 41
|
2020-03-15 09:05:43 +01:00
|
|
|
#define STATE_MAFIA2_STOP 1
|
|
|
|
#define STATE_MAFIA2_TURN180_UNDRAW_GUNS 2
|
|
|
|
#define STATE_MAFIA2_FIRE 3
|
|
|
|
#define STATE_MAFIA2_AIM 4
|
|
|
|
#define STATE_MAFIA2_WALK 5
|
|
|
|
#define STATE_MAFIA2_DEATH1 6
|
|
|
|
#define STATE_MAFIA2_RUN 7
|
|
|
|
#define STATE_MAFIA2_DEATH2 8
|
|
|
|
#define STATE_MAFIA2_STOP_START_JUMP 26
|
|
|
|
#define STATE_MAFIA2_JUMPING_1BLOCK 27
|
|
|
|
#define STATE_MAFIA2_JUMPING_2BLOCKS 28
|
|
|
|
#define STATE_MAFIA2_LANDING 29
|
|
|
|
#define STATE_MAFIA2_TURN180 32
|
|
|
|
#define STATE_MAFIA2_UNDRAW_GUNS 37
|
|
|
|
#define STATE_SNIPER_STOP 1
|
|
|
|
#define STATE_SNIPER_UNHIDE 2
|
|
|
|
#define STATE_SNIPER_AIM 3
|
|
|
|
#define STATE_SNIPER_FIRE 4
|
|
|
|
#define STATE_SNIPER_HIDE 5
|
|
|
|
#define STATE_SNIPER_DEATH 6
|
2019-12-20 11:23:03 +01:00
|
|
|
void InitialiseGuard(short itemNum)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item, *item2;
|
|
|
|
short anim;
|
|
|
|
short roomItemNumber;
|
|
|
|
item = &Items[itemNum];
|
|
|
|
ClearItem(itemNum);
|
|
|
|
anim = Objects[ID_SWAT].animIndex;
|
|
|
|
if (!Objects[ID_SWAT].loaded)
|
2020-03-14 07:48:35 +01:00
|
|
|
anim = Objects[ID_GUARD1].animIndex;
|
2019-12-20 11:23:03 +01:00
|
|
|
switch (item->triggerFlags)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 10:
|
|
|
|
item->animNumber = anim;
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-20 11:23:03 +01:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_RECOIL;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 23;
|
|
|
|
break;
|
|
|
|
case 2:
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_CROUCH;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 25;
|
|
|
|
// TODO: item->flags2 ^= (item->flags2 ^ ((item->flags2 & 0xFE) + 2)) & 6;
|
|
|
|
break;
|
|
|
|
case 3:
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_SITTING;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 28;
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 9216;
|
2019-12-20 11:23:03 +01:00
|
|
|
roomItemNumber = Rooms[item->roomNumber].itemNumber;
|
|
|
|
if (roomItemNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
item2 = &Items[roomItemNumber];
|
|
|
|
if (item2->objectNumber >= ID_ANIMATING1 && item2->objectNumber <= ID_ANIMATING15 && item2->roomNumber == item->roomNumber && item2->triggerFlags == 3)
|
|
|
|
break;
|
|
|
|
roomItemNumber = item2->nextItem;
|
|
|
|
if (roomItemNumber == NO_ITEM)
|
|
|
|
{
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
item->currentAnimState = item->goalAnimState;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
item2->meshBits = -5;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
item->goalAnimState = 17;
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 8192;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 30;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
FLOOR_INFO *floor;
|
|
|
|
short roomNumber;
|
|
|
|
item->animNumber = anim + 26;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_ROPE_DOWN;
|
2019-12-20 11:23:03 +01:00
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
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) - SECTOR(2);
|
|
|
|
break;
|
|
|
|
case 6:
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_WAITING_ON_WALL;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 32;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
case 9:
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_USE_COMPUTER;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 59;
|
|
|
|
item->pos.xPos -= SIN(item->pos.yRot); // 4 * not exist there ??
|
|
|
|
item->pos.zPos -= COS(item->pos.yRot); // 4 * not exist there ??
|
|
|
|
break;
|
|
|
|
case 8:
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_HUNTING_IDLE;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 46;
|
|
|
|
break;
|
|
|
|
case 11:
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_RUN;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->animNumber = anim + 12;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-03-15 09:05:43 +01:00
|
|
|
void InitialiseSniper(short itemNum)
|
2019-12-20 11:23:03 +01:00
|
|
|
{
|
|
|
|
ITEM_INFO* item;
|
|
|
|
item = &Items[itemNum];
|
|
|
|
ClearItem(itemNum);
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_SNIPER_STOP;
|
|
|
|
item->currentAnimState = STATE_SNIPER_STOP;
|
|
|
|
item->pos.yPos += STEP_SIZE * 2;
|
2019-12-20 11:23:03 +01:00
|
|
|
item->pos.xPos += SIN(item->pos.yRot);
|
|
|
|
item->pos.zPos += COS(item->pos.yRot);
|
|
|
|
}
|
|
|
|
void InitialiseGuardLaser(short itemNum)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item;
|
|
|
|
item = &Items[itemNum];
|
|
|
|
ClearItem(itemNum);
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 6;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
|
|
|
item->currentAnimState = STATE_GUARD_STOP;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2020-03-15 09:05:43 +01:00
|
|
|
void GuardControl(short itemNum)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
|
|
|
if (!CreatureActive(itemNum))
|
|
|
|
return;
|
|
|
|
int animIndex = 0;
|
|
|
|
if (Objects[ID_SWAT].loaded)
|
|
|
|
animIndex= Objects[ID_SWAT].animIndex;
|
|
|
|
else
|
2020-03-14 07:48:35 +01:00
|
|
|
animIndex = Objects[ID_GUARD1].animIndex;
|
2019-12-24 08:51:54 +01:00
|
|
|
ITEM_INFO* item = &Items[itemNum];
|
|
|
|
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
|
|
|
short angle = 0;
|
|
|
|
short joint2 = 0;
|
|
|
|
short joint1 = 0;
|
|
|
|
short joint0 = 0;
|
|
|
|
int x = item->pos.xPos;
|
|
|
|
int z = item->pos.zPos;
|
|
|
|
int dx = 870 * SIN(item->pos.yRot) >> W2V_SHIFT;
|
|
|
|
int dz = 870 * COS(item->pos.yRot) >> W2V_SHIFT;
|
|
|
|
x += dx;
|
|
|
|
z += dz;
|
|
|
|
short roomNumber = item->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(x, item->pos.yPos, z, &roomNumber);
|
|
|
|
int height1 = GetFloorHeight(floor, x, item->pos.yPos, z);
|
|
|
|
x += dx;
|
|
|
|
z += dz;
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, item->pos.yPos, z, &roomNumber);
|
|
|
|
int height2 = GetFloorHeight(floor, x, item->pos.yPos, z);
|
|
|
|
x += dx;
|
|
|
|
z += dz;
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, item->pos.yPos, z, &roomNumber);
|
|
|
|
int height3 = GetFloorHeight(floor, x, item->pos.yPos, z);
|
|
|
|
bool canJump1block;
|
|
|
|
if (item->boxNumber == LaraItem->boxNumber
|
|
|
|
|| item->pos.yPos >= height1 - 384
|
|
|
|
|| item->pos.yPos >= height2 + 256
|
|
|
|
|| item->pos.yPos <= height2 - 256)
|
|
|
|
canJump1block = false;
|
|
|
|
else
|
|
|
|
canJump1block = true;
|
|
|
|
bool canJump2blocks;
|
|
|
|
if (item->boxNumber == LaraItem->boxNumber
|
|
|
|
|| item->pos.yPos >= height1 - 384
|
|
|
|
|| item->pos.yPos >= height2 - 384
|
|
|
|
|| item->pos.yPos >= height3 + 256
|
|
|
|
|| item->pos.yPos <= height3 - 256)
|
|
|
|
canJump2blocks = false;
|
|
|
|
else
|
|
|
|
canJump2blocks = true;
|
|
|
|
if (item->firedWeapon)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
2019-12-30 00:01:00 +01:00
|
|
|
pos.x = SwatGun.x;
|
|
|
|
pos.y = SwatGun.y;
|
|
|
|
pos.z = SwatGun.z;
|
|
|
|
GetJointAbsPosition(item, &pos, SwatGun.meshNum);
|
2019-12-24 08:51:54 +01:00
|
|
|
TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * item->firedWeapon + 10, 192, 128, 32);
|
|
|
|
item->firedWeapon--;
|
|
|
|
}
|
|
|
|
if (item->aiBits)
|
|
|
|
GetAITarget(creature);
|
|
|
|
else
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
AI_INFO info;
|
|
|
|
AI_INFO laraInfo;
|
|
|
|
CreatureAIInfo(item, &info);
|
|
|
|
if (creature->enemy == LaraItem)
|
|
|
|
{
|
|
|
|
laraInfo.angle = info.angle;
|
|
|
|
laraInfo.distance = info.distance;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int dx = LaraItem->pos.xPos - item->pos.xPos;
|
|
|
|
int dz = LaraItem->pos.zPos - item->pos.zPos;
|
|
|
|
laraInfo.angle = ATAN(dz, dx) - item->pos.yRot;
|
|
|
|
laraInfo.distance = SQUARE(dx) + SQUARE(dz);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->hitPoints <= 0)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
if (item->currentAnimState != STATE_GUARD_DEATH1 && item->currentAnimState != STATE_GUARD_DEATH2)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
|
|
|
if (laraInfo.angle >= 12288 || laraInfo.angle <= -12288)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->currentAnimState = STATE_GUARD_DEATH2;
|
|
|
|
item->animNumber = animIndex + ANIMATION_GUARD_DEATH2;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->pos.yRot += laraInfo.angle + -ANGLE(180);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->currentAnimState = STATE_GUARD_DEATH1;
|
|
|
|
item->animNumber = animIndex + ANIMATION_GUARD_DEATH1;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->pos.yRot += laraInfo.angle;
|
|
|
|
}
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
GetCreatureMood(item, &info, creature->enemy != LaraItem);
|
|
|
|
if (item->objectNumber == ID_SCIENTIST)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->hitPoints >= Objects[ID_SCIENTIST].hitPoints)
|
|
|
|
{
|
|
|
|
if (creature->enemy == LaraItem)
|
|
|
|
creature->mood = BORED_MOOD;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
creature->mood = ESCAPE_MOOD;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if (Rooms[item->roomNumber].flags & ENV_FLAG_NO_LENSFLARE) // CHECK
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->objectNumber == ID_SWAT_PLUS)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
item->itemFlags[0]++;
|
|
|
|
if (item->itemFlags[0] > 60 && !(GetRandomControl() & 0xF))
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_BIO_BREATHE_OUT, &item->pos, 0);
|
|
|
|
item->itemFlags[0] = 0;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (!(GlobalCounter & 7))
|
|
|
|
item->hitPoints--;
|
|
|
|
creature->mood = ESCAPE_MOOD;
|
|
|
|
if (item->hitPoints <= 0)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->currentAnimState = STATE_GUARD_DEATH2;
|
|
|
|
item->animNumber = animIndex + ANIMATION_GUARD_DEATH2;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
CreatureMood(item, &info, creature->enemy != LaraItem);
|
|
|
|
ITEM_INFO * enemy = creature->enemy;
|
|
|
|
angle = CreatureTurn(item, creature->maximumTurn);
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
if (laraInfo.distance < 0x400000 && LaraItem->speed > 20
|
|
|
|
|| item->hitStatus
|
|
|
|
|| TargetVisible(item, &laraInfo))
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (!(item->aiBits & FOLLOW) && item->objectNumber != ID_SCIENTIST && abs(item->pos.yPos - LaraItem->pos.yPos) < 1280)
|
|
|
|
{
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
AlertAllGuards(itemNum);
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->enemy = enemy;
|
|
|
|
GAME_VECTOR src;
|
|
|
|
src.x = item->pos.xPos;
|
|
|
|
src.y = item->pos.yPos - 384;
|
|
|
|
src.z = item->pos.zPos;
|
2019-12-27 23:54:40 -03:00
|
|
|
src.roomNumber = item->roomNumber;
|
2019-12-24 13:52:22 +01:00
|
|
|
short* frame = GetBestFrame(LaraItem);
|
|
|
|
GAME_VECTOR dest;
|
|
|
|
dest.x = LaraItem->pos.xPos;
|
|
|
|
dest.y = LaraItem->pos.yPos + ((frame[3] + 3 * frame[2]) >> 2);
|
|
|
|
dest.z = LaraItem->pos.zPos;
|
|
|
|
bool los = !LOS(&src, &dest) && item->triggerFlags != 10;
|
|
|
|
creature->maximumTurn = 0;
|
2019-12-25 08:44:01 +01:00
|
|
|
ITEM_INFO* currentItem;
|
|
|
|
short currentItemNumber;
|
2020-03-16 12:36:29 +01:00
|
|
|
PHD_VECTOR pos1, pos2;
|
2019-12-24 13:52:22 +01:00
|
|
|
switch (item->currentAnimState)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
case STATE_GUARD_STOP:
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
joint2 = laraInfo.angle;
|
|
|
|
creature->flags = 0;
|
|
|
|
if (info.ahead)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (!(item->aiBits & FOLLOW))
|
|
|
|
{
|
|
|
|
joint0 = info.angle >> 1;
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->objectNumber == ID_SCIENTIST && item == Lara.target)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_SURREND;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else if (item->requiredAnimState)
|
|
|
|
{
|
|
|
|
item->goalAnimState = item->requiredAnimState;
|
|
|
|
}
|
|
|
|
else if (item->aiBits & GUARD)
|
|
|
|
{
|
|
|
|
if (item->aiBits & MODIFY)
|
|
|
|
joint2 = 0;
|
|
|
|
else
|
|
|
|
joint2 = AIGuard(creature);
|
|
|
|
if (item->aiBits & PATROL1)
|
|
|
|
{
|
|
|
|
item->triggerFlags--;
|
|
|
|
if (item->triggerFlags < 1)
|
|
|
|
item->aiBits &= ~GUARD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (creature->enemy == LaraItem && (laraInfo.angle > 20480 || laraInfo.angle < -20480) && item->objectNumber != ID_SCIENTIST)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_TURN180;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else if (item->aiBits & PATROL1)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_WALK;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else if (item->aiBits & AMBUSH)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_RUN;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else if (Targetable(item, &info) && item->objectNumber != ID_SCIENTIST)
|
|
|
|
{
|
|
|
|
if (info.distance >= 0x1000000 && info.zoneNumber == info.enemyZone)
|
|
|
|
{
|
|
|
|
if (!(item->aiBits & MODIFY))
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_WALK;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_AIM;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else if (canJump1block || canJump2blocks)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = animIndex + 41;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_GUARD_STOP_START_JUMP;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
if (canJump1block)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_JUMPING_1BLOCK;
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_JUMPING_2BLOCKS;
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
}
|
|
|
|
else if (los)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_HUNTING_IDLE;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else if (creature->mood)
|
|
|
|
{
|
|
|
|
if (info.distance < 0x900000 || item->aiBits & FOLLOW)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_WALK;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_RUN;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->triggerFlags == 11)
|
|
|
|
item->triggerFlags = 0;
|
|
|
|
break;
|
2020-03-13 06:56:09 +01:00
|
|
|
case STATE_GUARD_TURN180:
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->flags = 0;
|
2019-12-24 08:51:54 +01:00
|
|
|
if (info.angle >= 0)
|
2019-12-24 13:52:22 +01:00
|
|
|
item->pos.yRot -= ANGLE(2);
|
|
|
|
else
|
2019-12-24 08:51:54 +01:00
|
|
|
item->pos.yRot += ANGLE(2);
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameEnd)
|
|
|
|
item->pos.yRot += -ANGLE(180);
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_FIRE_SINGLE:
|
|
|
|
case STATE_GUARD_FIRE_FAST:
|
2019-12-24 13:52:22 +01:00
|
|
|
joint0 = laraInfo.angle >> 1;
|
|
|
|
joint2 = laraInfo.angle >> 1;
|
|
|
|
if (info.ahead)
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
if (abs(info.angle) >= ANGLE(2))
|
|
|
|
{
|
|
|
|
if (info.angle >= 0)
|
|
|
|
item->pos.yRot += ANGLE(2);
|
|
|
|
else
|
|
|
|
item->pos.yRot -= ANGLE(2);
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
else
|
2019-12-24 13:52:22 +01:00
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
2020-03-15 09:05:43 +01:00
|
|
|
if (item->currentAnimState == STATE_GUARD_FIRE_FAST)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (creature->flags)
|
|
|
|
{
|
|
|
|
if (item->frameNumber < Anims[item->animNumber].frameBase + 10
|
|
|
|
&& (item->frameNumber - Anims[item->animNumber].frameBase) & 1)
|
|
|
|
creature->flags = 0;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if (!creature->flags)
|
|
|
|
{
|
|
|
|
creature->flags = 1;
|
|
|
|
item->firedWeapon = 2;
|
2020-03-15 09:05:43 +01:00
|
|
|
if (item->currentAnimState == STATE_GUARD_FIRE_SINGLE)
|
2019-12-30 00:01:00 +01:00
|
|
|
ShotLara(item, &info, &SwatGun, joint0, 30);
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2019-12-30 00:01:00 +01:00
|
|
|
ShotLara(item, &info, &SwatGun, joint0, 10);
|
2020-03-16 12:36:29 +01:00
|
|
|
TriggerEnergyArc((PHD_VECTOR*)& item->pos, (PHD_VECTOR*)& LaraItem->pos, 0, 0, 128, 256, 150);
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-13 06:56:09 +01:00
|
|
|
case STATE_GUARD_AIM:
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->flags = 0;
|
|
|
|
joint0 = laraInfo.angle >> 1;
|
|
|
|
joint2 = laraInfo.angle >> 1;
|
|
|
|
if (info.ahead)
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
if (abs(info.angle) >= ANGLE(2))
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (info.angle >= 0)
|
|
|
|
item->pos.yRot += ANGLE(2);
|
2019-12-24 08:51:54 +01:00
|
|
|
else
|
2019-12-24 13:52:22 +01:00
|
|
|
item->pos.yRot -= ANGLE(2);
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
if (!Targetable(item, &info))
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2020-03-14 07:48:35 +01:00
|
|
|
else if (item->objectNumber == ID_GUARD1 || item->objectNumber == ID_GUARD2)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_FIRE_SINGLE;
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_FIRE_FAST;
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
2020-03-13 06:56:09 +01:00
|
|
|
case STATE_GUARD_WALK:
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
creature->maximumTurn = ANGLE(5);
|
|
|
|
if (!Targetable(item, &info)
|
|
|
|
|| info.distance >= 0x1000000 && info.zoneNumber == info.enemyZone
|
|
|
|
|| item->objectNumber == ID_SCIENTIST
|
|
|
|
|| item->aiBits & AMBUSH || item->aiBits & PATROL1) // CHECK
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (canJump1block || canJump2blocks)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = animIndex + 41;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_GUARD_STOP_START_JUMP;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
if (canJump1block)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_JUMPING_1BLOCK;
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_JUMPING_2BLOCKS;
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
}
|
|
|
|
else if (info.distance >= 0x100000)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (!los || item->aiBits)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (info.distance > 0x900000)
|
|
|
|
{
|
2020-01-16 19:14:35 +01:00
|
|
|
if (!(item->inDrawRoom))
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_RUN;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2019-12-24 13:52:22 +01:00
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_AIM;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-13 06:56:09 +01:00
|
|
|
case STATE_GUARD_RUN:
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
creature->maximumTurn = ANGLE(10);
|
|
|
|
if (Targetable(item, &info) && (info.distance < 0x1000000 || info.enemyZone == info.zoneNumber) && item->objectNumber != ID_SCIENTIST)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_AIM;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
else if (canJump1block || canJump2blocks)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = animIndex + 50;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_GUARD_STOP_START_JUMP;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
if (canJump1block)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_JUMPING_1BLOCK;
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_JUMPING_2BLOCKS;
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
}
|
|
|
|
else if (los)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else if (info.distance < 0x900000)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_WALK;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
if (item->triggerFlags == 11)
|
|
|
|
{
|
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_ROPE_DOWN:
|
2019-12-24 13:52:22 +01:00
|
|
|
joint2 = laraInfo.angle;
|
|
|
|
if (item->pos.yPos <= item->floor - 2048 || item->triggerFlags != 5)
|
|
|
|
{
|
|
|
|
if (item->pos.yPos >= item->floor - 512)
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_AIM;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
else
|
2019-12-24 13:52:22 +01:00
|
|
|
{
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
item->triggerFlags = 0;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
|
|
|
SoundEffect(SFX_LARA_ROPEDOWN_LOOP, &item->pos, 0);
|
|
|
|
}
|
|
|
|
if (abs(info.angle) >= 364)
|
|
|
|
{
|
|
|
|
if ((info.angle & 0x8000) == 0)
|
|
|
|
item->pos.yRot += ANGLE(2);
|
|
|
|
else
|
|
|
|
item->pos.yRot -= ANGLE(2);
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
else
|
2019-12-24 13:52:22 +01:00
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_SITTING:
|
2019-12-24 13:52:22 +01:00
|
|
|
joint2 = AIGuard(creature);
|
|
|
|
if (creature->alerted)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STAND_UP;
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_STAND_UP:
|
2019-12-24 13:52:22 +01:00
|
|
|
case 18:
|
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase)
|
|
|
|
{
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase + 44)
|
|
|
|
{
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
short currentItemNumber = Rooms[item->roomNumber].itemNumber;
|
|
|
|
if (currentItemNumber == NO_ITEM)
|
|
|
|
break;
|
|
|
|
ITEM_INFO * currentItem;
|
|
|
|
while (true)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
currentItem = &Items[currentItemNumber];
|
|
|
|
if (currentItem->objectNumber >= ID_ANIMATING1
|
|
|
|
&& currentItem->objectNumber <= ID_ANIMATING15
|
|
|
|
&& currentItem->roomNumber == item->roomNumber)
|
|
|
|
{
|
|
|
|
if (currentItem->triggerFlags > 2 && currentItem->triggerFlags < 5)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
currentItemNumber = currentItem->nextItem;
|
|
|
|
if (currentItemNumber == -1)
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if (currentItemNumber == NO_ITEM)
|
|
|
|
break;
|
|
|
|
currentItem->meshBits = -3;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else if (item->frameNumber == Anims[item->animNumber].frameEnd)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
item->pos.yRot -= ANGLE(90);
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
joint2 = 0;
|
|
|
|
if (!item->hitStatus && LaraItem->speed < 40 && !Lara.hasFired)
|
|
|
|
creature->alerted = false;
|
|
|
|
if (creature->alerted)
|
|
|
|
item->goalAnimState = 18;
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_WAITING_ON_WALL:
|
2019-12-24 13:52:22 +01:00
|
|
|
joint2 = AIGuard(creature);
|
|
|
|
if (creature->alerted)
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_HUNTING:
|
|
|
|
case STATE_GUARD_HUNTING_IDLE:
|
|
|
|
if (item->currentAnimState == STATE_GUARD_HUNTING_IDLE)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->triggerFlags != 8 || !los || item->hitStatus)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_HUNTING;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
creature->maximumTurn = ANGLE(5);
|
|
|
|
if (canJump1block || canJump2blocks || info.distance < 0x100000 || !los || item->hitStatus)
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_INSERT_CODE:
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase + 39)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_START_USE_COMPUTER:
|
2019-12-25 08:44:01 +01:00
|
|
|
currentItem = NULL;
|
|
|
|
for (currentItemNumber = Rooms[item->roomNumber].itemNumber; currentItemNumber != NO_ITEM; currentItemNumber = currentItem->nextItem)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
currentItem = &Items[currentItemNumber];
|
|
|
|
if (item->objectNumber == ID_PUZZLE_HOLE8)
|
|
|
|
break;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
currentItem->meshBits = 0x1FFF;
|
|
|
|
item->pos.xPos = currentItem->pos.xPos - 256;
|
|
|
|
item->pos.yRot = currentItem->pos.yRot;
|
|
|
|
item->pos.zPos = currentItem->pos.zPos + 128;
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 1024;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase + 32)
|
|
|
|
{
|
|
|
|
currentItem->meshBits = 16381;
|
|
|
|
}
|
|
|
|
else if (item->frameNumber == Anims[item->animNumber].frameBase + 74)
|
|
|
|
{
|
|
|
|
currentItem->meshBits = 278461;
|
|
|
|
}
|
|
|
|
else if (item->frameNumber == Anims[item->animNumber].frameBase + 120)
|
|
|
|
{
|
|
|
|
currentItem->meshBits = 802621;
|
|
|
|
}
|
|
|
|
else if (item->frameNumber == Anims[item->animNumber].frameBase + 157)
|
|
|
|
{
|
|
|
|
currentItem->meshBits = 819001;
|
|
|
|
}
|
|
|
|
else if (item->frameNumber == Anims[item->animNumber].frameBase + 190)
|
|
|
|
{
|
|
|
|
currentItem->meshBits = 17592121;
|
|
|
|
}
|
|
|
|
else if (item->frameNumber == Anims[item->animNumber].frameBase + Anims[item->animNumber].frameEnd)
|
|
|
|
{
|
|
|
|
currentItem->meshBits = 0x1FFF;
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
2020-03-13 06:56:09 +01:00
|
|
|
item->requiredAnimState = STATE_GUARD_WALK;
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_USE_COMPUTER:
|
2019-12-24 13:52:22 +01:00
|
|
|
if ((item->objectNumber != ID_SCIENTIST || item != Lara.target)
|
|
|
|
&& (GetRandomControl() & 0x7F || item->triggerFlags >= 10 || item->triggerFlags == 9))
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item->aiBits & GUARD)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
joint2 = AIGuard(creature);
|
|
|
|
if (item->aiBits & PATROL1)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
item->triggerFlags--;
|
|
|
|
if (item->triggerFlags < 1)
|
|
|
|
{
|
|
|
|
item->aiBits = PATROL1 | MODIFY;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
else
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_GUARD_SURREND:
|
2019-12-24 13:52:22 +01:00
|
|
|
if (item != Lara.target && !(GetRandomControl() & 0x3F))
|
|
|
|
{
|
|
|
|
if (item->triggerFlags == 7 || item->triggerFlags == 9)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->requiredAnimState = STATE_GUARD_USE_COMPUTER;
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
}
|
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase + 39)
|
|
|
|
{
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CreatureJoint(item, 0, joint0);
|
|
|
|
CreatureJoint(item, 1, joint1);
|
|
|
|
CreatureJoint(item, 2, joint2);
|
2019-12-24 13:52:22 +01:00
|
|
|
if (creature->reachedGoal && creature->enemy)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
ITEM_INFO* enemy = creature->enemy;
|
|
|
|
|
|
|
|
if (enemy->flags != 4)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2019-12-24 13:52:22 +01:00
|
|
|
if (enemy->flags & 0x10)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->requiredAnimState = STATE_GUARD_USE_COMPUTER;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->triggerFlags = 300;
|
|
|
|
item->aiBits = GUARD | PATROL1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (enemy->flags & 0x20)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->requiredAnimState = 36;
|
|
|
|
item->aiBits = PATROL1 | MODIFY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
roomNumber = enemy->roomNumber;
|
|
|
|
floor = GetFloor(creature->enemy->pos.xPos, creature->enemy->pos.yPos, creature->enemy->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, creature->enemy->pos.xPos, creature->enemy->pos.yPos, creature->enemy->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
2020-03-13 06:56:09 +01:00
|
|
|
item->requiredAnimState = STATE_GUARD_WALK;
|
2019-12-24 13:52:22 +01:00
|
|
|
if (creature->enemy->flags & 2)
|
2020-01-04 09:10:24 +01:00
|
|
|
item->itemFlags[3] = (item->TOSSPAD & 0xFF) - 1;
|
2019-12-24 13:52:22 +01:00
|
|
|
if (creature->enemy->flags & 8)
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->requiredAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->triggerFlags = 300;
|
|
|
|
item->aiBits |= GUARD | PATROL1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->requiredAnimState = 37;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-24 13:52:22 +01:00
|
|
|
if ((item->currentAnimState >= 20
|
|
|
|
|| item->currentAnimState == 6
|
|
|
|
|| item->currentAnimState == 8)
|
|
|
|
&& item->currentAnimState != 30)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
|
|
|
CreatureAnimation(itemNum, angle, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (CreatureVault(itemNum, angle, 2, 256) + 4)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
creature->maximumTurn = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->animNumber = animIndex + 38;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->currentAnimState = 23;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
creature->maximumTurn = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->animNumber = animIndex + 39;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->currentAnimState = 24;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
creature->maximumTurn = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->animNumber = animIndex + 40;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->currentAnimState = 25;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
creature->maximumTurn = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->animNumber = animIndex + 35;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->currentAnimState = 20;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
case 7:
|
2020-03-15 09:05:43 +01:00
|
|
|
creature->maximumTurn = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->animNumber = animIndex + 36;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->currentAnimState = 21;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
creature->maximumTurn = 0;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->animNumber = animIndex + 37;
|
2019-12-24 08:51:54 +01:00
|
|
|
item->currentAnimState = 22;
|
2019-12-24 13:52:22 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2019-12-24 08:51:54 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-12-29 20:53:05 +01:00
|
|
|
}
|
2020-03-15 09:05:43 +01:00
|
|
|
void SniperControl(short itemNumber)
|
2019-12-29 20:53:05 +01:00
|
|
|
{
|
|
|
|
if (CreatureActive(itemNumber))
|
|
|
|
{
|
|
|
|
short angle = 0;
|
|
|
|
short joint0 = 0;
|
|
|
|
short joint2 = 0;
|
|
|
|
short joint1 = 0;
|
|
|
|
ITEM_INFO* item = &Items[itemNumber];
|
|
|
|
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
|
|
|
if (item->firedWeapon)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
pos.x = SniperGun.x;
|
|
|
|
pos.y = SniperGun.y;
|
|
|
|
pos.z = SniperGun.z;
|
|
|
|
GetJointAbsPosition(item, &pos, SniperGun.meshNum);
|
|
|
|
TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * item->firedWeapon + 10, 192, 128, 32);
|
|
|
|
item->firedWeapon--;
|
|
|
|
}
|
|
|
|
if (item->hitPoints > 0)
|
|
|
|
{
|
|
|
|
if (item->aiBits)
|
|
|
|
{
|
|
|
|
GetAITarget(creature);
|
|
|
|
}
|
|
|
|
else if (creature->hurtByLara)
|
|
|
|
{
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
}
|
|
|
|
AI_INFO info;
|
|
|
|
CreatureAIInfo(item, &info);
|
|
|
|
GetCreatureMood(item, &info, VIOLENT);
|
|
|
|
CreatureMood(item, &info, VIOLENT);
|
|
|
|
angle = CreatureTurn(item, creature->maximumTurn);
|
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint0 = info.angle >> 1;
|
|
|
|
joint2 = info.angle >> 1;
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
}
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
switch (item->currentAnimState)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_SNIPER_STOP:
|
2019-12-29 20:53:05 +01:00
|
|
|
item->meshBits = 0;
|
|
|
|
if (TargetVisible(item, &info))
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_SNIPER_UNHIDE;
|
2019-12-29 20:53:05 +01:00
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_SNIPER_UNHIDE:
|
2019-12-29 20:53:05 +01:00
|
|
|
item->meshBits = -1;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
creature->flags = 0;
|
|
|
|
if (!TargetVisible(item, &info)
|
|
|
|
|| item->hitStatus
|
|
|
|
&& GetRandomControl() & 1)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_SNIPER_HIDE;
|
2019-12-29 20:53:05 +01:00
|
|
|
}
|
|
|
|
else if (!(GetRandomControl() & 0x1F))
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_SNIPER_FIRE;
|
2019-12-29 20:53:05 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_SNIPER_FIRE:
|
2019-12-29 20:53:05 +01:00
|
|
|
if (!creature->flags)
|
|
|
|
{
|
|
|
|
ShotLara(item, &info, &SniperGun, joint0, 100);
|
|
|
|
creature->flags = 1;
|
|
|
|
item->firedWeapon = 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->hitPoints = 0;
|
2020-03-15 09:05:43 +01:00
|
|
|
if (item->currentAnimState != STATE_SNIPER_DEATH)
|
2019-12-29 20:53:05 +01:00
|
|
|
{
|
|
|
|
item->animNumber = Objects[ID_SNIPER].animIndex + 5;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_SNIPER_DEATH;
|
2019-12-29 20:53:05 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CreatureTilt(item, 0);
|
|
|
|
CreatureJoint(item, 0, joint0);
|
|
|
|
CreatureJoint(item, 1, joint1);
|
|
|
|
CreatureJoint(item, 2, joint2);
|
|
|
|
CreatureAnimation(itemNumber, angle, 0);
|
|
|
|
}
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
2020-03-15 09:05:43 +01:00
|
|
|
void InitialiseMafia2(short itemNum)
|
2019-12-30 00:01:00 +01:00
|
|
|
{
|
|
|
|
ITEM_INFO* item = &Items[itemNum];
|
|
|
|
ClearItem(itemNum);
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
2020-03-13 06:56:09 +01:00
|
|
|
item->goalAnimState = STATE_GUARD_STOP;
|
|
|
|
item->currentAnimState = STATE_GUARD_STOP;
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 9216;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
2020-03-15 09:05:43 +01:00
|
|
|
void Mafia2Control(short itemNum)
|
2019-12-30 00:01:00 +01:00
|
|
|
{
|
|
|
|
if (!CreatureActive(itemNum))
|
|
|
|
return;
|
|
|
|
ITEM_INFO* item = &Items[itemNum];
|
|
|
|
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
|
|
|
short angle = 0;
|
|
|
|
short joint2 = 0;
|
|
|
|
short joint1 = 0;
|
|
|
|
short joint0 = 0;
|
|
|
|
// Can baddy jump? Check for a distance of 1 and 2 sectors
|
|
|
|
int x = item->pos.xPos;
|
|
|
|
int y = item->pos.yPos;
|
|
|
|
int z = item->pos.zPos;
|
|
|
|
int dx = 870 * SIN(item->pos.yRot) >> W2V_SHIFT;
|
|
|
|
int dz = 870 * COS(item->pos.yRot) >> W2V_SHIFT;
|
|
|
|
x += dx;
|
|
|
|
z += dz;
|
|
|
|
short roomNumber = item->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height1 = GetFloorHeight(floor, x, y, z);
|
|
|
|
x += dx;
|
|
|
|
z += dz;
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height2 = GetFloorHeight(floor, x, y, z);
|
|
|
|
x += dx;
|
|
|
|
z += dz;
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height3 = GetFloorHeight(floor, x, y, z);
|
|
|
|
int height = 0;
|
|
|
|
bool canJump1sector = true;
|
|
|
|
if (item->boxNumber == LaraItem->boxNumber
|
|
|
|
|| y >= height1 - 384
|
|
|
|
|| y >= height2 + 256
|
|
|
|
|| y <= height2 - 256)
|
|
|
|
{
|
|
|
|
height = height2;
|
|
|
|
canJump1sector = false;
|
|
|
|
}
|
|
|
|
bool canJump2sectors = true;
|
|
|
|
if (item->boxNumber == LaraItem->boxNumber
|
|
|
|
|| y >= height1 - 384
|
|
|
|
|| y >= height - 384
|
|
|
|
|| y >= height3 + 256
|
|
|
|
|| y <= height3 - 256)
|
|
|
|
{
|
|
|
|
canJump2sectors = false;
|
|
|
|
}
|
|
|
|
if (item->firedWeapon)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
pos.x = ArmedBaddy2Gun.x;
|
|
|
|
pos.y = ArmedBaddy2Gun.y;
|
|
|
|
pos.z = ArmedBaddy2Gun.z;
|
|
|
|
GetJointAbsPosition(item, &pos, ArmedBaddy2Gun.meshNum);
|
|
|
|
TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * item->firedWeapon + 8, 24, 16, 4);
|
|
|
|
item->firedWeapon--;
|
|
|
|
}
|
|
|
|
AI_INFO info;
|
|
|
|
AI_INFO laraInfo;
|
|
|
|
ZeroMemory(&info, sizeof(AI_INFO));
|
|
|
|
if (item->hitPoints > 0)
|
|
|
|
{
|
|
|
|
if (item->aiBits)
|
|
|
|
GetAITarget(creature);
|
|
|
|
else
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
CreatureAIInfo(item, &info);
|
|
|
|
if (creature->enemy == LaraItem)
|
|
|
|
{
|
|
|
|
laraInfo.angle = info.angle;
|
|
|
|
laraInfo.distance = info.distance;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dx = LaraItem->pos.xPos - item->pos.xPos;
|
|
|
|
dz = LaraItem->pos.zPos - item->pos.zPos;
|
|
|
|
laraInfo.angle = ATAN(dz, dx) - item->pos.yRot;
|
|
|
|
laraInfo.distance = SQUARE(dx) + SQUARE(dz);
|
|
|
|
}
|
|
|
|
GetCreatureMood(item, &info, creature->enemy != LaraItem);
|
|
|
|
CreatureMood(item, &info, creature->enemy != LaraItem);
|
|
|
|
angle = CreatureTurn(item, creature->maximumTurn);
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
if (laraInfo.distance < SQUARE(2048) && LaraItem->speed > 20 || item->hitStatus || TargetVisible(item, &laraInfo))
|
|
|
|
{
|
|
|
|
if (!(item->aiBits & FOLLOW))
|
|
|
|
{
|
|
|
|
creature->enemy = LaraItem;
|
|
|
|
AlertAllGuards(itemNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (item->currentAnimState)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_STOP:
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
joint2 = laraInfo.angle;
|
|
|
|
creature->flags = 0;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (info.ahead && !(item->aiBits & GUARD))
|
|
|
|
{
|
|
|
|
joint0 = info.angle >> 1;
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
}
|
|
|
|
if (item->aiBits & GUARD)
|
|
|
|
{
|
|
|
|
joint2 = AIGuard(creature);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (laraInfo.angle <= 20480 && laraInfo.angle >= -20480)
|
|
|
|
{
|
2020-01-04 09:10:24 +01:00
|
|
|
if (item->swapMeshFlags == 9216)
|
2019-12-30 00:01:00 +01:00
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_UNDRAW_GUNS;
|
2019-12-30 00:01:00 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-01-04 09:10:24 +01:00
|
|
|
else if (item->swapMeshFlags == 9216)
|
2019-12-30 00:01:00 +01:00
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_TURN180;
|
2019-12-30 00:01:00 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Targetable(item, &info))
|
|
|
|
{
|
|
|
|
if (info.distance < SQUARE(1024) || info.zoneNumber != info.enemyZone)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_AIM;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else if (!(item->aiBits & MODIFY))
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_WALK;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (item->aiBits & PATROL1)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_WALK;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (canJump1sector || canJump2sectors)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 41;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_MAFIA2_STOP_START_JUMP;
|
2019-12-30 00:01:00 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
if (canJump2sectors)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_JUMPING_2BLOCKS;
|
2019-12-30 00:01:00 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_JUMPING_1BLOCK;
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (creature->mood)
|
|
|
|
{
|
|
|
|
if (info.distance >= SQUARE(3072))
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_WALK;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_STOP;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_TURN180_UNDRAW_GUNS:
|
|
|
|
case STATE_MAFIA2_TURN180:
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (info.angle >= 0)
|
|
|
|
item->pos.yRot -= ANGLE(2);
|
|
|
|
else
|
|
|
|
item->pos.yRot += ANGLE(2);
|
2020-01-04 09:10:24 +01:00
|
|
|
if (item->frameNumber != Anims[item->animNumber].frameBase + 16
|
|
|
|
|| item->swapMeshFlags != 9216)
|
2019-12-30 00:01:00 +01:00
|
|
|
{
|
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameEnd)
|
|
|
|
item->pos.yRot += -ANGLE(180);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-01-04 09:10:24 +01:00
|
|
|
item->swapMeshFlags = 128;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_FIRE:
|
2019-12-30 00:01:00 +01:00
|
|
|
joint0 = laraInfo.angle >> 1;
|
|
|
|
joint2 = laraInfo.angle >> 1;
|
|
|
|
if (info.ahead)
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (abs(info.angle) >= ANGLE(2))
|
|
|
|
{
|
|
|
|
if (info.angle >= 0)
|
|
|
|
item->pos.yRot += ANGLE(2);
|
|
|
|
else
|
|
|
|
item->pos.yRot -= ANGLE(2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
if (!creature->flags)
|
|
|
|
{
|
|
|
|
ShotLara(item, &info, &ArmedBaddy2Gun, laraInfo.angle >> 1, 35);
|
|
|
|
creature->flags = 1;
|
|
|
|
item->firedWeapon = 2;
|
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_AIM:
|
2019-12-30 00:01:00 +01:00
|
|
|
joint0 = laraInfo.angle >> 1;
|
|
|
|
joint2 = laraInfo.angle >> 1;
|
|
|
|
creature->flags = 0;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (info.ahead)
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
if (abs(info.angle) >= ANGLE(2))
|
|
|
|
{
|
|
|
|
if (info.angle >= 0)
|
|
|
|
item->pos.yRot += ANGLE(2);
|
|
|
|
else
|
|
|
|
item->pos.yRot -= ANGLE(2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
if (Targetable(item, &info))
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_FIRE;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else if (laraInfo.angle > 20480 || laraInfo.angle < -20480)
|
|
|
|
{
|
|
|
|
item->goalAnimState = 32;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_STOP;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_WALK:
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
creature->maximumTurn = ANGLE(5);
|
|
|
|
if (Targetable(item, &info) && (info.distance < SQUARE(1024) || info.zoneNumber != info.enemyZone))
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_AIM;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (canJump1sector || canJump2sectors)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 41;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_MAFIA2_STOP_START_JUMP;
|
2019-12-30 00:01:00 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
if (canJump2sectors)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_JUMPING_2BLOCKS;
|
2019-12-30 00:01:00 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_JUMPING_1BLOCK;
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (info.distance >= SQUARE(1024))
|
|
|
|
{
|
|
|
|
if (info.distance > SQUARE(3072))
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_RUN;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_STOP;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_RUN:
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->LOT.isJumping = false;
|
|
|
|
creature->maximumTurn = ANGLE(10);
|
|
|
|
if (Targetable(item, &info) && (info.distance < SQUARE(1024) || info.zoneNumber != info.enemyZone))
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_AIM;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
else if (canJump1sector || canJump2sectors)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 50;
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_MAFIA2_STOP_START_JUMP;
|
2019-12-30 00:01:00 +01:00
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
if (canJump2sectors)
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_JUMPING_2BLOCKS;
|
2019-12-30 00:01:00 +01:00
|
|
|
else
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_JUMPING_1BLOCK;
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
}
|
|
|
|
else if (info.distance < SQUARE(3072))
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->goalAnimState = STATE_MAFIA2_WALK;
|
2019-12-30 00:01:00 +01:00
|
|
|
}
|
|
|
|
break;
|
2020-03-15 09:05:43 +01:00
|
|
|
case STATE_MAFIA2_UNDRAW_GUNS:
|
2019-12-30 00:01:00 +01:00
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (info.angle >= 0)
|
|
|
|
item->pos.yRot += ANGLE(2);
|
|
|
|
else
|
|
|
|
item->pos.yRot -= ANGLE(2);
|
2020-01-04 09:10:24 +01:00
|
|
|
if (item->frameNumber == Anims[item->animNumber].frameBase + 16
|
|
|
|
&& item->swapMeshFlags == 9216)
|
|
|
|
item->swapMeshFlags = 128;
|
2019-12-30 00:01:00 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
if (item->currentAnimState != STATE_MAFIA2_DEATH2 && item->currentAnimState != STATE_MAFIA2_DEATH1)
|
2019-12-30 00:01:00 +01:00
|
|
|
{
|
|
|
|
if (info.angle >= 12288 || info.angle <= -12288)
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_MAFIA2_DEATH2;
|
2019-12-30 00:01:00 +01:00
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 16;
|
|
|
|
item->pos.yRot += info.angle - ANGLE(180);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-15 09:05:43 +01:00
|
|
|
item->currentAnimState = STATE_MAFIA2_DEATH1;
|
2019-12-30 00:01:00 +01:00
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 11;
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CreatureJoint(item, 0, joint0);
|
|
|
|
CreatureJoint(item, 1, joint1);
|
|
|
|
CreatureJoint(item, 2, joint2);
|
|
|
|
if (item->currentAnimState >= 20 || item->currentAnimState == 6 || item->currentAnimState == 8)
|
|
|
|
{
|
|
|
|
CreatureAnimation(itemNum, angle, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (CreatureVault(itemNum, angle, 2, 256) + 4)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 38;
|
|
|
|
item->currentAnimState = 23;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 39;
|
|
|
|
item->currentAnimState = 24;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 40;
|
|
|
|
item->currentAnimState = 25;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 35;
|
|
|
|
item->currentAnimState = 20;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 36;
|
|
|
|
item->currentAnimState = 21;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 37;
|
|
|
|
item->currentAnimState = 22;
|
|
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-03-18 06:27:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ControlGuardLaser(short itemNumber)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|