TombEngine/TR5Main/Objects/TR5/tr5_guard.cpp

1364 lines
38 KiB
C++
Raw Normal View History

2020-02-01 07:54:26 +01:00
#include "../oldobjects.h"
#include "../../Game/items.h"
#include "../../Game/sphere.h"
#include "../../Game/Box.h"
#include "../../Game/effect2.h"
#include "../../Game/people.h"
#include "../../Game/tomb4fx.h"
#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 };
#define STATE_GUARD_STOP 1
#define STATE_GUARD_TURN180 2
2020-03-15 09:05:43 +01:00
#define STATE_GUARD_FIRE_SINGLE 3
#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
#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
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)
anim = Objects[ID_GUARD1].animIndex;
switch (item->triggerFlags)
{
case 0:
case 10:
item->animNumber = anim;
item->goalAnimState = STATE_GUARD_STOP;
break;
case 1:
2020-03-15 09:05:43 +01:00
item->goalAnimState = STATE_GUARD_RECOIL;
item->animNumber = anim + 23;
break;
case 2:
2020-03-15 09:05:43 +01:00
item->goalAnimState = STATE_GUARD_CROUCH;
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;
item->animNumber = anim + 28;
item->swapMeshFlags = 9216;
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;
item->swapMeshFlags = 8192;
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;
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;
item->animNumber = anim + 32;
break;
case 7:
case 9:
2020-03-15 09:05:43 +01:00
item->goalAnimState = STATE_GUARD_USE_COMPUTER;
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;
item->animNumber = anim + 46;
break;
case 11:
item->goalAnimState = STATE_GUARD_RUN;
item->animNumber = anim + 12;
break;
default:
break;
}
}
2020-03-15 09:05:43 +01:00
void InitialiseSniper(short itemNum)
{
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;
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;
item->goalAnimState = STATE_GUARD_STOP;
item->currentAnimState = STATE_GUARD_STOP;
}
2020-03-15 09:05:43 +01:00
void GuardControl(short itemNum)
{
if (!CreatureActive(itemNum))
return;
int animIndex = 0;
if (Objects[ID_SWAT].loaded)
animIndex= Objects[ID_SWAT].animIndex;
else
animIndex = Objects[ID_GUARD1].animIndex;
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);
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)
{
if (item->currentAnimState != STATE_GUARD_DEATH1 && item->currentAnimState != STATE_GUARD_DEATH2)
{
if (laraInfo.angle >= 12288 || laraInfo.angle <= -12288)
{
item->currentAnimState = STATE_GUARD_DEATH2;
item->animNumber = animIndex + ANIMATION_GUARD_DEATH2;
item->pos.yRot += laraInfo.angle + -ANGLE(180);
}
else
{
item->currentAnimState = STATE_GUARD_DEATH1;
item->animNumber = animIndex + ANIMATION_GUARD_DEATH1;
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 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 13:52:22 +01:00
if (Rooms[item->roomNumber].flags & ENV_FLAG_NO_LENSFLARE) // CHECK
{
2019-12-24 13:52:22 +01:00
if (item->objectNumber == ID_SWAT_PLUS)
{
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 13:52:22 +01:00
else
{
2019-12-24 13:52:22 +01:00
if (!(GlobalCounter & 7))
item->hitPoints--;
creature->mood = ESCAPE_MOOD;
if (item->hitPoints <= 0)
{
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 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 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 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;
PHD_VECTOR pos1, pos2;
2019-12-24 13:52:22 +01:00
switch (item->currentAnimState)
{
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 13:52:22 +01:00
if (!(item->aiBits & FOLLOW))
{
joint0 = info.angle >> 1;
joint1 = info.xAngle;
}
}
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)
{
item->goalAnimState = STATE_GUARD_TURN180;
}
2019-12-24 13:52:22 +01:00
else if (item->aiBits & PATROL1)
{
item->goalAnimState = STATE_GUARD_WALK;
2019-12-24 13:52:22 +01:00
}
else if (item->aiBits & AMBUSH)
{
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))
item->goalAnimState = STATE_GUARD_WALK;
2019-12-24 13:52:22 +01:00
}
else
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)
{
item->goalAnimState = STATE_GUARD_WALK;
2019-12-24 13:52:22 +01:00
}
else
item->goalAnimState = STATE_GUARD_RUN;
}
else
{
item->goalAnimState = STATE_GUARD_STOP;
}
2019-12-24 13:52:22 +01:00
if (item->triggerFlags == 11)
item->triggerFlags = 0;
break;
case STATE_GUARD_TURN180:
2019-12-24 13:52:22 +01:00
creature->flags = 0;
if (info.angle >= 0)
2019-12-24 13:52:22 +01:00
item->pos.yRot -= ANGLE(2);
else
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);
}
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 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 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);
TriggerEnergyArc((PHD_VECTOR*)& item->pos, (PHD_VECTOR*)& LaraItem->pos, 0, 0, 128, 256, 150);
2019-12-24 13:52:22 +01:00
}
break;
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 13:52:22 +01:00
if (info.angle >= 0)
item->pos.yRot += ANGLE(2);
else
2019-12-24 13:52:22 +01:00
item->pos.yRot -= ANGLE(2);
}
2019-12-24 13:52:22 +01:00
else
{
item->pos.yRot += info.angle;
}
if (!Targetable(item, &info))
item->goalAnimState = STATE_GUARD_STOP;
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;
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 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 13:52:22 +01:00
if (!los || item->aiBits)
{
2019-12-24 13:52:22 +01:00
if (info.distance > 0x900000)
{
if (!(item->inDrawRoom))
item->goalAnimState = STATE_GUARD_RUN;
2019-12-24 13:52:22 +01:00
}
}
else
{
item->goalAnimState = STATE_GUARD_STOP;
}
}
else
{
item->goalAnimState = STATE_GUARD_STOP;
}
}
else
2019-12-24 13:52:22 +01:00
{
item->goalAnimState = STATE_GUARD_AIM;
2019-12-24 13:52:22 +01:00
}
break;
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)
{
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)
{
item->goalAnimState = STATE_GUARD_STOP;
}
2019-12-24 13:52:22 +01:00
else if (info.distance < 0x900000)
{
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)
item->goalAnimState = STATE_GUARD_AIM;
2019-12-24 13:52:22 +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);
}
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)
{
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 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)
break;
}
2019-12-24 13:52:22 +01:00
if (currentItemNumber == NO_ITEM)
break;
currentItem->meshBits = -3;
}
2019-12-24 13:52:22 +01:00
else if (item->frameNumber == Anims[item->animNumber].frameEnd)
{
2019-12-24 13:52:22 +01:00
item->pos.yRot -= ANGLE(90);
}
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)
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 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 13:52:22 +01:00
creature->LOT.isJumping = false;
creature->maximumTurn = ANGLE(5);
if (canJump1block || canJump2blocks || info.distance < 0x100000 || !los || item->hitStatus)
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 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 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 13:52:22 +01:00
currentItem = &Items[currentItemNumber];
if (item->objectNumber == ID_PUZZLE_HOLE8)
break;
}
2019-12-24 13:52:22 +01:00
if (item->frameNumber == Anims[item->animNumber].frameBase)
{
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;
item->swapMeshFlags = 1024;
}
2019-12-24 13:52:22 +01:00
else
{
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);
item->requiredAnimState = STATE_GUARD_WALK;
item->swapMeshFlags = 0;
2019-12-24 13:52:22 +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 13:52:22 +01:00
if (item->aiBits & GUARD)
{
2019-12-24 13:52:22 +01:00
joint2 = AIGuard(creature);
if (item->aiBits & PATROL1)
{
2019-12-24 13:52:22 +01:00
item->triggerFlags--;
if (item->triggerFlags < 1)
{
item->aiBits = PATROL1 | MODIFY;
}
}
}
}
2019-12-24 13:52:22 +01:00
else
{
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;
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;
}
}
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 13:52:22 +01:00
ITEM_INFO* enemy = creature->enemy;
if (enemy->flags != 4)
{
2019-12-24 13:52:22 +01:00
if (enemy->flags & 0x10)
{
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)
{
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);
item->requiredAnimState = STATE_GUARD_WALK;
2019-12-24 13:52:22 +01:00
if (creature->enemy->flags & 2)
item->itemFlags[3] = (item->TOSSPAD & 0xFF) - 1;
2019-12-24 13:52:22 +01:00
if (creature->enemy->flags & 8)
{
item->requiredAnimState = STATE_GUARD_STOP;
2019-12-24 13:52:22 +01:00
item->triggerFlags = 300;
item->aiBits |= GUARD | PATROL1;
}
}
}
}
else
{
item->goalAnimState = STATE_GUARD_STOP;
2019-12-24 13:52:22 +01:00
item->requiredAnimState = 37;
}
}
2019-12-24 13:52:22 +01:00
if ((item->currentAnimState >= 20
|| item->currentAnimState == 6
|| item->currentAnimState == 8)
&& item->currentAnimState != 30)
{
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;
item->currentAnimState = 23;
2019-12-24 13:52:22 +01:00
item->frameNumber = Anims[item->animNumber].frameBase;
break;
case 1:
creature->maximumTurn = 0;
2019-12-24 13:52:22 +01:00
item->animNumber = animIndex + 39;
item->currentAnimState = 24;
2019-12-24 13:52:22 +01:00
item->frameNumber = Anims[item->animNumber].frameBase;
break;
case 2:
creature->maximumTurn = 0;
2019-12-24 13:52:22 +01:00
item->animNumber = animIndex + 40;
item->currentAnimState = 25;
2019-12-24 13:52:22 +01:00
item->frameNumber = Anims[item->animNumber].frameBase;
break;
case 6:
creature->maximumTurn = 0;
2019-12-24 13:52:22 +01:00
item->animNumber = animIndex + 35;
item->currentAnimState = 20;
2019-12-24 13:52:22 +01:00
item->frameNumber = Anims[item->animNumber].frameBase;
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;
item->currentAnimState = 21;
2019-12-24 13:52:22 +01:00
item->frameNumber = Anims[item->animNumber].frameBase;
break;
case 8:
creature->maximumTurn = 0;
2019-12-24 13:52:22 +01:00
item->animNumber = animIndex + 37;
item->currentAnimState = 22;
2019-12-24 13:52:22 +01:00
item->frameNumber = Anims[item->animNumber].frameBase;
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;
item->goalAnimState = STATE_GUARD_STOP;
item->currentAnimState = STATE_GUARD_STOP;
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)
{
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;
}
}
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);
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
{
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);
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)
{
}