Hold C to use a Chao Key

- Takes a second and a half.
- No accidential usage of your hard-earned Chao Keys.
- Does a full clockwise rotation around the unlocked spot, so there's an intuitive understanding of how long you have to bail out.
This commit is contained in:
toaster 2023-06-04 16:39:39 +01:00
parent 3aca89603b
commit 823315667b
3 changed files with 162 additions and 59 deletions

View file

@ -1176,6 +1176,10 @@ void M_DrawAddons(void);
#define TILEFLIP_MAX 16
#define CHAOHOLD_MAX (3*TICRATE/2)
#define CHAOHOLD_BEGIN 7
#define CHAOHOLD_END 3
extern struct timeattackmenu_s {
tic_t ticker; // How long the menu's been open for
@ -1201,7 +1205,9 @@ extern struct challengesmenu_s {
boolean pending;
boolean requestnew;
boolean chaokeyadd;
UINT8 chaokeyhold;
boolean requestflip;

View file

@ -5333,7 +5333,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
void M_DrawChallenges(void)
{
INT32 x = currentMenu->x, explodex, selectx;
INT32 x = currentMenu->x, explodex, selectx = 0, selecty = 0;
INT32 y;
INT16 i, j;
const char *str;
@ -5410,6 +5410,7 @@ void M_DrawChallenges(void)
}
selectx = explodex + (challengesmenu.hilix*challengesgridstep);
selecty = currentMenu->y + (challengesmenu.hiliy*challengesgridstep);
while (i >= 0 && x >= -(challengesgridstep*2))
{
@ -5447,49 +5448,12 @@ void M_DrawChallenges(void)
challengesmenu.hilix,
challengesmenu.hiliy,
selectx,
currentMenu->y + (challengesmenu.hiliy*challengesgridstep),
selecty,
true);
M_DrawCharSelectExplosions(false, explodex, currentMenu->y);
challengedesc:
// Chao Keys
{
patch_t *key = W_CachePatchName("UN_CHA00", PU_CACHE);
INT32 offs = challengesmenu.unlockcount[CC_CHAONOPE];
if (offs & 1)
offs = -offs;
offs /= 2;
if (gamedata->chaokeys > 9)
{
offs -= 6;
if (gamedata->chaokeys > 99)
offs -= 2; // as far as we can go
}
V_DrawFixedPatch((8+offs)*FRACUNIT, 5*FRACUNIT, FRACUNIT, 0, key, NULL);
V_DrawTimerString((27+offs), 9-challengesmenu.unlockcount[CC_CHAOANIM], 0, va("%u", gamedata->chaokeys));
offs = challengekeybarwidth;
if (gamedata->chaokeys < GDMAX_CHAOKEYS)
offs = ((gamedata->pendingkeyroundoffset * challengekeybarwidth)/GDCONVERT_ROUNDSTOKEY);
if (offs > 0)
V_DrawFill(1, 25, offs, 2, 0);
if (offs < challengekeybarwidth)
V_DrawFadeFill(1+offs, 25, challengekeybarwidth-offs, 2, 0, 31, challengetransparentstrength);
}
// Tally
{
str = va("%d/%d",
challengesmenu.unlockcount[CC_UNLOCKED] + challengesmenu.unlockcount[CC_TALLY],
challengesmenu.unlockcount[CC_TOTAL]
);
V_DrawRightAlignedTimerString(BASEVIDWIDTH-7, 9-challengesmenu.unlockcount[CC_ANIM], 0, str);
}
// Name bar
{
y = 120;
@ -5511,6 +5475,88 @@ challengedesc:
V_DrawLSTitleLowString(BASEVIDWIDTH/2 - offset, y+6, 0, str);
}
// Tally
{
str = va("%d/%d",
challengesmenu.unlockcount[CC_UNLOCKED] + challengesmenu.unlockcount[CC_TALLY],
challengesmenu.unlockcount[CC_TOTAL]
);
V_DrawRightAlignedTimerString(BASEVIDWIDTH-7, 9-challengesmenu.unlockcount[CC_ANIM], 0, str);
}
// Chao Keys
{
patch_t *key = W_CachePatchName("UN_CHA00", PU_CACHE);
INT32 offs = challengesmenu.unlockcount[CC_CHAONOPE];
if (offs & 1)
offs = -offs;
offs /= 2;
if (gamedata->chaokeys > 9)
{
offs -= 6;
if (gamedata->chaokeys > 99)
offs -= 2; // as far as we can go
}
fixed_t keyx = (8+offs)*FRACUNIT, keyy = 5*FRACUNIT;
if (!challengesmenu.chaokeyhold)
V_DrawFixedPatch(keyx, keyy, FRACUNIT, 0, key, NULL);
V_DrawTimerString((27+offs), 9-challengesmenu.unlockcount[CC_CHAOANIM], 0, va("%u", gamedata->chaokeys));
offs = challengekeybarwidth;
if (gamedata->chaokeys < GDMAX_CHAOKEYS)
offs = ((gamedata->pendingkeyroundoffset * challengekeybarwidth)/GDCONVERT_ROUNDSTOKEY);
if (offs > 0)
V_DrawFill(1, 25, offs, 2, 0);
if (offs < challengekeybarwidth)
V_DrawFadeFill(1+offs, 25, challengekeybarwidth-offs, 2, 0, 31, challengetransparentstrength);
if (challengesmenu.chaokeyhold)
{
fixed_t keyholdrotation = 0, radius = challengesgridstep;
if (challengesmenu.chaokeyhold < CHAOHOLD_BEGIN)
{
radius = (challengesmenu.chaokeyhold*radius)*(FRACUNIT/CHAOHOLD_BEGIN);
keyx += challengesmenu.chaokeyhold*((selectx*FRACUNIT) - keyx)/CHAOHOLD_BEGIN;
keyy += challengesmenu.chaokeyhold*((selecty*FRACUNIT) - keyy)/CHAOHOLD_BEGIN;
}
else
{
if (challengesmenu.chaokeyhold < CHAOHOLD_MAX - CHAOHOLD_END)
{
radius <<= FRACBITS;
keyholdrotation = 360 * ((challengesmenu.chaokeyhold - CHAOHOLD_BEGIN))
* (FRACUNIT/(CHAOHOLD_MAX - (CHAOHOLD_BEGIN + CHAOHOLD_END)));
}
else
{
radius = ((CHAOHOLD_MAX - challengesmenu.chaokeyhold)*radius)*(FRACUNIT/CHAOHOLD_END);
}
keyx = selectx*FRACUNIT;
keyy = selecty*FRACUNIT;
}
if (radius)
{
angle_t ang = (FixedAngle(
keyholdrotation
) >> ANGLETOFINESHIFT) & FINEMASK;
keyx += FixedMul(radius, FINESINE(ang));
keyy -= FixedMul(radius, FINECOSINE(ang));
}
}
V_DrawFixedPatch(keyx, keyy, FRACUNIT, 0, key, NULL);
}
// Derived from M_DrawCharSelectPreview
x = 40;
y = BASEVIDHEIGHT-16;

View file

@ -226,6 +226,7 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu)
challengesmenu.requestflip = false;
challengesmenu.requestnew = false;
challengesmenu.chaokeyadd = false;
challengesmenu.chaokeyhold = 0;
challengesmenu.currentunlock = MAXUNLOCKABLES;
challengesmenu.unlockcondition = NULL;
@ -284,6 +285,39 @@ void M_Challenges(INT32 choice)
M_SetupNextMenu(&MISC_ChallengesDef, false);
}
static boolean M_CanKeyHiliTile(void)
{
// No keys to do it with?
if (gamedata->chaokeys == 0)
return false;
// No tile data?
if (challengesmenu.extradata == NULL)
return false;
// No selected tile?
if (challengesmenu.currentunlock >= MAXUNLOCKABLES)
return false;
// Already unlocked?
if (gamedata->unlocked[challengesmenu.currentunlock] == true)
return false;
// Marked as unskippable?
if (unlockables[challengesmenu.currentunlock].majorunlock == true)
return false;
UINT16 i = (challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy;
// Not a hinted tile OR a fresh board.
if (!(challengesmenu.extradata[i].flags & CHE_HINT)
&& (challengesmenu.unlockcount[CC_UNLOCKED] + challengesmenu.unlockcount[CC_TALLY] > 0))
return false;
// All good!
return true;
}
void M_ChallengesTick(void)
{
const UINT8 pid = 0;
@ -328,7 +362,38 @@ void M_ChallengesTick(void)
}
}
if (challengesmenu.pending && challengesmenu.fade < 5)
if (challengesmenu.chaokeyhold)
{
if (M_MenuExtraHeld(pid) && M_CanKeyHiliTile())
{
// Not pressed just this frame?
if (!M_MenuExtraPressed(pid))
{
challengesmenu.chaokeyhold++;
if (challengesmenu.chaokeyhold > CHAOHOLD_MAX)
{
gamedata->chaokeys--;
challengesmenu.chaokeyhold = 0;
challengesmenu.unlockcount[CC_CHAOANIM]++;
S_StartSound(NULL, sfx_chchng);
challengesmenu.pending = true;
//M_ChallengesAutoFocus(challengesmenu.currentunlock, false);
challengesmenu.unlockanim = UNLOCKTIME-1;
}
}
}
else
{
challengesmenu.chaokeyhold = 0;
challengesmenu.unlockcount[CC_CHAONOPE] = 6;
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2
}
}
if ((challengesmenu.pending || challengesmenu.chaokeyhold) && challengesmenu.fade < 5)
{
// Fade increase.
challengesmenu.fade++;
@ -486,7 +551,7 @@ void M_ChallengesTick(void)
}
}
}
else
else if (!challengesmenu.chaokeyhold)
{
// Tick down the tally. (currently not visible)
@ -517,29 +582,15 @@ boolean M_ChallengesInputs(INT32 ch)
const boolean move = (menucmd[pid].dpad_ud != 0 || menucmd[pid].dpad_lr != 0);
(void) ch;
if (challengesmenu.fade || challengesmenu.chaokeyadd)
if (challengesmenu.fade || challengesmenu.chaokeyadd || challengesmenu.chaokeyhold)
{
;
}
else if (M_MenuExtraPressed(pid)
&& challengesmenu.extradata)
else if (M_MenuExtraPressed(pid))
{
i = (challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy;
if (challengesmenu.currentunlock < MAXUNLOCKABLES
&& !gamedata->unlocked[challengesmenu.currentunlock]
&& !unlockables[challengesmenu.currentunlock].majorunlock
&& ((challengesmenu.extradata[i].flags & CHE_HINT)
|| (challengesmenu.unlockcount[CC_UNLOCKED] + challengesmenu.unlockcount[CC_TALLY] == 0))
&& gamedata->chaokeys > 0)
if (M_CanKeyHiliTile())
{
gamedata->chaokeys--;
challengesmenu.unlockcount[CC_CHAOANIM]++;
S_StartSound(NULL, sfx_chchng);
challengesmenu.pending = true;
M_ChallengesAutoFocus(challengesmenu.currentunlock, false);
challengesmenu.chaokeyhold = 1;
}
else
{