diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9e519d61..4b47d4a5 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -97,7 +97,7 @@ SINT8 nodetoplayer[MAXNETNODES]; SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) SINT8 nodetoplayer3[MAXNETNODES]; // say the numplayer for this node if any (splitscreen3) SINT8 nodetoplayer4[MAXNETNODES]; // say the numplayer for this node if any (splitscreen4) -UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen +UINT8 playerpernode[MAXNETNODES]; // used specialy for splitscreen boolean nodeingame[MAXNETNODES]; // set false as nodes leave game static tic_t nettics[MAXNETNODES]; // what tic the client have received static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet @@ -269,6 +269,38 @@ void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) } } +void SendNetXCmd3(netxcmd_t id, const void *param, size_t nparam) +{ + if (localtextcmd3[0]+2+nparam > MAXTEXTCMD) + { + I_Error("No more place in the buffer for netcmd %d\n",id); + return; + } + localtextcmd3[0]++; + localtextcmd3[localtextcmd3[0]] = (UINT8)id; + if (param && nparam) + { + M_Memcpy(&localtextcmd3[localtextcmd3[0]+1], param, nparam); + localtextcmd3[0] = (UINT8)(localtextcmd3[0] + (UINT8)nparam); + } +} + +void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam) +{ + if (localtextcmd4[0]+2+nparam > MAXTEXTCMD) + { + I_Error("No more place in the buffer for netcmd %d\n",id); + return; + } + localtextcmd4[0]++; + localtextcmd4[localtextcmd4[0]] = (UINT8)id; + if (param && nparam) + { + M_Memcpy(&localtextcmd4[localtextcmd4[0]+1], param, nparam); + localtextcmd4[0] = (UINT8)(localtextcmd4[0] + (UINT8)nparam); + } +} + UINT8 GetFreeXCmdSize(void) { // -1 for the size and another -1 for the ID. @@ -2708,9 +2740,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) // Is playernum authorized to make this kick? if (playernum != serverplayer && !IsPlayerAdmin(playernum) && !(playerpernode[playernode[playernum]] >= 2 - && nodetoplayer2[playernode[playernum]] == pnum - && nodetoplayer3[playernode[playernum]] == pnum - && nodetoplayer4[playernode[playernum]] == pnum)) + && (nodetoplayer2[playernode[playernum]] == pnum + || nodetoplayer3[playernode[playernum]] == pnum + || nodetoplayer4[playernode[playernum]] == pnum))) { // We received a kick command from someone who isn't the // server or admin, and who isn't in splitscreen removing @@ -3115,24 +3147,22 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (node == mynode) { playernode[newplayernum] = 0; // for information only - if (splitscreenplayer == 0) + if (splitscreenplayer) { - consoleplayer = newplayernum; - displayplayer = newplayernum; - secondarydisplayplayer = newplayernum; - thirddisplayplayer = newplayernum; - fourthdisplayplayer = newplayernum; - DEBFILE("spawning me\n"); - // Apply player flags as soon as possible! - players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); - if (cv_flipcam.value) - players[newplayernum].pflags |= PF_FLIPCAM; - if (cv_analog.value) - players[newplayernum].pflags |= PF_ANALOGMODE; - } - else - { - if (splitscreenplayer == 2) + if (splitscreenplayer == 1) + { + secondarydisplayplayer = newplayernum; + DEBFILE("spawning my brother\n"); + if (botingame) + players[newplayernum].bot = 1; + // Same goes for player 2 when relevant + players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); + if (cv_flipcam2.value) + players[newplayernum].pflags |= PF_FLIPCAM; + if (cv_analog2.value) + players[newplayernum].pflags |= PF_ANALOGMODE; + } + else if (splitscreenplayer == 2) { thirddisplayplayer = newplayernum; DEBFILE("spawning my sister\n"); @@ -3152,19 +3182,21 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (cv_analog4.value) players[newplayernum].pflags |= PF_ANALOGMODE; } - else - { - secondarydisplayplayer = newplayernum; - DEBFILE("spawning my brother\n"); - if (botingame) - players[newplayernum].bot = 1; - // Same goes for player 2 when relevant - players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); - if (cv_flipcam2.value) - players[newplayernum].pflags |= PF_FLIPCAM; - if (cv_analog2.value) - players[newplayernum].pflags |= PF_ANALOGMODE; - } + } + else + { + consoleplayer = newplayernum; + displayplayer = newplayernum; + secondarydisplayplayer = newplayernum; + thirddisplayplayer = newplayernum; + fourthdisplayplayer = newplayernum; + DEBFILE("spawning me\n"); + // Apply player flags as soon as possible! + players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); + if (cv_flipcam.value) + players[newplayernum].pflags |= PF_FLIPCAM; + if (cv_analog.value) + players[newplayernum].pflags |= PF_ANALOGMODE; } D_SendPlayerConfig(); addedtogame = true; @@ -3233,7 +3265,7 @@ static boolean SV_AddWaitingPlayers(void) nodetoplayer3[node] = newplayernum; buf[1] += MAXPLAYERS*2; } - else if (playerpernode[node] < 4) + else { nodetoplayer4[node] = newplayernum; buf[1] += MAXPLAYERS*3; @@ -3752,6 +3784,7 @@ FILESTAMP realend = ExpandTics(netbuffer->u.clientpak.resendfrom); if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS + || netbuffer->packettype == PT_CLIENT3MIS || netbuffer->packettype == PT_CLIENT4MIS || netbuffer->packettype == PT_NODEKEEPALIVEMIS || supposedtics[node] < realend) { @@ -3800,20 +3833,26 @@ FILESTAMP if (((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) || (netbuffer->packettype == PT_CLIENT3CMD || netbuffer->packettype == PT_CLIENT3MIS) || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) - && nodetoplayer2[node] >= 0) + && (nodetoplayer2[node] >= 0)) + { G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); - + } + if (((netbuffer->packettype == PT_CLIENT3CMD || netbuffer->packettype == PT_CLIENT3MIS) || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) - && nodetoplayer3[node] >= 0) + && (nodetoplayer3[node] >= 0)) + { G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer3[node]], &netbuffer->u.client3pak.cmd3, 1); + } if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS) - && nodetoplayer4[node] >= 0) + && (nodetoplayer4[node] >= 0)) + { G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer4[node]], &netbuffer->u.client4pak.cmd4, 1); + } // A delay before we check resynching // Used on join or just after a synch fail @@ -3948,6 +3987,7 @@ FILESTAMP buf[1] = KICK_MSG_PLAYER_QUIT; SendNetXCmd(XD_KICK, &buf, 2); nodetoplayer[node] = -1; + if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 && playeringame[(UINT8)nodetoplayer2[node]]) { @@ -3955,6 +3995,7 @@ FILESTAMP SendNetXCmd(XD_KICK, &buf, 2); nodetoplayer2[node] = -1; } + if (nodetoplayer3[node] != -1 && nodetoplayer3[node] >= 0 && playeringame[(UINT8)nodetoplayer3[node]]) { @@ -3962,6 +4003,7 @@ FILESTAMP SendNetXCmd(XD_KICK, &buf, 2); nodetoplayer3[node] = -1; } + if (nodetoplayer4[node] != -1 && nodetoplayer4[node] >= 0 && playeringame[(UINT8)nodetoplayer4[node]]) { @@ -4326,7 +4368,7 @@ static void CL_SendClientCmd(void) if (gamestate == GS_WAITINGPLAYERS) { // Send PT_NODEKEEPALIVE packet - netbuffer->packettype += 4; + netbuffer->packettype += 8; packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); HSendPacket(servernode, false, 0, packetsize); } @@ -4335,23 +4377,26 @@ static void CL_SendClientCmd(void) G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); - if (splitscreen4) + if (splitscreen || botingame) // Send a special packet with 2 cmd for splitscreen { - netbuffer->packettype += 6; - G_MoveTiccmd(&netbuffer->u.client4pak.cmd2, &localcmds2, 1); - G_MoveTiccmd(&netbuffer->u.client4pak.cmd3, &localcmds3, 1); - G_MoveTiccmd(&netbuffer->u.client4pak.cmd4, &localcmds4, 1); + netbuffer->packettype += 2; + G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + packetsize = sizeof (client2cmd_pak); } else if (splitscreen3) { netbuffer->packettype += 4; - G_MoveTiccmd(&netbuffer->u.client3pak.cmd2, &localcmds2, 1); - G_MoveTiccmd(&netbuffer->u.client3pak.cmd3, &localcmds3, 1); - } - else if (splitscreen || botingame) // Send a special packet with 2 cmd for splitscreen - { - netbuffer->packettype += 2; G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + G_MoveTiccmd(&netbuffer->u.client3pak.cmd3, &localcmds3, 1); + packetsize = sizeof (client3cmd_pak); + } + else if (splitscreen4) + { + netbuffer->packettype += 6; + G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + G_MoveTiccmd(&netbuffer->u.client3pak.cmd3, &localcmds3, 1); + G_MoveTiccmd(&netbuffer->u.client4pak.cmd4, &localcmds4, 1); + packetsize = sizeof (client4cmd_pak); } else packetsize = sizeof (clientcmd_pak); @@ -4380,6 +4425,26 @@ static void CL_SendClientCmd(void) if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... localtextcmd2[0] = 0; } + + // Send extra data if needed for player 3 (splitscreen3) + if (localtextcmd3[0]) + { + netbuffer->packettype = PT_TEXTCMD3; + M_Memcpy(netbuffer->u.textcmd, localtextcmd3, localtextcmd3[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd3[0]+1)) // Send can fail... + localtextcmd3[0] = 0; + } + + // Send extra data if needed for player 4 (splitscreen4) + if (localtextcmd4[0]) + { + netbuffer->packettype = PT_TEXTCMD4; + M_Memcpy(netbuffer->u.textcmd, localtextcmd4, localtextcmd4[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd4[0]+1)) // Send can fail... + localtextcmd4[0] = 0; + } } } @@ -4558,8 +4623,12 @@ static void SV_Maketic(void) CONS_Debug(DBG_NETPLAY, "Client Misstic %d\n", maketic); #endif // copy the old tic - for (i = 0; i < playerpernode[j]; i++, player = nodetoplayer2[j]) + for (i = 0; i < playerpernode[j]; i++) { + if (i == 0) player = nodetoplayer[j]; + else if (i == 1) player = nodetoplayer2[j]; + else if (i == 2) player = nodetoplayer3[j]; + else if (i == 3) player = nodetoplayer4[j]; netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player]; netcmds[maketic%BACKUPTICS][player].angleturn &= ~TICCMD_RECEIVED; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 702e5d60..bc902ac5 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -70,8 +70,8 @@ typedef enum PT_TEXTCMD, // Extra text commands from the client. PT_TEXTCMD2, // Splitscreen text commands. - PT_TEXTCMD3, - PT_TEXTCMD4, + PT_TEXTCMD3, // 3P + PT_TEXTCMD4, // 4P PT_CLIENTJOIN, // Client wants to join; used in start game. PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_RESYNCHING, // Packet sent to resync players. @@ -506,6 +506,8 @@ void D_ClientServerInit(void); void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam); void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player +void SendNetXCmd3(netxcmd_t id, const void *param, size_t nparam); // splitsreen3 player +void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam); // splitsreen4 player // Create any new ticcmds and broadcast to other players. void NetUpdate(void); diff --git a/src/d_main.c b/src/d_main.c index 367bd012..6e469aad 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -401,7 +401,7 @@ static void D_Display(void) } // render the second screen - if (splitscreen && players[secondarydisplayplayer].mo) + if ((splitscreen || splitscreen3 || splitscreen4) && players[secondarydisplayplayer].mo) { #ifdef HWRENDER if (rendermode != render_soft) @@ -410,6 +410,8 @@ static void D_Display(void) #endif if (rendermode != render_none) { + if (splitscreen3 || splitscreen4) + viewwindowx = vid.width / 2; viewwindowy = vid.height / 2; M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0])); diff --git a/src/d_net.c b/src/d_net.c index 5c3f644d..5437af56 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -818,6 +818,10 @@ static const char *packettypename[NUMPACKETTYPE] = "CLIENTMIS", "CLIENT2CMD", "CLIENT2MIS", + "CLIENT3CMD", + "CLIENT3MIS", + "CLIENT4CMD", + "CLIENT4MIS", "NODEKEEPALIVE", "NODEKEEPALIVEMIS", "SERVERTICS", @@ -837,6 +841,8 @@ static const char *packettypename[NUMPACKETTYPE] = "FILEFRAGMENT", "TEXTCMD", "TEXTCMD2", + "TEXTCMD3", + "TEXTCMD4", "CLIENTJOIN", "NODETIMEOUT", "RESYNCHING", diff --git a/src/d_net.h b/src/d_net.h index cb70b6df..45fd8683 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -21,7 +21,7 @@ // Max computers in a game #define MAXNETNODES 16 #define BROADCASTADDR MAXNETNODES -#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer +#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer #define STATLENGTH (TICRATE*2) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6a454f46..2c2e2218 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -178,8 +178,8 @@ static void Command_Archivetest_f(void); void SendWeaponPref(void); void SendWeaponPref2(void); -//void SendWeaponPref3(void); -//void SendWeaponPref4(void); +void SendWeaponPref3(void); +void SendWeaponPref4(void); static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}}; #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) @@ -772,16 +772,28 @@ void D_RegisterClientCommands(void) // g_input.c CV_RegisterVar(&cv_sideaxis); CV_RegisterVar(&cv_sideaxis2); + CV_RegisterVar(&cv_sideaxis3); + CV_RegisterVar(&cv_sideaxis4); CV_RegisterVar(&cv_turnaxis); CV_RegisterVar(&cv_turnaxis2); + CV_RegisterVar(&cv_turnaxis3); + CV_RegisterVar(&cv_turnaxis4); CV_RegisterVar(&cv_moveaxis); CV_RegisterVar(&cv_moveaxis2); + CV_RegisterVar(&cv_moveaxis3); + CV_RegisterVar(&cv_moveaxis4); CV_RegisterVar(&cv_lookaxis); CV_RegisterVar(&cv_lookaxis2); + CV_RegisterVar(&cv_lookaxis3); + CV_RegisterVar(&cv_lookaxis4); CV_RegisterVar(&cv_fireaxis); CV_RegisterVar(&cv_fireaxis2); + CV_RegisterVar(&cv_fireaxis3); + CV_RegisterVar(&cv_fireaxis4); CV_RegisterVar(&cv_firenaxis); CV_RegisterVar(&cv_firenaxis2); + CV_RegisterVar(&cv_firenaxis3); + CV_RegisterVar(&cv_firenaxis4); // WARNING: the order is important when initialising mouse2 // we need the mouse2port @@ -1689,7 +1701,7 @@ void SendWeaponPref3(void) buf[0] |= 1; if (players[thirddisplayplayer].pflags & PF_ANALOGMODE) buf[0] |= 2; - //SendNetXCmd3(XD_WEAPONPREF, buf, 1); + SendNetXCmd3(XD_WEAPONPREF, buf, 1); } void SendWeaponPref4(void) @@ -1701,7 +1713,7 @@ void SendWeaponPref4(void) buf[0] |= 1; if (players[fourthdisplayplayer].pflags & PF_ANALOGMODE) buf[0] |= 2; - //SendNetXCmd4(XD_WEAPONPREF, buf, 1); + SendNetXCmd4(XD_WEAPONPREF, buf, 1); } static void Got_WeaponPref(UINT8 **cp,INT32 playernum) diff --git a/src/g_game.c b/src/g_game.c index 65f80109..7e4a4f4b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2109,8 +2109,6 @@ void G_Ticker(boolean run) if (playeringame[i]) { - G_CopyTiccmd(cmd, &netcmds[buf][i], 1); - // SRB2kart // Save the dir the player is holding // to allow items to be thrown forward or backward. @@ -2120,6 +2118,8 @@ void G_Ticker(boolean run) players[i].kartstuff[k_throwdir] = -1; else players[i].kartstuff[k_throwdir] = 0; + + G_CopyTiccmd(cmd, &netcmds[buf][i], 1); } } diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e46080e0..69e2a9dd 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1802,7 +1802,7 @@ static void HU_DrawRankings(void) HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer); // draw spectators in a ticker across the bottom - if ((!splitscreen || !splitscreen3 || !splitscreen4) && G_GametypeHasSpectators()) + if (!(splitscreen || splitscreen3 || splitscreen4) && G_GametypeHasSpectators()) HU_DrawSpectatorTicker(); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 8de54718..62bb3746 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6136,7 +6136,7 @@ void P_RunOverlays(void) if (!mo->target) continue; - if (!splitscreen /*&& rendermode != render_soft*/) + if (!(splitscreen || splitscreen3 || splitscreen4) /*&& rendermode != render_soft*/) { angle_t viewingangle; @@ -6779,8 +6779,7 @@ void P_MobjThinker(mobj_t *mobj) fixed_t scale = mobj->target->scale; mobj->color = mobj->target->color; - if ((splitscreen || !netgame) - || gametype == GT_RACE + if (!netgame || gametype == GT_RACE || mobj->target->player == &players[displayplayer] || mobj->target->player->kartstuff[k_balloon] <= 0 || (mobj->target->player->mo->flags2 & MF2_DONTDRAW)) @@ -8096,7 +8095,7 @@ void P_MobjThinker(mobj_t *mobj) CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 1 || splitscreen) + if (players[consoleplayer].ctfteam == 1 || (splitscreen || splitscreen3 || splitscreen4)) S_StartSound(NULL, sfx_hoop1); redflag = flagmo; @@ -8107,7 +8106,7 @@ void P_MobjThinker(mobj_t *mobj) CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 2 || splitscreen) + if (players[consoleplayer].ctfteam == 2 || (splitscreen || splitscreen3 || splitscreen4)) S_StartSound(NULL, sfx_hoop1); blueflag = flagmo; diff --git a/src/p_setup.c b/src/p_setup.c index 6086a346..1c57fd56 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2354,10 +2354,20 @@ static void P_ForceCharacter(const char *forcecharskin) if (netgame) { char skincmd[33]; - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) { sprintf(skincmd, "skin2 %s\n", forcecharskin); CV_Set(&cv_skin2, forcecharskin); + if (splitscreen3 || splitscreen4) + { + sprintf(skincmd, "skin3 %s\n", forcecharskin); + CV_Set(&cv_skin3, forcecharskin); + if (splitscreen4) + { + sprintf(skincmd, "skin4 %s\n", forcecharskin); + CV_Set(&cv_skin4, forcecharskin); + } + } } sprintf(skincmd, "skin %s\n", forcecharskin); @@ -2920,10 +2930,20 @@ boolean P_SetupLevel(boolean skipprecip) if (!cv_cam2_rotate.changed) CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue); + if (!cv_cam3_rotate.changed) + CV_Set(&cv_cam3_rotate, cv_cam3_rotate.defaultvalue); + + if (!cv_cam4_rotate.changed) + CV_Set(&cv_cam4_rotate, cv_cam4_rotate.defaultvalue); + if (!cv_analog.changed) CV_SetValue(&cv_analog, 0); if (!cv_analog2.changed) CV_SetValue(&cv_analog2, 0); + if (!cv_analog3.changed) + CV_SetValue(&cv_analog3, 0); + if (!cv_analog4.changed) + CV_SetValue(&cv_analog4, 0); #ifdef HWRENDER if (rendermode != render_soft && rendermode != render_none) @@ -2936,13 +2956,21 @@ boolean P_SetupLevel(boolean skipprecip) if (cv_useranalog.value) CV_SetValue(&cv_analog, true); - if (splitscreen && cv_useranalog2.value) + if ((splitscreen || splitscreen3 || splitscreen4) && cv_useranalog2.value) CV_SetValue(&cv_analog2, true); else if (botingame) CV_SetValue(&cv_analog2, true); + if ((splitscreen3 || splitscreen4) && cv_useranalog3.value) + CV_SetValue(&cv_analog3, true); + + if (splitscreen4 && cv_useranalog4.value) + CV_SetValue(&cv_analog4, true); + if (twodlevel) { + CV_SetValue(&cv_analog4, false); + CV_SetValue(&cv_analog3, false); CV_SetValue(&cv_analog2, false); CV_SetValue(&cv_analog, false); } @@ -2998,7 +3026,7 @@ boolean P_SetupLevel(boolean skipprecip) savedata.lives = 0; } - skyVisible = skyVisible1 = skyVisible2 = true; // assume the skybox is visible on level load. + skyVisible = skyVisible1 = skyVisible2 = skyVisible3 = skyVisible4 = true; // assume the skybox is visible on level load. if (loadprecip) // uglier hack { // to make a newly loaded level start on the second frame. INT32 buf = gametic % BACKUPTICS; diff --git a/src/p_spec.c b/src/p_spec.c index 693cf2b7..feb87b2c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3898,7 +3898,7 @@ DoneSection2: HU_SetCEchoDuration(5); HU_DoCEcho(va(M_GetText("%s\\captured the blue flag.\\\\\\\\"), player_names[player-players])); - if (splitscreen || players[consoleplayer].ctfteam == 1) + if ((splitscreen || splitscreen3 || splitscreen4) || players[consoleplayer].ctfteam == 1) S_StartSound(NULL, sfx_flgcap); else if (players[consoleplayer].ctfteam == 2) S_StartSound(NULL, sfx_lose); @@ -3931,7 +3931,7 @@ DoneSection2: HU_SetCEchoDuration(5); HU_DoCEcho(va(M_GetText("%s\\captured the red flag.\\\\\\\\"), player_names[player-players])); - if (splitscreen || players[consoleplayer].ctfteam == 2) + if ((splitscreen || splitscreen3 || splitscreen4) || players[consoleplayer].ctfteam == 2) S_StartSound(NULL, sfx_flgcap); else if (players[consoleplayer].ctfteam == 1) S_StartSound(NULL, sfx_lose); @@ -4189,7 +4189,7 @@ DoneSection2: if (P_IsLocalPlayer(player)) { // SRB2kart 200117 - if (!splitscreen) + if (!(splitscreen || splitscreen3 || splitscreen4)) { if (player->kartstuff[k_position] == 1) S_ChangeMusicInternal("karwin", true); diff --git a/src/p_user.c b/src/p_user.c index 67a89360..f8649a10 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1663,7 +1663,7 @@ void P_DoPlayerExit(player_t *player) if (P_IsLocalPlayer(player) && cv_inttime.value > 0) { - if (!splitscreen) + if (!(splitscreen || splitscreen3 || splitscreen4)) { if (player->kartstuff[k_position] == 1) S_ChangeMusicInternal("karwin", true); @@ -2388,7 +2388,7 @@ static void P_DoPlayerHeadSigns(player_t *player) { // Spawn a got-flag message over the head of the player that // has it (but not on your own screen if you have the flag). - if (splitscreen || player != &players[consoleplayer]) + if ((splitscreen || splitscreen3 || splitscreen4) || player != &players[consoleplayer]) { if (player->gotflag & GF_REDFLAG) { @@ -8840,7 +8840,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } // Make player translucent if camera is too close (only in single player). - /*if (!(multiplayer || netgame) && !splitscreen) + /*if (!(multiplayer || netgame) && !(splitscreen || splitscreen3 || splitscreen4)) { fixed_t vx = 0, vy = 0; if (player->awayviewtics) { @@ -9377,7 +9377,7 @@ void P_PlayerThink(player_t *player) player->realtime = 0; } - if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) + if ((netgame || (splitscreen || splitscreen3 || splitscreen4)) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) { if (P_SpectatorJoinGame(player)) return; // player->mo was removed. @@ -9619,7 +9619,10 @@ void P_PlayerThink(player_t *player) if (!(player->pflags & PF_NIGHTSMODE)) { // SRB2kart - fixes boo not flashing when it should. Mega doesn't flash either. Flashing is local. - if ((player == &players[displayplayer] || (splitscreen && player == &players[secondarydisplayplayer])) + if ((player == &players[displayplayer] + || ((splitscreen || splitscreen3 || splitscreen4) && player == &players[secondarydisplayplayer]) + || ((splitscreen3 || splitscreen4) && player == &players[thirddisplayplayer]) + || (splitscreen4 && player == &players[fourthdisplayplayer])) && player->kartstuff[k_bootimer] == 0 && player->kartstuff[k_growshrinktimer] <= 0 && (player->kartstuff[k_comebacktimer] == 0 || (gametype == GT_RACE || player->kartstuff[k_balloon] > 0))) { diff --git a/src/r_main.c b/src/r_main.c index 1c9e8744..a4840692 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -195,12 +195,12 @@ void SplitScreen_OnChange(void) CL_AddSplitscreenPlayer(); else CL_RemoveSplitscreenPlayer(secondarydisplayplayer); - + if (splitscreen3 || splitscreen4) CL_AddSplitscreenPlayer(); else CL_RemoveSplitscreenPlayer(thirddisplayplayer); - + if (splitscreen4) CL_AddSplitscreenPlayer(); else diff --git a/src/r_state.h b/src/r_state.h index 49d0457b..8436413b 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -85,7 +85,7 @@ extern side_t *sides; extern fixed_t viewx, viewy, viewz; extern angle_t viewangle, aimingangle; extern boolean viewsky, skyVisible; -extern boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, for splitscreen +extern boolean skyVisible1, skyVisible2, skyVisible3, skyVisible4; // saved values of skyVisible for P1 and P2, for splitscreen extern sector_t *viewsector; extern player_t *viewplayer; extern UINT8 portalrender; diff --git a/src/st_stuff.c b/src/st_stuff.c index cd774f30..c3aee555 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -229,7 +229,7 @@ void ST_doPaletteStuff(void) if (rendermode != render_none) { V_SetPaletteLump(GetPalette()); // Reset the palette - if (!splitscreen) + if (!(splitscreen || splitscreen3 || splitscreen4)) V_SetPalette(palette); } } @@ -445,7 +445,7 @@ static INT32 SCY(INT32 y) // do not scale to resolution for hardware accelerated // because these modes always scale by default y = SCZ(y); // scale to resolution - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) { y >>= 1; if (stplyr != &players[displayplayer]) @@ -459,7 +459,7 @@ static INT32 STRINGY(INT32 y) //31/10/99: fixed by Hurdler so it _works_ also in hardware mode // do not scale to resolution for hardware accelerated // because these modes always scale by default - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) { y >>= 1; if (stplyr != &players[displayplayer]) @@ -472,7 +472,7 @@ static INT32 STRINGY(INT32 y) static INT32 SPLITFLAGS(INT32 f) { // Pass this V_SNAPTO(TOP|BOTTOM) and it'll trim them to account for splitscreen! -Red - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) { if (stplyr != &players[displayplayer]) f &= ~V_SNAPTOTOP; @@ -496,7 +496,7 @@ static INT32 SCR(INT32 r) // do not scale to resolution for hardware accelerated // because these modes always scale by default y = FixedMul(r*FRACUNIT, vid.fdupy); // scale to resolution - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) { y >>= 1; if (stplyr != &players[displayplayer]) @@ -668,7 +668,7 @@ static void ST_drawTime(void) ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon); // Colon ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2); // Seconds - if (!splitscreen && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying! + if (!(splitscreen || splitscreen3 || splitscreen4) && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying! { ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics @@ -700,7 +700,7 @@ static inline void ST_drawRings(void) /* static void ST_drawLives(void) // SRB2kart - unused. { - const INT32 v_splitflag = (splitscreen && stplyr == &players[displayplayer] ? V_SPLITSCREEN : 0); + const INT32 v_splitflag = ((splitscreen || splitscreen3 || splitscreen4) && stplyr == &players[displayplayer] ? V_SPLITSCREEN : 0); if (!stplyr->skincolor) return; // Just joined a server, skin isn't loaded yet! @@ -838,7 +838,7 @@ static void ST_drawFirstPersonHUD(void) if (p) { - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); else V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); @@ -848,7 +848,7 @@ static void ST_drawFirstPersonHUD(void) invulntime = player->powers[pw_flashing] ? 1 : player->powers[pw_invulnerability]; if (invulntime > 3*TICRATE || (invulntime && leveltime & 1)) { - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); else V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); @@ -856,7 +856,7 @@ static void ST_drawFirstPersonHUD(void) if (player->powers[pw_sneakers] > 3*TICRATE || (player->powers[pw_sneakers] && leveltime & 1)) { - if (splitscreen) + if (splitscreen || splitscreen3 || splitscreen4) V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); else V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); @@ -1620,11 +1620,11 @@ static void ST_drawCTFHUD(void) // SRB2kart - unused. static inline void ST_drawTeamName(void) { if (stplyr->ctfteam == 1) - V_DrawString(256, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "RED TEAM"); + V_DrawString(256, (splitscreen || splitscreen3 || splitscreen4) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "RED TEAM"); else if (stplyr->ctfteam == 2) - V_DrawString(248, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "BLUE TEAM"); + V_DrawString(248, (splitscreen || splitscreen3 || splitscreen4) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "BLUE TEAM"); else - V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR"); + V_DrawString(244, (splitscreen || splitscreen3 || splitscreen4) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR"); } /* @@ -1914,7 +1914,7 @@ static void ST_overlayDrawer(void) ) ST_drawLevelTitle(); - if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer) + if (!hu_showscores && !(splitscreen || splitscreen3 || splitscreen4) && netgame && displayplayer == consoleplayer) { if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player.")); diff --git a/src/v_video.c b/src/v_video.c index bda2f5e8..a5d5f86b 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1977,7 +1977,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param) return; #endif - if (view < 0 || view >= 2 || (view == 1 && !splitscreen)) + if (view < 0 || view >= 2 || (view == 1 && !(splitscreen || splitscreen3 || splitscreen4))) return; if (splitscreen)