Merge branch 'master' into acs

This commit is contained in:
Sally Coolatta 2022-11-14 11:19:42 -05:00
commit 5b49f8a492
42 changed files with 480 additions and 273 deletions

View file

@ -1080,9 +1080,10 @@ static void COM_Toggle_f(void)
for (i = 2; i < COM_Argc() - 1; ++i)
{
const char *str = COM_Argv(i);
INT32 val;
INT32 val = 0;
if (CV_CompleteValue(cvar, &str, &val))
if (!cvar->PossibleValue ||
CV_CompleteValue(cvar, &str, &val))
{
if (str ? !stricmp(cvar->string, str)
: cvar->value == val)

View file

@ -581,7 +581,7 @@ static inline void CL_DrawConnectionStatus(void)
// Draw bottom box
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort");
for (i = 0; i < 16; ++i)
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15));
@ -644,7 +644,7 @@ static inline void CL_DrawConnectionStatus(void)
INT32 checkednum = 0;
INT32 i;
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort");
//ima just count files here
for (i = 0; i < fileneedednum; i++)
@ -666,7 +666,7 @@ static inline void CL_DrawConnectionStatus(void)
INT32 loadcompletednum = 0;
INT32 i;
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort");
//ima just count files here
for (i = 0; i < fileneedednum; i++)
@ -693,7 +693,7 @@ static inline void CL_DrawConnectionStatus(void)
// Draw the bottom box.
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-58-8, 32, 1);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press ESC to abort");
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press (B) to abort");
Net_GetNetStat();
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
@ -757,7 +757,7 @@ static inline void CL_DrawConnectionStatus(void)
//Draw bottom box
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press (B) to abort");
for (i = 0; i < 16; ++i)
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15));
@ -1483,11 +1483,9 @@ void CL_UpdateServerList (void)
SendAskInfo(BROADCASTADDR);
}
static void M_ConfirmConnect(event_t *ev)
static void M_ConfirmConnect(void)
{
if (ev->type == ev_keydown)
{
if (G_PlayerInputDown(0, gc_a, 1))
if (G_PlayerInputDown(0, gc_a, 1) || gamekeydown[0][KEY_ENTER])
{
if (totalfilesrequestednum > 0)
{
@ -1508,13 +1506,12 @@ static void M_ConfirmConnect(event_t *ev)
else
cl_mode = CL_LOADFILES;
M_ClearMenus(true);
M_StopMessage(0);
}
else if (G_PlayerInputDown(0, gc_x, 1))
else if (G_PlayerInputDown(0, gc_b, 1) || G_PlayerInputDown(0, gc_x, 1) || gamekeydown[0][KEY_ESCAPE])
{
cl_mode = CL_ABORTED;
M_ClearMenus(true);
}
M_StopMessage(0);
}
}
@ -1537,7 +1534,7 @@ static boolean CL_FinishedFileList(void)
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart Ring Racers before connecting.\n\n"
"Press ESC\n"
"Press (B)\n"
), NULL, MM_NOTHING);
return false;
}
@ -1552,7 +1549,7 @@ static boolean CL_FinishedFileList(void)
"the game and don't load any addons.\n"
"Ring Racers will automatically add\n"
"everything you need when you join.\n\n"
"Press ESC\n"
"Press (B)\n"
), NULL, MM_NOTHING);
return false;
}
@ -1565,8 +1562,8 @@ static boolean CL_FinishedFileList(void)
"\n"
"You may load server addons (if any), and wait for a slot.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), FUNCPTRCAST (M_ConfirmConnect), MM_EVENTHANDLER);
"Press (A) to continue or (B) to cancel\n"
), NULL, MM_NOTHING);
cl_mode = CL_CONFIRMCONNECT;
}
else
@ -1592,7 +1589,7 @@ static boolean CL_FinishedFileList(void)
"with the server, not your game.)\n\n"
"See the console or log file\n"
"for additional details.\n\n"
"Press ESC\n"
"Press (B)\n"
), NULL, MM_NOTHING);
return false;
}
@ -1622,18 +1619,21 @@ static boolean CL_FinishedFileList(void)
if (serverisfull)
M_StartMessage(va(M_GetText(
"This server is full!\n"
"Download of %s additional content is required to join.\n"
"Download of %s additional content\n"
"is required to join.\n"
"\n"
"You may download, load server addons, and wait for a slot.\n"
"You may download, load server addons,\n"
"and wait for a slot.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), downloadsize), FUNCPTRCAST(M_ConfirmConnect), MM_EVENTHANDLER);
"Press (A) to continue or (B) to cancel\n"
), downloadsize), NULL, MM_NOTHING);
else
M_StartMessage(va(M_GetText(
"Download of %s additional content is required to join.\n"
"Download of %s additional content\n"
"is required to join.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), downloadsize), FUNCPTRCAST(M_ConfirmConnect), MM_EVENTHANDLER);
"Press (A) to continue or (B) to cancel\n"
), downloadsize), NULL, MM_NOTHING);
Z_Free(downloadsize);
cl_mode = CL_CONFIRMCONNECT;
@ -1870,7 +1870,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
"5 minute wait time exceeded.\n"
"You may retry connection.\n"
"\n"
"Press ESC\n"
"Press (B)\n"
), NULL, MM_NOTHING);
return false;
}
@ -1921,28 +1921,40 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
I_OsPolling();
// Needs to be updated here for M_DrawEggaChannel
renderdeltatics = FRACUNIT;
rendertimefrac = FRACUNIT;
memset(deviceResponding, false, sizeof (deviceResponding));
if (cl_mode == CL_CONFIRMCONNECT)
{
D_ProcessEvents(); //needed for menu system to receive inputs
}
else
if (netgame)
{
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
{
G_MapEventsToControls(&events[eventtail]);
}
if (G_PlayerInputDown(0, gc_x, 1) || cl_mode == CL_ABORTED)
if (cl_mode == CL_CONFIRMCONNECT)
{
M_ConfirmConnect();
}
else
{
if (G_PlayerInputDown(0, gc_b, 1)
|| G_PlayerInputDown(0, gc_x, 1)
|| gamekeydown[0][KEY_ESCAPE])
cl_mode = CL_ABORTED;
}
}
if (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 (B)\n"), NULL, MM_NOTHING);
D_QuitNetGame();
CL_Reset();
D_StartTitle();
memset(gamekeydown, 0, sizeof (gamekeydown));
memset(deviceResponding, false, sizeof (deviceResponding));
return false;
}
@ -1959,17 +1971,20 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME)
{
F_TitleScreenTicker(true);
F_TitleScreenDrawer();
M_DrawEggaChannel();
}
CL_DrawConnectionStatus();
if (cl_mode == CL_CONFIRMCONNECT)
{
#ifdef HAVE_THREADS
I_lock_mutex(&k_menu_mutex);
#endif
M_Drawer(); //Needed for drawing messageboxes on the connection screen
M_DrawMenuMessage();
#ifdef HAVE_THREADS
I_unlock_mutex(k_menu_mutex);
#endif
}
I_UpdateNoVsync(); // page flip or blit buffer
if (moviemode)
M_SaveFrame();
@ -2017,16 +2032,21 @@ static void CL_ConnectToServer(void)
}
if (cv_currprofile.value == -1)
{
PR_ApplyProfilePretend(cv_ttlprofilen.value, 0);
for (i = 1; i < cv_splitplayers.value; i++)
{
PR_ApplyProfile(cv_lastprofile[i].value, i);
}
}
if (gamestate == GS_INTERMISSION)
Y_EndIntermission(); // clean up intermission graphics etc
if (gamestate == GS_VOTING)
Y_EndVote();
DEBFILE(va("waiting %d nodes\n", doomcom->numnodes));
G_SetGamestate(GS_WAITINGPLAYERS);
if (wipegamestate == GS_MENU)
M_ClearMenus(true);
G_SetGamestate(GS_WAITINGPLAYERS);
wipegamestate = GS_WAITINGPLAYERS;
ClearAdminPlayers();
@ -2391,33 +2411,6 @@ static void Command_connect(void)
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
return;
}
else if (cv_currprofile.value == 0)
{
CONS_Printf(M_GetText("You cannot connect while using the Guest Profile. Use a Custom Profile to play Online.\n"));
return;
}
else if (cv_currprofile.value == -1)
{
// No profile set, we're attempting to connect from the title screen. (Discord RPC / connect command)
// Automatically apply the last profiles for every potential split player.
// Make sure Player 1's Profile ISN'T the guest profile even if we do that.
UINT8 i;
CONS_Printf(M_GetText("No Profile set, attempting to use last used Profiles...\n"));
for (i = 0; i < cv_splitplayers.value; i++)
{
if (cv_lastprofile[i].value || i > 0)
PR_ApplyProfile(cv_lastprofile[i].value, i);
else
{
CONS_Printf(M_GetText("Player 1's last used Profile is the Guest Profile, which cannot be used to play Online.\n"));
return;
}
}
CONS_Printf(M_GetText("Profiles have been automatically set according to the last used Profiles.\n"));
}
// modified game check: no longer handled
// we don't request a restart unless the filelist differs
@ -2480,7 +2473,6 @@ static void Command_connect(void)
SplitScreen_OnChange();
}
M_ClearMenus(true);
CL_ConnectToServer();
}
@ -3096,17 +3088,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
D_StartTitle();
if (msg == KICK_MSG_CON_FAIL)
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress (B)\n"), NULL, MM_NOTHING);
else if (msg == KICK_MSG_PING_HIGH)
M_StartMessage(M_GetText("Server closed connection\n(Broke delay limit)\nPress ESC\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("Server closed connection\n(Broke delay limit)\nPress (B)\n"), NULL, MM_NOTHING);
else if (msg == KICK_MSG_BANNED)
M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("You have been banned by the server\n\nPress (B)\n"), NULL, MM_NOTHING);
else if (msg == KICK_MSG_CUSTOM_KICK)
M_StartMessage(va(M_GetText("You have been kicked\n(%s)\n\nPress ESC\n"), reason), NULL, MM_NOTHING);
M_StartMessage(va(M_GetText("You have been kicked\n(%s)\nPress (B)\n"), reason), NULL, MM_NOTHING);
else if (msg == KICK_MSG_CUSTOM_BAN)
M_StartMessage(va(M_GetText("You have been banned\n(%s)\n\nPress ESC\n"), reason), NULL, MM_NOTHING);
M_StartMessage(va(M_GetText("You have been banned\n(%s)\nPress (B)\n"), reason), NULL, MM_NOTHING);
else
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress (B)\n"), NULL, MM_NOTHING);
}
else if (server)
{
@ -3935,6 +3927,11 @@ static void HandleConnect(SINT8 node)
// If a server filled out, then it'd overwrite the host and turn everyone into weird husks.....
// It's too much effort to legimately fix right now. Just prevent it from reaching that state.
UINT8 maxplayers = min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxconnections.value);
UINT8 connectedplayers = 0;
for (i = dedicated ? 1 : 0; i < MAXPLAYERS; i++)
if (playernode[i] != UINT8_MAX) // We use this to count players because it is affected by SV_AddWaitingPlayers when more than one client joins on the same tic, unlike playeringame and D_NumPlayers. UINT8_MAX denotes no node for that player
connectedplayers++;
if (bannednode && bannednode[node].banid != SIZE_MAX)
{
@ -3992,7 +3989,7 @@ static void HandleConnect(SINT8 node)
{
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment."));
}
else if (D_NumPlayers() >= maxplayers)
else if (connectedplayers >= maxplayers)
{
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), maxplayers));
}
@ -4000,7 +3997,7 @@ static void HandleConnect(SINT8 node)
{
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
}
else if (netgame && D_NumPlayers() + netbuffer->u.clientcfg.localplayers > maxplayers)
else if (netgame && connectedplayers + netbuffer->u.clientcfg.localplayers > maxplayers)
{
SV_SendRefuse(node, va(M_GetText("Number of local players\nwould exceed maximum: %d"), maxplayers));
}
@ -4084,7 +4081,7 @@ static void HandleShutdown(SINT8 node)
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("Server has shutdown\n\nPress (B)\n"), NULL, MM_NOTHING);
}
/** Called when a PT_NODETIMEOUT packet is received
@ -4099,7 +4096,7 @@ static void HandleTimeout(SINT8 node)
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING);
M_StartMessage(M_GetText("Server Timeout\n\nPress (B)\n"), NULL, MM_NOTHING);
}
/** Called when a PT_SERVERINFO packet is received
@ -5483,14 +5480,6 @@ boolean TryRunTics(tic_t realtics)
if (ticking)
{
if (advancedemo)
{
if (timedemo_quit)
COM_ImmedExecute("quit");
else
D_StartTitle();
}
else
{
// run the count * tics
while (neededtic > gametic)

View file

@ -132,7 +132,6 @@ INT32 postimgparam[MAXSPLITSCREENPLAYERS];
boolean sound_disabled = false;
boolean digital_disabled = false;
boolean advancedemo;
#ifdef DEBUGFILE
INT32 debugload = 0;
#endif
@ -914,15 +913,6 @@ void D_SRB2Loop(void)
}
}
//
// D_AdvanceDemo
// Called after each demo or intro demosequence finishes
//
void D_AdvanceDemo(void)
{
advancedemo = true;
}
// =========================================================================
// D_SRB2Main
// =========================================================================
@ -998,7 +988,11 @@ void D_StartTitle(void)
//demosequence = -1;
G_SetGametype(GT_RACE); // SRB2kart
paused = false;
advancedemo = false;
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
memset(deviceResponding, false, sizeof (deviceResponding));
F_StartTitleScreen();
// Reset the palette
@ -1208,7 +1202,7 @@ D_ConvertVersionNumbers (void)
//
void D_SRB2Main(void)
{
INT32 p;
INT32 i, p;
INT32 numbasemapheaders;
@ -1772,6 +1766,11 @@ void D_SRB2Main(void)
// ttlprofilen used because it's roughly equivalent in functionality - a QoL aid for quickly getting from startup to action
PR_ApplyProfile(cv_ttlprofilen.value, 0);
for (i = 1; i < cv_splitplayers.value; i++)
{
PR_ApplyProfile(cv_lastprofile[i].value, i);
}
if (autostart || netgame)
{
gameaction = ga_nothing;

View file

@ -18,8 +18,6 @@
#include "d_event.h"
#include "w_wad.h" // for MAX_WADFILES
extern boolean advancedemo;
// make sure not to write back the config until it's been correctly loaded
extern tic_t rendergametic;
@ -52,7 +50,6 @@ const char *D_Home(void);
//
// BASE LEVEL
//
void D_AdvanceDemo(void);
void D_StartTitle(void);
#endif //__D_MAIN__

View file

@ -986,6 +986,9 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_bsaturation);
CV_RegisterVar(&cv_msaturation);
CV_RegisterVar(&cv_palette);
CV_RegisterVar(&cv_palettenum);
// k_menu.c
//CV_RegisterVar(&cv_compactscoreboard);
CV_RegisterVar(&cv_chatheight);
@ -1089,6 +1092,7 @@ void D_RegisterClientCommands(void)
COM_AddCommand("rteleport", Command_RTeleport_f);
COM_AddCommand("skynum", Command_Skynum_f);
COM_AddCommand("weather", Command_Weather_f);
COM_AddCommand("grayscale", Command_Grayscale_f);
#ifdef _DEBUG
COM_AddCommand("causecfail", Command_CauseCfail_f);
#endif

View file

@ -224,7 +224,10 @@ void readfreeslots(MYFILE *f)
// TODO: Out-of-slots warnings/errors.
// TODO: Name too long (truncated) warnings.
if (fastcmp(type, "SFX"))
{
CONS_Printf("Sound sfx_%s allocated.\n",word);
S_AddSoundFx(word, false, 0, false);
}
else if (fastcmp(type, "SPR"))
{
for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++)
@ -238,39 +241,54 @@ void readfreeslots(MYFILE *f)
// Found a free slot!
strncpy(sprnames[i],word,4);
//sprnames[i][4] = 0;
CONS_Printf("Sprite SPR_%s allocated.\n",word);
used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now.
break;
}
if (i > SPR_LASTFREESLOT)
I_Error("Out of Sprite Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
}
else if (fastcmp(type, "S"))
{
for (i = 0; i < NUMSTATEFREESLOTS; i++)
if (!FREE_STATES[i]) {
CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word);
freeslotusage[0][0]++;
break;
}
if (i == NUMSTATEFREESLOTS)
I_Error("Out of State Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
}
else if (fastcmp(type, "MT"))
{
for (i = 0; i < NUMMOBJFREESLOTS; i++)
if (!FREE_MOBJS[i]) {
CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word);
freeslotusage[1][0]++;
break;
}
if (i == NUMMOBJFREESLOTS)
I_Error("Out of Mobj Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
}
else if (fastcmp(type, "SKINCOLOR"))
{
for (i = 0; i < NUMCOLORFREESLOTS; i++)
if (!FREE_SKINCOLORS[i]) {
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++);
break;
}
if (i == NUMCOLORFREESLOTS)
I_Error("Out of Skincolor Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
}
else if (fastcmp(type, "SPR2"))
{
@ -287,7 +305,7 @@ void readfreeslots(MYFILE *f)
spr2defaults[free_spr2] = 0;
spr2names[free_spr2++][4] = 0;
} else
deh_warning("Ran out of free SPR2 slots!\n");
I_Error("Out of SPR2 Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
}
else if (fastcmp(type, "TOL"))
{
@ -302,7 +320,7 @@ void readfreeslots(MYFILE *f)
// We don't, so freeslot it.
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
deh_warning("Ran out of free typeoflevel slots!\n");
I_Error("Out of Typeoflevel Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
else
{
G_AddTOL(lastcustomtol, word);
@ -326,7 +344,7 @@ void readfreeslots(MYFILE *f)
precipprops[i].name = Z_StrDup(word);
precip_freeslot++;
} else
deh_warning("Ran out of free PRECIP slots!\n");
I_Error("Out of Precipitation Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
}
else
deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word);

View file

@ -3271,6 +3271,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_ITEM_DEBRIS_CLOUD_SPAWNER2",
"S_ITEMICON",
"S_ITEMBACKDROP",
// Item capsules
"S_ITEMCAPSULE",

View file

@ -2103,6 +2103,9 @@ luahook:
LUA_HookHUD(luahuddrawlist_title, HUD_HOOK(title));
}
LUA_HUD_DrawList(luahuddrawlist_title);
if (finalecount > 0)
M_DrawMenuMessage();
}
// (no longer) De-Demo'd Title Screen
@ -2112,13 +2115,15 @@ void F_TitleScreenTicker(boolean run)
if (run)
{
finalecount++;
if (finalecount == 1)
if (finalecount == 0)
{
// Now start the music
S_ChangeMusicInternal("_title", looptitle);
}
else if (menumessage.fadetimer < 9)
menumessage.fadetimer++;
finalecount++;
}
// don't trigger if doing anything besides idling on title

View file

@ -2006,7 +2006,7 @@ void G_BeginRecording(void)
if (wadfiles[i]->important)
{
nameonly(( filename = va("%s", wadfiles[i]->filename) ));
WRITESTRINGN(demo_p, filename, 64);
WRITESTRINGL(demo_p, filename, MAX_WADPATH);
WRITEMEM(demo_p, wadfiles[i]->md5sum, 16);
totalfiles++;
@ -3727,7 +3727,11 @@ static void G_StopTimingDemo(void)
if (restorecv_vidwait != cv_vidwait.value)
CV_SetValue(&cv_vidwait, restorecv_vidwait);
D_AdvanceDemo();
if (timedemo_quit)
COM_ImmedExecute("quit");
else
D_StartTitle();
}
// reset engine variable set for the demos
@ -3786,10 +3790,12 @@ boolean G_CheckDemoStatus(void)
{
G_StopDemo();
if (modeattacking)
if (timedemo_quit)
COM_ImmedExecute("quit");
else if (modeattacking)
M_EndModeAttackRun();
else
D_AdvanceDemo();
D_StartTitle();
}
return true;

View file

@ -1341,7 +1341,13 @@ void G_DoLoadLevel(boolean resetplayer)
wipegamestate = -1; // force a wipe
if (cv_currprofile.value == -1)
{
PR_ApplyProfilePretend(cv_ttlprofilen.value, 0);
for (i = 1; i < cv_splitplayers.value; i++)
{
PR_ApplyProfile(cv_lastprofile[i].value, i);
}
}
if (gamestate == GS_INTERMISSION)
Y_EndIntermission();
if (gamestate == GS_VOTING)

View file

@ -87,6 +87,8 @@ typedef struct gl_vissprite_s
boolean rotated;
UINT8 translucency; //alpha level 0-255
angle_t angle; // for splats
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing

View file

@ -4179,7 +4179,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
scale *= spr->shadowscale;
if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD)
angle = spr->mobj->angle;
angle = spr->angle;
else
angle = viewangle;
@ -4234,8 +4234,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
// Translate
for (i = 0; i < 4; i++)
{
wallVerts[i].x = rotated[i].x + FIXED_TO_FLOAT(spr->mobj->x);
wallVerts[i].z = rotated[i].y + FIXED_TO_FLOAT(spr->mobj->y);
wallVerts[i].x = rotated[i].x + spr->x1;
wallVerts[i].z = rotated[i].y + spr->z1;
}
if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT))
@ -4262,7 +4262,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
else
{
for (i = 0; i < 4; i++)
wallVerts[i].y = FIXED_TO_FLOAT(spr->mobj->z) + zoffset;
wallVerts[i].y = FIXED_TO_FLOAT(spr->gz) + zoffset;
}
}
else
@ -5254,9 +5254,16 @@ static void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif
if (splat)
{
ang = R_PointToAngle2(0, viewz, 0, interp.z);
}
else
{
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
if (mirrored)
ang = InvAngle(ang);
}
if (sprframe->rotate == SRF_SINGLE)
{
@ -5383,6 +5390,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
this_xscale = spritexscale * this_scale;
this_yscale = spriteyscale * this_scale;
if (splat)
{
z1 = z2 = tr_y;
x1 = x2 = tr_x;
gz = gzt = interp.z;
}
else
{
if (flip)
{
x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
@ -5395,7 +5410,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
}
// test if too close
/*
/*
if (papersprite)
{
z1 = tz - x1 * angle_scalez;
@ -5404,7 +5419,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (max(z1, z2) < ZCLIP_PLANE)
return;
}
*/
*/
z1 = tr_y + x1 * rightsin;
z2 = tr_y - x2 * rightsin;
@ -5421,6 +5436,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
gzt = FIXED_TO_FLOAT(interp.z) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
gz = gzt - (FIXED_TO_FLOAT(spr_height) * this_yscale);
}
}
if (thing->subsector->sector->cullheight)
{
@ -5575,6 +5591,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->precip = false;
vis->bbox = false;
vis->angle = interp.angle;
}
#ifdef HWPRECIP

View file

@ -1251,7 +1251,7 @@ boolean HU_Responder(event_t *ev)
if (chatlen+pastelen > HU_MAXMSGLEN)
return true; // we can't paste this!!
memmove(&w_chat[c_input + pastelen], &w_chat[c_input], pastelen);
memmove(&w_chat[c_input + pastelen], &w_chat[c_input], (chatlen - c_input) + 1); // +1 for '\0'
memcpy(&w_chat[c_input], paste, pastelen); // copy all of that.
c_input += pastelen;
return true;

View file

@ -531,6 +531,7 @@ char sprnames[NUMSPRITES + 1][5] =
"SBOX", // Sphere Box (for Battle)
"RPOP", // Random Item Box Pop
"ITRI", // Item Box Debris
"ITPA", // Paper item backdrop
"SGNS", // Signpost sparkle
"FAST", // Speed boost trail
"DSHR", // Speed boost dust release
@ -3879,6 +3880,7 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 7, {A_SpawnItemDebrisCloud}, 20, 0, S_ITEM_DEBRIS_CLOUD_SPAWNER1}, // S_ITEM_DEBRIS_CLOUD_SPAWNER2
{SPR_NULL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMICON
{SPR_ITPA, FF_FULLBRIGHT, -1, {NULL}, 1, 0, S_NULL}, // S_ITEMBACKDROP
{SPR_ICAP, FF_ADD|0, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE
{SPR_ICAP, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_TOP_SIDE

View file

@ -1077,6 +1077,7 @@ typedef enum sprite
SPR_SBOX, // Sphere Box (for Battle)
SPR_RPOP, // Random Item Box Pop
SPR_ITRI, // Item Box Debris
SPR_ITPA, // Paper item backdrop
SPR_SGNS, // Signpost sparkle
SPR_FAST, // Speed boost trail
SPR_DSHR, // Speed boost dust release
@ -4282,6 +4283,7 @@ typedef enum state
S_ITEM_DEBRIS_CLOUD_SPAWNER2,
S_ITEMICON,
S_ITEMBACKDROP,
// Item capsules
S_ITEMCAPSULE,

View file

@ -921,7 +921,7 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player)
Return:-
None
--------------------------------------------------*/
static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController)
static void K_BotTrick(player_t *player, ticcmd_t *cmd, const line_t *botController)
{
// Trick panel state -- do nothing until a controller line is found, in which case do a trick.
if (botController == NULL)
@ -1259,7 +1259,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
angle_t destangle = 0;
UINT8 spindash = 0;
INT32 turnamt = 0;
line_t *botController = NULL;
const line_t *botController = player->botvars.controller != UINT16_MAX ? &lines[player->botvars.controller] : NULL;
// Remove any existing controls
memset(cmd, 0, sizeof(ticcmd_t));
@ -1292,18 +1292,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
return;
}
botController = K_FindBotController(player->mo);
if (botController == NULL)
{
player->botvars.controller = UINT16_MAX;
}
else
{
player->botvars.controller = botController - lines;
}
player->botvars.rubberband = K_UpdateRubberband(player);
if (player->trickpanel != 0)
{
K_BotTrick(player, cmd, botController);
@ -1531,3 +1519,24 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
Z_Free(predict);
}
}
/*--------------------------------------------------
void K_UpdateBotGameplayVars(player_t *player);
See header file for description.
--------------------------------------------------*/
void K_UpdateBotGameplayVars(player_t *player)
{
const line_t *botController;
if (gamestate != GS_LEVEL || !player->mo)
{
// Not in the level.
return;
}
botController = K_FindBotController(player->mo);
player->botvars.controller = botController ? (botController - lines) : UINT16_MAX;
player->botvars.rubberband = K_UpdateRubberband(player);
}

View file

@ -238,6 +238,22 @@ INT32 K_PositionBully(player_t *player);
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);
/*--------------------------------------------------
void K_UpdateBotGameplayVars(player_t *player);
Updates gamestate affecting botvars. This must be
called for both client and server.
Input Arguments:-
player - Player to whom to update the botvars.
Return:-
None
--------------------------------------------------*/
void K_UpdateBotGameplayVars(player_t *player);
/*--------------------------------------------------
void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt);

View file

@ -6924,6 +6924,11 @@ void K_DropHnextList(player_t *player, boolean keepshields)
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount)
{
mobj_t *drop = P_SpawnMobj(x, y, z, MT_FLOATINGITEM);
mobj_t *backdrop = P_SpawnMobjFromMobj(drop, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&backdrop->target, drop);
P_SetMobjState(backdrop, S_ITEMBACKDROP);
P_SetScale(drop, drop->scale>>4);
drop->destscale = (3*drop->destscale)/2;
@ -7002,6 +7007,9 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
}
drop->flags |= MF_NOCLIPTHING;
backdrop->dispoffset = 1;
P_SetTarget(&backdrop->tracer, drop);
backdrop->flags2 |= MF2_LINKDRAW;
return drop;
}

View file

@ -568,6 +568,7 @@ void M_Init(void);
extern menu_t MessageDef;
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
void M_StopMessage(INT32 choice);
void M_DrawMenuMessage(void);
void M_QuitResponse(INT32 ch);
void M_QuitSRB2(INT32 choice);
@ -911,6 +912,8 @@ void M_HandleVideoModes(INT32 ch);
// data stuff
void M_HandleProfileErase(INT32 choice);
// Draws the EGGA CHANNEL background.
void M_DrawEggaChannel(void);
// Extras menu:
#define DF_ENCORE 0x40

View file

@ -433,7 +433,7 @@ static void M_DrawMenuTyping(void)
}
// Draw the message popup submenu
static void M_DrawMenuMessage(void)
void M_DrawMenuMessage(void)
{
INT32 y = menumessage.y + (9-menumessage.fadetimer)*20;
@ -443,6 +443,9 @@ static void M_DrawMenuMessage(void)
INT32 mlines;
const char *msg = menumessage.message;
if (!menumessage.active)
return;
mlines = menumessage.m>>8;
max = (INT16)((UINT8)(menumessage.m & 0xFF)*8);
@ -550,7 +553,6 @@ void M_Drawer(void)
}
// Draw message overlay when needed
if (menumessage.active)
M_DrawMenuMessage();
// Draw typing overlay when needed, above all other menu elements.
@ -2290,7 +2292,7 @@ static void M_MPOptDrawer(menu_t *m, INT16 extend[3][3])
}
// Draws the EGGA CHANNEL background.
static void M_DrawEggaChannel(void)
void M_DrawEggaChannel(void)
{
patch_t *background = W_CachePatchName("M_EGGACH", PU_CACHE);
@ -3896,6 +3898,18 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
if (demoref->gametype == GT_RACE)
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "TIME");
}
else
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
}
if (demoref->standings[0].timeorscore == (UINT32_MAX-1))
{
V_DrawThinString(x+32, y+39, V_SNAPTOTOP, "NO CONTEST");
}
else if (demoref->gametype == GT_RACE)
{
V_DrawRightAlignedString(x+84, y+40, V_SNAPTOTOP, va("%d'%02d\"%02d",
G_TicsToMinutes(demoref->standings[0].timeorscore, true),
G_TicsToSeconds(demoref->standings[0].timeorscore),
@ -3904,7 +3918,6 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
}
else
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
V_DrawString(x+32, y+40, V_SNAPTOTOP, va("%d", demoref->standings[0].timeorscore));
}
@ -3913,7 +3926,7 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
// Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this)
// and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid.
if (demoref->standings[0].skin != 0xFF)
if (demoref->standings[0].skin < numskins)
{
patch = faceprefix[demoref->standings[0].skin][FACE_WANTED];
colormap = R_GetTranslationColormap(
@ -4114,7 +4127,7 @@ void M_DrawReplayStartMenu(void)
// Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this)
// and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid.
if (demoref->standings[i].skin != 0xFF)
if (demoref->standings[i].skin < numskins)
{
patch = faceprefix[demoref->standings[i].skin][FACE_RANK];
colormap = R_GetTranslationColormap(

View file

@ -921,11 +921,6 @@ void M_StartControlPanel(void)
menucmd[i].delay = MENUDELAYTIME;
}
// No instantly skipping the titlescreen.
// (We can change this timer later when extra animation is added.)
if (gamestate == GS_TITLESCREEN && finalecount < 1)
return;
// intro might call this repeatedly
if (menuactive)
{
@ -935,6 +930,11 @@ void M_StartControlPanel(void)
if (gamestate == GS_TITLESCREEN) // Set up menu state
{
// No instantly skipping the titlescreen.
// (We can change this timer later when extra animation is added.)
if (finalecount < 1)
return;
G_SetGamestate(GS_MENU);
gameaction = ga_nothing;
@ -954,6 +954,8 @@ void M_StartControlPanel(void)
if (!Playing())
{
M_StopMessage(0); // Doesn't work with MM_YESNO or MM_EVENTHANDLER... but good enough to get the game as it is currently functional again
if (cv_currprofile.value == -1) // Only ask once per session.
{
// Make sure the profile data is ready now since we need to select a profile.
@ -1807,7 +1809,7 @@ void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtyp
strncpy(menumessage.message, string, MAXMENUMESSAGE);
menumessage.flags = itemtype;
*(void**)&menumessage.routine = routine;
menumessage.fadetimer = 1;
menumessage.fadetimer = (gamestate == GS_WAITINGPLAYERS) ? 9 : 1;
menumessage.active = true;
start = 0;
@ -1875,12 +1877,9 @@ void M_HandleMenuMessage(void)
boolean btok = M_MenuConfirmPressed(pid);
boolean btnok = M_MenuBackPressed(pid);
if (menumessage.fadetimer < 9)
menumessage.fadetimer++;
if (menumessage.fadetimer > 9)
menumessage.fadetimer = 9;
switch (menumessage.flags)
{
// Send 1 to the routine if we're pressing A/B/X/Y
@ -3830,7 +3829,6 @@ void M_JoinIP(const char *ipa)
}
COM_BufAddText(va("connect \"%s\"\n", ipa));
M_ClearMenus(true);
// A little "please wait" message.
M_DrawTextBox(56, BASEVIDHEIGHT/2-12, 24, 2);

View file

@ -762,6 +762,13 @@ void Command_Setlives_f(void)
D_Cheat(consoleplayer, CHEAT_LIVES, atoi(COM_Argv(1)));
}
void Command_Grayscale_f(void)
{
REQUIRE_CHEATS;
COM_ImmedExecute("toggle palette \"\" GRAYPAL");
}
//
// OBJECTPLACE (and related variables)
//

View file

@ -75,6 +75,7 @@ void Command_Teleport_f(void);
void Command_RTeleport_f(void);
void Command_Skynum_f(void);
void Command_Weather_f(void);
void Command_Grayscale_f(void);
#ifdef _DEBUG
void Command_CauseCfail_f(void);
#endif

View file

@ -406,7 +406,7 @@ hyudoro_patrol_hit_player
if (!player->itemamount)
return false;
K_AddHitLag(toucher, TICRATE/2, true);
K_AddHitLag(toucher, TICRATE/2, false);
hyudoro_mode(hyu) = HYU_RETURN;
hyudoro_itemtype(hyu) = player->itemtype;

View file

@ -1997,7 +1997,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// Check if the player is allowed to be damaged!
// If not, then spawn the instashield effect instead.
if (!force && !(inflictor && inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1 == 1))
if (!force)
{
if (gametyperules & GTR_BUMPERS)
{
@ -2037,7 +2037,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
allowcombo = false;
}
if ((target->hitlag == 0 || allowcombo == false) && player->flashing > 0)
// DMG_EXPLODE excluded from flashtic checks to prevent dodging eggbox/SPB with weak spinout
if ((target->hitlag == 0 || allowcombo == false) && player->flashing > 0 && type != DMG_EXPLODE)
{
// Post-hit invincibility
K_DoInstashield(player);

View file

@ -5257,27 +5257,8 @@ void P_RunOverlays(void)
continue;
}
if (!r_splitscreen /*&& rendermode != render_soft*/)
{
angle_t viewingangle;
if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera[0].x, camera[0].y);
if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
viewingangle += ANGLE_180;
destx = mo->target->x + P_ReturnThrustX(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
desty = mo->target->y + P_ReturnThrustY(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
}
else
{
destx = mo->target->x;
desty = mo->target->y;
}
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = FixedMul(mo->target->scale, mo->movefactor);
@ -5289,12 +5270,27 @@ void P_RunOverlays(void)
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
mo->flags ^= MF_DONTENCOREMAP;
mo->dispoffset = mo->target->dispoffset + mo->info->dispoffset;
if (!(mo->state->frame & FF_ANIMATE))
{
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
if (mo->state->var1)
{
mo->dispoffset--;
}
else
{
mo->dispoffset++;
}
}
else
{
// if you're using FF_ANIMATE on an overlay,
// then you're on your own.
else
zoffs = 0;
}
P_UnsetThingPosition(mo);
mo->x = destx;
@ -6786,6 +6782,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
break;
case MT_FLOATINGITEM:
{
mobj->pitch = mobj->roll = 0;
if (mobj->flags & MF_NOCLIPTHING)
{
if (P_CheckDeathPitCollide(mobj))
@ -10768,6 +10765,19 @@ void P_RemovePrecipMobj(precipmobj_t *mobj)
// Clearing out stuff for savegames
void P_RemoveSavegameMobj(mobj_t *mobj)
{
// unlink from sector and block lists
if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker)
{
P_UnsetPrecipThingPosition((precipmobj_t *)mobj);
if (precipsector_list)
{
P_DelPrecipSeclist(precipsector_list);
precipsector_list = NULL;
}
}
else
{
// unlink from sector and block lists
P_UnsetThingPosition(mobj);
@ -10777,13 +10787,20 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
P_DelSeclist(sector_list);
sector_list = NULL;
}
}
// stop any playing sound
S_StopSound(mobj);
R_RemoveMobjInterpolator(mobj);
// free block
P_RemoveThinker((thinker_t *)mobj);
R_RemoveMobjInterpolator(mobj);
// Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers
{
thinker_t *thinker = (thinker_t *)mobj;
thinker_t *next = thinker->next;
(next->prev = thinker->prev)->next = next;
Z_Free(thinker);
}
}
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};

View file

@ -3341,6 +3341,19 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
}
if (mobj->type == MT_SKYBOX)
{
mtag_t tag = mobj->movedir;
if (tag < 0 || tag > 15)
{
CONS_Debug(DBG_GAMELOGIC, "LoadMobjThinker: Skybox ID %d of netloaded object is not between 0 and 15!\n", tag);
}
else if (mobj->flags2 & MF2_AMBUSH)
skyboxcenterpnts[tag] = mobj;
else
skyboxviewpnts[tag] = mobj;
}
if (diff2 & MD2_WAYPOINTCAP)
P_SetTarget(&waypointcap, mobj);
@ -3968,12 +3981,16 @@ static void P_NetUnArchiveThinkers(void)
{
next = currentthinker->next;
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it
else
{
(next->prev = currentthinker->prev)->next = next;
R_DestroyLevelInterpolators(currentthinker);
Z_Free(currentthinker);
}
}
}
// we don't want the removed mobjs to come back
iquetail = iquehead = 0;

View file

@ -7351,7 +7351,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Reset the palette now all fades have been done
if (rendermode != render_none)
V_SetPaletteLump(GetPalette()); // Set the level palette
V_ReloadPalette(); // Set the level palette
if (!(reloadinggamestate || titlemapinaction))
{

View file

@ -2390,6 +2390,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
camera[i].y += y;
camera[i].z += z;
camera[i].subsector = R_PointInSubsector(camera[i].x, camera[i].y);
R_RelativeTeleportViewInterpolation(i, x, y, z, 0);
break;
}
}

View file

@ -17,6 +17,7 @@
#include "r_state.h"
#include "s_sound.h"
#include "r_main.h"
#include "r_fps.h"
/** \brief The P_MixUp function
@ -73,8 +74,12 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
// move chasecam at new player location
for (i = 0; i <= r_splitscreen; i++)
{
if (thing->player == &players[displayplayers[i]] && camera[i].chase)
if (thing->player != &players[displayplayers[i]])
continue;
if (camera[i].chase)
P_ResetCamera(thing->player, &camera[i]);
R_ResetViewInterpolation(i + 1);
break;
}
// don't run in place after a teleport

View file

@ -24,6 +24,7 @@
#include "lua_hook.h"
#include "m_perfstats.h"
#include "i_system.h" // I_GetPreciseTime
#include "i_video.h" // rendermode
#include "r_main.h"
#include "r_fps.h"
@ -792,9 +793,13 @@ void P_Ticker(boolean run)
// Hack: ensure newview is assigned every tic.
// Ensures view interpolation is T-1 to T in poor network conditions
// We need a better way to assign view state decoupled from game logic
if (rendermode != render_none)
{
for (i = 0; i <= r_splitscreen; i++)
{
player_t *player = &players[displayplayers[i]];
if (!player->mo)
continue;
const boolean skybox = (player->skybox.viewpoint && cv_skybox.value); // True if there's a skybox object and skyboxes are on
if (skybox)
{
@ -803,6 +808,7 @@ void P_Ticker(boolean run)
R_SetupFrame(i);
}
}
}
P_MapEnd();

View file

@ -4301,6 +4301,12 @@ void P_PlayerAfterThink(player_t *player)
// Run followers in AfterThink, after the players have moved,
// so a lag value of 1 is exactly attached to the player.
K_HandleFollower(player);
if (K_PlayerUsesBotMovement(player))
{
K_UpdateBotGameplayVars(player);
}
}
void P_SetPlayerAngle(player_t *player, angle_t angle)

View file

@ -216,6 +216,14 @@ void R_ResetViewInterpolation(UINT8 p)
}
}
void R_RelativeTeleportViewInterpolation(UINT8 p, fixed_t xdiff, fixed_t ydiff, fixed_t zdiff, angle_t angdiff)
{
pview_old[p].x += xdiff;
pview_old[p].y += ydiff;
pview_old[p].z += zdiff;
pview_old[p].angle += angdiff;
}
void R_SetViewContext(enum viewcontext_e _viewcontext)
{
UINT8 i = 0;

View file

@ -126,6 +126,8 @@ void R_InterpolateViewRollAngle(fixed_t frac);
void R_UpdateViewInterpolation(void);
// Reset the view states (e.g. after level load) so R_InterpolateView doesn't interpolate invalid data
void R_ResetViewInterpolation(UINT8 p);
// Update old view for seamless relative teleport
void R_RelativeTeleportViewInterpolation(UINT8 p, fixed_t xdiff, fixed_t ydiff, fixed_t zdiff, angle_t angdiff);
// Set the current view context (the viewvars pointed to by newview)
void R_SetViewContext(enum viewcontext_e _viewcontext);

View file

@ -185,7 +185,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
splat.scale = FixedMul(splat.scale, ((skin_t *)mobj->skin)->highresscale);
if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD)
splatangle = mobj->angle;
splatangle = spr->centerangle;
else
splatangle = spr->viewpoint.angle;
@ -209,14 +209,14 @@ void R_DrawFloorSplat(vissprite_t *spr)
xoffset = FixedMul(leftoffset, splat.xscale);
yoffset = FixedMul(topoffset, splat.yscale);
x = mobj->x;
y = mobj->y;
x = spr->gx;
y = spr->gy;
w = (splat.width * splat.xscale);
h = (splat.height * splat.yscale);
splat.x = x;
splat.y = y;
splat.z = mobj->z;
splat.z = spr->pz;
splat.slope = NULL;
// Set positions

View file

@ -1755,7 +1755,11 @@ static void R_ProjectSprite(mobj_t *thing)
I_Error("R_ProjectSprite: sprframes NULL for sprite %d\n", thing->sprite);
#endif
if (sprframe->rotate != SRF_SINGLE || papersprite)
if (splat)
{
ang = R_PointToAngle2(0, viewz, 0, interp.z);
}
else if (sprframe->rotate != SRF_SINGLE || papersprite)
{
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
if (mirrored)
@ -2056,6 +2060,7 @@ static void R_ProjectSprite(mobj_t *thing)
tr_y = (interp.y - sort_y) - viewy;
sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
sortsplat = FixedDiv(projectiony[viewssnum], sort_z);
centerangle = interp.angle;
}
// PORTAL SPRITE CLIPPING

View file

@ -171,7 +171,7 @@ typedef struct vissprite_s
fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle
fixed_t xiscale; // negative if flipped
angle_t centerangle; // for paper sprites
angle_t centerangle; // for paper sprites / splats
// for floor sprites
struct {

View file

@ -1089,10 +1089,10 @@ sfxinfo_t S_sfx[NUMSFX] =
{"bhurry", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // v1.0.2 Battle overtime
{"bsnipe", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Banana sniping
{"sploss", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Down to yellow sparks
{"join", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player joined server
{"leave", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player left server
{"requst", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Got a Discord join request
{"syfail", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Funny sync failure
{"join", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player joined server
{"leave", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player left server
{"requst", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Got a Discord join request
{"syfail", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Funny sync failure
{"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // :shitsfree:
{"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Debug notification
{"cock", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hammer cocks, bang bang
@ -1353,7 +1353,7 @@ sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean
return i;
}
CONS_Alert(CONS_WARNING, M_GetText("No more free sound slots\n"));
I_Error("Out of Sound Freeslots while allocating \"%s\"\nLoad less addons to fix this.", name);
return 0;
}

View file

@ -86,11 +86,16 @@ static CV_PossibleValue_t constextsize_cons_t[] = {
static void CV_constextsize_OnChange(void);
consvar_t cv_constextsize = CVAR_INIT ("con_textsize", "Medium", CV_SAVE|CV_CALL, constextsize_cons_t, CV_constextsize_OnChange);
consvar_t cv_palette = CVAR_INIT ("palette", "", CV_CHEAT|CV_CALL|CV_NOINIT, NULL, CV_palette_OnChange);
consvar_t cv_palettenum = CVAR_INIT ("palettenum", "0", CV_CHEAT|CV_CALL|CV_NOINIT, CV_Unsigned, CV_palette_OnChange);
// local copy of the palette for V_GetColor()
RGBA_t *pLocalPalette = NULL;
RGBA_t *pMasterPalette = NULL;
RGBA_t *pGammaCorrectedPalette = NULL;
static size_t currentPaletteSize;
/*
The following was an extremely helpful resource when developing my Colour Cube LUT.
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter24.html
@ -311,9 +316,12 @@ UINT32 V_GammaCorrect(UINT32 input, double power)
static void LoadPalette(const char *lumpname)
{
lumpnum_t lumpnum = W_GetNumForName(lumpname);
size_t i, palsize = W_LumpLength(lumpnum)/3;
size_t i, palsize;
UINT8 *pal;
currentPaletteSize = W_LumpLength(lumpnum);
palsize = currentPaletteSize / 3;
Cubeapply = InitCube();
if (pLocalPalette != pMasterPalette)
@ -400,8 +408,24 @@ const char *R_GetPalname(UINT16 num)
const char *GetPalette(void)
{
const char *user = cv_palette.string;
if (user && user[0])
{
if (W_CheckNumForName(user) == LUMPERROR)
{
CONS_Alert(CONS_WARNING,
"cv_palette %s lump does not exist\n", user);
}
else
{
return cv_palette.string;
}
}
if (gamestate == GS_LEVEL)
return R_GetPalname((encoremode ? mapheaderinfo[gamemap-1]->encorepal : mapheaderinfo[gamemap-1]->palette));
return "PLAYPAL";
}
@ -419,6 +443,19 @@ void V_SetPalette(INT32 palettenum)
if (!pLocalPalette)
V_ReloadPalette();
if (palettenum == 0)
{
palettenum = cv_palettenum.value;
if (palettenum * 256U > currentPaletteSize - 256)
{
CONS_Alert(CONS_WARNING,
"cv_palettenum %d out of range\n",
palettenum);
palettenum = 0;
}
}
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPalette(&pLocalPalette[palettenum*256]);
@ -433,23 +470,12 @@ void V_SetPalette(INT32 palettenum)
void V_SetPaletteLump(const char *pal)
{
LoadPalette(pal);
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPalette(pLocalPalette);
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
else
#endif
#endif
if (rendermode != render_none)
I_SetPalette(pLocalPalette);
#ifdef HASINVERT
R_MakeInvertmap();
#endif
V_SetPalette(0);
}
static void CV_palette_OnChange(void)
{
// reload palette
// recalculate Color Cube
V_ReloadPalette();
V_SetPalette(0);
}

View file

@ -34,7 +34,8 @@ extern consvar_t cv_ticrate, cv_constextsize,
cv_globalgamma, cv_globalsaturation,
cv_rhue, cv_yhue, cv_ghue, cv_chue, cv_bhue, cv_mhue,
cv_rgamma, cv_ygamma, cv_ggamma, cv_cgamma, cv_bgamma, cv_mgamma,
cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, cv_msaturation;
cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, cv_msaturation,
cv_palette, cv_palettenum;
// Allocates buffer screens, call before R_Init.
void V_Init(void);

View file

@ -99,9 +99,10 @@ void* vres_GetPatch(virtlump_t *vlump, INT32 tag);
// =========================================================================
#define MAX_WADPATH 512
#define MAX_WADFILES 127 // maximum of wad files used at the same time
// Replay code relies on it being an UINT8 and, just to be safe, in case some wad counter somewhere is a SINT8, you should NOT go above 127 here if you're lazy like me.
// Besides, are there truly 127 wads worth your interrest?
#define MAX_WADFILES 255 // maximum of wad files used at the same time
// Replay code relies on it being an UINT8. There are no SINT8s handling WAD indices, though.
// Can be set all the way up to 255 but not 256,
// because an UINT8 will never be >= 256, probably breaking some conditionals.
#define lumpcache_t void *

View file

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>