RingRacers/src/menus/extras-addons.c
2025-02-13 15:32:26 -06:00

364 lines
9 KiB
C

// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by Vivian "toastergrl" Grannell.
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
//
// 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/extras-addons.c
/// \brief Addons menu!
#include "../k_menu.h"
#include "../filesrch.h" // Addfile
#include "../d_main.h"
#include "../z_zone.h"
#include "../s_sound.h"
#include "../v_video.h"
menuitem_t MISC_AddonsMenu[] =
{
{IT_STRING | IT_CVAR | IT_CV_STRING, "Search for add-ons", "Provide a full or partial name to filter available files by.",
NULL, {.cvar = &cv_dummyaddonsearch}, 0, 0},
{IT_KEYHANDLER | IT_NOTHING, NULL, NULL,
NULL, {.routine = M_HandleAddons}, 0, 0}, // dummy menuitem for the control func
};
menu_t MISC_AddonsDef = {
sizeof (MISC_AddonsMenu)/sizeof (menuitem_t),
NULL,
0,
MISC_AddonsMenu,
50, 28,
0, 0,
MBF_NOLOOPENTRIES,
"EXTRAS",
0, 0,
M_DrawAddons,
M_DrawExtrasBack,
M_AddonsRefresh,
NULL,
NULL,
NULL
};
// Addons menu: (Merely copypasted, original code by toaster)
void M_Addons(INT32 choice)
{
const char *pathname = ".";
(void)choice;
pathname = addonsdir;
strlcpy(menupath, pathname, 1024);
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0])
{
menupath[menupathindex[menudepthleft]-1] = PATHSEP[0];
menupath[menupathindex[menudepthleft]] = 0;
}
else
--menupathindex[menudepthleft];
if (!preparefilemenu(false, false))
{
M_StartMessage("Add-ons Menu", va("No files/folders found.\n\n%s\n", LOCATIONSTRING1),NULL,MM_NOTHING, NULL, NULL);
return;
}
else
dir_on[menudepthleft] = 0;
MISC_AddonsDef.lastOn = 0; // Always start on search
MISC_AddonsDef.prevMenu = currentMenu;
M_SetupNextMenu(&MISC_AddonsDef, false);
}
char *M_AddonsHeaderPath(void)
{
UINT32 len;
static char header[1024];
strlcpy(header, va("addons%s", menupath+menupathindex[menudepth-1]-1), 1024);
len = strlen(header);
if (len > 34)
{
len = len-34;
header[len] = header[len+1] = header[len+2] = '.';
}
else
len = 0;
return header+len;
}
#define UNEXIST S_StartSound(NULL, sfx_s26d);\
M_SetupNextMenu(MISC_AddonsDef.prevMenu, false);\
M_StartMessage("Add-ons Menu", va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n", M_AddonsHeaderPath()),NULL,MM_NOTHING, NULL, NULL)
#define CLEARNAME Z_Free(refreshdirname);\
refreshdirname = NULL
static boolean prevmajormods = false;
static void M_AddonsClearName(INT32 choice)
{
(void)choice;
if (!majormods || prevmajormods)
{
CLEARNAME;
}
}
// Handles messages for addon errors.
void M_AddonsRefresh(void)
{
if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true, false))
{
UNEXIST;
if (refreshdirname)
{
CLEARNAME;
}
return;// true;
}
#ifdef DEVELOP
prevmajormods = majormods;
#else
if (!majormods && prevmajormods)
prevmajormods = false;
#endif
if ((refreshdirmenu & REFRESHDIR_ADDFILE) || (majormods && !prevmajormods))
{
char *message = NULL;
if (refreshdirmenu & REFRESHDIR_NOTLOADED)
{
S_StartSound(NULL, sfx_s26d);
if (refreshdirmenu & REFRESHDIR_MAX)
message = va("%c%s\x80\nMaximum number of addons reached.\nA file could not be loaded.\nIf you wish to play with this addon, restart the game to clear existing ones.\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
else
message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more info.\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
}
else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
{
S_StartSound(NULL, sfx_s224);
message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more info.\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings"));
}
else if (majormods && !prevmajormods)
{
S_StartSound(NULL, sfx_s221);
message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\nCheck the console log for more info.\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
prevmajormods = majormods;
}
if (message)
{
M_StartMessage("Add-ons Menu", message, &M_AddonsClearName,MM_NOTHING, NULL, NULL);
return;// true;
}
S_StartSound(NULL, sfx_s221);
CLEARNAME;
}
return;// false;
}
static void M_AddonExec(INT32 ch)
{
if (ch == MA_YES)
{
S_StartSound(NULL, sfx_zoom);
COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
}
}
void M_UpdateAddonsSearch(void);
void M_UpdateAddonsSearch(void)
{
menusearch[0] = strlen(cv_dummyaddonsearch.string);
strlcpy(menusearch+1, cv_dummyaddonsearch.string, MAXSTRINGLENGTH);
if (!cv_addons_search_case.value)
strupr(menusearch+1);
#if 0 // much slower
if (!preparefilemenu(true, false))
{
UNEXIST;
return;
}
#else // streamlined
searchfilemenu(NULL);
#endif
}
void M_HandleAddons(INT32 choice)
{
const UINT8 pid = 0;
boolean exitmenu = false; // exit to previous menu
(void) choice;
if (menucmd[pid].dpad_ud > 0)
{
if (dir_on[menudepthleft] < sizedirmenu-1)
{
dir_on[menudepthleft]++;
S_StartSound(NULL, sfx_s3k5b);
}
else if (M_NextOpt())
{
S_StartSound(NULL, sfx_s3k5b);
}
M_SetMenuDelay(pid);
}
else if (menucmd[pid].dpad_ud < 0)
{
if (dir_on[menudepthleft])
{
dir_on[menudepthleft]--;
S_StartSound(NULL, sfx_s3k5b);
}
else if (M_PrevOpt())
{
S_StartSound(NULL, sfx_s3k5b);
}
M_SetMenuDelay(pid);
}
else if (M_MenuButtonPressed(pid, MBT_L))
{
UINT8 i;
for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--)
dir_on[menudepthleft]++;
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
}
else if (M_MenuButtonPressed(pid, MBT_R))
{
UINT8 i;
for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--)
dir_on[menudepthleft]--;
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
}
else if (M_MenuConfirmPressed(pid))
{
boolean refresh = true;
M_SetMenuDelay(pid);
if (!dirmenu[dir_on[menudepthleft]])
S_StartSound(NULL, sfx_s26d);
else
{
switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
{
case EXT_FOLDER:
strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING);
if (menudepthleft)
{
menupathindex[--menudepthleft] = strlen(menupath);
menupath[menupathindex[menudepthleft]] = 0;
if (!preparefilemenu(false, false))
{
S_StartSound(NULL, sfx_s224);
M_StartMessage("Add-ons Menu", va("%c%s\x80\nThis folder is empty.\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING, NULL, NULL);
menupath[menupathindex[++menudepthleft]] = 0;
if (!preparefilemenu(true, false))
{
UNEXIST;
return;
}
}
else
{
S_StartSound(NULL, sfx_s3k5b);
dir_on[menudepthleft] = 1;
}
refresh = false;
}
else
{
S_StartSound(NULL, sfx_s26d);
M_StartMessage("Add-ons Menu", va("%c%s\x80\nThis folder is too deep to navigate to!\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING, NULL, NULL);
menupath[menupathindex[menudepthleft]] = 0;
}
break;
case EXT_UP:
S_StartSound(NULL, sfx_s3k5b);
menupath[menupathindex[++menudepthleft]] = 0;
if (!preparefilemenu(false, false))
{
UNEXIST;
return;
}
break;
case EXT_TXT:
M_StartMessage("Add-ons Menu", va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways?\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),&M_AddonExec,MM_YESNO, NULL, NULL);
break;
case EXT_CFG:
M_StartMessage("Add-ons Menu", va("%c%s\x80\nThis file may modify your settings.\nAttempt to run anyways?\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),&M_AddonExec,MM_YESNO, NULL, NULL);
break;
case EXT_LUA:
case EXT_SOC:
case EXT_WAD:
#ifdef USE_KART
case EXT_KART:
#endif
case EXT_PK3:
COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
break;
default:
S_StartSound(NULL, sfx_s26d);
}
if (refresh)
refreshdirmenu |= REFRESHDIR_NORMAL;
}
}
else if (M_MenuBackPressed(pid))
{
exitmenu = true;
M_SetMenuDelay(pid);
}
if (exitmenu)
{
closefilemenu(true);
// Secret menu!
//MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
// I could guard it, but let's just always do this.
M_InitExtras(-1);
if (currentMenu->prevMenu)
M_SetupNextMenu(M_InterruptMenuWithChallenges(currentMenu->prevMenu), false);
else
M_ClearMenus(true);
M_SetMenuDelay(pid);
}
}