mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
248 lines
5.1 KiB
C
248 lines
5.1 KiB
C
// DR. ROBOTNIK'S RING RACERS
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2024 by Vivian "toastergrl" Grannell.
|
|
// Copyright (C) 2024 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/extras-wrong.c
|
|
/// \brief Wrongwarp
|
|
|
|
#include "../k_menu.h"
|
|
#include "../s_sound.h"
|
|
#include "../m_random.h"
|
|
#include "../music.h"
|
|
#include "../r_skins.h"
|
|
#include "../v_video.h"
|
|
#include "../z_zone.h"
|
|
|
|
struct wrongwarp_s wrongwarp;
|
|
|
|
static menuitem_t MISC_WrongWarpMenu[] =
|
|
{
|
|
{IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0},
|
|
};
|
|
|
|
void M_WrongWarp(INT32 choice)
|
|
{
|
|
(void)choice;
|
|
|
|
wrongwarp.ticker = 0;
|
|
|
|
M_SetupNextMenu(&MISC_WrongWarpDef, false);
|
|
|
|
// Done here to avoid immediate music credit
|
|
Music_Remap("menu_nocred", "YEAWAY");
|
|
Music_Play("menu_nocred");
|
|
}
|
|
|
|
static void M_WrongWarpTick(void)
|
|
{
|
|
static boolean firsteggman = true;
|
|
static boolean antitailgate = false;
|
|
|
|
UINT8 i, j;
|
|
|
|
wrongwarp.ticker++;
|
|
if (wrongwarp.ticker < 2*TICRATE)
|
|
return;
|
|
|
|
if (wrongwarp.ticker == 2*TICRATE)
|
|
{
|
|
S_ShowMusicCredit();
|
|
|
|
for (i = 0; i < MAXWRONGPLAYER; i++)
|
|
wrongwarp.wrongplayers[i].skin = MAXSKINS;
|
|
|
|
firsteggman = true;
|
|
}
|
|
|
|
// SMK title screen recreation!?
|
|
|
|
for (i = 0; i < MAXWRONGPLAYER; i++)
|
|
{
|
|
if (wrongwarp.wrongplayers[i].skin == MAXSKINS)
|
|
continue;
|
|
|
|
wrongwarp.wrongplayers[i].across += 5;
|
|
if (wrongwarp.wrongplayers[i].across < BASEVIDWIDTH + WRONGPLAYEROFFSCREEN)
|
|
continue;
|
|
|
|
wrongwarp.wrongplayers[i].skin = MAXSKINS;
|
|
}
|
|
|
|
if (wrongwarp.delaytowrongplayer)
|
|
{
|
|
wrongwarp.delaytowrongplayer--;
|
|
return;
|
|
}
|
|
|
|
wrongwarp.delaytowrongplayer = M_RandomRange(TICRATE/3, 2*TICRATE/3);
|
|
|
|
if (wrongwarp.ticker == 2*TICRATE)
|
|
return;
|
|
|
|
UINT32 rskin = 0;
|
|
|
|
if (firsteggman == true)
|
|
{
|
|
// Eggman always leads the pack. It's not Sonic's game anymore...
|
|
firsteggman = false;
|
|
|
|
i = 0;
|
|
wrongwarp.wrongplayers[i].spinout = false;
|
|
}
|
|
else
|
|
{
|
|
rskin = R_GetLocalRandomSkin();
|
|
|
|
for (i = 0; i < MAXWRONGPLAYER; i++)
|
|
{
|
|
// Already in use.
|
|
if (wrongwarp.wrongplayers[i].skin == rskin)
|
|
return;
|
|
|
|
// Prevent tailgating.
|
|
if (antitailgate == !!(i & 1))
|
|
continue;
|
|
|
|
// Slot isn't free.
|
|
if (wrongwarp.wrongplayers[i].skin != MAXSKINS)
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
|
|
// No free slots.
|
|
if (i == MAXWRONGPLAYER)
|
|
return;
|
|
|
|
// Check to see if any later entry uses the skin too
|
|
for (j = i+1; j < MAXWRONGPLAYER; j++)
|
|
{
|
|
if (wrongwarp.wrongplayers[j].skin != rskin)
|
|
continue;
|
|
|
|
return;
|
|
}
|
|
|
|
wrongwarp.wrongplayers[i].spinout = M_RandomChance(FRACUNIT/11);
|
|
}
|
|
|
|
// Add the new character!
|
|
wrongwarp.wrongplayers[i].skin = rskin;
|
|
wrongwarp.wrongplayers[i].across = -WRONGPLAYEROFFSCREEN;
|
|
|
|
antitailgate = !!(i & 1);
|
|
}
|
|
|
|
static boolean M_WrongWarpInputs(INT32 ch)
|
|
{
|
|
(void)ch;
|
|
|
|
if (wrongwarp.ticker < TICRATE/2)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
static INT32 M_WrongWarpFallingHelper(INT32 y, INT32 falltime)
|
|
{
|
|
if (wrongwarp.ticker < falltime)
|
|
{
|
|
return y;
|
|
}
|
|
|
|
if (wrongwarp.ticker > falltime + 2*TICRATE)
|
|
{
|
|
return INT32_MAX;
|
|
}
|
|
|
|
if (wrongwarp.ticker < falltime + TICRATE)
|
|
{
|
|
y += + ((wrongwarp.ticker - falltime) & 1 ? 1 : -1);
|
|
return y;
|
|
}
|
|
|
|
y += floor(pow(1.5, (double)(wrongwarp.ticker - (falltime + TICRATE))));
|
|
return y;
|
|
}
|
|
|
|
static void M_DrawWrongWarpBack(void)
|
|
{
|
|
INT32 x, y;
|
|
|
|
if (gamestate == GS_MENU)
|
|
{
|
|
patch_t *pat, *pat2;
|
|
INT32 animtimer, anim2 = 0;
|
|
|
|
pat = W_CachePatchName("TITLEBG1", PU_CACHE);
|
|
pat2 = W_CachePatchName("TITLEBG2", PU_CACHE);
|
|
|
|
animtimer = ((wrongwarp.ticker*5)/16) % SHORT(pat->width);
|
|
anim2 = SHORT(pat2->width) - (((wrongwarp.ticker*5)/16) % SHORT(pat2->width));
|
|
|
|
// SRB2Kart: F_DrawPatchCol is over-engineered; recoded to be less shitty and error-prone
|
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
|
|
|
|
x = -((INT32)animtimer);
|
|
y = 0;
|
|
while (x < BASEVIDWIDTH)
|
|
{
|
|
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, pat, NULL);
|
|
x += SHORT(pat->width);
|
|
}
|
|
|
|
x = -anim2;
|
|
y = BASEVIDHEIGHT - SHORT(pat2->height);
|
|
while (x < BASEVIDWIDTH)
|
|
{
|
|
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, pat2, NULL);
|
|
x += SHORT(pat2->width);
|
|
}
|
|
}
|
|
|
|
{
|
|
patch_t *ttcheckers = W_CachePatchName("TTCHECK", PU_CACHE);
|
|
|
|
y = FixedMul(40<<FRACBITS, FixedDiv(wrongwarp.ticker%70, 70));
|
|
|
|
V_DrawSciencePatch(0, -y, 0, ttcheckers, FRACUNIT);
|
|
V_DrawSciencePatch(280<<FRACBITS, -(40<<FRACBITS) + y, 0, ttcheckers, FRACUNIT);
|
|
|
|
y = M_WrongWarpFallingHelper(36, 7*TICRATE/4);
|
|
if (y != INT32_MAX)
|
|
{
|
|
patch_t *ttbanner = W_CachePatchName("TTKBANNR", PU_CACHE);
|
|
V_DrawSmallScaledPatch(84, y, 0, ttbanner);
|
|
}
|
|
|
|
y = M_WrongWarpFallingHelper(87, 4*TICRATE/3);
|
|
if (y != INT32_MAX)
|
|
{
|
|
patch_t *ttkart = W_CachePatchName("TTKART", PU_CACHE);
|
|
V_DrawSmallScaledPatch(84, y, 0, ttkart);
|
|
}
|
|
}
|
|
}
|
|
|
|
menu_t MISC_WrongWarpDef = {
|
|
sizeof (MISC_WrongWarpMenu)/sizeof (menuitem_t),
|
|
NULL,
|
|
0,
|
|
MISC_WrongWarpMenu,
|
|
0, 0,
|
|
0, 0,
|
|
MBF_SOUNDLESS|MBF_DRAWBGWHILEPLAYING,
|
|
".",
|
|
98, 0,
|
|
M_DrawWrongWarp,
|
|
M_DrawWrongWarpBack,
|
|
M_WrongWarpTick,
|
|
NULL,
|
|
NULL,
|
|
M_WrongWarpInputs,
|
|
};
|