diff --git a/src/game/level_update.c b/src/game/level_update.c index 47480020..52d8def9 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1356,7 +1356,7 @@ s32 init_level(void) { if (gMarioState->action != ACT_UNINITIALIZED) { if (save_file_exists(gCurrSaveFileNum - 1)) { set_mario_action(gMarioState, ACT_IDLE, 0); - } else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0) { + } else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0 && gServerSettings.skipIntro == 0) { set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0); val4 = 1; } diff --git a/src/game/mario.c b/src/game/mario.c index 0d06fba5..3e947d73 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -391,6 +391,9 @@ void mario_set_bubbled(struct MarioState* m) { set_mario_action(m, ACT_BUBBLED, 0); if (m->numLives != -1) { m->numLives--; + if (gServerSettings.shareLives) { + network_send_death(); + } } m->healCounter = 0; m->hurtCounter = 31; diff --git a/src/menu/custom_menu.c b/src/menu/custom_menu.c index 98892b3e..111277e8 100644 --- a/src/menu/custom_menu.c +++ b/src/menu/custom_menu.c @@ -26,6 +26,7 @@ char sConnectionJoinError[128] = { 0 }; char gConnectionText[128] = { 0 }; struct CustomMenu* sConnectMenu = NULL; + u8 gOpenConnectMenu = FALSE; s8 sGotoGame = 0; @@ -42,9 +43,9 @@ static void menu_main_draw_strings(void) { static void host_menu_draw_strings(void) { #ifdef DISCORD_SDK - #define HOST_MENU_MAX_ITEMS 4 + #define HOST_MENU_MAX_ITEMS 6 #else - #define HOST_MENU_MAX_ITEMS 3 + #define HOST_MENU_MAX_ITEMS 5 #endif // set up server setting strings @@ -66,23 +67,26 @@ static void host_menu_draw_strings(void) { buttonText[2] = configStayInLevelAfterStar ? "Stay in level after star." : "Leave level after star."; + buttonText[3] = configSkipIntro ? "Skip intro cutscene." : "Play intro cutscene."; + + buttonText[4] = configShareLives ? "Share lives." : "Lives are not shared."; + #ifdef DISCORD_SDK - buttonText[3] = (configNetworkSystem == 0) ? "Host through Discord." : "Host direct connection."; + buttonText[5] = (configNetworkSystem == 0) ? "Host through Discord." : "Host direct connection."; #endif // display server setting strings for (int i = 0; i < HOST_MENU_MAX_ITEMS; i++) { - print_generic_ascii_string(95, 158 + -35 * i, buttonText[i]); + print_generic_ascii_string(95, 173 + -29 * i, buttonText[i]); } // display direct connection warning if (configNetworkSystem != 0) { - print_generic_ascii_string(0, 30, "For direct connections -"); f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f)); gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha); char warning[128]; - snprintf(warning, 127, "You must forward port '%d' in your router or use Hamachi.", configHostPort); - print_generic_ascii_string(0, 15, warning); + snprintf(warning, 127, "Port forward '%d' in network router settings or use Hamachi.", configHostPort); + print_generic_ascii_string(0, 5, warning); } else if ((configNetworkSystem == 0) && gDiscordFailed) { f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f)); gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha); @@ -134,6 +138,14 @@ static void host_menu_setting_stay_in_level(void) { configStayInLevelAfterStar = (configStayInLevelAfterStar == 0) ? 1 : 0; } +static void host_menu_setting_skip_intro(void) { + configSkipIntro = (configSkipIntro == 1) ? 0 : 1; +} + +static void host_menu_setting_share_lives(void) { + configShareLives = (configShareLives == 0) ? 1 : 0; +} + #ifdef DISCORD_SDK static void join_menu_draw_strings(void) { print_generic_ascii_string(30, 155, "Accept a Discord game invite in order to join."); @@ -217,7 +229,7 @@ static void connect_menu_on_click(void) { // fill in our last attempt if (configJoinPort == 0 || configJoinPort > 65535) { configJoinPort = DEFAULT_PORT; } - + // only print custom port if (configJoinPort == DEFAULT_PORT) { sprintf(gTextInput, "%s", configJoinIp); @@ -243,29 +255,32 @@ void custom_menu_init(struct CustomMenu* head) { head->draw_strings = menu_main_draw_strings; // create sub menus and buttons - struct CustomMenu* hostMenu = custom_menu_create(head, "HOST", -266, 0); + struct CustomMenu* hostMenu = custom_menu_create(head, "HOST", -266, 0, gButtonScale.large); + hostMenu->headerY = 30; hostMenu->draw_strings = host_menu_draw_strings; - custom_menu_create_button(hostMenu, "CANCEL", 700, -400 + (250 * 3), SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); - custom_menu_create_button(hostMenu, "HOST", 700, -400, SOUND_MENU_CAMERA_ZOOM_IN, host_menu_do_host); - custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 3), SOUND_ACTION_BONK, host_menu_setting_interaction); - custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 2), SOUND_ACTION_BONK, host_menu_setting_knockback); - custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 1), SOUND_ACTION_BONK, host_menu_setting_stay_in_level); + custom_menu_create_button(hostMenu, "CANCEL", 700, -196 + (210 * 3), gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); + custom_menu_create_button(hostMenu, "HOST", 700, -220, gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_IN, host_menu_do_host); + custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 3), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_interaction); + custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 2), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_knockback); + custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 1), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_stay_in_level); + custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 0), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_skip_intro); + custom_menu_create_button(hostMenu, "", -700, -180 + (210 * -1), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_share_lives); #ifdef DISCORD_SDK - custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 0), SOUND_ACTION_BONK, host_menu_setting_network_system); + custom_menu_create_button(hostMenu, "", -700, -180 + (210 * -2), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_network_system); #endif #ifdef DISCORD_SDK - struct CustomMenu* joinMenu = custom_menu_create(head, "JOIN", 266, 0); - custom_menu_create_button(joinMenu, "CANCEL", -266, -320, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); + struct CustomMenu* joinMenu = custom_menu_create(head, "JOIN", 266, 0, gButtonScale.large); + custom_menu_create_button(joinMenu, "CANCEL", -266, -320, gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); joinMenu->draw_strings = join_menu_draw_strings; - struct CustomMenu* connectMenu = custom_menu_create(joinMenu, "CONNECT", 266, -320); + struct CustomMenu* connectMenu = custom_menu_create(joinMenu, "CONNECT", 266, -320, gButtonScale.large); #else - struct CustomMenu* connectMenu = custom_menu_create(head, "CONNECT", 266, 0); + struct CustomMenu* connectMenu = custom_menu_create(head, "CONNECT", 266, 0, gButtonScale.large); #endif connectMenu->me->on_click = connect_menu_on_click; connectMenu->on_close = connect_menu_on_close; connectMenu->draw_strings = connect_menu_draw_strings; - custom_menu_create_button(connectMenu, "CANCEL", 0, -400, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); + custom_menu_create_button(connectMenu, "CANCEL", 0, -400, gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); sConnectMenu = connectMenu; } diff --git a/src/menu/custom_menu_system.c b/src/menu/custom_menu_system.c index 0fa5c6b2..ce1e14cf 100644 --- a/src/menu/custom_menu_system.c +++ b/src/menu/custom_menu_system.c @@ -20,6 +20,11 @@ static struct CustomMenu* sHead = NULL; static struct CustomMenu* sCurrentMenu = NULL; static struct CustomMenu* sLastMenu = NULL; +struct CustomMenuButtonScale gButtonScale = { + .small = 0.08111111f, + .medium = 0.09511111f, + .large = 0.11111111f, +}; u8 gMenuStringAlpha = 255; @@ -29,7 +34,7 @@ struct ErrorDialog { }; static struct ErrorDialog* sErrorDialog = NULL; -struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, s32 clickSound, void (*on_click)(void)) { +struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale, s32 clickSound, void (*on_click)(void)) { struct CustomMenuButton* button = calloc(1, sizeof(struct CustomMenuButton)); if (parent->buttons == NULL) { parent->buttons = button; @@ -45,7 +50,8 @@ struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, ch button->clickSound = clickSound; struct Object* obj = spawn_object_rel_with_rot(parent->me->object, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, x * -1, y, -1, 0, 0x8000, 0); - obj->oMenuButtonScale = 0.11111111f; + + obj->oMenuButtonScale = scale; obj->oFaceAngleRoll = 0; obj->oMenuButtonTimer = 0; obj->oMenuButtonOrigPosX = obj->oParentRelativePosX; @@ -57,8 +63,8 @@ struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, ch return button; } -struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y) { - struct CustomMenuButton* button = custom_menu_create_button(parent, label, x, y, SOUND_MENU_CAMERA_ZOOM_IN, NULL); +struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale) { + struct CustomMenuButton* button = custom_menu_create_button(parent, label, x, y, scale, SOUND_MENU_CAMERA_ZOOM_IN, NULL); struct CustomMenu* menu = calloc(1, sizeof(struct CustomMenu)); menu->parent = parent; menu->depth = parent->depth + 1; @@ -183,13 +189,15 @@ void custom_menu_close_system(void) { static s32 cursor_inside_button(struct CustomMenuButton* button, f32 cursorX, f32 cursorY) { f32 x = button->object->oParentRelativePosX; f32 y = button->object->oParentRelativePosY; + f32 scale = button->object->oMenuButtonScale; + x *= -0.137f; y *= 0.137f; - s16 maxX = x + 25.0f; - s16 minX = x - 25.0f; - s16 maxY = y + 21.0f; - s16 minY = y - 21.0f; + s16 maxX = x + scale * 185.0f; + s16 minX = x - scale * 185.0f; + s16 maxY = y + scale * 185.0f; + s16 minY = y - scale * 101.0f; return (cursorX < maxX && minX < cursorX && cursorY < maxY && minY < cursorY); } @@ -236,7 +244,7 @@ void custom_menu_cursor_click(f32 cursorX, f32 cursorY) { } if (didSomething) { break; } - } + } button = button->next; } } @@ -254,7 +262,7 @@ void custom_menu_print_strings(void) { // figure out alpha struct Object* curObj = sCurrentMenu->me->object; struct Object* lastObj = (sLastMenu != NULL) ? sLastMenu->me->object : NULL; - + if (curObj != NULL && lastObj != NULL) { if (curObj->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN && lastObj->oMenuButtonState != MENU_BUTTON_STATE_SHRINKING) { if (gMenuStringAlpha < 250) { @@ -398,4 +406,4 @@ void custom_menu_error(char* message) { item = item->next; } } -} \ No newline at end of file +} diff --git a/src/menu/custom_menu_system.h b/src/menu/custom_menu_system.h index 9bc5ed70..f2e998d4 100644 --- a/src/menu/custom_menu_system.h +++ b/src/menu/custom_menu_system.h @@ -21,11 +21,18 @@ struct CustomMenu { void (*on_close)(void); }; +struct CustomMenuButtonScale { + f32 small; + f32 medium; + f32 large; +}; +extern struct CustomMenuButtonScale gButtonScale; + extern u8 gMenuStringAlpha; void custom_menu_system_init(void); -struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y); -struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, s32 clickSound, void (*on_click)(void)); +struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale); +struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale, s32 clickSound, void (*on_click)(void)); void custom_menu_system_loop(void); void custom_menu_print_strings(void); diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 0e033076..da56a239 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -92,6 +92,7 @@ bool configCameraAnalog = true; bool configCameraMouse = false; #endif bool configSkipIntro = 0; +bool configShareLives = 0; bool configHUD = true; #ifdef DISCORDRPC bool configDiscordRPC = true; @@ -151,6 +152,7 @@ static const struct ConfigOption options[] = { {.name = "bettercam_degrade", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraDegrade}, #endif {.name = "skip_intro", .type = CONFIG_TYPE_BOOL, .boolValue = &configSkipIntro}, + {.name = "share_lives", .type = CONFIG_TYPE_BOOL, .boolValue = &configShareLives}, #ifdef DISCORDRPC {.name = "discordrpc_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configDiscordRPC}, #endif diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 9cae3866..a6cae697 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -60,6 +60,7 @@ extern bool configCameraAnalog; #endif extern bool configHUD; extern bool configSkipIntro; +extern bool configShareLives; #ifdef DISCORDRPC extern bool configDiscordRPC; #endif diff --git a/src/pc/network/network.c b/src/pc/network/network.c index ae015302..b9f9a6b7 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -28,6 +28,8 @@ struct StringLinkedList gRegisteredMods = { 0 }; struct ServerSettings gServerSettings = { .playerInteractions = PLAYER_INTERACTIONS_SOLID, .playerKnockbackStrength = 25, + .skipIntro = 0, + .shareLives = 0, }; void network_set_system(enum NetworkSystemType nsType) { @@ -51,6 +53,8 @@ bool network_init(enum NetworkType inNetworkType) { gServerSettings.playerInteractions = configPlayerInteraction; gServerSettings.playerKnockbackStrength = configPlayerKnockbackStrength; gServerSettings.stayInLevelAfterStar = configStayInLevelAfterStar; + gServerSettings.skipIntro = configSkipIntro; + gServerSettings.shareLives = configShareLives; // initialize the network system int rc = gNetworkSystem->initialize(inNetworkType); diff --git a/src/pc/network/network.h b/src/pc/network/network.h index fc82ca1c..e8f459cb 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -74,6 +74,8 @@ struct ServerSettings { enum PlayerInteractions playerInteractions; u8 playerKnockbackStrength; u8 stayInLevelAfterStar; + u8 skipIntro; + u8 shareLives; }; // Networking-specific externs diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index d2e185f8..800cc8db 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -55,6 +55,7 @@ void packet_receive(struct Packet* p) { case PACKET_SAVE_FILE: network_receive_save_file(p); break; case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break; case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break; + case PACKET_DEATH: network_receive_death(p); break; /// case PACKET_CUSTOM: network_receive_custom(p); break; default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); @@ -73,4 +74,4 @@ void packet_receive(struct Packet* p) { } } } -} \ No newline at end of file +} diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 969ca941..a5b1b036 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -32,6 +32,7 @@ enum PacketType { PACKET_SAVE_FILE, PACKET_INSTANT_WARP, PACKET_NETWORK_PLAYERS, + PACKET_DEATH, /// PACKET_CUSTOM = 255, }; diff --git a/src/pc/network/packets/packet_death.c b/src/pc/network/packets/packet_death.c new file mode 100644 index 00000000..67bf7cf4 --- /dev/null +++ b/src/pc/network/packets/packet_death.c @@ -0,0 +1,20 @@ +#include +#include "sm64.h" +#include "../network.h" + +extern struct MarioState gMarioStates[]; + +void network_send_death(void) { + if (gMarioStates[0].numLives < -1) { gMarioStates[0].numLives = -1; } + struct Packet p = { 0 }; + packet_init(&p, PACKET_DEATH, true, false); + packet_write(&p, &gMarioStates[0].numLives, sizeof(u8)); + network_send(&p); +} +void network_receive_death(struct Packet* p) { + u8 numLives = 0; + packet_read(p, &numLives, sizeof(u8)); + if (numLives < gMarioStates[0].numLives) { + gMarioStates[0].numLives = numLives; + } +} diff --git a/src/pc/network/packets/packet_join.c b/src/pc/network/packets/packet_join.c index fbc4aa48..ad7307ee 100644 --- a/src/pc/network/packets/packet_join.c +++ b/src/pc/network/packets/packet_join.c @@ -61,6 +61,8 @@ void network_send_join(struct Packet* joinRequestPacket) { packet_write(&p, &gServerSettings.playerInteractions, sizeof(u8)); packet_write(&p, &gServerSettings.playerKnockbackStrength, sizeof(u8)); packet_write(&p, &gServerSettings.stayInLevelAfterStar, sizeof(u8)); + packet_write(&p, &gServerSettings.skipIntro, sizeof(u8)); + packet_write(&p, &gServerSettings.shareLives, sizeof(u8)); packet_write(&p, eeprom, sizeof(u8) * 512); u8 modCount = string_linked_list_count(&gRegisteredMods); @@ -124,6 +126,8 @@ void network_receive_join(struct Packet* p) { packet_read(p, &gServerSettings.playerInteractions, sizeof(u8)); packet_read(p, &gServerSettings.playerKnockbackStrength, sizeof(u8)); packet_read(p, &gServerSettings.stayInLevelAfterStar, sizeof(u8)); + packet_read(p, &gServerSettings.skipIntro, sizeof(u8)); + packet_read(p, &gServerSettings.shareLives, sizeof(u8)); packet_read(p, eeprom, sizeof(u8) * 512); packet_read(p, &modCount, sizeof(u8));