Merge remote-tracking branch 'origin/master' into menu-execs

This commit is contained in:
mazmazz 2018-11-25 19:03:22 -05:00
commit ab47e83939
35 changed files with 1522 additions and 595 deletions

View file

@ -288,7 +288,9 @@ static void D_Display(void)
{
// Fade to black first
if ((wipegamestate == (gamestate_t)FORCEWIPE ||
!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) // fades to black on its own timing, always
(wipegamestate != (gamestate_t)-2
&& !(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
) // fades to black on its own timing, always
&& wipetypepre != UINT8_MAX)
{
F_WipeStartScreen();
@ -370,89 +372,96 @@ static void D_Display(void)
break;
}
// clean up border stuff
// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide))
// STUPID race condition...
if (wipegamestate == GS_INTRO && gamestate == GS_TITLESCREEN)
wipegamestate = -2;
else
{
// draw the view directly
wipegamestate = gamestate;
if (!automapactive && !dedicated && cv_renderview.value)
// clean up border stuff
// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide))
{
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// draw the view directly
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
if (!automapactive && !dedicated && cv_renderview.value)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
R_RenderPlayerView(&players[secondarydisplayplayer]);
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect
if (rendermode == render_soft)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
}
// Image postprocessing effect
if (rendermode == render_soft)
if (lastdraw)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
usebuffer = true;
}
lastdraw = false;
}
}
if (lastdraw)
{
if (rendermode == render_soft)
if (gamestate == GS_LEVEL)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
usebuffer = true;
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
lastdraw = false;
else
F_TitleScreenDrawer();
}
if (gamestate == GS_LEVEL)
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
else
F_TitleScreenDrawer();
}
// change gamma if needed
// (GS_LEVEL handles this already due to level-specific palettes)
if (forcerefresh && gamestate != GS_LEVEL)
if (forcerefresh && !(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
V_SetPalette(0);
wipegamestate = gamestate;
// draw pause pic
if (paused && cv_showhud.value && (!menuactive || netgame))
{
#if 0
INT32 py;
patch_t *patch;
if (automapactive)
@ -461,6 +470,11 @@ static void D_Display(void)
py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_CACHE);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch);
#else
INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2));
M_DrawTextBox((BASEVIDWIDTH/2) - (60), y - (16), 13, 2);
V_DrawCenteredString(BASEVIDWIDTH/2, y - (4), V_YELLOWMAP, "Game Paused");
#endif
}
// vid size change is now finished if it was on...

View file

@ -3105,26 +3105,14 @@ static void Command_Addfile(void)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
{
size_t packetsize = 0;
serverinfo_pak *dummycheck = NULL;
// Shut the compiler up.
(void)dummycheck;
// See W_LoadWadFile in w_wad.c
for (i = 0; i < numwadfiles; i++)
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
packetsize += nameonlylength(fn) + 22;
if ((numwadfiles >= MAX_WADFILES)
|| (packetsize > sizeof(dummycheck->fileneeded)))
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
WRITESTRINGN(buf_p,p,240);
@ -3174,11 +3162,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
boolean kick = false;
boolean toomany = false;
INT32 i;
size_t packetsize = 0;
serverinfo_pak *dummycheck = NULL;
// Shut the compiler up.
(void)dummycheck;
READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16);
@ -3205,13 +3188,8 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
}
// See W_LoadWadFile in w_wad.c
for (i = 0; i < numwadfiles; i++)
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
packetsize += nameonlylength(filename) + 22;
if ((numwadfiles >= MAX_WADFILES)
|| (packetsize > sizeof(dummycheck->fileneeded)))
|| ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8)))
toomany = true;
else
ncs = findfile(filename,md5sum,true);
@ -3364,6 +3342,9 @@ static void Command_Playintro_f(void)
if (netgame)
return;
if (dirmenu)
closefilemenu(true);
F_StartIntro();
}
@ -4012,6 +3993,9 @@ void Command_ExitGame_f(void)
cv_debug = 0;
emeralds = 0;
if (dirmenu)
closefilemenu(true);
if (!modeattacking)
D_StartTitle();
}

View file

@ -324,10 +324,6 @@ INT32 CL_CheckFiles(void)
INT32 ret = 1;
size_t packetsize = 0;
size_t filestoget = 0;
serverinfo_pak *dummycheck = NULL;
// Shut the compiler up.
(void)dummycheck;
// if (M_CheckParm("-nofiles"))
// return 1;
@ -371,8 +367,7 @@ INT32 CL_CheckFiles(void)
}
// See W_LoadWadFile in w_wad.c
for (i = 0; i < numwadfiles; i++)
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
packetsize = packetsizetally;
for (i = 1; i < fileneedednum; i++)
{
@ -396,7 +391,7 @@ INT32 CL_CheckFiles(void)
packetsize += nameonlylength(fileneeded[i].filename) + 22;
if ((numwadfiles+filestoget >= MAX_WADFILES)
|| (packetsize > sizeof(dummycheck->fileneeded)))
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
return 3;
filestoget++;
@ -899,10 +894,11 @@ void nameonly(char *s)
{
ns = &(s[j+1]);
len = strlen(ns);
if (false)
M_Memcpy(s, ns, len+1);
else
memmove(s, ns, len+1);
#if 0
M_Memcpy(s, ns, len+1);
#else
memmove(s, ns, len+1);
#endif
return;
}
}

View file

@ -455,6 +455,8 @@ typedef struct player_s
UINT8 drilldelay;
boolean bonustime; // Capsule destroyed, now it's bonus time!
mobj_t *capsule; // Go inside the capsule
mobj_t *drone; // Move center to the drone
fixed_t oldscale; // Pre-Nightserize scale
UINT8 mare; // Current mare
UINT8 marelap; // Current mare lap
UINT8 marebonuslap; // Current mare lap starting from bonus time

View file

@ -6582,8 +6582,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_TOAD",
// Nights-specific stuff
"S_NIGHTSDRONE1",
"S_NIGHTSDRONE2",
"S_NIGHTSDRONE_MAN1",
"S_NIGHTSDRONE_MAN2",
"S_NIGHTSDRONE_SPARKLING1",
"S_NIGHTSDRONE_SPARKLING2",
"S_NIGHTSDRONE_SPARKLING3",
@ -6600,10 +6600,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_NIGHTSDRONE_SPARKLING14",
"S_NIGHTSDRONE_SPARKLING15",
"S_NIGHTSDRONE_SPARKLING16",
"S_NIGHTSGOAL1",
"S_NIGHTSGOAL2",
"S_NIGHTSGOAL3",
"S_NIGHTSGOAL4",
"S_NIGHTSDRONE_GOAL1",
"S_NIGHTSDRONE_GOAL2",
"S_NIGHTSDRONE_GOAL3",
"S_NIGHTSDRONE_GOAL4",
"S_NIGHTSPARKLE1",
"S_NIGHTSPARKLE2",
@ -7474,7 +7474,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_AXISTRANSFER",
"MT_AXISTRANSFERLINE",
"MT_NIGHTSDRONE",
"MT_NIGHTSGOAL",
"MT_NIGHTSDRONE_MAN",
"MT_NIGHTSDRONE_SPARKLING",
"MT_NIGHTSDRONE_GOAL",
"MT_NIGHTSPARKLE",
"MT_NIGHTSLOOPHELPER",
"MT_NIGHTSBUMPER", // NiGHTS Bumper
@ -7491,6 +7493,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_NIGHTSEXTRATIME",
"MT_NIGHTSLINKFREEZE",
"MT_EGGCAPSULE",
"MT_IDEYAANCHOR",
"MT_NIGHTOPIANHELPER", // the actual helper object that orbits you
"MT_PIAN", // decorative singing friend
"MT_SHLEEP", // almost-decorative sleeping enemy

View file

@ -446,7 +446,7 @@ extern INT32 cv_debug;
#define DBG_BASIC 0x0001
#define DBG_DETAILED 0x0002
#define DBG_RANDOMIZER 0x0004
#define DBG_PLAYER 0x0004
#define DBG_RENDER 0x0008
#define DBG_NIGHTSBASIC 0x0010
#define DBG_NIGHTS 0x0020
@ -456,6 +456,7 @@ extern INT32 cv_debug;
#define DBG_MEMORY 0x0200
#define DBG_SETUP 0x0400
#define DBG_LUA 0x0800
#define DBG_RANDOMIZER 0x1000
// =======================
// Misc stuff for later...

View file

@ -29,6 +29,7 @@
#include "g_input.h"
#include "console.h"
#include "m_random.h"
#include "m_misc.h" // moviemode functionality
#include "y_inter.h"
#include "m_cond.h"
#include "p_local.h"
@ -249,7 +250,7 @@ void F_StartIntro(void)
introtext[2] = M_GetText(
"As it was about to drain the rings\n"
"away from the planet, Sonic burst into\n"
"the Satellite and for what he thought\n"
"the control room and for what he thought\n"
"would be the last time,\xB4 defeated\n"
"Dr. Eggman.\n#");
@ -259,11 +260,11 @@ void F_StartIntro(void)
"return,\xB8 bringing an all new threat.\n#");
introtext[4] = M_GetText(
"\xA8""About once every year, a strange asteroid\n"
"\xA8""About every five years, a strange asteroid\n"
"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 one week.\xBF\n"
"vanishes after only one week.\xBF\n"
"No one knows why it appears, or how.\n#");
introtext[5] = M_GetText(
@ -316,7 +317,7 @@ void F_StartIntro(void)
"\xA5\"6...\xD2""5...\xD2""4...\"\xA8\xD2\n"
"Sonic knew he was getting closer to the\n"
"zone, and pushed himself harder.\xB4 Finally,\n"
"the mountain appeared in the horizon.\xD2\xD2\n"
"the mountain appeared on the horizon.\xD2\xD2\n"
"\xA5\"3...\xD2""2...\xD2""1...\xD2""Zero.\"\n#");
introtext[11] = M_GetText(
@ -749,18 +750,27 @@ void F_IntroDrawer(void)
// Stay on black for a bit. =)
{
tic_t quittime;
quittime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
while (quittime > I_GetTime())
tic_t nowtime, quittime, lasttime;
nowtime = lasttime = I_GetTime();
quittime = nowtime + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
while (quittime > nowtime)
{
while (!((nowtime = I_GetTime()) - lasttime))
I_Sleep();
lasttime = nowtime;
I_OsPolling();
I_UpdateNoBlit();
M_Drawer(); // menu is drawn even on top of wipes
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
}
D_StartTitle();
wipegamestate = GS_INTRO;
return;
}
F_NewCutscene(introtext[++intro_scenenum]);
@ -1566,7 +1576,7 @@ void F_TitleScreenDrawer(void)
else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS)
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
// Don't draw outside of the title screewn, or if the patch isn't there.
// Don't draw outside of the title screen, or if the patch isn't there.
if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
return;
@ -1926,6 +1936,9 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
G_SetGamestate(GS_CUTSCENE);
if (wipegamestate == GS_CUTSCENE)
wipegamestate = -1;
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();

View file

@ -101,7 +101,7 @@ void F_MenuPresTicker(boolean run);
// WIPE
//
// HACK for menu fading while titlemapinaction; skips the level check
#define FORCEWIPE -2
#define FORCEWIPE -3
extern boolean WipeInAction;
extern INT32 lastwipetic;

View file

@ -306,9 +306,14 @@ closedir (DIR * dirp)
}
#endif
static CV_PossibleValue_t addons_cons_t[] = {{0, "SRB2 Folder"}, /*{1, "HOME"}, {2, "SRB2 Folder"},*/ {3, "CUSTOM"}, {0, NULL}};
consvar_t cv_addons_option = {"addons_option", "SRB2 Folder", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_folder = {"addons_folder", "./", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"},
#if 1
{1, "HOME"}, {2, "SRB2"},
#endif
{3, "CUSTOM"}, {0, NULL}};
consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -326,10 +331,11 @@ size_t menudepthleft = menudepth;
char menusearch[MAXSTRINGLENGTH+1];
char **dirmenu;
size_t sizedirmenu;
char **dirmenu, **coredirmenu; // core only local for this file
size_t sizedirmenu, sizecoredirmenu; // ditto
size_t dir_on[menudepth];
UINT8 refreshdirmenu = 0;
char *refreshdirname = NULL;
size_t packetsizetally = 0;
size_t mainwadstally = 0;
@ -362,9 +368,9 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
return FS_NOTFOUND;
}
if (searchpath[searchpathindex[depthleft]-2] != '/')
if (searchpath[searchpathindex[depthleft]-2] != PATHSEP[0])
{
searchpath[searchpathindex[depthleft]-1] = '/';
searchpath[searchpathindex[depthleft]-1] = PATHSEP[0];
searchpath[searchpathindex[depthleft]] = 0;
}
else
@ -406,7 +412,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
depthleft++;
}
searchpath[searchpathindex[depthleft]-1]='/';
searchpath[searchpathindex[depthleft]-1]=PATHSEP[0];
searchpath[searchpathindex[depthleft]]=0;
}
else if (!strcasecmp(searchname, dent->d_name))
@ -446,7 +452,7 @@ char exttable[NUM_EXT_TABLE][5] = {
char filenamebuf[MAX_WADFILES][MAX_WADPATH];
static boolean filemenusearch(char *haystack, char *needle)
static boolean filemenucmp(char *haystack, char *needle)
{
static char localhaystack[128];
strlcpy(localhaystack, haystack, 128);
@ -457,21 +463,151 @@ static boolean filemenusearch(char *haystack, char *needle)
: (!strncmp(localhaystack, needle, menusearch[0])));
}
#define searchdir if (menusearch[0] && !filemenusearch(dent->d_name, localmenusearch))\
{\
rejected++;\
continue;\
}\
void closefilemenu(boolean validsize)
{
// search
if (dirmenu)
{
if (dirmenu != coredirmenu)
{
if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS))
{
Z_Free(dirmenu[0]);
dirmenu[0] = NULL;
}
Z_Free(dirmenu);
}
dirmenu = NULL;
sizedirmenu = 0;
}
if (coredirmenu)
{
// core
if (validsize)
{
for (; sizecoredirmenu > 0; sizecoredirmenu--)
{
Z_Free(coredirmenu[sizecoredirmenu-1]);
coredirmenu[sizecoredirmenu-1] = NULL;
}
}
else
sizecoredirmenu = 0;
Z_Free(coredirmenu);
coredirmenu = NULL;
}
if (refreshdirname)
Z_Free(refreshdirname);
refreshdirname = NULL;
}
void searchfilemenu(char *tempname)
{
size_t i, first;
char localmenusearch[MAXSTRINGLENGTH] = "";
if (dirmenu)
{
if (dirmenu != coredirmenu)
{
if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS))
{
Z_Free(dirmenu[0]);
dirmenu[0] = NULL;
}
//Z_Free(dirmenu); -- Z_Realloc later tho...
}
else
dirmenu = NULL;
}
first = (((UINT8)(coredirmenu[0][DIR_TYPE]) == EXT_UP) ? 1 : 0); // skip UP...
if (!menusearch[0])
{
if (dirmenu)
Z_Free(dirmenu);
dirmenu = coredirmenu;
sizedirmenu = sizecoredirmenu;
if (tempname)
{
for (i = first; i < sizedirmenu; i++)
{
if (!strcmp(dirmenu[i]+DIR_STRING, tempname))
{
dir_on[menudepthleft] = i;
break;
}
}
if (i == sizedirmenu)
dir_on[menudepthleft] = first;
Z_Free(tempname);
}
return;
}
strcpy(localmenusearch, menusearch+1);
if (!cv_addons_search_case.value)
strupr(localmenusearch);
sizedirmenu = 0;
for (i = first; i < sizecoredirmenu; i++)
{
if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch))
sizedirmenu++;
}
if (!sizedirmenu) // no results...
{
if ((!(dirmenu = Z_Realloc(dirmenu, sizeof(char *), PU_STATIC, NULL)))
|| !(dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS))))
I_Error("Ran out of memory whilst preparing add-ons menu");
sizedirmenu = 1;
dir_on[menudepthleft] = 0;
if (tempname)
Z_Free(tempname);
return;
}
if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
I_Error("Ran out of memory whilst preparing add-ons menu");
sizedirmenu = 0;
for (i = first; i < sizecoredirmenu; i++)
{
if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch))
{
if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname))
{
dir_on[menudepthleft] = sizedirmenu;
Z_Free(tempname);
tempname = NULL;
}
dirmenu[sizedirmenu++] = coredirmenu[i]; // pointer reuse
}
}
if (tempname)
{
dir_on[menudepthleft] = 0;
Z_Free(tempname);
}
}
boolean preparefilemenu(boolean samedepth)
{
DIR *dirhandle;
struct dirent *dent;
struct stat fsstat;
size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0;
size_t pos = 0, folderpos = 0, numfolders = 0;
char *tempname = NULL;
boolean noresults = false;
char localmenusearch[MAXSTRINGLENGTH] = "";
if (samedepth)
{
@ -481,20 +617,16 @@ boolean preparefilemenu(boolean samedepth)
else
menusearch[0] = menusearch[1] = 0; // clear search
for (; sizedirmenu > 0; sizedirmenu--) // clear out existing items
if (!(dirhandle = opendir(menupath))) // get directory
{
Z_Free(dirmenu[sizedirmenu-1]);
dirmenu[sizedirmenu-1] = NULL;
closefilemenu(true);
return false;
}
if (!(dirhandle = opendir(menupath))) // get directory
return false;
if (menusearch[0])
for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items
{
strcpy(localmenusearch, menusearch+1);
if (!cv_addons_search_case.value)
strupr(localmenusearch);
Z_Free(coredirmenu[sizecoredirmenu-1]);
coredirmenu[sizecoredirmenu-1] = NULL;
}
while (true)
@ -526,43 +658,42 @@ boolean preparefilemenu(boolean samedepth)
if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
}
searchdir;
}
else // directory
{
searchdir;
numfolders++;
}
sizedirmenu++;
sizecoredirmenu++;
}
}
if (!rejected && !sizedirmenu)
if (!sizecoredirmenu)
{
closedir(dirhandle);
closefilemenu(false);
if (tempname)
Z_Free(tempname);
closedir(dirhandle);
return false;
}
if (((noresults = (menusearch[0] && !sizedirmenu)))
|| (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry
if (menudepthleft != menudepth-1) // Make room for UP...
{
sizedirmenu++;
sizecoredirmenu++;
numfolders++;
folderpos++;
}
if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
if (dirmenu && dirmenu == coredirmenu)
dirmenu = NULL;
if (!(coredirmenu = Z_Realloc(coredirmenu, sizecoredirmenu*sizeof(char *), PU_STATIC, NULL)))
{
closedir(dirhandle); // just in case
I_Error("Ran out of memory whilst preparing add-ons menu");
}
rejected = 0;
rewinddir(dirhandle);
while ((pos+folderpos) < sizedirmenu)
while ((pos+folderpos) < sizecoredirmenu)
{
menupath[menupathindex[menudepthleft]] = 0;
dent = readdir(dirhandle);
@ -588,14 +719,12 @@ boolean preparefilemenu(boolean samedepth)
if (!S_ISDIR(fsstat.st_mode)) // file
{
if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention
if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention
for (; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
ext += EXT_START; // moving to be appropriate position
searchdir;
if (ext >= EXT_LOADSTART)
{
size_t i;
@ -628,10 +757,7 @@ boolean preparefilemenu(boolean samedepth)
folder = 0;
}
else // directory
{
searchdir;
len += (folder = 1);
}
if (len > 255)
len = 255;
@ -643,46 +769,31 @@ boolean preparefilemenu(boolean samedepth)
strlcpy(temp+DIR_STRING, dent->d_name, len);
if (folder)
{
strcpy(temp+len, "/");
dirmenu[folderpos++] = temp;
strcpy(temp+len, PATHSEP);
coredirmenu[folderpos++] = temp;
}
else
dirmenu[numfolders + pos++] = temp;
coredirmenu[numfolders + pos++] = temp;
}
}
closedir(dirhandle);
if (noresults) // no results
dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS));
else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry
dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP));
if ((menudepthleft != menudepth-1) // now for UP... entry
&& !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP))))
I_Error("Ran out of memory whilst preparing add-ons menu");
menupath[menupathindex[menudepthleft]] = 0;
sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind
sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind
if (tempname)
{
size_t i;
for (i = 0; i < sizedirmenu; i++)
{
if (!strcmp(dirmenu[i]+DIR_STRING, tempname))
{
dir_on[menudepthleft] = i;
break;
}
}
Z_Free(tempname);
}
if (!sizedirmenu)
if (!sizecoredirmenu)
{
dir_on[menudepthleft] = 0;
Z_Free(dirmenu);
closefilemenu(false);
return false;
}
else if (dir_on[menudepthleft] >= sizedirmenu)
dir_on[menudepthleft] = sizedirmenu-1;
searchfilemenu(tempname);
return true;
}

View file

@ -40,6 +40,7 @@ extern char **dirmenu;
extern size_t sizedirmenu;
extern size_t dir_on[menudepth];
extern UINT8 refreshdirmenu;
extern char *refreshdirname;
extern size_t packetsizetally;
extern size_t mainwadstally;
@ -87,6 +88,8 @@ typedef enum
REFRESHDIR_MAX = 32
} refreshdir_enum;
void closefilemenu(boolean validsize);
void searchfilemenu(char *tempname);
boolean preparefilemenu(boolean samedepth);
#endif // __FILESRCH_H__

View file

@ -328,19 +328,21 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook = {"alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook = {"alwaysmlook", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse2 = {"invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook2 = {"alwaysmlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove = {"mousemove", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove2 = {"mousemove2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_analog = {"analog", "Off", CV_CALL, CV_OnOff, Analog_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_analog2 = {"analog2", "Off", CV_CALL, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog = {"useranalog", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog2 = {"useranalog2", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove = {"mousemove", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove2 = {"mousemove2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t directionchar_cons_t[] = {{0, "Camera"}, {1, "Movement"}, {0, NULL}};
// previously "analog", "analog2", "useranalog", and "useranalog2", invalidating 2.1-era copies of config.cfg
// changed because it'd be nice to see people try out our actually good controls with gamepads now autobrake exists
consvar_t cv_analog = {"sessionanalog", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_analog2 = {"sessionanalog2", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog = {"configanalog", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog2 = {"configanalog2", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
// deez New User eXperiences
static CV_PossibleValue_t directionchar_cons_t[] = {{0, "Camera"}, {1, "Movement"}, {0, NULL}};
consvar_t cv_directionchar = {"directionchar", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_directionchar2 = {"directionchar2", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobrake = {"autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange, 0, NULL, NULL, 0, 0, NULL};
@ -1650,7 +1652,8 @@ void G_DoLoadLevel(boolean resetplayer)
CON_ClearHUD();
}
static INT32 pausedelay = 0;
INT32 pausedelay = 0;
boolean pausebreakkey = false;
static INT32 camtoggledelay, camtoggledelay2 = 0;
//
@ -1798,19 +1801,35 @@ boolean G_Responder(event_t *ev)
{
case ev_keydown:
if (ev->data1 == gamecontrol[gc_pause][0]
|| ev->data1 == gamecontrol[gc_pause][1])
|| ev->data1 == gamecontrol[gc_pause][1]
|| ev->data1 == KEY_PAUSE)
{
if (!pausedelay)
if (modeattacking && !demoplayback && (gamestate == GS_LEVEL))
{
// don't let busy scripts prevent pausing
pausedelay = NEWTICRATE/7;
pausebreakkey = (ev->data1 == KEY_PAUSE);
if (menuactive || pausedelay < 0 || leveltime < 2)
return true;
// command will handle all the checks for us
COM_ImmedExecute("pause");
return true;
if (pausedelay < 1+(NEWTICRATE/2))
pausedelay = 1+(NEWTICRATE/2);
else if (++pausedelay > 1+(NEWTICRATE/2)+(NEWTICRATE/3))
{
G_SetRetryFlag();
return true;
}
pausedelay++; // counteract subsequent subtraction this frame
}
else
pausedelay = NEWTICRATE/7;
{
INT32 oldpausedelay = pausedelay;
pausedelay = (NEWTICRATE/7);
if (!oldpausedelay)
{
// command will handle all the checks for us
COM_ImmedExecute("pause");
return true;
}
}
}
if (ev->data1 == gamecontrol[gc_camtoggle][0]
|| ev->data1 == gamecontrol[gc_camtoggle][1])
@ -1870,11 +1889,19 @@ void G_Ticker(boolean run)
{
G_ClearRetryFlag();
// Costs a life to retry ... unless the player in question is dead already.
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
players[consoleplayer].lives -= 1;
if (modeattacking)
{
pausedelay = INT32_MIN;
M_ModeAttackRetry(0);
}
else
{
// Costs a life to retry ... unless the player in question is dead already.
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer);
G_DoReborn(consoleplayer);
}
}
for (i = 0; i < MAXPLAYERS; i++)
@ -1975,8 +2002,13 @@ void G_Ticker(boolean run)
if (run)
{
if (pausedelay)
pausedelay--;
if (pausedelay && pausedelay != INT32_MIN)
{
if (pausedelay > 0)
pausedelay--;
else
pausedelay++;
}
if (camtoggledelay)
camtoggledelay--;
@ -2922,6 +2954,9 @@ static void G_DoCompleted(void)
tokenlist = 0; // Reset the list
if (modeattacking && pausedelay)
pausedelay = 0;
gameaction = ga_nothing;
if (metalplayback)

View file

@ -53,6 +53,8 @@ extern INT16 prevmap, nextmap;
extern INT32 gameovertics;
extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
extern INT16 rw_maximums[NUM_WEAPONS];
extern INT32 pausedelay;
extern boolean pausebreakkey;
// used in game menu
extern consvar_t cv_tutorialprompt;

View file

@ -709,7 +709,7 @@ void G_DefineDefaultControls(void)
gamecontroldefault[i][gc_teamkey ][0] = 'y';
gamecontroldefault[i][gc_scores ][0] = KEY_TAB;
gamecontroldefault[i][gc_console ][0] = KEY_CONSOLE;
gamecontroldefault[i][gc_pause ][0] = KEY_PAUSE;
gamecontroldefault[i][gc_pause ][0] = 'p';
}
}
@ -814,11 +814,31 @@ static void setcontrol(INT32 (*gc)[2], INT32 na)
return;
}
keynum = G_KeyStringtoNum(COM_Argv(2));
if (keynum == KEY_PAUSE) // fail silently; pause is hardcoded
{
if (na == 4)
{
na--;
keynum = G_KeyStringtoNum(COM_Argv(3));
if (keynum == KEY_PAUSE)
return;
}
else
return;
}
G_CheckDoubleUsage(keynum);
gc[numctrl][0] = keynum;
if (na == 4)
gc[numctrl][1] = G_KeyStringtoNum(COM_Argv(3));
{
keynum = G_KeyStringtoNum(COM_Argv(3));
if (keynum != KEY_PAUSE)
gc[numctrl][1] = keynum;
else
gc[numctrl][1] = 0;
}
else
gc[numctrl][1] = 0;
}

View file

@ -29,6 +29,7 @@
#include "../m_argv.h"
#include "../i_video.h"
#include "../w_wad.h"
#include "../p_setup.h" // levelfadecol
// --------------------------------------------------------------------------
// This is global data for planes rendering
@ -644,7 +645,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
sprintf(s, "%d%%", (++ls_percent)<<1);
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); // Background to match fade in effect
//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
M_DrawTextBox(x-58, y-8, 13, 1);
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");

View file

@ -5731,7 +5731,7 @@ static void HWR_DrawSkyBackground(player_t *player)
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = ((float) (-angle) / ((ANGLE_90-1)*dimensionmultiply)); // left
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior

View file

@ -1040,25 +1040,29 @@ UINT16 hu_demorings;
static void HU_DrawDemoInfo(void)
{
V_DrawString(4, 188-24, V_YELLOWMAP, va(M_GetText("%s's replay"), player_names[0]));
INT32 h = 188;
if (modeattacking == ATTACKING_NIGHTS)
h -= 12;
V_DrawString(4, h-24, V_YELLOWMAP|V_ALLOWLOWERCASE, va(M_GetText("%s's replay"), player_names[0]));
if (modeattacking)
{
V_DrawString(4, 188-16, V_YELLOWMAP|V_MONOSPACE, "SCORE:");
V_DrawRightAlignedString(120, 188-16, V_MONOSPACE, va("%d", hu_demoscore));
V_DrawString(4, h-16, V_YELLOWMAP|V_MONOSPACE, "SCORE:");
V_DrawRightAlignedString(120, h-16, V_MONOSPACE, va("%d", hu_demoscore));
V_DrawString(4, 188- 8, V_YELLOWMAP|V_MONOSPACE, "TIME:");
V_DrawString(4, h-8, V_YELLOWMAP|V_MONOSPACE, "TIME:");
if (hu_demotime != UINT32_MAX)
V_DrawRightAlignedString(120, 188- 8, V_MONOSPACE, va("%i:%02i.%02i",
V_DrawRightAlignedString(120, h-8, V_MONOSPACE, va("%i:%02i.%02i",
G_TicsToMinutes(hu_demotime,true),
G_TicsToSeconds(hu_demotime),
G_TicsToCentiseconds(hu_demotime)));
else
V_DrawRightAlignedString(120, 188- 8, V_MONOSPACE, "--:--.--");
V_DrawRightAlignedString(120, h-8, V_MONOSPACE, "--:--.--");
if (modeattacking == ATTACKING_RECORD)
{
V_DrawString(4, 188 , V_YELLOWMAP|V_MONOSPACE, "RINGS:");
V_DrawRightAlignedString(120, 188 , V_MONOSPACE, va("%d", hu_demorings));
V_DrawString(4, h, V_YELLOWMAP|V_MONOSPACE, "RINGS:");
V_DrawRightAlignedString(120, h, V_MONOSPACE, va("%d", hu_demorings));
}
}
}
@ -1127,6 +1131,31 @@ void HU_Drawer(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text);
}
if (modeattacking && pausedelay > 0 && !pausebreakkey)
{
INT32 strength = ((pausedelay - 1 - NEWTICRATE/2)*10)/(NEWTICRATE/3);
INT32 y = hudinfo[HUD_LIVES].y - 13;
if (players[consoleplayer].powers[pw_carry] == CR_NIGHTSMODE)
y -= 16;
else
{
if (players[consoleplayer].pflags & PF_AUTOBRAKE)
y -= 8;
if (players[consoleplayer].pflags & PF_ANALOGMODE)
y -= 8;
}
V_DrawThinString(hudinfo[HUD_LIVES].x-2, y,
hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_SKYMAP : V_BLUEMAP),
"HOLD TO RETRY...");
if (strength > 9)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
else if (strength > 0)
V_DrawFadeScreen(0, strength);
}
}
//======================================================================

View file

@ -3278,8 +3278,8 @@ state_t states[NUMSTATES] =
{SPR_TOAD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_TOAD
// Nights Drone
{SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE2}, // S_NIGHTSDRONE1
{SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_NIGHTSDRONE2
{SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN2}, // S_NIGHTSDRONE_MAN1
{SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN1}, // S_NIGHTSDRONE_MAN2
// Sparkling point (RETURN TO THE GOAL, etc)
{SPR_IVSP, 0, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING2}, // S_NIGHTSDRONE_SPARKLING1
@ -3300,10 +3300,10 @@ state_t states[NUMSTATES] =
{SPR_IVSP, 30, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING1}, // S_NIGHTSDRONE_SPARKLING16
// NiGHTS GOAL banner (inside the sparkles!)
{SPR_GOAL, 0, 4, {NULL}, 0, 0, S_NIGHTSGOAL2}, // S_NIGHTSGOAL1
{SPR_GOAL, 1, 4, {NULL}, 0, 0, S_NIGHTSGOAL3}, // S_NIGHTSGOAL2
{SPR_GOAL, 2, 4, {NULL}, 0, 0, S_NIGHTSGOAL4}, // S_NIGHTSGOAL3
{SPR_GOAL, 3, 4, {NULL}, 0, 0, S_NIGHTSGOAL1}, // S_NIGHTSGOAL4
{SPR_GOAL, 0, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL2}, // S_NIGHTSDRONE_GOAL1
{SPR_GOAL, 1, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL3}, // S_NIGHTSDRONE_GOAL2
{SPR_GOAL, 2, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL4}, // S_NIGHTSDRONE_GOAL3
{SPR_GOAL, 3, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL1}, // S_NIGHTSDRONE_GOAL4
// Nights Sparkle
{SPR_NSPK, FF_FULLBRIGHT, 140, {NULL}, 0, 0, S_NIGHTSPARKLE2}, // S_NIGHTSPARKLE1
@ -16652,7 +16652,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSDRONE
1703, // doomednum
S_NIGHTSDRONE1, // spawnstate
S_INVISIBLE, // spawnstate
120, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -16668,18 +16668,45 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
56*FRACUNIT, // height
80*FRACUNIT, // height
1, // display offset
1000, // mass
0, // damage
sfx_ideya, // activesound
MF_SPECIAL, // flags
MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_NIGHTSGOAL
{ // MT_NIGHTSDRONE_MAN
-1, // doomednum
S_INVISIBLE, // spawnstate
120, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
255, // painchance
sfx_None, // painsound
S_NIGHTSDRONE_MAN1, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
56*FRACUNIT, // height
1, // display offset
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_NIGHTSDRONE_SPARKLING
-1, // doomednum
S_NIGHTSGOAL1, // spawnstate
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -16688,14 +16715,41 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // painstate
255, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NIGHTSDRONE_SPARKLING1, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
56*FRACUNIT, // height
24*FRACUNIT, // height
1, // display offset
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_NIGHTSDRONE_GOAL
-1, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
255, // painchance
sfx_None, // painsound
S_NIGHTSDRONE_GOAL1, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
-1, // display offset
1000, // mass
0, // damage
@ -17136,6 +17190,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_IDEYAANCHOR
1714, // doomednum
S_INVISIBLE, // spawnstate
0, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
1*FRACUNIT, // radius
2*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
{ // MT_NIGHTOPIANHELPER
-1, // doomednum
S_NIGHTOPIANHELPER1, // spawnstate

View file

@ -3344,8 +3344,8 @@ typedef enum state
S_TOAD,
// Nights-specific stuff
S_NIGHTSDRONE1,
S_NIGHTSDRONE2,
S_NIGHTSDRONE_MAN1,
S_NIGHTSDRONE_MAN2,
S_NIGHTSDRONE_SPARKLING1,
S_NIGHTSDRONE_SPARKLING2,
S_NIGHTSDRONE_SPARKLING3,
@ -3362,10 +3362,10 @@ typedef enum state
S_NIGHTSDRONE_SPARKLING14,
S_NIGHTSDRONE_SPARKLING15,
S_NIGHTSDRONE_SPARKLING16,
S_NIGHTSGOAL1,
S_NIGHTSGOAL2,
S_NIGHTSGOAL3,
S_NIGHTSGOAL4,
S_NIGHTSDRONE_GOAL1,
S_NIGHTSDRONE_GOAL2,
S_NIGHTSDRONE_GOAL3,
S_NIGHTSDRONE_GOAL4,
S_NIGHTSPARKLE1,
S_NIGHTSPARKLE2,
@ -4256,7 +4256,9 @@ typedef enum mobj_type
MT_AXISTRANSFER,
MT_AXISTRANSFERLINE,
MT_NIGHTSDRONE,
MT_NIGHTSGOAL,
MT_NIGHTSDRONE_MAN,
MT_NIGHTSDRONE_SPARKLING,
MT_NIGHTSDRONE_GOAL,
MT_NIGHTSPARKLE,
MT_NIGHTSLOOPHELPER,
MT_NIGHTSBUMPER, // NiGHTS Bumper
@ -4273,6 +4275,7 @@ typedef enum mobj_type
MT_NIGHTSEXTRATIME,
MT_NIGHTSLINKFREEZE,
MT_EGGCAPSULE,
MT_IDEYAANCHOR,
MT_NIGHTOPIANHELPER, // the actual helper object that orbits you
MT_PIAN, // decorative singing friend
MT_SHLEEP, // almost-decorative sleeping enemy

View file

@ -288,6 +288,10 @@ static int player_get(lua_State *L)
lua_pushboolean(L, plr->bonustime);
else if (fastcmp(field,"capsule"))
LUA_PushUserdata(L, plr->capsule, META_MOBJ);
else if (fastcmp(field,"drone"))
LUA_PushUserdata(L, plr->drone, META_MOBJ);
else if (fastcmp(field,"oldscale"))
lua_pushfixed(L, plr->oldscale);
else if (fastcmp(field,"mare"))
lua_pushinteger(L, plr->mare);
else if (fastcmp(field,"marelap"))
@ -586,6 +590,15 @@ static int player_set(lua_State *L)
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->capsule, mo);
}
else if (fastcmp(field,"drone"))
{
mobj_t *mo = NULL;
if (!lua_isnil(L, 3))
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->drone, mo);
}
else if (fastcmp(field,"oldscale"))
plr->oldscale = luaL_checkfixed(L, 3);
else if (fastcmp(field,"mare"))
plr->mare = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marelap"))

View file

@ -571,7 +571,7 @@ void Command_Teleport_f(void)
}
else // scan the thinkers to find starposts...
{
mobj_t *mo2;
mobj_t *mo2 = NULL;
thinker_t *th;
INT32 starpostmax = 0;

View file

@ -284,7 +284,6 @@ static void M_Statistics(INT32 choice);
static void M_ReplayTimeAttack(INT32 choice);
static void M_ChooseTimeAttack(INT32 choice);
static void M_ChooseNightsAttack(INT32 choice);
static void M_ModeAttackRetry(INT32 choice);
static void M_ModeAttackEndGame(INT32 choice);
static void M_SetGuestReplay(INT32 choice);
static void M_HandleChoosePlayerMenu(INT32 choice);
@ -344,7 +343,6 @@ static void M_EraseData(INT32 choice);
static void M_Addons(INT32 choice);
static void M_AddonsOptions(INT32 choice);
static patch_t *addonsp[NUM_EXT+6];
static UINT8 addonsresponselimit = 0;
#define numaddonsshown 4
@ -1078,10 +1076,10 @@ static menuitem_t OP_ChangeControlsMenu[] =
{IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_use },
{IT_HEADER, NULL, "Camera", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Camera Up", M_ChangeControl, gc_lookup },
{IT_CALL | IT_STRING2, NULL, "Camera Down", M_ChangeControl, gc_lookdown },
{IT_CALL | IT_STRING2, NULL, "Camera Left", M_ChangeControl, gc_turnleft },
{IT_CALL | IT_STRING2, NULL, "Camera Right", M_ChangeControl, gc_turnright },
{IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup },
{IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown },
{IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, gc_turnleft },
{IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, gc_turnright },
{IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview },
{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming },
{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle},
@ -1090,7 +1088,7 @@ static menuitem_t OP_ChangeControlsMenu[] =
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Game Status",
M_ChangeControl, gc_scores },
{IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause },
{IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, gc_pause },
{IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console },
{IT_HEADER, NULL, "Multiplayer", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
@ -2658,15 +2656,19 @@ static void M_GoBack(INT32 choice)
if (!Playing() && netgame && multiplayer)
{
MSCloseUDPSocket(); // Clean up so we can re-open the connection later.
netgame = false;
multiplayer = false;
netgame = multiplayer = false;
}
if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef))
{
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
Z_Free(levelselect.rows);
levelselect.rows = NULL;
if (levelselect.rows)
{
Z_Free(levelselect.rows);
levelselect.rows = NULL;
}
menuactive = false;
wipetypepre = menupres[M_GetYoungestChildMenu()].exitwipe;
D_StartTitle();
@ -5326,22 +5328,24 @@ static void M_Addons(INT32 choice)
(void)choice;
/*if (cv_addons_option.value == 0)
pathname = srb2home; usehome ? srb2home : srb2path;
#if 1
if (cv_addons_option.value == 0)
pathname = usehome ? srb2home : srb2path;
else if (cv_addons_option.value == 1)
pathname = srb2home;
else if (cv_addons_option.value == 2)
pathname = srb2path;
else*/
else
#endif
if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
pathname = cv_addons_folder.string;
strlcpy(menupath, pathname, 1024);
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
if (menupath[menupathindex[menudepthleft]-2] != '/')
if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0])
{
menupath[menupathindex[menudepthleft]-1] = '/';
menupath[menupathindex[menudepthleft]-1] = PATHSEP[0];
menupath[menupathindex[menudepthleft]] = 0;
}
else
@ -5435,11 +5439,7 @@ static char *M_AddonsHeaderPath(void)
UINT32 len;
static char header[1024];
if (menupath[0] == '.')
strlcpy(header, va("SRB2 folder%s", menupath+1), 1024);
else
strcpy(header, menupath);
strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024);
len = strlen(header);
if (len > 34)
{
@ -5456,6 +5456,15 @@ static char *M_AddonsHeaderPath(void)
M_SetupNextMenu(MISC_AddonsDef.prevMenu);\
M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
#define CLEARNAME Z_Free(refreshdirname);\
refreshdirname = NULL
static void M_AddonsClearName(INT32 choice)
{
CLEARNAME;
M_StopMessage(choice);
}
// returns whether to do message draw
static boolean M_AddonsRefresh(void)
{
@ -5467,35 +5476,35 @@ static boolean M_AddonsRefresh(void)
if (refreshdirmenu & REFRESHDIR_ADDFILE)
{
addonsresponselimit = 0;
char *message = NULL;
if (refreshdirmenu & REFRESHDIR_NOTLOADED)
{
char *message = NULL;
S_StartSound(NULL, sfx_lose);
if (refreshdirmenu & REFRESHDIR_MAX)
message = va("\x82%s\x80\nMaximum number of add-ons reached.\nThis file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
message = va("\x82%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", refreshdirname);
else
message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
M_StartMessage(message,NULL,MM_NOTHING);
return true;
message = va("\x82%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", refreshdirname);
}
if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
{
S_StartSound(NULL, sfx_skid);
M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING);
message = va("\x82%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings"));
}
if (message)
{
M_StartMessage(message,M_AddonsClearName,MM_EVENTHANDLER);
return true;
}
S_StartSound(NULL, sfx_strpst);
CLEARNAME;
}
return false;
}
#define offs 1
#ifdef FIXUPO0
#pragma GCC optimize ("0")
#endif
@ -5513,9 +5522,6 @@ static void M_DrawAddons(void)
return;
}
if (addonsresponselimit)
addonsresponselimit--;
if (Playing())
topstr = "\x85""Adding files mid-game may cause problems.";
else if (savemoddata)
@ -5525,7 +5531,7 @@ static void M_DrawAddons(void)
else
topstr = LOCATIONSTRING;
V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, topstr);
V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, topstr);
if (numwadfiles <= mainwads+1)
y = 0;
@ -5545,7 +5551,7 @@ static void M_DrawAddons(void)
// DRAW MENU
x = currentMenu->x;
y = currentMenu->y + offs;
y = currentMenu->y + 1;
//M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width
V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), V_YELLOWMAP|V_ALLOWLOWERCASE, M_AddonsHeaderPath());
@ -5553,7 +5559,7 @@ static void M_DrawAddons(void)
V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 26);
V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 26);
V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1 + offs) - (y - 1), 159);
V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1), 159);
// get bottom...
max = dir_on[menudepthleft] + numaddonsshown + 1;
@ -5609,7 +5615,7 @@ static void M_DrawAddons(void)
if (max != (ssize_t)sizedirmenu)
V_DrawString(19, y-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B");
y = BASEVIDHEIGHT - currentMenu->y + offs;
y = BASEVIDHEIGHT - currentMenu->y + 1;
M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
if (menusearch[0])
@ -5623,21 +5629,17 @@ static void M_DrawAddons(void)
x -= (21 + 5 + 16);
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
#define CANSAVE (!modifiedgame || savemoddata)
x = BASEVIDWIDTH - x - 16;
V_DrawSmallScaledPatch(x, y + 4, (CANSAVE ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]);
V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]);
if (modifiedgame)
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]);
#undef CANSAVE
}
#ifdef FIXUPO0
#pragma GCC reset_options
#endif
#undef offs
static void M_AddonExec(INT32 ch)
{
if (ch != 'y' && ch != KEY_ENTER)
@ -5689,16 +5691,17 @@ static void M_HandleAddons(INT32 choice)
{
boolean exitmenu = false; // exit to previous menu
if (addonsresponselimit)
return;
if (M_ChangeStringAddons(choice))
{
if (!preparefilemenu(true))
char *tempname = NULL;
if (dirmenu && dirmenu[dir_on[menudepthleft]])
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
searchfilemenu(tempname);
/*if (!preparefilemenu(true))
{
UNEXIST;
return;
}
}*/
}
switch (choice)
@ -5797,7 +5800,6 @@ static void M_HandleAddons(INT32 choice)
case EXT_WAD:
case EXT_PK3:
COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
addonsresponselimit = 5;
break;
default:
S_StartSound(NULL, sfx_lose);
@ -5817,14 +5819,7 @@ static void M_HandleAddons(INT32 choice)
}
if (exitmenu)
{
for (; sizedirmenu > 0; sizedirmenu--)
{
Z_Free(dirmenu[sizedirmenu-1]);
dirmenu[sizedirmenu-1] = NULL;
}
Z_Free(dirmenu);
dirmenu = NULL;
closefilemenu(true);
// secrets disabled by addfile...
MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
@ -8535,9 +8530,10 @@ static void M_SetGuestReplay(INT32 choice)
which(0);
}
static void M_ModeAttackRetry(INT32 choice)
void M_ModeAttackRetry(INT32 choice)
{
(void)choice;
// todo -- maybe seperate this out and G_SetRetryFlag() here instead? is just calling this from the menu 100% safe?
G_CheckDemoStatus(); // Cancel recording
if (modeattacking == ATTACKING_RECORD)
M_ChooseTimeAttack(0);
@ -9953,6 +9949,7 @@ static void M_DrawControl(void)
#undef controlbuffer
static INT32 controltochange;
static char controltochangetext[55];
static void M_ChangecontrolResponse(event_t *ev)
{
@ -9960,8 +9957,8 @@ static void M_ChangecontrolResponse(event_t *ev)
INT32 found;
INT32 ch = ev->data1;
// ESCAPE cancels
if (ch != KEY_ESCAPE)
// ESCAPE cancels; dummy out PAUSE
if (ch != KEY_ESCAPE && ch != KEY_PAUSE)
{
switch (ev->type)
@ -10022,6 +10019,24 @@ static void M_ChangecontrolResponse(event_t *ev)
}
S_StartSound(NULL, sfx_strpst);
}
else if (ch == KEY_PAUSE)
{
static char tmp[155];
menu_t *prev = currentMenu->prevMenu;
if (controltochange == gc_pause)
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit cannot be used to retry runs \nduring Record Attack. \n\nHit another key for\n%s\nESC for Cancel"),
controltochangetext);
else
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit is not configurable. \n\nHit another key for\n%s\nESC for Cancel"),
controltochangetext);
M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER);
currentMenu->prevMenu = prev;
S_StartSound(NULL, sfx_s3k42);
return;
}
else
S_StartSound(NULL, sfx_skid);
@ -10038,6 +10053,7 @@ static void M_ChangeControl(INT32 choice)
controltochange = currentMenu->menuitems[choice].alphaKey;
sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"),
currentMenu->menuitems[choice].text);
strncpy(controltochangetext, currentMenu->menuitems[choice].text, 55);
M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER);
}

View file

@ -370,7 +370,7 @@ extern INT16 startmap;
extern INT32 ultimate_selectable;
extern INT16 char_on, startchar;
#define MAXSAVEGAMES 31 //note: last save game is "no save"
#define MAXSAVEGAMES 31
#define NOSAVESLOT 0 //slot where Play Without Saving appears
#define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he
@ -381,6 +381,8 @@ void M_ForceSaveSlotSelected(INT32 sslot);
void M_CheatActivationResponder(INT32 ch);
void M_ModeAttackRetry(INT32 choice);
// Level select updating
void Nextmap_OnChange(void);

View file

@ -8553,17 +8553,43 @@ void A_ToggleFlameJet(mobj_t* actor)
// Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.)
//
// var1 = Angle adjustment (aka orbit speed)
// var2 = Lower four bits: height offset, Upper 4 bits = set if object is Nightopian Helper
// var2:
// Bits 1-10: height offset, max 1023
// Bits 11-16: X radius factor (max 63, default 20)
// Bit 17: set if object is Nightopian Helper
// Bit 18: set to define X/Y/Z rotation factor
// Bits 19-20: Unused
// Bits 21-26: Y radius factor (max 63, default 32)
// Bits 27-32: Z radius factor (max 63, default 32)
//
// If MF_GRENADEBOUNCE is flagged on mobj, use actor->threshold to define X/Y/Z radius factor, max 1023 each:
// Bits 1-10: X factor
// Bits 11-20: Y factor
// Bits 21-30: Z factor
void A_OrbitNights(mobj_t* actor)
{
INT32 ofs = (var2 & 0xFFFF);
boolean ishelper = (var2 & 0xFFFF0000);
INT32 ofs = (var2 & 0x3FF);
boolean ishelper = (var2 & 0x10000);
boolean donotrescale = (var2 & 0x40000);
INT32 xfactor = 32, yfactor = 32, zfactor = 20;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_OrbitNights", actor))
return;
#endif
if (actor->flags & MF_GRENADEBOUNCE)
{
xfactor = (actor->threshold & 0x3FF);
yfactor = (actor->threshold & 0xFFC00) >> 10;
zfactor = (actor->threshold & 0x3FF00000) >> 20;
}
else if (var2 & 0x20000)
{
xfactor = (var2 & 0xFC00) >> 10;
yfactor = (var2 & 0x3F00000) >> 20;
zfactor = (var2 & 0xFC000000) >> 26;
}
if (!actor->target
|| (actor->target->player &&
// if NiGHTS special stage and not NiGHTSmode.
@ -8582,9 +8608,9 @@ void A_OrbitNights(mobj_t* actor)
const angle_t fa = (angle_t)actor->extravalue1 >> ANGLETOFINESHIFT;
const angle_t ofa = ((angle_t)actor->extravalue1 + (ofs*ANG1)) >> ANGLETOFINESHIFT;
const fixed_t fc = FixedMul(FINECOSINE(fa),FixedMul(32*FRACUNIT, actor->scale));
const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(20*FRACUNIT, actor->scale));
const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(32*FRACUNIT, actor->scale));
const fixed_t fc = FixedMul(FINECOSINE(fa),FixedMul(xfactor*FRACUNIT, actor->scale));
const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(zfactor*FRACUNIT, actor->scale));
const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(yfactor*FRACUNIT, actor->scale));
actor->x = actor->target->x + fc;
actor->y = actor->target->y + fs;
@ -8603,6 +8629,9 @@ void A_OrbitNights(mobj_t* actor)
else
actor->flags2 &= ~MF2_DONTDRAW;
}
if (!donotrescale && actor->destscale != actor->target->destscale)
actor->destscale = actor->target->destscale;
}
}

View file

@ -793,28 +793,76 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_SwitchSpheresBonusMode(false);
if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE))
P_SetTarget(&special->tracer, toucher);
P_SetTarget(&player->drone, special); // Mark the player as 'center into the drone'
P_NightserizePlayer(player, special->health); // Transform!
if (!spec)
{
if (toucher->tracer) // Move the ideya over to the drone!
if (toucher->tracer) // Move the Ideya to an anchor!
{
mobj_t *hnext = special->hnext;
P_SetTarget(&special->hnext, toucher->tracer);
P_SetTarget(&special->hnext->hnext, hnext); // Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
P_SetTarget(&special->hnext->target, special);
mobj_t *orbittarget = special->target ? special->target : special;
mobj_t *hnext = orbittarget->hnext, *anchorpoint = NULL, *anchorpoint2 = NULL;
mobj_t *mo2;
thinker_t *th;
// The player might have two Ideyas: toucher->tracer and toucher->tracer->hnext
// so handle their anchorpoints accordingly.
// scan the thinkers to find the corresponding anchorpoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_IDEYAANCHOR)
{
if (mo2->health == toucher->tracer->health) // do ideya numberes match?
anchorpoint = mo2;
else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health)
anchorpoint2 = mo2;
if ((!toucher->tracer->hnext && anchorpoint)
|| (toucher->tracer->hnext && anchorpoint && anchorpoint2))
break;
}
}
if (anchorpoint)
{
toucher->tracer->flags |= MF_GRENADEBOUNCE; // custom radius factors
toucher->tracer->threshold = 8 << 20; // X factor 0, Y factor 0, Z factor 8
}
if (anchorpoint2)
{
toucher->tracer->hnext->flags |= MF_GRENADEBOUNCE; // custom radius factors
toucher->tracer->hnext->threshold = 8 << 20; // X factor 0, Y factor 0, Z factor 8
}
P_SetTarget(&orbittarget->hnext, toucher->tracer);
if (!orbittarget->hnext->hnext)
P_SetTarget(&orbittarget->hnext->hnext, hnext); // Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
else
P_SetTarget(&orbittarget->hnext->hnext->target, anchorpoint2 ? anchorpoint2 : orbittarget);
P_SetTarget(&orbittarget->hnext->target, anchorpoint ? anchorpoint : orbittarget);
P_SetTarget(&toucher->tracer, NULL);
if (hnext)
{
special->hnext->extravalue1 = (angle_t)(hnext->extravalue1 - 72*ANG1);
if (special->hnext->extravalue1 > hnext->extravalue1)
special->hnext->extravalue1 -= (72*ANG1)/special->hnext->extravalue1;
orbittarget->hnext->extravalue1 = (angle_t)(hnext->extravalue1 - 72*ANG1);
if (orbittarget->hnext->extravalue1 > hnext->extravalue1)
orbittarget->hnext->extravalue1 -= (72*ANG1)/orbittarget->hnext->extravalue1;
}
}
if (player->exiting) // ...then move it back?
{
mobj_t *hnext = special;
mobj_t *hnext = special->target ? special->target : special; // goalpost
while ((hnext = hnext->hnext))
{
hnext->flags &= ~MF_GRENADEBOUNCE;
hnext->threshold = 0;
P_SetTarget(&hnext->target, toucher);
}
}
return;
}
@ -961,8 +1009,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->powers[pw_carry] == CR_NIGHTSMODE && !toucher->target)
return;
if (toucher->tracer)
return; // Don't have multiple ideya
if (toucher->tracer && toucher->tracer->health > 0)
return; // Don't have multiple ideya, unless it's the first one given (health = 0)
if (player->mare != special->threshold) // wrong mare
return;

View file

@ -134,7 +134,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
fixed_t vertispeed = spring->info->mass;
fixed_t horizspeed = spring->info->damage;
boolean final;
boolean final = false;
// Object was already sprung this tic
if (object->eflags & MFE_SPRUNG)

View file

@ -7924,78 +7924,247 @@ void P_MobjThinker(mobj_t *mobj)
}
break;
case MT_NIGHTSDRONE:
// GOAL mode?
if (mobj->state >= &states[S_NIGHTSDRONE_SPARKLING1] && mobj->state <= &states[S_NIGHTSDRONE_SPARKLING16])
{
INT32 i;
boolean bonustime = false;
// variable setup
mobj_t *goalpost = NULL;
mobj_t *sparkle = NULL;
mobj_t *droneman = NULL;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{
bonustime = true;
break;
}
boolean flip = mobj->flags2 & MF2_OBJECTFLIP;
boolean topaligned = (mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE);
boolean middlealigned = (mobj->flags & MF_GRENADEBOUNCE) && !(mobj->flags & MF_SLIDEME);
boolean bottomoffsetted = !(mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE);
boolean flipchanged = false;
if (!bonustime)
fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff;
if (mobj->target && mobj->target->type == MT_NIGHTSDRONE_GOAL)
{
CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n");
P_RemoveMobj(mobj->target);
P_SetTarget(&mobj->target, NULL);
mobj->flags &= ~MF_NOGRAVITY;
mobj->flags2 |= MF2_DONTDRAW;
P_SetMobjState(mobj, S_NIGHTSDRONE1);
goalpost = mobj->target;
if (goalpost->target && goalpost->target->type == MT_NIGHTSDRONE_SPARKLING)
sparkle = goalpost->target;
if (goalpost->tracer && goalpost->tracer->type == MT_NIGHTSDRONE_MAN)
droneman = goalpost->tracer;
}
}
// Invisible/bouncing mode.
else
{
INT32 i;
boolean bonustime = false;
// Bouncy bouncy!
mobj->angle += ANG10;
if (mobj->flags2 & MF2_DONTDRAW)
mobj->momz = 0;
else if (mobj->z <= mobj->floorz)
mobj->momz = 5*FRACUNIT;
if (!goalpost || !sparkle || !droneman)
break;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{
bonustime = true;
break;
}
// did NIGHTSDRONE position, scale, flip, or flags change? all elements need to be synced
droneboxmandiff = max(mobj->height - droneman->height, 0);
dronemangoaldiff = max(droneman->height - goalpost->height, 0);
if (bonustime)
if (!(goalpost->flags2 & MF2_OBJECTFLIP) && (mobj->flags2 & MF2_OBJECTFLIP))
{
mobj->z = mobj->floorz + mobj->height;
mobj->angle = mobj->momz = 0;
if (mobj->spawnpoint)
mobj->z += (mobj->spawnpoint->options >> ZSHIFT)<<FRACBITS;
CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n");
P_SetTarget(&mobj->target, P_SpawnMobjFromMobj(mobj, 0, 0, FRACUNIT, MT_NIGHTSGOAL));
mobj->flags2 &= ~MF2_DONTDRAW;
mobj->flags |= MF_NOGRAVITY;
P_SetMobjState(mobj, S_NIGHTSDRONE_SPARKLING1);
goalpost->eflags |= MFE_VERTICALFLIP;
goalpost->flags2 |= MF2_OBJECTFLIP;
sparkle->eflags |= MFE_VERTICALFLIP;
sparkle->flags2 |= MF2_OBJECTFLIP;
droneman->eflags |= MFE_VERTICALFLIP;
droneman->flags2 |= MF2_OBJECTFLIP;
flipchanged = true;
}
else if (!G_IsSpecialStage(gamemap))
else if ((goalpost->flags2 & MF2_OBJECTFLIP) && !(mobj->flags2 & MF2_OBJECTFLIP))
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE)
goalpost->eflags &= ~MFE_VERTICALFLIP;
goalpost->flags2 &= ~MF2_OBJECTFLIP;
sparkle->eflags &= ~MFE_VERTICALFLIP;
sparkle->flags2 &= ~MF2_OBJECTFLIP;
droneman->eflags &= ~MFE_VERTICALFLIP;
droneman->flags2 &= ~MF2_OBJECTFLIP;
flipchanged = true;
}
if (goalpost->destscale != mobj->destscale
|| goalpost->movefactor != mobj->z
|| goalpost->friction != mobj->height
|| flipchanged
|| goalpost->threshold != (INT32)(mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE)))
{
goalpost->destscale = sparkle->destscale = droneman->destscale = mobj->destscale;
// straight copy-pasta from P_SpawnMapThing, case MT_NIGHTSDRONE
if (!flip)
{
if (topaligned) // Align droneman to top of hitbox
{
bonustime = true; // variable reuse
dronemanoffset = droneboxmandiff;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (middlealigned) // Align droneman to center of hitbox
{
dronemanoffset = droneboxmandiff / 2;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (bottomoffsetted)
{
dronemanoffset = 24*FRACUNIT;
goaloffset = dronemangoaldiff + dronemanoffset;
}
else
{
dronemanoffset = 0;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale);
}
else
{
if (topaligned) // Align droneman to top of hitbox
{
dronemanoffset = 0;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (middlealigned) // Align droneman to center of hitbox
{
dronemanoffset = droneboxmandiff / 2;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (bottomoffsetted)
{
dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale);
goaloffset = dronemangoaldiff + dronemanoffset;
}
else
{
dronemanoffset = droneboxmandiff;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale);
}
P_TeleportMove(goalpost, mobj->x, mobj->y, mobj->z + goaloffset);
P_TeleportMove(sparkle, mobj->x, mobj->y, mobj->z + sparkleoffset);
if (goalpost->movefactor != mobj->z || goalpost->friction != mobj->height)
{
P_TeleportMove(droneman, mobj->x, mobj->y, mobj->z + dronemanoffset);
goalpost->movefactor = mobj->z;
goalpost->friction = mobj->height;
}
goalpost->threshold = mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE);
}
else
{
if (goalpost->x != mobj->x || goalpost->y != mobj->y)
{
P_TeleportMove(goalpost, mobj->x, mobj->y, goalpost->z);
P_TeleportMove(sparkle, mobj->x, mobj->y, sparkle->z);
}
if (droneman->x != mobj->x || droneman->y != mobj->y)
P_TeleportMove(droneman, mobj->x, mobj->y,
droneman->z >= mobj->floorz && droneman->z <= mobj->ceilingz ? droneman->z : mobj->z);
}
// now toggle states!
// GOAL mode?
if (sparkle->state >= &states[S_NIGHTSDRONE_SPARKLING1] && sparkle->state <= &states[S_NIGHTSDRONE_SPARKLING16])
{
INT32 i;
boolean bonustime = false;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{
bonustime = true;
break;
}
if (!bonustime)
{
CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n");
if (goalpost && goalpost->state != &states[S_INVISIBLE])
P_SetMobjState(goalpost, S_INVISIBLE);
if (sparkle && sparkle->state != &states[S_INVISIBLE])
P_SetMobjState(sparkle, S_INVISIBLE);
}
}
// Invisible/bouncing mode.
else
{
fixed_t droneboxmandiff = max(mobj->height - droneman->height, 0);
INT32 i;
boolean bonustime = false;
fixed_t zcomp;
// Bouncy bouncy!
if (!flip)
{
if (topaligned)
zcomp = droneboxmandiff + mobj->z;
else if (middlealigned)
zcomp = (droneboxmandiff / 2) + mobj->z;
else if (bottomoffsetted)
zcomp = mobj->z + FixedMul(24*FRACUNIT, mobj->scale);
else
zcomp = mobj->z;
}
else
{
if (topaligned)
zcomp = mobj->z;
else if (middlealigned)
zcomp = (droneboxmandiff / 2) + mobj->z;
else if (bottomoffsetted)
zcomp = mobj->z + droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale);
else
zcomp = mobj->z + droneboxmandiff;
}
droneman->angle += ANG10;
if (!flip && droneman->z <= zcomp)
droneman->momz = FixedMul(5*FRACUNIT, droneman->scale);
else if (flip && droneman->z >= zcomp)
droneman->momz = FixedMul(-5*FRACUNIT, droneman->scale);
// state switching logic
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{
bonustime = true;
break;
}
if (bonustime)
mobj->flags2 &= ~MF2_DONTDRAW;
else
mobj->flags2 |= MF2_DONTDRAW;
{
CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n");
if (!(droneman->flags2 & MF2_DONTDRAW))
droneman->flags2 |= MF2_DONTDRAW;
if (goalpost->state == &states[S_INVISIBLE])
P_SetMobjState(goalpost, mobjinfo[goalpost->type].meleestate);
if (sparkle->state == &states[S_INVISIBLE])
P_SetMobjState(sparkle, mobjinfo[sparkle->type].meleestate);
}
else if (!G_IsSpecialStage(gamemap))
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE)
{
bonustime = true; // variable reuse
break;
}
if (bonustime)
{
// show droneman if at least one player is non-nights
if (goalpost->state != &states[S_INVISIBLE])
P_SetMobjState(goalpost, S_INVISIBLE);
if (sparkle->state != &states[S_INVISIBLE])
P_SetMobjState(sparkle, S_INVISIBLE);
if (droneman->state != &states[mobjinfo[droneman->type].meleestate])
P_SetMobjState(droneman, mobjinfo[droneman->type].meleestate);
if (droneman->flags2 & MF2_DONTDRAW)
droneman->flags2 &= ~MF2_DONTDRAW;
}
else
{
// else, hide it
if (!(droneman->flags2 & MF2_DONTDRAW))
droneman->flags2 |= MF2_DONTDRAW;
}
}
}
}
break;
@ -8850,13 +9019,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->fuse += 30 * TICRATE;
break;
case MT_NIGHTSDRONE:
if (G_IsSpecialStage(gamemap))
mobj->flags2 |= MF2_DONTDRAW;
nummaprings = -1; // no perfect bonus, rings are free
break;
case MT_EGGCAPSULE:
mobj->extravalue1 = -1; // sphere timer for how long a player has been at the capsule
mobj->extravalue2 = -1; // tic timer for how long a player has been at the capsule
mobj->reactiontime = 0;
mobj->extravalue1 = mobj->cvmem =\
mobj->cusval = mobj->movecount =\
mobj->lastlook = mobj->extravalue2 = -1;
break;
case MT_REDTEAMRING:
mobj->color = skincolor_redteam;
@ -9554,6 +9723,7 @@ void P_SpawnPlayer(INT32 playernum)
if (p == players) // this is totally the wrong place to do this aaargh.
{
mobj_t *idya = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_GOTEMERALD);
idya->health = 0; // for identification
P_SetTarget(&idya->target, mobj);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate);
P_SetTarget(&mobj->tracer, idya);
@ -10622,9 +10792,124 @@ ML_EFFECT4 : Don't clip inside the ground
mobj->health = mthing->angle & 255;
mobj->threshold = mthing->angle >> 8;
break;
case MT_IDEYAANCHOR:
mobj->health = mthing->extrainfo;
break;
case MT_NIGHTSDRONE:
if (mthing->angle > 0)
mobj->health = mthing->angle;
{
boolean flip = mthing->options & MTF_OBJECTFLIP;
boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA);
boolean middlealigned = (mthing->options & MTF_EXTRA) && !(mthing->options & MTF_OBJECTSPECIAL);
boolean bottomoffsetted = !(mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA);
INT16 timelimit = mthing->angle & 0xFFF;
fixed_t hitboxradius = ((mthing->angle & 0xF000) >> 12) * 32 * FRACUNIT;
fixed_t hitboxheight = mthing->extrainfo * 32 * FRACUNIT;
fixed_t oldheight = mobj->height;
fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff;
if (timelimit > 0)
mobj->health = timelimit;
if (hitboxradius > 0)
mobj->radius = hitboxradius;
if (hitboxheight > 0)
mobj->height = hitboxheight;
else
mobj->height = mobjinfo[MT_NIGHTSDRONE].height;
droneboxmandiff = max(mobj->height - mobjinfo[MT_NIGHTSDRONE_MAN].height, 0);
dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0);
if (flip && mobj->height != oldheight)
P_TeleportMove(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight));
if (!flip)
{
if (topaligned) // Align droneman to top of hitbox
{
dronemanoffset = droneboxmandiff;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (middlealigned) // Align droneman to center of hitbox
{
dronemanoffset = droneboxmandiff / 2;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (bottomoffsetted)
{
dronemanoffset = 24*FRACUNIT;
goaloffset = dronemangoaldiff + dronemanoffset;
}
else
{
dronemanoffset = 0;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale);
}
else
{
mobj->eflags |= MFE_VERTICALFLIP;
mobj->flags2 |= MF2_OBJECTFLIP;
if (topaligned) // Align droneman to top of hitbox
{
dronemanoffset = 0;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (middlealigned) // Align droneman to center of hitbox
{
dronemanoffset = droneboxmandiff / 2;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
else if (bottomoffsetted)
{
dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale);
goaloffset = dronemangoaldiff + dronemanoffset;
}
else
{
dronemanoffset = droneboxmandiff;
goaloffset = dronemangoaldiff / 2 + dronemanoffset;
}
sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale);
}
// spawn visual elements
mobj_t *goalpost = P_SpawnMobjFromMobj(mobj, 0, 0, goaloffset, MT_NIGHTSDRONE_GOAL);
mobj_t *sparkle = P_SpawnMobjFromMobj(mobj, 0, 0, sparkleoffset, MT_NIGHTSDRONE_SPARKLING);
mobj_t *droneman = P_SpawnMobjFromMobj(mobj, 0, 0, dronemanoffset, MT_NIGHTSDRONE_MAN);
P_SetTarget(&mobj->target, goalpost);
P_SetTarget(&goalpost->target, sparkle);
P_SetTarget(&goalpost->tracer, droneman);
// correct Z position
if (flip)
{
P_TeleportMove(goalpost, goalpost->x, goalpost->y, mobj->z + goaloffset);
P_TeleportMove(sparkle, sparkle->x, sparkle->y, mobj->z + sparkleoffset);
P_TeleportMove(droneman, droneman->x, droneman->y, mobj->z + dronemanoffset);
}
// Remember position preference for later
mobj->flags &= ~(MF_SLIDEME | MF_GRENADEBOUNCE);
if (topaligned)
mobj->flags |= MF_SLIDEME;
else if (middlealigned)
mobj->flags |= MF_GRENADEBOUNCE;
else if (!bottomoffsetted)
mobj->flags |= MF_SLIDEME | MF_GRENADEBOUNCE;
// Remember old Z position and flags for correction detection
goalpost->movefactor = mobj->z;
goalpost->friction = mobj->height;
goalpost->threshold = mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE);
}
break;
case MT_HIVEELEMENTAL:
if (mthing->extrainfo)

View file

@ -58,6 +58,7 @@ typedef enum
FIRSTAXIS = 0x10,
SECONDAXIS = 0x20,
FOLLOW = 0x40,
DRONE = 0x80,
} player_saveflags;
//
@ -198,10 +199,10 @@ static void P_NetArchivePlayers(void)
WRITEINT32(save_p, players[i].drillmeter);
WRITEUINT8(save_p, players[i].drilldelay);
WRITEUINT8(save_p, players[i].bonustime);
WRITEFIXED(save_p, players[i].oldscale);
WRITEUINT8(save_p, players[i].mare);
WRITEUINT8(save_p, players[i].marelap);
WRITEUINT8(save_p, players[i].marebonuslap);
WRITEUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime);
@ -236,6 +237,9 @@ static void P_NetArchivePlayers(void)
if (players[i].followmobj)
flags |= FOLLOW;
if (players[i].drone)
flags |= DRONE;
WRITEINT16(save_p, players[i].lastsidehit);
WRITEINT16(save_p, players[i].lastlinehit);
@ -264,6 +268,9 @@ static void P_NetArchivePlayers(void)
if (flags & FOLLOW)
WRITEUINT32(save_p, players[i].followmobj->mobjnum);
if (flags & DRONE)
WRITEUINT32(save_p, players[i].drone->mobjnum);
WRITEFIXED(save_p, players[i].camerascale);
WRITEFIXED(save_p, players[i].shieldscale);
@ -396,10 +403,10 @@ static void P_NetUnArchivePlayers(void)
players[i].drillmeter = READINT32(save_p);
players[i].drilldelay = READUINT8(save_p);
players[i].bonustime = (boolean)READUINT8(save_p);
players[i].oldscale = READFIXED(save_p);
players[i].mare = READUINT8(save_p);
players[i].marelap = READUINT8(save_p);
players[i].marebonuslap = READUINT8(save_p);
players[i].marebegunat = READUINT32(save_p);
players[i].startedtime = READUINT32(save_p);
players[i].finishedtime = READUINT32(save_p);
@ -447,6 +454,9 @@ static void P_NetUnArchivePlayers(void)
if (flags & FOLLOW)
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p);
if (flags & DRONE)
players[i].drone = (mobj_t *)(size_t)READUINT32(save_p);
players[i].camerascale = READFIXED(save_p);
players[i].shieldscale = READFIXED(save_p);
@ -486,7 +496,7 @@ static UINT32 num_ffloors = 0; // for loading
// But also check for equality and return the matching index
static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap)
{
extracolormap_t *exc, *exc_prev;
extracolormap_t *exc, *exc_prev = NULL;
UINT32 i = 0;
if (!net_colormaps)
@ -3670,6 +3680,13 @@ static void P_RelinkPointers(void)
if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->drone)
{
temp = (UINT32)(size_t)mobj->player->drone;
mobj->player->drone = NULL;
if (!P_SetTarget(&mobj->player->drone, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "drone not found on %d\n", mobj->type);
}
}
}
}

View file

@ -56,8 +56,11 @@
#include "filesrch.h" // refreshdirmenu
// wipes
#include "f_finale.h"
#ifdef HAVE_BLUA
#include "lua_hud.h" // level title
#endif
#include "f_finale.h" // wipes
#include "md5.h" // map MD5
@ -100,6 +103,7 @@ side_t *sides;
mapthing_t *mapthings;
INT32 numstarposts;
boolean levelloading;
UINT8 levelfadecol;
// BLOCKMAP
// Created from axis aligned bounding box
@ -2296,7 +2300,7 @@ static void P_LevelInitStuff(void)
players[i].texttimer = players[i].linkcount =\
players[i].linktimer = players[i].flyangle =\
players[i].anotherflyangle = players[i].nightstime =\
players[i].mare = players[i].marelap =\
players[i].oldscale = players[i].mare = players[i].marelap =\
players[i].marebonuslap = players[i].lapbegunat =\
players[i].lapstartedtime = players[i].totalmarescore =\
players[i].realtime = players[i].exiting = 0;
@ -2314,7 +2318,7 @@ static void P_LevelInitStuff(void)
// unset ALL the pointers. P_SetTarget isn't needed here because if this
// function is being called we're just going to clobber the data anyways
players[i].mo = players[i].followmobj = players[i].awayviewmobj =\
players[i].capsule = players[i].axis1 = players[i].axis2 = NULL;
players[i].capsule = players[i].axis1 = players[i].axis2 = players[i].drone = NULL;
}
}
@ -2672,7 +2676,6 @@ boolean P_SetupLevel(boolean skipprecip)
CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer
// Reset the palette
if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");
@ -2725,9 +2728,14 @@ boolean P_SetupLevel(boolean skipprecip)
// will be set by player think.
players[consoleplayer].viewz = 1;
// Cancel all d_main.c fadeouts (keep fade in though).
wipegamestate = -2;
// Special stage fade to white
// This is handled BEFORE sounds are stopped.
if (rendermode != render_none && G_IsSpecialStage(gamemap))
if (modeattacking && !demoplayback && (pausedelay == INT32_MIN))
ranspecialwipe = 2;
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2;
@ -2760,11 +2768,12 @@ boolean P_SetupLevel(boolean skipprecip)
S_StopSounds();
S_ClearSfx();
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
/// ... as long as this isn't a titlemap transition, that is
if (!titlemapinaction)
{
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
S_Start();
}
// Let's fade to black here
// But only if we didn't do the special stage wipe
@ -2783,20 +2792,31 @@ boolean P_SetupLevel(boolean skipprecip)
wipetypepre = -1;
}
// Print "SPEEDING OFF TO [ZONE] [ACT 1]..."
if (!titlemapinaction && rendermode != render_none)
if (!titlemapinaction)
{
// Don't include these in the fade!
char tx[64];
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
snprintf(tx, 63, "%s%s%s",
mapheaderinfo[gamemap-1]->lvlttl,
(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
I_UpdateNoVsync();
if (ranspecialwipe == 2)
{
pausedelay = -3; // preticker plus one
S_StartSound(NULL, sfx_s3k73);
}
// Print "SPEEDING OFF TO [ZONE] [ACT 1]..."
if (rendermode != render_none)
{
// Don't include these in the fade!
char tx[64];
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
snprintf(tx, 63, "%s%s%s",
mapheaderinfo[gamemap-1]->lvlttl,
(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
I_UpdateNoVsync();
}
}
levelfadecol = (ranspecialwipe) ? 0 : 31;
// Close text prompt before freeing the old level
F_EndTextPrompt(false, true);
@ -3144,8 +3164,8 @@ boolean P_SetupLevel(boolean skipprecip)
P_MapEnd();
// Remove the loading shit from the screen
if (rendermode != render_none)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (ranspecialwipe) ? 0 : 31);
if (rendermode != render_none && !titlemapinaction)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
if (precache || dedicated)
R_PrecacheLevel();
@ -3195,6 +3215,45 @@ boolean P_SetupLevel(boolean skipprecip)
#endif
}
// Stage title!
if (rendermode != render_none
&& (!titlemapinaction)
&& ranspecialwipe != 2
&& *mapheaderinfo[gamemap-1]->lvlttl != '\0'
#ifdef HAVE_BLUA
&& LUA_HudEnabled(hud_stagetitle)
#endif
)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (10*NEWTICRATERATIO);
tic_t nowtime = starttime;
tic_t lasttime = starttime;
while (nowtime < endtime)
{
// draw loop
while (!((nowtime = I_GetTime()) - lasttime))
I_Sleep();
lasttime = nowtime;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
stplyr = &players[consoleplayer];
ST_drawLevelTitle(nowtime - starttime);
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
ST_drawLevelTitle(nowtime - starttime);
}
I_OsPolling();
I_UpdateNoBlit();
I_FinishUpdate(); // page flip or blit buffer
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
}
return true;
}

View file

@ -27,6 +27,7 @@ extern mapthing_t *deathmatchstarts[MAX_DM_STARTS];
extern INT32 numdmstarts, numcoopstarts, numredctfstarts, numbluectfstarts;
extern boolean levelloading;
extern UINT8 levelfadecol;
extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame
//

View file

@ -634,6 +634,10 @@ static void P_DeNightserizePlayer(player_t *player)
break;
}
if (player->mo->scale != player->oldscale)
player->mo->destscale = player->oldscale;
player->oldscale = 0;
// Restore from drowning music
P_RestoreMusic(player);
@ -653,7 +657,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
return;
if (player->powers[pw_carry] != CR_NIGHTSMODE)
{
player->mo->height = P_GetPlayerHeight(player); // Just to make sure jumping into the drone doesn't result in a squashed hitbox.
player->oldscale = player->mo->scale;
}
player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING);
player->homing = 0;
@ -786,10 +793,13 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
// Don't show before title card
// Not consistency safe, but this only affects drawing
if (timeinmap + 40 < 110)
player->texttimer = (UINT8)(110 - timeinmap);
if (timeinmap + 40 < (110 - 70))
player->texttimer = (UINT8)((110 - 70) - timeinmap);
}
if (player->drone && player->drone->scale != player->mo->scale)
player->mo->destscale = player->drone->scale;
// force NiGHTS to face forward or backward
if (player->mo->target)
player->mo->angle = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y) // player->angle_pos, won't be set on first instance
@ -3955,7 +3965,7 @@ void P_DoJump(player_t *player, boolean soundandstate)
}
}
else if (maptol & TOL_NIGHTS)
player->mo->momz = 24*FRACUNIT;
player->mo->momz = 18*FRACUNIT;
else if (player->powers[pw_super])
{
player->mo->momz = 13*FRACUNIT;
@ -3996,6 +4006,9 @@ void P_DoJump(player_t *player, boolean soundandstate)
if (player->charflags & SF_MULTIABILITY && player->charability == CA_DOUBLEJUMP)
factor -= max(0, player->secondjump * player->jumpfactor / ((player->actionspd >> FRACBITS) + 1)); // Reduce the jump height each time
//if (maptol & TOL_NIGHTS)
// factor = player->jumpfactor; // all skins jump the same. if you nerf jumping abilities, you may want this.
P_SetObjectMomZ(player->mo, FixedMul(factor, player->mo->momz), false); // Custom height
// set just an eensy above the ground
@ -5960,11 +5973,10 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
//
static void P_DoNiGHTSCapsule(player_t *player)
{
INT32 i;
INT32 i, spherecount, totalduration, popduration, deductinterval, deductquantity, sphereresult, firstpoptic, startingspheres;
INT32 tictimer = ++player->capsule->extravalue2;
player->capsule->extravalue2++; // tic counter
if (abs(player->mo->x-player->capsule->x) <= 2*FRACUNIT)
if (abs(player->mo->x-player->capsule->x) <= 3*FRACUNIT)
{
P_UnsetThingPosition(player->mo);
player->mo->x = player->capsule->x;
@ -5972,7 +5984,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->mo->momx = 0;
}
if (abs(player->mo->y-player->capsule->y) <= 2*FRACUNIT)
if (abs(player->mo->y-player->capsule->y) <= 3*FRACUNIT)
{
P_UnsetThingPosition(player->mo);
player->mo->y = player->capsule->y;
@ -5980,26 +5992,26 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->mo->momy = 0;
}
if (abs(player->mo->z - (player->capsule->z+(player->capsule->height/3))) <= 2*FRACUNIT)
if (abs(player->mo->z - (player->capsule->z+(player->capsule->height/3))) <= 3*FRACUNIT)
{
player->mo->z = player->capsule->z+(player->capsule->height/3);
player->mo->momz = 0;
}
if (player->mo->x > player->capsule->x)
player->mo->momx = -2*FRACUNIT;
player->mo->momx = -3*FRACUNIT;
else if (player->mo->x < player->capsule->x)
player->mo->momx = 2*FRACUNIT;
player->mo->momx = 3*FRACUNIT;
if (player->mo->y > player->capsule->y)
player->mo->momy = -2*FRACUNIT;
player->mo->momy = -3*FRACUNIT;
else if (player->mo->y < player->capsule->y)
player->mo->momy = 2*FRACUNIT;
player->mo->momy = 3*FRACUNIT;
if (player->mo->z > player->capsule->z+(player->capsule->height/3))
player->mo->momz = -2*FRACUNIT;
player->mo->momz = -3*FRACUNIT;
else if (player->mo->z < player->capsule->z+(player->capsule->height/3))
player->mo->momz = 2*FRACUNIT;
player->mo->momz = 3*FRACUNIT;
if (player->powers[pw_carry] == CR_NIGHTSMODE)
{
@ -6014,6 +6026,13 @@ static void P_DoNiGHTSCapsule(player_t *player)
P_SetPlayerMobjState(player->mo, S_PLAY_NIGHTS_ATTACK);
}
}
else
{
if (!(player->pflags & PF_JUMPED) && !(player->pflags & PF_SPINNING))
player->pflags |= PF_JUMPED;
if (player->panim != PA_ROLL)
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
}
if (G_IsSpecialStage(gamemap))
{ // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here!
@ -6033,25 +6052,82 @@ static void P_DoNiGHTSCapsule(player_t *player)
&& player->mo->y == player->capsule->y
&& player->mo->z == player->capsule->z+(player->capsule->height/3))
{
if (player->spheres > 0)
if (player->capsule->lastlook < 0)
{
player->spheres--;
player->capsule->health--;
player->capsule->extravalue1++;
// Stretch the sphere deduction across the capsule time!
// 1. Force the remaining capsule time to `popduration`
// 2. Given `popduration` and `spherecount`, at what tic interval do we deduct spheres? `deductinterval`
// 3. And on each deduction, how many spheres do we deduct? `deductquantity`
// 4. Store the expected capsule health upon completion: `sphereresult`
spherecount = min(player->spheres, player->capsule->health);
totalduration = min(40 + spherecount, 60);
// Spawn a 'pop' for every 5 rings you deposit
if (!(player->capsule->extravalue1 % 5))
popduration = player->capsule->extravalue1 = max(totalduration - tictimer, 1);
deductinterval = player->capsule->cvmem = max(FixedFloor(FixedDiv(popduration, spherecount))/FRACUNIT, 1);
deductquantity = player->capsule->cusval = max(FixedRound(FixedDiv(spherecount, popduration))/FRACUNIT, 1);
sphereresult = player->capsule->movecount = player->capsule->health - spherecount;
firstpoptic = player->capsule->lastlook = tictimer;
}
else
{
popduration = player->capsule->extravalue1;
deductinterval = player->capsule->cvmem;
deductquantity = player->capsule->cusval;
sphereresult = player->capsule->movecount;
firstpoptic = player->capsule->lastlook;
}
if (tictimer - firstpoptic < popduration)
{
if (!((tictimer - firstpoptic) % deductinterval))
{
// Did you somehow get more spheres during destruct?
if (player->capsule->health <= sphereresult && player->spheres > 0 && player->capsule->health > 0)
sphereresult = max(sphereresult - player->spheres, 0);
if (player->capsule->health > sphereresult && player->spheres > 0)
{
player->spheres -= deductquantity;
player->capsule->health -= deductquantity;
}
if (player->spheres < 0)
player->spheres = 0;
if (player->capsule->health < sphereresult)
player->capsule->health = sphereresult;
}
// Spawn a 'pop' for every 5 tics
if (!((tictimer - firstpoptic) % 5))
S_StartSound(P_SpawnMobj(player->capsule->x + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->y + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS),
MT_BOSSEXPLODE),sfx_cybdth);
}
else
{
if (player->spheres != 0 && player->capsule->health > 0)
{
if (player->spheres < player->capsule->health)
{
player->capsule->health -= player->spheres;
player->spheres = 0;
}
else
{
startingspheres = player->spheres - player->capsule->health;
player->capsule->health = 0;
player->spheres = startingspheres;
}
}
if (player->capsule->health <= 0)
{
player->capsule->flags &= ~MF_NOGRAVITY;
player->capsule->momz = 5*FRACUNIT;
player->capsule->reactiontime = 0;
player->capsule->extravalue1 = player->capsule->extravalue2 = -1;
tictimer = -1;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && !player->exiting && players[i].mare == player->mare)
@ -6085,6 +6161,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
UINT8 em = P_GetNextEmerald();
// Only give it to ONE person, and THAT player has to get to the goal!
mobj_t *emmo = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
emmo->health = em; // for identification
P_SetTarget(&emmo->target, player->mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&player->mo->tracer, emmo);
@ -6111,8 +6188,17 @@ static void P_DoNiGHTSCapsule(player_t *player)
}*/
mobj_t *idya = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
idya->extravalue2 = player->mare/5;
idya->health = player->mare + 1; // for identification
P_SetTarget(&idya->target, player->mo);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate + ((player->mare + 1) % 5));
if (player->mo->tracer)
{
P_SetTarget(&idya->hnext, player->mo->tracer);
idya->extravalue1 = (angle_t)(player->mo->tracer->extravalue1 - 72*ANG1);
if (idya->extravalue1 > player->mo->tracer->extravalue1)
idya->extravalue1 -= (72*ANG1)/idya->extravalue1;
}
P_SetTarget(&player->mo->tracer, idya);
}
for (i = 0; i < MAXPLAYERS; i++)
@ -6122,19 +6208,68 @@ static void P_DoNiGHTSCapsule(player_t *player)
P_SwitchSpheresBonusMode(true);
P_RunNightsCapsuleTouchExecutors(player->mo, false, true); // run capsule exit executors, and we destroyed it
}
}
else
{
S_StartScreamSound(player->mo, sfx_lose);
player->texttimer = 4*TICRATE;
player->textvar = 3; // Get more rings!
player->capsule->reactiontime = 0;
player->capsule->extravalue1 = player->capsule->extravalue2 = -1;
P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked rings
else
{
S_StartScreamSound(player->mo, sfx_lose);
player->texttimer = 4*TICRATE;
player->textvar = 3; // Get more rings!
player->capsule->reactiontime = 0;
player->capsule->extravalue1 = player->capsule->cvmem =\
player->capsule->cusval = player->capsule->movecount =\
player->capsule->lastlook = player->capsule->extravalue2 = -1;
P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked rings
}
}
}
else if (player->capsule->lastlook > -1)
// We somehow moved out of the capsule (OBJECTPLACE?)
// So recalculate all the timings
player->capsule->lastlook = player->capsule->extravalue2 = -1;
}
//
// P_MoveNiGHTSToDrone
//
// Pull NiGHTS to the drone during Nightserizing
//
static void P_MoveNiGHTSToDrone(player_t *player)
{
if (!player->drone)
return;
boolean flip = player->drone->flags2 & MF2_OBJECTFLIP;
boolean topaligned = (player->drone->flags & MF_SLIDEME) && !(player->drone->flags & MF_GRENADEBOUNCE);
boolean middlealigned = (player->drone->flags & MF_GRENADEBOUNCE) && !(player->drone->flags & MF_SLIDEME);
boolean bottomoffsetted = !(player->drone->flags & MF_SLIDEME) && !(player->drone->flags & MF_GRENADEBOUNCE);
fixed_t droneboxmandiff = max(player->drone->height - player->mo->height, 0);
fixed_t zofs;
if (!flip)
{
if (topaligned)
zofs = droneboxmandiff;
else if (middlealigned)
zofs = droneboxmandiff / 2;
else if (bottomoffsetted)
zofs = FixedMul(24*FRACUNIT, player->drone->scale);
else
zofs = 0;
}
else
player->capsule->extravalue1 = -1;
{
if (topaligned)
zofs = 0;
else if (middlealigned)
zofs = droneboxmandiff / 2;
else if (bottomoffsetted)
zofs = droneboxmandiff - FixedMul(24*FRACUNIT, player->drone->scale);
else
zofs = droneboxmandiff;
}
player->mo->momx = player->mo->momy = player->mo->momz = 0;
P_TeleportMove(player->mo, player->drone->x, player->drone->y, player->drone->z + zofs);
P_SetTarget(&player->drone, NULL);
}
//
@ -7059,6 +7194,13 @@ static void P_MovePlayer(player_t *player)
return;
}
// Suck player into their drone
if (player->drone)
{
P_MoveNiGHTSToDrone(player);
return;
}
// Test revamped NiGHTS movement.
if (player->powers[pw_carry] == CR_NIGHTSMODE)
{
@ -8955,7 +9097,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// sets ideal cam pos
if (twodlevel || (mo->flags2 & MF2_TWOD))
dist = 480<<FRACBITS;
else if (player->powers[pw_carry] == CR_NIGHTSMODE)
else if (player->powers[pw_carry] == CR_NIGHTSMODE
|| ((maptol & TOL_NIGHTS) && player->capsule && player->capsule->reactiontime > 0 && player == &players[player->capsule->reactiontime-1]))
dist = 320<<FRACBITS;
else
{

View file

@ -441,15 +441,17 @@ void SCR_ClosedCaptions(void)
boolean gamestopped = (paused || P_AutoPause());
INT32 basey = BASEVIDHEIGHT;
if (gamestate != wipegamestate)
return;
if (gamestate == GS_LEVEL)
{
if (splitscreen)
basey -= 8;
else if ((modeattacking == ATTACKING_NIGHTS)
|| (!(maptol & TOL_NIGHTS)
&& ((cv_powerupdisplay.value == 2)
|| (cv_powerupdisplay.value == 1 && ((stplyr == &players[displayplayer] && !camera.chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))))))
&& ((cv_powerupdisplay.value == 2) // "Always"
|| (cv_powerupdisplay.value == 1 && !camera.chase)))) // "First-person only"
basey -= 16;
}

View file

@ -460,7 +460,8 @@ static void ST_DrawNightsOverlayNum(fixed_t x /* right border */, fixed_t y, fix
// Devmode information
static void ST_drawDebugInfo(void)
{
INT32 height = 0;
INT32 height = 0, h = 8, w = 18, lowh;
void (*textfunc)(INT32, INT32, INT32, const char *);
if (!(stplyr->mo && cv_debug))
return;
@ -469,135 +470,135 @@ static void ST_drawDebugInfo(void)
if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dupx == 1)
{
if (cv_debug & DBG_BASIC)
{
const fixed_t d = AngleFixed(stplyr->mo->angle);
V_DrawRightAlignedString(320, 0, VFLAGS, va("X: %6d", stplyr->mo->x>>FRACBITS));
V_DrawRightAlignedString(320, 8, VFLAGS, va("Y: %6d", stplyr->mo->y>>FRACBITS));
V_DrawRightAlignedString(320, 16, VFLAGS, va("Z: %6d", stplyr->mo->z>>FRACBITS));
V_DrawRightAlignedString(320, 24, VFLAGS, va("A: %6d", FixedInt(d)));
height += 4*9;
}
if (cv_debug & (DBG_MEMORY|DBG_RANDOMIZER|DBG_DETAILED))
{
V_DrawRightAlignedThinString(320, height, VFLAGS|V_REDMAP, "INFO NOT AVAILABLE");
V_DrawRightAlignedThinString(320, 8+height, VFLAGS|V_REDMAP, "AT THIS RESOLUTION");
}
textfunc = V_DrawRightAlignedString;
lowh = ((vid.height/vid.dupy) - 16);
}
else
{
#define h 4
#define dist 2
#define V_DrawDebugLine(str) V_DrawRightAlignedSmallString(320, height, VFLAGS, str);\
height += h
if (cv_debug & DBG_MEMORY)
{
V_DrawDebugLine(va("Heap: %8sKB", sizeu1(Z_TotalUsage()>>10)));
height += dist;
}
if (cv_debug & DBG_RANDOMIZER) // randomizer testing
{
fixed_t peekres = P_RandomPeek();
peekres *= 10000; // Change from fixed point
peekres >>= FRACBITS; // to displayable decimal
V_DrawDebugLine(va("Init: %08x", P_GetInitSeed()));
V_DrawDebugLine(va("Seed: %08x", P_GetRandSeed()));
V_DrawDebugLine(va("== : .%04d", peekres));
height += dist;
}
if (cv_debug & DBG_DETAILED)
{
#define V_DrawDebugFlag(f, str) V_DrawRightAlignedSmallString(w, height, VFLAGS|f, str);\
w -= 9
const fixed_t d = AngleFixed(stplyr->drawangle);
INT32 w = 320;
V_DrawDebugLine(va("SHIELD: %5x", stplyr->powers[pw_shield]));
V_DrawDebugLine(va("SCALE: %5d%%", (stplyr->mo->scale*100)>>FRACBITS));
V_DrawDebugLine(va("CARRY: %5x", stplyr->powers[pw_carry]));
V_DrawDebugLine(va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime]));
V_DrawDebugLine(va("ABILITY: %3d, %3d", stplyr->charability, stplyr->charability2));
V_DrawDebugLine(va("ACTIONSPD: %5d", stplyr->actionspd>>FRACBITS));
V_DrawDebugLine(va("PEEL: %3d", stplyr->dashmode));
V_DrawDebugLine(va("SCOREADD: %3d", stplyr->scoreadd));
// Flags
V_DrawDebugFlag(((stplyr->pflags & PF_SHIELDABILITY) ? V_GREENMAP : V_REDMAP), "SH");
V_DrawDebugFlag(((stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP), "TH");
V_DrawDebugFlag(((stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP), "ST");
V_DrawDebugFlag(((stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP), "SP");
V_DrawDebugFlag(((stplyr->pflags & PF_NOJUMPDAMAGE) ? V_GREENMAP : V_REDMAP), "ND");
V_DrawDebugFlag(((stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP), "JD");
V_DrawDebugFlag(((stplyr->pflags & PF_STARTJUMP) ? V_GREENMAP : V_REDMAP), "SJ");
V_DrawDebugFlag(0, "PF/SF:");
height += h;
w = 320;
V_DrawDebugFlag(((stplyr->pflags & PF_INVIS) ? V_GREENMAP : V_REDMAP), "*I");
V_DrawDebugFlag(((stplyr->pflags & PF_NOCLIP) ? V_GREENMAP : V_REDMAP), "*C");
V_DrawDebugFlag(((stplyr->pflags & PF_GODMODE) ? V_GREENMAP : V_REDMAP), "*G");
V_DrawDebugFlag(((stplyr->charflags & SF_SUPER) ? V_GREENMAP : V_REDMAP), "SU");
V_DrawDebugFlag(((stplyr->pflags & PF_APPLYAUTOBRAKE) ? V_GREENMAP : V_REDMAP), "AA");
V_DrawDebugFlag(((stplyr->pflags & PF_SLIDING) ? V_GREENMAP : V_REDMAP), "SL");
V_DrawDebugFlag(((stplyr->pflags & PF_BOUNCING) ? V_GREENMAP : V_REDMAP), "BO");
V_DrawDebugFlag(((stplyr->pflags & PF_GLIDING) ? V_GREENMAP : V_REDMAP), "GL");
height += h;
V_DrawDebugLine(va("CEILINGZ: %6d", stplyr->mo->ceilingz>>FRACBITS));
V_DrawDebugLine(va("FLOORZ: %6d", stplyr->mo->floorz>>FRACBITS));
V_DrawDebugLine(va("CMOMX: %6d", stplyr->cmomx>>FRACBITS));
V_DrawDebugLine(va("CMOMY: %6d", stplyr->cmomy>>FRACBITS));
V_DrawDebugLine(va("PMOMZ: %6d", stplyr->mo->pmomz>>FRACBITS));
w = 320;
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_APPLYPMOMZ) ? V_GREENMAP : V_REDMAP), "AP");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_SPRUNG) ? V_GREENMAP : V_REDMAP), "SP");
//V_DrawDebugFlag(((stplyr->mo->eflags & MFE_PUSHED) ? V_GREENMAP : V_REDMAP), "PU"); -- not relevant to players
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_GOOWATER) ? V_GREENMAP : V_REDMAP), "GW");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_VERTICALFLIP) ? V_GREENMAP : V_REDMAP), "VF");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_JUSTSTEPPEDDOWN) ? V_GREENMAP : V_REDMAP), "JS");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_UNDERWATER) ? V_GREENMAP : V_REDMAP), "UW");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_TOUCHWATER) ? V_GREENMAP : V_REDMAP), "TW");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_JUSTHITFLOOR) ? V_GREENMAP : V_REDMAP), "JH");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_ONGROUND) ? V_GREENMAP : V_REDMAP), "OG");
V_DrawDebugFlag(0, "MFE:");
height += h;
V_DrawDebugLine(va("MOMX: %6d", stplyr->rmomx>>FRACBITS));
V_DrawDebugLine(va("MOMY: %6d", stplyr->rmomy>>FRACBITS));
V_DrawDebugLine(va("MOMZ: %6d", stplyr->mo->momz>>FRACBITS));
V_DrawDebugLine(va("SPEED: %6d", stplyr->speed>>FRACBITS));
V_DrawDebugLine(va("DRAWANGLE: %6d", FixedInt(d)));
height += dist;
#undef V_DrawDebugFlag
}
if (cv_debug & DBG_BASIC)
{
const fixed_t d = AngleFixed(stplyr->mo->angle);
V_DrawDebugLine(va("X: %6d", stplyr->mo->x>>FRACBITS));
V_DrawDebugLine(va("Y: %6d", stplyr->mo->y>>FRACBITS));
V_DrawDebugLine(va("Z: %6d", stplyr->mo->z>>FRACBITS));
V_DrawDebugLine(va("A: %6d", FixedInt(d)));
//height += dist;
}
textfunc = V_DrawRightAlignedSmallString;
h /= 2;
w /= 2;
lowh = 0;
}
#define V_DrawDebugLine(str) if (lowh && (height > lowh))\
{\
V_DrawRightAlignedThinString(320, 8+lowh, VFLAGS|V_REDMAP, "SOME INFO NOT VISIBLE");\
return;\
}\
textfunc(320, height, VFLAGS, str);\
height += h;
#define V_DrawDebugFlag(f, str) textfunc(width, height, VFLAGS|f, str);\
width -= w
if (cv_debug & DBG_MEMORY)
{
V_DrawDebugLine(va("Heap: %8sKB", sizeu1(Z_TotalUsage()>>10)));
height += h/2;
}
if (cv_debug & DBG_RANDOMIZER) // randomizer testing
{
fixed_t peekres = P_RandomPeek();
peekres *= 10000; // Change from fixed point
peekres >>= FRACBITS; // to displayable decimal
V_DrawDebugLine(va("Init: %08x", P_GetInitSeed()));
V_DrawDebugLine(va("Seed: %08x", P_GetRandSeed()));
V_DrawDebugLine(va("== : .%04d", peekres));
height += h/2;
}
if (cv_debug & DBG_PLAYER)
{
INT32 width = 320;
const fixed_t d = AngleFixed(stplyr->drawangle);
V_DrawDebugLine(va("SHIELD: %5x", stplyr->powers[pw_shield]));
V_DrawDebugLine(va("SCALE: %5d%%", (stplyr->mo->scale*100)>>FRACBITS));
V_DrawDebugLine(va("CARRY: %5x", stplyr->powers[pw_carry]));
V_DrawDebugLine(va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime]));
V_DrawDebugLine(va("ABILITY: %3d, %3d", stplyr->charability, stplyr->charability2));
V_DrawDebugLine(va("ACTIONSPD: %5d", stplyr->actionspd>>FRACBITS));
V_DrawDebugLine(va("PEEL: %3d", stplyr->dashmode));
V_DrawDebugLine(va("SCOREADD: %3d", stplyr->scoreadd));
// Flags
V_DrawDebugFlag(((stplyr->pflags & PF_SHIELDABILITY) ? V_GREENMAP : V_REDMAP), "SH");
V_DrawDebugFlag(((stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP), "TH");
V_DrawDebugFlag(((stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP), "ST");
V_DrawDebugFlag(((stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP), "SP");
V_DrawDebugFlag(((stplyr->pflags & PF_NOJUMPDAMAGE) ? V_GREENMAP : V_REDMAP), "ND");
V_DrawDebugFlag(((stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP), "JD");
V_DrawDebugFlag(((stplyr->pflags & PF_STARTJUMP) ? V_GREENMAP : V_REDMAP), "SJ");
V_DrawDebugFlag(0, "PF/SF:");
height += h;
width = 320;
V_DrawDebugFlag(((stplyr->pflags & PF_INVIS) ? V_GREENMAP : V_REDMAP), "*I");
V_DrawDebugFlag(((stplyr->pflags & PF_NOCLIP) ? V_GREENMAP : V_REDMAP), "*C");
V_DrawDebugFlag(((stplyr->pflags & PF_GODMODE) ? V_GREENMAP : V_REDMAP), "*G");
V_DrawDebugFlag(((stplyr->charflags & SF_SUPER) ? V_GREENMAP : V_REDMAP), "SU");
V_DrawDebugFlag(((stplyr->pflags & PF_APPLYAUTOBRAKE) ? V_GREENMAP : V_REDMAP), "AA");
V_DrawDebugFlag(((stplyr->pflags & PF_SLIDING) ? V_GREENMAP : V_REDMAP), "SL");
V_DrawDebugFlag(((stplyr->pflags & PF_BOUNCING) ? V_GREENMAP : V_REDMAP), "BO");
V_DrawDebugFlag(((stplyr->pflags & PF_GLIDING) ? V_GREENMAP : V_REDMAP), "GL");
height += h;
V_DrawDebugLine(va("DRAWANGLE: %6d", FixedInt(d)));
height += h/2;
}
if (cv_debug & DBG_DETAILED)
{
INT32 width = 320;
V_DrawDebugLine(va("CEILINGZ: %6d", stplyr->mo->ceilingz>>FRACBITS));
V_DrawDebugLine(va("FLOORZ: %6d", stplyr->mo->floorz>>FRACBITS));
V_DrawDebugLine(va("CMOMX: %6d", stplyr->cmomx>>FRACBITS));
V_DrawDebugLine(va("CMOMY: %6d", stplyr->cmomy>>FRACBITS));
V_DrawDebugLine(va("PMOMZ: %6d", stplyr->mo->pmomz>>FRACBITS));
width = 320;
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_APPLYPMOMZ) ? V_GREENMAP : V_REDMAP), "AP");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_SPRUNG) ? V_GREENMAP : V_REDMAP), "SP");
//V_DrawDebugFlag(((stplyr->mo->eflags & MFE_PUSHED) ? V_GREENMAP : V_REDMAP), "PU"); -- not relevant to players
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_GOOWATER) ? V_GREENMAP : V_REDMAP), "GW");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_VERTICALFLIP) ? V_GREENMAP : V_REDMAP), "VF");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_JUSTSTEPPEDDOWN) ? V_GREENMAP : V_REDMAP), "JS");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_UNDERWATER) ? V_GREENMAP : V_REDMAP), "UW");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_TOUCHWATER) ? V_GREENMAP : V_REDMAP), "TW");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_JUSTHITFLOOR) ? V_GREENMAP : V_REDMAP), "JH");
V_DrawDebugFlag(((stplyr->mo->eflags & MFE_ONGROUND) ? V_GREENMAP : V_REDMAP), "OG");
V_DrawDebugFlag(0, "MFE:");
height += h;
V_DrawDebugLine(va("MOMX: %6d", stplyr->rmomx>>FRACBITS));
V_DrawDebugLine(va("MOMY: %6d", stplyr->rmomy>>FRACBITS));
V_DrawDebugLine(va("MOMZ: %6d", stplyr->mo->momz>>FRACBITS));
V_DrawDebugLine(va("SPEED: %6d", stplyr->speed>>FRACBITS));
height += h/2;
}
if (cv_debug & DBG_BASIC)
{
const fixed_t d = AngleFixed(stplyr->mo->angle);
V_DrawDebugLine(va("X: %6d", stplyr->mo->x>>FRACBITS));
V_DrawDebugLine(va("Y: %6d", stplyr->mo->y>>FRACBITS));
V_DrawDebugLine(va("Z: %6d", stplyr->mo->z>>FRACBITS));
V_DrawDebugLine(va("A: %6d", FixedInt(d)));
//height += h/2;
}
#undef V_DrawDebugFlag
#undef V_DrawDebugLine
#undef dist
#undef h
#undef VFLAGS
}
@ -1123,7 +1124,7 @@ static void ST_drawInput(void)
V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
}
static void ST_drawLevelTitle(void)
void ST_drawLevelTitle(tic_t titletime)
{
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *subttl = mapheaderinfo[gamemap-1]->subttl;
@ -1131,7 +1132,7 @@ static void ST_drawLevelTitle(void)
INT32 lvlttly, zoney, lvlttlxpos, ttlnumxpos, zonexpos;
INT32 subttlxpos = BASEVIDWIDTH/2;
if (!(timeinmap > 2 && timeinmap-3 < 110))
if (!(titletime > 2 && titletime-3 < 110))
return;
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
@ -1151,22 +1152,22 @@ static void ST_drawLevelTitle(void)
#define MIDZONEY 105
#define MIDDIFF 4
if (timeinmap < 10)
if (titletime < 10)
{
fixed_t z = ((timeinmap - 3)<<FRACBITS)/7;
fixed_t z = ((titletime - 3)<<FRACBITS)/7;
INT32 ttlh = V_LevelNameHeight(lvlttl);
zoney = (200<<FRACBITS) - ((200 - (MIDZONEY + MIDDIFF))*z);
lvlttly = ((MIDTTLY + ttlh - MIDDIFF)*z) - (ttlh<<FRACBITS);
}
else if (timeinmap < 105)
else if (titletime < 105)
{
fixed_t z = (((timeinmap - 10)*MIDDIFF)<<(FRACBITS+1))/95;
fixed_t z = (((titletime - 10)*MIDDIFF)<<(FRACBITS+1))/95;
zoney = ((MIDZONEY + MIDDIFF)<<FRACBITS) - z;
lvlttly = ((MIDTTLY - MIDDIFF)<<FRACBITS) + z;
}
else
{
fixed_t z = ((timeinmap - 105)<<FRACBITS)/7;
fixed_t z = ((titletime - 105)<<FRACBITS)/7;
INT32 zoneh = V_LevelNameHeight(M_GetText("ZONE"));
zoney = (MIDZONEY + zoneh - MIDDIFF)*(FRACUNIT - z) - (zoneh<<FRACBITS);
lvlttly = ((MIDTTLY + MIDDIFF)<<FRACBITS) + ((200 - (MIDTTLY + MIDDIFF))*z);
@ -1177,8 +1178,8 @@ static void ST_drawLevelTitle(void)
#undef MIDDIFF
#else
// There's no consistent algorithm that can accurately define the old positions
// so I just ended up resorting to a single switct statement to define them
switch (timeinmap-3)
// so I just ended up resorting to a single switch statement to define them
switch (titletime-3)
{
case 0: zoney = 200; lvlttly = 0; break;
case 1: zoney = 188; lvlttly = 12; break;
@ -1509,7 +1510,7 @@ static void ST_drawNiGHTSLink(void)
else
colornum = linkColor[mag][sel];
aflag |= ((stplyr->linktimer < nightslinktics/3)
aflag |= ((stplyr->linktimer < (UINT32)nightslinktics/3)
? (9 - 9*stplyr->linktimer/(nightslinktics/3)) << V_ALPHASHIFT
: 0);
@ -1613,11 +1614,12 @@ static void ST_drawNiGHTSHUD(void)
#endif
ST_DrawTopLeftOverlayPatch(16, 8, nbracket);
if (G_IsSpecialStage(gamemap))
ST_DrawTopLeftOverlayPatch(24, 16, (
#ifdef MANIASPHERES
(stplyr->bonustime && (leveltime & 4)) ? nssbon :
ST_DrawTopLeftOverlayPatch(24, 16, (
(stplyr->bonustime && (leveltime & 4)) ? nssbon : nsshud));
#else
ST_DrawTopLeftOverlayPatch(24, 16, (nsshud));
#endif
nsshud));
else
ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12)));
@ -2461,12 +2463,14 @@ static void ST_overlayDrawer(void)
{
ST_drawFirstPersonHUD();
if (cv_powerupdisplay.value)
ST_drawPowerupHUD();
ST_drawPowerupHUD(); // same as it ever was...
}
else if (cv_powerupdisplay.value == 2)
ST_drawPowerupHUD();
ST_drawPowerupHUD(); // same as it ever was...
}
}
else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2)
ST_drawPowerupHUD(); // same as it ever was...
#ifdef HAVE_BLUA
if (!(netgame || multiplayer) || !hu_showscores)
@ -2479,7 +2483,7 @@ static void ST_overlayDrawer(void)
&& LUA_HudEnabled(hud_stagetitle)
#endif
)
ST_drawLevelTitle();
ST_drawLevelTitle(timeinmap+70);
if (!hu_showscores && (netgame || multiplayer)
#ifdef HAVE_BLUA
@ -2488,7 +2492,7 @@ static void ST_overlayDrawer(void)
)
ST_drawTextHUD();
if (modeattacking)
if (modeattacking && !(demoplayback && hu_showscores))
ST_drawInput();
ST_drawDebugInfo();

View file

@ -47,6 +47,9 @@ void ST_ReloadSkinFaceGraphics(void);
void ST_doPaletteStuff(void);
// level title draw
void ST_drawLevelTitle(tic_t titletime);
// return if player a is in the same team as player b
boolean ST_SameTeam(player_t *a, player_t *b);

View file

@ -340,6 +340,16 @@ UINT16 W_InitFile(const char *filename)
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
if (refreshdirname)
Z_Free(refreshdirname);
if (dirmenu)
{
refreshdirname = Z_StrDup(filename);
nameonly(refreshdirname);
}
else
refreshdirname = NULL;
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
//
// check if limit of active wadfiles
@ -360,9 +370,7 @@ UINT16 W_InitFile(const char *filename)
// see PutFileNeeded in d_netfil.c
if ((important = !W_VerifyNMUSlumps(filename)))
{
packetsize = packetsizetally;
packetsize += nameonlylength(filename) + 22;
packetsize = packetsizetally + nameonlylength(filename) + 22;
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{

View file

@ -1909,8 +1909,8 @@ static void Y_AwardCoopBonuses(void)
}
ptlives = min(
((!ultimatemode && !modeattacking && players[i].lives != INFLIVES) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0),
(mapheaderinfo[prevmap]->maxbonuslives < 0 ? INT32_MAX : mapheaderinfo[prevmap]->maxbonuslives));
(INT32)((!ultimatemode && !modeattacking && players[i].lives != INFLIVES) ? max((INT32)((players[i].score/50000) - (oldscore/50000)), (INT32)0) : 0),
(INT32)(mapheaderinfo[prevmap]->maxbonuslives < 0 ? INT32_MAX : mapheaderinfo[prevmap]->maxbonuslives));
if (ptlives)
P_GivePlayerLives(&players[i], ptlives);
@ -1955,10 +1955,9 @@ static void Y_AwardSpecialStageBonus(void)
// grant extra lives right away since tally is faked
ptlives = min(
((!ultimatemode && !modeattacking && players[i].lives != INFLIVES) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0),
(mapheaderinfo[prevmap]->maxbonuslives < 0 ? INT32_MAX : mapheaderinfo[prevmap]->maxbonuslives));
if (ptlives)
P_GivePlayerLives(&players[i], ptlives);
(INT32)((!ultimatemode && !modeattacking && players[i].lives != INFLIVES) ? max((INT32)((players[i].score/50000) - (oldscore/50000)), (INT32)0) : 0),
(INT32)(mapheaderinfo[prevmap]->maxbonuslives < 0 ? INT32_MAX : mapheaderinfo[prevmap]->maxbonuslives));
P_GivePlayerLives(&players[i], ptlives);
if (i == consoleplayer)
{