Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

creature: perform safer conversion of hybrids #1517

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- fixed a potential softlock when killing the Torso boss in Great Pyramid (#1236)
- fixed Bacon Lara re-spawning after saving and loading (#1500, regression from 0.7)
- fixed config JSON not sanitizing some numeric values (#1515)
- fixed potential crashes in custom levels if hybrid creature objects are not present in the level (#1444)
- changed `/tp` console command to look for the closest place to teleport to when targeting items (#1484)
- changed the door cheat to also target drawbridges
- improved appearance of textures around edges when bilinear filter is off (#1483)
Expand Down
44 changes: 36 additions & 8 deletions src/game/creature.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
#include "global/vars.h"
#include "math/math.h"

#include <libtrx/log.h>

#include <stddef.h>

#define MAX_CREATURE_DISTANCE (WALL_L * 30)

static bool Creature_SwitchToWater(
int16_t item_num, int32_t *wh, const HYBRID_INFO *info);
int16_t item_num, const int32_t *wh, const HYBRID_INFO *info);
static bool Creature_SwitchToLand(
int16_t item_num, int32_t *wh, const HYBRID_INFO *info);
int16_t item_num, const int32_t *wh, const HYBRID_INFO *info);
static bool Creature_TestSwitchOrKill(
int16_t item_num, GAME_OBJECT_ID target_id);

void Creature_Initialise(int16_t item_num)
{
Expand Down Expand Up @@ -709,11 +713,11 @@ bool Creature_ShootAtLara(
}

bool Creature_EnsureHabitat(
int16_t item_num, int32_t *wh, const HYBRID_INFO *info)
const int16_t item_num, int32_t *const wh, const HYBRID_INFO *const info)
{
// Test the environment for a hybrid creature. Record the water height and
// return whether or not a type conversion has taken place.
ITEM_INFO *item = &g_Items[item_num];
const ITEM_INFO *const item = &g_Items[item_num];
*wh = Room_GetWaterHeight(
item->pos.x, item->pos.y, item->pos.z, item->room_num);

Expand All @@ -729,13 +733,14 @@ bool Creature_IsBoss(const int16_t item_num)
}

static bool Creature_SwitchToWater(
int16_t item_num, int32_t *wh, const HYBRID_INFO *info)
const int16_t item_num, const int32_t *const wh,
const HYBRID_INFO *const info)
{
if (*wh == NO_HEIGHT) {
return false;
}

ITEM_INFO *item = &g_Items[item_num];
ITEM_INFO *const item = &g_Items[item_num];

if (item->hit_points <= 0) {
// Dead land creatures should remain in their pose permanently.
Expand All @@ -744,6 +749,10 @@ static bool Creature_SwitchToWater(

// The land creature is alive and the room has been flooded. Switch to the
// water creature.
if (!Creature_TestSwitchOrKill(item_num, info->water.id)) {
return false;
}

item->object_id = info->water.id;
Item_SwitchToAnim(item, info->water.active_anim, 0);
item->current_anim_state = g_Anims[item->anim_num].current_anim_state;
Expand All @@ -754,13 +763,18 @@ static bool Creature_SwitchToWater(
}

static bool Creature_SwitchToLand(
int16_t item_num, int32_t *wh, const HYBRID_INFO *info)
const int16_t item_num, const int32_t *const wh,
const HYBRID_INFO *const info)
{
if (*wh != NO_HEIGHT) {
return false;
}

ITEM_INFO *item = &g_Items[item_num];
if (!Creature_TestSwitchOrKill(item_num, info->land.id)) {
return false;
}

ITEM_INFO *const item = &g_Items[item_num];

// Switch to the land creature regardless of death state.
item->object_id = info->land.id;
Expand Down Expand Up @@ -790,3 +804,17 @@ static bool Creature_SwitchToLand(

return true;
}

static bool Creature_TestSwitchOrKill(
const int16_t item_num, const GAME_OBJECT_ID target_id)
{
if (g_Objects[target_id].loaded) {
return true;
}

LOG_WARNING(
"Object %d is not loaded; item %d cannot be converted.", target_id,
item_num);
Item_Kill(item_num);
return false;
}
10 changes: 10 additions & 0 deletions src/game/objects/creatures/skate_kid.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "global/const.h"
#include "global/vars.h"

#include <libtrx/log.h>
#include <libtrx/utils.h>

#define SKATE_KID_STOP_SHOT_DAMAGE 50
Expand Down Expand Up @@ -57,6 +58,12 @@ void SkateKid_Setup(OBJECT_INFO *obj)
obj->save_anim = 1;
obj->save_flags = 1;
g_AnimBones[obj->bone_index] |= BEB_ROT_Y;

if (!g_Objects[O_SKATEBOARD].loaded) {
LOG_WARNING(
"Skateboard object (%d) is not loaded and so will not be drawn.",
O_SKATEBOARD);
}
}

void SkateKid_Initialise(int16_t item_num)
Expand Down Expand Up @@ -168,6 +175,9 @@ void SkateKid_Control(int16_t item_num)
void SkateKid_Draw(ITEM_INFO *item)
{
Object_DrawAnimatingItem(item);
if (!g_Objects[O_SKATEBOARD].loaded) {
return;
}

int16_t relative_anim =
item->anim_num - g_Objects[item->object_id].anim_index;
Expand Down