Fixed bugs relating to objects dying in lava (#766)

• Changed the generic object death function to now also check that an object has landed and is over lava before killing it. Previously it would die instantly if it was above lava which resulted in objects randomly dying above lava

• Also changed the same function to kill a non-buoyant and killable object (e.g. goombas) right when it touches water. Previously it would slowly sink to the bottom and then instantly die upon touching the floor underwater which is strange.

• Changed where lava checks are done so they are done in the same place as other object flag checks. This avoids bugs where e.g. objects die when touching the edge of a platform that is over lava, because the ground flags are updated, then the object's floor is updated to be over the lava, and then the lava move flags are updated causing the object to think it is over lava and touching ground at the same time (making it die)

• Fixed the coin flicker define for regular non-bully coins because apparently it just never worked and no-one noticed? Only the coins that come from bullies worked with this define and I guess people only ever tested coins in lava with bullies. I rewrote the coin behavior to be a little closer to the bully one. I think in the future the two types of moving coins could easily be merged into one object, they don't act visibly different at all.

Tested the PR with a lot of goombas being dropped into lava/water and also this stuff is in Mario Builder so I've been testing it there too. Feel free to test more.
This commit is contained in:
arthurtilly
2024-02-10 15:07:31 +13:00
committed by GitHub
parent 1de4b9144b
commit d07e6383f6
5 changed files with 56 additions and 45 deletions

View File

@@ -102,20 +102,33 @@ void bhv_coin_loop(void) {
struct Surface *floor = o->oFloor;
if (floor != NULL) {
if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) {
o->oAction = BOUNCING_COIN_ACT_BOUNCING;
}
if (o->oAction == BOUNCING_COIN_ACT_BOUNCING) {
o->oBounciness = 0;
if (floor->normal.y < 0.9f) {
s16 targetYaw = SURFACE_YAW(floor);
cur_obj_rotate_yaw_toward(targetYaw, 0x400);
}
}
}
switch (o->oAction) {
case BOUNCING_COIN_ACT_FALLING:
if (o->oTimer == 0) {
cur_obj_play_sound_2(SOUND_GENERAL_COIN_SPURT);
}
if (o->oMoveFlags & OBJ_MOVE_LANDED) {
o->oAction = BOUNCING_COIN_ACT_BOUNCING;
}
break;
if (o->oTimer == 0) {
cur_obj_play_sound_2(SOUND_GENERAL_COIN_SPURT);
case BOUNCING_COIN_ACT_BOUNCING:
o->oBounciness = 0;
if (floor->normal.y < 0.9f) {
s16 targetYaw = SURFACE_YAW(floor);
cur_obj_rotate_yaw_toward(targetYaw, 0x400);
}
break;
case OBJ_ACT_LAVA_DEATH:
#ifdef COIN_LAVA_FLICKER
obj_flicker_and_disappear(o, 0);
#else
obj_mark_for_deletion(o);
#endif
break;
}
}
if (o->oVelY < 0) {
@@ -123,16 +136,11 @@ void bhv_coin_loop(void) {
}
if (o->oMoveFlags & OBJ_MOVE_LANDED) {
#ifdef COIN_LAVA_FLICKER
if ((o->oMoveFlags & OBJ_MOVE_ABOVE_DEATH_BARRIER)
|| ((o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA) && cur_obj_wait_then_blink(0, 20))) {
if (o->oMoveFlags & OBJ_MOVE_ABOVE_DEATH_BARRIER) {
obj_mark_for_deletion(o);
} else if (o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA) {
o->oAction = OBJ_ACT_LAVA_DEATH;
}
#else
if (o->oMoveFlags & (OBJ_MOVE_ABOVE_DEATH_BARRIER | OBJ_MOVE_ABOVE_LAVA)) {
obj_mark_for_deletion(o);
}
#endif
}
if (o->oMoveFlags & OBJ_MOVE_BOUNCE) {

View File

@@ -93,9 +93,6 @@ void bhv_moving_yellow_coin_loop(void) {
break;
}
#ifdef COIN_LAVA_FLICKER
if (o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA) moving_coin_flicker();
#endif
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
coin_collected();
o->oInteractStatus = INT_STATUS_NONE;

View File

@@ -18,6 +18,7 @@ enum ObjCollisionFlags {
//! Lots of these are duplicates
void set_yoshi_as_not_dead(void);
s32 obj_flicker_and_disappear(struct Object *obj, s16 lifeSpan);
s32 coin_step(s16 *collisionFlagsPtr);
void moving_coin_flicker(void);
void coin_collected(void);

View File

@@ -521,24 +521,30 @@ static void obj_set_squished_action(void) {
}
static s32 obj_die_if_above_lava_and_health_non_positive(void) {
if (o->oMoveFlags & OBJ_MOVE_UNDERWATER_ON_GROUND) {
if (o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER) {
if (o->oGravity + o->oBuoyancy > 0.0f
|| find_water_level(o->oPosX, o->oPosZ) - o->oPosY < 150.0f) {
|| find_water_level(o->oPosX, o->oPosZ) - o->oPosY < 10.0f) {
return FALSE;
}
} else if (!(o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA)) {
if (o->oMoveFlags & OBJ_MOVE_ENTERED_WATER) {
if (o->oWallHitboxRadius < 200.0f) {
cur_obj_play_sound_2(SOUND_OBJ_DIVING_INTO_WATER);
} else {
cur_obj_play_sound_2(SOUND_OBJ_DIVING_IN_WATER);
}
obj_die_if_health_non_positive();
return TRUE;
} else if (o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA) {
if (o->oMoveFlags & (OBJ_MOVE_ON_GROUND | OBJ_MOVE_LANDED)) {
obj_die_if_health_non_positive();
return TRUE;
}
return FALSE;
}
obj_die_if_health_non_positive();
return TRUE;
if (o->oMoveFlags & OBJ_MOVE_ENTERED_WATER) {
if (o->oWallHitboxRadius < 200.0f) {
cur_obj_play_sound_2(SOUND_OBJ_DIVING_INTO_WATER);
} else {
cur_obj_play_sound_2(SOUND_OBJ_DIVING_IN_WATER);
}
}
return FALSE;
}
static s32 obj_handle_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction,

View File

@@ -1040,6 +1040,14 @@ static void cur_obj_move_update_ground_air_flags(UNUSED f32 gravity, f32 bouncin
}
}
o->oMoveFlags &= ~(OBJ_MOVE_ABOVE_LAVA | OBJ_MOVE_ABOVE_DEATH_BARRIER);
if (o->oFloorType == SURFACE_BURNING) {
o->oMoveFlags |= OBJ_MOVE_ABOVE_LAVA;
} else if ((o->oFloorType == SURFACE_DEATH_PLANE) || (o->oFloorType == SURFACE_VERTICAL_WIND)) {
//! This maybe misses SURFACE_WARP
o->oMoveFlags |= OBJ_MOVE_ABOVE_DEATH_BARRIER;
}
o->oMoveFlags &= ~OBJ_MOVE_MASK_IN_WATER;
}
@@ -1368,13 +1376,6 @@ static void cur_obj_update_floor(void) {
if (floor != NULL) {
SurfaceType floorType = floor->type;
if (floorType == SURFACE_BURNING) {
o->oMoveFlags |= OBJ_MOVE_ABOVE_LAVA;
} else if ((floorType == SURFACE_DEATH_PLANE) || (floorType == SURFACE_VERTICAL_WIND)) {
//! This maybe misses SURFACE_WARP
o->oMoveFlags |= OBJ_MOVE_ABOVE_DEATH_BARRIER;
}
o->oFloorType = floorType;
o->oFloorRoom = floor->room;
} else {
@@ -1384,8 +1385,6 @@ static void cur_obj_update_floor(void) {
}
static void cur_obj_update_floor_and_resolve_wall_collisions(s16 steepSlopeDegrees) {
o->oMoveFlags &= ~(OBJ_MOVE_ABOVE_LAVA | OBJ_MOVE_ABOVE_DEATH_BARRIER);
if (o->activeFlags & (ACTIVE_FLAG_FAR_AWAY | ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
cur_obj_update_floor();
o->oMoveFlags &= ~(OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER);