creature: move Creature_Animate to trx

This commit is contained in:
Marcin Kurczewski 2025-04-08 22:31:12 +02:00
parent 7718406bbe
commit 5afcc59d04
9 changed files with 274 additions and 511 deletions

View file

@ -1,5 +1,6 @@
#include "game/creature.h" #include "game/creature.h"
#include "game/lara/common.h" #include "game/lara/common.h"
#include "game/objects/vars.h"
#include "game/random.h" #include "game/random.h"
#include "game/rooms.h" #include "game/rooms.h"
#include "log.h" #include "log.h"
@ -16,6 +17,7 @@
#elif TR_VERSION >= 2 #elif TR_VERSION >= 2
#define M_HEAD_ARC 0x3000 // = 12288 #define M_HEAD_ARC 0x3000 // = 12288
#endif #endif
#define M_MAX_X_ROT (20 * DEG_1) // = 3640
static ITEM *M_ChooseEnemy(const ITEM *item); static ITEM *M_ChooseEnemy(const ITEM *item);
static bool M_SwitchToWater( static bool M_SwitchToWater(
@ -522,6 +524,267 @@ void Creature_Collision(
false); 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( int16_t Creature_Effect(
const ITEM *const item, const BITE *const bite, const ITEM *const item, const BITE *const bite,
int16_t (*const spawn)( int16_t (*const spawn)(

View file

@ -17,9 +17,11 @@ void Creature_Neck(ITEM *item, int16_t required);
bool Creature_CheckBaddieOverlap(int16_t item_num); bool Creature_CheckBaddieOverlap(int16_t item_num);
void Creature_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); 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_IsHostile(const ITEM *item);
extern bool Creature_Animate(int16_t item_num, int16_t angle, int16_t tilt);
int16_t Creature_Effect( int16_t Creature_Effect(
const ITEM *item, const BITE *bite, const ITEM *item, const BITE *bite,

View file

@ -53,3 +53,4 @@ void Item_PlayAnimSFX(const ITEM *item, const ANIM_COMMAND_EFFECT_DATA *data);
bool Item_TestBoundsCollide( bool Item_TestBoundsCollide(
const ITEM *src_item, const ITEM *dst_item, int32_t radius); const ITEM *src_item, const ITEM *dst_item, int32_t radius);
extern const BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *item);

View file

@ -18,264 +18,14 @@
#include <libtrx/game/math.h> #include <libtrx/game/math.h>
#include <libtrx/log.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); ITEM *const item = Item_Get(item_num);
CREATURE *creature = item->data; item->collidable = 0;
if (!creature) { item->hit_points = DONT_TARGET;
return false; LOT_DisableBaddieAI(item_num);
} Item_RemoveActive(item_num);
LOT_INFO *lot = &creature->lot; Carrier_TestItemDrops(item_num);
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;
} }
bool Creature_CanTargetEnemy(ITEM *item, AI_INFO *info) bool Creature_CanTargetEnemy(ITEM *item, AI_INFO *info)

View file

@ -21,7 +21,6 @@ int32_t Item_GetDistance(const ITEM *item, const XYZ_32 *target);
bool Item_IsTriggerActive(ITEM *item); 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); int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate);
void Item_TakeDamage(ITEM *item, int16_t damage, bool hit_status); void Item_TakeDamage(ITEM *item, int16_t damage, bool hit_status);

View file

@ -21,7 +21,6 @@
#include <libtrx/game/math.h> #include <libtrx/game/math.h>
#include <libtrx/utils.h> #include <libtrx/utils.h>
#define MAX_X_ROT (20 * DEG_1) // = 3640
#define FLOAT_SPEED 32 #define FLOAT_SPEED 32
#define TARGET_TOLERANCE 0x400000 #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) void Creature_Float(const int16_t item_num)
{ {
ITEM *const item = Item_Get(item_num); ITEM *const item = Item_Get(item_num);

View file

@ -4,7 +4,6 @@
#include <libtrx/game/creature.h> #include <libtrx/game/creature.h>
void Creature_Die(int16_t item_num, bool explode);
void Creature_Float(int16_t item_num); void Creature_Float(int16_t item_num);
void Creature_Underwater(ITEM *item, int32_t depth); void Creature_Underwater(ITEM *item, int32_t depth);
int32_t Creature_Vault( int32_t Creature_Vault(

View file

@ -359,7 +359,7 @@ int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frames[], int32_t *rate)
return final * 10; return final * 10;
} }
BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *const item) const BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *const item)
{ {
int32_t rate; int32_t rate;
ANIM_FRAME *frames[2]; ANIM_FRAME *frames[2];

View file

@ -14,7 +14,6 @@ void Item_AlignPosition(
const XYZ_32 *vec, const ITEM *src_item, ITEM *dst_item); const XYZ_32 *vec, const ITEM *src_item, ITEM *dst_item);
int32_t Item_IsTriggerActive(ITEM *item); int32_t Item_IsTriggerActive(ITEM *item);
int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate); 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_IsNearItem(const ITEM *item, const XYZ_32 *pos, int32_t distance);
bool Item_IsSmashable(const ITEM *item); bool Item_IsSmashable(const ITEM *item);