Complete rewrite of custom main menu
The vanilla main menu is an awful pile of code that is extremely painful to make additions to. So I've side-stepped the problem by writing an entiely new menu system without all of vanilla's quirks. I've separated the custom menu system from the menus I want to make, which allows for easy additions and a clear separation of responsibilities. Along with this rewrite comes a host menu, adding the missing configuration options in-game. Fixes #29
This commit is contained in:
parent
3e1b193ea8
commit
5abd0ca1ab
|
@ -82,6 +82,11 @@ ALIGNED8 static const u8 texture_hud_char_I[] = {
|
||||||
#include "textures/segment2/segment2.02400.rgba16.inc.c"
|
#include "textures/segment2/segment2.02400.rgba16.inc.c"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ALIGNED8 static const u8 texture_hud_char_J[] = {
|
||||||
|
#include "textures/segment2/custom_hud_j.rgba16.inc.c"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#if defined(VERSION_JP) || defined(VERSION_SH)
|
#if defined(VERSION_JP) || defined(VERSION_SH)
|
||||||
ALIGNED8 static const u8 texture_hud_char_J[] = {
|
ALIGNED8 static const u8 texture_hud_char_J[] = {
|
||||||
#include "textures/segment2/segment2.02600.rgba16.inc.c"
|
#include "textures/segment2/segment2.02600.rgba16.inc.c"
|
||||||
|
@ -1811,7 +1816,7 @@ const u8 *const main_hud_lut[] = {
|
||||||
texture_hud_char_4, texture_hud_char_5, texture_hud_char_6, texture_hud_char_7,
|
texture_hud_char_4, texture_hud_char_5, texture_hud_char_6, texture_hud_char_7,
|
||||||
texture_hud_char_8, texture_hud_char_9, texture_hud_char_A, texture_hud_char_B,
|
texture_hud_char_8, texture_hud_char_9, texture_hud_char_A, texture_hud_char_B,
|
||||||
texture_hud_char_C, texture_hud_char_D, texture_hud_char_E, texture_hud_char_F,
|
texture_hud_char_C, texture_hud_char_D, texture_hud_char_E, texture_hud_char_F,
|
||||||
texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, 0x0,
|
texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, texture_hud_char_J,
|
||||||
texture_hud_char_K, texture_hud_char_L, texture_hud_char_M, texture_hud_char_N,
|
texture_hud_char_K, texture_hud_char_L, texture_hud_char_M, texture_hud_char_N,
|
||||||
texture_hud_char_O, texture_hud_char_P, 0x0, texture_hud_char_R,
|
texture_hud_char_O, texture_hud_char_P, 0x0, texture_hud_char_R,
|
||||||
texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, texture_hud_char_V,
|
texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, texture_hud_char_V,
|
||||||
|
@ -1827,7 +1832,7 @@ const u8 *const main_hud_lut[] = {
|
||||||
texture_hud_char_4, texture_hud_char_5, texture_hud_char_6, texture_hud_char_7,
|
texture_hud_char_4, texture_hud_char_5, texture_hud_char_6, texture_hud_char_7,
|
||||||
texture_hud_char_8, texture_hud_char_9, texture_hud_char_A, texture_hud_char_B,
|
texture_hud_char_8, texture_hud_char_9, texture_hud_char_A, texture_hud_char_B,
|
||||||
texture_hud_char_C, texture_hud_char_D, texture_hud_char_E, texture_hud_char_F,
|
texture_hud_char_C, texture_hud_char_D, texture_hud_char_E, texture_hud_char_F,
|
||||||
texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, 0x0,
|
texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, texture_hud_char_J,
|
||||||
texture_hud_char_K, texture_hud_char_L, texture_hud_char_M, texture_hud_char_N,
|
texture_hud_char_K, texture_hud_char_L, texture_hud_char_M, texture_hud_char_N,
|
||||||
texture_hud_char_O, texture_hud_char_P, 0x0, texture_hud_char_R,
|
texture_hud_char_O, texture_hud_char_P, 0x0, texture_hud_char_R,
|
||||||
texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, 0x0,
|
texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, 0x0,
|
||||||
|
|
|
@ -3918,7 +3918,9 @@
|
||||||
<ClCompile Include="..\src\goddard\shape_helper.c" />
|
<ClCompile Include="..\src\goddard\shape_helper.c" />
|
||||||
<ClCompile Include="..\src\goddard\skin.c" />
|
<ClCompile Include="..\src\goddard\skin.c" />
|
||||||
<ClCompile Include="..\src\goddard\skin_movement.c" />
|
<ClCompile Include="..\src\goddard\skin_movement.c" />
|
||||||
|
<ClCompile Include="..\src\menu\custom_menu.c" />
|
||||||
<ClCompile Include="..\src\menu\file_select.c" />
|
<ClCompile Include="..\src\menu\file_select.c" />
|
||||||
|
<ClCompile Include="..\src\menu\custom_menu_system.c" />
|
||||||
<ClCompile Include="..\src\menu\intro_geo.c" />
|
<ClCompile Include="..\src\menu\intro_geo.c" />
|
||||||
<ClCompile Include="..\src\menu\level_select_menu.c" />
|
<ClCompile Include="..\src\menu\level_select_menu.c" />
|
||||||
<ClCompile Include="..\src\menu\star_select.c" />
|
<ClCompile Include="..\src\menu\star_select.c" />
|
||||||
|
@ -4311,6 +4313,8 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\include\behavior_table.h" />
|
<ClInclude Include="..\include\behavior_table.h" />
|
||||||
|
<ClInclude Include="..\src\menu\custom_menu.h" />
|
||||||
|
<ClInclude Include="..\src\menu\custom_menu_system.h" />
|
||||||
<ClInclude Include="..\src\pc\controller\controller_keyboard_debug.h" />
|
<ClInclude Include="..\src\pc\controller\controller_keyboard_debug.h" />
|
||||||
<ClInclude Include="..\src\pc\debuglog.h" />
|
<ClInclude Include="..\src\pc\debuglog.h" />
|
||||||
<ClInclude Include="..\src\pc\network\discord\activity.h" />
|
<ClInclude Include="..\src\pc\network\discord\activity.h" />
|
||||||
|
|
|
@ -15036,6 +15036,12 @@
|
||||||
<ClCompile Include="..\src\pc\network\discord\discord_network.c">
|
<ClCompile Include="..\src\pc\network\discord\discord_network.c">
|
||||||
<Filter>Source Files\src\pc\network\discord</Filter>
|
<Filter>Source Files\src\pc\network\discord</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\menu\custom_menu_system.c">
|
||||||
|
<Filter>Source Files\src\menu</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\menu\custom_menu.c">
|
||||||
|
<Filter>Source Files\src\menu</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\actors\common0.h">
|
<ClCompile Include="..\actors\common0.h">
|
||||||
|
@ -15976,5 +15982,11 @@
|
||||||
<ClInclude Include="..\src\pc\network\discord\discord_network.h">
|
<ClInclude Include="..\src\pc\network\discord\discord_network.h">
|
||||||
<Filter>Header Files\src\pc\network\discord</Filter>
|
<Filter>Header Files\src\pc\network\discord</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\menu\custom_menu_system.h">
|
||||||
|
<Filter>Header Files\src\menu</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\menu\custom_menu.h">
|
||||||
|
<Filter>Header Files\src\menu</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -672,6 +672,7 @@
|
||||||
#define /*0x104*/ oMenuButtonOrigPosZ OBJECT_FIELD_F32(0x1F)
|
#define /*0x104*/ oMenuButtonOrigPosZ OBJECT_FIELD_F32(0x1F)
|
||||||
#define /*0x108*/ oMenuButtonScale OBJECT_FIELD_F32(0x20)
|
#define /*0x108*/ oMenuButtonScale OBJECT_FIELD_F32(0x20)
|
||||||
#define /*0x10C*/ oMenuButtonActionPhase OBJECT_FIELD_S32(0x21)
|
#define /*0x10C*/ oMenuButtonActionPhase OBJECT_FIELD_S32(0x21)
|
||||||
|
#define /*0x110*/ oMenuButtonIsCustom OBJECT_FIELD_S32(0x22)
|
||||||
|
|
||||||
/* Manta Ray */
|
/* Manta Ray */
|
||||||
#define /*0x0F4*/ oMantaUnkF4 OBJECT_FIELD_S32(0x1B)
|
#define /*0x0F4*/ oMantaUnkF4 OBJECT_FIELD_S32(0x1B)
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "custom_menu.h"
|
||||||
|
#include "custom_menu_system.h"
|
||||||
|
#include "pc/network/network.h"
|
||||||
|
|
||||||
|
#include "pc/configfile.h"
|
||||||
|
#include "pc/controller/controller_keyboard.h"
|
||||||
|
#include "game/object_list_processor.h"
|
||||||
|
#include "game/object_helpers.h"
|
||||||
|
#include "game/ingame_menu.h"
|
||||||
|
#include "game/game_init.h"
|
||||||
|
#include "game/segment2.h"
|
||||||
|
#include "object_fields.h"
|
||||||
|
#include "model_ids.h"
|
||||||
|
#include "behavior_data.h"
|
||||||
|
|
||||||
|
#define MAIN_MENU_HEADER_TEXT "SM64 COOP"
|
||||||
|
|
||||||
|
char gConnectionJoinError[128] = { 0 };
|
||||||
|
char gConnectionText[128] = { 0 };
|
||||||
|
struct CustomMenu* sConnectMenu = NULL;
|
||||||
|
u8 gOpenConnectMenu = FALSE;
|
||||||
|
s8 sGotoGame = 0;
|
||||||
|
|
||||||
|
static void menu_main_draw_strings(void) {
|
||||||
|
print_generic_ascii_string(98, 150, "Still in early development.");
|
||||||
|
u8 red = (gGlobalTimer % 20 > 10) ? 0 : 222;
|
||||||
|
if (gGlobalTimer > 200) { red = 222; }
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 222, red, red, gMenuStringAlpha);
|
||||||
|
print_generic_ascii_string(50, 55, "Levels after Bowser 1 don't synchronize yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_menu_draw_strings(void) {
|
||||||
|
// set up server setting strings
|
||||||
|
char* buttonText[4];
|
||||||
|
buttonText[0] = (configNetworkSystem == 0) ? "Host through Discord." : "Host direct connection.";
|
||||||
|
switch (configPlayerInteraction) {
|
||||||
|
case 0: buttonText[1] = "Non-solid players."; break;
|
||||||
|
case 1: buttonText[1] = "Solid players."; break;
|
||||||
|
case 2: buttonText[1] = "Friendly fire."; break;
|
||||||
|
default: buttonText[1] = "UNKNOWN"; break;
|
||||||
|
}
|
||||||
|
if (configPlayerKnockbackStrength <= 20) {
|
||||||
|
buttonText[2] = "Weak knockback.";
|
||||||
|
} else if (configPlayerKnockbackStrength <= 40) {
|
||||||
|
buttonText[2] = "Normal knockback.";
|
||||||
|
} else {
|
||||||
|
buttonText[2] = "Too much knockback.";
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonText[3] = configStayInLevelAfterStar ? "Stay in level after star." : "Leave level after star.";
|
||||||
|
|
||||||
|
// display server setting strings
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
print_generic_ascii_string(95, 158 + -35 * 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_menu_do_host(void) {
|
||||||
|
if (configNetworkSystem == 0) {
|
||||||
|
network_set_system(NS_DISCORD);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
network_set_system(NS_SOCKET);
|
||||||
|
}
|
||||||
|
custom_menu_close_system();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_menu_setting_network_system(void) {
|
||||||
|
configNetworkSystem = (configNetworkSystem == 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_menu_setting_interaction(void) {
|
||||||
|
switch (configPlayerInteraction) {
|
||||||
|
case 0: configPlayerInteraction = 1; break;
|
||||||
|
case 1: configPlayerInteraction = 2; break;
|
||||||
|
default: configPlayerInteraction = 0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_menu_setting_knockback(void) {
|
||||||
|
if (configPlayerKnockbackStrength <= 20) {
|
||||||
|
configPlayerKnockbackStrength = 25;
|
||||||
|
} else if (configPlayerKnockbackStrength <= 40) {
|
||||||
|
configPlayerKnockbackStrength = 75;
|
||||||
|
} else {
|
||||||
|
configPlayerKnockbackStrength = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_menu_setting_stay_in_level(void) {
|
||||||
|
configStayInLevelAfterStar = (configStayInLevelAfterStar == 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void join_menu_draw_strings(void) {
|
||||||
|
print_generic_ascii_string(30, 155, "Accept a Discord game invite in order to join.");
|
||||||
|
print_generic_ascii_string(30, 130, "For direct connections, click connect to type in an IP.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connect_menu_draw_strings(void) {
|
||||||
|
if (gNetworkType == NT_CLIENT) {
|
||||||
|
f32 alpha = (f32)fabs(sin(gGlobalTimer / 20.0f));
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 222, 222, 222, gMenuStringAlpha * alpha);
|
||||||
|
print_generic_ascii_string(130, 130, "Connecting...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*gConnectionJoinError) {
|
||||||
|
f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f));
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha);
|
||||||
|
print_generic_ascii_string(30, 130, gConnectionJoinError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_generic_ascii_string(30, 175, "Type in or paste the host's IP.");
|
||||||
|
print_generic_ascii_string(30, 160, "Note - the host must forward a port on their router.");
|
||||||
|
|
||||||
|
if (keyboard_in_text_input()) {
|
||||||
|
if (strlen(gTextInput) >= 7) {
|
||||||
|
print_generic_ascii_string(30, 100, "Press (ENTER) to connect.");
|
||||||
|
} else {
|
||||||
|
print_generic_ascii_string(30, 100, "Press (ESC) to cancel.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 130, 222, 140, gMenuStringAlpha);
|
||||||
|
print_generic_ascii_string(30, 130, gTextInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connect_menu_on_connection_attempt(void) {
|
||||||
|
keyboard_stop_text_input();
|
||||||
|
if (gNetworkType != NT_NONE) { return; }
|
||||||
|
|
||||||
|
char delims[2] = " ";
|
||||||
|
|
||||||
|
// copy input
|
||||||
|
char buffer[MAX_TEXT_INPUT] = { 0 };
|
||||||
|
strncpy(buffer, gTextInput, MAX_TEXT_INPUT);
|
||||||
|
char* text = buffer;
|
||||||
|
|
||||||
|
// trim whitespace
|
||||||
|
while (*text == ' ') { text++; }
|
||||||
|
|
||||||
|
// grab IP
|
||||||
|
char* ip = strtok(text, delims);
|
||||||
|
if (ip == NULL) { custom_menu_close(); return; }
|
||||||
|
strncpy(configJoinIp, ip, MAX_CONFIG_STRING);
|
||||||
|
|
||||||
|
// grab port
|
||||||
|
char* port = strtok(NULL, delims);
|
||||||
|
if (port != NULL) {
|
||||||
|
unsigned int intPort = atoi(port);
|
||||||
|
if (intPort == 0) { custom_menu_close(); return; }
|
||||||
|
configJoinPort = intPort;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
configJoinPort = DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
network_set_system(NS_SOCKET);
|
||||||
|
network_init(NT_CLIENT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connect_menu_on_click(void) {
|
||||||
|
gConnectionJoinError[0] = '\0';
|
||||||
|
|
||||||
|
keyboard_start_text_input(TIM_IP, custom_menu_close, connect_menu_on_connection_attempt);
|
||||||
|
|
||||||
|
// fill in our last attempt
|
||||||
|
if (configJoinPort == 0) { configJoinPort = DEFAULT_PORT; }
|
||||||
|
sprintf(gTextInput, "%s %d", configJoinIp, configJoinPort);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connect_menu_on_close(void) {
|
||||||
|
keyboard_stop_text_input();
|
||||||
|
network_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_init(struct CustomMenu* head) {
|
||||||
|
|
||||||
|
// set the header text
|
||||||
|
head->me->label = calloc(strlen(MAIN_MENU_HEADER_TEXT) + 1, sizeof(char));
|
||||||
|
strcpy(head->me->label, MAIN_MENU_HEADER_TEXT);
|
||||||
|
|
||||||
|
// set main menu settings
|
||||||
|
head->headerY = 55;
|
||||||
|
head->draw_strings = menu_main_draw_strings;
|
||||||
|
|
||||||
|
// create sub menus and buttons
|
||||||
|
struct CustomMenu* hostMenu = custom_menu_create(head, "HOST", -266, 0);
|
||||||
|
hostMenu->draw_strings = host_menu_draw_strings;
|
||||||
|
custom_menu_create_button(hostMenu, "CANCEL", 700, -400 + (250 * 3), custom_menu_close);
|
||||||
|
custom_menu_create_button(hostMenu, "HOST", 700, -400, host_menu_do_host);
|
||||||
|
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 3), host_menu_setting_network_system);
|
||||||
|
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 2), host_menu_setting_interaction);
|
||||||
|
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 1), host_menu_setting_knockback);
|
||||||
|
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 0), host_menu_setting_stay_in_level);
|
||||||
|
|
||||||
|
struct CustomMenu* joinMenu = custom_menu_create(head, "JOIN", 266, 0);
|
||||||
|
custom_menu_create_button(joinMenu, "CANCEL", -266, -320, custom_menu_close);
|
||||||
|
joinMenu->draw_strings = join_menu_draw_strings;
|
||||||
|
|
||||||
|
struct CustomMenu* connectMenu = custom_menu_create(joinMenu, "CONNECT", 266, -320);
|
||||||
|
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, custom_menu_close);
|
||||||
|
sConnectMenu = connectMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_loop(void) {
|
||||||
|
// we've received an event that makes us exit the menus
|
||||||
|
if (sGotoGame) { sSelectedFileNum = sGotoGame; }
|
||||||
|
|
||||||
|
// force-start the load when command-line server hosting
|
||||||
|
if (gNetworkType == NT_SERVER && sSelectedFileNum == 0) {
|
||||||
|
sSelectedFileNum = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gOpenConnectMenu && sConnectMenu != NULL) {
|
||||||
|
gOpenConnectMenu = FALSE;
|
||||||
|
custom_menu_open(sConnectMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_on_load_save_file(s8 saveFileNum) {
|
||||||
|
if (gNetworkType != NT_CLIENT && saveFileNum != 0) {
|
||||||
|
configHostSaveSlot = saveFileNum;
|
||||||
|
network_init(NT_SERVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_goto_game(s16 saveFileNum) {
|
||||||
|
sGotoGame = saveFileNum;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef CUSTOM_MENU_H
|
||||||
|
#define CUSTOM_MENU_H
|
||||||
|
#include "custom_menu_system.h"
|
||||||
|
|
||||||
|
extern char gConnectionJoinError[];
|
||||||
|
extern u8 gOpenConnectMenu;
|
||||||
|
|
||||||
|
void custom_menu_init(struct CustomMenu* head);
|
||||||
|
void custom_menu_loop(void);
|
||||||
|
void custom_menu_on_load_save_file(s8 saveFileNum);
|
||||||
|
void custom_menu_goto_game(s16 saveFileNum);
|
||||||
|
|
||||||
|
#endif // CUSTOM_MENU_H
|
|
@ -0,0 +1,323 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "custom_menu_system.h"
|
||||||
|
#include "custom_menu.h"
|
||||||
|
|
||||||
|
#include "game/object_list_processor.h"
|
||||||
|
#include "game/object_helpers.h"
|
||||||
|
#include "game/ingame_menu.h"
|
||||||
|
#include "game/game_init.h"
|
||||||
|
#include "game/segment2.h"
|
||||||
|
#include "object_fields.h"
|
||||||
|
#include "model_ids.h"
|
||||||
|
#include "behavior_data.h"
|
||||||
|
#include "audio_defines.h"
|
||||||
|
#include "audio/external.h"
|
||||||
|
|
||||||
|
#define MAIN_MENU_HEADER_TEXT "SM64 COOP"
|
||||||
|
|
||||||
|
static struct CustomMenu* sHead = NULL;
|
||||||
|
static struct CustomMenu* sCurrentMenu = NULL;
|
||||||
|
static struct CustomMenu* sLastMenu = NULL;
|
||||||
|
u8 gMenuStringAlpha = 255;
|
||||||
|
|
||||||
|
struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, void (*on_click)(void)) {
|
||||||
|
struct CustomMenuButton* button = calloc(1, sizeof(struct CustomMenuButton));
|
||||||
|
if (parent->buttons == NULL) {
|
||||||
|
parent->buttons = button;
|
||||||
|
} else {
|
||||||
|
struct CustomMenuButton* parentButton = parent->buttons;
|
||||||
|
while (parentButton->next != NULL) { parentButton = parentButton->next; }
|
||||||
|
parentButton->next = button;
|
||||||
|
}
|
||||||
|
button->label = calloc(strlen(label), sizeof(char) + 1);
|
||||||
|
strcpy(button->label, label);
|
||||||
|
|
||||||
|
button->on_click = on_click;
|
||||||
|
|
||||||
|
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->oFaceAngleRoll = 0;
|
||||||
|
obj->oMenuButtonTimer = 0;
|
||||||
|
obj->oMenuButtonOrigPosX = obj->oParentRelativePosX;
|
||||||
|
obj->oMenuButtonOrigPosY = obj->oParentRelativePosY;
|
||||||
|
obj->oMenuButtonOrigPosZ = obj->oParentRelativePosZ;
|
||||||
|
obj->oMenuButtonIsCustom = 1;
|
||||||
|
obj->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT;
|
||||||
|
button->object = obj;
|
||||||
|
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, NULL);
|
||||||
|
struct CustomMenu* menu = calloc(1, sizeof(struct CustomMenu));
|
||||||
|
menu->parent = parent;
|
||||||
|
menu->depth = parent->depth + 1;
|
||||||
|
menu->headerY = 25;
|
||||||
|
menu->me = button;
|
||||||
|
button->menu = menu;
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_system_init(void) {
|
||||||
|
|
||||||
|
// allocate the main menu and set it to current
|
||||||
|
sHead = calloc(1, sizeof(struct CustomMenu));
|
||||||
|
sHead->me = calloc(1, sizeof(struct CustomMenuButton));
|
||||||
|
sCurrentMenu = sHead;
|
||||||
|
|
||||||
|
// spawn the main menu game object
|
||||||
|
struct Object* obj = spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, 0, 0, 0, 0, 0, 0);
|
||||||
|
obj->oParentRelativePosZ += 1000;
|
||||||
|
obj->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN;
|
||||||
|
obj->oFaceAngleYaw = 0x8000;
|
||||||
|
obj->oFaceAngleRoll = 0;
|
||||||
|
obj->oMenuButtonScale = 9.0f;
|
||||||
|
obj->oMenuButtonOrigPosZ = obj->oPosZ;
|
||||||
|
obj->oMenuButtonOrigPosX = 99999;
|
||||||
|
obj->oMenuButtonIsCustom = 1;
|
||||||
|
sHead->me->object = obj;
|
||||||
|
|
||||||
|
custom_menu_init(sHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_destroy(void) {
|
||||||
|
/* TODO: we should probably clean up all of this stuff */
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_system_loop(void) {
|
||||||
|
custom_menu_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_force_instant_close(struct Object* obj) {
|
||||||
|
obj->oFaceAngleYaw = 0x8000;
|
||||||
|
obj->oFaceAnglePitch = 0;
|
||||||
|
obj->oParentRelativePosX = obj->oMenuButtonOrigPosX;
|
||||||
|
obj->oParentRelativePosY = obj->oMenuButtonOrigPosY;
|
||||||
|
obj->oParentRelativePosZ = obj->oMenuButtonOrigPosZ;
|
||||||
|
obj->oMenuButtonScale = 0.11111111f;
|
||||||
|
obj->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT;
|
||||||
|
obj->oMenuButtonTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_force_instant_open(struct Object* obj) {
|
||||||
|
obj->oFaceAngleYaw = 0;
|
||||||
|
obj->oFaceAnglePitch = 0;
|
||||||
|
obj->oParentRelativePosX = 0.0f;
|
||||||
|
obj->oParentRelativePosY = 0.0f;
|
||||||
|
obj->oParentRelativePosZ = -801;
|
||||||
|
obj->oMenuButtonScale = 0.623111;
|
||||||
|
obj->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN;
|
||||||
|
obj->oMenuButtonTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_open(struct CustomMenu* menu) {
|
||||||
|
if (sCurrentMenu == menu) { return; }
|
||||||
|
if (menu == NULL) { return; }
|
||||||
|
// force instant-close all parents if not a direct route
|
||||||
|
{
|
||||||
|
// check all buttons of current menu to see if the desired menu is directly beneath it
|
||||||
|
struct CustomMenuButton* onButton = sCurrentMenu->buttons;
|
||||||
|
u8 foundMenu = FALSE;
|
||||||
|
while (onButton != NULL) {
|
||||||
|
if (onButton == menu->me) { foundMenu = TRUE; break; }
|
||||||
|
onButton = onButton->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not direct route, force close all the way to the main menu
|
||||||
|
if (!foundMenu) {
|
||||||
|
struct CustomMenu* onMenu = sCurrentMenu;
|
||||||
|
while (onMenu != NULL && onMenu != sHead) {
|
||||||
|
struct Object* obj = onMenu->me->object;
|
||||||
|
if (obj->oMenuButtonState != MENU_BUTTON_STATE_FULLSCREEN) { break; }
|
||||||
|
button_force_instant_close(obj);
|
||||||
|
if (onMenu->on_close != NULL) { onMenu->on_close(); }
|
||||||
|
onMenu = onMenu->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// force instant-open all parents
|
||||||
|
{
|
||||||
|
struct CustomMenu* onMenu = menu->parent;
|
||||||
|
while (onMenu != NULL) {
|
||||||
|
struct Object* obj = onMenu->me->object;
|
||||||
|
if (obj->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { break; }
|
||||||
|
button_force_instant_open(obj);
|
||||||
|
onMenu = onMenu->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct Object* obj = menu->me->object;
|
||||||
|
obj->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
||||||
|
obj->oMenuButtonTimer = 0;
|
||||||
|
gMenuStringAlpha = 0;
|
||||||
|
sLastMenu = sCurrentMenu;
|
||||||
|
sCurrentMenu = menu;
|
||||||
|
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_close(void) {
|
||||||
|
struct Object* obj = sCurrentMenu->me->object;
|
||||||
|
obj->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING;
|
||||||
|
obj->oMenuButtonTimer = 0;
|
||||||
|
gMenuStringAlpha = 0;
|
||||||
|
if (sCurrentMenu->on_close != NULL) { sCurrentMenu->on_close(); }
|
||||||
|
sLastMenu = sCurrentMenu;
|
||||||
|
if (sCurrentMenu->parent != NULL) {
|
||||||
|
sCurrentMenu = sCurrentMenu->parent;
|
||||||
|
}
|
||||||
|
play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_close_system(void) {
|
||||||
|
sHead->me->object->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING;
|
||||||
|
gInCustomMenu = FALSE;
|
||||||
|
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 cursor_inside_button(struct CustomMenuButton* button, f32 cursorX, f32 cursorY) {
|
||||||
|
f32 x = button->object->oParentRelativePosX;
|
||||||
|
f32 y = button->object->oParentRelativePosY;
|
||||||
|
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;
|
||||||
|
|
||||||
|
return (cursorX < maxX && minX < cursorX && cursorY < maxY && minY < cursorY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_menu_cursor_click(f32 cursorX, f32 cursorY) {
|
||||||
|
#ifdef VERSION_EU
|
||||||
|
u16 cursorClickButtons = (A_BUTTON | B_BUTTON | START_BUTTON | Z_TRIG);
|
||||||
|
#else
|
||||||
|
u16 cursorClickButtons = (A_BUTTON | B_BUTTON | START_BUTTON);
|
||||||
|
#endif
|
||||||
|
if (!(gPlayer3Controller->buttonPressed & cursorClickButtons)) { return; }
|
||||||
|
if (sCurrentMenu->me->object->oMenuButtonState != MENU_BUTTON_STATE_FULLSCREEN) { return; }
|
||||||
|
|
||||||
|
struct CustomMenuButton* button = sCurrentMenu->buttons;
|
||||||
|
while (button != NULL) {
|
||||||
|
if (cursor_inside_button(button, cursorX, cursorY)) {
|
||||||
|
u8 didSomething = FALSE;
|
||||||
|
if (button->menu != NULL) { custom_menu_open(button->menu); didSomething = TRUE; }
|
||||||
|
if (button->on_click != NULL) { button->on_click(); didSomething = TRUE; }
|
||||||
|
if (didSomething) { break; }
|
||||||
|
}
|
||||||
|
button = button->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_label_pos(struct CustomMenuButton* button, s16* outX, s16* outY) {
|
||||||
|
f32 x = button->object->oParentRelativePosX;
|
||||||
|
f32 y = button->object->oParentRelativePosY;
|
||||||
|
x -= strlen(button->label) * -27.0f;
|
||||||
|
y += -163.0f;
|
||||||
|
*outX = 165.0f + x * -0.137f;
|
||||||
|
*outY = 110.0f + y * 0.137f;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
gMenuStringAlpha += 10;
|
||||||
|
} else {
|
||||||
|
gMenuStringAlpha = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print header
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gMenuStringAlpha);
|
||||||
|
char* headerLabel = sCurrentMenu->me->label;
|
||||||
|
u16 headerLabelLen = strlen(headerLabel);
|
||||||
|
u16 headerX = (u16)(159.66f - (headerLabelLen * 5.66f));
|
||||||
|
|
||||||
|
unsigned char header[64];
|
||||||
|
str_ascii_to_dialog(headerLabel, header, headerLabelLen);
|
||||||
|
|
||||||
|
print_hud_lut_string(HUD_LUT_DIFF, headerX, sCurrentMenu->headerY, header);
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||||
|
|
||||||
|
// print text
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||||
|
struct CustomMenuButton* button = sCurrentMenu->buttons;
|
||||||
|
while (button != NULL) {
|
||||||
|
gDPSetEnvColor(gDisplayListHead++, 222, 222, 222, gMenuStringAlpha);
|
||||||
|
s16 x, y;
|
||||||
|
button_label_pos(button, &x, &y);
|
||||||
|
print_generic_ascii_string(x, y, button->label);
|
||||||
|
button = button->next;
|
||||||
|
}
|
||||||
|
if (sCurrentMenu->draw_strings != NULL) { sCurrentMenu->draw_strings(); }
|
||||||
|
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grow from submenu, used by selecting a file in the score menu.
|
||||||
|
*/
|
||||||
|
void bhv_menu_button_growing_from_custom(struct Object* button) {
|
||||||
|
if (button->oMenuButtonTimer < 16) {
|
||||||
|
button->oFaceAngleYaw += 0x800;
|
||||||
|
}
|
||||||
|
if (button->oMenuButtonTimer < 8) {
|
||||||
|
button->oFaceAnglePitch += 0x800;
|
||||||
|
}
|
||||||
|
if (button->oMenuButtonTimer >= 8 && button->oMenuButtonTimer < 16) {
|
||||||
|
button->oFaceAnglePitch -= 0x800;
|
||||||
|
}
|
||||||
|
|
||||||
|
button->oParentRelativePosX -= button->oMenuButtonOrigPosX / 16.0;
|
||||||
|
button->oParentRelativePosY -= button->oMenuButtonOrigPosY / 16.0;
|
||||||
|
button->oParentRelativePosZ -= 50;
|
||||||
|
|
||||||
|
button->oMenuButtonScale += 0.032f;
|
||||||
|
|
||||||
|
button->oMenuButtonTimer++;
|
||||||
|
if (button->oMenuButtonTimer == 16) {
|
||||||
|
button->oParentRelativePosX = 0.0f;
|
||||||
|
button->oParentRelativePosY = 0.0f;
|
||||||
|
button->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN;
|
||||||
|
button->oMenuButtonTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shrink back to submenu, used to return back while inside a score save menu.
|
||||||
|
*/
|
||||||
|
void bhv_menu_button_shrinking_to_custom(struct Object* button) {
|
||||||
|
if (button->oMenuButtonTimer < 16) {
|
||||||
|
button->oFaceAngleYaw -= 0x800;
|
||||||
|
}
|
||||||
|
if (button->oMenuButtonTimer < 8) {
|
||||||
|
button->oFaceAnglePitch -= 0x800;
|
||||||
|
}
|
||||||
|
if (button->oMenuButtonTimer >= 8 && button->oMenuButtonTimer < 16) {
|
||||||
|
button->oFaceAnglePitch += 0x800;
|
||||||
|
}
|
||||||
|
|
||||||
|
button->oParentRelativePosX += button->oMenuButtonOrigPosX / 16.0;
|
||||||
|
button->oParentRelativePosY += button->oMenuButtonOrigPosY / 16.0;
|
||||||
|
button->oParentRelativePosZ += 50;
|
||||||
|
|
||||||
|
button->oMenuButtonScale -= 0.032f;
|
||||||
|
|
||||||
|
button->oMenuButtonTimer++;
|
||||||
|
if (button->oMenuButtonTimer == 16) {
|
||||||
|
button->oParentRelativePosX = button->oMenuButtonOrigPosX;
|
||||||
|
button->oParentRelativePosY = button->oMenuButtonOrigPosY;
|
||||||
|
button->oMenuButtonScale = 0.11111111f;
|
||||||
|
button->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT;
|
||||||
|
button->oMenuButtonTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef CUSTOM_MENU_SYSTEM_H
|
||||||
|
#define CUSTOM_MENU_SYSTEM_H
|
||||||
|
#include "file_select.h"
|
||||||
|
|
||||||
|
struct CustomMenuButton {
|
||||||
|
struct Object* object;
|
||||||
|
char* label;
|
||||||
|
void (*on_click)(void);
|
||||||
|
struct CustomMenu* menu;
|
||||||
|
struct CustomMenuButton* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CustomMenu {
|
||||||
|
struct CustomMenu* parent;
|
||||||
|
struct CustomMenuButton* me;
|
||||||
|
struct CustomMenuButton* buttons;
|
||||||
|
u16 headerY;
|
||||||
|
u16 depth;
|
||||||
|
void (*draw_strings)(void);
|
||||||
|
void (*on_close)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
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, void (*on_click)(void));
|
||||||
|
|
||||||
|
void custom_menu_system_loop(void);
|
||||||
|
void custom_menu_print_strings(void);
|
||||||
|
void custom_menu_cursor_click(f32 x, f32 y);
|
||||||
|
|
||||||
|
void custom_menu_open(struct CustomMenu* menu);
|
||||||
|
void custom_menu_close(void);
|
||||||
|
void custom_menu_close_system(void);
|
||||||
|
|
||||||
|
void bhv_menu_button_growing_from_custom(struct Object* button);
|
||||||
|
void bhv_menu_button_shrinking_to_custom(struct Object* button);
|
||||||
|
|
||||||
|
#endif // CUSTOM_MENU_SYSTEM_H
|
|
@ -21,19 +21,16 @@
|
||||||
#include "sm64.h"
|
#include "sm64.h"
|
||||||
#include "text_strings.h"
|
#include "text_strings.h"
|
||||||
|
|
||||||
#include "game/ingame_menu.h"
|
|
||||||
|
|
||||||
#include "eu_translation.h"
|
#include "eu_translation.h"
|
||||||
|
|
||||||
|
#include "custom_menu_system.h"
|
||||||
|
#include "custom_menu.h"
|
||||||
|
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
#undef LANGUAGE_FUNCTION
|
#undef LANGUAGE_FUNCTION
|
||||||
#define LANGUAGE_FUNCTION sLanguageMode
|
#define LANGUAGE_FUNCTION sLanguageMode
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "pc/configfile.h"
|
|
||||||
#include "pc/controller/controller_keyboard.h"
|
|
||||||
#include "pc/network/network.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file file_select.c
|
* @file file_select.c
|
||||||
* This file implements how the file select and it's menus render and function.
|
* This file implements how the file select and it's menus render and function.
|
||||||
|
@ -41,9 +38,8 @@
|
||||||
* special menu messages and phases, button states and button clicked checks.
|
* special menu messages and phases, button states and button clicked checks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u8 joinVersionMismatch = FALSE;
|
u8 gInCustomMenu = 1;
|
||||||
static char joinMenuCustomText[64] = { 0 };
|
u8 sIgnoreMenuTimer = 5;
|
||||||
static u8 forceOpenJoinMenu = 0;
|
|
||||||
|
|
||||||
#ifdef VERSION_US
|
#ifdef VERSION_US
|
||||||
// The current sound mode is automatically centered on US due to
|
// The current sound mode is automatically centered on US due to
|
||||||
|
@ -63,7 +59,7 @@ static s16 sSoundTextY;
|
||||||
#define NUM_BUTTONS 34
|
#define NUM_BUTTONS 34
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define NUM_BUTTONS 36
|
#define NUM_BUTTONS 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Amount of main menu buttons defined in the code called by spawn_object_rel_with_rot.
|
// Amount of main menu buttons defined in the code called by spawn_object_rel_with_rot.
|
||||||
|
@ -98,7 +94,7 @@ static u8 sTextBaseAlpha = 0;
|
||||||
|
|
||||||
// 2D position of the cursor on the screen.
|
// 2D position of the cursor on the screen.
|
||||||
// sCursorPos[0]: X | sCursorPos[1]: Y
|
// sCursorPos[0]: X | sCursorPos[1]: Y
|
||||||
static f32 sCursorPos[] = {0, 0};
|
f32 sCursorPos[] = {0, 0};
|
||||||
|
|
||||||
// Determines which graphic to use for the cursor.
|
// Determines which graphic to use for the cursor.
|
||||||
static s16 sCursorClickingTimer = 0;
|
static s16 sCursorClickingTimer = 0;
|
||||||
|
@ -144,7 +140,7 @@ static s8 sAllFilesExist = FALSE;
|
||||||
|
|
||||||
// Defines the value of the save slot selected in the menu.
|
// Defines the value of the save slot selected in the menu.
|
||||||
// Mario A: 1 | Mario B: 2 | Mario C: 3 | Mario D: 4
|
// Mario A: 1 | Mario B: 2 | Mario C: 3 | Mario D: 4
|
||||||
static s8 sSelectedFileNum = 0;
|
s8 sSelectedFileNum = 0;
|
||||||
|
|
||||||
// Which coin score mode to use when scoring files. 0 for local
|
// Which coin score mode to use when scoring files. 0 for local
|
||||||
// coin high score, 1 for high score across all files.
|
// coin high score, 1 for high score across all files.
|
||||||
|
@ -379,256 +375,10 @@ static void bhv_menu_button_growing_from_main_menu(struct Object *button) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------- //
|
|
||||||
// ------- custom network menu code ------- //
|
|
||||||
// ---------------------------------------- //
|
|
||||||
|
|
||||||
void exit_join_to_network_menu(void) {
|
|
||||||
// Begin exit
|
|
||||||
if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN
|
|
||||||
&& sCursorClickingTimer == 2) {
|
|
||||||
// clear custom text
|
|
||||||
joinMenuCustomText[0] = '\0';
|
|
||||||
|
|
||||||
play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs);
|
|
||||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING;
|
|
||||||
network_shutdown();
|
|
||||||
keyboard_stop_text_input();
|
|
||||||
}
|
|
||||||
// End exit
|
|
||||||
if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) {
|
|
||||||
sSelectedButtonID = MENU_BUTTON_NETWORK_MODE;
|
|
||||||
if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) {
|
|
||||||
sCurrentMenuLevel = MENU_LAYER_MAIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyboard_exit_join_to_network_menu(void) {
|
|
||||||
sCursorClickingTimer = 2;
|
|
||||||
exit_join_to_network_menu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void join_server_as_client(void) {
|
|
||||||
if (gNetworkType != NT_NONE) { return; }
|
|
||||||
|
|
||||||
char delims[2] = " ";
|
|
||||||
|
|
||||||
// copy input
|
|
||||||
char buffer[MAX_TEXT_INPUT] = { 0 };
|
|
||||||
strncpy(buffer, gTextInput, MAX_TEXT_INPUT);
|
|
||||||
char* text = buffer;
|
|
||||||
|
|
||||||
// trim whitespace
|
|
||||||
while (*text == ' ') { text++; }
|
|
||||||
|
|
||||||
// grab IP
|
|
||||||
char* ip = strtok(text, delims);
|
|
||||||
if (ip == NULL) {
|
|
||||||
exit_join_to_network_menu();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strncpy(configJoinIp, ip, MAX_CONFIG_STRING);
|
|
||||||
|
|
||||||
// grab port
|
|
||||||
char* port = strtok(NULL, delims);
|
|
||||||
if (port != NULL) {
|
|
||||||
unsigned int intPort = atoi(port);
|
|
||||||
if (intPort == 0) {
|
|
||||||
exit_join_to_network_menu();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
configJoinPort = intPort;
|
|
||||||
} else {
|
|
||||||
configJoinPort = DEFAULT_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard_stop_text_input();
|
|
||||||
joinVersionMismatch = FALSE;
|
|
||||||
network_init(NT_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void joined_server_as_client(s16 fileIndex) {
|
|
||||||
if (gNetworkType != NT_CLIENT) { return; }
|
|
||||||
sSelectedFileNum = fileIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void joined_server_version_mismatch(void) {
|
|
||||||
if (gNetworkType != NT_CLIENT) { return; }
|
|
||||||
joinVersionMismatch = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void render_network_mode_menu_buttons(struct Object* soundModeButton) {
|
|
||||||
#define NETWORK_BUTTON_Y 0
|
|
||||||
// Host option button
|
|
||||||
sMainMenuButtons[MENU_BUTTON_HOST] = spawn_object_rel_with_rot(
|
|
||||||
soundModeButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 266, NETWORK_BUTTON_Y, -100, 0, -0x8000, 0);
|
|
||||||
sMainMenuButtons[MENU_BUTTON_HOST]->oMenuButtonScale = 0.11111111f;
|
|
||||||
sMainMenuButtons[MENU_BUTTON_HOST]->oFaceAngleRoll = 0;
|
|
||||||
|
|
||||||
// Join option button
|
|
||||||
sMainMenuButtons[MENU_BUTTON_JOIN] = spawn_object_rel_with_rot(
|
|
||||||
soundModeButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -266, NETWORK_BUTTON_Y, -100, 0, -0x8000, 0);
|
|
||||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonScale = 0.11111111f;
|
|
||||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oFaceAngleRoll = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void open_join_menu(char* customText) {
|
|
||||||
if (sMainMenuButtons[MENU_BUTTON_JOIN] == NULL) {
|
|
||||||
forceOpenJoinMenu = (forceOpenJoinMenu == 0) ? 1 : forceOpenJoinMenu;
|
|
||||||
} else if (sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState != MENU_BUTTON_STATE_FULLSCREEN) {
|
|
||||||
forceOpenJoinMenu = 0;
|
|
||||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
|
||||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
|
||||||
sSelectedButtonID = MENU_BUTTON_JOIN;
|
|
||||||
sCurrentMenuLevel = MENU_LAYER_SUBMENU;
|
|
||||||
} else {
|
|
||||||
forceOpenJoinMenu = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customText == joinMenuCustomText) { return; }
|
|
||||||
|
|
||||||
if (customText != NULL) {
|
|
||||||
strncpy(joinMenuCustomText, customText, 63);
|
|
||||||
} else if (*gTextInput == '\0') {
|
|
||||||
joinMenuCustomText[0] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_network_mode_menu_clicked_buttons(struct Object* networkModeButton) {
|
|
||||||
if (networkModeButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
|
||||||
|
|
||||||
if (forceOpenJoinMenu && forceOpenJoinMenu++ > 3) {
|
|
||||||
forceOpenJoinMenu = 0;
|
|
||||||
open_join_menu(joinMenuCustomText);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 buttonID;
|
|
||||||
// Configure sound mode menu button group
|
|
||||||
for (buttonID = MENU_BUTTON_NETWORK_MIN; buttonID < MENU_BUTTON_NETWORK_MAX; buttonID++) {
|
|
||||||
s16 buttonX = sMainMenuButtons[buttonID]->oPosX;
|
|
||||||
s16 buttonY = sMainMenuButtons[buttonID]->oPosY;
|
|
||||||
|
|
||||||
if (check_clicked_button(buttonX, buttonY, 22.0f) == TRUE) {
|
|
||||||
if (buttonID == MENU_BUTTON_HOST) {
|
|
||||||
if (networkModeButton->oMenuButtonActionPhase == SOUND_MODE_PHASE_MAIN) {
|
|
||||||
play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs);
|
|
||||||
sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT;
|
|
||||||
sSelectedButtonID = buttonID;
|
|
||||||
//sSoundMode = buttonID - MENU_BUTTON_OPTION_MIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (buttonID == MENU_BUTTON_JOIN) {
|
|
||||||
open_join_menu(NULL);
|
|
||||||
|
|
||||||
// start input
|
|
||||||
keyboard_start_text_input(TIM_IP, keyboard_exit_join_to_network_menu, join_server_as_client);
|
|
||||||
|
|
||||||
// fill in config ip/port
|
|
||||||
static u8 openedJoinMenu = FALSE;
|
|
||||||
if (!openedJoinMenu && strlen(configJoinIp) > 0) {
|
|
||||||
if (configJoinPort == 0) { configJoinPort = DEFAULT_PORT; }
|
|
||||||
sprintf(gTextInput, "%s %d", configJoinIp, configJoinPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sCurrentMenuLevel = MENU_LAYER_SUBMENU;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_network_mode_menu_strings(void) {
|
|
||||||
s32 mode;
|
|
||||||
s16 textX;
|
|
||||||
#define HEADER_HUD_X 106
|
|
||||||
unsigned char textHeader[10];
|
|
||||||
str_ascii_to_dialog("SM64 COOP", textHeader, 9);
|
|
||||||
|
|
||||||
// Print header text
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
|
||||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
|
||||||
|
|
||||||
print_hud_lut_string(HUD_LUT_DIFF, HEADER_HUD_X, 55, textHeader);
|
|
||||||
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
|
||||||
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
|
||||||
|
|
||||||
#define TEXT_HOST 0x11,0x18,0x1C,0x1D,0xFF
|
|
||||||
#define TEXT_JOIN 0x13,0x18,0x12,0x17,0xFF
|
|
||||||
static unsigned char textNetworkModes[][5] = { { TEXT_HOST }, { TEXT_JOIN } };
|
|
||||||
|
|
||||||
// Print network mode names
|
|
||||||
for (mode = 0; mode < 2; mode++) {
|
|
||||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
|
||||||
|
|
||||||
textX = get_str_x_pos_from_center(mode * 72 + 124, textNetworkModes[mode], 10.0f);
|
|
||||||
print_generic_string(textX, 87, textNetworkModes[mode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print disclaimers
|
|
||||||
print_generic_ascii_string(98, 150, "Still in early development.");
|
|
||||||
print_generic_ascii_string(35, 34, "Levels after Bowser 1 don't synchronize yet.");
|
|
||||||
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_join_mode_menu_strings(void) {
|
|
||||||
#define JOIN_MARIO_X 25
|
|
||||||
#define JOIN_FILE_LETTER_X 95
|
|
||||||
#define JOIN_LEVEL_NAME_X 25
|
|
||||||
#define JOIN_SECRET_STARS_X 171
|
|
||||||
#define JOIN_MYSCORE_X 238
|
|
||||||
#define JOIN_HISCORE_X 231
|
|
||||||
|
|
||||||
unsigned char textMario[8];
|
|
||||||
str_ascii_to_dialog("CONNECT", textMario, 7);
|
|
||||||
|
|
||||||
// Print file name at top
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
|
||||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
|
||||||
print_hud_lut_string(HUD_LUT_DIFF, JOIN_MARIO_X, 15, textMario);
|
|
||||||
|
|
||||||
// Print course scores
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin);
|
|
||||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
|
||||||
|
|
||||||
// Print level name
|
|
||||||
if (joinMenuCustomText[0] != '\0') {
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 3), joinMenuCustomText);
|
|
||||||
} else {
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 0), "Accept a Discord invite.");
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 1), "Alternatively, type or paste the host's IP.");
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (14 * 3), gTextInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print status
|
|
||||||
if (joinVersionMismatch) {
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (13 * 14), "Error - versions don't match. Both should rebuild!");
|
|
||||||
} else if (gNetworkType == NT_CLIENT) {
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (13 * 14), "Connecting...");
|
|
||||||
} else if (strlen(gTextInput) > 0) {
|
|
||||||
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (13 * 14), "Press (ENTER) to directly connect.");
|
|
||||||
}
|
|
||||||
|
|
||||||
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------- //
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shrink back to main menu, used to return back while inside menus.
|
* Shrink back to main menu, used to return back while inside menus.
|
||||||
*/
|
*/
|
||||||
static void bhv_menu_button_shrinking_to_main_menu(struct Object *button) {
|
static void bhv_menu_button_shrinking_to_main_menu(struct Object *button) {
|
||||||
// hack, make sure network button goes off-screen
|
|
||||||
if (button == sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]) {
|
|
||||||
button->oMenuButtonOrigPosX = 0;
|
|
||||||
button->oMenuButtonOrigPosY = -9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button->oMenuButtonTimer < 16) {
|
if (button->oMenuButtonTimer < 16) {
|
||||||
button->oFaceAngleYaw -= 0x800;
|
button->oFaceAngleYaw -= 0x800;
|
||||||
}
|
}
|
||||||
|
@ -764,6 +514,7 @@ static void bhv_menu_button_zoom_out(struct Object *button) {
|
||||||
* positions when you choose a button.
|
* positions when you choose a button.
|
||||||
*/
|
*/
|
||||||
void bhv_menu_button_init(void) {
|
void bhv_menu_button_init(void) {
|
||||||
|
if (gCurrentObject->oMenuButtonIsCustom) { return; }
|
||||||
gCurrentObject->oMenuButtonOrigPosX = gCurrentObject->oParentRelativePosX;
|
gCurrentObject->oMenuButtonOrigPosX = gCurrentObject->oParentRelativePosX;
|
||||||
gCurrentObject->oMenuButtonOrigPosY = gCurrentObject->oParentRelativePosY;
|
gCurrentObject->oMenuButtonOrigPosY = gCurrentObject->oParentRelativePosY;
|
||||||
}
|
}
|
||||||
|
@ -779,10 +530,11 @@ void bhv_menu_button_loop(void) {
|
||||||
gCurrentObject->oMenuButtonOrigPosZ = gCurrentObject->oPosZ;
|
gCurrentObject->oMenuButtonOrigPosZ = gCurrentObject->oPosZ;
|
||||||
break;
|
break;
|
||||||
case MENU_BUTTON_STATE_GROWING: // Switching from button to menu state
|
case MENU_BUTTON_STATE_GROWING: // Switching from button to menu state
|
||||||
if (sCurrentMenuLevel == MENU_LAYER_MAIN) {
|
if (gInCustomMenu) {
|
||||||
|
bhv_menu_button_growing_from_custom(gCurrentObject);
|
||||||
|
} else if (sCurrentMenuLevel == MENU_LAYER_MAIN) {
|
||||||
bhv_menu_button_growing_from_main_menu(gCurrentObject);
|
bhv_menu_button_growing_from_main_menu(gCurrentObject);
|
||||||
}
|
} else if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) {
|
||||||
if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) {
|
|
||||||
bhv_menu_button_growing_from_submenu(gCurrentObject); // Only used for score files
|
bhv_menu_button_growing_from_submenu(gCurrentObject); // Only used for score files
|
||||||
}
|
}
|
||||||
sTextBaseAlpha = 0;
|
sTextBaseAlpha = 0;
|
||||||
|
@ -791,10 +543,11 @@ void bhv_menu_button_loop(void) {
|
||||||
case MENU_BUTTON_STATE_FULLSCREEN: // Menu state
|
case MENU_BUTTON_STATE_FULLSCREEN: // Menu state
|
||||||
break;
|
break;
|
||||||
case MENU_BUTTON_STATE_SHRINKING: // Switching from menu to button state
|
case MENU_BUTTON_STATE_SHRINKING: // Switching from menu to button state
|
||||||
if (sCurrentMenuLevel == MENU_LAYER_MAIN) {
|
if (gInCustomMenu) {
|
||||||
|
bhv_menu_button_shrinking_to_custom(gCurrentObject);
|
||||||
|
} else if (sCurrentMenuLevel == MENU_LAYER_MAIN) {
|
||||||
bhv_menu_button_shrinking_to_main_menu(gCurrentObject);
|
bhv_menu_button_shrinking_to_main_menu(gCurrentObject);
|
||||||
}
|
} else if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) {
|
||||||
if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) {
|
|
||||||
bhv_menu_button_shrinking_to_submenu(gCurrentObject); // Only used for score files
|
bhv_menu_button_shrinking_to_submenu(gCurrentObject); // Only used for score files
|
||||||
}
|
}
|
||||||
sTextBaseAlpha = 0;
|
sTextBaseAlpha = 0;
|
||||||
|
@ -1279,17 +1032,14 @@ void render_sound_mode_menu_buttons(struct Object *soundModeButton) {
|
||||||
sMainMenuButtons[MENU_BUTTON_STEREO] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_STEREO] = spawn_object_rel_with_rot(
|
||||||
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_STEREO]->oMenuButtonScale = 0.11111111f;
|
sMainMenuButtons[MENU_BUTTON_STEREO]->oMenuButtonScale = 0.11111111f;
|
||||||
sMainMenuButtons[MENU_BUTTON_STEREO]->oFaceAngleRoll = 0;
|
|
||||||
// Mono option button
|
// Mono option button
|
||||||
sMainMenuButtons[MENU_BUTTON_MONO] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_MONO] = spawn_object_rel_with_rot(
|
||||||
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 0, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 0, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_MONO]->oMenuButtonScale = 0.11111111f;
|
sMainMenuButtons[MENU_BUTTON_MONO]->oMenuButtonScale = 0.11111111f;
|
||||||
sMainMenuButtons[MENU_BUTTON_MONO]->oFaceAngleRoll = 0;
|
|
||||||
// Headset option button
|
// Headset option button
|
||||||
sMainMenuButtons[MENU_BUTTON_HEADSET] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_HEADSET] = spawn_object_rel_with_rot(
|
||||||
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, -533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, -533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_HEADSET]->oMenuButtonScale = 0.11111111f;
|
sMainMenuButtons[MENU_BUTTON_HEADSET]->oMenuButtonScale = 0.11111111f;
|
||||||
sMainMenuButtons[MENU_BUTTON_HEADSET]->oFaceAngleRoll = 0;
|
|
||||||
|
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
// English option button
|
// English option button
|
||||||
|
@ -1377,8 +1127,7 @@ void check_sound_mode_menu_clicked_buttons(struct Object *soundModeButton) {
|
||||||
void load_main_menu_save_file(struct Object *fileButton, s32 fileNum) {
|
void load_main_menu_save_file(struct Object *fileButton, s32 fileNum) {
|
||||||
if (fileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
if (fileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) {
|
||||||
sSelectedFileNum = fileNum;
|
sSelectedFileNum = fileNum;
|
||||||
configHostSaveSlot = fileNum;
|
custom_menu_on_load_save_file(sSelectedFileNum);
|
||||||
network_init(NT_SERVER);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,11 +1169,6 @@ void return_to_main_menu(s16 prevMenuButtonID, struct Object *sourceButton) {
|
||||||
mark_obj_for_deletion(sMainMenuButtons[buttonID]);
|
mark_obj_for_deletion(sMainMenuButtons[buttonID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (prevMenuButtonID == MENU_BUTTON_NETWORK_MODE) {
|
|
||||||
for (buttonID = MENU_BUTTON_NETWORK_MIN; buttonID < MENU_BUTTON_NETWORK_MAX; buttonID++) {
|
|
||||||
mark_obj_for_deletion(sMainMenuButtons[buttonID]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1616,12 +1360,11 @@ void bhv_menu_button_manager_init(void) {
|
||||||
sMainMenuButtons[MENU_BUTTON_SOUND_MODE] = spawn_object_rel_with_rot(
|
sMainMenuButtons[MENU_BUTTON_SOUND_MODE] = spawn_object_rel_with_rot(
|
||||||
gCurrentObject, MODEL_MAIN_MENU_PURPLE_SOUND_BUTTON, bhvMenuButton, 6400, -3500, 0, 0, 0, 0);
|
gCurrentObject, MODEL_MAIN_MENU_PURPLE_SOUND_BUTTON, bhvMenuButton, 6400, -3500, 0, 0, 0, 0);
|
||||||
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f;
|
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f;
|
||||||
// Network menu button
|
|
||||||
sMainMenuButtons[MENU_BUTTON_NETWORK_MODE] = spawn_object_rel_with_rot(
|
|
||||||
gCurrentObject, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, 6400, -5500, 0, 0, 0, 0);
|
|
||||||
sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]->oMenuButtonScale = 1.0f;
|
|
||||||
|
|
||||||
sTextBaseAlpha = 0;
|
sTextBaseAlpha = 0;
|
||||||
|
|
||||||
|
// custom menus
|
||||||
|
custom_menu_system_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(VERSION_JP) || defined(VERSION_SH)
|
#if defined(VERSION_JP) || defined(VERSION_SH)
|
||||||
|
@ -1635,31 +1378,10 @@ void bhv_menu_button_manager_init(void) {
|
||||||
* Also play a sound and/or render buttons depending of the button ID selected.
|
* Also play a sound and/or render buttons depending of the button ID selected.
|
||||||
*/
|
*/
|
||||||
void check_main_menu_clicked_buttons(void) {
|
void check_main_menu_clicked_buttons(void) {
|
||||||
|
if (sIgnoreMenuTimer > 0) {
|
||||||
// force the network screen to open automatically
|
sIgnoreMenuTimer--;
|
||||||
static u8 networkInit = FALSE;
|
return;
|
||||||
if (!networkInit) {
|
|
||||||
sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
|
|
||||||
|
|
||||||
struct Object* button = sMainMenuButtons[MENU_BUTTON_NETWORK_MODE];
|
|
||||||
button->oFaceAnglePitch = 0;
|
|
||||||
button->oFaceAngleYaw = 32768;
|
|
||||||
button->oFaceAngleRoll = 0;
|
|
||||||
button->oParentRelativePosX = 0.0f;
|
|
||||||
button->oParentRelativePosY = 0.0f;
|
|
||||||
button->oParentRelativePosZ = 17800.0f;
|
|
||||||
button->oMenuButtonOrigPosX = 0;
|
|
||||||
button->oMenuButtonOrigPosY = 0;
|
|
||||||
button->oMenuButtonOrigPosZ = -17800.0f;
|
|
||||||
button->oMenuButtonScale = 1.0f;
|
|
||||||
button->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN;
|
|
||||||
button->oMenuButtonTimer = 0;
|
|
||||||
|
|
||||||
sSelectedButtonID = MENU_BUTTON_NETWORK_MODE;
|
|
||||||
|
|
||||||
networkInit = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
if (sMainMenuTimer >= 5) {
|
if (sMainMenuTimer >= 5) {
|
||||||
#endif
|
#endif
|
||||||
|
@ -1725,10 +1447,6 @@ void check_main_menu_clicked_buttons(void) {
|
||||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||||
render_sound_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
render_sound_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
||||||
break;
|
break;
|
||||||
case MENU_BUTTON_NETWORK_MODE:
|
|
||||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
|
||||||
render_network_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
}
|
}
|
||||||
|
@ -1743,6 +1461,10 @@ void check_main_menu_clicked_buttons(void) {
|
||||||
* is loaded, and that checks what buttonID is clicked in the main menu.
|
* is loaded, and that checks what buttonID is clicked in the main menu.
|
||||||
*/
|
*/
|
||||||
void bhv_menu_button_manager_loop(void) {
|
void bhv_menu_button_manager_loop(void) {
|
||||||
|
if (gInCustomMenu) {
|
||||||
|
custom_menu_system_loop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (sSelectedButtonID) {
|
switch (sSelectedButtonID) {
|
||||||
case MENU_BUTTON_NONE:
|
case MENU_BUTTON_NONE:
|
||||||
check_main_menu_clicked_buttons();
|
check_main_menu_clicked_buttons();
|
||||||
|
@ -1837,17 +1559,6 @@ void bhv_menu_button_manager_loop(void) {
|
||||||
check_sound_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
check_sound_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_BUTTON_NETWORK_MODE:
|
|
||||||
check_network_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_NETWORK_MODE]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MENU_BUTTON_HOST:
|
|
||||||
return_to_main_menu(MENU_BUTTON_NETWORK_MODE, sMainMenuButtons[MENU_BUTTON_HOST]);
|
|
||||||
break;
|
|
||||||
case MENU_BUTTON_JOIN:
|
|
||||||
exit_join_to_network_menu();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// STEREO, MONO and HEADSET buttons are undefined so they can be selected without
|
// STEREO, MONO and HEADSET buttons are undefined so they can be selected without
|
||||||
// exiting the Options menu, as a result they added a return button
|
// exiting the Options menu, as a result they added a return button
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
|
@ -1904,16 +1615,6 @@ void handle_cursor_button_input(void) {
|
||||||
sClickPos[1] = sCursorPos[1];
|
sClickPos[1] = sCursorPos[1];
|
||||||
sCursorClickingTimer = 1;
|
sCursorClickingTimer = 1;
|
||||||
}
|
}
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
sClickPos[0] = sCursorPos[0];
|
|
||||||
sClickPos[1] = sCursorPos[1];
|
|
||||||
sCursorClickingTimer = 1;
|
|
||||||
}
|
|
||||||
/*#ifdef IMMEDIATELOAD
|
|
||||||
sClickPos[0] = sCursorPos[0];
|
|
||||||
sClickPos[1] = sCursorPos[1];
|
|
||||||
sCursorClickingTimer = 1;
|
|
||||||
#endif*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,6 +1654,9 @@ void handle_controller_cursor_input(void) {
|
||||||
|
|
||||||
if (sCursorClickingTimer == 0) {
|
if (sCursorClickingTimer == 0) {
|
||||||
handle_cursor_button_input();
|
handle_cursor_button_input();
|
||||||
|
if (gInCustomMenu) {
|
||||||
|
custom_menu_cursor_click(sCursorPos[0], sCursorPos[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3036,6 +2740,12 @@ static void print_file_select_strings(void) {
|
||||||
UNUSED s32 unused2;
|
UNUSED s32 unused2;
|
||||||
|
|
||||||
create_dl_ortho_matrix();
|
create_dl_ortho_matrix();
|
||||||
|
|
||||||
|
if (gInCustomMenu) {
|
||||||
|
custom_menu_print_strings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sSelectedButtonID) {
|
switch (sSelectedButtonID) {
|
||||||
case MENU_BUTTON_NONE:
|
case MENU_BUTTON_NONE:
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
|
@ -3070,12 +2780,6 @@ static void print_file_select_strings(void) {
|
||||||
case MENU_BUTTON_SOUND_MODE:
|
case MENU_BUTTON_SOUND_MODE:
|
||||||
print_sound_mode_menu_strings();
|
print_sound_mode_menu_strings();
|
||||||
break;
|
break;
|
||||||
case MENU_BUTTON_NETWORK_MODE:
|
|
||||||
print_network_mode_menu_strings();
|
|
||||||
break;
|
|
||||||
case MENU_BUTTON_JOIN:
|
|
||||||
print_join_mode_menu_strings();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// If all 4 save file exists, define true to sAllFilesExist to prevent more copies in copy menu
|
// If all 4 save file exists, define true to sAllFilesExist to prevent more copies in copy menu
|
||||||
if (save_file_exists(SAVE_FILE_A) == TRUE && save_file_exists(SAVE_FILE_B) == TRUE &&
|
if (save_file_exists(SAVE_FILE_A) == TRUE && save_file_exists(SAVE_FILE_B) == TRUE &&
|
||||||
|
@ -3140,7 +2844,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) {
|
||||||
sClickPos[0] = -10000;
|
sClickPos[0] = -10000;
|
||||||
sClickPos[1] = -10000;
|
sClickPos[1] = -10000;
|
||||||
sCursorClickingTimer = 0;
|
sCursorClickingTimer = 0;
|
||||||
if (gNetworkType != NT_CLIENT) { sSelectedFileNum = 0; }
|
sSelectedFileNum = 0;
|
||||||
sSelectedFileIndex = MENU_BUTTON_NONE;
|
sSelectedFileIndex = MENU_BUTTON_NONE;
|
||||||
sFadeOutText = FALSE;
|
sFadeOutText = FALSE;
|
||||||
sStatusMessageID = 0;
|
sStatusMessageID = 0;
|
||||||
|
@ -3161,14 +2865,9 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// center cursor
|
// custom - center the cursor
|
||||||
sCursorPos[0] = 0.0f;
|
sCursorPos[0] = 0;
|
||||||
sCursorPos[1] = -24.0f;
|
sCursorPos[1] = 0;
|
||||||
|
|
||||||
// immediately jump in
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
sSelectedFileNum = configHostSaveSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! no return value
|
//! no return value
|
||||||
#ifdef AVOID_UB
|
#ifdef AVOID_UB
|
||||||
|
|
|
@ -87,14 +87,7 @@ enum MenuButtonTypes {
|
||||||
MENU_BUTTON_LANGUAGE_RETURN,
|
MENU_BUTTON_LANGUAGE_RETURN,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MENU_BUTTON_OPTION_MAX,
|
MENU_BUTTON_OPTION_MAX
|
||||||
|
|
||||||
MENU_BUTTON_NETWORK_MODE,
|
|
||||||
MENU_BUTTON_NETWORK_MIN,
|
|
||||||
MENU_BUTTON_HOST = MENU_BUTTON_NETWORK_MIN,
|
|
||||||
MENU_BUTTON_JOIN,
|
|
||||||
MENU_BUTTON_NETWORK_MAX,
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ScoreMenuMessageID {
|
enum ScoreMenuMessageID {
|
||||||
|
@ -134,6 +127,10 @@ enum SoundModeMenuActionPhase {
|
||||||
SOUND_MODE_PHASE_MAIN
|
SOUND_MODE_PHASE_MAIN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern f32 sCursorPos[2];
|
||||||
|
extern s8 sSelectedFileNum;
|
||||||
|
extern u8 gInCustomMenu;
|
||||||
|
|
||||||
void beh_yellow_background_menu_init(void);
|
void beh_yellow_background_menu_init(void);
|
||||||
void beh_yellow_background_menu_loop(void);
|
void beh_yellow_background_menu_loop(void);
|
||||||
void bhv_menu_button_init(void);
|
void bhv_menu_button_init(void);
|
||||||
|
@ -143,8 +140,5 @@ void bhv_menu_button_manager_loop(void);
|
||||||
Gfx *geo_file_select_strings_and_menu_cursor(s32 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx);
|
Gfx *geo_file_select_strings_and_menu_cursor(s32 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx);
|
||||||
s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused);
|
s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused);
|
||||||
s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused);
|
s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused);
|
||||||
void joined_server_as_client(s16 fileIndex);
|
|
||||||
void joined_server_version_mismatch(void);
|
|
||||||
void open_join_menu(char* customText);
|
|
||||||
|
|
||||||
#endif // FILE_SELECT_H
|
#endif // FILE_SELECT_H
|
||||||
|
|
|
@ -103,6 +103,7 @@ unsigned int configHostSaveSlot = 1;
|
||||||
unsigned int configPlayerInteraction = 1;
|
unsigned int configPlayerInteraction = 1;
|
||||||
unsigned int configPlayerKnockbackStrength = 25;
|
unsigned int configPlayerKnockbackStrength = 25;
|
||||||
unsigned int configStayInLevelAfterStar = 0;
|
unsigned int configStayInLevelAfterStar = 0;
|
||||||
|
unsigned int configNetworkSystem = 0;
|
||||||
|
|
||||||
static const struct ConfigOption options[] = {
|
static const struct ConfigOption options[] = {
|
||||||
{.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.fullscreen},
|
{.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.fullscreen},
|
||||||
|
@ -156,9 +157,10 @@ static const struct ConfigOption options[] = {
|
||||||
{.name = "coop_join_port", .type = CONFIG_TYPE_UINT , .uintValue = &configJoinPort},
|
{.name = "coop_join_port", .type = CONFIG_TYPE_UINT , .uintValue = &configJoinPort},
|
||||||
{.name = "coop_host_port", .type = CONFIG_TYPE_UINT , .uintValue = &configHostPort},
|
{.name = "coop_host_port", .type = CONFIG_TYPE_UINT , .uintValue = &configHostPort},
|
||||||
{.name = "coop_host_save_slot", .type = CONFIG_TYPE_UINT , .uintValue = &configHostSaveSlot},
|
{.name = "coop_host_save_slot", .type = CONFIG_TYPE_UINT , .uintValue = &configHostSaveSlot},
|
||||||
{.name = "coop_player_interaction", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerInteraction},
|
{.name = "coop_player_interaction", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerInteraction},
|
||||||
{.name = "coop_player_knockback_strength", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerKnockbackStrength},
|
{.name = "coop_player_knockback_strength", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerKnockbackStrength},
|
||||||
{.name = "coop_stay_in_level_after_star", .type = CONFIG_TYPE_UINT , .uintValue = &configStayInLevelAfterStar},
|
{.name = "coop_stay_in_level_after_star", .type = CONFIG_TYPE_UINT , .uintValue = &configStayInLevelAfterStar},
|
||||||
|
{.name = "coop_network_system", .type = CONFIG_TYPE_UINT , .uintValue = &configNetworkSystem},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reads an entire line from a file (excluding the newline character) and returns an allocated string
|
// Reads an entire line from a file (excluding the newline character) and returns an allocated string
|
||||||
|
|
|
@ -69,6 +69,7 @@ extern unsigned int configHostSaveSlot;
|
||||||
extern unsigned int configPlayerInteraction;
|
extern unsigned int configPlayerInteraction;
|
||||||
extern unsigned int configPlayerKnockbackStrength;
|
extern unsigned int configPlayerKnockbackStrength;
|
||||||
extern unsigned int configStayInLevelAfterStar;
|
extern unsigned int configStayInLevelAfterStar;
|
||||||
|
extern unsigned int configNetworkSystem;
|
||||||
|
|
||||||
void configfile_load(const char *filename);
|
void configfile_load(const char *filename);
|
||||||
void configfile_save(const char *filename);
|
void configfile_save(const char *filename);
|
||||||
|
|
|
@ -79,7 +79,9 @@ static void keyboard_alter_text_input_modifier(int scancode, bool down) {
|
||||||
|
|
||||||
bool keyboard_on_key_down(int scancode) {
|
bool keyboard_on_key_down(int scancode) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug_keyboard_on_key_down(scancode);
|
if (!inTextInput) {
|
||||||
|
debug_keyboard_on_key_down(scancode);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (inTextInput) {
|
if (inTextInput) {
|
||||||
// alter the held value of modifier keys
|
// alter the held value of modifier keys
|
||||||
|
@ -155,10 +157,12 @@ char* keyboard_start_text_input(enum TextInputMode inInputMode, void (*onEscape)
|
||||||
|
|
||||||
void keyboard_stop_text_input(void) {
|
void keyboard_stop_text_input(void) {
|
||||||
// stop allowing text input
|
// stop allowing text input
|
||||||
wm_api->stop_text_input();
|
|
||||||
inTextInput = false;
|
inTextInput = false;
|
||||||
|
wm_api->stop_text_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool keyboard_in_text_input(void) { return inTextInput; }
|
||||||
|
|
||||||
static bool keyboard_allow_character_input(char c) {
|
static bool keyboard_allow_character_input(char c) {
|
||||||
switch (textInputMode) {
|
switch (textInputMode) {
|
||||||
case TIM_IP:
|
case TIM_IP:
|
||||||
|
@ -190,6 +194,7 @@ static bool keyboard_allow_character_input(char c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyboard_on_text_input(char* text) {
|
void keyboard_on_text_input(char* text) {
|
||||||
|
if (!inTextInput) { return; }
|
||||||
// sanity check input
|
// sanity check input
|
||||||
if (text == NULL) { return; }
|
if (text == NULL) { return; }
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ void keyboard_on_all_keys_up(void);
|
||||||
void keyboard_on_text_input(char* text);
|
void keyboard_on_text_input(char* text);
|
||||||
char* keyboard_start_text_input(enum TextInputMode, void (*onEscape)(void), void (*onEnter)(void));
|
char* keyboard_start_text_input(enum TextInputMode, void (*onEscape)(void), void (*onEnter)(void));
|
||||||
void keyboard_stop_text_input(void);
|
void keyboard_stop_text_input(void);
|
||||||
|
bool keyboard_in_text_input(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "lobby.h"
|
#include "lobby.h"
|
||||||
#include "discord_network.h"
|
#include "discord_network.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
#include "menu/file_select.h"
|
#include "menu/custom_menu.h"
|
||||||
|
|
||||||
#define HASH_LENGTH 8
|
#define HASH_LENGTH 8
|
||||||
struct DiscordActivity gCurActivity = { 0 };
|
struct DiscordActivity gCurActivity = { 0 };
|
||||||
|
@ -32,7 +32,7 @@ static void on_activity_join_callback(UNUSED void* data, enum EDiscordResult res
|
||||||
|
|
||||||
static void on_activity_join(UNUSED void* data, const char* secret) {
|
static void on_activity_join(UNUSED void* data, const char* secret) {
|
||||||
LOG_INFO("> on_activity_join, secret: %s", secret);
|
LOG_INFO("> on_activity_join, secret: %s", secret);
|
||||||
open_join_menu("Joining Discord invite...");
|
gOpenConnectMenu = TRUE;
|
||||||
app.lobbies->connect_lobby_with_activity_secret(app.lobbies, (char*)secret, NULL, on_activity_join_callback);
|
app.lobbies->connect_lobby_with_activity_secret(app.lobbies, (char*)secret, NULL, on_activity_join_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "src/game/interaction.h"
|
#include "src/game/interaction.h"
|
||||||
#include "src/engine/math_util.h"
|
#include "src/engine/math_util.h"
|
||||||
#include "src/game/save_file.h"
|
#include "src/game/save_file.h"
|
||||||
#include "src/menu/file_select.h"
|
#include "src/menu/custom_menu.h"
|
||||||
#include "src/pc/fs/fs.h"
|
#include "src/pc/fs/fs.h"
|
||||||
#include "PR/os_eeprom.h"
|
#include "PR/os_eeprom.h"
|
||||||
|
|
||||||
|
@ -69,9 +69,9 @@ void network_receive_save_file(struct Packet* p) {
|
||||||
|
|
||||||
save_file_load_all(TRUE);
|
save_file_load_all(TRUE);
|
||||||
if (memcmp(hash, remoteHash, HASH_LENGTH) != 0) {
|
if (memcmp(hash, remoteHash, HASH_LENGTH) != 0) {
|
||||||
joined_server_version_mismatch();
|
strcpy(gConnectionJoinError, "Your versions don't match, both should rebuild!");
|
||||||
network_shutdown();
|
network_shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
joined_server_as_client(gCurrSaveFileNum);
|
custom_menu_goto_game(gCurrSaveFileNum);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "pc/configfile.h"
|
#include "pc/configfile.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
#include "menu/file_select.h"
|
#include "menu/custom_menu.h"
|
||||||
|
|
||||||
static SOCKET curSocket = INVALID_SOCKET;
|
static SOCKET curSocket = INVALID_SOCKET;
|
||||||
struct sockaddr_in txAddr = { 0 };
|
struct sockaddr_in txAddr = { 0 };
|
||||||
|
@ -75,7 +75,7 @@ static bool ns_socket_initialize(enum NetworkType networkType) {
|
||||||
if (networkType == NT_CLIENT) {
|
if (networkType == NT_CLIENT) {
|
||||||
char joinText[128] = { 0 };
|
char joinText[128] = { 0 };
|
||||||
snprintf(joinText, 63, "%s %d", configJoinIp, configJoinPort);
|
snprintf(joinText, 63, "%s %d", configJoinIp, configJoinPort);
|
||||||
open_join_menu(joinText);
|
gOpenConnectMenu = TRUE;
|
||||||
|
|
||||||
gNetworkType = NT_CLIENT;
|
gNetworkType = NT_CLIENT;
|
||||||
network_on_joined();
|
network_on_joined();
|
||||||
|
@ -88,6 +88,7 @@ static bool ns_socket_initialize(enum NetworkType networkType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ns_socket_update(void) {
|
static void ns_socket_update(void) {
|
||||||
|
if (gNetworkType == NT_NONE) { return; }
|
||||||
do {
|
do {
|
||||||
// receive packet
|
// receive packet
|
||||||
u8 data[PACKET_LENGTH];
|
u8 data[PACKET_LENGTH];
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
Loading…
Reference in New Issue