reset: implement quick-reset

This commit is contained in:
Leaze 2023-03-11 15:11:47 +01:00
parent 576d327fd3
commit 0fc9c95dbe
5 changed files with 93 additions and 15 deletions

View File

@ -251,6 +251,17 @@ void unload_area(void) {
}
}
void reload_objects(void) {
if (TRUE
|| gCurrentArea != NULL && (gCurrentArea->flags & 0x01)
&& gCurrentArea->index == gMarioSpawnInfo->areaIndex) {
unload_objects_from_area(0, gMarioSpawnInfo->activeAreaIndex);
gCurrentArea->flags |= 0x01;
spawn_objects_from_info(0, gMarioSpawnInfo);
}
}
void load_mario_area(void) {
stop_sounds_in_continuous_banks();
load_area(gMarioSpawnInfo->areaIndex);

View File

@ -156,6 +156,7 @@ void clear_areas(void);
void clear_area_graph_nodes(void);
void load_area(s32 index);
void unload_area(void);
void reload_objects(void);
void load_mario_area(void);
void unload_mario_area(void);
void change_area(s32 index);

View File

@ -39,6 +39,7 @@
#define WARP_TYPE_CHANGE_LEVEL 1
#define WARP_TYPE_CHANGE_AREA 2
#define WARP_TYPE_SAME_AREA 3
#define WARP_TYPE_RELOAD_LEVEL 4
#define WARP_NODE_F0 0xF0
#define WARP_NODE_DEATH 0xF1
@ -164,6 +165,8 @@ s16 sCurrPlayMode;
u16 D_80339ECA;
s16 sTransitionTimer;
void (*sTransitionUpdate)(s16 *);
s16 recentWarpSourceNodeId = -1;
struct WarpDest recentWarpDest;
struct WarpDest sWarpDest;
s16 D_80339EE0;
s16 sDelayedWarpOp;
@ -220,6 +223,19 @@ u32 pressed_pause(void) {
return FALSE;
}
u32 pressed_reset(void) {
u32 dialogActive = get_dialog_id() >= 0;
// TODO prevent resetting during star animations in speedrun mode
u32 intangible = (gMarioState->action & ACT_FLAG_INTANGIBLE) != 0;
if (!gWarpTransition.isActive && sDelayedWarpOp == WARP_OP_NONE
&& (gPlayer1Controller->buttonPressed & L_TRIG)) {
return TRUE;
}
return FALSE;
}
void set_play_mode(s16 playMode) {
sCurrPlayMode = playMode;
D_80339ECA = 0;
@ -387,10 +403,15 @@ void init_mario_after_warp(void) {
init_door_warp(&gPlayerSpawnInfos[0], sWarpDest.arg);
}
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL || sWarpDest.type == WARP_TYPE_CHANGE_AREA) {
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL || sWarpDest.type == WARP_TYPE_CHANGE_AREA
|| sWarpDest.type == WARP_TYPE_RELOAD_LEVEL) {
gPlayerSpawnInfos[0].areaIndex = sWarpDest.areaIdx;
load_mario_area();
}
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL || sWarpDest.type == WARP_TYPE_RELOAD_LEVEL) {
gMarioState->numCoins = 0;
gHudDisplay.coins = 0;
}
init_mario();
set_mario_initial_action(gMarioState, marioSpawnType, sWarpDest.arg);
@ -618,7 +639,7 @@ s16 music_changed_through_warp(s16 arg) {
/**
* Set the current warp type and destination level/area/node.
*/
void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg3) {
void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg3, bool reloadOnSameArea) {
if (destWarpNode >= WARP_NODE_CREDITS_MIN) {
sWarpDest.type = WARP_TYPE_CHANGE_LEVEL;
} else if (destLevel != gCurrLevelNum) {
@ -626,13 +647,18 @@ void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg3) {
} else if (destArea != gCurrentArea->index) {
sWarpDest.type = WARP_TYPE_CHANGE_AREA;
} else {
sWarpDest.type = WARP_TYPE_SAME_AREA;
if (reloadOnSameArea) {
sWarpDest.type = WARP_TYPE_CHANGE_LEVEL;
} else {
sWarpDest.type = WARP_TYPE_SAME_AREA;
}
}
sWarpDest.levelNum = destLevel;
sWarpDest.areaIdx = destArea;
sWarpDest.nodeId = destWarpNode;
sWarpDest.arg = arg3;
recentWarpDest = sWarpDest;
}
// From Surface 0xD3 to 0xFC
@ -676,7 +702,8 @@ void initiate_painting_warp(void) {
sWarpCheckpointActive = check_warp_checkpoint(&warpNode);
}
initiate_warp(warpNode.destLevel & 0x7F, warpNode.destArea, warpNode.destNode, 0);
initiate_warp(warpNode.destLevel & 0x7F, warpNode.destArea, warpNode.destNode, 0,
FALSE);
check_if_should_set_warp_checkpoint(&warpNode);
play_transition_after_delay(WARP_TRANSITION_FADE_INTO_COLOR, 30, 255, 255, 255, 45);
@ -727,6 +754,12 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
play_transition(WARP_TRANSITION_FADE_INTO_COLOR, 0x3C, 0x00, 0x00, 0x00);
break;
case WARP_OP_RELOAD:
sDelayedWarpTimer = 4;
sSourceWarpNodeId = WARP_NODE_F0;
play_transition(WARP_TRANSITION_FADE_INTO_COLOR, 0x3C, 0x00, 0x00, 0x00);
break;
case WARP_OP_STAR_EXIT:
sDelayedWarpTimer = 32;
sSourceWarpNodeId = WARP_NODE_F0;
@ -814,6 +847,7 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
if (val04 && gCurrDemoInput == NULL) {
fadeout_music((3 * sDelayedWarpTimer / 2) * 8 - 2);
}
recentWarpSourceNodeId = sSourceWarpNodeId;
}
return sDelayedWarpTimer;
@ -857,7 +891,7 @@ void initiate_delayed_warp(void) {
case WARP_OP_CREDITS_START:
gCurrCreditsEntry = &sCreditsSequence[0];
initiate_warp(gCurrCreditsEntry->levelNum, gCurrCreditsEntry->areaIndex,
WARP_NODE_CREDITS_START, 0);
WARP_NODE_CREDITS_START, 0, FALSE);
break;
case WARP_OP_CREDITS_NEXT:
@ -872,14 +906,19 @@ void initiate_delayed_warp(void) {
}
initiate_warp(gCurrCreditsEntry->levelNum, gCurrCreditsEntry->areaIndex,
destWarpNode, 0);
destWarpNode, 0, FALSE);
break;
case WARP_OP_RELOAD:
initiate_warp(recentWarpDest.levelNum & 0x7F, recentWarpDest.areaIdx,
recentWarpDest.nodeId, recentWarpDest.arg, TRUE);
break;
default:
warpNode = area_get_warp_node(sSourceWarpNodeId);
initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea,
warpNode->node.destNode, sDelayedWarpArg);
warpNode->node.destNode, sDelayedWarpArg, TRUE);
check_if_should_set_warp_checkpoint(&warpNode->node);
if (sWarpDest.type != WARP_TYPE_CHANGE_LEVEL) {
@ -994,13 +1033,15 @@ s32 play_mode_normal(void) {
initiate_painting_warp();
initiate_delayed_warp();
// If either initiate_painting_warp or initiate_delayed_warp initiated a
// warp, change play mode accordingly.
if (sCurrPlayMode == PLAY_MODE_NORMAL) {
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL) {
set_play_mode(PLAY_MODE_CHANGE_LEVEL);
} else if (sTransitionTimer != 0) {
set_play_mode(PLAY_MODE_CHANGE_AREA);
} else if (pressed_reset()) {
if (recentWarpSourceNodeId >= 0) {
level_trigger_warp(gMarioState, WARP_OP_RELOAD);
}
} else if (pressed_pause()) {
lower_background_noise(1);
#if ENABLE_RUMBLE
@ -1025,7 +1066,7 @@ s32 play_mode_paused(void) {
if (gDebugLevelSelect) {
fade_into_special_warp(-9, 1);
} else {
initiate_warp(LEVEL_CASTLE, 1, 0x1F, 0);
initiate_warp(LEVEL_CASTLE, 1, 0x0A, 0, FALSE); // TODO set pause menu warp here
fade_into_special_warp(0, 0);
gSavedCourseNum = COURSE_NONE;
}
@ -1258,10 +1299,31 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) {
break;
}
#endif
recentWarpDest.type = WARP_TYPE_NOT_WARPING;
sWarpDest.type = WARP_TYPE_NOT_WARPING;
sDelayedWarpOp = WARP_OP_NONE;
gNeverEnteredCastle = !save_file_exists(gCurrSaveFileNum - 1);
// TODO maybe do that independent of level?
if (gCurrLevelNum == LEVEL_CASTLE)
return 0;
if (gCurrLevelNum == LEVEL_BOB)
return 0;
if (gCurrLevelNum == LEVEL_HMC)
return 0;
if (gCurrLevelNum == LEVEL_LLL)
return 0;
if (gCurrLevelNum == LEVEL_SSL)
return 0;
if (gCurrLevelNum == LEVEL_BBH)
return 0;
if (gCurrLevelNum == LEVEL_CCM)
return 0;
if (gCurrLevelNum == LEVEL_JRB)
return 0;
if (gCurrLevelNum == LEVEL_WF)
return 0;
gCurrLevelNum = levelNum;
gCurrCourseNum = COURSE_NONE;
gSavedCourseNum = COURSE_NONE;

View File

@ -17,6 +17,7 @@
#define WARP_OP_WARP_DOOR 0x03
#define WARP_OP_WARP_OBJECT 0x04
#define WARP_OP_TELEPORT 0x05
#define WARP_OP_RELOAD 0x06
#define WARP_OP_STAR_EXIT 0x11
#define WARP_OP_DEATH 0x12
#define WARP_OP_WARP_FLOOR 0x13

View File

@ -638,6 +638,7 @@ void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
}
s32 act_star_dance(struct MarioState *m) {
// TODO end timer
m->faceAngle[1] = m->area->camera->yaw;
set_mario_animation(m, m->actionState == 2 ? MARIO_ANIM_RETURN_FROM_STAR_DANCE
: MARIO_ANIM_STAR_DANCE);
@ -650,6 +651,7 @@ s32 act_star_dance(struct MarioState *m) {
}
s32 act_star_dance_water(struct MarioState *m) {
// TODO end timer
m->faceAngle[1] = m->area->camera->yaw;
set_mario_animation(m, m->actionState == 2 ? MARIO_ANIM_RETURN_FROM_WATER_STAR_DANCE
: MARIO_ANIM_WATER_STAR_DANCE);
@ -1173,19 +1175,20 @@ s32 act_death_exit(struct MarioState *m) {
return FALSE;
}
/** (Ab-)used as a life-restoring level entry with no control downtime **/
s32 act_unused_death_exit(struct MarioState *m) {
// TODO begin timer
if (launch_mario_until_land(m, ACT_FREEFALL_LAND_STOP, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
#ifdef VERSION_JP
play_sound(SOUND_MARIO_OOOF, m->marioObj->header.gfx.cameraToObject);
#else
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
#endif
m->numLives--;
// restore 7.75 units of health
m->healCounter = 31;
}
// one unit of health
m->health = 0x0100;
// restore 7.75 units of health
m->healCounter = 31;
m->health = 0x880;
return FALSE;
}