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 // Fade to black first
if ((wipegamestate == (gamestate_t)FORCEWIPE || 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) && wipetypepre != UINT8_MAX)
{ {
F_WipeStartScreen(); F_WipeStartScreen();
@ -370,89 +372,96 @@ static void D_Display(void)
break; break;
} }
// clean up border stuff // STUPID race condition...
// see if the border needs to be initially drawn if (wipegamestate == GS_INTRO && gamestate == GS_TITLESCREEN)
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide)) 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) // draw the view directly
{
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]);
}
// render the second screen if (!automapactive && !dedicated && cv_renderview.value)
if (splitscreen && players[secondarydisplayplayer].mo)
{ {
#ifdef HWRENDER if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
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]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx; 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; topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
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 (lastdraw)
if (rendermode == render_soft)
{ {
if (postimgtype) if (rendermode == render_soft)
V_DoPostProcessor(0, postimgtype, postimgparam); {
if (postimgtype2) VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
V_DoPostProcessor(1, postimgtype2, postimgparam2); usebuffer = true;
}
lastdraw = false;
} }
}
if (lastdraw) if (gamestate == GS_LEVEL)
{
if (rendermode == render_soft)
{ {
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); ST_Drawer();
usebuffer = true; 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 // change gamma if needed
// (GS_LEVEL handles this already due to level-specific palettes) // (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); V_SetPalette(0);
wipegamestate = gamestate;
// draw pause pic // draw pause pic
if (paused && cv_showhud.value && (!menuactive || netgame)) if (paused && cv_showhud.value && (!menuactive || netgame))
{ {
#if 0
INT32 py; INT32 py;
patch_t *patch; patch_t *patch;
if (automapactive) if (automapactive)
@ -461,6 +470,11 @@ static void D_Display(void)
py = viewwindowy + 4; py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_CACHE); patch = W_CachePatchName("M_PAUSE", PU_CACHE);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch); 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... // 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 == ':') if (*p == '\\' || *p == '/' || *p == ':')
break; break;
++p; ++p;
// check total packet size and no of files currently loaded // 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; CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
serverinfo_pak *dummycheck = NULL; return;
// 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;
}
} }
WRITESTRINGN(buf_p,p,240); WRITESTRINGN(buf_p,p,240);
@ -3174,11 +3162,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
boolean kick = false; boolean kick = false;
boolean toomany = false; boolean toomany = false;
INT32 i; INT32 i;
size_t packetsize = 0;
serverinfo_pak *dummycheck = NULL;
// Shut the compiler up.
(void)dummycheck;
READSTRINGN(*cp, filename, 240); READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16); READMEM(*cp, md5sum, 16);
@ -3205,13 +3188,8 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
} }
// See W_LoadWadFile in w_wad.c // 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) if ((numwadfiles >= MAX_WADFILES)
|| (packetsize > sizeof(dummycheck->fileneeded))) || ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8)))
toomany = true; toomany = true;
else else
ncs = findfile(filename,md5sum,true); ncs = findfile(filename,md5sum,true);
@ -3364,6 +3342,9 @@ static void Command_Playintro_f(void)
if (netgame) if (netgame)
return; return;
if (dirmenu)
closefilemenu(true);
F_StartIntro(); F_StartIntro();
} }
@ -4012,6 +3993,9 @@ void Command_ExitGame_f(void)
cv_debug = 0; cv_debug = 0;
emeralds = 0; emeralds = 0;
if (dirmenu)
closefilemenu(true);
if (!modeattacking) if (!modeattacking)
D_StartTitle(); D_StartTitle();
} }

View file

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

View file

@ -455,6 +455,8 @@ typedef struct player_s
UINT8 drilldelay; UINT8 drilldelay;
boolean bonustime; // Capsule destroyed, now it's bonus time! boolean bonustime; // Capsule destroyed, now it's bonus time!
mobj_t *capsule; // Go inside the capsule 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 mare; // Current mare
UINT8 marelap; // Current mare lap UINT8 marelap; // Current mare lap
UINT8 marebonuslap; // Current mare lap starting from bonus time 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", "S_TOAD",
// Nights-specific stuff // Nights-specific stuff
"S_NIGHTSDRONE1", "S_NIGHTSDRONE_MAN1",
"S_NIGHTSDRONE2", "S_NIGHTSDRONE_MAN2",
"S_NIGHTSDRONE_SPARKLING1", "S_NIGHTSDRONE_SPARKLING1",
"S_NIGHTSDRONE_SPARKLING2", "S_NIGHTSDRONE_SPARKLING2",
"S_NIGHTSDRONE_SPARKLING3", "S_NIGHTSDRONE_SPARKLING3",
@ -6600,10 +6600,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_NIGHTSDRONE_SPARKLING14", "S_NIGHTSDRONE_SPARKLING14",
"S_NIGHTSDRONE_SPARKLING15", "S_NIGHTSDRONE_SPARKLING15",
"S_NIGHTSDRONE_SPARKLING16", "S_NIGHTSDRONE_SPARKLING16",
"S_NIGHTSGOAL1", "S_NIGHTSDRONE_GOAL1",
"S_NIGHTSGOAL2", "S_NIGHTSDRONE_GOAL2",
"S_NIGHTSGOAL3", "S_NIGHTSDRONE_GOAL3",
"S_NIGHTSGOAL4", "S_NIGHTSDRONE_GOAL4",
"S_NIGHTSPARKLE1", "S_NIGHTSPARKLE1",
"S_NIGHTSPARKLE2", "S_NIGHTSPARKLE2",
@ -7474,7 +7474,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_AXISTRANSFER", "MT_AXISTRANSFER",
"MT_AXISTRANSFERLINE", "MT_AXISTRANSFERLINE",
"MT_NIGHTSDRONE", "MT_NIGHTSDRONE",
"MT_NIGHTSGOAL", "MT_NIGHTSDRONE_MAN",
"MT_NIGHTSDRONE_SPARKLING",
"MT_NIGHTSDRONE_GOAL",
"MT_NIGHTSPARKLE", "MT_NIGHTSPARKLE",
"MT_NIGHTSLOOPHELPER", "MT_NIGHTSLOOPHELPER",
"MT_NIGHTSBUMPER", // NiGHTS Bumper "MT_NIGHTSBUMPER", // NiGHTS Bumper
@ -7491,6 +7493,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_NIGHTSEXTRATIME", "MT_NIGHTSEXTRATIME",
"MT_NIGHTSLINKFREEZE", "MT_NIGHTSLINKFREEZE",
"MT_EGGCAPSULE", "MT_EGGCAPSULE",
"MT_IDEYAANCHOR",
"MT_NIGHTOPIANHELPER", // the actual helper object that orbits you "MT_NIGHTOPIANHELPER", // the actual helper object that orbits you
"MT_PIAN", // decorative singing friend "MT_PIAN", // decorative singing friend
"MT_SHLEEP", // almost-decorative sleeping enemy "MT_SHLEEP", // almost-decorative sleeping enemy

View file

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

View file

@ -29,6 +29,7 @@
#include "g_input.h" #include "g_input.h"
#include "console.h" #include "console.h"
#include "m_random.h" #include "m_random.h"
#include "m_misc.h" // moviemode functionality
#include "y_inter.h" #include "y_inter.h"
#include "m_cond.h" #include "m_cond.h"
#include "p_local.h" #include "p_local.h"
@ -249,7 +250,7 @@ void F_StartIntro(void)
introtext[2] = M_GetText( introtext[2] = M_GetText(
"As it was about to drain the rings\n" "As it was about to drain the rings\n"
"away from the planet, Sonic burst into\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" "would be the last time,\xB4 defeated\n"
"Dr. Eggman.\n#"); "Dr. Eggman.\n#");
@ -259,11 +260,11 @@ void F_StartIntro(void)
"return,\xB8 bringing an all new threat.\n#"); "return,\xB8 bringing an all new threat.\n#");
introtext[4] = M_GetText( 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" "hovers around the planet.\xBF It suddenly\n"
"appears from nowhere, circles around, and\n" "appears from nowhere, circles around, and\n"
"\xB6- just as mysteriously as it arrives -\xB6\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#"); "No one knows why it appears, or how.\n#");
introtext[5] = M_GetText( introtext[5] = M_GetText(
@ -316,7 +317,7 @@ void F_StartIntro(void)
"\xA5\"6...\xD2""5...\xD2""4...\"\xA8\xD2\n" "\xA5\"6...\xD2""5...\xD2""4...\"\xA8\xD2\n"
"Sonic knew he was getting closer to the\n" "Sonic knew he was getting closer to the\n"
"zone, and pushed himself harder.\xB4 Finally,\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#"); "\xA5\"3...\xD2""2...\xD2""1...\xD2""Zero.\"\n#");
introtext[11] = M_GetText( introtext[11] = M_GetText(
@ -749,18 +750,27 @@ void F_IntroDrawer(void)
// Stay on black for a bit. =) // Stay on black for a bit. =)
{ {
tic_t quittime; tic_t nowtime, quittime, lasttime;
quittime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds nowtime = lasttime = I_GetTime();
while (quittime > 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_OsPolling();
I_UpdateNoBlit(); I_UpdateNoBlit();
M_Drawer(); // menu is drawn even on top of wipes M_Drawer(); // menu is drawn even on top of wipes
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 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(); D_StartTitle();
wipegamestate = GS_INTRO;
return; return;
} }
F_NewCutscene(introtext[++intro_scenenum]); F_NewCutscene(introtext[++intro_scenenum]);
@ -1566,7 +1576,7 @@ void F_TitleScreenDrawer(void)
else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS)
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); 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)) if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
return; return;
@ -1926,6 +1936,9 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
G_SetGamestate(GS_CUTSCENE); G_SetGamestate(GS_CUTSCENE);
if (wipegamestate == GS_CUTSCENE)
wipegamestate = -1;
gameaction = ga_nothing; gameaction = ga_nothing;
paused = false; paused = false;
CON_ToggleOff(); CON_ToggleOff();

View file

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

View file

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

View file

@ -40,6 +40,7 @@ extern char **dirmenu;
extern size_t sizedirmenu; extern size_t sizedirmenu;
extern size_t dir_on[menudepth]; extern size_t dir_on[menudepth];
extern UINT8 refreshdirmenu; extern UINT8 refreshdirmenu;
extern char *refreshdirname;
extern size_t packetsizetally; extern size_t packetsizetally;
extern size_t mainwadstally; extern size_t mainwadstally;
@ -87,6 +88,8 @@ typedef enum
REFRESHDIR_MAX = 32 REFRESHDIR_MAX = 32
} refreshdir_enum; } refreshdir_enum;
void closefilemenu(boolean validsize);
void searchfilemenu(char *tempname);
boolean preparefilemenu(boolean samedepth); boolean preparefilemenu(boolean samedepth);
#endif // __FILESRCH_H__ #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_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_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_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_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_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_mousemove = {"mousemove", "Off", 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_mousemove2 = {"mousemove2", "Off", 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};
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 // 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_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_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}; 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(); CON_ClearHUD();
} }
static INT32 pausedelay = 0; INT32 pausedelay = 0;
boolean pausebreakkey = false;
static INT32 camtoggledelay, camtoggledelay2 = 0; static INT32 camtoggledelay, camtoggledelay2 = 0;
// //
@ -1798,19 +1801,35 @@ boolean G_Responder(event_t *ev)
{ {
case ev_keydown: case ev_keydown:
if (ev->data1 == gamecontrol[gc_pause][0] 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 pausebreakkey = (ev->data1 == KEY_PAUSE);
pausedelay = NEWTICRATE/7; if (menuactive || pausedelay < 0 || leveltime < 2)
return true;
// command will handle all the checks for us if (pausedelay < 1+(NEWTICRATE/2))
COM_ImmedExecute("pause"); pausedelay = 1+(NEWTICRATE/2);
return true; else if (++pausedelay > 1+(NEWTICRATE/2)+(NEWTICRATE/3))
{
G_SetRetryFlag();
return true;
}
pausedelay++; // counteract subsequent subtraction this frame
} }
else 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] if (ev->data1 == gamecontrol[gc_camtoggle][0]
|| ev->data1 == gamecontrol[gc_camtoggle][1]) || ev->data1 == gamecontrol[gc_camtoggle][1])
@ -1870,11 +1889,19 @@ void G_Ticker(boolean run)
{ {
G_ClearRetryFlag(); G_ClearRetryFlag();
// Costs a life to retry ... unless the player in question is dead already. if (modeattacking)
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE) {
players[consoleplayer].lives -= 1; 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++) for (i = 0; i < MAXPLAYERS; i++)
@ -1975,8 +2002,13 @@ void G_Ticker(boolean run)
if (run) if (run)
{ {
if (pausedelay) if (pausedelay && pausedelay != INT32_MIN)
pausedelay--; {
if (pausedelay > 0)
pausedelay--;
else
pausedelay++;
}
if (camtoggledelay) if (camtoggledelay)
camtoggledelay--; camtoggledelay--;
@ -2922,6 +2954,9 @@ static void G_DoCompleted(void)
tokenlist = 0; // Reset the list tokenlist = 0; // Reset the list
if (modeattacking && pausedelay)
pausedelay = 0;
gameaction = ga_nothing; gameaction = ga_nothing;
if (metalplayback) if (metalplayback)

View file

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

View file

@ -709,7 +709,7 @@ void G_DefineDefaultControls(void)
gamecontroldefault[i][gc_teamkey ][0] = 'y'; gamecontroldefault[i][gc_teamkey ][0] = 'y';
gamecontroldefault[i][gc_scores ][0] = KEY_TAB; gamecontroldefault[i][gc_scores ][0] = KEY_TAB;
gamecontroldefault[i][gc_console ][0] = KEY_CONSOLE; 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; return;
} }
keynum = G_KeyStringtoNum(COM_Argv(2)); 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); G_CheckDoubleUsage(keynum);
gc[numctrl][0] = keynum; gc[numctrl][0] = keynum;
if (na == 4) 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 else
gc[numctrl][1] = 0; gc[numctrl][1] = 0;
} }

View file

@ -29,6 +29,7 @@
#include "../m_argv.h" #include "../m_argv.h"
#include "../i_video.h" #include "../i_video.h"
#include "../w_wad.h" #include "../w_wad.h"
#include "../p_setup.h" // levelfadecol
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// This is global data for planes rendering // 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); sprintf(s, "%d%%", (++ls_percent)<<1);
x = BASEVIDWIDTH/2; x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/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. //V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
M_DrawTextBox(x-58, y-8, 13, 1); M_DrawTextBox(x-58, y-8, 13, 1);
V_DrawString(x-50, y, V_YELLOWMAP, "Loading..."); 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); 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) 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 // 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) 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) if (modeattacking)
{ {
V_DrawString(4, 188-16, V_YELLOWMAP|V_MONOSPACE, "SCORE:"); V_DrawString(4, h-16, V_YELLOWMAP|V_MONOSPACE, "SCORE:");
V_DrawRightAlignedString(120, 188-16, V_MONOSPACE, va("%d", hu_demoscore)); 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) 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_TicsToMinutes(hu_demotime,true),
G_TicsToSeconds(hu_demotime), G_TicsToSeconds(hu_demotime),
G_TicsToCentiseconds(hu_demotime))); G_TicsToCentiseconds(hu_demotime)));
else else
V_DrawRightAlignedString(120, 188- 8, V_MONOSPACE, "--:--.--"); V_DrawRightAlignedString(120, h-8, V_MONOSPACE, "--:--.--");
if (modeattacking == ATTACKING_RECORD) if (modeattacking == ATTACKING_RECORD)
{ {
V_DrawString(4, 188 , V_YELLOWMAP|V_MONOSPACE, "RINGS:"); V_DrawString(4, h, V_YELLOWMAP|V_MONOSPACE, "RINGS:");
V_DrawRightAlignedString(120, 188 , V_MONOSPACE, va("%d", hu_demorings)); 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); 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 {SPR_TOAD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_TOAD
// Nights Drone // Nights Drone
{SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE2}, // S_NIGHTSDRONE1 {SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN2}, // S_NIGHTSDRONE_MAN1
{SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_NIGHTSDRONE2 {SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN1}, // S_NIGHTSDRONE_MAN2
// Sparkling point (RETURN TO THE GOAL, etc) // Sparkling point (RETURN TO THE GOAL, etc)
{SPR_IVSP, 0, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING2}, // S_NIGHTSDRONE_SPARKLING1 {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 {SPR_IVSP, 30, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING1}, // S_NIGHTSDRONE_SPARKLING16
// NiGHTS GOAL banner (inside the sparkles!) // NiGHTS GOAL banner (inside the sparkles!)
{SPR_GOAL, 0, 4, {NULL}, 0, 0, S_NIGHTSGOAL2}, // S_NIGHTSGOAL1 {SPR_GOAL, 0, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL2}, // S_NIGHTSDRONE_GOAL1
{SPR_GOAL, 1, 4, {NULL}, 0, 0, S_NIGHTSGOAL3}, // S_NIGHTSGOAL2 {SPR_GOAL, 1, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL3}, // S_NIGHTSDRONE_GOAL2
{SPR_GOAL, 2, 4, {NULL}, 0, 0, S_NIGHTSGOAL4}, // S_NIGHTSGOAL3 {SPR_GOAL, 2, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL4}, // S_NIGHTSDRONE_GOAL3
{SPR_GOAL, 3, 4, {NULL}, 0, 0, S_NIGHTSGOAL1}, // S_NIGHTSGOAL4 {SPR_GOAL, 3, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL1}, // S_NIGHTSDRONE_GOAL4
// Nights Sparkle // Nights Sparkle
{SPR_NSPK, FF_FULLBRIGHT, 140, {NULL}, 0, 0, S_NIGHTSPARKLE2}, // S_NIGHTSPARKLE1 {SPR_NSPK, FF_FULLBRIGHT, 140, {NULL}, 0, 0, S_NIGHTSPARKLE2}, // S_NIGHTSPARKLE1
@ -16652,7 +16652,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSDRONE { // MT_NIGHTSDRONE
1703, // doomednum 1703, // doomednum
S_NIGHTSDRONE1, // spawnstate S_INVISIBLE, // spawnstate
120, // spawnhealth 120, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -16668,18 +16668,45 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
56*FRACUNIT, // height 80*FRACUNIT, // height
1, // display offset 1, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_ideya, // activesound sfx_ideya, // activesound
MF_SPECIAL, // flags MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL, // flags
S_NULL // raisestate 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 -1, // doomednum
S_NIGHTSGOAL1, // spawnstate S_INVISIBLE, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -16688,14 +16715,41 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // painstate S_NULL, // painstate
255, // painchance 255, // painchance
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NIGHTSDRONE_SPARKLING1, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_NULL, // deathstate S_NULL, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
16*FRACUNIT, // radius 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 -1, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
@ -17136,6 +17190,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate 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 { // MT_NIGHTOPIANHELPER
-1, // doomednum -1, // doomednum
S_NIGHTOPIANHELPER1, // spawnstate S_NIGHTOPIANHELPER1, // spawnstate

View file

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

View file

@ -288,6 +288,10 @@ static int player_get(lua_State *L)
lua_pushboolean(L, plr->bonustime); lua_pushboolean(L, plr->bonustime);
else if (fastcmp(field,"capsule")) else if (fastcmp(field,"capsule"))
LUA_PushUserdata(L, plr->capsule, META_MOBJ); 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")) else if (fastcmp(field,"mare"))
lua_pushinteger(L, plr->mare); lua_pushinteger(L, plr->mare);
else if (fastcmp(field,"marelap")) 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)); mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->capsule, mo); 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")) else if (fastcmp(field,"mare"))
plr->mare = (UINT8)luaL_checkinteger(L, 3); plr->mare = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marelap")) else if (fastcmp(field,"marelap"))

View file

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

View file

@ -284,7 +284,6 @@ static void M_Statistics(INT32 choice);
static void M_ReplayTimeAttack(INT32 choice); static void M_ReplayTimeAttack(INT32 choice);
static void M_ChooseTimeAttack(INT32 choice); static void M_ChooseTimeAttack(INT32 choice);
static void M_ChooseNightsAttack(INT32 choice); static void M_ChooseNightsAttack(INT32 choice);
static void M_ModeAttackRetry(INT32 choice);
static void M_ModeAttackEndGame(INT32 choice); static void M_ModeAttackEndGame(INT32 choice);
static void M_SetGuestReplay(INT32 choice); static void M_SetGuestReplay(INT32 choice);
static void M_HandleChoosePlayerMenu(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_Addons(INT32 choice);
static void M_AddonsOptions(INT32 choice); static void M_AddonsOptions(INT32 choice);
static patch_t *addonsp[NUM_EXT+6]; static patch_t *addonsp[NUM_EXT+6];
static UINT8 addonsresponselimit = 0;
#define numaddonsshown 4 #define numaddonsshown 4
@ -1078,10 +1076,10 @@ static menuitem_t OP_ChangeControlsMenu[] =
{IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_use }, {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_use },
{IT_HEADER, NULL, "Camera", NULL, 0}, {IT_HEADER, NULL, "Camera", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Camera Up", M_ChangeControl, gc_lookup }, {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup },
{IT_CALL | IT_STRING2, NULL, "Camera Down", M_ChangeControl, gc_lookdown }, {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown },
{IT_CALL | IT_STRING2, NULL, "Camera Left", M_ChangeControl, gc_turnleft }, {IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, gc_turnleft },
{IT_CALL | IT_STRING2, NULL, "Camera Right", M_ChangeControl, gc_turnright }, {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, "Center View", M_ChangeControl, gc_centerview },
{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming }, {IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming },
{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle}, {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_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Game Status", {IT_CALL | IT_STRING2, NULL, "Game Status",
M_ChangeControl, gc_scores }, 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_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console },
{IT_HEADER, NULL, "Multiplayer", NULL, 0}, {IT_HEADER, NULL, "Multiplayer", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
@ -2658,15 +2656,19 @@ static void M_GoBack(INT32 choice)
if (!Playing() && netgame && multiplayer) if (!Playing() && netgame && multiplayer)
{ {
MSCloseUDPSocket(); // Clean up so we can re-open the connection later. MSCloseUDPSocket(); // Clean up so we can re-open the connection later.
netgame = false; netgame = multiplayer = false;
multiplayer = false;
} }
if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef))
{ {
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. // 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; menuactive = false;
wipetypepre = menupres[M_GetYoungestChildMenu()].exitwipe; wipetypepre = menupres[M_GetYoungestChildMenu()].exitwipe;
D_StartTitle(); D_StartTitle();
@ -5326,22 +5328,24 @@ static void M_Addons(INT32 choice)
(void)choice; (void)choice;
/*if (cv_addons_option.value == 0) #if 1
pathname = srb2home; usehome ? srb2home : srb2path; if (cv_addons_option.value == 0)
pathname = usehome ? srb2home : srb2path;
else if (cv_addons_option.value == 1) else if (cv_addons_option.value == 1)
pathname = srb2home; pathname = srb2home;
else if (cv_addons_option.value == 2) else if (cv_addons_option.value == 2)
pathname = srb2path; pathname = srb2path;
else*/ else
#endif
if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
pathname = cv_addons_folder.string; pathname = cv_addons_folder.string;
strlcpy(menupath, pathname, 1024); strlcpy(menupath, pathname, 1024);
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; 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; menupath[menupathindex[menudepthleft]] = 0;
} }
else else
@ -5435,11 +5439,7 @@ static char *M_AddonsHeaderPath(void)
UINT32 len; UINT32 len;
static char header[1024]; static char header[1024];
if (menupath[0] == '.') strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024);
strlcpy(header, va("SRB2 folder%s", menupath+1), 1024);
else
strcpy(header, menupath);
len = strlen(header); len = strlen(header);
if (len > 34) if (len > 34)
{ {
@ -5456,6 +5456,15 @@ static char *M_AddonsHeaderPath(void)
M_SetupNextMenu(MISC_AddonsDef.prevMenu);\ 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) 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 // returns whether to do message draw
static boolean M_AddonsRefresh(void) static boolean M_AddonsRefresh(void)
{ {
@ -5467,35 +5476,35 @@ static boolean M_AddonsRefresh(void)
if (refreshdirmenu & REFRESHDIR_ADDFILE) if (refreshdirmenu & REFRESHDIR_ADDFILE)
{ {
addonsresponselimit = 0; char *message = NULL;
if (refreshdirmenu & REFRESHDIR_NOTLOADED) if (refreshdirmenu & REFRESHDIR_NOTLOADED)
{ {
char *message = NULL;
S_StartSound(NULL, sfx_lose); S_StartSound(NULL, sfx_lose);
if (refreshdirmenu & REFRESHDIR_MAX) 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 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); message = va("\x82%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", refreshdirname);
M_StartMessage(message,NULL,MM_NOTHING);
return true;
} }
else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
{ {
S_StartSound(NULL, sfx_skid); 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; return true;
} }
S_StartSound(NULL, sfx_strpst); S_StartSound(NULL, sfx_strpst);
CLEARNAME;
} }
return false; return false;
} }
#define offs 1
#ifdef FIXUPO0 #ifdef FIXUPO0
#pragma GCC optimize ("0") #pragma GCC optimize ("0")
#endif #endif
@ -5513,9 +5522,6 @@ static void M_DrawAddons(void)
return; return;
} }
if (addonsresponselimit)
addonsresponselimit--;
if (Playing()) if (Playing())
topstr = "\x85""Adding files mid-game may cause problems."; topstr = "\x85""Adding files mid-game may cause problems.";
else if (savemoddata) else if (savemoddata)
@ -5525,7 +5531,7 @@ static void M_DrawAddons(void)
else else
topstr = LOCATIONSTRING; topstr = LOCATIONSTRING;
V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, topstr); V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, topstr);
if (numwadfiles <= mainwads+1) if (numwadfiles <= mainwads+1)
y = 0; y = 0;
@ -5545,7 +5551,7 @@ static void M_DrawAddons(void)
// DRAW MENU // DRAW MENU
x = currentMenu->x; x = currentMenu->x;
y = currentMenu->y + offs; y = currentMenu->y + 1;
//M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width //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()); 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 + (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 - 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... // get bottom...
max = dir_on[menudepthleft] + numaddonsshown + 1; max = dir_on[menudepthleft] + numaddonsshown + 1;
@ -5609,7 +5615,7 @@ static void M_DrawAddons(void)
if (max != (ssize_t)sizedirmenu) if (max != (ssize_t)sizedirmenu)
V_DrawString(19, y-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); 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); M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
if (menusearch[0]) if (menusearch[0])
@ -5623,21 +5629,17 @@ static void M_DrawAddons(void)
x -= (21 + 5 + 16); x -= (21 + 5 + 16);
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
#define CANSAVE (!modifiedgame || savemoddata)
x = BASEVIDWIDTH - x - 16; 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) if (modifiedgame)
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]); V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]);
#undef CANSAVE
} }
#ifdef FIXUPO0 #ifdef FIXUPO0
#pragma GCC reset_options #pragma GCC reset_options
#endif #endif
#undef offs
static void M_AddonExec(INT32 ch) static void M_AddonExec(INT32 ch)
{ {
if (ch != 'y' && ch != KEY_ENTER) if (ch != 'y' && ch != KEY_ENTER)
@ -5689,16 +5691,17 @@ static void M_HandleAddons(INT32 choice)
{ {
boolean exitmenu = false; // exit to previous menu boolean exitmenu = false; // exit to previous menu
if (addonsresponselimit)
return;
if (M_ChangeStringAddons(choice)) 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; UNEXIST;
return; return;
} }*/
} }
switch (choice) switch (choice)
@ -5797,7 +5800,6 @@ static void M_HandleAddons(INT32 choice)
case EXT_WAD: case EXT_WAD:
case EXT_PK3: case EXT_PK3:
COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
addonsresponselimit = 5;
break; break;
default: default:
S_StartSound(NULL, sfx_lose); S_StartSound(NULL, sfx_lose);
@ -5817,14 +5819,7 @@ static void M_HandleAddons(INT32 choice)
} }
if (exitmenu) if (exitmenu)
{ {
for (; sizedirmenu > 0; sizedirmenu--) closefilemenu(true);
{
Z_Free(dirmenu[sizedirmenu-1]);
dirmenu[sizedirmenu-1] = NULL;
}
Z_Free(dirmenu);
dirmenu = NULL;
// secrets disabled by addfile... // secrets disabled by addfile...
MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
@ -8535,9 +8530,10 @@ static void M_SetGuestReplay(INT32 choice)
which(0); which(0);
} }
static void M_ModeAttackRetry(INT32 choice) void M_ModeAttackRetry(INT32 choice)
{ {
(void)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 G_CheckDemoStatus(); // Cancel recording
if (modeattacking == ATTACKING_RECORD) if (modeattacking == ATTACKING_RECORD)
M_ChooseTimeAttack(0); M_ChooseTimeAttack(0);
@ -9953,6 +9949,7 @@ static void M_DrawControl(void)
#undef controlbuffer #undef controlbuffer
static INT32 controltochange; static INT32 controltochange;
static char controltochangetext[55];
static void M_ChangecontrolResponse(event_t *ev) static void M_ChangecontrolResponse(event_t *ev)
{ {
@ -9960,8 +9957,8 @@ static void M_ChangecontrolResponse(event_t *ev)
INT32 found; INT32 found;
INT32 ch = ev->data1; INT32 ch = ev->data1;
// ESCAPE cancels // ESCAPE cancels; dummy out PAUSE
if (ch != KEY_ESCAPE) if (ch != KEY_ESCAPE && ch != KEY_PAUSE)
{ {
switch (ev->type) switch (ev->type)
@ -10022,6 +10019,24 @@ static void M_ChangecontrolResponse(event_t *ev)
} }
S_StartSound(NULL, sfx_strpst); 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 else
S_StartSound(NULL, sfx_skid); S_StartSound(NULL, sfx_skid);
@ -10038,6 +10053,7 @@ static void M_ChangeControl(INT32 choice)
controltochange = currentMenu->menuitems[choice].alphaKey; controltochange = currentMenu->menuitems[choice].alphaKey;
sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"), sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"),
currentMenu->menuitems[choice].text); currentMenu->menuitems[choice].text);
strncpy(controltochangetext, currentMenu->menuitems[choice].text, 55);
M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER);
} }

View file

@ -370,7 +370,7 @@ extern INT16 startmap;
extern INT32 ultimate_selectable; extern INT32 ultimate_selectable;
extern INT16 char_on, startchar; 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 NOSAVESLOT 0 //slot where Play Without Saving appears
#define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he #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_CheatActivationResponder(INT32 ch);
void M_ModeAttackRetry(INT32 choice);
// Level select updating // Level select updating
void Nextmap_OnChange(void); 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.) // Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.)
// //
// var1 = Angle adjustment (aka orbit speed) // 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) void A_OrbitNights(mobj_t* actor)
{ {
INT32 ofs = (var2 & 0xFFFF); INT32 ofs = (var2 & 0x3FF);
boolean ishelper = (var2 & 0xFFFF0000); boolean ishelper = (var2 & 0x10000);
boolean donotrescale = (var2 & 0x40000);
INT32 xfactor = 32, yfactor = 32, zfactor = 20;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_OrbitNights", actor)) if (LUA_CallAction("A_OrbitNights", actor))
return; return;
#endif #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 if (!actor->target
|| (actor->target->player && || (actor->target->player &&
// if NiGHTS special stage and not NiGHTSmode. // 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 fa = (angle_t)actor->extravalue1 >> ANGLETOFINESHIFT;
const angle_t ofa = ((angle_t)actor->extravalue1 + (ofs*ANG1)) >> 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 fc = FixedMul(FINECOSINE(fa),FixedMul(xfactor*FRACUNIT, actor->scale));
const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(20*FRACUNIT, actor->scale)); const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(zfactor*FRACUNIT, actor->scale));
const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(32*FRACUNIT, actor->scale)); const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(yfactor*FRACUNIT, actor->scale));
actor->x = actor->target->x + fc; actor->x = actor->target->x + fc;
actor->y = actor->target->y + fs; actor->y = actor->target->y + fs;
@ -8603,6 +8629,9 @@ void A_OrbitNights(mobj_t* actor)
else else
actor->flags2 &= ~MF2_DONTDRAW; 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); P_SwitchSpheresBonusMode(false);
if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE))
P_SetTarget(&special->tracer, toucher); P_SetTarget(&special->tracer, toucher);
P_SetTarget(&player->drone, special); // Mark the player as 'center into the drone'
P_NightserizePlayer(player, special->health); // Transform! P_NightserizePlayer(player, special->health); // Transform!
if (!spec) 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; mobj_t *orbittarget = special->target ? special->target : special;
P_SetTarget(&special->hnext, toucher->tracer); mobj_t *hnext = orbittarget->hnext, *anchorpoint = NULL, *anchorpoint2 = NULL;
P_SetTarget(&special->hnext->hnext, hnext); // Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. mobj_t *mo2;
P_SetTarget(&special->hnext->target, special); 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); P_SetTarget(&toucher->tracer, NULL);
if (hnext) if (hnext)
{ {
special->hnext->extravalue1 = (angle_t)(hnext->extravalue1 - 72*ANG1); orbittarget->hnext->extravalue1 = (angle_t)(hnext->extravalue1 - 72*ANG1);
if (special->hnext->extravalue1 > hnext->extravalue1) if (orbittarget->hnext->extravalue1 > hnext->extravalue1)
special->hnext->extravalue1 -= (72*ANG1)/special->hnext->extravalue1; orbittarget->hnext->extravalue1 -= (72*ANG1)/orbittarget->hnext->extravalue1;
} }
} }
if (player->exiting) // ...then move it back? if (player->exiting) // ...then move it back?
{ {
mobj_t *hnext = special; mobj_t *hnext = special->target ? special->target : special; // goalpost
while ((hnext = hnext->hnext)) while ((hnext = hnext->hnext))
{
hnext->flags &= ~MF_GRENADEBOUNCE;
hnext->threshold = 0;
P_SetTarget(&hnext->target, toucher); P_SetTarget(&hnext->target, toucher);
}
} }
return; 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) if (player->powers[pw_carry] == CR_NIGHTSMODE && !toucher->target)
return; return;
if (toucher->tracer) if (toucher->tracer && toucher->tracer->health > 0)
return; // Don't have multiple ideya return; // Don't have multiple ideya, unless it's the first one given (health = 0)
if (player->mare != special->threshold) // wrong mare if (player->mare != special->threshold) // wrong mare
return; return;

View file

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

View file

@ -7924,78 +7924,247 @@ void P_MobjThinker(mobj_t *mobj)
} }
break; break;
case MT_NIGHTSDRONE: case MT_NIGHTSDRONE:
// GOAL mode?
if (mobj->state >= &states[S_NIGHTSDRONE_SPARKLING1] && mobj->state <= &states[S_NIGHTSDRONE_SPARKLING16])
{ {
INT32 i; // variable setup
boolean bonustime = false; mobj_t *goalpost = NULL;
mobj_t *sparkle = NULL;
mobj_t *droneman = NULL;
for (i = 0; i < MAXPLAYERS; i++) boolean flip = mobj->flags2 & MF2_OBJECTFLIP;
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) boolean topaligned = (mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE);
{ boolean middlealigned = (mobj->flags & MF_GRENADEBOUNCE) && !(mobj->flags & MF_SLIDEME);
bonustime = true; boolean bottomoffsetted = !(mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE);
break; 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"); goalpost = mobj->target;
P_RemoveMobj(mobj->target); if (goalpost->target && goalpost->target->type == MT_NIGHTSDRONE_SPARKLING)
P_SetTarget(&mobj->target, NULL); sparkle = goalpost->target;
if (goalpost->tracer && goalpost->tracer->type == MT_NIGHTSDRONE_MAN)
mobj->flags &= ~MF_NOGRAVITY; droneman = goalpost->tracer;
mobj->flags2 |= MF2_DONTDRAW;
P_SetMobjState(mobj, S_NIGHTSDRONE1);
} }
}
// Invisible/bouncing mode.
else
{
INT32 i;
boolean bonustime = false;
// Bouncy bouncy! if (!goalpost || !sparkle || !droneman)
mobj->angle += ANG10; break;
if (mobj->flags2 & MF2_DONTDRAW)
mobj->momz = 0;
else if (mobj->z <= mobj->floorz)
mobj->momz = 5*FRACUNIT;
for (i = 0; i < MAXPLAYERS; i++) // did NIGHTSDRONE position, scale, flip, or flags change? all elements need to be synced
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) droneboxmandiff = max(mobj->height - droneman->height, 0);
{ dronemangoaldiff = max(droneman->height - goalpost->height, 0);
bonustime = true;
break;
}
if (bonustime) if (!(goalpost->flags2 & MF2_OBJECTFLIP) && (mobj->flags2 & MF2_OBJECTFLIP))
{ {
mobj->z = mobj->floorz + mobj->height; goalpost->eflags |= MFE_VERTICALFLIP;
mobj->angle = mobj->momz = 0; goalpost->flags2 |= MF2_OBJECTFLIP;
sparkle->eflags |= MFE_VERTICALFLIP;
if (mobj->spawnpoint) sparkle->flags2 |= MF2_OBJECTFLIP;
mobj->z += (mobj->spawnpoint->options >> ZSHIFT)<<FRACBITS; droneman->eflags |= MFE_VERTICALFLIP;
droneman->flags2 |= MF2_OBJECTFLIP;
CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); flipchanged = true;
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);
} }
else if (!G_IsSpecialStage(gamemap)) else if ((goalpost->flags2 & MF2_OBJECTFLIP) && !(mobj->flags2 & MF2_OBJECTFLIP))
{ {
for (i = 0; i < MAXPLAYERS; i++) goalpost->eflags &= ~MFE_VERTICALFLIP;
if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE) 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; break;
} }
if (bonustime) if (bonustime)
mobj->flags2 &= ~MF2_DONTDRAW; {
else CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n");
mobj->flags2 |= MF2_DONTDRAW; 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; 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; mobj->fuse += 30 * TICRATE;
break; break;
case MT_NIGHTSDRONE: case MT_NIGHTSDRONE:
if (G_IsSpecialStage(gamemap))
mobj->flags2 |= MF2_DONTDRAW;
nummaprings = -1; // no perfect bonus, rings are free nummaprings = -1; // no perfect bonus, rings are free
break; break;
case MT_EGGCAPSULE: case MT_EGGCAPSULE:
mobj->extravalue1 = -1; // sphere timer for how long a player has been at the capsule mobj->reactiontime = 0;
mobj->extravalue2 = -1; // tic timer for how long a player has been at the capsule mobj->extravalue1 = mobj->cvmem =\
mobj->cusval = mobj->movecount =\
mobj->lastlook = mobj->extravalue2 = -1;
break; break;
case MT_REDTEAMRING: case MT_REDTEAMRING:
mobj->color = skincolor_redteam; 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. 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); mobj_t *idya = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_GOTEMERALD);
idya->health = 0; // for identification
P_SetTarget(&idya->target, mobj); P_SetTarget(&idya->target, mobj);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate); P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate);
P_SetTarget(&mobj->tracer, idya); P_SetTarget(&mobj->tracer, idya);
@ -10622,9 +10792,124 @@ ML_EFFECT4 : Don't clip inside the ground
mobj->health = mthing->angle & 255; mobj->health = mthing->angle & 255;
mobj->threshold = mthing->angle >> 8; mobj->threshold = mthing->angle >> 8;
break; break;
case MT_IDEYAANCHOR:
mobj->health = mthing->extrainfo;
break;
case MT_NIGHTSDRONE: 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; break;
case MT_HIVEELEMENTAL: case MT_HIVEELEMENTAL:
if (mthing->extrainfo) if (mthing->extrainfo)

View file

@ -58,6 +58,7 @@ typedef enum
FIRSTAXIS = 0x10, FIRSTAXIS = 0x10,
SECONDAXIS = 0x20, SECONDAXIS = 0x20,
FOLLOW = 0x40, FOLLOW = 0x40,
DRONE = 0x80,
} player_saveflags; } player_saveflags;
// //
@ -198,10 +199,10 @@ static void P_NetArchivePlayers(void)
WRITEINT32(save_p, players[i].drillmeter); WRITEINT32(save_p, players[i].drillmeter);
WRITEUINT8(save_p, players[i].drilldelay); WRITEUINT8(save_p, players[i].drilldelay);
WRITEUINT8(save_p, players[i].bonustime); WRITEUINT8(save_p, players[i].bonustime);
WRITEFIXED(save_p, players[i].oldscale);
WRITEUINT8(save_p, players[i].mare); WRITEUINT8(save_p, players[i].mare);
WRITEUINT8(save_p, players[i].marelap); WRITEUINT8(save_p, players[i].marelap);
WRITEUINT8(save_p, players[i].marebonuslap); WRITEUINT8(save_p, players[i].marebonuslap);
WRITEUINT32(save_p, players[i].marebegunat); WRITEUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].startedtime); WRITEUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime); WRITEUINT32(save_p, players[i].finishedtime);
@ -236,6 +237,9 @@ static void P_NetArchivePlayers(void)
if (players[i].followmobj) if (players[i].followmobj)
flags |= FOLLOW; flags |= FOLLOW;
if (players[i].drone)
flags |= DRONE;
WRITEINT16(save_p, players[i].lastsidehit); WRITEINT16(save_p, players[i].lastsidehit);
WRITEINT16(save_p, players[i].lastlinehit); WRITEINT16(save_p, players[i].lastlinehit);
@ -264,6 +268,9 @@ static void P_NetArchivePlayers(void)
if (flags & FOLLOW) if (flags & FOLLOW)
WRITEUINT32(save_p, players[i].followmobj->mobjnum); 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].camerascale);
WRITEFIXED(save_p, players[i].shieldscale); WRITEFIXED(save_p, players[i].shieldscale);
@ -396,10 +403,10 @@ static void P_NetUnArchivePlayers(void)
players[i].drillmeter = READINT32(save_p); players[i].drillmeter = READINT32(save_p);
players[i].drilldelay = READUINT8(save_p); players[i].drilldelay = READUINT8(save_p);
players[i].bonustime = (boolean)READUINT8(save_p); players[i].bonustime = (boolean)READUINT8(save_p);
players[i].oldscale = READFIXED(save_p);
players[i].mare = READUINT8(save_p); players[i].mare = READUINT8(save_p);
players[i].marelap = READUINT8(save_p); players[i].marelap = READUINT8(save_p);
players[i].marebonuslap = READUINT8(save_p); players[i].marebonuslap = READUINT8(save_p);
players[i].marebegunat = READUINT32(save_p); players[i].marebegunat = READUINT32(save_p);
players[i].startedtime = READUINT32(save_p); players[i].startedtime = READUINT32(save_p);
players[i].finishedtime = READUINT32(save_p); players[i].finishedtime = READUINT32(save_p);
@ -447,6 +454,9 @@ static void P_NetUnArchivePlayers(void)
if (flags & FOLLOW) if (flags & FOLLOW)
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p); 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].camerascale = READFIXED(save_p);
players[i].shieldscale = 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 // But also check for equality and return the matching index
static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap) static UINT32 CheckAddNetColormapToList(extracolormap_t *extra_colormap)
{ {
extracolormap_t *exc, *exc_prev; extracolormap_t *exc, *exc_prev = NULL;
UINT32 i = 0; UINT32 i = 0;
if (!net_colormaps) if (!net_colormaps)
@ -3670,6 +3680,13 @@ static void P_RelinkPointers(void)
if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp))) if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type); 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 #include "filesrch.h" // refreshdirmenu
// wipes #ifdef HAVE_BLUA
#include "f_finale.h" #include "lua_hud.h" // level title
#endif
#include "f_finale.h" // wipes
#include "md5.h" // map MD5 #include "md5.h" // map MD5
@ -100,6 +103,7 @@ side_t *sides;
mapthing_t *mapthings; mapthing_t *mapthings;
INT32 numstarposts; INT32 numstarposts;
boolean levelloading; boolean levelloading;
UINT8 levelfadecol;
// BLOCKMAP // BLOCKMAP
// Created from axis aligned bounding box // Created from axis aligned bounding box
@ -2296,7 +2300,7 @@ static void P_LevelInitStuff(void)
players[i].texttimer = players[i].linkcount =\ players[i].texttimer = players[i].linkcount =\
players[i].linktimer = players[i].flyangle =\ players[i].linktimer = players[i].flyangle =\
players[i].anotherflyangle = players[i].nightstime =\ 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].marebonuslap = players[i].lapbegunat =\
players[i].lapstartedtime = players[i].totalmarescore =\ players[i].lapstartedtime = players[i].totalmarescore =\
players[i].realtime = players[i].exiting = 0; 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 // 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 // function is being called we're just going to clobber the data anyways
players[i].mo = players[i].followmobj = players[i].awayviewmobj =\ 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 CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
// Reset the palette // Reset the palette
if (rendermode != render_none) if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL"); V_SetPaletteLump("PLAYPAL");
@ -2725,9 +2728,14 @@ boolean P_SetupLevel(boolean skipprecip)
// will be set by player think. // will be set by player think.
players[consoleplayer].viewz = 1; players[consoleplayer].viewz = 1;
// Cancel all d_main.c fadeouts (keep fade in though).
wipegamestate = -2;
// Special stage fade to white // Special stage fade to white
// This is handled BEFORE sounds are stopped. // 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 starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2; tic_t endtime = starttime + (3*TICRATE)/2;
@ -2760,11 +2768,12 @@ boolean P_SetupLevel(boolean skipprecip)
S_StopSounds(); S_StopSounds();
S_ClearSfx(); 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) if (!titlemapinaction)
{
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
S_Start(); S_Start();
}
// Let's fade to black here // Let's fade to black here
// But only if we didn't do the special stage wipe // But only if we didn't do the special stage wipe
@ -2783,20 +2792,31 @@ boolean P_SetupLevel(boolean skipprecip)
wipetypepre = -1; wipetypepre = -1;
} }
// Print "SPEEDING OFF TO [ZONE] [ACT 1]..." if (!titlemapinaction)
if (!titlemapinaction && rendermode != render_none)
{ {
// Don't include these in the fade! if (ranspecialwipe == 2)
char tx[64]; {
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to...")); pausedelay = -3; // preticker plus one
snprintf(tx, 63, "%s%s%s", S_StartSound(NULL, sfx_s3k73);
mapheaderinfo[gamemap-1]->lvlttl, }
(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : ""); // Print "SPEEDING OFF TO [ZONE] [ACT 1]..."
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx); if (rendermode != render_none)
I_UpdateNoVsync(); {
// 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 // Close text prompt before freeing the old level
F_EndTextPrompt(false, true); F_EndTextPrompt(false, true);
@ -3144,8 +3164,8 @@ boolean P_SetupLevel(boolean skipprecip)
P_MapEnd(); P_MapEnd();
// Remove the loading shit from the screen // Remove the loading shit from the screen
if (rendermode != render_none) if (rendermode != render_none && !titlemapinaction)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (ranspecialwipe) ? 0 : 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
if (precache || dedicated) if (precache || dedicated)
R_PrecacheLevel(); R_PrecacheLevel();
@ -3195,6 +3215,45 @@ boolean P_SetupLevel(boolean skipprecip)
#endif #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; return true;
} }

View file

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

View file

@ -634,6 +634,10 @@ static void P_DeNightserizePlayer(player_t *player)
break; break;
} }
if (player->mo->scale != player->oldscale)
player->mo->destscale = player->oldscale;
player->oldscale = 0;
// Restore from drowning music // Restore from drowning music
P_RestoreMusic(player); P_RestoreMusic(player);
@ -653,7 +657,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
return; return;
if (player->powers[pw_carry] != CR_NIGHTSMODE) 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->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->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; player->homing = 0;
@ -786,10 +793,13 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
// Don't show before title card // Don't show before title card
// Not consistency safe, but this only affects drawing // Not consistency safe, but this only affects drawing
if (timeinmap + 40 < 110) if (timeinmap + 40 < (110 - 70))
player->texttimer = (UINT8)(110 - timeinmap); 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 // force NiGHTS to face forward or backward
if (player->mo->target) 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 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) else if (maptol & TOL_NIGHTS)
player->mo->momz = 24*FRACUNIT; player->mo->momz = 18*FRACUNIT;
else if (player->powers[pw_super]) else if (player->powers[pw_super])
{ {
player->mo->momz = 13*FRACUNIT; 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) 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 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 P_SetObjectMomZ(player->mo, FixedMul(factor, player->mo->momz), false); // Custom height
// set just an eensy above the ground // 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) 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) <= 3*FRACUNIT)
if (abs(player->mo->x-player->capsule->x) <= 2*FRACUNIT)
{ {
P_UnsetThingPosition(player->mo); P_UnsetThingPosition(player->mo);
player->mo->x = player->capsule->x; player->mo->x = player->capsule->x;
@ -5972,7 +5984,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->mo->momx = 0; 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); P_UnsetThingPosition(player->mo);
player->mo->y = player->capsule->y; player->mo->y = player->capsule->y;
@ -5980,26 +5992,26 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->mo->momy = 0; 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->z = player->capsule->z+(player->capsule->height/3);
player->mo->momz = 0; player->mo->momz = 0;
} }
if (player->mo->x > player->capsule->x) 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) 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) 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) 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)) 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)) 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) 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); 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)) 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! { // 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->y == player->capsule->y
&& player->mo->z == player->capsule->z+(player->capsule->height/3)) && player->mo->z == player->capsule->z+(player->capsule->height/3))
{ {
if (player->spheres > 0) if (player->capsule->lastlook < 0)
{ {
player->spheres--; // Stretch the sphere deduction across the capsule time!
player->capsule->health--; // 1. Force the remaining capsule time to `popduration`
player->capsule->extravalue1++; // 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 popduration = player->capsule->extravalue1 = max(totalduration - tictimer, 1);
if (!(player->capsule->extravalue1 % 5)) 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), S_StartSound(P_SpawnMobj(player->capsule->x + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->y + ((P_SignedRandom()/2)<<FRACBITS), player->capsule->y + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS), player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS),
MT_BOSSEXPLODE),sfx_cybdth); 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) if (player->capsule->health <= 0)
{ {
player->capsule->flags &= ~MF_NOGRAVITY; player->capsule->flags &= ~MF_NOGRAVITY;
player->capsule->momz = 5*FRACUNIT; player->capsule->momz = 5*FRACUNIT;
player->capsule->reactiontime = 0; player->capsule->reactiontime = 0;
player->capsule->extravalue1 = player->capsule->extravalue2 = -1; tictimer = -1;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && !player->exiting && players[i].mare == player->mare) 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(); UINT8 em = P_GetNextEmerald();
// Only give it to ONE person, and THAT player has to get to the goal! // 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); 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_SetTarget(&emmo->target, player->mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&player->mo->tracer, emmo); 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); mobj_t *idya = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
idya->extravalue2 = player->mare/5; idya->extravalue2 = player->mare/5;
idya->health = player->mare + 1; // for identification
P_SetTarget(&idya->target, player->mo); P_SetTarget(&idya->target, player->mo);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate + ((player->mare + 1) % 5)); 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); P_SetTarget(&player->mo->tracer, idya);
} }
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -6122,19 +6208,68 @@ static void P_DoNiGHTSCapsule(player_t *player)
P_SwitchSpheresBonusMode(true); P_SwitchSpheresBonusMode(true);
P_RunNightsCapsuleTouchExecutors(player->mo, false, true); // run capsule exit executors, and we destroyed it P_RunNightsCapsuleTouchExecutors(player->mo, false, true); // run capsule exit executors, and we destroyed it
} }
} else
else {
{ S_StartScreamSound(player->mo, sfx_lose);
S_StartScreamSound(player->mo, sfx_lose); player->texttimer = 4*TICRATE;
player->texttimer = 4*TICRATE; player->textvar = 3; // Get more rings!
player->textvar = 3; // Get more rings! player->capsule->reactiontime = 0;
player->capsule->reactiontime = 0; player->capsule->extravalue1 = player->capsule->cvmem =\
player->capsule->extravalue1 = player->capsule->extravalue2 = -1; player->capsule->cusval = player->capsule->movecount =\
P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked rings 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 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; return;
} }
// Suck player into their drone
if (player->drone)
{
P_MoveNiGHTSToDrone(player);
return;
}
// Test revamped NiGHTS movement. // Test revamped NiGHTS movement.
if (player->powers[pw_carry] == CR_NIGHTSMODE) 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 // sets ideal cam pos
if (twodlevel || (mo->flags2 & MF2_TWOD)) if (twodlevel || (mo->flags2 & MF2_TWOD))
dist = 480<<FRACBITS; 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; dist = 320<<FRACBITS;
else else
{ {

View file

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

View file

@ -460,7 +460,8 @@ static void ST_DrawNightsOverlayNum(fixed_t x /* right border */, fixed_t y, fix
// Devmode information // Devmode information
static void ST_drawDebugInfo(void) 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)) if (!(stplyr->mo && cv_debug))
return; return;
@ -469,135 +470,135 @@ static void ST_drawDebugInfo(void)
if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dupx == 1) if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dupx == 1)
{ {
if (cv_debug & DBG_BASIC) textfunc = V_DrawRightAlignedString;
{ lowh = ((vid.height/vid.dupy) - 16);
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");
}
} }
else else
{ {
#define h 4 textfunc = V_DrawRightAlignedSmallString;
#define dist 2 h /= 2;
#define V_DrawDebugLine(str) V_DrawRightAlignedSmallString(320, height, VFLAGS, str);\ w /= 2;
height += h lowh = 0;
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;
}
} }
#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 V_DrawDebugLine
#undef dist
#undef h
#undef VFLAGS #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!!"); 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 *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *subttl = mapheaderinfo[gamemap-1]->subttl; char *subttl = mapheaderinfo[gamemap-1]->subttl;
@ -1131,7 +1132,7 @@ static void ST_drawLevelTitle(void)
INT32 lvlttly, zoney, lvlttlxpos, ttlnumxpos, zonexpos; INT32 lvlttly, zoney, lvlttlxpos, ttlnumxpos, zonexpos;
INT32 subttlxpos = BASEVIDWIDTH/2; INT32 subttlxpos = BASEVIDWIDTH/2;
if (!(timeinmap > 2 && timeinmap-3 < 110)) if (!(titletime > 2 && titletime-3 < 110))
return; return;
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2)); lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
@ -1151,22 +1152,22 @@ static void ST_drawLevelTitle(void)
#define MIDZONEY 105 #define MIDZONEY 105
#define MIDDIFF 4 #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); INT32 ttlh = V_LevelNameHeight(lvlttl);
zoney = (200<<FRACBITS) - ((200 - (MIDZONEY + MIDDIFF))*z); zoney = (200<<FRACBITS) - ((200 - (MIDZONEY + MIDDIFF))*z);
lvlttly = ((MIDTTLY + ttlh - MIDDIFF)*z) - (ttlh<<FRACBITS); 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; zoney = ((MIDZONEY + MIDDIFF)<<FRACBITS) - z;
lvlttly = ((MIDTTLY - MIDDIFF)<<FRACBITS) + z; lvlttly = ((MIDTTLY - MIDDIFF)<<FRACBITS) + z;
} }
else else
{ {
fixed_t z = ((timeinmap - 105)<<FRACBITS)/7; fixed_t z = ((titletime - 105)<<FRACBITS)/7;
INT32 zoneh = V_LevelNameHeight(M_GetText("ZONE")); INT32 zoneh = V_LevelNameHeight(M_GetText("ZONE"));
zoney = (MIDZONEY + zoneh - MIDDIFF)*(FRACUNIT - z) - (zoneh<<FRACBITS); zoney = (MIDZONEY + zoneh - MIDDIFF)*(FRACUNIT - z) - (zoneh<<FRACBITS);
lvlttly = ((MIDTTLY + MIDDIFF)<<FRACBITS) + ((200 - (MIDTTLY + MIDDIFF))*z); lvlttly = ((MIDTTLY + MIDDIFF)<<FRACBITS) + ((200 - (MIDTTLY + MIDDIFF))*z);
@ -1177,8 +1178,8 @@ static void ST_drawLevelTitle(void)
#undef MIDDIFF #undef MIDDIFF
#else #else
// There's no consistent algorithm that can accurately define the old positions // 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 // so I just ended up resorting to a single switch statement to define them
switch (timeinmap-3) switch (titletime-3)
{ {
case 0: zoney = 200; lvlttly = 0; break; case 0: zoney = 200; lvlttly = 0; break;
case 1: zoney = 188; lvlttly = 12; break; case 1: zoney = 188; lvlttly = 12; break;
@ -1509,7 +1510,7 @@ static void ST_drawNiGHTSLink(void)
else else
colornum = linkColor[mag][sel]; colornum = linkColor[mag][sel];
aflag |= ((stplyr->linktimer < nightslinktics/3) aflag |= ((stplyr->linktimer < (UINT32)nightslinktics/3)
? (9 - 9*stplyr->linktimer/(nightslinktics/3)) << V_ALPHASHIFT ? (9 - 9*stplyr->linktimer/(nightslinktics/3)) << V_ALPHASHIFT
: 0); : 0);
@ -1613,11 +1614,12 @@ static void ST_drawNiGHTSHUD(void)
#endif #endif
ST_DrawTopLeftOverlayPatch(16, 8, nbracket); ST_DrawTopLeftOverlayPatch(16, 8, nbracket);
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
ST_DrawTopLeftOverlayPatch(24, 16, (
#ifdef MANIASPHERES #ifdef MANIASPHERES
(stplyr->bonustime && (leveltime & 4)) ? nssbon : ST_DrawTopLeftOverlayPatch(24, 16, (
(stplyr->bonustime && (leveltime & 4)) ? nssbon : nsshud));
#else
ST_DrawTopLeftOverlayPatch(24, 16, (nsshud));
#endif #endif
nsshud));
else else
ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12))); ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12)));
@ -2461,12 +2463,14 @@ static void ST_overlayDrawer(void)
{ {
ST_drawFirstPersonHUD(); ST_drawFirstPersonHUD();
if (cv_powerupdisplay.value) if (cv_powerupdisplay.value)
ST_drawPowerupHUD(); ST_drawPowerupHUD(); // same as it ever was...
} }
else if (cv_powerupdisplay.value == 2) 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 #ifdef HAVE_BLUA
if (!(netgame || multiplayer) || !hu_showscores) if (!(netgame || multiplayer) || !hu_showscores)
@ -2479,7 +2483,7 @@ static void ST_overlayDrawer(void)
&& LUA_HudEnabled(hud_stagetitle) && LUA_HudEnabled(hud_stagetitle)
#endif #endif
) )
ST_drawLevelTitle(); ST_drawLevelTitle(timeinmap+70);
if (!hu_showscores && (netgame || multiplayer) if (!hu_showscores && (netgame || multiplayer)
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -2488,7 +2492,7 @@ static void ST_overlayDrawer(void)
) )
ST_drawTextHUD(); ST_drawTextHUD();
if (modeattacking) if (modeattacking && !(demoplayback && hu_showscores))
ST_drawInput(); ST_drawInput();
ST_drawDebugInfo(); ST_drawDebugInfo();

View file

@ -47,6 +47,9 @@ void ST_ReloadSkinFaceGraphics(void);
void ST_doPaletteStuff(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 // return if player a is in the same team as player b
boolean ST_SameTeam(player_t *a, player_t *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)) if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier 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); //CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
// //
// check if limit of active wadfiles // check if limit of active wadfiles
@ -360,9 +370,7 @@ UINT16 W_InitFile(const char *filename)
// see PutFileNeeded in d_netfil.c // see PutFileNeeded in d_netfil.c
if ((important = !W_VerifyNMUSlumps(filename))) if ((important = !W_VerifyNMUSlumps(filename)))
{ {
packetsize = packetsizetally; packetsize = packetsizetally + nameonlylength(filename) + 22;
packetsize += nameonlylength(filename) + 22;
if (packetsize > MAXFILENEEDED*sizeof(UINT8)) if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{ {

View file

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