2020-05-27 09:21:20 +02:00
|
|
|
#include "framework.h"
|
|
|
|
#include "tr4_baddy.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "box.h"
|
|
|
|
#include "sphere.h"
|
|
|
|
#include "effect2.h"
|
|
|
|
#include "lara.h"
|
|
|
|
#include "people.h"
|
|
|
|
#include "effect.h"
|
|
|
|
#include "setup.h"
|
|
|
|
#include "level.h"
|
2020-08-08 20:31:48 +02:00
|
|
|
#include <draw.h>
|
2021-04-18 07:20:27 +02:00
|
|
|
#include <Game/lot.h>
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
enum BADDY_STATES {
|
|
|
|
STATE_BADDY_STOP = 0,
|
|
|
|
STATE_BADDY_WALK = 1,
|
|
|
|
STATE_BADDY_RUN = 2,
|
|
|
|
// 3
|
|
|
|
STATE_BADDY_DODGE_START = 4,
|
|
|
|
// 5
|
|
|
|
// 6
|
|
|
|
// 7
|
|
|
|
STATE_BADDY_UNKNOWN_8 = 8,
|
|
|
|
STATE_BADDY_UNKNOWN_9 = 9,
|
|
|
|
STATE_BADDY_DRAW_GUN = 10,
|
|
|
|
STATE_BADDY_HOLSTER_GUN = 11,
|
|
|
|
STATE_BADDY_DRAW_SWORD = 12,
|
|
|
|
STATE_BADDY_HOLSTER_SWORD = 13,
|
|
|
|
STATE_BADDY_FIRE = 14,
|
|
|
|
STATE_BADDY_SWORD_HIT_FRONT = 15,
|
|
|
|
STATE_BADDY_SWORD_HIT_RIGHT = 16,
|
|
|
|
STATE_BADDY_SWORD_HIT_LEFT = 17,
|
|
|
|
STATE_BADDY_MONKEY_GRAB = 18,
|
|
|
|
STATE_BADDY_MONKEY_IDLE = 19,
|
|
|
|
STATE_BADDY_MONKEY_FORWARD = 20,
|
|
|
|
STATE_BADDY_MONKEY_PUSH_OFF = 21,
|
|
|
|
STATE_BADDY_MONKEY_FALL_LAND = 22,
|
|
|
|
STATE_BADDY_ROLL_LEFT = 23,
|
|
|
|
STATE_BADDY_JUMP_RIGHT = 24,
|
|
|
|
STATE_BADDY_STAND_TO_CROUCH = 25,
|
|
|
|
STATE_BADDY_CROUCH = 26,
|
|
|
|
STATE_BADDY_CROUCH_PICKUP = 27,
|
|
|
|
STATE_BADDY_CROUCH_TO_STAND = 28,
|
|
|
|
STATE_BADDY_WALK_SWORD_HIT_RIGHT = 29,
|
|
|
|
STATE_BADDY_SOMERSAULT = 30,
|
|
|
|
STATE_BADDY_AIM = 31,
|
|
|
|
STATE_BADDY_DEATH = 32,
|
|
|
|
STATE_BADDY_JUMP_FORWARD_1_BLOCK = 33,
|
|
|
|
STATE_BADDY_JUMP_FORWARD_FALL = 34,
|
|
|
|
STATE_BADDY_MONKEY_TO_FREEFALL = 35,
|
|
|
|
STATE_BADDY_FREEFALL = 36,
|
|
|
|
STATE_BADDY_FREEFALL_LAND_DEATH = 37,
|
|
|
|
STATE_BADDY_JUMP_FORWARD_2_BLOCKS = 38,
|
|
|
|
STATE_BADDY_CLIMB_4_CLICKS = 39,
|
|
|
|
STATE_BADDY_CLIMB_3_CLICKS = 40,
|
|
|
|
STATE_BADDY_CLIMB_2_CLICKS = 41,
|
|
|
|
STATE_BADDY_JUMP_OFF_4_CLICKS = 42,
|
|
|
|
STATE_BADDY_JUMP_OFF_3_CLICKS = 43,
|
|
|
|
STATE_BADDY_BLIND = 44
|
|
|
|
};
|
|
|
|
|
|
|
|
enum BADDY_ANIM {
|
|
|
|
ANIMATION_BADDY_RUN = 0,
|
|
|
|
ANIMATION_BADDY_RUN_STOP_START = 1,
|
|
|
|
ANIMATION_BADDY_RUN_STOP_END = 2,
|
|
|
|
ANIMATION_BADDY_SOMERSAULT_START = 3,
|
|
|
|
ANIMATION_BADDY_SOMERSAULT_END = 4,
|
|
|
|
ANIMATION_BADDY_DODGE_START = 5,
|
|
|
|
// 6
|
|
|
|
// 7
|
|
|
|
// 8
|
|
|
|
ANIMATION_BADDY_MONKEY_GRAB = 9,
|
|
|
|
ANIMATION_BADDY_MONKEY_IDLE = 10,
|
|
|
|
ANIMATION_BADDY_MONKEY_FORWARD = 11,
|
|
|
|
ANIMATION_BADDY_MONKEY_IDLE_TO_FORWARD = 12,
|
|
|
|
ANIMATION_BADDY_MONKEY_STOP_LEFT = 13,
|
|
|
|
ANIMATION_BADDY_MONKEY_STOP_RIGHT = 14,
|
|
|
|
ANIMATION_BADDY_MONKEY_FALL_LAND = 15,
|
|
|
|
ANIMATION_BADDY_MONKEY_PUSH_OFF = 16,
|
|
|
|
ANIMATION_BADDY_DODGE_END = 17,
|
|
|
|
ANIMATION_BADDY_STAND_IDLE = 18,
|
|
|
|
ANIMATION_BADDY_DODGE_END_TO_STAND = 19,
|
|
|
|
ANIMATION_BADDY_DRAW_GUN = 20,
|
|
|
|
ANIMATION_BADDY_HOLSTER_GUN = 21,
|
|
|
|
ANIMATION_BADDY_DRAW_SWORD = 22,
|
|
|
|
ANIMATION_BADDY_HOLSTER_SWORD = 23,
|
|
|
|
ANIMATION_BADDY_STAND_TO_ROLL_LEFT = 24,
|
|
|
|
ANIMATION_BADDY_ROLL_LEFT_START = 25,
|
|
|
|
ANIMATION_BADDY_ROLL_LEFT_CONTINUE = 26,
|
|
|
|
ANIMATION_BADDY_ROLL_LEFT_END = 27,
|
|
|
|
ANIMATION_BADDY_ROLL_LEFT_TO_CROUCH = 28,
|
|
|
|
ANIMATION_BADDY_CROUCH = 29,
|
|
|
|
ANIMATION_BADDY_CROUCH_TO_STAND = 30,
|
|
|
|
ANIMATION_BADDY_STAND_TO_WALK = 31,
|
|
|
|
ANIMATION_BADDY_WALK = 32,
|
|
|
|
ANIMATION_BADDY_WALK_TO_RUN = 33,
|
|
|
|
ANIMATION_BADDY_STAND_TO_AIM = 34,
|
|
|
|
ANIMATION_BADDY_AIM = 35,
|
|
|
|
ANIMATION_BADDY_FIRE = 36,
|
|
|
|
ANIMATION_BADDY_AIM_TO_STAND = 37,
|
|
|
|
ANIMATION_BADDY_SWORD_HIT_FRONT = 38,
|
|
|
|
ANIMATION_BADDY_CROUCH_PICKUP = 39,
|
|
|
|
ANIMATION_BADDY_STAND_TO_CROUCH = 40,
|
|
|
|
ANIMATION_BADDY_SWORD_HIT_RIGHT = 41,
|
|
|
|
ANIMATION_BADDY_SWORD_HIT_RIGHT_TO_LEFT = 42,
|
|
|
|
ANIMATION_BADDY_SWORD_HIT_RIGHT_TO_STAND = 43,
|
|
|
|
ANIMATION_BADDY_SWORD_HIT_LEFT = 44,
|
|
|
|
ANIMATION_BADDY_STAND_DEATH = 45,
|
|
|
|
ANIMATION_BADDY_WALK_SWORD_HIT_RIGHT = 46,
|
|
|
|
ANIMATION_BADDY_STAND_TO_JUMP_RIGHT = 47,
|
|
|
|
ANIMATION_BADDY_JUMP_RIGHT_START = 48,
|
|
|
|
ANIMATION_BADDY_JUMP_RIGHT_CONTINUE = 49,
|
|
|
|
ANIMATION_BADDY_JUMP_RIGHT_END = 50,
|
|
|
|
ANIMATION_BADDY_RUN_TO_WALK = 51,
|
|
|
|
// 52
|
|
|
|
// 53
|
|
|
|
ANIMATION_BADDY_WALK_STOP_RIGHT = 54,
|
|
|
|
ANIMATION_BADDY_STAND_TO_JUMP_FORWARD = 55,
|
|
|
|
ANIMATION_BADDY_JUMP_FORWARD_1_BLOCK = 56,
|
|
|
|
ANIMATION_BADDY_JUMP_FORWARD_FALL = 57,
|
|
|
|
ANIMATION_BADDY_JUMP_FORWARD_LAND = 58,
|
|
|
|
ANIMATION_BADDY_MONKEY_TO_FREEFALL = 59,
|
|
|
|
ANIMATION_BADDY_FREEFALL = 60,
|
|
|
|
ANIMATION_BADDY_FREEFALL_LAND_DEATH = 61,
|
|
|
|
ANIMATION_BADDY_CLIMB_4_CLICKS = 62,
|
|
|
|
ANIMATION_BADDY_CLIMB_3_CLICKS = 63,
|
|
|
|
ANIMATION_BADDY_CLIMB_2_CLICKS = 64,
|
|
|
|
ANIMATION_BADDY_JUMP_OFF_4_CLICKS = 65,
|
|
|
|
ANIMATION_BADDY_JUMP_OFF_3_CLICKS = 66,
|
|
|
|
ANIMATION_BADDY_JUMP_FORWARD_2_BLOCKS = 67,
|
|
|
|
ANIMATION_BADDY_BLIND = 68,
|
|
|
|
ANIMATION_BADDY_BLIND_TO_STAND = 69,
|
|
|
|
ANIMATION_BADDY_DEAD = 70,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum BADDY_FRAMES {
|
|
|
|
FRAME_BADDY_HOLSTER_GUN = 20,
|
|
|
|
FRAME_BADDY_DRAW_GUN = 21,
|
|
|
|
FRAME_BADDY_HOLSTER_SWORD = 22,
|
|
|
|
FRAME_BADDY_DRAW_SWORD = 12,
|
|
|
|
FRAME_BADDY_RUN_TO_SOMERSAULT = 11,
|
|
|
|
FRAME_BADDY_SWORD_HIT_NO_DAMAGE_MAX = 12,
|
|
|
|
FRAME_BADDY_SWORD_HIT_DAMAGE_MIN = 13,
|
|
|
|
FRAME_BADDY_SWORD_HIT_DAMAGE_MAX = 21,
|
|
|
|
FRAME_BADDY_CROUCH_PICKUP = 9,
|
|
|
|
FRAME_BADDY_FIRE_MIN = 1,
|
|
|
|
FRAME_BADDY_FIRE_MAX = 13,
|
|
|
|
FRAME_BADDY_SOMERSAULT_START_TAKE_OFF = 18,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum BADDY_SWAP_MESH_FLAGS {
|
|
|
|
SWAPMESHFLAGS_BADDY_EMPTY = 0x7FC800,
|
|
|
|
SWAPMESHFLAGS_BADDY_SWORD_SIMPLE = 0x7E0880,
|
|
|
|
SWAPMESHFLAGS_BADDY_SWORD_NINJA = 0x000880,
|
|
|
|
SWAPMESHFLAGS_BADDY_GUN = 0x7FC010,
|
|
|
|
};
|
|
|
|
|
2021-04-19 07:41:37 +02:00
|
|
|
#define BADDY_USE_UZI 24
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
BITE_INFO baddyGun = { 0, -16, 200, 11 };
|
|
|
|
BITE_INFO baddySword = { 0, 0, 0, 15 };
|
|
|
|
|
|
|
|
void InitialiseBaddy(short itemNum)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
ClearItem(itemNum);
|
|
|
|
|
|
|
|
short objectNumber = (Objects[ID_BADDY2].loaded ? ID_BADDY2 : ID_BADDY1);
|
2020-05-28 01:23:47 +02:00
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
if (item->objectNumber == ID_BADDY1)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_GUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->meshBits = 0xFF81FFFF;
|
2021-04-19 07:41:37 +02:00
|
|
|
item->itemFlags[2] = BADDY_USE_UZI;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_SWORD_NINJA;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->meshBits = -1;
|
|
|
|
item->itemFlags[2] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->itemFlags[1] = -1;
|
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
short ocb = item->triggerFlags % 1000;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// To the same things of OCB 1, 2, 3, 4 but also drawing uzis
|
2019-12-05 17:35:57 +01:00
|
|
|
if (ocb > 9 && ocb < 20)
|
|
|
|
{
|
2021-04-19 07:41:37 +02:00
|
|
|
item->itemFlags[2] += BADDY_USE_UZI;
|
2021-04-18 07:20:27 +02:00
|
|
|
item->triggerFlags -= 10;
|
2019-12-05 17:35:57 +01:00
|
|
|
ocb -= 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ocb || ocb > 4 && ocb < 7)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_STAND_IDLE;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
|
|
|
item->currentAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// OCB: jump right
|
2019-12-05 17:35:57 +01:00
|
|
|
if (ocb == 1)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_STAND_TO_JUMP_RIGHT;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_JUMP_RIGHT;
|
|
|
|
item->currentAnimState = STATE_BADDY_JUMP_RIGHT;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// OCB: jump left
|
2019-12-05 17:35:57 +01:00
|
|
|
if (ocb == 2)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_STAND_TO_ROLL_LEFT;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_ROLL_LEFT;
|
|
|
|
item->currentAnimState = STATE_BADDY_ROLL_LEFT;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// OCB: crouch
|
2019-12-05 17:35:57 +01:00
|
|
|
if (ocb == 3)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_CROUCH;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_CROUCH;
|
|
|
|
item->currentAnimState = STATE_BADDY_CROUCH;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// OCB: climb up 4 or 6 clicks
|
2019-12-05 17:35:57 +01:00
|
|
|
if (ocb == 4)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_CLIMB_4_CLICKS;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_CLIMB_4_CLICKS;
|
|
|
|
item->currentAnimState = STATE_BADDY_CLIMB_4_CLICKS;
|
2020-10-05 22:24:57 -03:00
|
|
|
item->pos.xPos += phd_sin(item->pos.yRot) * (STEP_SIZE * 4);
|
|
|
|
item->pos.zPos += phd_cos(item->pos.yRot) * (STEP_SIZE * 4);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// OCB: crouch and jump in train levels?
|
2019-12-05 17:35:57 +01:00
|
|
|
if (ocb > 100)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_CROUCH;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_CROUCH;
|
|
|
|
item->currentAnimState = STATE_BADDY_CROUCH;
|
2020-10-05 22:24:57 -03:00
|
|
|
item->pos.xPos += phd_sin(item->pos.yRot) * (STEP_SIZE * 4);
|
|
|
|
item->pos.zPos += phd_cos(item->pos.yRot) * (STEP_SIZE * 4);
|
2019-12-05 17:35:57 +01:00
|
|
|
item->itemFlags[3] = ocb;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void BaddyControl(short itemNum)
|
|
|
|
{
|
|
|
|
if (!CreatureActive(itemNum))
|
|
|
|
return;
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2019-12-05 17:35:57 +01:00
|
|
|
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
|
|
|
ITEM_INFO* enemyItem = creature->enemy;
|
2020-07-07 07:32:33 +02:00
|
|
|
OBJECT_INFO* obj = &Objects[ID_BADDY1];
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
short tilt = 0;
|
|
|
|
short angle = 0;
|
|
|
|
short joint1 = 0;
|
|
|
|
short joint2 = 0;
|
|
|
|
short joint3 = 0;
|
|
|
|
|
|
|
|
// TODO: better add a second control routine for baddy 2 instead of mixing them?
|
|
|
|
short objectNumber = (Objects[ID_BADDY2].loaded ? ID_BADDY2 : ID_BADDY1);
|
|
|
|
|
|
|
|
int roll = false;
|
|
|
|
int jump = false;
|
|
|
|
int someFlag3 = false;
|
|
|
|
|
|
|
|
if (item->triggerFlags % 1000)
|
|
|
|
{
|
|
|
|
creature->LOT.isJumping = true;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
if (item->triggerFlags % 1000 > 100)
|
|
|
|
{
|
|
|
|
item->itemFlags[0] = -80;
|
|
|
|
FindAITargetObject(creature, ID_AI_X1);
|
|
|
|
}
|
|
|
|
item->triggerFlags = 1000 * (item->triggerFlags / 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
int dx = 942 * phd_sin(item->pos.yRot);
|
|
|
|
int dz = 942 * phd_cos(item->pos.yRot);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
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 (enemyItem && item->boxNumber == enemyItem->boxNumber
|
2020-05-28 01:23:47 +02:00
|
|
|
|| y >= height1 - (STEP_SIZE * 1.5f)
|
|
|
|
|| y >= height2 + STEP_SIZE
|
|
|
|
|| y <= height2 - STEP_SIZE)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
height = height2;
|
|
|
|
canJump1sector = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool canJump2sectors = true;
|
|
|
|
if (enemyItem && item->boxNumber == enemyItem->boxNumber
|
2020-05-28 01:23:47 +02:00
|
|
|
|| y >= height1 - (STEP_SIZE * 1.5f)
|
|
|
|
|| y >= height - (STEP_SIZE * 1.5f)
|
|
|
|
|| y >= height3 + STEP_SIZE
|
|
|
|
|| y <= height3 - STEP_SIZE)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
canJump2sectors = false;
|
|
|
|
}
|
|
|
|
|
2021-04-16 10:13:59 +02:00
|
|
|
CREATURE_INFO* currentCreature = creature;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->itemFlags[1] == item->roomNumber
|
2021-04-16 10:13:59 +02:00
|
|
|
|| g_Level.Rooms[item->roomNumber].itemNumber == NO_ITEM)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
currentCreature = creature;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentCreature = creature;
|
2021-04-18 07:20:27 +02:00
|
|
|
creature->enemy = LaraItem;
|
|
|
|
ITEM_INFO* currentItem = NULL;
|
2021-04-16 10:13:59 +02:00
|
|
|
for (short itemNum = g_Level.Rooms[item->roomNumber].itemNumber; itemNum != NO_ITEM; itemNum = currentItem->nextItem)
|
|
|
|
{
|
|
|
|
currentItem = &g_Level.Items[itemNum];
|
2021-04-19 07:41:37 +02:00
|
|
|
if ((currentItem->objectNumber == ID_SMALLMEDI_ITEM
|
|
|
|
|| currentItem->objectNumber == ID_BIGMEDI_ITEM
|
|
|
|
|| currentItem->objectNumber == ID_UZI_AMMO_ITEM)
|
2021-04-16 10:13:59 +02:00
|
|
|
&& SameZone(creature, currentItem))
|
|
|
|
{
|
|
|
|
if (item->status != ITEM_INVISIBLE)
|
2021-04-18 07:20:27 +02:00
|
|
|
{
|
|
|
|
creature->enemy = currentItem;
|
2021-04-16 10:13:59 +02:00
|
|
|
break;
|
2021-04-18 07:20:27 +02:00
|
|
|
}
|
2021-04-16 10:13:59 +02:00
|
|
|
}
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
item->itemFlags[1] = item->roomNumber;
|
|
|
|
|
|
|
|
// Handle baddy firing
|
|
|
|
if (item->firedWeapon)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
|
|
|
|
pos.x = baddyGun.x;
|
|
|
|
pos.y = baddyGun.y;
|
|
|
|
pos.z = baddyGun.z;
|
|
|
|
|
|
|
|
GetJointAbsPosition(item, &pos, baddyGun.meshNum);
|
|
|
|
TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * item->firedWeapon + 8, 24, 16, 4);
|
|
|
|
item->firedWeapon--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->hitPoints <= 0)
|
|
|
|
{
|
|
|
|
currentCreature->LOT.isMonkeying = false;
|
|
|
|
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
item->floor = height;
|
|
|
|
|
|
|
|
switch (item->currentAnimState)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_DEATH:
|
2019-12-05 17:35:57 +01:00
|
|
|
item->gravityStatus = true;
|
|
|
|
currentCreature->LOT.isMonkeying = false;
|
|
|
|
if (item->pos.yPos >= item->floor)
|
|
|
|
{
|
|
|
|
item->pos.yPos = item->floor;
|
|
|
|
item->fallspeed = 0;
|
|
|
|
item->gravityStatus = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_MONKEY_TO_FREEFALL:
|
|
|
|
item->goalAnimState = STATE_BADDY_FREEFALL;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->gravityStatus = false;
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_FREEFALL:
|
2019-12-05 17:35:57 +01:00
|
|
|
item->gravityStatus = true;
|
|
|
|
if (item->pos.yPos >= item->floor)
|
|
|
|
{
|
|
|
|
item->pos.yPos = item->floor;
|
|
|
|
item->fallspeed = 0;
|
|
|
|
item->gravityStatus = false;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_FREEFALL_LAND_DEATH;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_FREEFALL_LAND_DEATH:
|
2019-12-05 17:35:57 +01:00
|
|
|
item->pos.yPos = item->floor;
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_MONKEY_GRAB:
|
|
|
|
case STATE_BADDY_MONKEY_IDLE:
|
|
|
|
case STATE_BADDY_MONKEY_FORWARD:
|
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_MONKEY_TO_FREEFALL;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->currentAnimState = STATE_BADDY_MONKEY_TO_FREEFALL;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->speed = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
currentCreature->LOT.isJumping = true;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_STAND_DEATH;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->currentAnimState = STATE_BADDY_DEATH;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// OCB: respawn code for BADDY_1
|
|
|
|
if (item->triggerFlags > 999)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < g_Level.NumItems; i++)
|
|
|
|
{
|
|
|
|
ITEM_INFO* possibleEnemy = &g_Level.Items[i];
|
|
|
|
if (possibleEnemy->objectNumber == ID_BADDY1 || possibleEnemy->objectNumber == ID_BADDY2
|
|
|
|
&& (item->triggerFlags / 1000) == (possibleEnemy->triggerFlags / 1000) - 1
|
|
|
|
&& !(possibleEnemy->flags & IFLAG_KILLED))
|
|
|
|
{
|
|
|
|
if (EnableBaddieAI(i, 0))
|
|
|
|
{
|
|
|
|
possibleEnemy->status = ITEM_ACTIVE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
possibleEnemy->status = ITEM_INVISIBLE;
|
|
|
|
}
|
|
|
|
AddActiveItem(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (item->aiBits)
|
|
|
|
GetAITarget(currentCreature);
|
|
|
|
else if (!currentCreature->enemy)
|
|
|
|
currentCreature->enemy = LaraItem;
|
|
|
|
|
|
|
|
AI_INFO info;
|
|
|
|
AI_INFO laraInfo;
|
|
|
|
|
|
|
|
CreatureAIInfo(item, &info);
|
|
|
|
|
|
|
|
if (currentCreature->enemy == LaraItem)
|
|
|
|
{
|
|
|
|
laraInfo.angle = info.angle;
|
|
|
|
laraInfo.ahead = info.ahead;
|
|
|
|
laraInfo.distance = info.distance;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dx = LaraItem->pos.xPos - item->pos.xPos;
|
|
|
|
dz = LaraItem->pos.zPos - item->pos.zPos;
|
2020-04-25 16:23:53 +02:00
|
|
|
laraInfo.angle = phd_atan(dz, dx) - item->pos.yRot;
|
2019-12-05 17:35:57 +01:00
|
|
|
laraInfo.ahead = true;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
if (laraInfo.angle <= -ANGLE(90) || laraInfo.angle >= ANGLE(90))
|
2019-12-05 17:35:57 +01:00
|
|
|
laraInfo.ahead = false;
|
|
|
|
|
|
|
|
laraInfo.distance = dx * dx + dz * dz;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetCreatureMood(item, &info, VIOLENT);
|
|
|
|
|
|
|
|
// Vehicle handling
|
2020-04-27 14:01:00 +02:00
|
|
|
if (Lara.Vehicle != NO_ITEM && info.bite)
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->mood == ESCAPE_MOOD;
|
|
|
|
|
|
|
|
CreatureMood(item, &info, VIOLENT);
|
|
|
|
|
|
|
|
angle = CreatureTurn(item, currentCreature->maximumTurn);
|
|
|
|
|
|
|
|
//currentCreature->enemy = LaraItem;
|
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
//ITEM_INFO* oldEnemy = creature->enemy;
|
|
|
|
//creature->enemy = LaraItem;
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
// Is baddy alerted?
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->hitStatus
|
|
|
|
|| laraInfo.distance < SQUARE(1024)
|
2021-04-21 06:45:08 +02:00
|
|
|
|| TargetVisible(item, &laraInfo)
|
|
|
|
&& abs(LaraItem->pos.yPos - item->pos.yPos) < STEP_SIZE * 4)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
currentCreature->alerted = true;
|
|
|
|
}
|
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
if (item != Lara.target
|
|
|
|
|| laraInfo.distance <= 942
|
|
|
|
|| laraInfo.angle <= -ANGLE(56.25f)
|
|
|
|
|| laraInfo.angle >= ANGLE(56.25f))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
roll = false;
|
|
|
|
jump = false;
|
|
|
|
}
|
2021-04-21 06:45:08 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
dx = 942 * phd_sin(item->pos.yRot + ANGLE(45));
|
|
|
|
dz = 942 * phd_cos(item->pos.yRot + ANGLE(45));
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
x = item->pos.xPos + dx;
|
|
|
|
y = item->pos.yPos;
|
|
|
|
z = item->pos.zPos + dz;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height4 = GetFloorHeight(floor, x, y, z);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
dx = 942 * phd_sin(item->pos.yRot + ANGLE(78.75f));
|
|
|
|
dz = 942 * phd_cos(item->pos.yRot + ANGLE(78.75f));
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
x = item->pos.xPos + dx;
|
|
|
|
y = item->pos.yPos;
|
|
|
|
z = item->pos.zPos + dz;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height5 = GetFloorHeight(floor, x, y, z);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
if (abs(height5 - item->pos.yPos) > STEP_SIZE)
|
2019-12-05 17:35:57 +01:00
|
|
|
jump = false;
|
2021-04-21 06:45:08 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
jump = true;
|
|
|
|
if (height4 + 512 >= item->pos.yPos)
|
|
|
|
jump = false;
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
dx = 942 * phd_sin(item->pos.yRot - ANGLE(45));
|
|
|
|
dz = 942 * phd_cos(item->pos.yRot - ANGLE(45));
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
x = item->pos.xPos + dx;
|
|
|
|
y = item->pos.yPos;
|
|
|
|
z = item->pos.zPos + dz;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height6 = GetFloorHeight(floor, x, y, z);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
dx = 942 * phd_sin(item->pos.yRot - ANGLE(78.75f));
|
|
|
|
dz = 942 * phd_cos(item->pos.yRot - ANGLE(78.75f));
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
x = item->pos.xPos + dx;
|
|
|
|
y = item->pos.yPos;
|
|
|
|
z = item->pos.zPos + dz;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height7 = GetFloorHeight(floor, x, y, z);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
if (abs(height7 - item->pos.yPos) > STEP_SIZE || height6 + (STEP_SIZE * 2) >= item->pos.yPos)
|
|
|
|
{
|
|
|
|
roll = false;
|
|
|
|
someFlag3 = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
roll = true;
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (item->currentAnimState)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_STOP:
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->LOT.isMonkeying = false;
|
|
|
|
currentCreature->LOT.isJumping = false;
|
|
|
|
currentCreature->flags = 0;
|
|
|
|
currentCreature->maximumTurn = 0;
|
|
|
|
joint3 = info.angle / 2;
|
2021-04-21 06:45:08 +02:00
|
|
|
if (info.ahead && item->aiBits != GUARD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
joint1 = info.angle / 2;
|
|
|
|
joint2 = info.xAngle;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->aiBits & GUARD)
|
|
|
|
{
|
|
|
|
joint3 = AIGuard(currentCreature);
|
|
|
|
item->goalAnimState = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_SWORD_NINJA
|
2019-12-05 17:35:57 +01:00
|
|
|
&& item == Lara.target
|
|
|
|
&& laraInfo.ahead
|
|
|
|
&& laraInfo.distance > SQUARE(682))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_DODGE_START;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Targetable(item, &info) && item->itemFlags[2] > 0)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_GUN)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_AIM;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags != SWAPMESHFLAGS_BADDY_SWORD_SIMPLE && item->swapMeshFlags != SWAPMESHFLAGS_BADDY_SWORD_NINJA)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_DRAW_GUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-04-21 06:45:08 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_HOLSTER_SWORD;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->aiBits & MODIFY)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
|
|
|
if (item->floor > item->pos.yPos + (STEP_SIZE * 3))
|
2019-12-05 17:35:57 +01:00
|
|
|
item->aiBits &= ~MODIFY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (canJump1sector || canJump2sectors)
|
|
|
|
{
|
|
|
|
currentCreature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_STAND_TO_JUMP_FORWARD;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->currentAnimState = STATE_BADDY_JUMP_FORWARD_1_BLOCK;
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->LOT.isJumping = true;
|
|
|
|
|
|
|
|
if (!canJump2sectors)
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_JUMP_FORWARD_1_BLOCK;
|
2019-12-05 17:35:57 +01:00
|
|
|
else
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_JUMP_FORWARD_2_BLOCKS;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentCreature->enemy)
|
|
|
|
{
|
|
|
|
short objNum = currentCreature->enemy->objectNumber;
|
2021-04-19 07:41:37 +02:00
|
|
|
if ((objNum == ID_SMALLMEDI_ITEM || objNum == ID_UZI_AMMO_ITEM || objNum == ID_BIGMEDI_ITEM)
|
|
|
|
&& info.distance < SQUARE(512))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STAND_TO_CROUCH;
|
|
|
|
item->requiredAnimState = STATE_BADDY_CROUCH_PICKUP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_GUN && item->itemFlags[2] < 1)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_HOLSTER_GUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentCreature->monkeyAhead)
|
|
|
|
{
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
2020-05-28 01:23:47 +02:00
|
|
|
if (GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) == height - (STEP_SIZE * 6))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_EMPTY)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_MONKEY_GRAB;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_GUN)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_HOLSTER_GUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_HOLSTER_SWORD;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (roll)
|
|
|
|
{
|
|
|
|
currentCreature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_ROLL_LEFT;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (jump)
|
|
|
|
{
|
|
|
|
currentCreature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_JUMP_RIGHT;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_EMPTY)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_DRAW_SWORD;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (currentCreature->enemy && currentCreature->enemy->hitPoints > 0 && info.distance < SQUARE(682))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags == SWAPMESHFLAGS_BADDY_GUN)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_HOLSTER_GUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-04-21 06:45:08 +02:00
|
|
|
else if (info.distance >= SQUARE(512))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_SWORD_HIT_FRONT;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else if (GetRandomControl() & 1)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_SWORD_HIT_LEFT;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_SWORD_HIT_RIGHT;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-04-21 06:45:08 +02:00
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_WALK:
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->LOT.isMonkeying = false;
|
|
|
|
currentCreature->LOT.isJumping = false;
|
|
|
|
currentCreature->maximumTurn = ANGLE(7);
|
|
|
|
currentCreature->flags = 0;
|
|
|
|
|
|
|
|
if (laraInfo.ahead)
|
|
|
|
{
|
|
|
|
joint3 = laraInfo.angle;
|
|
|
|
}
|
|
|
|
else if (laraInfo.ahead)
|
|
|
|
{
|
|
|
|
joint3 = laraInfo.angle;
|
|
|
|
}
|
|
|
|
if (Targetable(item, &info) && item->itemFlags[2] > 0)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (canJump1sector || canJump2sectors)
|
|
|
|
{
|
|
|
|
currentCreature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (currentCreature->reachedGoal && currentCreature->monkeyAhead)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->itemFlags[2] < 1)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->swapMeshFlags != SWAPMESHFLAGS_BADDY_SWORD_SIMPLE && item->swapMeshFlags != SWAPMESHFLAGS_BADDY_SWORD_NINJA)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (info.ahead && info.distance < 0x40000)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (info.bite)
|
|
|
|
{
|
|
|
|
if (info.distance < SQUARE(482))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (info.distance < SQUARE(1024))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_WALK_SWORD_HIT_RIGHT;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (roll || jump)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->currentAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (currentCreature->mood == ATTACK_MOOD &&
|
|
|
|
!(currentCreature->jumpAhead) &&
|
|
|
|
info.distance > SQUARE(1024))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_RUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_RUN:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint3 = info.angle;
|
|
|
|
}
|
|
|
|
currentCreature->maximumTurn = ANGLE(11);
|
|
|
|
tilt = abs(angle) / 2;
|
|
|
|
if (objectNumber == ID_BADDY2
|
2020-07-21 09:56:47 +02:00
|
|
|
&& item->frameNumber == g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_RUN_TO_SOMERSAULT
|
2019-12-05 17:35:57 +01:00
|
|
|
&& height3 == height1
|
2020-05-28 01:23:47 +02:00
|
|
|
&& abs(height1 - item->pos.yPos) < STEP_SIZE * 1.5f
|
|
|
|
&& (info.angle > -ANGLE(22.5f) && info.angle < ANGLE(22.5f) &&
|
2019-12-05 17:35:57 +01:00
|
|
|
info.distance < SQUARE(3072)
|
|
|
|
|| height2 >= height1 + 512))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_SOMERSAULT;
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->maximumTurn = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Targetable(item, &info)
|
|
|
|
&& item->itemFlags[2] > 0
|
|
|
|
|| canJump1sector
|
|
|
|
|| canJump2sectors
|
|
|
|
|| currentCreature->monkeyAhead
|
|
|
|
|| item->aiBits & FOLLOW
|
|
|
|
|| info.distance < SQUARE(614)
|
|
|
|
|| currentCreature->jumpAhead)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (info.distance < SQUARE(1024))
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_SWORD_HIT_RIGHT:
|
|
|
|
case STATE_BADDY_SWORD_HIT_FRONT:
|
|
|
|
case STATE_BADDY_SWORD_HIT_LEFT:
|
|
|
|
case STATE_BADDY_WALK_SWORD_HIT_RIGHT:
|
|
|
|
if (item->currentAnimState == STATE_BADDY_SWORD_HIT_RIGHT &&
|
2019-12-05 17:35:57 +01:00
|
|
|
info.distance < 0x40000)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_SWORD_HIT_LEFT;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint1 = info.angle;
|
|
|
|
joint2 = info.xAngle;
|
|
|
|
}
|
|
|
|
currentCreature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->currentAnimState != STATE_BADDY_SWORD_HIT_FRONT ||
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber < g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_SWORD_HIT_NO_DAMAGE_MAX)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
if (abs(info.angle) >= ANGLE(7))
|
|
|
|
{
|
|
|
|
if (info.angle >= 0)
|
|
|
|
{
|
|
|
|
item->pos.yRot += ANGLE(7);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot -= ANGLE(7);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!currentCreature->flags)
|
|
|
|
{
|
|
|
|
if (item->touchBits & 0x1C000)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber > g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_SWORD_HIT_DAMAGE_MIN &&
|
|
|
|
item->frameNumber < g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_SWORD_HIT_DAMAGE_MAX)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
LaraItem->hitPoints -= 120;
|
|
|
|
LaraItem->hitStatus = true;
|
|
|
|
CreatureEffect2(
|
|
|
|
item,
|
|
|
|
&baddySword,
|
|
|
|
10,
|
|
|
|
item->pos.yRot,
|
|
|
|
DoBloodSplat);
|
|
|
|
currentCreature->flags = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd - 1)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
currentCreature->flags = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_MONKEY_IDLE:
|
2019-12-05 17:35:57 +01:00
|
|
|
joint2 = 0;
|
|
|
|
joint1 = 0;
|
|
|
|
currentCreature->maximumTurn = 0;
|
|
|
|
currentCreature->flags = 0;
|
|
|
|
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
|
|
|
|
if (laraInfo.ahead
|
|
|
|
&& laraInfo.distance < SQUARE(682)
|
2020-08-04 20:32:07 +10:00
|
|
|
&& (LaraItem->currentAnimState == LS_MONKEYSWING_IDLE
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_FORWARD
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_LEFT
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_RIGHT
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_TURN_180
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_TURN_LEFT
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_TURN_RIGHT))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_MONKEY_PUSH_OFF;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else if (item->boxNumber != currentCreature->LOT.targetBox
|
|
|
|
&& currentCreature->monkeyAhead
|
2020-05-28 01:23:47 +02:00
|
|
|
|| GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) != height - (STEP_SIZE * 6))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_MONKEY_FORWARD;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_MONKEY_FALL_LAND;
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->LOT.isMonkeying = false;
|
|
|
|
currentCreature->LOT.isJumping = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_MONKEY_FORWARD:
|
2019-12-05 17:35:57 +01:00
|
|
|
joint2 = 0;
|
|
|
|
joint1 = 0;
|
|
|
|
currentCreature->LOT.isJumping = true;
|
|
|
|
currentCreature->LOT.isMonkeying = true;
|
|
|
|
currentCreature->flags = 0;
|
|
|
|
currentCreature->maximumTurn = ANGLE(7);
|
|
|
|
if (item->boxNumber == currentCreature->LOT.targetBox ||
|
|
|
|
!currentCreature->monkeyAhead)
|
|
|
|
{
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
2020-05-28 01:23:47 +02:00
|
|
|
if (GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) == height - (STEP_SIZE * 6))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_MONKEY_IDLE;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (laraInfo.ahead)
|
|
|
|
{
|
|
|
|
if (laraInfo.distance < SQUARE(682))
|
|
|
|
{
|
|
|
|
|
2020-08-04 20:32:07 +10:00
|
|
|
if (LaraItem->currentAnimState == LS_MONKEYSWING_IDLE
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_FORWARD
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_LEFT
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_RIGHT
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_TURN_180
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_TURN_LEFT
|
|
|
|
|| LaraItem->currentAnimState == LS_MONKEYSWING_TURN_RIGHT)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_MONKEY_IDLE;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_MONKEY_PUSH_OFF:
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->maximumTurn = ANGLE(7);
|
|
|
|
if (currentCreature->flags == someFlag3)
|
|
|
|
{
|
|
|
|
if (item->touchBits)
|
|
|
|
{
|
2020-08-04 20:32:07 +10:00
|
|
|
LaraItem->currentAnimState = LS_JUMP_UP;
|
|
|
|
LaraItem->goalAnimState = LS_JUMP_UP;
|
|
|
|
LaraItem->animNumber = LA_JUMP_UP;
|
2020-07-21 09:56:47 +02:00
|
|
|
LaraItem->frameNumber = g_Level.Anims[LaraItem->frameNumber].frameBase + 9;
|
2019-12-05 17:35:57 +01:00
|
|
|
LaraItem->gravityStatus = true;
|
|
|
|
LaraItem->speed = 2;
|
|
|
|
LaraItem->fallspeed = 1;
|
2020-05-28 01:23:47 +02:00
|
|
|
LaraItem->pos.yPos += (STEP_SIZE * 0.75f);
|
2020-06-05 14:01:22 +02:00
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->flags = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_ROLL_LEFT:
|
|
|
|
case STATE_BADDY_JUMP_RIGHT:
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->alerted = false;
|
|
|
|
currentCreature->maximumTurn = someFlag3;
|
|
|
|
item->status = ITEM_ACTIVE;
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_CROUCH:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (item->itemFlags[0] == someFlag3)
|
|
|
|
{
|
|
|
|
if (currentCreature->enemy)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
if ((currentCreature->enemy->objectNumber == ID_SMALLMEDI_ITEM
|
2021-04-19 07:41:37 +02:00
|
|
|
|| currentCreature->enemy->objectNumber == ID_BIGMEDI_ITEM
|
2020-05-28 01:23:47 +02:00
|
|
|
|| currentCreature->enemy->objectNumber == ID_UZI_AMMO_ITEM)
|
2021-04-19 07:41:37 +02:00
|
|
|
&& info.distance < SQUARE(512))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_CROUCH_PICKUP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (currentCreature->alerted)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_CROUCH_TO_STAND;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (info.distance >= SQUARE(682))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_CROUCH_TO_STAND;
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->enemy = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_CROUCH_PICKUP:
|
2019-12-05 17:35:57 +01:00
|
|
|
ClampRotation(&item->pos, info.angle, ANGLE(11));
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber != g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_CROUCH_PICKUP)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!currentCreature->enemy)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (currentCreature->enemy->objectNumber != ID_SMALLMEDI_ITEM &&
|
2021-04-19 07:41:37 +02:00
|
|
|
currentCreature->enemy->objectNumber != ID_BIGMEDI_ITEM &&
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->enemy->objectNumber != ID_UZI_AMMO_ITEM)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2020-05-28 01:23:47 +02:00
|
|
|
if (currentCreature->enemy->roomNumber == NO_ROOM ||
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->enemy->status == ITEM_INVISIBLE ||
|
2020-01-16 19:14:35 +01:00
|
|
|
currentCreature->enemy->inDrawRoom)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
currentCreature->enemy = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (currentCreature->enemy->objectNumber == ID_SMALLMEDI_ITEM)
|
|
|
|
{
|
2020-10-17 23:36:06 -05:00
|
|
|
item->hitPoints += Objects[item->objectNumber].hitPoints / 2;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-04-19 07:41:37 +02:00
|
|
|
else if (currentCreature->enemy->objectNumber == ID_BIGMEDI_ITEM)
|
|
|
|
{
|
|
|
|
item->hitPoints = Objects[item->objectNumber].hitPoints;
|
|
|
|
}
|
|
|
|
else if (currentCreature->enemy->objectNumber == ID_UZI_AMMO_ITEM)
|
|
|
|
{
|
|
|
|
item->itemFlags[2] += BADDY_USE_UZI;
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
else
|
|
|
|
{
|
2021-04-19 07:41:37 +02:00
|
|
|
currentCreature->enemy = NULL;
|
|
|
|
break;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-04-18 07:20:27 +02:00
|
|
|
|
|
|
|
KillItem(currentCreature->enemy - g_Level.Items.data());
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-04-18 07:20:27 +02:00
|
|
|
// cancel enemy pointer for other active baddies
|
|
|
|
for (int i = 0; i < NUM_SLOTS; i++)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2021-04-18 07:20:27 +02:00
|
|
|
if (BaddieSlots[i].itemNum != NO_ITEM && BaddieSlots[i].itemNum != itemNum && BaddieSlots[i].enemy == creature->enemy)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2021-04-18 07:20:27 +02:00
|
|
|
BaddieSlots[i].enemy = NULL;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-04-18 07:20:27 +02:00
|
|
|
}
|
|
|
|
creature->enemy = NULL;
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_AIM:
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->maximumTurn = 0;
|
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint1 = info.angle;
|
|
|
|
joint2 = info.xAngle;
|
|
|
|
}
|
|
|
|
ClampRotation(&item->pos, info.angle, ANGLE(7));
|
2020-05-28 01:23:47 +02:00
|
|
|
if (!Targetable(item, &info)
|
|
|
|
|| item->itemFlags[2] < 1)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_FIRE;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_FIRE:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint1 = info.angle;
|
|
|
|
joint2 = info.xAngle;
|
|
|
|
}
|
|
|
|
ClampRotation(&item->pos, info.angle, ANGLE(7));
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber >= g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_FIRE_MAX ||
|
|
|
|
item->frameNumber == g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_FIRE_MIN)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
item->firedWeapon = true;
|
|
|
|
if (!item->hitStatus)
|
|
|
|
{
|
|
|
|
item->itemFlags[2]--;
|
|
|
|
}
|
|
|
|
if (!ShotLara(item, &info, &baddyGun, joint1, 15));
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_HOLSTER_GUN:
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_HOLSTER_GUN)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_EMPTY;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_DRAW_GUN:
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_DRAW_GUN)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_GUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_HOLSTER_SWORD:
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_HOLSTER_SWORD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_EMPTY;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_DRAW_SWORD:
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber != g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_DRAW_SWORD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (item->objectNumber == ID_BADDY1)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_SWORD_SIMPLE;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->swapMeshFlags = SWAPMESHFLAGS_BADDY_SWORD_NINJA;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_UNKNOWN_8:
|
2019-12-05 17:35:57 +01:00
|
|
|
currentCreature->maximumTurn = 0;
|
|
|
|
ClampRotation(&item->pos, info.angle, ANGLE(11));
|
|
|
|
if (laraInfo.distance < SQUARE(682) ||
|
|
|
|
item != Lara.target)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_UNKNOWN_9;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_BLIND:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (!WeaponEnemyTimer)
|
|
|
|
{
|
|
|
|
if ((GetRandomControl() & 0x7F) == 0)
|
|
|
|
{
|
2020-05-28 01:23:47 +02:00
|
|
|
item->goalAnimState = STATE_BADDY_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_SOMERSAULT:
|
|
|
|
if (item->animNumber == Objects[objectNumber].animIndex + ANIMATION_BADDY_SOMERSAULT_END)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
ClampRotation(&item->pos, info.angle, ANGLE(7));
|
|
|
|
break;
|
|
|
|
}
|
2020-07-21 09:56:47 +02:00
|
|
|
if (item->frameNumber != g_Level.Anims[item->animNumber].frameBase + FRAME_BADDY_SOMERSAULT_START_TAKE_OFF)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
currentCreature->LOT.isJumping = true;
|
|
|
|
break;
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
case STATE_BADDY_JUMP_FORWARD_1_BLOCK:
|
|
|
|
case STATE_BADDY_JUMP_FORWARD_2_BLOCKS:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (item->itemFlags[0] >= someFlag3)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->animNumber != Objects[objectNumber].animIndex + ANIMATION_BADDY_STAND_TO_JUMP_FORWARD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
item->itemFlags[0] += 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CreatureTilt(item, tilt);
|
|
|
|
CreatureJoint(item, 0, joint1);
|
|
|
|
CreatureJoint(item, 1, joint2);
|
|
|
|
CreatureJoint(item, 2, joint3);
|
|
|
|
|
2020-05-28 01:23:47 +02:00
|
|
|
if (item->currentAnimState >= STATE_BADDY_JUMP_FORWARD_2_BLOCKS ||
|
|
|
|
item->currentAnimState == STATE_BADDY_JUMP_FORWARD_1_BLOCK ||
|
|
|
|
item->currentAnimState == STATE_BADDY_MONKEY_FORWARD ||
|
|
|
|
item->currentAnimState == STATE_BADDY_DEATH ||
|
|
|
|
item->currentAnimState == STATE_BADDY_SOMERSAULT ||
|
|
|
|
item->currentAnimState == STATE_BADDY_BLIND)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
CreatureAnimation(itemNum, angle, 0);
|
|
|
|
}
|
|
|
|
else if (WeaponEnemyTimer <= 100)
|
|
|
|
{
|
|
|
|
int vault = CreatureVault(itemNum, angle, 2, 260);
|
|
|
|
|
|
|
|
switch (vault)
|
|
|
|
{
|
|
|
|
case 2:
|
|
|
|
creature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_CLIMB_2_CLICKS;
|
|
|
|
item->currentAnimState = STATE_BADDY_CLIMB_2_CLICKS;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
creature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_CLIMB_3_CLICKS;
|
|
|
|
item->currentAnimState = STATE_BADDY_CLIMB_3_CLICKS;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
creature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_CLIMB_4_CLICKS;
|
|
|
|
item->currentAnimState = STATE_BADDY_CLIMB_4_CLICKS;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case -3:
|
|
|
|
creature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_JUMP_OFF_3_CLICKS;
|
|
|
|
item->currentAnimState = STATE_BADDY_JUMP_OFF_3_CLICKS;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case -4:
|
|
|
|
creature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_JUMP_OFF_4_CLICKS;
|
|
|
|
item->currentAnimState = STATE_BADDY_JUMP_OFF_4_CLICKS;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
2020-05-28 01:23:47 +02:00
|
|
|
item->animNumber = Objects[objectNumber].animIndex + ANIMATION_BADDY_BLIND;
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase + (GetRandomControl() & 7);
|
2020-05-28 01:23:47 +02:00
|
|
|
item->currentAnimState = STATE_BADDY_BLIND;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2018-09-12 20:37:37 +02:00
|
|
|
}
|