mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
New titlecards
This commit is contained in:
parent
47ab83c2d8
commit
f2f0a6cbe2
11 changed files with 544 additions and 125 deletions
10
src/d_main.c
10
src/d_main.c
|
|
@ -615,16 +615,6 @@ static void D_Display(void)
|
|||
{
|
||||
F_WipeEndScreen();
|
||||
|
||||
// Funny.
|
||||
if (WipeStageTitle && st_overlay)
|
||||
{
|
||||
lt_ticker--;
|
||||
lt_lasttic = lt_ticker;
|
||||
ST_preLevelTitleCardDrawer();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
F_WipeStartScreen();
|
||||
}
|
||||
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN, "FADEMAP0", true, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ typedef struct
|
|||
extern mapheader_t* mapheaderinfo[NUMMAPS];
|
||||
|
||||
// This could support more, but is that a good idea?
|
||||
// Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory.
|
||||
// Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory.
|
||||
#define MAXLEVELLIST 5
|
||||
|
||||
typedef struct cupheader_s
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ extern INT32 lastwipetic;
|
|||
|
||||
// Don't know where else to place this constant
|
||||
// But this file seems appropriate
|
||||
#define PRELEVELTIME 24 // frames in tics
|
||||
#define PRELEVELTIME TICRATE // frames in tics
|
||||
|
||||
void F_WipeStartScreen(void);
|
||||
void F_WipeEndScreen(void);
|
||||
|
|
|
|||
|
|
@ -1139,7 +1139,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
|
||||
// Send leveltime when this tic was generated to the server for control lag calculations.
|
||||
// Only do this when in a level. Also do this after the hook, so that it can't overwrite this.
|
||||
cmd->latency = (leveltime & 0xFF);
|
||||
cmd->latency = (leveltime & 0xFF);
|
||||
}
|
||||
|
||||
if (cmd->forwardmove > MAXPLMOVE)
|
||||
|
|
@ -1301,7 +1301,7 @@ void G_StartTitleCard(void)
|
|||
ST_startTitleCard();
|
||||
|
||||
// start the title card
|
||||
WipeStageTitle = false; //(!titlemapinaction); -- temporary until titlecards are reworked
|
||||
WipeStageTitle = (!titlemapinaction);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1322,7 +1322,7 @@ void G_PreLevelTitleCard(void)
|
|||
lasttime = nowtime;
|
||||
|
||||
ST_runTitleCard();
|
||||
ST_preLevelTitleCardDrawer();
|
||||
ST_drawTitleCard();
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
|
||||
if (moviemode)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@
|
|||
patch_t *pinggfx[5]; // small ping graphic
|
||||
patch_t *mping[5]; // smaller ping graphic
|
||||
|
||||
patch_t *tc_font[2][LT_FONTSIZE]; // Special font stuff for titlecard
|
||||
|
||||
patch_t *framecounter;
|
||||
patch_t *frameslash; // framerate stuff. Used in screen.c
|
||||
|
||||
|
|
@ -178,7 +180,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum);
|
|||
|
||||
void HU_LoadGraphics(void)
|
||||
{
|
||||
INT32 i;
|
||||
char buffer[9];
|
||||
INT32 i, j;
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
|
|
@ -191,6 +194,27 @@ void HU_LoadGraphics(void)
|
|||
emblemicon = HU_CachePatch("EMBLICON");
|
||||
songcreditbg = HU_CachePatch("K_SONGCR");
|
||||
|
||||
// Cache titlecard font
|
||||
j = LT_FONTSTART;
|
||||
for (i = 0; i < LT_FONTSIZE; i++, j++)
|
||||
{
|
||||
// cache the titlecard font
|
||||
|
||||
// Bottom layer
|
||||
sprintf(buffer, "GTOL%.3d", j);
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
tc_font[0][i] = NULL;
|
||||
else
|
||||
tc_font[0][i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
|
||||
// Top layer
|
||||
sprintf(buffer, "GTFN%.3d", j);
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
tc_font[1][i] = NULL;
|
||||
else
|
||||
tc_font[1][i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache ping gfx:
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
|
|
@ -704,7 +728,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
}
|
||||
else if (target == -1) // say team
|
||||
{
|
||||
if (players[playernum].ctfteam == 1)
|
||||
if (players[playernum].ctfteam == 1)
|
||||
{
|
||||
// red text
|
||||
cstart = textcolor = "\x85";
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@
|
|||
#define LT_FONTEND 'z' // the last font characters
|
||||
#define LT_FONTSIZE (LT_FONTEND - LT_FONTSTART + 1)
|
||||
|
||||
// Under regular circumstances, we'd use the built in font stuff, however this font is a bit messy because of how we're gonna draw shit.
|
||||
// tc_font[0][n] is used for the "bottom" layer
|
||||
// tc_font[1][n] is used for the "top" layer
|
||||
extern patch_t *tc_font[2][LT_FONTSIZE];
|
||||
|
||||
#define CRED_FONTSTART '!' // the first font character
|
||||
#define CRED_FONTEND 'Z' // the last font character
|
||||
#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1)
|
||||
|
|
|
|||
|
|
@ -946,6 +946,24 @@ static int libd_drawString(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawTitleCardString(lua_State *L)
|
||||
{
|
||||
|
||||
fixed_t x = luaL_checkinteger(L, 1);
|
||||
fixed_t y = luaL_checkinteger(L, 2);
|
||||
const char *str = luaL_checkstring(L, 3);
|
||||
INT32 flags = luaL_optinteger(L, 4, V_ALLOWLOWERCASE);
|
||||
boolean rightalign = lua_optboolean(L, 5);
|
||||
INT32 timer = luaL_optinteger(L, 6, 0);
|
||||
INT32 threshold = luaL_optinteger(L, 7, 0);
|
||||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
HUDONLY
|
||||
V_DrawTitleCardString(x, y, str, flags, rightalign, timer, threshold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawKartString(lua_State *L)
|
||||
{
|
||||
fixed_t x = luaL_checkinteger(L, 1);
|
||||
|
|
@ -960,6 +978,15 @@ static int libd_drawKartString(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int libd_titleCardStringWidth(lua_State *L)
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 1);
|
||||
HUDONLY
|
||||
|
||||
lua_pushinteger(L, V_TitleCardStringWidth(str));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int libd_stringWidth(lua_State *L)
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 1);
|
||||
|
|
@ -1163,9 +1190,11 @@ static luaL_Reg lib_draw[] = {
|
|||
{"drawFill", libd_drawFill},
|
||||
{"fadeScreen", libd_fadeScreen},
|
||||
{"drawString", libd_drawString},
|
||||
{"drawTitleCardString", libd_drawTitleCardString},
|
||||
{"drawKartString", libd_drawKartString},
|
||||
// misc
|
||||
{"stringWidth", libd_stringWidth},
|
||||
{"titleCardStringWidth", libd_titleCardStringWidth},
|
||||
// m_random
|
||||
{"RandomFixed",libd_RandomFixed},
|
||||
{"RandomByte",libd_RandomByte},
|
||||
|
|
|
|||
|
|
@ -3981,8 +3981,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
F_RunWipe(wipedefs[wipe_level_toblack], false, ((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), false, false);
|
||||
}
|
||||
if (!titlemapinaction)
|
||||
wipegamestate = GS_LEVEL;
|
||||
/*if (!titlemapinaction)
|
||||
wipegamestate = GS_LEVEL;*/
|
||||
|
||||
// Close text prompt before freeing the old level
|
||||
F_EndTextPrompt(false, true);
|
||||
|
|
|
|||
430
src/st_stuff.c
430
src/st_stuff.c
|
|
@ -31,6 +31,7 @@
|
|||
#include "m_misc.h" // moviemode
|
||||
#include "m_anigif.h" // cv_gif_downscale
|
||||
#include "p_setup.h" // NiGHTS grading
|
||||
#include "k_grandprix.h" // we need to know grandprix status for titlecards
|
||||
|
||||
//random index
|
||||
#include "m_random.h"
|
||||
|
|
@ -622,23 +623,97 @@ static void ST_drawDebugInfo(void)
|
|||
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("Heap used: %7sKB", sizeu1(Z_TagsUsage(0, INT32_MAX)>>10)));
|
||||
}
|
||||
|
||||
static patch_t *lt_patches[3];
|
||||
static INT32 lt_scroll = 0;
|
||||
static INT32 lt_mom = 0;
|
||||
static INT32 lt_zigzag = 0;
|
||||
|
||||
tic_t lt_ticker = 0, lt_lasttic = 0;
|
||||
tic_t lt_exitticker = 0, lt_endtime = 0;
|
||||
|
||||
// SRB2KART: HUD shit for new titlecards:
|
||||
static patch_t *tcchev1;
|
||||
static patch_t *tcchev2;
|
||||
|
||||
static patch_t *tcol1;
|
||||
static patch_t *tcol2;
|
||||
|
||||
static patch_t *tcroundbar;
|
||||
static patch_t *tcround;
|
||||
|
||||
static patch_t *tccircletop;
|
||||
static patch_t *tccirclebottom;
|
||||
static patch_t *tccirclebg;
|
||||
|
||||
static patch_t *tcbanner;
|
||||
static patch_t *tcbanner2;
|
||||
|
||||
static patch_t *tcroundnum[10];
|
||||
static patch_t *tcactnum[10];
|
||||
static patch_t *tcact;
|
||||
|
||||
// some coordinates define to make my life easier....
|
||||
#define FINAL_ROUNDX (24)
|
||||
#define FINAL_EGGY (160)
|
||||
#define FINAL_ROUNDY (16)
|
||||
#define FINAL_BANNERY (160)
|
||||
|
||||
INT32 chev1x, chev1y, chev2x, chev2y, chevtflag;
|
||||
INT32 roundx, roundy;
|
||||
INT32 bannerx, bannery;
|
||||
|
||||
INT32 roundnumx, roundnumy;
|
||||
INT32 eggx1, eggx2, eggy1, eggy2;
|
||||
|
||||
// These are all arbitrary values found by trial and error trying to align the hud lmao.
|
||||
// But they'll work.
|
||||
#define BASE_CHEV1X (252)
|
||||
#define BASE_CHEV1Y (60)
|
||||
#define BASE_CHEV2X (65)
|
||||
#define BASE_CHEV2Y (135)
|
||||
|
||||
#define TTANIMTHRESHOLD (TICRATE)
|
||||
#define TTANIMSTART (TTANIMTHRESHOLD-16)
|
||||
#define TTANIMENDTHRESHOLD (TICRATE*3)
|
||||
#define TTANIMEND (TICRATE*4)
|
||||
|
||||
//
|
||||
// Load the graphics for the title card.
|
||||
// Don't let LJ see this
|
||||
//
|
||||
static void ST_cacheLevelTitle(void)
|
||||
{
|
||||
lt_patches[0] = (patch_t *)W_CachePatchName("LTACTBLU", PU_HUDGFX);
|
||||
lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGZAG", PU_HUDGFX);
|
||||
lt_patches[2] = (patch_t *)W_CachePatchName("LTZZTEXT", PU_HUDGFX);
|
||||
UINT8 i;
|
||||
char buf[9];
|
||||
|
||||
// SRB2KART
|
||||
tcchev1 = (patch_t *)W_CachePatchName("TCCHEV1W", PU_HUDGFX);
|
||||
tcchev2 = (patch_t *)W_CachePatchName("TCCHEV2W", PU_HUDGFX);
|
||||
|
||||
tcol1 = (patch_t *)W_CachePatchName("TCCHOL1", PU_HUDGFX);
|
||||
tcol2 = (patch_t *)W_CachePatchName("TCCHOL2", PU_HUDGFX);
|
||||
|
||||
tcroundbar = (patch_t *)W_CachePatchName("TCBB0", PU_HUDGFX);
|
||||
tcround = (patch_t *)W_CachePatchName("TCROUND", PU_HUDGFX);
|
||||
|
||||
tccircletop = (patch_t *)W_CachePatchName("TCSN1", PU_HUDGFX);
|
||||
tccirclebottom =(patch_t *)W_CachePatchName("TCSN2", PU_HUDGFX);
|
||||
tccirclebg = (patch_t *)W_CachePatchName("TCEG3", PU_HUDGFX);
|
||||
|
||||
tcbanner = (patch_t *)W_CachePatchName("TCBSKA0", PU_HUDGFX);
|
||||
tcbanner2 = (patch_t *)W_CachePatchName("TCBC0", PU_HUDGFX);
|
||||
|
||||
tcact = (patch_t *)W_CachePatchName("TT_ACT", PU_HUDGFX);
|
||||
|
||||
// Cache round #
|
||||
for (i=1; i < 11; i++)
|
||||
{
|
||||
sprintf(buf, "TT_RND%d", i);
|
||||
tcroundnum[i-1] = (patch_t *)W_CachePatchName(buf, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// Cache act #
|
||||
for (i=0; i < 10; i++)
|
||||
{
|
||||
sprintf(buf, "TT_ACT%d", i);
|
||||
tcactnum[i] = (patch_t *)W_CachePatchName(buf, PU_HUDGFX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -649,12 +724,28 @@ void ST_startTitleCard(void)
|
|||
// cache every HUD patch used
|
||||
ST_cacheLevelTitle();
|
||||
|
||||
// Set most elements to start off-screen, ST_runTitleCard will have them slide in afterwards
|
||||
chev1x = BASE_CHEV1X +350; // start off-screen
|
||||
chev1y = BASE_CHEV1Y;
|
||||
chev2x = BASE_CHEV2X -350; // start off-screen
|
||||
chev2y = BASE_CHEV2Y;
|
||||
chevtflag = 0;
|
||||
|
||||
roundx = -999;
|
||||
roundy = -999;
|
||||
|
||||
roundnumx = -999;
|
||||
roundnumy = -999;
|
||||
eggx1 = -999;
|
||||
eggx2 = -999;
|
||||
eggy1 = -999;
|
||||
eggy2 = -999;
|
||||
|
||||
bannery = 300;
|
||||
|
||||
// initialize HUD variables
|
||||
lt_ticker = lt_exitticker = lt_lasttic = 0;
|
||||
lt_endtime = 2*TICRATE + (10*NEWTICRATERATIO);
|
||||
lt_scroll = BASEVIDWIDTH * FRACUNIT;
|
||||
lt_zigzag = -((lt_patches[1])->width * FRACUNIT);
|
||||
lt_mom = 0;
|
||||
lt_endtime = 4*TICRATE; // + (10*NEWTICRATERATIO);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -679,6 +770,8 @@ void ST_preDrawTitleCard(void)
|
|||
void ST_runTitleCard(void)
|
||||
{
|
||||
boolean run = !(paused || P_AutoPause());
|
||||
tic_t auxticker;
|
||||
boolean gp = (grandprixinfo.gp && grandprixinfo.roundnum); // check whether we're in grandprix
|
||||
|
||||
if (!G_IsTitleCardAvailable())
|
||||
return;
|
||||
|
|
@ -690,35 +783,152 @@ void ST_runTitleCard(void)
|
|||
{
|
||||
// tick
|
||||
lt_ticker++;
|
||||
|
||||
// SRB2KART
|
||||
// side Zig-Zag positions...
|
||||
|
||||
// TITLECARD START
|
||||
if (lt_ticker < TTANIMSTART)
|
||||
{
|
||||
chev1x = (BASE_CHEV1X + 350) - lt_ticker*50;
|
||||
if (chev1x < BASE_CHEV1X)
|
||||
chev1x = BASE_CHEV1X; // min/max macros don't work well with signed, it seems
|
||||
|
||||
chev2x = (BASE_CHEV2X - 350) + lt_ticker*50;
|
||||
if (chev2x > BASE_CHEV2X)
|
||||
chev2x = BASE_CHEV2X; // ditto
|
||||
}
|
||||
|
||||
// OPEN ZIG-ZAGS 1 SECOND IN
|
||||
if (lt_ticker > TTANIMTHRESHOLD)
|
||||
{
|
||||
auxticker = lt_ticker - TTANIMTHRESHOLD;
|
||||
|
||||
chev1x = BASE_CHEV1X + auxticker*16;
|
||||
if (chev1x > 320)
|
||||
chev1x = 320;
|
||||
|
||||
chev1y = BASE_CHEV1Y - auxticker*16;
|
||||
if (chev1y < 0)
|
||||
chev1y = 0;
|
||||
|
||||
chev2x = BASE_CHEV2X - auxticker*16;
|
||||
if (chev2x < 0)
|
||||
chev2x = 0;
|
||||
|
||||
chev2y = BASE_CHEV2Y + auxticker*16;
|
||||
if (chev2y > 200)
|
||||
chev2y = 200;
|
||||
|
||||
// translucent fade after opening up.
|
||||
chevtflag = min(5, ((auxticker)/5)) << V_ALPHASHIFT;
|
||||
|
||||
|
||||
// OPEN ZIG-ZAG: END OF ANIMATION (they leave the screen borders)
|
||||
if (lt_ticker > TTANIMENDTHRESHOLD)
|
||||
{
|
||||
auxticker = lt_ticker - TTANIMENDTHRESHOLD;
|
||||
|
||||
chev1x += auxticker*16;
|
||||
chev1y -= auxticker*16;
|
||||
|
||||
chev2x -= auxticker*16;
|
||||
chev2y += auxticker*16;
|
||||
}
|
||||
}
|
||||
|
||||
// ROUND BAR + EGG
|
||||
|
||||
eggy1 = FINAL_EGGY; // Make sure to reset that each call so that Y position doesn't go bonkers
|
||||
|
||||
// SLIDE BAR IN, SLIDE "ROUND" DOWNWARDS
|
||||
if (lt_ticker <= TTANIMTHRESHOLD)
|
||||
{
|
||||
INT32 interptimer = (INT32)lt_ticker - TTANIMSTART;
|
||||
// INT32 because tic_t is unsigned and we want this to be potentially negative
|
||||
|
||||
if (interptimer >= 0)
|
||||
{
|
||||
INT32 interpdiff = ((TTANIMTHRESHOLD-TTANIMSTART) - interptimer);
|
||||
interpdiff *= interpdiff; // interpdiff^2
|
||||
|
||||
roundx = FINAL_ROUNDX - interpdiff;
|
||||
roundy = FINAL_ROUNDY - interpdiff;
|
||||
eggy1 = FINAL_EGGY + interpdiff;
|
||||
|
||||
}
|
||||
}
|
||||
// SLIDE BAR OUT, SLIDE "ROUND" DOWNWARDS FASTER
|
||||
else if (lt_ticker >= TTANIMENDTHRESHOLD)
|
||||
{
|
||||
auxticker = lt_ticker - TTANIMENDTHRESHOLD;
|
||||
|
||||
roundx = FINAL_ROUNDX - auxticker*24;
|
||||
roundy = FINAL_ROUNDY + auxticker*48;
|
||||
eggy1 = FINAL_EGGY + auxticker*48;
|
||||
}
|
||||
|
||||
// follow the round bar.
|
||||
eggx1 = roundx + tcroundbar->width/2;
|
||||
|
||||
// initially, both halves are on the same coordinates.
|
||||
eggx2 = eggx1;
|
||||
eggy2 = eggy1;
|
||||
// same for the background (duh)
|
||||
roundnumx = eggx1;
|
||||
roundnumy = eggy1;
|
||||
|
||||
// split both halves of the egg, but only do that in grand prix!
|
||||
if (gp && lt_ticker > TTANIMTHRESHOLD + TICRATE/2)
|
||||
{
|
||||
auxticker = lt_ticker - (TTANIMTHRESHOLD + TICRATE/2);
|
||||
|
||||
eggx1 -= auxticker*12;
|
||||
eggy1 -= auxticker*12;
|
||||
|
||||
eggx2 += auxticker*12;
|
||||
eggy2 += auxticker*12;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// SCROLLING BOTTOM BANNER
|
||||
|
||||
// SLIDE BANNER UPWARDS WITH A FUNNY BOUNCE (this requires trig :death:)
|
||||
if (lt_ticker < TTANIMTHRESHOLD)
|
||||
{
|
||||
INT32 costimer = (INT32)lt_ticker - TTANIMSTART;
|
||||
// INT32 because tic_t is unsigned and we want this to be potentially negative
|
||||
|
||||
if (costimer > 0)
|
||||
{
|
||||
// For this animation, we're going to do a tiny bit of stupid trigonometry.
|
||||
// Admittedly all of this is going to look like magic numbers, and honestly? They are.
|
||||
|
||||
// start at angle 355 (where y = ~230 with our params)
|
||||
// and go to angle 131 (where y = ~160 with our params)
|
||||
|
||||
UINT8 basey = 190;
|
||||
UINT8 amplitude = 45;
|
||||
fixed_t ang = (355 - costimer*14)*FRACUNIT;
|
||||
|
||||
bannery = basey + (amplitude * FINECOSINE(FixedAngle(ang)>>ANGLETOFINESHIFT)) / FRACUNIT;
|
||||
}
|
||||
}
|
||||
// SLIDE BANNER DOWNWARDS OUT OF THE SCREEN AT THE END
|
||||
else if (lt_ticker >= TTANIMENDTHRESHOLD)
|
||||
{
|
||||
auxticker = lt_ticker - TTANIMENDTHRESHOLD;
|
||||
bannery = FINAL_BANNERY + auxticker*16;
|
||||
}
|
||||
|
||||
// No matter the circumstances, scroll the banner...
|
||||
bannerx = -(lt_ticker%(tcbanner->width));
|
||||
|
||||
|
||||
// used for hud slidein
|
||||
if (lt_ticker >= lt_endtime)
|
||||
lt_exitticker++;
|
||||
|
||||
// scroll to screen (level title)
|
||||
if (!lt_exitticker)
|
||||
{
|
||||
if (abs(lt_scroll) > FRACUNIT)
|
||||
lt_scroll -= (lt_scroll>>2);
|
||||
else
|
||||
lt_scroll = 0;
|
||||
}
|
||||
// scroll away from screen (level title)
|
||||
else
|
||||
{
|
||||
lt_mom -= FRACUNIT*6;
|
||||
lt_scroll += lt_mom;
|
||||
}
|
||||
|
||||
// scroll to screen (zigzag)
|
||||
if (!lt_exitticker)
|
||||
{
|
||||
if (abs(lt_zigzag) > FRACUNIT)
|
||||
lt_zigzag -= (lt_zigzag>>2);
|
||||
else
|
||||
lt_zigzag = 0;
|
||||
}
|
||||
// scroll away from screen (zigzag)
|
||||
else
|
||||
lt_zigzag += lt_mom;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -729,25 +939,17 @@ void ST_runTitleCard(void)
|
|||
void ST_drawTitleCard(void)
|
||||
{
|
||||
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
|
||||
char *subttl = mapheaderinfo[gamemap-1]->subttl;
|
||||
char *zonttl = mapheaderinfo[gamemap-1]->zonttl; // SRB2kart
|
||||
UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
|
||||
INT32 lvlttlxpos, ttlnumxpos, zonexpos;
|
||||
INT32 subttlxpos = BASEVIDWIDTH/2;
|
||||
INT32 ttlscroll = FixedInt(lt_scroll);
|
||||
#ifdef TITLEPATCHES
|
||||
INT32 zzticker;
|
||||
patch_t *actpat, *zigzag, *zztext;
|
||||
UINT8 colornum;
|
||||
const UINT8 *colormap;
|
||||
boolean gp = (grandprixinfo.gp && grandprixinfo.roundnum);
|
||||
|
||||
if (players[g_localplayers[0]].skincolor)
|
||||
colornum = players[g_localplayers[0]].skincolor;
|
||||
else
|
||||
colornum = cv_playercolor[0].value;
|
||||
INT32 acttimer;
|
||||
fixed_t actscale;
|
||||
angle_t fakeangle;
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE);
|
||||
#endif
|
||||
INT32 bx = bannerx; // We need to make a copy of that otherwise pausing will cause problems.
|
||||
|
||||
UINT8 i;
|
||||
|
||||
if (!G_IsTitleCardAvailable())
|
||||
return;
|
||||
|
|
@ -761,66 +963,88 @@ void ST_drawTitleCard(void)
|
|||
if ((lt_ticker-lt_lasttic) > 1)
|
||||
lt_ticker = lt_lasttic+1;
|
||||
|
||||
ST_cacheLevelTitle();
|
||||
// Avoid HOMs while drawing the start of the titlecard
|
||||
if (lt_ticker < TTANIMSTART)
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
|
||||
#ifdef TITLEPATCHES
|
||||
actpat = lt_patches[0];
|
||||
zigzag = lt_patches[1];
|
||||
zztext = lt_patches[2];
|
||||
#endif
|
||||
// Background zig-zags
|
||||
V_DrawFixedPatch((chev1x)*FRACUNIT, (chev1y)*FRACUNIT, FRACUNIT, chevtflag, tcchev1, NULL);
|
||||
V_DrawFixedPatch((chev2x)*FRACUNIT, (chev2y)*FRACUNIT, FRACUNIT, chevtflag, tcchev2, NULL);
|
||||
|
||||
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
|
||||
|
||||
if (actnum > 0)
|
||||
lvlttlxpos -= V_LevelNameWidth(va("%d", actnum));
|
||||
// Draw ROUND bar, scroll it downwards.
|
||||
V_DrawFixedPatch(roundx*FRACUNIT, ((-32) + (lt_ticker%32))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, tcroundbar, NULL);
|
||||
// Draw ROUND text
|
||||
if (gp)
|
||||
V_DrawFixedPatch((roundx+10)*FRACUNIT, roundy*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, tcround, NULL);
|
||||
|
||||
zonexpos = ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl);
|
||||
if (zonttl[0])
|
||||
zonexpos -= V_LevelNameWidth(zonttl); // SRB2kart
|
||||
else
|
||||
zonexpos -= V_LevelNameWidth(M_GetText("Zone"));
|
||||
// round num background
|
||||
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccirclebg, NULL);
|
||||
|
||||
ttlnumxpos++;
|
||||
|
||||
if (lvlttlxpos < 0)
|
||||
lvlttlxpos = 0;
|
||||
|
||||
#ifdef TITLEPATCHES
|
||||
if (!splitscreen || (splitscreen && stplyr == &players[displayplayers[0]]))
|
||||
// Scrolling banner, we'll draw 3 of those back to back.
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
zzticker = lt_ticker;
|
||||
V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
|
||||
V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
|
||||
V_DrawMappedPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
|
||||
V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
|
||||
V_DrawFixedPatch((bannerx + bx)*FRACUNIT, (bannery)*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tcbanner, NULL);
|
||||
bx += tcbanner->width;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (actnum)
|
||||
// If possible, draw round number
|
||||
if (gp && grandprixinfo.roundnum > 0 && grandprixinfo.roundnum < 11) // Check boundaries JUST IN CASE.
|
||||
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tcroundnum[grandprixinfo.roundnum-1], NULL);
|
||||
|
||||
// Draw both halves of the egg
|
||||
V_DrawFixedPatch(eggx1*FRACUNIT, eggy1*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccircletop, NULL);
|
||||
V_DrawFixedPatch(eggx2*FRACUNIT, eggy2*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccirclebottom, NULL);
|
||||
|
||||
// Now the level name.
|
||||
V_DrawTitleCardString((actnum) ? 265 : 280, 60, lvlttl, V_SNAPTORIGHT, true, lt_ticker, TTANIMENDTHRESHOLD);
|
||||
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
V_DrawTitleCardString((actnum) ? 265 : 280, 60+32, strlen(zonttl) ? zonttl : "ZONE", V_SNAPTORIGHT, true, lt_ticker - strlen(lvlttl), TTANIMENDTHRESHOLD);
|
||||
|
||||
// the act has a similar graphic animation, but we'll handle it here since it's only like 2 graphics lmfao.
|
||||
if (actnum && actnum < 10)
|
||||
{
|
||||
#ifdef TITLEPATCHES
|
||||
if (!splitscreen)
|
||||
|
||||
// compute delay before the act should appear.
|
||||
acttimer = lt_ticker - strlen(lvlttl);
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
acttimer -= strlen((strlen(zonttl)) ? (zonttl) : ("ZONE"));
|
||||
|
||||
actscale = 0;
|
||||
fakeangle = 0;
|
||||
|
||||
if (acttimer >= 0)
|
||||
{
|
||||
if (actnum > 9) // slightly offset the act diamond for two-digit act numbers
|
||||
V_DrawMappedPatch(ttlnumxpos + (V_LevelNameWidth(va("%d", actnum))/4) + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
|
||||
else
|
||||
V_DrawMappedPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
|
||||
}
|
||||
#endif
|
||||
V_DrawLevelTitle(ttlnumxpos + ttlscroll, 104, 0, va("%d", actnum));
|
||||
}
|
||||
|
||||
V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, 0, lvlttl);
|
||||
if (zonttl[0])
|
||||
V_DrawLevelTitle(zonexpos + ttlscroll, 104, 0, zonttl);
|
||||
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
V_DrawLevelTitle(zonexpos + ttlscroll, 104, 0, M_GetText("Zone"));
|
||||
V_DrawCenteredString(subttlxpos - ttlscroll, 135, 0|V_ALLOWLOWERCASE, subttl);
|
||||
if (acttimer < TTANIMENDTHRESHOLD) // spin in
|
||||
{
|
||||
fakeangle = min(360 + 90, acttimer*41) * ANG1;
|
||||
actscale = FINESINE(fakeangle>>ANGLETOFINESHIFT);
|
||||
}
|
||||
else // spin out
|
||||
{
|
||||
// Make letters disappear...
|
||||
acttimer -= TTANIMENDTHRESHOLD;
|
||||
|
||||
fakeangle = max(0, (360+90) - acttimer*41)*ANG1;
|
||||
actscale = FINESINE(fakeangle>>ANGLETOFINESHIFT);
|
||||
}
|
||||
|
||||
if (actscale)
|
||||
{
|
||||
// draw the top:
|
||||
V_DrawStretchyFixedPatch(286*FRACUNIT, 76*FRACUNIT, abs(actscale), FRACUNIT, V_SNAPTORIGHT|(actscale < 0 ? V_FLIP : 0), tcact, NULL);
|
||||
V_DrawStretchyFixedPatch(286*FRACUNIT, 123*FRACUNIT, abs(actscale), FRACUNIT, V_SNAPTORIGHT|(actscale < 0 ? V_FLIP : 0), tcactnum[actnum], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lt_lasttic = lt_ticker;
|
||||
|
||||
luahook:
|
||||
LUAh_TitleCardHUD(stplyr);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -829,6 +1053,7 @@ luahook:
|
|||
void ST_preLevelTitleCardDrawer(void)
|
||||
{
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
|
||||
ST_drawWipeTitleCard();
|
||||
I_OsPolling();
|
||||
I_UpdateNoBlit();
|
||||
|
|
@ -840,14 +1065,7 @@ void ST_preLevelTitleCardDrawer(void)
|
|||
//
|
||||
void ST_drawWipeTitleCard(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
stplyr = &players[displayplayers[i]];
|
||||
ST_preDrawTitleCard();
|
||||
ST_drawTitleCard();
|
||||
}
|
||||
ST_drawTitleCard();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
143
src/v_video.c
143
src/v_video.c
|
|
@ -1676,6 +1676,149 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UI
|
|||
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/2, flags, fontv[HU_FONT].font[c], colormap);
|
||||
}
|
||||
|
||||
// V_TitleCardStringWidth
|
||||
// Get the string's width using the titlecard font.
|
||||
INT32 V_TitleCardStringWidth(const char *str)
|
||||
{
|
||||
INT32 xoffs = 0;
|
||||
const char *ch = str;
|
||||
char c;
|
||||
patch_t *pp;
|
||||
|
||||
for (;;ch++)
|
||||
{
|
||||
if (!*ch)
|
||||
break;
|
||||
|
||||
if (*ch == '\n')
|
||||
{
|
||||
xoffs = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *ch;
|
||||
c = toupper(c);
|
||||
c -= LT_FONTSTART;
|
||||
|
||||
// check if character exists, if not, it's a space.
|
||||
if (c < 0 || c >= LT_FONTSIZE || !tc_font[0][(INT32)c])
|
||||
{
|
||||
xoffs += 10;
|
||||
continue;
|
||||
}
|
||||
|
||||
pp = tc_font[1][(INT32)c];
|
||||
|
||||
xoffs += pp->width-5;
|
||||
}
|
||||
|
||||
return xoffs;
|
||||
}
|
||||
|
||||
// V_DrawTitleCardScreen.
|
||||
// see v_video.h's prototype for more information.
|
||||
//
|
||||
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean alignright, INT32 timer, INT32 threshold)
|
||||
{
|
||||
|
||||
INT32 xoffs = 0;
|
||||
INT32 yoffs = 0;
|
||||
INT32 i = 0;
|
||||
|
||||
// per-letter variables
|
||||
fixed_t scalex;
|
||||
fixed_t offs;
|
||||
INT32 let_time;
|
||||
INT32 flipflag;
|
||||
angle_t fakeang;
|
||||
|
||||
const char *ch = str;
|
||||
char c;
|
||||
patch_t *pp;
|
||||
patch_t *ol;
|
||||
|
||||
x -= 2; // Account for patch width...
|
||||
|
||||
if (alignright)
|
||||
x -= V_TitleCardStringWidth(str);
|
||||
|
||||
|
||||
for (;;ch++, i++)
|
||||
{
|
||||
|
||||
scalex = FRACUNIT;
|
||||
offs = 0;
|
||||
let_time = timer - i;
|
||||
flipflag = 0;
|
||||
|
||||
if (!*ch)
|
||||
break;
|
||||
|
||||
if (*ch == '\n')
|
||||
{
|
||||
xoffs = x;
|
||||
yoffs += 32;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *ch;
|
||||
|
||||
c = toupper(c);
|
||||
c -= LT_FONTSTART;
|
||||
|
||||
// check if character exists, if not, it's a space.
|
||||
if (c < 0 || c >= LT_FONTSIZE || !tc_font[1][(INT32)c])
|
||||
{
|
||||
xoffs += 10;
|
||||
continue;
|
||||
}
|
||||
|
||||
ol = tc_font[0][(INT32)c];
|
||||
pp = tc_font[1][(INT32)c];
|
||||
|
||||
if (timer)
|
||||
{
|
||||
|
||||
// make letters appear
|
||||
if (!threshold || let_time < threshold)
|
||||
{
|
||||
if (let_time <= 0)
|
||||
return; // No reason to continue drawing, none of the next letters will be drawn either.
|
||||
|
||||
// otherwise; scalex must start at 0
|
||||
// let's have each letter do 4 spins (360*4 + 90 = 1530 "degrees")
|
||||
fakeang = min(360 + 90, let_time*41) * ANG1;
|
||||
scalex = FINESINE(fakeang>>ANGLETOFINESHIFT);
|
||||
}
|
||||
else if (let_time > threshold)
|
||||
{
|
||||
// Make letters disappear...
|
||||
let_time -= threshold;
|
||||
|
||||
fakeang = max(0, (360+90) - let_time*41)*ANG1;
|
||||
scalex = FINESINE(fakeang>>ANGLETOFINESHIFT);
|
||||
}
|
||||
|
||||
// Because of how our patches are offset, we need to counter the displacement caused by changing the scale with an offset of our own.
|
||||
offs = ((FRACUNIT-scalex)*pp->width)/2;
|
||||
}
|
||||
|
||||
// And now, we just need to draw the stuff.
|
||||
flipflag = (scalex < 0) ? V_FLIP : 0;
|
||||
|
||||
if (scalex && ol && pp)
|
||||
{
|
||||
//CONS_Printf("%d\n", (INT32)c);
|
||||
V_DrawStretchyFixedPatch((x + xoffs)*FRACUNIT + offs, (y+yoffs)*FRACUNIT, abs(scalex), FRACUNIT, flags|flipflag, ol, NULL);
|
||||
V_DrawStretchyFixedPatch((x + xoffs)*FRACUNIT + offs, (y+yoffs)*FRACUNIT, abs(scalex), FRACUNIT, flags|flipflag, pp, NULL);
|
||||
}
|
||||
|
||||
xoffs += pp->width -5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Precompile a wordwrapped string to any given width.
|
||||
// This is a muuuch better method than V_WORDWRAP.
|
||||
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
||||
|
|
|
|||
|
|
@ -262,6 +262,16 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st
|
|||
#define V_DrawThinStringAtFixed( x,y,option,string ) \
|
||||
V__DrawOneScaleString (x,y,FRACUNIT,option,TINY_FONT,string)
|
||||
|
||||
// Draws a titlecard font string.
|
||||
// timer: when the letters start appearing (leave to 0 to disable)
|
||||
// threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...)
|
||||
// NOTE: This function ignores most conventional string flags (V_RETURN8, V_ALLOWLOWERCASE ...)
|
||||
// NOTE: This font only works with uppercase letters.
|
||||
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean alignright, INT32 timer, INT32 threshold);
|
||||
|
||||
// returns thr width of a string drawn using the above function.
|
||||
INT32 V_TitleCardStringWidth(const char *str);
|
||||
|
||||
// Draw tall nums, used for menu, HUD, intermission
|
||||
void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num);
|
||||
void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue