Fix lives (#1119)
Some checks failed
Build coop / build-linux (push) Has been cancelled
Build coop / build-steamos (push) Has been cancelled
Build coop / build-windows-opengl (push) Has been cancelled
Build coop / build-windows-directx (push) Has been cancelled
Build coop / build-macos-arm (push) Has been cancelled
Build coop / build-macos-intel (push) Has been cancelled

- Fix lives going below 0 right before a game over (also fixes a crash where if you exited with -1 lives and went into a subarea you would crash)
- Restore how lives get removed upon death exit (like in vanilla)
- Prevent bubbling from happening if you don't have enough lives (this fixes the annoying bug where you would get put back in a bubble and get popped immediately after over and over again)
This commit is contained in:
Blockyyy 2026-03-27 04:32:44 +01:00 committed by GitHub
parent b27fa1dd7a
commit dfb3b2523d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 23 additions and 16 deletions

View file

@ -2445,7 +2445,7 @@ void check_death_barrier(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
switch (gCurrCourseNum) {
case COURSE_COTMC: // (20) Cavern of the Metal Cap
case COURSE_TOTWC: // (21) Tower of the Wing Cap

View file

@ -878,8 +878,7 @@ void verify_warp(struct MarioState *m, bool killMario) {
return;
}
m->numLives--;
if (m->numLives < 0) {
if (m->numLives <= 0) {
sDelayedWarpOp = WARP_OP_GAME_OVER;
} else {
sSourceWarpNodeId = WARP_NODE_DEATH;
@ -934,8 +933,7 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
break;
case WARP_OP_DEATH:
m->numLives--;
if (m->numLives <= -1) {
if (m->numLives <= 0) {
sDelayedWarpOp = WARP_OP_GAME_OVER;
}
sDelayedWarpTimer = 48;

View file

@ -447,7 +447,7 @@ void mario_set_bubbled(struct MarioState* m) {
gLocalBubbleCounter = 20;
drop_and_set_mario_action(m, ACT_BUBBLED, 0);
if (m->numLives > -1) {
if (m->numLives > 0) {
m->numLives--;
}
m->healCounter = 0;

View file

@ -1734,7 +1734,7 @@ s32 act_lava_boost(struct MarioState *m) {
return FALSE;
}
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
m->health = 0xFF;
mario_set_bubbled(m);
} else {

View file

@ -849,7 +849,7 @@ s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWa
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return animFrame; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
@ -922,8 +922,7 @@ s32 act_quicksand_death(struct MarioState *m) {
bool allowDeath = true;
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
@ -947,7 +946,7 @@ s32 act_eaten_by_bubba(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
m->health = 0xFF;
mario_set_bubbled(m);
} else {
@ -1437,6 +1436,12 @@ s32 act_exit_land_save_dialog(struct MarioState *m) {
return FALSE;
}
static void lose_life_after_death_exit(struct MarioState *m) {
if (sDelayedWarpArg != WARP_ARG_EXIT_COURSE) {
m->numLives--;
}
}
s32 act_death_exit(struct MarioState *m) {
if (!m) { return 0; }
if (15 < m->actionTimer++
@ -1447,6 +1452,7 @@ s32 act_death_exit(struct MarioState *m) {
play_character_sound(m, CHAR_SOUND_OOOF2);
#endif
queue_rumble_data_mario(m, 5, 80);
lose_life_after_death_exit(m);
// restore 7.75 units of health
m->healCounter = 31;
}
@ -1463,6 +1469,7 @@ s32 act_unused_death_exit(struct MarioState *m) {
#else
play_character_sound(m, CHAR_SOUND_OOOF2);
#endif
lose_life_after_death_exit(m);
// restore 7.75 units of health
m->healCounter = 31;
}
@ -1479,6 +1486,7 @@ s32 act_falling_death_exit(struct MarioState *m) {
#else
play_character_sound(m, CHAR_SOUND_OOOF2);
#endif
lose_life_after_death_exit(m);
queue_rumble_data_mario(m, 5, 80);
// restore 7.75 units of health
m->healCounter = 31;
@ -1526,6 +1534,7 @@ s32 act_special_death_exit(struct MarioState *m) {
if (launch_mario_until_land(m, ACT_HARD_BACKWARD_GROUND_KB, CHAR_ANIM_BACKWARD_AIR_KB, -24.0f)) {
queue_rumble_data_mario(m, 5, 80);
lose_life_after_death_exit(m);
m->healCounter = 31;
}
// show Mario
@ -1829,7 +1838,7 @@ s32 act_squished(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
@ -1880,7 +1889,7 @@ s32 act_squished(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
// 0 units of health

View file

@ -1003,7 +1003,7 @@ static s32 act_drowning(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
@ -1038,7 +1038,7 @@ static s32 act_water_death(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
@ -1164,7 +1164,7 @@ static s32 act_caught_in_whirlpool(struct MarioState *m) {
smlua_call_event_hooks(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { reset_rumble_timers(m); return FALSE; }
if (mario_can_bubble(m)) {
if ((mario_can_bubble(m) && m->numLives > 0)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);