Merge branch 'master' of https://git.magicalgirl.moe/STJr/SRB2Internal.git into hardcoding-time-again

This commit is contained in:
toasterbabe 2018-04-08 16:23:19 +01:00
commit 976331fb03
47 changed files with 3562 additions and 2198 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();

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);

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

@ -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);
}
@ -4518,6 +4522,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",
@ -5055,6 +5060,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",
@ -5072,6 +5093,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",
@ -5552,8 +5589,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Got Flag Sign
"S_GOTFLAG",
"S_GOTREDFLAG",
"S_GOTBLUEFLAG",
"S_CORK",
@ -5893,6 +5928,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
@ -6567,7 +6606,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
};
@ -6840,32 +6878,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",
@ -6873,7 +6901,7 @@ static const char *const HUDITEMS_LIST[] = {
"TIMELEFTNUM",
"TIMEUP",
"HUNTPICS",
"GRAVBOOTSICO",
"POWERUPS",
"LAP"
};
@ -7362,13 +7390,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},
@ -7394,7 +7430,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},
@ -7544,7 +7580,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"

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);

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;

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;

View File

@ -68,6 +68,7 @@ typedef struct gr_vissprite_s
struct gr_vissprite_s *prev;
struct gr_vissprite_s *next;
float x1, x2;
float z1, z2;
float tz, ty;
lumpnum_t patchlumpnum;
boolean flip;
@ -78,7 +79,6 @@ typedef struct gr_vissprite_s
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
float z1, z2;
} gr_vissprite_t;
// --------

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

@ -89,8 +89,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;
@ -250,20 +249,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
@ -939,7 +947,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;
@ -982,6 +990,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;
@ -1466,25 +1480,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]);
}
//
@ -1539,7 +1553,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;
@ -1551,7 +1565,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];
@ -1560,43 +1573,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)
@ -1753,19 +1735,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)
@ -1780,7 +1762,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

@ -63,8 +63,7 @@ extern patch_t *tallnum[10];
extern patch_t *nightsnum[10];
extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE];
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

@ -685,7 +685,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
@ -1732,9 +1732,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
@ -2264,39 +2265,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
@ -2785,8 +2818,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
@ -3171,11 +3202,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
@ -6436,8 +6471,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
@ -6463,8 +6498,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
@ -6490,8 +6525,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
@ -6517,8 +6552,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
@ -6544,8 +6579,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
@ -6571,8 +6606,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
@ -6598,8 +6633,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
@ -6625,8 +6660,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
@ -6652,8 +6687,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
@ -6679,8 +6714,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
@ -6706,8 +6741,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
@ -6733,8 +6768,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
@ -6760,8 +6795,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
@ -6787,8 +6822,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
@ -6814,8 +6849,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
@ -6841,8 +6876,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
@ -6868,8 +6903,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
@ -6895,8 +6930,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
@ -6922,8 +6957,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
@ -6949,8 +6984,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
@ -6976,8 +7011,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
@ -7003,8 +7038,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
@ -7030,8 +7065,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
@ -7057,8 +7092,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
@ -7084,8 +7119,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
@ -7111,8 +7146,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
@ -7138,8 +7173,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
@ -7165,8 +7200,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
@ -7192,8 +7227,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
@ -7219,8 +7254,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
@ -7246,8 +7281,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
@ -7273,8 +7308,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
@ -7300,8 +7335,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
@ -7327,8 +7362,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
@ -7354,8 +7389,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
@ -9250,7 +9285,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
},
@ -9277,7 +9312,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
},
@ -9304,7 +9339,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
},
@ -9331,7 +9366,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
},
@ -9358,7 +9393,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
},
@ -9385,7 +9420,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
},
@ -9412,7 +9447,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
},
@ -9434,7 +9469,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

@ -1840,6 +1840,7 @@ typedef enum state
S_BOXSPARKLE1,
S_BOXSPARKLE2,
S_BOXSPARKLE3,
S_BOXSPARKLE4,
S_BOX_FLICKER,
S_BOX_POP1,
@ -2379,6 +2380,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,
@ -2396,6 +2413,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,
@ -2876,8 +2909,6 @@ typedef enum state
// Got Flag Sign
S_GOTFLAG,
S_GOTREDFLAG,
S_GOTBLUEFLAG,
S_CORK,
@ -3217,6 +3248,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

@ -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

@ -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;
}
}

View File

@ -3244,14 +3244,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
@ -4918,6 +4911,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;
@ -4928,7 +4922,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;
@ -4937,10 +4930,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

@ -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)
{
@ -8617,6 +8702,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)
@ -9303,6 +9395,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
@ -9541,7 +9634,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
@ -9708,11 +9801,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;
@ -9749,8 +9842,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;
@ -9769,30 +9864,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)
@ -9830,7 +9924,7 @@ ML_EFFECT4 : Don't clip inside the ground
break;
}
if (!macetype)
if (!macetype && !chainlink)
break;
if (mobj->type != MT_CHAINPOINT)
@ -9859,7 +9953,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.
@ -9867,8 +9961,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));
@ -9877,25 +9973,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
@ -9903,14 +10001,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
{
@ -9929,36 +10027,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
@ -10062,9 +10197,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)
@ -10283,7 +10415,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

@ -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);

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;
@ -2336,12 +2364,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 +2382,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 +2441,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 +2610,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 +9561,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 +9734,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 +10444,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

@ -1446,6 +1446,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

@ -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)
@ -1771,13 +1822,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));
}
}
@ -1815,16 +1866,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)