Merge branch 'udmf-polyobjects' into udmf-lighting

This commit is contained in:
MascaraSnake 2021-12-03 19:22:37 +01:00
commit aee4996eba
59 changed files with 2105 additions and 1466 deletions

View file

@ -78,7 +78,7 @@ NONX86 = $(shell test "`echo $(CROSS_COMPILE_HOST) | grep 'i[3-6]86'`" || echo "
MAKEARGS = $(OS) $(NONX86) $(PREFIX) EXENAME=$(EXENAME) DBGNAME=$(DBGNAME) NOOBJDUMP=1 # SDL_PKGCONFIG=sdl2 PNG_PKGCONFIG=libpng
MENUFILE1 = ?package($(PACKAGE)):needs="X11" section="$(SECTION)"
MENUFILE2 = title="$(TITLE)" command="/$(PKGDIR)/$(PACKAGE)"
BINDIR := $(DIR)/bin/Linux/Release
BINDIR := $(DIR)/bin/
# FIXME pkg-config dir hacks
# Launchpad doesn't need this; it actually makes i386 builds fail due to cross-compile

View file

@ -776,7 +776,6 @@ linedeftypes
{
title = "Make FOF Bouncy";
prefix = "(76)";
flags16384text = "[14] Dampen";
}
}
@ -1999,7 +1998,7 @@ linedeftypes
title = "Set Tagged Sector's Floor Height/Texture";
prefix = "(400)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Keep floor flat";
flags64text = "[6] Don't change floor texture";
}
401
@ -2007,7 +2006,7 @@ linedeftypes
title = "Set Tagged Sector's Ceiling Height/Texture";
prefix = "(401)";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Keep floor flat";
flags64text = "[6] Don't change ceiling texture";
}
402
@ -2114,7 +2113,7 @@ linedeftypes
prefix = "(403)";
flags2text = "[1] Trigger linedef executor";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Change floor flat";
flags64text = "[6] Change floor texture";
}
404
@ -2123,7 +2122,7 @@ linedeftypes
prefix = "(404)";
flags2text = "[1] Trigger linedef executor";
flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Change ceiling flat";
flags64text = "[6] Change ceiling texture";
}
405

View file

@ -1979,12 +1979,6 @@ udmf
{
title = "Bounce strength";
}
arg2
{
title = "Dampen?";
type = 11;
enum = "noyes";
}
}
}

View file

@ -35,8 +35,6 @@ ifndef GCC295
WFLAGS+=-Wendif-labels
endif
ifdef GCC41
WFLAGS+=-Wdeclaration-after-statement
WFLAGS+=-Wno-error=declaration-after-statement
WFLAGS+=-Wshadow
endif
#WFLAGS+=-Wlarger-than-%len%

View file

@ -8,6 +8,11 @@ else
EXENAME?=srb2win64.exe
endif
# disable dynamicbase if under msys2
ifdef MSYSTEM
libs+=-Wl,--disable-dynamicbase
endif
sources+=win32/Srb2win.rc
opts+=-DSTDC_HEADERS
libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32

View file

@ -484,6 +484,19 @@ void CON_Init(void)
Unlock_state();
}
}
void CON_StartRefresh(void)
{
if (con_startup)
con_refresh = true;
}
void CON_StopRefresh(void)
{
if (con_startup)
con_refresh = false;
}
// Console input initialization
//
static void CON_InputInit(void)

View file

@ -16,6 +16,9 @@
void CON_Init(void);
void CON_StartRefresh(void);
void CON_StopRefresh(void);
boolean CON_Responder(event_t *ev);
#ifdef HAVE_THREADS

View file

@ -128,10 +128,14 @@ static UINT8 localtextcmd[MAXTEXTCMD];
static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen
static tic_t neededtic;
SINT8 servernode = 0; // the number of the server node
/// \brief do we accept new players?
/// \todo WORK!
boolean acceptnewnode = true;
static boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not
static tic_t firstconnectattempttime = 0;
// engine
// Must be a power of two
@ -511,18 +515,24 @@ static INT16 Consistancy(void);
typedef enum
{
CL_SEARCHING,
CL_CHECKFILES,
CL_DOWNLOADFILES,
CL_ASKJOIN,
CL_LOADFILES,
CL_WAITJOINRESPONSE,
CL_DOWNLOADSAVEGAME,
CL_CONNECTED,
CL_ABORTED
CL_ABORTED,
CL_ASKFULLFILELIST,
CL_CONFIRMCONNECT
} cl_mode_t;
static void GetPackets(void);
static cl_mode_t cl_mode = CL_SEARCHING;
static UINT16 cl_lastcheckedfilecount = 0; // used for full file list
#ifndef NONET
#define SNAKE_SPEED 5
@ -920,6 +930,8 @@ static void Snake_Draw(void)
INT16 i;
// Background
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawFlatFill(
SNAKE_LEFT_X + SNAKE_BORDER_SIZE,
SNAKE_TOP_Y + SNAKE_BORDER_SIZE,
@ -1021,6 +1033,13 @@ static void Snake_Draw(void)
);
}
static void CL_DrawConnectionStatusBox(void)
{
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
if (cl_mode != CL_CONFIRMCONNECT)
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
}
//
// CL_DrawConnectionStatus
//
@ -1031,28 +1050,32 @@ static inline void CL_DrawConnectionStatus(void)
INT32 ccstime = I_GetTime();
// Draw background fade
if (!menuactive) // menu already draws its own fade
V_DrawFadeScreen(0xFF00, 16); // force default
V_DrawFadeScreen(0xFF00, 16); // force default
// Draw the bottom box.
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
if (cl_mode != CL_DOWNLOADFILES)
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES)
{
INT32 i, animtime = ((ccstime / 4) & 15) + 16;
UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96;
// 15 pal entries total.
UINT8 palstart;
const char *cltext;
// Draw the bottom box.
CL_DrawConnectionStatusBox();
if (cl_mode == CL_SEARCHING)
palstart = 32; // Red
else if (cl_mode == CL_CONFIRMCONNECT)
palstart = 48; // Orange
else
palstart = 96; // Green
if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1))
for (i = 0; i < 16; ++i)
for (i = 0; i < 16; ++i) // 15 pal entries total.
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15));
switch (cl_mode)
{
case CL_DOWNLOADSAVEGAME:
if (lastfilenum != -1)
if (fileneeded && lastfilenum != -1)
{
UINT32 currentsize = fileneeded[lastfilenum].currentsize;
UINT32 totalsize = fileneeded[lastfilenum].totalsize;
@ -1076,9 +1099,22 @@ static inline void CL_DrawConnectionStatus(void)
else
cltext = M_GetText("Waiting to download game state...");
break;
case CL_ASKFULLFILELIST:
case CL_CHECKFILES:
cltext = M_GetText("Checking server addon list...");
break;
case CL_CONFIRMCONNECT:
cltext = "";
break;
case CL_LOADFILES:
cltext = M_GetText("Loading server addons...");
break;
case CL_ASKJOIN:
case CL_WAITJOINRESPONSE:
cltext = M_GetText("Requesting to join...");
if (serverisfull)
cltext = M_GetText("Server full, waiting for a slot...");
else
cltext = M_GetText("Requesting to join...");
break;
default:
cltext = M_GetText("Connecting to server...");
@ -1088,14 +1124,51 @@ static inline void CL_DrawConnectionStatus(void)
}
else
{
if (lastfilenum != -1)
if (cl_mode == CL_LOADFILES)
{
INT32 totalfileslength;
INT32 loadcompletednum = 0;
INT32 i;
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
//ima just count files here
if (fileneeded)
{
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_OPEN)
loadcompletednum++;
}
// Loading progress
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, "Loading server addons...");
totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256);
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, totalfileslength, 8, 96);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
}
else if (lastfilenum != -1)
{
INT32 dldlength;
static char tempname[28];
fileneeded_t *file = &fileneeded[lastfilenum];
char *filename = file->filename;
fileneeded_t *file;
char *filename;
Snake_Draw();
if (snake)
Snake_Draw();
// Draw the bottom box.
CL_DrawConnectionStatusBox();
if (fileneeded)
{
file = &fileneeded[lastfilenum];
filename = file->filename;
}
else
return;
Net_GetNetStat();
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
@ -1128,20 +1201,32 @@ static inline void CL_DrawConnectionStatus(void)
va("%3.1fK/s ", ((double)getbps)/1024));
}
else
{
if (snake)
Snake_Draw();
CL_DrawConnectionStatusBox();
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP,
M_GetText("Waiting to download files..."));
}
}
}
#endif
static boolean CL_AskFileList(INT32 firstfile)
{
netbuffer->packettype = PT_TELLFILESNEEDED;
netbuffer->u.filesneedednum = firstfile;
return HSendPacket(servernode, false, 0, sizeof (INT32));
}
/** Sends a special packet to declare how many players in local
* Used only in arbitratrenetstart()
* Sends a PT_CLIENTJOIN packet to the server
*
* \return True if the packet was successfully sent
* \todo Improve the description...
* Because to be honest, I have no idea what arbitratrenetstart is...
* Is it even used...?
*
*/
static boolean CL_SendJoin(void)
@ -1240,7 +1325,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
sizeof netbuffer->u.serverinfo.gametypename);
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated;
netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0);
strncpy(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME);
strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7);
@ -1275,7 +1360,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
if (mapheaderinfo[gamemap-1])
netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum;
p = PutFileNeeded();
p = PutFileNeeded(0);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
}
@ -1526,6 +1611,8 @@ static void CL_LoadReceivedSavegame(boolean reloading)
size_t length, decompressedlen;
char tmpsave[256];
FreeFileNeeded();
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
length = FIL_ReadFile(tmpsave, &savebuffer);
@ -1838,12 +1925,162 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
#endif // ifndef NONET
static const char * InvalidServerReason (INT32 i)
static void M_ConfirmConnect(event_t *ev)
{
#ifndef NONET
if (ev->type == ev_keydown)
{
if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)
{
if (totalfilesrequestednum > 0)
{
if (CL_SendFileRequest())
{
cl_mode = CL_DOWNLOADFILES;
Snake_Initialise();
}
}
else
cl_mode = CL_LOADFILES;
M_ClearMenus(true);
}
else if (ev->key == 'n' || ev->key == KEY_ESCAPE)
{
cl_mode = CL_ABORTED;
M_ClearMenus(true);
}
}
#else
(void)ev;
#endif
}
static boolean CL_FinishedFileList(void)
{
INT32 i;
char *downloadsize = NULL;
//CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
if (i == 4) // still checking ...
{
return true;
}
else if (i == 3) // too many files
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart SRB2 before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have the wrong addons loaded.\n\n"
"To play on this server, restart\n"
"the game and don't load any addons.\n"
"SRB2 will automatically add\n"
"everything you need when you join.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 1)
{
if (serverisfull)
{
M_StartMessage(M_GetText(
"This server is full!\n"
"\n"
"You may load server addons (if any), and wait for a slot.\n"
"\n"
"Press ENTER to continue\nor ESC to cancel.\n\n"
), M_ConfirmConnect, MM_EVENTHANDLER);
cl_mode = CL_CONFIRMCONNECT;
curfadevalue = 0;
}
else
cl_mode = CL_LOADFILES;
}
else
{
// must download something
// can we, though?
if (!CL_CheckDownloadable()) // nope!
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"An error occured when trying to\n"
"download missing addons.\n"
"(This is almost always a problem\n"
"with the server, not your game.)\n\n"
"See the console or log file\n"
"for additional details.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
#ifndef NONET
downloadcompletednum = 0;
downloadcompletedsize = 0;
totalfilesrequestednum = 0;
totalfilesrequestedsize = 0;
if (fileneeded == NULL)
I_Error("CL_FinishedFileList: fileneeded == NULL");
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
{
totalfilesrequestednum++;
totalfilesrequestedsize += fileneeded[i].totalsize;
}
if (totalfilesrequestedsize>>20 >= 100)
downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20));
else
downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10));
#endif
if (serverisfull)
M_StartMessage(va(M_GetText(
"This server is full!\n"
"Download of %s additional content\nis required to join.\n"
"\n"
"You may download, load server addons,\nand wait for a slot.\n"
"\n"
"Press ENTER to continue\nor ESC to cancel.\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
else
M_StartMessage(va(M_GetText(
"Download of %s additional content\nis required to join.\n"
"\n"
"Press ENTER to continue\nor ESC to cancel.\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
Z_Free(downloadsize);
cl_mode = CL_CONFIRMCONNECT;
curfadevalue = 0;
}
return true;
}
static const char * InvalidServerReason (serverinfo_pak *info)
{
#define EOT "\nPress ESC\n"
serverinfo_pak *info = &serverlist[i].info;
/* magic number for new packet format */
if (info->_255 != 255)
{
@ -1936,86 +2173,44 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
if (client)
{
const char *reason = InvalidServerReason(i);
serverinfo_pak *info = &serverlist[i].info;
// Quit here rather than downloading files
// and being refused later.
if (reason)
{
char *message = Z_StrDup(reason);
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(message, NULL, MM_NOTHING);
Z_Free(message);
return false;
}
D_ParseFileneeded(serverlist[i].info.fileneedednum,
serverlist[i].info.fileneeded);
CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
if (i == 3) // too many files
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart SRB2 before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have the wrong addons loaded.\n\n"
"To play on this server, restart\n"
"the game and don't load any addons.\n"
"SRB2 will automatically add\n"
"everything you need when you join.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 1)
cl_mode = CL_ASKJOIN;
if (info->refusereason == REFUSE_SLOTS_FULL)
serverisfull = true;
else
{
// must download something
// can we, though?
if (!CL_CheckDownloadable()) // nope!
const char *reason = InvalidServerReason(info);
// Quit here rather than downloading files
// and being refused later.
if (reason)
{
char *message = Z_StrDup(reason);
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You cannot connect to this server\n"
"because you cannot download the files\n"
"that you are missing from the server.\n\n"
"See the console or log file for\n"
"more details.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
M_StartMessage(message, NULL, MM_NOTHING);
Z_Free(message);
return false;
}
// no problem if can't send packet, we will retry later
if (CL_SendFileRequest())
{
cl_mode = CL_DOWNLOADFILES;
#ifndef NONET
Snake_Initialise();
#endif
}
}
D_ParseFileneeded(info->fileneedednum, info->fileneeded, 0);
if (info->flags & SV_LOTSOFADDONS)
{
cl_mode = CL_ASKFULLFILELIST;
cl_lastcheckedfilecount = 0;
return true;
}
cl_mode = CL_CHECKFILES;
}
else
{
cl_mode = CL_ASKJOIN; // files need not be checked for the server.
*asksent = 0;
}
return true;
}
@ -2061,6 +2256,22 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
return false;
break;
case CL_ASKFULLFILELIST:
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
cl_mode = CL_CHECKFILES;
else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent)
{
if (CL_AskFileList(fileneedednum))
{
cl_lastcheckedfilecount = fileneedednum;
*asksent = I_GetTime() + NEWTICRATE;
}
}
break;
case CL_CHECKFILES:
if (!CL_FinishedFileList())
return false;
break;
case CL_DOWNLOADFILES:
waitmore = false;
for (i = 0; i < fileneedednum; i++)
@ -2081,21 +2292,51 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
}
#endif
cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now
/* FALLTHRU */
cl_mode = CL_LOADFILES;
break;
case CL_LOADFILES:
if (CL_LoadServerFiles())
{
FreeFileNeeded();
*asksent = 0; //This ensure the first join ask is right away
firstconnectattempttime = I_GetTime();
cl_mode = CL_ASKJOIN;
}
break;
case CL_ASKJOIN:
CL_LoadServerFiles();
if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime() && !server)
{
CONS_Printf(M_GetText("5 minute wait time exceeded.\n"));
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"5 minute wait time exceeded.\n"
"You may retry connection.\n"
"\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
#ifndef NONET
// prepare structures to save the file
// WARNING: this can be useless in case of server not in GS_LEVEL
// but since the network layer doesn't provide ordered packets...
CL_PrepareDownloadSaveGame(tmpsave);
#endif
if (CL_SendJoin())
if (I_GetTime() >= *asksent && CL_SendJoin())
{
*asksent = I_GetTime() + NEWTICRATE*3;
cl_mode = CL_WAITJOINRESPONSE;
}
break;
case CL_WAITJOINRESPONSE:
if (I_GetTime() >= *asksent)
{
cl_mode = CL_ASKJOIN;
}
break;
#ifndef NONET
case CL_DOWNLOADSAVEGAME:
// At this state, the first (and only) needed file is the gamestate
@ -2109,8 +2350,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
break;
#endif
case CL_WAITJOINRESPONSE:
case CL_CONNECTED:
case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect
default:
break;
@ -2118,7 +2359,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
case CL_ABORTED:
cl_mode = CL_SEARCHING;
return false;
}
GetPackets();
@ -2128,13 +2368,19 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (*oldtic != I_GetTime())
{
I_OsPolling();
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
G_MapEventsToControls(&events[eventtail]);
if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1])
if (cl_mode == CL_CONFIRMCONNECT)
D_ProcessEvents(); //needed for menu system to receive inputs
else
{
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
G_MapEventsToControls(&events[eventtail]);
}
if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED)
{
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
#ifndef NONET
if (snake)
@ -2167,13 +2413,20 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
#ifndef NONET
if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
{
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME)
if (!snake)
{
F_MenuPresTicker(true); // title sky
F_TitleScreenTicker(true);
F_TitleScreenDrawer();
}
CL_DrawConnectionStatus();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); //Needed for drawing messageboxes on the connection screen
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_UpdateNoVsync(); // page flip or blit buffer
if (moviemode)
M_SaveFrame();
@ -2235,8 +2488,10 @@ static void CL_ConnectToServer(void)
ClearAdminPlayers();
pnumnodes = 1;
oldtic = I_GetTime() - 1;
#ifndef NONET
asksent = (tic_t) - TICRATE;
firstconnectattempttime = I_GetTime();
i = SL_SearchServer(servernode);
@ -2676,8 +2931,16 @@ void CL_Reset(void)
SV_ResetServer();
// make sure we don't leave any fileneeded gunk over from a failed join
FreeFileNeeded();
fileneedednum = 0;
memset(fileneeded, 0, sizeof(fileneeded));
#ifndef NONET
totalfilesrequestednum = 0;
totalfilesrequestedsize = 0;
#endif
firstconnectattempttime = 0;
serverisfull = false;
connectiontimeout = (tic_t)cv_nettimeout.value; //reset this temporary hack
// D_StartTitle should get done now, but the calling function will handle it
}
@ -2932,6 +3195,34 @@ static void Command_Kick(void)
else
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
}
static void Command_ResendGamestate(void)
{
SINT8 playernum;
if (COM_Argc() == 1)
{
CONS_Printf(M_GetText("resendgamestate <playername/playernum>: resend the game state to a player\n"));
return;
}
else if (client)
{
CONS_Printf(M_GetText("Only the server can use this.\n"));
return;
}
playernum = nametonum(COM_Argv(1));
if (playernum == -1 || playernum == 0)
return;
// Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
if (!HSendPacket(playernode[playernum], true, 0, 0))
{
CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n"));
return;
}
}
#endif
static void Got_KickCmd(UINT8 **p, INT32 playernum)
@ -3139,34 +3430,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_RemovePlayer(pnum, kickreason);
}
static void Command_ResendGamestate(void)
{
SINT8 playernum;
if (COM_Argc() == 1)
{
CONS_Printf(M_GetText("resendgamestate <playername/playernum>: resend the game state to a player\n"));
return;
}
else if (client)
{
CONS_Printf(M_GetText("Only the server can use this.\n"));
return;
}
playernum = nametonum(COM_Argv(1));
if (playernum == -1 || playernum == 0)
return;
// Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
if (!HSendPacket(playernode[playernum], true, 0, 0))
{
CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n"));
return;
}
}
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL);
@ -3189,7 +3452,7 @@ consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_
consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
// Speed of file downloading (in packets per tic)
static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}};
static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL);
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
@ -3903,6 +4166,7 @@ static void HandleServerInfo(SINT8 node)
static void PT_WillResendGamestate(void)
{
#ifndef NONET
char tmpsave[256];
if (server || cl_redownloadinggamestate)
@ -3925,10 +4189,12 @@ static void PT_WillResendGamestate(void)
CL_PrepareDownloadSaveGame(tmpsave);
cl_redownloadinggamestate = true;
#endif
}
static void PT_CanReceiveGamestate(SINT8 node)
{
#ifndef NONET
if (client || sendingsavegame[node])
return;
@ -3936,6 +4202,9 @@ static void PT_CanReceiveGamestate(SINT8 node)
SV_SendSaveGame(node, true); // Resend a complete game state
resendingsavegame[node] = true;
#else
(void)node;
#endif
}
/** Handles a packet received from a node that isn't in game
@ -3962,31 +4231,40 @@ static void HandlePacketFromAwayNode(SINT8 node)
switch (netbuffer->packettype)
{
case PT_ASKINFOVIAMS:
#if 0
Net_CloseConnection(node);
break;
case PT_TELLFILESNEEDED:
if (server && serverrunning)
{
INT32 clientnode;
if (ms_RoomId < 0) // ignore if we're not actually on the MS right now
{
Net_CloseConnection(node); // and yes, close connection
return;
}
clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
if (clientnode != -1)
{
SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
SV_SendPlayerInfo(clientnode); // Send extra info
Net_CloseConnection(clientnode);
// Don't close connection to MS...
}
else
Net_CloseConnection(node); // ...unless the IP address is not valid
UINT8 *p;
INT32 firstfile = netbuffer->u.filesneedednum;
netbuffer->packettype = PT_MOREFILESNEEDED;
netbuffer->u.filesneededcfg.first = firstfile;
netbuffer->u.filesneededcfg.more = 0;
p = PutFileNeeded(firstfile);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
}
else // Shouldn't get this if you aren't the server...?
Net_CloseConnection(node);
break;
case PT_MOREFILESNEEDED:
if (server && serverrunning)
{ // But wait I thought I'm the server?
Net_CloseConnection(node);
break;
}
SERVERONLY
if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum)
{
D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first);
if (!netbuffer->u.filesneededcfg.more)
cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list
}
else
Net_CloseConnection(node); // you're not supposed to get it, so ignore it
#else
Net_CloseConnection(node);
#endif
break;
case PT_ASKINFO:
@ -4012,13 +4290,24 @@ static void HandlePacketFromAwayNode(SINT8 node)
if (!reason)
I_Error("Out of memory!\n");
D_QuitNetGame();
CL_Reset();
D_StartTitle();
if (strstr(reason, "Maximum players reached"))
{
serverisfull = true;
//Special timeout for when refusing due to player cap. The client will wait 3 seconds between join requests when waiting for a slot, so we need this to be much longer
//We set it back to the value of cv_nettimeout.value in CL_Reset
connectiontimeout = NEWTICRATE*7;
cl_mode = CL_ASKJOIN;
free(reason);
break;
}
M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
reason), NULL, MM_NOTHING);
D_QuitNetGame();
CL_Reset();
D_StartTitle();
free(reason);
// Will be reset by caller. Signals refusal.
@ -4222,8 +4511,10 @@ static void HandlePacketFromPlayer(SINT8 node)
// Check player consistancy during the level
if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL
&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()
&& !SV_ResendingSavegameToAnyone())
#ifndef NONET
&& !SV_ResendingSavegameToAnyone()
#endif
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime())
{
if (cv_resynchattempts.value)
{
@ -4974,16 +5265,23 @@ void TryRunTics(tic_t realtics)
// run the count * tics
while (neededtic > gametic)
{
boolean update_stats = !(paused || P_AutoPause());
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
ps_tictime = I_GetPreciseTime();
if (update_stats)
PS_START_TIMING(ps_tictime);
G_Ticker((gametic % NEWTICRATERATIO) == 0);
ExtraDataTicker();
gametic++;
consistancy[gametic%BACKUPTICS] = Consistancy();
ps_tictime = I_GetPreciseTime() - ps_tictime;
if (update_stats)
{
PS_STOP_TIMING(ps_tictime);
PS_UpdateTickStats();
}
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
@ -5127,9 +5425,11 @@ void NetUpdate(void)
if (client)
{
#ifndef NONET
// If the client just finished redownloading the game state, load it
if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND)
CL_ReloadReceivedSavegame();
#endif
CL_SendClientCmd(); // Send tic cmd
hu_redownloadinggamestate = cl_redownloadinggamestate;

View file

@ -94,6 +94,9 @@ typedef enum
PT_LOGIN, // Login attempt from the client.
PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?"
PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)"
PT_PING, // Packet sent to tell clients the other client's latency to server.
NUMPACKETTYPE
} packettype_t;
@ -198,6 +201,9 @@ typedef struct
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
} ATTRPACK clientconfig_pak;
#define SV_DEDICATED 0x40 // server is dedicated
#define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil
enum {
REFUSE_JOINS_DISABLED = 1,
REFUSE_SLOTS_FULL,
@ -225,7 +231,7 @@ typedef struct
char gametypename[24];
UINT8 modifiedgame;
UINT8 cheatsenabled;
UINT8 isdedicated;
UINT8 flags;
UINT8 fileneedednum;
tic_t time;
tic_t leveltime;
@ -279,6 +285,14 @@ typedef struct
UINT8 ctfteam;
} ATTRPACK plrconfig;
typedef struct
{
INT32 first;
UINT8 num;
UINT8 more;
UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK filesneededconfig_pak;
//
// Network packet data
//
@ -308,6 +322,8 @@ typedef struct
msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
INT32 filesneedednum; // 4 bytes
filesneededconfig_pak filesneededcfg; // ??? bytes
UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
} u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t;

View file

@ -65,7 +65,7 @@
#include "m_cond.h" // condition initialization
#include "fastcmp.h"
#include "keys.h"
#include "filesrch.h" // refreshdirmenu, mainwadstally
#include "filesrch.h" // refreshdirmenu
#include "g_input.h" // tutorial mode control scheming
#include "m_perfstats.h"
@ -96,11 +96,8 @@ int SUBVERSION;
// platform independant focus loss
UINT8 window_notinfocus = false;
//
// DEMO LOOP
//
static char *startupwadfiles[MAX_WADFILES];
static char *startuppwads[MAX_WADFILES];
static addfilelist_t startupwadfiles;
static addfilelist_t startuppwads;
boolean devparm = false; // started game with -devparm
@ -119,6 +116,9 @@ boolean midi_disabled = false;
boolean sound_disabled = false;
boolean digital_disabled = false;
//
// DEMO LOOP
//
boolean advancedemo;
#ifdef DEBUGFILE
INT32 debugload = 0;
@ -272,7 +272,7 @@ void D_ProcessEvents(void)
if (eaten)
continue; // ate the event
if (!hooked && G_LuaResponder(ev))
if (!hooked && !CON_Ready() && G_LuaResponder(ev))
continue;
G_Responder(ev);
@ -476,7 +476,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value)
{
ps_rendercalltime = I_GetPreciseTime();
PS_START_TIMING(ps_rendercalltime);
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
@ -523,7 +523,7 @@ static void D_Display(void)
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime;
PS_STOP_TIMING(ps_rendercalltime);
}
if (lastdraw)
@ -537,7 +537,7 @@ static void D_Display(void)
lastdraw = false;
}
ps_uitime = I_GetPreciseTime();
PS_START_TIMING(ps_uitime);
if (gamestate == GS_LEVEL)
{
@ -550,7 +550,7 @@ static void D_Display(void)
}
else
{
ps_uitime = I_GetPreciseTime();
PS_START_TIMING(ps_uitime);
}
}
@ -592,7 +592,7 @@ static void D_Display(void)
CON_Drawer();
ps_uitime = I_GetPreciseTime() - ps_uitime;
PS_STOP_TIMING(ps_uitime);
//
// wipe update
@ -678,9 +678,9 @@ static void D_Display(void)
M_DrawPerfStats();
}
ps_swaptime = I_GetPreciseTime();
PS_START_TIMING(ps_swaptime);
I_FinishUpdate(); // page flip or blit buffer
ps_swaptime = I_GetPreciseTime() - ps_swaptime;
PS_STOP_TIMING(ps_swaptime);
}
}
@ -923,51 +923,68 @@ void D_StartTitle(void)
tutorialmode = false;
}
//
// D_AddFile
//
static void D_AddFile(char **list, const char *file)
{
size_t pnumwadfiles;
char *newfile;
#define REALLOC_FILE_LIST \
if (list->files == NULL) \
{ \
list->files = calloc(sizeof(list->files), 2); \
list->numfiles = 1; \
} \
else \
{ \
index = list->numfiles; \
list->files = realloc(list->files, sizeof(list->files) * ((++list->numfiles) + 1)); \
if (list->files == NULL) \
I_Error("%s: No more free memory to add file %s", __FUNCTION__, file); \
}
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
;
static void D_AddFile(addfilelist_t *list, const char *file)
{
char *newfile;
size_t index = 0;
REALLOC_FILE_LIST
newfile = malloc(strlen(file) + 1);
if (!newfile)
I_Error("No more free memory to AddFile %s",file);
I_Error("D_AddFile: No more free memory to add file %s", file);
strcpy(newfile, file);
list[pnumwadfiles] = newfile;
list->files[index] = newfile;
}
static void D_AddFolder(char **list, const char *file)
static void D_AddFolder(addfilelist_t *list, const char *file)
{
size_t pnumwadfiles;
char *newfile;
size_t index = 0;
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
;
REALLOC_FILE_LIST
newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator
if (!newfile)
I_Error("No more free memory to AddFolder %s",file);
I_Error("D_AddFolder: No more free memory to add folder %s", file);
strcpy(newfile, file);
strcat(newfile, PATHSEP);
list[pnumwadfiles] = newfile;
list->files[index] = newfile;
}
static inline void D_CleanFile(char **list)
#undef REALLOC_FILE_LIST
static inline void D_CleanFile(addfilelist_t *list)
{
size_t pnumwadfiles;
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
if (list->files)
{
free(list[pnumwadfiles]);
list[pnumwadfiles] = NULL;
size_t pnumwadfiles = 0;
for (; pnumwadfiles < list->numfiles; pnumwadfiles++)
free(list->files[pnumwadfiles]);
free(list->files);
list->files = NULL;
}
list->numfiles = 0;
}
///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so.
@ -1051,7 +1068,7 @@ static void IdentifyVersion(void)
// Load the IWAD
if (srb2wad != NULL && FIL_ReadFileOK(srb2wad))
D_AddFile(startupwadfiles, srb2wad);
D_AddFile(&startupwadfiles, srb2wad);
else
I_Error("srb2.pk3 not found! Expected in %s, ss file: %s\n", srb2waddir, srb2wad);
@ -1062,14 +1079,14 @@ static void IdentifyVersion(void)
// checking in D_SRB2Main
// Add the maps
D_AddFile(startupwadfiles, va(pandf,srb2waddir,"zones.pk3"));
D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "zones.pk3"));
// Add the players
D_AddFile(startupwadfiles, va(pandf,srb2waddir, "player.dta"));
D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "player.dta"));
#ifdef USE_PATCH_DTA
// Add our crappy patches to fix our bugs
D_AddFile(startupwadfiles, va(pandf,srb2waddir,"patch.pk3"));
D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "patch.pk3"));
#endif
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -1079,7 +1096,7 @@ static void IdentifyVersion(void)
const char *musicpath = va(pandf,srb2waddir,str);\
int ms = W_VerifyNMUSlumps(musicpath, false); \
if (ms == 1) \
D_AddFile(startupwadfiles, musicpath); \
D_AddFile(&startupwadfiles, musicpath); \
else if (ms == 0) \
I_Error("File "str" has been modified with non-music/sound lumps"); \
}
@ -1269,9 +1286,9 @@ void D_SRB2Main(void)
else if (myargv[i][0] == '-' || myargv[i][0] == '+')
addontype = 0;
else if (addontype == 1)
D_AddFile(startuppwads, myargv[i]);
D_AddFile(&startuppwads, myargv[i]);
else if (addontype == 2)
D_AddFolder(startuppwads, myargv[i]);
D_AddFolder(&startuppwads, myargv[i]);
}
}
@ -1310,8 +1327,8 @@ void D_SRB2Main(void)
// load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
W_InitMultipleFiles(startupwadfiles);
D_CleanFile(startupwadfiles);
W_InitMultipleFiles(&startupwadfiles);
D_CleanFile(&startupwadfiles);
#ifndef DEVELOP // md5s last updated 22/02/20 (ddmmyy)
@ -1326,8 +1343,6 @@ void D_SRB2Main(void)
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
#endif //ifndef DEVELOP
mainwadstally = packetsizetally; // technically not accurate atm, remember to port the two-stage -file process from kart in 2.2.x
cht_Init();
//---------------------------------------------------- READY SCREEN
@ -1358,9 +1373,16 @@ void D_SRB2Main(void)
I_RegisterSysCommands();
CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n");
W_InitMultipleFiles(startuppwads);
D_CleanFile(startuppwads);
CON_StopRefresh(); // Temporarily stop refreshing the screen for wad loading
if (startuppwads.numfiles)
{
CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n");
W_InitMultipleFiles(&startuppwads);
D_CleanFile(&startuppwads);
}
CON_StartRefresh(); // Restart the refresh!
CONS_Printf("HU_LoadGraphics()...\n");
HU_LoadGraphics();

View file

@ -815,6 +815,8 @@ static const char *packettypename[NUMPACKETTYPE] =
"CLIENTJOIN",
"NODETIMEOUT",
"LOGIN",
"TELLFILESNEEDED",
"MOREFILESNEEDED",
"PING"
};

View file

@ -47,6 +47,7 @@
#include "m_cond.h"
#include "m_anigif.h"
#include "md5.h"
#include "m_perfstats.h"
#ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR
@ -374,7 +375,14 @@ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL)
static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange);
static CV_PossibleValue_t ps_samplesize_cons_t[] = {
{1, "MIN"}, {1000, "MAX"}, {0, NULL}};
consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "1", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange);
static CV_PossibleValue_t ps_descriptor_cons_t[] = {
{1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}};
consvar_t cv_ps_descriptor = CVAR_INIT ("ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL);
consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL);
char timedemo_name[256];
@ -867,6 +875,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_soundtest);
CV_RegisterVar(&cv_perfstats);
CV_RegisterVar(&cv_ps_samplesize);
CV_RegisterVar(&cv_ps_descriptor);
// ingame object placing
COM_AddCommand("objectplace", Command_ObjectPlace_f);
@ -3223,7 +3233,7 @@ static void Command_RunSOC(void)
static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
{
char filename[256];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
@ -3347,10 +3357,9 @@ static void Command_Addfile(void)
break;
++p;
// check total packet size and no of files currently loaded
// See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
// check no of files currently loaded
// See W_LoadWadFile in w_wad.c
if (numwadfiles >= MAX_WADFILES)
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
@ -3379,6 +3388,9 @@ static void Command_Addfile(void)
for (i = 0; i < numwadfiles; i++)
{
if (wadfiles[i]->type == RET_FOLDER)
continue;
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
@ -3469,10 +3481,9 @@ static void Command_Addfolder(void)
continue;
}
// check total packet size and no of files currently loaded
// See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + strlen(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
// check no of files currently loaded
// See W_LoadWadFile in w_wad.c
if (numwadfiles >= MAX_WADFILES)
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
@ -3534,7 +3545,7 @@ static void Command_Addfolder(void)
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16];
boolean kick = false;
boolean toomany = false;
@ -3559,9 +3570,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
return;
}
// See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename,md5sum,true);
@ -3594,7 +3603,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
{
char path[241];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
boolean kick = false;
boolean toomany = false;
INT32 i,j;
@ -3619,9 +3628,7 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
return;
}
// See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + strlen(path) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfolder(path);
@ -3652,7 +3659,7 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16];
READSTRINGN(*cp, filename, 240);
@ -3700,7 +3707,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum)
{
char path[241];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
READSTRINGN(*cp, path, 240);
@ -3744,7 +3751,13 @@ static void Command_ListWADS_f(void)
{
INT32 i = numwadfiles;
char *tempname;
CONS_Printf(M_GetText("There are %d wads loaded:\n"),numwadfiles);
#ifdef ENFORCE_WAD_LIMIT
CONS_Printf(M_GetText("There are %d/%d files loaded:\n"),numwadfiles,MAX_WADFILES);
#else
CONS_Printf(M_GetText("There are %d files loaded:\n"),numwadfiles);
#endif
for (i--; i >= 0; i--)
{
nameonly(tempname = va("%s", wadfiles[i]->filename));

View file

@ -73,6 +73,7 @@ extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange;
extern consvar_t cv_netstat;
extern consvar_t cv_nettimeout;
extern consvar_t cv_countdowntime;
extern consvar_t cv_runscripts;
@ -110,6 +111,8 @@ extern consvar_t cv_skipmapcheck;
extern consvar_t cv_sleep;
extern consvar_t cv_perfstats;
extern consvar_t cv_ps_samplesize;
extern consvar_t cv_ps_descriptor;
extern char timedemo_name[256];
extern boolean timedemo_csv;

View file

@ -52,7 +52,7 @@
#include <errno.h>
// Prototypes
static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid);
static boolean AddFileToSendQueue(INT32 node, UINT8 fileid);
// Sender structure
typedef struct filetx_s
@ -87,7 +87,7 @@ static filetran_t transfer[MAXNETNODES];
// Receiver structure
INT32 fileneedednum; // Number of files needed to join the server
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
fileneeded_t *fileneeded; // List of needed files
static tic_t lasttimeackpacketsent = 0;
char downloaddir[512] = "DOWNLOAD";
@ -105,6 +105,10 @@ static pauseddownload_t *pauseddownload = NULL;
#ifndef NONET
// for cl loading screen
INT32 lastfilenum = -1;
INT32 downloadcompletednum = 0;
UINT32 downloadcompletedsize = 0;
INT32 totalfilesrequestednum = 0;
UINT32 totalfilesrequestedsize = 0;
#endif
luafiletransfer_t *luafiletransfers = NULL;
@ -113,25 +117,62 @@ boolean waitingforluafilecommand = false;
char luafiledir[256 + 16] = "luafiles";
static UINT16 GetWadNumFromFileNeededId(UINT8 id)
{
UINT16 wadnum;
for (wadnum = mainwads; wadnum < numwadfiles; wadnum++)
{
if (!wadfiles[wadnum]->important)
continue;
if (id == 0)
return wadnum;
id--;
}
return UINT16_MAX;
}
/** Fills a serverinfo packet with information about wad files loaded.
*
* \todo Give this function a better name since it is in global scope.
* Used to have size limiting built in - now handled via W_InitFile in w_wad.c
*
*/
UINT8 *PutFileNeeded(void)
UINT8 *PutFileNeeded(UINT16 firstfile)
{
size_t i, count = 0;
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
size_t i;
UINT8 count = 0;
UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded;
UINT8 *p = p_start;
char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus, folder;
for (i = 0; i < numwadfiles; i++)
for (i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad
{
// If it has only music/sound lumps, don't put it in the list
if (!wadfiles[i]->important)
continue;
if (firstfile)
{ // Skip files until we reach the first file.
firstfile--;
continue;
}
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
// Look below at the WRITE macros to understand what these numbers mean.
if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED)
{
// Too many files to send all at once
if (netbuffer->packettype == PT_MOREFILESNEEDED)
netbuffer->u.filesneededcfg.more = 1;
else
netbuffer->u.serverinfo.flags |= SV_LOTSOFADDONS;
break;
}
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
folder = (wadfiles[i]->type == RET_FOLDER);
@ -148,32 +189,53 @@ UINT8 *PutFileNeeded(void)
count++;
WRITEUINT32(p, wadfiles[i]->filesize);
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
WRITESTRINGN(p, wadfilename, MAX_WADPATH);
WRITEMEM(p, wadfiles[i]->md5sum, 16);
}
netbuffer->u.serverinfo.fileneedednum = (UINT8)count;
if (netbuffer->packettype == PT_MOREFILESNEEDED)
netbuffer->u.filesneededcfg.num = count;
else
netbuffer->u.serverinfo.fileneedednum = count;
return p;
}
void AllocFileNeeded(INT32 size)
{
if (fileneeded == NULL)
fileneeded = Z_Calloc(sizeof(fileneeded_t) * size, PU_STATIC, NULL);
else
fileneeded = Z_Realloc(fileneeded, sizeof(fileneeded_t) * size, PU_STATIC, NULL);
}
void FreeFileNeeded(void)
{
Z_Free(fileneeded);
fileneeded = NULL;
}
/** Parses the serverinfo packet and fills the fileneeded table on client
*
* \param fileneedednum_parm The number of files needed to join the server
* \param fileneededstr The memory block containing the list of needed files
*
*/
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile)
{
INT32 i;
UINT8 *p;
UINT8 filestatus;
fileneedednum = fileneedednum_parm;
fileneedednum = firstfile + fileneedednum_parm;
p = (UINT8 *)fileneededstr;
for (i = 0; i < fileneedednum; i++)
AllocFileNeeded(fileneedednum);
for (i = firstfile; i < fileneedednum; i++)
{
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
fileneeded[i].type = FILENEEDED_WAD;
fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet
fileneeded[i].justdownloaded = false;
filestatus = READUINT8(p); // The first byte is the file status
fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag
@ -191,7 +253,11 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
lastfilenum = -1;
#endif
FreeFileNeeded();
AllocFileNeeded(1);
fileneedednum = 1;
fileneeded[0].type = FILENEEDED_SAVEGAME;
fileneeded[0].status = FS_REQUESTED;
fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX;
@ -322,14 +388,18 @@ boolean CL_SendFileRequest(void)
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
{
totalfreespaceneeded += fileneeded[i].totalsize;
nameonly(fileneeded[i].filename);
WRITEUINT8(p, i); // fileid
WRITESTRINGN(p, fileneeded[i].filename, MAX_WADPATH);
// put it in download dir
nameonly(fileneeded[i].filename);
strcatbf(fileneeded[i].filename, downloaddir, "/");
fileneeded[i].status = FS_REQUESTED;
}
WRITEUINT8(p, 0xFF);
I_GetDiskFreeSpace(&availablefreespace);
if (totalfreespaceneeded > availablefreespace)
I_Error("To play on this server you must download %s KB,\n"
@ -345,21 +415,22 @@ boolean CL_SendFileRequest(void)
// returns false if a requested file was not found or cannot be sent
boolean PT_RequestFile(INT32 node)
{
char wad[MAX_WADPATH+1];
UINT8 *p = netbuffer->u.textcmd;
UINT8 id;
while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow
{
id = READUINT8(p);
if (id == 0xFF)
break;
READSTRINGN(p, wad, MAX_WADPATH);
if (!AddFileToSendQueue(node, wad, id))
if (!AddFileToSendQueue(node, id))
{
SV_AbortSendFiles(node);
return false; // don't read the rest of the files
}
}
return true; // no problems with any files
}
@ -368,23 +439,16 @@ boolean PT_RequestFile(INT32 node)
* \return 0 if some files are missing
* 1 if all files exist
* 2 if some already loaded files are not requested or are in a different order
* 3 too many files, over WADLIMIT
* 4 still checking, continuing next tic
*
*/
INT32 CL_CheckFiles(void)
{
INT32 i, j;
char wadfilename[MAX_WADPATH];
INT32 ret = 1;
size_t packetsize = 0;
size_t filestoget = 0;
// if (M_CheckParm("-nofiles"))
// return 1;
// the first is the iwad (the main wad file)
// we don't care if it's called srb2.pk3 or not.
// Never download the IWAD, just assume it's there and identical
fileneeded[0].status = FS_OPEN;
size_t filestoload = 0;
boolean downloadrequired = false;
// Modified game handling -- check for an identical file list
// must be identical in files loaded AND in order
@ -392,7 +456,7 @@ INT32 CL_CheckFiles(void)
if (modifiedgame)
{
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;)
{
if (j < numwadfiles && !wadfiles[j]->important)
{
@ -419,15 +483,21 @@ INT32 CL_CheckFiles(void)
return 1;
}
// See W_InitFile in w_wad.c
packetsize = packetsizetally;
for (i = 1; i < fileneedednum; i++)
for (i = 0; i < fileneedednum; i++)
{
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
downloadrequired = true;
if (fileneeded[i].status != FS_OPEN)
filestoload++;
if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics
continue;
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
// Check in already loaded files
for (j = 1; wadfiles[j]; j++)
for (j = mainwads; wadfiles[j]; j++)
{
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) &&
@ -435,43 +505,34 @@ INT32 CL_CheckFiles(void)
{
CONS_Debug(DBG_NETPLAY, "already loaded\n");
fileneeded[i].status = FS_OPEN;
break;
return 4;
}
}
if (fileneeded[i].status != FS_NOTFOUND)
continue;
if (fileneeded[i].folder)
packetsize += strlen(fileneeded[i].filename) + FILENEEDEDSIZE;
else
packetsize += nameonlylength(fileneeded[i].filename) + FILENEEDEDSIZE;
if ((numwadfiles+filestoget >= MAX_WADFILES)
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
return 3;
filestoget++;
if (fileneeded[i].folder)
fileneeded[i].status = findfolder(fileneeded[i].filename);
else
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
if (fileneeded[i].status != FS_FOUND)
ret = 0;
return 4;
}
return ret;
//now making it here means we've checked the entire list and no FS_NOTCHECKED files remain
if (numwadfiles+filestoload > MAX_WADFILES)
return 3;
else if (downloadrequired)
return 0; //some stuff is FS_NOTFOUND, needs download
else
return 1; //everything is FS_OPEN or FS_FOUND, proceed to loading
}
// Load it now
void CL_LoadServerFiles(void)
boolean CL_LoadServerFiles(void)
{
INT32 i;
// if (M_CheckParm("-nofiles"))
// return;
for (i = 1; i < fileneedednum; i++)
for (i = 0; i < fileneedednum; i++)
{
if (fileneeded[i].status == FS_OPEN)
continue; // Already loaded
@ -483,6 +544,7 @@ void CL_LoadServerFiles(void)
P_AddWadFile(fileneeded[i].filename);
G_SetGameModified(true);
fileneeded[i].status = FS_OPEN;
return false;
}
else if (fileneeded[i].status == FS_MD5SUMBAD)
I_Error("Wrong version of file %s", fileneeded[i].filename);
@ -508,6 +570,7 @@ void CL_LoadServerFiles(void)
fileneeded[i].status, s);
}
}
return true;
}
void AddLuaFileTransfer(const char *filename, const char *mode)
@ -689,7 +752,11 @@ void CL_PrepareDownloadLuaFile(void)
netbuffer->packettype = PT_ASKLUAFILE;
HSendPacket(servernode, true, 0, 0);
FreeFileNeeded();
AllocFileNeeded(1);
fileneedednum = 1;
fileneeded[0].type = FILENEEDED_LUAFILE;
fileneeded[0].status = FS_REQUESTED;
fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX;
@ -716,15 +783,11 @@ static INT32 filestosend = 0;
* \sa AddLuaFileToSendQueue
*
*/
static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid)
static boolean AddFileToSendQueue(INT32 node, UINT8 fileid)
{
filetx_t **q; // A pointer to the "next" field of the last file in the list
filetx_t *p; // The new file request
INT32 i;
char wadfilename[MAX_WADPATH];
if (cv_noticedownload.value)
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node));
UINT16 wadnum;
// Find the last file in the list and set a pointer to its "next" field
q = &transfer[node].txlist;
@ -744,51 +807,43 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
if (!p->id.filename)
I_Error("AddFileToSendQueue: No more memory\n");
// Set the file name and get rid of the path
strlcpy(p->id.filename, filename, MAX_WADPATH);
nameonly(p->id.filename);
// Look for the requested file through all loaded files
for (i = 0; wadfiles[i]; i++)
{
strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH);
nameonly(wadfilename);
if (!stricmp(wadfilename, p->id.filename))
{
// Copy file name with full path
strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH);
break;
}
}
// Find the wad the ID refers to
wadnum = GetWadNumFromFileNeededId(fileid);
// Handle non-loaded file requests
if (!wadfiles[i])
if (wadnum == UINT16_MAX)
{
DEBFILE(va("%s not found in wadfiles\n", filename));
DEBFILE(va("fileneeded %d not found in wadfiles\n", fileid));
// This formerly checked if (!findfile(p->id.filename, NULL, true))
// Not found
// Don't inform client
DEBFILE(va("Client %d request %s: not found\n", node, filename));
DEBFILE(va("Client %d request fileneeded %d: not found\n", node, fileid));
free(p->id.filename);
free(p);
*q = NULL;
return false; // cancel the rest of the requests
}
// Set the file name and get rid of the path
strlcpy(p->id.filename, wadfiles[wadnum]->filename, MAX_WADPATH);
// Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)
if (wadfiles[wadnum]->filesize > (UINT32)cv_maxsend.value * 1024)
{
// Too big
// Don't inform client (client sucks, man)
DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename));
DEBFILE(va("Client %d request %s: file too big, not sending\n", node, p->id.filename));
free(p->id.filename);
free(p);
*q = NULL;
return false; // cancel the rest of the requests
}
DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node));
if (cv_noticedownload.value)
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", p->id.filename, node, I_GetNodeAddress(node));
DEBFILE(va("Sending file %s (id=%d) to %d\n", p->id.filename, fileid, node));
p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
p->fileid = fileid;
p->next = NULL; // End of list
@ -925,7 +980,6 @@ static void SV_EndFileSend(INT32 node)
filestosend--;
}
#define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH)
#define FILEFRAGMENTSIZE (software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE))
/** Handles file transmission
@ -958,14 +1012,7 @@ void FileSendTicker(void)
if (!filestosend) // No file to send
return;
if (cv_downloadspeed.value) // New behavior
packetsent = cv_downloadspeed.value;
else // Old behavior
{
packetsent = PACKETPERTIC;
if (!packetsent)
packetsent = 1;
}
packetsent = cv_downloadspeed.value;
netbuffer->packettype = PT_FILEFRAGMENT;
@ -1242,6 +1289,9 @@ void PT_FileFragment(void)
UINT16 boundedfragmentsize = doomcom->datalength - BASEPACKETSIZE - sizeof(netbuffer->u.filetxpak);
char *filename;
if (!file)
return;
filename = va("%s", file->filename);
nameonly(filename);
@ -1353,6 +1403,7 @@ void PT_FileFragment(void)
// Tell the server we have received the file
netbuffer->packettype = PT_HASLUAFILE;
HSendPacket(servernode, true, 0, 0);
FreeFileNeeded();
}
}
}
@ -1423,32 +1474,37 @@ void CloseNetFile(void)
SV_AbortSendFiles(i);
// Receiving a file?
for (i = 0; i < MAX_WADFILES; i++)
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
{
fclose(fileneeded[i].file);
free(fileneeded[i].ackpacket);
if (!pauseddownload && i != 0) // 0 is either srb2.srb or the gamestate...
if (fileneeded)
{
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
{
// Don't remove the file, save it for later in case we resume the download
pauseddownload = malloc(sizeof(*pauseddownload));
if (!pauseddownload)
I_Error("CloseNetFile: No more memory\n");
fclose(fileneeded[i].file);
free(fileneeded[i].ackpacket);
strcpy(pauseddownload->filename, fileneeded[i].filename);
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16);
pauseddownload->currentsize = fileneeded[i].currentsize;
pauseddownload->receivedfragments = fileneeded[i].receivedfragments;
pauseddownload->fragmentsize = fileneeded[i].fragmentsize;
if (!pauseddownload && (fileneeded[i].type == FILENEEDED_WAD || i != 0)) // 0 is the gamestate...
{
// Don't remove the file, save it for later in case we resume the download
pauseddownload = malloc(sizeof(*pauseddownload));
if (!pauseddownload)
I_Error("CloseNetFile: No more memory\n");
strcpy(pauseddownload->filename, fileneeded[i].filename);
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16);
pauseddownload->currentsize = fileneeded[i].currentsize;
pauseddownload->receivedfragments = fileneeded[i].receivedfragments;
pauseddownload->fragmentsize = fileneeded[i].fragmentsize;
}
else
{
// File is not complete, delete it.
free(fileneeded[i].receivedfragments);
remove(fileneeded[i].filename);
}
}
else
{
free(fileneeded[i].receivedfragments);
// File is not complete delete it
remove(fileneeded[i].filename);
}
}
}
FreeFileNeeded();
}
void Command_Downloads_f(void)

View file

@ -27,6 +27,7 @@ typedef enum
typedef enum
{
FS_NOTCHECKED,
FS_NOTFOUND,
FS_FOUND,
FS_REQUESTED,
@ -35,13 +36,21 @@ typedef enum
FS_MD5SUMBAD
} filestatus_t;
typedef enum
{
FILENEEDED_WAD,
FILENEEDED_SAVEGAME,
FILENEEDED_LUAFILE
} fileneededtype_t;
typedef struct
{
UINT8 willsend; // Is the server willing to send it?
UINT8 folder; // File is a folder
char filename[MAX_WADPATH];
UINT8 md5sum[16];
filestatus_t status; // The value returned by recsearch
UINT8 willsend; // Is the server willing to send it?
UINT8 folder; // File is a folder
fileneededtype_t type;
boolean justdownloaded; // To prevent late fragments from causing an I_Error
// Used only for download
@ -58,19 +67,25 @@ typedef struct
#define FILENEEDEDSIZE 23
extern INT32 fileneedednum;
extern fileneeded_t fileneeded[MAX_WADFILES];
extern fileneeded_t *fileneeded;
extern char downloaddir[512];
#ifndef NONET
extern INT32 lastfilenum;
extern INT32 downloadcompletednum;
extern UINT32 downloadcompletedsize;
extern INT32 totalfilesrequestednum;
extern UINT32 totalfilesrequestedsize;
#endif
UINT8 *PutFileNeeded(void);
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr);
void AllocFileNeeded(INT32 size);
void FreeFileNeeded(void);
UINT8 *PutFileNeeded(UINT16 firstfile);
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile);
void CL_PrepareDownloadSaveGame(const char *tmpsave);
INT32 CL_CheckFiles(void);
void CL_LoadServerFiles(void);
boolean CL_LoadServerFiles(void);
void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemethod,
UINT8 fileid);

View file

@ -5236,12 +5236,10 @@ struct int_const_s const INT_CONST[] = {
{"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players
{"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible)
// FOF special flags
{"FS_PUSHABLES",FS_PUSHABLES},
{"FS_EXECUTOR",FS_EXECUTOR},
{"FS_ONLYBOTTOM",FS_ONLYBOTTOM},
{"FS_BUSTMASK",FS_BUSTMASK},
{"FS_DAMPEN",FS_DAMPEN},
// FOF bustable flags
{"FB_PUSHABLES",FB_PUSHABLES},
{"FB_EXECUTOR",FB_EXECUTOR},
{"FB_ONLYBOTTOM",FB_ONLYBOTTOM},
// Bustable FOF type
{"BT_TOUCH",BT_TOUCH},

View file

@ -152,6 +152,9 @@ extern char logfilename[1024];
// Comment or uncomment this as necessary.
#define USE_PATCH_DTA
// Enforce a limit of loaded WAD files.
//#define ENFORCE_WAD_LIMIT
// Use .kart extension addons
//#define USE_KART

View file

@ -1091,11 +1091,11 @@ static const char *credits[] = {
"Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe",
"Iestyn \"Monster Iestyn\" Jealous",
"\"Jimita\"",
"\"Kaito Sinclaire\"",
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"Ronald \"Furyhunter\" Kinard", // The SDL2 port
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"\"LZA\"",
"Matthew \"Shuffle\" Marsalko",
"Steven \"StroggOnMeth\" McGranahan",
"\"Morph\"", // For SRB2Morphed stuff
@ -1167,8 +1167,8 @@ static const char *credits[] = {
"Alexander \"DrTapeworm\" Moench-Ford",
"Stefan \"Stuf\" Rimalia",
"Shane Mychal Sexton",
"David \"Big Wave Dave\" Spencer Sr.",
"David \"Instant Sonic\" Spencer Jr.",
"Dave \"Big Wave Dave\" Spencer",
"David \"instantSonic\" Spencer",
"\"SSNTails\"",
"",
"\1Level Design",
@ -1219,7 +1219,7 @@ static const char *credits[] = {
"Bill \"Tets\" Reed",
"",
"\1Special Thanks",
"iD Software",
"id Software",
"Doom Legacy Project",
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
"Kart Krew",

View file

@ -338,9 +338,6 @@ size_t dir_on[menudepth];
UINT8 refreshdirmenu = 0;
char *refreshdirname = NULL;
size_t packetsizetally = 0;
size_t mainwadstally = 0;
#define dirpathlen 1024
#define maxdirdepth 48
@ -830,7 +827,7 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl
#endif
"\5.pk3", "\5.soc", "\5.lua"}; // addfile
char filenamebuf[MAX_WADFILES][MAX_WADPATH];
static char (*filenamebuf)[MAX_WADPATH];
static boolean filemenucmp(char *haystack, char *needle)
{
@ -1102,6 +1099,10 @@ boolean preparefilemenu(boolean samedepth)
if (ext >= EXT_LOADSTART)
{
size_t i;
if (filenamebuf == NULL)
filenamebuf = calloc(sizeof(char) * MAX_WADPATH, numwadfiles);
for (i = 0; i < numwadfiles; i++)
{
if (!filenamebuf[i][0])
@ -1151,6 +1152,12 @@ boolean preparefilemenu(boolean samedepth)
}
}
if (filenamebuf)
{
free(filenamebuf);
filenamebuf = NULL;
}
closedir(dirhandle);
if ((menudepthleft != menudepth-1) // now for UP... entry

View file

@ -53,9 +53,6 @@ extern size_t dir_on[menudepth];
extern UINT8 refreshdirmenu;
extern char *refreshdirname;
extern size_t packetsizetally;
extern size_t mainwadstally;
typedef enum
{
EXT_FOLDER = 0,

View file

@ -2433,12 +2433,13 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
{
WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker
WriteDemoChecksum();
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
sprintf(demoname, "%sMS.LMP", G_BuildMapName(gamemap));
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
}
free(demobuffer);
metalrecording = false;
if (saved)
I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap));
I_Error("Saved to %s", demoname);
I_Error("Failed to save demo!");
}

View file

@ -1549,8 +1549,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// Note: Majority of botstuffs are handled in G_Ticker now.
if (player->bot == BOT_2PHUMAN) //Player-controlled bot
{
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Strafe
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
}

View file

@ -233,323 +233,323 @@ typedef struct
static keyname_t keynames[] =
{
{KEY_SPACE, "SPACE"},
{KEY_CAPSLOCK, "CAPS LOCK"},
{KEY_ENTER, "ENTER"},
{KEY_TAB, "TAB"},
{KEY_ESCAPE, "ESCAPE"},
{KEY_BACKSPACE, "BACKSPACE"},
{KEY_SPACE, "space"},
{KEY_CAPSLOCK, "caps lock"},
{KEY_ENTER, "enter"},
{KEY_TAB, "tab"},
{KEY_ESCAPE, "escape"},
{KEY_BACKSPACE, "backspace"},
{KEY_NUMLOCK, "NUMLOCK"},
{KEY_SCROLLLOCK, "SCROLLLOCK"},
{KEY_NUMLOCK, "numlock"},
{KEY_SCROLLLOCK, "scrolllock"},
// bill gates keys
{KEY_LEFTWIN, "LEFTWIN"},
{KEY_RIGHTWIN, "RIGHTWIN"},
{KEY_MENU, "MENU"},
{KEY_LEFTWIN, "leftwin"},
{KEY_RIGHTWIN, "rightwin"},
{KEY_MENU, "menu"},
{KEY_LSHIFT, "LSHIFT"},
{KEY_RSHIFT, "RSHIFT"},
{KEY_LSHIFT, "SHIFT"},
{KEY_LCTRL, "LCTRL"},
{KEY_RCTRL, "RCTRL"},
{KEY_LCTRL, "CTRL"},
{KEY_LALT, "LALT"},
{KEY_RALT, "RALT"},
{KEY_LALT, "ALT"},
{KEY_LSHIFT, "lshift"},
{KEY_RSHIFT, "rshift"},
{KEY_LSHIFT, "shift"},
{KEY_LCTRL, "lctrl"},
{KEY_RCTRL, "rctrl"},
{KEY_LCTRL, "ctrl"},
{KEY_LALT, "lalt"},
{KEY_RALT, "ralt"},
{KEY_LALT, "alt"},
// keypad keys
{KEY_KPADSLASH, "KEYPAD /"},
{KEY_KEYPAD7, "KEYPAD 7"},
{KEY_KEYPAD8, "KEYPAD 8"},
{KEY_KEYPAD9, "KEYPAD 9"},
{KEY_MINUSPAD, "KEYPAD -"},
{KEY_KEYPAD4, "KEYPAD 4"},
{KEY_KEYPAD5, "KEYPAD 5"},
{KEY_KEYPAD6, "KEYPAD 6"},
{KEY_PLUSPAD, "KEYPAD +"},
{KEY_KEYPAD1, "KEYPAD 1"},
{KEY_KEYPAD2, "KEYPAD 2"},
{KEY_KEYPAD3, "KEYPAD 3"},
{KEY_KEYPAD0, "KEYPAD 0"},
{KEY_KPADDEL, "KEYPAD ."},
{KEY_KPADSLASH, "keypad /"},
{KEY_KEYPAD7, "keypad 7"},
{KEY_KEYPAD8, "keypad 8"},
{KEY_KEYPAD9, "keypad 9"},
{KEY_MINUSPAD, "keypad -"},
{KEY_KEYPAD4, "keypad 4"},
{KEY_KEYPAD5, "keypad 5"},
{KEY_KEYPAD6, "keypad 6"},
{KEY_PLUSPAD, "keypad +"},
{KEY_KEYPAD1, "keypad 1"},
{KEY_KEYPAD2, "keypad 2"},
{KEY_KEYPAD3, "keypad 3"},
{KEY_KEYPAD0, "keypad 0"},
{KEY_KPADDEL, "keypad ."},
// extended keys (not keypad)
{KEY_HOME, "HOME"},
{KEY_UPARROW, "UP ARROW"},
{KEY_PGUP, "PGUP"},
{KEY_LEFTARROW, "LEFT ARROW"},
{KEY_RIGHTARROW, "RIGHT ARROW"},
{KEY_END, "END"},
{KEY_DOWNARROW, "DOWN ARROW"},
{KEY_PGDN, "PGDN"},
{KEY_INS, "INS"},
{KEY_DEL, "DEL"},
{KEY_HOME, "home"},
{KEY_UPARROW, "up arrow"},
{KEY_PGUP, "pgup"},
{KEY_LEFTARROW, "left arrow"},
{KEY_RIGHTARROW, "right arrow"},
{KEY_END, "end"},
{KEY_DOWNARROW, "down arrow"},
{KEY_PGDN, "pgdn"},
{KEY_INS, "ins"},
{KEY_DEL, "del"},
// other keys
{KEY_F1, "F1"},
{KEY_F2, "F2"},
{KEY_F3, "F3"},
{KEY_F4, "F4"},
{KEY_F5, "F5"},
{KEY_F6, "F6"},
{KEY_F7, "F7"},
{KEY_F8, "F8"},
{KEY_F9, "F9"},
{KEY_F10, "F10"},
{KEY_F11, "F11"},
{KEY_F12, "F12"},
{KEY_F1, "f1"},
{KEY_F2, "f2"},
{KEY_F3, "f3"},
{KEY_F4, "f4"},
{KEY_F5, "f5"},
{KEY_F6, "f6"},
{KEY_F7, "f7"},
{KEY_F8, "f8"},
{KEY_F9, "f9"},
{KEY_F10, "f10"},
{KEY_F11, "f11"},
{KEY_F12, "f12"},
// KEY_CONSOLE has an exception in the keyname code
{'`', "TILDE"},
{KEY_PAUSE, "PAUSE/BREAK"},
{KEY_PAUSE, "pause/break"},
// virtual keys for mouse buttons and joystick buttons
{KEY_MOUSE1+0,"MOUSE1"},
{KEY_MOUSE1+1,"MOUSE2"},
{KEY_MOUSE1+2,"MOUSE3"},
{KEY_MOUSE1+3,"MOUSE4"},
{KEY_MOUSE1+4,"MOUSE5"},
{KEY_MOUSE1+5,"MOUSE6"},
{KEY_MOUSE1+6,"MOUSE7"},
{KEY_MOUSE1+7,"MOUSE8"},
{KEY_2MOUSE1+0,"SEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_2MOUSE1+1,"SEC_MOUSE1"},
{KEY_2MOUSE1+2,"SEC_MOUSE3"},
{KEY_2MOUSE1+3,"SEC_MOUSE4"},
{KEY_2MOUSE1+4,"SEC_MOUSE5"},
{KEY_2MOUSE1+5,"SEC_MOUSE6"},
{KEY_2MOUSE1+6,"SEC_MOUSE7"},
{KEY_2MOUSE1+7,"SEC_MOUSE8"},
{KEY_MOUSEWHEELUP, "Wheel 1 UP"},
{KEY_MOUSEWHEELDOWN, "Wheel 1 Down"},
{KEY_2MOUSEWHEELUP, "Wheel 2 UP"},
{KEY_2MOUSEWHEELDOWN, "Wheel 2 Down"},
{KEY_MOUSE1+0,"mouse1"},
{KEY_MOUSE1+1,"mouse2"},
{KEY_MOUSE1+2,"mouse3"},
{KEY_MOUSE1+3,"mouse4"},
{KEY_MOUSE1+4,"mouse5"},
{KEY_MOUSE1+5,"mouse6"},
{KEY_MOUSE1+6,"mouse7"},
{KEY_MOUSE1+7,"mouse8"},
{KEY_2MOUSE1+0,"sec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_2MOUSE1+1,"sec_mouse1"},
{KEY_2MOUSE1+2,"sec_mouse3"},
{KEY_2MOUSE1+3,"sec_mouse4"},
{KEY_2MOUSE1+4,"sec_mouse5"},
{KEY_2MOUSE1+5,"sec_mouse6"},
{KEY_2MOUSE1+6,"sec_mouse7"},
{KEY_2MOUSE1+7,"sec_mouse8"},
{KEY_MOUSEWHEELUP, "wheel 1 up"},
{KEY_MOUSEWHEELDOWN, "wheel 1 down"},
{KEY_2MOUSEWHEELUP, "wheel 2 up"},
{KEY_2MOUSEWHEELDOWN, "wheel 2 down"},
{KEY_JOY1+0, "JOY1"},
{KEY_JOY1+1, "JOY2"},
{KEY_JOY1+2, "JOY3"},
{KEY_JOY1+3, "JOY4"},
{KEY_JOY1+4, "JOY5"},
{KEY_JOY1+5, "JOY6"},
{KEY_JOY1+6, "JOY7"},
{KEY_JOY1+7, "JOY8"},
{KEY_JOY1+8, "JOY9"},
{KEY_JOY1+0, "joy1"},
{KEY_JOY1+1, "joy2"},
{KEY_JOY1+2, "joy3"},
{KEY_JOY1+3, "joy4"},
{KEY_JOY1+4, "joy5"},
{KEY_JOY1+5, "joy6"},
{KEY_JOY1+6, "joy7"},
{KEY_JOY1+7, "joy8"},
{KEY_JOY1+8, "joy9"},
#if !defined (NOMOREJOYBTN_1S)
// we use up to 32 buttons in DirectInput
{KEY_JOY1+9, "JOY10"},
{KEY_JOY1+10, "JOY11"},
{KEY_JOY1+11, "JOY12"},
{KEY_JOY1+12, "JOY13"},
{KEY_JOY1+13, "JOY14"},
{KEY_JOY1+14, "JOY15"},
{KEY_JOY1+15, "JOY16"},
{KEY_JOY1+16, "JOY17"},
{KEY_JOY1+17, "JOY18"},
{KEY_JOY1+18, "JOY19"},
{KEY_JOY1+19, "JOY20"},
{KEY_JOY1+20, "JOY21"},
{KEY_JOY1+21, "JOY22"},
{KEY_JOY1+22, "JOY23"},
{KEY_JOY1+23, "JOY24"},
{KEY_JOY1+24, "JOY25"},
{KEY_JOY1+25, "JOY26"},
{KEY_JOY1+26, "JOY27"},
{KEY_JOY1+27, "JOY28"},
{KEY_JOY1+28, "JOY29"},
{KEY_JOY1+29, "JOY30"},
{KEY_JOY1+30, "JOY31"},
{KEY_JOY1+31, "JOY32"},
{KEY_JOY1+9, "joy10"},
{KEY_JOY1+10, "joy11"},
{KEY_JOY1+11, "joy12"},
{KEY_JOY1+12, "joy13"},
{KEY_JOY1+13, "joy14"},
{KEY_JOY1+14, "joy15"},
{KEY_JOY1+15, "joy16"},
{KEY_JOY1+16, "joy17"},
{KEY_JOY1+17, "joy18"},
{KEY_JOY1+18, "joy19"},
{KEY_JOY1+19, "joy20"},
{KEY_JOY1+20, "joy21"},
{KEY_JOY1+21, "joy22"},
{KEY_JOY1+22, "joy23"},
{KEY_JOY1+23, "joy24"},
{KEY_JOY1+24, "joy25"},
{KEY_JOY1+25, "joy26"},
{KEY_JOY1+26, "joy27"},
{KEY_JOY1+27, "joy28"},
{KEY_JOY1+28, "joy29"},
{KEY_JOY1+29, "joy30"},
{KEY_JOY1+30, "joy31"},
{KEY_JOY1+31, "joy32"},
#endif
// the DOS version uses Allegro's joystick support
{KEY_HAT1+0, "HATUP"},
{KEY_HAT1+1, "HATDOWN"},
{KEY_HAT1+2, "HATLEFT"},
{KEY_HAT1+3, "HATRIGHT"},
{KEY_HAT1+4, "HATUP2"},
{KEY_HAT1+5, "HATDOWN2"},
{KEY_HAT1+6, "HATLEFT2"},
{KEY_HAT1+7, "HATRIGHT2"},
{KEY_HAT1+8, "HATUP3"},
{KEY_HAT1+9, "HATDOWN3"},
{KEY_HAT1+10, "HATLEFT3"},
{KEY_HAT1+11, "HATRIGHT3"},
{KEY_HAT1+12, "HATUP4"},
{KEY_HAT1+13, "HATDOWN4"},
{KEY_HAT1+14, "HATLEFT4"},
{KEY_HAT1+15, "HATRIGHT4"},
{KEY_HAT1+0, "hatup"},
{KEY_HAT1+1, "hatdown"},
{KEY_HAT1+2, "hatleft"},
{KEY_HAT1+3, "hatright"},
{KEY_HAT1+4, "hatup2"},
{KEY_HAT1+5, "hatdown2"},
{KEY_HAT1+6, "hatleft2"},
{KEY_HAT1+7, "hatright2"},
{KEY_HAT1+8, "hatup3"},
{KEY_HAT1+9, "hatdown3"},
{KEY_HAT1+10, "hatleft3"},
{KEY_HAT1+11, "hatright3"},
{KEY_HAT1+12, "hatup4"},
{KEY_HAT1+13, "hatdown4"},
{KEY_HAT1+14, "hatleft4"},
{KEY_HAT1+15, "hatright4"},
{KEY_DBLMOUSE1+0, "DBLMOUSE1"},
{KEY_DBLMOUSE1+1, "DBLMOUSE2"},
{KEY_DBLMOUSE1+2, "DBLMOUSE3"},
{KEY_DBLMOUSE1+3, "DBLMOUSE4"},
{KEY_DBLMOUSE1+4, "DBLMOUSE5"},
{KEY_DBLMOUSE1+5, "DBLMOUSE6"},
{KEY_DBLMOUSE1+6, "DBLMOUSE7"},
{KEY_DBLMOUSE1+7, "DBLMOUSE8"},
{KEY_DBL2MOUSE1+0, "DBLSEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_DBL2MOUSE1+1, "DBLSEC_MOUSE1"},
{KEY_DBL2MOUSE1+2, "DBLSEC_MOUSE3"},
{KEY_DBL2MOUSE1+3, "DBLSEC_MOUSE4"},
{KEY_DBL2MOUSE1+4, "DBLSEC_MOUSE5"},
{KEY_DBL2MOUSE1+5, "DBLSEC_MOUSE6"},
{KEY_DBL2MOUSE1+6, "DBLSEC_MOUSE7"},
{KEY_DBL2MOUSE1+7, "DBLSEC_MOUSE8"},
{KEY_DBLMOUSE1+0, "dblmouse1"},
{KEY_DBLMOUSE1+1, "dblmouse2"},
{KEY_DBLMOUSE1+2, "dblmouse3"},
{KEY_DBLMOUSE1+3, "dblmouse4"},
{KEY_DBLMOUSE1+4, "dblmouse5"},
{KEY_DBLMOUSE1+5, "dblmouse6"},
{KEY_DBLMOUSE1+6, "dblmouse7"},
{KEY_DBLMOUSE1+7, "dblmouse8"},
{KEY_DBL2MOUSE1+0, "dblsec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_DBL2MOUSE1+1, "dblsec_mouse1"},
{KEY_DBL2MOUSE1+2, "dblsec_mouse3"},
{KEY_DBL2MOUSE1+3, "dblsec_mouse4"},
{KEY_DBL2MOUSE1+4, "dblsec_mouse5"},
{KEY_DBL2MOUSE1+5, "dblsec_mouse6"},
{KEY_DBL2MOUSE1+6, "dblsec_mouse7"},
{KEY_DBL2MOUSE1+7, "dblsec_mouse8"},
{KEY_DBLJOY1+0, "DBLJOY1"},
{KEY_DBLJOY1+1, "DBLJOY2"},
{KEY_DBLJOY1+2, "DBLJOY3"},
{KEY_DBLJOY1+3, "DBLJOY4"},
{KEY_DBLJOY1+4, "DBLJOY5"},
{KEY_DBLJOY1+5, "DBLJOY6"},
{KEY_DBLJOY1+6, "DBLJOY7"},
{KEY_DBLJOY1+7, "DBLJOY8"},
{KEY_DBLJOY1+0, "dbljoy1"},
{KEY_DBLJOY1+1, "dbljoy2"},
{KEY_DBLJOY1+2, "dbljoy3"},
{KEY_DBLJOY1+3, "dbljoy4"},
{KEY_DBLJOY1+4, "dbljoy5"},
{KEY_DBLJOY1+5, "dbljoy6"},
{KEY_DBLJOY1+6, "dbljoy7"},
{KEY_DBLJOY1+7, "dbljoy8"},
#if !defined (NOMOREJOYBTN_1DBL)
{KEY_DBLJOY1+8, "DBLJOY9"},
{KEY_DBLJOY1+9, "DBLJOY10"},
{KEY_DBLJOY1+10, "DBLJOY11"},
{KEY_DBLJOY1+11, "DBLJOY12"},
{KEY_DBLJOY1+12, "DBLJOY13"},
{KEY_DBLJOY1+13, "DBLJOY14"},
{KEY_DBLJOY1+14, "DBLJOY15"},
{KEY_DBLJOY1+15, "DBLJOY16"},
{KEY_DBLJOY1+16, "DBLJOY17"},
{KEY_DBLJOY1+17, "DBLJOY18"},
{KEY_DBLJOY1+18, "DBLJOY19"},
{KEY_DBLJOY1+19, "DBLJOY20"},
{KEY_DBLJOY1+20, "DBLJOY21"},
{KEY_DBLJOY1+21, "DBLJOY22"},
{KEY_DBLJOY1+22, "DBLJOY23"},
{KEY_DBLJOY1+23, "DBLJOY24"},
{KEY_DBLJOY1+24, "DBLJOY25"},
{KEY_DBLJOY1+25, "DBLJOY26"},
{KEY_DBLJOY1+26, "DBLJOY27"},
{KEY_DBLJOY1+27, "DBLJOY28"},
{KEY_DBLJOY1+28, "DBLJOY29"},
{KEY_DBLJOY1+29, "DBLJOY30"},
{KEY_DBLJOY1+30, "DBLJOY31"},
{KEY_DBLJOY1+31, "DBLJOY32"},
{KEY_DBLJOY1+8, "dbljoy9"},
{KEY_DBLJOY1+9, "dbljoy10"},
{KEY_DBLJOY1+10, "dbljoy11"},
{KEY_DBLJOY1+11, "dbljoy12"},
{KEY_DBLJOY1+12, "dbljoy13"},
{KEY_DBLJOY1+13, "dbljoy14"},
{KEY_DBLJOY1+14, "dbljoy15"},
{KEY_DBLJOY1+15, "dbljoy16"},
{KEY_DBLJOY1+16, "dbljoy17"},
{KEY_DBLJOY1+17, "dbljoy18"},
{KEY_DBLJOY1+18, "dbljoy19"},
{KEY_DBLJOY1+19, "dbljoy20"},
{KEY_DBLJOY1+20, "dbljoy21"},
{KEY_DBLJOY1+21, "dbljoy22"},
{KEY_DBLJOY1+22, "dbljoy23"},
{KEY_DBLJOY1+23, "dbljoy24"},
{KEY_DBLJOY1+24, "dbljoy25"},
{KEY_DBLJOY1+25, "dbljoy26"},
{KEY_DBLJOY1+26, "dbljoy27"},
{KEY_DBLJOY1+27, "dbljoy28"},
{KEY_DBLJOY1+28, "dbljoy29"},
{KEY_DBLJOY1+29, "dbljoy30"},
{KEY_DBLJOY1+30, "dbljoy31"},
{KEY_DBLJOY1+31, "dbljoy32"},
#endif
{KEY_DBLHAT1+0, "DBLHATUP"},
{KEY_DBLHAT1+1, "DBLHATDOWN"},
{KEY_DBLHAT1+2, "DBLHATLEFT"},
{KEY_DBLHAT1+3, "DBLHATRIGHT"},
{KEY_DBLHAT1+4, "DBLHATUP2"},
{KEY_DBLHAT1+5, "DBLHATDOWN2"},
{KEY_DBLHAT1+6, "DBLHATLEFT2"},
{KEY_DBLHAT1+7, "DBLHATRIGHT2"},
{KEY_DBLHAT1+8, "DBLHATUP3"},
{KEY_DBLHAT1+9, "DBLHATDOWN3"},
{KEY_DBLHAT1+10, "DBLHATLEFT3"},
{KEY_DBLHAT1+11, "DBLHATRIGHT3"},
{KEY_DBLHAT1+12, "DBLHATUP4"},
{KEY_DBLHAT1+13, "DBLHATDOWN4"},
{KEY_DBLHAT1+14, "DBLHATLEFT4"},
{KEY_DBLHAT1+15, "DBLHATRIGHT4"},
{KEY_DBLHAT1+0, "dblhatup"},
{KEY_DBLHAT1+1, "dblhatdown"},
{KEY_DBLHAT1+2, "dblhatleft"},
{KEY_DBLHAT1+3, "dblhatright"},
{KEY_DBLHAT1+4, "dblhatup2"},
{KEY_DBLHAT1+5, "dblhatdown2"},
{KEY_DBLHAT1+6, "dblhatleft2"},
{KEY_DBLHAT1+7, "dblhatright2"},
{KEY_DBLHAT1+8, "dblhatup3"},
{KEY_DBLHAT1+9, "dblhatdown3"},
{KEY_DBLHAT1+10, "dblhatleft3"},
{KEY_DBLHAT1+11, "dblhatright3"},
{KEY_DBLHAT1+12, "dblhatup4"},
{KEY_DBLHAT1+13, "dblhatdown4"},
{KEY_DBLHAT1+14, "dblhatleft4"},
{KEY_DBLHAT1+15, "dblhatright4"},
{KEY_2JOY1+0, "SEC_JOY1"},
{KEY_2JOY1+1, "SEC_JOY2"},
{KEY_2JOY1+2, "SEC_JOY3"},
{KEY_2JOY1+3, "SEC_JOY4"},
{KEY_2JOY1+4, "SEC_JOY5"},
{KEY_2JOY1+5, "SEC_JOY6"},
{KEY_2JOY1+6, "SEC_JOY7"},
{KEY_2JOY1+7, "SEC_JOY8"},
{KEY_2JOY1+0, "sec_joy1"},
{KEY_2JOY1+1, "sec_joy2"},
{KEY_2JOY1+2, "sec_joy3"},
{KEY_2JOY1+3, "sec_joy4"},
{KEY_2JOY1+4, "sec_joy5"},
{KEY_2JOY1+5, "sec_joy6"},
{KEY_2JOY1+6, "sec_joy7"},
{KEY_2JOY1+7, "sec_joy8"},
#if !defined (NOMOREJOYBTN_2S)
// we use up to 32 buttons in DirectInput
{KEY_2JOY1+8, "SEC_JOY9"},
{KEY_2JOY1+9, "SEC_JOY10"},
{KEY_2JOY1+10, "SEC_JOY11"},
{KEY_2JOY1+11, "SEC_JOY12"},
{KEY_2JOY1+12, "SEC_JOY13"},
{KEY_2JOY1+13, "SEC_JOY14"},
{KEY_2JOY1+14, "SEC_JOY15"},
{KEY_2JOY1+15, "SEC_JOY16"},
{KEY_2JOY1+16, "SEC_JOY17"},
{KEY_2JOY1+17, "SEC_JOY18"},
{KEY_2JOY1+18, "SEC_JOY19"},
{KEY_2JOY1+19, "SEC_JOY20"},
{KEY_2JOY1+20, "SEC_JOY21"},
{KEY_2JOY1+21, "SEC_JOY22"},
{KEY_2JOY1+22, "SEC_JOY23"},
{KEY_2JOY1+23, "SEC_JOY24"},
{KEY_2JOY1+24, "SEC_JOY25"},
{KEY_2JOY1+25, "SEC_JOY26"},
{KEY_2JOY1+26, "SEC_JOY27"},
{KEY_2JOY1+27, "SEC_JOY28"},
{KEY_2JOY1+28, "SEC_JOY29"},
{KEY_2JOY1+29, "SEC_JOY30"},
{KEY_2JOY1+30, "SEC_JOY31"},
{KEY_2JOY1+31, "SEC_JOY32"},
{KEY_2JOY1+8, "sec_joy9"},
{KEY_2JOY1+9, "sec_joy10"},
{KEY_2JOY1+10, "sec_joy11"},
{KEY_2JOY1+11, "sec_joy12"},
{KEY_2JOY1+12, "sec_joy13"},
{KEY_2JOY1+13, "sec_joy14"},
{KEY_2JOY1+14, "sec_joy15"},
{KEY_2JOY1+15, "sec_joy16"},
{KEY_2JOY1+16, "sec_joy17"},
{KEY_2JOY1+17, "sec_joy18"},
{KEY_2JOY1+18, "sec_joy19"},
{KEY_2JOY1+19, "sec_joy20"},
{KEY_2JOY1+20, "sec_joy21"},
{KEY_2JOY1+21, "sec_joy22"},
{KEY_2JOY1+22, "sec_joy23"},
{KEY_2JOY1+23, "sec_joy24"},
{KEY_2JOY1+24, "sec_joy25"},
{KEY_2JOY1+25, "sec_joy26"},
{KEY_2JOY1+26, "sec_joy27"},
{KEY_2JOY1+27, "sec_joy28"},
{KEY_2JOY1+28, "sec_joy29"},
{KEY_2JOY1+29, "sec_joy30"},
{KEY_2JOY1+30, "sec_joy31"},
{KEY_2JOY1+31, "sec_joy32"},
#endif
// the DOS version uses Allegro's joystick support
{KEY_2HAT1+0, "SEC_HATUP"},
{KEY_2HAT1+1, "SEC_HATDOWN"},
{KEY_2HAT1+2, "SEC_HATLEFT"},
{KEY_2HAT1+3, "SEC_HATRIGHT"},
{KEY_2HAT1+4, "SEC_HATUP2"},
{KEY_2HAT1+5, "SEC_HATDOWN2"},
{KEY_2HAT1+6, "SEC_HATLEFT2"},
{KEY_2HAT1+7, "SEC_HATRIGHT2"},
{KEY_2HAT1+8, "SEC_HATUP3"},
{KEY_2HAT1+9, "SEC_HATDOWN3"},
{KEY_2HAT1+10, "SEC_HATLEFT3"},
{KEY_2HAT1+11, "SEC_HATRIGHT3"},
{KEY_2HAT1+12, "SEC_HATUP4"},
{KEY_2HAT1+13, "SEC_HATDOWN4"},
{KEY_2HAT1+14, "SEC_HATLEFT4"},
{KEY_2HAT1+15, "SEC_HATRIGHT4"},
{KEY_2HAT1+0, "sec_hatup"},
{KEY_2HAT1+1, "sec_hatdown"},
{KEY_2HAT1+2, "sec_hatleft"},
{KEY_2HAT1+3, "sec_hatright"},
{KEY_2HAT1+4, "sec_hatup2"},
{KEY_2HAT1+5, "sec_hatdown2"},
{KEY_2HAT1+6, "sec_hatleft2"},
{KEY_2HAT1+7, "sec_hatright2"},
{KEY_2HAT1+8, "sec_hatup3"},
{KEY_2HAT1+9, "sec_hatdown3"},
{KEY_2HAT1+10, "sec_hatleft3"},
{KEY_2HAT1+11, "sec_hatright3"},
{KEY_2HAT1+12, "sec_hatup4"},
{KEY_2HAT1+13, "sec_hatdown4"},
{KEY_2HAT1+14, "sec_hatleft4"},
{KEY_2HAT1+15, "sec_hatright4"},
{KEY_DBL2JOY1+0, "DBLSEC_JOY1"},
{KEY_DBL2JOY1+1, "DBLSEC_JOY2"},
{KEY_DBL2JOY1+2, "DBLSEC_JOY3"},
{KEY_DBL2JOY1+3, "DBLSEC_JOY4"},
{KEY_DBL2JOY1+4, "DBLSEC_JOY5"},
{KEY_DBL2JOY1+5, "DBLSEC_JOY6"},
{KEY_DBL2JOY1+6, "DBLSEC_JOY7"},
{KEY_DBL2JOY1+7, "DBLSEC_JOY8"},
{KEY_DBL2JOY1+0, "dblsec_joy1"},
{KEY_DBL2JOY1+1, "dblsec_joy2"},
{KEY_DBL2JOY1+2, "dblsec_joy3"},
{KEY_DBL2JOY1+3, "dblsec_joy4"},
{KEY_DBL2JOY1+4, "dblsec_joy5"},
{KEY_DBL2JOY1+5, "dblsec_joy6"},
{KEY_DBL2JOY1+6, "dblsec_joy7"},
{KEY_DBL2JOY1+7, "dblsec_joy8"},
#if !defined (NOMOREJOYBTN_2DBL)
{KEY_DBL2JOY1+8, "DBLSEC_JOY9"},
{KEY_DBL2JOY1+9, "DBLSEC_JOY10"},
{KEY_DBL2JOY1+10, "DBLSEC_JOY11"},
{KEY_DBL2JOY1+11, "DBLSEC_JOY12"},
{KEY_DBL2JOY1+12, "DBLSEC_JOY13"},
{KEY_DBL2JOY1+13, "DBLSEC_JOY14"},
{KEY_DBL2JOY1+14, "DBLSEC_JOY15"},
{KEY_DBL2JOY1+15, "DBLSEC_JOY16"},
{KEY_DBL2JOY1+16, "DBLSEC_JOY17"},
{KEY_DBL2JOY1+17, "DBLSEC_JOY18"},
{KEY_DBL2JOY1+18, "DBLSEC_JOY19"},
{KEY_DBL2JOY1+19, "DBLSEC_JOY20"},
{KEY_DBL2JOY1+20, "DBLSEC_JOY21"},
{KEY_DBL2JOY1+21, "DBLSEC_JOY22"},
{KEY_DBL2JOY1+22, "DBLSEC_JOY23"},
{KEY_DBL2JOY1+23, "DBLSEC_JOY24"},
{KEY_DBL2JOY1+24, "DBLSEC_JOY25"},
{KEY_DBL2JOY1+25, "DBLSEC_JOY26"},
{KEY_DBL2JOY1+26, "DBLSEC_JOY27"},
{KEY_DBL2JOY1+27, "DBLSEC_JOY28"},
{KEY_DBL2JOY1+28, "DBLSEC_JOY29"},
{KEY_DBL2JOY1+29, "DBLSEC_JOY30"},
{KEY_DBL2JOY1+30, "DBLSEC_JOY31"},
{KEY_DBL2JOY1+31, "DBLSEC_JOY32"},
{KEY_DBL2JOY1+8, "dblsec_joy9"},
{KEY_DBL2JOY1+9, "dblsec_joy10"},
{KEY_DBL2JOY1+10, "dblsec_joy11"},
{KEY_DBL2JOY1+11, "dblsec_joy12"},
{KEY_DBL2JOY1+12, "dblsec_joy13"},
{KEY_DBL2JOY1+13, "dblsec_joy14"},
{KEY_DBL2JOY1+14, "dblsec_joy15"},
{KEY_DBL2JOY1+15, "dblsec_joy16"},
{KEY_DBL2JOY1+16, "dblsec_joy17"},
{KEY_DBL2JOY1+17, "dblsec_joy18"},
{KEY_DBL2JOY1+18, "dblsec_joy19"},
{KEY_DBL2JOY1+19, "dblsec_joy20"},
{KEY_DBL2JOY1+20, "dblsec_joy21"},
{KEY_DBL2JOY1+21, "dblsec_joy22"},
{KEY_DBL2JOY1+22, "dblsec_joy23"},
{KEY_DBL2JOY1+23, "dblsec_joy24"},
{KEY_DBL2JOY1+24, "dblsec_joy25"},
{KEY_DBL2JOY1+25, "dblsec_joy26"},
{KEY_DBL2JOY1+26, "dblsec_joy27"},
{KEY_DBL2JOY1+27, "dblsec_joy28"},
{KEY_DBL2JOY1+28, "dblsec_joy29"},
{KEY_DBL2JOY1+29, "dblsec_joy30"},
{KEY_DBL2JOY1+30, "dblsec_joy31"},
{KEY_DBL2JOY1+31, "dblsec_joy32"},
#endif
{KEY_DBL2HAT1+0, "DBLSEC_HATUP"},
{KEY_DBL2HAT1+1, "DBLSEC_HATDOWN"},
{KEY_DBL2HAT1+2, "DBLSEC_HATLEFT"},
{KEY_DBL2HAT1+3, "DBLSEC_HATRIGHT"},
{KEY_DBL2HAT1+4, "DBLSEC_HATUP2"},
{KEY_DBL2HAT1+5, "DBLSEC_HATDOWN2"},
{KEY_DBL2HAT1+6, "DBLSEC_HATLEFT2"},
{KEY_DBL2HAT1+7, "DBLSEC_HATRIGHT2"},
{KEY_DBL2HAT1+8, "DBLSEC_HATUP3"},
{KEY_DBL2HAT1+9, "DBLSEC_HATDOWN3"},
{KEY_DBL2HAT1+10, "DBLSEC_HATLEFT3"},
{KEY_DBL2HAT1+11, "DBLSEC_HATRIGHT3"},
{KEY_DBL2HAT1+12, "DBLSEC_HATUP4"},
{KEY_DBL2HAT1+13, "DBLSEC_HATDOWN4"},
{KEY_DBL2HAT1+14, "DBLSEC_HATLEFT4"},
{KEY_DBL2HAT1+15, "DBLSEC_HATRIGHT4"},
{KEY_DBL2HAT1+0, "dblsec_hatup"},
{KEY_DBL2HAT1+1, "dblsec_hatdown"},
{KEY_DBL2HAT1+2, "dblsec_hatleft"},
{KEY_DBL2HAT1+3, "dblsec_hatright"},
{KEY_DBL2HAT1+4, "dblsec_hatup2"},
{KEY_DBL2HAT1+5, "dblsec_hatdown2"},
{KEY_DBL2HAT1+6, "dblsec_hatleft2"},
{KEY_DBL2HAT1+7, "dblsec_hatright2"},
{KEY_DBL2HAT1+8, "dblsec_hatup3"},
{KEY_DBL2HAT1+9, "dblsec_hatdown3"},
{KEY_DBL2HAT1+10, "dblsec_hatleft3"},
{KEY_DBL2HAT1+11, "dblsec_hatright3"},
{KEY_DBL2HAT1+12, "dblsec_hatup4"},
{KEY_DBL2HAT1+13, "dblsec_hatdown4"},
{KEY_DBL2HAT1+14, "dblsec_hatleft4"},
{KEY_DBL2HAT1+15, "dblsec_hatright4"},
};

View file

@ -245,13 +245,16 @@ void HWR_RenderBatches(void)
currently_batching = false;// no longer collecting batches
if (!polygonArraySize)
{
ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0;
ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i
= ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i
= ps_hw_numcolors.value.i = 0;
return;// nothing to draw
}
// init stats vars
ps_hw_numpolys = polygonArraySize;
ps_hw_numcalls = ps_hw_numverts = 0;
ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 1;
ps_hw_numpolys.value.i = polygonArraySize;
ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0;
ps_hw_numshaders.value.i = ps_hw_numtextures.value.i
= ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1;
// init polygonIndexArray
for (i = 0; i < polygonArraySize; i++)
{
@ -259,12 +262,12 @@ void HWR_RenderBatches(void)
}
// sort polygons
ps_hw_batchsorttime = I_GetPreciseTime();
PS_START_TIMING(ps_hw_batchsorttime);
if (cv_glshaders.value && gl_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime;
PS_STOP_TIMING(ps_hw_batchsorttime);
// sort order
// 1. shader
// 2. texture
@ -272,7 +275,7 @@ void HWR_RenderBatches(void)
// 4. colors + light level
// not sure about what order of the last 2 should be, or if it even matters
ps_hw_batchdrawtime = I_GetPreciseTime();
PS_START_TIMING(ps_hw_batchdrawtime);
currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture;
@ -408,8 +411,8 @@ void HWR_RenderBatches(void)
// execute draw call
HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// update stats
ps_hw_numcalls++;
ps_hw_numverts += finalIndexWritePos;
ps_hw_numcalls.value.i++;
ps_hw_numverts.value.i += finalIndexWritePos;
// reset write positions
finalVertexWritePos = 0;
finalIndexWritePos = 0;
@ -426,7 +429,7 @@ void HWR_RenderBatches(void)
currentShader = nextShader;
changeShader = false;
ps_hw_numshaders++;
ps_hw_numshaders.value.i++;
}
if (changeTexture)
{
@ -435,21 +438,21 @@ void HWR_RenderBatches(void)
currentTexture = nextTexture;
changeTexture = false;
ps_hw_numtextures++;
ps_hw_numtextures.value.i++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
ps_hw_numpolyflags++;
ps_hw_numpolyflags.value.i++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
ps_hw_numcolors++;
ps_hw_numcolors.value.i++;
}
// and that should be it?
}
@ -457,7 +460,7 @@ void HWR_RenderBatches(void)
polygonArraySize = 0;
unsortedVertexArraySize = 0;
ps_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime;
PS_STOP_TIMING(ps_hw_batchdrawtime);
}

View file

@ -147,22 +147,22 @@ static angle_t gl_aimingangle;
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
// Render stats
precise_t ps_hw_skyboxtime = 0;
precise_t ps_hw_nodesorttime = 0;
precise_t ps_hw_nodedrawtime = 0;
precise_t ps_hw_spritesorttime = 0;
precise_t ps_hw_spritedrawtime = 0;
ps_metric_t ps_hw_skyboxtime = {0};
ps_metric_t ps_hw_nodesorttime = {0};
ps_metric_t ps_hw_nodedrawtime = {0};
ps_metric_t ps_hw_spritesorttime = {0};
ps_metric_t ps_hw_spritedrawtime = {0};
// Render stats for batching
int ps_hw_numpolys = 0;
int ps_hw_numverts = 0;
int ps_hw_numcalls = 0;
int ps_hw_numshaders = 0;
int ps_hw_numtextures = 0;
int ps_hw_numpolyflags = 0;
int ps_hw_numcolors = 0;
precise_t ps_hw_batchsorttime = 0;
precise_t ps_hw_batchdrawtime = 0;
ps_metric_t ps_hw_numpolys = {0};
ps_metric_t ps_hw_numverts = {0};
ps_metric_t ps_hw_numcalls = {0};
ps_metric_t ps_hw_numshaders = {0};
ps_metric_t ps_hw_numtextures = {0};
ps_metric_t ps_hw_numpolyflags = {0};
ps_metric_t ps_hw_numcolors = {0};
ps_metric_t ps_hw_batchsorttime = {0};
ps_metric_t ps_hw_batchdrawtime = {0};
boolean gl_init = false;
boolean gl_maploaded = false;
@ -3235,7 +3235,7 @@ static void HWR_Subsector(size_t num)
}
// for render stats
ps_numpolyobjects += numpolys;
ps_numpolyobjects.value.i += numpolys;
// Sort polyobjects
R_SortPolyObjects(sub);
@ -3343,7 +3343,7 @@ static void HWR_RenderBSPNode(INT32 bspnum)
// Decide which side the view point is on
INT32 side;
ps_numbspcalls++;
ps_numbspcalls.value.i++;
// Found a subsector?
if (bspnum & NF_SUBSECTOR)
@ -4718,7 +4718,7 @@ static void HWR_CreateDrawNodes(void)
// that is already lying around. This should all be in some sort of linked list or lists.
sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL);
ps_hw_nodesorttime = I_GetPreciseTime();
PS_START_TIMING(ps_hw_nodesorttime);
for (i = 0; i < numplanes; i++, p++)
{
@ -4738,7 +4738,7 @@ static void HWR_CreateDrawNodes(void)
sortindex[p] = p;
}
ps_numdrawnodes = p;
ps_numdrawnodes.value.i = p;
// p is the number of stuff to sort
@ -4773,9 +4773,9 @@ static void HWR_CreateDrawNodes(void)
}
}
ps_hw_nodesorttime = I_GetPreciseTime() - ps_hw_nodesorttime;
PS_STOP_TIMING(ps_hw_nodesorttime);
ps_hw_nodedrawtime = I_GetPreciseTime();
PS_START_TIMING(ps_hw_nodedrawtime);
// Okay! Let's draw it all! Woo!
HWD.pfnSetTransform(&atransform);
@ -4812,7 +4812,7 @@ static void HWR_CreateDrawNodes(void)
}
}
ps_hw_nodedrawtime = I_GetPreciseTime() - ps_hw_nodedrawtime;
PS_STOP_TIMING(ps_hw_nodedrawtime);
numwalls = 0;
numplanes = 0;
@ -6095,10 +6095,10 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
if (viewnumber == 0) // Only do it if it's the first screen being rendered
HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs.
ps_hw_skyboxtime = I_GetPreciseTime();
PS_START_TIMING(ps_hw_skyboxtime);
if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox
HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind
ps_hw_skyboxtime = I_GetPreciseTime() - ps_hw_skyboxtime;
PS_STOP_TIMING(ps_hw_skyboxtime);
{
// do we really need to save player (is it not the same)?
@ -6208,9 +6208,9 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
// Reset the shader state.
HWR_SetShaderState();
ps_numbspcalls = 0;
ps_numpolyobjects = 0;
ps_bsptime = I_GetPreciseTime();
ps_numbspcalls.value.i = 0;
ps_numpolyobjects.value.i = 0;
PS_START_TIMING(ps_bsptime);
validcount++;
@ -6248,7 +6248,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
}
#endif
ps_bsptime = I_GetPreciseTime() - ps_bsptime;
PS_STOP_TIMING(ps_bsptime);
if (cv_glbatching.value)
HWR_RenderBatches();
@ -6263,22 +6263,22 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
#endif
// Draw MD2 and sprites
ps_numsprites = gl_visspritecount;
ps_hw_spritesorttime = I_GetPreciseTime();
ps_numsprites.value.i = gl_visspritecount;
PS_START_TIMING(ps_hw_spritesorttime);
HWR_SortVisSprites();
ps_hw_spritesorttime = I_GetPreciseTime() - ps_hw_spritesorttime;
ps_hw_spritedrawtime = I_GetPreciseTime();
PS_STOP_TIMING(ps_hw_spritesorttime);
PS_START_TIMING(ps_hw_spritedrawtime);
HWR_DrawSprites();
ps_hw_spritedrawtime = I_GetPreciseTime() - ps_hw_spritedrawtime;
PS_STOP_TIMING(ps_hw_spritedrawtime);
#ifdef NEWCORONAS
//Hurdler: they must be drawn before translucent planes, what about gl fog?
HWR_DrawCoronas();
#endif
ps_numdrawnodes = 0;
ps_hw_nodesorttime = 0;
ps_hw_nodedrawtime = 0;
ps_numdrawnodes.value.i = 0;
ps_hw_nodesorttime.value.p = 0;
ps_hw_nodedrawtime.value.p = 0;
if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
{
HWR_CreateDrawNodes();

View file

@ -20,6 +20,8 @@
#include "../d_player.h"
#include "../r_defs.h"
#include "../m_perfstats.h"
// Startup & Shutdown the hardware mode renderer
void HWR_Startup(void);
void HWR_Switch(void);
@ -116,22 +118,22 @@ extern FTransform atransform;
// Render stats
extern precise_t ps_hw_skyboxtime;
extern precise_t ps_hw_nodesorttime;
extern precise_t ps_hw_nodedrawtime;
extern precise_t ps_hw_spritesorttime;
extern precise_t ps_hw_spritedrawtime;
extern ps_metric_t ps_hw_skyboxtime;
extern ps_metric_t ps_hw_nodesorttime;
extern ps_metric_t ps_hw_nodedrawtime;
extern ps_metric_t ps_hw_spritesorttime;
extern ps_metric_t ps_hw_spritedrawtime;
// Render stats for batching
extern int ps_hw_numpolys;
extern int ps_hw_numverts;
extern int ps_hw_numcalls;
extern int ps_hw_numshaders;
extern int ps_hw_numtextures;
extern int ps_hw_numpolyflags;
extern int ps_hw_numcolors;
extern precise_t ps_hw_batchsorttime;
extern precise_t ps_hw_batchdrawtime;
extern ps_metric_t ps_hw_numpolys;
extern ps_metric_t ps_hw_numverts;
extern ps_metric_t ps_hw_numcalls;
extern ps_metric_t ps_hw_numshaders;
extern ps_metric_t ps_hw_numtextures;
extern ps_metric_t ps_hw_numpolyflags;
extern ps_metric_t ps_hw_numcolors;
extern ps_metric_t ps_hw_batchsorttime;
extern ps_metric_t ps_hw_batchdrawtime;
extern boolean gl_init;
extern boolean gl_maploaded;

View file

@ -50,7 +50,7 @@ tic_t I_GetTime(void);
*/
precise_t I_GetPreciseTime(void);
/** \brief Returns the difference between precise times as microseconds.
/** \brief Converts a precise_t to microseconds and casts it to a 32 bit integer.
*/
int I_PreciseToMicros(precise_t);
@ -318,10 +318,6 @@ void I_RegisterSysCommands(void);
*/
void I_GetCursorPosition(INT32 *x, INT32 *y);
/** \brief Returns whether the mouse is grabbed
*/
boolean I_GetMouseGrab(void);
/** \brief Sets whether the mouse is grabbed
*/
void I_SetMouseGrab(boolean grab);

View file

@ -2069,7 +2069,7 @@ state_t states[NUMSTATES] =
{SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2
{SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1
{SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLERWAP_ICON2
{SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLEWRAP_ICON2
{SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1
{SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2
@ -5199,7 +5199,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // radius
34*FRACUNIT, // height
0, // display offset
100, // mass
DMG_FIRE, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags
@ -7974,7 +7974,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
4, // mass
DMG_SPIKE, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
@ -8001,7 +8001,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
16*FRACUNIT, // radius
14*FRACUNIT, // height
0, // display offset
4, // mass
DMG_SPIKE, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags
@ -11430,7 +11430,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
17*FRACUNIT, // radius
34*FRACUNIT, // height
1, // display offset
0, // mass
DMG_SPIKE, // mass
1, // damage
sfx_s3kc9s, //sfx_mswing, -- activesound
MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
@ -11457,7 +11457,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
34*FRACUNIT, // radius
68*FRACUNIT, // height
1, // display offset
0, // mass
DMG_SPIKE, // mass
1, // damage
sfx_s3kc9s, //sfx_mswing, -- activesound
MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
@ -13401,7 +13401,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
30*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
DMG_FIRE, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_PAIN|MF_NOGRAVITY|MF_FIRE, // flags
@ -13806,7 +13806,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
0, // mass
0, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_PAIN, // flags
@ -20380,7 +20380,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
18*FRACUNIT, // radius
28*FRACUNIT, // height
0, // display offset
0, // mass
DMG_SPIKE, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_PAIN, // flags

View file

@ -31,6 +31,7 @@
#include "m_misc.h" // M_MapNumber
#include "b_bot.h" // B_UpdateBotleader
#include "d_clisrv.h" // CL_RemovePlayer
#include "i_system.h" // I_GetPreciseTime, I_PreciseToMicros
#include "lua_script.h"
#include "lua_libs.h"
@ -187,6 +188,8 @@ static const struct {
{META_MAPHEADER, "mapheader_t"},
{META_POLYOBJ, "polyobj_t"},
{META_POLYOBJVERTICES, "polyobj_t.vertices"},
{META_POLYOBJLINES, "polyobj_t.lines"},
{META_CVAR, "consvar_t"},
@ -216,6 +219,7 @@ static const struct {
{META_LUABANKS, "luabanks[]"},
{META_KEYEVENT, "keyevent_t"},
{META_MOUSE, "mouse_t"},
{NULL, NULL}
};
@ -3877,6 +3881,12 @@ static int lib_gTicsToMilliseconds(lua_State *L)
return 1;
}
static int lib_getTimeMicros(lua_State *L)
{
lua_pushinteger(L, I_PreciseToMicros(I_GetPreciseTime()));
return 1;
}
static luaL_Reg lib[] = {
{"print", lib_print},
{"chatprint", lib_chatprint},
@ -4151,6 +4161,8 @@ static luaL_Reg lib[] = {
{"G_TicsToCentiseconds",lib_gTicsToCentiseconds},
{"G_TicsToMilliseconds",lib_gTicsToMilliseconds},
{"getTimeMicros",lib_getTimeMicros},
{NULL, NULL}
};

View file

@ -505,7 +505,7 @@ static int call_hooks
calls += call_mobj_type_hooks(hook, MT_NULL);
calls += call_mobj_type_hooks(hook, hook->mobj_type);
ps_lua_mobjhooks += calls;
ps_lua_mobjhooks.value.i += calls;
}
else
calls += call_mapped(hook, &hookIds[hook->hook_type]);
@ -868,7 +868,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, sector, META_SECTOR);
ps_lua_mobjhooks += call_hooks(&hook, 0, res_none);
ps_lua_mobjhooks.value.i += call_hooks(&hook, 0, res_none);
}
}

View file

@ -265,7 +265,7 @@ static int hudinfo_num(lua_State *L)
static int colormap_get(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
UINT32 i = luaL_checkinteger(L, 2);
if (i >= 256)
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
@ -273,23 +273,6 @@ static int colormap_get(lua_State *L)
return 1;
}
static int colormap_set(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
UINT32 i = luaL_checkinteger(L, 2);
if (i >= 256)
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
colormap[i] = (UINT8)luaL_checkinteger(L, 3);
return 0;
}
static int colormap_free(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
Z_Free(colormap);
return 0;
}
static int patch_get(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
@ -1057,7 +1040,7 @@ static int libd_getColormap(lua_State *L)
// all was successful above, now we generate the colormap at last!
colormap = R_GetTranslationColormap(skinnum, color, 0);
colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE);
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1;
}
@ -1066,14 +1049,10 @@ static int libd_getStringColormap(lua_State *L)
{
INT32 flags = luaL_checkinteger(L, 1);
UINT8* colormap = NULL;
UINT8* lua_colormap = NULL;
HUDONLY
colormap = V_GetStringColormap(flags & V_CHARCOLORMASK);
if (colormap) {
lua_colormap = Z_Malloc(256 * sizeof(UINT8), PU_LUA, NULL);
memcpy(lua_colormap, colormap, 256 * sizeof(UINT8));
LUA_PushUserdata(L, lua_colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1;
}
return 0;
@ -1348,12 +1327,6 @@ int LUA_HudLib(lua_State *L)
luaL_newmetatable(L, META_COLORMAP);
lua_pushcfunction(L, colormap_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, colormap_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, colormap_free);
lua_setfield(L, -2, "__gc");
lua_pop(L,1);
luaL_newmetatable(L, META_PATCH);

View file

@ -204,7 +204,7 @@ enum ffloor_e {
ffloor_next,
ffloor_prev,
ffloor_alpha,
ffloor_specialflags,
ffloor_bustflags,
ffloor_busttype,
ffloor_busttag,
ffloor_sinkspeed,
@ -228,7 +228,7 @@ static const char *const ffloor_opt[] = {
"next",
"prev",
"alpha",
"specialflags",
"bustflags",
"busttype",
"busttag",
"sinkspeed",
@ -1851,8 +1851,8 @@ static int ffloor_get(lua_State *L)
case ffloor_alpha:
lua_pushinteger(L, ffloor->alpha);
return 1;
case ffloor_specialflags:
lua_pushinteger(L, ffloor->specialflags);
case ffloor_bustflags:
lua_pushinteger(L, ffloor->bustflags);
return 1;
case ffloor_busttype:
lua_pushinteger(L, ffloor->busttype);

View file

@ -3215,7 +3215,7 @@ boolean M_Responder(event_t *ev)
if (gamestate == GS_TITLESCREEN && finalecount < TICRATE)
return false;
if (CON_Ready())
if (CON_Ready() && gamestate != GS_WAITINGPLAYERS)
return false;
if (noFurtherInput)
@ -4062,14 +4062,6 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop)
for (i = 1; i < SLIDER_RANGE; i++)
V_DrawScaledPatch (x+i*8, y, 0,p);
if (ontop)
{
V_DrawCharacter(x - 6 - (skullAnimCounter/5), y,
'\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(x+i*8 + 8 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
}
p = W_CachePatchName("M_SLIDER", PU_PATCH);
V_DrawScaledPatch(x+i*8, y, 0, p);
@ -4105,6 +4097,16 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop)
range = 100;
V_DrawMappedPatch(x + 2 + (SLIDER_RANGE*8*range)/100, y, 0, p, yellowmap);
if (ontop)
{
V_DrawCharacter(x - 6 - (skullAnimCounter/5), y,
'\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(x + 80 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
V_DrawCenteredString(x + 40, y, V_30TRANS,
(cv->flags & CV_FLOAT) ? va("%.2f", FIXED_TO_FLOAT(cv->value)) : va("%d", cv->value));
}
}
//
@ -6410,6 +6412,7 @@ static void M_Addons(INT32 choice)
M_SetupNextMenu(&MISC_AddonsDef);
}
#ifdef ENFORCE_WAD_LIMIT
#define width 4
#define vpadding 27
#define h (BASEVIDHEIGHT-(2*vpadding))
@ -6457,6 +6460,7 @@ static void M_DrawTemperature(INT32 x, fixed_t t)
#undef vpadding
#undef h
#undef NUMCOLOURS
#endif
static char *M_AddonsHeaderPath(void)
{
@ -6550,21 +6554,20 @@ static void M_DrawAddons(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, LOCATIONSTRING1);
// (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)
#ifdef ENFORCE_WAD_LIMIT
if (numwadfiles <= mainwads+1)
y = 0;
else if (numwadfiles >= MAX_WADFILES)
y = FRACUNIT;
else
{
x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))<<FRACBITS, ((ssize_t)MAX_WADFILES - (ssize_t)(mainwads+1))<<FRACBITS);
y = FixedDiv((((ssize_t)packetsizetally-(ssize_t)mainwadstally)<<FRACBITS), ((((ssize_t)MAXFILENEEDED*sizeof(UINT8)-(ssize_t)mainwadstally)-(5+22))<<FRACBITS)); // 5+22 = (a.ext + checksum length) is minimum addition to packet size tally
if (x > y)
y = x;
y = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))<<FRACBITS, ((ssize_t)MAX_WADFILES - (ssize_t)(mainwads+1))<<FRACBITS);
if (y > FRACUNIT) // happens because of how we're shrinkin' it a little
y = FRACUNIT;
}
M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y);
#endif
// DRAW MENU
x = currentMenu->x;
@ -7187,13 +7190,20 @@ static void M_HandleChecklist(INT32 choice)
static void M_DrawChecklist(void)
{
INT32 i = check_on, j = 0, y = currentMenu->y;
INT32 i = check_on, j = 0, y = currentMenu->y, emblems = numemblems+numextraemblems;
UINT32 condnum, previd, maxcond;
condition_t *cond;
// draw title (or big pic)
M_DrawMenuTitle();
// draw emblem counter
if (emblems > 0)
{
V_DrawString(42, 20, (emblems == M_CountEmblems()) ? V_GREENMAP : 0, va("%d/%d", M_CountEmblems(), emblems));
V_DrawSmallScaledPatch(28, 20, 0, W_CachePatchName("EMBLICON", PU_PATCH));
}
if (check_on)
V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A");
@ -8652,6 +8662,12 @@ static void M_DrawLoad(void)
loadgameoffset = 0;
M_DrawLoadGameData();
if (modifiedgame && !savemoddata)
{
V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING: \x80The game is modified.");
V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved.");
}
}
//
@ -8953,7 +8969,7 @@ static void M_HandleLoadSave(INT32 choice)
break;
case KEY_ENTER:
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT)
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata && !modifiedgame)
{
loadgamescroll = 0;
S_StartSound(NULL, sfx_skid);

File diff suppressed because it is too large Load diff

View file

@ -16,26 +16,45 @@
#include "lua_script.h"
#include "p_local.h"
extern precise_t ps_tictime;
extern precise_t ps_playerthink_time;
extern precise_t ps_thinkertime;
extern precise_t ps_thlist_times[];
extern int ps_checkposition_calls;
extern precise_t ps_lua_thinkframe_time;
extern int ps_lua_mobjhooks;
typedef struct
{
union {
precise_t p;
INT32 i;
} value;
void *history;
} ps_metric_t;
typedef struct
{
precise_t time_taken;
ps_metric_t time_taken;
char short_src[LUA_IDSIZE];
} ps_hookinfo_t;
#define PS_START_TIMING(metric) metric.value.p = I_GetPreciseTime()
#define PS_STOP_TIMING(metric) metric.value.p = I_GetPreciseTime() - metric.value.p
extern ps_metric_t ps_tictime;
extern ps_metric_t ps_playerthink_time;
extern ps_metric_t ps_thinkertime;
extern ps_metric_t ps_thlist_times[];
extern ps_metric_t ps_checkposition_calls;
extern ps_metric_t ps_lua_thinkframe_time;
extern ps_metric_t ps_lua_mobjhooks;
extern ps_metric_t ps_otherlogictime;
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
void PS_UpdateTickStats(void);
void M_DrawPerfStats(void);
void PS_PerfStats_OnChange(void);
void PS_SampleSize_OnChange(void);
#endif

View file

@ -3518,9 +3518,7 @@ void A_Scream(mobj_t *actor)
if (LUA_CallAction(A_SCREAM, actor))
return;
if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL))
S_StartScreamSound(actor, sfx_mario2);
else if (actor->info->deathsound)
if (actor->info->deathsound && !S_SoundPlaying(actor, sfx_mario2))
S_StartScreamSound(actor, actor->info->deathsound);
}
@ -5284,7 +5282,7 @@ void A_OverlayThink(mobj_t *actor)
actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
else
actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
actor->angle = actor->target->angle + actor->movedir;
actor->angle = (actor->target->player ? actor->target->player->drawangle : actor->target->angle) + actor->movedir;
actor->eflags = actor->target->eflags;
actor->momx = actor->target->momx;

View file

@ -988,6 +988,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
case MT_THUNDERCOIN_ORB:
case MT_IVSP:
case MT_SUPERSPARK:
case MT_BOXSPARKLE:
case MT_RAIN:
case MT_SNOWFLAKE:
case MT_SPLISH:

View file

@ -2385,7 +2385,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mobj_t *mo;
if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
P_SetTarget(&target->tracer, inflictor);
S_StartScreamSound(target, sfx_mario2);
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6)
target->player->nightstime = 6; // Just let P_Ticker take care of the rest.
@ -3645,7 +3645,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return true;
}
if (!force && inflictor && inflictor->flags & MF_FIRE)
if (!force && inflictor && inflictor->flags & MF_FIRE && !(damagetype && damagetype != DMG_FIRE))
{
if (player->powers[pw_shield] & SH_PROTECTFIRE)
return false; // Invincible to fire objects

View file

@ -1156,7 +1156,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
return true;
}
@ -2029,7 +2029,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
subsector_t *newsubsec;
boolean blockval = true;
ps_checkposition_calls++;
ps_checkposition_calls.value.i++;
I_Assert(thing != NULL);
#ifdef PARANOIA

View file

@ -78,7 +78,7 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
//
// P_SetupStateAnimation
//
FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
{
INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin)
? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1
@ -1688,7 +1688,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
if (!(rover->flags & FF_BUSTUP))
continue;
if (!(rover->specialflags & FS_PUSHABLES))
if (!(rover->bustflags & FB_PUSHABLES))
continue;
if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
@ -1698,7 +1698,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
// Height checks
if (rover->specialflags & FS_ONLYBOTTOM)
if (rover->bustflags & FB_ONLYBOTTOM)
{
if (mo->z + mo->momz + mo->height < bottomheight)
continue;
@ -1740,7 +1740,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->specialflags & FS_EXECUTOR)
if (rover->bustflags & FB_EXECUTOR)
P_LinedefExecute(rover->busttag, mo, node->m_sector);
goto bustupdone;
@ -3241,8 +3241,8 @@ void P_MobjCheckWater(mobj_t *mobj)
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
continue;
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, sector);
bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, sector);
if (mobj->eflags & MFE_VERTICALFLIP)
{
@ -6842,7 +6842,7 @@ void P_RunOverlays(void)
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = mo->target->scale;
mo->angle = mo->target->angle + mo->movedir;
mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
if (!(mo->state->frame & FF_ANIMATE))
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);

View file

@ -3252,8 +3252,6 @@ static void P_ConvertBinaryMap(void)
case 76: //Make FOF bouncy
lines[i].args[0] = tag;
lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
if (lines[i].flags & ML_BOUNCY)
lines[i].args[2] = 1;
break;
case 100: //FOF: solid, opaque, shadowcasting
case 101: //FOF: solid, opaque, non-shadowcasting

View file

@ -1965,7 +1965,7 @@ void P_SwitchWeather(INT32 weathernum)
continue; // not a precipmobj thinker
precipmobj = (precipmobj_t *)think;
if (weathernum == (PRECIP_RAIN || PRECIP_STORM || PRECIP_STORM_NOSTRIKES)) // Snow To Rain
if (weathernum == PRECIP_RAIN || weathernum == PRECIP_STORM || weathernum == PRECIP_STORM_NOSTRIKES) // Snow To Rain
{
precipmobj->flags = mobjinfo[MT_RAIN].flags;
st = &states[mobjinfo[MT_RAIN].spawnstate];
@ -5880,10 +5880,6 @@ static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline)
rover->flags |= FF_BOUNCY;
rover->spawnflags |= FF_BOUNCY;
rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100;
if (paramline->args[2])
rover->specialflags |= FS_DAMPEN;
else
rover->specialflags &= ~FS_DAMPEN;
CheckForBouncySector = true;
break;
}
@ -6513,7 +6509,7 @@ void P_SpawnSpecials(boolean fromnetsave)
case 254: // Bustable block
{
UINT8 busttype = BT_REGULAR;
ffloorspecialflags_e bustflags = 0;
ffloorbustflags_e bustflags = 0;
ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP;
@ -6536,15 +6532,15 @@ void P_SpawnSpecials(boolean fromnetsave)
//Flags
if (lines[i].args[3] & TMFB_PUSHABLES)
bustflags |= FS_PUSHABLES;
bustflags |= FB_PUSHABLES;
if (lines[i].args[3] & TMFB_EXECUTOR)
bustflags |= FS_EXECUTOR;
bustflags |= FB_EXECUTOR;
if (lines[i].args[3] & TMFB_ONLYBOTTOM)
bustflags |= FS_ONLYBOTTOM;
bustflags |= FB_ONLYBOTTOM;
if (lines[i].args[3] & TMFB_SPLAT)
ffloorflags |= FF_SPLAT;
if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM)
if (busttype != BT_TOUCH || bustflags & FB_ONLYBOTTOM)
ffloorflags |= FF_BLOCKPLAYER;
TAG_ITER_SECTORS(lines[i].args[0], s)
@ -6552,8 +6548,8 @@ void P_SpawnSpecials(boolean fromnetsave)
ffloor_t *fflr = P_AddFakeFloor(&sectors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers);
if (!fflr)
continue;
fflr->bustflags = bustflags;
fflr->busttype = busttype;
fflr->specialflags = bustflags;
fflr->busttag = lines[i].args[4];
}
break;
@ -6613,12 +6609,12 @@ void P_SpawnSpecials(boolean fromnetsave)
}
if (lines[i].args[3] & TMFB_ONLYBOTTOM)
fflr->specialflags |= FS_ONLYBOTTOM;
fflr->bustflags |= FB_ONLYBOTTOM;
if (lines[i].flags & ML_EFFECT4)
fflr->specialflags |= FS_PUSHABLES;
fflr->bustflags |= FB_PUSHABLES;
if (lines[i].flags & ML_EFFECT5)
{
fflr->specialflags |= FS_EXECUTOR;
fflr->bustflags |= FB_EXECUTOR;
fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
}
}
@ -6943,7 +6939,7 @@ void P_SpawnSpecials(boolean fromnetsave)
case 74: // Make FOF bustable
{
UINT8 busttype = BT_REGULAR;
ffloorspecialflags_e bustflags = 0;
ffloorbustflags_e bustflags = 0;
if (!udmf)
break;
@ -6965,11 +6961,11 @@ void P_SpawnSpecials(boolean fromnetsave)
}
if (lines[i].args[2] & TMFB_PUSHABLES)
bustflags |= FS_PUSHABLES;
bustflags |= FB_PUSHABLES;
if (lines[i].args[2] & TMFB_EXECUTOR)
bustflags |= FS_EXECUTOR;
bustflags |= FB_EXECUTOR;
if (lines[i].args[2] & TMFB_ONLYBOTTOM)
bustflags |= FS_ONLYBOTTOM;
bustflags |= FB_ONLYBOTTOM;
TAG_ITER_LINES(lines[i].args[0], l)
{
@ -6987,9 +6983,8 @@ void P_SpawnSpecials(boolean fromnetsave)
rover->flags |= FF_BUSTUP;
rover->spawnflags |= FF_BUSTUP;
rover->bustflags = bustflags;
rover->busttype = busttype;
rover->specialflags &= ~FS_BUSTMASK;
rover->specialflags |= bustflags;
rover->busttag = lines[i].args[3];
CheckForBustableBlocks = true;
break;

View file

@ -329,7 +329,7 @@ static inline void P_RunThinkers(void)
size_t i;
for (i = 0; i < NUM_THINKERLISTS; i++)
{
ps_thlist_times[i] = I_GetPreciseTime();
PS_START_TIMING(ps_thlist_times[i]);
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{
#ifdef PARANOIA
@ -337,7 +337,7 @@ static inline void P_RunThinkers(void)
#endif
currentthinker->function.acp1(currentthinker);
}
ps_thlist_times[i] = I_GetPreciseTime() - ps_thlist_times[i];
PS_STOP_TIMING(ps_thlist_times[i]);
}
}
@ -493,7 +493,7 @@ static inline void P_DoSpecialStageStuff(void)
continue;
// If in water, deplete timer 6x as fast.
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & SH_PROTECTWATER))
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & ((players[i].mo->eflags & MFE_TOUCHLAVA) ? SH_PROTECTFIRE : SH_PROTECTWATER)))
players[i].nightstime -= 5;
if (--players[i].nightstime > 6)
{
@ -659,16 +659,16 @@ void P_Ticker(boolean run)
}
}
ps_lua_mobjhooks = 0;
ps_checkposition_calls = 0;
ps_lua_mobjhooks.value.i = 0;
ps_checkposition_calls.value.i = 0;
LUA_HOOK(PreThinkFrame);
ps_playerthink_time = I_GetPreciseTime();
PS_START_TIMING(ps_playerthink_time);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]);
ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time;
PS_STOP_TIMING(ps_playerthink_time);
}
// Keep track of how long they've been playing!
@ -683,18 +683,18 @@ void P_Ticker(boolean run)
if (run)
{
ps_thinkertime = I_GetPreciseTime();
PS_START_TIMING(ps_thinkertime);
P_RunThinkers();
ps_thinkertime = I_GetPreciseTime() - ps_thinkertime;
PS_STOP_TIMING(ps_thinkertime);
// Run any "after all the other thinkers" stuff
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
ps_lua_thinkframe_time = I_GetPreciseTime();
PS_START_TIMING(ps_lua_thinkframe_time);
LUA_HookThinkFrame();
ps_lua_thinkframe_time = I_GetPreciseTime() - ps_lua_thinkframe_time;
PS_STOP_TIMING(ps_lua_thinkframe_time);
}
// Run shield positioning

View file

@ -777,7 +777,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
UINT8 oldmare, oldmarelap, oldmarebonuslap;
// Bots can't be NiGHTSerized, silly!1 :P
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN)
if (player->bot)
return;
if (player->powers[pw_carry] != CR_NIGHTSMODE)
@ -969,9 +969,6 @@ pflags_t P_GetJumpFlags(player_t *player)
//
boolean P_PlayerInPain(player_t *player)
{
// If the player doesn't have a mobj, it can't be in pain.
if (!player->mo)
return false;
// no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true;
@ -1191,9 +1188,9 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
{
if (!player)
return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
player = player->botleader;
if (player->bot)
player = &players[consoleplayer];
if (!player->mo)
return;
@ -1237,8 +1234,8 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
if (!player)
return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
player = player->botleader;
if (player->bot)
player = &players[consoleplayer];
if (!player->mo)
return;
@ -1264,8 +1261,8 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
if (!player)
return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader)
player = player->botleader;
if (player->bot)
player = &players[consoleplayer];
if (gamestate == GS_LEVEL)
{
@ -2659,7 +2656,7 @@ static void P_CheckBustableBlocks(player_t *player)
}
// Height checks
if (rover->specialflags & FS_ONLYBOTTOM)
if (rover->bustflags & FB_ONLYBOTTOM)
{
if (player->mo->z + player->mo->momz + player->mo->height < bottomheight)
continue;
@ -2713,7 +2710,7 @@ static void P_CheckBustableBlocks(player_t *player)
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->specialflags & FS_EXECUTOR)
if (rover->bustflags & FB_EXECUTOR)
P_LinedefExecute(rover->busttag, player->mo, node->m_sector);
goto bustupdone;
@ -2769,10 +2766,6 @@ static void P_CheckBouncySectors(player_t *player)
{
rover->flags |= FF_BOUNCY;
rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100;
if (rover->master->flags & ML_BOUNCY)
rover->specialflags |= FS_DAMPEN;
else
rover->specialflags &= ~FS_DAMPEN;
}
if (!(rover->flags & FF_BOUNCY))
@ -2792,17 +2785,9 @@ static void P_CheckBouncySectors(player_t *player)
{
player->mo->momx = -FixedMul(player->mo->momx,rover->bouncestrength);
player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength);
if (player->pflags & PF_SPINNING)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
}
else
{
fixed_t newmom;
pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope;
momentum.x = player->mo->momx;
@ -2812,53 +2797,28 @@ static void P_CheckBouncySectors(player_t *player)
if (slope)
P_ReverseQuantizeMomentumToSlope(&momentum, slope);
newmom = momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2;
momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2;
if (abs(newmom) < (rover->bouncestrength*2))
if (abs(momentum.z) < (rover->bouncestrength*2))
goto bouncydone;
if (!(rover->specialflags & FS_DAMPEN))
{
if (newmom > 0)
{
if (newmom < 8*FRACUNIT)
newmom = 8*FRACUNIT;
}
else if (newmom < 0)
{
if (newmom > -8*FRACUNIT)
newmom = -8*FRACUNIT;
}
}
if (newmom > P_GetPlayerHeight(player)/2)
newmom = P_GetPlayerHeight(player)/2;
else if (newmom < -P_GetPlayerHeight(player)/2)
newmom = -P_GetPlayerHeight(player)/2;
momentum.z = newmom*2;
if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height
momentum.z = FixedMul(24*FRACUNIT, player->mo->scale);
else if (momentum.z < -FixedMul(24*FRACUNIT, player->mo->scale))
momentum.z = -FixedMul(24*FRACUNIT, player->mo->scale);
if (slope)
P_QuantizeMomentumToSlope(&momentum, slope);
player->mo->momx = momentum.x;
player->mo->momy = momentum.y;
player->mo->momz = momentum.z/2;
player->mo->momz = momentum.z;
if (player->pflags & PF_SPINNING)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
}
if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<<FRACBITS, player->mo->scale) && player->mo->momz)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
}
goto bouncydone;
}
}

View file

@ -808,7 +808,7 @@ static void R_AddPolyObjects(subsector_t *sub)
}
// for render stats
ps_numpolyobjects += numpolys;
ps_numpolyobjects.value.i += numpolys;
// sort polyobjects
R_SortPolyObjects(sub);
@ -1243,7 +1243,7 @@ void R_RenderBSPNode(INT32 bspnum)
node_t *bsp;
INT32 side;
ps_numbspcalls++;
ps_numbspcalls.value.i++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{

View file

@ -154,12 +154,10 @@ typedef enum
typedef enum
{
FS_PUSHABLES = 0x1, // FF_BUSTABLE: Bustable by pushables
FS_EXECUTOR = 0x2, // FF_BUSTABLE: Trigger linedef executor
FS_ONLYBOTTOM = 0x4, // FF_BUSTABLE: Only bustable from below
FS_BUSTMASK = 0x7,
FS_DAMPEN = 0x8, // FF_BOUNCY: Dampen bounce
} ffloorspecialflags_e;
FB_PUSHABLES = 0x1, // Bustable by pushables
FB_EXECUTOR = 0x2, // Trigger linedef executor
FB_ONLYBOTTOM = 0x4, // Only bustable from below
} ffloorbustflags_e;
typedef enum
{
@ -201,10 +199,8 @@ typedef struct ffloor_s
INT32 alpha;
tic_t norender; // for culling
// Flags that are only relevant for special ffloor types
ffloorspecialflags_e specialflags;
// Only relevant for FF_BUSTUP
ffloorbustflags_e bustflags;
UINT8 busttype;
INT16 busttag;

View file

@ -666,7 +666,6 @@ void R_DrawTiltedSplat_NPO2_8(void)
for (; width != 0; width--)
{
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u) >> FRACBITS);

View file

@ -101,21 +101,22 @@ extracolormap_t *extra_colormaps = NULL;
// Render stats
precise_t ps_prevframetime = 0;
precise_t ps_rendercalltime = 0;
precise_t ps_uitime = 0;
precise_t ps_swaptime = 0;
ps_metric_t ps_rendercalltime = {0};
ps_metric_t ps_otherrendertime = {0};
ps_metric_t ps_uitime = {0};
ps_metric_t ps_swaptime = {0};
precise_t ps_bsptime = 0;
ps_metric_t ps_bsptime = {0};
precise_t ps_sw_spritecliptime = 0;
precise_t ps_sw_portaltime = 0;
precise_t ps_sw_planetime = 0;
precise_t ps_sw_maskedtime = 0;
ps_metric_t ps_sw_spritecliptime = {0};
ps_metric_t ps_sw_portaltime = {0};
ps_metric_t ps_sw_planetime = {0};
ps_metric_t ps_sw_maskedtime = {0};
int ps_numbspcalls = 0;
int ps_numsprites = 0;
int ps_numdrawnodes = 0;
int ps_numpolyobjects = 0;
ps_metric_t ps_numbspcalls = {0};
ps_metric_t ps_numsprites = {0};
ps_metric_t ps_numdrawnodes = {0};
ps_metric_t ps_numpolyobjects = {0};
static CV_PossibleValue_t drawdist_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"},
@ -1496,11 +1497,11 @@ void R_RenderPlayerView(player_t *player)
mytotal = 0;
ProfZeroTimer();
#endif
ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0;
ps_bsptime = I_GetPreciseTime();
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1);
ps_bsptime = I_GetPreciseTime() - ps_bsptime;
ps_numsprites = visspritecount;
PS_STOP_TIMING(ps_bsptime);
ps_numsprites.value.i = visspritecount;
#ifdef TIMING
RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add
@ -1510,9 +1511,9 @@ void R_RenderPlayerView(player_t *player)
//profile stuff ---------------------------------------------------------
Mask_Post(&masks[nummasks - 1]);
ps_sw_spritecliptime = I_GetPreciseTime();
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites(drawsegs, NULL);
ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime;
PS_STOP_TIMING(ps_sw_spritecliptime);
// Add skybox portals caused by sky visplanes.
@ -1520,7 +1521,7 @@ void R_RenderPlayerView(player_t *player)
Portal_AddSkyboxPortals();
// Portal rendering. Hijacks the BSP traversal.
ps_sw_portaltime = I_GetPreciseTime();
PS_START_TIMING(ps_sw_portaltime);
if (portal_base)
{
portal_t *portal;
@ -1560,17 +1561,17 @@ void R_RenderPlayerView(player_t *player)
Portal_Remove(portal);
}
}
ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime;
PS_STOP_TIMING(ps_sw_portaltime);
ps_sw_planetime = I_GetPreciseTime();
PS_START_TIMING(ps_sw_planetime);
R_DrawPlanes();
ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime;
PS_STOP_TIMING(ps_sw_planetime);
// draw mid texture and sprite
// And now 3D floors/sides!
ps_sw_maskedtime = I_GetPreciseTime();
PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked(masks, nummasks);
ps_sw_maskedtime = I_GetPreciseTime() - ps_sw_maskedtime;
PS_STOP_TIMING(ps_sw_maskedtime);
free(masks);
}

View file

@ -17,6 +17,7 @@
#include "d_player.h"
#include "r_data.h"
#include "r_textures.h"
#include "m_perfstats.h" // ps_metric_t
//
// POV related.
@ -79,21 +80,22 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
// Render stats
extern precise_t ps_prevframetime;// time when previous frame was rendered
extern precise_t ps_rendercalltime;
extern precise_t ps_uitime;
extern precise_t ps_swaptime;
extern ps_metric_t ps_rendercalltime;
extern ps_metric_t ps_otherrendertime;
extern ps_metric_t ps_uitime;
extern ps_metric_t ps_swaptime;
extern precise_t ps_bsptime;
extern ps_metric_t ps_bsptime;
extern precise_t ps_sw_spritecliptime;
extern precise_t ps_sw_portaltime;
extern precise_t ps_sw_planetime;
extern precise_t ps_sw_maskedtime;
extern ps_metric_t ps_sw_spritecliptime;
extern ps_metric_t ps_sw_portaltime;
extern ps_metric_t ps_sw_planetime;
extern ps_metric_t ps_sw_maskedtime;
extern int ps_numbspcalls;
extern int ps_numsprites;
extern int ps_numdrawnodes;
extern int ps_numpolyobjects;
extern ps_metric_t ps_numbspcalls;
extern ps_metric_t ps_numsprites;
extern ps_metric_t ps_numdrawnodes;
extern ps_metric_t ps_numpolyobjects;
//
// REFRESH - the actual rendering functions.

View file

@ -227,8 +227,8 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
ox = (newwidth / 2) + (leftoffset - xpivot);
oy = (newheight / 2) + (patch->topoffset - ypivot);
width = (maxx - minx);
height = (maxy - miny);
width = (maxx+1 - minx);
height = (maxy+1 - miny);
if ((unsigned)(width * height) != size)
{

View file

@ -318,7 +318,7 @@ static visplane_t *new_visplane(unsigned hash)
visplane_t *check = freetail;
if (!check)
{
check = calloc(2, sizeof (*check));
check = malloc(sizeof (*check));
if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly
}
else

View file

@ -2745,7 +2745,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link)
node->ffloor = NULL;
node->sprite = NULL;
ps_numdrawnodes++;
ps_numdrawnodes.value.i++;
return node;
}

View file

@ -2163,7 +2163,13 @@ precise_t I_GetPreciseTime(void)
int I_PreciseToMicros(precise_t d)
{
return (int)(d / (timer_frequency / 1000000.0));
// d is going to be converted into a double. So remove the highest bits
// to avoid loss of precision in the lower bits, for the (probably rare) case
// that the higher bits are actually used.
d &= ((precise_t)1 << 53) - 1; // The mantissa of a double can handle 53 bits at most.
// The resulting double from the calculation is converted first to UINT64 to avoid overflow,
// which is undefined behaviour when converting floating point values to integers.
return (int)(UINT64)(d / (timer_frequency / 1000000.0));
}
//

View file

@ -409,11 +409,6 @@ void I_UpdateMouseGrab(void)
SDLdoGrabMouse();
}
boolean I_GetMouseGrab(void)
{
return (boolean)SDL_GetWindowGrab(window);
}
void I_SetMouseGrab(boolean grab)
{
if (grab)

View file

@ -2037,9 +2037,8 @@ static void ST_drawNiGHTSHUD(void)
else
numbersize = 48/2;
if ((oldspecialstage && leveltime & 2)
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
&& !(stplyr->powers[pw_shield] & SH_PROTECTWATER))
if ((oldspecialstage && leveltime & 2) &&
(stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(stplyr->powers[pw_shield] & ((stplyr->mo->eflags & MFE_TOUCHLAVA) ? SH_PROTECTFIRE : SH_PROTECTWATER))))
col = SKINCOLOR_ORANGE;
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, col);
@ -2188,7 +2187,7 @@ static void ST_drawMatchHUD(void)
{
sprintf(penaltystr, "-%d", stplyr->ammoremoval);
V_DrawString(offset + 8 + stplyr->ammoremovalweapon * 20, y,
V_REDMAP|V_SNAPTOBOTTOM, penaltystr);
V_REDMAP|V_SNAPTOBOTTOM|V_PERPLAYER, penaltystr);
}
}

View file

@ -105,7 +105,7 @@ static UINT16 lumpnumcacheindex = 0;
// GLOBALS
//===========================================================================
UINT16 numwadfiles; // number of active wadfiles
wadfile_t *wadfiles[MAX_WADFILES]; // 0 to numwadfiles-1 are valid
wadfile_t **wadfiles; // 0 to numwadfiles-1 are valid
// W_Shutdown
// Closes all of the WAD files before quitting
@ -134,6 +134,8 @@ void W_Shutdown(void)
Z_Free(wad->lumpinfo);
Z_Free(wad);
}
Z_Free(wadfiles);
}
//===========================================================================
@ -844,7 +846,6 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
#ifndef NOMD5
size_t i;
#endif
size_t packetsize;
UINT8 md5sum[16];
int important;
@ -862,9 +863,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
refreshdirname = NULL;
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
//
// check if limit of active wadfiles
//
// Check if the game reached the limit of active wadfiles.
if (numwadfiles >= MAX_WADFILES)
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
@ -884,24 +884,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
return INT16_MAX;
}
// Check if wad files will overflow fileneededbuffer. Only the filename part
// is send in the packet; cf.
// see PutFileNeeded in d_netfil.c
if ((important = !important))
{
packetsize = packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE;
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
if (handle)
fclose(handle);
return W_InitFileError(filename, startup);
}
packetsizetally = packetsize;
}
important = !important;
#ifndef NOMD5
//
@ -913,11 +896,12 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
for (i = 0; i < numwadfiles; i++)
{
if (wadfiles[i]->type == RET_FOLDER)
continue;
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (important)
packetsizetally -= nameonlylength(filename) + FILENEEDEDSIZE;
if (handle)
fclose(handle);
return W_InitFileError(filename, false);
@ -984,6 +968,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
// add the wadfile
//
CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps);
wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t) * (numwadfiles + 1), PU_STATIC, NULL);
wadfiles[numwadfiles] = wadfile;
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
@ -1046,22 +1031,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
return W_InitFileError(path, startup);
}
important = 0; // ???
/// \todo Implement a W_VerifyFolder.
if ((important = !important))
{
size_t packetsize = packetsizetally + strlen(path) + FILENEEDEDSIZE;
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
return W_InitFileError(path, startup);
}
packetsizetally = packetsize;
}
important = 0; /// \todo Implement a W_VerifyFolder.
// Remove path delimiters.
p = path + (strlen(path) - 1);
@ -1132,8 +1102,6 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
if (samepaths(wadfiles[i]->path, fullpath) > 0)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path);
if (important)
packetsizetally -= strlen(path) + FILENEEDEDSIZE;
Z_Free(fn);
Z_Free(fullpath);
return W_InitFileError(path, false);
@ -1197,11 +1165,13 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
*
* \param filenames A null-terminated list of files to use.
*/
void W_InitMultipleFiles(char **filenames)
void W_InitMultipleFiles(addfilelist_t *list)
{
for (; *filenames; filenames++)
size_t i = 0;
for (; i < list->numfiles; i++)
{
const char *fn = (*filenames);
const char *fn = list->files[i];
char pathsep = fn[strlen(fn) - 1];
boolean mainfile = (numwadfiles < mainwads);
@ -1219,7 +1189,7 @@ void W_InitMultipleFiles(char **filenames)
*/
static boolean TestValidLump(UINT16 wad, UINT16 lump)
{
I_Assert(wad < MAX_WADFILES);
I_Assert(wad < numwadfiles);
if (!wadfiles[wad]) // make sure the wad file exists
return false;
@ -1636,7 +1606,7 @@ size_t W_LumpLength(lumpnum_t lumpnum)
//
// W_IsLumpWad
// Is the lump a WAD? (presumably in a PK3)
// Is the lump a WAD? (presumably not in a WAD)
//
boolean W_IsLumpWad(lumpnum_t lumpnum)
{
@ -1649,12 +1619,12 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4);
}
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned
return false; // WADs should never be inside WADs as far as SRB2 is concerned
}
//
// W_IsLumpFolder
// Is the lump a folder? (in a PK3 obviously)
// Is the lump a folder? (not in a WAD obviously)
//
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
{
@ -1665,7 +1635,7 @@ boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
return (name[strlen(name)-1] == '/'); // folders end in '/'
}
return false; // non-PK3s don't have folders
return false; // WADs don't have folders
}
#ifdef HAVE_ZLIB
@ -2217,7 +2187,7 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
#else
I_Error
#endif
(M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);
(M_GetText("File is old, is corrupt or has been modified:\n%s\nFound MD5: %s\nWanted MD5: %s\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);
}
#endif
}

View file

@ -97,9 +97,15 @@ virtlump_t* vres_Find(const virtres_t*, const char*);
// DYNAMIC WAD LOADING
// =========================================================================
// Maximum of files that can be loaded
// (there is a max of simultaneous open files anyway)
#ifdef ENFORCE_WAD_LIMIT
#define MAX_WADFILES 2048 // This cannot be any higher than UINT16_MAX.
#else
#define MAX_WADFILES UINT16_MAX
#endif
#define MAX_WADPATH 512
#define MAX_WADFILES 48 // maximum of wad files used at the same time
// (there is a max of simultaneous open files anyway, and this should be plenty)
#define lumpcache_t void *
@ -134,7 +140,13 @@ typedef struct wadfile_s
#define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad
extern UINT16 numwadfiles;
extern wadfile_t *wadfiles[MAX_WADFILES];
extern wadfile_t **wadfiles;
typedef struct
{
char **files;
size_t numfiles;
} addfilelist_t;
// =========================================================================
@ -148,7 +160,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup);
// W_InitMultipleFiles exits if a file was not found, but not if all is okay.
void W_InitMultipleFiles(char **filenames);
void W_InitMultipleFiles(addfilelist_t *list);
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER)

View file

@ -239,12 +239,12 @@ void Y_LoadIntermissionData(void)
}
data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH);
// get background patches
bgpatch = W_CachePatchName("INTERSCR", PU_PATCH);
// grab an interscreen if appropriate
if (mapheaderinfo[gamemap-1]->interscreen[0] != '#')
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH);
else // no interscreen? use default background
bgpatch = W_CachePatchName("INTERSCR", PU_PATCH);
break;
}
case int_spec:
@ -255,12 +255,11 @@ void Y_LoadIntermissionData(void)
data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH);
data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH);
// get background tile
bgtile = W_CachePatchName("SPECTILE", PU_PATCH);
// grab an interscreen if appropriate
if (mapheaderinfo[gamemap-1]->interscreen[0] != '#')
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH);
else // no interscreen? use default background
bgtile = W_CachePatchName("SPECTILE", PU_PATCH);
break;
}
case int_ctf:

View file

@ -39,6 +39,7 @@ enum
// Tags < PU_LEVEL are not purged until freed explicitly.
PU_STATIC = 1, // static entire execution time
PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever
PU_PERFSTATS = 3, // static between changes to ps_samplesize cvar
PU_SOUND = 11, // static while playing
PU_MUSIC = 12, // static while playing