Merge branch 'master' of git.magicalgirl.moe:KartKrew/Kart into v2-master

This commit is contained in:
Latapostrophe 2020-05-03 22:37:07 +02:00
commit 78a328328a
48 changed files with 1692 additions and 526 deletions

View file

@ -18,6 +18,7 @@ set(SRB2_CORE_SOURCES
filesrch.c
g_game.c
g_input.c
g_splitscreen.c
hu_stuff.c
i_tcp.c
info.c
@ -156,7 +157,13 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c
p_tick.c
p_user.c
k_battle.c
k_bheap.c
k_collide.c
k_kart.c
k_pathfind.c
k_pwrlv.c
k_waypoint.c
p_local.h
p_maputl.h
@ -168,7 +175,13 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h
p_spec.h
p_tick.h
k_battle.h
k_bheap.h
k_collide.h
k_kart.h
k_pathfind.h
k_pwrlv.h
k_waypoint.h
)
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))

View file

@ -1543,7 +1543,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
}
// Only add to netcmd buffer if in a netgame, otherwise, just change it.
if (netgame || multiplayer)
if (netgame)
{
WRITEUINT16(p, var->netid);
WRITESTRING(p, value);

View file

@ -1474,32 +1474,32 @@ static void CON_DrawInput(void)
if (input_sel < c)
V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 77 | V_NOSCALESTART);
for (i = 0; i < 3; ++i, x += charwidth)
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, true);
}
else
V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, true);
for (cend = c + clen; c < cend; ++c, x += charwidth)
{
if ((input_sel > c && input_cur <= c) || (input_sel <= c && input_cur > c))
{
V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 77 | V_NOSCALESTART);
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, true);
}
else
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, true);
if (c == input_cur && con_tick >= 4)
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, true);
}
if (cend == input_cur && con_tick >= 4)
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, true);
if (rellip)
{
if (input_sel > cend)
V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 77 | V_NOSCALESTART);
for (i = 0; i < 3; ++i, x += charwidth)
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, true);
}
}
@ -1545,11 +1545,11 @@ static void CON_DrawHudlines(void)
else
{
//charwidth = SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
}
//V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
//V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, true);
y += charheight;
}
@ -1620,7 +1620,7 @@ static void CON_DrawConsole(void)
charflags = (*p & 0x7f) << V_CHARCOLORSHIFT;
p++;
}
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
}

View file

@ -1880,7 +1880,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
{
char version[8] = "";
#if VERSION > 0 || SUBVERSION > 0
snprintf(version, sizeof (version), "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
snprintf(version, sizeof (version), "%d.%d", VERSION, SUBVERSION);
#else
strcpy(version, GetRevisionString());
#endif
@ -2355,8 +2355,8 @@ static void CL_ConnectToServer(boolean viams)
gametypestr = Gametype_Names[num];
if (gametypestr)
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100,
serverlist[i].info.version%100, serverlist[i].info.subversion);
CONS_Printf(M_GetText("Version: %d.%d\n"),
serverlist[i].info.version, serverlist[i].info.subversion);
}
SL_ClearServerList(servernode);
#endif
@ -3296,8 +3296,8 @@ static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
// called one time at init
void D_ClientServerInit(void)
{
DEBFILE(va("- - -== SRB2Kart v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n",
VERSION/100, VERSION%100, SUBVERSION));
DEBFILE(va("- - -== SRB2Kart v%d.%d "VERSIONSTRING" debugfile ==- - -\n",
VERSION, SUBVERSION));
#ifndef NONET
COM_AddCommand("getplayernum", Command_GetPlayerNum);
@ -3822,7 +3822,7 @@ static void HandleConnect(SINT8 node)
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
else if (netbuffer->u.clientcfg.version != VERSION
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d)"), VERSION, SUBVERSION));
else if (!cv_allownewplayer.value && node)
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
else if (D_NumPlayers() >= maxplayers)

View file

@ -1083,7 +1083,10 @@ void D_SRB2Main(void)
// use user specific config file
#ifdef DEFAULTDIR
snprintf(srb2home, sizeof srb2home, "%s" PATHSEP DEFAULTDIR, userhome);
snprintf(downloaddir, sizeof downloaddir, "%s" PATHSEP "DOWNLOAD", srb2home);
#else
snprintf(srb2home, sizeof srb2home, "%s", userhome);
#endif
if (dedicated)
snprintf(configfile, sizeof configfile, "%s" PATHSEP "d"CONFIGFILENAME, srb2home);
else
@ -1091,18 +1094,6 @@ void D_SRB2Main(void)
// can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP);
#else
snprintf(srb2home, sizeof srb2home, "%s", userhome);
snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
if (dedicated)
snprintf(configfile, sizeof configfile, "%s" PATHSEP "d"CONFIGFILENAME, userhome);
else
snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, userhome);
// can't use sprintf since there is %u in savegamename
strcatbf(savegamename, userhome, PATHSEP);
#endif
}
configfile[sizeof configfile - 1] = '\0';
@ -1116,6 +1107,10 @@ void D_SRB2Main(void)
snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons");
I_mkdir(addonsdir, 0755);
/* and downloads in a subdirectory */
snprintf(downloaddir, sizeof downloaddir, "%s%s%s",
addonsdir, PATHSEP, "downloads");
// rand() needs seeded regardless of password
srand((unsigned int)time(NULL));

View file

@ -811,6 +811,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_screenshot_option);
CV_RegisterVar(&cv_screenshot_folder);
CV_RegisterVar(&cv_screenshot_colorprofile);
CV_RegisterVar(&cv_moviemode);
CV_RegisterVar(&cv_movie_option);
CV_RegisterVar(&cv_movie_folder);
@ -828,6 +829,7 @@ void D_RegisterClientCommands(void)
// GIF variables
CV_RegisterVar(&cv_gif_optimize);
CV_RegisterVar(&cv_gif_downscale);
CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS
CV_RegisterVar(&cv_splats);
@ -880,7 +882,29 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_netdemosyncquality);
// FIXME: not to be here.. but needs be done for config loading
CV_RegisterVar(&cv_usegamma);
CV_RegisterVar(&cv_globalgamma);
CV_RegisterVar(&cv_globalsaturation);
CV_RegisterVar(&cv_rhue);
CV_RegisterVar(&cv_yhue);
CV_RegisterVar(&cv_ghue);
CV_RegisterVar(&cv_chue);
CV_RegisterVar(&cv_bhue);
CV_RegisterVar(&cv_mhue);
CV_RegisterVar(&cv_rgamma);
CV_RegisterVar(&cv_ygamma);
CV_RegisterVar(&cv_ggamma);
CV_RegisterVar(&cv_cgamma);
CV_RegisterVar(&cv_bgamma);
CV_RegisterVar(&cv_mgamma);
CV_RegisterVar(&cv_rsaturation);
CV_RegisterVar(&cv_ysaturation);
CV_RegisterVar(&cv_gsaturation);
CV_RegisterVar(&cv_csaturation);
CV_RegisterVar(&cv_bsaturation);
CV_RegisterVar(&cv_msaturation);
// m_menu.c
//CV_RegisterVar(&cv_compactscoreboard);

View file

@ -6305,18 +6305,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_RANDOMITEM10",
"S_RANDOMITEM11",
"S_RANDOMITEM12",
"S_RANDOMITEM13",
"S_RANDOMITEM14",
"S_RANDOMITEM15",
"S_RANDOMITEM16",
"S_RANDOMITEM17",
"S_RANDOMITEM18",
"S_RANDOMITEM19",
"S_RANDOMITEM20",
"S_RANDOMITEM21",
"S_RANDOMITEM22",
"S_RANDOMITEM23",
"S_RANDOMITEM24",
"S_DEADRANDOMITEM",
// Random Item Pop
@ -6456,18 +6444,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMANITEM10",
"S_EGGMANITEM11",
"S_EGGMANITEM12",
"S_EGGMANITEM13",
"S_EGGMANITEM14",
"S_EGGMANITEM15",
"S_EGGMANITEM16",
"S_EGGMANITEM17",
"S_EGGMANITEM18",
"S_EGGMANITEM19",
"S_EGGMANITEM20",
"S_EGGMANITEM21",
"S_EGGMANITEM22",
"S_EGGMANITEM23",
"S_EGGMANITEM24",
"S_EGGMANITEM_DEAD",
//}
@ -6931,8 +6907,32 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAYERBOMB18",
"S_PLAYERBOMB19",
"S_PLAYERBOMB20",
"S_PLAYERITEM", // Player item overlay
"S_PLAYERFAKE", // Player fake overlay
"S_PLAYERITEM1", // Player item overlay
"S_PLAYERITEM2",
"S_PLAYERITEM3",
"S_PLAYERITEM4",
"S_PLAYERITEM5",
"S_PLAYERITEM6",
"S_PLAYERITEM7",
"S_PLAYERITEM8",
"S_PLAYERITEM9",
"S_PLAYERITEM10",
"S_PLAYERITEM11",
"S_PLAYERITEM12",
"S_PLAYERFAKE1", // Player fake overlay
"S_PLAYERFAKE2",
"S_PLAYERFAKE3",
"S_PLAYERFAKE4",
"S_PLAYERFAKE5",
"S_PLAYERFAKE6",
"S_PLAYERFAKE7",
"S_PLAYERFAKE8",
"S_PLAYERFAKE9",
"S_PLAYERFAKE10",
"S_PLAYERFAKE11",
"S_PLAYERFAKE12",
"S_KARMAWHEEL", // Karma player wheels
@ -7898,6 +7898,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_DEZLASER",
"MT_WAYPOINT",
"MT_WAYPOINT_RISER",
"MT_WAYPOINT_ANCHOR",
"MT_RANDOMAUDIENCE",
@ -8104,6 +8106,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_KARMAFIREWORK",
"MT_RINGSPARKS",
"MT_DRAFTDUST",
"MT_SPBDUST",
"MT_TIREGREASE",
"MT_OVERTIMEFOG",

View file

@ -150,7 +150,7 @@ extern char logfilename[1024];
// most interface strings are ignored in development mode.
// we use comprevision and compbranch instead.
#else
#define VERSION 200 // Game version
#define VERSION 2 // Game version
#define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v2.0"
#define VERSIONSTRINGW L"v2.0"

View file

@ -157,7 +157,7 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
while (lsize--)
{
// Determine pixel to use from fademask
pcolor = &pLocalPalette[*lump++];
pcolor = &pMasterPalette[*lump++];
*mask++ = FixedDiv((pcolor->s.red+1)<<FRACBITS, paldiv)>>FRACBITS;
}

View file

@ -1196,21 +1196,24 @@ UINT8 *HWR_GetScreenshot(void)
return buf;
}
boolean HWR_Screenshot(const char *lbmname)
boolean HWR_Screenshot(const char *pathname)
{
boolean ret;
UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf));
if (!buf)
{
CONS_Debug(DBG_RENDER, "HWR_Screenshot: Failed to allocate memory\n");
return false;
}
// returns 24bit 888 RGB
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
#ifdef USE_PNG
ret = M_SavePNG(lbmname, buf, vid.width, vid.height, NULL);
ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL);
#else
ret = saveTGA(lbmname, buf, vid.width, vid.height);
ret = saveTGA(pathname, buf, vid.width, vid.height);
#endif
free(buf);
return ret;

View file

@ -582,7 +582,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
if (nrPlaneVerts < 3) //not even a triangle ?
return;
if ((UINT32)nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size
if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size
{
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX);
return;
@ -3229,7 +3229,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
if (nrPlaneVerts < 3) //not even a triangle ?
return;
if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size
if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size
{
CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX);
return;

View file

@ -38,8 +38,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player);
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player);
void HWR_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
UINT8 *HWR_GetScreenshot(void);
boolean HWR_Screenshot(const char *lbmname);
void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void);
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option);
@ -54,6 +52,9 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color);
void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum);
UINT8 *HWR_GetScreenshot(void);
boolean HWR_Screenshot(const char *pathname);
void HWR_AddCommands(void);
void HWR_CorrectSWTricks(void);
void transform(float *cx, float *cy, float *cz);

View file

@ -1586,7 +1586,7 @@ static void HU_drawMiniChat(void)
if (cv_chatbacktint.value) // on request of wolfy
V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 159|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap);
}
dx += charwidth;
@ -1680,7 +1680,7 @@ static void HU_drawChatLog(INT32 offset)
else
{
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap);
else
j++; // don't forget to increment this or we'll get stuck in the limbo.
}
@ -1781,7 +1781,7 @@ static void HU_DrawChat(void)
++i;
else
{
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, !cv_allcaps.value, V_GetStringColormap(talk[i]|cflag));
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, true, V_GetStringColormap(talk[i]|cflag));
i++;
}
@ -1799,7 +1799,7 @@ static void HU_DrawChat(void)
typelines = 1;
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL);
while (w_chat[i])
{
@ -1809,7 +1809,7 @@ static void HU_DrawChat(void)
INT32 cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
INT32 cursory = (cursorx != chatx+1) ? (y) : (y+charheight);
if (hu_tick < 4)
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL);
if (cursorx == chatx+1 && saylen == i) // a weirdo hack
{
@ -1822,7 +1822,7 @@ static void HU_DrawChat(void)
if (w_chat[i] < HU_FONTSTART)
++i;
else
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, true, NULL);
c += charwidth;
if (c > boxw-(charwidth*2) && !skippedline)
@ -1948,13 +1948,13 @@ static void HU_DrawChat_Old(void)
else
{
//charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true);
}
c += charwidth;
}
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value);
V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true);
i = 0;
while (w_chat[i])
@ -1964,7 +1964,7 @@ static void HU_DrawChat_Old(void)
{
INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down.
INT32 cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight);
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value);
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true);
}
//Hurdler: isn't it better like that?
@ -1976,7 +1976,7 @@ static void HU_DrawChat_Old(void)
else
{
//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true);
}
c += charwidth;

View file

@ -2534,38 +2534,25 @@ state_t states[NUMSTATES] =
{SPR_SRBO, 0, 2, {A_BuzzFly}, 0, 0, S_SRB1_GENREX2}, // S_SRB1_GENREX2
// SRB2kart
{SPR_RNDM, 0|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM2}, // S_RANDOMITEM1
{SPR_RNDM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM3}, // S_RANDOMITEM2
{SPR_RNDM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM4}, // S_RANDOMITEM3
{SPR_RNDM, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM5}, // S_RANDOMITEM4
{SPR_RNDM, 4|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM6}, // S_RANDOMITEM5
{SPR_RNDM, 5|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM7}, // S_RANDOMITEM6
{SPR_RNDM, 6|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM8}, // S_RANDOMITEM7
{SPR_RNDM, 7|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM9}, // S_RANDOMITEM8
{SPR_RNDM, 8|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM10}, // S_RANDOMITEM9
{SPR_RNDM, 9|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM11}, // S_RANDOMITEM10
{SPR_RNDM, 10|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM12}, // S_RANDOMITEM11
{SPR_RNDM, 11|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM13}, // S_RANDOMITEM12
{SPR_RNDM, 12|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM14}, // S_RANDOMITEM13
{SPR_RNDM, 13|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM15}, // S_RANDOMITEM14
{SPR_RNDM, 14|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM16}, // S_RANDOMITEM15
{SPR_RNDM, 15|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM17}, // S_RANDOMITEM16
{SPR_RNDM, 16|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM18}, // S_RANDOMITEM17
{SPR_RNDM, 17|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM19}, // S_RANDOMITEM18
{SPR_RNDM, 18|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM20}, // S_RANDOMITEM19
{SPR_RNDM, 19|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM21}, // S_RANDOMITEM20
{SPR_RNDM, 20|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM22}, // S_RANDOMITEM21
{SPR_RNDM, 21|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM23}, // S_RANDOMITEM22
{SPR_RNDM, 22|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM24}, // S_RANDOMITEM23
{SPR_RNDM, 23|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_RANDOMITEM1}, // S_RANDOMITEM24
{SPR_RNDM, 0|FF_FULLBRIGHT, 1, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM
{SPR_RNDM, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM2}, // S_RANDOMITEM1
{SPR_RNDM, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM3}, // S_RANDOMITEM2
{SPR_RNDM, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM4}, // S_RANDOMITEM3
{SPR_RNDM, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM5}, // S_RANDOMITEM4
{SPR_RNDM, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM6}, // S_RANDOMITEM5
{SPR_RNDM, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM7}, // S_RANDOMITEM6
{SPR_RNDM, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM8}, // S_RANDOMITEM7
{SPR_RNDM, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM9}, // S_RANDOMITEM8
{SPR_RNDM, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM10}, // S_RANDOMITEM9
{SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM11}, // S_RANDOMITEM10
{SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM12}, // S_RANDOMITEM11
{SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12
{SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM
{SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1
{SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2
{SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3
{SPR_RPOP, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL}, // S_RANDOMITEMPOP4
{SPR_NULL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMICON
{SPR_SGNS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1
@ -2672,31 +2659,19 @@ state_t states[NUMSTATES] =
{SPR_RSHE, 2, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_LVIBRATE
{SPR_RSHE, 3, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_RVIBRATE
{SPR_FITM, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM2}, // S_EGGMANITEM1
{SPR_FITM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM3}, // S_EGGMANITEM2
{SPR_FITM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM4}, // S_EGGMANITEM3
{SPR_FITM, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM5}, // S_EGGMANITEM4
{SPR_FITM, 4|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM6}, // S_EGGMANITEM5
{SPR_FITM, 5|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM7}, // S_EGGMANITEM6
{SPR_FITM, 6|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM8}, // S_EGGMANITEM7
{SPR_FITM, 7|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM9}, // S_EGGMANITEM8
{SPR_FITM, 8|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM10}, // S_EGGMANITEM9
{SPR_FITM, 9|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM11}, // S_EGGMANITEM10
{SPR_FITM, 10|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM12}, // S_EGGMANITEM11
{SPR_FITM, 11|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM13}, // S_EGGMANITEM12
{SPR_FITM, 12|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM14}, // S_EGGMANITEM13
{SPR_FITM, 13|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM15}, // S_EGGMANITEM14
{SPR_FITM, 14|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM16}, // S_EGGMANITEM15
{SPR_FITM, 15|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM17}, // S_EGGMANITEM16
{SPR_FITM, 16|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM18}, // S_EGGMANITEM17
{SPR_FITM, 17|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM19}, // S_EGGMANITEM18
{SPR_FITM, 18|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM20}, // S_EGGMANITEM19
{SPR_FITM, 19|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM21}, // S_EGGMANITEM20
{SPR_FITM, 20|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM22}, // S_EGGMANITEM21
{SPR_FITM, 21|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM23}, // S_EGGMANITEM22 // *****
{SPR_FITM, 22|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM24}, // S_EGGMANITEM23 // *****
{SPR_FITM, 23|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_EGGMANITEM1}, // S_EGGMANITEM24 // *****
{SPR_FITM, FF_FULLBRIGHT, 175, {NULL}, 0, 0, S_EGGMANITEM1}, // S_EGGMANITEM_DEAD
{SPR_FITM, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM2}, // S_EGGMANITEM1
{SPR_FITM, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM3}, // S_EGGMANITEM2
{SPR_FITM, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM4}, // S_EGGMANITEM3
{SPR_FITM, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM5}, // S_EGGMANITEM4
{SPR_FITM, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM6}, // S_EGGMANITEM5
{SPR_FITM, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM7}, // S_EGGMANITEM6
{SPR_FITM, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM8}, // S_EGGMANITEM7
{SPR_FITM, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM9}, // S_EGGMANITEM8
{SPR_FITM, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM10}, // S_EGGMANITEM9
{SPR_FITM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM11}, // S_EGGMANITEM10
{SPR_FITM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM12}, // S_EGGMANITEM11
{SPR_FITM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_EGGMANITEM1}, // S_EGGMANITEM12
{SPR_FITM, 24|FF_FULLBRIGHT, 175, {NULL}, 0, 0, S_NULL}, // S_EGGMANITEM_DEAD
{SPR_BANA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BANANA
{SPR_BANA, 0, 175, {NULL}, 0, 0, S_NULL}, // S_BANANA_DEAD
@ -3143,8 +3118,32 @@ state_t states[NUMSTATES] =
{SPR_SPBM, 8, 1, {NULL}, 0, 0, S_PLAYERBOMB19}, // S_PLAYERBOMB18
{SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB20}, // S_PLAYERBOMB19
{SPR_SPBM, 8, 1, {NULL}, 0, 0, S_PLAYERBOMB1}, // S_PLAYERBOMB20
{SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM
{SPR_FITM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERFAKE
{SPR_RNDM, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM2}, // S_PLAYERITEM1
{SPR_RNDM, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM3}, // S_PLAYERITEM2
{SPR_RNDM, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM4}, // S_PLAYERITEM3
{SPR_RNDM, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM5}, // S_PLAYERITEM4
{SPR_RNDM, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM6}, // S_PLAYERITEM5
{SPR_RNDM, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM7}, // S_PLAYERITEM6
{SPR_RNDM, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM8}, // S_PLAYERITEM7
{SPR_RNDM, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM9}, // S_PLAYERITEM8
{SPR_RNDM, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM10}, // S_PLAYERITEM9
{SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM11}, // S_PLAYERITEM10
{SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM12}, // S_PLAYERITEM11
{SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERITEM1}, // S_PLAYERITEM12
{SPR_FITM, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE2}, // S_PLAYERFAKE1
{SPR_FITM, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE3}, // S_PLAYERFAKE2
{SPR_FITM, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE4}, // S_PLAYERFAKE3
{SPR_FITM, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE5}, // S_PLAYERFAKE4
{SPR_FITM, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE6}, // S_PLAYERFAKE5
{SPR_FITM, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE7}, // S_PLAYERFAKE6
{SPR_FITM, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE8}, // S_PLAYERFAKE7
{SPR_FITM, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE9}, // S_PLAYERFAKE8
{SPR_FITM, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE10}, // S_PLAYERFAKE9
{SPR_FITM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE11}, // S_PLAYERFAKE10
{SPR_FITM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE12}, // S_PLAYERFAKE11
{SPR_FITM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_PLAYERFAKE1}, // S_PLAYERFAKE12
{SPR_PBOM, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL
@ -15640,7 +15639,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_EGGMANITEM
-1, // doomednum
S_EGGMANITEM1, // spawnstate
S_EGGMANITEM1, // spawnstate
2, // spawnhealth
S_NULL, // seestate
sfx_tossed, // seesound
@ -16529,6 +16528,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_WAYPOINT_RISER
2002, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
100, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
1*FRACUNIT, // radius
2*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_WAYPOINT_ANCHOR
2003, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
100, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
1*FRACUNIT, // radius
2*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_RANDOMAUDIENCE
1488, // doomednum
S_RANDOMAUDIENCE, // spawnstate
@ -17775,11 +17828,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
-1, // doomednum
S_PLAYERBOMB1, // spawnstate
1000, // spawnhealth
S_PLAYERITEM, // seestate
S_PLAYERITEM1, // seestate
sfx_kc2e, // seesound
8, // reactiontime
sfx_s3k4e, // attacksound
S_PLAYERFAKE, // painstate
S_PLAYERFAKE1, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
@ -20554,6 +20607,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SPBDUST
-1, // doomednum
S_DRAFTDUST1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16<<FRACBITS, // radius
32<<FRACBITS, // height
1, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_DONTENCOREMAP|MF_NOGRAVITY|MF_PAIN, // flags
S_NULL // raisestate
},
{ // MT_TIREGREASE
-1, // doomednum
S_TIREGREASE, // spawnstate

View file

@ -3204,18 +3204,6 @@ typedef enum state
S_RANDOMITEM10,
S_RANDOMITEM11,
S_RANDOMITEM12,
S_RANDOMITEM13,
S_RANDOMITEM14,
S_RANDOMITEM15,
S_RANDOMITEM16,
S_RANDOMITEM17,
S_RANDOMITEM18,
S_RANDOMITEM19,
S_RANDOMITEM20,
S_RANDOMITEM21,
S_RANDOMITEM22,
S_RANDOMITEM23,
S_RANDOMITEM24,
S_DEADRANDOMITEM,
// Random Item Pop
@ -3355,18 +3343,6 @@ typedef enum state
S_EGGMANITEM10,
S_EGGMANITEM11,
S_EGGMANITEM12,
S_EGGMANITEM13,
S_EGGMANITEM14,
S_EGGMANITEM15,
S_EGGMANITEM16,
S_EGGMANITEM17,
S_EGGMANITEM18,
S_EGGMANITEM19,
S_EGGMANITEM20,
S_EGGMANITEM21,
S_EGGMANITEM22,
S_EGGMANITEM23,
S_EGGMANITEM24,
S_EGGMANITEM_DEAD,
//}
@ -3830,8 +3806,32 @@ typedef enum state
S_PLAYERBOMB18,
S_PLAYERBOMB19,
S_PLAYERBOMB20,
S_PLAYERITEM,
S_PLAYERFAKE,
S_PLAYERITEM1,
S_PLAYERITEM2,
S_PLAYERITEM3,
S_PLAYERITEM4,
S_PLAYERITEM5,
S_PLAYERITEM6,
S_PLAYERITEM7,
S_PLAYERITEM8,
S_PLAYERITEM9,
S_PLAYERITEM10,
S_PLAYERITEM11,
S_PLAYERITEM12,
S_PLAYERFAKE1,
S_PLAYERFAKE2,
S_PLAYERFAKE3,
S_PLAYERFAKE4,
S_PLAYERFAKE5,
S_PLAYERFAKE6,
S_PLAYERFAKE7,
S_PLAYERFAKE8,
S_PLAYERFAKE9,
S_PLAYERFAKE10,
S_PLAYERFAKE11,
S_PLAYERFAKE12,
S_KARMAWHEEL,
@ -4829,6 +4829,8 @@ typedef enum mobj_type
MT_DEZLASER,
MT_WAYPOINT,
MT_WAYPOINT_RISER,
MT_WAYPOINT_ANCHOR,
MT_RANDOMAUDIENCE,
@ -5035,6 +5037,7 @@ typedef enum mobj_type
MT_KARMAFIREWORK,
MT_RINGSPARKS,
MT_DRAFTDUST,
MT_SPBDUST,
MT_TIREGREASE,
MT_OVERTIMEFOG,

View file

@ -542,6 +542,44 @@ UINT8 K_GetKartColorByName(const char *name)
//}
player_t *K_GetItemBoxPlayer(mobj_t *mobj)
{
fixed_t closest = INT32_MAX;
player_t *player = NULL;
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!(playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo) && !players[i].spectator))
{
continue;
}
// Always use normal item box rules -- could pass in "2" for fakes but they blend in better like this
if (P_CanPickupItem(&players[i], 1))
{
fixed_t dist = P_AproxDistance(P_AproxDistance(
players[i].mo->x - mobj->x,
players[i].mo->y - mobj->y),
players[i].mo->z - mobj->z
);
if (dist > 8192*mobj->scale)
{
continue;
}
if (dist < closest)
{
player = &players[i];
closest = dist;
}
}
}
return player;
}
//{ SRB2kart Net Variables
void K_RegisterKartStuff(void)
@ -758,6 +796,7 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
{
if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items
indirectitemcooldown = 20*TICRATE;
if (getitem == KITEM_HYUDORO) // Hyudoro cooldown
hyubgone = 5*TICRATE;
@ -1129,7 +1168,17 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
&& players[i].kartstuff[k_position] == 1)
{
// This player is first! Yay!
pdis = player->distancetofinish - players[i].distancetofinish;
if (player->distancetofinish <= players[i].distancetofinish)
{
// Guess you're in first / tied for first?
pdis = 0;
}
else
{
// Subtract 1st's distance from your distance, to get your distance from 1st!
pdis = player->distancetofinish - players[i].distancetofinish;
}
break;
}
}
@ -1243,7 +1292,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
player->kartstuff[k_itemroulette] = 0;
player->kartstuff[k_roulettetype] = 0;
if (P_IsDisplayPlayer(player))
S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf));
S_StartSound(NULL, sfx_itrolm);
return;
}
}
@ -1396,7 +1445,7 @@ static void K_DebtStingPlayer(player_t *player, INT32 length)
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
K_DropHnextList(player);
K_DropHnextList(player, false);
return;
}
@ -2585,20 +2634,29 @@ static void K_GetKartBoostPower(player_t *player)
player->kartstuff[k_numboosts] = numboosts;
}
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
// Returns kart speed from a stat. Boost power and scale are NOT taken into account, no player or object is necessary.
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed)
{
const fixed_t xspd = (3*FRACUNIT)/64;
fixed_t g_cc = K_GetKartGameSpeedScalar(gamespeed) + xspd;
fixed_t k_speed = 150;
UINT8 kartspeed = player->kartspeed;
fixed_t finalspeed;
if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0)
kartspeed = 1;
k_speed += kartspeed*3; // 153 - 177
finalspeed = FixedMul(k_speed<<14, g_cc);
return finalspeed;
}
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
{
fixed_t finalspeed;
UINT8 kartspeed = player->kartspeed;
if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0)
kartspeed = 1;
finalspeed = K_GetKartSpeedFromStat(kartspeed);
if (player->mo && !P_MobjWasRemoved(player->mo))
finalspeed = FixedMul(finalspeed, player->mo->scale);
@ -2828,7 +2886,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
if (cv_kartdebughuddrop.value && !modeattacking)
K_DropItems(player);
else
K_DropHnextList(player);
K_DropHnextList(player, false);
return;
}
@ -2973,7 +3031,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor)
if (cv_kartdebughuddrop.value && !modeattacking)
K_DropItems(player);
else
K_DropHnextList(player);
K_DropHnextList(player, false);
return;
}
@ -3179,7 +3237,7 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force)
if (cv_kartdebughuddrop.value && !modeattacking)
K_DropItems(victim);
else
K_DropHnextList(victim);
K_DropHnextList(victim, false);
return;
}
@ -4642,54 +4700,58 @@ void K_UpdateHnextList(player_t *player, boolean clean)
nextwork = work->hnext;
while ((work = nextwork) && !P_MobjWasRemoved(work))
while ((work = nextwork) && !(work == NULL || P_MobjWasRemoved(work)))
{
nextwork = work->hnext;
if (!clean && (!work->movedir || work->movedir <= (UINT16)player->kartstuff[k_itemamount]))
{
continue;
}
P_RemoveMobj(work);
}
if (player->mo->hnext == NULL || P_MobjWasRemoved(player->mo->hnext))
{
// Like below, try to clean up the pointer if it's NULL.
// Maybe this was a cause of the shrink/eggbox fails?
P_SetTarget(&player->mo->hnext, NULL);
}
}
// For getting hit!
void K_DropHnextList(player_t *player)
void K_DropHnextList(player_t *player, boolean keepshields)
{
mobj_t *work = player->mo, *nextwork, *dropwork;
INT32 flip;
mobjtype_t type;
boolean orbit, ponground, dropall = true;
INT32 shield = K_GetShieldFromItem(player->kartstuff[k_itemtype]);
if (!work || P_MobjWasRemoved(work))
if (work == NULL || P_MobjWasRemoved(work))
{
return;
}
flip = P_MobjFlip(player->mo);
ponground = P_IsObjectOnGround(player->mo);
if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD)
if (shield != KSHIELD_NONE && !keepshields)
{
K_DoThunderShield(player);
player->kartstuff[k_itemtype] = KITEM_NONE;
player->kartstuff[k_itemamount] = 0;
if (shield == KSHIELD_THUNDER)
{
K_DoThunderShield(player);
}
player->kartstuff[k_curshield] = KSHIELD_NONE;
}
else if (player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD)
{
player->kartstuff[k_itemtype] = KITEM_NONE;
player->kartstuff[k_itemamount] = 0;
player->kartstuff[k_curshield] = KSHIELD_NONE;
}
else if (player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)
{
player->kartstuff[k_itemtype] = KITEM_NONE;
player->kartstuff[k_itemamount] = 0;
player->kartstuff[k_curshield] = KSHIELD_NONE;
player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0;
}
nextwork = work->hnext;
while ((work = nextwork) && !P_MobjWasRemoved(work))
while ((work = nextwork) && !(work == NULL || P_MobjWasRemoved(work)))
{
nextwork = work->hnext;
@ -4718,20 +4780,20 @@ void K_DropHnextList(player_t *player)
orbit = false;
type = MT_EGGMANITEM;
break;
// intentionally do nothing
case MT_SINK_SHIELD:
case MT_ROCKETSNEAKER:
return;
default:
continue;
}
dropwork = P_SpawnMobj(work->x, work->y, work->z, type);
P_SetTarget(&dropwork->target, player->mo);
P_AddKartItem(dropwork); // needs to be called here so shrink can bust items off players in front of the user.
P_AddKartItem(dropwork); // needs to be called here so shrink can bust items off players in front of the user.
dropwork->angle = work->angle;
dropwork->flags2 = work->flags2;
dropwork->flags |= MF_NOCLIPTHING;
dropwork->flags2 = work->flags2;
dropwork->floorz = work->floorz;
dropwork->ceilingz = work->ceilingz;
@ -4760,19 +4822,29 @@ void K_DropHnextList(player_t *player)
if (orbit) // splay out
{
dropwork->flags2 |= MF2_AMBUSH;
dropwork->z += flip;
dropwork->momx = player->mo->momx>>1;
dropwork->momy = player->mo->momy>>1;
dropwork->momz = 3*flip*mapobjectscale;
if (dropwork->eflags & MFE_UNDERWATER)
dropwork->momz = (117 * dropwork->momz) / 200;
P_Thrust(dropwork, work->angle - ANGLE_90, 6*mapobjectscale);
dropwork->movecount = 2;
dropwork->movedir = work->angle - ANGLE_90;
P_SetMobjState(dropwork, dropwork->info->deathstate);
dropwork->tics = -1;
if (type == MT_JAWZ_DUD)
{
dropwork->z += 20*flip*dropwork->scale;
}
else
{
dropwork->color = work->color;
@ -4788,39 +4860,33 @@ void K_DropHnextList(player_t *player)
P_RemoveMobj(work);
}
// we need this here too because this is done in afterthink - pointers are cleaned up at the START of each tic...
P_SetTarget(&player->mo->hnext, NULL);
player->kartstuff[k_bananadrag] = 0;
if (player->kartstuff[k_eggmanheld])
{
// we need this here too because this is done in afterthink - pointers are cleaned up at the START of each tic...
P_SetTarget(&player->mo->hnext, NULL);
player->kartstuff[k_bananadrag] = 0;
if (player->kartstuff[k_eggmanheld])
player->kartstuff[k_eggmanheld] = 0;
else if (player->kartstuff[k_itemheld]
&& (dropall || (--player->kartstuff[k_itemamount] <= 0)))
{
player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0;
player->kartstuff[k_itemtype] = KITEM_NONE;
}
player->kartstuff[k_eggmanheld] = 0;
}
else if (player->kartstuff[k_itemheld]
&& (dropall || (--player->kartstuff[k_itemamount] <= 0)))
{
player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0;
player->kartstuff[k_itemtype] = KITEM_NONE;
}
}
// For getting EXTRA hit!
void K_DropItems(player_t *player)
{
INT32 shieldhack = 0;
K_DropHnextList(player, true);
if (player->kartstuff[k_curshield])
shieldhack = K_GetShieldFromItem(player->kartstuff[k_itemtype]);
if (shieldhack)
player->kartstuff[k_itemtype] = KITEM_NONE;
K_DropHnextList(player);
if (player->mo && !P_MobjWasRemoved(player->mo) && player->kartstuff[k_itemamount])
if (player->mo && !P_MobjWasRemoved(player->mo) && player->kartstuff[k_itemamount] > 0)
{
mobj_t *drop = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FLOATINGITEM);
P_SetScale(drop, drop->scale>>4);
drop->destscale = (3*drop->destscale)/2;;
drop->destscale = (3*drop->destscale)/2;
drop->angle = player->mo->angle + ANGLE_90;
P_Thrust(drop,
@ -4830,13 +4896,7 @@ void K_DropItems(player_t *player)
if (drop->eflags & MFE_UNDERWATER)
drop->momz = (117 * drop->momz) / 200;
switch (shieldhack)
{
case KSHIELD_THUNDER: drop->threshold = KITEM_THUNDERSHIELD; break;
case KSHIELD_BUBBLE: drop->threshold = KITEM_BUBBLESHIELD; break;
case KSHIELD_FLAME: drop->threshold = KITEM_FLAMESHIELD; break;
default: drop->threshold = player->kartstuff[k_itemtype]; break;
}
drop->threshold = player->kartstuff[k_itemtype];
drop->movecount = player->kartstuff[k_itemamount];
drop->flags |= MF_NOCLIPTHING;
@ -5176,6 +5236,12 @@ static void K_MoveHeldObjects(player_t *player)
fixed_t targx, targy, targz;
fixed_t speed, dist;
if (cur->type == MT_EGGMANITEM_SHIELD)
{
// Decided that this should use their "canon" color.
cur->color = SKINCOLOR_BLACK;
}
cur->flags &= ~MF_NOCLIPTHING;
if (!cur->health)
@ -6223,10 +6289,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
void K_KartPlayerAfterThink(player_t *player)
{
// Moved to afterthink, as at this point the players have had their distances to the finish line updated
// and this will correctly account for all players
K_KartUpdatePosition(player);
if (player->kartstuff[k_curshield]
|| player->kartstuff[k_invincibilitytimer]
|| (player->kartstuff[k_growshrinktimer] != 0 && player->kartstuff[k_growshrinktimer] % 5 == 4)) // 4 instead of 0 because this is afterthink!
@ -6543,7 +6605,7 @@ static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_
}
/*--------------------------------------------------
static void K_UpdateDistanceFromFinishLine(player_t *const player)
void K_UpdateDistanceFromFinishLine(player_t *const player)
Updates the distance a player has to the finish line.
@ -6553,7 +6615,7 @@ static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_
Return:-
None
--------------------------------------------------*/
static void K_UpdateDistanceFromFinishLine(player_t *const player)
void K_UpdateDistanceFromFinishLine(player_t *const player)
{
if ((player != NULL) && (player->mo != NULL))
{
@ -7103,7 +7165,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
boolean HOLDING_ITEM = (player->kartstuff[k_itemheld] || player->kartstuff[k_eggmanheld]);
boolean NO_HYUDORO = (player->kartstuff[k_stolentimer] == 0 && player->kartstuff[k_stealingtimer] == 0);
K_UpdateDistanceFromFinishLine(player);
player->pflags &= ~PF_HITFINISHLINE;
if (!player->exiting)

View file

@ -18,6 +18,7 @@ extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color);
UINT8 K_GetKartColorByName(const char *name);
player_t *K_GetItemBoxPlayer(mobj_t *mobj);
void K_RegisterKartStuff(void);
@ -55,9 +56,10 @@ void K_DoSneaker(player_t *player, INT32 type);
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound);
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source);
void K_UpdateHnextList(player_t *player, boolean clean);
void K_DropHnextList(player_t *player);
void K_DropHnextList(player_t *player, boolean keepshields);
void K_RepairOrbitChain(mobj_t *orbit);
player_t *K_FindJawzTarget(mobj_t *actor, player_t *source);
void K_UpdateDistanceFromFinishLine(player_t *const player);
boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y);
INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
INT32 K_GetKartDriftSparkValue(player_t *player);
@ -66,6 +68,7 @@ void K_DropItems(player_t *player);
void K_StripItems(player_t *player);
void K_StripOther(player_t *player);
void K_MomentumToFacing(player_t *player);
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
fixed_t K_GetKartAccel(player_t *player);
UINT16 K_GetKartFlashing(player_t *player);

View file

@ -16,6 +16,7 @@
#include "d_netcmd.h"
#include "p_local.h"
#include "p_tick.h"
#include "r_local.h"
#include "z_zone.h"
#include "g_game.h"
@ -318,6 +319,16 @@ size_t K_GetWaypointHeapIndex(waypoint_t *waypoint)
return waypointindex;
}
/*--------------------------------------------------
size_t K_GetNumWaypoints(void)
See header file for description.
--------------------------------------------------*/
size_t K_GetNumWaypoints(void)
{
return numwaypoints;
}
/*--------------------------------------------------
waypoint_t *K_GetWaypointFromIndex(size_t waypointindex)
@ -1478,7 +1489,6 @@ static waypoint_t *K_MakeWaypoint(mobj_t *const mobj)
I_Assert(waypointcap != NULL); // No waypoint mobjs in map load
I_Assert(numwaypoints < numwaypointmobjs); // waypoint array reached max capacity
// numwaypoints is incremented later in K_SetupWaypoint
madewaypoint = &waypointheap[numwaypoints];
numwaypoints++;
@ -1761,3 +1771,176 @@ void K_ClearWaypoints(void)
numwaypointmobjs = 0U;
circuitlength = 0U;
}
/*--------------------------------------------------
static boolean K_RaiseWaypoint(
mobj_t *const waypointmobj,
const mobj_t *const riser)
Raise a waypoint according a waypoint riser thing.
Input Arguments:-
waypointmobj - The mobj of the waypoint to raise
riser - The waypoint riser mobj
Return:-
True if the waypoint was risen, false if not.
--------------------------------------------------*/
static boolean K_RaiseWaypoint(
mobj_t *const waypointmobj,
const mobj_t *const riser)
{
fixed_t x;
fixed_t y;
const sector_t *sector;
ffloor_t *rover;
boolean descending;
fixed_t sort;
fixed_t z;
if (
!( riser->spawnpoint->options & MTF_OBJECTSPECIAL ) ||
riser->spawnpoint->angle == waypointmobj->spawnpoint->angle
){
if (( riser->spawnpoint->options & MTF_AMBUSH ))
{
waypointmobj->z = riser->z;
}
else
{
x = waypointmobj->x;
y = waypointmobj->y;
descending = ( riser->spawnpoint->options & MTF_OBJECTFLIP );
sector = waypointmobj->subsector->sector;
if (descending)
sort = sector->ceilingheight;
else
sort = sector->floorheight;
for (
rover = sector->ffloors;
rover;
rover = rover->next
){
if (descending)
{
z = P_GetFOFBottomZAt(rover, x, y);
if (z > riser->z && z < sort)
sort = z;
}
else
{
z = P_GetFOFTopZAt(rover, x, y);
if (z < riser->z && z > sort)
sort = z;
}
}
waypointmobj->z = sort;
}
return true;
}
else
return false;
}
/*--------------------------------------------------
static boolean K_AnchorWaypointRadius(
mobj_t *const waypointmobj,
const mobj_t *const anchor)
Adjust a waypoint's radius by distance from an "anchor".
Input Arguments:-
waypointmobj - The mobj of the waypoint whose radius to adjust
riser - The waypoint anchor mobj
Return:-
True if the waypoint's radius was adjusted, false if not.
--------------------------------------------------*/
static boolean K_AnchorWaypointRadius(
mobj_t *const waypointmobj,
const mobj_t *const anchor)
{
if (anchor->spawnpoint->angle == waypointmobj->spawnpoint->angle)
{
waypointmobj->radius = R_PointToDist2(
waypointmobj->x, waypointmobj->y,
anchor->x, anchor->y);
return true;
}
else
return false;
}
/*--------------------------------------------------
void K_AdjustWaypointsParameters(void)
See header file for description.
--------------------------------------------------*/
void K_AdjustWaypointsParameters (void)
{
mobj_t *waypointmobj;
const mobj_t *riser;
const thinker_t *th;
const mobj_t *anchor;
const sector_t *sector;
for (
waypointmobj = waypointcap;
waypointmobj;
waypointmobj = waypointmobj->tracer
){
sector = waypointmobj->subsector->sector;
for (
riser = sector->thinglist;
riser;
riser = riser->snext
){
if (riser->type == MT_WAYPOINT_RISER)
{
if (K_RaiseWaypoint(waypointmobj, riser))
break;
}
}
}
for (
th = thinkercap.next;
th != &thinkercap;
th = th->next
){
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{
anchor = (const mobj_t *)th;
if (anchor->type == MT_WAYPOINT_ANCHOR)
{
for (
waypointmobj = waypointcap;
waypointmobj;
waypointmobj = waypointmobj->tracer
){
if (K_AnchorWaypointRadius(waypointmobj, anchor))
break;
}
}
}
}
}

View file

@ -287,6 +287,16 @@ waypoint_t *K_SearchWaypointHeapForMobj(mobj_t * const mobj);
--------------------------------------------------*/
size_t K_GetWaypointHeapIndex(waypoint_t *waypoint);
/*--------------------------------------------------
size_t K_GetNumWaypoints(void)
Returns the number of waypoints that are in the heap.
Intended for Net Archiving/Unarchiving
Return:-
The number of waypoints in the heap
--------------------------------------------------*/
size_t K_GetNumWaypoints(void);
/*--------------------------------------------------
waypoint_t *K_GetWaypointFromIndex(size_t waypointindex)
@ -335,4 +345,14 @@ boolean K_SetupWaypointList(void);
void K_ClearWaypoints(void);
#endif
/*--------------------------------------------------
void K_AdjustWaypointsParameters(void)
Adjusts waypoint parameters after P_SpawnSpecials. This is for
raising waypoints to an FOF, which requires that the FOF is
already spawned.
--------------------------------------------------*/
void K_AdjustWaypointsParameters (void);
#endif

View file

@ -18,17 +18,30 @@
#include "z_zone.h"
#include "v_video.h"
#include "i_video.h"
#include "m_misc.h"
#include "st_stuff.h" // st_palette
#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif
// GIFs are always little-endian
#include "byteptr.h"
consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb
static boolean gif_downscale = false; // like changing cvars mid output
// Palette handling
static boolean gif_localcolortable = false;
static boolean gif_colorprofile = false;
static RGBA_t *gif_headerpalette = NULL;
static RGBA_t *gif_framepalette = NULL;
static FILE *gif_out = NULL;
static INT32 gif_frames = 0;
static UINT8 gif_writeover = 0;
@ -387,17 +400,47 @@ const UINT8 gifhead_nsid[19] = {0x21,0xFF,0x0B, // extension block + size
0x4E,0x45,0x54,0x53,0x43,0x41,0x50,0x45,0x32,0x2E,0x30, // NETSCAPE2.0
0x03,0x01,0xFF,0xFF,0x00}; // sub-block, repetitions
//
// GIF_getpalette
// determine the palette for the current frame.
//
static RGBA_t *GIF_getpalette(size_t palnum)
{
// In hardware mode, uses the master palette
return ((gif_colorprofile
#ifdef HWRENDER
&& (rendermode == render_soft)
#endif
) ? &pLocalPalette[palnum*256]
: &pMasterPalette[palnum*256]);
}
//
// GIF_palwrite
// writes the gif palette.
// used both for the header and local color tables.
//
static UINT8 *GIF_palwrite(UINT8 *p, RGBA_t *pal)
{
INT32 i;
for (i = 0; i < 256; i++)
{
WRITEUINT8(p, pal[i].s.red);
WRITEUINT8(p, pal[i].s.green);
WRITEUINT8(p, pal[i].s.blue);
}
return p;
}
//
// GIF_headwrite
// writes the gif header to the currently open output file.
// NOTE that this code does not accomodate for palette changes.
//
static void GIF_headwrite(void)
{
UINT8 *gifhead = Z_Malloc(800, PU_STATIC, NULL);
UINT8 *p = gifhead;
RGBA_t *c;
INT32 i;
UINT16 rwidth, rheight;
if (!gif_out)
@ -418,22 +461,21 @@ static void GIF_headwrite(void)
rwidth = vid.width;
rheight = vid.height;
}
WRITEUINT16(p, rwidth);
WRITEUINT16(p, rheight);
// colors, aspect, etc
WRITEUINT8(p, 0xFF); // TRANSPARENTPIXEL
/*
also these are magical values, check out
https://tronche.com/computer-graphics/gif/gif89a.html#screen-descriptor
*/
WRITEUINT8(p, 0xF7); // (0xF7 = 1111 0111)
WRITEUINT8(p, 0x00);
WRITEUINT8(p, 0x00);
// write color table
for (i = 0; i < 256; ++i)
{
c = &pLocalPalette[i];
WRITEUINT8(p, c->s.red);
WRITEUINT8(p, c->s.green);
WRITEUINT8(p, c->s.blue);
}
p = GIF_palwrite(p, gif_headerpalette);
// write extension block
WRITEMEM(p, gifhead_nsid, sizeof(gifhead_nsid));
@ -452,6 +494,32 @@ const UINT8 gifframe_gchead[4] = {0x21,0xF9,0x04,0x04}; // GCE, bytes, packed by
static UINT8 *gifframe_data = NULL;
static size_t gifframe_size = 8192;
#ifdef HWRENDER
static void hwrconvert(void)
{
UINT8 *linear = HWR_GetScreenshot();
UINT8 *dest = screens[2];
UINT8 r, g, b;
INT32 x, y;
size_t i = 0;
InitColorLUT(gif_framepalette);
for (y = 0; y < vid.height; y++)
{
for (x = 0; x < vid.width; x++, i += 3)
{
r = (UINT8)linear[i];
g = (UINT8)linear[i + 1];
b = (UINT8)linear[i + 2];
dest[(y * vid.width) + x] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS];
}
}
free(linear);
}
#endif
//
// GIF_framewrite
// writes a frame into the file.
@ -461,6 +529,7 @@ static void GIF_framewrite(void)
UINT8 *p;
UINT8 *movie_screen = screens[2];
INT32 blitx, blity, blitw, blith;
boolean palchanged;
if (!gifframe_data)
gifframe_data = Z_Malloc(gifframe_size, PU_STATIC, NULL);
@ -469,15 +538,30 @@ static void GIF_framewrite(void)
if (!gif_out)
return;
// Lactozilla: Compare the header's palette with the current frame's palette and see if it changed.
if (gif_localcolortable)
{
gif_framepalette = GIF_getpalette(max(st_palette, 0));
palchanged = memcmp(gif_headerpalette, gif_framepalette, sizeof(RGBA_t) * 256);
}
else
palchanged = false;
// Compare image data (for optimizing GIF)
if (gif_optimize && gif_frames > 0)
// If the palette has changed, the entire frame is considered to be different.
if (gif_optimize && gif_frames > 0 && (!palchanged))
{
// before blit movie_screen points to last frame, cur_screen points to this frame
UINT8 *cur_screen = screens[0];
GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith);
// blit to temp screen
I_ReadScreen(movie_screen);
if (rendermode == render_soft)
I_ReadScreen(movie_screen);
#ifdef HWRENDER
else if (rendermode == render_opengl)
hwrconvert();
#endif
}
else
{
@ -486,7 +570,18 @@ static void GIF_framewrite(void)
blith = vid.height;
if (gif_frames == 0)
I_ReadScreen(movie_screen);
{
if (rendermode == render_soft)
I_ReadScreen(movie_screen);
#ifdef HWRENDER
else if (rendermode == render_opengl)
{
hwrconvert();
VID_BlitLinearScreen(screens[2], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
}
#endif
}
movie_screen = screens[0];
}
@ -517,7 +612,20 @@ static void GIF_framewrite(void)
WRITEUINT16(p, (UINT16)(blity / scrbuf_downscaleamt));
WRITEUINT16(p, (UINT16)(blitw / scrbuf_downscaleamt));
WRITEUINT16(p, (UINT16)(blith / scrbuf_downscaleamt));
WRITEUINT8(p, 0); // no local table of colors
if (!gif_localcolortable)
WRITEUINT8(p, 0); // no local table of colors
else
{
if (palchanged)
{
// The palettes are different, so write the Local Color Table!
WRITEUINT8(p, 0x87); // (0x87 = 1000 0111)
p = GIF_palwrite(p, gif_framepalette);
}
else
WRITEUINT8(p, 0); // They are equal, no Local Color Table needed.
}
scrbuf_pos = movie_screen + blitx + (blity * vid.width);
scrbuf_writeend = scrbuf_pos + (blitw - 1) + ((blith - 1) * vid.width);
@ -575,20 +683,16 @@ static void GIF_framewrite(void)
//
INT32 GIF_open(const char *filename)
{
#ifdef HWRENDER
if (rendermode != render_soft)
{
CONS_Alert(CONS_WARNING, M_GetText("GIFs cannot be taken in non-software modes!\n"));
return 0;
}
#endif
gif_out = fopen(filename, "wb");
if (!gif_out)
return 0;
gif_optimize = (!!cv_gif_optimize.value);
gif_downscale = (!!cv_gif_downscale.value);
gif_localcolortable = (!!cv_gif_localcolortable.value);
gif_colorprofile = (!!cv_screenshot_colorprofile.value);
gif_headerpalette = GIF_getpalette(0);
GIF_headwrite();
gif_frames = 0;
return 1;

View file

@ -27,6 +27,6 @@ void GIF_frame(void);
INT32 GIF_close(void);
#endif
extern consvar_t cv_gif_optimize, cv_gif_downscale;
extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_localcolortable;
#endif

View file

@ -1252,7 +1252,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 20},
#endif
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
NULL, "Gamma", &cv_usegamma, 30},
NULL, "Gamma", &cv_globalgamma, 30},
{IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 45},
//{IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist", &cv_drawdist_nights, 55},
@ -2101,14 +2101,14 @@ static void Nextmap_OnChange(void)
if (currentMenu == &SP_TimeAttackDef)
{
// see also p_setup.c's P_LoadRecordGhosts
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
const size_t glen = strlen(srb2home)+1+strlen("media")+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath = malloc(glen);
INT32 i;
if (!gpath)
return;
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
CV_StealthSetValue(&cv_dummystaff, 0);
@ -2675,7 +2675,7 @@ boolean M_Responder(event_t *ev)
return true;
case KEY_F11: // Gamma Level
CV_AddValue(&cv_usegamma, 1);
CV_AddValue(&cv_globalgamma, 1);
return true;
// Spymode on F12 handled in game logic
@ -3321,9 +3321,6 @@ void M_Init(void)
#ifndef NONET
CV_RegisterVar(&cv_serversort);
#endif
//todo put this somewhere better...
CV_RegisterVar(&cv_allcaps);
}
void M_InitCharacterTables(void)
@ -5145,7 +5142,7 @@ void M_ReplayHut(INT32 choice)
if (!demo.inreplayhut)
{
snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home);
snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home);
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath);
}
if (!preparefilemenu(false, true))
@ -7879,20 +7876,21 @@ static boolean M_QuitTimeAttackMenu(void)
static void M_ChooseTimeAttack(INT32 choice)
{
char *gpath;
const size_t glen = strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
const size_t glen = strlen("media")+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char nameofdemo[256];
(void)choice;
emeralds = 0;
M_ClearMenus(true);
modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD);
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s",
srb2home, timeattackfolder);
M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755);
if ((gpath = malloc(glen)) == NULL)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value));
sprintf(gpath,"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value));
snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_chooseskin.string);
if (!cv_autorecord.value)

View file

@ -32,6 +32,7 @@
#include "g_game.h"
#include "m_misc.h"
#include "hu_stuff.h"
#include "st_stuff.h"
#include "v_video.h"
#include "z_zone.h"
#include "g_input.h"
@ -106,6 +107,8 @@ static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2
consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
@ -591,6 +594,21 @@ void M_SaveConfig(const char *filename)
fclose(f);
}
// ==========================================================================
// SCREENSHOTS
// ==========================================================================
static UINT8 screenshot_palette[768];
static void M_CreateScreenShotPalette(void)
{
size_t i, j;
for (i = 0, j = 0; i < 768; i += 3, j++)
{
RGBA_t locpal = pLocalPalette[(max(st_palette,0)*256)+j];
screenshot_palette[i] = locpal.s.red;
screenshot_palette[i+1] = locpal.s.green;
screenshot_palette[i+2] = locpal.s.blue;
}
}
#if NUMSCREENS > 2
static const char *Newsnapshotfile(const char *pathname, const char *ext)
@ -665,14 +683,17 @@ static void M_PNGhdr(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png_
if (palette)
{
png_colorp png_PLTE = png_malloc(png_ptr, sizeof(png_color)*256); //palette
const png_byte *pal = palette;
png_uint_16 i;
const png_byte *pal = palette;
for (i = 0; i < 256; i++)
{
png_PLTE[i].red = *pal; pal++;
png_PLTE[i].green = *pal; pal++;
png_PLTE[i].blue = *pal; pal++;
}
png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, PNG_COLOR_TYPE_PALETTE,
png_interlace, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info_before_PLTE(png_ptr, png_info_ptr);
@ -1022,6 +1043,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
static inline moviemode_t M_StartMovieAPNG(const char *pathname)
{
#ifdef USE_APNG
UINT8 *palette;
const char *freename = NULL;
boolean ret = false;
@ -1037,10 +1059,8 @@ static inline moviemode_t M_StartMovieAPNG(const char *pathname)
return MM_OFF;
}
if (rendermode == render_soft)
ret = M_SetupaPNG(va(pandf,pathname,freename), W_CacheLumpName(GetPalette(), PU_CACHE));
else
ret = M_SetupaPNG(va(pandf,pathname,freename), NULL);
if (rendermode == render_soft) M_CreateScreenShotPalette();
ret = M_SetupaPNG(va(pandf,pathname,freename), (palette = screenshot_palette));
if (!ret)
{
@ -1101,8 +1121,8 @@ void M_StartMovie(void)
if (cv_movie_option.value != 3)
{
strcat(pathname, PATHSEP"movies"PATHSEP);
I_mkdir(pathname, 0755);
strcat(pathname, PATHSEP"media"PATHSEP"movies"PATHSEP);
M_MkdirEach(pathname, M_PathParts(pathname) - 2, 0755);
}
if (rendermode == render_none)
@ -1111,12 +1131,8 @@ void M_StartMovie(void)
switch (cv_moviemode.value)
{
case MM_GIF:
if (rendermode == render_soft)
{
moviemode = M_StartMovieGIF(pathname);
break;
}
/* FALLTHRU */
moviemode = M_StartMovieGIF(pathname);
break;
case MM_APNG:
moviemode = M_StartMovieAPNG(pathname);
break;
@ -1249,14 +1265,13 @@ void M_StopMovie(void)
* \param data The image data.
* \param width Width of the picture.
* \param height Height of the picture.
* \param palette Palette of image data
* \param palette Palette of image data.
* \note if palette is NULL, BGR888 format
*/
boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette)
{
png_structp png_ptr;
png_infop png_info_ptr;
PNG_CONST png_byte *PLTE = (const png_byte *)palette;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf;
@ -1271,8 +1286,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
return false;
}
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
PNG_error, PNG_warn);
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn);
if (!png_ptr)
{
CONS_Debug(DBG_RENDER, "M_SavePNG: Error on initialize libpng\n");
@ -1319,7 +1333,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
png_set_compression_strategy(png_ptr, cv_zlib_strategy.value);
png_set_compression_window_bits(png_ptr, cv_zlib_window_bits.value);
M_PNGhdr(png_ptr, png_info_ptr, width, height, PLTE);
M_PNGhdr(png_ptr, png_info_ptr, width, height, palette);
M_PNGText(png_ptr, png_info_ptr, false);
@ -1366,7 +1380,7 @@ typedef struct
* \param palette Palette of image data
*/
#if NUMSCREENS > 2
static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, int height, const UINT8 *palette)
static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, int height)
{
int i;
size_t length;
@ -1407,8 +1421,20 @@ static boolean WritePCXfile(const char *filename, const UINT8 *data, int width,
// write the palette
*pack++ = 0x0c; // palette ID byte
for (i = 0; i < 768; i++)
*pack++ = *palette++;
// write color table
{
RGBA_t *pal = ((cv_screenshot_colorprofile.value)
? pLocalPalette
: pMasterPalette);
for (i = 0; i < 256; i++)
{
*pack++ = pal[i].s.red;
*pack++ = pal[i].s.green;
*pack++ = pal[i].s.blue;
}
}
// write output file
length = pack - (UINT8 *)pcx;
@ -1426,9 +1452,8 @@ void M_ScreenShot(void)
}
/** Takes a screenshot.
* The screenshot is saved as "kartxxxx.pcx" (or "kartxxxx.tga" in hardware
* rendermode) where xxxx is the lowest four-digit number for which a file
* does not already exist.
* The screenshot is saved as "srb2xxxx.png" where xxxx is the lowest
* four-digit number for which a file does not already exist.
*
* \sa HWR_ScreenShot
*/
@ -1443,6 +1468,10 @@ void M_DoScreenShot(void)
// Don't take multiple screenshots, obviously
takescreenshot = false;
// how does one take a screenshot without a render system?
if (rendermode == render_none)
return;
if (cv_screenshot_option.value == 0)
strcpy(pathname, usehome ? srb2home : srb2path);
else if (cv_screenshot_option.value == 1)
@ -1454,21 +1483,18 @@ void M_DoScreenShot(void)
if (cv_screenshot_option.value != 3)
{
strcat(pathname, PATHSEP"screenshots"PATHSEP);
I_mkdir(pathname, 0755);
strcat(pathname, PATHSEP"media"PATHSEP"screenshots"PATHSEP);
M_MkdirEach(pathname, M_PathParts(pathname) - 2, 0755);
}
#ifdef USE_PNG
if (rendermode != render_none)
freename = Newsnapshotfile(pathname,"png");
freename = Newsnapshotfile(pathname,"png");
#else
if (rendermode == render_soft)
freename = Newsnapshotfile(pathname,"pcx");
else if (rendermode != render_none)
else if (rendermode == render_opengl)
freename = Newsnapshotfile(pathname,"tga");
#endif
else
I_Error("Can't take a screenshot without a render system");
if (rendermode == render_soft)
{
@ -1482,18 +1508,16 @@ void M_DoScreenShot(void)
// save the pcx file
#ifdef HWRENDER
if (rendermode != render_soft)
if (rendermode == render_opengl)
ret = HWR_Screenshot(va(pandf,pathname,freename));
else
#endif
if (rendermode != render_none)
{
M_CreateScreenShotPalette();
#ifdef USE_PNG
ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height,
W_CacheLumpName(GetPalette(), PU_CACHE));
ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette);
#else
ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height,
W_CacheLumpName(GetPalette(), PU_CACHE));
ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette);
#endif
}
@ -1501,14 +1525,14 @@ failure:
if (ret)
{
if (moviemode != MM_SCREENSHOT)
CONS_Printf(M_GetText("screen shot %s saved in %s\n"), freename, pathname);
CONS_Printf(M_GetText("Screen shot %s saved in %s\n"), freename, pathname);
}
else
{
if (freename)
CONS_Printf(M_GetText("Couldn't create screen shot %s in %s\n"), freename, pathname);
CONS_Alert(CONS_ERROR, M_GetText("Couldn't create screen shot %s in %s\n"), freename, pathname);
else
CONS_Printf(M_GetText("Couldn't create screen shot (all 10000 slots used!) in %s\n"), pathname);
CONS_Alert(CONS_ERROR, M_GetText("Couldn't create screen shot in %s (all 10000 slots used!)\n"), pathname);
if (moviemode == MM_SCREENSHOT)
M_StopMovie();

View file

@ -29,7 +29,7 @@ typedef enum {
} moviemode_t;
extern moviemode_t moviemode;
extern consvar_t cv_screenshot_option, cv_screenshot_folder;
extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_colorprofile;
extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option;
extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits;
extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa;

View file

@ -751,7 +751,7 @@ static INT32 AddToMasterServer(boolean firstadd)
strcpy(info->name, cv_servername.string);
M_Memcpy(&info->room, & room, sizeof (INT32));
#if VERSION > 0 || SUBVERSION > 0
sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
sprintf(info->version, "%d.%d", VERSION, SUBVERSION);
#else // Trunk build, send revision info
strcpy(info->version, GetRevisionString());
#endif
@ -789,7 +789,7 @@ static INT32 RemoveFromMasterSever(void)
strcpy(info->ip, "");
strcpy(info->port, int2str(current_port));
strcpy(info->name, registered_server.name);
sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
sprintf(info->version, "%d.%d", VERSION, SUBVERSION);
msg.type = REMOVE_SERVER_MSG;
msg.length = (UINT32)sizeof (msg_server_t);

View file

@ -8453,13 +8453,109 @@ static void SpawnSPBTrailRings(mobj_t *actor)
if (leveltime % 6 == 0)
{
mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy,
actor->z - actor->momz + (24*mapobjectscale), MT_RING);
ring->threshold = 10;
ring->fuse = 120*TICRATE;
if (leveltime % (actor->extravalue1 == 2 ? 6 : 3) == 0) // Extravalue1 == 2 is seeking mode. Because the SPB is about twice as fast as normal in that mode, also spawn the rings twice as often to make up for it!
{
mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy,
actor->z - actor->momz + (24*mapobjectscale), MT_RING);
ring->threshold = 10;
ring->fuse = 35*TICRATE;
ring->colorized = true;
ring->color = SKINCOLOR_RED;
}
}
}
// Spawns the V shaped dust. To be used when the SPB is going mostly forward.
static void SpawnSPBDust(mobj_t *mo)
{
// The easiest way to spawn a V shaped cone of dust from the SPB is simply to spawn 2 particles, and to both move them to the sides in opposite direction.
mobj_t *dust;
fixed_t sx;
fixed_t sy;
fixed_t sz = mo->floorz;
angle_t sa = mo->angle - ANG1*60;
INT32 i;
if (mo->eflags & MFE_VERTICALFLIP)
sz = mo->ceilingz;
if (leveltime & 1 && abs(mo->z - sz) < FRACUNIT*64) // Only ever other frame. Also don't spawn it if we're way above the ground.
{
// Determine spawning position next to the SPB:
for (i=0; i < 2; i++)
{
sx = mo->x + FixedMul((mo->scale*96), FINECOSINE((sa)>>ANGLETOFINESHIFT));
sy = mo->y + FixedMul((mo->scale*96), FINESINE((sa)>>ANGLETOFINESHIFT));
dust = P_SpawnMobj(sx, sy, sz, MT_SPBDUST);
dust->momx = mo->momx/2;
dust->momy = mo->momy/2;
dust->momz = mo->momz/2; // Give some of the momentum to the dust
P_SetScale(dust, mo->scale*2);
dust->colorized = true;
dust->color = SKINCOLOR_RED;
dust->angle = mo->angle - FixedAngle(FRACUNIT*90 - FRACUNIT*180*i); // The first one will spawn to the right of the spb, the second one to the left.
P_Thrust(dust, dust->angle, 6*dust->scale);
K_MatchGenericExtraFlags(dust, mo);
sa += ANG1*120; // Add 120 degrees to get to mo->angle + ANG1*60
}
}
}
// Spawns SPB slip tide. To be used when the SPB is turning.
// Modified version of K_SpawnAIZDust. Maybe we could merge those to be cleaner?
// dir should be either 1 or -1 to determine where to spawn the dust.
static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir)
{
fixed_t newx;
fixed_t newy;
mobj_t *spark;
angle_t travelangle;
fixed_t sz = mo->floorz;
if (mo->eflags & MFE_VERTICALFLIP)
sz = mo->ceilingz;
travelangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
if (leveltime & 1 && abs(mo->z - sz) < FRACUNIT*64)
{
newx = mo->x + P_ReturnThrustX(mo, travelangle - (dir*ANGLE_45), FixedMul(24*FRACUNIT, mo->scale));
newy = mo->y + P_ReturnThrustY(mo, travelangle - (dir*ANGLE_45), FixedMul(24*FRACUNIT, mo->scale));
spark = P_SpawnMobj(newx, newy, sz, MT_AIZDRIFTSTRAT);
spark->colorized = true;
spark->color = SKINCOLOR_RED;
spark->flags = MF_NOGRAVITY|MF_PAIN;
P_SetTarget(&spark->target, mo);
spark->angle = travelangle+(dir*ANGLE_90);
P_SetScale(spark, (spark->destscale = mo->scale*3/2));
spark->momx = (6*mo->momx)/5;
spark->momy = (6*mo->momy)/5;
K_MatchGenericExtraFlags(spark, mo);
}
}
// Used for seeking and when SPB is trailing its target from way too close!
static void SpawnSPBSpeedLines(mobj_t *actor)
{
mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale),
actor->y + (P_RandomRange(-24,24) * actor->scale),
actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale),
MT_FASTLINE);
fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
fast->color = SKINCOLOR_RED;
fast->colorized = true;
K_MatchGenericExtraFlags(fast, actor);
}
void A_SPBChase(mobj_t *actor)
{
player_t *player = NULL;
@ -8478,7 +8574,7 @@ void A_SPBChase(mobj_t *actor)
#endif
// Default speed
wspeed = actor->movefactor;
wspeed = FixedMul(mapobjectscale, K_GetKartSpeedFromStat(5)*2); // Go at twice the average speed a player would be going at!
if (actor->threshold) // Just fired, go straight.
{
@ -8630,19 +8726,7 @@ void A_SPBChase(mobj_t *actor)
if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15
: (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target
&& xyspeed > K_GetKartSpeed(actor->tracer->player, false)/4) // Don't display speedup lines at pitifully low speeds
{
mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale),
actor->y + (P_RandomRange(-24,24) * actor->scale),
actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale),
MT_FASTLINE);
fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
//fast->momx = (3*actor->momx)/4;
//fast->momy = (3*actor->momy)/4;
//fast->momz = (3*actor->momz)/4;
fast->color = SKINCOLOR_RED;
fast->colorized = true;
K_MatchGenericExtraFlags(fast, actor);
}
SpawnSPBSpeedLines(actor);
return;
}
@ -8704,6 +8788,12 @@ void A_SPBChase(mobj_t *actor)
spbplace = bestrank;
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
/*
K_GetBestWaypointForMobj returns the waypoint closest to the object that isn't its current waypoint. While this is usually good enough,
in cases where the track overlaps, this means that the SPB will sometimes target a waypoint on an earlier/later portion of the track instead of following along.
For this reason, we're going to try and make sure to avoid these situations.
*/
// Move along the waypoints until you get close enough
if (actor->cusval > -1 && actor->extravalue2 > 0)
{
@ -8771,6 +8861,8 @@ void A_SPBChase(mobj_t *actor)
// Smoothly rotate horz angle
angle_t input = hang - actor->angle;
boolean invert = (input > ANGLE_180);
INT32 turnangle;
if (invert)
input = InvAngle(input);
@ -8783,6 +8875,17 @@ void A_SPBChase(mobj_t *actor)
input = InvAngle(input);
actor->angle += input;
// If input is small enough, spawn dust. Otherwise, spawn a slip tide!
turnangle = AngleFixed(input)/FRACUNIT;
// The SPB is really turning if that value is >= 3 and <= 357. This looks pretty bad check-wise so feel free to change it for something that isn't as terrible.
if (turnangle >= 3 && turnangle <= 357)
SpawnSPBAIZDust(actor, turnangle < 180 ? 1 : -1); // 1 if turning left, -1 if turning right. Angles work counterclockwise, remember!
else
SpawnSPBDust(actor); // if we're mostly going straight, then spawn the V dust cone!
SpawnSPBSpeedLines(actor); // Always spawn speed lines while seeking
// Smoothly rotate vert angle
input = vang - actor->movedir;
invert = (input > ANGLE_180);
@ -8831,7 +8934,7 @@ void A_SPBChase(mobj_t *actor)
// Spawn a trail of rings behind the SPB!
SpawnSPBTrailRings(actor);
if (dist <= (1024*actor->tracer->scale)) // Close enough to target?
if (dist <= (1024*actor->tracer->scale) && !(actor->flags2 & MF2_AMBUSH)) // Close enough to target? Use Ambush flag to disable targetting so I can have an easier time testing stuff...
{
S_StartSound(actor, actor->info->attacksound);
actor->extravalue1 = 1; // TARGET ACQUIRED

View file

@ -542,7 +542,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->kartstuff[k_bubbleblowup] > 0)
{
K_DropHnextList(player);
K_DropHnextList(player, false);
special->extravalue1 = 2; // WAIT...
special->extravalue2 = 52; // Slightly over the respawn timer length
return;

View file

@ -355,6 +355,12 @@ boolean PIT_PushableMoved(mobj_t *thing);
boolean P_DoSpring(mobj_t *spring, mobj_t *object);
fixed_t P_GetFOFTopZAt (ffloor_t *rover, fixed_t x, fixed_t y);
fixed_t P_GetFOFBottomZAt (ffloor_t *rover, fixed_t x, fixed_t y);
fixed_t P_VeryTopOfFOF (ffloor_t *rover);
fixed_t P_VeryBottomOfFOF (ffloor_t *rover);
//
// P_SETUP
//

View file

@ -4749,3 +4749,51 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
return floorz;
}
fixed_t
P_GetFOFTopZAt (ffloor_t *rover, fixed_t x, fixed_t y)
{
(void)x;
(void)y;
#ifdef ESLOPE
if (*rover->t_slope)
return P_GetZAt(*rover->t_slope, x, y);
else
#endif
return *rover->topheight;
}
fixed_t
P_GetFOFBottomZAt (ffloor_t *rover, fixed_t x, fixed_t y)
{
(void)x;
(void)y;
#ifdef ESLOPE
if (*rover->b_slope)
return P_GetZAt(*rover->b_slope, x, y);
else
#endif
return *rover->bottomheight;
}
fixed_t
P_VeryTopOfFOF (ffloor_t *rover)
{
#ifdef ESLOPE
if (*rover->t_slope)
return (*rover->t_slope)->highz;
else
#endif
return *rover->topheight;
}
fixed_t
P_VeryBottomOfFOF (ffloor_t *rover)
{
#ifdef ESLOPE
if (*rover->b_slope)
return (*rover->b_slope)->lowz;
else
#endif
return *rover->bottomheight;
}

View file

@ -3991,6 +3991,9 @@ void P_PrecipThinker(precipmobj_t *mobj)
static void P_RingThinker(mobj_t *mobj)
{
mobj_t *spark; // Ring Fuse
if (mobj->momx || mobj->momy)
{
P_RingXYMovement(mobj);
@ -4010,6 +4013,38 @@ static void P_RingThinker(mobj_t *mobj)
return;
}
// This thinker splits apart before the regular fuse handling so we need to handle it here instead.
if (mobj->fuse)
{
mobj->fuse--;
if (mobj->fuse < TICRATE*3)
{
if (leveltime & 1)
mobj->flags2 |= MF2_DONTDRAW;
else
mobj->flags2 &= ~MF2_DONTDRAW;
}
if (!mobj->fuse)
{
#ifdef HAVE_BLUA
if (!LUAh_MobjFuse(mobj))
#endif
{
mobj->flags2 &= ~MF2_DONTDRAW;
spark = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SIGNSPARKLE); // Spawn a fancy sparkle
K_MatchGenericExtraFlags(spark, mobj);
spark->colorized = true;
spark->color = mobj->color ? : SKINCOLOR_YELLOW; // Use yellow if the ring doesn't use a skin color. (It should be red for SPB rings, but let normal rings look fancy too!)
P_RemoveMobj(mobj); // Adieu, monde cruel!
return;
}
}
}
P_CycleMobjState(mobj);
}
@ -6118,7 +6153,7 @@ boolean P_IsKartItem(INT32 type)
type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD ||
type == MT_SSMINE || type == MT_SSMINE_SHIELD ||
type == MT_SINK || type == MT_SINK_SHIELD ||
type == MT_SPB)
type == MT_SPB || type == MT_BALLHOG || type == MT_BUBBLESHIELDTRAP)
return true;
else
return false;
@ -7140,6 +7175,41 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
#endif
// Destroy items sector special
if (mobj->type == MT_BANANA || mobj->type == MT_EGGMANITEM
|| mobj->type == MT_ORBINAUT || mobj->type == MT_BALLHOG
|| mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD
|| mobj->type == MT_SSMINE || mobj->type == MT_BUBBLESHIELDTRAP)
{
if (mobj->health > 0 && P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
if (mobj->type == MT_SSMINE
|| mobj->type == MT_BUBBLESHIELDTRAP
|| mobj->type == MT_BALLHOG)
{
S_StartSound(mobj, mobj->info->deathsound);
P_KillMobj(mobj, NULL, NULL);
}
else
{
// This Item Damage
if (mobj->eflags & MFE_VERTICALFLIP)
mobj->z -= mobj->height;
else
mobj->z += mobj->height;
S_StartSound(mobj, mobj->info->deathsound);
P_KillMobj(mobj, NULL, NULL);
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_90, 16*FRACUNIT);
}
return;
}
}
// if it's pushable, or if it would be pushable other than temporary disablement, use the
// separate thinker
if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse))
@ -7904,12 +7974,6 @@ void P_MobjThinker(mobj_t *mobj)
{
boolean grounded = P_IsObjectOnGround(mobj);
if (P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
P_RemoveMobj(mobj);
return;
}
if (mobj->flags2 & MF2_AMBUSH)
{
if (grounded && (mobj->flags & MF_NOCLIPTHING))
@ -7980,12 +8044,6 @@ void P_MobjThinker(mobj_t *mobj)
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
if (P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
P_RemoveMobj(mobj);
return;
}
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
@ -8010,12 +8068,6 @@ void P_MobjThinker(mobj_t *mobj)
{
boolean grounded = P_IsObjectOnGround(mobj);
if (P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
P_RemoveMobj(mobj);
return;
}
if (mobj->flags2 & MF2_AMBUSH)
{
if (grounded && (mobj->flags & MF_NOCLIPTHING))
@ -8072,15 +8124,22 @@ void P_MobjThinker(mobj_t *mobj)
break;
}
case MT_BANANA:
case MT_EGGMANITEM:
mobj->friction = ORIG_FRICTION/4;
if (P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
P_RemoveMobj(mobj);
return;
player_t *player = K_GetItemBoxPlayer(mobj);
UINT8 color = SKINCOLOR_BLACK;
if (player != NULL)
{
color = player->skincolor;
}
mobj->color = color;
mobj->colorized = false;
}
/* FALLTHRU */
case MT_BANANA:
mobj->friction = ORIG_FRICTION/4;
if (mobj->momx || mobj->momy)
{
@ -8111,12 +8170,6 @@ void P_MobjThinker(mobj_t *mobj)
mobj_t *ghost = P_SpawnGhostMobj(mobj);
ghost->fuse = 3;
if (P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
P_RemoveMobj(mobj);
return;
}
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
@ -8149,12 +8202,6 @@ void P_MobjThinker(mobj_t *mobj)
mobj->threshold--;
break;
case MT_SSMINE:
if (P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
P_RemoveMobj(mobj);
return;
}
if (mobj->target && mobj->target->player)
mobj->color = mobj->target->player->skincolor;
else
@ -8825,8 +8872,8 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->target->player->kartstuff[k_comebacktimer] > 0)
{
if (state < mobj->info->spawnstate || state > mobj->info->spawnstate+19)
P_SetMobjState(mobj, mobj->info->spawnstate);
if (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20)
P_SetMobjState(mobj, S_PLAYERBOMB1);
if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1))
mobj->flags2 &= ~MF2_DONTDRAW;
else
@ -8835,14 +8882,14 @@ void P_MobjThinker(mobj_t *mobj)
else
{
if (!mobj->target->player->kartstuff[k_comebackmode]
&& (state < mobj->info->spawnstate || state > mobj->info->spawnstate+19))
P_SetMobjState(mobj, mobj->info->spawnstate);
&& (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20))
P_SetMobjState(mobj, S_PLAYERBOMB1);
else if (mobj->target->player->kartstuff[k_comebackmode] == 1
&& state != mobj->info->seestate)
P_SetMobjState(mobj, mobj->info->seestate);
&& (state < S_PLAYERITEM1 || state > S_PLAYERITEM12))
P_SetMobjState(mobj, S_PLAYERITEM1);
else if (mobj->target->player->kartstuff[k_comebackmode] == 2
&& state != mobj->info->painstate)
P_SetMobjState(mobj, mobj->info->painstate);
&& (state < S_PLAYERFAKE1 || state > S_PLAYERFAKE12))
P_SetMobjState(mobj, S_PLAYERFAKE1);
if (mobj->target->player->powers[pw_flashing] && (leveltime & 1))
mobj->flags2 |= MF2_DONTDRAW;
@ -9922,7 +9969,15 @@ void P_MobjThinker(mobj_t *mobj)
}
else
{
mobj->color = SKINCOLOR_NONE;
player_t *player = K_GetItemBoxPlayer(mobj);
UINT8 color = SKINCOLOR_BLACK;
if (player != NULL)
{
color = player->skincolor;
}
mobj->color = color;
mobj->colorized = false;
}
break;

View file

@ -49,6 +49,7 @@ UINT8 *save_p;
#define ARCHIVEBLOCK_POBJS 0x7F928546
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
#define ARCHIVEBLOCK_SPECIALS 0x7F228378
#define ARCHIVEBLOCK_WAYPOINTS 0x7F46498F
// Note: This cannot be bigger
// than an UINT16
@ -1908,6 +1909,49 @@ static void P_NetArchiveThinkers(void)
WRITEUINT8(save_p, tc_end);
}
static void P_NetArchiveWaypoints(void)
{
waypoint_t *waypoint;
size_t i;
size_t numWaypoints = K_GetNumWaypoints();
WRITEUINT32(save_p, ARCHIVEBLOCK_WAYPOINTS);
WRITEUINT32(save_p, numWaypoints);
for (i = 0U; i < numWaypoints; i++) {
waypoint = K_GetWaypointFromIndex(i);
// The only thing we save for each waypoint is the mobj.
// Waypoints should NEVER be completely created or destroyed mid-race as a result of this
WRITEUINT32(save_p, waypoint->mobj->mobjnum);
}
}
static void P_NetUnArchiveWaypoints(void)
{
if (READUINT32(save_p) != ARCHIVEBLOCK_WAYPOINTS)
I_Error("Bad $$$.sav at archive block Waypoints!");
else {
UINT32 numArchiveWaypoints = READUINT32(save_p);
size_t numSpawnedWaypoints = K_GetNumWaypoints();
if (numArchiveWaypoints != numSpawnedWaypoints) {
I_Error("Bad $$$.sav: More saved waypoints than created!");
} else {
waypoint_t *waypoint;
UINT32 i;
UINT32 temp;
for (i = 0U; i < numArchiveWaypoints; i++) {
waypoint = K_GetWaypointFromIndex(i);
temp = READUINT32(save_p);
if (!P_SetTarget(&waypoint->mobj, P_FindNewPosition(temp))) {
CONS_Debug(DBG_GAMELOGIC, "waypoint mobj not found for %d\n", i);
}
}
}
}
}
// Now save the pointers, tracer and target, but at load time we must
// relink to this; the savegame contains the old position in the pointer
// field copyed in the info field temporarily, but finally we just search
@ -3526,6 +3570,7 @@ void P_SaveNetGame(void)
#endif
P_NetArchiveThinkers();
P_NetArchiveSpecials();
P_NetArchiveWaypoints();
}
#ifdef HAVE_BLUA
LUA_Archive();
@ -3570,6 +3615,7 @@ boolean P_LoadNetGame(void)
#endif
P_NetUnArchiveThinkers();
P_NetUnArchiveSpecials();
P_NetUnArchiveWaypoints();
P_RelinkPointers();
P_FinishMobjs();
}

View file

@ -2621,14 +2621,14 @@ static void P_ForceCharacter(const char *forcecharskin)
static void P_LoadRecordGhosts(void)
{
// see also m_menu.c's Nextmap_OnChange
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
const size_t glen = strlen(srb2home)+1+strlen("media")+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath = malloc(glen);
INT32 i;
if (!gpath)
return;
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
// Best Time ghost
if (cv_ghost_besttime.value)
@ -3126,6 +3126,8 @@ boolean P_SetupLevel(boolean skipprecip)
// set up world state
P_SpawnSpecials(fromnetsave);
K_AdjustWaypointsParameters();
if (loadprecip) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame)
P_SpawnPrecipitation();
@ -3203,10 +3205,12 @@ boolean P_SetupLevel(boolean skipprecip)
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
if (!demo.playback && multiplayer && !dedicated) {
static char buf[256];
sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap));
char *path;
sprintf(buf, "media"PATHSEP"replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap));
path = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online", srb2home);
M_MkdirEach(path, M_PathParts(path) - 4, 0755);
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
G_RecordDemo(buf);
}

View file

@ -54,6 +54,13 @@ static void P_ReconfigureVertexSlope(pslope_t *slope)
max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)),
max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z))
) >> (FRACBITS+5);
if (slope->extent == 0)
{
// Prevent divide by zero
slope->extent = 1;
}
vec1.x /= slope->extent;
vec1.y /= slope->extent;
vec1.z /= slope->extent;
@ -757,7 +764,6 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
return slope->o.z + FixedMul(dist, slope->zdelta);
}
//
// P_QuantizeMomentumToSlope
//

View file

@ -5350,6 +5350,72 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
return ffloor;
}
static fixed_t
Floor_height (sector_t *s, fixed_t x, fixed_t y)
{
#ifdef ESLOPE
return s->f_slope ? P_GetZAt(s->f_slope, x, y) : s->floorheight;
#else
(void)x;
(void)y;
return s->floorheight;
#endif
}
static fixed_t
Ceiling_height (sector_t *s, fixed_t x, fixed_t y)
{
#ifdef ESLOPE
return s->c_slope ? P_GetZAt(s->c_slope, x, y) : s->ceilingheight;
#else
(void)x;
(void)y;
return s->ceilingheight;
#endif
}
static void
P_RaiseTaggedThingsToFakeFloor (
UINT16 type,
INT16 tag,
sector_t *control
){
sector_t *target;
mobj_t *mo;
mapthing_t *mthing;
fixed_t offset;
size_t i;
for (i = 0; i < control->numattached; ++i)
{
target = &sectors[control->attached[i]];
for (mo = target->thinglist; mo; mo = mo->snext)
{
mthing = mo->spawnpoint;
if (
mthing->type == type &&
mthing->angle == tag
){
if (( mo->flags2 & MF2_OBJECTFLIP ))
{
offset = ( mo->ceilingz - mo->info->height ) - mo->z;
mo->z = ( Floor_height(control, mo->x, mo->y) - mo->info->height ) - offset;
}
else
{
offset = mo->z - mo->floorz;
mo->z = Ceiling_height(control, mo->x, mo->y) + offset;
}
}
}
}
}
//
// SPECIAL SPAWNING
//
@ -6813,6 +6879,22 @@ void P_SpawnSpecials(INT32 fromnetsave)
}
}
/* some things have to be done after FOF spawn */
for (i = 0; i < numlines; ++i)
{
switch (lines[i].special)
{
case 80: // Raise tagged things by type to this FOF
P_RaiseTaggedThingsToFakeFloor(
( sides[lines[i].sidenum[0]].textureoffset >> FRACBITS ),
lines[i].tag,
lines[i].frontsector
);
break;
}
}
// Allocate each list
for (i = 0; i < numsectors; i++)
if(secthinkers[i].thinkers)
@ -7205,9 +7287,15 @@ static void P_SpawnScrollers(void)
{
fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling
fixed_t dy = l->dy >> SCROLL_SHIFT;
fixed_t bx = 0;/* backside variants */
fixed_t by = 0;
INT32 control = -1, accel = 0; // no control sector or acceleration
INT32 special = l->special;
INT32 s;
// These types are same as the ones they get set to except that the
// first side's sector's heights cause scrolling when they change, and
// this linedef controls the direction and speed of the scrolling. The
@ -7236,10 +7324,24 @@ static void P_SpawnScrollers(void)
control = (INT32)(sides[*l->sidenum].sector - sectors);
}
if (special == 507) // front and back scrollers
{
s = l->sidenum[0];
dx = -(sides[s].textureoffset);
dy = sides[s].rowoffset;
s = l->sidenum[1];
if (s != 0xffff)
{
bx = -(sides[s].textureoffset);
by = sides[s].rowoffset;
}
}
switch (special)
{
register INT32 s;
case 513: // scroll effect ceiling
case 533: // scroll and carry objects on ceiling
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
@ -7292,6 +7394,18 @@ static void P_SpawnScrollers(void)
CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing 2nd side!\n", sizeu1(i));
break;
case 507: // scroll front and backside of tagged lines
for (s = -1; (s = P_FindLineFromLineTag(l, s)) >= 0 ;)
{
if (s != (INT32)i)
{
Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0);
if (lines[s].sidenum[1] != 0xffff)
Add_Scroller(sc_side, bx, by, control, lines[s].sidenum[1], accel, 0);
}
}
break;
case 500: // scroll first side
Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0);
break;

View file

@ -616,6 +616,17 @@ void P_Ticker(boolean run)
G_ReadDemoTiccmd(&players[i].cmd, i);
}
// First loop: Ensure all players' distance to the finish line are all accurate
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_UpdateDistanceFromFinishLine(&players[i]);
// Second loop: Ensure all player positions reflect everyone's distances
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_KartUpdatePosition(&players[i]);
// OK! Now that we got all of that sorted, players can think!
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]);
@ -778,6 +789,17 @@ void P_PreTicker(INT32 frames)
{
P_MapStart();
// First loop: Ensure all players' distance to the finish line are all accurate
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_UpdateDistanceFromFinishLine(&players[i]);
// Second loop: Ensure all player positions reflect everyone's distances
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_KartUpdatePosition(&players[i]);
// OK! Now that we got all of that sorted, players can think!
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
{

View file

@ -7157,13 +7157,14 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled)
{
static UINT8 lookbackdelay[4] = {0,0,0,0};
static boolean lookbackactive[MAXSPLITSCREENPLAYERS];
static UINT8 lookbackdelay[MAXSPLITSCREENPLAYERS];
UINT8 num;
angle_t angle = 0, focusangle = 0, focusaiming = 0, pitch = 0;
fixed_t x, y, z, dist, distxy, distz, height, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
fixed_t x, y, z, dist, distxy, distz, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
fixed_t pan, xpan, ypan;
INT32 camrotate;
boolean camstill, lookback;
boolean camstill, lookback, lookbackdown;
UINT8 timeover;
mobj_t *mo;
fixed_t f1, f2;
@ -7343,15 +7344,19 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camstill = true;
else if (lookback || lookbackdelay[num]) // SRB2kart - Camera flipper
{
#define MAXLOOKBACKDELAY 2
camspeed = FRACUNIT;
if (lookback)
{
camrotate += 180;
lookbackdelay[num] = 2;
lookbackdelay[num] = MAXLOOKBACKDELAY;
}
else
lookbackdelay[num]--;
}
lookbackdown = (lookbackdelay[num] == MAXLOOKBACKDELAY) != lookbackactive[num];
lookbackactive[num] = (lookbackdelay[num] == MAXLOOKBACKDELAY);
#undef MAXLOOKBACKDELAY
if (mo->eflags & MFE_VERTICALFLIP)
camheight += thiscam->height;
@ -7394,8 +7399,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
thiscam->angle = angle;
}
height = camheight;
// sets ideal cam pos
dist = camdist;
@ -7404,14 +7407,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
dist += abs(thiscam->momz)/4;
if (player->karthud[khud_boostcam])
{
dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]);
height -= FixedMul(height, player->karthud[khud_boostcam]);
}
if (mo->standingslope)
{
pitch = (angle_t)FixedMul(P_ReturnThrustX(mo, player->frameangle - mo->standingslope->xydirection, FRACUNIT), (fixed_t)mo->standingslope->zangle);
pitch = (angle_t)FixedMul(P_ReturnThrustX(mo, thiscam->angle - mo->standingslope->xydirection, FRACUNIT), (fixed_t)mo->standingslope->zangle);
if (mo->eflags & MFE_VERTICALFLIP)
{
if (pitch >= ANGLE_180)
@ -7434,8 +7434,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
else
distxy = dist;
distz = -FixedMul(dist, FINESINE((pitch>>ANGLETOFINESHIFT) & FINEMASK));
if (r_splitscreen == 1) // 2 player is weird, this helps keep players on screen
distz = 3*distz/5;
x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy);
y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy);
@ -7476,9 +7474,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
pviewheight = FixedMul(32<<FRACBITS, mo->scale);
if (mo->eflags & MFE_VERTICALFLIP)
z = mo->z + mo->height - pviewheight - camheight + distz;
{
distz = min(-camheight, distz);
z = mo->z + mo->height - pviewheight + distz;
}
else
z = mo->z + pviewheight + camheight + distz;
{
distz = max(camheight, distz);
z = mo->z + pviewheight + distz;
}
#ifndef NOCLIPCAM // Disable all z-clipping for noclip cam
// move camera down to move under lower ceilings
@ -7724,13 +7728,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - P_GetPlayerHeight(player));
if (thiscam->pitch < ANGLE_180 && thiscam->pitch > angle)
angle = thiscam->pitch;
angle += (thiscam->pitch - angle)/2;
}
else
{
angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + P_GetPlayerHeight(player));
if (thiscam->pitch >= ANGLE_180 && thiscam->pitch < angle)
angle = thiscam->pitch;
angle -= (angle - thiscam->pitch)/2;
}
if (player->playerstate != PST_DEAD && !((player->pflags & PF_NIGHTSMODE) && player->exiting))
@ -7773,6 +7777,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
thiscam->aiming = ANGLE_22h;
}
if (lookbackdown)
P_MoveChaseCamera(player, thiscam, false);
return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming);
}

View file

@ -22,7 +22,7 @@
#include "w_wad.h"
#include "z_zone.h"
#include "p_setup.h" // levelflats
#include "v_video.h" // pLocalPalette
#include "v_video.h" // pMasterPalette
#include "dehacked.h"
#if defined (_WIN32) || defined (_WIN32_WCE)
@ -1192,7 +1192,7 @@ void R_MakeInvertmap(void)
INT32 R_CreateColormap(char *p1, char *p2, char *p3)
{
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
double maskamt = 0, othermask = 0;
double r, g, b, cbrightness, maskamt = 0, othermask = 0;
int mask, fog = 0;
size_t mapnum = num_extra_colormaps;
size_t i;
@ -1300,6 +1300,32 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
num_extra_colormaps++;
if (rendermode == render_soft)
{
for (i = 0; i < 256; i++)
{
r = pMasterPalette[i].s.red;
g = pMasterPalette[i].s.green;
b = pMasterPalette[i].s.blue;
cbrightness = sqrt((r*r) + (g*g) + (b*b));
map[i][0] = (cbrightness * cmaskr) + (r * othermask);
if (map[i][0] > 255.0l)
map[i][0] = 255.0l;
deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist;
map[i][1] = (cbrightness * cmaskg) + (g * othermask);
if (map[i][1] > 255.0l)
map[i][1] = 255.0l;
deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist;
map[i][2] = (cbrightness * cmaskb) + (b * othermask);
if (map[i][2] > 255.0l)
map[i][2] = 255.0l;
deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist;
}
}
foundcolormaps[mapnum] = LUMPERROR;
// aligned on 8 bit for asm code
@ -1313,7 +1339,6 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
if (rendermode == render_soft)
{
double r, g, b, cbrightness;
int p;
lighttable_t *colormap_p;
@ -1324,9 +1349,9 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
// map[i]'s values are decremented by after each use
for (i = 0; i < 256; i++)
{
r = pLocalPalette[i].s.red;
g = pLocalPalette[i].s.green;
b = pLocalPalette[i].s.blue;
r = pMasterPalette[i].s.red;
g = pMasterPalette[i].s.green;
b = pMasterPalette[i].s.blue;
cbrightness = sqrt((r*r) + (g*g) + (b*b));
map[i][0] = (cbrightness * cmaskr) + (r * othermask);
@ -1402,16 +1427,20 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
// Thanks to quake2 source!
// utils3/qdata/images.c
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette)
{
int dr, dg, db;
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
// Use master palette if none specified
if (palette == NULL)
palette = pMasterPalette;
for (i = 0; i < 256; i++)
{
dr = r - pLocalPalette[i].s.red;
dg = g - pLocalPalette[i].s.green;
db = b - pLocalPalette[i].s.blue;
dr = r - palette[i].s.red;
dg = g - palette[i].s.green;
db = b - palette[i].s.blue;
distortion = dr*dr + dg*dg + db*db;
if (distortion < bestdistortion)
{

View file

@ -99,6 +99,9 @@ void R_MakeInvertmap(void);
#endif
const char *R_ColormapNameForNum(INT32 num);
UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette);
#define NearestColor(r, g, b) NearestPaletteColor(r, g, b, NULL)
extern INT32 numtextures;
#endif

View file

@ -841,7 +841,7 @@ static void R_SetupFreelook(void)
// clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...)
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
dy = AIMINGTODY(aimingangle) * viewheight/BASEVIDHEIGHT;
dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH;
yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
}
centery = (viewheight/2) + dy;

View file

@ -219,7 +219,7 @@ char *GetPlayerFacePic(INT32 skinnum);
// Future: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@ ]]
FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
{
#if 1 // 2.1 compat
#if 0 // 2.1 compat
return 'A' + frame;
#else
if (frame < 26) return 'A' + frame;
@ -233,7 +233,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
{
#if 1 // 2.1 compat
#if 0 // 2.1 compat
if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead
return cn - 'A';
#else

View file

@ -213,6 +213,7 @@ int main(int argc, char **argv)
I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno));
}
#else/*__unix__*/
(void)link;
logstream = fopen("latest-log.txt", "wt+");
#endif/*__unix__*/
}

View file

@ -3282,7 +3282,7 @@ static void Shittylogcopy(void)
{
char buf[8192];
FILE *fp;
int n;
size_t n;
if (fseek(logstream, 0, SEEK_SET) == -1)
{
Shittycopyerror("fseek");

View file

@ -1647,6 +1647,7 @@ INT32 VID_SetMode(INT32 modeNum)
//Impl_SetWindowName("SRB2Kart "VERSIONSTRING);
SDLSetMode(vid.width, vid.height, USE_FULLSCREEN);
Impl_VideoSetupBuffer();
if (rendermode == render_soft)
{
@ -1655,8 +1656,6 @@ INT32 VID_SetMode(INT32 modeNum)
SDL_FreeSurface(bufSurface);
bufSurface = NULL;
}
Impl_VideoSetupBuffer();
}
return SDL_TRUE;
@ -1779,7 +1778,7 @@ static void Impl_VideoSetupSDLBuffer(void)
static void Impl_VideoSetupBuffer(void)
{
// Set up game's software render buffer
if (rendermode == render_soft)
//if (rendermode == render_soft)
{
vid.rowbytes = vid.width * vid.bpp;
vid.direct = NULL;

View file

@ -203,7 +203,7 @@ void ST_Ticker(void)
}
// 0 is default, any others are special palettes.
static INT32 st_palette = 0;
INT32 st_palette = 0;
void ST_doPaletteStuff(void)
{

View file

@ -61,6 +61,7 @@ boolean ST_SameTeam(player_t *a, player_t *b);
//--------------------
extern boolean st_overlay; // sb overlay on or off when fullscreen
extern INT32 st_palette; // 0 is default, any others are special palettes.
extern lumpnum_t st_borderpatchnum;
// patches, also used in intermission

View file

@ -38,13 +38,39 @@ UINT8 *screens[5];
// screens[3] = fade screen start
// screens[4] = fade screen end, postimage tempoarary buffer
static CV_PossibleValue_t gamma_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
static void CV_usegamma_OnChange(void);
consvar_t cv_ticrate = {"showfps", "No", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ticrate = {"showfps", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usegamma = {"gamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_usegamma_OnChange, 0, NULL, NULL, 0, 0, NULL};
static void CV_palette_OnChange(void);
consvar_t cv_allcaps = {"allcaps", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t gamma_cons_t[] = {{-15, "MIN"}, {5, "MAX"}, {0, NULL}};
consvar_t cv_globalgamma = {"gamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t saturation_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
consvar_t cv_globalsaturation = {"saturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
#define huecoloursteps 4
static CV_PossibleValue_t hue_cons_t[] = {{0, "MIN"}, {(huecoloursteps*6)-1, "MAX"}, {0, NULL}};
consvar_t cv_rhue = {"rhue", "0", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_yhue = {"yhue", "4", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghue = {"ghue", "8", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chue = {"chue", "12", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_bhue = {"bhue", "16", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mhue = {"mhue", "20", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rgamma = {"rgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ygamma = {"ygamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ggamma = {"ggamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cgamma = {"cgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_bgamma = {"bgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mgamma = {"mgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rsaturation = {"rsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ysaturation = {"ysaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gsaturation = {"gsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_csaturation = {"csaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_bsaturation = {"bsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_msaturation = {"msaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t constextsize_cons_t[] = {
{V_NOSCALEPATCH, "Small"}, {V_SMALLSCALEPATCH, "Medium"}, {V_MEDSCALEPATCH, "Large"}, {0, "Huge"},
@ -84,112 +110,261 @@ consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE,
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
const UINT8 gammatable[5][256] =
{
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,
97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255},
{2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23,24,25,26,27,29,30,31,
32,33,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,54,55,
56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,
78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,
99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,
115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,129,
130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
146,147,148,148,149,150,151,152,153,154,155,156,157,158,159,160,
161,162,163,163,164,165,166,167,168,169,170,171,172,173,174,175,
175,176,177,178,179,180,181,182,183,184,185,186,186,187,188,189,
190,191,192,193,194,195,196,196,197,198,199,200,201,202,203,204,
205,205,206,207,208,209,210,211,212,213,214,214,215,216,217,218,
219,220,221,222,222,223,224,225,226,227,228,229,230,230,231,232,
233,234,235,236,237,237,238,239,240,241,242,243,244,245,245,246,
247,248,249,250,251,252,252,253,254,255},
{4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32,33,35,36,38,39,40,42,
43,45,46,47,48,50,51,52,54,55,56,57,59,60,61,62,63,65,66,67,68,69,
70,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,
94,95,96,97,98,100,101,102,103,104,105,106,107,108,109,110,111,112,
113,114,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
129,130,131,132,133,133,134,135,136,137,138,139,140,141,142,143,144,
144,145,146,147,148,149,150,151,152,153,153,154,155,156,157,158,159,
160,160,161,162,163,164,165,166,166,167,168,169,170,171,172,172,173,
174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,187,188,
188,189,190,191,192,193,193,194,195,196,197,197,198,199,200,201,201,
202,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,
216,217,217,218,219,220,221,221,222,223,224,224,225,226,227,228,228,
229,230,231,231,232,233,234,235,235,236,237,238,238,239,240,241,241,
242,243,244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,
255},
{8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45,47,49,50,52,53,55,
57,58,60,61,63,64,65,67,68,70,71,72,74,75,76,77,79,80,81,82,84,85,
86,87,88,90,91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,
125,126,127,128,129,130,131,132,133,134,135,135,136,137,138,139,140,
141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,
155,156,157,158,159,160,160,161,162,163,164,165,165,166,167,168,169,
169,170,171,172,173,173,174,175,176,176,177,178,179,180,180,181,182,
183,183,184,185,186,186,187,188,189,189,190,191,192,192,193,194,195,
195,196,197,197,198,199,200,200,201,202,202,203,204,205,205,206,207,
207,208,209,210,210,211,212,212,213,214,214,215,216,216,217,218,219,
219,220,221,221,222,223,223,224,225,225,226,227,227,228,229,229,230,
231,231,232,233,233,234,235,235,236,237,237,238,238,239,240,240,241,
242,242,243,244,244,245,246,246,247,247,248,249,249,250,251,251,252,
253,253,254,254,255},
{16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64,66,68,69,71,73,75,76,
78,80,81,83,84,86,87,89,90,92,93,94,96,97,98,100,101,102,103,105,106,
107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,
125,126,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,
156,157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169,
169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180,181,
182,182,183,184,184,185,186,187,187,188,189,189,190,191,191,192,193,
193,194,195,195,196,196,197,198,198,199,200,200,201,202,202,203,203,
204,205,205,206,207,207,208,208,209,210,210,211,211,212,213,213,214,
214,215,216,216,217,217,218,219,219,220,220,221,221,222,223,223,224,
224,225,225,226,227,227,228,228,229,229,230,230,231,232,232,233,233,
234,234,235,235,236,236,237,237,238,239,239,240,240,241,241,242,242,
243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,
251,252,252,253,254,254,255,255}
};
// local copy of the palette for V_GetColor()
RGBA_t *pLocalPalette = NULL;
RGBA_t *pMasterPalette = NULL;
/*
The following was an extremely helpful resource when developing my Colour Cube LUT.
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter24.html
Please check it out if you're trying to maintain this.
toast 18/04/17
*/
float Cubepal[2][2][2][3];
// returns whether to apply cube, selectively avoiding expensive operations
static boolean InitCube(void)
{
boolean apply = false;
UINT8 q;
float working[2][2][2][3] = // the initial positions of the corners of the colour cube!
{
{
{
{0.0, 0.0, 0.0}, // black corner
{0.0, 0.0, 1.0} // blue corner
},
{
{0.0, 1.0, 0.0}, // green corner
{0.0, 1.0, 1.0} // cyan corner
}
},
{
{
{1.0, 0.0, 0.0}, // red corner
{1.0, 0.0, 1.0} // magenta corner
},
{
{1.0, 1.0, 0.0}, // yellow corner
{1.0, 1.0, 1.0} // white corner
}
}
};
float desatur[3]; // grey
float globalgammamul, globalgammaoffs;
boolean doinggamma;
#define diffcons(cv) (cv.value != atoi(cv.defaultvalue))
doinggamma = diffcons(cv_globalgamma);
#define gammascale 8
globalgammamul = (cv_globalgamma.value ? ((255 - (gammascale*abs(cv_globalgamma.value)))/255.0) : 1.0);
globalgammaoffs = ((cv_globalgamma.value > 0) ? ((gammascale*cv_globalgamma.value)/255.0) : 0.0);
desatur[0] = desatur[1] = desatur[2] = globalgammaoffs + (0.33*globalgammamul);
if (doinggamma
|| diffcons(cv_rhue)
|| diffcons(cv_yhue)
|| diffcons(cv_ghue)
|| diffcons(cv_chue)
|| diffcons(cv_bhue)
|| diffcons(cv_mhue)
|| diffcons(cv_rgamma)
|| diffcons(cv_ygamma)
|| diffcons(cv_ggamma)
|| diffcons(cv_cgamma)
|| diffcons(cv_bgamma)
|| diffcons(cv_mgamma)) // set the gamma'd/hued positions (saturation is done later)
{
float mod, tempgammamul, tempgammaoffs;
apply = true;
working[0][0][0][0] = working[0][0][0][1] = working[0][0][0][2] = globalgammaoffs;
working[1][1][1][0] = working[1][1][1][1] = working[1][1][1][2] = globalgammaoffs+globalgammamul;
#define dohue(hue, gamma, loc) \
tempgammamul = (gamma ? ((255 - (gammascale*abs(gamma)))/255.0)*globalgammamul : globalgammamul);\
tempgammaoffs = ((gamma > 0) ? ((gammascale*gamma)/255.0) + globalgammaoffs : globalgammaoffs);\
mod = ((hue % huecoloursteps)*(tempgammamul)/huecoloursteps);\
switch (hue/huecoloursteps)\
{\
case 0:\
default:\
loc[0] = tempgammaoffs+tempgammamul;\
loc[1] = tempgammaoffs+mod;\
loc[2] = tempgammaoffs;\
break;\
case 1:\
loc[0] = tempgammaoffs+tempgammamul-mod;\
loc[1] = tempgammaoffs+tempgammamul;\
loc[2] = tempgammaoffs;\
break;\
case 2:\
loc[0] = tempgammaoffs;\
loc[1] = tempgammaoffs+tempgammamul;\
loc[2] = tempgammaoffs+mod;\
break;\
case 3:\
loc[0] = tempgammaoffs;\
loc[1] = tempgammaoffs+tempgammamul-mod;\
loc[2] = tempgammaoffs+tempgammamul;\
break;\
case 4:\
loc[0] = tempgammaoffs+mod;\
loc[1] = tempgammaoffs;\
loc[2] = tempgammaoffs+tempgammamul;\
break;\
case 5:\
loc[0] = tempgammaoffs+tempgammamul;\
loc[1] = tempgammaoffs;\
loc[2] = tempgammaoffs+tempgammamul-mod;\
break;\
}
dohue(cv_rhue.value, cv_rgamma.value, working[1][0][0]);
dohue(cv_yhue.value, cv_ygamma.value, working[1][1][0]);
dohue(cv_ghue.value, cv_ggamma.value, working[0][1][0]);
dohue(cv_chue.value, cv_cgamma.value, working[0][1][1]);
dohue(cv_bhue.value, cv_bgamma.value, working[0][0][1]);
dohue(cv_mhue.value, cv_mgamma.value, working[1][0][1]);
#undef dohue
}
#define dosaturation(a, e) a = ((1 - work)*e + work*a)
#define docvsat(cv_sat, hue, gamma, r, g, b) \
if diffcons(cv_sat)\
{\
float work, mod, tempgammamul, tempgammaoffs;\
apply = true;\
work = (cv_sat.value/10.0);\
mod = ((hue % huecoloursteps)*(1.0)/huecoloursteps);\
if (hue & huecoloursteps)\
mod = 2-mod;\
else\
mod += 1;\
tempgammamul = (gamma ? ((255 - (gammascale*abs(gamma)))/255.0)*globalgammamul : globalgammamul);\
tempgammaoffs = ((gamma > 0) ? ((gammascale*gamma)/255.0) + globalgammaoffs : globalgammaoffs);\
for (q = 0; q < 3; q++)\
dosaturation(working[r][g][b][q], (tempgammaoffs+(desatur[q]*mod*tempgammamul)));\
}
docvsat(cv_rsaturation, cv_rhue.value, cv_rgamma.value, 1, 0, 0);
docvsat(cv_ysaturation, cv_yhue.value, cv_ygamma.value, 1, 1, 0);
docvsat(cv_gsaturation, cv_ghue.value, cv_ggamma.value, 0, 1, 0);
docvsat(cv_csaturation, cv_chue.value, cv_cgamma.value, 0, 1, 1);
docvsat(cv_bsaturation, cv_bhue.value, cv_bgamma.value, 0, 0, 1);
docvsat(cv_msaturation, cv_mhue.value, cv_mgamma.value, 1, 0, 1);
#undef gammascale
if diffcons(cv_globalsaturation)
{
float work = (cv_globalsaturation.value/10.0);
apply = true;
for (q = 0; q < 3; q++)
{
dosaturation(working[1][0][0][q], desatur[q]);
dosaturation(working[0][1][0][q], desatur[q]);
dosaturation(working[0][0][1][q], desatur[q]);
dosaturation(working[1][1][0][q], 2*desatur[q]);
dosaturation(working[0][1][1][q], 2*desatur[q]);
dosaturation(working[1][0][1][q], 2*desatur[q]);
}
}
#undef dosaturation
#undef diffcons
if (!apply)
return false;
#define dowork(i, j, k, l) \
if (working[i][j][k][l] > 1.0)\
working[i][j][k][l] = 1.0;\
else if (working[i][j][k][l] < 0.0)\
working[i][j][k][l] = 0.0;\
Cubepal[i][j][k][l] = working[i][j][k][l]
for (q = 0; q < 3; q++)
{
dowork(0, 0, 0, q);
dowork(1, 0, 0, q);
dowork(0, 1, 0, q);
dowork(1, 1, 0, q);
dowork(0, 0, 1, q);
dowork(1, 0, 1, q);
dowork(0, 1, 1, q);
dowork(1, 1, 1, q);
}
#undef dowork
return true;
}
// keep a copy of the palette so that we can get the RGB value for a color index at any time.
static void LoadPalette(const char *lumpname)
{
const UINT8 *usegamma = gammatable[cv_usegamma.value];
boolean cube = InitCube();
lumpnum_t lumpnum = W_GetNumForName(lumpname);
size_t i, palsize = W_LumpLength(lumpnum)/3;
UINT8 *pal;
Z_Free(pLocalPalette);
Z_Free(pMasterPalette);
pLocalPalette = Z_Malloc(sizeof (*pLocalPalette)*palsize, PU_STATIC, NULL);
pMasterPalette = Z_Malloc(sizeof (*pMasterPalette)*palsize, PU_STATIC, NULL);
pal = W_CacheLumpNum(lumpnum, PU_CACHE);
for (i = 0; i < palsize; i++)
{
pLocalPalette[i].s.red = usegamma[*pal++];
pLocalPalette[i].s.green = usegamma[*pal++];
pLocalPalette[i].s.blue = usegamma[*pal++];
pLocalPalette[i].s.alpha = 0xFF;
pMasterPalette[i].s.red = pLocalPalette[i].s.red = *pal++;
pMasterPalette[i].s.green = pLocalPalette[i].s.green = *pal++;
pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = *pal++;
pMasterPalette[i].s.alpha = pLocalPalette[i].s.alpha = 0xFF;
// lerp of colour cubing!
if (cube)
{
float working[4][3];
float linear;
UINT8 q;
linear = (pLocalPalette[i].s.red/255.0);
#define dolerp(e1, e2) ((1 - linear)*e1 + linear*e2)
for (q = 0; q < 3; q++)
{
working[0][q] = dolerp(Cubepal[0][0][0][q], Cubepal[1][0][0][q]);
working[1][q] = dolerp(Cubepal[0][1][0][q], Cubepal[1][1][0][q]);
working[2][q] = dolerp(Cubepal[0][0][1][q], Cubepal[1][0][1][q]);
working[3][q] = dolerp(Cubepal[0][1][1][q], Cubepal[1][1][1][q]);
}
linear = (pLocalPalette[i].s.green/255.0);
for (q = 0; q < 3; q++)
{
working[0][q] = dolerp(working[0][q], working[1][q]);
working[1][q] = dolerp(working[2][q], working[3][q]);
}
linear = (pLocalPalette[i].s.blue/255.0);
for (q = 0; q < 3; q++)
{
working[0][q] = 255*dolerp(working[0][q], working[1][q]);
if (working[0][q] > 255.0)
working[0][q] = 255.0;
else if (working[0][q] < 0.0)
working[0][q] = 0.0;
}
#undef dolerp
pLocalPalette[i].s.red = (UINT8)(working[0][0]);
pLocalPalette[i].s.green = (UINT8)(working[0][1]);
pLocalPalette[i].s.blue = (UINT8)(working[0][2]);
}
}
}
@ -254,7 +429,7 @@ void V_SetPaletteLump(const char *pal)
#endif
}
static void CV_usegamma_OnChange(void)
static void CV_palette_OnChange(void)
{
// reload palette
LoadMapPalette();
@ -2668,6 +2843,28 @@ Unoptimized version
#endif
}
// Generates a color look-up table
// which has up to 64 colors at each channel
// (see the defines in v_video.h)
UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE];
void InitColorLUT(RGBA_t *palette)
{
UINT8 r, g, b;
static boolean clutinit = false;
static RGBA_t *lastpalette = NULL;
if ((!clutinit) || (lastpalette != palette))
{
for (r = 0; r < CLUTSIZE; r++)
for (g = 0; g < CLUTSIZE; g++)
for (b = 0; b < CLUTSIZE; b++)
colorlookup[r][g][b] = NearestPaletteColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS, palette);
clutinit = true;
lastpalette = palette;
}
}
// V_Init
// old software stuff, buffers are allocated at video mode setup
// here we set the screens[x] pointers accordingly
@ -2679,13 +2876,9 @@ void V_Init(void)
const INT32 screensize = vid.rowbytes * vid.height;
LoadMapPalette();
// hardware modes do not use screens[] pointers
for (i = 0; i < NUMSCREENS; i++)
screens[i] = NULL;
if (rendermode != render_soft)
{
return; // be sure to cause a NULL read/write error so we detect it, in case of..
}
// start address of NUMSCREENS * width*height vidbuffers
if (base)

View file

@ -27,12 +27,24 @@
extern UINT8 *screens[5];
extern const UINT8 gammatable[5][256];
extern consvar_t cv_ticrate, cv_usegamma, cv_allcaps, cv_constextsize;
extern consvar_t cv_ticrate, cv_constextsize,\
cv_globalgamma, cv_globalsaturation, \
cv_rhue, cv_yhue, cv_ghue, cv_chue, cv_bhue, cv_mhue,\
cv_rgamma, cv_ygamma, cv_ggamma, cv_cgamma, cv_bgamma, cv_mgamma, \
cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, cv_msaturation;
// Allocates buffer screens, call before R_Init.
void V_Init(void);
// Color look-up table
#define COLORBITS 6
#define SHIFTCOLORBITS (8-COLORBITS)
#define CLUTSIZE (1<<COLORBITS)
extern UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE];
void InitColorLUT(RGBA_t *palette);
// Set the current RGB palette lookup to use for palettized graphics
void V_SetPalette(INT32 palettenum);
@ -42,6 +54,7 @@ const char *R_GetPalname(UINT16 num);
const char *GetPalette(void);
extern RGBA_t *pLocalPalette;
extern RGBA_t *pMasterPalette;
extern UINT8 hudtrans;

View file

@ -787,7 +787,7 @@ void Y_Ticker(void)
//
static void Y_UpdateRecordReplays(void)
{
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
const size_t glen = strlen(srb2home)+1+strlen("media")+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath;
char lastdemo[256], bestdemo[256];
UINT8 earnedEmblems;
@ -823,13 +823,14 @@ static void Y_UpdateRecordReplays(void)
G_SetDemoTime(players[consoleplayer].realtime, bestlap);
G_CheckDemoStatus();
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s",
srb2home, timeattackfolder);
M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755);
if ((gpath = malloc(glen)) == NULL)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string);
if (FIL_FileExists(lastdemo))