mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
creature: move Creature_Animate to trx
This commit is contained in:
parent
7718406bbe
commit
5afcc59d04
9 changed files with 274 additions and 511 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "game/creature.h"
|
||||
#include "game/lara/common.h"
|
||||
#include "game/objects/vars.h"
|
||||
#include "game/random.h"
|
||||
#include "game/rooms.h"
|
||||
#include "log.h"
|
||||
|
@ -16,6 +17,7 @@
|
|||
#elif TR_VERSION >= 2
|
||||
#define M_HEAD_ARC 0x3000 // = 12288
|
||||
#endif
|
||||
#define M_MAX_X_ROT (20 * DEG_1) // = 3640
|
||||
|
||||
static ITEM *M_ChooseEnemy(const ITEM *item);
|
||||
static bool M_SwitchToWater(
|
||||
|
@ -522,6 +524,267 @@ void Creature_Collision(
|
|||
false);
|
||||
}
|
||||
|
||||
bool Creature_Animate(
|
||||
const int16_t item_num, const int16_t angle, const int16_t tilt)
|
||||
{
|
||||
ITEM *const item = Item_Get(item_num);
|
||||
const CREATURE *const creature = item->data;
|
||||
const OBJECT *const obj = Object_Get(item->object_id);
|
||||
if (creature == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const LOT_INFO *const lot = &creature->lot;
|
||||
const XYZ_32 old = item->pos;
|
||||
|
||||
const int16_t *const zone = Box_GetLotZone(lot);
|
||||
|
||||
if (TR_VERSION >= 2 && !Object_IsType(item->object_id, g_WaterObjects)) {
|
||||
int16_t room_num = item->room_num;
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (room_num != item->room_num) {
|
||||
Item_NewRoom(item_num, room_num);
|
||||
}
|
||||
}
|
||||
|
||||
Item_Animate(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
Creature_Die(item_num, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
|
||||
int32_t y = item->pos.y + bounds->min.y;
|
||||
|
||||
int16_t room_num = item->room_num;
|
||||
Room_GetSector(old.x, y, old.z, &room_num);
|
||||
const SECTOR *sector =
|
||||
Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
int32_t height = Box_GetBox(sector->box)->height;
|
||||
int16_t next_box = lot->node[sector->box].exit_box;
|
||||
int32_t next_height =
|
||||
next_box != NO_BOX ? Box_GetBox(next_box)->height : height;
|
||||
|
||||
const int32_t box_height = Box_GetBox(item->box_num)->height;
|
||||
if (sector->box == NO_BOX || zone[item->box_num] != zone[sector->box]
|
||||
|| box_height - height > lot->step || box_height - height < lot->drop) {
|
||||
const int32_t pos_x = item->pos.x >> WALL_SHIFT;
|
||||
const int32_t shift_x = old.x >> WALL_SHIFT;
|
||||
const int32_t shift_z = old.z >> WALL_SHIFT;
|
||||
|
||||
if (pos_x < shift_x) {
|
||||
item->pos.x = old.x & (~(WALL_L - 1));
|
||||
} else if (pos_x > shift_x) {
|
||||
item->pos.x = old.x | (WALL_L - 1);
|
||||
}
|
||||
|
||||
if (pos_x < shift_z) {
|
||||
item->pos.z = old.z & (~(WALL_L - 1));
|
||||
} else if (pos_x > shift_z) {
|
||||
item->pos.z = old.z | (WALL_L - 1);
|
||||
}
|
||||
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
height = Box_GetBox(sector->box)->height;
|
||||
next_box = lot->node[sector->box].exit_box;
|
||||
next_height =
|
||||
next_box != NO_BOX ? Box_GetBox(next_box)->height : height;
|
||||
}
|
||||
|
||||
const int32_t x = item->pos.x;
|
||||
const int32_t z = item->pos.z;
|
||||
const int32_t pos_x = x & (WALL_L - 1);
|
||||
const int32_t pos_z = z & (WALL_L - 1);
|
||||
int32_t shift_x = 0;
|
||||
int32_t shift_z = 0;
|
||||
const int32_t radius = obj->radius;
|
||||
|
||||
if (pos_z < radius) {
|
||||
if (Box_BadFloor(
|
||||
x, y, z - radius, height, next_height, room_num, lot)) {
|
||||
shift_z = radius - pos_z;
|
||||
}
|
||||
|
||||
if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x - radius, y, z - radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_135 && item->rot.y < DEG_45) {
|
||||
shift_z = radius - pos_z;
|
||||
} else {
|
||||
shift_x = radius - pos_x;
|
||||
}
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x + radius, y, z - radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_45 && item->rot.y < DEG_135) {
|
||||
shift_z = radius - pos_z;
|
||||
} else {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pos_z > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x, y, z + radius, height, next_height, room_num, lot)) {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
|
||||
if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x - radius, y, z + radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_45 && item->rot.y < DEG_135) {
|
||||
shift_x = radius - pos_x;
|
||||
} else {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x + radius, y, z + radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_135 && item->rot.y < DEG_45) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
}
|
||||
}
|
||||
|
||||
item->pos.x += shift_x;
|
||||
item->pos.z += shift_z;
|
||||
|
||||
if (shift_x || shift_z) {
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
item->rot.y += angle;
|
||||
Creature_Tilt(item, tilt * 2);
|
||||
}
|
||||
|
||||
if (Creature_CheckBaddieOverlap(item_num)) {
|
||||
item->pos = old;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lot->fly) {
|
||||
int32_t dy = creature->target.y - item->pos.y;
|
||||
CLAMP(dy, -lot->fly, lot->fly);
|
||||
|
||||
height = Room_GetHeight(sector, item->pos.x, y, item->pos.z);
|
||||
if (item->pos.y + dy <= height) {
|
||||
const int32_t ceiling =
|
||||
Room_GetCeiling(sector, item->pos.x, y, item->pos.z);
|
||||
int32_t min_y = bounds->min.y;
|
||||
switch (item->object_id) {
|
||||
#if TR_VERSION == 1
|
||||
case O_ALLIGATOR:
|
||||
min_y = 0;
|
||||
break;
|
||||
#elif TR_VERSION == 2
|
||||
case O_SHARK:
|
||||
min_y = 128;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (item->pos.y + min_y + dy < ceiling) {
|
||||
if (item->pos.y + min_y < ceiling) {
|
||||
item->pos.x = old.x;
|
||||
item->pos.z = old.z;
|
||||
dy = lot->fly;
|
||||
} else {
|
||||
dy = 0;
|
||||
}
|
||||
}
|
||||
} else if (item->pos.y <= height) {
|
||||
item->pos.y = height;
|
||||
dy = 0;
|
||||
} else {
|
||||
item->pos.x = old.x;
|
||||
item->pos.z = old.z;
|
||||
dy = -lot->fly;
|
||||
}
|
||||
|
||||
item->pos.y += dy;
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
item->floor = Room_GetHeight(sector, item->pos.x, y, item->pos.z);
|
||||
|
||||
int16_t angle = item->speed ? Math_Atan(item->speed, -dy) : 0;
|
||||
if (TR_VERSION >= 2) {
|
||||
CLAMP(angle, -M_MAX_X_ROT, M_MAX_X_ROT);
|
||||
}
|
||||
|
||||
if (angle < item->rot.x - DEG_1) {
|
||||
item->rot.x -= DEG_1;
|
||||
} else if (angle > item->rot.x + DEG_1) {
|
||||
item->rot.x += DEG_1;
|
||||
} else {
|
||||
item->rot.x = angle;
|
||||
}
|
||||
} else {
|
||||
const SECTOR *const sector =
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
item->floor =
|
||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
if (item->pos.y > item->floor) {
|
||||
item->pos.y = item->floor;
|
||||
} else if (item->floor - item->pos.y > STEP_L / 4) {
|
||||
item->pos.y += STEP_L / 4;
|
||||
} else if (item->pos.y < item->floor) {
|
||||
item->pos.y = item->floor;
|
||||
}
|
||||
item->rot.x = 0;
|
||||
}
|
||||
|
||||
if (TR_VERSION >= 2 && !Object_IsType(item->object_id, g_WaterObjects)) {
|
||||
Room_GetSector(
|
||||
item->pos.x, item->pos.y - (STEP_L * 2), item->pos.z, &room_num);
|
||||
if (Room_Get(room_num)->flags & RF_UNDERWATER) {
|
||||
item->hit_points = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->room_num != room_num) {
|
||||
Item_NewRoom(item_num, room_num);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int16_t Creature_Effect(
|
||||
const ITEM *const item, const BITE *const bite,
|
||||
int16_t (*const spawn)(
|
||||
|
|
|
@ -17,9 +17,11 @@ void Creature_Neck(ITEM *item, int16_t required);
|
|||
|
||||
bool Creature_CheckBaddieOverlap(int16_t item_num);
|
||||
void Creature_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll);
|
||||
bool Creature_Animate(int16_t item_num, int16_t angle, int16_t tilt);
|
||||
|
||||
extern void Creature_Die(int16_t item_num, bool explode);
|
||||
|
||||
extern bool Creature_IsHostile(const ITEM *item);
|
||||
extern bool Creature_Animate(int16_t item_num, int16_t angle, int16_t tilt);
|
||||
|
||||
int16_t Creature_Effect(
|
||||
const ITEM *item, const BITE *bite,
|
||||
|
|
|
@ -53,3 +53,4 @@ void Item_PlayAnimSFX(const ITEM *item, const ANIM_COMMAND_EFFECT_DATA *data);
|
|||
|
||||
bool Item_TestBoundsCollide(
|
||||
const ITEM *src_item, const ITEM *dst_item, int32_t radius);
|
||||
extern const BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *item);
|
||||
|
|
|
@ -18,264 +18,14 @@
|
|||
#include <libtrx/game/math.h>
|
||||
#include <libtrx/log.h>
|
||||
|
||||
bool Creature_Animate(int16_t item_num, int16_t angle, int16_t tilt)
|
||||
void Creature_Die(const int16_t item_num, const bool explode)
|
||||
{
|
||||
ITEM *const item = Item_Get(item_num);
|
||||
CREATURE *creature = item->data;
|
||||
if (!creature) {
|
||||
return false;
|
||||
}
|
||||
LOT_INFO *lot = &creature->lot;
|
||||
|
||||
XYZ_32 old = {
|
||||
.x = item->pos.x,
|
||||
.y = item->pos.y,
|
||||
.z = item->pos.z,
|
||||
};
|
||||
|
||||
const int32_t box_height = Box_GetBox(item->box_num)->height;
|
||||
|
||||
const int16_t *const zone = Box_GetLotZone(lot);
|
||||
|
||||
Item_Animate(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
item->collidable = 0;
|
||||
item->hit_points = DONT_TARGET;
|
||||
LOT_DisableBaddieAI(item_num);
|
||||
Item_RemoveActive(item_num);
|
||||
Carrier_TestItemDrops(item_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
|
||||
int32_t y = item->pos.y + bounds->min.y;
|
||||
|
||||
int16_t room_num = item->room_num;
|
||||
const SECTOR *sector =
|
||||
Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
int32_t height = Box_GetBox(sector->box)->height;
|
||||
int16_t next_box = lot->node[sector->box].exit_box;
|
||||
int32_t next_height;
|
||||
if (next_box != NO_BOX) {
|
||||
next_height = Box_GetBox(next_box)->height;
|
||||
} else {
|
||||
next_height = height;
|
||||
}
|
||||
|
||||
int32_t pos_x;
|
||||
int32_t pos_z;
|
||||
int32_t shift_x;
|
||||
int32_t shift_z;
|
||||
if (sector->box == NO_BOX || zone[item->box_num] != zone[sector->box]
|
||||
|| box_height - height > lot->step || box_height - height < lot->drop) {
|
||||
pos_x = item->pos.x >> WALL_SHIFT;
|
||||
|
||||
shift_x = old.x >> WALL_SHIFT;
|
||||
shift_z = old.z >> WALL_SHIFT;
|
||||
|
||||
if (pos_x < shift_x) {
|
||||
item->pos.x = old.x & (~(WALL_L - 1));
|
||||
} else if (pos_x > shift_x) {
|
||||
item->pos.x = old.x | (WALL_L - 1);
|
||||
}
|
||||
|
||||
if (pos_x < shift_z) {
|
||||
item->pos.z = old.z & (~(WALL_L - 1));
|
||||
} else if (pos_x > shift_z) {
|
||||
item->pos.z = old.z | (WALL_L - 1);
|
||||
}
|
||||
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
height = Box_GetBox(sector->box)->height;
|
||||
next_box = lot->node[sector->box].exit_box;
|
||||
if (next_box != NO_BOX) {
|
||||
next_height = Box_GetBox(next_box)->height;
|
||||
} else {
|
||||
next_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
|
||||
pos_x = x & (WALL_L - 1);
|
||||
pos_z = z & (WALL_L - 1);
|
||||
shift_x = 0;
|
||||
shift_z = 0;
|
||||
|
||||
const int32_t radius = Object_Get(item->object_id)->radius;
|
||||
|
||||
if (pos_z < radius) {
|
||||
if (Box_BadFloor(
|
||||
x, y, z - radius, height, next_height, room_num, lot)) {
|
||||
shift_z = radius - pos_z;
|
||||
}
|
||||
|
||||
if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x - radius, y, z - radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_135 && item->rot.y < DEG_45) {
|
||||
shift_z = radius - pos_z;
|
||||
} else {
|
||||
shift_x = radius - pos_x;
|
||||
}
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x + radius, y, z - radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_45 && item->rot.y < DEG_135) {
|
||||
shift_z = radius - pos_z;
|
||||
} else {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pos_z > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x, y, z + radius, height, next_height, room_num, lot)) {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
|
||||
if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x - radius, y, z + radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_45 && item->rot.y < DEG_135) {
|
||||
shift_x = radius - pos_x;
|
||||
} else {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x + radius, y, z + radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_135 && item->rot.y < DEG_45) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
}
|
||||
}
|
||||
|
||||
item->pos.x += shift_x;
|
||||
item->pos.z += shift_z;
|
||||
|
||||
if (shift_x || shift_z) {
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
|
||||
item->rot.y += angle;
|
||||
Creature_Tilt(item, tilt * 2);
|
||||
}
|
||||
|
||||
if (Creature_CheckBaddieOverlap(item_num)) {
|
||||
item->pos.x = old.x;
|
||||
item->pos.y = old.y;
|
||||
item->pos.z = old.z;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lot->fly) {
|
||||
int32_t dy = creature->target.y - item->pos.y;
|
||||
if (dy > lot->fly) {
|
||||
dy = lot->fly;
|
||||
} else if (dy < -lot->fly) {
|
||||
dy = -lot->fly;
|
||||
}
|
||||
|
||||
height = Room_GetHeight(sector, item->pos.x, y, item->pos.z);
|
||||
if (item->pos.y + dy > height) {
|
||||
if (item->pos.y > height) {
|
||||
item->pos.x = old.x;
|
||||
item->pos.z = old.z;
|
||||
dy = -lot->fly;
|
||||
} else {
|
||||
dy = 0;
|
||||
item->pos.y = height;
|
||||
}
|
||||
} else {
|
||||
int32_t ceiling =
|
||||
Room_GetCeiling(sector, item->pos.x, y, item->pos.z);
|
||||
|
||||
int32_t min_y = item->object_id == O_ALLIGATOR ? 0 : bounds->min.y;
|
||||
if (item->pos.y + min_y + dy < ceiling) {
|
||||
if (item->pos.y + min_y < ceiling) {
|
||||
item->pos.x = old.x;
|
||||
item->pos.z = old.z;
|
||||
dy = lot->fly;
|
||||
} else {
|
||||
dy = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item->pos.y += dy;
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
item->floor = Room_GetHeight(sector, item->pos.x, y, item->pos.z);
|
||||
|
||||
angle = item->speed ? Math_Atan(item->speed, -dy) : 0;
|
||||
if (angle < item->rot.x - DEG_1) {
|
||||
item->rot.x -= DEG_1;
|
||||
} else if (angle > item->rot.x + DEG_1) {
|
||||
item->rot.x += DEG_1;
|
||||
} else {
|
||||
item->rot.x = angle;
|
||||
}
|
||||
} else {
|
||||
sector =
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
item->floor =
|
||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
if (item->pos.y > item->floor) {
|
||||
item->pos.y = item->floor;
|
||||
} else if (item->floor - item->pos.y > STEP_L / 4) {
|
||||
item->pos.y += STEP_L / 4;
|
||||
} else if (item->pos.y < item->floor) {
|
||||
item->pos.y = item->floor;
|
||||
}
|
||||
|
||||
item->rot.x = 0;
|
||||
}
|
||||
|
||||
if (item->room_num != room_num) {
|
||||
Item_NewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
return true;
|
||||
item->collidable = 0;
|
||||
item->hit_points = DONT_TARGET;
|
||||
LOT_DisableBaddieAI(item_num);
|
||||
Item_RemoveActive(item_num);
|
||||
Carrier_TestItemDrops(item_num);
|
||||
}
|
||||
|
||||
bool Creature_CanTargetEnemy(ITEM *item, AI_INFO *info)
|
||||
|
|
|
@ -21,7 +21,6 @@ int32_t Item_GetDistance(const ITEM *item, const XYZ_32 *target);
|
|||
|
||||
bool Item_IsTriggerActive(ITEM *item);
|
||||
|
||||
const BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *item);
|
||||
int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate);
|
||||
|
||||
void Item_TakeDamage(ITEM *item, int16_t damage, bool hit_status);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <libtrx/game/math.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
||||
#define MAX_X_ROT (20 * DEG_1) // = 3640
|
||||
#define FLOAT_SPEED 32
|
||||
#define TARGET_TOLERANCE 0x400000
|
||||
|
||||
|
@ -80,255 +79,6 @@ void Creature_Die(const int16_t item_num, const bool explode)
|
|||
}
|
||||
}
|
||||
|
||||
bool Creature_Animate(
|
||||
const int16_t item_num, const int16_t angle, const int16_t tilt)
|
||||
{
|
||||
ITEM *const item = Item_Get(item_num);
|
||||
const CREATURE *const creature = item->data;
|
||||
const OBJECT *const obj = Object_Get(item->object_id);
|
||||
if (creature == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const LOT_INFO *const lot = &creature->lot;
|
||||
const XYZ_32 old = item->pos;
|
||||
|
||||
const int16_t *const zone = Box_GetLotZone(lot);
|
||||
|
||||
if (!Object_IsType(item->object_id, g_WaterObjects)) {
|
||||
int16_t room_num = item->room_num;
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (room_num != item->room_num) {
|
||||
Item_NewRoom(item_num, room_num);
|
||||
}
|
||||
}
|
||||
|
||||
Item_Animate(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
Creature_Die(item_num, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
|
||||
int32_t y = item->pos.y + bounds->min.y;
|
||||
|
||||
int16_t room_num = item->room_num;
|
||||
Room_GetSector(old.x, y, old.z, &room_num);
|
||||
const SECTOR *sector =
|
||||
Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
int32_t height = Box_GetBox(sector->box)->height;
|
||||
int16_t next_box = lot->node[sector->box].exit_box;
|
||||
int32_t next_height =
|
||||
next_box != NO_BOX ? Box_GetBox(next_box)->height : height;
|
||||
|
||||
const int32_t box_height = Box_GetBox(item->box_num)->height;
|
||||
if (sector->box == NO_BOX || zone[item->box_num] != zone[sector->box]
|
||||
|| box_height - height > lot->step || box_height - height < lot->drop) {
|
||||
const int32_t pos_x = item->pos.x >> WALL_SHIFT;
|
||||
const int32_t shift_x = old.x >> WALL_SHIFT;
|
||||
const int32_t shift_z = old.z >> WALL_SHIFT;
|
||||
|
||||
if (pos_x < shift_x) {
|
||||
item->pos.x = old.x & (~(WALL_L - 1));
|
||||
} else if (pos_x > shift_x) {
|
||||
item->pos.x = old.x | (WALL_L - 1);
|
||||
}
|
||||
|
||||
if (pos_x < shift_z) {
|
||||
item->pos.z = old.z & (~(WALL_L - 1));
|
||||
} else if (pos_x > shift_z) {
|
||||
item->pos.z = old.z | (WALL_L - 1);
|
||||
}
|
||||
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
height = Box_GetBox(sector->box)->height;
|
||||
next_box = lot->node[sector->box].exit_box;
|
||||
next_height =
|
||||
next_box != NO_BOX ? Box_GetBox(next_box)->height : height;
|
||||
}
|
||||
|
||||
const int32_t x = item->pos.x;
|
||||
const int32_t z = item->pos.z;
|
||||
const int32_t pos_x = x & (WALL_L - 1);
|
||||
const int32_t pos_z = z & (WALL_L - 1);
|
||||
int32_t shift_x = 0;
|
||||
int32_t shift_z = 0;
|
||||
const int32_t radius = obj->radius;
|
||||
|
||||
if (pos_z < radius) {
|
||||
if (Box_BadFloor(
|
||||
x, y, z - radius, height, next_height, room_num, lot)) {
|
||||
shift_z = radius - pos_z;
|
||||
}
|
||||
|
||||
if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x - radius, y, z - radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_135 && item->rot.y < DEG_45) {
|
||||
shift_z = radius - pos_z;
|
||||
} else {
|
||||
shift_x = radius - pos_x;
|
||||
}
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x + radius, y, z - radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_45 && item->rot.y < DEG_135) {
|
||||
shift_z = radius - pos_z;
|
||||
} else {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pos_z > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x, y, z + radius, height, next_height, room_num, lot)) {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
|
||||
if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x - radius, y, z + radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_45 && item->rot.y < DEG_135) {
|
||||
shift_x = radius - pos_x;
|
||||
} else {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else if (
|
||||
!shift_z
|
||||
&& Box_BadFloor(
|
||||
x + radius, y, z + radius, height, next_height, room_num,
|
||||
lot)) {
|
||||
if (item->rot.y > -DEG_135 && item->rot.y < DEG_45) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
} else {
|
||||
shift_z = WALL_L - radius - pos_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pos_x < radius) {
|
||||
if (Box_BadFloor(
|
||||
x - radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = radius - pos_x;
|
||||
}
|
||||
} else if (pos_x > WALL_L - radius) {
|
||||
if (Box_BadFloor(
|
||||
x + radius, y, z, height, next_height, room_num, lot)) {
|
||||
shift_x = WALL_L - radius - pos_x;
|
||||
}
|
||||
}
|
||||
|
||||
item->pos.x += shift_x;
|
||||
item->pos.z += shift_z;
|
||||
|
||||
if (shift_x || shift_z) {
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
item->rot.y += angle;
|
||||
if (tilt != 0) {
|
||||
Creature_Tilt(item, tilt * 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (Creature_CheckBaddieOverlap(item_num)) {
|
||||
item->pos = old;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lot->fly) {
|
||||
int32_t dy = creature->target.y - item->pos.y;
|
||||
CLAMP(dy, -lot->fly, lot->fly);
|
||||
|
||||
height = Room_GetHeight(sector, item->pos.x, y, item->pos.z);
|
||||
if (item->pos.y + dy <= height) {
|
||||
const int32_t ceiling =
|
||||
Room_GetCeiling(sector, item->pos.x, y, item->pos.z);
|
||||
const int32_t min_y =
|
||||
item->object_id == O_SHARK ? 128 : bounds->min.y;
|
||||
if (item->pos.y + min_y + dy < ceiling) {
|
||||
if (item->pos.y + min_y < ceiling) {
|
||||
item->pos.x = old.x;
|
||||
item->pos.z = old.z;
|
||||
dy = lot->fly;
|
||||
} else {
|
||||
dy = 0;
|
||||
}
|
||||
}
|
||||
} else if (item->pos.y <= height) {
|
||||
item->pos.y = height;
|
||||
dy = 0;
|
||||
} else {
|
||||
item->pos.x = old.x;
|
||||
item->pos.z = old.z;
|
||||
dy = -lot->fly;
|
||||
}
|
||||
|
||||
item->pos.y += dy;
|
||||
sector = Room_GetSector(item->pos.x, y, item->pos.z, &room_num);
|
||||
item->floor = Room_GetHeight(sector, item->pos.x, y, item->pos.z);
|
||||
|
||||
int16_t angle = item->speed != 0 ? Math_Atan(item->speed, -dy) : 0;
|
||||
CLAMP(angle, -MAX_X_ROT, MAX_X_ROT);
|
||||
|
||||
if (angle < item->rot.x - DEG_1) {
|
||||
item->rot.x -= DEG_1;
|
||||
} else if (angle > item->rot.x + DEG_1) {
|
||||
item->rot.x += DEG_1;
|
||||
} else {
|
||||
item->rot.x = angle;
|
||||
}
|
||||
} else {
|
||||
const SECTOR *const sector =
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
item->floor =
|
||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
if (item->pos.y > item->floor) {
|
||||
item->pos.y = item->floor;
|
||||
} else if (item->floor - item->pos.y > STEP_L / 4) {
|
||||
item->pos.y += STEP_L / 4;
|
||||
} else if (item->pos.y < item->floor) {
|
||||
item->pos.y = item->floor;
|
||||
}
|
||||
item->rot.x = 0;
|
||||
}
|
||||
|
||||
if (!Object_IsType(item->object_id, g_WaterObjects)) {
|
||||
Room_GetSector(
|
||||
item->pos.x, item->pos.y - (STEP_L * 2), item->pos.z, &room_num);
|
||||
if (Room_Get(room_num)->flags & RF_UNDERWATER) {
|
||||
item->hit_points = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->room_num != room_num) {
|
||||
Item_NewRoom(item_num, room_num);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Creature_Float(const int16_t item_num)
|
||||
{
|
||||
ITEM *const item = Item_Get(item_num);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <libtrx/game/creature.h>
|
||||
|
||||
void Creature_Die(int16_t item_num, bool explode);
|
||||
void Creature_Float(int16_t item_num);
|
||||
void Creature_Underwater(ITEM *item, int32_t depth);
|
||||
int32_t Creature_Vault(
|
||||
|
|
|
@ -359,7 +359,7 @@ int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frames[], int32_t *rate)
|
|||
return final * 10;
|
||||
}
|
||||
|
||||
BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *const item)
|
||||
const BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *const item)
|
||||
{
|
||||
int32_t rate;
|
||||
ANIM_FRAME *frames[2];
|
||||
|
|
|
@ -14,7 +14,6 @@ void Item_AlignPosition(
|
|||
const XYZ_32 *vec, const ITEM *src_item, ITEM *dst_item);
|
||||
int32_t Item_IsTriggerActive(ITEM *item);
|
||||
int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate);
|
||||
BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *item);
|
||||
bool Item_IsNearItem(const ITEM *item, const XYZ_32 *pos, int32_t distance);
|
||||
|
||||
bool Item_IsSmashable(const ITEM *item);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue