A serious defuckening of my fancy character select code.

This commit is contained in:
toasterbabe 2017-03-17 14:27:17 +00:00
parent 3fdb8a3181
commit 6fa319041a
3 changed files with 156 additions and 167 deletions

View File

@ -432,22 +432,20 @@ static void readAnimTex(MYFILE *f, INT32 num)
}
*/
static boolean findFreeSlot(INT32 *num, UINT16 wadnum)
static boolean findFreeSlot(INT32 *num)
{
// Send the character select entry to a free slot.
while (*num < 32 && (!(PlayerMenu[*num].status & IT_DISABLED) || description[*num].wadnum == wadnum)) // Will kill hidden characters from other files, but that's okay.
while (*num < 32 && (description[*num].used))
*num = *num+1;
// No more free slots. :(
if (*num >= 32)
return false;
PlayerMenu[*num].status = IT_CALL;
description[*num].wadnum = wadnum;
description[*num].picname[0] = '\0'; // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
// Found one! ^_^
return true;
return (description[*num].used = true);
}
// Reads a player.
@ -479,7 +477,7 @@ static void readPlayer(MYFILE *f, INT32 num)
{
char *playertext = NULL;
if (!slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false)
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
for (i = 0; i < MAXLINELEN-3; i++)
@ -528,7 +526,7 @@ static void readPlayer(MYFILE *f, INT32 num)
if (fastcmp(word, "PICNAME"))
{
if (!slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false)
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE);
@ -536,12 +534,6 @@ static void readPlayer(MYFILE *f, INT32 num)
}
else if (fastcmp(word, "STATUS"))
{
// Limit the status to only IT_DISABLED and IT_CALL
if (i)
i = IT_CALL;
else
i = IT_DISABLED;
/*
You MAY disable previous entries if you so desire...
But try to enable something that's already enabled and you will be sent to a free slot.
@ -549,15 +541,15 @@ static void readPlayer(MYFILE *f, INT32 num)
Because of this, you are allowed to edit any previous entries you like, but only if you
signal that you are purposely doing so by disabling and then reenabling the slot.
*/
if (i != IT_DISABLED && !slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false)
if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, va("%d", PlayerMenu[num].status), UNDO_NONE);
PlayerMenu[num].status = (INT16)i;
DEH_WriteUndoline(word, va("%d", description[num].used), UNDO_NONE);
description[num].used = (!!i);
}
else if (fastcmp(word, "SKINNAME"))
{
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false)
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE);

View File

@ -108,41 +108,45 @@ typedef enum
const char *quitmsg[NUM_QUITMESSAGES];
// Stuff for customizing the player select screen Tails 09-22-2003
// A rare case.
// External files modify this menu, so we can't call it static.
// And I'm too lazy to go through and rename it everywhere. ARRGH!
description_t description[32] =
{
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0},
{"???", "", "", 0, 0, 0}
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0},
{false, "???", "", "", 0, 0}
};
static INT16 char_on = 0;
static char *char_notes = NULL;
static fixed_t char_scroll = 0;
@ -170,7 +174,6 @@ static saveinfo_t savegameinfo[MAXSAVEGAMES]; // Extra info about the save games
INT16 startmap; // Mario, NiGHTS, or just a plain old normal game?
static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002
static boolean lastdirection = true; // toaster - Only You Can Prevent Hacks - true is for forward, false is for backwards
static INT16 skullAnimCounter = 10; // skull animation counter
static boolean setupcontrols_secondaryplayer;
@ -246,6 +249,7 @@ static void M_ChooseNightsAttack(INT32 choice);
static void M_ModeAttackRetry(INT32 choice);
static void M_ModeAttackEndGame(INT32 choice);
static void M_SetGuestReplay(INT32 choice);
static void M_HandleChoosePlayerMenu(INT32 choice);
static void M_ChoosePlayer(INT32 choice);
menu_t SP_GameStatsDef, SP_LevelStatsDef;
static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
@ -820,43 +824,10 @@ static menuitem_t SP_LevelStatsMenu[] =
{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, '\0'}, // dummy menuitem for the control func
};
// A rare case.
// External files modify this menu, so we can't call it static.
// And I'm too lazy to go through and rename it everywhere. ARRGH!
menuitem_t PlayerMenu[32] =
// Player menu dummy
static menuitem_t SP_PlayerMenu[32] =
{
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}
{IT_NOTHING | IT_KEYHANDLER, NULL, "", M_HandleChoosePlayerMenu, 0}, // dummy menuitem for the control func
};
// -----------------------------------
@ -1594,9 +1565,9 @@ static menu_t SP_NightsGhostDef =
menu_t SP_PlayerDef =
{
"M_PICKP",
sizeof (PlayerMenu)/sizeof (menuitem_t),//player_end,
sizeof (SP_PlayerMenu)/sizeof (menuitem_t),
&SP_MainDef,
PlayerMenu,
SP_PlayerMenu,
M_DrawSetupChoosePlayerMenu,
24, 32,
0,
@ -2034,8 +2005,6 @@ static boolean M_ChangeStringCvar(INT32 choice)
static void M_NextOpt(void)
{
INT16 oldItemOn = itemOn; // prevent infinite loop
lastdirection = true;
do
{
if (itemOn + 1 > currentMenu->numitems - 1)
@ -2048,8 +2017,6 @@ static void M_NextOpt(void)
static void M_PrevOpt(void)
{
INT16 oldItemOn = itemOn; // prevent infinite loop
lastdirection = false;
do
{
if (!itemOn)
@ -2320,21 +2287,11 @@ boolean M_Responder(event_t *ev)
case KEY_DOWNARROW:
M_NextOpt();
S_StartSound(NULL, sfx_menu1);
if (currentMenu == &SP_PlayerDef)
{
Z_Free(char_notes);
char_notes = NULL;
}
return true;
case KEY_UPARROW:
M_PrevOpt();
S_StartSound(NULL, sfx_menu1);
if (currentMenu == &SP_PlayerDef)
{
Z_Free(char_notes);
char_notes = NULL;
}
return true;
case KEY_LEFTARROW:
@ -4768,15 +4725,15 @@ static void M_SetupChoosePlayer(INT32 choice)
UINT8 i;
UINT8 firstvalid = 255;
UINT8 lastvalid = 0;
boolean allowed = false;
char *name;
(void)choice;
if (PlayerMenu[0].status & (IT_DYBIGSPACE)) // Correcting a hack that may be made below.
PlayerMenu[0].status = (IT_DISABLED|(PlayerMenu[0].status & IT_CENTER));
SP_PlayerMenu[0].status &= ~IT_DYBIGSPACE; // Correcting a hack that may be made below.
for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks.
{
if (PlayerMenu[i].status != IT_DISABLED) // If the character's disabled through SOC, there's nothing we can do for it.
if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it.
{
name = strtok(Z_StrDup(description[i].skinname), "&");
skinnum = R_SkinAvailable(name);
@ -4792,14 +4749,13 @@ static void M_SetupChoosePlayer(INT32 choice)
}
lastvalid = i;
// Handling visibility.
if (PlayerMenu[i].status & (IT_DISABLED|IT_CENTER))
PlayerMenu[i].status = IT_CALL;
if (i == char_on)
allowed = true;
if (description[i].picname[0] == '\0')
strncpy(description[i].picname, skins[skinnum].charsel, 8);
}
else // Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them.
PlayerMenu[i].status = (IT_DISABLED|IT_CENTER);
// else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them.
Z_Free(name);
}
}
@ -4815,7 +4771,7 @@ static void M_SetupChoosePlayer(INT32 choice)
}
else // We're being forced into a specific character, so might as well.
{
PlayerMenu[0].status = (IT_CALL|IT_DYBIGSPACE|(PlayerMenu[0].status & IT_CENTER)); // This is a hack to make a non-IT_CALL character in slot 0 not softlock the game. IT_DYBIGSPACE is a dummy flag, whilst IT_CENTER is preserved.
SP_PlayerMenu[0].status |= IT_DYBIGSPACE; // This is a dummy flag hack to make a non-IT_CALL character in slot 0 not softlock the game.
M_ChoosePlayer(0);
return;
}
@ -4829,9 +4785,77 @@ static void M_SetupChoosePlayer(INT32 choice)
SP_PlayerDef.prevMenu = currentMenu;
M_SetupNextMenu(&SP_PlayerDef);
char_scroll = itemOn*128*FRACUNIT; // finish scrolling the menu
if (!allowed)
char_on = firstvalid;
char_scroll = 0; // finish scrolling the menu
Z_Free(char_notes);
char_notes = NULL;
char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes);
}
//
// M_HandleChoosePlayerMenu
//
// Reacts to your key inputs. Basically a mini menu thinker.
//
static void M_HandleChoosePlayerMenu(INT32 choice)
{
boolean exitmenu = false; // exit to previous menu
INT32 selectval;
switch (choice)
{
case KEY_DOWNARROW:
if ((selectval = description[char_on].next) != char_on)
{
S_StartSound(NULL,sfx_s3kb7);
char_on = selectval;
char_scroll = -128*FRACUNIT;
Z_Free(char_notes);
char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes);
}
else if (!char_scroll)
{
S_StartSound(NULL,sfx_s3kb7);
char_scroll = 16*FRACUNIT;
}
break;
case KEY_UPARROW:
if ((selectval = description[char_on].prev) != char_on)
{
S_StartSound(NULL,sfx_s3kb7);
char_on = selectval;
char_scroll = 128*FRACUNIT;
Z_Free(char_notes);
char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes);
}
else if (!char_scroll)
{
S_StartSound(NULL,sfx_s3kb7);
char_scroll = -16*FRACUNIT;
}
break;
case KEY_ENTER:
S_StartSound(NULL, sfx_menu1);
M_ChoosePlayer(char_on);
break;
case KEY_ESCAPE:
exitmenu = true;
break;
default:
break;
}
if (exitmenu)
{
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
}
// Draw the choose player setup menu, had some fun with player anim
@ -4841,7 +4865,6 @@ static void M_DrawSetupChoosePlayerMenu(void)
patch_t *patch;
INT32 i, o;
UINT8 prev, next;
boolean loophack = false;
// Black BG
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
@ -4850,37 +4873,20 @@ static void M_DrawSetupChoosePlayerMenu(void)
// Character select profile images!1
M_DrawTextBox(0, my, 16, 20);
i = (itemOn*128 - (char_scroll / FRACUNIT));
if (!char_notes)
{
if (i) // turns out this and the preceding check is better then (abs(i) > 128)
{
o = (lastdirection) ? -1 : 1;
char_scroll = (itemOn + o)*128*FRACUNIT;
i = -o*128;
}
char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[itemOn].notes);
}
if (abs(i) > 1)
char_scroll += i*FRACUNIT>>2;
if (abs(char_scroll) > FRACUNIT)
char_scroll -= (char_scroll>>2);
else // close enough.
char_scroll = itemOn*128*FRACUNIT; // just be exact now.
char_scroll = 0; // just be exact now.
o = ((char_scroll / FRACUNIT) + 16);
o = (char_scroll >> FRACBITS) + 16;
if (o < 0) // This hack is to prevent visual glitches when looping from the last character to the 1st character.
loophack = true;
if (loophack)
if (o < 0) // A little hacky...
{
i = description[char_on].prev;
o += 128;
i = (o / 128);
o = (o % 128);
if (loophack)
i = description[i].prev;
}
else
i = char_on;
// Get prev character...
prev = description[i].prev;
@ -4891,7 +4897,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
next = description[i].next;
// Draw prev character if it's visible and its number isn't greater than the current one or there's more than two
if (o < 32) // (prev != i) was previously a part of this, but we don't need to check again after above.
if (o < 32)
{
patch = W_CachePatchName(description[prev].picname, PU_CACHE);
if (SHORT(patch->width) >= 256)
@ -4911,31 +4917,24 @@ static void M_DrawSetupChoosePlayerMenu(void)
V_DrawCroppedPatch(8<<FRACBITS, (my + 168 - o)<<FRACBITS, FRACUNIT, 0, patch, 0, 0, SHORT(patch->width), o);
W_UnlockCachedPatch(patch);
}
// current character
if (PlayerMenu[i].status & IT_DISABLED) // Prevent flickering.
i = (lastdirection) ? prev : next; // This actually causes duplication at slow scroll speeds (<16FU per tic), but thankfully we always go quickly.
}
if (!(PlayerMenu[i].status & IT_DISABLED))
patch = W_CachePatchName(description[i].picname, PU_CACHE);
if (o >= 0 && o <= 32)
{
patch = W_CachePatchName(description[i].picname, PU_CACHE);
if (o >= 0 && o <= 32)
{
if (SHORT(patch->width) >= 256)
V_DrawSmallScaledPatch(8, my + 40 - o, 0, patch);
else
V_DrawScaledPatch(8, my + 40 - o, 0, patch);
}
if (SHORT(patch->width) >= 256)
V_DrawSmallScaledPatch(8, my + 40 - o, 0, patch);
else
{
if (SHORT(patch->width) >= 256)
V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT/2, 0, patch, 0, (o - 32)*2, SHORT(patch->width), SHORT(patch->height));
else
V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT, 0, patch, 0, o - 32, SHORT(patch->width), SHORT(patch->height));
}
W_UnlockCachedPatch(patch);
V_DrawScaledPatch(8, my + 40 - o, 0, patch);
}
else
{
if (SHORT(patch->width) >= 256)
V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT/2, 0, patch, 0, (o-32)*2, SHORT(patch->width), SHORT(patch->height));
else
V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT, 0, patch, 0, (o-32), SHORT(patch->width), SHORT(patch->height));
}
W_UnlockCachedPatch(patch);
// draw title (or big pic)
M_DrawMenuTitle();
@ -4953,10 +4952,10 @@ static void M_ChoosePlayer(INT32 choice)
boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT);
// skip this if forcecharacter or no characters available
if (!(PlayerMenu[choice].status & IT_DYBIGSPACE))
if (!(SP_PlayerMenu[choice].status & IT_DYBIGSPACE))
{
// M_SetupChoosePlayer didn't call us directly, that means we've been properly set up.
char_scroll = itemOn*128*FRACUNIT; // finish scrolling the menu
char_scroll = 0; // finish scrolling the menu
M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout
}
M_ClearMenus(true);

View File

@ -149,8 +149,6 @@ typedef struct menuitem_s
UINT8 alphaKey;
} menuitem_t;
extern menuitem_t PlayerMenu[32];
typedef struct menu_s
{
const char *menutitlepic;
@ -174,10 +172,10 @@ extern menu_t SP_LoadDef;
// Stuff for customizing the player select screen
typedef struct
{
boolean used;
char notes[441];
char picname[8];
char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
UINT16 wadnum; // for duplicate characters
UINT8 prev;
UINT8 next;
} description_t;