mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
246 lines
6.8 KiB
C
246 lines
6.8 KiB
C
// DR. ROBOTNIK'S RING RACERS
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2025 by "Lat'".
|
|
// Copyright (C) 2025 by Kart Krew.
|
|
//
|
|
// This program is free software distributed under the
|
|
// terms of the GNU General Public License, version 2.
|
|
// See the 'LICENSE' file for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file menus/options-profiles-edit-1.c
|
|
/// \brief Profile Editor
|
|
|
|
#include "../i_time.h"
|
|
#include "../k_menu.h"
|
|
#include "../s_sound.h"
|
|
#include "../m_cond.h"
|
|
|
|
// These are placed in descending order next to the things they modify, for clarity.
|
|
// Try to keep the mvar2 in order, if you add new profile info!!
|
|
menuitem_t OPTIONS_EditProfile[] = {
|
|
{IT_STRING | IT_CVAR | IT_CV_STRING, "Profile ID", "6-character long name to display on menus.",
|
|
NULL, {.cvar = &cv_dummyprofilename}, 0, 41},
|
|
|
|
{IT_STRING | IT_CVAR | IT_CV_STRING, "Player Tag", "Full name, displayed online and in replays.",
|
|
NULL, {.cvar = &cv_dummyprofileplayername}, 0, 61},
|
|
|
|
{IT_STRING | IT_CALL, "Controls", "Change the button mappings.",
|
|
NULL, {.routine = M_ProfileDeviceSelect}, 0, 91},
|
|
|
|
{IT_STRING | IT_SUBMENU, "Accessibility", "Accessibility and quality of life options.",
|
|
NULL, {.submenu = &OPTIONS_ProfileAccessibilityDef}, 0, 111},
|
|
|
|
{IT_STRING | IT_CALL, "Character", NULL, // tooltip set in M_StartEditProfile
|
|
NULL, {.routine = M_CharacterSelect}, 0, 131},
|
|
|
|
{IT_STRING | IT_CALL, "Confirm", "Confirm changes.",
|
|
NULL, {.routine = M_ConfirmProfile}, 0, 171},
|
|
|
|
};
|
|
|
|
menu_t OPTIONS_EditProfileDef = {
|
|
sizeof (OPTIONS_EditProfile) / sizeof (menuitem_t),
|
|
&OPTIONS_ProfilesDef,
|
|
0,
|
|
OPTIONS_EditProfile,
|
|
32, 80,
|
|
SKINCOLOR_ULTRAMARINE, 0,
|
|
MBF_DRAWBGWHILEPLAYING,
|
|
"FILE",
|
|
2, 5,
|
|
M_DrawEditProfile,
|
|
M_DrawOptionsCogs,
|
|
M_HandleProfileEdit,
|
|
NULL,
|
|
NULL,
|
|
M_ProfileEditInputs,
|
|
};
|
|
|
|
// Returns true if the profile can be saved, false otherwise. Also starts messages if necessary.
|
|
static boolean M_ProfileEditEnd(const UINT8 pid)
|
|
{
|
|
UINT8 i;
|
|
|
|
// Guest profile, you can't edit that one!
|
|
if (optionsmenu.profilen == 0)
|
|
{
|
|
S_StartSound(NULL, sfx_s3k7b);
|
|
M_StartMessage("Profiles", M_GetText("Guest profile cannot be edited.\nCreate a new profile instead."), NULL, MM_NOTHING, NULL, NULL);
|
|
M_SetMenuDelay(pid);
|
|
return false;
|
|
}
|
|
|
|
// check if some profiles have the same name
|
|
for (i = 0; i < PR_GetNumProfiles(); i++)
|
|
{
|
|
profile_t *check = PR_GetProfile(i);
|
|
|
|
// For obvious reasons don't check if our name is the same as our name....
|
|
if (check != optionsmenu.profile)
|
|
{
|
|
if (!(strcmp(optionsmenu.profile->profilename, check->profilename)))
|
|
{
|
|
S_StartSound(NULL, sfx_s3k7b);
|
|
M_StartMessage("Profiles", M_GetText("Another profile uses the same name.\nThis must be changed to be able to save."), NULL, MM_NOTHING, NULL, NULL);
|
|
M_SetMenuDelay(pid);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void M_ProfileEditApply(void)
|
|
{
|
|
SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile);
|
|
// Save the profile
|
|
optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value;
|
|
optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value;
|
|
optionsmenu.profile->litesteer = cv_dummyprofilelitesteer.value;
|
|
optionsmenu.profile->strictfastfall = cv_dummyprofilestrictfastfall.value;
|
|
optionsmenu.profile->descriptiveinput = cv_dummyprofiledescriptiveinput.value;
|
|
optionsmenu.profile->autoring = cv_dummyprofileautoring.value;
|
|
optionsmenu.profile->rumble = cv_dummyprofilerumble.value;
|
|
optionsmenu.profile->fov = cv_dummyprofilefov.value;
|
|
|
|
// If this profile is in-use by anyone, apply the changes immediately upon exiting.
|
|
// Don't apply the full profile itself as that would lead to issues mid-game.
|
|
if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS)
|
|
{
|
|
PR_ApplyProfileToggles(optionsmenu.profilen, belongsto);
|
|
if (gamestate == GS_MENU)
|
|
{
|
|
// Safe to apply skin, etc here.
|
|
PR_ApplyProfileLight(optionsmenu.profilen, belongsto);
|
|
}
|
|
}
|
|
|
|
// Reapply player 1's real profile ID.
|
|
if (cv_currprofile.value > -1)
|
|
{
|
|
PR_ApplyProfilePretend(cv_lastprofile[0].value, 0);
|
|
}
|
|
}
|
|
|
|
static void M_ProfileEditExit(void)
|
|
{
|
|
M_ProfileEditApply();
|
|
|
|
if (M_GameTrulyStarted() == true)
|
|
{
|
|
optionsmenu.toptx = 160;
|
|
optionsmenu.topty = 35;
|
|
optionsmenu.resetprofile = true; // Reset profile after the transition is done.
|
|
}
|
|
else
|
|
{
|
|
M_ResetOptions(); // Reset all options variables otherwise things are gonna go reaaal bad lol.
|
|
}
|
|
|
|
PR_SaveProfiles(); // save profiles after we do that.
|
|
}
|
|
|
|
// For profile edit, just make sure going back resets the card to its position, the rest is taken care of automatically.
|
|
boolean M_ProfileEditInputs(INT32 ch)
|
|
{
|
|
|
|
(void) ch;
|
|
const UINT8 pid = 0;
|
|
|
|
if (M_MenuBackPressed(pid))
|
|
{
|
|
if (M_ProfileEditEnd(pid))
|
|
{
|
|
M_ProfileEditExit();
|
|
if (cv_currprofile.value == -1)
|
|
M_SetupNextMenu(&MAIN_ProfilesDef, false);
|
|
else
|
|
M_GoBack(0);
|
|
M_SetMenuDelay(pid);
|
|
}
|
|
return true;
|
|
}
|
|
else if (M_MenuConfirmPressed(pid))
|
|
{
|
|
if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT)
|
|
return true; // No.
|
|
}
|
|
|
|
if (menucmd[pid].dpad_ud != 0)
|
|
{
|
|
optionsmenu.offset.start = I_GetTime();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Handle some actions in profile editing
|
|
void M_HandleProfileEdit(void)
|
|
{
|
|
// Always copy the profile name and player name in the profile.
|
|
if (optionsmenu.profile && !menutyping.active)
|
|
{
|
|
// Copy the first 6 chars for profile name
|
|
if (cv_dummyprofilename.string[0])
|
|
{
|
|
char *s;
|
|
// convert dummyprofilename to uppercase
|
|
strncpy(optionsmenu.profile->profilename, cv_dummyprofilename.string, PROFILENAMELEN);
|
|
s = optionsmenu.profile->profilename;
|
|
while (*s)
|
|
{
|
|
*s = toupper(*s);
|
|
s++;
|
|
}
|
|
}
|
|
|
|
if (cv_dummyprofileplayername.string[0])
|
|
{
|
|
strncpy(optionsmenu.profile->playername, cv_dummyprofileplayername.string, MAXPLAYERNAME);
|
|
}
|
|
}
|
|
|
|
M_OptionsTick(); // Has to be afterwards because this can unset optionsmenu.profile
|
|
}
|
|
|
|
// Confirm Profile edi via button.
|
|
void M_ConfirmProfile(INT32 choice)
|
|
{
|
|
const UINT8 pid = 0;
|
|
(void) choice;
|
|
|
|
if (M_ProfileEditEnd(pid))
|
|
{
|
|
if (cv_currprofile.value > -1)
|
|
{
|
|
M_ProfileEditExit();
|
|
M_GoBack(0);
|
|
M_SetMenuDelay(pid);
|
|
}
|
|
else
|
|
{
|
|
M_StartMessage("Profiles", M_GetText("Are you sure you wish to\nselect this profile?\n"), &M_FirstPickProfile, MM_YESNO, NULL, NULL);
|
|
M_SetMenuDelay(pid);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Prompt a device selection window (just tap any button on the device you want)
|
|
void M_ProfileDeviceSelect(INT32 choice)
|
|
{
|
|
(void)choice;
|
|
|
|
// While we're here, setup the incoming controls menu to reset the scroll & bind status:
|
|
optionsmenu.controlscroll = 0;
|
|
optionsmenu.bindtimer = 0;
|
|
|
|
optionsmenu.lastkey = 0;
|
|
optionsmenu.keyheldfor = 0;
|
|
|
|
optionsmenu.contx = optionsmenu.tcontx = controlleroffsets[gc_a][0];
|
|
optionsmenu.conty = optionsmenu.tconty = controlleroffsets[gc_a][1];
|
|
|
|
M_SetupNextMenu(&OPTIONS_ProfileControlsDef, false); // Don't set device here anymore.
|
|
}
|