Tons of new things, but mostly a revamp of the stay in level setting

This commit is contained in:
Mors 2021-03-31 05:32:05 +03:00
parent 33cc07883e
commit bca5769586
25 changed files with 351 additions and 53 deletions

View File

@ -14,7 +14,9 @@ These features include (but not limited to):
Features that _might_ be added in the future:
- Discord Rich Presence support.
- Smoother vertical movement for "Improved Camera".
- Smoother vertical camera movement.
- Rumble.
- Custom texture pack support.
- Full OpenGL support.
To learn about all the options, visit the [Wiki](https://github.com/MorsGames/sm64-port/wiki).

View File

@ -1,3 +1,3 @@
#include "resource.h"
#include "include/resource.h"
STAR_ICON ICON "star.ico"

View File

@ -201,7 +201,8 @@
#define TEXT_MYSCORE _("MYSCORE")
#define TEXT_CONTINUE _("CONTINUE")
#define TEXT_EXIT_COURSE _("EXIT COURSE")
#define TEXT_EXIT_GAME _("QUIT GAME")
#define TEXT_EXIT_GAME _("EXIT TO DESKTOP")
#define TEXT_EXIT_GAME_ZR _("Z & R: EXIT TO DESKTOP")
#ifndef VERSION_EU // "R" text is different in EU
#define TEXT_CAMERA_ANGLE_R _("SET CAMERA ANGLE WITH R")
#endif
@ -487,4 +488,6 @@
#define TEXT_MENU_STARS_DE _(" GEHEIME STERNE")
#endif // VERSION_EU
#define TEXT_YOU_GOT_A_STAR _("YOU GOT A STAR")
#endif // TEXT_STRINGS_H

View File

@ -25,6 +25,8 @@
#include "surface_collision.h"
#include "surface_load.h"
#include "game/settings.h"
#define CMD_GET(type, offset) (*(type *) (CMD_PROCESS_OFFSET(offset) + (u8 *) sCurrentCmd))
// These are equal
@ -471,7 +473,13 @@ static void level_cmd_place_object(void) {
u16 model;
struct SpawnInfo *spawnInfo;
if (sCurrAreaIndex != -1 && ((CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
// This is a mess, you probably won't forgive me but I hope god will.
u8 canLoad = (gCurrLevelNum != LEVEL_DDD && gCurrLevelNum != LEVEL_JRB && ( gCurrLevelNum == LEVEL_LLL || (!(CMD_GET(u8, 2) & (1 << 0)) && gCurrActNum != 1) || ((CMD_GET(u8, 2) & (1 << 0)) && gCurrActNum == 1))) ||
(gCurrLevelNum == LEVEL_DDD && (save_file_get_flags() & SAVE_FLAG_DDD_MOVED_BACK)) ||
(gCurrLevelNum == LEVEL_JRB && ((gCurrActNum == 1 && (CMD_GET(u8, 2) & (1 << 0))) || (CMD_GET(u8, 2) & (1 << 1))));
if (sCurrAreaIndex != -1 &&
(((!gStayInLevel || gCurrLevelNum != LEVEL_JRB) && (CMD_GET(u8, 2) & val7)) || CMD_GET(u8, 2) == 0x1F || (gStayInLevel && canLoad))) {
model = CMD_GET(u8, 3);
spawnInfo = alloc_only_pool_alloc(sLevelPool, sizeof(struct SpawnInfo));

View File

@ -139,7 +139,7 @@ void bhv_blue_coin_switch_loop(void) {
if (gRespawnBlueCoinSwitch && o->oTimer > 240) {
cur_obj_unhide();
o->oAction = BLUE_COIN_SWITCH_ACT_IDLE;
o->oPosY = o->oPosY - 120.0f;
o->oPosY = o->oPosY + 120.0f;
}
else {
obj_mark_for_deletion(o);

View File

@ -80,7 +80,10 @@ void bhv_koopa_init(void) {
// Koopa the Quick. Race index is 0 for BoB and 1 for THI
o->oKoopaTheQuickRaceIndex = o->oKoopaMovementType - KOOPA_BP_KOOPA_THE_QUICK_BASE;
o->oKoopaAgility = 4.0f;
cur_obj_scale(3.0f);
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE)
cur_obj_scale(0.8f);
else
cur_obj_scale(3.0f);
} else {
o->oKoopaAgility = 1.0f;
}

View File

@ -5379,10 +5379,16 @@ u8 get_cutscene_from_mario_status(struct Camera *c) {
cutscene = CUTSCENE_STANDING_DEATH;
break;
case ACT_STAR_DANCE_EXIT:
cutscene = determine_dance_cutscene(c);
if (stay_in_level())
cutscene = CUTSCENE_DANCE_DEFAULT;
else
cutscene = determine_dance_cutscene(c);
break;
case ACT_STAR_DANCE_WATER:
cutscene = determine_dance_cutscene(c);
if (stay_in_level())
cutscene = CUTSCENE_DANCE_DEFAULT;
else
cutscene = determine_dance_cutscene(c);
break;
case ACT_STAR_DANCE_NO_EXIT:
cutscene = CUTSCENE_DANCE_DEFAULT;

View File

@ -14,6 +14,8 @@
#include "save_file.h"
#include "print.h"
#include "text_strings.h"
#include "settings.h"
/* @file hud.c
@ -55,6 +57,10 @@ static struct PowerMeterHUD sPowerMeterHUD = {
// when the power meter is hidden.
s32 sPowerMeterVisibleTimer = 0;
float sStarGetAlpha = 0.0f;
float sStarGetBounce = 0.0f;
float sStarGetSpeed = 0.0f;
// Custom left and right snapping functions
s32 get_left(s32 value) {
if (gCenterHud || configForce4by3) {
@ -100,6 +106,8 @@ static u32 sPowerMeterLastRenderTimestamp;
static s16 sPowerMeterLastY;
static Gfx *sPowerMeterDisplayListPos;
static Gfx *sStarGetDisplayListPos;
void patch_interpolated_hud(void) {
if (sPowerMeterDisplayListPos != NULL) {
Mtx *mtx = alloc_display_list(sizeof(Mtx));
@ -581,6 +589,91 @@ void render_hud_camera_status(void) {
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
}
void render_hud_level_stars() {
s32 i;
u8 flag = 1;
u8 starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1);
for (i = 0; i < 7; i++, flag <<= 1) {
if (starFlags & flag) {
print_text(get_left(HUD_LEFT_X) + i*16, 19, "-");
}
/*else {
print_text(get_left(HUD_LEFT_X) + i*16, 19, "*");
}*/
}
}
void render_you_got_a_star(u32 secondFrame) {
if (!gHudDisplay.starGet)
return;
u8 youGotAStar[] = { TEXT_YOU_GOT_A_STAR };
// Set the bounce speed at the start
if (sStarGetAlpha == 0.0f)
sStarGetSpeed = -4.0f;
// Gravity
sStarGetSpeed += 0.25f;
// Add the speed to the position and limit it
sStarGetBounce = MIN(sStarGetBounce + sStarGetSpeed, 0.0f);
// Rendering
if (secondFrame == 1) {
if (sStarGetDisplayListPos != NULL) {
gDPSetEnvColor(sStarGetDisplayListPos++, 255, 255, 255, 255 * sStarGetAlpha);
print_hud_lut_string_to_displaylist(HUD_LUT_GLOBAL, SCREEN_WIDTH / 2 - 78, 160 + sStarGetBounce, youGotAStar, sStarGetDisplayListPos);
sStarGetDisplayListPos = NULL;
}
}
if (secondFrame == 0) {
Mtx *matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
if (matrix) {
create_dl_translation_matrix(MENU_MTX_PUSH, (get_left(0)*2) / 2, 88.0f - (1.0f - sStarGetAlpha) * 16.0f, 0);
guScale(matrix, (SCREEN_WIDTH + get_right(0)*2) / 130.0f, 32.0f * sStarGetAlpha / 80.0f, 1.f);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255 * sStarGetAlpha / 2);
gSPDisplayList(gDisplayListHead++, dl_draw_text_bg_box);
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
sStarGetDisplayListPos = gDisplayListHead;
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255 * sStarGetAlpha);
print_hud_lut_string(HUD_LUT_GLOBAL, SCREEN_WIDTH / 2 - 78, 160 + sStarGetBounce, youGotAStar);
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
if (sStarGetSpeed > 4.0f && sStarGetSpeed < 25.0f) {
print_text_centered(SCREEN_WIDTH / 2 - 8, 34, "STAR");
print_text_fmt_int(SCREEN_WIDTH / 2 + 20, 34, "%2d", gCollectedStar+1);
}
}
// Using the speed as a timer since we never actually stop the speed from increasing
if (sStarGetSpeed > 27.0f) {
// Reduce the alpha, no one likes suddenly disappearing UI elements
sStarGetAlpha -= 0.0625f;
// If finally fully transparent, reset stuff
if (sStarGetAlpha <= 0.0f) {
gHudDisplay.starGet = 0;
sStarGetSpeed = 0.0f;
sStarGetAlpha = 0.0f;
sStarGetBounce = 0.0f;
}
}
// Fade in
else if (sStarGetAlpha < 1.0f)
sStarGetAlpha += 0.0625f;
}
/**
* Render HUD strings using hudDisplayFlags with it's render functions,
* excluding the cannon reticle which detects a camera preset for it.
@ -643,5 +736,14 @@ void render_hud(void) {
if (hudDisplayFlags & HUD_DISPLAY_FLAG_TIMER) {
render_hud_timer();
}
if (gStayInLevel && gHudStyle &&
gCurrLevelNum != LEVEL_CASTLE_GROUNDS && gCurrLevelNum != LEVEL_CASTLE && gCurrLevelNum != LEVEL_CASTLE_COURTYARD && gCurrLevelNum != LEVEL_BOWSER_1 && gCurrLevelNum != LEVEL_BOWSER_2 && gCurrLevelNum != LEVEL_BOWSER_3) {
render_hud_level_stars();
}
if (gStarGetText) {
render_you_got_a_star(0);
}
}
}
}

View File

@ -24,4 +24,6 @@ enum CameraHUDLut {
void set_hud_camera_status(s16 status);
void render_hud(void);
void render_you_got_a_star(u32 secondFrame);
#endif // HUD_H

View File

@ -1,4 +1,5 @@
#include <ultra64.h>
#include <stdlib.h>
#include "actors/common1.h"
#include "area.h"
@ -634,6 +635,77 @@ void print_hud_lut_string(s8 hudLUT, s16 x, s16 y, const u8 *str) {
strPos++;
}
}
void print_hud_lut_string_to_displaylist(s8 hudLUT, s16 x, s16 y, const u8 *str, Gfx* displayList) {
s32 strPos = 0;
void **hudLUT1 = segmented_to_virtual(menu_hud_lut); // Japanese Menu HUD Color font
void **hudLUT2 = segmented_to_virtual(main_hud_lut); // 0-9 A-Z HUD Color Font
u32 curX = x;
u32 curY = y;
u32 xStride; // X separation
if (hudLUT == HUD_LUT_JPMENU) {
xStride = 16;
} else { // HUD_LUT_GLOBAL
#if defined(VERSION_JP)
xStride = 14;
#else
xStride = 12; //? Shindou uses this.
#endif
}
while (str[strPos] != GLOBAR_CHAR_TERMINATOR) {
#ifdef VERSION_EU
switch (str[strPos]) {
case GLOBAL_CHAR_SPACE:
curX += xStride / 2;
break;
case HUD_CHAR_A_UMLAUT:
print_hud_char_umlaut(curX, curY, ASCII_TO_DIALOG('A'));
curX += xStride;
break;
case HUD_CHAR_O_UMLAUT:
print_hud_char_umlaut(curX, curY, ASCII_TO_DIALOG('O'));
curX += xStride;
break;
case HUD_CHAR_U_UMLAUT:
print_hud_char_umlaut(curX, curY, ASCII_TO_DIALOG('U'));
curX += xStride;
break;
default:
#endif
#if defined(VERSION_US) || defined(VERSION_SH)
if (str[strPos] == GLOBAL_CHAR_SPACE) {
if (0) //! dead code
{
}
curX += 8;
; //! useless statement
} else {
#endif
gDPPipeSync(displayList++);
if (hudLUT == HUD_LUT_JPMENU)
gDPSetTextureImage(displayList++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, hudLUT1[str[strPos]]);
if (hudLUT == HUD_LUT_GLOBAL)
gDPSetTextureImage(displayList++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, hudLUT2[str[strPos]]);
gSPDisplayList(displayList++, dl_rgba16_load_tex_block);
gSPTextureRectangle(displayList++, curX << 2, curY << 2, (curX + 16) << 2,
(curY + 16) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
curX += xStride;
#ifdef VERSION_EU
break;
}
#endif
#if defined(VERSION_US) || defined(VERSION_SH)
}
#endif
strPos++;
}
}
#ifdef VERSION_EU
void print_menu_char_umlaut(s16 x, s16 y, u8 chr) {
@ -2738,6 +2810,16 @@ s16 render_pause_courses_and_castle(void) {
print_hud_pause_colorful_str();
render_pause_castle_menu_box(160, 143);
render_pause_castle_main_strings(104, 60);
if (gQuitOption) {
u8 textExitGameR[] = { TEXT_EXIT_GAME_ZR };
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha);
print_generic_string(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(12), 8, textExitGameR);
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
if ((gPlayer1Controller->buttonDown & Z_TRIG) && (gPlayer1Controller->buttonDown & R_TRIG)) {
exit(0);
}
}
#ifdef VERSION_EU
if (gPlayer3Controller->buttonPressed & (A_BUTTON | Z_TRIG | START_BUTTON))

View File

@ -119,6 +119,7 @@ void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z);
void create_dl_ortho_matrix(void);
void print_generic_string(s16 x, s16 y, const u8 *str);
void print_hud_lut_string(s8 hudLUT, s16 x, s16 y, const u8 *str);
void print_hud_lut_string_to_displaylist(s8 hudLUT, s16 x, s16 y, const u8 *str, Gfx* displayList);
void print_menu_generic_string(s16 x, s16 y, const u8 *str);
void handle_menu_scrolling(s8 scrollDirection, s8 *currentIndex, s8 minIndex, s8 maxIndex);
#if defined(VERSION_US) || defined(VERSION_EU)

View File

@ -772,11 +772,12 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
u32 starGrabAction = ACT_STAR_DANCE_EXIT;
u32 noExit = (o->oInteractionSubtype & INT_SUBTYPE_NO_EXIT) != 0;
u32 grandStar = (o->oInteractionSubtype & INT_SUBTYPE_GRAND_STAR) != 0;
u32 canStay = gStayInLevel && gCurrLevelNum != LEVEL_BOWSER_1 && gCurrLevelNum != LEVEL_BOWSER_2
&& gCurrLevelNum != LEVEL_CASTLE && gCurrLevelNum != LEVEL_CASTLE_COURTYARD && gCurrLevelNum != LEVEL_CASTLE_GROUNDS;
starIndex = (o->oBehParams >> 24) & 0x1F;
gCollectedStar = starIndex;
// Don't kick Mario if staying in levels is active
if (canStay) {
if (stay_in_level()) {
noExit = 1;
}
@ -810,17 +811,13 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
starGrabAction = ACT_FALL_AFTER_STAR_GRAB;
}
if (canStay) {
starGrabAction = ACT_STAR_DANCE_NO_EXIT;
}
spawn_object(o, MODEL_NONE, bhvStarKeyCollectionPuffSpawner);
o->oInteractStatus = INT_STATUS_INTERACTED;
m->interactObj = o;
m->usedObj = o;
starIndex = (o->oBehParams >> 24) & 0x1F;
save_file_collect_star_or_key(m->numCoins, starIndex);
m->numStars =
@ -1125,7 +1122,7 @@ u32 interact_tornado(struct MarioState *m, UNUSED u32 interactType, struct Objec
u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
struct Object *marioObj = m->marioObj;
if (m->action != ACT_CAUGHT_IN_WHIRLPOOL) {
if (!mario_has_improved_metal_cap(m) && m->action != ACT_CAUGHT_IN_WHIRLPOOL) {
mario_stop_riding_and_holding(m);
o->oInteractStatus = INT_STATUS_INTERACTED;
m->interactObj = o;
@ -1148,7 +1145,7 @@ u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Obj
u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
UNUSED struct Object *marioObj = m->marioObj;
if (m->action != ACT_GETTING_BLOWN) {
if (!mario_has_improved_metal_cap(m) && m->action != ACT_GETTING_BLOWN) {
mario_stop_riding_and_holding(m);
o->oInteractStatus = INT_STATUS_INTERACTED;
m->interactObj = o;
@ -1227,7 +1224,7 @@ u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct
o->oInteractStatus = INT_STATUS_INTERACTED;
m->interactObj = o;
return set_mario_action(m, ACT_EATEN_BY_BUBBA, 0);
} else if (take_damage_and_knock_back(m, o)) {
} else if (!mario_has_improved_metal_cap(m) && take_damage_and_knock_back(m, o)) {
return TRUE;
}
@ -1322,6 +1319,9 @@ static u32 interact_stub(UNUSED struct MarioState *m, UNUSED u32 interactType, s
}
u32 interact_mr_blizzard(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (mario_has_improved_metal_cap(m))
return FALSE;
if (take_damage_and_knock_back(m, o)) {
return TRUE;
}
@ -1496,7 +1496,8 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O
}
u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !sInvulnerable)
if (!mario_has_improved_metal_cap(m)
&& (!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !sInvulnerable)
&& (o->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO)) {
if (object_facing_mario(m, o, 0x2AAA)) {
mario_stop_riding_and_holding(m);
@ -1838,7 +1839,7 @@ void check_death_barrier(struct MarioState *m) {
}
void check_lava_boost(struct MarioState *m) {
if (!(m->action & ACT_FLAG_RIDING_SHELL) && m->pos[1] < m->floorHeight + 10.0f) {
if (!mario_has_improved_metal_cap(m) && !(m->action & ACT_FLAG_RIDING_SHELL) && m->pos[1] < m->floorHeight + 10.0f) {
if (!(m->flags & MARIO_METAL_CAP)) {
m->hurtCounter += (m->flags & MARIO_CAP_ON_HEAD) ? 12 : 18;
}

View File

@ -97,6 +97,7 @@ struct HudDisplay {
/*0x08*/ s16 keys;
/*0x0A*/ s16 flags;
/*0x0C*/ u16 timer;
u16 starGet;
};
extern struct HudDisplay gHudDisplay;

View File

@ -33,6 +33,9 @@
#include "sound_init.h"
#include "thread6.h"
#include "audio/external.h"
#include "seq_ids.h"
#include "settings.h"
u32 unused80339F10;
@ -1712,7 +1715,7 @@ static void debug_update_mario_cap(u16 button, s32 flags, u16 capTimer, u16 capM
// This checks for Z_TRIG instead of Z_DOWN flag
// (which is also what other debug functions do),
// so likely debug behavior rather than unused behavior.
if ((gPlayer1Controller->buttonDown & Z_TRIG) && (gPlayer1Controller->buttonPressed & button)
if ((gPlayer1Controller->buttonDown & L_TRIG) && (gPlayer1Controller->buttonPressed & button)
&& !(gMarioState->flags & flags)) {
gMarioState->flags |= (flags + MARIO_CAP_ON_HEAD);
@ -1745,6 +1748,13 @@ void func_sh_8025574C(void) {
s32 execute_mario_action(UNUSED struct Object *o) {
s32 inLoop = TRUE;
if (gDebugCapChanger) {
debug_update_mario_cap(CONT_LEFT, MARIO_WING_CAP, 1800, SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP));
debug_update_mario_cap(CONT_UP, MARIO_METAL_CAP, 600, SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP));
debug_update_mario_cap(CONT_RIGHT, MARIO_VANISH_CAP, 600, SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP));
}
if (gMarioState->action) {
gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
mario_reset_bodystate(gMarioState);
@ -1827,6 +1837,10 @@ s32 execute_mario_action(UNUSED struct Object *o) {
return 0;
}
u32 mario_has_improved_metal_cap(struct MarioState *m) {
return (gImprovedMetalCap) && (m->flags & MARIO_METAL_CAP);
}
/**************************************************
* INITIALIZATION *
**************************************************/

View File

@ -48,6 +48,9 @@ s32 check_common_hold_action_exits(struct MarioState *m);
s32 transition_submerged_to_walking(struct MarioState *m);
s32 set_water_plunge_action(struct MarioState *m);
s32 execute_mario_action(UNUSED struct Object *o);
u32 mario_has_improved_metal_cap(struct MarioState *m);
void init_mario(void);
void init_mario_from_save_file(void);

View File

@ -45,6 +45,10 @@ void play_knockback_sound(struct MarioState *m) {
#endif
s32 lava_boost_on_wall(struct MarioState *m) {
if (mario_has_improved_metal_cap(m))
return FALSE;
m->faceAngle[1] = atan2s(m->wall->normal.z, m->wall->normal.x);
if (m->forwardVel < 24.0f) {
@ -163,7 +167,7 @@ s32 check_horizontal_wind(struct MarioState *m) {
floor = m->floor;
if (floor->type == SURFACE_HORIZONTAL_WIND) {
if (!mario_has_improved_metal_cap(m) && floor->type == SURFACE_HORIZONTAL_WIND) {
pushAngle = floor->force << 8;
m->slideVelX += 1.2f * sins(pushAngle);
@ -496,9 +500,6 @@ u32 common_air_action_step(struct MarioState *m, u32 landAction, s32 animation,
}
s32 act_jump(struct MarioState *m) {
if (gDebugMovementMode) {
set_mario_action(m, ACT_DEBUG_FREE_MOVE, 0);
}
if (check_kick_or_dive_in_air(m)) {
return TRUE;
}
@ -2273,5 +2274,9 @@ s32 mario_execute_airborne_action(struct MarioState *m) {
}
/* clang-format on */
if ((gDebugMovementMode) && (gPlayer1Controller->buttonDown & L_TRIG)) {
set_mario_action(gMarioState, ACT_DEBUG_FREE_MOVE, 0);
}
return cancel;
}

View File

@ -611,19 +611,22 @@ void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
case 42:
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
if (gStarGetText) {
gHudDisplay.starGet = 1;
}
break;
case 80:
if ((m->actionArg & 1) == 0) {
level_trigger_warp(m, WARP_OP_STAR_EXIT);
} else {
if (gStayInLevel == 2) {
if (gStayInLevel >= 2) {
save_file_do_save(gCurrSaveFileNum - 1);
m->actionState = 2;
}
else {
enable_time_stop();
if (gStayInLevel) {
if (stay_in_level()) {
create_dialog_box_with_response(DIALOG_170);
}
else {
@ -638,7 +641,7 @@ void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
if (gDialogResponse == 1) {
save_file_do_save(gCurrSaveFileNum - 1);
}
else if (gStayInLevel && gLastCompletedStarNum < 7) {
else if (stay_in_level() && gLastCompletedStarNum < 7) {
level_trigger_warp(m, WARP_OP_STAR_EXIT);
}
m->actionState = 2;

View File

@ -111,7 +111,7 @@ static void toad_message_faded(void) {
}
static void toad_message_opaque(void) {
if (!gDisableToadFading && gCurrentObject->oDistanceToMario > 700.0f) {
if (!gTalkEasier && gCurrentObject->oDistanceToMario > 700.0f) {
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING;
} else if (!gCurrentObject->oToadMessageRecentlyTalked) {
gCurrentObject->oInteractionSubtype = INT_SUBTYPE_NPC;
@ -127,7 +127,7 @@ static void toad_message_talking(void) {
if (cur_obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId)
!= 0) {
gCurrentObject->oToadMessageRecentlyTalked = TRUE;
if (gDisableToadFading) {
if (gTalkEasier) {
gCurrentObject->oToadMessageState = TOAD_MESSAGE_OPACIFYING;
gCurrentObject->oOpacity = 249;
}
@ -215,7 +215,7 @@ void bhv_toad_message_init(void) {
if (enoughStars) {
gCurrentObject->oToadMessageDialogId = dialogId;
gCurrentObject->oToadMessageRecentlyTalked = FALSE;
if (gDisableToadFading) {
if (gTalkEasier) {
gCurrentObject->oToadMessageState = TOAD_MESSAGE_OPAQUE;
gCurrentObject->oOpacity = 255;
}

View File

@ -139,15 +139,25 @@ u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) {
case SURFACE_DEEP_QUICKSAND:
case SURFACE_DEEP_MOVING_QUICKSAND:
if ((m->quicksandDepth += sinkingSpeed) >= 160.0f) {
update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
if (mario_has_improved_metal_cap(m)) {
m->quicksandDepth = 160.0f;
}
else {
update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
}
}
break;
case SURFACE_INSTANT_QUICKSAND:
case SURFACE_INSTANT_MOVING_QUICKSAND:
update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
if (mario_has_improved_metal_cap(m)) {
m->quicksandDepth = 0.0f;
}
else {
update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
}
break;
default:
@ -194,7 +204,7 @@ u32 mario_update_moving_sand(struct MarioState *m) {
u32 mario_update_windy_ground(struct MarioState *m) {
struct Surface *floor = m->floor;
if (floor->type == SURFACE_HORIZONTAL_WIND) {
if (!mario_has_improved_metal_cap(m) && floor->type == SURFACE_HORIZONTAL_WIND) {
f32 pushSpeed;
s16 pushAngle = floor->force << 8;
@ -571,8 +581,15 @@ void apply_gravity(struct MarioState *m) {
m->vel[1] /= 4.0f;
} else if (m->action & ACT_FLAG_METAL_WATER) {
m->vel[1] -= 1.6f;
if (m->vel[1] < -16.0f) {
m->vel[1] = -16.0f;
if (gImprovedMetalCap) {
if (m->vel[1] < -24.0f) {
m->vel[1] = -24.0f;
}
}
else {
if (m->vel[1] < -16.0f) {
m->vel[1] = -16.0f;
}
}
} else if ((m->flags & MARIO_WING_CAP) && m->vel[1] < 0.0f && (m->input & INPUT_A_DOWN)) {
m->marioBodyState->wingFlutter = TRUE;

View File

@ -1,5 +1,8 @@
#include <ultra64.h>
#include "area.h"
#include "save_file.h"
// DirectInput keyboard scan codes (from https://gist.github.com/tracend/912308)
#define DIK_ESCAPE 0x01
@ -147,6 +150,8 @@
#define DIK_MAIL 0xEC /* Mail */
#define DIK_MEDIASELECT 0xED /* Media Select */
char* gTitleString = "Super Mario 64 Plus v1.0.0";
s8 configFullscreen = 1;
unsigned int configCustomFullscreenResolution = 0;
unsigned int configFullscreenWidth = 1920;
@ -167,24 +172,24 @@ s8 gDisableBLJ = 0;
s8 gDisableFallDamage = 0;
unsigned int gControllerDeadzone = 512;
unsigned int gStayInLevel = 2;
s8 gCollisionFixes = 1;
s8 gFixMantaRayRings = 1;
s8 gRespawnBlueCoinSwitch = 1;
s8 gRemoveAnnoyingWarps = 1;
s8 gImprovedMetalCap = 1;
s8 gDisableBooDialogue = 1;
s8 gTalkEasier = 1;
s8 gDisableToadFading = 1;
s8 gQuitOption = 1;
s8 gLeaveAnyTime = 0;
s8 gShow100CoinStar = 0;
s8 gVisibleSecrets = 0;
s8 gFlexibleCannons = 0;
unsigned int gStayInLevel = 0;
s8 gSkipCutscenes = 0;
s8 gImprovedCamera = 1;
s8 gManualCamera = 1;
s8 gCenterCameraButton = 1;
s8 gManualCamera = 1;
s8 gInvertedCamera = 0;
float gCameraSpeed = 32.0f;
float gAdditionalCameraDistance = 0.0f;
@ -201,6 +206,7 @@ s8 gCenterHud = 0;
s8 gHUDFiltering = 0;
unsigned int gHUDUpscaling = 0;
s8 gAlwaysShowHealth = 0;
s8 gStarGetText = 0;
s8 gHideHud = 0;
s8 gWallSliding = 1;
@ -228,6 +234,7 @@ s8 gForceLowPoly = 0;
s8 gNearestNeighbor = 0;
s8 gDebugMovementMode = 0;
s8 gDebugCapChanger = 0;
s8 gVerticalCamera = 0;
unsigned int gTextureUpscaling = 0;
@ -257,4 +264,26 @@ unsigned int configKeyCRight = 0x014D;
unsigned int configKeyStickUp = DIK_W;
unsigned int configKeyStickDown = DIK_S;
unsigned int configKeyStickLeft = DIK_A;
unsigned int configKeyStickRight = DIK_D;
unsigned int configKeyStickRight = DIK_D;
// These probably don't belong here, but I don't have a better place for them at the moment.
unsigned int gCollectedStar = 0;
s8 stay_in_level() {
if (gStayInLevel == 2 && (
// If we have collected the first star in the first act in these levels, kick us out.
(gCurrActNum == 1 && gCollectedStar == 0 &&
(gCurrLevelNum == LEVEL_BOB || gCurrLevelNum == LEVEL_WF || gCurrLevelNum == LEVEL_JRB || gCurrLevelNum == LEVEL_SSL
|| gCurrLevelNum == LEVEL_CCM || gCurrLevelNum == LEVEL_BBH || gCurrLevelNum == LEVEL_TTM
// In addition to all of above, kick us only if the submarine is there in DDD.
|| (!save_file_get_flags() & SAVE_FLAG_DDD_MOVED_BACK) && gCurrLevelNum == LEVEL_DDD)) ||
// Kick us from the slide exit and the lonely mushroom in TTM as well.
(gCollectedStar == 5 && gCurrLevelNum == LEVEL_TTM) ||
// If we have collected any stars in any sublevels except for these, kick us again.
(gCurrAreaIndex > 1 && gCurrLevelNum != LEVEL_DDD && gCurrLevelNum != LEVEL_THI) ||
// Well, kick us from the wiggler room tho.
(gCollectedStar == 5 && gCurrLevelNum == LEVEL_THI)
))
return FALSE;
return gStayInLevel && gCurrLevelNum != LEVEL_BOWSER_1 && gCurrLevelNum != LEVEL_BOWSER_2
&& gCurrLevelNum != LEVEL_CASTLE && gCurrLevelNum != LEVEL_CASTLE_COURTYARD && gCurrLevelNum != LEVEL_CASTLE_GROUNDS;
}

View File

@ -1,5 +1,7 @@
#include <ultra64.h>
extern char* gTitleString;
extern s8 configFullscreen;
extern s8 configCustomFullscreenResolution;
extern unsigned int configFullscreenWidth;
@ -20,24 +22,24 @@ extern s8 gDisableBLJ;
extern s8 gDisableFallDamage;
extern unsigned int gControllerDeadzone;
extern unsigned int gStayInLevel;
extern s8 gCollisionFixes;
extern s8 gFixMantaRayRings;
extern s8 gRespawnBlueCoinSwitch;
extern s8 gRemoveAnnoyingWarps;
extern s8 gImprovedMetalCap;
extern s8 gDisableBooDialogue;
extern s8 gTalkEasier;
extern s8 gDisableToadFading;
extern s8 gQuitOption;
extern s8 gLeaveAnyTime;
extern s8 gShow100CoinStar;
extern s8 gVisibleSecrets;
extern s8 gFlexibleCannons;
extern unsigned int gStayInLevel;
extern s8 gSkipCutscenes;
extern s8 gImprovedCamera;
extern s8 gManualCamera;
extern s8 gCenterCameraButton;
extern s8 gManualCamera;
extern s8 gInvertedCamera;
extern float gCameraSpeed;
extern float gAdditionalCameraDistance;
@ -54,6 +56,7 @@ extern s8 gCenterHud;
extern s8 gHUDFiltering;
extern unsigned int gHUDUpscaling;
extern s8 gAlwaysShowHealth;
extern s8 gStarGetText;
extern s8 gHideHud;
extern s8 gWallSliding;
@ -81,6 +84,7 @@ extern s8 gForceLowPoly;
extern s8 gNearestNeighbor;
extern s8 gDebugMovementMode;
extern s8 gDebugCapChanger;
extern s8 gVerticalCamera;
extern unsigned int gTextureUpscaling;
@ -110,4 +114,7 @@ extern unsigned int configKeyCRight;
extern unsigned int configKeyStickUp;
extern unsigned int configKeyStickDown;
extern unsigned int configKeyStickLeft;
extern unsigned int configKeyStickRight;
extern unsigned int configKeyStickRight;
extern unsigned int gCollectedStar;
extern s8 stay_in_level();

View File

@ -53,25 +53,25 @@ static const struct ConfigOption options[] = {
{ .name = "analog_stick_deadzone", .type = CONFIG_TYPE_UINT, .uintValue = &gControllerDeadzone },
{ .name = "TWEAKS", .type = CONFIG_TYPE_SECTION },
{ .name = "stay_in_level_after_getting_a_star", .type = CONFIG_TYPE_UINT, .uintValue = &gStayInLevel },
{ .name = "fix_collision_errors", .type = CONFIG_TYPE_BOOL, .boolValue = &gCollisionFixes },
{ .name = "fix_manta_ray_rings", .type = CONFIG_TYPE_BOOL, .boolValue = &gFixMantaRayRings },
{ .name = "make_blue_coin_switches_respawn", .type = CONFIG_TYPE_BOOL, .boolValue = &gRespawnBlueCoinSwitch },
{ .name = "remove_annoying_warps", .type = CONFIG_TYPE_BOOL, .boolValue = &gRemoveAnnoyingWarps },
{ .name = "improve_metal_mario", .type = CONFIG_TYPE_BOOL, .boolValue = &gImprovedMetalCap },
{ .name = "disable_repeat_boo_messages", .type = CONFIG_TYPE_BOOL, .boolValue = &gDisableBooDialogue },
{ .name = "make_it_easier_to_talk_to_the_npcs", .type = CONFIG_TYPE_BOOL, .boolValue = &gTalkEasier },
{ .name = "disable_toads_fading_out", .type = CONFIG_TYPE_BOOL, .boolValue = &gDisableToadFading },
{ .name = "add_a_quit_option_to_the_pause_menu", .type = CONFIG_TYPE_BOOL, .boolValue = &gQuitOption },
{ .name = "allow_leaving_the_level_at_any_time", .type = CONFIG_TYPE_BOOL, .boolValue = &gLeaveAnyTime },
{ .name = "show_the_100_coin_star_in_star_select", .type = CONFIG_TYPE_BOOL, .boolValue = &gShow100CoinStar },
{ .name = "make_secrets_visible", .type = CONFIG_TYPE_BOOL, .boolValue = &gVisibleSecrets },
{ .name = "allow_the_cannons_to_rotate_more", .type = CONFIG_TYPE_BOOL, .boolValue = &gFlexibleCannons },
{ .name = "stay_in_level_after_getting_a_star", .type = CONFIG_TYPE_UINT, .uintValue = &gStayInLevel },
{ .name = "skip_cutscenes", .type = CONFIG_TYPE_BOOL, .boolValue = &gSkipCutscenes },
{ .name = "CAMERA", .type = CONFIG_TYPE_SECTION },
{ .name = "analog_camera", .type = CONFIG_TYPE_BOOL, .boolValue = &gImprovedCamera },
{ .name = "manual_camera", .type = CONFIG_TYPE_BOOL, .boolValue = &gManualCamera },
{ .name = "center_camera_button", .type = CONFIG_TYPE_BOOL, .boolValue = &gCenterCameraButton },
{ .name = "manual_camera", .type = CONFIG_TYPE_BOOL, .boolValue = &gManualCamera },
{ .name = "invert_camera_controls", .type = CONFIG_TYPE_BOOL, .boolValue = &gInvertedCamera },
{ .name = "analog_camera_speed", .type = CONFIG_TYPE_FLOAT, .floatValue = &gCameraSpeed },
{ .name = "additional_camera_distance", .type = CONFIG_TYPE_FLOAT, .floatValue = &gAdditionalCameraDistance },
@ -90,6 +90,7 @@ static const struct ConfigOption options[] = {
{ .name = "hud_filtering", .type = CONFIG_TYPE_BOOL, .boolValue = &gHUDFiltering },
{ .name = "hud_upscaling", .type = CONFIG_TYPE_UINT, .uintValue = &gHUDUpscaling },
{ .name = "always_show_the_health_meter", .type = CONFIG_TYPE_BOOL, .boolValue = &gAlwaysShowHealth },
{ .name = "show_the_you_got_a_star_text", .type = CONFIG_TYPE_BOOL, .boolValue = &gStarGetText },
{ .name = "hide_hud", .type = CONFIG_TYPE_BOOL, .boolValue = &gHideHud },
{ .name = "EXTRA MOVES", .type = CONFIG_TYPE_SECTION },
@ -124,6 +125,7 @@ static const struct ConfigOption options[] = {
{ .name = "level_select", .type = CONFIG_TYPE_BOOL, .boolValue = &gDebugLevelSelect },
{ .name = "show_debug_display", .type = CONFIG_TYPE_BOOL, .boolValue = &gShowDebugText },
{ .name = "debug_movement_mode", .type = CONFIG_TYPE_BOOL, .boolValue = &gDebugMovementMode },
{ .name = "debug_cap_changer", .type = CONFIG_TYPE_BOOL, .boolValue = &gDebugCapChanger },
{ .name = "show_debug_profiler", .type = CONFIG_TYPE_BOOL, .boolValue = &gShowProfiler },
{ .name = "vertical_analog_camera", .type = CONFIG_TYPE_BOOL, .boolValue = &gVerticalCamera },
{ .name = "texture_upscaling", .type = CONFIG_TYPE_UINT, .uintValue = &gTextureUpscaling },

View File

@ -27,7 +27,7 @@
#include "gfx_screen_config.h"
#include "gfx_pc.h"
#include ".\resource.h"
#include "resource.h"
#define DECLARE_GFX_DXGI_FUNCTIONS
#include "gfx_dxgi.h"

View File

@ -92,6 +92,10 @@ static void patch_interpolations(void) {
patch_title_screen_scales();
patch_interpolated_dialog();
patch_interpolated_hud();
if (gStarGetText)
render_you_got_a_star(1);
patch_interpolated_paintings();
patch_interpolated_bubble_particles();
patch_interpolated_snow_particles();
@ -121,6 +125,9 @@ void produce_one_frame(void) {
if (g60FPS) {
patch_interpolations();
}
else if (gStarGetText) {
render_you_got_a_star(3);
}
send_display_list(gGfxSPTask);
gfx_end_frame();
}
@ -202,7 +209,7 @@ void main_func(void) {
wm_api = &gfx_dummy_wm_api;
#endif
gfx_init(wm_api, rendering_api, "Super Mario 64 Plus", configFullscreen);
gfx_init(wm_api, rendering_api, gTitleString, configFullscreen);
wm_api->set_fullscreen_changed_callback(on_fullscreen_changed);
wm_api->set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up);