Merge branch 'master' into leveltitle-tinkering

# Conflicts:
#	src/hu_stuff.h
#	src/st_stuff.c
This commit is contained in:
Monster Iestyn 2018-06-14 21:26:44 +01:00
commit fe6b47dc00
57 changed files with 4115 additions and 2512 deletions

View File

@ -226,13 +226,9 @@ static void CONS_Bind_f(void)
// Font colormap colors
// TODO: This could probably be improved somehow...
// These colormaps are 99% identical, with just a few changed bytes
UINT8 *yellowmap;
UINT8 *purplemap;
UINT8 *lgreenmap;
UINT8 *bluemap;
UINT8 *graymap;
UINT8 *redmap;
UINT8 *orangemap;
// This could EASILY be handled by modifying a centralised colormap
// for software depending on the prior state - but yknow, OpenGL...
UINT8 *yellowmap, *magentamap, *lgreenmap, *bluemap, *graymap, *redmap, *orangemap, *skymap, *purplemap, *aquamap, *peridotmap, *azuremap, *brownmap, *rosymap, *invertmap;
// Console BG color
UINT8 *consolebgmap = NULL;
@ -280,45 +276,55 @@ static void CONS_backcolor_Change(void)
static void CON_SetupColormaps(void)
{
INT32 i;
UINT8 *memorysrc = (UINT8 *)Z_Malloc((256*15), PU_STATIC, NULL);
yellowmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
graymap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
purplemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
lgreenmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
bluemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
redmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
orangemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
magentamap = memorysrc;
yellowmap = (magentamap+256);
lgreenmap = (yellowmap+256);
bluemap = (lgreenmap+256);
redmap = (bluemap+256);
graymap = (redmap+256);
orangemap = (graymap+256);
skymap = (orangemap+256);
purplemap = (skymap+256);
aquamap = (purplemap+256);
peridotmap = (aquamap+256);
azuremap = (peridotmap+256);
brownmap = (azuremap+256);
rosymap = (brownmap+256);
invertmap = (rosymap+256);
// setup the other colormaps, for console text
// these don't need to be aligned, unless you convert the
// V_DrawMappedPatch() into optimised asm.
for (i = 0; i < 256; i++)
{
yellowmap[i] = (UINT8)i; // remap each color to itself...
graymap[i] = (UINT8)i;
purplemap[i] = (UINT8)i;
lgreenmap[i] = (UINT8)i;
bluemap[i] = (UINT8)i;
redmap[i] = (UINT8)i;
orangemap[i] = (UINT8)i;
}
for (i = 0; i < (256*15); i++, ++memorysrc)
*memorysrc = (UINT8)(i & 0xFF); // remap each color to itself...
yellowmap[3] = (UINT8)73;
yellowmap[9] = (UINT8)66;
purplemap[3] = (UINT8)184;
purplemap[9] = (UINT8)186;
lgreenmap[3] = (UINT8)98;
lgreenmap[9] = (UINT8)106;
bluemap[3] = (UINT8)147;
bluemap[9] = (UINT8)158;
graymap[3] = (UINT8)10;
graymap[9] = (UINT8)15;
redmap[3] = (UINT8)210;
redmap[9] = (UINT8)32;
orangemap[3] = (UINT8)52;
orangemap[9] = (UINT8)57;
#define colset(map, a, b, c) \
map[1] = (UINT8)a;\
map[3] = (UINT8)b;\
map[9] = (UINT8)c
colset(magentamap, 177, 178, 184);
colset(yellowmap, 82, 73, 66);
colset(lgreenmap, 97, 98, 106);
colset(bluemap, 146, 147, 155);
colset(redmap, 210, 32, 39);
colset(graymap, 8, 10, 15);
colset(orangemap, 51, 52, 57);
colset(skymap, 129, 130, 133);
colset(purplemap, 160, 161, 163);
colset(aquamap, 120, 121, 123);
colset(peridotmap, 88, 188, 190);
colset(azuremap, 144, 145, 170);
colset(brownmap, 219, 221, 224);
colset(rosymap, 200, 201, 203);
colset(invertmap, 27, 26, 22);
invertmap[26] = (UINT8)3;
#undef colset
// Init back colormap
CON_SetupBackColormap();
@ -839,8 +845,9 @@ boolean CON_Responder(event_t *ev)
return true;
}
// don't eat the key
return false;
// ...why shouldn't it eat the key? if it doesn't, it just means you
// can control Sonic from the console, which is silly
return true; //return false;
}
// command completion forward (tab) and backward (shift-tab)
@ -1039,7 +1046,7 @@ boolean CON_Responder(event_t *ev)
// enter a char into the command prompt
if (key < 32 || key > 127)
return false;
return true; // even if key can't be printed, eat it anyway
// add key to cmd line here
if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers

View File

@ -34,7 +34,7 @@ extern UINT32 con_scalefactor; // console text scale factor
extern consvar_t cons_backcolor;
extern UINT8 *yellowmap, *purplemap, *lgreenmap, *bluemap, *graymap, *redmap, *orangemap;
extern UINT8 *yellowmap, *magentamap, *lgreenmap, *bluemap, *graymap, *redmap, *orangemap, *skymap, *purplemap, *aquamap, *peridotmap, *azuremap, *brownmap, *rosymap, *invertmap;
// Console bg color (auto updated to match)
extern UINT8 *consolebgmap;

View File

@ -1125,7 +1125,7 @@ static inline void CL_DrawConnectionStatus(void)
INT32 ccstime = I_GetTime();
// Draw background fade
V_DrawFadeScreen();
V_DrawFadeScreen(0xFF00, 16);
// Draw the bottom box.
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
@ -1173,22 +1173,37 @@ static inline void CL_DrawConnectionStatus(void)
if (lastfilenum != -1)
{
INT32 dldlength;
static char tempname[32];
static char tempname[28];
fileneeded_t *file = &fileneeded[lastfilenum];
char *filename = file->filename;
Net_GetNetStat();
dldlength = (INT32)((fileneeded[lastfilenum].currentsize/(double)fileneeded[lastfilenum].totalsize) * 256);
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
if (dldlength > 256)
dldlength = 256;
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 96);
memset(tempname, 0, sizeof(tempname));
nameonly(strncpy(tempname, fileneeded[lastfilenum].filename, 31));
// offset filename to just the name only part
filename += strlen(filename) - nameonlylength(filename);
if (strlen(filename) > sizeof(tempname)-1) // too long to display fully
{
size_t endhalfpos = strlen(filename)-10;
// display as first 14 chars + ... + last 10 chars
// which should add up to 27 if our math(s) is correct
snprintf(tempname, sizeof(tempname), "%.14s...%.10s", filename, filename+endhalfpos);
}
else // we can copy the whole thing in safely
{
strncpy(tempname, filename, sizeof(tempname)-1);
}
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP,
va(M_GetText("Downloading \"%s\""), tempname));
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,fileneeded[lastfilenum].totalsize>>10));
va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10));
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
va("%3.1fK/s ", ((double)getbps)/1024));
}
@ -2239,7 +2254,7 @@ static void Command_connect(void)
// Assume we connect directly.
boolean viams = false;
if (COM_Argc() < 2)
if (COM_Argc() < 2 || *COM_Argv(1) == 0)
{
CONS_Printf(M_GetText(
"Connect <serveraddress> (port): connect to a server\n"

View File

@ -734,11 +734,6 @@ void D_StartTitle(void)
CON_ToggleOff();
// Reset the palette
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPaletteColor(0);
else
#endif
if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");
}
@ -1049,7 +1044,7 @@ void D_SRB2Main(void)
// add any files specified on the command line with -file wadfile
// to the wad list
if (!(M_CheckParm("-connect")))
if (!(M_CheckParm("-connect") && !M_CheckParm("-server")))
{
if (M_CheckParm("-file"))
{
@ -1204,7 +1199,15 @@ void D_SRB2Main(void)
R_Init();
// setting up sound
CONS_Printf("S_Init(): Setting up sound.\n");
if (dedicated)
{
nosound = true;
nomidimusic = nodigimusic = true;
}
else
{
CONS_Printf("S_Init(): Setting up sound.\n");
}
if (M_CheckParm("-nosound"))
nosound = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
@ -1316,7 +1319,7 @@ void D_SRB2Main(void)
}
}
if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect"))
if (autostart || netgame)
{
gameaction = ga_nothing;
@ -1350,8 +1353,7 @@ void D_SRB2Main(void)
}
}
if (server && !M_CheckParm("+map") && !M_CheckParm("+connect")
&& !M_CheckParm("-connect"))
if (server && !M_CheckParm("+map"))
{
// Prevent warping to nonexistent levels
if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR)

View File

@ -309,9 +309,12 @@ consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL,
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Normal"}, {1, "Tics"}, {2, "Centiseconds"}, {3, "Mania"}, {0, NULL}};
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Normal"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}};
consvar_t cv_timetic = {"timerres", "Normal", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}};
consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t pointlimit_cons_t[] = {{0, "MIN"}, {999999990, "MAX"}, {0, NULL}};
@ -670,6 +673,7 @@ void D_RegisterClientCommands(void)
// HUD
CV_RegisterVar(&cv_timetic);
CV_RegisterVar(&cv_powerupdisplay);
CV_RegisterVar(&cv_itemfinder);
CV_RegisterVar(&cv_showinputjoy);

View File

@ -950,15 +950,37 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
return FS_FOUND; // will never happen, but makes the compiler shut up
}
// Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
{
filestatus_t homecheck = filesearch(filename, srb2home, wantedmd5sum, false, 10);
if (homecheck == FS_FOUND)
return filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
homecheck = filesearch(filename, srb2path, wantedmd5sum, false, 10);
if (homecheck == FS_FOUND)
return filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
// first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
return filesearch(filename, ".", wantedmd5sum, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5
badmd5 = true;
// if not found at all, just move on without doing anything
// next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5
badmd5 = true;
// if not found at all, just move on without doing anything
// finally check "." directory
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
}

View File

@ -1584,6 +1584,10 @@ static void readhuditem(MYFILE *f, INT32 num)
{
hudinfo[num].y = i;
}
else if (fastcmp(word, "F"))
{
hudinfo[num].f = i;
}
else
deh_warning("Level header %d: unknown word '%s'", num, word);
}
@ -1819,7 +1823,6 @@ static void readframe(MYFILE *f, INT32 num)
char *word1;
char *word2 = NULL;
char *tmp;
INT32 j;
do
{
@ -1834,16 +1837,6 @@ static void readframe(MYFILE *f, INT32 num)
if (s == tmp)
continue; // Skip comment lines, but don't break.
for (j = 0; s[j] != '\n'; j++)
{
if (s[j] == '=')
{
j += 2;
j = atoi(&s[j]);
break;
}
}
word1 = strtok(s, " ");
if (word1)
strupr(word1);
@ -4528,6 +4521,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BOXSPARKLE1",
"S_BOXSPARKLE2",
"S_BOXSPARKLE3",
"S_BOXSPARKLE4",
"S_BOX_FLICKER",
"S_BOX_POP1",
@ -5021,6 +5015,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ARMF14",
"S_ARMF15",
"S_ARMF16",
"S_ARMF17",
"S_ARMF18",
"S_ARMF19",
"S_ARMF20",
"S_ARMF21",
"S_ARMF22",
"S_ARMF23",
"S_ARMF24",
"S_ARMF25",
"S_ARMF26",
"S_ARMF27",
"S_ARMF28",
"S_ARMF29",
"S_ARMF30",
"S_ARMF31",
"S_ARMF32",
"S_ARMB1",
"S_ARMB2",
@ -5038,6 +5048,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ARMB14",
"S_ARMB15",
"S_ARMB16",
"S_ARMB17",
"S_ARMB18",
"S_ARMB19",
"S_ARMB20",
"S_ARMB21",
"S_ARMB22",
"S_ARMB23",
"S_ARMB24",
"S_ARMB25",
"S_ARMB26",
"S_ARMB27",
"S_ARMB28",
"S_ARMB29",
"S_ARMB30",
"S_ARMB31",
"S_ARMB32",
"S_WIND1",
"S_WIND2",
@ -5518,8 +5544,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Got Flag Sign
"S_GOTFLAG",
"S_GOTREDFLAG",
"S_GOTBLUEFLAG",
"S_CORK",
@ -5859,6 +5883,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_XPLD_FLICKY",
"S_XPLD1",
"S_XPLD2",
"S_XPLD3",
"S_XPLD4",
"S_XPLD5",
"S_XPLD6",
"S_XPLD_EGGTRAP",
// Underwater Explosion
@ -6526,7 +6554,6 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
"SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
"MACEROTATE", // Thinker calls P_MaceRotate around tracer
NULL
};
@ -6799,32 +6826,22 @@ static const char *const POWERS_LIST[] = {
};
static const char *const HUDITEMS_LIST[] = {
"LIVESNAME",
"LIVESPIC",
"LIVESNUM",
"LIVESX",
"LIVES",
"RINGS",
"RINGSSPLIT",
"RINGSNUM",
"RINGSNUMSPLIT",
"SCORE",
"SCORENUM",
"TIME",
"TIMESPLIT",
"MINUTES",
"MINUTESSPLIT",
"TIMECOLON",
"TIMECOLONSPLIT",
"SECONDS",
"SECONDSSPLIT",
"TIMETICCOLON",
"TICS",
"SS_TOTALRINGS",
"SS_TOTALRINGS_SPLIT",
"GETRINGS",
"GETRINGSNUM",
@ -6832,7 +6849,7 @@ static const char *const HUDITEMS_LIST[] = {
"TIMELEFTNUM",
"TIMEUP",
"HUNTPICS",
"GRAVBOOTSICO",
"POWERUPS",
"LAP"
};
@ -7321,13 +7338,21 @@ struct {
{"V_6WIDTHSPACE",V_6WIDTHSPACE},
{"V_OLDSPACING",V_OLDSPACING},
{"V_MONOSPACE",V_MONOSPACE},
{"V_PURPLEMAP",V_PURPLEMAP},
{"V_MAGENTAMAP",V_MAGENTAMAP},
{"V_YELLOWMAP",V_YELLOWMAP},
{"V_GREENMAP",V_GREENMAP},
{"V_BLUEMAP",V_BLUEMAP},
{"V_REDMAP",V_REDMAP},
{"V_GRAYMAP",V_GRAYMAP},
{"V_ORANGEMAP",V_ORANGEMAP},
{"V_SKYMAP",V_SKYMAP},
{"V_PURPLEMAP",V_PURPLEMAP},
{"V_AQUAMAP",V_AQUAMAP},
{"V_PERIDOTMAP",V_PERIDOTMAP},
{"V_AZUREMAP",V_AZUREMAP},
{"V_BROWNMAP",V_BROWNMAP},
{"V_ROSYMAP",V_ROSYMAP},
{"V_INVERTMAP",V_INVERTMAP},
{"V_TRANSLUCENT",V_TRANSLUCENT},
{"V_10TRANS",V_10TRANS},
{"V_20TRANS",V_20TRANS},
@ -7353,7 +7378,7 @@ struct {
{"V_WRAPX",V_WRAPX},
{"V_WRAPY",V_WRAPY},
{"V_NOSCALESTART",V_NOSCALESTART},
{"V_SPLITSCREEN",V_SPLITSCREEN},
{"V_PERPLAYER",V_PERPLAYER},
{"V_PARAMMASK",V_PARAMMASK},
{"V_SCALEPATCHMASK",V_SCALEPATCHMASK},
@ -7503,7 +7528,7 @@ static hudnum_t get_huditem(const char *word)
if (fastcmp(word, HUDITEMS_LIST[i]))
return i;
deh_warning("Couldn't find huditem named 'HUD_%s'",word);
return HUD_LIVESNAME;
return HUD_LIVES;
}
#ifndef HAVE_BLUA

View File

@ -560,9 +560,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls.
//#define PAPER_COLLISIONCORRECTION
/// Hudname padding.
#define SKINNAMEPADDING
/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
/// on the bright side it fixes some weird issues with translucent walls

View File

@ -498,6 +498,7 @@ extern boolean singletics;
#include "d_clisrv.h"
extern consvar_t cv_timetic; // display high resolution timer
extern consvar_t cv_powerupdisplay; // display powerups
extern consvar_t cv_showinputjoy; // display joystick in time attack
extern consvar_t cv_forceskin; // force clients to use the server's skin
extern consvar_t cv_downloading; // allow clients to downloading WADs.

View File

@ -242,11 +242,19 @@ static void F_SkyScroll(INT32 scrollspeed)
#ifdef HWRENDER
else if (rendermode != render_none)
{ // if only software rendering could be this simple and retarded
scrolled = animtimer;
if (scrolled > 0)
V_DrawScaledPatch(scrolled - patwidth, 0, 0, pat);
for (x = 0; x < fakedwidth; x += patwidth)
V_DrawScaledPatch(x + scrolled, 0, 0, pat);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT32 y, pw = patwidth * dupz, ph = SHORT(pat->height) * dupz;
scrolled = animtimer * dupz;
for (x = 0; x < vid.width; x += pw)
{
for (y = 0; y < vid.height; y += ph)
{
if (scrolled > 0)
V_DrawScaledPatch(scrolled - pw, y, V_NOSCALESTART, pat);
V_DrawScaledPatch(x + scrolled, y, V_NOSCALESTART, pat);
}
}
}
#endif
@ -322,7 +330,7 @@ void F_StartIntro(void)
"hovers around the planet.\xBF It suddenly\n"
"appears from nowhere, circles around, and\n"
"\xB6- just as mysteriously as it arrives -\xB6\n"
"vanishes after about two months.\xBF\n"
"vanishes after about one week.\xBF\n"
"No one knows why it appears, or how.\n#");
introtext[5] = M_GetText(
@ -334,11 +342,11 @@ void F_StartIntro(void)
"the screen, and just shrugged it off.\n#");
introtext[6] = M_GetText(
"It was only later\n"
"It was hours later\n"
"that he had an\n"
"idea. \xBF\xA7\"The Black\n"
"Rock usually has a\n"
"lot of energy\n"
"Rock has a large\n"
"amount of energy\n"
"within it\xAC...\xA7\xBF\n"
"If I can somehow\n"
"harness this,\xB8 I\n"
@ -356,37 +364,37 @@ void F_StartIntro(void)
"a reunion party...\n#");
introtext[8] = M_GetText(
"\xA5\"We're\xB6 ready\xB6 to\xB4 fire\xB6 in\xB6 15\xB6 seconds!\"\xA8\xB8\n"
"The robot said, his voice crackling a\n"
"little down the com-link. \xBF\xA7\"Good!\"\xA8\xB8\n"
"Eggman sat back in his Egg-Mobile and\n"
"\xA5\"PRE-""\xB6""PARING-""\xB6""TO-""\xB4""FIRE-\xB6IN-""\xB6""15-""\xB6""SECONDS!\"\xA8\xB8\n"
"his targeting system crackled\n"
"robotically down the com-link. \xBF\xA7\"Good!\"\xA8\xB8\n"
"Eggman sat back in his eggmobile and\n"
"began to count down as he saw the\n"
"GreenFlower city on the main monitor.\n#");
"Greenflower mountain on the monitor.\n#");
introtext[9] = M_GetText(
"\xA5\"10...\xD2""9...\xD2""8...\"\xA8\xD2\n"
"Meanwhile, Sonic was tearing across the\n"
"zones. Everything became a blur as he\n"
"ran around loops, skimmed over water,\n"
"ran up slopes, skimmed over water,\n"
"and catapulted himself off rocks with\n"
"his phenomenal speed.\n#");
introtext[10] = M_GetText(
"\xA5\"6...\xD2""5...\xD2""4...\"\xA8\xD2\n"
"Sonic knew he was getting closer to the\n"
"City, and pushed himself harder.\xB4 Finally,\n"
"the city appeared in the horizon.\xD2\xD2\n"
"zone, and pushed himself harder.\xB4 Finally,\n"
"the mountain appeared in the horizon.\xD2\xD2\n"
"\xA5\"3...\xD2""2...\xD2""1...\xD2""Zero.\"\n#");
introtext[11] = M_GetText(
"GreenFlower City was gone.\xC4\n"
"Greenflower Mountain was no more.\xC4\n"
"Sonic arrived just in time to see what\n"
"little of the 'ruins' were left.\n"
"Everyone and everything in the city\n"
"The natural beauty of the zone\n"
"had been obliterated.\n#");
introtext[12] = M_GetText(
"\xA7\"You're not quite as dead as we thought,\n"
"\xA7\"You're not quite as gone as we thought,\n"
"huh?\xBF Are you going to tell us your plan as\n"
"usual or will I \xA8\xB4'have to work it out'\xA7 or\n"
"something?\"\xD2\xD2\n"
@ -400,8 +408,8 @@ void F_StartIntro(void)
"leaving Sonic\n"
"and Tails behind.\xB6\n"
"Tails looked at\n"
"the ruins of the\n"
"Greenflower City\n"
"the once-perfect\n"
"mountainside\n"
"with a grim face\n"
"and sighed.\xC6\n"
"\xA7\"Now\xB6 what do we\n"
@ -979,7 +987,7 @@ static const char *credits[] = {
"\1Programming",
"Alam \"GBC\" Arias",
"Logan \"GBA\" Arias",
"Tim \"RedEnchilada\" Bordelon",
"Colette \"fickle\" Bordelon",
"Callum Dickinson",
"Scott \"Graue\" Feeney",
"Nathan \"Jazz\" Giroux",
@ -988,12 +996,12 @@ static const char *credits[] = {
"Ronald \"Furyhunter\" Kinard", // The SDL2 port
"John \"JTE\" Muniz",
"Ehab \"Wolfy\" Saeed",
"\"Kaito Sinclaire\"",
"\"SSNTails\"",
"Matthew \"Inuyasha\" Walsh",
"",
"\1Programming",
"\1Assistance",
"\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom)
"\"chi.miru\"", // helped port slope drawing code from ZDoom
"Andrew \"orospakr\" Clunis",
"Gregor \"Oogaland\" Dick",
"Louis-Antoine \"LJSonic\" de Moulins", // for fixing 2.1's netcode (de Rochefort doesn't quite fit on the screen sorry lol)
@ -1028,7 +1036,7 @@ static const char *credits[] = {
"\1Music and Sound",
"\1Production",
"Malcolm \"RedXVI\" Brown",
"David \"Bulmybag\" Bulmer",
"Dave \"DemonTomatoDave\" Bulmer",
"Paul \"Boinciel\" Clempson",
"Cyan Helkaraxe",
"Kepa \"Nev3r\" Iceta",
@ -1053,13 +1061,13 @@ static const char *credits[] = {
"Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe",
"Erik \"Torgo\" Nielsen",
"\"Kaito Sinclaire\"",
"Wessel \"Spherallic\" Smit",
"\"Spazzo\"",
"\"SSNTails\"",
"Rob Tisdell",
"Jarrett \"JEV3\" Voight",
"Johnny \"Sonikku\" Wallbank",
"Matthew \"Inuyasha\" Walsh",
"Marco \"Digiku\" Zafra",
"",
"\1Boss Design",

View File

@ -133,8 +133,8 @@ boolean useNightsSS = false;
UINT8 skincolor_redteam = SKINCOLOR_RED;
UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
UINT8 skincolor_redring = SKINCOLOR_RED;
UINT8 skincolor_bluering = SKINCOLOR_AZURE;
UINT8 skincolor_redring = SKINCOLOR_SALMON;
UINT8 skincolor_bluering = SKINCOLOR_CORNFLOWER;
tic_t countdowntimer = 0;
boolean countdowntimeup = false;
@ -888,7 +888,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
// why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn.
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
// ...OR if we're blindfolded. No looking into the floor.
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK)
&& (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT)))))
{
cmd->angleturn = (INT16)(localangle >> 16);
cmd->aiming = G_ClipAimingPitch(&localaiming);
@ -3813,7 +3815,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
unlocktriggers = 0;
// clear itemfinder, just in case
CV_StealthSetValue(&cv_itemfinder, 0);
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
CV_StealthSetValue(&cv_itemfinder, 0);
}
// internal game map

View File

@ -62,19 +62,31 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
UINT8 texel;
UINT16 texelu16;
if (!ptexturewidth)
return;
x1 = originx;
x2 = x1 + SHORT(realpatch->width);
if (x1 > ptexturewidth || x2 < 0)
return; // patch not located within texture's x bounds, ignore
if (originy > ptextureheight || (originy + SHORT(realpatch->height)) < 0)
return; // patch not located within texture's y bounds, ignore
// patch is actually inside the texture!
// now check if texture is partly off-screen and adjust accordingly
// left edge
if (x1 < 0)
x = 0;
else
x = x1;
// right edge
if (x2 > ptexturewidth)
x2 = ptexturewidth;
if (!ptexturewidth)
return;
col = x * pblockwidth / ptexturewidth;
ncols = ((x2 - x) * pblockwidth) / ptexturewidth;
@ -581,8 +593,8 @@ void HWR_FreeTextureCache(void)
// free all hardware-converted graphics cached in the heap
// our gool is only the textures since user of the texture is the texture cache
Z_FreeTags(PU_HWRCACHE, PU_HWRCACHE);
Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRCACHE_UNLOCKED);
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
// Alam: free the Z_Blocks before freeing it's users
@ -629,8 +641,8 @@ void HWR_SetPalette(RGBA_t *palette)
// now flush data texture cache so 32 bit texture are recomputed
if (patchformat == GR_RGBA || textureformat == GR_RGBA)
{
Z_FreeTags(PU_HWRCACHE, PU_HWRCACHE);
Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRCACHE_UNLOCKED);
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
}
}

View File

@ -20,8 +20,8 @@
#define _HWR_DEFS_
#include "../doomtype.h"
#define ZCLIP_PLANE 4.0f
#define NZCLIP_PLANE 0.9f
#define ZCLIP_PLANE 4.0f // Used for the actual game drawing
#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures
// ==========================================================================
// SIMPLE TYPES
@ -127,12 +127,13 @@ enum EPolyFlags
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture)
PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency
PF_Additive = 0x00000024, // Poly is added to the frame buffer
PF_Additive = 0x00000004, // Poly is added to the frame buffer
PF_Environment = 0x00000008, // Poly should be drawn environment mapped.
// Hurdler: used for text drawing
PF_Substractive = 0x00000010, // for splat
PF_NoAlphaTest = 0x00000020, // hiden param
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive)&~PF_NoAlphaTest,
PF_Fog = 0x00000040, // Fog blocks
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest,
// other flag bits

View File

@ -33,6 +33,8 @@
#include "../z_zone.h"
#include "../v_video.h"
#include "../st_stuff.h"
#include "../p_local.h" // stplyr
#include "../g_game.h" // players
#include <fcntl.h>
#include "../i_video.h" // for rendermode != render_glide
@ -147,14 +149,11 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
// | /|
// |/ |
// 0--1
float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale);
float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale);
float dupx, dupy, fscalew, fscaleh, fwidth, fheight;
if (alphalevel == 12)
alphalevel = 0;
else if (alphalevel >= 10 && alphalevel < 13)
UINT8 perplayershuffle = 0;
if (alphalevel >= 10 && alphalevel < 13)
return;
// make patch ready in hardware cache
@ -163,40 +162,179 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
else
HWR_GetMappedPatch(gpatch, colormap);
dupx = (float)vid.dupx;
dupy = (float)vid.dupy;
switch (option & V_SCALEPATCHMASK)
{
case V_NOSCALEPATCH:
pdupx = pdupy = 2.0f;
dupx = dupy = 1.0f;
break;
case V_SMALLSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
dupx = (float)vid.smalldupx;
dupy = (float)vid.smalldupy;
break;
case V_MEDSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
dupx = (float)vid.meddupx;
dupy = (float)vid.meddupy;
break;
}
if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f;
dupx = dupy = (dupx < dupy ? dupx : dupy);
fscalew = fscaleh = FIXED_TO_FLOAT(pscale);
if (option & V_SPLITSCREEN)
sdupy /= 2.0f;
if (option & V_FLIP) // Need to flip both this and sow
if (option & V_OFFSET)
{
v[0].x = v[3].x = (cx*sdupx-(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (cx*sdupx+gpatch->leftoffset*pdupx)/vid.width - 1;
cx -= (float)gpatch->leftoffset * dupx * fscalew;
cy -= (float)gpatch->topoffset * dupy * fscaleh;
}
else
{
v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1;
v[2].x = v[1].x = (cx*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
cy -= (float)gpatch->topoffset * fscaleh;
if (option & V_FLIP)
cx -= ((float)gpatch->width - (float)gpatch->leftoffset) * fscalew;
else
cx -= (float)gpatch->leftoffset * fscalew;
}
v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height;
v[2].y = v[3].y = 1-(cy*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
if (splitscreen && (option & V_PERPLAYER))
{
float adjusty = ((option & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
fscaleh /= 2;
cy /= 2;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
fscalew /= 2;
cx /= 2;
if (stplyr == &players[displayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
option &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
cx += adjustx;
option &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
cy += adjusty;
option &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else if (stplyr == &players[fourthdisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
cx += adjustx;
cy += adjusty;
option &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 1;
option &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 2;
cy += adjusty;
option &= ~V_SNAPTOTOP;
}
}
}
if (!(option & V_NOSCALESTART))
{
cx = cx * dupx;
cy = cy * dupy;
if (!(option & V_SCALEPATCHMASK))
{
// if it's meant to cover the whole screen, black out the rest
// cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
{
// Need to temporarily cache the real patch to get the colour of the top left pixel
patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
Z_Free(realpatch);
}
// centre screen
if (vid.width != BASEVIDWIDTH * vid.dupx)
{
if (option & V_SNAPTORIGHT)
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT))
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
if (perplayershuffle & 4)
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
else if (perplayershuffle & 8)
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
}
if (vid.height != BASEVIDHEIGHT * vid.dupy)
{
if (option & V_SNAPTOBOTTOM)
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP))
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
if (perplayershuffle & 1)
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
else if (perplayershuffle & 2)
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
}
}
}
if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{
fwidth = (float)gpatch->width * fscalew * dupx;
fheight = (float)gpatch->height * fscaleh * dupy;
}
else
{
fwidth = (float)gpatch->width * dupx;
fheight = (float)gpatch->height * dupy;
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
cx = -1 + (cx / (vid.width/2));
cy = 1 - (cy / (vid.height/2));
// fwidth and fheight are similar
fwidth /= vid.width / 2;
fheight /= vid.height / 2;
// set the polygon vertices to the right positions
v[0].x = v[3].x = cx;
v[2].x = v[1].x = cx + fwidth;
v[0].y = v[1].y = cy;
v[2].y = v[3].y = cy - fheight;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
@ -249,48 +387,125 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// | /|
// |/ |
// 0--1
float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale);
float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale);
float dupx, dupy, fscale, fwidth, fheight;
if (alphalevel == 12)
alphalevel = 0;
else if (alphalevel >= 10 && alphalevel < 13)
if (alphalevel >= 10 && alphalevel < 13)
return;
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
dupx = (float)vid.dupx;
dupy = (float)vid.dupy;
switch (option & V_SCALEPATCHMASK)
{
case V_NOSCALEPATCH:
pdupx = pdupy = 2.0f;
dupx = dupy = 1.0f;
break;
case V_SMALLSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
dupx = (float)vid.smalldupx;
dupy = (float)vid.smalldupy;
break;
case V_MEDSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
dupx = (float)vid.meddupx;
dupy = (float)vid.meddupy;
break;
}
if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f;
dupx = dupy = (dupx < dupy ? dupx : dupy);
fscale = FIXED_TO_FLOAT(pscale);
v[0].x = v[3].x = (cx*sdupx - gpatch->leftoffset * pdupx) / vid.width - 1;
v[2].x = v[1].x = (cx*sdupx + ((w) - gpatch->leftoffset) * pdupx) / vid.width - 1;
v[0].y = v[1].y = 1 - (cy*sdupy - gpatch->topoffset * pdupy) / vid.height;
v[2].y = v[3].y = 1 - (cy*sdupy + ((h) - gpatch->topoffset) * pdupy) / vid.height;
// fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus...
cy -= (float)gpatch->topoffset * fscale;
cx -= (float)gpatch->leftoffset * fscale;
if (!(option & V_NOSCALESTART))
{
cx = cx * dupx;
cy = cy * dupy;
if (!(option & V_SCALEPATCHMASK))
{
// if it's meant to cover the whole screen, black out the rest
// cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
{
// Need to temporarily cache the real patch to get the colour of the top left pixel
patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
Z_Free(realpatch);
}
// centre screen
if (vid.width != BASEVIDWIDTH * vid.dupx)
{
if (option & V_SNAPTORIGHT)
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT))
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
}
if (vid.height != BASEVIDHEIGHT * vid.dupy)
{
if (option & V_SNAPTOBOTTOM)
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP))
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
}
}
}
fwidth = w;
fheight = h;
if (fwidth > gpatch->width)
fwidth = gpatch->width;
if (fheight > gpatch->height)
fheight = gpatch->height;
if (pscale != FRACUNIT)
{
fwidth *= fscale * dupx;
fheight *= fscale * dupy;
}
else
{
fwidth *= dupx;
fheight *= dupy;
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
cx = -1 + (cx / (vid.width/2));
cy = 1 - (cy / (vid.height/2));
// fwidth and fheight are similar
fwidth /= vid.width / 2;
fheight /= vid.height / 2;
// set the polygon vertices to the right positions
v[0].x = v[3].x = cx;
v[2].x = v[1].x = cx + fwidth;
v[0].y = v[1].y = cy;
v[2].y = v[3].y = cy - fheight;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = ((sx )/(float)gpatch->width )*gpatch->max_s;
v[2].sow = v[1].sow = ((sx+w)/(float)gpatch->width )*gpatch->max_s;
v[0].tow = v[1].tow = ((sy )/(float)gpatch->height)*gpatch->max_t;
v[2].tow = v[3].tow = ((sy+h)/(float)gpatch->height)*gpatch->max_t;
v[0].sow = v[3].sow = ((sx )/(float)gpatch->width )*gpatch->max_s;
if (sx + w > gpatch->width)
v[2].sow = v[1].sow = gpatch->max_s;
else
v[2].sow = v[1].sow = ((sx+w)/(float)gpatch->width )*gpatch->max_s;
v[0].tow = v[1].tow = ((sy )/(float)gpatch->height)*gpatch->max_t;
if (sy + h > gpatch->height)
v[2].tow = v[3].tow = gpatch->max_t;
else
v[2].tow = v[3].tow = ((sy+h)/(float)gpatch->height)*gpatch->max_t;
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest;
@ -434,18 +649,14 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
// | /|
// |/ |
// 0--1
void HWR_FadeScreenMenuBack(UINT32 color, INT32 height)
void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
{
FOutVector v[4];
FSurfaceInfo Surf;
// setup some neat-o translucency effect
if (!height) //cool hack 0 height is full height
height = vid.height;
v[0].x = v[3].x = -1.0f;
v[2].x = v[1].x = 1.0f;
v[0].y = v[1].y = 1.0f-((height<<1)/(float)vid.height);
v[0].y = v[1].y = -1.0f;
v[2].y = v[3].y = 1.0f;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
@ -454,8 +665,16 @@ void HWR_FadeScreenMenuBack(UINT32 color, INT32 height)
v[0].tow = v[1].tow = 1.0f;
v[2].tow = v[3].tow = 0.0f;
Surf.FlatColor.rgba = UINT2RGBA(color);
Surf.FlatColor.s.alpha = (UINT8)((0xff/2) * ((float)height / vid.height)); //calum: varies console alpha
if (color & 0xFF00) // Do COLORMAP fade.
{
Surf.FlatColor.rgba = UINT2RGBA(0x01010160);
Surf.FlatColor.s.alpha = (strength*8);
}
else // Do TRANSMAP** fade.
{
Surf.FlatColor.rgba = pLocalPalette[color].rgba;
Surf.FlatColor.s.alpha = (UINT8)(strength*25.5f);
}
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
}
@ -660,7 +879,9 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
{
FOutVector v[4];
FSurfaceInfo Surf;
float sdupx, sdupy;
float fx, fy, fw, fh;
UINT8 perplayershuffle = 0;
if (w < 0 || h < 0)
return; // consistency w/ software
@ -669,16 +890,155 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
// | /|
// |/ |
// 0--1
sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
if (color & V_NOSCALESTART)
sdupx = sdupy = 2.0f;
if (splitscreen && (color & V_PERPLAYER))
{
fixed_t adjusty = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
h >>= 1;
y >>= 1;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
fixed_t adjustx = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
w >>= 1;
x >>= 1;
if (stplyr == &players[displayplayer])
{
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
color &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
color &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
y += adjusty;
color &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else //if (stplyr == &players[fourthdisplayplayer])
{
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
y += adjusty;
color &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
color &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
y += adjusty;
color &= ~V_SNAPTOTOP;
}
}
}
v[0].x = v[3].x = (x*sdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx + w*sdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy + h*sdupy)/vid.height;
fx = (float)x;
fy = (float)y;
fw = (float)w;
fh = (float)h;
if (!(color & V_NOSCALESTART))
{
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{
RGBA_t rgbaColour = V_GetColor(color);
FRGBAFloat clearColour;
clearColour.red = (float)rgbaColour.s.red / 255;
clearColour.green = (float)rgbaColour.s.green / 255;
clearColour.blue = (float)rgbaColour.s.blue / 255;
clearColour.alpha = 1;
HWD.pfnClearBuffer(true, false, &clearColour);
return;
}
fx *= dupx;
fy *= dupy;
fw *= dupx;
fh *= dupy;
if (vid.width != BASEVIDWIDTH * vid.dupx)
{
if (color & V_SNAPTORIGHT)
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(color & V_SNAPTOLEFT))
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
if (perplayershuffle & 4)
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
else if (perplayershuffle & 8)
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if (color & V_SNAPTOBOTTOM)
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(color & V_SNAPTOTOP))
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
if (perplayershuffle & 1)
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
else if (perplayershuffle & 2)
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
}
}
if (fx >= vid.width || fy >= vid.height)
return;
if (fx < 0)
{
fw += fx;
fx = 0;
}
if (fy < 0)
{
fh += fy;
fy = 0;
}
if (fw <= 0 || fh <= 0)
return;
if (fx + fw > vid.width)
fw = (float)vid.width - fx;
if (fy + fh > vid.height)
fh = (float)vid.height - fy;
fx = -1 + fx / (vid.width / 2);
fy = 1 - fy / (vid.height / 2);
fw = fw / (vid.width / 2);
fh = fh / (vid.height / 2);
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
v[0].y = v[1].y = fy;
v[2].y = v[3].y = fy - fh;
//Hurdler: do we still use this argb color? if not, we should remove it
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;

View File

@ -79,6 +79,7 @@ EXPORT char *HWRAPI(GetRenderer) (void);
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
#endif
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void);
EXPORT void HWRAPI(DoScreenWipe) (float alpha);
@ -124,6 +125,7 @@ struct hwdriver_s
#ifdef SHUFFLE
PostImgRedraw pfnPostImgRedraw;
#endif
FlushScreenTextures pfnFlushScreenTextures;
StartScreenWipe pfnStartScreenWipe;
EndScreenWipe pfnEndScreenWipe;
DoScreenWipe pfnDoScreenWipe;

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ void HWR_Shutdown(void);
void HWR_clearAutomap(void);
void HWR_drawAMline(const fline_t *fl, INT32 color);
void HWR_FadeScreenMenuBack(UINT32 color, INT32 height);
void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength);
void HWR_DrawConsoleBack(UINT32 color, INT32 height);
void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player);
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player);

View File

@ -57,7 +57,7 @@ typedef struct GLRGBAFloat GLRGBAFloat;
#define N_PI_DEMI (M_PIl/2.0f) //(1.5707963268f)
#define ASPECT_RATIO (1.0f) //(320.0f/200.0f)
#define FAR_CLIPPING_PLANE 150000.0f // Draw further! Tails 01-21-2001
#define FAR_CLIPPING_PLANE 32768.0f // Draw further! Tails 01-21-2001
static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE;
// **************************************************************************
@ -101,10 +101,19 @@ static GLint viewport[4];
#endif
// Yay for arbitrary numbers! NextTexAvail is buggy for some reason.
static GLuint screentexture = 60000;
static GLuint startScreenWipe = 60001;
static GLuint endScreenWipe = 60002;
static GLuint finalScreenTexture = 60003;
// Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing
// flush all of the stored textures, leaving them unavailable at times such as between levels
// These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs
// can know when the textures aren't there, as textures are always considered resident in their virtual memory
// TODO: Store them in a more normal way
#define SCRTEX_SCREENTEXTURE 65535
#define SCRTEX_STARTSCREENWIPE 65534
#define SCRTEX_ENDSCREENWIPE 65533
#define SCRTEX_FINALSCREENTEXTURE 65532
static GLuint screentexture = 0;
static GLuint startScreenWipe = 0;
static GLuint endScreenWipe = 0;
static GLuint finalScreenTexture = 0;
#if 0
GLuint screentexture = FIRST_TEX_AVAIL;
#endif
@ -245,6 +254,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...)
#define pglBindTexture glBindTexture
/* texture mapping */ //GL_EXT_copy_texture
#define pglCopyTexImage2D glCopyTexImage2D
#define pglCopyTexSubImage2D glCopyTexSubImage2D
#else //!STATIC_OPENGL
@ -361,6 +371,8 @@ static PFNglBindTexture pglBindTexture;
/* texture mapping */ //GL_EXT_copy_texture
typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
static PFNglCopyTexImage2D pglCopyTexImage2D;
typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
static PFNglCopyTexSubImage2D pglCopyTexSubImage2D;
#endif
/* GLU functions */
typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data);
@ -460,6 +472,7 @@ boolean SetupGLfunc(void)
GETOPENGLFUNC(pglBindTexture , glBindTexture)
GETOPENGLFUNC(pglCopyTexImage2D , glCopyTexImage2D)
GETOPENGLFUNC(pglCopyTexSubImage2D , glCopyTexSubImage2D)
#undef GETOPENGLFUNC
@ -597,6 +610,10 @@ void SetModelView(GLint w, GLint h)
{
// DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h);
// The screen textures need to be flushed if the width or height change so that they be remade for the correct size
if (screen_width != w || screen_height != h)
FlushScreenTextures();
screen_width = w;
screen_height = h;
@ -734,6 +751,7 @@ void Flush(void)
screentexture = FIRST_TEX_AVAIL;
}
#endif
tex_downloaded = 0;
}
@ -948,26 +966,38 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
switch (PolyFlags & PF_Blending) {
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Additive & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Substractive & PF_Blending:
// good for shadow
// not realy but what else ?
pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
default : // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
@ -1120,6 +1150,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
tex[w*j+i].s.green = 0;
tex[w*j+i].s.blue = 0;
tex[w*j+i].s.alpha = 0;
pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it
}
else
{
@ -1189,8 +1220,17 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
tex_downloaded = pTexInfo->downloaded;
pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
if (pTexInfo->flags & TF_TRANSPARENT)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
}
#ifdef USE_PALETTED_TEXTURE
//Hurdler: not really supported and not tested recently
@ -1559,12 +1599,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration,
ambient[1] = 0.75f;
if (ambient[2] > 0.75f)
ambient[2] = 0.75f;
if (color[3] < 255)
{
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
pglDepthMask(GL_FALSE);
}
}
pglEnable(GL_CULL_FACE);
@ -1589,10 +1623,12 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration,
pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
#endif
if (color[3] < 255)
SetBlend(PF_Translucent|PF_Modulated|PF_Clip);
else
SetBlend(PF_Masked|PF_Modulated|PF_Occlude|PF_Clip);
}
DrawPolygon(NULL, NULL, 0, PF_Masked|PF_Modulated|PF_Occlude|PF_Clip);
pglPushMatrix(); // should be the same as glLoadIdentity
//Hurdler: now it seems to work
pglTranslatef(pos->x, pos->z, pos->y);
@ -1600,14 +1636,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration,
scaley = -scaley;
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f);
//pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
// Remove depth mask when the model is transparent so it doesn't cut thorugh sprites // SRB2CBTODO: For all stuff too?!
if (color && color[3] < 255)
{
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
pglDepthMask(GL_FALSE);
}
val = *gl_cmd_buffer++;
@ -1675,7 +1703,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration,
if (color)
pglDisable(GL_LIGHTING);
pglShadeModel(GL_FLAT);
pglDepthMask(GL_TRUE);
pglDisable(GL_CULL_FACE);
}
@ -1822,10 +1849,25 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2])
}
#endif //SHUFFLE
// Sryder: This needs to be called whenever the screen changes resolution in order to reset the screen textures to use
// a new size
EXPORT void HWRAPI(FlushScreenTextures) (void)
{
pglDeleteTextures(1, &screentexture);
pglDeleteTextures(1, &startScreenWipe);
pglDeleteTextures(1, &endScreenWipe);
pglDeleteTextures(1, &finalScreenTexture);
screentexture = 0;
startScreenWipe = 0;
endScreenWipe = 0;
finalScreenTexture = 0;
}
// Create Screen to fade from
EXPORT void HWRAPI(StartScreenWipe) (void)
{
INT32 texsize = 2048;
boolean firstTime = (startScreenWipe == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
@ -1834,20 +1876,29 @@ EXPORT void HWRAPI(StartScreenWipe) (void)
texsize = 1024;
// Create screen texture
if (firstTime)
startScreenWipe = SCRTEX_STARTSCREENWIPE;
pglBindTexture(GL_TEXTURE_2D, startScreenWipe);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = startScreenWipe;
}
// Create Screen to fade to
EXPORT void HWRAPI(EndScreenWipe)(void)
{
INT32 texsize = 2048;
boolean firstTime = (endScreenWipe == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
@ -1856,14 +1907,22 @@ EXPORT void HWRAPI(EndScreenWipe)(void)
texsize = 1024;
// Create screen texture
if (firstTime)
endScreenWipe = SCRTEX_ENDSCREENWIPE;
pglBindTexture(GL_TEXTURE_2D, endScreenWipe);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = endScreenWipe;
}
@ -1905,7 +1964,7 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void)
pglEnd();
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
tex_downloaded = screentexture;
}
// Do screen fades!
@ -1993,6 +2052,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha)
pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit
pglActiveTexture(GL_TEXTURE0);
tex_downloaded = endScreenWipe;
}
else
{
@ -2017,9 +2077,8 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha)
pglTexCoord2f(xfix, 0.0f);
pglVertex3f(1.0f, -1.0f, 1.0f);
pglEnd();
tex_downloaded = endScreenWipe;
}
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
}
@ -2027,6 +2086,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha)
EXPORT void HWRAPI(MakeScreenTexture) (void)
{
INT32 texsize = 2048;
boolean firstTime = (screentexture == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
@ -2035,19 +2095,28 @@ EXPORT void HWRAPI(MakeScreenTexture) (void)
texsize = 1024;
// Create screen texture
if (firstTime)
screentexture = SCRTEX_SCREENTEXTURE;
pglBindTexture(GL_TEXTURE_2D, screentexture);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = screentexture;
}
EXPORT void HWRAPI(MakeScreenFinalTexture) (void)
{
INT32 texsize = 2048;
boolean firstTime = (finalScreenTexture == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
@ -2056,20 +2125,31 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void)
texsize = 1024;
// Create screen texture
if (firstTime)
finalScreenTexture = SCRTEX_FINALSCREENTEXTURE;
pglBindTexture(GL_TEXTURE_2D, finalScreenTexture);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = finalScreenTexture;
}
EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height)
{
float xfix, yfix;
float origaspect, newaspect;
float xoff = 1, yoff = 1; // xoffset and yoffset for the polygon to have black bars around the screen
FRGBAFloat clearColour;
INT32 texsize = 2048;
if(screen_width <= 1024)
@ -2080,35 +2160,47 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height)
xfix = 1/((float)(texsize)/((float)((screen_width))));
yfix = 1/((float)(texsize)/((float)((screen_height))));
//pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
origaspect = (float)screen_width / screen_height;
newaspect = (float)width / height;
if (origaspect < newaspect)
{
xoff = origaspect / newaspect;
yoff = 1;
}
else if (origaspect > newaspect)
{
xoff = 1;
yoff = newaspect / origaspect;
}
pglViewport(0, 0, width, height);
clearColour.red = clearColour.green = clearColour.blue = 0;
clearColour.alpha = 1;
ClearBuffer(true, false, &clearColour);
pglBindTexture(GL_TEXTURE_2D, finalScreenTexture);
pglBegin(GL_QUADS);
pglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// Bottom left
pglTexCoord2f(0.0f, 0.0f);
pglVertex3f(-1, -1, 1.0f);
pglVertex3f(-xoff, -yoff, 1.0f);
// Top left
pglTexCoord2f(0.0f, yfix);
pglVertex3f(-1, 1, 1.0f);
pglVertex3f(-xoff, yoff, 1.0f);
// Top right
pglTexCoord2f(xfix, yfix);
pglVertex3f(1, 1, 1.0f);
pglVertex3f(xoff, yoff, 1.0f);
// Bottom right
pglTexCoord2f(xfix, 0.0f);
pglVertex3f(1, -1, 1.0f);
pglVertex3f(xoff, -yoff, 1.0f);
pglEnd();
SetModelView(screen_width, screen_height);
SetStates();
tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
tex_downloaded = finalScreenTexture;
}
#endif //HWRENDER

View File

@ -90,8 +90,7 @@ patch_t *tallinfin;
// coop hud
//-------------------------------------------
patch_t *emeraldpics[7];
patch_t *tinyemeraldpics[7];
patch_t *emeraldpics[3][7]; // 0 = normal, 1 = tiny, 2 = coinbox
static patch_t *emblemicon;
patch_t *tokenicon;
static patch_t *exiticon;
@ -258,20 +257,29 @@ void HU_LoadGraphics(void)
tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX);
exiticon = W_CachePatchName("EXITICON", PU_HUDGFX);
emeraldpics[0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
emeraldpics[1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
emeraldpics[2] = W_CachePatchName("CHAOS3", PU_HUDGFX);
emeraldpics[3] = W_CachePatchName("CHAOS4", PU_HUDGFX);
emeraldpics[4] = W_CachePatchName("CHAOS5", PU_HUDGFX);
emeraldpics[5] = W_CachePatchName("CHAOS6", PU_HUDGFX);
emeraldpics[6] = W_CachePatchName("CHAOS7", PU_HUDGFX);
tinyemeraldpics[0] = W_CachePatchName("TEMER1", PU_HUDGFX);
tinyemeraldpics[1] = W_CachePatchName("TEMER2", PU_HUDGFX);
tinyemeraldpics[2] = W_CachePatchName("TEMER3", PU_HUDGFX);
tinyemeraldpics[3] = W_CachePatchName("TEMER4", PU_HUDGFX);
tinyemeraldpics[4] = W_CachePatchName("TEMER5", PU_HUDGFX);
tinyemeraldpics[5] = W_CachePatchName("TEMER6", PU_HUDGFX);
tinyemeraldpics[6] = W_CachePatchName("TEMER7", PU_HUDGFX);
emeraldpics[0][0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
emeraldpics[0][1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
emeraldpics[0][2] = W_CachePatchName("CHAOS3", PU_HUDGFX);
emeraldpics[0][3] = W_CachePatchName("CHAOS4", PU_HUDGFX);
emeraldpics[0][4] = W_CachePatchName("CHAOS5", PU_HUDGFX);
emeraldpics[0][5] = W_CachePatchName("CHAOS6", PU_HUDGFX);
emeraldpics[0][6] = W_CachePatchName("CHAOS7", PU_HUDGFX);
emeraldpics[1][0] = W_CachePatchName("TEMER1", PU_HUDGFX);
emeraldpics[1][1] = W_CachePatchName("TEMER2", PU_HUDGFX);
emeraldpics[1][2] = W_CachePatchName("TEMER3", PU_HUDGFX);
emeraldpics[1][3] = W_CachePatchName("TEMER4", PU_HUDGFX);
emeraldpics[1][4] = W_CachePatchName("TEMER5", PU_HUDGFX);
emeraldpics[1][5] = W_CachePatchName("TEMER6", PU_HUDGFX);
emeraldpics[1][6] = W_CachePatchName("TEMER7", PU_HUDGFX);
emeraldpics[2][0] = W_CachePatchName("EMBOX1", PU_HUDGFX);
emeraldpics[2][1] = W_CachePatchName("EMBOX2", PU_HUDGFX);
emeraldpics[2][2] = W_CachePatchName("EMBOX3", PU_HUDGFX);
emeraldpics[2][3] = W_CachePatchName("EMBOX4", PU_HUDGFX);
emeraldpics[2][4] = W_CachePatchName("EMBOX5", PU_HUDGFX);
emeraldpics[2][5] = W_CachePatchName("EMBOX6", PU_HUDGFX);
emeraldpics[2][6] = W_CachePatchName("EMBOX7", PU_HUDGFX);
}
// Initialise Heads up
@ -947,7 +955,7 @@ static void HU_DrawCEcho(void)
INT32 y = (BASEVIDHEIGHT/2)-4;
INT32 pnumlines = 0;
UINT32 realflags = cechoflags;
UINT32 realflags = cechoflags|V_PERPLAYER; // requested as part of splitscreen's stuff
INT32 realalpha = (INT32)((cechoflags & V_ALPHAMASK) >> V_ALPHASHIFT);
char *line;
@ -990,6 +998,12 @@ static void HU_DrawCEcho(void)
*line = '\0';
V_DrawCenteredString(BASEVIDWIDTH/2, y, realflags, echoptr);
if (splitscreen)
{
stplyr = ((stplyr == &players[displayplayer]) ? &players[secondarydisplayplayer] : &players[displayplayer]);
V_DrawCenteredString(BASEVIDWIDTH/2, y, realflags, echoptr);
stplyr = ((stplyr == &players[displayplayer]) ? &players[secondarydisplayplayer] : &players[displayplayer]);
}
y += ((realflags & V_RETURN8) ? 8 : 12);
echoptr = line;
@ -1474,25 +1488,25 @@ void HU_DrawEmeralds(INT32 x, INT32 y, INT32 pemeralds)
{
//Draw the emeralds, in the CORRECT order, using tiny emerald sprites.
if (pemeralds & EMERALD1)
V_DrawSmallScaledPatch(x , y-6, 0, tinyemeraldpics[0]);
V_DrawSmallScaledPatch(x , y-6, 0, emeraldpics[1][0]);
if (pemeralds & EMERALD2)
V_DrawSmallScaledPatch(x+4, y-3, 0, tinyemeraldpics[1]);
V_DrawSmallScaledPatch(x+4, y-3, 0, emeraldpics[1][1]);
if (pemeralds & EMERALD3)
V_DrawSmallScaledPatch(x+4, y+3, 0, tinyemeraldpics[2]);
V_DrawSmallScaledPatch(x+4, y+3, 0, emeraldpics[1][2]);
if (pemeralds & EMERALD4)
V_DrawSmallScaledPatch(x , y+6, 0, tinyemeraldpics[3]);
V_DrawSmallScaledPatch(x , y+6, 0, emeraldpics[1][3]);
if (pemeralds & EMERALD5)
V_DrawSmallScaledPatch(x-4, y+3, 0, tinyemeraldpics[4]);
V_DrawSmallScaledPatch(x-4, y+3, 0, emeraldpics[1][4]);
if (pemeralds & EMERALD6)
V_DrawSmallScaledPatch(x-4, y-3, 0, tinyemeraldpics[5]);
V_DrawSmallScaledPatch(x-4, y-3, 0, emeraldpics[1][5]);
if (pemeralds & EMERALD7)
V_DrawSmallScaledPatch(x, y, 0, tinyemeraldpics[6]);
V_DrawSmallScaledPatch(x, y, 0, emeraldpics[1][6]);
}
//
@ -1547,7 +1561,7 @@ static inline void HU_DrawSpectatorTicker(void)
templength = length;
}
V_DrawString(templength, height + 8, V_TRANSLUCENT, current);
V_DrawString(templength, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE, current);
}
length += (signed)strlen(player_names[i]) * 8 + 16;
@ -1559,7 +1573,6 @@ static inline void HU_DrawSpectatorTicker(void)
//
static void HU_DrawRankings(void)
{
patch_t *p;
playersort_t tab[MAXPLAYERS];
INT32 i, j, scorelines;
boolean completed[MAXPLAYERS];
@ -1568,43 +1581,12 @@ static void HU_DrawRankings(void)
// draw the current gametype in the lower right
HU_drawGametype();
if (G_GametypeHasTeams())
{
if (gametype == GT_CTF)
p = bflagico;
else
p = bmatcico;
V_DrawSmallScaledPatch(128 - SHORT(p->width)/4, 4, 0, p);
V_DrawCenteredString(128, 16, 0, va("%u", bluescore));
if (gametype == GT_CTF)
p = rflagico;
else
p = rmatcico;
V_DrawSmallScaledPatch(192 - SHORT(p->width)/4, 4, 0, p);
V_DrawCenteredString(192, 16, 0, va("%u", redscore));
}
if (gametype != GT_RACE && gametype != GT_COMPETITION && gametype != GT_COOP)
{
if (cv_timelimit.value && timelimitintics > 0)
{
INT32 timeval = (timelimitintics+1-leveltime)/TICRATE;
if (leveltime <= timelimitintics)
{
V_DrawCenteredString(64, 8, 0, "TIME LEFT");
V_DrawCenteredString(64, 16, 0, va("%u", timeval));
}
// overtime
if ((leveltime > (timelimitintics + TICRATE/2)) && cv_overtime.value)
{
V_DrawCenteredString(64, 8, 0, "TIME LEFT");
V_DrawCenteredString(64, 16, 0, "OVERTIME");
}
V_DrawCenteredString(64, 8, 0, "TIME");
V_DrawCenteredString(64, 16, 0, va("%i:%02i", G_TicsToMinutes(stplyr->realtime, true), G_TicsToSeconds(stplyr->realtime)));
}
if (cv_pointlimit.value > 0)
@ -1761,19 +1743,19 @@ static void HU_DrawCoopOverlay(void)
#endif
if (emeralds & EMERALD1)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)-32, 0, emeraldpics[0]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)-32, 0, emeraldpics[0][0]);
if (emeralds & EMERALD2)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)-16, 0, emeraldpics[1]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)-16, 0, emeraldpics[0][1]);
if (emeralds & EMERALD3)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)+16, 0, emeraldpics[2]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8+24, (BASEVIDHEIGHT/3)+16, 0, emeraldpics[0][2]);
if (emeralds & EMERALD4)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)+32, 0, emeraldpics[3]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3)+32, 0, emeraldpics[0][3]);
if (emeralds & EMERALD5)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)+16, 0, emeraldpics[4]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)+16, 0, emeraldpics[0][4]);
if (emeralds & EMERALD6)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)-16, 0, emeraldpics[5]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8-24, (BASEVIDHEIGHT/3)-16, 0, emeraldpics[0][5]);
if (emeralds & EMERALD7)
V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3) , 0, emeraldpics[6]);
V_DrawScaledPatch((BASEVIDWIDTH/2)-8 , (BASEVIDHEIGHT/3) , 0, emeraldpics[0][6]);
}
static void HU_DrawNetplayCoopOverlay(void)
@ -1788,7 +1770,7 @@ static void HU_DrawNetplayCoopOverlay(void)
for (i = 0; i < 7; ++i)
{
if (emeralds & (1 << i))
V_DrawScaledPatch(20 + (i * 20), 6, 0, emeraldpics[i]);
V_DrawScaledPatch(20 + (i * 20), 6, 0, emeraldpics[0][i]);
}
}

View File

@ -64,8 +64,7 @@ extern patch_t *nightsnum[10];
extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE];
extern patch_t *ttlnum[20];
extern patch_t *emeraldpics[7];
extern patch_t *tinyemeraldpics[7];
extern patch_t *emeraldpics[3][7];
extern patch_t *rflagico;
extern patch_t *bflagico;
extern patch_t *rmatcico;

View File

@ -680,7 +680,7 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY
// 1-Up box sprites (uses player sprite)
{SPR_PLAY, SPR2_LIFE, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1
{SPR_PLAY, SPR2_LIFE, 2, {NULL}, 0, 18, S_PLAY_BOX2}, // S_PLAY_BOX1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2
{SPR_PLAY, SPR2_LIFE, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1
{SPR_NULL, 0, 12, {NULL}, 0, 0, S_PLAY_ICON3}, // S_PLAY_ICON2
@ -1727,9 +1727,10 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 2, {A_SetRandomTics}, TICRATE/2, 3*TICRATE, S_CANNONLAUNCHER1}, // S_CANNONLAUNCHER3
// Monitor Miscellany
{SPR_NSPK, FF_TRANS40, 20, {NULL}, 0, 0, S_BOXSPARKLE2}, // S_BOXSPARKLE1
{SPR_NSPK, FF_TRANS60, 10, {NULL}, 0, 0, S_BOXSPARKLE3}, // S_BOXSPARKLE2
{SPR_NSPK, FF_TRANS80, 5, {NULL}, 0, 0, S_NULL}, // S_BOXSPARKLE3
{SPR_NSPK, 0, 16, {NULL}, 0, 0, S_BOXSPARKLE2}, // S_BOXSPARKLE1
{SPR_NSPK, 1, 12, {NULL}, 0, 0, S_BOXSPARKLE3}, // S_BOXSPARKLE2
{SPR_NSPK, 2, 8, {NULL}, 0, 0, S_BOXSPARKLE4}, // S_BOXSPARKLE3
{SPR_NSPK, 3, 4, {NULL}, 0, 0, S_NULL}, // S_BOXSPARKLE4
{SPR_MSTV, 0, 1, {NULL}, 0, 0, S_SPAWNSTATE}, // S_BOX_FLICKER
{SPR_MSTV, 0, 4, {A_MonitorPop}, 0, 0, S_BOX_POP2}, // S_BOX_POP1
@ -2214,39 +2215,71 @@ state_t states[NUMSTATES] =
{SPR_ARMA, FF_TRANS40|14, 2, {NULL}, 0, 0, S_ARMA16}, // S_ARMA15
{SPR_ARMA, FF_TRANS40|15, 2, {NULL}, 0, 0, S_ARMA1 }, // S_ARMA16
{SPR_ARMF, FF_FULLBRIGHT , 3, {NULL}, 0, 0, S_ARMF2 }, // S_ARMF1
{SPR_ARMF, FF_FULLBRIGHT| 1, 3, {NULL}, 0, 0, S_ARMF3 }, // S_ARMF2
{SPR_ARMF, FF_FULLBRIGHT| 2, 3, {NULL}, 0, 0, S_ARMF4 }, // S_ARMF3
{SPR_ARMF, FF_FULLBRIGHT| 3, 3, {NULL}, 0, 0, S_ARMF5 }, // S_ARMF4
{SPR_ARMF, FF_FULLBRIGHT| 4, 3, {NULL}, 0, 0, S_ARMF6 }, // S_ARMF5
{SPR_ARMF, FF_FULLBRIGHT| 5, 3, {NULL}, 0, 0, S_ARMF7 }, // S_ARMF6
{SPR_ARMF, FF_FULLBRIGHT| 6, 3, {NULL}, 0, 0, S_ARMF8 }, // S_ARMF7
{SPR_ARMF, FF_FULLBRIGHT| 7, 3, {NULL}, 0, 0, S_ARMF9 }, // S_ARMF8
{SPR_ARMF, FF_FULLBRIGHT| 8, 3, {NULL}, 0, 0, S_ARMF10}, // S_ARMF9
{SPR_ARMF, FF_FULLBRIGHT| 9, 3, {NULL}, 0, 0, S_ARMF11}, // S_ARMF10
{SPR_ARMF, FF_FULLBRIGHT|10, 3, {NULL}, 0, 0, S_ARMF12}, // S_ARMF11
{SPR_ARMF, FF_FULLBRIGHT|11, 3, {NULL}, 0, 0, S_ARMF13}, // S_ARMF12
{SPR_ARMF, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ARMF14}, // S_ARMF13
{SPR_ARMF, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ARMF15}, // S_ARMF14
{SPR_ARMF, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ARMF16}, // S_ARMF15
{SPR_ARMF, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ARMF1 }, // S_ARMF16
{SPR_ARMF, FF_FULLBRIGHT , 2, {NULL}, 0, 0, S_ARMF2 }, // S_ARMF1
{SPR_ARMF, FF_FULLBRIGHT| 1, 2, {NULL}, 0, 0, S_ARMF3 }, // S_ARMF2
{SPR_ARMF, FF_FULLBRIGHT| 2, 2, {NULL}, 0, 0, S_ARMF4 }, // S_ARMF3
{SPR_ARMF, FF_FULLBRIGHT| 3, 2, {NULL}, 0, 0, S_ARMF5 }, // S_ARMF4
{SPR_ARMF, FF_FULLBRIGHT| 4, 2, {NULL}, 0, 0, S_ARMF6 }, // S_ARMF5
{SPR_ARMF, FF_FULLBRIGHT| 5, 2, {NULL}, 0, 0, S_ARMF7 }, // S_ARMF6
{SPR_ARMF, FF_FULLBRIGHT| 6, 2, {NULL}, 0, 0, S_ARMF8 }, // S_ARMF7
{SPR_ARMF, FF_FULLBRIGHT| 7, 2, {NULL}, 0, 0, S_ARMF9 }, // S_ARMF8
{SPR_ARMF, FF_FULLBRIGHT| 8, 2, {NULL}, 0, 0, S_ARMF10}, // S_ARMF9
{SPR_ARMF, FF_FULLBRIGHT| 9, 2, {NULL}, 0, 0, S_ARMF11}, // S_ARMF10
{SPR_ARMF, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_ARMF12}, // S_ARMF11
{SPR_ARMF, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_ARMF13}, // S_ARMF12
{SPR_ARMF, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_ARMF14}, // S_ARMF13
{SPR_ARMF, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_ARMF15}, // S_ARMF14
{SPR_ARMF, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_ARMF16}, // S_ARMF15
{SPR_ARMF, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_ARMF17}, // S_ARMF16
{SPR_ARMB, FF_FULLBRIGHT , 2, {NULL}, 0, 0, S_ARMF18}, // S_ARMF17
{SPR_ARMB, FF_FULLBRIGHT| 1, 2, {NULL}, 0, 0, S_ARMF19}, // S_ARMF18
{SPR_ARMB, FF_FULLBRIGHT| 2, 2, {NULL}, 0, 0, S_ARMF20}, // S_ARMF19
{SPR_ARMB, FF_FULLBRIGHT| 3, 2, {NULL}, 0, 0, S_ARMF21}, // S_ARMF20
{SPR_ARMB, FF_FULLBRIGHT| 4, 2, {NULL}, 0, 0, S_ARMF22}, // S_ARMF21
{SPR_ARMB, FF_FULLBRIGHT| 5, 2, {NULL}, 0, 0, S_ARMF23}, // S_ARMF22
{SPR_ARMB, FF_FULLBRIGHT| 6, 2, {NULL}, 0, 0, S_ARMF24}, // S_ARMF23
{SPR_ARMB, FF_FULLBRIGHT| 7, 2, {NULL}, 0, 0, S_ARMF25}, // S_ARMF24
{SPR_ARMB, FF_FULLBRIGHT| 8, 2, {NULL}, 0, 0, S_ARMF26}, // S_ARMF25
{SPR_ARMB, FF_FULLBRIGHT| 9, 2, {NULL}, 0, 0, S_ARMF27}, // S_ARMF26
{SPR_ARMB, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_ARMF28}, // S_ARMF27
{SPR_ARMB, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_ARMF29}, // S_ARMF28
{SPR_ARMB, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_ARMF30}, // S_ARMF29
{SPR_ARMB, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_ARMF31}, // S_ARMF30
{SPR_ARMB, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_ARMF32}, // S_ARMF31
{SPR_ARMB, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_ARMF1 }, // S_ARMF32
{SPR_ARMB, FF_FULLBRIGHT| 0, 3, {NULL}, 1, 0, S_ARMB2 }, // S_ARMB1
{SPR_ARMB, FF_FULLBRIGHT| 1, 3, {NULL}, 1, 0, S_ARMB3 }, // S_ARMB2
{SPR_ARMB, FF_FULLBRIGHT| 2, 3, {NULL}, 1, 0, S_ARMB4 }, // S_ARMB3
{SPR_ARMB, FF_FULLBRIGHT| 3, 3, {NULL}, 1, 0, S_ARMB5 }, // S_ARMB4
{SPR_ARMB, FF_FULLBRIGHT| 4, 3, {NULL}, 1, 0, S_ARMB6 }, // S_ARMB5
{SPR_ARMB, FF_FULLBRIGHT| 5, 3, {NULL}, 1, 0, S_ARMB7 }, // S_ARMB6
{SPR_ARMB, FF_FULLBRIGHT| 6, 3, {NULL}, 1, 0, S_ARMB8 }, // S_ARMB7
{SPR_ARMB, FF_FULLBRIGHT| 7, 3, {NULL}, 1, 0, S_ARMB9 }, // S_ARMB8
{SPR_ARMB, FF_FULLBRIGHT| 8, 3, {NULL}, 1, 0, S_ARMB10}, // S_ARMB9
{SPR_ARMB, FF_FULLBRIGHT| 9, 3, {NULL}, 1, 0, S_ARMB11}, // S_ARMB10
{SPR_ARMB, FF_FULLBRIGHT|10, 3, {NULL}, 1, 0, S_ARMB12}, // S_ARMB11
{SPR_ARMB, FF_FULLBRIGHT|11, 3, {NULL}, 1, 0, S_ARMB13}, // S_ARMB12
{SPR_ARMB, FF_FULLBRIGHT|12, 3, {NULL}, 1, 0, S_ARMB14}, // S_ARMB13
{SPR_ARMB, FF_FULLBRIGHT|13, 3, {NULL}, 1, 0, S_ARMB15}, // S_ARMB14
{SPR_ARMB, FF_FULLBRIGHT|14, 3, {NULL}, 1, 0, S_ARMB16}, // S_ARMB15
{SPR_ARMB, FF_FULLBRIGHT|15, 3, {NULL}, 1, 0, S_ARMB1 }, // S_ARMB16
{SPR_ARMB, FF_FULLBRIGHT , 2, {NULL}, 1, 0, S_ARMB2 }, // S_ARMB1
{SPR_ARMB, FF_FULLBRIGHT| 1, 2, {NULL}, 1, 0, S_ARMB3 }, // S_ARMB2
{SPR_ARMB, FF_FULLBRIGHT| 2, 2, {NULL}, 1, 0, S_ARMB4 }, // S_ARMB3
{SPR_ARMB, FF_FULLBRIGHT| 3, 2, {NULL}, 1, 0, S_ARMB5 }, // S_ARMB4
{SPR_ARMB, FF_FULLBRIGHT| 4, 2, {NULL}, 1, 0, S_ARMB6 }, // S_ARMB5
{SPR_ARMB, FF_FULLBRIGHT| 5, 2, {NULL}, 1, 0, S_ARMB7 }, // S_ARMB6
{SPR_ARMB, FF_FULLBRIGHT| 6, 2, {NULL}, 1, 0, S_ARMB8 }, // S_ARMB7
{SPR_ARMB, FF_FULLBRIGHT| 7, 2, {NULL}, 1, 0, S_ARMB9 }, // S_ARMB8
{SPR_ARMB, FF_FULLBRIGHT| 8, 2, {NULL}, 1, 0, S_ARMB10}, // S_ARMB9
{SPR_ARMB, FF_FULLBRIGHT| 9, 2, {NULL}, 1, 0, S_ARMB11}, // S_ARMB10
{SPR_ARMB, FF_FULLBRIGHT|10, 2, {NULL}, 1, 0, S_ARMB12}, // S_ARMB11
{SPR_ARMB, FF_FULLBRIGHT|11, 2, {NULL}, 1, 0, S_ARMB13}, // S_ARMB12
{SPR_ARMB, FF_FULLBRIGHT|12, 2, {NULL}, 1, 0, S_ARMB14}, // S_ARMB13
{SPR_ARMB, FF_FULLBRIGHT|13, 2, {NULL}, 1, 0, S_ARMB15}, // S_ARMB14
{SPR_ARMB, FF_FULLBRIGHT|14, 2, {NULL}, 1, 0, S_ARMB16}, // S_ARMB15
{SPR_ARMB, FF_FULLBRIGHT|15, 2, {NULL}, 1, 0, S_ARMB17}, // S_ARMB16
{SPR_ARMF, FF_FULLBRIGHT , 2, {NULL}, 1, 0, S_ARMB18}, // S_ARMB17
{SPR_ARMF, FF_FULLBRIGHT| 1, 2, {NULL}, 1, 0, S_ARMB19}, // S_ARMB18
{SPR_ARMF, FF_FULLBRIGHT| 2, 2, {NULL}, 1, 0, S_ARMB20}, // S_ARMB19
{SPR_ARMF, FF_FULLBRIGHT| 3, 2, {NULL}, 1, 0, S_ARMB21}, // S_ARMB20
{SPR_ARMF, FF_FULLBRIGHT| 4, 2, {NULL}, 1, 0, S_ARMB22}, // S_ARMB21
{SPR_ARMF, FF_FULLBRIGHT| 5, 2, {NULL}, 1, 0, S_ARMB23}, // S_ARMB22
{SPR_ARMF, FF_FULLBRIGHT| 6, 2, {NULL}, 1, 0, S_ARMB24}, // S_ARMB23
{SPR_ARMF, FF_FULLBRIGHT| 7, 2, {NULL}, 1, 0, S_ARMB25}, // S_ARMB24
{SPR_ARMF, FF_FULLBRIGHT| 8, 2, {NULL}, 1, 0, S_ARMB26}, // S_ARMB25
{SPR_ARMF, FF_FULLBRIGHT| 9, 2, {NULL}, 1, 0, S_ARMB27}, // S_ARMB26
{SPR_ARMF, FF_FULLBRIGHT|10, 2, {NULL}, 1, 0, S_ARMB28}, // S_ARMB27
{SPR_ARMF, FF_FULLBRIGHT|11, 2, {NULL}, 1, 0, S_ARMB29}, // S_ARMB28
{SPR_ARMF, FF_FULLBRIGHT|12, 2, {NULL}, 1, 0, S_ARMB30}, // S_ARMB29
{SPR_ARMF, FF_FULLBRIGHT|13, 2, {NULL}, 1, 0, S_ARMB31}, // S_ARMB30
{SPR_ARMF, FF_FULLBRIGHT|14, 2, {NULL}, 1, 0, S_ARMB32}, // S_ARMB31
{SPR_ARMF, FF_FULLBRIGHT|15, 2, {NULL}, 1, 0, S_ARMB1 }, // S_ARMB32
{SPR_WIND, FF_TRANS70 , 2, {NULL}, 0, 0, S_WIND2}, // S_WIND1
{SPR_WIND, FF_TRANS70|1, 2, {NULL}, 0, 0, S_WIND3}, // S_WIND2
@ -2735,8 +2768,6 @@ state_t states[NUMSTATES] =
// CTF Sign
{SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG
{SPR_GFLG, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTREDFLAG
{SPR_GFLG, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTBLUEFLAG
{SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK
@ -3121,11 +3152,15 @@ state_t states[NUMSTATES] =
{SPR_SPRK, FF_TRANS90|3, 1, {NULL}, 0, 0, S_NULL}, // S_SPRK16
// Robot Explosion
{SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY
{SPR_BOM1, 0, 1, {A_Scream}, 0, 0, S_XPLD2}, // S_XPLD1
{SPR_BOM1, FF_ANIMATE|1, 15, {NULL}, 2, 5, S_NULL}, // S_XPLD2
{SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY
{SPR_BOM1, 0, 2, {A_Scream}, 0, 0, S_XPLD2}, // S_XPLD1
{SPR_BOM1, 1, 2, {NULL}, 0, 0, S_XPLD3}, // S_XPLD2
{SPR_BOM1, 2, 3, {NULL}, 0, 0, S_XPLD4}, // S_XPLD3
{SPR_BOM1, 3, 3, {NULL}, 0, 0, S_XPLD5}, // S_XPLD4
{SPR_BOM1, 4, 4, {NULL}, 0, 0, S_XPLD6}, // S_XPLD5
{SPR_BOM1, 5, 4, {NULL}, 0, 0, S_NULL}, // S_XPLD6
{SPR_BOM1, FF_ANIMATE, 20, {NULL}, 3, 5, S_INVISIBLE}, // S_XPLD_EGGTRAP
{SPR_BOM1, FF_ANIMATE, 21, {NULL}, 5, 4, S_INVISIBLE}, // S_XPLD_EGGTRAP
// Underwater Explosion
{SPR_BOM4, 0, 3, {A_Scream}, 0, 0, S_WPLD2}, // S_WPLD1
@ -6386,8 +6421,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_RING_ICON, // damage
@ -6413,8 +6448,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_PITY_ICON, // damage
@ -6440,8 +6475,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_ATTRACT_ICON,// damage
@ -6467,8 +6502,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_FORCE_ICON, // damage
@ -6494,8 +6529,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_ARMAGEDDON_ICON, // damage
@ -6521,8 +6556,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_WHIRLWIND_ICON, // damage
@ -6548,8 +6583,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_ELEMENTAL_ICON, // damage
@ -6575,8 +6610,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_SNEAKERS_ICON, // damage
@ -6602,8 +6637,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_INVULN_ICON, // damage
@ -6629,8 +6664,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_1UP_ICON, // damage
@ -6656,8 +6691,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_EGGMAN_ICON, // damage
@ -6683,8 +6718,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_MIXUP_ICON, // damage
@ -6710,8 +6745,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_UNKNOWN, // damage
@ -6737,8 +6772,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_GRAVITY_ICON, // damage
@ -6764,8 +6799,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_RECYCLER_ICON, // damage
@ -6791,8 +6826,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_SCORE1K_ICON, // damage
@ -6818,8 +6853,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_SCORE10K_ICON, // damage
@ -6845,8 +6880,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_FLAMEAURA_ICON, // damage
@ -6872,8 +6907,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_BUBBLEWRAP_ICON, // damage
@ -6899,8 +6934,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_THUNDERCOIN_ICON, // damage
@ -6926,8 +6961,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_PITY_ICON, // damage
@ -6953,8 +6988,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_ATTRACT_ICON,// damage
@ -6980,8 +7015,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_FORCE_ICON, // damage
@ -7007,8 +7042,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_ARMAGEDDON_ICON, // damage
@ -7034,8 +7069,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_WHIRLWIND_ICON, // damage
@ -7061,8 +7096,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_ELEMENTAL_ICON, // damage
@ -7088,8 +7123,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_SNEAKERS_ICON, // damage
@ -7115,8 +7150,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_INVULN_ICON, // damage
@ -7142,8 +7177,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_EGGMAN_ICON, // damage
@ -7169,8 +7204,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_GRAVITY_ICON, // damage
@ -7196,8 +7231,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_FLAMEAURA_ICON, // damage
@ -7223,8 +7258,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_BUBBLEWRAP_ICON, // damage
@ -7250,8 +7285,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
36*FRACUNIT, // height
20*FRACUNIT, // radius
44*FRACUNIT, // height
0, // display offset
100, // mass
MT_THUNDERCOIN_ICON, // damage
@ -7277,8 +7312,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_RING_ICON, // damage
@ -7304,8 +7339,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_pop, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
18*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
MT_RING_ICON, // damage
@ -9011,7 +9046,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9038,7 +9073,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9065,7 +9100,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9092,7 +9127,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9119,7 +9154,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9146,7 +9181,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
200, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9173,7 +9208,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
200, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -9195,7 +9230,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
24*FRACUNIT, // speed
24*FRACUNIT, // radius
48*FRACUNIT, // height
32*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage

View File

@ -1834,6 +1834,7 @@ typedef enum state
S_BOXSPARKLE1,
S_BOXSPARKLE2,
S_BOXSPARKLE3,
S_BOXSPARKLE4,
S_BOX_FLICKER,
S_BOX_POP1,
@ -2329,6 +2330,22 @@ typedef enum state
S_ARMF14,
S_ARMF15,
S_ARMF16,
S_ARMF17,
S_ARMF18,
S_ARMF19,
S_ARMF20,
S_ARMF21,
S_ARMF22,
S_ARMF23,
S_ARMF24,
S_ARMF25,
S_ARMF26,
S_ARMF27,
S_ARMF28,
S_ARMF29,
S_ARMF30,
S_ARMF31,
S_ARMF32,
S_ARMB1,
S_ARMB2,
@ -2346,6 +2363,22 @@ typedef enum state
S_ARMB14,
S_ARMB15,
S_ARMB16,
S_ARMB17,
S_ARMB18,
S_ARMB19,
S_ARMB20,
S_ARMB21,
S_ARMB22,
S_ARMB23,
S_ARMB24,
S_ARMB25,
S_ARMB26,
S_ARMB27,
S_ARMB28,
S_ARMB29,
S_ARMB30,
S_ARMB31,
S_ARMB32,
S_WIND1,
S_WIND2,
@ -2826,8 +2859,6 @@ typedef enum state
// Got Flag Sign
S_GOTFLAG,
S_GOTREDFLAG,
S_GOTBLUEFLAG,
S_CORK,
@ -3167,6 +3198,10 @@ typedef enum state
S_XPLD_FLICKY,
S_XPLD1,
S_XPLD2,
S_XPLD3,
S_XPLD4,
S_XPLD5,
S_XPLD6,
S_XPLD_EGGTRAP,
// Underwater Explosion

View File

@ -214,15 +214,7 @@ static int lib_pRandomRange(lua_State *L)
return 1;
}
// Deprecated, macros, etc.
static int lib_pRandom(lua_State *L)
{
NOHUD
LUA_Deprecated(L, "P_Random", "P_RandomByte");
lua_pushinteger(L, P_RandomByte());
return 1;
}
// Macros.
static int lib_pSignedRandom(lua_State *L)
{
NOHUD
@ -776,6 +768,19 @@ static int lib_pCanRunOnWater(lua_State *L)
return 1;
}
static int lib_pMaceRotate(lua_State *L)
{
mobj_t *center = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
INT32 baserot = luaL_checkinteger(L, 2);
INT32 baseprevrot = luaL_checkinteger(L, 3);
NOHUD
INLEVEL
if (!center)
return LUA_ErrInvalid(L, "mobj_t");
P_MaceRotate(center, baserot, baseprevrot);
return 0;
}
// P_USER
////////////
@ -2481,7 +2486,6 @@ static luaL_Reg lib[] = {
{"P_RandomByte",lib_pRandomByte},
{"P_RandomKey",lib_pRandomKey},
{"P_RandomRange",lib_pRandomRange},
{"P_Random",lib_pRandom}, // DEPRECATED
{"P_SignedRandom",lib_pSignedRandom}, // MACRO
{"P_RandomChance",lib_pRandomChance}, // MACRO
@ -2526,6 +2530,7 @@ static luaL_Reg lib[] = {
{"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide},
{"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_MaceRotate",lib_pMaceRotate},
// p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight},

View File

@ -20,6 +20,7 @@
#include "i_video.h" // rendermode
#include "p_local.h" // camera_t
#include "screen.h" // screen width/height
#include "m_random.h" // m_random
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
@ -63,12 +64,14 @@ static const char *const hud_disable_options[] = {
enum hudinfo {
hudinfo_x = 0,
hudinfo_y
hudinfo_y,
hudinfo_f
};
static const char *const hudinfo_opt[] = {
"x",
"y",
"f",
NULL};
enum patch {
@ -198,6 +201,9 @@ static int hudinfo_get(lua_State *L)
case hudinfo_y:
lua_pushinteger(L, info->y);
break;
case hudinfo_f:
lua_pushinteger(L, info->f);
break;
}
return 1;
}
@ -216,6 +222,9 @@ static int hudinfo_set(lua_State *L)
case hudinfo_y:
info->y = (INT32)luaL_checkinteger(L, 3);
break;
case hudinfo_f:
info->f = (INT32)luaL_checkinteger(L, 3);
break;
}
return 0;
}
@ -679,6 +688,30 @@ static int libd_getColormap(lua_State *L)
return 1;
}
static int libd_fadeScreen(lua_State *L)
{
UINT16 color = luaL_checkinteger(L, 1);
UINT8 strength = luaL_checkinteger(L, 2);
const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10);
HUDONLY
if (!strength)
return 0;
if (strength > maxstrength)
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
if (strength == maxstrength) // Allow as a shortcut for drawfill...
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
return 0;
}
V_DrawFadeScreen(color, strength);
return 0;
}
static int libd_width(lua_State *L)
{
HUDONLY
@ -720,19 +753,92 @@ static int libd_renderer(lua_State *L)
return 1;
}
// M_RANDOM
//////////////
static int libd_RandomFixed(lua_State *L)
{
HUDONLY
lua_pushfixed(L, M_RandomFixed());
return 1;
}
static int libd_RandomByte(lua_State *L)
{
HUDONLY
lua_pushinteger(L, M_RandomByte());
return 1;
}
static int libd_RandomKey(lua_State *L)
{
INT32 a = (INT32)luaL_checkinteger(L, 1);
HUDONLY
if (a > 65536)
LUA_UsageWarning(L, "v.RandomKey: range > 65536 is undefined behavior");
lua_pushinteger(L, M_RandomKey(a));
return 1;
}
static int libd_RandomRange(lua_State *L)
{
INT32 a = (INT32)luaL_checkinteger(L, 1);
INT32 b = (INT32)luaL_checkinteger(L, 2);
HUDONLY
if (b < a) {
INT32 c = a;
a = b;
b = c;
}
if ((b-a+1) > 65536)
LUA_UsageWarning(L, "v.RandomRange: range > 65536 is undefined behavior");
lua_pushinteger(L, M_RandomRange(a, b));
return 1;
}
// Macros.
static int libd_SignedRandom(lua_State *L)
{
HUDONLY
lua_pushinteger(L, M_SignedRandom());
return 1;
}
static int libd_RandomChance(lua_State *L)
{
fixed_t p = luaL_checkfixed(L, 1);
HUDONLY
lua_pushboolean(L, M_RandomChance(p));
return 1;
}
static luaL_Reg lib_draw[] = {
// cache
{"patchExists", libd_patchExists},
{"cachePatch", libd_cachePatch},
{"getSpritePatch", libd_getSpritePatch},
{"getSprite2Patch", libd_getSprite2Patch},
{"getColormap", libd_getColormap},
// drawing
{"draw", libd_draw},
{"drawScaled", libd_drawScaled},
{"drawNum", libd_drawNum},
{"drawPaddedNum", libd_drawPaddedNum},
{"drawFill", libd_drawFill},
{"drawString", libd_drawString},
{"fadeScreen", libd_fadeScreen},
// misc
{"stringWidth", libd_stringWidth},
{"getColormap", libd_getColormap},
// m_random
{"RandomFixed",libd_RandomFixed},
{"RandomByte",libd_RandomByte},
{"RandomKey",libd_RandomKey},
{"RandomRange",libd_RandomRange},
{"SignedRandom",libd_SignedRandom}, // MACRO
{"RandomChance",libd_RandomChance}, // MACRO
// properties
{"width", libd_width},
{"height", libd_height},
{"dupx", libd_dupx},

View File

@ -530,10 +530,22 @@ static int mobj_set(lua_State *L)
case mobj_bprev:
return UNIMPLEMENTED;
case mobj_hnext:
mo->hnext = luaL_checkudata(L, 3, META_MOBJ);
if (lua_isnil(L, 3))
P_SetTarget(&mo->hnext, NULL);
else
{
mobj_t *hnext = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&mo->hnext, hnext);
}
break;
case mobj_hprev:
mo->hprev = luaL_checkudata(L, 3, META_MOBJ);
if (lua_isnil(L, 3))
P_SetTarget(&mo->hprev, NULL);
else
{
mobj_t *hprev = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&mo->hprev, hprev);
}
break;
case mobj_type: // yeah sure, we'll let you change the mobj's type.
{

View File

@ -524,10 +524,10 @@ static const struct {
{NULL, ARCH_NULL}
};
static UINT8 GetUserdataArchType(void)
static UINT8 GetUserdataArchType(int index)
{
UINT8 i;
lua_getmetatable(gL, -1);
lua_getmetatable(gL, index);
for (i = 0; meta2arch[i].meta; i++)
{
@ -606,7 +606,7 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
break;
}
case LUA_TUSERDATA:
switch (GetUserdataArchType())
switch (GetUserdataArchType(myindex))
{
case ARCH_MOBJINFO:
{
@ -881,6 +881,7 @@ static void ArchiveTables(void)
CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1));
lua_pop(gL, 1);
}
lua_pop(gL, 1);
}
lua_pop(gL, 1);

View File

@ -1266,7 +1266,7 @@ void Command_ObjectPlace_f(void)
if (!COM_CheckParm("-silent"))
{
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE);
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT);
HU_SetCEchoDuration(10);
HU_DoCEcho(va(M_GetText(
"\\\\\\\\\\\\\\\\\\\\\\\\\x82"

View File

@ -33,7 +33,9 @@
*/
fixed_t FixedMul(fixed_t a, fixed_t b)
{
return (fixed_t)((((INT64)a * b) ) / FRACUNIT);
// Need to cast to unsigned before shifting to avoid undefined behaviour
// for negative integers
return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS);
}
#endif //__USE_C_FIXEDMUL__

View File

@ -1188,7 +1188,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
#endif
{IT_HEADER, NULL, "Color Profile", NULL, 30},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness (F11)", &cv_globalgamma, 36},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness (F11)", &cv_globalgamma,36},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_globalsaturation, 41},
{IT_SUBMENU|IT_STRING, NULL, "Advanced Settings...", &OP_ColorOptionsDef, 46},
@ -1196,24 +1196,25 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 61},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
NULL, "HUD Transparency", &cv_translucenthud, 66},
{IT_STRING | IT_CVAR, NULL, "Time Display", &cv_timetic, 71},
{IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71},
{IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76},
#ifdef SEENAMES
{IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 76},
{IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 81},
#endif
{IT_HEADER, NULL, "Console", NULL, 85},
{IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 91},
{IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 96},
{IT_HEADER, NULL, "Console", NULL, 90},
{IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 96},
{IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 101},
{IT_HEADER, NULL, "Level", NULL, 105},
{IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 111},
{IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist.", &cv_drawdist_nights, 116},
{IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 121},
{IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 126},
{IT_HEADER, NULL, "Level", NULL, 110},
{IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 116},
{IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist.", &cv_drawdist_nights, 121},
{IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 126},
{IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 131},
{IT_HEADER, NULL, "Diagnostic", NULL, 135},
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 141},
{IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 146},
{IT_HEADER, NULL, "Diagnostic", NULL, 140},
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 146},
{IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 151},
};
static menuitem_t OP_VideoModeMenu[] =
@ -2049,35 +2050,7 @@ static void Newgametype_OnChange(void)
P_AllocMapHeader((INT16)(cv_nextmap.value-1));
if (!M_CanShowLevelOnPlatter(cv_nextmap.value-1, cv_newgametype.value))
{
INT32 value = 0;
switch (cv_newgametype.value)
{
case GT_COOP:
value = TOL_COOP;
break;
case GT_COMPETITION:
value = TOL_COMPETITION;
break;
case GT_RACE:
value = TOL_RACE;
break;
case GT_MATCH:
case GT_TEAMMATCH:
value = TOL_MATCH;
break;
case GT_TAG:
case GT_HIDEANDSEEK:
value = TOL_TAG;
break;
case GT_CTF:
value = TOL_CTF;
break;
}
CV_SetValue(&cv_nextmap, M_GetFirstLevelInList(value));
}
CV_SetValue(&cv_nextmap, M_GetFirstLevelInList(cv_newgametype.value));
}
}
@ -2611,7 +2584,7 @@ void M_Drawer(void)
{
// now that's more readable with a faded background (yeah like Quake...)
if (!WipeInAction)
V_DrawFadeScreen();
V_DrawFadeScreen(0xFF00, 16);
if (currentMenu->drawroutine)
currentMenu->drawroutine(); // call current menu Draw routine
@ -4453,14 +4426,14 @@ static void M_DrawLevelPlatterMenu(void)
V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
// finds row at top of the screen
while (y > 0)
while (y > -8)
{
iter = ((iter == 0) ? levelselect.numrows-1 : iter-1);
y -= lsvseperation(iter);
}
// draw from top to bottom
while (y < 200)
while (y < (vid.height/vid.dupy))
{
M_DrawLevelPlatterRow(iter, y);
y += lsvseperation(iter);
@ -5710,7 +5683,7 @@ static void M_DrawChecklist(void)
beat = va("Get %d points in %s", cond[condnum].requirement, level);
break;
case UC_MAPTIME:
beat = va("Beat %s in %d:%d.%d", level,
beat = va("Beat %s in %d:%02d.%02d", level,
G_TicsToMinutes(cond[condnum].requirement, true),
G_TicsToSeconds(cond[condnum].requirement),
G_TicsToCentiseconds(cond[condnum].requirement));
@ -5735,7 +5708,7 @@ static void M_DrawChecklist(void)
beat = va("Get %d points over all maps", cond[condnum].requirement);
break;
case UC_OVERALLTIME:
beat = va("Get a total time of less than %d:%d.%d",
beat = va("Get a total time of less than %d:%02d.%02d",
G_TicsToMinutes(cond[condnum].requirement, true),
G_TicsToSeconds(cond[condnum].requirement),
G_TicsToCentiseconds(cond[condnum].requirement));
@ -5783,12 +5756,12 @@ static void M_DrawChecklist(void)
break;
case UC_NIGHTSTIME:
if (cond[condnum].extrainfo2)
beat = va("Beat %s, mare %d in %d:%d.%d", level, cond[condnum].extrainfo2,
beat = va("Beat %s, mare %d in %d:%02d.%02d", level, cond[condnum].extrainfo2,
G_TicsToMinutes(cond[condnum].requirement, true),
G_TicsToSeconds(cond[condnum].requirement),
G_TicsToCentiseconds(cond[condnum].requirement));
else
beat = va("Beat %s in %d:%d.%d",
beat = va("Beat %s in %d:%02d.%02d",
level,
G_TicsToMinutes(cond[condnum].requirement, true),
G_TicsToSeconds(cond[condnum].requirement),
@ -6193,7 +6166,7 @@ static void M_DrawLoadGameData(void)
{
V_DrawSmallScaledPatch(x+2, y+64, 0, savselp[5]);
}
#ifndef PERFECTSAVE // disabled, don't touch
#ifdef PERFECTSAVE // disabled on request
else if ((savegameinfo[savetodraw].skinnum == 1)
&& (savegameinfo[savetodraw].lives == 99)
&& (savegameinfo[savetodraw].gamemap & 8192)
@ -6281,7 +6254,7 @@ static void M_DrawLoadGameData(void)
for (j = 0; j < 7; ++j)
{
if (savegameinfo[savetodraw].numemeralds & (1 << j))
V_DrawScaledPatch(workx, y, 0, tinyemeraldpics[j]);
V_DrawScaledPatch(workx, y, 0, emeraldpics[1][j]);
workx += 10;
}
}
@ -8468,6 +8441,13 @@ Update the maxplayers label...
static void M_ConnectIP(INT32 choice)
{
(void)choice;
if (*setupm_ip == 0)
{
M_StartMessage("You must specify an IP address.\n", NULL, MM_NOTHING);
return;
}
COM_BufAddText(va("connect \"%s\"\n", setupm_ip));
// A little "please wait" message.

View File

@ -3243,14 +3243,7 @@ void A_ExtraLife(mobj_t *actor)
return;
}
// In shooter gametypes, give the player 100 rings instead of an extra life.
if (gametype != GT_COOP && gametype != GT_COMPETITION)
{
P_GivePlayerRings(player, 100);
P_PlayLivesJingle(player);
}
else
P_GiveCoopLives(player, 1, true);
P_GiveCoopLives(player, 1, true);
}
// Function: A_GiveShield
@ -4917,6 +4910,7 @@ void A_SlingAppear(mobj_t *actor)
boolean firsttime = true;
UINT8 mlength = 4;
mobj_t *spawnee;
mobj_t *hprev = actor;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SlingAppear", actor))
return;
@ -4927,7 +4921,6 @@ void A_SlingAppear(mobj_t *actor)
P_SetThingPosition(actor);
actor->lastlook = 128;
actor->movecount = actor->lastlook;
actor->health = actor->angle>>ANGLETOFINESHIFT;
actor->threshold = 0;
actor->movefactor = actor->threshold;
actor->friction = 128;
@ -4936,10 +4929,13 @@ void A_SlingAppear(mobj_t *actor)
{
spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN);
P_SetTarget(&spawnee->target, actor);
P_SetTarget(&spawnee->tracer, actor);
P_SetTarget(&spawnee->hprev, hprev);
P_SetTarget(&hprev->hnext, spawnee);
hprev = spawnee;
spawnee->threshold = 0;
spawnee->reactiontime = mlength;
spawnee->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT;
spawnee->movecount = mlength;
if (firsttime)
{

View File

@ -2144,6 +2144,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
boolean floortouch = false;
fixed_t bottomheight, topheight;
msecnode_t *node;
ffloor_t *rover;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -2191,6 +2192,19 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
{
targetsec = &sectors[targetsecnum];
// Find the FOF corresponding to the control linedef
for (rover = targetsec->ffloors; rover; rover = rover->next)
{
if (rover->master == sec->lines[i])
break;
}
if (!rover) // This should be impossible, but don't complain if it is the case somehow
continue;
if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there
continue;
for (j = 0; j < MAXPLAYERS; j++)
{
if (!playeringame[j])

View File

@ -577,25 +577,27 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_TOKEN:
if (player->bot)
return;
tokenlist += special->health;
P_AddPlayerScore(player, 1000);
if (!modeattacking) // score only there...
if (gametype != GT_COOP || modeattacking) // score only?
break;
tokenlist += special->health;
if (ALL7EMERALDS(emeralds)) // Got all 7
{
if (ALL7EMERALDS(emeralds)) // Got all 7
if (!(netgame || multiplayer))
{
if (!(netgame || multiplayer))
{
player->continues += 1;
players->gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
}
player->continues += 1;
players->gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
}
else
token++;
}
else
token++;
break;
// Emerald Hunt
@ -1503,10 +1505,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->powers[pw_flashing])
return;
if (special->movefactor && special->tracer && (angle_t)special->tracer->health != ANGLE_90 && (angle_t)special->tracer->health != ANGLE_270)
if (special->movefactor && special->tracer && special->tracer->angle != ANGLE_90 && special->tracer->angle != ANGLE_270)
{ // I don't expect you to understand this, Mr Bond...
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->threshold;
if ((special->movefactor > 0) == ((angle_t)special->tracer->health > ANGLE_90 && (angle_t)special->tracer->health < ANGLE_270))
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->angle;
if ((special->movefactor > 0) == (special->tracer->angle > ANGLE_90 && special->tracer->angle < ANGLE_270))
ang += ANGLE_180;
if (ang < ANGLE_180)
return; // I expect you to die.
@ -3365,8 +3367,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
P_KillPlayer(player, source, damage);
}
P_HitDeathMessages(player, inflictor, source, damagetype);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
}
@ -3381,6 +3381,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
else
target->health -= damage;
if (player)
P_HitDeathMessages(player, inflictor, source, damagetype);
if (source && source->player && target)
G_GhostAddHit(target);

View File

@ -280,6 +280,8 @@ mobj_t *P_GetClosestAxis(mobj_t *source);
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover);
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot);
void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration);
#define PAL_WHITE 1
#define PAL_MIXUP 2

View File

@ -6176,124 +6176,217 @@ static void P_NightsItemChase(mobj_t *thing)
//
// P_MaceRotate
// Spins an object around its target, or, swings it from side to side.
// Spins a hnext-chain of objects around its centerpoint, side to side or periodically.
//
static void P_MaceRotate(mobj_t *mobj)
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
{
TVector v;
TVector unit_lengthways, unit_sideways, pos_lengthways, pos_sideways;
TVector *res;
fixed_t radius, dist;
fixed_t radius, dist, zstore;
angle_t fa;
INT32 prevswing;
boolean donetwice = false;
boolean dosound = false;
mobj_t *mobj = center->hnext, *hnext = NULL;
// Tracer was removed.
if (!mobj->health)
return;
else if (!mobj->tracer)
INT32 rot = (baserot &= FINEMASK);
INT32 prevrot = (baseprevrot &= FINEMASK);
INT32 lastthreshold = FINEMASK; // needs to never be equal at start of loop
fixed_t lastfriction = INT32_MIN; // ditto; almost certainly never, but...
dist = pos_sideways[0] = pos_sideways[1] = pos_sideways[2] = pos_sideways[3] = unit_sideways[3] = pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
while (mobj)
{
P_KillMobj(mobj, NULL, NULL, 0);
return;
}
if (!mobj->health)
{
mobj = mobj->hnext;
continue;
}
mobj->momx = mobj->momy = mobj->momz = 0;
mobj->momx = mobj->momy = mobj->momz = 0;
prevswing = mobj->threshold;
mobj->threshold += mobj->tracer->lastlook;
mobj->threshold &= FINEMASK;
if (mobj->threshold != lastthreshold
|| mobj->friction != lastfriction)
{
rot = (baserot + mobj->threshold) & FINEMASK;
prevrot = (baseprevrot + mobj->threshold) & FINEMASK;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
// Radius of the link's rotation.
radius = FixedMul(dist * mobj->movecount, mobj->tracer->scale) + mobj->tracer->extravalue1;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
dist = ((center->scale == FRACUNIT) ? dist : FixedMul(dist, center->scale));
maceretry:
fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
radius = FixedMul(dist, FINECOSINE(fa));
unit_lengthways[1] = -FixedMul(dist, FINESINE(fa));
unit_lengthways[3] = FRACUNIT;
fa = (FixedAngle(mobj->tracer->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
radius = FixedMul(FINECOSINE(fa), radius);
v[1] = -FixedMul(FINESINE(fa), radius)
+ FixedMul(dist * mobj->movefactor, mobj->tracer->scale);
v[3] = FRACUNIT;
// Swinging Chain.
if (center->flags2 & MF2_STRONGBOX)
{
fixed_t swingmag = FixedMul(FINECOSINE(rot), center->lastlook << FRACBITS);
fixed_t prevswingmag = FINECOSINE(prevrot);
// Swinging Chain.
if (mobj->tracer->flags2 & MF2_STRONGBOX)
{
fixed_t swingmagnitude = FixedMul(FINECOSINE(mobj->threshold), mobj->tracer->lastlook << FRACBITS);
prevswing = FINECOSINE(prevswing);
if ((prevswingmag > 0) != (swingmag > 0)) // just passed its lowest point
dosound = true;
if (!donetwice
&& (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
&& ((prevswing > 0) != (swingmagnitude > 0))) // just passed its lowest point
fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
unit_lengthways[0] = FixedMul(FINESINE(fa), -radius);
unit_lengthways[2] = FixedMul(FINECOSINE(fa), -radius);
}
// Rotating Chain.
else
{
angle_t prevfa = (prevrot + mobj->friction) & FINEMASK;
fa = (rot + mobj->friction) & FINEMASK;
if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing
dosound = true;
unit_lengthways[0] = FixedMul(FINECOSINE(fa), radius);
unit_lengthways[2] = FixedMul(FINESINE(fa), radius);
}
// Calculate the angle matrixes for the link.
res = VectorMatrixMultiply(unit_lengthways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
res = VectorMatrixMultiply(unit_lengthways, *RotateZMatrix(center->angle));
M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
lastthreshold = mobj->threshold;
lastfriction = mobj->friction;
}
if (dosound && (mobj->flags2 & MF2_BOSSNOTRAP))
{
S_StartSound(mobj, mobj->info->activesound);
dosound = false;
}
fa = ((FixedAngle(swingmagnitude) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
if (pos_sideways[3] != mobj->movefactor)
{
if (!unit_sideways[3])
{
unit_sideways[1] = dist;
unit_sideways[0] = unit_sideways[2] = 0;
unit_sideways[3] = FRACUNIT;
v[0] = FixedMul(FINESINE(fa), -radius);
v[2] = FixedMul(FINECOSINE(fa), -radius);
res = VectorMatrixMultiply(unit_sideways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
res = VectorMatrixMultiply(unit_sideways, *RotateZMatrix(center->angle));
M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
}
if (pos_sideways[3] > mobj->movefactor)
{
do
{
pos_sideways[0] -= unit_sideways[0];
pos_sideways[1] -= unit_sideways[1];
pos_sideways[2] -= unit_sideways[2];
}
while ((--pos_sideways[3]) != mobj->movefactor);
}
else
{
do
{
pos_sideways[0] += unit_sideways[0];
pos_sideways[1] += unit_sideways[1];
pos_sideways[2] += unit_sideways[2];
}
while ((++pos_sideways[3]) != mobj->movefactor);
}
}
hnext = mobj->hnext; // just in case the mobj is removed
if (pos_lengthways[3] > mobj->movecount)
{
do
{
pos_lengthways[0] -= unit_lengthways[0];
pos_lengthways[1] -= unit_lengthways[1];
pos_lengthways[2] -= unit_lengthways[2];
}
while ((--pos_lengthways[3]) != mobj->movecount);
}
else if (pos_lengthways[3] < mobj->movecount)
{
do
{
pos_lengthways[0] += unit_lengthways[0];
pos_lengthways[1] += unit_lengthways[1];
pos_lengthways[2] += unit_lengthways[2];
}
while ((++pos_lengthways[3]) != mobj->movecount);
}
P_UnsetThingPosition(mobj);
mobj->x = center->x;
mobj->y = center->y;
mobj->z = center->z;
// Add on the appropriate distances to the center's co-ordinates.
if (pos_lengthways[3])
{
mobj->x += pos_lengthways[0];
mobj->y += pos_lengthways[1];
zstore = pos_lengthways[2] + pos_sideways[2];
}
else
zstore = pos_sideways[2];
mobj->x += pos_sideways[0];
mobj->y += pos_sideways[1];
// Cut the height to align the link with the axis.
if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
zstore -= P_MobjFlip(mobj)*mobj->height/4;
else
zstore -= P_MobjFlip(mobj)*mobj->height/2;
mobj->z += zstore;
#if 0 // toaster's testing flashie!
if (!(mobj->movecount & 1) && !(leveltime & TICRATE)) // I had a brainfart and the flashing isn't exactly what I expected it to be, but it's actually much more useful.
mobj->flags2 ^= MF2_DONTDRAW;
#endif
P_SetThingPosition(mobj);
#if 0 // toaster's height-clipping dealie!
if (!pos_lengthways[3] || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT))
goto cont;
if ((fa = ((center->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
goto cont;
if (mobj->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
if (mobj->floorz > mobj->z)
zstore = (mobj->floorz - zstore);
else if (mobj->ceilingz < mobj->z)
zstore = (mobj->ceilingz - mobj->height - zstore);
else
goto cont;
zstore = FixedDiv(zstore, dist); // Still needs work... scaling factor is wrong!
P_UnsetThingPosition(mobj);
mobj->x -= FixedMul(unit_lengthways[0], zstore);
mobj->y -= FixedMul(unit_lengthways[1], zstore);
P_SetThingPosition(mobj);
cont:
#endif
mobj = hnext;
}
// Rotating Chain.
else
{
prevswing = (prevswing + mobj->friction) & FINEMASK;
fa = (mobj->threshold + mobj->friction) & FINEMASK;
if (!donetwice
&& (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound
&& (!(prevswing > (FINEMASK/2)) && (fa > (FINEMASK/2)))) // completed a full swing
S_StartSound(mobj, mobj->info->activesound);
v[0] = FixedMul(FINECOSINE(fa), radius);
v[2] = FixedMul(FINESINE(fa), radius);
}
// Calculate the angle matrixes for the link.
res = VectorMatrixMultiply(v, *RotateXMatrix(mobj->tracer->threshold << ANGLETOFINESHIFT));
M_Memcpy(&v, res, sizeof(v));
res = VectorMatrixMultiply(v, *RotateZMatrix(mobj->tracer->health << ANGLETOFINESHIFT));
M_Memcpy(&v, res, sizeof(v));
// Cut the height to align the link with the axis.
if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN)
v[2] -= P_MobjFlip(mobj)*mobj->height/4;
else
v[2] -= P_MobjFlip(mobj)*mobj->height/2;
P_UnsetThingPosition(mobj);
// Add on the appropriate distances to the center's co-ordinates.
mobj->x = mobj->tracer->x + v[0];
mobj->y = mobj->tracer->y + v[1];
mobj->z = mobj->tracer->z + v[2];
P_SetThingPosition(mobj);
if (donetwice || P_MobjWasRemoved(mobj))
return;
if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT))
return;
if ((fa = ((mobj->tracer->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
return;
if (mobj->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2);
// Variable reuse
if (mobj->floorz > mobj->z)
dist = (mobj->floorz - mobj->tracer->z);
else if (mobj->ceilingz < mobj->z)
dist = (mobj->ceilingz - mobj->tracer->z);
else
return;
if ((dist = FixedDiv(dist, v[2])) > FRACUNIT)
return;
radius = FixedMul(radius, dist);
donetwice = true;
dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
goto maceretry;
}
static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
@ -6664,13 +6757,6 @@ void P_MobjThinker(mobj_t *mobj)
}
}
if (mobj->flags2 & MF2_MACEROTATE)
{
P_MaceRotate(mobj);
if (P_MobjWasRemoved(mobj))
return;
}
// Special thinker for scenery objects
if (mobj->flags & MF_SCENERY)
{
@ -6687,6 +6773,18 @@ void P_MobjThinker(mobj_t *mobj)
switch (mobj->type)
{
case MT_MACEPOINT:
case MT_CHAINMACEPOINT:
case MT_SPRINGBALLPOINT:
case MT_CHAINPOINT:
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
case MT_HIDDEN_SLING:
// The following was pretty good, but liked breaking whenever mobj->lastlook changed.
//P_MaceRotate(mobj, ((leveltime + 1) * mobj->lastlook), (leveltime * mobj->lastlook));
P_MaceRotate(mobj, mobj->movedir + mobj->lastlook, mobj->movedir);
mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK;
break;
case MT_HOOP:
if (mobj->fuse > 1)
P_MoveHoop(mobj);
@ -7337,19 +7435,6 @@ void P_MobjThinker(mobj_t *mobj)
}
}
break;
case MT_CHAINPOINT:
case MT_CHAINMACEPOINT:
if (leveltime & 1)
{
if (mobj->lastlook > mobj->movecount)
mobj->lastlook--;
/*
if (mobj->threshold > mobj->movefactor)
mobj->threshold -= FRACUNIT;
else if (mobj->threshold < mobj->movefactor)
mobj->threshold += FRACUNIT;*/
}
break;
case MT_EGGCAPSULE:
if (!mobj->reactiontime)
{
@ -8615,6 +8700,13 @@ void P_RemoveMobj(mobj_t *mobj)
// Remove any references to other mobjs.
P_SetTarget(&mobj->target, P_SetTarget(&mobj->tracer, NULL));
if (mobj->hnext && !P_MobjWasRemoved(mobj->hnext))
P_SetTarget(&mobj->hnext->hprev, mobj->hprev);
if (mobj->hprev && !P_MobjWasRemoved(mobj->hprev))
P_SetTarget(&mobj->hprev->hnext, mobj->hnext);
P_SetTarget(&mobj->hnext, P_SetTarget(&mobj->hprev, NULL));
// free block
// DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error.
if (mobj->flags & MF_NOTHINK && !mobj->thinker.next)
@ -9301,6 +9393,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
mobj_t *mobj;
fixed_t x, y, z;
subsector_t *ss;
boolean doangle = true;
if (!mthing->type)
return; // Ignore type-0 things as NOPs
@ -9539,7 +9632,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
// They're likely facets of the level's design and therefore required to progress.
}
if (i == MT_TOKEN && (gametype != GT_COOP || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++)))
if (i == MT_TOKEN && ((gametype != GT_COOP && gametype != GT_COMPETITION) || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++)))
return; // you already got this token, or there are too many, or the gametype's not right
// Objectplace landing point
@ -9706,11 +9799,11 @@ void P_SpawnMapThing(mapthing_t *mthing)
case MT_FIREBARPOINT:
case MT_CUSTOMMACEPOINT:
{
fixed_t mlength, mlengthset, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mnumspokesset, mpinch, mroll, mnumnospokes, mwidth, mmin, msound, radiusfactor;
fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor;
angle_t mspokeangle;
mobjtype_t chainlink, macetype, firsttype, linktype;
boolean mdoall = true;
mobj_t *spawnee;
boolean mdosound, mdocenter;
mobj_t *spawnee = NULL, *hprev = mobj;
mobjflag_t mflagsapply;
mobjflag2_t mflags2apply;
mobjeflag_t meflagsapply;
@ -9747,8 +9840,10 @@ ML_EFFECT4 : Don't clip inside the ground
mlength = abs(lines[line].dx >> FRACBITS);
mspeed = abs(lines[line].dy >> (FRACBITS - 4));
mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360;
if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> (FRACBITS - 4)) < mspeed)
mmaxspeed = mspeed << 1;
if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset>>FRACBITS) < 0)
mminlength = 0;
else if (mminlength > mlength-1)
mminlength = mlength-1;
mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360;
myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360;
@ -9767,30 +9862,29 @@ ML_EFFECT4 : Don't clip inside the ground
mpinch = mroll = mnumnospokes = mwidth = 0;
CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n"
"Length is %d\n"
"Length is %d (minus %d)\n"
"Speed is %d\n"
"Phase is %d\n"
"Yaw is %d\n"
"Pitch is %d\n"
"Max. speed is %d\n"
"No. of spokes is %d\n"
"No. of spokes is %d (%d antispokes)\n"
"Pinch is %d\n"
"Roll is %d\n"
"No. of antispokes is %d\n"
"Width is %d\n",
sizeu1(mthingi), mlength, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mpinch, mroll, mnumnospokes, mwidth);
sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth);
if (mnumnospokes > 0 && (mnumnospokes < mnumspokes))
mnumnospokes = mnumspokes/mnumnospokes;
else
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0);
mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0);
mobj->lastlook = mspeed;
mobj->movecount = mobj->lastlook;
mobj->health = (FixedAngle(myaw*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->angle = FixedAngle(myaw*FRACUNIT);
doangle = false;
mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT);
mobj->friction = mmaxspeed;
mobj->movefactor = mpinch;
mobj->movedir = 0;
// Mobjtype selection
switch(mobj->type)
@ -9828,7 +9922,7 @@ ML_EFFECT4 : Don't clip inside the ground
break;
}
if (!macetype)
if (!macetype && !chainlink)
break;
if (mobj->type != MT_CHAINPOINT)
@ -9857,7 +9951,7 @@ ML_EFFECT4 : Don't clip inside the ground
mmin = mnumspokes;
// Make the links the same type as the end - repeated below
if ((mobj->type != MT_CHAINPOINT) && ((lines[line].flags & ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or
if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or
{
linktype = macetype;
radiusfactor = 2; // Double the radius.
@ -9865,8 +9959,10 @@ ML_EFFECT4 : Don't clip inside the ground
else
radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1);
widthfactor = ((firsttype == chainlink) ? 1 : 2);
mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT));
mflags2apply = (MF2_MACEROTATE|((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0));
mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0);
meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0);
msound = ((firsttype == chainlink) ? 0 : (mwidth & 1));
@ -9875,25 +9971,27 @@ ML_EFFECT4 : Don't clip inside the ground
mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT);
mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT);
#define makemace(mobjtype, dist, moreflags2) P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
P_SetTarget(&spawnee->tracer, mobj);\
spawnee->threshold = mphase;\
spawnee->friction = mroll;\
spawnee->movefactor = mwidth;\
spawnee->movecount = dist;\
spawnee->angle = myaw;\
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
spawnee->flags2 |= (mflags2apply|moreflags2);\
spawnee->eflags |= meflagsapply
#define makemace(mobjtype, dist, moreflags2) {\
spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\
P_SetTarget(&spawnee->tracer, mobj);\
spawnee->threshold = mphase;\
spawnee->friction = mroll;\
spawnee->movefactor = mwidthset;\
spawnee->movecount = dist;\
spawnee->angle = myaw;\
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
spawnee->flags2 |= (mflags2apply|moreflags2);\
spawnee->eflags |= meflagsapply;\
P_SetTarget(&hprev->hnext, spawnee);\
P_SetTarget(&spawnee->hprev, hprev);\
hprev = spawnee;\
}
domaceagain:
mnumspokesset = mnumspokes;
if (mdoall && lines[line].flags & ML_EFFECT3) // Innermost mace/link
{ spawnee = makemace(macetype, 0, MF2_AMBUSH); }
mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL));
mdocenter = (macetype && (lines[line].flags & ML_EFFECT3));
// The actual spawning of spokes
while (mnumspokesset-- > 0)
while (mnumspokes-- > 0)
{
// Offsets
if (lines[line].flags & ML_EFFECT1) // Swinging
@ -9901,14 +9999,14 @@ domaceagain:
else // Spinning
mphase = (mphase - mspokeangle) & FINEMASK;
if (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke
if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke
{
if (mobj->type != MT_CHAINMACEPOINT)
continue;
firsttype = linktype = chainlink;
mlengthset = 1 + (mlength - 1)*radiusfactor;
radiusfactor = 1;
mmaxlength = 1 + (mlength - 1)*radiusfactor;
radiusfactor = widthfactor = 1;
}
else
{
@ -9927,36 +10025,73 @@ domaceagain:
}
firsttype = macetype;
widthfactor = 2;
}
mlengthset = mlength;
mmaxlength = mlength;
}
mwidthset = mwidth;
mlengthset = mminlength;
if (mdocenter) // Innermost mace/link
makemace(macetype, 0, 0);
// Out from the center...
if (linktype)
{
while ((++mlengthset) < mmaxlength)
makemace(linktype, radiusfactor*mlengthset, 0);
}
else
mlengthset = mmaxlength;
// Outermost mace/link
spawnee = makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
if (firsttype)
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (mspeed && (mwidth == msound) && !(mthing->options & MTF_OBJECTSPECIAL) && mnumspokesset <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
if (!mwidth)
{
if (mdosound && mnumspokes <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
}
else
{
// Across the bar!
if (!firsttype)
mwidthset = -mwidth;
else if (mwidth > 0)
{
while ((mwidthset -= widthfactor) > -mwidth)
{
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
}
}
else
{
while ((mwidthset += widthfactor) < -mwidth)
{
makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH);
if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound?
spawnee->flags2 |= MF2_BOSSNOTRAP;
}
}
mwidth = -mwidth;
if (!mdoall || !linktype)
continue;
// Outermost mace/link again!
if (firsttype)
makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH);
// The rest of the links
while (mlengthset > 0)
{ spawnee = makemace(linktype, radiusfactor*(mlengthset--), 0); }
}
// ...and then back into the center!
if (linktype)
while (mlengthset > mminlength)
makemace(linktype, radiusfactor*(mlengthset--), 0);
if (mwidth > 0)
{
mwidth *= -1;
goto domaceagain;
}
else if (mwidth != 0)
{
if ((mwidth = -(mwidth + ((firsttype == chainlink) ? 1 : 2))) < 0)
break;
mdoall = false;
goto domaceagain;
if (mdocenter) // Innermost mace/link
makemace(macetype, 0, 0);
}
}
#undef makemace
@ -10060,9 +10195,6 @@ domaceagain:
// the bumper in 30 degree increments.
mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc
P_SetMobjState(mobj, mobj->info->spawnstate+mobj->threshold);
// you can shut up now, OBJECTFLIP. And all of the other options, for that matter.
mthing->options &= ~0xF;
break;
case MT_EGGCAPSULE:
if (mthing->angle <= 0)
@ -10264,7 +10396,15 @@ domaceagain:
}
}
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
if (doangle)
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
// ignore MTF_ flags and return early
if (i == MT_NIGHTSBUMPER)
{
mthing->mobj = mobj;
return;
}
if ((mthing->options & MTF_AMBUSH)
&& (mthing->options & MTF_OBJECTSPECIAL)

View File

@ -194,7 +194,6 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer
// free: to and including 1<<31
} mobjflag2_t;

View File

@ -2675,11 +2675,6 @@ boolean P_SetupLevel(boolean skipprecip)
// Reset the palette
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPaletteColor(0);
else
#endif
if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");
@ -2737,6 +2732,7 @@ boolean P_SetupLevel(boolean skipprecip)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime;
S_StartSound(NULL, sfx_s3kaf);
@ -2746,9 +2742,17 @@ boolean P_SetupLevel(boolean skipprecip)
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
nowtime = lastwipetic;
// Hold on white for extra effect.
while (I_GetTime() < endtime)
I_Sleep();
while (nowtime < endtime)
{
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
I_Sleep();
lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
ranspecialwipe = 1;
}
@ -3336,7 +3340,7 @@ boolean P_AddWadFile(const char *wadfilename)
if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename);
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename);
return false;
}
else

View File

@ -251,7 +251,7 @@ void P_SpawnSlope_Line(int linenum)
UINT8 flags = 0; // Slope flags
if (line->flags & ML_NOSONIC)
flags |= SL_NOPHYSICS;
if (line->flags & ML_NOTAILS)
if (!(line->flags & ML_NOTAILS))
flags |= SL_NODYNAMIC;
if (line->flags & ML_NOKNUX)
flags |= SL_ANCHORVERTEX;

View File

@ -31,6 +31,7 @@
#include "p_polyobj.h"
#include "p_slopes.h"
#include "hu_stuff.h"
#include "v_video.h" // V_AUTOFADEOUT|V_ALLOWLOWERCASE
#include "m_misc.h"
#include "m_cond.h" //unlock triggers
#include "lua_hook.h" // LUAh_LinedefExecute
@ -3815,9 +3816,9 @@ DoneSection2:
if (!P_IsFlagAtBase(MT_REDFLAG))
break;
HU_SetCEchoFlags(0);
HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE);
HU_SetCEchoDuration(5);
HU_DoCEcho(va(M_GetText("%s\\captured the blue flag.\\\\\\\\"), player_names[player-players]));
HU_DoCEcho(va(M_GetText("%s%s%s\\CAPTURED THE %sBLUE FLAG%s.\\\\\\\\"), "\x85", player_names[player-players], "\x80", "\x84", "\x80"));
if (splitscreen || players[consoleplayer].ctfteam == 1)
S_StartSound(NULL, sfx_flgcap);
@ -3848,9 +3849,9 @@ DoneSection2:
if (!P_IsFlagAtBase(MT_BLUEFLAG))
break;
HU_SetCEchoFlags(0);
HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE);
HU_SetCEchoDuration(5);
HU_DoCEcho(va(M_GetText("%s\\captured the red flag.\\\\\\\\"), player_names[player-players]));
HU_DoCEcho(va(M_GetText("%s%s%s\\CAPTURED THE %sRED FLAG%s.\\\\\\\\"), "\x84", player_names[player-players], "\x80", "\x85", "\x80"));
if (splitscreen || players[consoleplayer].ctfteam == 2)
S_StartSound(NULL, sfx_flgcap);
@ -5526,6 +5527,30 @@ void P_InitSpecials(void)
P_InitTagLists(); // Create xref tables for tags
}
static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs)
{
if (!(master->flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
{
sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle;
sector->floor_xoffs += xoffs;
sector->floor_yoffs += yoffs;
// saved for netgames
sector->spawn_flr_xoffs = sector->floor_xoffs;
sector->spawn_flr_yoffs = sector->floor_yoffs;
}
if (!(master->flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
{
sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle;
sector->ceiling_xoffs += xoffs;
sector->ceiling_yoffs += yoffs;
// saved for netgames
sector->spawn_ceil_xoffs = sector->ceiling_xoffs;
sector->spawn_ceil_yoffs = sector->ceiling_yoffs;
}
}
/** After the map has loaded, scans for specials that spawn 3Dfloors and
* thinkers.
*
@ -5729,27 +5754,13 @@ void P_SpawnSpecials(INT32 fromnetsave)
yoffs = lines[i].v1->y;
}
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
//If no tag is given, apply to front sector
if (lines[i].tag == 0)
P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs);
else
{
if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
{
sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle;
sectors[s].floor_xoffs += xoffs;
sectors[s].floor_yoffs += yoffs;
// saved for netgames
sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs;
sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs;
}
if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
{
sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle;
sectors[s].ceiling_xoffs += xoffs;
sectors[s].ceiling_yoffs += yoffs;
// saved for netgames
sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs;
sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs;
}
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0;)
P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs);
}
}
else // Otherwise, print a helpful warning. Can I do no less?
@ -6688,6 +6699,7 @@ void T_Scroll(scroll_t *s)
line_t *line;
size_t i;
INT32 sect;
ffloor_t *rover;
case sc_side: // scroll wall texture
side = sides + s->affectee;
@ -6729,6 +6741,19 @@ void T_Scroll(scroll_t *s)
sector_t *psec;
psec = sectors + sect;
// Find the FOF corresponding to the control linedef
for (rover = psec->ffloors; rover; rover = rover->next)
{
if (rover->master == sec->lines[i])
break;
}
if (!rover) // This should be impossible, but don't complain if it is the case somehow
continue;
if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there
continue;
for (node = psec->touching_thinglist; node; node = node->m_thinglist_next)
{
thing = node->m_thing;
@ -6792,6 +6817,19 @@ void T_Scroll(scroll_t *s)
sector_t *psec;
psec = sectors + sect;
// Find the FOF corresponding to the control linedef
for (rover = psec->ffloors; rover; rover = rover->next)
{
if (rover->master == sec->lines[i])
break;
}
if (!rover) // This should be impossible, but don't complain if it is the case somehow
continue;
if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there
continue;
for (node = psec->touching_thinglist; node; node = node->m_thinglist_next)
{
thing = node->m_thing;

View File

@ -606,7 +606,8 @@ void P_Ticker(boolean run)
}
// Keep track of how long they've been playing!
totalplaytime++;
if (!demoplayback) // Don't increment if a demo is playing.
totalplaytime++;
if (!useNightsSS && G_IsSpecialStage(gamemap))
P_DoSpecialStageStuff();

View File

@ -909,8 +909,12 @@ void P_ResetPlayer(player_t *player)
// Gives rings to the player, and does any special things required.
// Call this function when you want to increment the player's health.
//
void P_GivePlayerRings(player_t *player, INT32 num_rings)
{
if (!player)
return;
if (player->bot)
player = &players[consoleplayer];
@ -929,7 +933,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
player->rings = 0;
// Now extra life bonuses are handled here instead of in P_MovePlayer, since why not?
if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives())
if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives() && player->lives != 0x7f)
{
INT32 gainlives = 0;
@ -941,7 +945,12 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
if (gainlives)
{
P_GivePlayerLives(player, gainlives);
player->lives += gainlives;
if (player->lives > 99)
player->lives = 99;
else if (player->lives < 1)
player->lives = 1;
P_PlayLivesJingle(player);
}
}
@ -955,7 +964,30 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
//
void P_GivePlayerLives(player_t *player, INT32 numlives)
{
if (player->lives == 0x7f) return;
if (!player)
return;
if (player->bot)
player = &players[consoleplayer];
if (gamestate == GS_LEVEL)
{
if (player->lives == 0x7f || (gametype != GT_COOP && gametype != GT_COMPETITION))
{
P_GivePlayerRings(player, 100*numlives);
return;
}
if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0)
{
UINT8 prevlives = player->lives;
P_GivePlayerRings(player, 100*numlives);
if (player->lives - prevlives >= numlives)
return;
numlives = (numlives + prevlives - player->lives);
}
}
player->lives += numlives;
@ -1159,11 +1191,7 @@ void P_PlayLivesJingle(player_t *player)
if (player && !P_IsLocalPlayer(player))
return;
if ((player && player->lives == 0x7f)
|| (!player && &players[consoleplayer] && players[consoleplayer].lives == 0x7f)
|| (gametype == GT_COOP && (netgame || multiplayer) && cv_cooplives.value == 0))
S_StartSound(NULL, sfx_lose);
else if (use1upSound)
if (use1upSound)
S_StartSound(NULL, sfx_oneup);
else if (mariomode)
S_StartSound(NULL, sfx_marioa);
@ -1725,7 +1753,7 @@ void P_DoPlayerExit(player_t *player)
else if (gametype == GT_RACE || gametype == GT_COMPETITION) // If in Race Mode, allow
{
if (!countdown) // a 60-second wait ala Sonic 2.
countdown = cv_countdowntime.value*TICRATE + 1; // Use cv_countdowntime
countdown = (cv_countdowntime.value - 1)*TICRATE + 1; // Use cv_countdowntime
player->exiting = 3*TICRATE;
@ -1768,6 +1796,9 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space
for (rover = sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL)
continue;
#ifdef ESLOPE
@ -2128,6 +2159,12 @@ static void P_CheckBouncySectors(player_t *player)
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue; // FOFs should not be bouncy if they don't even "exist"
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15)
continue; // this sector type is required for FOFs to be bouncy
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
@ -2141,7 +2178,6 @@ static void P_CheckBouncySectors(player_t *player)
&& oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL))
top = false;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 15)
{
fixed_t linedist;
@ -2336,12 +2372,17 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
{
tic_t timeleft = (player->powers[pw_spacetime]) ? player->powers[pw_spacetime] : player->powers[pw_underwater];
if ((timeleft == 11*TICRATE + 1) // 5
|| (timeleft == 9*TICRATE + 1) // 4
|| (timeleft == 7*TICRATE + 1) // 3
|| (timeleft == 5*TICRATE + 1) // 2
|| (timeleft == 3*TICRATE + 1) // 1
|| (timeleft == 1*TICRATE + 1) // 0
if (player->exiting)
player->powers[pw_underwater] = player->powers[pw_spacetime] = 0;
timeleft--; // The original code was all n*TICRATE + 1, so let's remove 1 tic for simplicity
if ((timeleft == 11*TICRATE) // 5
|| (timeleft == 9*TICRATE) // 4
|| (timeleft == 7*TICRATE) // 3
|| (timeleft == 5*TICRATE) // 2
|| (timeleft == 3*TICRATE) // 1
|| (timeleft == 1*TICRATE) // 0
) {
fixed_t height = (player->mo->eflags & MFE_VERTICALFLIP)
? player->mo->z - FixedMul(8*FRACUNIT + mobjinfo[MT_DROWNNUMBERS].height, FixedMul(player->mo->scale, player->shieldscale))
@ -2349,7 +2390,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
mobj_t *numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS);
timeleft /= (2*TICRATE); // To be strictly accurate it'd need to be (((timeleft - 1)/TICRATE) - 1)/2, but integer division rounds down for us
timeleft /= (2*TICRATE); // To be strictly accurate it'd need to be ((timeleft/TICRATE) - 1)/2, but integer division rounds down for us
if (player->charflags & SF_MACHINE)
{
@ -2408,14 +2449,6 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
S_ChangeMusicInternal("_drown", false);
}
}
if (player->exiting)
{
if (player->powers[pw_underwater] > 1)
player->powers[pw_underwater] = 0;
player->powers[pw_spacetime] = 0;
}
}
//
@ -2585,13 +2618,11 @@ static void P_DoPlayerHeadSigns(player_t *player)
}
else
sign->z += P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale);
if (leveltime & 4)
{
if (player->gotflag & GF_REDFLAG)
P_SetMobjStateNF(sign, S_GOTREDFLAG);
}
else if (player->gotflag & GF_BLUEFLAG)
P_SetMobjStateNF(sign, S_GOTBLUEFLAG);
if (player->gotflag & GF_REDFLAG)
sign->frame = 1|FF_FULLBRIGHT;
else //if (player->gotflag & GF_BLUEFLAG)
sign->frame = 2|FF_FULLBRIGHT;
}
}
}
@ -9538,7 +9569,7 @@ void P_PlayerThink(player_t *player)
if (i == MAXPLAYERS && player->exiting == 3*TICRATE) // finished
player->exiting = (14*TICRATE)/5 + 1;
// If 10 seconds are left on the timer,
// If 11 seconds are left on the timer,
// begin the drown music for countdown!
if (countdown == 11*TICRATE - 1)
{
@ -9711,7 +9742,7 @@ void P_PlayerThink(player_t *player)
}
}
if (player->linktimer && (player->linktimer >= (2*TICRATE - 1) || !player->powers[pw_nights_linkfreeze]))
if (player->linktimer && !player->powers[pw_nights_linkfreeze])
{
if (--player->linktimer <= 0) // Link timer
player->linkcount = 0;
@ -10421,21 +10452,10 @@ void P_PlayerAfterThink(player_t *player)
player->secondjump = 0;
player->pflags &= ~PF_THOKKED;
if (cmd->forwardmove > 0)
{
if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction)
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->friction;
}
else if (cmd->forwardmove < 0)
{
if ((player->mo->tracer->tracer->lastlook -= 2) < player->mo->tracer->tracer->movecount)
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->movecount;
}
if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
&& !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode?
{
player->mo->tracer->tracer->health += cmd->sidemove;
player->mo->tracer->tracer->angle += cmd->sidemove<<ANGLETOFINESHIFT;
player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX
if (!demoplayback || P_AnalogMove(player))

View File

@ -439,11 +439,22 @@ static UINT8 *R_GenerateTexture(size_t texnum)
height = SHORT(realpatch->height);
x2 = x1 + width;
if (x1 > texture->width || x2 < 0)
continue; // patch not located within texture's x bounds, ignore
if (patch->originy > texture->height || (patch->originy + height) < 0)
continue; // patch not located within texture's y bounds, ignore
// patch is actually inside the texture!
// now check if texture is partly off-screen and adjust accordingly
// left edge
if (x1 < 0)
x = 0;
else
x = x1;
// right edge
if (x2 > texture->width)
x2 = texture->width;

View File

@ -2497,11 +2497,7 @@ static void Sk_SetDefaultValue(skin_t *skin)
skin->flags = 0;
strcpy(skin->realname, "Someone");
#ifdef SKINNAMEPADDING
strcpy(skin->hudname, " ???");
#else
strcpy(skin->hudname, "???");
#endif
strncpy(skin->charsel, "CHRSONIC", 8);
strncpy(skin->face, "MISSING", 8);
strncpy(skin->superface, "MISSING", 8);
@ -2733,11 +2729,7 @@ static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
return INT16_MAX; // not found
}
#ifdef SKINNAMEPADDING
#define HUDNAMEWRITE(value) snprintf(skin->hudname, sizeof(skin->hudname), "%5s", value)
#else
#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value)
#endif
// turn _ into spaces and . into katana dot
#define SYMBOLCONVERT(name) for (value = name; *value; value++)\

View File

@ -414,7 +414,7 @@ void SCR_DisplayTicRate(void)
tic_t ontic = I_GetTime();
tic_t totaltics = 0;
INT32 ticcntcolor = 0;
INT32 offs = (cv_debug ? 8 : 0);
const INT32 h = vid.height-(8*vid.dupy);
for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
fpsgraph[i % TICRATE] = false;
@ -428,9 +428,9 @@ void SCR_DisplayTicRate(void)
if (totaltics <= TICRATE/2) ticcntcolor = V_REDMAP;
else if (totaltics == TICRATE) ticcntcolor = V_GREENMAP;
V_DrawString(vid.width-((24+(6*offs))*vid.dupx), vid.height-((16-offs)*vid.dupy),
V_YELLOWMAP|V_NOSCALESTART, "FPS");
V_DrawString(vid.width-(40*vid.dupx), vid.height-(8*vid.dupy),
V_DrawString(vid.width-(72*vid.dupx), h,
V_YELLOWMAP|V_NOSCALESTART, "FPS:");
V_DrawString(vid.width-(40*vid.dupx), h,
ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));
lasttic = ontic;
@ -440,6 +440,18 @@ void SCR_ClosedCaptions(void)
{
UINT8 i;
boolean gamestopped = (paused || P_AutoPause());
INT32 basey = BASEVIDHEIGHT;
if (gamestate == GS_LEVEL)
{
if (splitscreen)
basey -= 8;
else if (((maptol & TOL_NIGHTS) && (modeattacking == ATTACKING_NIGHTS))
|| (cv_powerupdisplay.value == 2)
|| (cv_powerupdisplay.value == 1 && ((stplyr == &players[displayplayer] && !camera.chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))))
basey -= 16;
}
for (i = 0; i < NUMCAPTIONS; i++)
{
@ -455,9 +467,8 @@ void SCR_ClosedCaptions(void)
if (music && !gamestopped && (closedcaptions[i].t < flashingtics) && (closedcaptions[i].t & 1))
continue;
flags = V_NOSCALESTART|V_ALLOWLOWERCASE;
y = vid.height-((i + 2)*10*vid.dupy);
dot = ' ';
flags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_ALLOWLOWERCASE;
y = basey-((i + 2)*10);
if (closedcaptions[i].b)
y -= (closedcaptions[i].b--)*vid.dupy;
@ -469,8 +480,10 @@ void SCR_ClosedCaptions(void)
dot = '\x19';
else if (closedcaptions[i].c && closedcaptions[i].c->origin)
dot = '\x1E';
else
dot = ' ';
V_DrawRightAlignedString(vid.width-(20*vid.dupx), y,
flags, va("%c [%s]", dot, (closedcaptions[i].s->caption[0] ? closedcaptions[i].s->caption : closedcaptions[i].s->name)));
V_DrawRightAlignedString(BASEVIDWIDTH - 20, y, flags,
va("%c [%s]", dot, (closedcaptions[i].s->caption[0] ? closedcaptions[i].s->caption : closedcaptions[i].s->name)));
}
}

View File

@ -94,6 +94,7 @@ void *hwSym(const char *funcName,void *handle)
#ifdef SHUFFLE
GETFUNC(PostImgRedraw);
#endif //SHUFFLE
GETFUNC(FlushScreenTextures);
GETFUNC(StartScreenWipe);
GETFUNC(EndScreenWipe);
GETFUNC(DoScreenWipe);

View File

@ -2693,7 +2693,7 @@ const char *I_LocateWad(void)
return waddir;
}
#if defined(LINUX) || defined(LINUX64)
#ifdef __linux__
#define MEMINFO_FILE "/proc/meminfo"
#define MEMTOTAL "MemTotal:"
#define MEMFREE "MemFree:"
@ -2713,20 +2713,23 @@ UINT32 I_GetFreeMem(UINT32 *total)
};
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
{
*total = 0L;
if (total)
*total = 0L;
return 0;
}
if (kvm_nlist(kd, namelist) != 0)
{
kvm_close (kd);
*total = 0L;
if (total)
*total = 0L;
return 0;
}
if (kvm_read(kd, namelist[X_SUM].n_value, &sum,
sizeof (sum)) != sizeof (sum))
{
kvm_close(kd);
*total = 0L;
if (total)
*total = 0L;
return 0;
}
kvm_close(kd);
@ -2747,7 +2750,7 @@ UINT32 I_GetFreeMem(UINT32 *total)
if (total)
*total = (UINT32)info.dwTotalPhys;
return (UINT32)info.dwAvailPhys;
#elif defined (LINUX) || defined (LINUX64)
#elif defined (__linux__)
/* Linux */
char buf[1024];
char *memTag;
@ -2763,25 +2766,28 @@ UINT32 I_GetFreeMem(UINT32 *total)
if (n < 0)
{
// Error
*total = 0L;
if (total)
*total = 0L;
return 0;
}
buf[n] = '\0';
if (NULL == (memTag = strstr(buf, MEMTOTAL)))
if ((memTag = strstr(buf, MEMTOTAL)) == NULL)
{
// Error
*total = 0L;
if (total)
*total = 0L;
return 0;
}
memTag += sizeof (MEMTOTAL);
totalKBytes = atoi(memTag);
if (NULL == (memTag = strstr(buf, MEMFREE)))
if ((memTag = strstr(buf, MEMFREE)) == NULL)
{
// Error
*total = 0L;
if (total)
*total = 0L;
return 0;
}
@ -2796,7 +2802,7 @@ UINT32 I_GetFreeMem(UINT32 *total)
if (total)
*total = 48<<20;
return 48<<20;
#endif /* LINUX */
#endif
}
const CPUInfoFlags *I_CPUInfo(void)

View File

@ -658,6 +658,14 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
SDL_memset(&event, 0, sizeof(event_t));
// Ignore the event if the mouse is not actually focused on the window.
// This can happen if you used the mouse to restore keyboard focus;
// this apparently makes a mouse button down event but not a mouse button up event,
// resulting in whatever key was pressed down getting "stuck" if we don't ignore it.
// -- Monster Iestyn (28/05/18)
if (SDL_GetMouseFocus() != window)
return;
/// \todo inputEvent.button.which
if (USE_MOUSEINPUT)
{
@ -1446,6 +1454,7 @@ void I_StartupGraphics(void)
#ifdef SHUFFLE
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
#endif
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL);

View File

@ -214,8 +214,11 @@ void OglSdlFinishUpdate(boolean waitvbl)
HWR_DrawScreenFinalTexture(sdlw, sdlh);
SDL_GL_SwapWindow(window);
SetModelView(realwidth, realheight);
SetStates();
GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE);
// Sryder: We need to draw the final screen texture again into the other buffer in the original position so that
// effects that want to take the old screen can do so after this
HWR_DrawScreenFinalTexture(realwidth, realheight);
}
EXPORT void HWRAPI( OglSdlSetPalette) (RGBA_t *palette, RGBA_t *pgamma)

View File

@ -1180,12 +1180,6 @@ void I_StartupSound(void)
audio.callback = I_UpdateStream;
audio.userdata = &localdata;
if (dedicated)
{
nosound = nomidimusic = nodigimusic = true;
return;
}
// Configure sound device
CONS_Printf("I_StartupSound:\n");
@ -1481,9 +1475,6 @@ void I_InitMusic(void)
I_AddExitFunc(I_ShutdownGMEMusic);
#endif
if ((nomidimusic && nodigimusic) || dedicated)
return;
#ifdef HAVE_MIXER
MIX_VERSION(&MIXcompiled)
MIXlinked = Mix_Linked_Version();

View File

@ -85,14 +85,14 @@ sfxinfo_t S_sfx[NUMSFX] =
{"athun1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder"},
{"athun2", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder"},
{"amwtr1", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr2", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr3", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr4", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr5", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr6", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr7", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr8", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running water"},
{"amwtr1", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr2", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr3", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr4", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr5", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr6", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr7", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"amwtr8", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"},
{"bubbl1", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"},
{"bubbl2", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"},
{"bubbl3", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"},

File diff suppressed because it is too large Load Diff

View File

@ -72,38 +72,28 @@ extern patch_t *ngradeletters[7];
*/
typedef struct
{
INT32 x, y;
INT32 x, y, f;
} hudinfo_t;
typedef enum
{
HUD_LIVESNAME,
HUD_LIVESPIC,
HUD_LIVESNUM,
HUD_LIVESX,
HUD_LIVES,
HUD_RINGS,
HUD_RINGSSPLIT,
HUD_RINGSNUM,
HUD_RINGSNUMSPLIT,
HUD_RINGSNUMTICS,
HUD_SCORE,
HUD_SCORENUM,
HUD_TIME,
HUD_TIMESPLIT,
HUD_MINUTES,
HUD_MINUTESSPLIT,
HUD_TIMECOLON,
HUD_TIMECOLONSPLIT,
HUD_SECONDS,
HUD_SECONDSSPLIT,
HUD_TIMETICCOLON,
HUD_TICS,
HUD_SS_TOTALRINGS,
HUD_SS_TOTALRINGS_SPLIT,
HUD_GETRINGS,
HUD_GETRINGSNUM,
@ -111,8 +101,7 @@ typedef enum
HUD_TIMELEFTNUM,
HUD_TIMEUP,
HUD_HUNTPICS,
HUD_GRAVBOOTSICO,
HUD_LAP,
HUD_POWERUPS,
NUMHUDITEMS
} hudnum_t;

View File

@ -15,6 +15,8 @@
#include "doomdef.h"
#include "r_local.h"
#include "p_local.h" // stplyr
#include "g_game.h" // players
#include "v_video.h"
#include "hu_stuff.h"
#include "r_draw.h"
@ -540,6 +542,8 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
fixed_t pwidth; // patch width
fixed_t offx = 0; // x offset
UINT8 perplayershuffle = 0;
if (rendermode == render_none)
return;
@ -624,8 +628,74 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale);
}
if (scrn & V_SPLITSCREEN)
y>>=1;
if (splitscreen && (scrn & V_PERPLAYER))
{
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
fdup >>= 1;
rowfrac <<= 1;
y >>= 1;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
colfrac <<= 1;
x >>= 1;
if (stplyr == &players[displayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
y += adjusty;
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else //if (stplyr == &players[fourthdisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
y += adjusty;
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 1;
scrn &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 2;
y += adjusty;
scrn &= ~V_SNAPTOTOP;
}
}
}
desttop = screens[scrn&V_PARAMMASK];
@ -666,16 +736,22 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(scrn & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
if (perplayershuffle & 4)
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
else if (perplayershuffle & 8)
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if ((scrn & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM))
y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
else if (scrn & V_SNAPTOBOTTOM)
if (scrn & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(scrn & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
if (perplayershuffle & 1)
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
else if (perplayershuffle & 2)
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
}
}
@ -750,6 +826,8 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
UINT8 *desttop, *dest;
const UINT8 *source, *deststop;
UINT8 perplayershuffle = 0;
if (rendermode == render_none)
return;
@ -793,6 +871,84 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
y -= FixedMul(SHORT(patch->topoffset)<<FRACBITS, pscale);
x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale);
if (splitscreen && (scrn & V_PERPLAYER))
{
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
fdup >>= 1;
rowfrac <<= 1;
y >>= 1;
sy >>= 1;
h >>= 1;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
colfrac <<= 1;
x >>= 1;
sx >>= 1;
w >>= 1;
if (stplyr == &players[displayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
sx += adjustx;
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
y += adjusty;
sy += adjusty;
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else //if (stplyr == &players[fourthdisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
sx += adjustx;
y += adjusty;
sy += adjusty;
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
scrn &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
y += adjusty;
sy += adjusty;
scrn &= ~V_SNAPTOTOP;
}
}
}
desttop = screens[scrn&V_PARAMMASK];
if (!desttop)
@ -831,16 +987,22 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(scrn & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
if (perplayershuffle & 4)
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
else if (perplayershuffle & 8)
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if ((scrn & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM))
y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
else if (scrn & V_SNAPTOBOTTOM)
if (scrn & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(scrn & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
if (perplayershuffle & 1)
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
else if (perplayershuffle & 2)
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
}
}
@ -987,6 +1149,8 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
UINT8 *dest;
const UINT8 *deststop;
UINT8 perplayershuffle = 0;
if (rendermode == render_none)
return;
@ -998,6 +1162,74 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
}
#endif
if (splitscreen && (c & V_PERPLAYER))
{
fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
h >>= 1;
y >>= 1;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
w >>= 1;
x >>= 1;
if (stplyr == &players[displayplayer])
{
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
y += adjusty;
c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else //if (stplyr == &players[fourthdisplayplayer])
{
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
x += adjustx;
y += adjusty;
c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
c &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
y += adjusty;
c &= ~V_SNAPTOTOP;
}
}
}
if (!(c & V_NOSCALESTART))
{
INT32 dupx = vid.dupx, dupy = vid.dupy;
@ -1022,6 +1254,10 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(c & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
if (perplayershuffle & 4)
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
else if (perplayershuffle & 8)
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
@ -1030,6 +1266,10 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(c & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
if (perplayershuffle & 1)
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
else if (perplayershuffle & 2)
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
}
}
@ -1165,14 +1405,6 @@ void V_DrawPatchFill(patch_t *pat)
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
#ifdef HWRENDER
if (rendermode == render_opengl)
{
pw = FixedMul(SHORT(pat->width)*FRACUNIT, vid.fdupx)>>FRACBITS;
ph = FixedMul(SHORT(pat->height)*FRACUNIT, vid.fdupy)>>FRACBITS;
}
#endif
for (x = 0; x < vid.width; x += pw)
{
for (y = 0; y < vid.height; y += ph)
@ -1183,25 +1415,34 @@ void V_DrawPatchFill(patch_t *pat)
//
// Fade all the screen buffer, so that the menu is more readable,
// especially now that we use the small hufont in the menus...
// If color is 0x00 to 0xFF, draw transtable (strength range 0-9).
// Else, use COLORMAP lump (strength range 0-31).
// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH!
// I have kept the safety checks out of this function;
// the v.fadeScreen Lua interface handles those.
//
void V_DrawFadeScreen(void)
void V_DrawFadeScreen(UINT16 color, UINT8 strength)
{
const UINT8 *fadetable = (UINT8 *)colormaps + 16*256;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *buf = screens[0];
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
{
HWR_FadeScreenMenuBack(0x01010160, 0); // hack, 0 means full height
HWR_FadeScreenMenuBack(color, strength);
return;
}
#endif
// heavily simplified -- we don't need to know x or y
// position when we're doing a full screen fade
for (; buf < deststop; ++buf)
*buf = fadetable[*buf];
{
const UINT8 *fadetable = ((color & 0xFF00) // Color is not palette index?
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade.
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *buf = screens[0];
// heavily simplified -- we don't need to know x or y
// position when we're doing a full screen fade
for (; buf < deststop; ++buf)
*buf = fadetable[*buf];
}
}
// Simple translucency with one color, over a set number of lines starting from the top.
@ -1245,20 +1486,36 @@ static const UINT8 *V_GetStringColormap(INT32 colorflags)
{
switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT)
{
case 1: // 0x81, purple
return purplemap;
case 2: // 0x82, yellow
case 1: // 0x81, magenta
return magentamap;
case 2: // 0x82, yellow
return yellowmap;
case 3: // 0x83, lgreen
case 3: // 0x83, lgreen
return lgreenmap;
case 4: // 0x84, blue
case 4: // 0x84, blue
return bluemap;
case 5: // 0x85, red
case 5: // 0x85, red
return redmap;
case 6: // 0x86, gray
case 6: // 0x86, gray
return graymap;
case 7: // 0x87, orange
case 7: // 0x87, orange
return orangemap;
case 8: // 0x88, sky
return skymap;
case 9: // 0x89, purple
return purplemap;
case 10: // 0x8A, aqua
return aquamap;
case 11: // 0x8B, peridot
return peridotmap;
case 12: // 0x8C, azure
return azuremap;
case 13: // 0x8D, brown
return brownmap;
case 14: // 0x8E, rosy
return rosymap;
case 15: // 0x8F, invert
return invertmap;
default: // reset
return NULL;
}

View File

@ -73,13 +73,21 @@ extern RGBA_t *pMasterPalette;
#define V_CHARCOLORSHIFT 12
#define V_CHARCOLORMASK 0x0000F000
// for simplicity's sake, shortcuts to specific colors
#define V_PURPLEMAP 0x00001000
#define V_MAGENTAMAP 0x00001000
#define V_YELLOWMAP 0x00002000
#define V_GREENMAP 0x00003000
#define V_BLUEMAP 0x00004000
#define V_REDMAP 0x00005000
#define V_GRAYMAP 0x00006000
#define V_ORANGEMAP 0x00007000
#define V_SKYMAP 0x00008000
#define V_PURPLEMAP 0x00009000
#define V_AQUAMAP 0x0000A000
#define V_PERIDOTMAP 0x0000B000
#define V_AZUREMAP 0x0000C000
#define V_BROWNMAP 0x0000D000
#define V_ROSYMAP 0x0000E000
#define V_INVERTMAP 0x0000F000
// use bits 17-20 for alpha transparency
#define V_ALPHASHIFT 16
@ -112,8 +120,8 @@ extern RGBA_t *pMasterPalette;
#define V_WRAPX 0x10000000 // Don't clamp texture on X (for HW mode)
#define V_WRAPY 0x20000000 // Don't clamp texture on Y (for HW mode)
#define V_NOSCALESTART 0x40000000 // don't scale x, y, start coords
#define V_SPLITSCREEN 0x80000000
#define V_NOSCALESTART 0x40000000 // don't scale x, y, start coords
#define V_PERPLAYER 0x80000000 // automatically adjust coordinates/scaling for splitscreen mode
// defines for old functions
#define V_DrawPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, s|V_NOSCALESTART|V_NOSCALEPATCH, p, NULL)
@ -147,7 +155,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c);
void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
// fade down the screen buffer before drawing the menu over
void V_DrawFadeScreen(void);
void V_DrawFadeScreen(UINT16 color, UINT8 strength);
void V_DrawFadeConsBack(INT32 plines);

View File

@ -117,6 +117,7 @@ static loadfunc_t hwdFuncTable[] = {
#ifdef SHUFFLE
{"PostImgRedraw@4", &hwdriver.pfnPostImgRedraw},
#endif
{"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures},
{"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe},
{"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe},
{"DoScreenWipe@4", &hwdriver.pfnDoScreenWipe},
@ -147,6 +148,7 @@ static loadfunc_t hwdFuncTable[] = {
#ifdef SHUFFLE
{"PostImgRedraw", &hwdriver.pfnPostImgRedraw},
#endif
{"FlushScreenTextures"},&hwdriver.pfnFlushScreenTextures},
{"StartScreenWipe", &hwdriver.pfnStartScreenWipe},
{"EndScreenWipe", &hwdriver.pfnEndScreenWipe},
{"DoScreenWipe", &hwdriver.pfnDoScreenWipe},

View File

@ -161,27 +161,25 @@ static void Y_FollowIntermission(void);
static void Y_UnloadData(void);
// Stuff copy+pasted from st_stuff.c
static INT32 SCX(INT32 x)
{
return FixedInt(FixedMul(x<<FRACBITS, vid.fdupx));
}
static INT32 SCY(INT32 z)
{
return FixedInt(FixedMul(z<<FRACBITS, vid.fdupy));
}
#define ST_DrawNumFromHud(h,n) V_DrawTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART, n)
#define ST_DrawPadNumFromHud(h,n,q) V_DrawPaddedTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART, n, q)
#define ST_DrawPatchFromHud(h,p) V_DrawScaledPatch(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART, p)
#define ST_DrawNumFromHud(h,n) V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n)
#define ST_DrawPadNumFromHud(h,n,q) V_DrawPaddedTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n, q)
#define ST_DrawPatchFromHud(h,p) V_DrawScaledPatch(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, p)
static void Y_IntermissionTokenDrawer(void)
{
INT32 y;
INT32 offs = 0;
INT32 y, offs, lowy, calc;
UINT32 tokencount;
INT32 lowy = BASEVIDHEIGHT - 32;
INT16 temp = SHORT(tokenicon->height)/2;
INT32 calc;
INT16 temp;
UINT8 em;
offs = 0;
lowy = BASEVIDHEIGHT - 32 - 8;
temp = SHORT(tokenicon->height)/2;
em = 0;
while (emeralds & (1 << em))
if (++em == 7)
return;
if (tallydonetic != -1)
{
@ -190,7 +188,7 @@ static void Y_IntermissionTokenDrawer(void)
offs = 8;
}
V_DrawFill(32, lowy-1, 16, 1, 31); // slot
V_DrawSmallScaledPatch(32, lowy-1, 0, emeraldpics[2][em]); // coinbox
y = (lowy + offs + 1) - (temp + (token + 1)*8);
@ -255,31 +253,34 @@ void Y_IntermissionDrawer(void)
if (gottoken) // first to be behind everything else
Y_IntermissionTokenDrawer();
// draw score
ST_DrawPatchFromHud(HUD_SCORE, sboscore);
ST_DrawNumFromHud(HUD_SCORENUM, data.coop.score);
// draw time
ST_DrawPatchFromHud(HUD_TIME, sbotime);
if (cv_timetic.value == 1)
ST_DrawNumFromHud(HUD_SECONDS, data.coop.tics);
else
if (!splitscreen)
{
INT32 seconds, minutes, tictrn;
// draw score
ST_DrawPatchFromHud(HUD_SCORE, sboscore);
ST_DrawNumFromHud(HUD_SCORENUM, data.coop.score);
seconds = G_TicsToSeconds(data.coop.tics);
minutes = G_TicsToMinutes(data.coop.tics, true);
tictrn = G_TicsToCentiseconds(data.coop.tics);
ST_DrawNumFromHud(HUD_MINUTES, minutes); // Minutes
ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon
ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds
// we should show centiseconds on the intermission screen too, if the conditions are right.
if (modeattacking || cv_timetic.value == 2)
// draw time
ST_DrawPatchFromHud(HUD_TIME, sbotime);
if (cv_timetic.value == 1)
ST_DrawNumFromHud(HUD_SECONDS, data.coop.tics);
else
{
ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period
ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics
INT32 seconds, minutes, tictrn;
seconds = G_TicsToSeconds(data.coop.tics);
minutes = G_TicsToMinutes(data.coop.tics, true);
tictrn = G_TicsToCentiseconds(data.coop.tics);
ST_DrawNumFromHud(HUD_MINUTES, minutes); // Minutes
ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon
ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds
// we should show centiseconds on the intermission screen too, if the conditions are right.
if (modeattacking || cv_timetic.value == 2)
{
ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period
ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics
}
}
}
@ -320,7 +321,7 @@ void Y_IntermissionDrawer(void)
Y_IntermissionTokenDrawer();
// draw the header
if (intertic <= TICRATE)
if (intertic <= 2*TICRATE)
animatetic = 0;
else if (!animatetic && data.spec.bonus.points == 0 && data.spec.passed3[0] != '\0')
animatetic = intertic;
@ -370,14 +371,64 @@ void Y_IntermissionDrawer(void)
}
// draw the emeralds
if (intertic & 1)
//if (intertic & 1)
{
INT32 emeraldx = 80;
INT32 emeraldx = 152 - 3*28;
INT32 em = (gamemap - sstage_start);
for (i = 0; i < 7; ++i)
{
if (emeralds & (1 << i))
V_DrawScaledPatch(emeraldx, 74, 0, emeraldpics[i]);
emeraldx += 24;
if ((i != em) && !(intertic & 1) && (emeralds & (1 << i)))
V_DrawScaledPatch(emeraldx, 74, 0, emeraldpics[0][i]);
emeraldx += 28;
}
if (em < 7)
{
static UINT8 emeraldbounces = 0;
static INT32 emeraldmomy = 20;
static INT32 emeraldy = -40;
emeraldx = 152 + (em-3)*28;
if (intertic <= 1)
{
emeraldbounces = 0;
emeraldmomy = 20;
emeraldy = -40;
}
else
{
if (emeralds & (1 << em))
{
if (emeraldbounces < 3)
{
emeraldmomy += 1;
emeraldy += emeraldmomy;
if (emeraldy > 74)
{
S_StartSound(NULL, sfx_tink); // tink
emeraldbounces++;
emeraldmomy = -(emeraldmomy/2);
emeraldy = 74;
}
}
}
else
{
emeraldmomy += 1;
emeraldy += emeraldmomy;
emeraldx += intertic - 6;
if (emeraldbounces < 1 && emeraldy > 74)
{
S_StartSound(NULL, sfx_shldls); // nope
emeraldbounces++;
emeraldmomy = -(emeraldmomy/2);
emeraldy = 74;
}
}
V_DrawScaledPatch(emeraldx, emeraldy, 0, emeraldpics[0][em]);
}
}
}
@ -774,7 +825,7 @@ void Y_Ticker(void)
{
tallydonetic = intertic;
endtic = intertic + 3*TICRATE; // 3 second pause after end of tally
S_StartSound(NULL, sfx_chchng); // cha-ching!
S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching!
// Update when done with tally
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
@ -807,7 +858,7 @@ void Y_Ticker(void)
tallydonetic = -1;
}
if (intertic < TICRATE) // one second pause before tally begins
if (intertic < 2*TICRATE) // TWO second pause before tally begins, thank you mazmazz
return;
for (i = 0; i < MAXPLAYERS; i++)
@ -819,7 +870,7 @@ void Y_Ticker(void)
if ((intertic - tallydonetic) > (3*TICRATE)/2)
{
endtic = intertic + 4*TICRATE; // 4 second pause after end of tally
S_StartSound(NULL, sfx_s3kac); // cha-ching!
S_StartSound(NULL, sfx_s3kac); // bingly-bingly-bing!
}
return;
}
@ -839,7 +890,7 @@ void Y_Ticker(void)
if (!(data.spec.continues & 0x80)) // don't set endtic yet!
endtic = intertic + 4*TICRATE; // 4 second pause after end of tally
S_StartSound(NULL, sfx_chchng); // cha-ching!
S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching!
// Update when done with tally
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
@ -1767,13 +1818,13 @@ static void Y_AwardCoopBonuses(void)
players[i].score = MAXSCORE;
}
ptlives = (!ultimatemode && !modeattacking) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0;
ptlives = (!ultimatemode && !modeattacking && players[i].lives != 0x7f) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0;
if (ptlives)
P_GivePlayerLives(&players[i], ptlives);
if (i == consoleplayer)
{
data.coop.gotlife = ptlives;
data.coop.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
M_Memcpy(&data.coop.bonuses, &localbonuses, sizeof(data.coop.bonuses));
}
}
@ -1811,16 +1862,15 @@ static void Y_AwardSpecialStageBonus(void)
players[i].score = MAXSCORE;
// grant extra lives right away since tally is faked
ptlives = (!ultimatemode && !modeattacking) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0;
ptlives = (!ultimatemode && !modeattacking && players[i].lives != 0x7f) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0;
if (ptlives)
P_GivePlayerLives(&players[i], ptlives);
if (i == consoleplayer)
{
data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
M_Memcpy(&data.spec.bonus, &localbonus, sizeof(data.spec.bonus));
data.spec.gotlife = ptlives;
// Continues related
data.spec.continues = min(players[i].continues, 8);
if (players[i].gotcontinue)

View File

@ -82,6 +82,59 @@ typedef struct memblock_s
struct memblock_s *next, *prev;
} ATTRPACK memblock_t;
// both the head and tail of the zone memory block list
static memblock_t head;
//
// Function prototypes
//
static void Command_Memfree_f(void);
#ifdef ZDEBUG
static void Command_Memdump_f(void);
#endif
// --------------------------
// Zone memory initialisation
// --------------------------
/** Initialises zone memory.
* Used at game startup.
*
* \sa I_GetFreeMem, Command_Memfree_f, Command_Memdump_f
*/
void Z_Init(void)
{
UINT32 total, memfree;
memset(&head, 0x00, sizeof(head));
head.next = head.prev = &head;
memfree = I_GetFreeMem(&total)>>20;
CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree);
// Note: This allocates memory. Watch out.
COM_AddCommand("memfree", Command_Memfree_f);
#ifdef ZDEBUG
COM_AddCommand("memdump", Command_Memdump_f);
#endif
}
// ----------------------
// Zone memory allocation
// ----------------------
/** Returns the corresponding memblock_t for a given memory block.
*
* \param ptr A pointer to allocated memory,
* assumed to have been allocated with Z_Malloc/Z_Calloc.
* \param func A string containing the name of the function that called this,
* to be printed if the function I_Errors
* \return A pointer to the memblock_t for the given memory.
* \sa Z_Free, Z_ReallocAlign
*/
#ifdef ZDEBUG
#define Ptr2Memblock(s, f) Ptr2Memblock2(s, f, __FILE__, __LINE__)
static memblock_t *Ptr2Memblock2(void *ptr, const char* func, const char *file, INT32 line)
@ -131,32 +184,12 @@ static memblock_t *Ptr2Memblock(void *ptr, const char* func)
}
static memblock_t head;
static void Command_Memfree_f(void);
#ifdef ZDEBUG
static void Command_Memdump_f(void);
#endif
void Z_Init(void)
{
UINT32 total, memfree;
memset(&head, 0x00, sizeof(head));
head.next = head.prev = &head;
memfree = I_GetFreeMem(&total)>>20;
CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree);
// Note: This allocates memory. Watch out.
COM_AddCommand("memfree", Command_Memfree_f);
#ifdef ZDEBUG
COM_AddCommand("memdump", Command_Memdump_f);
#endif
}
/** Frees allocated memory.
*
* \param ptr A pointer to allocated memory,
* assumed to have been allocated with Z_Malloc/Z_Calloc.
* \sa Z_FreeTags
*/
#ifdef ZDEBUG
void Z_Free2(void *ptr, const char *file, INT32 line)
#else
@ -206,7 +239,11 @@ void Z_Free(void *ptr)
#endif
}
// malloc() that doesn't accept failure.
/** malloc() that doesn't accept failure.
*
* \param size Amount of memory to be allocated, in bytes.
* \return A pointer to the allocated memory.
*/
static void *xm(size_t size)
{
const size_t padedsize = size+sizeof (size_t);
@ -227,10 +264,18 @@ static void *xm(size_t size)
return p;
}
// Z_Malloc
// You can pass Z_Malloc() a NULL user if the tag is less than
// PU_PURGELEVEL.
/** The Z_MallocAlign function.
* Allocates a block of memory, adds it to a linked list so we can keep track of it.
*
* \param size Amount of memory to be allocated, in bytes.
* \param tag Purge tag.
* \param user The address of a pointer to the memory to be allocated.
* When the memory is freed by Z_Free later,
* the pointer at this address will then be automatically set to NULL.
* \param alignbits The alignment of the memory to be allocated, in bits. Can be 0.
* \note You can pass Z_Malloc() a NULL user if the tag is less than PU_PURGELEVEL.
* \sa Z_CallocAlign, Z_ReallocAlign
*/
#ifdef ZDEBUG
void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits,
const char *file, INT32 line)
@ -307,6 +352,19 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
return given;
}
/** The Z_CallocAlign function.
* Allocates a block of memory, adds it to a linked list so we can keep track of it.
* Unlike Z_MallocAlign, this also initialises the bytes to zero.
*
* \param size Amount of memory to be allocated, in bytes.
* \param tag Purge tag.
* \param user The address of a pointer to the memory to be allocated.
* When the memory is freed by Z_Free later,
* the pointer at this address will then be automatically set to NULL.
* \param alignbits The alignment of the memory to be allocated, in bits. Can be 0.
* \note You can pass Z_Calloc() a NULL user if the tag is less than PU_PURGELEVEL.
* \sa Z_MallocAlign, Z_ReallocAlign
*/
#ifdef ZDEBUG
void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line)
#else
@ -323,10 +381,26 @@ void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
#endif
}
/** The Z_ReallocAlign function.
* Reallocates a block of memory with a new size.
*
* \param ptr A pointer to allocated memory,
* assumed to have been allocated with Z_Malloc/Z_Calloc.
* If NULL, this function instead acts as a wrapper for Z_CallocAlign.
* \param size New size of memory block, in bytes.
* If zero, then the memory is freed and NULL is returned.
* \param tag New purge tag.
* \param user The address of a pointer to the memory to be reallocated.
* This can be a different user to the one originally assigned to the memory block.
* \param alignbits The alignment of the memory to be allocated, in bits. Can be 0.
* \return A pointer to the reallocated memory. Can be NULL if memory was freed.
* \note You can pass Z_Realloc() a NULL user if the tag is less than PU_PURGELEVEL.
* \sa Z_MallocAlign, Z_CallocAlign
*/
#ifdef ZDEBUG
void *Z_Realloc2(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line)
#else
void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignbits)
void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits)
#endif
{
void *rez;
@ -393,6 +467,11 @@ void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignb
return rez;
}
/** Frees all memory for a given set of tags.
*
* \param lowtag The lowest tag to consider.
* \param hightag The highest tag to consider.
*/
void Z_FreeTags(INT32 lowtag, INT32 hightag)
{
memblock_t *block, *next;
@ -407,22 +486,25 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
}
}
//
// Z_CheckMemCleanup
//
// TODO: Currently blocks >= PU_PURGELEVEL are freed every
// CLEANUPCOUNT. It might be better to keep track of
// the total size of all purgable memory and free it when the
// size exceeds some value.
//
// This was in Z_Malloc, but was freeing data at
// unsafe times. Now it is only called when it is safe
// to cleanup memory.
// -----------------
// Utility functions
// -----------------
// starting value of nextcleanup
#define CLEANUPCOUNT 2000
// number of function calls left before next cleanup
static INT32 nextcleanup = CLEANUPCOUNT;
/** This was in Z_Malloc, but was freeing data at
* unsafe times. Now it is only called when it is safe
* to cleanup memory.
*
* \todo Currently blocks >= PU_PURGELEVEL are freed every
* CLEANUPCOUNT. It might be better to keep track of
* the total size of all purgable memory and free it when the
* size exceeds some value.
*/
void Z_CheckMemCleanup(void)
{
if (nextcleanup-- == 0)
@ -538,10 +620,21 @@ void Z_CheckHeap(INT32 i)
}
}
// ------------------------
// Zone memory modification
// ------------------------
/** Changes a memory block's purge tag.
*
* \param ptr A pointer to allocated memory,
* assumed to have been allocated with Z_Malloc/Z_Calloc.
* \param tag The new tag.
* \sa Z_SetUser
*/
#ifdef PARANOIA
void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line)
#else
void Z_ChangeTag2(void *ptr, INT32 tag)
void Z_ChangeTag(void *ptr, INT32 tag)
#endif
{
memblock_t *block;
@ -583,99 +676,17 @@ void Z_ChangeTag2(void *ptr, INT32 tag)
block->tag = tag;
}
/** Calculates memory usage for a given set of tags.
* \param lowtag The lowest tag to consider.
* \param hightag The highest tag to consider.
* \return Number of bytes currently allocated in the heap for the
* given tags.
* \sa Z_TagUsage
/** Changes a memory block's user.
*
* \param ptr A pointer to allocated memory,
* assumed to have been allocated with Z_Malloc/Z_Calloc.
* \param newuser The new user for the memory block.
* \sa Z_ChangeTag
*/
size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
{
size_t cnt = 0;
memblock_t *rover;
for (rover = head.next; rover != &head; rover = rover->next)
{
if (rover->tag < lowtag || rover->tag > hightag)
continue;
cnt += rover->size + sizeof *rover;
}
return cnt;
}
size_t Z_TagUsage(INT32 tagnum)
{
return Z_TagsUsage(tagnum, tagnum);
}
void Command_Memfree_f(void)
{
UINT32 freebytes, totalbytes;
Z_CheckHeap(-1);
CONS_Printf("\x82%s", M_GetText("Memory Info\n"));
CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TagsUsage(0, INT32_MAX)>>10));
CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10));
CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10));
CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10));
CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10));
CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10));
CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10));
CONS_Printf(M_GetText("All purgable : %7s KB\n"),
sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10));
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
{
CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10));
CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10));
CONS_Printf(M_GetText("HW Texture cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10));
CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10));
CONS_Printf(M_GetText("HW Texture used : %7d KB\n"), HWR_GetTextureUsed()>>10);
}
#endif
CONS_Printf("\x82%s", M_GetText("System Memory Info\n"));
freebytes = I_GetFreeMem(&totalbytes);
CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10);
CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10);
}
#ifdef ZDEBUG
static void Command_Memdump_f(void)
{
memblock_t *block;
INT32 mintag = 0, maxtag = INT32_MAX;
INT32 i;
if ((i = COM_CheckParm("-min")))
mintag = atoi(COM_Argv(i + 1));
if ((i = COM_CheckParm("-max")))
maxtag = atoi(COM_Argv(i + 1));
for (block = head.next; block != &head; block = block->next)
if (block->tag >= mintag && block->tag <= maxtag)
{
char *filename = strrchr(block->ownerfile, PATHSEP[0]);
CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline);
}
}
#endif
// Creates a copy of a string.
char *Z_StrDup(const char *s)
{
return strcpy(ZZ_Alloc(strlen(s) + 1), s);
}
#ifdef PARANOIA
void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line)
#else
void Z_SetUser2(void *ptr, void **newuser)
void Z_SetUser(void *ptr, void **newuser)
#endif
{
memblock_t *block;
@ -707,3 +718,106 @@ void Z_SetUser2(void *ptr, void **newuser)
block->user = (void*)newuser;
*newuser = ptr;
}
// -----------------
// Zone memory usage
// -----------------
/** Calculates memory usage for a given set of tags.
*
* \param lowtag The lowest tag to consider.
* \param hightag The highest tag to consider.
* \return Number of bytes currently allocated in the heap for the
* given tags.
*/
size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
{
size_t cnt = 0;
memblock_t *rover;
for (rover = head.next; rover != &head; rover = rover->next)
{
if (rover->tag < lowtag || rover->tag > hightag)
continue;
cnt += rover->size + sizeof *rover;
}
return cnt;
}
// -----------------------
// Miscellaneous functions
// -----------------------
/** The function called by the "memfree" console command.
* Prints the memory being used by each part of the game to the console.
*/
static void Command_Memfree_f(void)
{
UINT32 freebytes, totalbytes;
Z_CheckHeap(-1);
CONS_Printf("\x82%s", M_GetText("Memory Info\n"));
CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TotalUsage()>>10));
CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10));
CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10));
CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10));
CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10));
CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10));
CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10));
CONS_Printf(M_GetText("All purgable : %7s KB\n"),
sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10));
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
{
CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10));
CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10));
CONS_Printf(M_GetText("HW Texture cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10));
CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10));
CONS_Printf(M_GetText("HW Texture used : %7d KB\n"), HWR_GetTextureUsed()>>10);
}
#endif
CONS_Printf("\x82%s", M_GetText("System Memory Info\n"));
freebytes = I_GetFreeMem(&totalbytes);
CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10);
CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10);
}
#ifdef ZDEBUG
/** The function called by the "memdump" console command.
* Prints zone memory debugging information (i.e. tag, size, location in code allocated).
* Can be all memory allocated in game, or between a set of tags (if -min/-max args used).
* This command is available only if ZDEBUG is enabled.
*/
static void Command_Memdump_f(void)
{
memblock_t *block;
INT32 mintag = 0, maxtag = INT32_MAX;
INT32 i;
if ((i = COM_CheckParm("-min")))
mintag = atoi(COM_Argv(i + 1));
if ((i = COM_CheckParm("-max")))
maxtag = atoi(COM_Argv(i + 1));
for (block = head.next; block != &head; block = block->next)
if (block->tag >= mintag && block->tag <= maxtag)
{
char *filename = strrchr(block->ownerfile, PATHSEP[0]);
CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline);
}
}
#endif
/** Creates a copy of a string.
*
* \param s The string to be copied.
* \return A copy of the string, allocated in zone memory.
*/
char *Z_StrDup(const char *s)
{
return strcpy(ZZ_Alloc(strlen(s) + 1), s);
}

View File

@ -30,92 +30,115 @@
//#define ZDEBUG
//
// ZONE MEMORY
// PU - purge tags.
// Tags < PU_LEVEL are not purged until freed explicitly.
#define PU_STATIC 1 // static entire execution time
#define PU_LUA 2 // static entire execution time -- used by lua so it doesn't get caught in loops forever
// Purge tags
//
// Now they are an enum! -- Monster Iestyn 15/02/18
//
enum
{
// Tags < PU_LEVEL are not purged until freed explicitly.
PU_STATIC = 1, // static entire execution time
PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever
#define PU_SOUND 11 // static while playing
#define PU_MUSIC 12 // static while playing
#define PU_HUDGFX 13 // static until WAD added
PU_SOUND = 11, // static while playing
PU_MUSIC = 12, // static while playing
PU_HUDGFX = 13, // static until WAD added
#define PU_HWRPATCHINFO 21 // Hardware GLPatch_t struct for OpenGL texture cache
#define PU_HWRPATCHCOLMIPMAP 22 // Hardware GLMipmap_t struct colromap variation of patch
PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache
PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch
#define PU_HWRCACHE 48 // static until unlocked
#define PU_CACHE 49 // static until unlocked
PU_HWRCACHE = 48, // static until unlocked
PU_CACHE = 49, // static until unlocked
// Tags s.t. PU_LEVEL <= tag < PU_PURGELEVEL are purged at level start
#define PU_LEVEL 50 // static until level exited
#define PU_LEVSPEC 51 // a special thinker in a level
#define PU_HWRPLANE 52
// Tags s.t. PU_LEVEL <= tag < PU_PURGELEVEL are purged at level start
PU_LEVEL = 50, // static until level exited
PU_LEVSPEC = 51, // a special thinker in a level
PU_HWRPLANE = 52, // if ZPLANALLOC is enabled in hw_bsp.c, this is used to alloc polygons for OpenGL
// Tags >= PU_PURGELEVEL are purgable whenever needed
#define PU_PURGELEVEL 100
#define PU_CACHE_UNLOCKED 101
#define PU_HWRCACHE_UNLOCKED 102 // 'second-level' cache for graphics
// stored in hardware format and downloaded as needed
#define PU_HWRPATCHINFO_UNLOCKED 103
// Tags >= PU_PURGELEVEL are purgable whenever needed
PU_PURGELEVEL = 100, // Note: this is never actually used as a tag
PU_CACHE_UNLOCKED = 101, // Note: unused
PU_HWRCACHE_UNLOCKED = 102, // 'unlocked' PU_HWRCACHE memory:
// 'second-level' cache for graphics
// stored in hardware format and downloaded as needed
PU_HWRPATCHINFO_UNLOCKED = 103, // 'unlocked' PU_HWRPATCHINFO memory
};
//
// Zone memory initialisation
//
void Z_Init(void);
void Z_FreeTags(INT32 lowtag, INT32 hightag);
void Z_CheckMemCleanup(void);
void Z_CheckHeap(INT32 i);
#ifdef PARANOIA
void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line);
#else
void Z_ChangeTag2(void *ptr, INT32 tag);
#endif
#ifdef PARANOIA
void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line);
#else
void Z_SetUser2(void *ptr, void **newuser);
#endif
//
// Zone memory allocation
//
// enable ZDEBUG to get the file + line the functions were called from
// for ZZ_Alloc, see doomdef.h
//
// Z_Free and alloc with alignment
#ifdef ZDEBUG
#define Z_Free(p) Z_Free2(p, __FILE__, __LINE__)
void Z_Free2(void *ptr, const char *file, INT32 line);
#define Z_Malloc(s,t,u) Z_Malloc2(s, t, u, 0, __FILE__, __LINE__)
#define Z_MallocAlign(s,t,u,a) Z_Malloc2(s, t, u, a, __FILE__, __LINE__)
void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1);
#define Z_Calloc(s,t,u) Z_Calloc2(s, t, u, 0, __FILE__, __LINE__)
#define Z_CallocAlign(s,t,u,a) Z_Calloc2(s, t, u, a, __FILE__, __LINE__)
void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1);
#define Z_Realloc(p,s,t,u) Z_Realloc2(p, s, t, u, 0, __FILE__, __LINE__)
#define Z_Free(p) Z_Free2(p, __FILE__, __LINE__)
#define Z_MallocAlign(s,t,u,a) Z_Malloc2(s, t, u, a, __FILE__, __LINE__)
#define Z_CallocAlign(s,t,u,a) Z_Calloc2(s, t, u, a, __FILE__, __LINE__)
#define Z_ReallocAlign(p,s,t,u,a) Z_Realloc2(p,s, t, u, a, __FILE__, __LINE__)
void Z_Free2(void *ptr, const char *file, INT32 line);
void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1);
void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1);
void *Z_Realloc2(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(2);
#else
void Z_Free(void *ptr);
void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(1);
#define Z_Malloc(s,t,u) Z_MallocAlign(s, t, u, 0)
void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(1);
#define Z_Calloc(s,t,u) Z_CallocAlign(s, t, u, 0)
void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(2) ;
#define Z_Realloc(p, s,t,u) Z_ReallocAlign(p, s, t, u, 0)
void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(2);
#endif
size_t Z_TagUsage(INT32 tagnum);
size_t Z_TagsUsage(INT32 lowtag, INT32 hightag);
// Alloc with no alignment
#define Z_Malloc(s,t,u) Z_MallocAlign(s, t, u, 0)
#define Z_Calloc(s,t,u) Z_CallocAlign(s, t, u, 0)
#define Z_Realloc(p,s,t,u) Z_ReallocAlign(p, s, t, u, 0)
char *Z_StrDup(const char *in);
// Free all memory by tag
// these don't give line numbers for ZDEBUG currently though
// (perhaps this should be changed in future?)
#define Z_FreeTag(tagnum) Z_FreeTags(tagnum, tagnum)
void Z_FreeTags(INT32 lowtag, INT32 hightag);
// This is used to get the local FILE : LINE info from CPP
// prior to really call the function in question.
//
// Utility functions
//
void Z_CheckMemCleanup(void);
void Z_CheckHeap(INT32 i);
//
// Zone memory modification
//
// enable PARANOIA to get the file + line the functions were called from
//
#ifdef PARANOIA
#define Z_ChangeTag(p,t) Z_ChangeTag2(p, t, __FILE__, __LINE__)
#define Z_SetUser(p,u) Z_SetUser2(p, u, __FILE__, __LINE__)
void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line);
void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line);
#else
#define Z_ChangeTag(p,t) Z_ChangeTag2(p, t)
void Z_ChangeTag(void *ptr, INT32 tag);
void Z_SetUser(void *ptr, void **newuser);
#endif
#ifdef PARANOIA
#define Z_SetUser(p,u) Z_SetUser2(p, u, __FILE__, __LINE__)
#else
#define Z_SetUser(p,u) Z_SetUser2(p, u)
#endif
//
// Zone memory usage
//
// Note: These give the memory used in bytes,
// shift down by 10 to convert to KB
//
#define Z_TagUsage(tagnum) Z_TagsUsage(tagnum, tagnum)
size_t Z_TagsUsage(INT32 lowtag, INT32 hightag);
#define Z_TotalUsage() Z_TagsUsage(0, INT32_MAX)
#define Z_Unlock(p) (void)p
//
// Miscellaneous functions
//
char *Z_StrDup(const char *in);
#define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed
#endif