Merge branch 'INTERNAL_netreplays' into 'v1'

Netreplays

See merge request KartKrew/Kart!146
This commit is contained in:
Sal 2019-05-06 21:46:18 -04:00
commit f3f74388e6
61 changed files with 5453 additions and 2137 deletions

View file

@ -1398,7 +1398,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
Setvalue(cvar, svalue, stealth); Setvalue(cvar, svalue, stealth);
} }
void CV_SaveNetVars(UINT8 **p) void CV_SaveNetVars(UINT8 **p, boolean isdemorecording)
{ {
consvar_t *cvar; consvar_t *cvar;
UINT8 *count_p = *p; UINT8 *count_p = *p;
@ -1408,10 +1408,32 @@ void CV_SaveNetVars(UINT8 **p)
// the client will reset all netvars to default before loading // the client will reset all netvars to default before loading
WRITEUINT16(*p, 0x0000); WRITEUINT16(*p, 0x0000);
for (cvar = consvar_vars; cvar; cvar = cvar->next) for (cvar = consvar_vars; cvar; cvar = cvar->next)
if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (isdemorecording && cvar->netid == cv_numlaps.netid))
{ {
WRITEUINT16(*p, cvar->netid); WRITEUINT16(*p, cvar->netid);
WRITESTRING(*p, cvar->string);
// UGLY HACK: Save proper lap count in net replays
if (isdemorecording && cvar->netid == cv_numlaps.netid)
{
if (cv_basenumlaps.value &&
(!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))
)
{
WRITESTRING(*p, cv_basenumlaps.string);
}
else
{
char buf[9];
sprintf(buf, "%d", mapheaderinfo[gamemap - 1]->numlaps);
WRITESTRING(*p, buf);
}
}
else
{
WRITESTRING(*p, cvar->string);
}
WRITEUINT8(*p, false); WRITEUINT8(*p, false);
++count; ++count;
} }

View file

@ -161,7 +161,7 @@ void CV_AddValue(consvar_t *var, INT32 increment);
void CV_SaveVariables(FILE *f); void CV_SaveVariables(FILE *f);
// load/save gamesate (load and save option and for network join in game) // load/save gamesate (load and save option and for network join in game)
void CV_SaveNetVars(UINT8 **p); void CV_SaveNetVars(UINT8 **p, boolean isdemorecording);
void CV_LoadNetVars(UINT8 **p); void CV_LoadNetVars(UINT8 **p);
// reset cheat netvars after cheats is deactivated // reset cheat netvars after cheats is deactivated

View file

@ -138,6 +138,7 @@ static UINT8 localtextcmd3[MAXTEXTCMD]; // splitscreen == 2
static UINT8 localtextcmd4[MAXTEXTCMD]; // splitscreen == 3 static UINT8 localtextcmd4[MAXTEXTCMD]; // splitscreen == 3
static tic_t neededtic; static tic_t neededtic;
SINT8 servernode = 0; // the number of the server node SINT8 servernode = 0; // the number of the server node
char connectedservername[MAXSERVERNAME];
/// \brief do we accept new players? /// \brief do we accept new players?
/// \todo WORK! /// \todo WORK!
boolean acceptnewnode = true; boolean acceptnewnode = true;
@ -1512,7 +1513,7 @@ static boolean SV_SendServerConfig(INT32 node)
op = p = netbuffer->u.servercfg.varlengthinputs; op = p = netbuffer->u.servercfg.varlengthinputs;
CV_SavePlayerNames(&p); CV_SavePlayerNames(&p);
CV_SaveNetVars(&p); CV_SaveNetVars(&p, false);
{ {
const size_t len = sizeof (serverconfig_pak) + (size_t)(p - op); const size_t len = sizeof (serverconfig_pak) + (size_t)(p - op);
@ -1691,8 +1692,8 @@ static void CL_LoadReceivedSavegame(void)
} }
paused = false; paused = false;
demoplayback = false; demo.playback = false;
titledemo = false; demo.title = false;
automapactive = false; automapactive = false;
// load a base level // load a base level
@ -2270,6 +2271,9 @@ static void CL_ConnectToServer(boolean viams)
{ {
INT32 j; INT32 j;
const char *gametypestr = NULL; const char *gametypestr = NULL;
strncpy(connectedservername, serverlist[i].info.servername, MAXSERVERNAME);
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
for (j = 0; gametype_cons_t[j].strvalue; j++) for (j = 0; gametype_cons_t[j].strvalue; j++)
{ {
@ -2315,7 +2319,7 @@ static void CL_ConnectToServer(boolean viams)
#endif #endif
DEBFILE(va("Synchronisation Finished\n")); DEBFILE(va("Synchronisation Finished\n"));
displayplayer = consoleplayer; displayplayers[0] = consoleplayer;
} }
#ifndef NONET #ifndef NONET
@ -2487,7 +2491,7 @@ static void Command_connect(void)
return; return;
} }
if (Playing() || titledemo) if (Playing() || demo.title)
{ {
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
return; return;
@ -2579,14 +2583,16 @@ void CL_ClearPlayer(INT32 playernum)
// //
// Removes a player from the current game // Removes a player from the current game
// //
static void CL_RemovePlayer(INT32 playernum, INT32 reason) void CL_RemovePlayer(INT32 playernum, INT32 reason)
{ {
// Sanity check: exceptional cases (i.e. c-fails) can cause multiple // Sanity check: exceptional cases (i.e. c-fails) can cause multiple
// kick commands to be issued for the same player. // kick commands to be issued for the same player.
if (!playeringame[playernum]) if (!playeringame[playernum])
return; return;
if (server && !demoplayback) demo_extradata[playernum] |= DXD_PLAYSTATE;
if (server && !demo.playback)
{ {
INT32 node = playernode[playernum]; INT32 node = playernode[playernum];
//playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one //playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one
@ -2661,8 +2667,8 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
RemoveAdminPlayer(playernum); // don't stay admin after you're gone RemoveAdminPlayer(playernum); // don't stay admin after you're gone
} }
if (playernum == displayplayer) if (playernum == displayplayers[0] && !demo.playback)
displayplayer = consoleplayer; // don't look through someone's view who isn't there displayplayers[0] = consoleplayer; // don't look through someone's view who isn't there
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUA_InvalidatePlayer(&players[playernum]); LUA_InvalidatePlayer(&players[playernum]);
@ -2682,7 +2688,7 @@ void CL_Reset(void)
G_StopMetalRecording(); G_StopMetalRecording();
if (metalplayback) if (metalplayback)
G_StopMetalDemo(); G_StopMetalDemo();
if (demorecording) if (demo.recording)
G_CheckDemoStatus(); G_CheckDemoStatus();
// reset client/server code // reset client/server code
@ -3382,6 +3388,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
{ {
INT16 node, newplayernum; INT16 node, newplayernum;
UINT8 splitscreenplayer = 0; UINT8 splitscreenplayer = 0;
UINT8 i;
if (playernum != serverplayer && !IsPlayerAdmin(playernum)) if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{ {
@ -3415,34 +3422,19 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (node == mynode) if (node == mynode)
{ {
playernode[newplayernum] = 0; // for information only playernode[newplayernum] = 0; // for information only
if (splitscreenplayer) if (splitscreenplayer)
{ {
if (splitscreenplayer == 1) displayplayers[splitscreenplayer] = newplayernum;
{ DEBFILE(va("spawning one of my sister number %d\n", splitscreenplayer));
secondarydisplayplayer = newplayernum; if (splitscreenplayer == 1 && botingame)
DEBFILE("spawning my brother\n"); players[newplayernum].bot = 1;
if (botingame)
players[newplayernum].bot = 1;
// Same goes for player 2 when relevant
}
else if (splitscreenplayer == 2)
{
thirddisplayplayer = newplayernum;
DEBFILE("spawning my sister\n");
}
else if (splitscreenplayer == 3)
{
fourthdisplayplayer = newplayernum;
DEBFILE("spawning my trusty pet dog\n");
}
} }
else else
{ {
consoleplayer = newplayernum; consoleplayer = newplayernum;
displayplayer = newplayernum; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
secondarydisplayplayer = newplayernum; displayplayers[i] = newplayernum;
thirddisplayplayer = newplayernum;
fourthdisplayplayer = newplayernum;
DEBFILE("spawning me\n"); DEBFILE("spawning me\n");
} }
D_SendPlayerConfig(); D_SendPlayerConfig();
@ -3591,7 +3583,7 @@ boolean Playing(void)
boolean SV_SpawnServer(void) boolean SV_SpawnServer(void)
{ {
if (demoplayback) if (demo.playback)
G_StopDemo(); // reset engine parameter G_StopDemo(); // reset engine parameter
if (metalplayback) if (metalplayback)
G_StopMetalDemo(); G_StopMetalDemo();
@ -5177,9 +5169,9 @@ void TryRunTics(tic_t realtics)
NetUpdate(); NetUpdate();
if (demoplayback) if (demo.playback)
{ {
neededtic = gametic + (realtics * cv_playbackspeed.value); neededtic = gametic + realtics * (gamestate == GS_LEVEL ? cv_playbackspeed.value : 1);
// start a game after a demo // start a game after a demo
maketic += realtics; maketic += realtics;
firstticstosend = maketic; firstticstosend = maketic;
@ -5432,7 +5424,7 @@ FILESTAMP
} }
else else
{ {
if (!demoplayback) if (!demo.playback)
{ {
INT32 counts; INT32 counts;

View file

@ -512,6 +512,7 @@ extern boolean dedicated; // For dedicated server
extern UINT16 software_MAXPACKETLENGTH; extern UINT16 software_MAXPACKETLENGTH;
extern boolean acceptnewnode; extern boolean acceptnewnode;
extern SINT8 servernode; extern SINT8 servernode;
extern char connectedservername[MAXSERVERNAME];
void Command_Ping_f(void); void Command_Ping_f(void);
extern tic_t connectiontimeout; extern tic_t connectiontimeout;
@ -551,6 +552,7 @@ void CL_AddSplitscreenPlayer(void);
void CL_RemoveSplitscreenPlayer(UINT8 p); void CL_RemoveSplitscreenPlayer(UINT8 p);
void CL_Reset(void); void CL_Reset(void);
void CL_ClearPlayer(INT32 playernum); void CL_ClearPlayer(INT32 playernum);
void CL_RemovePlayer(INT32 playernum, INT32 reason);
void CL_UpdateServerList(boolean internetsearch, INT32 room); void CL_UpdateServerList(boolean internetsearch, INT32 room);
boolean CL_Responder(event_t *ev); boolean CL_Responder(event_t *ev);
// Is there a game running // Is there a game running

View file

@ -118,14 +118,8 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo boolean singletics = false; // timedemo
boolean lastdraw = false; boolean lastdraw = false;
postimg_t postimgtype = postimg_none; postimg_t postimgtype[MAXSPLITSCREENPLAYERS];
INT32 postimgparam; INT32 postimgparam[MAXSPLITSCREENPLAYERS];
postimg_t postimgtype2 = postimg_none;
INT32 postimgparam2;
postimg_t postimgtype3 = postimg_none;
INT32 postimgparam3;
postimg_t postimgtype4 = postimg_none;
INT32 postimgparam4;
// These variables are only true if // These variables are only true if
// whether the respective sound system is disabled // whether the respective sound system is disabled
@ -248,6 +242,12 @@ void D_ProcessEvents(void)
continue; continue;
} }
if (demo.savemode == DSM_TITLEENTRY)
{
if (G_DemoTitleResponder(ev))
continue;
}
// Menu input // Menu input
if (M_Responder(ev)) if (M_Responder(ev))
continue; // menu ate the event continue; // menu ate the event
@ -274,6 +274,7 @@ static void D_Display(void)
boolean forcerefresh = false; boolean forcerefresh = false;
static boolean wipe = false; static boolean wipe = false;
INT32 wipedefindex = 0; INT32 wipedefindex = 0;
UINT8 i;
if (dedicated) if (dedicated)
return; return;
@ -422,109 +423,77 @@ static void D_Display(void)
// draw the view directly // draw the view directly
if (cv_renderview.value && !automapactive) if (cv_renderview.value && !automapactive)
{ {
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) for (i = 0; i <= splitscreen; i++)
{ {
viewwindowy = 0; if (players[displayplayers[i]].mo || players[displayplayers[i]].playerstate == PST_DEAD)
viewwindowx = 0;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{ {
if (splitscreen > 1) if (i == 0) // Initialize for P1
{ {
viewwindowx = viewwidth;
viewwindowy = 0; viewwindowy = 0;
}
else
{
viewwindowx = 0; viewwindowx = 0;
viewwindowy = viewheight;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
} }
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0])); viewssnum = i;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// render the third screen
if (splitscreen > 1 && players[thirddisplayplayer].mo)
{
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft) if (rendermode != render_soft)
HWR_RenderPlayerView(2, &players[thirddisplayplayer]); HWR_RenderPlayerView(i, &players[displayplayers[i]]);
else else
#endif #endif
if (rendermode != render_none) if (rendermode != render_none)
{ {
viewwindowx = 0; if (i > 0) // Splitscreen-specific
viewwindowy = viewheight; {
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0])); switch (i)
{
case 1:
if (splitscreen > 1)
{
viewwindowx = viewwidth;
viewwindowy = 0;
}
else
{
viewwindowx = 0;
viewwindowy = viewheight;
}
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
break;
case 2:
viewwindowx = 0;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
break;
case 3:
viewwindowx = viewwidth;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
default:
break;
}
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[thirddisplayplayer]); topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
}
viewwindowy = 0; R_RenderPlayerView(&players[displayplayers[i]]);
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
if (splitscreen > 2 && players[fourthdisplayplayer].mo) // render the fourth screen if (i > 0)
{ M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
#ifdef HWRENDER }
if (rendermode != render_soft)
HWR_RenderPlayerView(3, &players[fourthdisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowx = viewwidth;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[fourthdisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
} }
} }
if (rendermode == render_soft) if (rendermode == render_soft)
{ {
if (postimgtype) for (i = 0; i <= splitscreen; i++)
V_DoPostProcessor(0, postimgtype, postimgparam); {
if (postimgtype2) if (postimgtype[i])
V_DoPostProcessor(1, postimgtype2, postimgparam2); V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
if (postimgtype3) }
V_DoPostProcessor(2, postimgtype3, postimgparam3);
if (postimgtype4)
V_DoPostProcessor(3, postimgtype4, postimgparam4);
} }
} }
@ -550,7 +519,7 @@ static void D_Display(void)
wipegamestate = gamestate; wipegamestate = gamestate;
// draw pause pic // draw pause pic
if (paused && cv_showhud.value) if (paused && cv_showhud.value && !demo.playback)
{ {
INT32 py; INT32 py;
patch_t *patch; patch_t *patch;
@ -562,6 +531,12 @@ static void D_Display(void)
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch); V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch);
} }
if (demo.rewinding)
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1)))
V_DrawVhsEffect(demo.rewinding);
// vid size change is now finished if it was on... // vid size change is now finished if it was on...
vid.recalc = 0; vid.recalc = 0;
@ -619,6 +594,9 @@ static void D_Display(void)
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
} }
if (cv_shittyscreen.value)
V_DrawVhsEffect(cv_shittyscreen.value == 2);
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
} }
} }
@ -732,7 +710,7 @@ void D_SRB2Loop(void)
M_DoScreenShot(); M_DoScreenShot();
} }
// consoleplayer -> displayplayer (hear sounds from viewpoint) // consoleplayer -> displayplayers (hear sounds from viewpoint)
S_UpdateSounds(); // move positional sounds S_UpdateSounds(); // move positional sounds
// check for media change, loop music.. // check for media change, loop music..
@ -811,7 +789,8 @@ void D_StartTitle(void)
maptol = 0; maptol = 0;
gameaction = ga_nothing; gameaction = ga_nothing;
displayplayer = consoleplayer = 0; memset(displayplayers, 0, sizeof(displayplayers));
consoleplayer = 0;
//demosequence = -1; //demosequence = -1;
gametype = GT_RACE; // SRB2kart gametype = GT_RACE; // SRB2kart
paused = false; paused = false;
@ -1510,7 +1489,7 @@ void D_SRB2Main(void)
if (M_CheckParm("-playdemo")) if (M_CheckParm("-playdemo"))
{ {
singledemo = true; // quit after one demo demo.quitafterplaying = true; // quit after one demo
G_DeferedPlayDemo(tmp); G_DeferedPlayDemo(tmp);
} }
else else
@ -1537,6 +1516,8 @@ void D_SRB2Main(void)
// as having been modified for the first game. // as having been modified for the first game.
M_PushSpecialParameters(); // push all "+" parameter at the command buffer M_PushSpecialParameters(); // push all "+" parameter at the command buffer
strncpy(connectedservername, cv_servername.string, MAXSERVERNAME);
if (M_CheckParm("-gametype") && M_IsNextParm()) if (M_CheckParm("-gametype") && M_IsNextParm())
{ {
// from Command_Map_f // from Command_Map_f

View file

@ -21,7 +21,6 @@
// Max computers in a game // Max computers in a game
#define MAXNETNODES (MAXPLAYERS+4) #define MAXNETNODES (MAXPLAYERS+4)
#define BROADCASTADDR MAXNETNODES #define BROADCASTADDR MAXNETNODES
#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer
#define NETSPLITSCREEN // Kart's splitscreen netgame feature #define NETSPLITSCREEN // Kart's splitscreen netgame feature
#define STATLENGTH (TICRATE*2) #define STATLENGTH (TICRATE*2)

View file

@ -129,6 +129,9 @@ static void Command_StopMovie_f(void);
static void Command_Map_f(void); static void Command_Map_f(void);
static void Command_ResetCamera_f(void); static void Command_ResetCamera_f(void);
static void Command_View_f (void);
static void Command_SetViews_f(void);
static void Command_Addfile(void); static void Command_Addfile(void);
static void Command_ListWADS_f(void); static void Command_ListWADS_f(void);
#ifdef DELFILE #ifdef DELFILE
@ -741,6 +744,13 @@ void D_RegisterClientCommands(void)
COM_AddCommand("resetcamera", Command_ResetCamera_f); COM_AddCommand("resetcamera", Command_ResetCamera_f);
COM_AddCommand("view", Command_View_f);
COM_AddCommand("view2", Command_View_f);
COM_AddCommand("view3", Command_View_f);
COM_AddCommand("view4", Command_View_f);
COM_AddCommand("setviews", Command_SetViews_f);
COM_AddCommand("setcontrol", Command_Setcontrol_f); COM_AddCommand("setcontrol", Command_Setcontrol_f);
COM_AddCommand("setcontrol2", Command_Setcontrol2_f); COM_AddCommand("setcontrol2", Command_Setcontrol2_f);
COM_AddCommand("setcontrol3", Command_Setcontrol3_f); COM_AddCommand("setcontrol3", Command_Setcontrol3_f);
@ -815,6 +825,9 @@ void D_RegisterClientCommands(void)
COM_AddCommand("displayplayer", Command_Displayplayer_f); COM_AddCommand("displayplayer", Command_Displayplayer_f);
CV_RegisterVar(&cv_recordmultiplayerdemos);
CV_RegisterVar(&cv_netdemosyncquality);
// FIXME: not to be here.. but needs be done for config loading // FIXME: not to be here.. but needs be done for config loading
CV_RegisterVar(&cv_usegamma); CV_RegisterVar(&cv_usegamma);
@ -938,6 +951,8 @@ void D_RegisterClientCommands(void)
// screen.c // screen.c
CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_fullscreen);
CV_RegisterVar(&cv_renderview); CV_RegisterVar(&cv_renderview);
CV_RegisterVar(&cv_vhseffect);
CV_RegisterVar(&cv_shittyscreen);
CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_depth);
CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_width);
CV_RegisterVar(&cv_scr_height); CV_RegisterVar(&cv_scr_height);
@ -1149,11 +1164,11 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
// spaces may have been removed // spaces may have been removed
if (playernum == consoleplayer) if (playernum == consoleplayer)
CV_StealthSet(&cv_playername, tmpname); CV_StealthSet(&cv_playername, tmpname);
else if (playernum == secondarydisplayplayer || (!netgame && playernum == 1)) else if (playernum == displayplayers[1] || (!netgame && playernum == 1))
CV_StealthSet(&cv_playername2, tmpname); CV_StealthSet(&cv_playername2, tmpname);
else if (playernum == thirddisplayplayer || (!netgame && playernum == 2)) else if (playernum == displayplayers[2] || (!netgame && playernum == 2))
CV_StealthSet(&cv_playername3, tmpname); CV_StealthSet(&cv_playername3, tmpname);
else if (playernum == fourthdisplayplayer || (!netgame && playernum == 3)) else if (playernum == displayplayers[3] || (!netgame && playernum == 3))
CV_StealthSet(&cv_playername4, tmpname); CV_StealthSet(&cv_playername4, tmpname);
else I_Assert(((void)"CleanupPlayerName used on non-local player", 0)); else I_Assert(((void)"CleanupPlayerName used on non-local player", 0));
@ -1185,6 +1200,7 @@ static void SetPlayerName(INT32 playernum, char *newname)
HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false); HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
strcpy(player_names[playernum], newname); strcpy(player_names[playernum], newname);
demo_extradata[playernum] |= DXD_NAME;
} }
} }
else else
@ -1260,11 +1276,11 @@ static void ForceAllSkins(INT32 forcedskin)
{ {
if (i == consoleplayer) if (i == consoleplayer)
CV_StealthSet(&cv_skin, skins[forcedskin].name); CV_StealthSet(&cv_skin, skins[forcedskin].name);
else if (i == secondarydisplayplayer) else if (i == displayplayers[1])
CV_StealthSet(&cv_skin2, skins[forcedskin].name); CV_StealthSet(&cv_skin2, skins[forcedskin].name);
else if (i == thirddisplayplayer) else if (i == displayplayers[2])
CV_StealthSet(&cv_skin3, skins[forcedskin].name); CV_StealthSet(&cv_skin3, skins[forcedskin].name);
else if (i == fourthdisplayplayer) else if (i == displayplayers[3])
CV_StealthSet(&cv_skin4, skins[forcedskin].name); CV_StealthSet(&cv_skin4, skins[forcedskin].name);
} }
} }
@ -1399,8 +1415,8 @@ static void SendNameAndColor2(void)
if (splitscreen < 1 && !botingame) if (splitscreen < 1 && !botingame)
return; // can happen if skin2/color2/name2 changed return; // can happen if skin2/color2/name2 changed
if (secondarydisplayplayer != consoleplayer) if (displayplayers[1] != consoleplayer)
secondplaya = secondarydisplayplayer; secondplaya = displayplayers[1];
else if (!netgame) // HACK else if (!netgame) // HACK
secondplaya = 1; secondplaya = 1;
@ -1449,7 +1465,7 @@ static void SendNameAndColor2(void)
CleanupPlayerName(secondplaya, cv_playername2.zstring); CleanupPlayerName(secondplaya, cv_playername2.zstring);
strcpy(player_names[secondplaya], cv_playername2.zstring); strcpy(player_names[secondplaya], cv_playername2.zstring);
// don't use secondarydisplayplayer: the second player must be 1 // don't use displayplayers[1]: the second player must be 1
players[secondplaya].skincolor = cv_playercolor2.value; players[secondplaya].skincolor = cv_playercolor2.value;
if (players[secondplaya].mo) if (players[secondplaya].mo)
players[secondplaya].mo->color = players[secondplaya].skincolor; players[secondplaya].mo->color = players[secondplaya].skincolor;
@ -1488,14 +1504,14 @@ static void SendNameAndColor2(void)
snac2pending++; snac2pending++;
// Don't change name if muted // Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(secondarydisplayplayer))) if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[1])))
CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]); CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]);
else // Cleanup name if changing it else // Cleanup name if changing it
CleanupPlayerName(secondarydisplayplayer, cv_playername2.zstring); CleanupPlayerName(displayplayers[1], cv_playername2.zstring);
// Don't change skin if the server doesn't want you to. // Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(secondarydisplayplayer)) if (!CanChangeSkin(displayplayers[1]))
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name); CV_StealthSet(&cv_skin2, skins[players[displayplayers[1]].skin].name);
// check if player has the skin loaded (cv_skin2 may have // check if player has the skin loaded (cv_skin2 may have
// the name of a skin that was available in the previous game) // the name of a skin that was available in the previous game)
@ -1522,8 +1538,8 @@ static void SendNameAndColor3(void)
if (splitscreen < 2) if (splitscreen < 2)
return; // can happen if skin3/color3/name3 changed return; // can happen if skin3/color3/name3 changed
if (thirddisplayplayer != consoleplayer) if (displayplayers[2] != consoleplayer)
thirdplaya = thirddisplayplayer; thirdplaya = displayplayers[2];
else if (!netgame) // HACK else if (!netgame) // HACK
thirdplaya = 2; thirdplaya = 2;
@ -1564,7 +1580,7 @@ static void SendNameAndColor3(void)
CleanupPlayerName(thirdplaya, cv_playername3.zstring); CleanupPlayerName(thirdplaya, cv_playername3.zstring);
strcpy(player_names[thirdplaya], cv_playername3.zstring); strcpy(player_names[thirdplaya], cv_playername3.zstring);
// don't use thirddisplayplayer: the third player must be 2 // don't use displayplayers[2]: the third player must be 2
players[thirdplaya].skincolor = cv_playercolor3.value; players[thirdplaya].skincolor = cv_playercolor3.value;
if (players[thirdplaya].mo) if (players[thirdplaya].mo)
players[thirdplaya].mo->color = players[thirdplaya].skincolor; players[thirdplaya].mo->color = players[thirdplaya].skincolor;
@ -1603,14 +1619,14 @@ static void SendNameAndColor3(void)
snac3pending++; snac3pending++;
// Don't change name if muted // Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(thirddisplayplayer))) if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[2])))
CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]); CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]);
else // Cleanup name if changing it else // Cleanup name if changing it
CleanupPlayerName(thirddisplayplayer, cv_playername3.zstring); CleanupPlayerName(displayplayers[2], cv_playername3.zstring);
// Don't change skin if the server doesn't want you to. // Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(thirddisplayplayer)) if (!CanChangeSkin(displayplayers[2]))
CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].skin].name); CV_StealthSet(&cv_skin3, skins[players[displayplayers[2]].skin].name);
// check if player has the skin loaded (cv_skin3 may have // check if player has the skin loaded (cv_skin3 may have
// the name of a skin that was available in the previous game) // the name of a skin that was available in the previous game)
@ -1637,8 +1653,8 @@ static void SendNameAndColor4(void)
if (splitscreen < 3) if (splitscreen < 3)
return; // can happen if skin4/color4/name4 changed return; // can happen if skin4/color4/name4 changed
if (fourthdisplayplayer != consoleplayer) if (displayplayers[3] != consoleplayer)
fourthplaya = fourthdisplayplayer; fourthplaya = displayplayers[3];
else if (!netgame) // HACK else if (!netgame) // HACK
fourthplaya = 3; fourthplaya = 3;
@ -1687,7 +1703,7 @@ static void SendNameAndColor4(void)
CleanupPlayerName(fourthplaya, cv_playername4.zstring); CleanupPlayerName(fourthplaya, cv_playername4.zstring);
strcpy(player_names[fourthplaya], cv_playername4.zstring); strcpy(player_names[fourthplaya], cv_playername4.zstring);
// don't use fourthdisplayplayer: the second player must be 4 // don't use displayplayers[3]: the second player must be 4
players[fourthplaya].skincolor = cv_playercolor4.value; players[fourthplaya].skincolor = cv_playercolor4.value;
if (players[fourthplaya].mo) if (players[fourthplaya].mo)
players[fourthplaya].mo->color = players[fourthplaya].skincolor; players[fourthplaya].mo->color = players[fourthplaya].skincolor;
@ -1726,14 +1742,14 @@ static void SendNameAndColor4(void)
snac4pending++; snac4pending++;
// Don't change name if muted // Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(fourthdisplayplayer))) if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[3])))
CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]); CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]);
else // Cleanup name if changing it else // Cleanup name if changing it
CleanupPlayerName(fourthdisplayplayer, cv_playername4.zstring); CleanupPlayerName(displayplayers[3], cv_playername4.zstring);
// Don't change skin if the server doesn't want you to. // Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(fourthdisplayplayer)) if (!CanChangeSkin(displayplayers[3]))
CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].skin].name); CV_StealthSet(&cv_skin4, skins[players[displayplayers[3]].skin].name);
// check if player has the skin loaded (cv_skin4 may have // check if player has the skin loaded (cv_skin4 may have
// the name of a skin that was available in the previous game) // the name of a skin that was available in the previous game)
@ -1763,12 +1779,12 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
#endif #endif
if (playernum == consoleplayer) if (playernum == consoleplayer)
snacpending--; snacpending--; // TODO: make snacpending an array instead of 4 separate vars?
else if (playernum == secondarydisplayplayer) else if (playernum == displayplayers[1])
snac2pending--; snac2pending--;
else if (playernum == thirddisplayplayer) else if (playernum == displayplayers[2])
snac3pending--; snac3pending--;
else if (playernum == fourthdisplayplayer) else if (playernum == displayplayers[3])
snac4pending--; snac4pending--;
#ifdef PARANOIA #ifdef PARANOIA
@ -1788,10 +1804,11 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
p->skincolor = color % MAXSKINCOLORS; p->skincolor = color % MAXSKINCOLORS;
if (p->mo) if (p->mo)
p->mo->color = (UINT8)p->skincolor; p->mo->color = (UINT8)p->skincolor;
demo_extradata[playernum] |= DXD_COLOR;
// normal player colors // normal player colors
if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer] if (server && (p != &players[consoleplayer] && p != &players[displayplayers[1]]
&& p != &players[thirddisplayplayer] && p != &players[fourthdisplayplayer])) && p != &players[displayplayers[2]] && p != &players[displayplayers[3]]))
{ {
boolean kick = false; boolean kick = false;
@ -1828,11 +1845,11 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
if (playernum == consoleplayer) if (playernum == consoleplayer)
CV_StealthSet(&cv_skin, skins[forcedskin].name); CV_StealthSet(&cv_skin, skins[forcedskin].name);
else if (playernum == secondarydisplayplayer) else if (playernum == displayplayers[1])
CV_StealthSet(&cv_skin2, skins[forcedskin].name); CV_StealthSet(&cv_skin2, skins[forcedskin].name);
else if (playernum == thirddisplayplayer) else if (playernum == displayplayers[2])
CV_StealthSet(&cv_skin3, skins[forcedskin].name); CV_StealthSet(&cv_skin3, skins[forcedskin].name);
else if (playernum == fourthdisplayplayer) else if (playernum == displayplayers[3])
CV_StealthSet(&cv_skin4, skins[forcedskin].name); CV_StealthSet(&cv_skin4, skins[forcedskin].name);
} }
else else
@ -1919,7 +1936,198 @@ void D_SendPlayerConfig(void)
// Only works for displayplayer, sorry! // Only works for displayplayer, sorry!
static void Command_ResetCamera_f(void) static void Command_ResetCamera_f(void)
{ {
P_ResetCamera(&players[displayplayer], &camera); P_ResetCamera(&players[displayplayers[0]], &camera[0]);
}
/* Consider replacing nametonum with this */
static INT32 LookupPlayer(const char *s)
{
INT32 playernum;
if (*s == '0')/* clever way to bypass atoi */
return 0;
if (( playernum = atoi(s) ))
{
playernum = max(min(playernum, MAXPLAYERS-1), 0);/* not out of range */
return playernum;
}
for (playernum = 0; playernum < MAXPLAYERS; ++playernum)
{
/* Match name case-insensitively: fully, or partially the start. */
if (playeringame[playernum])
if (strnicmp(player_names[playernum], s, strlen(s)) == 0)
{
return playernum;
}
}
return -1;
}
static INT32 FindPlayerByPlace(INT32 place)
{
INT32 playernum;
for (playernum = 0; playernum < MAXPLAYERS; ++playernum)
if (playeringame[playernum])
{
if (players[playernum].kartstuff[k_position] == place)
{
return playernum;
}
}
return -1;
}
//
// GetViewablePlayerPlaceRange
// Return in first and last, that player available to view, sorted by placement
// in the race.
//
static void GetViewablePlayerPlaceRange(INT32 *first, INT32 *last)
{
INT32 i;
INT32 place;
(*first) = MAXPLAYERS;
(*last) = 0;
for (i = 0; i < MAXPLAYERS; ++i)
if (G_CouldView(i))
{
place = players[i].kartstuff[k_position];
if (place < (*first))
(*first) = place;
if (place > (*last))
(*last) = place;
}
}
#define PRINTVIEWPOINT( pre,suf ) \
CONS_Printf(pre"viewing \x84(%d) \x83%s\x80"suf".\n",\
(*displayplayerp), player_names[(*displayplayerp)]);
static void Command_View_f(void)
{
INT32 *displayplayerp;
INT32 olddisplayplayer;
int viewnum;
const char *playerparam;
INT32 placenum;
INT32 playernum;
INT32 firstplace, lastplace;
char c;
/* easy peasy */
c = COM_Argv(0)[strlen(COM_Argv(0))-1];/* may be digit */
switch (c)
{
case '2': viewnum = 2; break;
case '3': viewnum = 3; break;
case '4': viewnum = 4; break;
default: viewnum = 1;
}
if (viewnum > 1 && !( multiplayer && demo.playback ))
{
CONS_Alert(CONS_NOTICE,
"You must be viewing a multiplayer replay to use this.\n");
return;
}
displayplayerp = &displayplayers[viewnum];
if (COM_Argc() > 1)/* switch to player */
{
playerparam = COM_Argv(1);
if (playerparam[0] == '#')/* search by placement */
{
placenum = atoi(&playerparam[1]);
playernum = FindPlayerByPlace(placenum);
if (playernum == -1 || !G_CouldView(playernum))
{
GetViewablePlayerPlaceRange(&firstplace, &lastplace);
if (playernum == -1)
{
CONS_Alert(CONS_WARNING, "There is no player in that place! ");
}
else
{
CONS_Alert(CONS_WARNING,
"That player cannot be viewed currently! "
"The first player that you can view is \x82#%d\x80; ",
firstplace);
}
CONS_Printf("Last place is \x82#%d\x80.\n", lastplace);
return;
}
}
else
{
if (( playernum = LookupPlayer(COM_Argv(1)) ) == -1)
{
CONS_Alert(CONS_WARNING, "There is no player by that name!\n");
return;
}
if (!playeringame[playernum])
{
CONS_Alert(CONS_WARNING, "There is no player using that slot!\n");
return;
}
}
olddisplayplayer = (*displayplayerp);
G_ResetView(viewnum, playernum, false);
/* The player we wanted was corrected to who it already was. */
if ((*displayplayerp) == olddisplayplayer)
return;
if ((*displayplayerp) != playernum)/* differ parameter */
{
/* skipped some */
CONS_Alert(CONS_NOTICE, "That player cannot be viewed currently.\n");
PRINTVIEWPOINT ("Now "," instead")
}
else
PRINTVIEWPOINT ("Now ",)
}
else/* print current view */
{
if (splitscreen < viewnum-1)/* We can't see those guys! */
return;
PRINTVIEWPOINT ("Currently ",)
}
}
#undef PRINTVIEWPOINT
static void Command_SetViews_f(void)
{
UINT8 splits;
UINT8 newsplits;
if (!( demo.playback && multiplayer ))
{
CONS_Alert(CONS_NOTICE,
"You must be viewing a multiplayer replay to use this.\n");
return;
}
if (COM_Argc() != 2)
{
CONS_Printf("setviews <views>: set the number of split screens\n");
return;
}
splits = splitscreen+1;
newsplits = atoi(COM_Argv(1));
newsplits = min(max(newsplits, 1), 4);
if (newsplits > splits)
G_AdjustView(newsplits, 0, true);
else
{
splitscreen = newsplits-1;
R_ExecuteSetViewSize();
}
} }
// ======================================================================== // ========================================================================
@ -1932,9 +2140,14 @@ static void Command_Playdemo_f(void)
{ {
char name[256]; char name[256];
if (COM_Argc() != 2) if (COM_Argc() < 2)
{ {
CONS_Printf(M_GetText("playdemo <demoname>: playback a demo\n")); CONS_Printf("playdemo <demoname> [-addfiles / -force]:\n");
CONS_Printf(M_GetText(
"Play back a demo file. The full path from your Kart directory must be given.\n\n"
"* With \"-addfiles\", any required files are added from a list contained within the demo file.\n"
"* With \"-force\", the demo is played even if the necessary files have not been added.\n"));
return; return;
} }
@ -1945,7 +2158,7 @@ static void Command_Playdemo_f(void)
} }
// disconnect from server here? // disconnect from server here?
if (demoplayback) if (demo.playback)
G_StopDemo(); G_StopDemo();
if (metalplayback) if (metalplayback)
G_StopMetalDemo(); G_StopMetalDemo();
@ -1956,6 +2169,9 @@ static void Command_Playdemo_f(void)
CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name); CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name);
demo.loadfiles = strcmp(COM_Argv(2), "-addfiles") == 0;
demo.ignorefiles = strcmp(COM_Argv(2), "-force") == 0;
// Internal if no extension, external if one exists // Internal if no extension, external if one exists
// If external, convert the file name to a path in SRB2's home directory // If external, convert the file name to a path in SRB2's home directory
if (FIL_CheckExtension(name)) if (FIL_CheckExtension(name))
@ -1981,7 +2197,7 @@ static void Command_Timedemo_f(void)
} }
// disconnect from server here? // disconnect from server here?
if (demoplayback) if (demo.playback)
G_StopDemo(); G_StopDemo();
if (metalplayback) if (metalplayback)
G_StopMetalDemo(); G_StopMetalDemo();
@ -2105,7 +2321,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
{ {
//CL_AddSplitscreenPlayer(); //CL_AddSplitscreenPlayer();
botingame = true; botingame = true;
secondarydisplayplayer = 1; displayplayers[1] = 1;
playeringame[1] = true; playeringame[1] = true;
players[1].bot = 1; players[1].bot = 1;
SendNameAndColor2(); SendNameAndColor2();
@ -2157,12 +2373,8 @@ void D_ModifyClientVote(SINT8 voted, UINT8 splitplayer)
char *p = buf; char *p = buf;
UINT8 player = consoleplayer; UINT8 player = consoleplayer;
if (splitplayer == 1) if (splitplayer > 0)
player = secondarydisplayplayer; player = displayplayers[splitplayer];
else if (splitplayer == 2)
player = thirddisplayplayer;
else if (splitplayer == 3)
player = fourthdisplayplayer;
WRITESINT8(p, voted); WRITESINT8(p, voted);
WRITEUINT8(p, player); WRITEUINT8(p, player);
@ -2432,7 +2644,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
CON_ToggleOff(); CON_ToggleOff();
CON_ClearHUD(); CON_ClearHUD();
if (demoplayback && !timingdemo) if (demo.playback && !demo.timing)
precache = false; precache = false;
if (resetplayer) if (resetplayer)
@ -2449,17 +2661,19 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
LUAh_MapChange(mapnumber); LUAh_MapChange(mapnumber);
#endif*/ #endif*/
demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING;
demo.savebutton = 0;
G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene); G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene);
if (demoplayback && !timingdemo) if (demo.playback && !demo.timing)
precache = true; precache = true;
if (timingdemo) if (demo.timing)
G_DoneLevelLoad(); G_DoneLevelLoad();
if (metalrecording) if (metalrecording)
G_BeginMetal(); G_BeginMetal();
if (demorecording) // Okay, level loaded, character spawned and skinned, if (demo.recording) // Okay, level loaded, character spawned and skinned,
G_BeginRecording(); // I AM NOW READY TO RECORD. G_BeginRecording(); // I AM NOW READY TO RECORD.
demo_start = true; demo.deferstart = true;
} }
static void Command_Pause(void) static void Command_Pause(void)
@ -2509,13 +2723,13 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
return; return;
} }
if (modeattacking) if (modeattacking && !demo.playback)
return; return;
paused = READUINT8(*cp); paused = READUINT8(*cp);
dedicatedpause = READUINT8(*cp); dedicatedpause = READUINT8(*cp);
if (!demoplayback) if (!demo.playback)
{ {
if (netgame) if (netgame)
{ {
@ -2602,6 +2816,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
if (players[respawnplayer].mo) if (players[respawnplayer].mo)
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000); P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000);
demo_extradata[playernum] |= DXD_RESPAWN;
} }
/** Deals with an ::XD_RANDOMSEED message in a netgame. /** Deals with an ::XD_RANDOMSEED message in a netgame.
@ -2823,11 +3038,11 @@ static void Command_Teamchange2_f(void)
return; return;
} }
if (players[secondarydisplayplayer].spectator) if (players[displayplayers[1]].spectator)
error = !(NetPacket.packet.newteam || (players[secondarydisplayplayer].pflags & PF_WANTSTOJOIN)); error = !(NetPacket.packet.newteam || (players[displayplayers[1]].pflags & PF_WANTSTOJOIN));
else if (G_GametypeHasTeams()) else if (G_GametypeHasTeams())
error = (NetPacket.packet.newteam == (unsigned)players[secondarydisplayplayer].ctfteam); error = (NetPacket.packet.newteam == (unsigned)players[displayplayers[1]].ctfteam);
else if (G_GametypeHasSpectators() && !players[secondarydisplayplayer].spectator) else if (G_GametypeHasSpectators() && !players[displayplayers[1]].spectator)
error = (NetPacket.packet.newteam == 3); error = (NetPacket.packet.newteam == 3);
#ifdef PARANOIA #ifdef PARANOIA
else else
@ -2914,11 +3129,11 @@ static void Command_Teamchange3_f(void)
return; return;
} }
if (players[thirddisplayplayer].spectator) if (players[displayplayers[2]].spectator)
error = !(NetPacket.packet.newteam || (players[thirddisplayplayer].pflags & PF_WANTSTOJOIN)); error = !(NetPacket.packet.newteam || (players[displayplayers[2]].pflags & PF_WANTSTOJOIN));
else if (G_GametypeHasTeams()) else if (G_GametypeHasTeams())
error = (NetPacket.packet.newteam == (unsigned)players[thirddisplayplayer].ctfteam); error = (NetPacket.packet.newteam == (unsigned)players[displayplayers[2]].ctfteam);
else if (G_GametypeHasSpectators() && !players[thirddisplayplayer].spectator) else if (G_GametypeHasSpectators() && !players[displayplayers[2]].spectator)
error = (NetPacket.packet.newteam == 3); error = (NetPacket.packet.newteam == 3);
#ifdef PARANOIA #ifdef PARANOIA
else else
@ -3005,11 +3220,11 @@ static void Command_Teamchange4_f(void)
return; return;
} }
if (players[fourthdisplayplayer].spectator) if (players[displayplayers[3]].spectator)
error = !(NetPacket.packet.newteam || (players[fourthdisplayplayer].pflags & PF_WANTSTOJOIN)); error = !(NetPacket.packet.newteam || (players[displayplayers[3]].pflags & PF_WANTSTOJOIN));
else if (G_GametypeHasTeams()) else if (G_GametypeHasTeams())
error = (NetPacket.packet.newteam == (unsigned)players[fourthdisplayplayer].ctfteam); error = (NetPacket.packet.newteam == (unsigned)players[displayplayers[3]].ctfteam);
else if (G_GametypeHasSpectators() && !players[fourthdisplayplayer].spectator) else if (G_GametypeHasSpectators() && !players[displayplayers[3]].spectator)
error = (NetPacket.packet.newteam == 3); error = (NetPacket.packet.newteam == 3);
#ifdef PARANOIA #ifdef PARANOIA
else else
@ -3406,8 +3621,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame
//reset view if you are changed, or viewing someone who was changed. //reset view if you are changed, or viewing someone who was changed.
if (playernum == consoleplayer || displayplayer == playernum) if (playernum == consoleplayer || displayplayers[0] == playernum)
displayplayer = consoleplayer; displayplayers[0] = consoleplayer;
if (G_GametypeHasTeams()) if (G_GametypeHasTeams())
{ {
@ -3415,11 +3630,11 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
{ {
if (playernum == consoleplayer) //CTF and Team Match colors. if (playernum == consoleplayer) //CTF and Team Match colors.
CV_SetValue(&cv_playercolor, NetPacket.packet.newteam + 5); CV_SetValue(&cv_playercolor, NetPacket.packet.newteam + 5);
else if (playernum == secondarydisplayplayer) else if (playernum == displayplayers[1])
CV_SetValue(&cv_playercolor2, NetPacket.packet.newteam + 5); CV_SetValue(&cv_playercolor2, NetPacket.packet.newteam + 5);
else if (playernum == thirddisplayplayer) else if (playernum == displayplayers[2])
CV_SetValue(&cv_playercolor3, NetPacket.packet.newteam + 5); CV_SetValue(&cv_playercolor3, NetPacket.packet.newteam + 5);
else if (playernum == fourthdisplayplayer) else if (playernum == displayplayers[3])
CV_SetValue(&cv_playercolor4, NetPacket.packet.newteam + 5); CV_SetValue(&cv_playercolor4, NetPacket.packet.newteam + 5);
} }
} }
@ -3427,6 +3642,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
return; return;
demo_extradata[playernum] |= DXD_PLAYSTATE;
// Clear player score and rings if a spectator. // Clear player score and rings if a spectator.
if (players[playernum].spectator) if (players[playernum].spectator)
{ {
@ -4485,7 +4702,7 @@ static void PointLimit_OnChange(void)
static void NumLaps_OnChange(void) static void NumLaps_OnChange(void)
{ {
if (!G_RaceGametype() || (modeattacking || demoplayback)) if (!G_RaceGametype() || (modeattacking || demo.playback))
return; return;
if (server && Playing() if (server && Playing()
@ -4925,7 +5142,7 @@ static void Command_ExitLevel_f(void)
CONS_Printf(M_GetText("This only works in a netgame.\n")); CONS_Printf(M_GetText("This only works in a netgame.\n"));
else if (!(server || (IsPlayerAdmin(consoleplayer)))) else if (!(server || (IsPlayerAdmin(consoleplayer))))
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
else if (gamestate != GS_LEVEL || demoplayback) else if (gamestate != GS_LEVEL || demo.playback)
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else else
SendNetXCmd(XD_EXITLEVEL, NULL, 0); SendNetXCmd(XD_EXITLEVEL, NULL, 0);
@ -5023,13 +5240,13 @@ static void Got_PickVotecmd(UINT8 **cp, INT32 playernum)
Y_SetupVoteFinish(pick, level); Y_SetupVoteFinish(pick, level);
} }
/** Prints the number of the displayplayer. /** Prints the number of displayplayers[0].
* *
* \todo Possibly remove this; it was useful for debugging at one point. * \todo Possibly remove this; it was useful for debugging at one point.
*/ */
static void Command_Displayplayer_f(void) static void Command_Displayplayer_f(void)
{ {
CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayer); CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayers[0]);
} }
/** Quits a game and returns to the title screen. /** Quits a game and returns to the title screen.
@ -5224,7 +5441,7 @@ static void Name2_OnChange(void)
if (cv_mute.value) //Secondary player can't be admin. if (cv_mute.value) //Secondary player can't be admin.
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]); CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]);
} }
else else
SendNameAndColor2(); SendNameAndColor2();
@ -5235,7 +5452,7 @@ static void Name3_OnChange(void)
if (cv_mute.value) //Third player can't be admin. if (cv_mute.value) //Third player can't be admin.
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]); CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]);
} }
else else
SendNameAndColor3(); SendNameAndColor3();
@ -5246,7 +5463,7 @@ static void Name4_OnChange(void)
if (cv_mute.value) //Secondary player can't be admin. if (cv_mute.value) //Secondary player can't be admin.
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]); CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]);
} }
else else
SendNameAndColor4(); SendNameAndColor4();
@ -5287,12 +5504,12 @@ static void Skin2_OnChange(void)
if (!Playing() || !splitscreen) if (!Playing() || !splitscreen)
return; // do whatever you want return; // do whatever you want
if (CanChangeSkin(secondarydisplayplayer) && !P_PlayerMoving(secondarydisplayplayer)) if (CanChangeSkin(displayplayers[1]) && !P_PlayerMoving(displayplayers[1]))
SendNameAndColor2(); SendNameAndColor2();
else else
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name); CV_StealthSet(&cv_skin2, skins[players[displayplayers[1]].skin].name);
} }
} }
@ -5301,12 +5518,12 @@ static void Skin3_OnChange(void)
if (!Playing() || splitscreen < 2) if (!Playing() || splitscreen < 2)
return; // do whatever you want return; // do whatever you want
if (CanChangeSkin(thirddisplayplayer) && !P_PlayerMoving(thirddisplayplayer)) if (CanChangeSkin(displayplayers[2]) && !P_PlayerMoving(displayplayers[2]))
SendNameAndColor3(); SendNameAndColor3();
else else
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].skin].name); CV_StealthSet(&cv_skin3, skins[players[displayplayers[2]].skin].name);
} }
} }
@ -5315,12 +5532,12 @@ static void Skin4_OnChange(void)
if (!Playing() || splitscreen < 3) if (!Playing() || splitscreen < 3)
return; // do whatever you want return; // do whatever you want
if (CanChangeSkin(fourthdisplayplayer) && !P_PlayerMoving(fourthdisplayplayer)) if (CanChangeSkin(displayplayers[3]) && !P_PlayerMoving(displayplayers[3]))
SendNameAndColor4(); SendNameAndColor4();
else else
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].skin].name); CV_StealthSet(&cv_skin4, skins[players[displayplayers[3]].skin].name);
} }
} }
@ -5361,7 +5578,7 @@ static void Color2_OnChange(void)
if (!Playing() || !splitscreen) if (!Playing() || !splitscreen)
return; // do whatever you want return; // do whatever you want
if (!P_PlayerMoving(secondarydisplayplayer)) if (!P_PlayerMoving(displayplayers[1]))
{ {
// Color change menu scrolling fix is no longer necessary // Color change menu scrolling fix is no longer necessary
SendNameAndColor2(); SendNameAndColor2();
@ -5369,7 +5586,7 @@ static void Color2_OnChange(void)
else else
{ {
CV_StealthSetValue(&cv_playercolor2, CV_StealthSetValue(&cv_playercolor2,
players[secondarydisplayplayer].skincolor); players[displayplayers[1]].skincolor);
} }
} }
@ -5378,7 +5595,7 @@ static void Color3_OnChange(void)
if (!Playing() || splitscreen < 2) if (!Playing() || splitscreen < 2)
return; // do whatever you want return; // do whatever you want
if (!P_PlayerMoving(thirddisplayplayer)) if (!P_PlayerMoving(displayplayers[2]))
{ {
// Color change menu scrolling fix is no longer necessary // Color change menu scrolling fix is no longer necessary
SendNameAndColor3(); SendNameAndColor3();
@ -5386,7 +5603,7 @@ static void Color3_OnChange(void)
else else
{ {
CV_StealthSetValue(&cv_playercolor3, CV_StealthSetValue(&cv_playercolor3,
players[thirddisplayplayer].skincolor); players[displayplayers[2]].skincolor);
} }
} }
@ -5395,7 +5612,7 @@ static void Color4_OnChange(void)
if (!Playing() || splitscreen < 3) if (!Playing() || splitscreen < 3)
return; // do whatever you want return; // do whatever you want
if (!P_PlayerMoving(fourthdisplayplayer)) if (!P_PlayerMoving(displayplayers[3]))
{ {
// Color change menu scrolling fix is no longer necessary // Color change menu scrolling fix is no longer necessary
SendNameAndColor4(); SendNameAndColor4();
@ -5403,7 +5620,7 @@ static void Color4_OnChange(void)
else else
{ {
CV_StealthSetValue(&cv_playercolor4, CV_StealthSetValue(&cv_playercolor4,
players[fourthdisplayplayer].skincolor); players[displayplayers[3]].skincolor);
} }
} }

View file

@ -2142,11 +2142,12 @@ static boolean GoodDataFileName(const char *s)
p = s + strlen(s) - strlen(tail); p = s + strlen(s) - strlen(tail);
if (p <= s) return false; // too short if (p <= s) return false; // too short
if (!fasticmp(p, tail)) return false; // doesn't end in .dat if (!fasticmp(p, tail)) return false; // doesn't end in .dat
#ifdef DELFILE
if (fasticmp(s, "gamedata.dat") && !disableundo) return false; if (fasticmp(s, "gamedata.dat")) return false; // Vanilla SRB2 gamedata
#else if (fasticmp(s, "main.dat")) return false; // Vanilla SRB2 time attack replay folder
if (fasticmp(s, "gamedata.dat")) return false; if (fasticmp(s, "kartdata.dat")) return false; // SRB2Kart gamedata
#endif if (fasticmp(s, "kart.dat")) return false; // SRB2Kart time attack replay folder
if (fasticmp(s, "online.dat")) return false; // SRB2Kart online replay folder
return true; return true;
} }
@ -9785,7 +9786,7 @@ static inline int lib_getenum(lua_State *L)
// DYNAMIC variables too!! // DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here. // Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime. // You know, like consoleplayer, displayplayers, or gametime.
if (fastcmp(word,"gamemap")) { if (fastcmp(word,"gamemap")) {
lua_pushinteger(L, gamemap); lua_pushinteger(L, gamemap);
return 1; return 1;
@ -9859,7 +9860,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, mapmusflags); lua_pushinteger(L, mapmusflags);
return 1; return 1;
} else if (fastcmp(word,"server")) { } else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer]) if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer])
return 0; return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1; return 1;

View file

@ -157,6 +157,9 @@ extern FILE *logstream;
// Otherwise we can't force updates! // Otherwise we can't force updates!
#endif #endif
// Maintain compatibility with 1.0.x record attack replays?
#define DEMO_COMPAT_100
// Does this version require an added patch file? // Does this version require an added patch file?
// Comment or uncomment this as necessary. // Comment or uncomment this as necessary.
//#define USE_PATCH_DTA //#define USE_PATCH_DTA

View file

@ -77,7 +77,10 @@ extern boolean addedtogame; // true after the server has added you
extern boolean multiplayer; extern boolean multiplayer;
extern INT16 gametype; extern INT16 gametype;
#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer
extern UINT8 splitscreen; extern UINT8 splitscreen;
extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean circuitmap; // Does this level have 'circuit mode'?
extern boolean fromlevelselect; extern boolean fromlevelselect;
extern boolean forceresetplayers, deferencoremode; extern boolean forceresetplayers, deferencoremode;
@ -106,14 +109,8 @@ extern UINT8 window_notinfocus; // are we in focus? (backend independant -- hand
extern boolean nodrawers; extern boolean nodrawers;
extern boolean noblit; extern boolean noblit;
extern boolean lastdraw; extern boolean lastdraw;
extern postimg_t postimgtype; extern postimg_t postimgtype[MAXSPLITSCREENPLAYERS];
extern INT32 postimgparam; extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
extern postimg_t postimgtype2;
extern INT32 postimgparam2;
extern postimg_t postimgtype3;
extern INT32 postimgparam3;
extern postimg_t postimgtype4;
extern INT32 postimgparam4;
extern INT32 viewwindowx, viewwindowy; extern INT32 viewwindowx, viewwindowy;
extern INT32 viewwidth, scaledviewwidth; extern INT32 viewwidth, scaledviewwidth;
@ -122,10 +119,7 @@ extern boolean gamedataloaded;
// Player taking events, and displaying. // Player taking events, and displaying.
extern INT32 consoleplayer; extern INT32 consoleplayer;
extern INT32 displayplayer; extern INT32 displayplayers[MAXSPLITSCREENPLAYERS];
extern INT32 secondarydisplayplayer; // for splitscreen
extern INT32 thirddisplayplayer;
extern INT32 fourthdisplayplayer;
// Maps of special importance // Maps of special importance
extern INT16 spstage_start; extern INT16 spstage_start;

View file

@ -584,6 +584,7 @@ void F_StartCredits(void)
S_StopMusic(); S_StopMusic();
S_ChangeMusicInternal("credit", false); S_ChangeMusicInternal("credit", false);
S_ShowMusicCredit();
finalecount = 0; finalecount = 0;
animtimer = 0; animtimer = 0;
@ -927,9 +928,9 @@ void F_StartTitleScreen(void)
// IWAD dependent stuff. // IWAD dependent stuff.
// music is started in the ticker // music is started in the ticker
if (!fromtitledemo) // SRB2Kart: Don't reset music if the right track is already playing if (!demo.fromtitle) // SRB2Kart: Don't reset music if the right track is already playing
S_StopMusic(); S_StopMusic();
fromtitledemo = false; demo.fromtitle = false;
animtimer = 0; animtimer = 0;
@ -1042,11 +1043,29 @@ void F_TitleScreenTicker(boolean run)
// is it time? // is it time?
if (!(--demoIdleLeft)) if (!(--demoIdleLeft))
{ {
//static boolean use_netreplay = false;
char dname[9]; char dname[9];
lumpnum_t l; lumpnum_t l;
const char *mapname; const char *mapname;
UINT8 numstaff; UINT8 numstaff;
//@TODO uncomment this when this goes into vanilla
/*if ((use_netreplay = !use_netreplay))*/
{
numstaff = 1;
while ((l = W_CheckNumForName(va("TDEMO%03u", numstaff))) != LUMPERROR)
numstaff++;
numstaff--;
if (numstaff)
{
numstaff = M_RandomKey(numstaff)+1;
snprintf(dname, 9, "TDEMO%03u", numstaff);
goto loadreplay;
}
}
// prevent console spam if failed // prevent console spam if failed
demoIdleLeft = demoIdleTime; demoIdleLeft = demoIdleTime;
@ -1097,7 +1116,10 @@ void F_TitleScreenTicker(boolean run)
return; return;
}*/ }*/
titledemo = fromtitledemo = true; loadreplay:
demo.title = demo.fromtitle = true;
demo.ignorefiles = true;
demo.loadfiles = false;
G_DoPlayDemo(dname); G_DoPlayDemo(dname);
} }
} }

View file

@ -368,9 +368,10 @@ void searchfilemenu(char *tempname)
return; return;
} }
boolean preparefilemenu(boolean samedepth) boolean preparefilemenu(boolean samedepth, boolean replayhut)
{ {
(void)samedepth; (void)samedepth;
(void)replayhut;
return false; return false;
} }
@ -437,9 +438,10 @@ void searchfilemenu(char *tempname)
return; return;
} }
boolean preparefilemenu(boolean samedepth) boolean preparefilemenu(boolean samedepth, boolean replayhut)
{ {
(void)samedepth; (void)samedepth;
(void)replayhut;
return false; return false;
} }
@ -710,7 +712,7 @@ void searchfilemenu(char *tempname)
} }
} }
boolean preparefilemenu(boolean samedepth) boolean preparefilemenu(boolean samedepth, boolean replayhut)
{ {
DIR *dirhandle; DIR *dirhandle;
struct dirent *dent; struct dirent *dent;
@ -759,9 +761,13 @@ boolean preparefilemenu(boolean samedepth)
{ {
if (!S_ISDIR(fsstat.st_mode)) // file if (!S_ISDIR(fsstat.st_mode)) // file
{ {
if (!cv_addons_showall.value) size_t len = strlen(dent->d_name)+1;
if (replayhut)
{
if (strcasecmp(".lmp", dent->d_name+len-5)) continue; // Not a replay
}
else if (!cv_addons_showall.value)
{ {
size_t len = strlen(dent->d_name)+1;
UINT8 ext; UINT8 ext;
for (ext = 0; ext < NUM_EXT_TABLE; ext++) for (ext = 0; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
@ -829,40 +835,49 @@ boolean preparefilemenu(boolean samedepth)
if (!S_ISDIR(fsstat.st_mode)) // file if (!S_ISDIR(fsstat.st_mode)) // file
{ {
if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention
for (; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
ext += EXT_START; // moving to be appropriate position
if (ext >= EXT_LOADSTART) if (replayhut)
{ {
size_t i; if (strcasecmp(".lmp", dent->d_name+len-5)) continue; // Not a replay
for (i = 0; i < numwadfiles; i++) ext = EXT_TXT; // This isn't used anywhere but better safe than sorry for messing with this...
}
else
{
for (; ext < NUM_EXT_TABLE; ext++)
if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
ext += EXT_START; // moving to be appropriate position
if (ext >= EXT_LOADSTART)
{ {
if (!filenamebuf[i][0]) size_t i;
for (i = 0; i < numwadfiles; i++)
{ {
strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH); if (!filenamebuf[i][0])
filenamebuf[i][MAX_WADPATH - 1] = '\0'; {
nameonly(filenamebuf[i]); strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
filenamebuf[i][MAX_WADPATH - 1] = '\0';
nameonly(filenamebuf[i]);
}
if (strcmp(dent->d_name, filenamebuf[i]))
continue;
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
continue;
ext |= EXT_LOADED;
} }
if (strcmp(dent->d_name, filenamebuf[i]))
continue;
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
continue;
ext |= EXT_LOADED;
} }
} else if (ext == EXT_TXT)
else if (ext == EXT_TXT) {
{ if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) ext |= EXT_LOADED;
}
if (!strcmp(dent->d_name, configfile))
ext |= EXT_LOADED; ext |= EXT_LOADED;
} }
if (!strcmp(dent->d_name, configfile))
ext |= EXT_LOADED;
folder = 0; folder = 0;
} }
else // directory else // directory
@ -881,6 +896,8 @@ boolean preparefilemenu(boolean samedepth)
strcpy(temp+len, PATHSEP); strcpy(temp+len, PATHSEP);
coredirmenu[folderpos++] = temp; coredirmenu[folderpos++] = temp;
} }
else if (replayhut) // Reverse-alphabetical on just the files; acts as a fake "most recent first" with the current filename format
coredirmenu[sizecoredirmenu - 1 - pos++] = temp;
else else
coredirmenu[numfolders + pos++] = temp; coredirmenu[numfolders + pos++] = temp;
} }

View file

@ -94,6 +94,6 @@ typedef enum
void closefilemenu(boolean validsize); void closefilemenu(boolean validsize);
void searchfilemenu(char *tempname); void searchfilemenu(char *tempname);
boolean preparefilemenu(boolean samedepth); boolean preparefilemenu(boolean samedepth, boolean replayhut);
#endif // __FILESRCH_H__ #endif // __FILESRCH_H__

File diff suppressed because it is too large Load diff

View file

@ -36,11 +36,61 @@ extern boolean playeringame[MAXPLAYERS];
// ====================================== // ======================================
// demoplaying back and demo recording // demoplaying back and demo recording
extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo; extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality;
// Publicly-accessible demo vars
struct demovars_s {
char titlename[65];
boolean recording, playback, timing;
UINT16 version; // Current file format of the demo being played
boolean title; // Title Screen demo can be cancelled by any key
boolean rewinding; // Rewind in progress
boolean loadfiles, ignorefiles; // Demo file loading options
boolean fromtitle; // SRB2Kart: Don't stop the music
boolean inreplayhut; // Go back to replayhut after demos
boolean quitafterplaying; // quit after playing a demo from cmdline
boolean deferstart; // don't start playing demo right away
tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going
enum {
DSM_NOTSAVING,
DSM_WILLAUTOSAVE,
DSM_TITLEENTRY,
DSM_WILLSAVE,
DSM_SAVED
} savemode;
};
extern struct demovars_s demo;
typedef enum {
MD_NOTLOADED,
MD_LOADED,
MD_SUBDIR,
MD_OUTDATED,
MD_INVALID
} menudemotype_e;
typedef struct menudemo_s {
char filepath[256];
menudemotype_e type;
char title[65]; // Null-terminated for string prints
UINT16 map;
UINT8 addonstatus; // What do we need to do addon-wise to play this demo?
UINT8 gametype;
UINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk
UINT8 numlaps;
struct {
UINT8 ranking;
char name[17];
UINT8 skin, color;
UINT32 timeorscore;
} standings[MAXPLAYERS];
} menudemo_t;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
extern boolean demo_start;
extern mobj_t *metalplayback; extern mobj_t *metalplayback;
@ -102,9 +152,9 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
boolean InputDown(INT32 gc, UINT8 p); boolean InputDown(INT32 gc, UINT8 p);
INT32 JoyAxis(axis_input_e axissel, UINT8 p); INT32 JoyAxis(axis_input_e axissel, UINT8 p);
extern angle_t localangle, localangle2, localangle3, localangle4; extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming, localaiming2, localaiming3, localaiming4; // should be an angle_t but signed extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
extern boolean camspin, camspin2, camspin3, camspin4; // SRB2Kart extern boolean camspin[MAXSPLITSCREENPLAYERS]; // SRB2Kart
// //
// GAME // GAME
@ -128,6 +178,7 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar
UINT8 ssplayers, boolean FLS); UINT8 ssplayers, boolean FLS);
void G_DoLoadLevel(boolean resetplayer); void G_DoLoadLevel(boolean resetplayer);
void G_LoadDemoInfo(menudemo_t *pdemo);
void G_DeferedPlayDemo(const char *demo); void G_DeferedPlayDemo(const char *demo);
// Can be called by the startup code or M_Responder, calls P_SetupLevel. // Can be called by the startup code or M_Responder, calls P_SetupLevel.
@ -144,6 +195,7 @@ void G_BeginRecording(void);
void G_BeginMetal(void); void G_BeginMetal(void);
// Only called by shutdown code. // Only called by shutdown code.
void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val);
void G_SetDemoTime(UINT32 ptime, UINT32 plap); void G_SetDemoTime(UINT32 ptime, UINT32 plap);
UINT8 G_CmpDemoTime(char *oldname, char *newname); UINT8 G_CmpDemoTime(char *oldname, char *newname);
@ -155,19 +207,41 @@ typedef enum
GHC_INVINCIBLE GHC_INVINCIBLE
} ghostcolor_t; } ghostcolor_t;
extern UINT8 demo_extradata[MAXPLAYERS];
extern UINT8 demo_writerng;
#define DXD_RESPAWN 0x01 // "respawn" command in console
#define DXD_SKIN 0x02 // skin changed
#define DXD_NAME 0x04 // name changed
#define DXD_COLOR 0x08 // color changed
#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game
#define DXD_PST_PLAYING 0x01
#define DXD_PST_SPECTATING 0x02
#define DXD_PST_LEFT 0x03
// Record/playback tics // Record/playback tics
void G_ReadDemoExtraData(void);
void G_WriteDemoExtraData(void);
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum); void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum); void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
void G_GhostAddThok(void); void G_GhostAddThok(INT32 playernum);
void G_GhostAddSpin(void); void G_GhostAddSpin(INT32 playernum);
void G_GhostAddRev(void); void G_GhostAddRev(INT32 playernum);
void G_GhostAddColor(ghostcolor_t color); void G_GhostAddColor(INT32 playernum, ghostcolor_t color);
void G_GhostAddFlip(void); void G_GhostAddFlip(INT32 playernum);
void G_GhostAddScale(fixed_t scale); void G_GhostAddScale(INT32 playernum, fixed_t scale);
void G_GhostAddHit(mobj_t *victim); void G_GhostAddHit(INT32 playernum, mobj_t *victim);
void G_WriteGhostTic(mobj_t *ghost); void G_WriteAllGhostTics(void);
void G_ConsGhostTic(void); void G_WriteGhostTic(mobj_t *ghost, INT32 playernum);
void G_ConsAllGhostTics(void);
void G_ConsGhostTic(INT32 playernum);
void G_GhostTicker(void); void G_GhostTicker(void);
void G_InitDemoRewind(void);
void G_StoreRewindInfo(void);
void G_PreviewRewind(tic_t previewtime);
void G_ConfirmRewind(tic_t rewindtime);
void G_ReadMetalTic(mobj_t *metal); void G_ReadMetalTic(mobj_t *metal);
void G_WriteMetalTic(mobj_t *metal); void G_WriteMetalTic(mobj_t *metal);
void G_SaveMetal(UINT8 **buffer); void G_SaveMetal(UINT8 **buffer);
@ -184,6 +258,13 @@ typedef struct demoghost {
} demoghost; } demoghost;
extern demoghost *ghosts; extern demoghost *ghosts;
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
#define DFILE_ERROR_NOTLOADED 0x01 // Files are not loaded, but can be without a restart.
#define DFILE_ERROR_OUTOFORDER 0x02 // Files are loaded, but out of order.
#define DFILE_ERROR_INCOMPLETEOUTOFORDER 0x03 // Some files are loaded out of order, but others are not.
#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded.
#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded.
void G_DoPlayDemo(char *defdemoname); void G_DoPlayDemo(char *defdemoname);
void G_TimeDemo(const char *name); void G_TimeDemo(const char *name);
void G_AddGhost(char *defdemoname); void G_AddGhost(char *defdemoname);
@ -194,6 +275,8 @@ void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
void G_StopDemo(void); void G_StopDemo(void);
boolean G_CheckDemoStatus(void); boolean G_CheckDemoStatus(void);
void G_SaveDemo(void);
boolean G_DemoTitleResponder(event_t *ev);
boolean G_IsSpecialStage(INT32 mapnum); boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void); boolean G_GametypeUsesLives(void);
@ -214,6 +297,16 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed
void G_Ticker(boolean run); void G_Ticker(boolean run);
boolean G_Responder(event_t *ev); boolean G_Responder(event_t *ev);
boolean G_CouldView(INT32 playernum);
boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive);
INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive, boolean reverse);
INT32 G_CountPlayersPotentiallyViewable(boolean active);
void G_ResetViews(void);
void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive);
void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive);
void G_AddPlayer(INT32 playernum); void G_AddPlayer(INT32 playernum);
void G_SetExitGameFlag(void); void G_SetExitGameFlag(void);

View file

@ -296,7 +296,7 @@ static void HW3S_FillSourceParameters
data->max_distance = MAX_DISTANCE; data->max_distance = MAX_DISTANCE;
data->min_distance = MIN_DISTANCE; data->min_distance = MIN_DISTANCE;
if (origin && origin != players[displayplayer].mo) if (origin && origin != players[displayplayers[0]].mo)
{ {
data->head_relative = false; data->head_relative = false;
@ -356,10 +356,10 @@ INT32 HW3S_I_StartSound(const void *origin_p, source3D_data_t *source_parm, chan
source3D_data_t source3d_data; source3D_data_t source3d_data;
INT32 s_num = 0; INT32 s_num = 0;
source_t *source = NULL; source_t *source = NULL;
mobj_t *listenmobj = players[displayplayer].mo; mobj_t *listenmobj = players[displayplayers[0]].mo; // TODO: Kart 4P does not support sounds properly here
mobj_t *listenmobj2 = NULL; mobj_t *listenmobj2 = NULL;
if (splitscreen) listenmobj2 = players[secondarydisplayplayer].mo; if (splitscreen) listenmobj2 = players[displayplayers[1]].mo;
if (sound_disabled) if (sound_disabled)
return -1; return -1;
@ -876,12 +876,12 @@ static void HW3S_Update3DSource(source_t *src)
void HW3S_UpdateSources(void) void HW3S_UpdateSources(void)
{ {
mobj_t *listener = players[displayplayer].mo; mobj_t *listener = players[displayplayers[0]].mo;
mobj_t *listener2 = NULL; mobj_t *listener2 = NULL;
source_t *src; source_t *src;
INT32 audible, snum, volume, sep, pitch; INT32 audible, snum, volume, sep, pitch;
if (splitscreen) listener2 = players[secondarydisplayplayer].mo; if (splitscreen) listener2 = players[displayplayers[1]].mo;
HW3S_UpdateListener2(listener2); HW3S_UpdateListener2(listener2);
HW3S_UpdateListener(listener); HW3S_UpdateListener(listener);

View file

@ -63,7 +63,7 @@ struct hwdriver_s hwdriver;
// ========================================================================== // ==========================================================================
static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer); static void HWR_AddSprites(sector_t *sec);
static void HWR_ProjectSprite(mobj_t *thing); static void HWR_ProjectSprite(mobj_t *thing);
#ifdef HWPRECIP #ifdef HWPRECIP
static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
@ -3389,7 +3389,7 @@ static void HWR_AddPolyObjectPlanes(void)
// : Draw one or more line segments. // : Draw one or more line segments.
// Notes : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures // Notes : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures
// -----------------+ // -----------------+
static void HWR_Subsector(size_t num, UINT8 ssplayer) static void HWR_Subsector(size_t num)
{ {
INT16 count; INT16 count;
seg_t *line; seg_t *line;
@ -3754,7 +3754,7 @@ static void HWR_Subsector(size_t num, UINT8 ssplayer)
{ {
// draw sprites first, coz they are clipped to the solidsegs of // draw sprites first, coz they are clipped to the solidsegs of
// subsectors more 'in front' // subsectors more 'in front'
HWR_AddSprites(gr_frontsector, ssplayer); HWR_AddSprites(gr_frontsector);
//Hurdler: at this point validcount must be the same, but is not because //Hurdler: at this point validcount must be the same, but is not because
// gr_frontsector doesn't point anymore to sub->sector due to // gr_frontsector doesn't point anymore to sub->sector due to
@ -3806,7 +3806,7 @@ static boolean HWR_CheckHackBBox(fixed_t *bb)
// BP: big hack for a test in lighning ref : 1249753487AB // BP: big hack for a test in lighning ref : 1249753487AB
fixed_t *hwbbox; fixed_t *hwbbox;
static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer) static void HWR_RenderBSPNode(INT32 bspnum)
{ {
/*//GZDoom code /*//GZDoom code
if(bspnum == -1) if(bspnum == -1)
@ -3846,12 +3846,12 @@ static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer)
if (bspnum == -1) if (bspnum == -1)
{ {
//*(gr_drawsubsector_p++) = 0; //*(gr_drawsubsector_p++) = 0;
HWR_Subsector(0, ssplayer); HWR_Subsector(0);
} }
else else
{ {
//*(gr_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR); //*(gr_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR);
HWR_Subsector(bspnum&(~NF_SUBSECTOR), ssplayer); HWR_Subsector(bspnum&(~NF_SUBSECTOR));
} }
return; return;
} }
@ -3863,14 +3863,14 @@ static void HWR_RenderBSPNode(INT32 bspnum, UINT8 ssplayer)
hwbbox = bsp->bbox[side]; hwbbox = bsp->bbox[side];
// Recursively divide front space. // Recursively divide front space.
HWR_RenderBSPNode(bsp->children[side], ssplayer); HWR_RenderBSPNode(bsp->children[side]);
// Possibly divide back space. // Possibly divide back space.
if (HWR_CheckBBox(bsp->bbox[side^1])) if (HWR_CheckBBox(bsp->bbox[side^1]))
{ {
// BP: big hack for a test in lighning ref : 1249753487AB // BP: big hack for a test in lighning ref : 1249753487AB
hwbbox = bsp->bbox[side^1]; hwbbox = bsp->bbox[side^1];
HWR_RenderBSPNode(bsp->children[side^1], ssplayer); HWR_RenderBSPNode(bsp->children[side^1]);
} }
} }
@ -4097,14 +4097,14 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
angle_t shadowdir; angle_t shadowdir;
// Set direction // Set direction
if (splitscreen && stplyr == &players[secondarydisplayplayer]) if (splitscreen && stplyr == &players[displayplayers[1]])
shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value); shadowdir = localangle[1] + FixedAngle(cv_cam2_rotate.value);
else if (splitscreen > 1 && stplyr == &players[thirddisplayplayer]) else if (splitscreen > 1 && stplyr == &players[displayplayers[2]])
shadowdir = localangle3 + FixedAngle(cv_cam3_rotate.value); shadowdir = localangle[2] + FixedAngle(cv_cam3_rotate.value);
else if (splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) else if (splitscreen > 2 && stplyr == &players[displayplayers[3]])
shadowdir = localangle4 + FixedAngle(cv_cam4_rotate.value); shadowdir = localangle[3] + FixedAngle(cv_cam4_rotate.value);
else else
shadowdir = localangle + FixedAngle(cv_cam_rotate.value); shadowdir = localangle[0] + FixedAngle(cv_cam_rotate.value);
// Find floorheight // Find floorheight
floorheight = HWR_OpaqueFloorAtPos( floorheight = HWR_OpaqueFloorAtPos(
@ -5283,7 +5283,7 @@ static void HWR_DrawSprites(void)
// During BSP traversal, this adds sprites by sector. // During BSP traversal, this adds sprites by sector.
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static UINT8 sectorlight; static UINT8 sectorlight;
static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer) static void HWR_AddSprites(sector_t *sec)
{ {
mobj_t *thing; mobj_t *thing;
#ifdef HWPRECIP #ifdef HWPRECIP
@ -5316,19 +5316,19 @@ static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer)
if (splitscreen) if (splitscreen)
{ {
if (thing->eflags & MFE_DRAWONLYFORP1) if (thing->eflags & MFE_DRAWONLYFORP1)
if (ssplayer != 1) if (viewssnum != 0)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP2) if (thing->eflags & MFE_DRAWONLYFORP2)
if (ssplayer != 2) if (viewssnum != 1)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
if (ssplayer != 3) if (viewssnum != 2)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
if (ssplayer != 4) if (viewssnum != 3)
continue; continue;
} }
@ -5351,19 +5351,19 @@ static void HWR_AddSprites(sector_t *sec, UINT8 ssplayer)
if (splitscreen) if (splitscreen)
{ {
if (thing->eflags & MFE_DRAWONLYFORP1) if (thing->eflags & MFE_DRAWONLYFORP1)
if (ssplayer != 1) if (viewssnum != 0)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP2) if (thing->eflags & MFE_DRAWONLYFORP2)
if (ssplayer != 2) if (viewssnum != 1)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
if (ssplayer != 3) if (viewssnum != 2)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
if (ssplayer != 4) if (viewssnum != 3)
continue; continue;
} }
@ -5906,33 +5906,8 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
{ {
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
UINT8 ssplayer = 0;
if (splitscreen) type = &postimgtype[viewnumber];
{
if (player == &players[secondarydisplayplayer])
{
type = &postimgtype2;
ssplayer = 2;
}
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
{
type = &postimgtype3;
ssplayer = 3;
}
else if (splitscreen > 2 && player == &players[fourthdisplayplayer])
{
type = &postimgtype4;
ssplayer = 4;
}
else
{
type = &postimgtype;
ssplayer = 1;
}
}
else
type = &postimgtype;
{ {
// do we really need to save player (is it not the same)? // do we really need to save player (is it not the same)?
@ -6056,36 +6031,36 @@ if (0)
validcount++; validcount++;
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); HWR_RenderBSPNode((INT32)numnodes-1);
#ifndef NEWCLIP #ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
viewangle = localaiming; viewangle = localaiming[0];
else if (splitscreen && player == &players[secondarydisplayplayer]) else if (splitscreen && player == &players[displayplayers[1]])
viewangle = localaiming2; viewangle = localaiming[1];
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) else if (splitscreen > 1 && player == &players[displayplayers[2]])
viewangle = localaiming3; viewangle = localaiming[2];
else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) else if (splitscreen > 2 && player == &players[displayplayers[3]])
viewangle = localaiming4; viewangle = localaiming[3];
// Handle stuff when you are looking farther up or down. // Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{ {
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //left HWR_RenderBSPNode((INT32)numnodes-1); //left
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45))
{ {
HWR_ClearClipSegs(); HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //back HWR_RenderBSPNode((INT32)numnodes-1); //back
} }
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //right HWR_RenderBSPNode((INT32)numnodes-1); //right
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
} }
@ -6149,38 +6124,13 @@ if (0)
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
{ {
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type = &postimgtype[viewnumber];
UINT8 ssplayer = 0;
const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on
FRGBAFloat ClearColor; FRGBAFloat ClearColor;
if (splitscreen) type = &postimgtype[viewnumber];
{
if (player == &players[secondarydisplayplayer])
{
type = &postimgtype2;
ssplayer = 2;
}
else if (splitscreen > 1 && player == &players[thirddisplayplayer])
{
type = &postimgtype3;
ssplayer = 3;
}
else if (splitscreen > 2 && player == &players[fourthdisplayplayer])
{
type = &postimgtype4;
ssplayer = 4;
}
else
{
type = &postimgtype;
ssplayer = 1;
}
}
else
type = &postimgtype;
ClearColor.red = 0.0f; ClearColor.red = 0.0f;
ClearColor.green = 0.0f; ClearColor.green = 0.0f;
@ -6315,36 +6265,36 @@ if (0)
validcount++; validcount++;
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); HWR_RenderBSPNode((INT32)numnodes-1);
#ifndef NEWCLIP #ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
viewangle = localaiming; viewangle = localaiming[0];
else if (splitscreen && player == &players[secondarydisplayplayer]) else if (splitscreen && player == &players[displayplayers[1]])
viewangle = localaiming2; viewangle = localaiming[1];
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) else if (splitscreen > 1 && player == &players[displayplayers[2]])
viewangle = localaiming3; viewangle = localaiming[2];
else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) else if (splitscreen > 2 && player == &players[displayplayers[3]])
viewangle = localaiming4; viewangle = localaiming[3];
// Handle stuff when you are looking farther up or down. // Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{ {
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //left HWR_RenderBSPNode((INT32)numnodes-1); //left
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45))
{ {
HWR_ClearClipSegs(); HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //back HWR_RenderBSPNode((INT32)numnodes-1); //back
} }
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1, ssplayer); //right HWR_RenderBSPNode((INT32)numnodes-1); //right
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
} }
@ -6802,16 +6752,17 @@ INT32 HWR_GetTextureUsed(void)
void HWR_DoPostProcessor(player_t *player) void HWR_DoPostProcessor(player_t *player)
{ {
postimg_t *type; postimg_t *type = &postimgtype[0];
UINT8 i;
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) for (i = splitscreen; i > 0; i--)
type = &postimgtype4; {
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) if (player == &players[displayplayers[i]])
type = &postimgtype3; {
else if (splitscreen && player == &players[secondarydisplayplayer]) type = &postimgtype[i];
type = &postimgtype2; break;
else }
type = &postimgtype; }
// Armageddon Blast Flash! // Armageddon Blast Flash!
// Could this even be considered postprocessor? // Could this even be considered postprocessor?

View file

@ -39,7 +39,7 @@
#include "am_map.h" #include "am_map.h"
#include "d_main.h" #include "d_main.h"
#include "p_local.h" // camera, camera2, camera3, camera4 #include "p_local.h" // camera[]
#include "p_tick.h" #include "p_tick.h"
#ifdef HWRENDER #ifdef HWRENDER
@ -1998,7 +1998,7 @@ static void HU_DrawChat_Old(void)
if (!i) if (!i)
return; return;
if ((netgame || multiplayer) && players[displayplayer].spectator) if ((netgame || multiplayer) && players[displayplayers[0]].spectator)
return; return;
#ifdef HWRENDER #ifdef HWRENDER
@ -2025,7 +2025,7 @@ static inline void HU_DrawCrosshair2(void)
if (!i) if (!i)
return; return;
if ((netgame || multiplayer) && players[secondarydisplayplayer].spectator) if ((netgame || multiplayer) && players[displayplayers[1]].spectator)
return; return;
#ifdef HWRENDER #ifdef HWRENDER
@ -2072,7 +2072,7 @@ static inline void HU_DrawCrosshair3(void)
if (!i) if (!i)
return; return;
if ((netgame || multiplayer) && players[thirddisplayplayer].spectator) if ((netgame || multiplayer) && players[displayplayers[2]].spectator)
return; return;
#ifdef HWRENDER #ifdef HWRENDER
@ -2109,7 +2109,7 @@ static inline void HU_DrawCrosshair4(void)
if (!i) if (!i)
return; return;
if ((netgame || multiplayer) && players[fourthdisplayplayer].spectator) if ((netgame || multiplayer) && players[displayplayers[3]].spectator)
return; return;
#ifdef HWRENDER #ifdef HWRENDER
@ -2210,8 +2210,16 @@ UINT32 hu_demolap;
static void HU_DrawDemoInfo(void) static void HU_DrawDemoInfo(void)
{ {
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Replay:")); if (!multiplayer)/* netreplay */
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[0]); {
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Replay:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[0]);
}
else
{
V_DrawRightAlignedThinString(BASEVIDWIDTH-2, BASEVIDHEIGHT-10, V_ALLOWLOWERCASE, demo.titlename);
}
if (modeattacking) if (modeattacking)
{ {
V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:"); V_DrawRightAlignedString((BASEVIDWIDTH/2)-4, BASEVIDHEIGHT-24, V_YELLOWMAP|V_MONOSPACE, "BEST TIME:");
@ -2238,7 +2246,7 @@ static void HU_DrawDemoInfo(void)
// //
// Song credits // Song credits
// //
static void HU_DrawSongCredits(void) void HU_DrawSongCredits(void)
{ {
char *str; char *str;
INT32 len, destx; INT32 len, destx;
@ -2329,10 +2337,7 @@ void HU_Drawer(void)
if (cechotimer) if (cechotimer)
HU_DrawCEcho(); HU_DrawCEcho();
if (demoplayback && hu_showscores) if (!( Playing() || demo.playback )
HU_DrawDemoInfo();
if (!Playing()
|| gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_CREDITS || gamestate == GS_EVALUATION
|| gamestate == GS_GAMEEND || gamestate == GS_GAMEEND
@ -2352,24 +2357,28 @@ void HU_Drawer(void)
LUAh_ScoresHUD(); LUAh_ScoresHUD();
#endif #endif
} }
if (demo.playback)
{
HU_DrawDemoInfo();
}
} }
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
return; return;
// draw the crosshair, not when viewing demos nor with chasecam // draw the crosshair, not when viewing demos nor with chasecam
/*if (!automapactive && !demoplayback) /*if (!automapactive && !demo.playback)
{ {
if (cv_crosshair.value && !camera.chase && !players[displayplayer].spectator) if (cv_crosshair.value && !camera[0].chase && !players[displayplayers[0]].spectator)
HU_DrawCrosshair(); HU_DrawCrosshair();
if (cv_crosshair2.value && !camera2.chase && !players[secondarydisplayplayer].spectator) if (cv_crosshair2.value && !camera[1].chase && !players[displayplayers[1]].spectator)
HU_DrawCrosshair2(); HU_DrawCrosshair2();
if (cv_crosshair3.value && !camera3.chase && !players[thirddisplayplayer].spectator) if (cv_crosshair3.value && !camera[2].chase && !players[displayplayers[2]].spectator)
HU_DrawCrosshair3(); HU_DrawCrosshair3();
if (cv_crosshair4.value && !camera4.chase && !players[fourthdisplayplayer].spectator) if (cv_crosshair4.value && !camera[3].chase && !players[displayplayers[3]].spectator)
HU_DrawCrosshair4(); HU_DrawCrosshair4();
}*/ }*/
@ -3011,7 +3020,7 @@ static void HU_DrawRankings(void)
// When you play, you quickly see your score because your name is displayed in white. // When you play, you quickly see your score because your name is displayed in white.
// When playing back a demo, you quickly see who's the view. // When playing back a demo, you quickly see who's the view.
if (!splitscreen) if (!splitscreen)
whiteplayer = demoplayback ? displayplayer : consoleplayer; whiteplayer = demo.playback ? displayplayers[0] : consoleplayer;
scorelines = 0; scorelines = 0;
memset(completed, 0, sizeof (completed)); memset(completed, 0, sizeof (completed));

View file

@ -109,6 +109,7 @@ void HU_Start(void);
boolean HU_Responder(event_t *ev); boolean HU_Responder(event_t *ev);
void HU_Ticker(void); void HU_Ticker(void);
void HU_DrawSongCredits(void);
void HU_Drawer(void); void HU_Drawer(void);
char HU_dequeueChatChar(void); char HU_dequeueChatChar(void);
void HU_Erase(void); void HU_Erase(void);

View file

@ -1062,34 +1062,14 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
} }
// This makes the roulette produce the random noises. // This makes the roulette produce the random noises.
if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player)) if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player))
{ {
#define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->kartstuff[k_itemroulette] / 3) % 8)); #define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->kartstuff[k_itemroulette] / 3) % 8))
if (splitscreen) for (i = 0; i <= splitscreen; i++)
{ {
if (players[displayplayer].kartstuff[k_itemroulette]) if (player == &players[displayplayers[i]] && players[displayplayers[i]].kartstuff[k_itemroulette])
{ PLAYROULETTESND;
if (player == &players[displayplayer])
PLAYROULETTESND;
}
else if (players[secondarydisplayplayer].kartstuff[k_itemroulette])
{
if (player == &players[secondarydisplayplayer])
PLAYROULETTESND;
}
else if (players[thirddisplayplayer].kartstuff[k_itemroulette] && splitscreen > 1)
{
if (player == &players[thirddisplayplayer])
PLAYROULETTESND;
}
else if (players[fourthdisplayplayer].kartstuff[k_itemroulette] && splitscreen > 2)
{
if (player == &players[fourthdisplayplayer])
PLAYROULETTESND;
}
} }
else
PLAYROULETTESND;
#undef PLAYROULETTESND #undef PLAYROULETTESND
} }
@ -1116,7 +1096,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
//player->kartstuff[k_itemblinkmode] = 1; //player->kartstuff[k_itemblinkmode] = 1;
player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_itemroulette] = 0;
player->kartstuff[k_roulettetype] = 0; player->kartstuff[k_roulettetype] = 0;
if (P_IsLocalPlayer(player)) if (P_IsDisplayPlayer(player))
S_StartSound(NULL, sfx_itrole); S_StartSound(NULL, sfx_itrole);
return; return;
} }
@ -1129,7 +1109,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
player->kartstuff[k_itemblinkmode] = 2; player->kartstuff[k_itemblinkmode] = 2;
player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_itemroulette] = 0;
player->kartstuff[k_roulettetype] = 0; player->kartstuff[k_roulettetype] = 0;
if (P_IsLocalPlayer(player)) if (P_IsDisplayPlayer(player))
S_StartSound(NULL, sfx_dbgsal); S_StartSound(NULL, sfx_dbgsal);
return; return;
} }
@ -1161,7 +1141,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
player->kartstuff[k_itemamount] = 1; player->kartstuff[k_itemamount] = 1;
} }
if (P_IsLocalPlayer(player)) if (P_IsDisplayPlayer(player))
S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf)));
player->kartstuff[k_itemblink] = TICRATE; player->kartstuff[k_itemblink] = TICRATE;
@ -4369,10 +4349,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd)
if (!playeringame[i] || !players[i].mo || players[i].spectator || players[i].exiting) if (!playeringame[i] || !players[i].mo || players[i].spectator || players[i].exiting)
continue; continue;
if ((i == displayplayer) if (P_IsDisplayPlayer(&players[i]))
|| (i == secondarydisplayplayer && splitscreen)
|| (i == thirddisplayplayer && splitscreen > 1)
|| (i == fourthdisplayplayer && splitscreen > 2))
{ {
volumedampen += FRACUNIT; // We already know what this is gonna be, let's not waste our time. volumedampen += FRACUNIT; // We already know what this is gonna be, let's not waste our time.
continue; continue;
@ -5745,13 +5722,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (player->kartstuff[k_hyudorotimer] >= (1*TICRATE/2) && player->kartstuff[k_hyudorotimer] <= hyudorotime-(1*TICRATE/2)) if (player->kartstuff[k_hyudorotimer] >= (1*TICRATE/2) && player->kartstuff[k_hyudorotimer] <= hyudorotime-(1*TICRATE/2))
{ {
if (player == &players[secondarydisplayplayer]) if (player == &players[displayplayers[1]])
player->mo->eflags |= MFE_DRAWONLYFORP2; player->mo->eflags |= MFE_DRAWONLYFORP2;
else if (player == &players[thirddisplayplayer] && splitscreen > 1) else if (player == &players[displayplayers[2]] && splitscreen > 1)
player->mo->eflags |= MFE_DRAWONLYFORP3; player->mo->eflags |= MFE_DRAWONLYFORP3;
else if (player == &players[fourthdisplayplayer] && splitscreen > 2) else if (player == &players[displayplayers[3]] && splitscreen > 2)
player->mo->eflags |= MFE_DRAWONLYFORP4; player->mo->eflags |= MFE_DRAWONLYFORP4;
else if (player == &players[consoleplayer]) else if (player == &players[displayplayers[0]])
player->mo->eflags |= MFE_DRAWONLYFORP1; player->mo->eflags |= MFE_DRAWONLYFORP1;
else else
player->mo->flags2 |= MF2_DONTDRAW; player->mo->flags2 |= MF2_DONTDRAW;
@ -5761,8 +5738,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
} }
else else
{ {
if (player == &players[displayplayer] if (P_IsDisplayPlayer(player)
|| (player != &players[displayplayer] && (player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2)))) || (!P_IsDisplayPlayer(player) && (player->kartstuff[k_hyudorotimer] < (1*TICRATE/2) || player->kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2))))
{ {
if (leveltime & 1) if (leveltime & 1)
player->mo->flags2 |= MF2_DONTDRAW; player->mo->flags2 |= MF2_DONTDRAW;
@ -5862,7 +5839,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
} }
// Play the starting countdown sounds // Play the starting countdown sounds
if (player == &players[displayplayer]) // Don't play louder in splitscreen if (player == &players[displayplayers[0]]) // Don't play louder in splitscreen
{ {
if ((leveltime == starttime-(3*TICRATE)) || (leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE)) if ((leveltime == starttime-(3*TICRATE)) || (leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE))
S_StartSound(NULL, sfx_s3ka7); S_StartSound(NULL, sfx_s3ka7);
@ -6747,17 +6724,17 @@ INT32 K_calcSplitFlags(INT32 snapflags)
if (splitscreen == 0) if (splitscreen == 0)
return snapflags; return snapflags;
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
{ {
if (splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) if (splitscreen == 1 && stplyr == &players[displayplayers[1]])
{ {
splitflags |= V_SPLITSCREEN; splitflags |= V_SPLITSCREEN;
} }
else if (splitscreen > 1) else if (splitscreen > 1)
{ {
if (stplyr == &players[thirddisplayplayer] || stplyr == &players[fourthdisplayplayer]) if (stplyr == &players[displayplayers[2]] || (splitscreen == 3 && stplyr == &players[displayplayers[3]]))
splitflags |= V_SPLITSCREEN; splitflags |= V_SPLITSCREEN;
if (stplyr == &players[secondarydisplayplayer] || stplyr == &players[fourthdisplayplayer]) if (stplyr == &players[displayplayers[1]] || (splitscreen == 3 && stplyr == &players[displayplayers[3]]))
splitflags |= V_HORZSCREEN; splitflags |= V_HORZSCREEN;
} }
} }
@ -7019,25 +6996,25 @@ static void K_drawKartItem(void)
} }
// pain and suffering defined below // pain and suffering defined below
if (splitscreen < 2) // don't change shit for THIS splitscreen. if (splitscreen < 2) // don't change shit for THIS splitscreen.
{ {
fx = ITEM_X; fx = ITEM_X;
fy = ITEM_Y; fy = ITEM_Y;
fflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); fflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT);
} }
else // now we're having a fun game. else // now we're having a fun game.
{ {
if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{ {
fx = ITEM_X; fx = ITEM_X;
fy = ITEM_Y; fy = ITEM_Y;
fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P3 to the bottom. fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P3 to the bottom.
} }
else // else, that means we're P2 or P4. else // else, that means we're P2 or P4.
{ {
fx = ITEM2_X; fx = ITEM2_X;
fy = ITEM2_Y; fy = ITEM2_Y;
fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P4 to the bottom fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P4 to the bottom
flipamount = true; flipamount = true;
} }
} }
@ -7050,10 +7027,10 @@ static void K_drawKartItem(void)
// Then, the numbers: // Then, the numbers:
if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette]) if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette])
{ {
V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it. V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it.
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, FRACUNIT, V_HUDTRANS|fflags, localpatch, colmap); V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, FRACUNIT, V_HUDTRANS|fflags, localpatch, colmap);
if (offset) if (offset)
if (flipamount) // reminder that this is for 3/4p's right end of the screen. if (flipamount) // reminder that this is for 3/4p's right end of the screen.
V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount])); V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount]));
else else
V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount])); V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount]));
@ -7169,7 +7146,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
else if ((drawtime/TICRATE) & 1) else if ((drawtime/TICRATE) & 1)
V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99")); V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99"));
if (emblemmap && (modeattacking || (mode == 1)) && !demoplayback) // emblem time! if (emblemmap && (modeattacking || (mode == 1)) && !demo.playback) // emblem time!
{ {
INT32 workx = TX + 96, worky = TY+18; INT32 workx = TX + 96, worky = TY+18;
SINT8 curemb = 0; SINT8 curemb = 0;
@ -7280,7 +7257,7 @@ static void K_DrawKartPositionNum(INT32 num)
else if (splitscreen == 1) // for this splitscreen, we'll use case by case because it's a bit different. else if (splitscreen == 1) // for this splitscreen, we'll use case by case because it's a bit different.
{ {
fx = POSI_X; fx = POSI_X;
if (stplyr == &players[displayplayer]) // for player 1: display this at the top right, above the minimap. if (stplyr == &players[displayplayers[0]]) // for player 1: display this at the top right, above the minimap.
{ {
fy = 30; fy = 30;
fflags = V_SNAPTOTOP|V_SNAPTORIGHT; fflags = V_SNAPTOTOP|V_SNAPTORIGHT;
@ -7295,11 +7272,11 @@ static void K_DrawKartPositionNum(INT32 num)
} }
else else
{ {
if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{ {
fx = POSI_X; fx = POSI_X;
fy = POSI_Y; fy = POSI_Y;
fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
flipdraw = true; flipdraw = true;
if (num && num >= 10) if (num && num >= 10)
fx += W; // this seems dumb, but we need to do this in order for positions above 10 going off screen. fx += W; // this seems dumb, but we need to do this in order for positions above 10 going off screen.
@ -7308,7 +7285,7 @@ static void K_DrawKartPositionNum(INT32 num)
{ {
fx = POSI2_X; fx = POSI2_X;
fy = POSI2_Y; fy = POSI2_Y;
fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
} }
} }
@ -7634,17 +7611,17 @@ static void K_drawKartLaps(void)
} }
else else
{ {
if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{ {
fx = LAPS_X; fx = LAPS_X;
fy = LAPS_Y; fy = LAPS_Y;
fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
} }
else // else, that means we're P2 or P4. else // else, that means we're P2 or P4.
{ {
fx = LAPS2_X; fx = LAPS2_X;
fy = LAPS2_Y; fy = LAPS2_Y;
fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
flipstring = true; // make the string right aligned and other shit flipstring = true; // make the string right aligned and other shit
} }
} }
@ -7716,17 +7693,17 @@ static void K_drawKartBumpersOrKarma(void)
// we will reuse lap coords here since it's essentially the same shit. // we will reuse lap coords here since it's essentially the same shit.
if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3... if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
{ {
fx = LAPS_X; fx = LAPS_X;
fy = LAPS_Y; fy = LAPS_Y;
fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
} }
else // else, that means we're P2 or P4. else // else, that means we're P2 or P4.
{ {
fx = LAPS2_X; fx = LAPS2_X;
fy = LAPS2_Y; fy = LAPS2_Y;
fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
flipstring = true; flipstring = true;
} }
@ -7803,7 +7780,7 @@ static void K_drawKartWanted(void)
UINT8 *colormap = NULL; UINT8 *colormap = NULL;
INT32 basex = 0, basey = 0; INT32 basex = 0, basey = 0;
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
return; return;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
@ -7883,7 +7860,7 @@ static void K_drawKartPlayerCheck(void)
if (stplyr->awayviewtics) if (stplyr->awayviewtics)
return; return;
if (camspin) if (camspin[0])
return; return;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -8029,7 +8006,7 @@ static void K_drawKartMinimap(void)
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
return; return;
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
return; return;
lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap))); lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap)));
@ -8103,7 +8080,7 @@ static void K_drawKartMinimap(void)
if (!players[i].mo || players[i].spectator) if (!players[i].mo || players[i].spectator)
continue; continue;
if (i != displayplayer || splitscreen) if (i != displayplayers[0] || splitscreen)
{ {
if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0) if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0)
continue; continue;
@ -8117,7 +8094,7 @@ static void K_drawKartMinimap(void)
} }
} }
if (i == displayplayer || i == secondarydisplayplayer || i == thirddisplayplayer || i == fourthdisplayplayer) if (P_IsDisplayPlayer(&players[i]))
{ {
// Draw display players on top of everything else // Draw display players on top of everything else
localplayers[numlocalplayers] = i; localplayers[numlocalplayers] = i;
@ -8187,7 +8164,7 @@ static void K_drawKartFinish(void)
xval = (SHORT(kp_racefinish[pnum]->width)<<FRACBITS); xval = (SHORT(kp_racefinish[pnum]->width)<<FRACBITS);
x = ((TICRATE - stplyr->kartstuff[k_cardanimation])*(xval > x ? xval : x))/TICRATE; x = ((TICRATE - stplyr->kartstuff[k_cardanimation])*(xval > x ? xval : x))/TICRATE;
if (splitscreen && stplyr == &players[secondarydisplayplayer]) if (splitscreen && stplyr == &players[displayplayers[1]])
x = -x; x = -x;
V_DrawFixedPatch(x + (STCD_X<<FRACBITS) - (xval>>1), V_DrawFixedPatch(x + (STCD_X<<FRACBITS) - (xval>>1),
@ -8206,9 +8183,9 @@ static void K_drawBattleFullscreen(void)
if (splitscreen) if (splitscreen)
{ {
if ((splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) if ((splitscreen == 1 && stplyr == &players[displayplayers[1]])
|| (splitscreen > 1 && (stplyr == &players[thirddisplayplayer] || (splitscreen > 1 && (stplyr == &players[displayplayers[2]]
|| (stplyr == &players[fourthdisplayplayer] && splitscreen > 2)))) || (stplyr == &players[displayplayers[3]] && splitscreen > 2))))
{ {
y = 232-(stplyr->kartstuff[k_cardanimation]/2); y = 232-(stplyr->kartstuff[k_cardanimation]/2);
splitflags = V_SNAPTOBOTTOM; splitflags = V_SNAPTOBOTTOM;
@ -8220,8 +8197,8 @@ static void K_drawBattleFullscreen(void)
{ {
scale /= 2; scale /= 2;
if (stplyr == &players[secondarydisplayplayer] if (stplyr == &players[displayplayers[1]]
|| (stplyr == &players[fourthdisplayplayer] && splitscreen > 2)) || (stplyr == &players[displayplayers[3]] && splitscreen > 2))
x = 3*BASEVIDWIDTH/4; x = 3*BASEVIDWIDTH/4;
else else
x = BASEVIDWIDTH/4; x = BASEVIDWIDTH/4;
@ -8230,7 +8207,7 @@ static void K_drawBattleFullscreen(void)
{ {
if (stplyr->exiting) if (stplyr->exiting)
{ {
if (stplyr == &players[secondarydisplayplayer]) if (stplyr == &players[displayplayers[1]])
x = BASEVIDWIDTH-96; x = BASEVIDWIDTH-96;
else else
x = 96; x = 96;
@ -8242,7 +8219,7 @@ static void K_drawBattleFullscreen(void)
if (stplyr->exiting) if (stplyr->exiting)
{ {
if (stplyr == &players[displayplayer]) if (stplyr == &players[displayplayers[0]])
V_DrawFadeScreen(0xFF00, 16); V_DrawFadeScreen(0xFF00, 16);
if (stplyr->exiting < 6*TICRATE && !stplyr->spectator) if (stplyr->exiting < 6*TICRATE && !stplyr->spectator)
{ {
@ -8272,9 +8249,9 @@ static void K_drawBattleFullscreen(void)
{ {
if (splitscreen > 1) if (splitscreen > 1)
ty = (BASEVIDHEIGHT/4)+33; ty = (BASEVIDHEIGHT/4)+33;
if ((splitscreen == 1 && stplyr == &players[secondarydisplayplayer]) if ((splitscreen == 1 && stplyr == &players[displayplayers[1]])
|| (stplyr == &players[thirddisplayplayer] && splitscreen > 1) || (stplyr == &players[displayplayers[2]] && splitscreen > 1)
|| (stplyr == &players[fourthdisplayplayer] && splitscreen > 2)) || (stplyr == &players[displayplayers[3]] && splitscreen > 2))
ty += (BASEVIDHEIGHT/2); ty += (BASEVIDHEIGHT/2);
} }
else else
@ -8301,7 +8278,7 @@ static void K_drawBattleFullscreen(void)
// check to see if there's anyone else at all // check to see if there's anyone else at all
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (i == displayplayer) if (i == displayplayers[0])
continue; continue;
if (playeringame[i] && !stplyr->spectator) if (playeringame[i] && !stplyr->spectator)
return; return;
@ -8327,11 +8304,11 @@ static void K_drawKartFirstPerson(void)
if (stplyr->spectator || !stplyr->mo || (stplyr->mo->flags2 & MF2_DONTDRAW)) if (stplyr->spectator || !stplyr->mo || (stplyr->mo->flags2 & MF2_DONTDRAW))
return; return;
if (stplyr == &players[secondarydisplayplayer] && splitscreen) if (stplyr == &players[displayplayers[1]] && splitscreen)
{ pn = pnum[1]; tn = turn[1]; dr = drift[1]; } { pn = pnum[1]; tn = turn[1]; dr = drift[1]; }
else if (stplyr == &players[thirddisplayplayer] && splitscreen > 1) else if (stplyr == &players[displayplayers[2]] && splitscreen > 1)
{ pn = pnum[2]; tn = turn[2]; dr = drift[2]; } { pn = pnum[2]; tn = turn[2]; dr = drift[2]; }
else if (stplyr == &players[fourthdisplayplayer] && splitscreen > 2) else if (stplyr == &players[displayplayers[3]] && splitscreen > 2)
{ pn = pnum[3]; tn = turn[3]; dr = drift[3]; } { pn = pnum[3]; tn = turn[3]; dr = drift[3]; }
else else
{ pn = pnum[0]; tn = turn[0]; dr = drift[0]; } { pn = pnum[0]; tn = turn[0]; dr = drift[0]; }
@ -8456,11 +8433,11 @@ static void K_drawKartFirstPerson(void)
V_DrawFixedPatch(x, y, scale, splitflags, kp_fpview[target], colmap); V_DrawFixedPatch(x, y, scale, splitflags, kp_fpview[target], colmap);
if (stplyr == &players[secondarydisplayplayer] && splitscreen) if (stplyr == &players[displayplayers[1]] && splitscreen)
{ pnum[1] = pn; turn[1] = tn; drift[1] = dr; } { pnum[1] = pn; turn[1] = tn; drift[1] = dr; }
else if (stplyr == &players[thirddisplayplayer] && splitscreen > 1) else if (stplyr == &players[displayplayers[2]] && splitscreen > 1)
{ pnum[2] = pn; turn[2] = tn; drift[2] = dr; } { pnum[2] = pn; turn[2] = tn; drift[2] = dr; }
else if (stplyr == &players[fourthdisplayplayer] && splitscreen > 2) else if (stplyr == &players[displayplayers[3]] && splitscreen > 2)
{ pnum[3] = pn; turn[3] = tn; drift[3] = dr; } { pnum[3] = pn; turn[3] = tn; drift[3] = dr; }
else else
{ pnum[0] = pn; turn[0] = tn; drift[0] = dr; } { pnum[0] = pn; turn[0] = tn; drift[0] = dr; }
@ -8482,19 +8459,12 @@ static void K_drawInput(void)
if (timeinmap < 113) if (timeinmap < 113)
{ {
INT32 count = ((INT32)(timeinmap) - 105); INT32 count = ((INT32)(timeinmap) - 105);
offs = (titledemo ? 128 : 64); offs = 64;
while (count-- > 0) while (count-- > 0)
offs >>= 1; offs >>= 1;
x += offs; x += offs;
} }
if (titledemo)
{
V_DrawTinyScaledPatch(x-54, 128, splitflags, W_CachePatchName("TTKBANNR", PU_CACHE));
V_DrawTinyScaledPatch(x-54, 128+25, splitflags, W_CachePatchName("TTKART", PU_CACHE));
return;
}
#define BUTTW 8 #define BUTTW 8
#define BUTTH 11 #define BUTTH 11
@ -8688,7 +8658,7 @@ static void K_drawDistributionDebugger(void)
boolean dontforcespb = false; boolean dontforcespb = false;
boolean spbrush = false; boolean spbrush = false;
if (stplyr != &players[displayplayer]) // only for p1 if (stplyr != &players[displayplayers[0]]) // only for p1
return; return;
// The only code duplication from the Kart, just to avoid the actual item function from calculating pingame twice // The only code duplication from the Kart, just to avoid the actual item function from calculating pingame twice
@ -8752,7 +8722,7 @@ static void K_drawDistributionDebugger(void)
static void K_drawCheckpointDebugger(void) static void K_drawCheckpointDebugger(void)
{ {
if (stplyr != &players[displayplayer]) // only for p1 if (stplyr != &players[displayplayers[0]]) // only for p1
return; return;
if (stplyr->starpostnum >= (numstarposts - (numstarposts/2))) if (stplyr->starpostnum >= (numstarposts - (numstarposts/2)))
@ -8766,20 +8736,21 @@ void K_drawKartHUD(void)
{ {
boolean isfreeplay = false; boolean isfreeplay = false;
boolean battlefullscreen = false; boolean battlefullscreen = false;
UINT8 i;
// Define the X and Y for each drawn object // Define the X and Y for each drawn object
// This is handled by console/menu values // This is handled by console/menu values
K_initKartHUD(); K_initKartHUD();
// Draw that fun first person HUD! Drawn ASAP so it looks more "real". // Draw that fun first person HUD! Drawn ASAP so it looks more "real".
if ((stplyr == &players[displayplayer] && !camera.chase) for (i = 0; i <= splitscreen; i++)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase) {
|| ((splitscreen > 1 && stplyr == &players[thirddisplayplayer]) && !camera3.chase) if (stplyr == &players[displayplayers[i]] && !camera[i].chase)
|| ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) K_drawKartFirstPerson();
K_drawKartFirstPerson(); }
// Draw full screen stuff that turns off the rest of the HUD // Draw full screen stuff that turns off the rest of the HUD
if (mapreset && stplyr == &players[displayplayer]) if (mapreset && stplyr == &players[displayplayers[0]])
{ {
K_drawChallengerScreen(); K_drawChallengerScreen();
return; return;
@ -8792,10 +8763,10 @@ void K_drawKartHUD(void)
&& comeback && comeback
&& stplyr->playerstate == PST_LIVE))); && stplyr->playerstate == PST_LIVE)));
if (!battlefullscreen || splitscreen) if (!demo.title && (!battlefullscreen || splitscreen))
{ {
// Draw the CHECK indicator before the other items, so it's overlapped by everything else // Draw the CHECK indicator before the other items, so it's overlapped by everything else
if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) if (cv_kartcheck.value && !splitscreen && !players[displayplayers[0]].exiting)
K_drawKartPlayerCheck(); K_drawKartPlayerCheck();
// Draw WANTED status // Draw WANTED status
@ -8807,7 +8778,7 @@ void K_drawKartHUD(void)
K_drawKartWanted(); K_drawKartWanted();
} }
if (cv_kartminimap.value && !titledemo) if (cv_kartminimap.value)
{ {
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_minimap)) if (LUA_HudEnabled(hud_minimap))
@ -8829,7 +8800,7 @@ void K_drawKartHUD(void)
K_drawKartItem(); K_drawKartItem();
// If not splitscreen, draw... // If not splitscreen, draw...
if (!splitscreen && !titledemo) if (!splitscreen && !demo.title)
{ {
// Draw the timestamp // Draw the timestamp
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -8849,25 +8820,44 @@ void K_drawKartHUD(void)
if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode
{ {
if (G_RaceGametype()) // Race-only elements if (demo.title) // Draw title logo instead in demo.titles
{ {
if (!titledemo) INT32 x = BASEVIDWIDTH - 32, y = 128, offs;
{
// Draw the lap counter
#ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_gametypeinfo))
#endif
K_drawKartLaps();
if (!splitscreen) if (splitscreen == 3)
{ {
// Draw the speedometer x = BASEVIDWIDTH/2 + 10;
// TODO: Make a better speedometer. y = BASEVIDHEIGHT/2 - 30;
}
if (timeinmap < 113)
{
INT32 count = ((INT32)(timeinmap) - 104);
offs = 256;
while (count-- > 0)
offs >>= 1;
x += offs;
}
V_DrawTinyScaledPatch(x-54, y, 0, W_CachePatchName("TTKBANNR", PU_CACHE));
V_DrawTinyScaledPatch(x-54, y+25, 0, W_CachePatchName("TTKART", PU_CACHE));
}
else if (G_RaceGametype()) // Race-only elements
{
// Draw the lap counter
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_speedometer)) if (LUA_HudEnabled(hud_gametypeinfo))
#endif #endif
K_drawKartSpeedometer(); K_drawKartLaps();
}
if (!splitscreen)
{
// Draw the speedometer
// TODO: Make a better speedometer.
#ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_speedometer))
#endif
K_drawKartSpeedometer();
} }
if (isfreeplay) if (isfreeplay)
@ -8880,7 +8870,7 @@ void K_drawKartHUD(void)
#endif #endif
K_DrawKartPositionNum(stplyr->kartstuff[k_position]); K_DrawKartPositionNum(stplyr->kartstuff[k_position]);
} }
else //if (!(demoplayback && hu_showscores)) else //if (!(demo.playback && hu_showscores))
{ {
// Draw the input UI // Draw the input UI
#ifdef HAVE_BLUA #ifdef HAVE_BLUA

View file

@ -163,6 +163,7 @@ static int lib_pRandomFixed(lua_State *L)
{ {
NOHUD NOHUD
lua_pushfixed(L, P_RandomFixed()); lua_pushfixed(L, P_RandomFixed());
demo_writerng = 2;
return 1; return 1;
} }
@ -170,6 +171,7 @@ static int lib_pRandomByte(lua_State *L)
{ {
NOHUD NOHUD
lua_pushinteger(L, P_RandomByte()); lua_pushinteger(L, P_RandomByte());
demo_writerng = 2;
return 1; return 1;
} }
@ -181,6 +183,7 @@ static int lib_pRandomKey(lua_State *L)
if (a > 65536) if (a > 65536)
LUA_UsageWarning(L, "P_RandomKey: range > 65536 is undefined behavior"); LUA_UsageWarning(L, "P_RandomKey: range > 65536 is undefined behavior");
lua_pushinteger(L, P_RandomKey(a)); lua_pushinteger(L, P_RandomKey(a));
demo_writerng = 2;
return 1; return 1;
} }
@ -198,6 +201,7 @@ static int lib_pRandomRange(lua_State *L)
if ((b-a+1) > 65536) if ((b-a+1) > 65536)
LUA_UsageWarning(L, "P_RandomRange: range > 65536 is undefined behavior"); LUA_UsageWarning(L, "P_RandomRange: range > 65536 is undefined behavior");
lua_pushinteger(L, P_RandomRange(a, b)); lua_pushinteger(L, P_RandomRange(a, b));
demo_writerng = 2;
return 1; return 1;
} }
@ -207,6 +211,7 @@ static int lib_pRandom(lua_State *L)
NOHUD NOHUD
LUA_Deprecated(L, "P_Random", "P_RandomByte"); LUA_Deprecated(L, "P_Random", "P_RandomByte");
lua_pushinteger(L, P_RandomByte()); lua_pushinteger(L, P_RandomByte());
demo_writerng = 2;
return 1; return 1;
} }
@ -214,6 +219,7 @@ static int lib_pSignedRandom(lua_State *L)
{ {
NOHUD NOHUD
lua_pushinteger(L, P_SignedRandom()); lua_pushinteger(L, P_SignedRandom());
demo_writerng = 2;
return 1; return 1;
} }
@ -222,6 +228,7 @@ static int lib_pRandomChance(lua_State *L)
fixed_t p = luaL_checkfixed(L, 1); fixed_t p = luaL_checkfixed(L, 1);
NOHUD NOHUD
lua_pushboolean(L, P_RandomChance(p)); lua_pushboolean(L, P_RandomChance(p));
demo_writerng = 2;
return 1; return 1;
} }

View file

@ -118,14 +118,14 @@ void COM_Lua_f(void)
flags = (UINT8)lua_tointeger(gL, -1); flags = (UINT8)lua_tointeger(gL, -1);
lua_pop(gL, 1); // pop flags lua_pop(gL, 1); // pop flags
if (flags & 2) // flag 2: splitscreen player command. if (flags & 2) // flag 2: splitscreen player command. TODO: support 4P
{ {
if (!splitscreen) if (!splitscreen)
{ {
lua_pop(gL, 1); // pop command info table lua_pop(gL, 1); // pop command info table
return; // can't execute splitscreen command without player 2! return; // can't execute splitscreen command without player 2!
} }
playernum = secondarydisplayplayer; playernum = displayplayers[1];
} }
if (netgame) if (netgame)

View file

@ -797,24 +797,24 @@ void LUAh_GameHUD(player_t *stplayr)
lua_remove(gL, -3); // pop HUD lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER); LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen > 2 && stplayr == &players[fourthdisplayplayer]) if (splitscreen > 2 && stplayr == &players[displayplayers[3]])
{ {
LUA_PushUserdata(gL, &camera4, META_CAMERA); LUA_PushUserdata(gL, &camera[3], META_CAMERA);
camnum = 4; camnum = 4;
} }
else if (splitscreen > 1 && stplayr == &players[thirddisplayplayer]) else if (splitscreen > 1 && stplayr == &players[displayplayers[2]])
{ {
LUA_PushUserdata(gL, &camera3, META_CAMERA); LUA_PushUserdata(gL, &camera[2], META_CAMERA);
camnum = 3; camnum = 3;
} }
else if (splitscreen && stplayr == &players[secondarydisplayplayer]) else if (splitscreen && stplayr == &players[displayplayers[1]])
{ {
LUA_PushUserdata(gL, &camera2, META_CAMERA); LUA_PushUserdata(gL, &camera[1], META_CAMERA);
camnum = 2; camnum = 2;
} }
else else
{ {
LUA_PushUserdata(gL, &camera, META_CAMERA); LUA_PushUserdata(gL, &camera[0], META_CAMERA);
camnum = 1; camnum = 1;
} }

View file

@ -421,13 +421,13 @@ static int mobj_set(lua_State *L)
case mobj_angle: case mobj_angle:
mo->angle = luaL_checkangle(L, 3); mo->angle = luaL_checkangle(L, 3);
if (mo->player == &players[consoleplayer]) if (mo->player == &players[consoleplayer])
localangle = mo->angle; localangle[0] = mo->angle;
else if (mo->player == &players[secondarydisplayplayer]) else if (mo->player == &players[displayplayers[1]])
localangle2 = mo->angle; localangle[1] = mo->angle;
else if (mo->player == &players[thirddisplayplayer]) else if (mo->player == &players[displayplayers[2]])
localangle3 = mo->angle; localangle[2] = mo->angle;
else if (mo->player == &players[fourthdisplayplayer]) else if (mo->player == &players[displayplayers[3]])
localangle4 = mo->angle; localangle[3] = mo->angle;
break; break;
case mobj_sprite: case mobj_sprite:
mo->sprite = luaL_checkinteger(L, 3); mo->sprite = luaL_checkinteger(L, 3);

View file

@ -354,13 +354,13 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"aiming")) { else if (fastcmp(field,"aiming")) {
plr->aiming = luaL_checkangle(L, 3); plr->aiming = luaL_checkangle(L, 3);
if (plr == &players[consoleplayer]) if (plr == &players[consoleplayer])
localaiming = plr->aiming; localaiming[0] = plr->aiming;
else if (plr == &players[secondarydisplayplayer]) else if (plr == &players[displayplayers[1]])
localaiming2 = plr->aiming; localaiming[1] = plr->aiming;
else if (plr == &players[thirddisplayplayer]) else if (plr == &players[displayplayers[2]])
localaiming3 = plr->aiming; localaiming[2] = plr->aiming;
else if (plr == &players[fourthdisplayplayer]) else if (plr == &players[displayplayers[3]])
localaiming4 = plr->aiming; localaiming[3] = plr->aiming;
} }
else if (fastcmp(field,"health")) else if (fastcmp(field,"health"))
plr->health = (INT32)luaL_checkinteger(L, 3); plr->health = (INT32)luaL_checkinteger(L, 3);

View file

@ -273,7 +273,7 @@ boolean cht_Responder(event_t *ev)
#define REQUIRE_OBJECTPLACE if (!objectplacing)\ #define REQUIRE_OBJECTPLACE if (!objectplacing)\
{ CONS_Printf(M_GetText("OBJECTPLACE must be enabled.\n")); return; } { CONS_Printf(M_GetText("OBJECTPLACE must be enabled.\n")); return; }
#define REQUIRE_INLEVEL if (gamestate != GS_LEVEL || demoplayback)\ #define REQUIRE_INLEVEL if (gamestate != GS_LEVEL || demo.playback)\
{ CONS_Printf(M_GetText("You must be in a level to use this.\n")); return; } { CONS_Printf(M_GetText("You must be in a level to use this.\n")); return; }
#define REQUIRE_SINGLEPLAYER if (netgame || multiplayer)\ #define REQUIRE_SINGLEPLAYER if (netgame || multiplayer)\

File diff suppressed because it is too large Load diff

View file

@ -235,6 +235,9 @@ void Screenshot_option_Onchange(void);
// Addons menu updating // Addons menu updating
void Addons_option_Onchange(void); void Addons_option_Onchange(void);
void M_ReplayHut(INT32 choice);
void M_SetPlaybackMenuPointer(void);
INT32 HU_GetHighlightColor(void); INT32 HU_GetHighlightColor(void);
// These defines make it a little easier to make menus // These defines make it a little easier to make menus

View file

@ -743,12 +743,12 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png
else else
snprintf(lvlttltext, 48, "Unknown"); snprintf(lvlttltext, 48, "Unknown");
if (gamestate == GS_LEVEL && &players[displayplayer] && players[displayplayer].mo) if (gamestate == GS_LEVEL && &players[displayplayers[0]] && players[displayplayers[0]].mo)
snprintf(locationtxt, 40, "X:%d Y:%d Z:%d A:%d", snprintf(locationtxt, 40, "X:%d Y:%d Z:%d A:%d",
players[displayplayer].mo->x>>FRACBITS, players[displayplayers[0]].mo->x>>FRACBITS,
players[displayplayer].mo->y>>FRACBITS, players[displayplayers[0]].mo->y>>FRACBITS,
players[displayplayer].mo->z>>FRACBITS, players[displayplayers[0]].mo->z>>FRACBITS,
FixedInt(AngleFixed(players[displayplayer].mo->angle))); FixedInt(AngleFixed(players[displayplayers[0]].mo->angle)));
else else
snprintf(locationtxt, 40, "Unknown"); snprintf(locationtxt, 40, "Unknown");

View file

@ -3079,7 +3079,7 @@ void A_Invincibility(mobj_t *actor)
{ {
S_StopMusic(); S_StopMusic();
if (mariomode) if (mariomode)
G_GhostAddColor(GHC_INVINCIBLE); G_GhostAddColor((INT32) (player - players), GHC_INVINCIBLE);
S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false); S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false);
} }
} }
@ -4174,12 +4174,12 @@ void A_OverlayThink(mobj_t *actor)
{ {
angle_t viewingangle; angle_t viewingangle;
if (players[displayplayer].awayviewtics) if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo) else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else else
viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, camera.x, camera.y); viewingangle = R_PointToAngle2(actor->target->x, actor->target->y, camera[0].x, camera[0].y);
destx = actor->target->x + P_ReturnThrustX(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale)); destx = actor->target->x + P_ReturnThrustX(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale));
desty = actor->target->y + P_ReturnThrustY(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale)); desty = actor->target->y + P_ReturnThrustY(actor->target, viewingangle, FixedMul(FRACUNIT, actor->scale));

View file

@ -2536,9 +2536,9 @@ void T_CameraScanner(elevator_t *elevator)
lastleveltime = leveltime; lastleveltime = leveltime;
} }
if (players[displayplayer].mo) if (players[displayplayers[0]].mo)
{ {
if (players[displayplayer].mo->subsector->sector == elevator->actionsector) if (players[displayplayers[0]].mo->subsector->sector == elevator->actionsector)
{ {
if (t_cam_dist == -42) if (t_cam_dist == -42)
t_cam_dist = cv_cam_dist.value; t_cam_dist = cv_cam_dist.value;
@ -2564,9 +2564,9 @@ void T_CameraScanner(elevator_t *elevator)
} }
} }
if (splitscreen && players[secondarydisplayplayer].mo) if (splitscreen && players[displayplayers[1]].mo)
{ {
if (players[secondarydisplayplayer].mo->subsector->sector == elevator->actionsector) if (players[displayplayers[1]].mo->subsector->sector == elevator->actionsector)
{ {
if (t_cam2_rotate == -42) if (t_cam2_rotate == -42)
t_cam2_dist = cv_cam2_dist.value; t_cam2_dist = cv_cam2_dist.value;
@ -2592,9 +2592,9 @@ void T_CameraScanner(elevator_t *elevator)
} }
} }
if (splitscreen > 1 && players[thirddisplayplayer].mo) if (splitscreen > 1 && players[displayplayers[2]].mo)
{ {
if (players[thirddisplayplayer].mo->subsector->sector == elevator->actionsector) if (players[displayplayers[2]].mo->subsector->sector == elevator->actionsector)
{ {
if (t_cam3_rotate == -42) if (t_cam3_rotate == -42)
t_cam3_dist = cv_cam3_dist.value; t_cam3_dist = cv_cam3_dist.value;
@ -2620,9 +2620,9 @@ void T_CameraScanner(elevator_t *elevator)
} }
} }
if (splitscreen > 2 && players[fourthdisplayplayer].mo) if (splitscreen > 2 && players[displayplayers[3]].mo)
{ {
if (players[fourthdisplayplayer].mo->subsector->sector == elevator->actionsector) if (players[displayplayers[3]].mo->subsector->sector == elevator->actionsector)
{ {
if (t_cam4_rotate == -42) if (t_cam4_rotate == -42)
t_cam4_dist = cv_cam4_dist.value; t_cam4_dist = cv_cam4_dist.value;

View file

@ -62,11 +62,11 @@ void P_ForceConstant(const BasicFF_t *FFInfo)
ConstantQuake.Magnitude = FFInfo->Magnitude; ConstantQuake.Magnitude = FFInfo->Magnitude;
if (FFInfo->player == &players[consoleplayer]) if (FFInfo->player == &players[consoleplayer])
I_Tactile(ConstantForce, &ConstantQuake); I_Tactile(ConstantForce, &ConstantQuake);
else if (splitscreen && FFInfo->player == &players[secondarydisplayplayer]) else if (splitscreen && FFInfo->player == &players[displayplayers[1]])
I_Tactile2(ConstantForce, &ConstantQuake); I_Tactile2(ConstantForce, &ConstantQuake);
else if (splitscreen > 1 && FFInfo->player == &players[thirddisplayplayer]) else if (splitscreen > 1 && FFInfo->player == &players[displayplayers[2]])
I_Tactile3(ConstantForce, &ConstantQuake); I_Tactile3(ConstantForce, &ConstantQuake);
else if (splitscreen > 2 && FFInfo->player == &players[fourthdisplayplayer]) else if (splitscreen > 2 && FFInfo->player == &players[displayplayers[3]])
I_Tactile4(ConstantForce, &ConstantQuake); I_Tactile4(ConstantForce, &ConstantQuake);
} }
void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End) void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
@ -83,11 +83,11 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
RampQuake.End = End; RampQuake.End = End;
if (FFInfo->player == &players[consoleplayer]) if (FFInfo->player == &players[consoleplayer])
I_Tactile(ConstantForce, &RampQuake); I_Tactile(ConstantForce, &RampQuake);
else if (splitscreen && FFInfo->player == &players[secondarydisplayplayer]) else if (splitscreen && FFInfo->player == &players[displayplayers[1]])
I_Tactile2(ConstantForce, &RampQuake); I_Tactile2(ConstantForce, &RampQuake);
else if (splitscreen > 1 && FFInfo->player == &players[thirddisplayplayer]) else if (splitscreen > 1 && FFInfo->player == &players[displayplayers[2]])
I_Tactile3(ConstantForce, &RampQuake); I_Tactile3(ConstantForce, &RampQuake);
else if (splitscreen > 2 && FFInfo->player == &players[fourthdisplayplayer]) else if (splitscreen > 2 && FFInfo->player == &players[displayplayers[3]])
I_Tactile4(ConstantForce, &RampQuake); I_Tactile4(ConstantForce, &RampQuake);
} }
@ -218,7 +218,7 @@ void P_DoNightsScore(player_t *player)
dummymo->fuse = 3*TICRATE; dummymo->fuse = 3*TICRATE;
// What?! NO, don't use the camera! Scale up instead! // What?! NO, don't use the camera! Scale up instead!
//P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera.x, camera.y), 3*FRACUNIT); //P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera[0].x, camera[0].y), 3*FRACUNIT);
dummymo->scalespeed = FRACUNIT/25; dummymo->scalespeed = FRACUNIT/25;
dummymo->destscale = 2*FRACUNIT; dummymo->destscale = 2*FRACUNIT;
} }
@ -851,7 +851,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Secret emblem thingy // Secret emblem thingy
case MT_EMBLEM: case MT_EMBLEM:
{ {
if (demoplayback || player->bot) if (demo.playback || player->bot)
return; return;
emblemlocations[special->health-1].collected = true; emblemlocations[special->health-1].collected = true;
@ -1180,13 +1180,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->angle = special->angle; toucher->angle = special->angle;
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = toucher->angle; localangle[0] = toucher->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = toucher->angle; localangle[1] = toucher->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = toucher->angle; localangle[2] = toucher->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = toucher->angle; localangle[3] = toucher->angle;
P_ResetPlayer(player); P_ResetPlayer(player);
@ -1209,7 +1209,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
// CECHO showing you what this item is // CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap)) if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{ {
HU_SetCEchoFlags(V_AUTOFADEOUT); HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4); HU_SetCEchoDuration(4);
@ -1231,7 +1231,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
// CECHO showing you what this item is // CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap)) if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{ {
HU_SetCEchoFlags(V_AUTOFADEOUT); HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4); HU_SetCEchoDuration(4);
@ -1263,7 +1263,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
// CECHO showing you what this item is // CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap)) if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{ {
HU_SetCEchoFlags(V_AUTOFADEOUT); HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4); HU_SetCEchoDuration(4);
@ -1293,7 +1293,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
// CECHO showing you what this item is // CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap)) if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{ {
HU_SetCEchoFlags(V_AUTOFADEOUT); HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4); HU_SetCEchoDuration(4);
@ -1321,7 +1321,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
// CECHO showing you what this item is // CECHO showing you what this item is
if (player == &players[displayplayer] || G_IsSpecialStage(gamemap)) if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap))
{ {
HU_SetCEchoFlags(V_AUTOFADEOUT); HU_SetCEchoFlags(V_AUTOFADEOUT);
HU_SetCEchoDuration(4); HU_SetCEchoDuration(4);
@ -1433,7 +1433,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
player->powers[pw_shield] |= SH_FIREFLOWER; player->powers[pw_shield] |= SH_FIREFLOWER;
toucher->color = SKINCOLOR_WHITE; toucher->color = SKINCOLOR_WHITE;
G_GhostAddColor(GHC_FIREFLOWER); G_GhostAddColor(player - players, GHC_FIREFLOWER);
break; break;
// *************** // // *************** //
@ -2324,17 +2324,17 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
AM_Stop(); AM_Stop();
//added : 22-02-98: recenter view for next life... //added : 22-02-98: recenter view for next life...
localaiming = 0; localaiming[0] = 0;
} }
if (target->player == &players[secondarydisplayplayer]) if (target->player == &players[displayplayers[1]])
{ {
// added : 22-02-98: recenter view for next life... // added : 22-02-98: recenter view for next life...
localaiming2 = 0; localaiming[1] = 0;
} }
if (target->player == &players[thirddisplayplayer]) if (target->player == &players[displayplayers[2]])
localaiming3 = 0; localaiming[2] = 0;
if (target->player == &players[fourthdisplayplayer]) if (target->player == &players[displayplayers[3]])
localaiming4 = 0; localaiming[3] = 0;
//tag deaths handled differently in suicide cases. Don't count spectators! //tag deaths handled differently in suicide cases. Don't count spectators!
/*if (G_TagGametype() /*if (G_TagGametype()
@ -2978,7 +2978,7 @@ void P_RemoveShield(player_t *player)
if (!player->powers[pw_super]) if (!player->powers[pw_super])
{ {
player->mo->color = player->skincolor; player->mo->color = player->skincolor;
G_GhostAddColor(GHC_NORMAL); G_GhostAddColor((INT32) (player - players), GHC_NORMAL);
} }
} }
else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them! else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them!
@ -3409,7 +3409,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
target->health -= damage; target->health -= damage;
if (source && source->player && target) if (source && source->player && target)
G_GhostAddHit(target); G_GhostAddHit((INT32) (source->player - players), target);
if (target->health <= 0) if (target->health <= 0)
{ {

View file

@ -22,6 +22,7 @@
#include "p_tick.h" #include "p_tick.h"
#include "r_defs.h" #include "r_defs.h"
#include "p_maputl.h" #include "p_maputl.h"
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#define FLOATSPEED (FRACUNIT*4) #define FLOATSPEED (FRACUNIT*4)
@ -108,7 +109,7 @@ typedef struct camera_s
fixed_t pan; fixed_t pan;
} camera_t; } camera_t;
extern camera_t camera, camera2, camera3, camera4; extern camera_t camera[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height;
extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed; extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed;
@ -137,6 +138,7 @@ boolean P_PlayerInPain(player_t *player);
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player); void P_ResetPlayer(player_t *player);
boolean P_IsLocalPlayer(player_t *player); boolean P_IsLocalPlayer(player_t *player);
boolean P_IsDisplayPlayer(player_t *player);
boolean P_SpectatorJoinGame(player_t *player); boolean P_SpectatorJoinGame(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectInGoop(mobj_t *mo);

View file

@ -212,16 +212,16 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{ {
object->angle = spring->angle; object->angle = spring->angle;
if (!demoplayback || P_AnalogMove(object->player)) if (!demo.playback || P_AnalogMove(object->player))
{ {
if (object->player == &players[consoleplayer]) if (object->player == &players[consoleplayer])
localangle = spring->angle; localangle[0] = spring->angle;
else if (object->player == &players[secondarydisplayplayer]) else if (object->player == &players[displayplayers[1]])
localangle2 = spring->angle; localangle[1] = spring->angle;
else if (object->player == &players[thirddisplayplayer]) else if (object->player == &players[displayplayers[2]])
localangle3 = spring->angle; localangle[2] = spring->angle;
else if (object->player == &players[fourthdisplayplayer]) else if (object->player == &players[displayplayers[3]])
localangle4 = spring->angle; localangle[3] = spring->angle;
} }
} }
@ -1264,16 +1264,16 @@ static boolean PIT_CheckThing(mobj_t *thing)
thing->angle = tmthing->angle; thing->angle = tmthing->angle;
if (!demoplayback || P_AnalogMove(thing->player)) if (!demo.playback || P_AnalogMove(thing->player))
{ {
if (thing->player == &players[consoleplayer]) if (thing->player == &players[consoleplayer])
localangle = thing->angle; localangle[0] = thing->angle;
else if (thing->player == &players[secondarydisplayplayer]) else if (thing->player == &players[displayplayers[1]])
localangle2 = thing->angle; localangle[1] = thing->angle;
else if (thing->player == &players[thirddisplayplayer]) else if (thing->player == &players[displayplayers[2]])
localangle3 = thing->angle; localangle[2] = thing->angle;
else if (thing->player == &players[fourthdisplayplayer]) else if (thing->player == &players[displayplayers[3]])
localangle4 = thing->angle; localangle[3] = thing->angle;
} }
return true; return true;
@ -2504,41 +2504,46 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
subsector_t *s = R_PointInSubsector(x, y); subsector_t *s = R_PointInSubsector(x, y);
boolean retval = true; boolean retval = true;
boolean itsatwodlevel = false; boolean itsatwodlevel = false;
UINT8 i;
floatok = false; floatok = false;
if (twodlevel if (twodlevel)
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera3 && players[thirddisplayplayer].mo && (players[thirddisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera4 && players[fourthdisplayplayer].mo && (players[fourthdisplayplayer].mo->flags2 & MF2_TWOD)))
itsatwodlevel = true; itsatwodlevel = true;
else
{
for (i = 0; i <= splitscreen; i++)
{
if (thiscam == &camera[i] && players[displayplayers[i]].mo
&& (players[displayplayers[i]].mo->flags2 & MF2_TWOD))
{
itsatwodlevel = true;
break;
}
}
}
if (!itsatwodlevel && players[displayplayer].mo) if (!itsatwodlevel && players[displayplayers[0]].mo)
{ {
fixed_t tryx = thiscam->x; fixed_t tryx = thiscam->x;
fixed_t tryy = thiscam->y; fixed_t tryy = thiscam->y;
for (i = 0; i <= splitscreen; i++)
{
#ifndef NOCLIPCAM #ifndef NOCLIPCAM
if ((thiscam == &camera && (players[displayplayer].pflags & PF_NOCLIP)) if ((thiscam == &camera[i] && (players[displayplayers[i]].pflags & PF_NOCLIP)) || (leveltime < introtime)) // Noclipping player camera noclips too!!
|| (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera3 && (players[thirddisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP))
|| (leveltime < introtime))
#else #else
if ((thiscam == &camera && !(players[displayplayer].pflags & PF_TIMEOVER)) if (thiscam == &camera[i] && !(players[displayplayers[i]].pflags & PF_TIMEOVER)) // Time Over should not clip through walls
|| (thiscam == &camera2 && !(players[secondarydisplayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera3 && !(players[thirddisplayplayer].pflags & PF_TIMEOVER))
|| (thiscam == &camera4 && !(players[fourthdisplayplayer].pflags & PF_TIMEOVER)))
#endif #endif
{ // Noclipping player camera noclips too!! {
floatok = true; floatok = true;
thiscam->floorz = thiscam->z; thiscam->floorz = thiscam->z;
thiscam->ceilingz = thiscam->z + thiscam->height; thiscam->ceilingz = thiscam->z + thiscam->height;
thiscam->x = x; thiscam->x = x;
thiscam->y = y; thiscam->y = y;
thiscam->subsector = s; thiscam->subsector = s;
return true; return true;
}
} }
do { do {

View file

@ -339,9 +339,9 @@ void P_CameraLineOpening(line_t *linedef)
frontceiling = sectors[front->camsec].ceilingheight; frontceiling = sectors[front->camsec].ceilingheight;
#ifdef ESLOPE #ifdef ESLOPE
if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y); frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera[0].x, camera[0].y);
if (sectors[front->camsec].c_slope) if (sectors[front->camsec].c_slope)
frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y); frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera[0].x, camera[0].y);
#endif #endif
} }
@ -351,9 +351,9 @@ void P_CameraLineOpening(line_t *linedef)
frontceiling = sectors[front->heightsec].ceilingheight; frontceiling = sectors[front->heightsec].ceilingheight;
#ifdef ESLOPE #ifdef ESLOPE
if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y); frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera[0].x, camera[0].y);
if (sectors[front->heightsec].c_slope) if (sectors[front->heightsec].c_slope)
frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y); frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera[0].x, camera[0].y);
#endif #endif
} }
else else
@ -367,9 +367,9 @@ void P_CameraLineOpening(line_t *linedef)
backceiling = sectors[back->camsec].ceilingheight; backceiling = sectors[back->camsec].ceilingheight;
#ifdef ESLOPE #ifdef ESLOPE
if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y); frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera[0].x, camera[0].y);
if (sectors[back->camsec].c_slope) if (sectors[back->camsec].c_slope)
frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y); frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera[0].x, camera[0].y);
#endif #endif
} }
else if (back->heightsec >= 0) else if (back->heightsec >= 0)
@ -378,9 +378,9 @@ void P_CameraLineOpening(line_t *linedef)
backceiling = sectors[back->heightsec].ceilingheight; backceiling = sectors[back->heightsec].ceilingheight;
#ifdef ESLOPE #ifdef ESLOPE
if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y); frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera[0].x, camera[0].y);
if (sectors[back->heightsec].c_slope) if (sectors[back->heightsec].c_slope)
frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y); frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera[0].x, camera[0].y);
#endif #endif
} }
else else

View file

@ -1125,7 +1125,7 @@ static void P_PlayerFlip(mobj_t *mo)
if (!mo->player) if (!mo->player)
return; return;
G_GhostAddFlip(); G_GhostAddFlip((INT32) (mo->player - players));
// Flip aiming to match! // Flip aiming to match!
if (mo->player->pflags & PF_NIGHTSMODE) // NiGHTS doesn't use flipcam if (mo->player->pflags & PF_NIGHTSMODE) // NiGHTS doesn't use flipcam
@ -1135,45 +1135,21 @@ static void P_PlayerFlip(mobj_t *mo)
} }
else if (mo->player->pflags & PF_FLIPCAM) else if (mo->player->pflags & PF_FLIPCAM)
{ {
UINT8 i;
mo->player->aiming = InvAngle(mo->player->aiming); mo->player->aiming = InvAngle(mo->player->aiming);
if (mo->player-players == displayplayer)
for (i = 0; i <= splitscreen; i++)
{ {
localaiming = mo->player->aiming; if (mo->player-players == displayplayers[i])
if (camera.chase) { {
camera.aiming = InvAngle(camera.aiming); localaiming[i] = mo->player->aiming;
camera.z = mo->z - camera.z + mo->z; if (camera[i].chase) {
if (mo->eflags & MFE_VERTICALFLIP) camera[i].aiming = InvAngle(camera[i].aiming);
camera.z += FixedMul(20*FRACUNIT, mo->scale); camera[i].z = mo->z - camera[i].z + mo->z;
} if (mo->eflags & MFE_VERTICALFLIP)
} camera[i].z += FixedMul(20*FRACUNIT, mo->scale);
else if (mo->player-players == secondarydisplayplayer) }
{
localaiming2 = mo->player->aiming;
if (camera2.chase) {
camera2.aiming = InvAngle(camera2.aiming);
camera2.z = mo->z - camera2.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera2.z += FixedMul(20*FRACUNIT, mo->scale);
}
}
else if (mo->player-players == thirddisplayplayer)
{
localaiming3 = mo->player->aiming;
if (camera3.chase) {
camera3.aiming = InvAngle(camera3.aiming);
camera3.z = mo->z - camera3.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera3.z += FixedMul(20*FRACUNIT, mo->scale);
}
}
else if (mo->player-players == fourthdisplayplayer)
{
localaiming4 = mo->player->aiming;
if (camera4.chase) {
camera4.aiming = InvAngle(camera4.aiming);
camera4.z = mo->z - camera4.z + mo->z;
if (mo->eflags & MFE_VERTICALFLIP)
camera4.z += FixedMul(20*FRACUNIT, mo->scale);
} }
} }
} }
@ -3546,17 +3522,26 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
{ {
boolean itsatwodlevel = false; boolean itsatwodlevel = false;
postimg_t postimg = postimg_none; postimg_t postimg = postimg_none;
UINT8 i;
// This can happen when joining // This can happen when joining
if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL)
return true; return true;
if (twodlevel if (twodlevel)
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera3 && players[thirddisplayplayer].mo && (players[thirddisplayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera4 && players[fourthdisplayplayer].mo && (players[fourthdisplayplayer].mo->flags2 & MF2_TWOD)))
itsatwodlevel = true; itsatwodlevel = true;
else
{
for (i = 0; i <= splitscreen; i++)
{
if (thiscam == &camera[i] && players[displayplayers[i]].mo
&& (players[displayplayers[i]].mo->flags2 & MF2_TWOD))
{
itsatwodlevel = true;
break;
}
}
}
if (encoremode) if (encoremode)
postimg = postimg_mirror; postimg = postimg_mirror;
@ -3588,14 +3573,11 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
if (postimg != postimg_none) if (postimg != postimg_none)
{ {
if (splitscreen && player == &players[secondarydisplayplayer]) for (i = 0; i <= splitscreen; i++)
postimgtype2 = postimg; {
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) if (player == &players[displayplayers[i]])
postimgtype3 = postimg; postimgtype[i] = postimg;
else if (splitscreen > 2 && player == &players[fourthdisplayplayer]) }
postimgtype4 = postimg;
else
postimgtype = postimg;
} }
if (thiscam->momx || thiscam->momy) if (thiscam->momx || thiscam->momy)
@ -3641,11 +3623,11 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
fixed_t cam_height = cv_cam_height.value; fixed_t cam_height = cv_cam_height.value;
thiscam->z = thiscam->floorz; thiscam->z = thiscam->floorz;
if (player == &players[secondarydisplayplayer]) if (player == &players[displayplayers[1]])
cam_height = cv_cam2_height.value; cam_height = cv_cam2_height.value;
if (player == &players[thirddisplayplayer]) if (player == &players[displayplayers[2]])
cam_height = cv_cam3_height.value; cam_height = cv_cam3_height.value;
if (player == &players[fourthdisplayplayer]) if (player == &players[displayplayers[3]])
cam_height = cv_cam4_height.value; cam_height = cv_cam4_height.value;
if (thiscam->z > player->mo->z + player->mo->height + FixedMul(cam_height*FRACUNIT + 16*FRACUNIT, player->mo->scale)) if (thiscam->z > player->mo->z + player->mo->height + FixedMul(cam_height*FRACUNIT + 16*FRACUNIT, player->mo->scale))
{ {
@ -5897,7 +5879,7 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale)
if (player) if (player)
{ {
G_GhostAddScale(newscale); G_GhostAddScale((INT32) (player - players), newscale);
player->viewheight = FixedMul(FixedDiv(player->viewheight, oldscale), newscale); // Nonono don't calculate viewheight elsewhere, this is the best place for it! player->viewheight = FixedMul(FixedDiv(player->viewheight, oldscale), newscale); // Nonono don't calculate viewheight elsewhere, this is the best place for it!
player->dashspeed = FixedMul(FixedDiv(player->dashspeed, oldscale), newscale); // Prevents the player from having to re-charge up spindash if the player grew in size player->dashspeed = FixedMul(FixedDiv(player->dashspeed, oldscale), newscale); // Prevents the player from having to re-charge up spindash if the player grew in size
} }
@ -6101,12 +6083,12 @@ void P_RunOverlays(void)
{ {
angle_t viewingangle; angle_t viewingangle;
if (players[displayplayer].awayviewtics) if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo) else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else else
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera.x, camera.y); viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera[0].x, camera[0].y);
if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1) if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
viewingangle += ANGLE_180; viewingangle += ANGLE_180;
@ -6680,7 +6662,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->target && mobj->target->health if (mobj->target && mobj->target->health
&& mobj->target->player && !mobj->target->player->spectator && mobj->target->player && !mobj->target->player->spectator
&& mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD && mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD
/*&& players[displayplayer].mo && !players[displayplayer].spectator*/) /*&& players[displayplayers[0]].mo && !players[displayplayers[0]].spectator*/)
{ {
fixed_t scale = 3*mobj->target->scale; fixed_t scale = 3*mobj->target->scale;
mobj->color = mobj->target->color; mobj->color = mobj->target->color;
@ -6688,7 +6670,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0) if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0)
#if 1 // Set to 0 to test without needing to host #if 1 // Set to 0 to test without needing to host
|| ((mobj->target->player == &players[displayplayer]) || P_IsLocalPlayer(mobj->target->player)) || ((mobj->target->player == &players[displayplayers[0]]) || P_IsLocalPlayer(mobj->target->player))
#endif #endif
) )
mobj->flags2 |= MF2_DONTDRAW; mobj->flags2 |= MF2_DONTDRAW;
@ -6699,10 +6681,10 @@ void P_MobjThinker(mobj_t *mobj)
mobj->angle = R_PointToAngle(mobj->x, mobj->y) + ANGLE_90; // literally only happened because i wanted to ^L^R the SPR_ITEM's mobj->angle = R_PointToAngle(mobj->x, mobj->y) + ANGLE_90; // literally only happened because i wanted to ^L^R the SPR_ITEM's
if (!splitscreen && players[displayplayer].mo) if (!splitscreen && players[displayplayers[0]].mo)
{ {
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x, scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x,
players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
if (scale > 16*mobj->target->scale) if (scale > 16*mobj->target->scale)
scale = 16*mobj->target->scale; scale = 16*mobj->target->scale;
} }
@ -6887,7 +6869,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->target && mobj->target->health && mobj->tracer if (mobj->target && mobj->target->health && mobj->tracer
&& mobj->target->player && !mobj->target->player->spectator && mobj->target->player && !mobj->target->player->spectator
&& mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD && mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD
&& players[displayplayer].mo && !players[displayplayer].spectator) && players[displayplayers[0]].mo && !players[displayplayers[0]].spectator)
{ {
fixed_t scale = 3*mobj->target->scale; fixed_t scale = 3*mobj->target->scale;
@ -6909,8 +6891,8 @@ void P_MobjThinker(mobj_t *mobj)
if (!splitscreen) if (!splitscreen)
{ {
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x, scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x,
players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
if (scale > 16*mobj->target->scale) if (scale > 16*mobj->target->scale)
scale = 16*mobj->target->scale; scale = 16*mobj->target->scale;
} }
@ -8296,12 +8278,12 @@ void P_MobjThinker(mobj_t *mobj)
angle_t viewingangle; angle_t viewingangle;
statenum_t curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); statenum_t curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states)));
if (players[displayplayer].awayviewtics) if (players[displayplayers[0]].awayviewtics)
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo) else if (!camera[0].chase && players[displayplayers[0]].mo)
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
else else
viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera.x, camera.y); viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y);
if (curstate > S_THUNDERSHIELD15) if (curstate > S_THUNDERSHIELD15)
viewingangle += ANGLE_180; viewingangle += ANGLE_180;
@ -10562,13 +10544,13 @@ void P_PrecipitationEffects(void)
// Local effects from here on out! // Local effects from here on out!
// If we're not in game fully yet, we don't worry about them. // If we're not in game fully yet, we don't worry about them.
if (!playeringame[displayplayer] || !players[displayplayer].mo) if (!playeringame[displayplayers[0]] || !players[displayplayers[0]].mo)
return; return;
if (sound_disabled) if (sound_disabled)
return; // Sound off? D'aw, no fun. return; // Sound off? D'aw, no fun.
if (players[displayplayer].mo->subsector->sector->ceilingpic == skyflatnum) if (players[displayplayers[0]].mo->subsector->sector->ceilingpic == skyflatnum)
volume = 255; // Sky above? We get it full blast. volume = 255; // Sky above? We get it full blast.
else else
{ {
@ -10576,17 +10558,17 @@ void P_PrecipitationEffects(void)
fixed_t closedist, newdist; fixed_t closedist, newdist;
// Essentially check in a 1024 unit radius of the player for an outdoor area. // Essentially check in a 1024 unit radius of the player for an outdoor area.
yl = players[displayplayer].mo->y - 1024*FRACUNIT; yl = players[displayplayers[0]].mo->y - 1024*FRACUNIT;
yh = players[displayplayer].mo->y + 1024*FRACUNIT; yh = players[displayplayers[0]].mo->y + 1024*FRACUNIT;
xl = players[displayplayer].mo->x - 1024*FRACUNIT; xl = players[displayplayers[0]].mo->x - 1024*FRACUNIT;
xh = players[displayplayer].mo->x + 1024*FRACUNIT; xh = players[displayplayers[0]].mo->x + 1024*FRACUNIT;
closedist = 2048*FRACUNIT; closedist = 2048*FRACUNIT;
for (y = yl; y <= yh; y += FRACUNIT*64) for (y = yl; y <= yh; y += FRACUNIT*64)
for (x = xl; x <= xh; x += FRACUNIT*64) for (x = xl; x <= xh; x += FRACUNIT*64)
{ {
if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors! if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors!
{ {
newdist = S_CalculateSoundDistance(players[displayplayer].mo->x, players[displayplayer].mo->y, 0, x, y, 0); newdist = S_CalculateSoundDistance(players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y, 0, x, y, 0);
if (newdist < closedist) if (newdist < closedist)
closedist = newdist; closedist = newdist;
} }
@ -10601,7 +10583,7 @@ void P_PrecipitationEffects(void)
volume = 255; volume = 255;
if (sounds_rain && (!leveltime || leveltime % 80 == 1)) if (sounds_rain && (!leveltime || leveltime % 80 == 1))
S_StartSoundAtVolume(players[displayplayer].mo, sfx_rainin, volume); S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_rainin, volume);
if (!sounds_thunder) if (!sounds_thunder)
return; return;
@ -10609,7 +10591,7 @@ void P_PrecipitationEffects(void)
if (effects_lightning && lightningStrike && volume) if (effects_lightning && lightningStrike && volume)
{ {
// Large, close thunder sounds to go with our lightning. // Large, close thunder sounds to go with our lightning.
S_StartSoundAtVolume(players[displayplayer].mo, sfx_litng1 + M_RandomKey(4), volume); S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_litng1 + M_RandomKey(4), volume);
} }
else if (thunderchance < 20) else if (thunderchance < 20)
{ {
@ -10617,7 +10599,7 @@ void P_PrecipitationEffects(void)
if (volume < 80) if (volume < 80)
volume = 80; volume = 80;
S_StartSoundAtVolume(players[displayplayer].mo, sfx_athun1 + M_RandomKey(2), volume); S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_athun1 + M_RandomKey(2), volume);
} }
} }
@ -10789,7 +10771,8 @@ void P_SpawnPlayer(INT32 playernum)
} }
// spawn as spectator determination // spawn as spectator determination
if (!G_GametypeHasSpectators()) if (multiplayer && demo.playback); // Don't mess with spectator values since the demo setup handles them already.
else if (!G_GametypeHasSpectators())
p->spectator = false; p->spectator = false;
else if (netgame && p->jointime <= 1 && pcount) else if (netgame && p->jointime <= 1 && pcount)
{ {
@ -10923,15 +10906,21 @@ void P_AfterPlayerSpawn(INT32 playernum)
{ {
player_t *p = &players[playernum]; player_t *p = &players[playernum];
mobj_t *mobj = p->mo; mobj_t *mobj = p->mo;
UINT8 i;
if (playernum == consoleplayer) if (playernum == consoleplayer)
localangle = mobj->angle; localangle[0] = mobj->angle;
else if (playernum == secondarydisplayplayer) else if (splitscreen)
localangle2 = mobj->angle; {
else if (playernum == thirddisplayplayer) for (i = 1; i <= splitscreen; i++)
localangle3 = mobj->angle; {
else if (playernum == fourthdisplayplayer) if (playernum == displayplayers[i])
localangle4 = mobj->angle; {
localangle[i] = mobj->angle;
break;
}
}
}
p->viewheight = 32<<FRACBITS; p->viewheight = 32<<FRACBITS;
@ -10953,25 +10942,13 @@ void P_AfterPlayerSpawn(INT32 playernum)
SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle); SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle);
if (camera.chase) for (i = 0; i <= splitscreen; i++)
{ {
if (displayplayer == playernum) if (camera[i].chase)
P_ResetCamera(p, &camera); {
} if (displayplayers[i] == playernum)
if (camera2.chase && splitscreen) P_ResetCamera(p, &camera[i]);
{ }
if (secondarydisplayplayer == playernum)
P_ResetCamera(p, &camera2);
}
if (camera3.chase && splitscreen > 1)
{
if (thirddisplayplayer == playernum)
P_ResetCamera(p, &camera3);
}
if (camera4.chase && splitscreen > 2)
{
if (fourthdisplayplayer == playernum)
P_ResetCamera(p, &camera4);
} }
if (CheckForReverseGravity) if (CheckForReverseGravity)

View file

@ -1336,13 +1336,13 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
if (turnthings == 2 || (turnthings == 1 && !mo->player)) { if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta; mo->angle += delta;
if (mo->player == &players[consoleplayer]) if (mo->player == &players[consoleplayer])
localangle = mo->angle; localangle[0] += delta;
else if (mo->player == &players[secondarydisplayplayer]) else if (mo->player == &players[displayplayers[1]])
localangle2 = mo->angle; localangle[1] += delta;
else if (mo->player == &players[thirddisplayplayer]) else if (mo->player == &players[displayplayers[2]])
localangle3 = mo->angle; localangle[2] += delta;
else if (mo->player == &players[fourthdisplayplayer]) else if (mo->player == &players[displayplayers[3]])
localangle4 = mo->angle; localangle[3] += delta;
} }
} }
} }

View file

@ -2078,13 +2078,13 @@ static void LoadMobjThinker(actionf_p1 thinker)
mobj->player->mo = mobj; mobj->player->mo = mobj;
// added for angle prediction // added for angle prediction
if (consoleplayer == i) if (consoleplayer == i)
localangle = mobj->angle; localangle[0] = mobj->angle;
if (secondarydisplayplayer == i) if (displayplayers[1] == i)
localangle2 = mobj->angle; localangle[1] = mobj->angle;
if (thirddisplayplayer == i) if (displayplayers[2] == i)
localangle3 = mobj->angle; localangle[2] = mobj->angle;
if (fourthdisplayplayer == i) if (displayplayers[3] == i)
localangle4 = mobj->angle; localangle[3] = mobj->angle;
} }
if (diff & MD_MOVEDIR) if (diff & MD_MOVEDIR)
mobj->movedir = READANGLE(save_p); mobj->movedir = READANGLE(save_p);
@ -3423,7 +3423,7 @@ void P_SaveNetGame(void)
mobj_t *mobj; mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p); CV_SaveNetVars(&save_p, false);
P_NetArchiveMisc(); P_NetArchiveMisc();
// Assign the mobjnumber for pointer tracking // Assign the mobjnumber for pointer tracking

View file

@ -65,6 +65,10 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_hook.h" #include "lua_hook.h"
#if !defined (UNDER_CE)
#include <time.h>
#endif
#if defined (_WIN32) || defined (_WIN32_WCE) #if defined (_WIN32) || defined (_WIN32_WCE)
#include <malloc.h> #include <malloc.h>
#include <math.h> #include <math.h>
@ -2265,7 +2269,7 @@ static void P_LevelInitStuff(void)
leveltime = 0; leveltime = 0;
localaiming = localaiming2 = localaiming3 = localaiming4 = 0; memset(localaiming, 0, sizeof(localaiming));
// map object scale // map object scale
mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale; mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale;
@ -2532,29 +2536,29 @@ static void P_ForceCharacter(const char *forcecharskin)
{ {
if (splitscreen) if (splitscreen)
{ {
SetPlayerSkin(secondarydisplayplayer, forcecharskin); SetPlayerSkin(displayplayers[1], forcecharskin);
if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin].prefcolor && !modeattacking) if ((unsigned)cv_playercolor2.value != skins[players[displayplayers[1]].skin].prefcolor && !modeattacking)
{ {
CV_StealthSetValue(&cv_playercolor2, skins[players[secondarydisplayplayer].skin].prefcolor); CV_StealthSetValue(&cv_playercolor2, skins[players[displayplayers[1]].skin].prefcolor);
players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin].prefcolor; players[displayplayers[1]].skincolor = skins[players[displayplayers[1]].skin].prefcolor;
} }
if (splitscreen > 1) if (splitscreen > 1)
{ {
SetPlayerSkin(thirddisplayplayer, forcecharskin); SetPlayerSkin(displayplayers[2], forcecharskin);
if ((unsigned)cv_playercolor3.value != skins[players[thirddisplayplayer].skin].prefcolor && !modeattacking) if ((unsigned)cv_playercolor3.value != skins[players[displayplayers[2]].skin].prefcolor && !modeattacking)
{ {
CV_StealthSetValue(&cv_playercolor3, skins[players[thirddisplayplayer].skin].prefcolor); CV_StealthSetValue(&cv_playercolor3, skins[players[displayplayers[2]].skin].prefcolor);
players[thirddisplayplayer].skincolor = skins[players[thirddisplayplayer].skin].prefcolor; players[displayplayers[2]].skincolor = skins[players[displayplayers[2]].skin].prefcolor;
} }
if (splitscreen > 2) if (splitscreen > 2)
{ {
SetPlayerSkin(fourthdisplayplayer, forcecharskin); SetPlayerSkin(displayplayers[3], forcecharskin);
if ((unsigned)cv_playercolor4.value != skins[players[fourthdisplayplayer].skin].prefcolor && !modeattacking) if ((unsigned)cv_playercolor4.value != skins[players[displayplayers[3]].skin].prefcolor && !modeattacking)
{ {
CV_StealthSetValue(&cv_playercolor4, skins[players[fourthdisplayplayer].skin].prefcolor); CV_StealthSetValue(&cv_playercolor4, skins[players[displayplayers[3]].skin].prefcolor);
players[fourthdisplayplayer].skincolor = skins[players[fourthdisplayplayer].skin].prefcolor; players[displayplayers[3]].skincolor = skins[players[displayplayers[3]].skin].prefcolor;
} }
} }
} }
@ -2725,7 +2729,7 @@ static boolean P_CanSave(void)
if ((cursaveslot < 0) // Playing without saving if ((cursaveslot < 0) // Playing without saving
|| (modifiedgame && !savemoddata) // Game is modified || (modifiedgame && !savemoddata) // Game is modified
|| (netgame || multiplayer) // Not in single-player || (netgame || multiplayer) // Not in single-player
|| (demoplayback || demorecording || metalrecording) // Currently in demo || (demo.playback || demo.recording || metalrecording) // Currently in demo
|| (players[consoleplayer].lives <= 0) // Completely dead || (players[consoleplayer].lives <= 0) // Completely dead
|| (modeattacking || ultimatemode || G_IsSpecialStage(gamemap))) // Specialized instances || (modeattacking || ultimatemode || G_IsSpecialStage(gamemap))) // Specialized instances
return false; return false;
@ -2789,7 +2793,8 @@ boolean P_SetupLevel(boolean skipprecip)
P_LevelInitStuff(); P_LevelInitStuff();
postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none; for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0' if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'
&& atoi(mapheaderinfo[gamemap-1]->forcecharacter) != 255) && atoi(mapheaderinfo[gamemap-1]->forcecharacter) != 255)
@ -2825,7 +2830,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Encore mode fade to pink to white // Encore mode fade to pink to white
// This is handled BEFORE sounds are stopped. // This is handled BEFORE sounds are stopped.
if (rendermode != render_none && encoremode && !prevencoremode) if (rendermode != render_none && encoremode && !prevencoremode && !demo.rewinding)
{ {
tic_t locstarttime, endtime, nowtime; tic_t locstarttime, endtime, nowtime;
@ -2877,7 +2882,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Let's fade to white here // Let's fade to white here
// But only if we didn't do the encore startup wipe // But only if we didn't do the encore startup wipe
if (rendermode != render_none && !ranspecialwipe) if (rendermode != render_none && !ranspecialwipe && !demo.rewinding)
{ {
F_WipeStartScreen(); F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
@ -3109,9 +3114,9 @@ boolean P_SetupLevel(boolean skipprecip)
} }
} }
if (modeattacking == ATTACKING_RECORD && !demoplayback) if (modeattacking == ATTACKING_RECORD && !demo.playback)
P_LoadRecordGhosts(); P_LoadRecordGhosts();
/*else if (modeattacking == ATTACKING_NIGHTS && !demoplayback) /*else if (modeattacking == ATTACKING_NIGHTS && !demo.playback)
P_LoadNightsGhosts();*/ P_LoadNightsGhosts();*/
if (G_TagGametype()) if (G_TagGametype())
@ -3159,25 +3164,25 @@ boolean P_SetupLevel(boolean skipprecip)
? cv_basenumlaps.value ? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps); : mapheaderinfo[gamemap - 1]->numlaps);
// Start recording replay in multiplayer with a temp filename
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
if (!demo.playback && multiplayer && !dedicated) {
static char buf[256];
sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap));
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
G_RecordDemo(buf);
}
// =========== // ===========
// landing point for netgames. // landing point for netgames.
netgameskip: netgameskip:
if (!dedicated) if (!dedicated)
{ {
P_SetupCamera(displayplayer, &camera); for (i = 0; i <= splitscreen; i++)
if (splitscreen) P_SetupCamera(displayplayers[i], &camera[i]);
{
P_SetupCamera(secondarydisplayplayer, &camera2);
if (splitscreen > 1)
{
P_SetupCamera(thirddisplayplayer, &camera3);
if (splitscreen > 2)
{
P_SetupCamera(fourthdisplayplayer, &camera4);
}
}
}
// Salt: CV_ClearChangedFlags() messes with your settings :( // Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_height.changed) /*if (!cv_cam_height.changed)
@ -3218,7 +3223,7 @@ boolean P_SetupLevel(boolean skipprecip)
/*if (rendermode != render_none) /*if (rendermode != render_none)
CV_Set(&cv_fov, cv_fov.defaultvalue);*/ CV_Set(&cv_fov, cv_fov.defaultvalue);*/
displayplayer = consoleplayer; // Start with your OWN view, please! displayplayers[0] = consoleplayer; // Start with your OWN view, please!
} }
/*if (cv_useranalog.value) /*if (cv_useranalog.value)
@ -3297,7 +3302,10 @@ boolean P_SetupLevel(boolean skipprecip)
savedata.lives = 0; savedata.lives = 0;
} }
skyVisible = skyVisible1 = skyVisible2 = skyVisible3 = skyVisible4 = true; // assume the skybox is visible on level load. // assume the skybox is visible on level load.
skyVisible = true;
memset(skyVisiblePerPlayer, true, sizeof(skyVisiblePerPlayer));
if (loadprecip) // uglier hack if (loadprecip) // uglier hack
{ // to make a newly loaded level start on the second frame. { // to make a newly loaded level start on the second frame.
INT32 buf = gametic % BACKUPTICS; INT32 buf = gametic % BACKUPTICS;

View file

@ -2243,7 +2243,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid! I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid!
if (mo && mo->player && botingame) if (mo && mo->player && botingame)
bot = players[secondarydisplayplayer].mo; bot = players[displayplayers[1]].mo;
// note: only commands with linedef types >= 400 && < 500 can be used // note: only commands with linedef types >= 400 && < 500 can be used
switch (line->special) switch (line->special)
@ -2381,35 +2381,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (mo->player) if (mo->player)
{ {
UINT8 i;
if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3 if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3
P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z); P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z);
if (splitscreen > 2 && mo->player == &players[fourthdisplayplayer] && camera4.chase)
for (i = 0; i <= splitscreen; i++)
{ {
camera4.x += x; if (mo->player == &players[displayplayers[i]] && camera[i].chase)
camera4.y += y; {
camera4.z += z; camera[i].x += x;
camera4.subsector = R_PointInSubsector(camera4.x, camera4.y); camera[i].y += y;
} camera[i].z += z;
else if (splitscreen > 1 && mo->player == &players[thirddisplayplayer] && camera3.chase) camera[i].subsector = R_PointInSubsector(camera[i].x, camera[i].y);
{ break;
camera3.x += x; }
camera3.y += y;
camera3.z += z;
camera3.subsector = R_PointInSubsector(camera3.x, camera3.y);
}
else if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase)
{
camera2.x += x;
camera2.y += y;
camera2.z += z;
camera2.subsector = R_PointInSubsector(camera2.x, camera2.y);
}
else if (camera.chase && mo->player == &players[displayplayer])
{
camera.x += x;
camera.y += y;
camera.z += z;
camera.subsector = R_PointInSubsector(camera.x, camera.y);
} }
} }
} }
@ -2515,8 +2501,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (line->flags & ML_NOCLIMB) if (line->flags & ML_NOCLIMB)
{ {
// play the sound from nowhere, but only if display player triggered it // play the sound from nowhere, but only if display player triggered it
if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer] if (mo && mo->player && P_IsDisplayPlayer(mo->player))
|| mo->player == &players[thirddisplayplayer] || mo->player == &players[fourthdisplayplayer]))
S_StartSound(NULL, sfxnum); S_StartSound(NULL, sfxnum);
} }
else if (line->flags & ML_EFFECT4) else if (line->flags & ML_EFFECT4)
@ -3834,16 +3819,16 @@ DoneSection2:
if (player->mo->scale > mapobjectscale) if (player->mo->scale > mapobjectscale)
linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale)); linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale));
if (!demoplayback || P_AnalogMove(player)) if (!demo.playback || P_AnalogMove(player))
{ {
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
} }
if (!(lines[i].flags & ML_EFFECT4)) if (!(lines[i].flags & ML_EFFECT4))
@ -7841,44 +7826,44 @@ void T_Pusher(pusher_t *p)
thing->player->pflags |= PF_SLIDING; thing->player->pflags |= PF_SLIDING;
thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR));
if (!demoplayback || P_AnalogMove(thing->player)) if (!demo.playback || P_AnalogMove(thing->player))
{ {
if (thing->player == &players[consoleplayer]) if (thing->player == &players[consoleplayer])
{ {
if (thing->angle - localangle > ANGLE_180) if (thing->angle - localangle[0] > ANGLE_180)
localangle -= (localangle - thing->angle) / 8; localangle[0] -= (localangle[0] - thing->angle) / 8;
else else
localangle += (thing->angle - localangle) / 8; localangle[0] += (thing->angle - localangle[0]) / 8;
} }
else if (thing->player == &players[secondarydisplayplayer]) else if (thing->player == &players[displayplayers[1]])
{ {
if (thing->angle - localangle2 > ANGLE_180) if (thing->angle - localangle[1] > ANGLE_180)
localangle2 -= (localangle2 - thing->angle) / 8; localangle[1] -= (localangle[1] - thing->angle) / 8;
else else
localangle2 += (thing->angle - localangle2) / 8; localangle[1] += (thing->angle - localangle[1]) / 8;
} }
else if (thing->player == &players[thirddisplayplayer]) else if (thing->player == &players[displayplayers[2]])
{ {
if (thing->angle - localangle3 > ANGLE_180) if (thing->angle - localangle[2] > ANGLE_180)
localangle3 -= (localangle3 - thing->angle) / 8; localangle[2] -= (localangle[2] - thing->angle) / 8;
else else
localangle3 += (thing->angle - localangle3) / 8; localangle[2] += (thing->angle - localangle[2]) / 8;
} }
else if (thing->player == &players[fourthdisplayplayer]) else if (thing->player == &players[displayplayers[3]])
{ {
if (thing->angle - localangle4 > ANGLE_180) if (thing->angle - localangle[3] > ANGLE_180)
localangle4 -= (localangle4 - thing->angle) / 8; localangle[3] -= (localangle[3] - thing->angle) / 8;
else else
localangle4 += (thing->angle - localangle4) / 8; localangle[3] += (thing->angle - localangle[3]) / 8;
} }
/*if (thing->player == &players[consoleplayer]) /*if (thing->player == &players[consoleplayer])
localangle = thing->angle; localangle[0] = thing->angle;
else if (thing->player == &players[secondarydisplayplayer]) else if (thing->player == &players[displayplayers[1]])
localangle2 = thing->angle; localangle[1] = thing->angle;
else if (thing->player == &players[thirddisplayplayer]) else if (thing->player == &players[displayplayers[2]])
localangle3 = thing->angle; localangle[2] = thing->angle;
else if (thing->player == &players[fourthdisplayplayer]) else if (thing->player == &players[displayplayers[3]])
localangle4 = thing->angle;*/ localangle[3] = thing->angle;*/
} }
} }

View file

@ -36,6 +36,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
INT32 flags2) INT32 flags2)
{ {
const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP; const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
UINT8 i;
// the move is ok, // the move is ok,
// so link the thing into its new position // so link the thing into its new position
@ -64,23 +65,25 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
// absolute angle position // absolute angle position
if (thing == players[consoleplayer].mo) if (thing == players[consoleplayer].mo)
localangle = angle; localangle[0] = angle;
if (thing == players[secondarydisplayplayer].mo) else if (splitscreen)
localangle2 = angle; {
if (thing == players[thirddisplayplayer].mo) for (i = 1; i <= splitscreen; i++)
localangle3 = angle; {
if (thing == players[fourthdisplayplayer].mo) if (thing == players[displayplayers[i]].mo)
localangle4 = angle; {
localangle[i] = angle;
break;
}
}
}
// move chasecam at new player location // move chasecam at new player location
if (splitscreen > 2 && camera4.chase && thing->player == &players[fourthdisplayplayer]) for (i = 0; i <= splitscreen; i++)
P_ResetCamera(thing->player, &camera4); {
else if (splitscreen > 1 && camera3.chase && thing->player == &players[thirddisplayplayer]) if (thing->player == &players[displayplayers[i]] && camera[i].chase)
P_ResetCamera(thing->player, &camera3); P_ResetCamera(thing->player, &camera[i]);
else if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer]) }
P_ResetCamera(thing->player, &camera2);
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
// don't run in place after a teleport // don't run in place after a teleport
thing->player->cmomx = thing->player->cmomy = 0; thing->player->cmomx = thing->player->cmomy = 0;
@ -123,6 +126,8 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
*/ */
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove) boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove)
{ {
UINT8 i;
if (!P_TeleportMove(thing, x, y, z)) if (!P_TeleportMove(thing, x, y, z))
return false; return false;
@ -144,24 +149,26 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
thing->reactiontime = TICRATE/2; // don't move for about half a second thing->reactiontime = TICRATE/2; // don't move for about half a second
// absolute angle position // absolute angle position
if (thing->player == &players[consoleplayer]) if (thing == players[consoleplayer].mo)
localangle = angle; localangle[0] = angle;
if (thing->player == &players[secondarydisplayplayer]) else if (splitscreen)
localangle2 = angle; {
if (thing->player == &players[thirddisplayplayer]) for (i = 1; i <= splitscreen; i++)
localangle3 = angle; {
if (thing->player == &players[fourthdisplayplayer]) if (thing == players[displayplayers[i]].mo)
localangle4 = angle; {
localangle[i] = angle;
break;
}
}
}
// move chasecam at new player location // move chasecam at new player location
if (splitscreen > 2 && camera4.chase && thing->player == &players[fourthdisplayplayer]) for (i = 0; i <= splitscreen; i++)
P_ResetCamera(thing->player, &camera4); {
else if (splitscreen > 1 && camera3.chase && thing->player == &players[thirddisplayplayer]) if (thing->player == &players[displayplayers[i]] && camera[i].chase)
P_ResetCamera(thing->player, &camera3); P_ResetCamera(thing->player, &camera[i]);
else if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer]) }
P_ResetCamera(thing->player, &camera2);
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
// don't run in place after a teleport // don't run in place after a teleport
if (!dontstopmove) if (!dontstopmove)

View file

@ -13,6 +13,7 @@
#include "doomstat.h" #include "doomstat.h"
#include "g_game.h" #include "g_game.h"
#include "g_input.h"
#include "p_local.h" #include "p_local.h"
#include "z_zone.h" #include "z_zone.h"
#include "s_sound.h" #include "s_sound.h"
@ -582,7 +583,7 @@ void P_Ticker(boolean run)
{ {
P_MapStart(); P_MapStart();
OP_ObjectplaceMovement(&players[0]); OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera, false); P_MoveChaseCamera(&players[0], &camera[0], false);
P_MapEnd(); P_MapEnd();
return; return;
} }
@ -590,18 +591,60 @@ void P_Ticker(boolean run)
// Check for pause or menu up in single player // Check for pause or menu up in single player
if (paused || P_AutoPause()) if (paused || P_AutoPause())
return; {
if (demo.rewinding && leveltime > 0)
{
leveltime = (leveltime-1) & ~3;
G_PreviewRewind(leveltime);
}
postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none; return;
}
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
P_MapStart(); P_MapStart();
if (run) if (run)
{ {
if (demorecording) if (demo.recording)
G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); {
if (demoplayback) G_WriteDemoExtraData();
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
G_WriteDemoTiccmd(&players[i].cmd, i);
}
if (demo.playback)
{
#ifdef DEMO_COMPAT_100
if (demo.version == 0x0001)
{
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
}
else
{
#endif
G_ReadDemoExtraData();
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
//@TODO all this throwdir stuff shouldn't be here! But it's added to maintain 1.0.4 compat for now...
// Remove for 1.1!
if (players[i].cmd.buttons & BT_FORWARD)
players[i].kartstuff[k_throwdir] = 1;
else if (players[i].cmd.buttons & BT_BACKWARD)
players[i].kartstuff[k_throwdir] = -1;
else
players[i].kartstuff[k_throwdir] = 0;
G_ReadDemoTiccmd(&players[i].cmd, i);
}
#ifdef DEMO_COMPAT_100
}
#endif
}
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
@ -609,7 +652,7 @@ void P_Ticker(boolean run)
} }
// Keep track of how long they've been playing! // Keep track of how long they've been playing!
if (!demoplayback) // Don't increment if a demo is playing. if (!demo.playback) // Don't increment if a demo is playing.
totalplaytime++; totalplaytime++;
/*if (!useNightsSS && G_IsSpecialStage(gamemap)) /*if (!useNightsSS && G_IsSpecialStage(gamemap))
@ -705,10 +748,25 @@ void P_Ticker(boolean run)
G_ReadMetalTic(metalplayback); G_ReadMetalTic(metalplayback);
if (metalrecording) if (metalrecording)
G_WriteMetalTic(players[consoleplayer].mo); G_WriteMetalTic(players[consoleplayer].mo);
if (demorecording)
G_WriteGhostTic(players[consoleplayer].mo); if (demo.recording)
if (demoplayback) // Use Ghost data for consistency checks. {
G_ConsGhostTic(); G_WriteAllGhostTics();
if (cv_recordmultiplayerdemos.value && (demo.savemode == DSM_NOTSAVING || demo.savemode == DSM_WILLAUTOSAVE))
if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1))
demo.savemode = DSM_TITLEENTRY;
}
else if (demo.playback) // Use Ghost data for consistency checks.
{
#ifdef DEMO_COMPAT_100
if (demo.version == 0x0001)
G_ConsGhostTic(0);
else
#endif
G_ConsAllGhostTics();
}
if (modeattacking) if (modeattacking)
G_GhostTicker(); G_GhostTicker();
@ -719,17 +777,17 @@ void P_Ticker(boolean run)
} }
// Always move the camera. // Always move the camera.
if (camera.chase) for (i = 0; i <= splitscreen; i++)
P_MoveChaseCamera(&players[displayplayer], &camera, false); {
if (splitscreen && camera2.chase) if (camera[i].chase)
P_MoveChaseCamera(&players[secondarydisplayplayer], &camera2, false); P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
if (splitscreen > 1 && camera3.chase) }
P_MoveChaseCamera(&players[thirddisplayplayer], &camera3, false);
if (splitscreen > 2 && camera4.chase)
P_MoveChaseCamera(&players[fourthdisplayplayer], &camera4, false);
P_MapEnd(); P_MapEnd();
if (demo.playback)
G_StoreRewindInfo();
// Z_CheckMemCleanup(); // Z_CheckMemCleanup();
} }
@ -739,7 +797,8 @@ void P_PreTicker(INT32 frames)
INT32 i,framecnt; INT32 i,framecnt;
ticcmd_t temptic; ticcmd_t temptic;
postimgtype = postimgtype2 = postimgtype3 = postimgtype4 = postimg_none; for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
for (framecnt = 0; framecnt < frames; ++framecnt) for (framecnt = 0; framecnt < frames; ++framecnt)
{ {

View file

@ -169,10 +169,10 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move)
boolean P_AutoPause(void) boolean P_AutoPause(void)
{ {
// Don't pause even on menu-up or focus-lost in netgames or record attack // Don't pause even on menu-up or focus-lost in netgames or record attack
if (netgame || modeattacking) if (netgame || modeattacking || demo.title)
return false; return false;
return (menuactive || ( window_notinfocus && cv_pauseifunfocused.value )); return ((menuactive && !demo.playback) || ( window_notinfocus && cv_pauseifunfocused.value ));
} }
// //
@ -654,13 +654,13 @@ static void P_DeNightserizePlayer(player_t *player)
// Restore aiming angle // Restore aiming angle
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localaiming = 0; localaiming[0] = 0;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localaiming2 = 0; localaiming[1] = 0;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localaiming3 = 0; localaiming[2] = 0;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localaiming4 = 0; localaiming[3] = 0;
if (player->mo->tracer) if (player->mo->tracer)
P_RemoveMobj(player->mo->tracer); P_RemoveMobj(player->mo->tracer);
@ -1147,29 +1147,32 @@ boolean P_EndingMusic(player_t *player)
if (!P_IsLocalPlayer(player)) // Only applies to a local player if (!P_IsLocalPlayer(player)) // Only applies to a local player
return false; return false;
if (multiplayer && demo.playback) // Don't play this in multiplayer replays
return false;
// Event - Level Finish // Event - Level Finish
// Check for if this is valid or not // Check for if this is valid or not
if (splitscreen) if (splitscreen)
{ {
if (!((players[displayplayer].exiting || (players[displayplayer].pflags & PF_TIMEOVER)) if (!((players[displayplayers[0]].exiting || (players[displayplayers[0]].pflags & PF_TIMEOVER))
|| (players[secondarydisplayplayer].exiting || (players[secondarydisplayplayer].pflags & PF_TIMEOVER)) || (players[displayplayers[1]].exiting || (players[displayplayers[1]].pflags & PF_TIMEOVER))
|| ((splitscreen < 2) && (players[thirddisplayplayer].exiting || (players[thirddisplayplayer].pflags & PF_TIMEOVER))) || ((splitscreen < 2) && (players[displayplayers[2]].exiting || (players[displayplayers[2]].pflags & PF_TIMEOVER)))
|| ((splitscreen < 3) && (players[fourthdisplayplayer].exiting || (players[fourthdisplayplayer].pflags & PF_TIMEOVER))))) || ((splitscreen < 3) && (players[displayplayers[3]].exiting || (players[displayplayers[3]].pflags & PF_TIMEOVER)))))
return false; return false;
bestlocalplayer = &players[displayplayer]; bestlocalplayer = &players[displayplayers[0]];
bestlocalpos = ((players[displayplayer].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayer].kartstuff[k_position]); bestlocalpos = ((players[displayplayers[0]].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayers[0]].kartstuff[k_position]);
#define setbests(p) \ #define setbests(p) \
if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \ if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \
{ \ { \
bestlocalplayer = &players[p]; \ bestlocalplayer = &players[p]; \
bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \ bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \
} }
setbests(secondarydisplayplayer); setbests(displayplayers[1]);
if (splitscreen > 1) if (splitscreen > 1)
setbests(thirddisplayplayer); setbests(displayplayers[2]);
if (splitscreen > 2) if (splitscreen > 2)
setbests(fourthdisplayplayer); setbests(displayplayers[3]);
#undef setbests #undef setbests
} }
else else
@ -1250,12 +1253,12 @@ void P_RestoreMusic(player_t *player)
else if (players[p].kartstuff[k_invincibilitytimer] > bestlocaltimer) \ else if (players[p].kartstuff[k_invincibilitytimer] > bestlocaltimer) \
{ wantedmus = 1; bestlocaltimer = players[p].kartstuff[k_invincibilitytimer]; } \ { wantedmus = 1; bestlocaltimer = players[p].kartstuff[k_invincibilitytimer]; } \
} }
setbests(displayplayer); setbests(displayplayers[0]);
setbests(secondarydisplayplayer); setbests(displayplayers[1]);
if (splitscreen > 1) if (splitscreen > 1)
setbests(thirddisplayplayer); setbests(displayplayers[2]);
if (splitscreen > 2) if (splitscreen > 2)
setbests(fourthdisplayplayer); setbests(displayplayers[3]);
#undef setbests #undef setbests
} }
else else
@ -1513,10 +1516,39 @@ fixed_t P_GetPlayerSpinHeight(player_t *player)
// //
boolean P_IsLocalPlayer(player_t *player) boolean P_IsLocalPlayer(player_t *player)
{ {
return ((splitscreen > 2 && player == &players[fourthdisplayplayer]) UINT8 i;
|| (splitscreen > 1 && player == &players[thirddisplayplayer])
|| (splitscreen && player == &players[secondarydisplayplayer]) if (player == &players[consoleplayer])
|| player == &players[consoleplayer]); return true;
else if (splitscreen)
{
for (i = 1; i <= splitscreen; i++) // Skip P1
{
if (player == &players[displayplayers[i]])
return true;
}
}
return false;
}
//
// P_IsDisplayPlayer
//
// Returns true if player is
// currently being watched.
//
boolean P_IsDisplayPlayer(player_t *player)
{
UINT8 i;
for (i = 0; i <= splitscreen; i++) // DON'T skip P1
{
if (player == &players[displayplayers[i]])
return true;
}
return false;
} }
// //
@ -1662,11 +1694,7 @@ void P_DoPlayerExit(player_t *player)
if (player->exiting || mapreset) if (player->exiting || mapreset)
return; return;
if ((player == &players[consoleplayer] if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback))
|| (splitscreen && player == &players[secondarydisplayplayer])
|| (splitscreen > 1 && player == &players[thirddisplayplayer])
|| (splitscreen > 2 && player == &players[fourthdisplayplayer]))
&& (!player->spectator && !demoplayback))
legitimateexit = true; legitimateexit = true;
if (G_RaceGametype()) // If in Race Mode, allow if (G_RaceGametype()) // If in Race Mode, allow
@ -1725,6 +1753,9 @@ void P_DoPlayerExit(player_t *player)
player->powers[pw_spacetime] = 0; player->powers[pw_spacetime] = 0;
player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation
if (player == &players[consoleplayer])
demo.savebutton = leveltime;
/*if (playeringame[player-players] && netgame && !circuitmap) /*if (playeringame[player-players] && netgame && !circuitmap)
CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/ CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/
} }
@ -2306,12 +2337,12 @@ static void P_CheckInvincibilityTimer(player_t *player)
//if (player->powers[pw_shield] & SH_FIREFLOWER) //if (player->powers[pw_shield] & SH_FIREFLOWER)
//{ //{
// player->mo->color = SKINCOLOR_WHITE; // player->mo->color = SKINCOLOR_WHITE;
// G_GhostAddColor(GHC_FIREFLOWER); // G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER);
//} //}
//else //else
{ {
player->mo->color = player->skincolor; player->mo->color = player->skincolor;
G_GhostAddColor(GHC_NORMAL); G_GhostAddColor((INT32) (player - players), GHC_NORMAL);
} }
} }
@ -2402,8 +2433,7 @@ static void P_DoPlayerHeadSigns(player_t *player)
// If you're "IT", show a big "IT" over your head for others to see. // If you're "IT", show a big "IT" over your head for others to see.
if (player->pflags & PF_TAGIT) if (player->pflags & PF_TAGIT)
{ {
if (!(player == &players[consoleplayer] || player == &players[displayplayer] || player == &players[secondarydisplayplayer] if (!P_IsDisplayPlayer(player)) // Don't display it on your own view.
|| player == &players[thirddisplayplayer] || player == &players[fourthdisplayplayer])) // Don't display it on your own view.
{ {
if (!(player->mo->eflags & MFE_VERTICALFLIP)) if (!(player->mo->eflags & MFE_VERTICALFLIP))
P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height, MT_TAG); P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height, MT_TAG);
@ -2891,13 +2921,13 @@ static void P_DoClimbing(player_t *player) // SRB2kart - unused
} }
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
if (player->climbing == 0) if (player->climbing == 0)
P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
@ -3576,8 +3606,8 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd) // SRB2kart - unused.
// Now spawn the color thok circle. // Now spawn the color thok circle.
P_SpawnSpinMobj(player, player->revitem); P_SpawnSpinMobj(player, player->revitem);
if (demorecording) if (demo.recording)
G_GhostAddRev(); G_GhostAddRev((INT32) (player - players));
} }
} }
// If not moving up or down, and travelling faster than a speed of four while not holding // If not moving up or down, and travelling faster than a speed of four while not holding
@ -3735,14 +3765,14 @@ boolean P_AnalogMove(player_t *player)
fixed_t tempx = 0, tempy = 0; fixed_t tempx = 0, tempy = 0;
angle_t tempangle, origtempangle; angle_t tempangle, origtempangle;
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) if (splitscreen > 2 && player == &players[displayplayers[3]])
thiscam = &camera4; thiscam = &camera[3];
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) else if (splitscreen > 1 && player == &players[displayplayers[2]])
thiscam = &camera3; thiscam = &camera[2];
else if (splitscreen && player == &players[secondarydisplayplayer]) else if (splitscreen && player == &players[displayplayers[1]])
thiscam = &camera2; thiscam = &camera[1];
else else
thiscam = &camera; thiscam = &camera[0];
if (!cmd->forwardmove && !cmd->sidemove) if (!cmd->forwardmove && !cmd->sidemove)
return 0; return 0;
@ -3883,13 +3913,13 @@ static void P_2dMovement(player_t *player)
} }
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
if (player->pflags & PF_GLIDING) if (player->pflags & PF_GLIDING)
movepushangle = player->mo->angle; movepushangle = player->mo->angle;
@ -5419,13 +5449,13 @@ static void P_NiGHTSMovement(player_t *player)
P_SetMobjStateNF(player->mo->tracer, leveltime & 1 ? flystate : flystate+1); P_SetMobjStateNF(player->mo->tracer, leveltime & 1 ? flystate : flystate+1);
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
if (still) if (still)
{ {
@ -5452,13 +5482,13 @@ static void P_NiGHTSMovement(player_t *player)
movingangle = InvAngle(movingangle); movingangle = InvAngle(movingangle);
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localaiming = movingangle; localaiming[0] = movingangle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localaiming2 = movingangle; localaiming[1] = movingangle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localaiming3 = movingangle; localaiming[2] = movingangle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localaiming4 = movingangle; localaiming[3] = movingangle;
player->mo->tracer->angle = player->mo->angle; player->mo->tracer->angle = player->mo->angle;
@ -5722,7 +5752,7 @@ static void P_MovePlayer(player_t *player)
{ {
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
if (player == &players[displayplayer]) // only play the sound for yourself landing if (player == &players[displayplayers[0]]) // only play the sound for yourself landing
S_StartSound(NULL, sfx_s3k6a); S_StartSound(NULL, sfx_s3k6a);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]) if (playeringame[i])
@ -6130,8 +6160,8 @@ static void P_MovePlayer(player_t *player)
if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED)) if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED))
{ {
P_SpawnSpinMobj(player, player->spinitem); P_SpawnSpinMobj(player, player->spinitem);
if (demorecording) if (demo.recording)
G_GhostAddSpin(); G_GhostAddSpin((INT32) (player - players));
} }
*/ */
@ -6228,13 +6258,13 @@ static void P_MovePlayer(player_t *player)
// Update the local angle control. // Update the local angle control.
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
} }
#endif #endif
@ -6556,13 +6586,13 @@ static void P_DoZoomTube(player_t *player)
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y);
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
} }
#if 0 #if 0
if (player->mo->state != &states[S_KART_SPIN]) if (player->mo->state != &states[S_KART_SPIN])
@ -6952,13 +6982,13 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
if (source->player) if (source->player)
{ {
if (source->player == &players[consoleplayer]) if (source->player == &players[consoleplayer])
localangle = source->angle; localangle[0] = source->angle;
else if (source->player == &players[secondarydisplayplayer]) else if (source->player == &players[displayplayers[1]])
localangle2 = source->angle; localangle[1] = source->angle;
else if (source->player == &players[thirddisplayplayer]) else if (source->player == &players[displayplayers[2]])
localangle3 = source->angle; localangle[2] = source->angle;
else if (source->player == &players[fourthdisplayplayer]) else if (source->player == &players[displayplayers[3]])
localangle4 = source->angle; localangle[3] = source->angle;
} }
// change slope // change slope
@ -7091,7 +7121,7 @@ notrealplayer:
// P_MoveCamera: make sure the camera is not outside the world and looks at the player avatar // P_MoveCamera: make sure the camera is not outside the world and looks at the player avatar
// //
camera_t camera, camera2, camera3, camera4; // Four cameras, three for splitscreen camera_t camera[MAXSPLITSCREENPLAYERS]; // Four cameras, three for splitscreen
static void CV_CamRotate_OnChange(void) static void CV_CamRotate_OnChange(void)
{ {
@ -7196,10 +7226,10 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
thiscam->y = y; thiscam->y = y;
thiscam->z = z; thiscam->z = z;
if (!(thiscam == &camera && (cv_cam_still.value || cv_analog.value)) if (!(thiscam == &camera[0] && (cv_cam_still.value || cv_analog.value))
&& !(thiscam == &camera2 && (cv_cam2_still.value || cv_analog2.value)) && !(thiscam == &camera[1] && (cv_cam2_still.value || cv_analog2.value))
&& !(thiscam == &camera3 && (cv_cam3_still.value || cv_analog3.value)) && !(thiscam == &camera[2] && (cv_cam3_still.value || cv_analog3.value))
&& !(thiscam == &camera4 && (cv_cam4_still.value || cv_analog4.value))) && !(thiscam == &camera[3] && (cv_cam4_still.value || cv_analog4.value)))
{ {
thiscam->angle = player->mo->angle; thiscam->angle = player->mo->angle;
thiscam->aiming = 0; thiscam->aiming = 0;
@ -7257,46 +7287,49 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (player->spectator) // force cam off for spectators if (player->spectator) // force cam off for spectators
return true; return true;
if (!cv_chasecam.value && thiscam == &camera) if (!cv_chasecam.value && thiscam == &camera[0])
return true; return true;
if (!cv_chasecam2.value && thiscam == &camera2) if (!cv_chasecam2.value && thiscam == &camera[1])
return true; return true;
if (!cv_chasecam3.value && thiscam == &camera3) if (!cv_chasecam3.value && thiscam == &camera[2])
return true; return true;
if (!cv_chasecam4.value && thiscam == &camera4) if (!cv_chasecam4.value && thiscam == &camera[3])
return true; return true;
} }
if (!thiscam->chase && !resetcalled) if (!thiscam->chase && !resetcalled)
{ {
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
focusangle = localangle; focusangle = localangle[0];
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
focusangle = localangle2; focusangle = localangle[1];
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
focusangle = localangle3; focusangle = localangle[2];
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
focusangle = localangle4; focusangle = localangle[3];
else else
focusangle = mo->angle; focusangle = mo->angle;
if (thiscam == &camera)
if (thiscam == &camera[0])
camrotate = cv_cam_rotate.value; camrotate = cv_cam_rotate.value;
else if (thiscam == &camera2) else if (thiscam == &camera[1])
camrotate = cv_cam2_rotate.value; camrotate = cv_cam2_rotate.value;
else if (thiscam == &camera3) else if (thiscam == &camera[2])
camrotate = cv_cam3_rotate.value; camrotate = cv_cam3_rotate.value;
else if (thiscam == &camera4) else if (thiscam == &camera[3])
camrotate = cv_cam4_rotate.value; camrotate = cv_cam4_rotate.value;
else else
camrotate = 0; camrotate = 0;
if (leveltime < introtime) // Whoooshy camera! if (leveltime < introtime) // Whoooshy camera!
{ {
const INT32 introcam = (introtime - leveltime); const INT32 introcam = (introtime - leveltime);
camrotate += introcam*5; camrotate += introcam*5;
} }
thiscam->angle = focusangle + FixedAngle(camrotate*FRACUNIT); thiscam->angle = focusangle + FixedAngle(camrotate*FRACUNIT);
P_ResetCamera(player, thiscam); P_ResetCamera(player, thiscam);
return true; return true;
@ -7310,30 +7343,30 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// if (leveltime > 0 && timeinmap <= 0) // if (leveltime > 0 && timeinmap <= 0)
// return true; // return true;
if (demoplayback) if (demo.playback)
{ {
focusangle = mo->angle; focusangle = mo->angle;
focusaiming = 0; focusaiming = 0;
} }
else if (player == &players[consoleplayer]) else if (player == &players[consoleplayer])
{ {
focusangle = localangle; focusangle = localangle[0];
focusaiming = localaiming; focusaiming = localaiming[0];
} }
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
{ {
focusangle = localangle2; focusangle = localangle[1];
focusaiming = localaiming2; focusaiming = localaiming[1];
} }
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
{ {
focusangle = localangle3; focusangle = localangle[2];
focusaiming = localaiming3; focusaiming = localaiming[2];
} }
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
{ {
focusangle = localangle4; focusangle = localangle[3];
focusaiming = localaiming4; focusaiming = localaiming[3];
} }
else else
{ {
@ -7344,17 +7377,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (P_CameraThinker(player, thiscam, resetcalled)) if (P_CameraThinker(player, thiscam, resetcalled))
return true; return true;
if (thiscam == &camera)
{ if (thiscam == &camera[1]) // Camera 2
num = 0;
camspeed = cv_cam_speed.value;
camstill = cv_cam_still.value;
camrotate = cv_cam_rotate.value;
camdist = FixedMul(cv_cam_dist.value, mapobjectscale);
camheight = FixedMul(cv_cam_height.value, mapobjectscale);
lookback = camspin;
}
else if (thiscam == &camera2) // Camera 2
{ {
num = 1; num = 1;
camspeed = cv_cam2_speed.value; camspeed = cv_cam2_speed.value;
@ -7362,9 +7386,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camrotate = cv_cam2_rotate.value; camrotate = cv_cam2_rotate.value;
camdist = FixedMul(cv_cam2_dist.value, mapobjectscale); camdist = FixedMul(cv_cam2_dist.value, mapobjectscale);
camheight = FixedMul(cv_cam2_height.value, mapobjectscale); camheight = FixedMul(cv_cam2_height.value, mapobjectscale);
lookback = camspin2; lookback = camspin[1];
} }
else if (thiscam == &camera3) // Camera 3 else if (thiscam == &camera[2]) // Camera 3
{ {
num = 2; num = 2;
camspeed = cv_cam3_speed.value; camspeed = cv_cam3_speed.value;
@ -7372,9 +7396,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camrotate = cv_cam3_rotate.value; camrotate = cv_cam3_rotate.value;
camdist = FixedMul(cv_cam3_dist.value, mapobjectscale); camdist = FixedMul(cv_cam3_dist.value, mapobjectscale);
camheight = FixedMul(cv_cam3_height.value, mapobjectscale); camheight = FixedMul(cv_cam3_height.value, mapobjectscale);
lookback = camspin3; lookback = camspin[2];
} }
else // Camera 4 else if (thiscam == &camera[3]) // Camera 4
{ {
num = 3; num = 3;
camspeed = cv_cam4_speed.value; camspeed = cv_cam4_speed.value;
@ -7382,7 +7406,17 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camrotate = cv_cam4_rotate.value; camrotate = cv_cam4_rotate.value;
camdist = FixedMul(cv_cam4_dist.value, mapobjectscale); camdist = FixedMul(cv_cam4_dist.value, mapobjectscale);
camheight = FixedMul(cv_cam4_height.value, mapobjectscale); camheight = FixedMul(cv_cam4_height.value, mapobjectscale);
lookback = camspin4; lookback = camspin[3];
}
else // Camera 1
{
num = 0;
camspeed = cv_cam_speed.value;
camstill = cv_cam_still.value;
camrotate = cv_cam_rotate.value;
camdist = FixedMul(cv_cam_dist.value, mapobjectscale);
camheight = FixedMul(cv_cam_height.value, mapobjectscale);
lookback = camspin[0];
} }
if (timeover) if (timeover)
@ -7443,10 +7477,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
} }
if (!resetcalled && (leveltime > starttime && timeover != 2) if (!resetcalled && (leveltime > starttime && timeover != 2)
&& ((thiscam == &camera && t_cam_rotate != -42) && ((thiscam == &camera[0] && t_cam_rotate != -42)
|| (thiscam == &camera2 && t_cam2_rotate != -42) || (thiscam == &camera[1] && t_cam2_rotate != -42)
|| (thiscam == &camera3 && t_cam3_rotate != -42) || (thiscam == &camera[2] && t_cam3_rotate != -42)
|| (thiscam == &camera4 && t_cam4_rotate != -42))) || (thiscam == &camera[3] && t_cam4_rotate != -42)))
{ {
angle = FixedAngle(camrotate*FRACUNIT); angle = FixedAngle(camrotate*FRACUNIT);
thiscam->angle = angle; thiscam->angle = angle;
@ -7841,8 +7875,8 @@ boolean P_SpectatorJoinGame(player_t *player)
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
//Reset away view //Reset away view
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer)
displayplayer = consoleplayer; displayplayers[0] = consoleplayer;
if (changeto == 1) if (changeto == 1)
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80'); CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80');
@ -7865,8 +7899,8 @@ boolean P_SpectatorJoinGame(player_t *player)
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
//Reset away view //Reset away view
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer)
displayplayer = consoleplayer; displayplayers[0] = consoleplayer;
HU_AddChatText(va(M_GetText("\x82*%s entered the game."), player_names[player-players]), false); HU_AddChatText(va(M_GetText("\x82*%s entered the game."), player_names[player-players]), false);
return true; // no more player->mo, cannot continue. return true; // no more player->mo, cannot continue.
@ -7877,9 +7911,10 @@ boolean P_SpectatorJoinGame(player_t *player)
static void P_CalcPostImg(player_t *player) static void P_CalcPostImg(player_t *player)
{ {
sector_t *sector = player->mo->subsector->sector; sector_t *sector = player->mo->subsector->sector;
postimg_t *type; postimg_t *type = postimg_none;
INT32 *param; INT32 *param;
fixed_t pviewheight; fixed_t pviewheight;
UINT8 i;
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight; pviewheight = player->mo->z + player->mo->height - player->viewheight;
@ -7892,25 +7927,14 @@ static void P_CalcPostImg(player_t *player)
pviewheight = player->awayviewmobj->z + 20*FRACUNIT; pviewheight = player->awayviewmobj->z + 20*FRACUNIT;
} }
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) for (i = 0; i <= splitscreen; i++)
{ {
type = &postimgtype4; if (player == &players[displayplayers[i]])
param = &postimgparam4; {
} type = &postimgtype[i];
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) param = &postimgparam[i];
{ break;
type = &postimgtype3; }
param = &postimgparam3;
}
else if (splitscreen && player == &players[secondarydisplayplayer])
{
type = &postimgtype2;
param = &postimgparam2;
}
else
{
type = &postimgtype;
param = &postimgparam;
} }
// see if we are in heat (no, not THAT kind of heat...) // see if we are in heat (no, not THAT kind of heat...)
@ -8018,11 +8042,7 @@ void P_DoTimeOver(player_t *player)
player->pflags |= PF_TIMEOVER; player->pflags |= PF_TIMEOVER;
if ((player == &players[consoleplayer] if (P_IsLocalPlayer(player) && !demo.playback)
|| (splitscreen && player == &players[secondarydisplayplayer])
|| (splitscreen > 1 && player == &players[thirddisplayplayer])
|| (splitscreen > 2 && player == &players[fourthdisplayplayer]))
&& !demoplayback)
legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p
if (player->mo) if (player->mo)
@ -8069,7 +8089,7 @@ void P_PlayerThink(player_t *player)
} }
#ifdef SEENAMES #ifdef SEENAMES
if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)) && !splitscreen) if (netgame && player == &players[displayplayers[0]] && !(leveltime % (TICRATE/5)) && !splitscreen)
{ {
seenplayer = NULL; seenplayer = NULL;
@ -8131,6 +8151,19 @@ void P_PlayerThink(player_t *player)
cmd = &player->cmd; cmd = &player->cmd;
//@TODO This fixes a one-tic latency on direction handling, AND makes behavior consistent while paused, but is not BC with 1.0.4. Do this for 1.1!
#if 0
// SRB2kart
// Save the dir the player is holding
// to allow items to be thrown forward or backward.
if (cmd->buttons & BT_FORWARD)
player->kartstuff[k_throwdir] = 1;
else if (cmd->buttons & BT_BACKWARD)
player->kartstuff[k_throwdir] = -1;
else
player->kartstuff[k_throwdir] = 0;
#endif
// Add some extra randomization. // Add some extra randomization.
if (cmd->forwardmove) if (cmd->forwardmove)
P_RandomFixed(); P_RandomFixed();
@ -8403,7 +8436,9 @@ void P_PlayerThink(player_t *player)
|| player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart || player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart
&& (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale))
{ {
UINT8 i;
mobj_t *gmobj = P_SpawnGhostMobj(player->mo); mobj_t *gmobj = P_SpawnGhostMobj(player->mo);
gmobj->fuse = 2; gmobj->fuse = 2;
if (leveltime & 1) if (leveltime & 1)
{ {
@ -8411,15 +8446,17 @@ void P_PlayerThink(player_t *player)
gmobj->frame |= tr_trans70<<FF_TRANSSHIFT; gmobj->frame |= tr_trans70<<FF_TRANSSHIFT;
} }
// Hide the mobj from our sights if we're the displayplayer and chasecam is off, // Hide the mobj from our sights if we're the displayplayer and chasecam is off.
// or secondarydisplayplayer and chasecam2 is off.
// Why not just not spawn the mobj? Well, I'd rather only flirt with // Why not just not spawn the mobj? Well, I'd rather only flirt with
// consistency so much... // consistency so much...
if ((player == &players[displayplayer] && !camera.chase) for (i = 0; i <= splitscreen; i++)
|| (splitscreen && player == &players[secondarydisplayplayer] && !camera2.chase) {
|| (splitscreen > 1 && player == &players[thirddisplayplayer] && !camera3.chase) if (player == &players[displayplayers[i]] && !camera[i].chase)
|| (splitscreen > 2 && player == &players[fourthdisplayplayer] && !camera4.chase)) {
gmobj->flags2 |= MF2_DONTDRAW; gmobj->flags2 |= MF2_DONTDRAW;
break;
}
}
} }
#endif #endif
@ -8619,6 +8656,7 @@ void P_PlayerAfterThink(player_t *player)
ticcmd_t *cmd; ticcmd_t *cmd;
//INT32 oldweapon = player->currentweapon; // SRB2kart - unused //INT32 oldweapon = player->currentweapon; // SRB2kart - unused
camera_t *thiscam = NULL; // if not one of the displayed players, just don't bother camera_t *thiscam = NULL; // if not one of the displayed players, just don't bother
UINT8 i;
#ifdef PARANOIA #ifdef PARANOIA
if (!player->mo) if (!player->mo)
@ -8641,14 +8679,14 @@ void P_PlayerAfterThink(player_t *player)
P_PlayerInSpecialSector(player); P_PlayerInSpecialSector(player);
#endif #endif
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) for (i = 0; i <= splitscreen; i++)
thiscam = &camera4; {
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) if (player == &players[displayplayers[i]])
thiscam = &camera3; {
else if (splitscreen && player == &players[secondarydisplayplayer]) thiscam = &camera[i];
thiscam = &camera2; break;
else if (player == &players[displayplayer]) }
thiscam = &camera; }
if (player->playerstate == PST_DEAD) if (player->playerstate == PST_DEAD)
{ {
@ -8833,13 +8871,13 @@ void P_PlayerAfterThink(player_t *player)
player->mo->angle = player->mo->tracer->angle; player->mo->angle = player->mo->tracer->angle;
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle[0] = player->mo->angle;
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
} }
if (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius) if (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius)
@ -8907,13 +8945,13 @@ void P_PlayerAfterThink(player_t *player)
player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; // Adjust the local control angle. localangle[0] = player->mo->angle; // Adjust the local control angle.
else if (player == &players[secondarydisplayplayer]) else if (player == &players[displayplayers[1]])
localangle2 = player->mo->angle; localangle[1] = player->mo->angle;
else if (player == &players[thirddisplayplayer]) else if (player == &players[displayplayers[2]])
localangle3 = player->mo->angle; localangle[2] = player->mo->angle;
else if (player == &players[fourthdisplayplayer]) else if (player == &players[displayplayers[3]])
localangle4 = player->mo->angle; localangle[3] = player->mo->angle;
} }
} }

View file

@ -252,20 +252,23 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
mobj_t *viewmobj = viewplayer->mo; mobj_t *viewmobj = viewplayer->mo;
INT32 heightsec; INT32 heightsec;
boolean underwater; boolean underwater;
UINT8 i;
if (splitscreen > 2 && viewplayer == &players[fourthdisplayplayer] && camera4.chase) for (i = 0; i <= splitscreen; i++)
heightsec = R_PointInSubsector(camera4.x, camera4.y)->sector->heightsec; {
else if (splitscreen > 1 && viewplayer == &players[thirddisplayplayer] && camera3.chase) if (viewplayer == &players[displayplayers[i]] && camera[i].chase)
heightsec = R_PointInSubsector(camera3.x, camera3.y)->sector->heightsec; {
else if (splitscreen && viewplayer == &players[secondarydisplayplayer] && camera2.chase) heightsec = R_PointInSubsector(camera[i].x, camera[i].y)->sector->heightsec;
heightsec = R_PointInSubsector(camera2.x, camera2.y)->sector->heightsec; break;
else if (camera.chase && viewplayer == &players[displayplayer]) }
heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec; }
else if (viewmobj)
if (i > splitscreen && viewmobj)
heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec; heightsec = R_PointInSubsector(viewmobj->x, viewmobj->y)->sector->heightsec;
else else
return sec; return sec;
underwater = heightsec != -1 && viewz <= sectors[heightsec].floorheight;
underwater = (heightsec != -1 && viewz <= sectors[heightsec].floorheight);
// Replace sector being drawn, with a copy to be hacked // Replace sector being drawn, with a copy to be hacked
*tempsec = *sec; *tempsec = *sec;
@ -827,7 +830,7 @@ static void R_AddPolyObjects(subsector_t *sub)
drawseg_t *firstseg; drawseg_t *firstseg;
static void R_Subsector(size_t num, UINT8 viewnumber) static void R_Subsector(size_t num)
{ {
INT32 count, floorlightlevel, ceilinglightlevel, light; INT32 count, floorlightlevel, ceilinglightlevel, light;
seg_t *line; seg_t *line;
@ -1149,7 +1152,7 @@ static void R_Subsector(size_t num, UINT8 viewnumber)
// Either you must pass the fake sector and handle validcount here, on the // Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way, // real sector, or you must account for the lighting in some other way,
// like passing it as an argument. // like passing it as an argument.
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2, viewnumber); R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2);
firstseg = NULL; firstseg = NULL;
@ -1355,7 +1358,7 @@ INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside)
// //
// killough 5/2/98: reformatted, removed tail recursion // killough 5/2/98: reformatted, removed tail recursion
void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber) void R_RenderBSPNode(INT32 bspnum)
{ {
node_t *bsp; node_t *bsp;
INT32 side; INT32 side;
@ -1366,7 +1369,7 @@ void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber)
// Decide which side the view point is on. // Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp); side = R_PointOnSide(viewx, viewy, bsp);
// Recursively divide front space. // Recursively divide front space.
R_RenderBSPNode(bsp->children[side], viewnumber); R_RenderBSPNode(bsp->children[side]);
// Possibly divide back space. // Possibly divide back space.
@ -1384,5 +1387,5 @@ void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber)
portalcullsector = NULL; portalcullsector = NULL;
} }
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR, viewnumber); R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
} }

View file

@ -37,7 +37,7 @@ extern INT32 doorclosed;
void R_ClearClipSegs(void); void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end); void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void); void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum, UINT8 viewnumber); void R_RenderBSPNode(INT32 bspnum);
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2); void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2);
#ifdef POLYOBJECTS #ifdef POLYOBJECTS

View file

@ -1600,7 +1600,7 @@ void R_PrecacheLevel(void)
thinker_t *th; thinker_t *th;
spriteframe_t *sf; spriteframe_t *sf;
if (demoplayback) if (demo.playback)
return; return;
// do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap() // do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap()

View file

@ -30,6 +30,7 @@
#include "p_spec.h" // skyboxmo #include "p_spec.h" // skyboxmo
#include "z_zone.h" #include "z_zone.h"
#include "m_random.h" // quake camera shake #include "m_random.h" // quake camera shake
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
@ -65,9 +66,10 @@ size_t loopcount;
fixed_t viewx, viewy, viewz; fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle; angle_t viewangle, aimingangle;
UINT8 viewssnum;
fixed_t viewcos, viewsin; fixed_t viewcos, viewsin;
boolean viewsky, skyVisible; boolean viewsky, skyVisible;
boolean skyVisible1, skyVisible2, skyVisible3, skyVisible4; // saved values of skyVisible for P1/P2/P3/P4, for splitscreen boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player
sector_t *viewsector; sector_t *viewsector;
player_t *viewplayer; player_t *viewplayer;
@ -193,19 +195,12 @@ void SplitScreen_OnChange(void)
// recompute screen size // recompute screen size
R_ExecuteSetViewSize(); R_ExecuteSetViewSize();
if (!demoplayback && !botingame) if (!demo.playback && !botingame)
{ {
for (i = 1; i < 3; i++) for (i = 1; i < MAXSPLITSCREENPLAYERS; i++)
{ {
if (i > splitscreen) if (i > splitscreen)
{ CL_RemoveSplitscreenPlayer(displayplayers[i]);
if (i == 1)
CL_RemoveSplitscreenPlayer(secondarydisplayplayer);
else if (i == 2)
CL_RemoveSplitscreenPlayer(thirddisplayplayer);
else if (i == 3)
CL_RemoveSplitscreenPlayer(fourthdisplayplayer);
}
else else
CL_AddSplitscreenPlayer(); CL_AddSplitscreenPlayer();
} }
@ -215,21 +210,27 @@ void SplitScreen_OnChange(void)
} }
else else
{ {
secondarydisplayplayer = consoleplayer; for (i = 1; i < MAXSPLITSCREENPLAYERS; i++)
thirddisplayplayer = consoleplayer; displayplayers[i] = consoleplayer;
fourthdisplayplayer = consoleplayer;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && i != consoleplayer) if (playeringame[i] && i != consoleplayer)
{ {
if (secondarydisplayplayer == consoleplayer) UINT8 j;
secondarydisplayplayer = i; for (j = 1; j < MAXSPLITSCREENPLAYERS; j++)
else if (thirddisplayplayer == consoleplayer) {
thirddisplayplayer = i; if (displayplayers[j] == consoleplayer)
else if (fourthdisplayplayer == consoleplayer) {
fourthdisplayplayer = i; displayplayers[j] = i;
else break;
}
}
if (j == MAXSPLITSCREENPLAYERS)
break; break;
} }
}
} }
} }
static void Fov_OnChange(void) static void Fov_OnChange(void)
@ -844,16 +845,20 @@ static void R_SetupFreelook(void)
void R_SkyboxFrame(player_t *player) void R_SkyboxFrame(player_t *player)
{ {
camera_t *thiscam; camera_t *thiscam = &camera[0];
UINT8 i;
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) if (splitscreen)
thiscam = &camera4; {
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) for (i = 1; i <= splitscreen; i++)
thiscam = &camera3; {
else if (splitscreen && player == &players[secondarydisplayplayer]) if (player == &players[displayplayers[i]])
thiscam = &camera2; {
else thiscam = &camera[i];
thiscam = &camera; break;
}
}
}
// cut-away view stuff // cut-away view stuff
viewsky = true; viewsky = true;
@ -879,27 +884,24 @@ void R_SkyboxFrame(player_t *player)
{ {
aimingangle = player->aiming; aimingangle = player->aiming;
viewangle = player->mo->angle; viewangle = player->mo->angle;
if (/*!demoplayback && */player->playerstate != PST_DEAD) if (/*!demo.playback && */player->playerstate != PST_DEAD)
{ {
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
{ {
viewangle = localangle; // WARNING: camera uses this viewangle = localangle[0]; // WARNING: camera uses this
aimingangle = localaiming; aimingangle = localaiming[0];
} }
else if (player == &players[secondarydisplayplayer]) else if (splitscreen)
{ {
viewangle = localangle2; for (i = 1; i <= splitscreen; i++)
aimingangle = localaiming2; {
} if (player == &players[displayplayers[i]])
else if (player == &players[thirddisplayplayer]) {
{ viewangle = localangle[i];
viewangle = localangle3; aimingangle = localaiming[i];
aimingangle = localaiming3; break;
} }
else if (player == &players[fourthdisplayplayer]) }
{
viewangle = localangle4;
aimingangle = localaiming4;
} }
} }
} }
@ -1078,24 +1080,24 @@ void R_SetupFrame(player_t *player, boolean skybox)
camera_t *thiscam; camera_t *thiscam;
boolean chasecam = false; boolean chasecam = false;
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) if (splitscreen > 2 && player == &players[displayplayers[3]])
{ {
thiscam = &camera4; thiscam = &camera[3];
chasecam = (cv_chasecam4.value != 0); chasecam = (cv_chasecam4.value != 0);
} }
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) else if (splitscreen > 1 && player == &players[displayplayers[2]])
{ {
thiscam = &camera3; thiscam = &camera[2];
chasecam = (cv_chasecam3.value != 0); chasecam = (cv_chasecam3.value != 0);
} }
else if (splitscreen && player == &players[secondarydisplayplayer]) else if (splitscreen && player == &players[displayplayers[1]])
{ {
thiscam = &camera2; thiscam = &camera[1];
chasecam = (cv_chasecam2.value != 0); chasecam = (cv_chasecam2.value != 0);
} }
else else
{ {
thiscam = &camera; thiscam = &camera[0];
chasecam = (cv_chasecam.value != 0); chasecam = (cv_chasecam.value != 0);
} }
@ -1141,27 +1143,25 @@ void R_SetupFrame(player_t *player, boolean skybox)
aimingangle = player->aiming; aimingangle = player->aiming;
viewangle = viewmobj->angle; viewangle = viewmobj->angle;
if (/*!demoplayback && */player->playerstate != PST_DEAD) if (/*!demo.playback && */player->playerstate != PST_DEAD)
{ {
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
{ {
viewangle = localangle; // WARNING: camera uses this viewangle = localangle[0]; // WARNING: camera uses this
aimingangle = localaiming; aimingangle = localaiming[0];
} }
else if (player == &players[secondarydisplayplayer]) else if (splitscreen)
{ {
viewangle = localangle2; UINT8 i;
aimingangle = localaiming2; for (i = 1; i <= splitscreen; i++)
} {
else if (player == &players[thirddisplayplayer]) if (player == &players[displayplayers[i]])
{ {
viewangle = localangle3; viewangle = localangle[i];
aimingangle = localaiming3; aimingangle = localaiming[i];
} break;
else if (player == &players[fourthdisplayplayer]) }
{ }
viewangle = localangle4;
aimingangle = localaiming4;
} }
} }
} }
@ -1323,19 +1323,10 @@ void R_RenderPlayerView(player_t *player)
{ {
portal_pair *portal; portal_pair *portal;
const boolean skybox = (skyboxmo[0] && cv_skybox.value); const boolean skybox = (skyboxmo[0] && cv_skybox.value);
UINT8 viewnumber; UINT8 i;
if (player == &players[secondarydisplayplayer] && splitscreen)
viewnumber = 1;
else if (player == &players[thirddisplayplayer] && splitscreen > 1)
viewnumber = 2;
else if (player == &players[fourthdisplayplayer] && splitscreen > 2)
viewnumber = 3;
else
viewnumber = 0;
// if this is display player 1 // if this is display player 1
if (cv_homremoval.value && player == &players[displayplayer]) if (cv_homremoval.value && player == &players[displayplayers[0]])
{ {
if (cv_homremoval.value == 1) if (cv_homremoval.value == 1)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect! V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
@ -1343,7 +1334,7 @@ void R_RenderPlayerView(player_t *player)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15)); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15));
} }
// Draw over the fourth screen so you don't have to stare at a HOM :V // Draw over the fourth screen so you don't have to stare at a HOM :V
else if (splitscreen == 2 && player == &players[thirddisplayplayer]) else if (splitscreen == 2 && player == &players[displayplayers[2]])
#if 1 #if 1
{ {
// V_DrawPatchFill, but for the fourth screen only // V_DrawPatchFill, but for the fourth screen only
@ -1362,14 +1353,14 @@ void R_RenderPlayerView(player_t *player)
#endif #endif
// load previous saved value of skyVisible for the player // load previous saved value of skyVisible for the player
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) for (i = 0; i <= splitscreen; i++)
skyVisible = skyVisible4; {
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) if (player == &players[displayplayers[i]])
skyVisible = skyVisible3; {
else if (splitscreen && player == &players[secondarydisplayplayer]) skyVisible = skyVisiblePerPlayer[i];
skyVisible = skyVisible2; break;
else }
skyVisible = skyVisible1; }
portalrender = 0; portalrender = 0;
portal_base = portal_cap = NULL; portal_base = portal_cap = NULL;
@ -1386,7 +1377,7 @@ void R_RenderPlayerView(player_t *player)
R_ClearVisibleFloorSplats(); R_ClearVisibleFloorSplats();
#endif #endif
R_RenderBSPNode((INT32)numnodes - 1, viewnumber); R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites(); R_ClipSprites();
R_DrawPlanes(); R_DrawPlanes();
#ifdef FLOORSPLATS #ifdef FLOORSPLATS
@ -1419,7 +1410,7 @@ void R_RenderPlayerView(player_t *player)
mytotal = 0; mytotal = 0;
ProfZeroTimer(); ProfZeroTimer();
#endif #endif
R_RenderBSPNode((INT32)numnodes - 1, viewnumber); R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites(); R_ClipSprites();
#ifdef TIMING #ifdef TIMING
RDMSR(0x10, &mycount); RDMSR(0x10, &mycount);
@ -1444,7 +1435,7 @@ void R_RenderPlayerView(player_t *player)
validcount++; validcount++;
R_RenderBSPNode((INT32)numnodes - 1, viewnumber); R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites(); R_ClipSprites();
//R_DrawPlanes(); //R_DrawPlanes();
//R_DrawMasked(); //R_DrawMasked();
@ -1470,16 +1461,16 @@ void R_RenderPlayerView(player_t *player)
// Check for new console commands. // Check for new console commands.
NetUpdate(); NetUpdate();
// save value to skyVisible1 or skyVisible2 // save value to skyVisiblePerPlayer
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa // this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
if (splitscreen > 2 && player == &players[fourthdisplayplayer]) for (i = 0; i <= splitscreen; i++)
skyVisible4 = skyVisible; {
else if (splitscreen > 1 && player == &players[thirddisplayplayer]) if (player == &players[displayplayers[i]])
skyVisible3 = skyVisible; {
else if (splitscreen && player == &players[secondarydisplayplayer]) skyVisiblePerPlayer[i] = skyVisible;
skyVisible2 = skyVisible; break;
else }
skyVisible1 = skyVisible; }
} }
// ========================================================================= // =========================================================================

View file

@ -883,12 +883,12 @@ void R_DrawSinglePlane(visplane_t *pl)
if (bottom > vid.height) if (bottom > vid.height)
bottom = vid.height; bottom = vid.height;
if (splitscreen > 2 && viewplayer == &players[fourthdisplayplayer]) // Only copy the part of the screen we need if (splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need
scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth); scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth);
else if ((splitscreen == 1 && viewplayer == &players[secondarydisplayplayer]) else if ((splitscreen == 1 && viewplayer == &players[displayplayers[1]])
|| (splitscreen > 1 && viewplayer == &players[thirddisplayplayer])) || (splitscreen > 1 && viewplayer == &players[displayplayers[2]]))
scr = (screens[0] + (top+(viewheight))*vid.width); scr = (screens[0] + (top+(viewheight))*vid.width);
else if (splitscreen > 1 && viewplayer == &players[secondarydisplayplayer]) else if (splitscreen > 1 && viewplayer == &players[displayplayers[1]])
scr = (screens[0] + ((top)*vid.width) + viewwidth); scr = (screens[0] + ((top)*vid.width) + viewwidth);
else else
scr = (screens[0] + ((top)*vid.width)); scr = (screens[0] + ((top)*vid.width));

View file

@ -17,6 +17,7 @@
// Need data structure definitions. // Need data structure definitions.
#include "d_player.h" #include "d_player.h"
#include "r_data.h" #include "r_data.h"
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#ifdef __GNUG__ #ifdef __GNUG__
#pragma interface #pragma interface
@ -88,8 +89,9 @@ extern side_t *sides;
// //
extern fixed_t viewx, viewy, viewz; extern fixed_t viewx, viewy, viewz;
extern angle_t viewangle, aimingangle; extern angle_t viewangle, aimingangle;
extern UINT8 viewssnum; // splitscreen view number
extern boolean viewsky, skyVisible; extern boolean viewsky, skyVisible;
extern boolean skyVisible1, skyVisible2, skyVisible3, skyVisible4; // saved values of skyVisible for P1 and P2, for splitscreen extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player
extern sector_t *viewsector; extern sector_t *viewsector;
extern player_t *viewplayer; extern player_t *viewplayer;
extern UINT8 portalrender; extern UINT8 portalrender;

View file

@ -927,6 +927,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (vis->x2 >= vid.width) if (vis->x2 >= vid.width)
vis->x2 = vid.width-1; vis->x2 = vid.width-1;
#if 1
// Something is occasionally setting 1px-wide sprites whose frac is exactly the width of the sprite, causing crashes due to
// accessing invalid column info. Until the cause is found, let's try to correct those manually...
while (frac + vis->xiscale*(vis->x2-vis->x1) > SHORT(patch->width)<<FRACBITS && vis->x2 >= vis->x1)
vis->x2--;
#endif
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
{ {
if (vis->scalestep) // currently papersprites only if (vis->scalestep) // currently papersprites only
@ -1697,7 +1704,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// R_AddSprites // R_AddSprites
// During BSP traversal, this adds sprites by sector. // During BSP traversal, this adds sprites by sector.
// //
void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber) void R_AddSprites(sector_t *sec, INT32 lightlevel)
{ {
mobj_t *thing; mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002 precipmobj_t *precipthing; // Tails 08-25-2002
@ -1743,19 +1750,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
if (splitscreen) if (splitscreen)
{ {
if (thing->eflags & MFE_DRAWONLYFORP1) if (thing->eflags & MFE_DRAWONLYFORP1)
if (viewnumber != 0) if (viewssnum != 0)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP2) if (thing->eflags & MFE_DRAWONLYFORP2)
if (viewnumber != 1) if (viewssnum != 1)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
if (viewnumber != 2) if (viewssnum != 2)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
if (viewnumber != 3) if (viewssnum != 3)
continue; continue;
} }
@ -1778,19 +1785,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
if (splitscreen) if (splitscreen)
{ {
if (thing->eflags & MFE_DRAWONLYFORP1) if (thing->eflags & MFE_DRAWONLYFORP1)
if (viewnumber != 0) if (viewssnum != 0)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP2) if (thing->eflags & MFE_DRAWONLYFORP2)
if (viewnumber != 1) if (viewssnum != 1)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
if (viewnumber != 2) if (viewssnum != 2)
continue; continue;
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
if (viewnumber != 3) if (viewssnum != 3)
continue; continue;
} }
@ -2652,15 +2659,15 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
player->kartspeed = skin->kartspeed; player->kartspeed = skin->kartspeed;
player->kartweight = skin->kartweight; player->kartweight = skin->kartweight;
/*if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking)) /*if (!(cv_debug || devparm) && !(netgame || multiplayer || demo.playback || modeattacking))
{ {
if (playernum == consoleplayer) if (playernum == consoleplayer)
CV_StealthSetValue(&cv_playercolor, skin->prefcolor); CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
else if (playernum == secondarydisplayplayer) else if (playernum == displayplayers[1])
CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); CV_StealthSetValue(&cv_playercolor2, skin->prefcolor);
else if (playernum == thirddisplayplayer) else if (playernum == displayplayers[2])
CV_StealthSetValue(&cv_playercolor3, skin->prefcolor); CV_StealthSetValue(&cv_playercolor3, skin->prefcolor);
else if (playernum == fourthdisplayplayer) else if (playernum == displayplayers[3])
CV_StealthSetValue(&cv_playercolor4, skin->prefcolor); CV_StealthSetValue(&cv_playercolor4, skin->prefcolor);
player->skincolor = skin->prefcolor; player->skincolor = skin->prefcolor;
if (player->mo) if (player->mo)
@ -2669,6 +2676,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
if (player->mo) if (player->mo)
P_SetScale(player->mo, player->mo->scale); P_SetScale(player->mo, player->mo->scale);
demo_extradata[playernum] |= DXD_SKIN;
return; return;
} }

View file

@ -55,7 +55,7 @@ void R_DelSpriteDefs(UINT16 wadnum);
#endif #endif
//SoM: 6/5/2000: Light sprites correctly! //SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber); void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_InitSprites(void); void R_InitSprites(void);
void R_ClearSprites(void); void R_ClearSprites(void);
void R_ClipSprites(void); void R_ClipSprites(void);

View file

@ -438,7 +438,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
listener_t listener3 = {0,0,0,0}; listener_t listener3 = {0,0,0,0};
listener_t listener4 = {0,0,0,0}; listener_t listener4 = {0,0,0,0};
mobj_t *listenmobj = players[displayplayer].mo; mobj_t *listenmobj = players[displayplayers[0]].mo;
mobj_t *listenmobj2 = NULL; mobj_t *listenmobj2 = NULL;
mobj_t *listenmobj3 = NULL; mobj_t *listenmobj3 = NULL;
mobj_t *listenmobj4 = NULL; mobj_t *listenmobj4 = NULL;
@ -450,26 +450,26 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (sfx_id == sfx_None) if (sfx_id == sfx_None)
return; return;
if (players[displayplayer].awayviewtics) if (players[displayplayers[0]].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj; listenmobj = players[displayplayers[0]].awayviewmobj;
if (splitscreen) if (splitscreen)
{ {
listenmobj2 = players[secondarydisplayplayer].mo; listenmobj2 = players[displayplayers[1]].mo;
if (players[secondarydisplayplayer].awayviewtics) if (players[displayplayers[1]].awayviewtics)
listenmobj2 = players[secondarydisplayplayer].awayviewmobj; listenmobj2 = players[displayplayers[1]].awayviewmobj;
if (splitscreen > 1) if (splitscreen > 1)
{ {
listenmobj3 = players[thirddisplayplayer].mo; listenmobj3 = players[displayplayers[2]].mo;
if (players[thirddisplayplayer].awayviewtics) if (players[displayplayers[2]].awayviewtics)
listenmobj3 = players[thirddisplayplayer].awayviewmobj; listenmobj3 = players[displayplayers[2]].awayviewmobj;
if (splitscreen > 2) if (splitscreen > 2)
{ {
listenmobj4 = players[fourthdisplayplayer].mo; listenmobj4 = players[displayplayers[3]].mo;
if (players[fourthdisplayplayer].awayviewtics) if (players[displayplayers[3]].awayviewtics)
listenmobj4 = players[fourthdisplayplayer].awayviewmobj; listenmobj4 = players[displayplayers[3]].awayviewmobj;
} }
} }
} }
@ -482,12 +482,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
}; };
#endif #endif
if (camera.chase && !players[displayplayer].awayviewtics) if (camera[0].chase && !players[displayplayers[0]].awayviewtics)
{ {
listener.x = camera.x; listener.x = camera[0].x;
listener.y = camera.y; listener.y = camera[0].y;
listener.z = camera.z; listener.z = camera[0].z;
listener.angle = camera.angle; listener.angle = camera[0].angle;
} }
else if (listenmobj) else if (listenmobj)
{ {
@ -501,12 +501,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (listenmobj2) if (listenmobj2)
{ {
if (camera2.chase && !players[secondarydisplayplayer].awayviewtics) if (camera[1].chase && !players[displayplayers[1]].awayviewtics)
{ {
listener2.x = camera2.x; listener2.x = camera[1].x;
listener2.y = camera2.y; listener2.y = camera[1].y;
listener2.z = camera2.z; listener2.z = camera[1].z;
listener2.angle = camera2.angle; listener2.angle = camera[1].angle;
} }
else else
{ {
@ -519,12 +519,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (listenmobj3) if (listenmobj3)
{ {
if (camera3.chase && !players[thirddisplayplayer].awayviewtics) if (camera[2].chase && !players[displayplayers[2]].awayviewtics)
{ {
listener3.x = camera3.x; listener3.x = camera[2].x;
listener3.y = camera3.y; listener3.y = camera[2].y;
listener3.z = camera3.z; listener3.z = camera[2].z;
listener3.angle = camera3.angle; listener3.angle = camera[2].angle;
} }
else else
{ {
@ -537,12 +537,12 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (listenmobj4) if (listenmobj4)
{ {
if (camera4.chase && !players[fourthdisplayplayer].awayviewtics) if (camera[3].chase && !players[displayplayers[3]].awayviewtics)
{ {
listener4.x = camera4.x; listener4.x = camera[3].x;
listener4.y = camera4.y; listener4.y = camera[3].y;
listener4.z = camera4.z; listener4.z = camera[3].z;
listener4.angle = camera4.angle; listener4.angle = camera[3].angle;
} }
else else
{ {
@ -899,7 +899,7 @@ void S_UpdateSounds(void)
listener_t listener3; listener_t listener3;
listener_t listener4; listener_t listener4;
mobj_t *listenmobj = players[displayplayer].mo; mobj_t *listenmobj = players[displayplayers[0]].mo;
mobj_t *listenmobj2 = NULL; mobj_t *listenmobj2 = NULL;
mobj_t *listenmobj3 = NULL; mobj_t *listenmobj3 = NULL;
mobj_t *listenmobj4 = NULL; mobj_t *listenmobj4 = NULL;
@ -935,36 +935,36 @@ void S_UpdateSounds(void)
if (dedicated || sound_disabled) if (dedicated || sound_disabled)
return; return;
if (players[displayplayer].awayviewtics) if (players[displayplayers[0]].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj; listenmobj = players[displayplayers[0]].awayviewmobj;
if (splitscreen) if (splitscreen)
{ {
listenmobj2 = players[secondarydisplayplayer].mo; listenmobj2 = players[displayplayers[1]].mo;
if (players[secondarydisplayplayer].awayviewtics) if (players[displayplayers[1]].awayviewtics)
listenmobj2 = players[secondarydisplayplayer].awayviewmobj; listenmobj2 = players[displayplayers[1]].awayviewmobj;
if (splitscreen > 1) if (splitscreen > 1)
{ {
listenmobj3 = players[thirddisplayplayer].mo; listenmobj3 = players[displayplayers[2]].mo;
if (players[thirddisplayplayer].awayviewtics) if (players[displayplayers[2]].awayviewtics)
listenmobj3 = players[thirddisplayplayer].awayviewmobj; listenmobj3 = players[displayplayers[2]].awayviewmobj;
if (splitscreen > 2) if (splitscreen > 2)
{ {
listenmobj4 = players[fourthdisplayplayer].mo; listenmobj4 = players[displayplayers[3]].mo;
if (players[fourthdisplayplayer].awayviewtics) if (players[displayplayers[3]].awayviewtics)
listenmobj4 = players[fourthdisplayplayer].awayviewmobj; listenmobj4 = players[displayplayers[3]].awayviewmobj;
} }
} }
} }
if (camera.chase && !players[displayplayer].awayviewtics) if (camera[0].chase && !players[displayplayers[0]].awayviewtics)
{ {
listener.x = camera.x; listener.x = camera[0].x;
listener.y = camera.y; listener.y = camera[0].y;
listener.z = camera.z; listener.z = camera[0].z;
listener.angle = camera.angle; listener.angle = camera[0].angle;
} }
else if (listenmobj) else if (listenmobj)
{ {
@ -989,12 +989,12 @@ void S_UpdateSounds(void)
if (listenmobj2) if (listenmobj2)
{ {
if (camera2.chase && !players[secondarydisplayplayer].awayviewtics) if (camera[1].chase && !players[displayplayers[1]].awayviewtics)
{ {
listener2.x = camera2.x; listener2.x = camera[1].x;
listener2.y = camera2.y; listener2.y = camera[1].y;
listener2.z = camera2.z; listener2.z = camera[1].z;
listener2.angle = camera2.angle; listener2.angle = camera[1].angle;
} }
else else
{ {
@ -1007,12 +1007,12 @@ void S_UpdateSounds(void)
if (listenmobj3) if (listenmobj3)
{ {
if (camera3.chase && !players[thirddisplayplayer].awayviewtics) if (camera[2].chase && !players[displayplayers[2]].awayviewtics)
{ {
listener3.x = camera3.x; listener3.x = camera[2].x;
listener3.y = camera3.y; listener3.y = camera[2].y;
listener3.z = camera3.z; listener3.z = camera[2].z;
listener3.angle = camera3.angle; listener3.angle = camera[2].angle;
} }
else else
{ {
@ -1025,12 +1025,12 @@ void S_UpdateSounds(void)
if (listenmobj4) if (listenmobj4)
{ {
if (camera4.chase && !players[fourthdisplayplayer].awayviewtics) if (camera[3].chase && !players[displayplayers[3]].awayviewtics)
{ {
listener4.x = camera4.x; listener4.x = camera[3].x;
listener4.y = camera4.y; listener4.y = camera[3].y;
listener4.z = camera4.z; listener4.z = camera[3].z;
listener4.angle = camera4.angle; listener4.angle = camera[3].angle;
} }
else else
{ {
@ -1060,9 +1060,9 @@ void S_UpdateSounds(void)
// check non-local sounds for distance clipping // check non-local sounds for distance clipping
// or modify their params // or modify their params
if (c->origin && ((c->origin != players[consoleplayer].mo) if (c->origin && ((c->origin != players[consoleplayer].mo)
|| (splitscreen && c->origin != players[secondarydisplayplayer].mo) || (splitscreen && c->origin != players[displayplayers[1]].mo)
|| (splitscreen > 1 && c->origin != players[thirddisplayplayer].mo) || (splitscreen > 1 && c->origin != players[displayplayers[2]].mo)
|| (splitscreen > 2 && c->origin != players[fourthdisplayplayer].mo))) || (splitscreen > 2 && c->origin != players[displayplayers[3]].mo)))
{ {
// Whomever is closer gets the sound, but only in splitscreen. // Whomever is closer gets the sound, but only in splitscreen.
if (splitscreen) if (splitscreen)
@ -1071,13 +1071,10 @@ void S_UpdateSounds(void)
fixed_t recdist = -1; fixed_t recdist = -1;
INT32 i, p = -1; INT32 i, p = -1;
for (i = 0; i < 4; i++) for (i = 0; i <= splitscreen; i++)
{ {
fixed_t thisdist = -1; fixed_t thisdist = -1;
if (i > splitscreen)
break;
if (i == 0 && listenmobj) if (i == 0 && listenmobj)
thisdist = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y); thisdist = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y);
else if (i == 1 && listenmobj2) else if (i == 1 && listenmobj2)
@ -1250,33 +1247,33 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v
if (!listener) if (!listener)
return false; return false;
if (listener == players[displayplayer].mo && camera.chase) if (listener == players[displayplayers[0]].mo && camera[0].chase)
{ {
listensource.x = camera.x; listensource.x = camera[0].x;
listensource.y = camera.y; listensource.y = camera[0].y;
listensource.z = camera.z; listensource.z = camera[0].z;
listensource.angle = camera.angle; listensource.angle = camera[0].angle;
} }
else if (splitscreen && listener == players[secondarydisplayplayer].mo && camera2.chase) else if (splitscreen && listener == players[displayplayers[1]].mo && camera[1].chase)
{ {
listensource.x = camera2.x; listensource.x = camera[1].x;
listensource.y = camera2.y; listensource.y = camera[1].y;
listensource.z = camera2.z; listensource.z = camera[1].z;
listensource.angle = camera2.angle; listensource.angle = camera[1].angle;
} }
else if (splitscreen > 1 && listener == players[thirddisplayplayer].mo && camera3.chase) else if (splitscreen > 1 && listener == players[displayplayers[2]].mo && camera[2].chase)
{ {
listensource.x = camera3.x; listensource.x = camera[2].x;
listensource.y = camera3.y; listensource.y = camera[2].y;
listensource.z = camera3.z; listensource.z = camera[2].z;
listensource.angle = camera3.angle; listensource.angle = camera[2].angle;
} }
else if (splitscreen > 2 && listener == players[fourthdisplayplayer].mo && camera4.chase) else if (splitscreen > 2 && listener == players[displayplayers[3]].mo && camera[3].chase)
{ {
listensource.x = camera4.x; listensource.x = camera[3].x;
listensource.y = camera4.y; listensource.y = camera[3].y;
listensource.z = camera4.z; listensource.z = camera[3].z;
listensource.angle = camera4.angle; listensource.angle = camera[3].angle;
} }
else else
{ {
@ -1733,7 +1730,7 @@ void S_ShowMusicCredit(void)
{ {
musicdef_t *def = musicdefstart; musicdef_t *def = musicdefstart;
if (!cv_songcredits.value) if (!cv_songcredits.value || demo.rewinding)
return; return;
if (!def) // No definitions if (!def) // No definitions
@ -1920,7 +1917,8 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
#endif #endif
if (S_MusicDisabled() if (S_MusicDisabled()
|| titledemo) // SRB2Kart: Demos don't interrupt title screen music || demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return; return;
// No Music (empty string) // No Music (empty string)
@ -1955,7 +1953,8 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
void S_StopMusic(void) void S_StopMusic(void)
{ {
if (!I_SongPlaying() if (!I_SongPlaying()
|| titledemo) // SRB2Kart: Demos don't interrupt title screen music || demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return; return;
if (I_SongPaused()) if (I_SongPaused())

View file

@ -59,6 +59,8 @@ INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set +
static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}}; static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}};
static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}};
//added : 03-02-98: default screen mode, as loaded/saved in config //added : 03-02-98: default screen mode, as loaded/saved in config
#ifdef WII #ifdef WII
consvar_t cv_scr_width = {"scr_width", "640", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_scr_width = {"scr_width", "640", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -70,6 +72,8 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N
consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif #endif
consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_vhseffect = {"vhspause", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shittyscreen = {"televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static void SCR_ChangeFullscreen (void); static void SCR_ChangeFullscreen (void);

View file

@ -158,7 +158,7 @@ extern INT32 setmodeneeded; // mode number to set if needed, or 0
extern INT32 scr_bpp; extern INT32 scr_bpp;
extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern UINT8 *scr_borderpatch; // patch used to fill the view borders
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen; extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen;
// wait for page flipping to end or not // wait for page flipping to end or not
extern consvar_t cv_vidwait; extern consvar_t cv_vidwait;

View file

@ -3061,7 +3061,7 @@ void I_Quit(void)
//added:16-02-98: when recording a demo, should exit using 'q' key, //added:16-02-98: when recording a demo, should exit using 'q' key,
// but sometimes we forget and use 'F10'.. so save here too. // but sometimes we forget and use 'F10'.. so save here too.
if (demorecording) if (demo.recording)
G_CheckDemoStatus(); G_CheckDemoStatus();
if (metalrecording) if (metalrecording)
G_StopMetalRecording(); G_StopMetalRecording();
@ -3179,7 +3179,7 @@ void I_Error(const char *error, ...)
G_SaveGameData(false); // Tails 12-08-2002 G_SaveGameData(false); // Tails 12-08-2002
// Shutdown. Here might be other errors. // Shutdown. Here might be other errors.
if (demorecording) if (demo.recording)
G_CheckDemoStatus(); G_CheckDemoStatus();
if (metalrecording) if (metalrecording)
G_StopMetalRecording(); G_StopMetalRecording();

View file

@ -372,7 +372,7 @@ static inline void ST_InitData(void)
// 'link' the statusbar display to a player, which could be // 'link' the statusbar display to a player, which could be
// another player than consoleplayer, for example, when you // another player than consoleplayer, for example, when you
// change the view in a multiplayer demo with F12. // change the view in a multiplayer demo with F12.
stplyr = &players[displayplayer]; stplyr = &players[displayplayers[0]];
st_palette = -1; st_palette = -1;
} }
@ -442,7 +442,7 @@ static INT32 SCY(INT32 y)
if (splitscreen) if (splitscreen)
{ {
y >>= 1; y >>= 1;
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
y += vid.height / 2; y += vid.height / 2;
} }
return y; return y;
@ -458,7 +458,7 @@ static INT32 STRINGY(INT32 y)
if (splitscreen) if (splitscreen)
{ {
y >>= 1; y >>= 1;
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
y += BASEVIDHEIGHT / 2; y += BASEVIDHEIGHT / 2;
} }
return y; return y;
@ -471,7 +471,7 @@ static INT32 SPLITFLAGS(INT32 f)
// Pass this V_SNAPTO(TOP|BOTTOM) and it'll trim them to account for splitscreen! -Red // Pass this V_SNAPTO(TOP|BOTTOM) and it'll trim them to account for splitscreen! -Red
if (splitscreen) if (splitscreen)
{ {
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
f &= ~V_SNAPTOTOP; f &= ~V_SNAPTOTOP;
else else
f &= ~V_SNAPTOBOTTOM; f &= ~V_SNAPTOBOTTOM;
@ -498,7 +498,7 @@ static INT32 SCR(INT32 r)
if (splitscreen) if (splitscreen)
{ {
y >>= 1; y >>= 1;
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
y += vid.height / 2; y += vid.height / 2;
} }
return FixedInt(FixedDiv(y, vid.fdupy)); return FixedInt(FixedDiv(y, vid.fdupy));
@ -701,7 +701,7 @@ static inline void ST_drawRings(void) // SRB2kart - unused.
/* /*
static void ST_drawLives(void) // SRB2kart - unused. static void ST_drawLives(void) // SRB2kart - unused.
{ {
const INT32 v_splitflag = (splitscreen && stplyr == &players[displayplayer] ? V_SPLITSCREEN : 0); const INT32 v_splitflag = (splitscreen && stplyr == &players[displayplayers[0]] ? V_SPLITSCREEN : 0);
if (!stplyr->skincolor) if (!stplyr->skincolor)
return; // Just joined a server, skin isn't loaded yet! return; // Just joined a server, skin isn't loaded yet!
@ -1019,7 +1019,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused.
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ // Since special stages share score, time, rings, etc. { // Since special stages share score, time, rings, etc.
// disable splitscreen mode for its HUD. // disable splitscreen mode for its HUD.
if (stplyr != &players[displayplayer]) if (stplyr != &players[displayplayers[0]])
return; return;
nosshack = splitscreen; nosshack = splitscreen;
splitscreen = 0; splitscreen = 0;
@ -1124,7 +1124,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused.
V_DrawScaledPatch(locx, STRINGY(locy)-3, V_HUDTRANS, drillbar); V_DrawScaledPatch(locx, STRINGY(locy)-3, V_HUDTRANS, drillbar);
for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill)
V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_HUDTRANS, drillfill[fillpatch]); V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_HUDTRANS, drillfill[fillpatch]);
stplyr = &players[secondarydisplayplayer]; stplyr = &players[displayplayers[1]];
if (stplyr->pflags & PF_DRILLING) if (stplyr->pflags & PF_DRILLING)
fillpatch = (stplyr->drillmeter & 1) + 1; fillpatch = (stplyr->drillmeter & 1) + 1;
else else
@ -1132,7 +1132,7 @@ static void ST_drawNiGHTSHUD(void) // SRB2kart - unused.
V_DrawScaledPatch(locx, STRINGY(locy-3), V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); V_DrawScaledPatch(locx, STRINGY(locy-3), V_SNAPTOBOTTOM|V_HUDTRANS, drillbar);
for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill)
V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]);
stplyr = &players[displayplayer]; stplyr = &players[displayplayers[0]];
splitscreen = 0; splitscreen = 0;
} }
else else
@ -1881,7 +1881,7 @@ static void ST_overlayDrawer(void)
ST_drawTeamName(); ST_drawTeamName();
// Special Stage HUD // Special Stage HUD
if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer]) if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayers[0]])
ST_drawSpecialStageHUD(); ST_drawSpecialStageHUD();
// Emerald Hunt Indicators // Emerald Hunt Indicators
@ -1894,22 +1894,46 @@ static void ST_overlayDrawer(void)
V_DrawScaledPatch(hudinfo[HUD_GRAVBOOTSICO].x, STRINGY(hudinfo[HUD_GRAVBOOTSICO].y), V_SNAPTORIGHT, gravboots); V_DrawScaledPatch(hudinfo[HUD_GRAVBOOTSICO].x, STRINGY(hudinfo[HUD_GRAVBOOTSICO].y), V_SNAPTORIGHT, gravboots);
*/ */
if(!P_IsLocalPlayer(stplyr)) if (!(multiplayer && demo.playback))
{ {
/*char name[MAXPLAYERNAME+1]; if(!P_IsLocalPlayer(stplyr))
// shorten the name if its more than twelve characters. {
strlcpy(name, player_names[stplyr-players], 13);*/ /*char name[MAXPLAYERNAME+1];
// shorten the name if its more than twelve characters.
strlcpy(name, player_names[stplyr-players], 13);*/
// Show name of player being displayed // Show name of player being displayed
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Viewpoint:")); V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, 0, M_GetText("Viewpoint:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]); V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_ALLOWLOWERCASE, player_names[stplyr-players]);
}
}
else if (!demo.title)
{
if (!splitscreen)
{
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Viewpoint:"));
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_HUDTRANSHALF|V_ALLOWLOWERCASE, player_names[stplyr-players]);
}
else if (splitscreen == 1)
{
char name[MAXPLAYERNAME+12];
INT32 y = (stplyr == &players[displayplayers[0]]) ? 4 : BASEVIDHEIGHT/2-12;
sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]);
V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name);
}
else if (splitscreen)
{
V_DrawCenteredThinString((vid.width/vid.dupx)/4, BASEVIDHEIGHT/2 - 12, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT), player_names[stplyr-players]);
}
} }
// This is where we draw all the fun cheese if you have the chasecam off! // This is where we draw all the fun cheese if you have the chasecam off!
/*if ((stplyr == &players[displayplayer] && !camera.chase) /*if ((stplyr == &players[displayplayers[0]] && !camera[0].chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase) || ((splitscreen && stplyr == &players[displayplayers[1]]) && !camera[1].chase)
|| ((splitscreen > 1 && stplyr == &players[thirddisplayplayer]) && !camera3.chase) || ((splitscreen > 1 && stplyr == &players[displayplayers[2]]) && !camera[2].chase)
|| ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) || ((splitscreen > 2 && stplyr == &players[displayplayers[3]]) && !camera[3].chase))
{ {
ST_drawFirstPersonHUD(); ST_drawFirstPersonHUD();
}*/ }*/
@ -1990,9 +2014,65 @@ static void ST_overlayDrawer(void)
} }
} }
// Replay manual-save stuff
if (demo.recording && multiplayer && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime)
{
switch (demo.savemode)
{
case DSM_NOTSAVING:
V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Look Backward: Save replay");
break;
case DSM_WILLAUTOSAVE:
V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved. (Look Backward: Change title)");
break;
case DSM_WILLSAVE:
V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved.");
break;
case DSM_TITLEENTRY:
ST_DrawDemoTitleEntry();
break;
default: // Don't render anything
break;
}
}
ST_drawDebugInfo(); ST_drawDebugInfo();
} }
void ST_DrawDemoTitleEntry(void)
{
static UINT8 skullAnimCounter = 0;
char *nametodraw;
skullAnimCounter++;
skullAnimCounter %= 8;
nametodraw = demo.titlename;
while (V_StringWidth(nametodraw, 0) > MAXSTRINGLENGTH*8 - 8)
nametodraw++;
#define x (BASEVIDWIDTH/2 - 139)
#define y (BASEVIDHEIGHT/2)
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, nametodraw);
if (skullAnimCounter < 4)
V_DrawCharacter(x + 8 + V_StringWidth(nametodraw, 0), y + 12,
'_' | 0x80, false);
M_DrawTextBox(x + 30, y - 24, 26, 1);
V_DrawString(x + 38, y - 16, V_ALLOWLOWERCASE, "Enter the name of the replay.");
M_DrawTextBox(x + 50, y + 20, 20, 1);
V_DrawThinString(x + 58, y + 28, V_ALLOWLOWERCASE, "Escape - Cancel");
V_DrawRightAlignedThinString(x + 220, y + 28, V_ALLOWLOWERCASE, "Enter - Confirm");
#undef x
#undef y
}
// MayonakaStatic: draw Midnight Channel's TV-like borders // MayonakaStatic: draw Midnight Channel's TV-like borders
static void ST_MayonakaStatic(void) static void ST_MayonakaStatic(void)
{ {
@ -2006,8 +2086,10 @@ static void ST_MayonakaStatic(void)
void ST_Drawer(void) void ST_Drawer(void)
{ {
UINT8 i;
#ifdef SEENAMES #ifdef SEENAMES
if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo && !mapreset) if (cv_seenames.value && cv_allowseenames.value && displayplayers[0] == consoleplayer && seenplayer && seenplayer->mo && !mapreset)
{ {
if (cv_seenames.value == 1) if (cv_seenames.value == 1)
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]);
@ -2041,26 +2123,12 @@ void ST_Drawer(void)
if (st_overlay) if (st_overlay)
{ {
// No deadview! // No deadview!
stplyr = &players[displayplayer]; for (i = 0; i <= splitscreen; i++)
ST_overlayDrawer();
if (splitscreen)
{ {
stplyr = &players[secondarydisplayplayer]; stplyr = &players[displayplayers[i]];
ST_overlayDrawer(); ST_overlayDrawer();
if (splitscreen > 1)
{
stplyr = &players[thirddisplayplayer];
ST_overlayDrawer();
if (splitscreen > 2)
{
stplyr = &players[fourthdisplayplayer];
ST_overlayDrawer();
}
}
} }
// draw Midnight Channel's overlay ontop // draw Midnight Channel's overlay ontop
if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff.
ST_MayonakaStatic(); ST_MayonakaStatic();

View file

@ -26,6 +26,9 @@
// Called by main loop. // Called by main loop.
void ST_Ticker(void); void ST_Ticker(void);
// Called when naming a replay.
void ST_DrawDemoTitleEntry(void);
// Called by main loop. // Called by main loop.
void ST_Drawer(void); void ST_Drawer(void);

View file

@ -1214,6 +1214,66 @@ void V_DrawPatchFill(patch_t *pat)
} }
} }
void V_DrawVhsEffect(boolean rewind)
{
static fixed_t upbary = 100, downbary = 150;
UINT8 *buf = screens[0], *tmp = screens[4];
UINT16 y;
UINT32 x, pos = 0;
UINT8 *normalmapstart = ((UINT8 *)transtables + (8<<FF_TRANSSHIFT|(19<<8)));
#ifdef HQ_VHS
UINT8 *tmapstart = ((UINT8 *)transtables + (6<<FF_TRANSSHIFT));
#endif
UINT8 *thismapstart;
SINT8 offs;
UINT8 barsize = vid.dupy<<5;
UINT8 updistort = vid.dupx<<(rewind ? 5 : 3);
UINT8 downdistort = updistort>>1;
if (rewind)
V_DrawVhsEffect(false); // experimentation
upbary -= vid.dupy * (rewind ? 3 : 1.8f);
downbary += vid.dupy * (rewind ? 2 : 1);
if (upbary < -barsize) upbary = vid.height;
if (downbary > vid.height) downbary = -barsize;
for (y = 0; y < vid.height; y+=2)
{
thismapstart = normalmapstart;
offs = 0;
if (y >= upbary && y < upbary+barsize)
{
thismapstart -= (2<<FF_TRANSSHIFT) - (5<<8);
offs += updistort * 2.0f * min(y-upbary, upbary+barsize-y) / barsize;
}
if (y >= downbary && y < downbary+barsize)
{
thismapstart -= (2<<FF_TRANSSHIFT) - (5<<8);
offs -= downdistort * 2.0f * min(y-downbary, downbary+barsize-y) / barsize;
}
offs += M_RandomKey(vid.dupx<<1);
// lazy way to avoid crashes
if (y == 0 && offs < 0) offs = 0;
else if (y >= vid.height-2 && offs > 0) offs = 0;
for (x = pos+vid.rowbytes*2; pos < x; pos++)
{
tmp[pos] = thismapstart[buf[pos+offs]];
#ifdef HQ_VHS
tmp[pos] = tmapstart[buf[pos]<<8 | tmp[pos]];
#endif
}
}
memcpy(buf, tmp, vid.rowbytes*vid.height);
}
// //
// Fade all the screen buffer, so that the menu is more readable, // Fade all the screen buffer, so that the menu is more readable,
// especially now that we use the small hufont in the menus... // especially now that we use the small hufont in the menus...
@ -1234,9 +1294,12 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
#endif #endif
{ {
const UINT8 *fadetable = ((color & 0xFF00) // Color is not palette index? const UINT8 *fadetable =
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. (color > 0xFFF0) // Grab a specific colormap palette?
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade. ? R_GetTranslationColormap(color | 0xFFFF0000, strength, GTC_CACHE)
: ((color & 0xFF00) // Color is not palette index?
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade.
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *buf = screens[0]; UINT8 *buf = screens[0];
@ -1460,8 +1523,11 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
{ {
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; if (!(option & V_SNAPTOLEFT))
scrwidth -= left; {
left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
}
} }
charflags = (option & V_CHARCOLORMASK); charflags = (option & V_CHARCOLORMASK);
@ -1870,6 +1936,12 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
} }
} }
void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string)
{
x -= V_ThinStringWidth(string, option)/2;
V_DrawThinString(x, y, option, string);
}
void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string) void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string)
{ {
x -= V_ThinStringWidth(string, option); x -= V_ThinStringWidth(string, option);

View file

@ -153,6 +153,9 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c);
// fill a box with a flat as a pattern // fill a box with a flat as a pattern
void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
// draw wobbly VHS pause stuff
void V_DrawVhsEffect(boolean rewind);
// fade down the screen buffer before drawing the menu over // fade down the screen buffer before drawing the menu over
void V_DrawFadeScreen(UINT16 color, UINT8 strength); void V_DrawFadeScreen(UINT16 color, UINT8 strength);
@ -182,6 +185,7 @@ void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *s
// draw a string using the tny_font // draw a string using the tny_font
void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);

View file

@ -644,7 +644,7 @@ void I_Error(const char *error, ...)
// save demo, could be useful for debug // save demo, could be useful for debug
// NOTE: demos are normally not saved here. // NOTE: demos are normally not saved here.
if (demorecording) if (demo.recording)
G_CheckDemoStatus(); G_CheckDemoStatus();
if (metalrecording) if (metalrecording)
G_StopMetalRecording(); G_StopMetalRecording();
@ -730,7 +730,7 @@ void I_Quit(void)
DWORD mode; DWORD mode;
// when recording a demo, should exit using 'q', // when recording a demo, should exit using 'q',
// but sometimes we forget and use Alt+F4, so save here too. // but sometimes we forget and use Alt+F4, so save here too.
if (demorecording) if (demo.recording)
G_CheckDemoStatus(); G_CheckDemoStatus();
if (metalrecording) if (metalrecording)
G_StopMetalRecording(); G_StopMetalRecording();

View file

@ -305,6 +305,15 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
players[i].score += data.match.increase[i]; players[i].score += data.match.increase[i];
} }
if (demo.recording && !rankingsmode)
G_WriteStanding(
data.match.pos[data.match.numplayers],
data.match.name[data.match.numplayers],
*data.match.character[data.match.numplayers],
*data.match.color[data.match.numplayers],
data.match.val[data.match.numplayers]
);
data.match.numplayers++; data.match.numplayers++;
} }
} }
@ -352,7 +361,7 @@ void Y_IntermissionDrawer(void)
V_DrawFadeScreen(0xFF00, 22); V_DrawFadeScreen(0xFF00, 22);
if (!splitscreen) if (!splitscreen)
whiteplayer = demoplayback ? displayplayer : consoleplayer; whiteplayer = demo.playback ? displayplayers[0] : consoleplayer;
if (cons_menuhighlight.value) if (cons_menuhighlight.value)
hilicol = cons_menuhighlight.value; hilicol = cons_menuhighlight.value;
@ -361,7 +370,7 @@ void Y_IntermissionDrawer(void)
else else
hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP); hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP);
if (sorttic != -1 && intertic > sorttic) if (sorttic != -1 && intertic > sorttic && !demo.playback)
{ {
INT32 count = (intertic - sorttic); INT32 count = (intertic - sorttic);
@ -551,11 +560,37 @@ void Y_IntermissionDrawer(void)
dotimer: dotimer:
if (timer) if (timer)
{ {
char *string;
INT32 tickdown = (timer+1)/TICRATE; INT32 tickdown = (timer+1)/TICRATE;
if (multiplayer && demo.playback)
string = va("Replay ends in %d", tickdown);
else
string = va("%s starts in %d", cv_advancemap.string, tickdown);
V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol, V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol,
va("%s starts in %d", cv_advancemap.string, tickdown)); string);
} }
if ((demo.recording || demo.savemode == DSM_SAVED) && !demo.playback)
switch (demo.savemode)
{
case DSM_NOTSAVING:
V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Look Backward: Save replay");
break;
case DSM_SAVED:
V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|hilicol, "Replay saved!");
break;
case DSM_TITLEENTRY:
ST_DrawDemoTitleEntry();
break;
default: // Don't render any text here
break;
}
// Make it obvious that scrambling is happening next round. // Make it obvious that scrambling is happening next round.
if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0))
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!")); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!"));
@ -571,6 +606,15 @@ void Y_Ticker(void)
if (intertype == int_none) if (intertype == int_none)
return; return;
if (demo.recording)
{
if (demo.savemode == DSM_NOTSAVING && InputDown(gc_lookback, 1))
demo.savemode = DSM_TITLEENTRY;
if (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE)
G_SaveDemo();
}
// Check for pause or menu up in single player // Check for pause or menu up in single player
if (paused || P_AutoPause()) if (paused || P_AutoPause())
return; return;
@ -618,7 +662,7 @@ void Y_Ticker(void)
{ {
if (sorttic == -1) if (sorttic == -1)
sorttic = intertic + max((cv_inttime.value/2)-2, 2)*TICRATE; // 8 second pause after match results sorttic = intertic + max((cv_inttime.value/2)-2, 2)*TICRATE; // 8 second pause after match results
else else if (!(multiplayer && demo.playback)) // Don't advance to rankings in replays
{ {
if (!data.match.rankingsmode && (intertic >= sorttic + 8)) if (!data.match.rankingsmode && (intertic >= sorttic + 8))
Y_CalculateMatchData(1, Y_CompareRank); Y_CalculateMatchData(1, Y_CompareRank);
@ -767,6 +811,8 @@ void Y_StartIntermission(void)
{ {
if (cv_inttime.value == 0 && gametype == GT_COOP) if (cv_inttime.value == 0 && gametype == GT_COOP)
timer = 0; timer = 0;
else if (demo.playback) // Override inttime (which is pulled from the replay anyway
timer = 10*TICRATE;
else else
{ {
timer = cv_inttime.value*TICRATE; timer = cv_inttime.value*TICRATE;
@ -801,7 +847,7 @@ void Y_StartIntermission(void)
} }
case int_race: // (time-only race) case int_race: // (time-only race)
{ {
if (!majormods && !multiplayer && !demoplayback) // remove this once we have a proper time attack screen if (!majormods && !multiplayer && !demo.playback) // remove this once we have a proper time attack screen
{ {
// Update visitation flags // Update visitation flags
mapvisited[gamemap-1] |= MV_BEATEN; mapvisited[gamemap-1] |= MV_BEATEN;
@ -1010,19 +1056,19 @@ void Y_VoteDrawer(void)
{ {
case 1: case 1:
thiscurs = cursor2; thiscurs = cursor2;
p = secondarydisplayplayer; p = displayplayers[1];
break; break;
case 2: case 2:
thiscurs = cursor3; thiscurs = cursor3;
p = thirddisplayplayer; p = displayplayers[2];
break; break;
case 3: case 3:
thiscurs = cursor4; thiscurs = cursor4;
p = fourthdisplayplayer; p = displayplayers[3];
break; break;
default: default:
thiscurs = cursor1; thiscurs = cursor1;
p = displayplayer; p = displayplayers[0];
break; break;
} }
@ -1177,10 +1223,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level)
S_StartSound(NULL, sfx_noooo2); // gasp S_StartSound(NULL, sfx_noooo2); // gasp
else if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU)) else if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU))
S_StartSound(NULL, sfx_noooo1); // this is bad S_StartSound(NULL, sfx_noooo1); // this is bad
else if (netgame && (pick == consoleplayer else if (netgame && P_IsLocalPlayer(&players[pick]))
|| pick == secondarydisplayplayer
|| pick == thirddisplayplayer
|| pick == fourthdisplayplayer))
S_StartSound(NULL, sfx_yeeeah); // yeeeah! S_StartSound(NULL, sfx_yeeeah); // yeeeah!
else else
S_StartSound(NULL, sfx_kc48); // just a cool sound S_StartSound(NULL, sfx_kc48); // just a cool sound
@ -1313,13 +1356,13 @@ void Y_VoteTicker(void)
switch (i) switch (i)
{ {
case 1: case 1:
p = secondarydisplayplayer; p = displayplayers[1];
break; break;
case 2: case 2:
p = thirddisplayplayer; p = displayplayers[2];
break; break;
case 3: case 3:
p = fourthdisplayplayer; p = displayplayers[3];
break; break;
default: default:
p = consoleplayer; p = consoleplayer;