Merge branch 'next' of https://git.magicalgirl.moe/STJr/SRB2/ into udmf-next

This commit is contained in:
Nev3r 2020-04-20 09:05:21 +02:00
commit efb81fc526
21 changed files with 314 additions and 126 deletions

View File

@ -15,7 +15,7 @@
* Oogaland
* Rob
* Shadow Hog
* Spherallic
* sphere
* SRB2-Playah
* SSNTails
* SteelT
@ -2208,6 +2208,7 @@ linedeftypes
title = "Spawn Object";
prefix = "(461)";
flags8text = "[3] Set delay by backside sector";
flags32text = "[5] Use line angle for object";
flags64text = "[6] Spawn inside a range";
}

View File

@ -80,7 +80,7 @@ static boolean joyaxis2_default = false;
static INT32 joyaxis_count = 0;
static INT32 joyaxis2_count = 0;
#define COM_BUF_SIZE 8192 // command buffer size
#define COM_BUF_SIZE (32<<10) // command buffer size
#define MAX_ALIAS_RECURSION 100 // max recursion allowed for aliases
static INT32 com_wait; // one command per frame (for cmd sequences)

View File

@ -20,12 +20,9 @@
#include "d_player.h"
/*
The 'packet version' may be used with packets whose
format is expected to change between versions.
This version is independent of the mod name, and standard
version and subversion. It should only account for the
basic fields of the packet, and change infrequently.
The 'packet version' is used to distinguish packet formats.
This version is independent of VERSION and SUBVERSION. Different
applications may follow different packet versions.
*/
#define PACKETVERSION 3

View File

@ -876,6 +876,40 @@ static inline void D_CleanFile(void)
}
}
///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so.
/// Done because browsers (at least, Firefox on Windows) launch the game from the browser's directory, which causes problems.
static void ChangeDirForUrlHandler(void)
{
// URL handlers are opened by web browsers (at least Firefox) from the browser's working directory, not the game's stored directory,
// so chdir to that directory unless overridden.
if (M_GetUrlProtocolArg() != NULL && !M_CheckParm("-nochdir"))
{
size_t i;
CONS_Printf("%s connect links load game files from the SRB2 application's stored directory. Switching to ", SERVER_URL_PROTOCOL);
strlcpy(srb2path, myargv[0], sizeof(srb2path));
// Get just the directory, minus the EXE name
for (i = strlen(srb2path)-1; i > 0; i--)
{
if (srb2path[i] == '/' || srb2path[i] == '\\')
{
srb2path[i] = '\0';
break;
}
}
CONS_Printf("%s\n", srb2path);
#if defined (_WIN32)
SetCurrentDirectoryA(srb2path);
#else
if (chdir(srb2path) == -1)
I_OutputMsg("Couldn't change working directory\n");
#endif
}
}
// ==========================================================================
// Identify the SRB2 version, and IWAD file to use.
// ==========================================================================
@ -1064,6 +1098,9 @@ void D_SRB2Main(void)
// Test Dehacked lists
DEH_Check();
// Netgame URL special case: change working dir to EXE folder.
ChangeDirForUrlHandler();
// identify the main IWAD file to use
IdentifyVersion();
@ -1149,9 +1186,15 @@ void D_SRB2Main(void)
if (M_CheckParm("-password") && M_IsNextParm())
D_SetPassword(M_GetNextParm());
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
Z_Init();
// Do this up here so that WADs loaded through the command line can use ExecCfg
COM_Init();
// add any files specified on the command line with -file wadfile
// to the wad list
if (!(M_CheckParm("-connect") && !M_CheckParm("-server")))
if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server")))
{
if (M_CheckParm("-file"))
{
@ -1176,9 +1219,6 @@ void D_SRB2Main(void)
if (M_CheckParm("-server") || dedicated)
netgame = server = true;
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
Z_Init();
// adapt tables to SRB2's needs, including extra slots for dehacked file support
P_PatchInfoTables();
@ -1186,7 +1226,7 @@ void D_SRB2Main(void)
M_InitMenuPresTables();
// init title screen display params
if (M_CheckParm("-connect"))
if (M_GetUrlProtocolArg() || M_CheckParm("-connect"))
F_InitMenuPresValues();
//---------------------------------------------------- READY TIME
@ -1250,7 +1290,6 @@ void D_SRB2Main(void)
CONS_Printf("HU_Init(): Setting up heads up display.\n");
HU_Init();
COM_Init();
CON_Init();
D_RegisterServerCommands();

View File

@ -3881,7 +3881,26 @@ static void readmaincfg(MYFILE *f)
value = atoi(word2); // used for numerical settings
if (fastcmp(word, "EXECCFG"))
COM_BufAddText(va("exec %s\n", word2));
{
if (strchr(word2, '.'))
COM_BufAddText(va("exec %s\n", word2));
else
{
lumpnum_t lumpnum;
char newname[9];
strncpy(newname, word2, 8);
newname[8] = '\0';
lumpnum = W_CheckNumForName(newname);
if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0)
CONS_Debug(DBG_SETUP, "SOC Error: script lump %s not found/not valid.\n", newname);
else
COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE));
}
}
else if (fastcmp(word, "SPSTAGE_START"))
{
@ -4123,6 +4142,10 @@ static void readmaincfg(MYFILE *f)
{
maxXtraLife = (UINT8)get_number(word2);
}
else if (fastcmp(word, "USECONTINUES"))
{
useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "GAMEDATA"))
{

View File

@ -150,6 +150,9 @@ extern char logfilename[1024];
// Otherwise we can't force updates!
#endif
/* A custom URL protocol for server links. */
#define SERVER_URL_PROTOCOL "srb2://"
// Does this version require an added patch file?
// Comment or uncomment this as necessary.
#define USE_PATCH_DTA

View File

@ -575,6 +575,8 @@ extern UINT8 creditscutscene;
extern UINT8 use1upSound;
extern UINT8 maxXtraLife; // Max extra lives from rings
extern UINT8 useContinues;
#define continuesInSession (!multiplayer && (useContinues || ultimatemode || !(cursaveslot > 0)))
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations

View File

@ -3618,7 +3618,7 @@ void F_StartContinue(void)
{
I_Assert(!netgame && !multiplayer);
if (players[consoleplayer].continues <= 0)
if (continuesInSession && players[consoleplayer].continues <= 0)
{
Command_ExitGame_f();
return;
@ -3725,7 +3725,9 @@ void F_ContinueDrawer(void)
}
// Draw the continue markers! Show continues.
if (ncontinues > 10)
if (!continuesInSession)
;
else if (ncontinues > 10)
{
if (!(continuetime & 1) || continuetime > 17)
V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);

View File

@ -219,6 +219,7 @@ UINT8 ammoremovaltics = 2*TICRATE;
UINT8 use1upSound = 0;
UINT8 maxXtraLife = 2; // Max extra lives from rings
UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes
UINT8 introtoplay;
UINT8 creditscutscene;
@ -3859,7 +3860,8 @@ static void G_DoContinued(void)
I_Assert(!netgame && !multiplayer);
I_Assert(pl->continues > 0);
pl->continues--;
if (pl->continues)
pl->continues--;
// Reset score
pl->score = 0;

View File

@ -467,7 +467,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
// -----------------+
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
{
polyvertex_t * pv;
@ -489,8 +489,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
(void)sector; ///@TODO remove shitty unused variable
// no convex poly were generated for this subsector
if (!xsub->planepoly)
return;
@ -587,8 +585,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight);
// transform
v3d = planeVerts;
if (FOFsector != NULL)
{
if (!isceiling) // it's a floor
@ -631,44 +627,43 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
{
// Hurdler: add scrolling texture on floor/ceiling
if (texflat)
{
v3d->sow = (float)(pv->x / fflatwidth) + scrollx;
v3d->tow = -(float)(pv->y / fflatheight) + scrolly;
}
else
{
v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx);
v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly);
}
#define SETUP3DVERT(vert, vx, vy) {\
/* Hurdler: add scrolling texture on floor/ceiling */\
if (texflat)\
{\
vert->sow = (float)((vx) / fflatwidth) + scrollx;\
vert->tow = -(float)((vy) / fflatheight) + scrolly;\
}\
else\
{\
vert->sow = (float)(((vx) / fflatwidth) - flatxref + scrollx);\
vert->tow = (float)(flatyref - ((vy) / fflatheight) + scrolly);\
}\
\
/* Need to rotate before translate */\
if (angle) /* Only needs to be done if there's an altered angle */\
{\
tempxsow = FLOAT_TO_FIXED(vert->sow);\
tempytow = FLOAT_TO_FIXED(vert->tow);\
if (texflat)\
tempytow = -tempytow;\
vert->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\
vert->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\
}\
\
vert->x = (vx);\
vert->y = height;\
vert->z = (vy);\
\
if (slope)\
{\
fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\
vert->y = FIXED_TO_FLOAT(fixedheight);\
}\
}
// Need to rotate before translate
if (angle) // Only needs to be done if there's an altered angle
{
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
if (texflat)
tempytow = -tempytow;
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
//v3d->sow = (float)(v3d->sow - flatxref + scrollx);
//v3d->tow = (float)(flatyref - v3d->tow + scrolly);
v3d->x = pv->x;
v3d->y = height;
v3d->z = pv->y;
if (slope)
{
fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y));
v3d->y = FIXED_TO_FLOAT(fixedheight);
}
}
for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++)
SETUP3DVERT(v3d, pv->x, pv->y);
// only useful for flat coloured triangles
//Surf.FlatColor = 0xff804020;
@ -679,36 +674,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
Surf.FlatColor.s.red = Surf.FlatColor.s.green =
Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); // Don't take from the frontsector, or the game will crash
#if 0 // no colormap test
// colormap test
if (gr_frontsector)
{
sector_t *psector = gr_frontsector;
if (slope)
fixedheight = P_GetZAt(slope, psector->soundorg.x, psector->soundorg.y);
if (psector->ffloors)
{
ffloor_t *caster = psector->lightlist[R_GetPlaneLight(psector, fixedheight, false)].caster;
psector = caster ? &sectors[caster->secnum] : psector;
if (caster)
{
lightlevel = psector->lightlevel;
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = LightLevelToLum(lightlevel);
}
}
if (psector->extra_colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel,psector->extra_colormap->rgba,psector->extra_colormap->fadergba, false, true);
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel,NORMALFOG,FADEFOG, false, true);
}
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel,NORMALFOG,FADEFOG, false, true);
#endif // NOPE
if (planecolormap)
{
if (fogplane)
@ -734,6 +699,79 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags);
if (subsector)
{
// Horizon lines
FOutVector horizonpts[6];
float dist, vx, vy;
float x1, y1, xd, yd;
UINT8 numplanes, j;
vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
const float renderdist = 27000.0f; // How far out to properly render the plane
const float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
seg_t *line = &segs[subsector->firstline];
for (i = 0; i < subsector->numlines; i++, line++)
{
if (!line->glseg && line->linedef->special == HORIZONSPECIAL && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0)
{
P_ClosestPointOnLine(viewx, viewy, line->linedef, &v);
dist = FIXED_TO_FLOAT(R_PointToDist(v.x, v.y));
x1 = ((polyvertex_t *)line->pv1)->x;
y1 = ((polyvertex_t *)line->pv1)->y;
xd = ((polyvertex_t *)line->pv2)->x - x1;
yd = ((polyvertex_t *)line->pv2)->y - y1;
// Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion
dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f;
if (dist > 100.0f)
numplanes = 100;
else
numplanes = (UINT8)dist + 1;
for (j = 0; j < numplanes; j++)
{
// Left side
vx = x1 + xd * j / numplanes;
vy = y1 + yd * j / numplanes;
SETUP3DVERT((&horizonpts[1]), vx, vy);
dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
SETUP3DVERT((&horizonpts[0]), vx, vy);
// Right side
vx = x1 + xd * (j+1) / numplanes;
vy = y1 + yd * (j+1) / numplanes;
SETUP3DVERT((&horizonpts[2]), vx, vy);
dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
SETUP3DVERT((&horizonpts[3]), vx, vy);
// Horizon fills
vx = (horizonpts[0].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
vy = (horizonpts[0].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
SETUP3DVERT((&horizonpts[5]), vx, vy);
horizonpts[5].y = gr_viewz;
vx = (horizonpts[3].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
vy = (horizonpts[3].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
SETUP3DVERT((&horizonpts[4]), vx, vy);
horizonpts[4].y = gr_viewz;
// Draw
HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags);
}
}
}
}
#ifdef ALAM_LIGHTING
// add here code for dynamic lighting on planes
HWR_PlaneLighting(planeVerts, nrPlaneVerts);
@ -3339,7 +3377,7 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount)
{
HWR_GetLevelFlat(&levelflats[gr_frontsector->floorpic]);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
HWR_RenderPlane(sub, &extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
@ -3361,7 +3399,7 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount)
{
HWR_GetLevelFlat(&levelflats[gr_frontsector->ceilingpic]);
HWR_RenderPlane(NULL, &extrasubsectors[num], true,
HWR_RenderPlane(sub, &extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
@ -3453,7 +3491,7 @@ static void HWR_Subsector(size_t num)
{
HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -3515,7 +3553,7 @@ static void HWR_Subsector(size_t num)
{
HWR_GetLevelFlat(&levelflats[*rover->toppic]);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}

View File

@ -1478,7 +1478,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
// rotation pivot
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height/2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height/(flip ? -2 : 2));
// rotation axis
if (sprinfo->available)
@ -1490,6 +1490,9 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
p.rollflip = 1;
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
p.rollflip = -1;
if (flip)
p.rollflip *= -1;
}
p.anglex = 0.0f;

View File

@ -1423,6 +1423,7 @@ static void SOCK_ClearBans(void)
boolean I_InitTcpNetwork(void)
{
char serverhostname[255];
const char *urlparam = NULL;
boolean ret = false;
// initilize the OS's TCP/IP stack
if (!I_InitTcpDriver())
@ -1476,10 +1477,12 @@ boolean I_InitTcpNetwork(void)
ret = true;
}
else if (M_CheckParm("-connect"))
else if ((urlparam = M_GetUrlProtocolArg()) != NULL || M_CheckParm("-connect"))
{
if (M_IsNextParm())
strcpy(serverhostname, M_GetNextParm());
if (urlparam != NULL)
strlcpy(serverhostname, urlparam, sizeof(serverhostname));
else if (M_IsNextParm())
strlcpy(serverhostname, M_GetNextParm(), sizeof(serverhostname));
else
serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it

View File

@ -34,6 +34,25 @@ boolean myargmalloc = false;
*/
static INT32 found;
/** \brief Parses a server URL (such as srb2://127.0.0.1) as may be passed to the game via a web browser, etc.
\return the contents of the URL after the protocol (a server to join), or NULL if not found
*/
const char *M_GetUrlProtocolArg(void)
{
INT32 i;
const size_t len = strlen(SERVER_URL_PROTOCOL);
for (i = 1; i < myargc; i++)
{
if (strlen(myargv[i]) > len && !strnicmp(myargv[i], SERVER_URL_PROTOCOL, len))
{
return &myargv[i][len];
}
}
return NULL;
}
/** \brief The M_CheckParm function

View File

@ -21,6 +21,9 @@ extern INT32 myargc;
extern char **myargv;
extern boolean myargmalloc;
// Looks for an srb2:// (or similar) URL passed in as an argument and returns the IP to connect to if found.
const char *M_GetUrlProtocolArg(void);
// Returns the position of the given parameter in the arg list (0 if not found).
INT32 M_CheckParm(const char *check);

View File

@ -934,6 +934,12 @@ void Command_Setcontinues_f(void)
REQUIRE_NOULTIMATE;
REQUIRE_PANDORA;
if (!continuesInSession)
{
CONS_Printf(M_GetText("This session does not use continues.\n"));
return;
}
if (COM_Argc() > 1)
{
INT32 numcontinues = atoi(COM_Argv(1));

View File

@ -6728,6 +6728,7 @@ static void M_PandorasBox(INT32 choice)
else
CV_StealthSetValue(&cv_dummylives, max(players[consoleplayer].lives, 1));
CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues);
SR_PandorasBox[3].status = (continuesInSession) ? (IT_STRING | IT_CVAR) : (IT_GRAYEDOUT);
SR_PandorasBox[6].status = (players[consoleplayer].charflags & SF_SUPER) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL);
SR_PandorasBox[7].status = (emeralds == ((EMERALD7)*2)-1) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL);
M_SetupNextMenu(&SR_PandoraDef);
@ -6744,7 +6745,7 @@ static boolean M_ExitPandorasBox(void)
}
if (cv_dummylives.value != players[consoleplayer].lives)
COM_ImmedExecute(va("setlives %d", cv_dummylives.value));
if (cv_dummycontinues.value != players[consoleplayer].continues)
if (continuesInSession && cv_dummycontinues.value != players[consoleplayer].continues)
COM_ImmedExecute(va("setcontinues %d", cv_dummycontinues.value));
return true;
}
@ -8264,9 +8265,19 @@ static void M_DrawLoadGameData(void)
V_DrawRightAlignedThinString(x + 79, y, V_YELLOWMAP, savegameinfo[savetodraw].levelname);
}
if ((savegameinfo[savetodraw].lives == -42)
|| (savegameinfo[savetodraw].lives == -666))
if (savegameinfo[savetodraw].lives == -42)
{
if (!useContinues)
V_DrawRightAlignedThinString(x + 80, y+1+60+16, V_GRAYMAP, "00000000");
continue;
}
if (savegameinfo[savetodraw].lives == -666)
{
if (!useContinues)
V_DrawRightAlignedThinString(x + 80, y+1+60+16, V_REDMAP, "????????");
continue;
}
y += 64;
@ -8283,7 +8294,7 @@ static void M_DrawLoadGameData(void)
y -= 4;
// character heads, lives, and continues
// character heads, lives, and continues/score
{
spritedef_t *sprdef;
spriteframe_t *sprframe;
@ -8334,10 +8345,14 @@ skipbot:
skipsign:
y += 16;
tempx = x + 10;
if (savegameinfo[savetodraw].lives != INFLIVES
&& savegameinfo[savetodraw].lives > 9)
tempx -= 4;
tempx = x;
if (useContinues)
{
tempx += 10;
if (savegameinfo[savetodraw].lives != INFLIVES
&& savegameinfo[savetodraw].lives > 9)
tempx -= 4;
}
if (!charskin) // shut up compiler
goto skiplife;
@ -8367,22 +8382,45 @@ skiplife:
else
V_DrawString(tempx, y, 0, va("%d", savegameinfo[savetodraw].lives));
tempx = x + 47;
if (savegameinfo[savetodraw].continues > 9)
tempx -= 4;
// continues
if (savegameinfo[savetodraw].continues > 0)
if (!useContinues)
{
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH));
V_DrawScaledPatch(tempx + 9, y + 2, 0, patch);
V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continues));
INT32 workingscorenum = savegameinfo[savetodraw].continuescore;
char workingscorestr[11] = " 000000000\0";
SINT8 j = 9;
// Change the above two lines if MAXSCORE ever changes from 8 digits long.
workingscorestr[0] = '\x86'; // done here instead of in initialiser 'cuz compiler complains
if (!workingscorenum)
j--; // just so ONE digit is not greyed out
else
{
while (workingscorenum)
{
workingscorestr[j--] = '0' + (workingscorenum % 10);
workingscorenum /= 10;
}
}
workingscorestr[j] = (savegameinfo[savetodraw].continuescore == MAXSCORE) ? '\x83' : '\x80';
V_DrawRightAlignedThinString(x + 80, y+1, 0, workingscorestr);
}
else
{
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH));
V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH));
V_DrawString(tempx + 16, y, V_GRAYMAP, "0");
tempx = x + 47;
if (savegameinfo[savetodraw].continuescore > 9)
tempx -= 4;
// continues
if (savegameinfo[savetodraw].continuescore > 0)
{
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH));
V_DrawScaledPatch(tempx + 9, y + 2, 0, patch);
V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continuescore));
}
else
{
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH));
V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH));
V_DrawString(tempx + 16, y, V_GRAYMAP, "0");
}
}
}
}
@ -8515,9 +8553,11 @@ static void M_ReadSavegameInfo(UINT32 slot)
CHECKPOS
savegameinfo[slot].lives = READSINT8(save_p); // lives
CHECKPOS
(void)READINT32(save_p); // Score
savegameinfo[slot].continuescore = READINT32(save_p); // score
CHECKPOS
savegameinfo[slot].continues = READINT32(save_p); // continues
fake = READINT32(save_p); // continues
if (useContinues)
savegameinfo[slot].continuescore = fake;
// File end marker check
CHECKPOS

View File

@ -397,7 +397,7 @@ typedef struct
UINT8 numemeralds;
UINT8 numgameovers;
INT32 lives;
INT32 continues;
INT32 continuescore;
INT32 gamemap;
} saveinfo_t;

View File

@ -633,7 +633,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (ALL7EMERALDS(emeralds)) // Got all 7
{
if (!(netgame || multiplayer))
if (continuesInSession)
{
player->continues += 1;
player->gotcontinue = true;
@ -643,7 +643,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(toucher, sfx_chchng);
}
else
{
P_GiveCoopLives(player, 1, true); // if continues are disabled, a life is a reasonable substitute
S_StartSound(toucher, sfx_chchng);
}
}
else
{

View File

@ -4045,7 +4045,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
mobj = P_SpawnMobj(x, y, z, type);
if (mobj)
{
if (line->flags & ML_EFFECT1)
mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y);
CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow.
}
else
CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special);
}

View File

@ -1388,7 +1388,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
// Continues are worthless in netgames.
// If that stops being the case uncomment this.
/* if (!ultimatemode && players[i].marescore > 50000
/* if (!ultimatemode && continuesInSession && players[i].marescore > 50000
&& oldscore < 50000)
{
players[i].continues += 1;
@ -1408,7 +1408,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
else
player->marescore = MAXSCORE;
if (!ultimatemode && !(netgame || multiplayer) && G_IsSpecialStage(gamemap)
if (!ultimatemode && continuesInSession && G_IsSpecialStage(gamemap)
&& player->marescore >= 50000 && oldscore < 50000)
{
player->continues += 1;
@ -9543,7 +9543,7 @@ static void P_DeathThink(player_t *player)
// continue logic
if (!(netgame || multiplayer) && player->lives <= 0)
{
if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0)
if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0))
G_UseContinue();
else if (player->deadtimer >= gameovertics)
G_UseContinue(); // Even if we don't have one this handles ending the game

View File

@ -564,7 +564,7 @@ dontdrawbg:
V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score);
// Draw continues!
if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay
if (continuesInSession /* && (data.spec.continues & 0x80) */) // Always draw when continues are a thing
{
UINT8 continues = data.spec.continues & 0x7F;