A lot lol

The importants:
- Fixed compiling
- Combined G_BuildTiccmd for all players, no more need for a function
for each
- You can actually start 3p/4p mode
This commit is contained in:
TehRealSalt 2017-12-16 22:32:43 -05:00
parent fb976ab26c
commit 0393e24fa6
29 changed files with 2966 additions and 589 deletions

View file

@ -95,8 +95,8 @@ UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
#endif
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 (splitscreen)
SINT8 nodetoplayer4[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
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
static tic_t nettics[MAXNETNODES]; // what tic the client have received
@ -121,14 +121,16 @@ UINT8 hu_resynching = 0;
// Client specific
static ticcmd_t localcmds;
static ticcmd_t localcmds2;
static ticcmd_t localcmds3;
static ticcmd_t localcmds4;
static boolean cl_packetmissed;
// here it is for the secondary local player (splitscreen)
static UINT8 mynode; // my address pointofview server
static UINT8 localtextcmd[MAXTEXTCMD];
static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen
static UINT8 localtextcmd3[MAXTEXTCMD]; // splitscreen
static UINT8 localtextcmd4[MAXTEXTCMD]; // splitscreen
static UINT8 localtextcmd3[MAXTEXTCMD]; // splitscreen3
static UINT8 localtextcmd4[MAXTEXTCMD]; // splitscreen4
static tic_t neededtic;
SINT8 servernode = 0; // the number of the server node
/// \brief do we accept new players?
@ -438,6 +440,8 @@ void D_ResetTiccmds(void)
memset(&localcmds, 0, sizeof(ticcmd_t));
memset(&localcmds2, 0, sizeof(ticcmd_t));
memset(&localcmds3, 0, sizeof(ticcmd_t));
memset(&localcmds4, 0, sizeof(ticcmd_t));
// Reset the net command list
for (i = 0; i < TEXTCMD_HASH_SIZE; i++)
@ -1218,7 +1222,11 @@ static boolean CL_SendJoin(void)
CONS_Printf(M_GetText("Sending join request...\n"));
netbuffer->packettype = PT_CLIENTJOIN;
if (splitscreen || botingame)
if ((splitscreen || splitscreen3 || splitscreen4) || botingame)
localplayers++;
if (splitscreen3 || splitscreen4)
localplayers++;
if (splitscreen4)
localplayers++;
netbuffer->u.clientcfg.localplayers = localplayers;
netbuffer->u.clientcfg.version = VERSION;
@ -2701,7 +2709,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))
&& 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
@ -2927,6 +2937,8 @@ static void ResetNode(INT32 node)
nodeingame[node] = false;
nodetoplayer[node] = -1;
nodetoplayer2[node] = -1;
nodetoplayer3[node] = -1;
nodetoplayer4[node] = -1;
nettics[node] = gametic;
supposedtics[node] = gametic;
nodewaiting[node] = 0;
@ -2962,6 +2974,7 @@ void SV_ResetServer(void)
playeringame[i] = false;
playernode[i] = UINT8_MAX;
sprintf(player_names[i], "Player %d", i + 1);
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
}
mynode = 0;
@ -3089,7 +3102,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
// Clear player before joining, lest some things get set incorrectly
// HACK: don't do this for splitscreen, it relies on preset values
if ((!splitscreen || !splitscreen3 || !splitscreen4) && !botingame)
if (!(splitscreen || splitscreen3 || splitscreen4) && !botingame)
CL_ClearPlayer(newplayernum);
playeringame[newplayernum] = true;
G_AddPlayer(newplayernum);
@ -3185,7 +3198,7 @@ static boolean SV_AddWaitingPlayers(void)
buf[1] = newplayernum;
if (playerpernode[node] < 1)
nodetoplayer[node] = newplayernum;
else
else if (playerpernode[node] < 2)
{
nodetoplayer2[node] = newplayernum;
buf[1] |= 0x80;
@ -3209,14 +3222,14 @@ void CL_AddSplitscreenPlayer(void)
CL_SendJoin();
}
void CL_RemoveSplitscreenPlayer(void)
void CL_RemoveSplitscreenPlayer(UINT8 p)
{
XBOXSTATIC UINT8 buf[2];
if (cl_mode != CL_CONNECTED)
return;
buf[0] = (UINT8)secondarydisplayplayer;
buf[0] = p;
buf[1] = KICK_MSG_PLAYER_QUIT;
SendNetXCmd(XD_KICK, &buf, 2);
}
@ -3229,10 +3242,6 @@ boolean Playing(void)
boolean SV_SpawnServer(void)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
if (demoplayback)
G_StopDemo(); // reset engine parameter
if (metalplayback)
@ -3271,6 +3280,8 @@ void SV_StopServer(void)
localtextcmd[0] = 0;
localtextcmd2[0] = 0;
localtextcmd3[0] = 0;
localtextcmd4[0] = 0;
for (i = 0; i < BACKUPTICS; i++)
D_Clearticcmd(i);
@ -4256,7 +4267,6 @@ static void CL_SendClientCmd(void)
{
netbuffer->packettype += 2;
G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1);
packetsize = sizeof (client2cmd_pak);
}
else
packetsize = sizeof (clientcmd_pak);
@ -4415,17 +4425,15 @@ static void Local_Maketic(INT32 realtics)
// and G_MapEventsToControls
if (!dedicated) rendergametic = gametic;
// translate inputs (keyboard/mouse/joystick) into game controls
G_BuildTiccmd(&localcmds, realtics);
G_BuildTiccmd(&localcmds, realtics, 1);
if ((splitscreen || splitscreen3 || splitscreen4) || botingame)
{
G_BuildTiccmd2(&localcmds2, realtics);
G_BuildTiccmd(&localcmds2, realtics, 2);
if (splitscreen3 || splitscreen4)
{
G_BuildTiccmd3(&localcmds3, realtics);
G_BuildTiccmd(&localcmds3, realtics, 3);
if (splitscreen4)
G_BuildTiccmd4(&localcmds4, realtics);
G_BuildTiccmd(&localcmds4, realtics, 4);
}
}

View file

@ -107,6 +107,26 @@ typedef struct
ticcmd_t cmd, cmd2;
} ATTRPACK client2cmd_pak;
// Splitscreen3 packet
// WARNING: must have the same format of clientcmd_pak, for more easy use
typedef struct
{
UINT8 client_tic;
UINT8 resendfrom;
INT16 consistancy;
ticcmd_t cmd, cmd2, cmd3;
} ATTRPACK client3cmd_pak;
// Splitscreen4 packet
// WARNING: must have the same format of clientcmd_pak, for more easy use
typedef struct
{
UINT8 client_tic;
UINT8 resendfrom;
INT16 consistancy;
ticcmd_t cmd, cmd2, cmd3, cmd4;
} ATTRPACK client4cmd_pak;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
@ -397,6 +417,8 @@ typedef struct
{
clientcmd_pak clientpak; // 144 bytes
client2cmd_pak client2pak; // 200 bytes
client3cmd_pak client3pak; // 256 bytes(?)
client4cmd_pak client4pak; // 312 bytes(?)
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; //
@ -488,7 +510,7 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle);
void SV_StopServer(void);
void SV_ResetServer(void);
void CL_AddSplitscreenPlayer(void);
void CL_RemoveSplitscreenPlayer(void);
void CL_RemoveSplitscreenPlayer(UINT8 p);
void CL_Reset(void);
void CL_ClearPlayer(INT32 playernum);
void CL_UpdateServerList(boolean internetsearch, INT32 room);

View file

@ -27,6 +27,8 @@ typedef enum
ev_joystick,
ev_mouse2,
ev_joystick2,
ev_joystick3,
ev_joystick4,
} evtype_t;
// Event structure.

View file

@ -636,7 +636,7 @@ void D_SRB2Loop(void)
if ((splitscreen3 || splitscreen4) && camera3.chase)
P_MoveChaseCamera(&players[thirddisplayplayer], &camera3, false);
if (splitscreen4 && camera4.chase)
P_MoveChaseCamera(&players[fourthdisplayplayer], &camera3, false);
P_MoveChaseCamera(&players[fourthdisplayplayer], &camera4, false);
if (camera.chase)
P_MoveChaseCamera(&players[displayplayer], &camera, false);
}

View file

@ -36,6 +36,8 @@ extern INT64 sendbytes; // Realtime updated
extern SINT8 nodetoplayer[MAXNETNODES];
extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen)
extern SINT8 nodetoplayer3[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen3)
extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen4)
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game

View file

@ -806,7 +806,7 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming)
return (INT16)((*aiming)>>16);
}
static INT32 JoyAxis(axis_input_e axissel)
static INT32 Joy1Axis(axis_input_e axissel)
{
INT32 retaxis;
INT32 axisval;
@ -1039,7 +1039,7 @@ static INT32 Joy3Axis(axis_input_e axissel)
return retaxis;
}
static INT32 Joy3Axis(axis_input_e axissel)
static INT32 Joy4Axis(axis_input_e axissel)
{
INT32 retaxis;
INT32 axisval;
@ -1117,6 +1117,35 @@ static INT32 Joy3Axis(axis_input_e axissel)
return retaxis;
}
static boolean InputDown(INT32 gc, UINT8 p)
{
switch (p)
{
case 2:
return PLAYER2INPUTDOWN(gc);
case 3:
return PLAYER3INPUTDOWN(gc);
case 4:
return PLAYER4INPUTDOWN(gc);
default:
return PLAYER1INPUTDOWN(gc);
}
}
static INT32 JoyAxis(axis_input_e axissel, UINT8 p)
{
switch (p)
{
case 2:
return Joy2Axis(axissel);
case 3:
return Joy3Axis(axissel);
case 4:
return Joy4Axis(axissel);
default:
return Joy1Axis(axissel);
}
}
//
// G_BuildTiccmd
@ -1133,37 +1162,111 @@ static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16};
static fixed_t sidemove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; // faster!
static fixed_t angleturn[3] = {400, 800, 200}; // + slow turn
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{
boolean forcestrafe = false;
INT32 tspeed, forward, side, axis, i;
INT32 laim, th, tspeed, forward, side, axis, i;
const INT32 speed = 1;
// these ones used for multiple conditions
boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove;
player_t *player = &players[consoleplayer];
camera_t *thiscam = &camera;
boolean turnleft, turnright, invertmouse, mouseaiming, lookaxis, analog, analogjoystickmove, gamepadjoystickmove, kbl;
player_t *player;
camera_t *thiscam;
angle_t lang;
static INT32 turnheld; // for accelerative turning
static boolean keyboard_look; // true if lookup/down using keyboard
static INT32 turnheld, turnheld2, turnheld3, turnheld4; // for accelerative turning
static boolean keyboard_look, keyboard_look2, keyboard_look3, keyboard_look4; // true if lookup/down using keyboard
if (ssplayer == 2)
{
player = &players[secondarydisplayplayer];
thiscam = (player->bot == 2 ? &camera : &camera2);
lang = localangle2;
laim = localaiming2;
th = turnheld2;
kbl = keyboard_look2;
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1);
}
else if (ssplayer == 3)
{
player = &players[thirddisplayplayer];
thiscam = &camera3;
lang = localangle3;
laim = localaiming3;
th = turnheld3;
kbl = keyboard_look3;
G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1);
}
else if (ssplayer == 4)
{
player = &players[fourthdisplayplayer];
thiscam = &camera4;
lang = localangle3;
laim = localaiming3;
th = turnheld4;
kbl = keyboard_look4;
G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1);
}
else
{
player = &players[consoleplayer];
thiscam = &camera;
lang = localangle;
laim = localaiming;
th = turnheld;
kbl = keyboard_look;
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
}
// why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn.
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
{
cmd->angleturn = (INT16)(localangle >> 16);
cmd->aiming = G_ClipAimingPitch(&localaiming);
cmd->angleturn = (INT16)(lang >> 16);
cmd->aiming = G_ClipAimingPitch(&laim);
return;
}
turnright = PLAYER1INPUTDOWN(gc_turnright);
turnleft = PLAYER1INPUTDOWN(gc_turnleft);
if (ssplayer == 2)
{
mouseaiming = (PLAYER2INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook2.value;
invertmouse = cv_invertmouse2.value;
lookaxis = cv_lookaxis2.value;
analogjoystickmove = cv_usejoystick2.value && !Joystick2.bGamepadStyle;
gamepadjoystickmove = cv_usejoystick2.value && Joystick2.bGamepadStyle;
analog = cv_analog2.value;
}
else if (ssplayer == 3)
{
mouseaiming = false;
invertmouse = false;
lookaxis = cv_lookaxis3.value;
analogjoystickmove = cv_usejoystick3.value && !Joystick3.bGamepadStyle;
gamepadjoystickmove = cv_usejoystick3.value && Joystick3.bGamepadStyle;
analog = cv_analog3.value;
}
else if (ssplayer == 4)
{
mouseaiming = false;
invertmouse = false;
lookaxis = cv_lookaxis4.value;
analogjoystickmove = cv_usejoystick4.value && !Joystick4.bGamepadStyle;
gamepadjoystickmove = cv_usejoystick4.value && Joystick4.bGamepadStyle;
analog = cv_analog4.value;
}
else
{
mouseaiming = (PLAYER1INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook.value;
invertmouse = cv_invertmouse.value;
lookaxis = cv_lookaxis.value;
analogjoystickmove = cv_usejoystick.value && !Joystick.bGamepadStyle;
gamepadjoystickmove = cv_usejoystick.value && Joystick.bGamepadStyle;
analog = cv_analog.value;
}
axis = JoyAxis(AXISTURN);
turnright = InputDown(gc_turnright, ssplayer);
turnleft = InputDown(gc_turnleft, ssplayer);
axis = JoyAxis(AXISTURN, ssplayer);
if (gamepadjoystickmove && axis != 0)
{
turnright = turnright || (axis > 0);
@ -1174,30 +1277,32 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
// use two stage accelerative turning
// on the keyboard and joystick
if (turnleft || turnright)
turnheld += realtics;
th += realtics;
else
turnheld = 0;
th = 0;
if (turnheld < SLOWTURNTICS)
if (th < SLOWTURNTICS)
tspeed = 2; // slow turn
else
tspeed = speed;
// let movement keys cancel each other out
if (cv_analog.value) // Analog
if (analog) // Analog
{
if (turnright)
cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]);
if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
}
if (cv_analog.value || twodlevel
if (analog || twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| (!demoplayback && (player->climbing
|| (player->pflags & PF_NIGHTSMODE)
|| (player->pflags & PF_SLIDING)
|| (player->pflags & PF_FORCESTRAFE)))) // Analog
forcestrafe = true;
if (forcestrafe) // Analog
{
if (turnright)
@ -1226,7 +1331,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
}
/*
axis = JoyAxis(AXISSTRAFE);
axis = JoyAxis(AXISSTRAFE, ssplayer);
if (gamepadjoystickmove && axis != 0)
{
if (axis < 0)
@ -1242,26 +1347,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
*/
// forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
if (PLAYER1INPUTDOWN(gc_accelerate) || player->kartstuff[k_mushroomtimer])
if (InputDown(gc_accelerate, ssplayer) || player->kartstuff[k_mushroomtimer])
{
cmd->buttons |= BT_ACCELERATE;
forward = forwardmove[1]; // 50
}
if (PLAYER1INPUTDOWN(gc_brake))
if (InputDown(gc_brake, ssplayer))
{
cmd->buttons |= BT_BRAKE;
forward -= forwardmove[0]; // 25 - Halved value so clutching is possible
}
// But forward/backward IS used for aiming.
axis = JoyAxis(AXISMOVE);
if (PLAYER1INPUTDOWN(gc_aimforward) || (gamepadjoystickmove && axis < 0) || (analogjoystickmove && axis < 0))
axis = JoyAxis(AXISMOVE, ssplayer);
if (InputDown(gc_aimforward, ssplayer) || (gamepadjoystickmove && axis < 0) || (analogjoystickmove && axis < 0))
cmd->buttons |= BT_FORWARD;
if (PLAYER1INPUTDOWN(gc_aimbackward) || (gamepadjoystickmove && axis > 0) || (analogjoystickmove && axis > 0))
if (InputDown(gc_aimbackward, ssplayer) || (gamepadjoystickmove && axis > 0) || (analogjoystickmove && axis > 0))
cmd->buttons |= BT_BACKWARD;
/*
if (PLAYER1INPUTDOWN(gc_forward) || (gamepadjoystickmove && axis < 0))
if (InputDown(gc_forward, ssplayer) || (gamepadjoystickmove && axis < 0))
forward = forwardmove[speed];
if (PLAYER1INPUTDOWN(gc_backward) || (gamepadjoystickmove && axis > 0))
if (InputDown(gc_backward, ssplayer) || (gamepadjoystickmove && axis > 0))
forward -= forwardmove[speed];
*/
@ -1274,14 +1379,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
// those people are weird
/* // SRB2kart - these aren't used in kart
if (PLAYER1INPUTDOWN(gc_straferight))
if (InputDown(gc_straferight, ssplayer))
side += sidemove[speed];
if (PLAYER1INPUTDOWN(gc_strafeleft))
if (InputDown(gc_strafeleft, ssplayer))
side -= sidemove[speed];
if (PLAYER1INPUTDOWN(gc_driftleft))
if (InputDown(gc_driftleft, ssplayer))
cmd->buttons |= BT_WEAPONNEXT; // Next Weapon
if (PLAYER1INPUTDOWN(gc_driftright))
if (InputDown(gc_driftright, ssplayer))
cmd->buttons |= BT_WEAPONPREV; // Previous Weapon
*/
@ -1291,38 +1396,38 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
//use the four avaliable bits to determine the weapon.
cmd->buttons &= ~BT_WEAPONMASK;
for (i = 0; i < NUM_WEAPONS; ++i)
if (PLAYER1INPUTDOWN(gc_wepslot1 + i))
if (InputDown(gc_wepslot1 + i, ssplayer))
{
cmd->buttons |= (UINT16)(i + 1);
break;
}
// fire with any button/key
axis = JoyAxis(AXISFIRE);
if (PLAYER1INPUTDOWN(gc_fire) || (cv_usejoystick.value && axis > 0))
axis = JoyAxis(AXISFIRE, ssplayer);
if (InputDown(gc_fire, ssplayer) || (cv_usejoystick.value && axis > 0))
cmd->buttons |= BT_ATTACK;
// fire normal with any button/key
/*
axis = JoyAxis(AXISFIRENORMAL);
if (PLAYER1INPUTDOWN(gc_accelerate) || (cv_usejoystick.value && axis > 0))
axis = JoyAxis(ssplayer, AXISFIRENORMAL);
if (InputDown(gc_accelerate, ssplayer) || (cv_usejoystick.value && axis > 0))
cmd->buttons |= BT_ACCELERATE;
*/
if (PLAYER1INPUTDOWN(gc_spectate))
if (InputDown(gc_spectate, ssplayer))
cmd->buttons |= BT_SPECTATE;
// Lua scriptable buttons
if (PLAYER1INPUTDOWN(gc_custom1))
if (InputDown(gc_custom1, ssplayer))
cmd->buttons |= BT_CUSTOM1;
if (PLAYER1INPUTDOWN(gc_custom2))
if (InputDown(gc_custom2, ssplayer))
cmd->buttons |= BT_CUSTOM2;
if (PLAYER1INPUTDOWN(gc_custom3))
if (InputDown(gc_custom3, ssplayer))
cmd->buttons |= BT_CUSTOM3;
// use with any button/key
/*
if (PLAYER1INPUTDOWN(gc_brake))
if (InputDown(gc_brake, ssplayer))
cmd->buttons |= BT_BRAKE;
*/
@ -1330,17 +1435,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
/*
if (cv_debug || cv_analog.value || demoplayback || objectplacing || player->pflags & PF_NIGHTSMODE)
{
if (PLAYER1INPUTDOWN(gc_aimforward))
if (InputDown(gc_aimforward, ssplayer))
cmd->buttons |= BT_FORWARD;
if (PLAYER1INPUTDOWN(gc_aimbackward))
if (InputDown(gc_aimbackward, ssplayer))
cmd->buttons |= BT_BACKWARD;
}
*/
/*
if (PLAYER1INPUTDOWN(gc_lookback))
if (InputDown(gc_lookback, ssplayer))
{
if (camera.chase && !player->kartstuff[k_camspin])
if (thiscam->chase && !player->kartstuff[k_camspin])
player->kartstuff[k_camspin] = 1;
}
else if (player->kartstuff[k_camspin] > 0)
@ -1348,58 +1453,58 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
*/
// jump button
if (PLAYER1INPUTDOWN(gc_jump))
if (InputDown(gc_jump, ssplayer))
cmd->buttons |= BT_JUMP;
// player aiming shit, ahhhh...
{
INT32 player_invert = cv_invertmouse.value ? -1 : 1;
INT32 player_invert = invertmouse ? -1 : 1;
INT32 screen_invert =
(player->mo && (player->mo->eflags & MFE_VERTICALFLIP)
&& (!camera.chase || player->pflags & PF_FLIPCAM)) //because chasecam's not inverted
&& (!thiscam->chase || player->pflags & PF_FLIPCAM)) //because chasecam's not inverted
? -1 : 1; // set to -1 or 1 to multiply
// mouse look stuff (mouse look is not the same as mouse aim)
if (mouseaiming)
{
keyboard_look = false;
kbl = false;
// looking up/down
localaiming += (mlooky<<19)*player_invert*screen_invert;
laim += (mlooky<<19)*player_invert*screen_invert;
}
axis = JoyAxis(AXISLOOK);
if (analogjoystickmove && axis != 0 && cv_lookaxis.value != 0)
localaiming += (axis<<16) * screen_invert;
axis = JoyAxis(AXISLOOK, ssplayer);
if (analogjoystickmove && axis != 0 && lookaxis)
laim += (axis<<16) * screen_invert;
// spring back if not using keyboard neither mouselookin'
if (!keyboard_look && cv_lookaxis.value == 0 && !mouseaiming)
localaiming = 0;
if (!kbl && !lookaxis && !mouseaiming)
laim = 0;
if (PLAYER1INPUTDOWN(gc_lookup) || (gamepadjoystickmove && axis < 0))
if (InputDown(gc_lookup, ssplayer) || (gamepadjoystickmove && axis < 0))
{
localaiming += KB_LOOKSPEED * screen_invert;
keyboard_look = true;
laim += KB_LOOKSPEED * screen_invert;
kbl = true;
}
else if (PLAYER1INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && axis > 0))
else if (InputDown(gc_lookdown, ssplayer) || (gamepadjoystickmove && axis > 0))
{
localaiming -= KB_LOOKSPEED * screen_invert;
keyboard_look = true;
laim -= KB_LOOKSPEED * screen_invert;
kbl = true;
}
else if (PLAYER1INPUTDOWN(gc_centerview))
localaiming = 0;
else if (InputDown(gc_centerview, ssplayer))
laim = 0;
// accept no mlook for network games
if (!cv_allowmlook.value)
localaiming = 0;
laim = 0;
cmd->aiming = G_ClipAimingPitch(&localaiming);
cmd->aiming = G_ClipAimingPitch(&laim);
}
if (!mouseaiming && cv_mousemove.value)
forward += mousey;
if (cv_analog.value ||
if (analog ||
(!demoplayback && (player->climbing
|| (player->pflags & PF_SLIDING)))) // Analog for mouse
side += mousex*2;
@ -1426,7 +1531,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
}
//Silly hack to make 2d mode *somewhat* playable with no chasecam.
if ((twodlevel || (player->mo && player->mo->flags2 & MF2_TWOD)) && !camera.chase)
if ((twodlevel || (player->mo && player->mo->flags2 & MF2_TWOD)) && !thiscam->chase)
{
INT32 temp = forward;
forward = side;
@ -1437,7 +1542,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
cmd->sidemove = (SINT8)(cmd->sidemove + side);
//{ SRB2kart - Drift support
axis = JoyAxis(AXISTURN);
axis = JoyAxis(AXISTURN, ssplayer);
if (cmd->angleturn > 0) // Drifting to the left
cmd->buttons |= BT_DRIFTLEFT;
@ -1450,339 +1555,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
cmd->buttons &= ~BT_DRIFTRIGHT;
//}
if (cv_analog.value) {
cmd->angleturn = (INT16)(thiscam->angle >> 16);
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
}
else
{
// limit turning to angleturn[1] to stop mouselook letting you look too fast
if (cmd->angleturn > angleturn[1])
cmd->angleturn = angleturn[1];
else if (cmd->angleturn < -angleturn[1])
cmd->angleturn = -angleturn[1];
if (player->mo)
cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn);
// SRB2kart - no additional angle if not moving
if ((player->mo && player->speed > 0) || (leveltime > 140 && (cmd->buttons & BT_ACCELERATE) && (cmd->buttons & BT_BRAKE)))
localangle += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(localangle >> 16);
}
//Reset away view if a command is given.
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer)
displayplayer = consoleplayer;
}
// like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ...
void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
{
boolean forcestrafe = false;
INT32 tspeed, forward, side, axis, i;
const INT32 speed = 1;
// these ones used for multiple conditions
boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove;
player_t *player = &players[secondarydisplayplayer];
camera_t *thiscam = (player->bot == 2 ? &camera : &camera2);
static INT32 turnheld; // for accelerative turning
static boolean keyboard_look; // true if lookup/down using keyboard
static boolean resetdown; // don't cam reset every frame
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver
//why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn.
if (paused || P_AutoPause() || player->playerstate == PST_REBORN)
{
cmd->angleturn = (INT16)(localangle2 >> 16);
cmd->aiming = G_ClipAimingPitch(&localaiming2);
return;
}
turnright = PLAYER2INPUTDOWN(gc_turnright);
turnleft = PLAYER2INPUTDOWN(gc_turnleft);
mouseaiming = (PLAYER2INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook2.value;
analogjoystickmove = cv_usejoystick2.value && !Joystick2.bGamepadStyle;
gamepadjoystickmove = cv_usejoystick2.value && Joystick2.bGamepadStyle;
axis = Joy2Axis(AXISTURN);
if (gamepadjoystickmove && axis != 0)
{
turnright = turnright || (axis > 0);
turnleft = turnleft || (axis < 0);
}
forward = side = 0;
// use two stage accelerative turning
// on the keyboard and joystick
if (turnleft || turnright)
turnheld += realtics;
else
turnheld = 0;
if (turnheld < SLOWTURNTICS)
tspeed = 2; // slow turn
else
tspeed = speed;
// let movement keys cancel each other out
if (cv_analog2.value) // Analog
{
if (turnright)
cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]);
if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
}
if (cv_analog2.value || twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| player->climbing
|| (player->pflags & PF_NIGHTSMODE)
|| (player->pflags & PF_SLIDING)
|| (player->pflags & PF_FORCESTRAFE)) // Analog
forcestrafe = true;
if (forcestrafe) // Analog
{
if (turnright)
side += sidemove[speed];
if (turnleft)
side -= sidemove[speed];
if (analogjoystickmove && axis != 0)
{
// JOYAXISRANGE is supposed to be 1023 (divide by 1024)
side += ((axis * sidemove[1]) >> 10);
}
}
else
{
if (turnright)
cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]);
else if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
if (analogjoystickmove && axis != 0)
{
// JOYAXISRANGE should be 1023 (divide by 1024)
cmd->angleturn = (INT16)(cmd->angleturn - ((axis * angleturn[1]) >> 10)); // ANALOG!
}
}
/*
axis = Joy2Axis(AXISSTRAFE);
if (gamepadjoystickmove && axis != 0)
{
if (axis < 0)
side += sidemove[speed];
else if (axis > 0)
side -= sidemove[speed];
}
else if (analogjoystickmove && axis != 0)
{
// JOYAXISRANGE is supposed to be 1023 (divide by 1024)
side += ((axis * sidemove[1]) >> 10);
}
*/
// forward with key or button
if (PLAYER2INPUTDOWN(gc_accelerate) || player->kartstuff[k_mushroomtimer])
{
cmd->buttons |= BT_ACCELERATE;
forward = forwardmove[1];
}
if (PLAYER2INPUTDOWN(gc_brake))
{
cmd->buttons |= BT_BRAKE;
forward -= forwardmove[0];
}
// forward/backward is used for aiming.
axis = Joy2Axis(AXISMOVE);
if (PLAYER2INPUTDOWN(gc_aimforward) || (gamepadjoystickmove && axis < 0))
cmd->buttons |= BT_FORWARD;
if (PLAYER2INPUTDOWN(gc_aimbackward) || (gamepadjoystickmove && axis > 0))
cmd->buttons |= BT_BACKWARD;
/*
if (analogjoystickmove && axis != 0)
forward -= ((axis * forwardmove[1]) >> 10); // ANALOG!
*/
// some people strafe left & right with mouse buttons
// those people are (still) weird
if (PLAYER2INPUTDOWN(gc_straferight))
side += sidemove[speed];
if (PLAYER2INPUTDOWN(gc_strafeleft))
side -= sidemove[speed];
/* // SRB2kart - these aren't used in kart
if (PLAYER2INPUTDOWN(gc_weaponnext))
cmd->buttons |= BT_WEAPONNEXT; // Next Weapon
if (PLAYER2INPUTDOWN(gc_weaponprev))
cmd->buttons |= BT_WEAPONPREV; // Previous Weapon
*/
//use the four avaliable bits to determine the weapon.
cmd->buttons &= ~BT_WEAPONMASK;
for (i = 0; i < NUM_WEAPONS; ++i)
if (PLAYER2INPUTDOWN(gc_wepslot1 + i))
{
cmd->buttons |= (UINT16)(i + 1);
break;
}
// fire with any button/key
axis = Joy2Axis(AXISFIRE);
if (PLAYER2INPUTDOWN(gc_fire) || (cv_usejoystick2.value && axis > 0))
cmd->buttons |= BT_ATTACK;
// fire normal with any button/key
/*
axis = Joy2Axis(AXISFIRENORMAL);
if (PLAYER2INPUTDOWN(gc_accelerate) || (cv_usejoystick2.value && axis > 0))
cmd->buttons |= BT_ACCELERATE;
*/
if (PLAYER2INPUTDOWN(gc_spectate))
cmd->buttons |= BT_SPECTATE;
// Lua scriptable buttons
if (PLAYER2INPUTDOWN(gc_custom1))
cmd->buttons |= BT_CUSTOM1;
if (PLAYER2INPUTDOWN(gc_custom2))
cmd->buttons |= BT_CUSTOM2;
if (PLAYER2INPUTDOWN(gc_custom3))
cmd->buttons |= BT_CUSTOM3;
// use with any button/key
if (PLAYER2INPUTDOWN(gc_brake))
cmd->buttons |= BT_BRAKE;
// Camera Controls
if (cv_debug || cv_analog2.value || player->pflags & PF_NIGHTSMODE)
{
if (PLAYER2INPUTDOWN(gc_aimforward))
cmd->buttons |= BT_FORWARD;
if (PLAYER2INPUTDOWN(gc_aimbackward))
cmd->buttons |= BT_BACKWARD;
}
if (PLAYER2INPUTDOWN(gc_lookback))
{
if (camera2.chase && !resetdown)
P_ResetCamera(&players[secondarydisplayplayer], &camera2); // TODO: Replace with a camflip
resetdown = true;
}
else
resetdown = false;
// jump button
if (PLAYER2INPUTDOWN(gc_jump))
cmd->buttons |= BT_JUMP;
// player aiming shit, ahhhh...
{
INT32 player_invert = cv_invertmouse2.value ? -1 : 1;
INT32 screen_invert =
(player->mo && (player->mo->eflags & MFE_VERTICALFLIP)
&& (!camera2.chase || player->pflags & PF_FLIPCAM)) //because chasecam's not inverted
? -1 : 1; // set to -1 or 1 to multiply
// mouse look stuff (mouse look is not the same as mouse aim)
if (mouseaiming)
{
keyboard_look = false;
// looking up/down
localaiming2 += (mlook2y<<19)*player_invert*screen_invert;
}
axis = Joy2Axis(AXISLOOK);
if (analogjoystickmove && axis != 0 && cv_lookaxis2.value != 0)
localaiming2 += (axis<<16) * screen_invert;
// spring back if not using keyboard neither mouselookin'
if (!keyboard_look && cv_lookaxis2.value == 0 && !mouseaiming)
localaiming2 = 0;
if (PLAYER2INPUTDOWN(gc_lookup) || (gamepadjoystickmove && axis < 0))
{
localaiming2 += KB_LOOKSPEED * screen_invert;
keyboard_look = true;
}
else if (PLAYER2INPUTDOWN(gc_lookdown) || (gamepadjoystickmove && axis > 0))
{
localaiming2 -= KB_LOOKSPEED * screen_invert;
keyboard_look = true;
}
else if (PLAYER2INPUTDOWN(gc_centerview))
localaiming2 = 0;
// accept no mlook for network games
if (!cv_allowmlook.value)
localaiming2 = 0;
cmd->aiming = G_ClipAimingPitch(&localaiming2);
}
if (!mouseaiming && cv_mousemove2.value)
forward += mouse2y;
if (cv_analog2.value || player->climbing
|| (player->pflags & PF_SLIDING)) // Analog for mouse
side += mouse2x*2;
else
cmd->angleturn = (INT16)(cmd->angleturn - (mouse2x*8));
mouse2x = mouse2y = mlook2y = 0;
if (forward > MAXPLMOVE)
forward = MAXPLMOVE;
else if (forward < -MAXPLMOVE)
forward = -MAXPLMOVE;
if (side > MAXPLMOVE)
side = MAXPLMOVE;
else if (side < -MAXPLMOVE)
side = -MAXPLMOVE;
// No additional acceleration when moving forward/backward and strafing simultaneously.
// do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this.
if (!forcestrafe && forward && side)
{
forward = FixedMul(forward, 3*FRACUNIT/4);
side = FixedMul(side, 3*FRACUNIT/4);
}
//Silly hack to make 2d mode *somewhat* playable with no chasecam.
if ((twodlevel || (player->mo && player->mo->flags2 & MF2_TWOD)) && !camera2.chase)
{
INT32 temp = forward;
forward = side;
side = temp;
}
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
cmd->sidemove = (SINT8)(cmd->sidemove + side);
//{ SRB2kart - Drift support
axis = Joy2Axis(AXISTURN);
if (cmd->angleturn > 0) // Drifting to the left
cmd->buttons |= BT_DRIFTLEFT;
else
cmd->buttons &= ~BT_DRIFTLEFT;
if (cmd->angleturn < 0) // Drifting to the right
cmd->buttons |= BT_DRIFTRIGHT;
else
cmd->buttons &= ~BT_DRIFTRIGHT;
//}
if (player->bot == 1) {
if (ssplayer == 2 && player->bot == 1) {
if (!player->powers[pw_tailsfly] && (cmd->forwardmove || cmd->sidemove || cmd->buttons))
{
player->bot = 2; // A player-controlled bot. Returns to AI when it respawns.
@ -1795,7 +1568,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
}
}
if (cv_analog2.value) {
if (analog) {
cmd->angleturn = (INT16)(thiscam->angle >> 16);
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
@ -1813,10 +1586,44 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
// SRB2kart - no additional angle if not moving
if ((player->mo && player->speed > 0) || (leveltime > 140 && (cmd->buttons & BT_ACCELERATE) && (cmd->buttons & BT_BRAKE)))
localangle2 += (cmd->angleturn<<16);
lang += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(localangle2 >> 16);
cmd->angleturn = (INT16)(lang >> 16);
}
if (ssplayer == 2)
{
localangle2 = lang;
localaiming2 = laim;
keyboard_look2 = kbl;
turnheld2 = th;
}
else if (ssplayer == 3)
{
localangle3 = lang;
localaiming3 = laim;
keyboard_look3 = kbl;
turnheld3 = th;
}
else if (ssplayer == 4)
{
localangle4 = lang;
localaiming4 = laim;
keyboard_look4 = kbl;
turnheld4 = th;
}
else
{
localangle = lang;
localaiming = laim;
keyboard_look = kbl;
turnheld = th;
}
//Reset away view if a command is given.
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer && ssplayer == 1)
displayplayer = consoleplayer;
}
// User has designated that they want
@ -1978,8 +1785,12 @@ void G_DoLoadLevel(boolean resetplayer)
P_FindEmerald();
displayplayer = consoleplayer; // view the guy you are playing
if (!splitscreen && !botingame)
if (!(splitscreen || splitscreen3 || splitscreen4) && !botingame)
secondarydisplayplayer = consoleplayer;
if (!(splitscreen3 || splitscreen4))
thirddisplayplayer = consoleplayer;
if (!splitscreen4)
fourthdisplayplayer = consoleplayer;
gameaction = ga_nothing;
#ifdef PARANOIA
@ -2232,6 +2043,11 @@ boolean G_Responder(event_t *ev)
case ev_joystick2:
return true; // eat events
case ev_joystick3:
return true; // eat events
case ev_joystick4:
return true; // eat events
default:
break;
@ -2752,13 +2568,19 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
{
if (nummapthings)
{
if (playernum == consoleplayer || ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer) || ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer) || (splitscreen4 && playernum == fourthdisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n"));
spawnpoint = &mapthings[0];
}
else
{
if (playernum == consoleplayer || ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer) || ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer) || (splitscreen4 && playernum == fourthdisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n"));
//P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL.
}
@ -2777,7 +2599,10 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
if (!numredctfstarts && !numbluectfstarts) //why even bother, eh?
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n"));
return NULL;
}
@ -2786,7 +2611,10 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
{
if (!numredctfstarts)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No Red Team starts in this map!\n"));
return NULL;
}
@ -2798,7 +2626,10 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
return redctfstarts[i];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Red Team starts!\n"));
return NULL;
}
@ -2806,7 +2637,10 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
{
if (!numbluectfstarts)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No Blue Team starts in this map!\n"));
return NULL;
}
@ -2817,7 +2651,10 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
if (G_CheckSpot(playernum, bluectfstarts[i]))
return bluectfstarts[i];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Blue Team starts!\n"));
return NULL;
}
@ -2837,12 +2674,18 @@ mapthing_t *G_FindMatchStart(INT32 playernum)
if (G_CheckSpot(playernum, deathmatchstarts[i]))
return deathmatchstarts[i];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Deathmatch starts!\n"));
return NULL;
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No Deathmatch starts in this map!\n"));
return NULL;
}
@ -2860,7 +2703,10 @@ mapthing_t *G_FindCoopStart(INT32 playernum)
return playerstarts[0];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
if (playernum == consoleplayer
|| ((splitscreen || splitscreen3 || splitscreen4) && playernum == secondarydisplayplayer)
|| ((splitscreen3 || splitscreen4) && playernum == thirddisplayplayer)
|| (splitscreen4 && playernum == fourthdisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No Co-op starts in this map!\n"));
return NULL;
}
@ -3925,7 +3771,7 @@ void G_SaveGame(UINT32 savegameslot)
// Can be called by the startup code or the menu task,
// consoleplayer, displayplayer, playeringame[] should be set.
//
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS)
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS)
{
UINT8 color = 0;
paused = false;
@ -3944,9 +3790,27 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b
botcolor = savedata.botcolor;
botingame = (botskin != 0);
}
else if (splitscreen != SSSG)
else if (!splitscreen4 && ssplayers == 4)
{
splitscreen = SSSG;
splitscreen4 = true;
splitscreen = splitscreen3 = false;
SplitScreen_OnChange();
}
else if (!splitscreen3 && ssplayers == 3)
{
splitscreen3 = true;
splitscreen = splitscreen4 = false;
SplitScreen_OnChange();
}
else if (!splitscreen && ssplayers == 2)
{
splitscreen = true;
splitscreen3 = splitscreen4 = false;
SplitScreen_OnChange();
}
else if ((splitscreen || splitscreen3 || splitscreen4) && ssplayers == 1)
{
splitscreen = splitscreen3 = splitscreen4 = false;
SplitScreen_OnChange();
}

View file

@ -69,8 +69,7 @@ extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_last, cv_ghost_
// build an internal map name MAPxx from map number
const char *G_BuildMapName(INT32 map);
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics);
void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics);
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
// copy ticcmd_t to and fro the normal way
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n);
@ -82,7 +81,7 @@ INT16 G_ClipAimingPitch(INT32 *aiming);
INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
extern angle_t localangle, localangle2, localangle3, localangle4;
extern INT32 localaiming, localaiming2; // should be an angle_t but signed
extern INT32 localaiming, localaiming2, localaiming3, localaiming4; // should be an angle_t but signed
//
// GAME
@ -103,7 +102,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost);
// Can be called by the startup code or M_Responder.
// A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,
boolean SSSG, boolean FLS);
UINT8 ssplayers, boolean FLS);
void G_DoLoadLevel(boolean resetplayer);
void G_DeferedPlayDemo(const char *demo);

View file

@ -174,6 +174,18 @@ void G_MapEventsToControls(event_t *ev)
flag = G_CheckDoubleClick(gamekeydown[KEY_2JOY1+i], &joy2dclicks[i]);
gamekeydown[KEY_DBL2JOY1+i] = flag;
}
for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++)
{
flag = G_CheckDoubleClick(gamekeydown[KEY_3JOY1+i], &joy3dclicks[i]);
gamekeydown[KEY_DBL3JOY1+i] = flag;
}
for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++)
{
flag = G_CheckDoubleClick(gamekeydown[KEY_4JOY1+i], &joy4dclicks[i]);
gamekeydown[KEY_DBL4JOY1+i] = flag;
}
}
//
@ -970,6 +982,602 @@ static keyname_t keynames[] =
#endif
#endif
#ifdef DC
{KEY_3JOY1+0, "TRD_JOYC"},
{KEY_3JOY1+1, "TRD_JOYB"},
{KEY_3JOY1+2, "TRD_JOYA"},
{KEY_3JOY1+3, "TRD_JOYS"},
{KEY_3JOY1+4, "TRD_JOYZ"},
{KEY_3JOY1+5, "TRD_JOYY"},
{KEY_3JOY1+6, "TRD_JOYX"},
{KEY_3JOY1+7, "TRD_JOYD"},
#elif defined (_XBOX)
{KEY_3JOY1+0, "TRD_JOYA"},
{KEY_3JOY1+1, "TRD_JOYB"},
{KEY_3JOY1+2, "TRD_JOYX"},
{KEY_3JOY1+3, "TRD_JOYY"},
{KEY_3JOY1+4, "TRD_JOYG"},
{KEY_3JOY1+5, "TRD_JOYW"},
{KEY_3JOY1+6, "TRD_JOYL"},
{KEY_3JOY1+7, "TRD_JOYR"},
{KEY_3JOY1+8, "TRD_JOYS"},
{KEY_3JOY1+9, "TRD_JOYN"},
{KEY_3JOY1+10,"TRD_JOYW"},
{KEY_3JOY1+11,"TRD_JOYE"},
#define NOMOREJOYBTN_2S
#elif defined (_PSP)
{KEY_3JOY1+0, "TRD_TRIANGLE"},
{KEY_3JOY1+1, "TRD_CIRCLE" },
{KEY_3JOY1+2, "TRD_CROSS" },
{KEY_3JOY1+3, "TRD_SQUARE" },
{KEY_3JOY1+4, "TRD_LTRIGGER"},
{KEY_3JOY1+5, "TRD_RTRIGGER"},
{KEY_3JOY1+6, "TRD_SELECT" },
{KEY_3JOY1+7, "TRD_START" },
{KEY_3JOY1+8, "TRD_HOME" },
{KEY_3JOY1+9, "TRD_HOLD" },
#define NOMOREJOYBTN_2S
#elif defined (WMINPUT)
{KEY_3JOY1+0, "TRD_JOYB"},
{KEY_3JOY1+1, "TRD_JOYA"},
{KEY_3JOY1+2, "TRD_JOYUP"},
{KEY_3JOY1+3, "TRD_JOYDOWN"},
{KEY_3JOY1+4, "TRD_JOYLEFT"},
{KEY_3JOY1+5, "TRD_JOYRIGHT"},
{KEY_3JOY1+6, "TRD_JOYAA"},
{KEY_3JOY1+7, "TRD_JOYBB"},
{KEY_3JOY1+8, "TRD_JOYCC"},
{KEY_3JOY1+9, "TRD_JOYXX"},
{KEY_3JOY1+10, "TRD_JOYYY"},
{KEY_3JOY1+11, "TRD_JOYZZ"},
{KEY_3JOY1+12, "TRD_JOYL"},
{KEY_3JOY1+13, "TRD_JOYR"},
{KEY_3JOY1+14, "TRD_JOYZL"},
{KEY_3JOY1+15, "TRD_JOYZR"},
{KEY_3JOY1+16, "TRD_JOYSELECT"},
{KEY_3JOY1+17, "TRD_JOYSTART"},
{KEY_3JOY1+18, "TRD_JOYHOME"},
{KEY_3JOY1+19, "TRD_JOYMINUS"},
{KEY_3JOY1+20, "TRD_JOYPLUS"},
{KEY_3JOY1+21, "TRD_JOY_1"},
{KEY_3JOY1+22, "TRD_JOY_2"},
{KEY_3JOY1+23, "TRD_JOY24"},
{KEY_3JOY1+24, "TRD_JOY25"},
{KEY_3JOY1+25, "TRD_JOY26"},
{KEY_3JOY1+26, "TRD_JOY27"},
{KEY_3JOY1+27, "TRD_JOY28"},
{KEY_3JOY1+28, "TRD_JOY29"},
{KEY_3JOY1+29, "TRD_JOY30"},
{KEY_3JOY1+30, "TRD_JOY31"},
{KEY_3JOY1+31, "TRD_JOY32"},
#define NOMOREJOYBTN_2S
#elif defined (_WII)
{KEY_3JOY1+0, "TRD_JOYA"},
{KEY_3JOY1+1, "TRD_JOYB"},
{KEY_3JOY1+2, "TRD_JOY1"},
{KEY_3JOY1+3, "TRD_JOY2"},
{KEY_3JOY1+4, "TRD_JOYMINUS"},
{KEY_3JOY1+5, "TRD_JOYPLUS"},
{KEY_3JOY1+6, "TRD_JOYHOME"},
{KEY_3JOY1+7, "TRD_JOYZ"},
{KEY_3JOY1+8, "TRD_JOYC"},
{KEY_3JOY1+9, "TRD_JOYA_CC"},
{KEY_3JOY1+10, "TRD_JOYB_CC"},
{KEY_3JOY1+11, "TRD_JOYX"},
{KEY_3JOY1+12, "TRD_JOYY"},
{KEY_3JOY1+13, "TRD_JOYL"},
{KEY_3JOY1+14, "TRD_JOYR"},
{KEY_3JOY1+15, "TRD_JOYZL"},
{KEY_3JOY1+16, "TRD_JOYZR"},
{KEY_3JOY1+17, "TRD_JOYMINUS_CC"},
{KEY_3JOY1+18, "TRD_JOYHPLUS_CC"},
{KEY_3JOY1+19, "TRD_JOYMHOME_CC"},
#define NOMOREJOYBTN_2S
#else
{KEY_3JOY1+0, "TRD_JOY1"},
{KEY_3JOY1+1, "TRD_JOY2"},
{KEY_3JOY1+2, "TRD_JOY3"},
{KEY_3JOY1+3, "TRD_JOY4"},
{KEY_3JOY1+4, "TRD_JOY5"},
{KEY_3JOY1+5, "TRD_JOY6"},
{KEY_3JOY1+6, "TRD_JOY7"},
{KEY_3JOY1+7, "TRD_JOY8"},
#endif
#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_2S)
// we use up to 32 buttons in DirectInput
{KEY_3JOY1+8, "TRD_JOY9"},
{KEY_3JOY1+9, "TRD_JOY10"},
{KEY_3JOY1+10, "TRD_JOY11"},
{KEY_3JOY1+11, "TRD_JOY12"},
{KEY_3JOY1+12, "TRD_JOY13"},
{KEY_3JOY1+13, "TRD_JOY14"},
{KEY_3JOY1+14, "TRD_JOY15"},
{KEY_3JOY1+15, "TRD_JOY16"},
{KEY_3JOY1+16, "TRD_JOY17"},
{KEY_3JOY1+17, "TRD_JOY18"},
{KEY_3JOY1+18, "TRD_JOY19"},
{KEY_3JOY1+19, "TRD_JOY20"},
{KEY_3JOY1+20, "TRD_JOY21"},
{KEY_3JOY1+21, "TRD_JOY22"},
{KEY_3JOY1+22, "TRD_JOY23"},
{KEY_3JOY1+23, "TRD_JOY24"},
{KEY_3JOY1+24, "TRD_JOY25"},
{KEY_3JOY1+25, "TRD_JOY26"},
{KEY_3JOY1+26, "TRD_JOY27"},
{KEY_3JOY1+27, "TRD_JOY28"},
{KEY_3JOY1+28, "TRD_JOY29"},
{KEY_3JOY1+29, "TRD_JOY30"},
{KEY_3JOY1+30, "TRD_JOY31"},
{KEY_3JOY1+31, "TRD_JOY32"},
#endif
// the DOS version uses Allegro's joystick support
{KEY_3HAT1+0, "TRD_HATUP"},
{KEY_3HAT1+1, "TRD_HATDOWN"},
{KEY_3HAT1+2, "TRD_HATLEFT"},
{KEY_3HAT1+3, "TRD_HATRIGHT"},
#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII)
{KEY_3HAT1+4, "TRD_HATUP2"},
{KEY_3HAT1+5, "TRD_HATDOWN2"},
{KEY_3HAT1+6, "TRD_HATLEFT2"},
{KEY_3HAT1+7, "TRD_HATRIGHT2"},
#ifndef _arch_dreamcast
{KEY_3HAT1+8, "TRD_HATUP3"},
{KEY_3HAT1+9, "TRD_HATDOWN3"},
{KEY_3HAT1+10, "TRD_HATLEFT3"},
{KEY_3HAT1+11, "TRD_HATRIGHT3"},
{KEY_3HAT1+12, "TRD_HATUP4"},
{KEY_3HAT1+13, "TRD_HATDOWN4"},
{KEY_3HAT1+14, "TRD_HATLEFT4"},
{KEY_3HAT1+15, "TRD_HATRIGHT4"},
#endif
#endif
#ifdef DC
{KEY_DBL3JOY1+0, "DBLTRD_JOYC"},
{KEY_DBL3JOY1+1, "DBLTRD_JOYB"},
{KEY_DBL3JOY1+2, "DBLTRD_JOYA"},
{KEY_DBL3JOY1+3, "DBLTRD_JOYS"},
{KEY_DBL3JOY1+4, "DBLTRD_JOYZ"},
{KEY_DBL3JOY1+5, "DBLTRD_JOYY"},
{KEY_DBL3JOY1+6, "DBLTRD_JOYX"},
{KEY_DBL3JOY1+7, "DBLTRD_JOYD"},
#elif defined (_XBOX)
{KEY_DBL3JOY1+0, "DBLTRD_JOYA"},
{KEY_DBL3JOY1+1, "DBLTRD_JOYB"},
{KEY_DBL3JOY1+2, "DBLTRD_JOYX"},
{KEY_DBL3JOY1+3, "DBLTRD_JOYY"},
{KEY_DBL3JOY1+4, "DBLTRD_JOYG"},
{KEY_DBL3JOY1+5, "DBLTRD_JOYW"},
{KEY_DBL3JOY1+6, "DBLTRD_JOYL"},
{KEY_DBL3JOY1+7, "DBLTRD_JOYR"},
{KEY_DBL3JOY1+8, "DBLTRD_JOYS"},
{KEY_DBL3JOY1+9, "DBLTRD_JOYN"},
{KEY_DBL3JOY1+10,"DBLTRD_JOYW"},
{KEY_DBL3JOY1+11,"DBLTRD_JOYE"},
#define NOMOREJOYBTN_2DBL
#elif defined (_PSP)
{KEY_DBL3JOY1+0, "DBLTRD_TRIANGLE"},
{KEY_DBL3JOY1+1, "DBLTRD_CIRCLE" },
{KEY_DBL3JOY1+2, "DBLTRD_CROSS" },
{KEY_DBL3JOY1+3, "DBLTRD_SQUARE" },
{KEY_DBL3JOY1+4, "DBLTRD_LTRIGGER"},
{KEY_DBL3JOY1+5, "DBLTRD_RTRIGGER"},
{KEY_DBL3JOY1+6, "DBLTRD_SELECT" },
{KEY_DBL3JOY1+7, "DBLTRD_START" },
{KEY_DBL3JOY1+8, "DBLTRD_HOME" },
{KEY_DBL3JOY1+9, "DBLTRD_HOLD" },
#define NOMOREJOYBTN_2DBL
#elif defined (WMINPUT)
{KEY_DBL3JOY1+0, "DBLTRD_JOYB"},
{KEY_DBL3JOY1+1, "DBLTRD_JOYA"},
{KEY_DBL3JOY1+2, "DBLTRD_JOYUP"},
{KEY_DBL3JOY1+3, "DBLTRD_JOYDOWN"},
{KEY_DBL3JOY1+4, "DBLTRD_JOYLEFT"},
{KEY_DBL3JOY1+5, "DBLTRD_JOYRIGHT"},
{KEY_DBL3JOY1+6, "DBLTRD_JOYAA"},
{KEY_DBL3JOY1+7, "DBLTRD_JOYBB"},
{KEY_DBL3JOY1+8, "DBLTRD_JOYCC"},
{KEY_DBL3JOY1+9, "DBLTRD_JOYXX"},
{KEY_DBL3JOY1+10, "DBLTRD_JOYYY"},
{KEY_DBL3JOY1+11, "DBLTRD_JOYZZ"},
{KEY_DBL3JOY1+12, "DBLTRD_JOYL"},
{KEY_DBL3JOY1+13, "DBLTRD_JOYR"},
{KEY_DBL3JOY1+14, "DBLTRD_JOYZL"},
{KEY_DBL3JOY1+15, "DBLTRD_JOYZR"},
{KEY_DBL3JOY1+16, "DBLTRD_JOYSELECT"},
{KEY_DBL3JOY1+17, "DBLTRD_JOYSTART"},
{KEY_DBL3JOY1+18, "DBLTRD_JOYHOME"},
{KEY_DBL3JOY1+19, "DBLTRD_JOYMINUS"},
{KEY_DBL3JOY1+20, "DBLTRD_JOYPLUS"},
{KEY_DBL3JOY1+21, "DBLTRD_JOY_1"},
{KEY_DBL3JOY1+22, "DBLTRD_JOY_2"},
{KEY_DBL3JOY1+23, "DBLTRD_JOY24"},
{KEY_DBL3JOY1+24, "DBLTRD_JOY25"},
{KEY_DBL3JOY1+25, "DBLTRD_JOY26"},
{KEY_DBL3JOY1+26, "DBLTRD_JOY27"},
{KEY_DBL3JOY1+27, "DBLTRD_JOY28"},
{KEY_DBL3JOY1+28, "DBLTRD_JOY29"},
{KEY_DBL3JOY1+29, "DBLTRD_JOY30"},
{KEY_DBL3JOY1+30, "DBLTRD_JOY31"},
{KEY_DBL3JOY1+31, "DBLTRD_JOY32"},
#define NOMOREJOYBTN_2SDBL
#elif defined (_WII)
{KEY_DBL3JOY1+0, "DBLTRD_JOYA"},
{KEY_DBL3JOY1+1, "DBLTRD_JOYB"},
{KEY_DBL3JOY1+2, "DBLTRD_JOY1"},
{KEY_DBL3JOY1+3, "DBLTRD_JOY2"},
{KEY_DBL3JOY1+4, "DBLTRD_JOYMINUS"},
{KEY_DBL3JOY1+5, "DBLTRD_JOYPLUS"},
{KEY_DBL3JOY1+6, "DBLTRD_JOYHOME"},
{KEY_DBL3JOY1+7, "DBLTRD_JOYZ"},
{KEY_DBL3JOY1+8, "DBLTRD_JOYC"},
{KEY_DBL3JOY1+9, "DBLTRD_JOYA_CC"},
{KEY_DBL3JOY1+10, "DBLTRD_JOYB_CC"},
{KEY_DBL3JOY1+11, "DBLTRD_JOYX"},
{KEY_DBL3JOY1+12, "DBLTRD_JOYY"},
{KEY_DBL3JOY1+13, "DBLTRD_JOYL"},
{KEY_DBL3JOY1+14, "DBLTRD_JOYR"},
{KEY_DBL3JOY1+15, "DBLTRD_JOYZL"},
{KEY_DBL3JOY1+16, "DBLTRD_JOYZR"},
{KEY_DBL3JOY1+17, "DBLTRD_JOYMINUS_CC"},
{KEY_DBL3JOY1+18, "DBLTRD_JOYHPLUS_CC"},
{KEY_DBL3JOY1+19, "DBLTRD_JOYMHOME_CC"},
#define NOMOREJOYBTN_2DBL
#else
{KEY_DBL3JOY1+0, "DBLTRD_JOY1"},
{KEY_DBL3JOY1+1, "DBLTRD_JOY2"},
{KEY_DBL3JOY1+2, "DBLTRD_JOY3"},
{KEY_DBL3JOY1+3, "DBLTRD_JOY4"},
{KEY_DBL3JOY1+4, "DBLTRD_JOY5"},
{KEY_DBL3JOY1+5, "DBLTRD_JOY6"},
{KEY_DBL3JOY1+6, "DBLTRD_JOY7"},
{KEY_DBL3JOY1+7, "DBLTRD_JOY8"},
#endif
#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_2DBL)
{KEY_DBL3JOY1+8, "DBLTRD_JOY9"},
{KEY_DBL3JOY1+9, "DBLTRD_JOY10"},
{KEY_DBL3JOY1+10, "DBLTRD_JOY11"},
{KEY_DBL3JOY1+11, "DBLTRD_JOY12"},
{KEY_DBL3JOY1+12, "DBLTRD_JOY13"},
{KEY_DBL3JOY1+13, "DBLTRD_JOY14"},
{KEY_DBL3JOY1+14, "DBLTRD_JOY15"},
{KEY_DBL3JOY1+15, "DBLTRD_JOY16"},
{KEY_DBL3JOY1+16, "DBLTRD_JOY17"},
{KEY_DBL3JOY1+17, "DBLTRD_JOY18"},
{KEY_DBL3JOY1+18, "DBLTRD_JOY19"},
{KEY_DBL3JOY1+19, "DBLTRD_JOY20"},
{KEY_DBL3JOY1+20, "DBLTRD_JOY21"},
{KEY_DBL3JOY1+21, "DBLTRD_JOY22"},
{KEY_DBL3JOY1+22, "DBLTRD_JOY23"},
{KEY_DBL3JOY1+23, "DBLTRD_JOY24"},
{KEY_DBL3JOY1+24, "DBLTRD_JOY25"},
{KEY_DBL3JOY1+25, "DBLTRD_JOY26"},
{KEY_DBL3JOY1+26, "DBLTRD_JOY27"},
{KEY_DBL3JOY1+27, "DBLTRD_JOY28"},
{KEY_DBL3JOY1+28, "DBLTRD_JOY29"},
{KEY_DBL3JOY1+29, "DBLTRD_JOY30"},
{KEY_DBL3JOY1+30, "DBLTRD_JOY31"},
{KEY_DBL3JOY1+31, "DBLTRD_JOY32"},
#endif
{KEY_DBL3HAT1+0, "DBLTRD_HATUP"},
{KEY_DBL3HAT1+1, "DBLTRD_HATDOWN"},
{KEY_DBL3HAT1+2, "DBLTRD_HATLEFT"},
{KEY_DBL3HAT1+3, "DBLTRD_HATRIGHT"},
#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII)
{KEY_DBL3HAT1+4, "DBLTRD_HATUP2"},
{KEY_DBL3HAT1+5, "DBLTRD_HATDOWN2"},
{KEY_DBL3HAT1+6, "DBLTRD_HATLEFT2"},
{KEY_DBL3HAT1+7, "DBLTRD_HATRIGHT2"},
#ifndef _arch_dreamcast
{KEY_DBL3HAT1+8, "DBLTRD_HATUP3"},
{KEY_DBL3HAT1+9, "DBLTRD_HATDOWN3"},
{KEY_DBL3HAT1+10, "DBLTRD_HATLEFT3"},
{KEY_DBL3HAT1+11, "DBLTRD_HATRIGHT3"},
{KEY_DBL3HAT1+12, "DBLTRD_HATUP4"},
{KEY_DBL3HAT1+13, "DBLTRD_HATDOWN4"},
{KEY_DBL3HAT1+14, "DBLTRD_HATLEFT4"},
{KEY_DBL3HAT1+15, "DBLTRD_HATRIGHT4"},
#endif
#endif
#ifdef DC
{KEY_4JOY1+0, "FOR_JOYC"},
{KEY_4JOY1+1, "FOR_JOYB"},
{KEY_4JOY1+2, "FOR_JOYA"},
{KEY_4JOY1+3, "FOR_JOYS"},
{KEY_4JOY1+4, "FOR_JOYZ"},
{KEY_4JOY1+5, "FOR_JOYY"},
{KEY_4JOY1+6, "FOR_JOYX"},
{KEY_4JOY1+7, "FOR_JOYD"},
#elif defined (_XBOX)
{KEY_4JOY1+0, "FOR_JOYA"},
{KEY_4JOY1+1, "FOR_JOYB"},
{KEY_4JOY1+2, "FOR_JOYX"},
{KEY_4JOY1+3, "FOR_JOYY"},
{KEY_4JOY1+4, "FOR_JOYG"},
{KEY_4JOY1+5, "FOR_JOYW"},
{KEY_4JOY1+6, "FOR_JOYL"},
{KEY_4JOY1+7, "FOR_JOYR"},
{KEY_4JOY1+8, "FOR_JOYS"},
{KEY_4JOY1+9, "FOR_JOYN"},
{KEY_4JOY1+10,"FOR_JOYW"},
{KEY_4JOY1+11,"FOR_JOYE"},
#define NOMOREJOYBTN_2S
#elif defined (_PSP)
{KEY_4JOY1+0, "FOR_TRIANGLE"},
{KEY_4JOY1+1, "FOR_CIRCLE" },
{KEY_4JOY1+2, "FOR_CROSS" },
{KEY_4JOY1+3, "FOR_SQUARE" },
{KEY_4JOY1+4, "FOR_LTRIGGER"},
{KEY_4JOY1+5, "FOR_RTRIGGER"},
{KEY_4JOY1+6, "FOR_SELECT" },
{KEY_4JOY1+7, "FOR_START" },
{KEY_4JOY1+8, "FOR_HOME" },
{KEY_4JOY1+9, "FOR_HOLD" },
#define NOMOREJOYBTN_2S
#elif defined (WMINPUT)
{KEY_4JOY1+0, "FOR_JOYB"},
{KEY_4JOY1+1, "FOR_JOYA"},
{KEY_4JOY1+2, "FOR_JOYUP"},
{KEY_4JOY1+3, "FOR_JOYDOWN"},
{KEY_4JOY1+4, "FOR_JOYLEFT"},
{KEY_4JOY1+5, "FOR_JOYRIGHT"},
{KEY_4JOY1+6, "FOR_JOYAA"},
{KEY_4JOY1+7, "FOR_JOYBB"},
{KEY_4JOY1+8, "FOR_JOYCC"},
{KEY_4JOY1+9, "FOR_JOYXX"},
{KEY_4JOY1+10, "FOR_JOYYY"},
{KEY_4JOY1+11, "FOR_JOYZZ"},
{KEY_4JOY1+12, "FOR_JOYL"},
{KEY_4JOY1+13, "FOR_JOYR"},
{KEY_4JOY1+14, "FOR_JOYZL"},
{KEY_4JOY1+15, "FOR_JOYZR"},
{KEY_4JOY1+16, "FOR_JOYSELECT"},
{KEY_4JOY1+17, "FOR_JOYSTART"},
{KEY_4JOY1+18, "FOR_JOYHOME"},
{KEY_4JOY1+19, "FOR_JOYMINUS"},
{KEY_4JOY1+20, "FOR_JOYPLUS"},
{KEY_4JOY1+21, "FOR_JOY_1"},
{KEY_4JOY1+22, "FOR_JOY_2"},
{KEY_4JOY1+23, "FOR_JOY24"},
{KEY_4JOY1+24, "FOR_JOY25"},
{KEY_4JOY1+25, "FOR_JOY26"},
{KEY_4JOY1+26, "FOR_JOY27"},
{KEY_4JOY1+27, "FOR_JOY28"},
{KEY_4JOY1+28, "FOR_JOY29"},
{KEY_4JOY1+29, "FOR_JOY30"},
{KEY_4JOY1+30, "FOR_JOY31"},
{KEY_4JOY1+31, "FOR_JOY32"},
#define NOMOREJOYBTN_2S
#elif defined (_WII)
{KEY_4JOY1+0, "FOR_JOYA"},
{KEY_4JOY1+1, "FOR_JOYB"},
{KEY_4JOY1+2, "FOR_JOY1"},
{KEY_4JOY1+3, "FOR_JOY2"},
{KEY_4JOY1+4, "FOR_JOYMINUS"},
{KEY_4JOY1+5, "FOR_JOYPLUS"},
{KEY_4JOY1+6, "FOR_JOYHOME"},
{KEY_4JOY1+7, "FOR_JOYZ"},
{KEY_4JOY1+8, "FOR_JOYC"},
{KEY_4JOY1+9, "FOR_JOYA_CC"},
{KEY_4JOY1+10, "FOR_JOYB_CC"},
{KEY_4JOY1+11, "FOR_JOYX"},
{KEY_4JOY1+12, "FOR_JOYY"},
{KEY_4JOY1+13, "FOR_JOYL"},
{KEY_4JOY1+14, "FOR_JOYR"},
{KEY_4JOY1+15, "FOR_JOYZL"},
{KEY_4JOY1+16, "FOR_JOYZR"},
{KEY_4JOY1+17, "FOR_JOYMINUS_CC"},
{KEY_4JOY1+18, "FOR_JOYHPLUS_CC"},
{KEY_4JOY1+19, "FOR_JOYMHOME_CC"},
#define NOMOREJOYBTN_2S
#else
{KEY_4JOY1+0, "FOR_JOY1"},
{KEY_4JOY1+1, "FOR_JOY2"},
{KEY_4JOY1+2, "FOR_JOY3"},
{KEY_4JOY1+3, "FOR_JOY4"},
{KEY_4JOY1+4, "FOR_JOY5"},
{KEY_4JOY1+5, "FOR_JOY6"},
{KEY_4JOY1+6, "FOR_JOY7"},
{KEY_4JOY1+7, "FOR_JOY8"},
#endif
#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_2S)
// we use up to 32 buttons in DirectInput
{KEY_4JOY1+8, "FOR_JOY9"},
{KEY_4JOY1+9, "FOR_JOY10"},
{KEY_4JOY1+10, "FOR_JOY11"},
{KEY_4JOY1+11, "FOR_JOY12"},
{KEY_4JOY1+12, "FOR_JOY13"},
{KEY_4JOY1+13, "FOR_JOY14"},
{KEY_4JOY1+14, "FOR_JOY15"},
{KEY_4JOY1+15, "FOR_JOY16"},
{KEY_4JOY1+16, "FOR_JOY17"},
{KEY_4JOY1+17, "FOR_JOY18"},
{KEY_4JOY1+18, "FOR_JOY19"},
{KEY_4JOY1+19, "FOR_JOY20"},
{KEY_4JOY1+20, "FOR_JOY21"},
{KEY_4JOY1+21, "FOR_JOY22"},
{KEY_4JOY1+22, "FOR_JOY23"},
{KEY_4JOY1+23, "FOR_JOY24"},
{KEY_4JOY1+24, "FOR_JOY25"},
{KEY_4JOY1+25, "FOR_JOY26"},
{KEY_4JOY1+26, "FOR_JOY27"},
{KEY_4JOY1+27, "FOR_JOY28"},
{KEY_4JOY1+28, "FOR_JOY29"},
{KEY_4JOY1+29, "FOR_JOY30"},
{KEY_4JOY1+30, "FOR_JOY31"},
{KEY_4JOY1+31, "FOR_JOY32"},
#endif
// the DOS version uses Allegro's joystick support
{KEY_4HAT1+0, "FOR_HATUP"},
{KEY_4HAT1+1, "FOR_HATDOWN"},
{KEY_4HAT1+2, "FOR_HATLEFT"},
{KEY_4HAT1+3, "FOR_HATRIGHT"},
#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII)
{KEY_4HAT1+4, "FOR_HATUP2"},
{KEY_4HAT1+5, "FOR_HATDOWN2"},
{KEY_4HAT1+6, "FOR_HATLEFT2"},
{KEY_4HAT1+7, "FOR_HATRIGHT2"},
#ifndef _arch_dreamcast
{KEY_4HAT1+8, "FOR_HATUP3"},
{KEY_4HAT1+9, "FOR_HATDOWN3"},
{KEY_4HAT1+10, "FOR_HATLEFT3"},
{KEY_4HAT1+11, "FOR_HATRIGHT3"},
{KEY_4HAT1+12, "FOR_HATUP4"},
{KEY_4HAT1+13, "FOR_HATDOWN4"},
{KEY_4HAT1+14, "FOR_HATLEFT4"},
{KEY_4HAT1+15, "FOR_HATRIGHT4"},
#endif
#endif
#ifdef DC
{KEY_DBL4JOY1+0, "DBLFOR_JOYC"},
{KEY_DBL4JOY1+1, "DBLFOR_JOYB"},
{KEY_DBL4JOY1+2, "DBLFOR_JOYA"},
{KEY_DBL4JOY1+3, "DBLFOR_JOYS"},
{KEY_DBL4JOY1+4, "DBLFOR_JOYZ"},
{KEY_DBL4JOY1+5, "DBLFOR_JOYY"},
{KEY_DBL4JOY1+6, "DBLFOR_JOYX"},
{KEY_DBL4JOY1+7, "DBLFOR_JOYD"},
#elif defined (_XBOX)
{KEY_DBL4JOY1+0, "DBLFOR_JOYA"},
{KEY_DBL4JOY1+1, "DBLFOR_JOYB"},
{KEY_DBL4JOY1+2, "DBLFOR_JOYX"},
{KEY_DBL4JOY1+3, "DBLFOR_JOYY"},
{KEY_DBL4JOY1+4, "DBLFOR_JOYG"},
{KEY_DBL4JOY1+5, "DBLFOR_JOYW"},
{KEY_DBL4JOY1+6, "DBLFOR_JOYL"},
{KEY_DBL4JOY1+7, "DBLFOR_JOYR"},
{KEY_DBL4JOY1+8, "DBLFOR_JOYS"},
{KEY_DBL4JOY1+9, "DBLFOR_JOYN"},
{KEY_DBL4JOY1+10,"DBLFOR_JOYW"},
{KEY_DBL4JOY1+11,"DBLFOR_JOYE"},
#define NOMOREJOYBTN_2DBL
#elif defined (_PSP)
{KEY_DBL4JOY1+0, "DBLFOR_TRIANGLE"},
{KEY_DBL4JOY1+1, "DBLFOR_CIRCLE" },
{KEY_DBL4JOY1+2, "DBLFOR_CROSS" },
{KEY_DBL4JOY1+3, "DBLFOR_SQUARE" },
{KEY_DBL4JOY1+4, "DBLFOR_LTRIGGER"},
{KEY_DBL4JOY1+5, "DBLFOR_RTRIGGER"},
{KEY_DBL4JOY1+6, "DBLFOR_SELECT" },
{KEY_DBL4JOY1+7, "DBLFOR_START" },
{KEY_DBL4JOY1+8, "DBLFOR_HOME" },
{KEY_DBL4JOY1+9, "DBLFOR_HOLD" },
#define NOMOREJOYBTN_2DBL
#elif defined (WMINPUT)
{KEY_DBL4JOY1+0, "DBLFOR_JOYB"},
{KEY_DBL4JOY1+1, "DBLFOR_JOYA"},
{KEY_DBL4JOY1+2, "DBLFOR_JOYUP"},
{KEY_DBL4JOY1+3, "DBLFOR_JOYDOWN"},
{KEY_DBL4JOY1+4, "DBLFOR_JOYLEFT"},
{KEY_DBL4JOY1+5, "DBLFOR_JOYRIGHT"},
{KEY_DBL4JOY1+6, "DBLFOR_JOYAA"},
{KEY_DBL4JOY1+7, "DBLFOR_JOYBB"},
{KEY_DBL4JOY1+8, "DBLFOR_JOYCC"},
{KEY_DBL4JOY1+9, "DBLFOR_JOYXX"},
{KEY_DBL4JOY1+10, "DBLFOR_JOYYY"},
{KEY_DBL4JOY1+11, "DBLFOR_JOYZZ"},
{KEY_DBL4JOY1+12, "DBLFOR_JOYL"},
{KEY_DBL4JOY1+13, "DBLFOR_JOYR"},
{KEY_DBL4JOY1+14, "DBLFOR_JOYZL"},
{KEY_DBL4JOY1+15, "DBLFOR_JOYZR"},
{KEY_DBL4JOY1+16, "DBLFOR_JOYSELECT"},
{KEY_DBL4JOY1+17, "DBLFOR_JOYSTART"},
{KEY_DBL4JOY1+18, "DBLFOR_JOYHOME"},
{KEY_DBL4JOY1+19, "DBLFOR_JOYMINUS"},
{KEY_DBL4JOY1+20, "DBLFOR_JOYPLUS"},
{KEY_DBL4JOY1+21, "DBLFOR_JOY_1"},
{KEY_DBL4JOY1+22, "DBLFOR_JOY_2"},
{KEY_DBL4JOY1+23, "DBLFOR_JOY24"},
{KEY_DBL4JOY1+24, "DBLFOR_JOY25"},
{KEY_DBL4JOY1+25, "DBLFOR_JOY26"},
{KEY_DBL4JOY1+26, "DBLFOR_JOY27"},
{KEY_DBL4JOY1+27, "DBLFOR_JOY28"},
{KEY_DBL4JOY1+28, "DBLFOR_JOY29"},
{KEY_DBL4JOY1+29, "DBLFOR_JOY30"},
{KEY_DBL4JOY1+30, "DBLFOR_JOY31"},
{KEY_DBL4JOY1+31, "DBLFOR_JOY32"},
#define NOMOREJOYBTN_2SDBL
#elif defined (_WII)
{KEY_DBL4JOY1+0, "DBLFOR_JOYA"},
{KEY_DBL4JOY1+1, "DBLFOR_JOYB"},
{KEY_DBL4JOY1+2, "DBLFOR_JOY1"},
{KEY_DBL4JOY1+3, "DBLFOR_JOY2"},
{KEY_DBL4JOY1+4, "DBLFOR_JOYMINUS"},
{KEY_DBL4JOY1+5, "DBLFOR_JOYPLUS"},
{KEY_DBL4JOY1+6, "DBLFOR_JOYHOME"},
{KEY_DBL4JOY1+7, "DBLFOR_JOYZ"},
{KEY_DBL4JOY1+8, "DBLFOR_JOYC"},
{KEY_DBL4JOY1+9, "DBLFOR_JOYA_CC"},
{KEY_DBL4JOY1+10, "DBLFOR_JOYB_CC"},
{KEY_DBL4JOY1+11, "DBLFOR_JOYX"},
{KEY_DBL4JOY1+12, "DBLFOR_JOYY"},
{KEY_DBL4JOY1+13, "DBLFOR_JOYL"},
{KEY_DBL4JOY1+14, "DBLFOR_JOYR"},
{KEY_DBL4JOY1+15, "DBLFOR_JOYZL"},
{KEY_DBL4JOY1+16, "DBLFOR_JOYZR"},
{KEY_DBL4JOY1+17, "DBLFOR_JOYMINUS_CC"},
{KEY_DBL4JOY1+18, "DBLFOR_JOYHPLUS_CC"},
{KEY_DBL4JOY1+19, "DBLFOR_JOYMHOME_CC"},
#define NOMOREJOYBTN_2DBL
#else
{KEY_DBL4JOY1+0, "DBLFOR_JOY1"},
{KEY_DBL4JOY1+1, "DBLFOR_JOY2"},
{KEY_DBL4JOY1+2, "DBLFOR_JOY3"},
{KEY_DBL4JOY1+3, "DBLFOR_JOY4"},
{KEY_DBL4JOY1+4, "DBLFOR_JOY5"},
{KEY_DBL4JOY1+5, "DBLFOR_JOY6"},
{KEY_DBL4JOY1+6, "DBLFOR_JOY7"},
{KEY_DBL4JOY1+7, "DBLFOR_JOY8"},
#endif
#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_2DBL)
{KEY_DBL4JOY1+8, "DBLFOR_JOY9"},
{KEY_DBL4JOY1+9, "DBLFOR_JOY10"},
{KEY_DBL4JOY1+10, "DBLFOR_JOY11"},
{KEY_DBL4JOY1+11, "DBLFOR_JOY12"},
{KEY_DBL4JOY1+12, "DBLFOR_JOY13"},
{KEY_DBL4JOY1+13, "DBLFOR_JOY14"},
{KEY_DBL4JOY1+14, "DBLFOR_JOY15"},
{KEY_DBL4JOY1+15, "DBLFOR_JOY16"},
{KEY_DBL4JOY1+16, "DBLFOR_JOY17"},
{KEY_DBL4JOY1+17, "DBLFOR_JOY18"},
{KEY_DBL4JOY1+18, "DBLFOR_JOY19"},
{KEY_DBL4JOY1+19, "DBLFOR_JOY20"},
{KEY_DBL4JOY1+20, "DBLFOR_JOY21"},
{KEY_DBL4JOY1+21, "DBLFOR_JOY22"},
{KEY_DBL4JOY1+22, "DBLFOR_JOY23"},
{KEY_DBL4JOY1+23, "DBLFOR_JOY24"},
{KEY_DBL4JOY1+24, "DBLFOR_JOY25"},
{KEY_DBL4JOY1+25, "DBLFOR_JOY26"},
{KEY_DBL4JOY1+26, "DBLFOR_JOY27"},
{KEY_DBL4JOY1+27, "DBLFOR_JOY28"},
{KEY_DBL4JOY1+28, "DBLFOR_JOY29"},
{KEY_DBL4JOY1+29, "DBLFOR_JOY30"},
{KEY_DBL4JOY1+30, "DBLFOR_JOY31"},
{KEY_DBL4JOY1+31, "DBLFOR_JOY32"},
#endif
{KEY_DBL4HAT1+0, "DBLFOR_HATUP"},
{KEY_DBL4HAT1+1, "DBLFOR_HATDOWN"},
{KEY_DBL4HAT1+2, "DBLFOR_HATLEFT"},
{KEY_DBL4HAT1+3, "DBLFOR_HATRIGHT"},
#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII)
{KEY_DBL4HAT1+4, "DBLFOR_HATUP2"},
{KEY_DBL4HAT1+5, "DBLFOR_HATDOWN2"},
{KEY_DBL4HAT1+6, "DBLFOR_HATLEFT2"},
{KEY_DBL4HAT1+7, "DBLFOR_HATRIGHT2"},
#ifndef _arch_dreamcast
{KEY_DBL4HAT1+8, "DBLFOR_HATUP3"},
{KEY_DBL4HAT1+9, "DBLFOR_HATDOWN3"},
{KEY_DBL4HAT1+10, "DBLFOR_HATLEFT3"},
{KEY_DBL4HAT1+11, "DBLFOR_HATRIGHT3"},
{KEY_DBL4HAT1+12, "DBLFOR_HATUP4"},
{KEY_DBL4HAT1+13, "DBLFOR_HATDOWN4"},
{KEY_DBL4HAT1+14, "DBLFOR_HATLEFT4"},
{KEY_DBL4HAT1+15, "DBLFOR_HATRIGHT4"},
#endif
#endif
};
static const char *gamecontrolname[num_gamecontrols] =

View file

@ -71,7 +71,19 @@ typedef enum
KEY_DBL2JOY1 = KEY_DBL2MOUSE1 + MOUSEBUTTONS,
KEY_DBL2HAT1 = KEY_DBL2JOY1 + JOYBUTTONS,
KEY_MOUSEWHEELUP = KEY_DBL2HAT1 + JOYHATS*4,
KEY_3JOY1 = KEY_DBL2HAT1 + JOYHATS*4,
KEY_3HAT1 = KEY_3JOY1 + JOYBUTTONS,
KEY_DBL3JOY1 = KEY_3HAT1 + JOYHATS*4,
KEY_DBL3HAT1 = KEY_DBL3JOY1 + JOYBUTTONS,
KEY_4JOY1 = KEY_DBL3HAT1 + JOYHATS*4,
KEY_4HAT1 = KEY_4JOY1 + JOYBUTTONS,
KEY_DBL4JOY1 = KEY_4HAT1 + JOYHATS*4,
KEY_DBL4HAT1 = KEY_DBL4JOY1 + JOYBUTTONS,
KEY_MOUSEWHEELUP = KEY_DBL4HAT1 + JOYHATS*4,
KEY_MOUSEWHEELDOWN = KEY_MOUSEWHEELUP + 1,
KEY_2MOUSEWHEELUP = KEY_MOUSEWHEELDOWN + 1,
KEY_2MOUSEWHEELDOWN = KEY_2MOUSEWHEELUP + 1,

View file

@ -39,7 +39,7 @@
#include "am_map.h"
#include "d_main.h"
#include "p_local.h" // camera, camera2
#include "p_local.h" // camera, camera2, camera3, camera4
#include "p_tick.h"
#ifdef HWRENDER

View file

@ -76,10 +76,18 @@ void I_OsPolling(void);
*/
ticcmd_t *I_BaseTiccmd(void);
/** \brief Input for the sencond player
/** \brief Input for the second player
*/
ticcmd_t *I_BaseTiccmd2(void);
/** \brief Input for the third player
*/
ticcmd_t *I_BaseTiccmd3(void);
/** \brief Input for the fourth player
*/
ticcmd_t *I_BaseTiccmd4(void);
/** \brief Called by M_Responder when quit is selected, return exit code 0
*/
void I_Quit(void) FUNCNORETURN;

View file

@ -716,7 +716,11 @@ void LUAh_GameHUD(player_t *stplayr)
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen && stplayr == &players[secondarydisplayplayer])
if (splitscreen4 && stplayr == &players[fourthdisplayplayer])
LUA_PushUserdata(gL, &camera4, META_CAMERA);
else if ((splitscreen3 || splitscreen4) && stplayr == &players[thirddisplayplayer])
LUA_PushUserdata(gL, &camera3, META_CAMERA);
else if ((splitscreen || splitscreen3 || splitscreen4) && stplayr == &players[secondarydisplayplayer])
LUA_PushUserdata(gL, &camera2, META_CAMERA);
else
LUA_PushUserdata(gL, &camera, META_CAMERA);

View file

@ -404,6 +404,10 @@ static int mobj_set(lua_State *L)
localangle = mo->angle;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle;
else if (mo->player == &players[thirddisplayplayer])
localangle3 = mo->angle;
else if (mo->player == &players[fourthdisplayplayer])
localangle4 = mo->angle;
break;
case mobj_sprite:
mo->sprite = luaL_checkinteger(L, 3);

View file

@ -176,7 +176,7 @@ static INT16 skullAnimCounter = 10; // skull animation counter
static boolean setupcontrols_secondaryplayer;
static boolean setupcontrols_thirdplayer;
static boolean setupcontrols_fourthplayer;
static INT32 (*setupcontrols)[4]; // pointer to the gamecontrols of the player being edited
static INT32 (*setupcontrols)[2]; // pointer to the gamecontrols of the player being edited
// shhh... what am I doing... nooooo!
static INT32 vidm_testingmode = 0;
@ -261,6 +261,8 @@ static void M_ConnectMenu(INT32 choice);
static void M_ConnectIPMenu(INT32 choice);
#endif
static void M_StartSplitServerMenu(INT32 choice);
static void M_Start3PServerMenu(INT32 choice);
static void M_Start4PServerMenu(INT32 choice);
static void M_StartServer(INT32 choice);
#ifndef NONET
static void M_Refresh(INT32 choice);
@ -888,8 +890,8 @@ static menuitem_t MP_MainMenu[] =
{IT_CALL | IT_STRING, NULL, "JOIN GAME (Specify IP)", M_ConnectIPMenu, 40},
#endif
{IT_CALL | IT_STRING, NULL, "TWO PLAYER GAME", M_StartSplitServerMenu, 60},
{IT_CALL | IT_STRING, NULL, "THREE PLAYER GAME", M_StartSplitServerMenu, 70},
{IT_CALL | IT_STRING, NULL, "FOUR PLAYER GAME", M_StartSplitServerMenu, 80},
{IT_CALL | IT_STRING, NULL, "THREE PLAYER GAME", M_Start3PServerMenu, 70},
{IT_CALL | IT_STRING, NULL, "FOUR PLAYER GAME", M_Start4PServerMenu, 80},
{IT_CALL | IT_STRING, NULL, "SETUP PLAYER 1", M_SetupMultiPlayer, 100},
{IT_CALL | IT_STRING, NULL, "SETUP PLAYER 2", M_SetupMultiPlayer2, 110},
@ -1728,6 +1730,8 @@ menu_t MP_RoomDef =
};
#endif
menu_t MP_SplitServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef);
menu_t MP_3PServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef);
menu_t MP_4PServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef);
menu_t MP_PlayerSetupDef =
{
NULL, //"M_SPLAYR"
@ -2406,7 +2410,7 @@ boolean M_Responder(event_t *ev)
{
// dirty hack: for customising controls, I want only buttons/keys, not moves
if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick
|| ev->type == ev_joystick2)
|| ev->type == ev_joystick2 || ev->type == ev_joystick3 || ev->type == ev_joystick4)
return true;
if (routine)
{
@ -5085,7 +5089,7 @@ static void M_ChoosePlayer(INT32 choice)
lastmapsaved = 0;
gamecomplete = false;
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect);
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, 1, fromlevelselect);
COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this
}
@ -5675,7 +5679,7 @@ static void M_ChooseNightsAttack(INT32 choice)
else
G_RecordDemo(nameofdemo);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), 0, false, false);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), 0, 1, false);
}
// Player has selected the "START" from the time attack screen
@ -5703,7 +5707,7 @@ static void M_ChooseTimeAttack(INT32 choice)
else
G_RecordDemo(nameofdemo);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), false, false);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), 1, false);
}
static void M_HandleStaffReplay(INT32 choice)
@ -6325,10 +6329,17 @@ static INT32 M_FindFirstMap(INT32 gtype)
static void M_StartServer(INT32 choice)
{
boolean StartSplitScreenGame = (currentMenu == &MP_SplitServerDef);
UINT8 ssplayers = 1;
if (currentMenu == &MP_SplitServerDef)
ssplayers = 2;
else if (currentMenu == &MP_3PServerDef)
ssplayers = 3;
else if (currentMenu == &MP_4PServerDef)
ssplayers = 4;
(void)choice;
if (!StartSplitScreenGame)
if (ssplayers < 2)
netgame = true;
multiplayer = true;
@ -6341,7 +6352,7 @@ static void M_StartServer(INT32 choice)
if (metalrecording)
G_StopMetalDemo();
if (!StartSplitScreenGame)
if (ssplayers < 2)
{
D_MapChange(cv_nextmap.value, cv_newgametype.value, false, 1, 1, false, false);
COM_BufAddText("dummyconsvar 1\n");
@ -6350,11 +6361,26 @@ static void M_StartServer(INT32 choice)
{
paused = false;
SV_StartSinglePlayerServer();
if (!splitscreen)
if (!splitscreen4 && ssplayers == 4)
{
splitscreen = true;
splitscreen4 = true;
splitscreen = splitscreen3 = false;
SplitScreen_OnChange();
}
else if (!splitscreen3 && ssplayers == 3)
{
splitscreen3 = true;
splitscreen = splitscreen4 = false;
SplitScreen_OnChange();
}
else if (!splitscreen && ssplayers == 2)
{
splitscreen = true;
splitscreen3 = splitscreen4 = false;
SplitScreen_OnChange();
}
D_MapChange(cv_nextmap.value, cv_newgametype.value, false, 1, 1, false, false);
}
@ -6422,6 +6448,22 @@ static void M_StartSplitServerMenu(INT32 choice)
M_SetupNextMenu(&MP_SplitServerDef);
}
static void M_Start3PServerMenu(INT32 choice)
{
(void)choice;
levellistmode = LLM_CREATESERVER;
M_PrepareLevelSelect();
M_SetupNextMenu(&MP_3PServerDef);
}
static void M_Start4PServerMenu(INT32 choice)
{
(void)choice;
levellistmode = LLM_CREATESERVER;
M_PrepareLevelSelect();
M_SetupNextMenu(&MP_4PServerDef);
}
#ifndef NONET
static void M_StartServerMenu(INT32 choice)
{
@ -7040,8 +7082,10 @@ static void M_DrawJoystick(void)
{
M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i);
if ((setupcontrols_secondaryplayer && (i == cv_usejoystick2.value))
|| (!setupcontrols_secondaryplayer && (i == cv_usejoystick.value)))
if ((setupcontrols_fourthplayer && (i == cv_usejoystick4.value))
|| (setupcontrols_thirdplayer && (i == cv_usejoystick3.value))
|| (setupcontrols_secondaryplayer && (i == cv_usejoystick2.value))
|| (!(setupcontrols_secondaryplayer || setupcontrols_thirdplayer || setupcontrols_fourthplayer) && (i == cv_usejoystick.value)))
V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,V_GREENMAP,joystickInfo[i]);
else
V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,0,joystickInfo[i]);
@ -7075,6 +7119,8 @@ static void M_SetupJoystickMenu(INT32 choice)
static void M_Setup1PJoystickMenu(INT32 choice)
{
setupcontrols_secondaryplayer = false;
setupcontrols_thirdplayer = false;
setupcontrols_fourthplayer = false;
OP_JoystickSetDef.prevMenu = &OP_Joystick1Def;
M_SetupJoystickMenu(choice);
}
@ -7082,6 +7128,8 @@ static void M_Setup1PJoystickMenu(INT32 choice)
static void M_Setup2PJoystickMenu(INT32 choice)
{
setupcontrols_secondaryplayer = true;
setupcontrols_thirdplayer = false;
setupcontrols_fourthplayer = false;
OP_JoystickSetDef.prevMenu = &OP_Joystick2Def;
M_SetupJoystickMenu(choice);
}
@ -7089,6 +7137,8 @@ static void M_Setup2PJoystickMenu(INT32 choice)
static void M_Setup3PJoystickMenu(INT32 choice)
{
setupcontrols_thirdplayer = true;
setupcontrols_secondaryplayer = false;
setupcontrols_fourthplayer = false;
OP_JoystickSetDef.prevMenu = &OP_Joystick3Def;
M_SetupJoystickMenu(choice);
}
@ -7096,6 +7146,8 @@ static void M_Setup3PJoystickMenu(INT32 choice)
static void M_Setup4PJoystickMenu(INT32 choice)
{
setupcontrols_fourthplayer = true;
setupcontrols_secondaryplayer = false;
setupcontrols_thirdplayer = false;
OP_JoystickSetDef.prevMenu = &OP_Joystick4Def;
M_SetupJoystickMenu(choice);
}
@ -7291,6 +7343,10 @@ static void M_ChangecontrolResponse(event_t *ev)
setupcontrols[control][found] = ch-KEY_2MOUSE1+KEY_DBL2MOUSE1;
else if (ch >= KEY_2JOY1 && ch <= KEY_2JOY1+JOYBUTTONS)
setupcontrols[control][found] = ch-KEY_2JOY1+KEY_DBL2JOY1;
else if (ch >= KEY_3JOY1 && ch <= KEY_3JOY1+JOYBUTTONS)
setupcontrols[control][found] = ch-KEY_3JOY1+KEY_DBL3JOY1;
else if (ch >= KEY_4JOY1 && ch <= KEY_4JOY1+JOYBUTTONS)
setupcontrols[control][found] = ch-KEY_4JOY1+KEY_DBL4JOY1;
}
else
{

View file

@ -2490,11 +2490,11 @@ void T_CameraScanner(elevator_t *elevator)
{
// leveltime is compared to make multiple scanners in one map function correctly.
static tic_t lastleveltime = 32000; // any number other than 0 should do here
static boolean camerascanned, camerascanned2;
static boolean camerascanned, camerascanned2, camerascanned3, camerascanned4;
if (leveltime != lastleveltime) // Back on the first camera scanner
{
camerascanned = camerascanned2 = false;
camerascanned = camerascanned2 = camerascanned3 = camerascanned4 = false;
lastleveltime = leveltime;
}
@ -2526,7 +2526,7 @@ void T_CameraScanner(elevator_t *elevator)
}
}
if (splitscreen && players[secondarydisplayplayer].mo)
if ((splitscreen || splitscreen3 || splitscreen4) && players[secondarydisplayplayer].mo)
{
if (players[secondarydisplayplayer].mo->subsector->sector == elevator->actionsector)
{
@ -2553,6 +2553,62 @@ void T_CameraScanner(elevator_t *elevator)
t_cam2_dist = t_cam2_height = t_cam2_rotate = -42;
}
}
if ((splitscreen3 || splitscreen4) && players[thirddisplayplayer].mo)
{
if (players[thirddisplayplayer].mo->subsector->sector == elevator->actionsector)
{
if (t_cam3_rotate == -42)
t_cam3_dist = cv_cam3_dist.value;
if (t_cam3_rotate == -42)
t_cam3_height = cv_cam3_height.value;
if (t_cam3_rotate == -42)
t_cam3_rotate = cv_cam3_rotate.value;
CV_SetValue(&cv_cam3_height, FixedInt(elevator->sector->floorheight));
CV_SetValue(&cv_cam3_dist, FixedInt(elevator->sector->ceilingheight));
CV_SetValue(&cv_cam3_rotate, elevator->distance);
camerascanned3 = true;
}
else if (!camerascanned3)
{
if (t_cam3_height != -42 && cv_cam3_height.value != t_cam3_height)
CV_Set(&cv_cam3_height, va("%f", (double)FIXED_TO_FLOAT(t_cam3_height)));
if (t_cam3_dist != -42 && cv_cam3_dist.value != t_cam3_dist)
CV_Set(&cv_cam3_dist, va("%f", (double)FIXED_TO_FLOAT(t_cam3_dist)));
if (t_cam3_rotate != -42 && cv_cam3_rotate.value != t_cam3_rotate)
CV_Set(&cv_cam3_rotate, va("%f", (double)t_cam3_rotate));
t_cam3_dist = t_cam3_height = t_cam3_rotate = -42;
}
}
if (splitscreen4 && players[fourthdisplayplayer].mo)
{
if (players[fourthdisplayplayer].mo->subsector->sector == elevator->actionsector)
{
if (t_cam4_rotate == -42)
t_cam4_dist = cv_cam4_dist.value;
if (t_cam4_rotate == -42)
t_cam4_height = cv_cam4_height.value;
if (t_cam4_rotate == -42)
t_cam4_rotate = cv_cam4_rotate.value;
CV_SetValue(&cv_cam4_height, FixedInt(elevator->sector->floorheight));
CV_SetValue(&cv_cam4_dist, FixedInt(elevator->sector->ceilingheight));
CV_SetValue(&cv_cam4_rotate, elevator->distance);
camerascanned4 = true;
}
else if (!camerascanned4)
{
if (t_cam4_height != -42 && cv_cam4_height.value != t_cam4_height)
CV_Set(&cv_cam4_height, va("%f", (double)FIXED_TO_FLOAT(t_cam4_height)));
if (t_cam4_dist != -42 && cv_cam4_dist.value != t_cam4_dist)
CV_Set(&cv_cam4_dist, va("%f", (double)FIXED_TO_FLOAT(t_cam4_dist)));
if (t_cam4_rotate != -42 && cv_cam4_rotate.value != t_cam4_rotate)
CV_Set(&cv_cam4_rotate, va("%f", (double)t_cam4_rotate));
t_cam4_dist = t_cam4_height = t_cam4_rotate = -42;
}
}
}
//

View file

@ -951,6 +951,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
localangle = toucher->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = toucher->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = toucher->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = toucher->angle;
P_ResetPlayer(player);

View file

@ -216,6 +216,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
localangle = spring->angle;
else if (object->player == &players[secondarydisplayplayer])
localangle2 = spring->angle;
else if (object->player == &players[thirddisplayplayer])
localangle3 = spring->angle;
else if (object->player == &players[fourthdisplayplayer])
localangle4 = spring->angle;
}
}
@ -2511,7 +2515,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
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 == &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;
if (!itsatwodlevel && players[displayplayer].mo)
@ -2520,7 +2526,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
fixed_t tryy = thiscam->y;
if ((thiscam == &camera && (players[displayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP)))
|| (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera3 && (players[thirddisplayplayer].pflags & PF_NOCLIP))
|| (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP)))
{ // Noclipping player camera noclips too!!
floatok = true;
thiscam->floorz = thiscam->z;
@ -3481,6 +3489,10 @@ isblocking:
localangle = slidemo->angle;
else if (slidemo->player == &players[secondarydisplayplayer])
localangle2 = slidemo->angle;
else if (slidemo->player == &players[thirddisplayplayer])
localangle3 = slidemo->angle;
else if (slidemo->player == &players[fourthdisplayplayer])
localangle4 = slidemo->angle;
}
if (!slidemo->player->climbing)

View file

@ -1249,6 +1249,26 @@ static void P_PlayerFlip(mobj_t *mo)
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);
}
}
}
}
@ -3578,7 +3598,9 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
postimg_t postimg = postimg_none;
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 == &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;
if (player->pflags & PF_FLIPCAM && !(player->pflags & PF_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP)
@ -9552,6 +9574,10 @@ void P_AfterPlayerSpawn(INT32 playernum)
localangle = mobj->angle;
else if (playernum == secondarydisplayplayer)
localangle2 = mobj->angle;
else if (playernum == thirddisplayplayer)
localangle3 = mobj->angle;
else if (playernum == fourthdisplayplayer)
localangle4 = mobj->angle;
p->viewheight = cv_viewheight.value<<FRACBITS;
@ -9578,11 +9604,21 @@ void P_AfterPlayerSpawn(INT32 playernum)
if (displayplayer == playernum)
P_ResetCamera(p, &camera);
}
if (camera2.chase && splitscreen)
if (camera2.chase && (splitscreen || splitscreen3 || splitscreen4))
{
if (secondarydisplayplayer == playernum)
P_ResetCamera(p, &camera2);
}
if (camera3.chase && (splitscreen3 || splitscreen4))
{
if (thirddisplayplayer == playernum)
P_ResetCamera(p, &camera3);
}
if (camera4.chase && splitscreen4)
{
if (fourthdisplayplayer == playernum)
P_ResetCamera(p, &camera4);
}
if (CheckForReverseGravity)
P_CheckGravity(mobj, false);

View file

@ -1339,6 +1339,10 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
localangle = mo->angle;
else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle;
else if (mo->player == &players[thirddisplayplayer])
localangle3 = mo->angle;
else if (mo->player == &players[fourthdisplayplayer])
localangle4 = mo->angle;
}
}
}

View file

@ -2064,6 +2064,10 @@ static void LoadMobjThinker(actionf_p1 thinker)
localangle = mobj->angle;
if (secondarydisplayplayer == i)
localangle2 = mobj->angle;
if (thirddisplayplayer == i)
localangle3 = mobj->angle;
if (fourthdisplayplayer == i)
localangle4 = mobj->angle;
}
if (diff & MD_MOVEDIR)
mobj->movedir = READANGLE(save_p);
@ -3370,7 +3374,7 @@ boolean P_LoadGame(INT16 mapoverride)
return false;
// Only do this after confirming savegame is ok
G_DeferedInitNew(false, G_BuildMapName(gamemap), savedata.skin, false, true);
G_DeferedInitNew(false, G_BuildMapName(gamemap), savedata.skin, 1, true);
COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this
return true;

View file

@ -2381,7 +2381,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{
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);
if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase)
if (splitscreen4 && mo->player == &players[fourthdisplayplayer] && camera4.chase)
{
camera4.x += x;
camera4.y += y;
camera4.z += z;
camera4.subsector = R_PointInSubsector(camera4.x, camera4.y);
}
else if ((splitscreen3 || splitscreen4) && mo->player == &players[thirddisplayplayer] && camera3.chase)
{
camera3.x += x;
camera3.y += y;
camera3.z += z;
camera3.subsector = R_PointInSubsector(camera3.x, camera3.y);
}
else if ((splitscreen || splitscreen3 || splitscreen4) && mo->player == &players[secondarydisplayplayer] && camera2.chase)
{
camera2.x += x;
camera2.y += y;
@ -3770,6 +3784,10 @@ DoneSection2:
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
if (!(lines[i].flags & ML_EFFECT4))
@ -7709,10 +7727,28 @@ void T_Pusher(pusher_t *p)
else
localangle2 += (thing->angle - localangle2) / 8;
}
else if (thing->player == &players[thirddisplayplayer])
{
if (thing->angle - localangle3 > ANGLE_180)
localangle3 -= (localangle3 - thing->angle) / 8;
else
localangle3 += (thing->angle - localangle3) / 8;
}
else if (thing->player == &players[fourthdisplayplayer])
{
if (thing->angle - localangle4 > ANGLE_180)
localangle4 -= (localangle4 - thing->angle) / 8;
else
localangle4 += (thing->angle - localangle4) / 8;
}
/*if (thing->player == &players[consoleplayer])
localangle = thing->angle;
else if (thing->player == &players[secondarydisplayplayer])
localangle2 = thing->angle;*/
localangle2 = thing->angle;
else if (thing->player == &players[thirddisplayplayer])
localangle3 = thing->angle;
else if (thing->player == &players[fourthdisplayplayer])
localangle4 = thing->angle;*/
}
}

View file

@ -67,13 +67,18 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
localangle = angle;
if (thing == players[secondarydisplayplayer].mo)
localangle2 = angle;
if (thing == players[thirddisplayplayer].mo)
localangle3 = angle;
if (thing == players[fourthdisplayplayer].mo)
localangle4 = angle;
// move chasecam at new player location
if (splitscreen && camera2.chase
&& thing->player == &players[secondarydisplayplayer])
{
if (splitscreen4 && camera4.chase && thing->player == &players[fourthdisplayplayer])
P_ResetCamera(thing->player, &camera4);
else if ((splitscreen3 || splitscreen4) && camera3.chase && thing->player == &players[thirddisplayplayer])
P_ResetCamera(thing->player, &camera3);
else if ((splitscreen || splitscreen3 || splitscreen4) && camera2.chase && thing->player == &players[secondarydisplayplayer])
P_ResetCamera(thing->player, &camera2);
}
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
@ -147,9 +152,17 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
localangle = angle;
if (thing->player == &players[secondarydisplayplayer])
localangle2 = angle;
if (thing->player == &players[thirddisplayplayer])
localangle3 = angle;
if (thing->player == &players[fourthdisplayplayer])
localangle4 = angle;
// move chasecam at new player location
if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])
if (splitscreen4 && camera4.chase && thing->player == &players[fourthdisplayplayer])
P_ResetCamera(thing->player, &camera4);
else if ((splitscreen3 || splitscreen4) && camera3.chase && thing->player == &players[thirddisplayplayer])
P_ResetCamera(thing->player, &camera3);
else if ((splitscreen || splitscreen3 || splitscreen4) && camera2.chase && thing->player == &players[secondarydisplayplayer])
P_ResetCamera(thing->player, &camera2);
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);

View file

@ -2858,6 +2858,10 @@ static void P_DoClimbing(player_t *player) // SRB2kart - unused
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
if (player->climbing == 0)
@ -3687,6 +3691,10 @@ void P_DoJump(player_t *player, boolean soundandstate)
localangle = player->mo->angle; // Adjust the local control angle.
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
player->climbing = 0; // Stop climbing, duh!
@ -4372,7 +4380,11 @@ INT32 P_GetPlayerControlDirection(player_t *player)
fixed_t tempx = 0, tempy = 0;
angle_t tempangle, origtempangle;
if (splitscreen && player == &players[secondarydisplayplayer])
if (splitscreen4 && player == &players[fourthdisplayplayer])
thiscam = &camera4;
else if ((splitscreen3 || splitscreen4) && player == &players[thirddisplayplayer])
thiscam = &camera3;
else if ((splitscreen || splitscreen3 || splitscreen4) && player == &players[secondarydisplayplayer])
thiscam = &camera2;
else
thiscam = &camera;
@ -4519,6 +4531,10 @@ static void P_2dMovement(player_t *player)
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
if (player->pflags & PF_GLIDING)
movepushangle = player->mo->angle;
@ -6251,6 +6267,10 @@ static void P_NiGHTSMovement(player_t *player)
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
if (still)
{
@ -7110,6 +7130,10 @@ static void P_MovePlayer(player_t *player)
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
///////////////////////////
@ -7501,6 +7525,10 @@ static void P_DoZoomTube(player_t *player)
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
}
@ -7882,6 +7910,10 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
localangle = source->angle;
else if (source->player == &players[secondarydisplayplayer])
localangle2 = source->angle;
else if (source->player == &players[thirddisplayplayer])
localangle3 = source->angle;
else if (source->player == &players[fourthdisplayplayer])
localangle4 = source->angle;
}
// change slope
@ -8072,7 +8104,7 @@ static void P_DeathThink(player_t *player)
// P_MoveCamera: make sure the camera is not outside the world and looks at the player avatar
//
camera_t camera, camera2; // Two cameras.. one for split!
camera_t camera, camera2, camera3, camera4; // Four cameras, three for splitscreen
static void CV_CamRotate_OnChange(void)
{
@ -8141,6 +8173,12 @@ fixed_t t_cam_rotate = -42;
fixed_t t_cam2_dist = -42;
fixed_t t_cam2_height = -42;
fixed_t t_cam2_rotate = -42;
fixed_t t_cam3_dist = -42;
fixed_t t_cam3_height = -42;
fixed_t t_cam3_rotate = -42;
fixed_t t_cam4_dist = -42;
fixed_t t_cam4_height = -42;
fixed_t t_cam4_rotate = -42;
#define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode)
@ -8169,7 +8207,9 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
thiscam->z = z;
if (!(thiscam == &camera && (cv_cam_still.value || cv_analog.value))
&& !(thiscam == &camera2 && (cv_cam2_still.value || cv_analog2.value)))
&& !(thiscam == &camera2 && (cv_cam2_still.value || cv_analog2.value))
&& !(thiscam == &camera3 && (cv_cam3_still.value || cv_analog3.value))
&& !(thiscam == &camera4 && (cv_cam4_still.value || cv_analog4.value)))
{
thiscam->angle = player->mo->angle;
thiscam->aiming = 0;
@ -8206,6 +8246,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (!cv_chasecam2.value && thiscam == &camera2)
return true;
if (!cv_chasecam3.value && thiscam == &camera3)
return true;
if (!cv_chasecam4.value && thiscam == &camera4)
return true;
}
if (!thiscam->chase && !resetcalled)
@ -8214,12 +8260,20 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
focusangle = localangle;
else if (player == &players[secondarydisplayplayer])
focusangle = localangle2;
else if (player == &players[thirddisplayplayer])
focusangle = localangle3;
else if (player == &players[fourthdisplayplayer])
focusangle = localangle4;
else
focusangle = player->mo->angle;
if (thiscam == &camera)
camrotate = cv_cam_rotate.value;
else if (thiscam == &camera2)
camrotate = cv_cam2_rotate.value;
else if (thiscam == &camera3)
camrotate = cv_cam3_rotate.value;
else if (thiscam == &camera4)
camrotate = cv_cam4_rotate.value;
else
camrotate = 0;
thiscam->angle = focusangle + FixedAngle(camrotate*FRACUNIT);
@ -8258,6 +8312,16 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
focusangle = localangle2;
focusaiming = localaiming2;
}
else if (player == &players[thirddisplayplayer])
{
focusangle = localangle3;
focusaiming = localaiming3;
}
else if (player == &players[fourthdisplayplayer])
{
focusangle = localangle4;
focusaiming = localaiming4;
}
else
{
focusangle = player->mo->angle;
@ -8332,8 +8396,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
else
angle = focusangle + FixedAngle(camrotate*FRACUNIT);
if (!resetcalled && (cv_analog.value || demoplayback) && ((thiscam == &camera && t_cam_rotate != -42) || (thiscam == &camera2
&& t_cam2_rotate != -42)))
if (!resetcalled && (cv_analog.value || demoplayback)
&& ((thiscam == &camera && t_cam_rotate != -42)
|| (thiscam == &camera2 && t_cam2_rotate != -42)
|| (thiscam == &camera3 && t_cam3_rotate != -42)
|| (thiscam == &camera4 && t_cam4_rotate != -42)))
{
angle = FixedAngle(camrotate*FRACUNIT);
thiscam->angle = angle;
@ -8424,12 +8491,21 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
dist = camdist;
// x1.5 dist for splitscreen
if (splitscreen)
if (splitscreen) // x1.5 dist for splitscreen
{
dist = FixedMul(dist, 3*FRACUNIT/2);
height = FixedMul(height, 3*FRACUNIT/2);
}
else if (splitscreen3) // x1.75 dist for 3p
{
dist = FixedMul(dist, 7*FRACUNIT/4);
height = FixedMul(height, 7*FRACUNIT/4);
}
else if (splitscreen4) // x2 dist for 4p
{
dist = FixedMul(dist, 2*FRACUNIT);
height = FixedMul(height, 2*FRACUNIT);
}
// x1.2 dist for analog
if (P_AnalogMove(player))
@ -9401,7 +9477,9 @@ void P_PlayerThink(player_t *player)
// Why not just not spawn the mobj? Well, I'd rather only flirt with
// consistency so much...
if ((player == &players[displayplayer] && !camera.chase)
|| (splitscreen && player == &players[secondarydisplayplayer] && !camera2.chase))
|| ((splitscreen || splitscreen3 || splitscreen4) && player == &players[secondarydisplayplayer] && !camera2.chase)
|| ((splitscreen3 || splitscreen4) && player == &players[thirddisplayplayer] && !camera3.chase)
|| (splitscreen4 && player == &players[fourthdisplayplayer] && !camera4.chase))
gmobj->flags2 |= MF2_DONTDRAW;
}
#endif
@ -9617,7 +9695,11 @@ void P_PlayerAfterThink(player_t *player)
P_PlayerInSpecialSector(player);
#endif
if (splitscreen && player == &players[secondarydisplayplayer])
if (splitscreen4 && player == &players[fourthdisplayplayer])
thiscam = &camera4;
else if ((splitscreen3 || splitscreen4) && player == &players[thirddisplayplayer])
thiscam = &camera3;
else if ((splitscreen || splitscreen3 || splitscreen4) && player == &players[secondarydisplayplayer])
thiscam = &camera2;
else if (player == &players[displayplayer])
thiscam = &camera;
@ -9816,6 +9898,10 @@ void P_PlayerAfterThink(player_t *player)
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
}
@ -9889,6 +9975,10 @@ void P_PlayerAfterThink(player_t *player)
localangle = player->mo->angle; // Adjust the local control angle.
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
else if (player == &players[thirddisplayplayer])
localangle3 = player->mo->angle;
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
}
}

View file

@ -257,7 +257,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 heightsec;
boolean underwater;
if (splitscreen && viewplayer == &players[secondarydisplayplayer] && camera2.chase)
if (splitscreen4 && viewplayer == &players[fourthdisplayplayer] && camera4.chase)
heightsec = R_PointInSubsector(camera4.x, camera4.y)->sector->heightsec;
else if ((splitscreen3 || splitscreen4) && viewplayer == &players[thirddisplayplayer] && camera3.chase)
heightsec = R_PointInSubsector(camera3.x, camera3.y)->sector->heightsec;
else if ((splitscreen || splitscreen3 || splitscreen4) && viewplayer == &players[secondarydisplayplayer] && camera2.chase)
heightsec = R_PointInSubsector(camera2.x, camera2.y)->sector->heightsec;
else if (camera.chase && viewplayer == &players[displayplayer])
heightsec = R_PointInSubsector(camera.x, camera.y)->sector->heightsec;

View file

@ -67,7 +67,7 @@ fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle;
fixed_t viewcos, viewsin;
boolean viewsky, skyVisible;
boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, for splitscreen
boolean skyVisible1, skyVisible2, skyVisible3, skyVisible4; // saved values of skyVisible for P1/P2/P3/P4, for splitscreen
sector_t *viewsector;
player_t *viewplayer;
@ -178,10 +178,10 @@ void SplitScreen_OnChange(void)
{
if (!cv_debug && netgame)
{
if (splitscreen)
if (splitscreen || splitscreen3 || splitscreen4)
{
CONS_Alert(CONS_NOTICE, M_GetText("Splitscreen not supported in netplay, sorry!\n"));
splitscreen = false;
splitscreen = splitscreen3 = splitscreen4 = false;
}
return;
}
@ -191,22 +191,49 @@ void SplitScreen_OnChange(void)
if (!demoplayback && !botingame)
{
if (splitscreen)
if (splitscreen || splitscreen3 || splitscreen4)
CL_AddSplitscreenPlayer();
else
CL_RemoveSplitscreenPlayer();
CL_RemoveSplitscreenPlayer(secondarydisplayplayer);
if (splitscreen3 || splitscreen4)
CL_AddSplitscreenPlayer();
else
CL_RemoveSplitscreenPlayer(thirddisplayplayer);
if (splitscreen4)
CL_AddSplitscreenPlayer();
else
CL_RemoveSplitscreenPlayer(fourthdisplayplayer);
if (server && !netgame)
multiplayer = splitscreen;
multiplayer = (splitscreen || splitscreen3 || splitscreen4);
}
else
{
INT32 i;
secondarydisplayplayer = consoleplayer;
thirddisplayplayer = consoleplayer;
fourthdisplayplayer = consoleplayer;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && i != consoleplayer)
{
if (secondarydisplayplayer == consoleplayer)
{
secondarydisplayplayer = i;
continue;
}
else if (thirddisplayplayer == consoleplayer)
{
thirddisplayplayer = i;
continue;
}
else if (fourthdisplayplayer == consoleplayer)
{
fourthdisplayplayer = i;
break;
}
else
break;
}
}
@ -232,8 +259,6 @@ static void ChaseCam2_OnChange(void)
static void ChaseCam3_OnChange(void)
{
if (botingame)
return;
if (!cv_chasecam3.value || !cv_useranalog3.value)
CV_SetValue(&cv_analog3, 0);
else
@ -242,8 +267,6 @@ static void ChaseCam3_OnChange(void)
static void ChaseCam4_OnChange(void)
{
if (botingame)
return;
if (!cv_chasecam4.value || !cv_useranalog4.value)
CV_SetValue(&cv_analog4, 0);
else
@ -634,9 +657,12 @@ void R_ExecuteSetViewSize(void)
scaledviewwidth = vid.width;
viewheight = vid.height;
if (splitscreen)
if (splitscreen || splitscreen3 || splitscreen4)
viewheight >>= 1;
if (splitscreen3 || splitscreen4)
viewwidth >>= 1;
viewwidth = scaledviewwidth;
centerx = viewwidth/2;
@ -803,8 +829,11 @@ void R_SkyboxFrame(player_t *player)
INT32 dy = 0;
camera_t *thiscam;
if (splitscreen && player == &players[secondarydisplayplayer]
&& player != &players[consoleplayer])
if (splitscreen4 && player == &players[fourthdisplayplayer])
thiscam = &camera4;
else if ((splitscreen3 || splitscreen4) && player == &players[thirddisplayplayer])
thiscam = &camera3;
else if ((splitscreen || splitscreen3 || splitscreen4) && player == &players[secondarydisplayplayer])
thiscam = &camera2;
else
thiscam = &camera;
@ -845,6 +874,16 @@ void R_SkyboxFrame(player_t *player)
viewangle = localangle2;
aimingangle = localaiming2;
}
else if (player == &players[thirddisplayplayer])
{
viewangle = localangle3;
aimingangle = localaiming3;
}
else if (player == &players[fourthdisplayplayer])
{
viewangle = localangle4;
aimingangle = localaiming4;
}
}
}
viewangle += viewmobj->angle;
@ -1039,8 +1078,17 @@ void R_SetupFrame(player_t *player, boolean skybox)
camera_t *thiscam;
boolean chasecam = false;
if (splitscreen && player == &players[secondarydisplayplayer]
&& player != &players[consoleplayer])
if (splitscreen4 && player == &players[fourthdisplayplayer])
{
thiscam = &camera4;
chasecam = (cv_chasecam4.value != 0);
}
else if ((splitscreen3 || splitscreen4) && player == &players[thirddisplayplayer])
{
thiscam = &camera3;
chasecam = (cv_chasecam3.value != 0);
}
else if ((splitscreen || splitscreen3 || splitscreen4) && player == &players[secondarydisplayplayer])
{
thiscam = &camera2;
chasecam = (cv_chasecam2.value != 0);
@ -1105,6 +1153,16 @@ void R_SetupFrame(player_t *player, boolean skybox)
viewangle = localangle2;
aimingangle = localaiming2;
}
else if (player == &players[thirddisplayplayer])
{
viewangle = localangle3;
aimingangle = localaiming3;
}
else if (player == &players[fourthdisplayplayer])
{
viewangle = localangle4;
aimingangle = localaiming4;
}
}
}
viewz += quake.z;

View file

@ -396,9 +396,13 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
listener_t listener = {0,0,0,0};
listener_t listener2 = {0,0,0,0};
listener_t listener3 = {0,0,0,0};
listener_t listener4 = {0,0,0,0};
mobj_t *listenmobj = players[displayplayer].mo;
mobj_t *listenmobj2 = NULL;
mobj_t *listenmobj3 = NULL;
mobj_t *listenmobj4 = NULL;
if (sound_disabled || !sound_started || nosound)
return;
@ -410,13 +414,27 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (players[displayplayer].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj;
if (splitscreen)
if (splitscreen || splitscreen3 || splitscreen4)
{
listenmobj2 = players[secondarydisplayplayer].mo;
if (players[secondarydisplayplayer].awayviewtics)
listenmobj2 = players[secondarydisplayplayer].awayviewmobj;
}
if (splitscreen3 || splitscreen4)
{
listenmobj3 = players[thirddisplayplayer].mo;
if (players[thirddisplayplayer].awayviewtics)
listenmobj3 = players[thirddisplayplayer].awayviewmobj;
}
if (splitscreen4)
{
listenmobj4 = players[fourthdisplayplayer].mo;
if (players[fourthdisplayplayer].awayviewtics)
listenmobj4 = players[fourthdisplayplayer].awayviewmobj;
}
#ifdef HW3SOUND
if (hws_mode != HWS_DEFAULT_MODE)
{
@ -460,6 +478,42 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
}
}
if (listenmobj3)
{
if (camera3.chase && !players[thirddisplayplayer].awayviewtics)
{
listener3.x = camera3.x;
listener3.y = camera3.y;
listener3.z = camera3.z;
listener3.angle = camera3.angle;
}
else
{
listener3.x = listenmobj3->x;
listener3.y = listenmobj3->y;
listener3.z = listenmobj3->z;
listener3.angle = listenmobj3->angle;
}
}
if (listenmobj4)
{
if (camera4.chase && !players[fourthdisplayplayer].awayviewtics)
{
listener4.x = camera4.x;
listener4.y = camera4.y;
listener4.z = camera4.z;
listener4.angle = camera4.angle;
}
else
{
listener4.x = listenmobj4->x;
listener4.y = listenmobj4->y;
listener4.z = listenmobj4->z;
listener4.angle = listenmobj4->angle;
}
}
// check for bogus sound #
I_Assert(sfx_id >= 1);
I_Assert(sfx_id < NUMSFX);
@ -477,7 +531,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
pitch = NORM_PITCH;
priority = NORM_PRIORITY;
if (splitscreen && listenmobj2) // Copy the sound for the split player
if ((splitscreen || splitscreen3 || splitscreen4) && listenmobj2) // Copy the sound for the split player
{
// Check to see if it is audible, and if not, modify the params
if (origin && origin != listenmobj2)
@ -518,6 +572,116 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
#ifdef SURROUND
// Avoid channel reverse if surround
if (stereoreverse.value && sep != SURROUND_SEP)
sep = (~sep) & 255;
#else
if (stereoreverse.value)
sep = (~sep) & 255;
#endif
// Assigns the handle to one of the channels in the
// mix/output buffer.
channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority);
}
if ((splitscreen3 || splitscreen4) && listenmobj3) // Copy the sound for the third player
{
// Check to see if it is audible, and if not, modify the params
if (origin && origin != listenmobj3)
{
INT32 rc;
rc = S_AdjustSoundParams(listenmobj3, origin, &volume, &sep, &pitch, sfx);
if (!rc)
goto dontplay; // Maybe the other player can hear it...
if (origin->x == listener3.x && origin->y == listener3.y)
sep = NORM_SEP;
}
else if (!origin)
// Do not play origin-less sounds for the second player.
// The first player will be able to hear it just fine,
// we really don't want it playing twice.
goto dontplay;
else
sep = NORM_SEP;
// try to find a channel
cnum = S_getChannel(origin, sfx);
if (cnum < 0)
return; // If there's no free channels, it's not gonna be free for player 1, either.
// This is supposed to handle the loading/caching.
// For some odd reason, the caching is done nearly
// each time the sound is needed?
// cache data if necessary
// NOTE: set sfx->data NULL sfx->lump -1 to force a reload
if (!sfx->data)
sfx->data = I_GetSfx(sfx);
// increase the usefulness
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
#ifdef SURROUND
// Avoid channel reverse if surround
if (stereoreverse.value && sep != SURROUND_SEP)
sep = (~sep) & 255;
#else
if (stereoreverse.value)
sep = (~sep) & 255;
#endif
// Assigns the handle to one of the channels in the
// mix/output buffer.
channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority);
}
if (splitscreen4 && listenmobj4) // Copy the sound for the split player
{
// Check to see if it is audible, and if not, modify the params
if (origin && origin != listenmobj4)
{
INT32 rc;
rc = S_AdjustSoundParams(listenmobj4, origin, &volume, &sep, &pitch, sfx);
if (!rc)
goto dontplay; // Maybe the other player can hear it...
if (origin->x == listener4.x && origin->y == listener4.y)
sep = NORM_SEP;
}
else if (!origin)
// Do not play origin-less sounds for the second player.
// The first player will be able to hear it just fine,
// we really don't want it playing twice.
goto dontplay;
else
sep = NORM_SEP;
// try to find a channel
cnum = S_getChannel(origin, sfx);
if (cnum < 0)
return; // If there's no free channels, it's not gonna be free for player 1, either.
// This is supposed to handle the loading/caching.
// For some odd reason, the caching is done nearly
// each time the sound is needed?
// cache data if necessary
// NOTE: set sfx->data NULL sfx->lump -1 to force a reload
if (!sfx->data)
sfx->data = I_GetSfx(sfx);
// increase the usefulness
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
#ifdef SURROUND
// Avoid channel reverse if surround
if (stereoreverse.value && sep != SURROUND_SEP)
@ -691,12 +855,18 @@ void S_UpdateSounds(void)
listener_t listener;
listener_t listener2;
listener_t listener3;
listener_t listener4;
mobj_t *listenmobj = players[displayplayer].mo;
mobj_t *listenmobj2 = NULL;
mobj_t *listenmobj3 = NULL;
mobj_t *listenmobj4 = NULL;
memset(&listener, 0, sizeof(listener_t));
memset(&listener2, 0, sizeof(listener_t));
memset(&listener3, 0, sizeof(listener_t));
memset(&listener4, 0, sizeof(listener_t));
// Update sound/music volumes, if changed manually at console
if (actualsfxvolume != cv_soundvolume.value)
@ -725,13 +895,27 @@ void S_UpdateSounds(void)
if (players[displayplayer].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj;
if (splitscreen)
if (splitscreen || splitscreen3 || splitscreen4)
{
listenmobj2 = players[secondarydisplayplayer].mo;
if (players[secondarydisplayplayer].awayviewtics)
listenmobj2 = players[secondarydisplayplayer].awayviewmobj;
}
if (splitscreen3 || splitscreen4)
{
listenmobj3 = players[thirddisplayplayer].mo;
if (players[thirddisplayplayer].awayviewtics)
listenmobj3 = players[thirddisplayplayer].awayviewmobj;
}
if (splitscreen4)
{
listenmobj4 = players[fourthdisplayplayer].mo;
if (players[fourthdisplayplayer].awayviewtics)
listenmobj4 = players[fourthdisplayplayer].awayviewmobj;
}
if (camera.chase && !players[displayplayer].awayviewtics)
{
listener.x = camera.x;
@ -778,6 +962,42 @@ void S_UpdateSounds(void)
}
}
if (listenmobj3)
{
if (camera3.chase && !players[thirddisplayplayer].awayviewtics)
{
listener3.x = camera3.x;
listener3.y = camera3.y;
listener3.z = camera3.z;
listener3.angle = camera3.angle;
}
else
{
listener3.x = listenmobj3->x;
listener3.y = listenmobj3->y;
listener3.z = listenmobj3->z;
listener3.angle = listenmobj3->angle;
}
}
if (listenmobj4)
{
if (camera4.chase && !players[fourthdisplayplayer].awayviewtics)
{
listener4.x = camera4.x;
listener4.y = camera4.y;
listener4.z = camera4.z;
listener4.angle = camera4.angle;
}
else
{
listener4.x = listenmobj4->x;
listener4.y = listenmobj4->y;
listener4.z = listenmobj4->z;
listener4.angle = listenmobj4->angle;
}
}
for (cnum = 0; cnum < numofchannels; cnum++)
{
c = &channels[cnum];
@ -793,11 +1013,13 @@ void S_UpdateSounds(void)
// check non-local sounds for distance clipping
// or modify their params
if (c->origin && ((c->origin != players[consoleplayer].mo) ||
(splitscreen && c->origin != players[secondarydisplayplayer].mo)))
if (c->origin && ((c->origin != players[consoleplayer].mo)
|| ((splitscreen || splitscreen3 || splitscreen4) && c->origin != players[secondarydisplayplayer].mo)
|| ((splitscreen3 || splitscreen4) && c->origin != players[thirddisplayplayer].mo)
|| (splitscreen4 && c->origin != players[fourthdisplayplayer].mo)))
{
// Whomever is closer gets the sound, but only in splitscreen.
if (listenmobj && listenmobj2 && splitscreen)
if (listenmobj && listenmobj2 && (splitscreen || splitscreen3 || splitscreen4))
{
const mobj_t *soundmobj = c->origin;
@ -823,7 +1045,59 @@ void S_UpdateSounds(void)
else
S_StopChannel(cnum);
}
else if (listenmobj && !splitscreen)
else if (listenmobj && listenmobj3 && (splitscreen3 || splitscreen4)) // TODO: make 3/4P compare their distances with all players, not just the first player and themselves V:
{
const mobj_t *soundmobj = c->origin;
fixed_t dist1, dist2;
dist1 = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y);
dist2 = P_AproxDistance(listener3.x-soundmobj->x, listener3.y-soundmobj->y);
if (dist1 <= dist2)
{
// Player 1 gets the sound
audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch,
c->sfxinfo);
}
else
{
// Player 3 gets the sound
audible = S_AdjustSoundParams(listenmobj3, c->origin, &volume, &sep, &pitch,
c->sfxinfo);
}
if (audible)
I_UpdateSoundParams(c->handle, volume, sep, pitch);
else
S_StopChannel(cnum);
}
else if (listenmobj && listenmobj4 && splitscreen4)
{
const mobj_t *soundmobj = c->origin;
fixed_t dist1, dist2;
dist1 = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y);
dist2 = P_AproxDistance(listener4.x-soundmobj->x, listener4.y-soundmobj->y);
if (dist1 <= dist2)
{
// Player 1 gets the sound
audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch,
c->sfxinfo);
}
else
{
// Player 4 gets the sound
audible = S_AdjustSoundParams(listenmobj4, c->origin, &volume, &sep, &pitch,
c->sfxinfo);
}
if (audible)
I_UpdateSoundParams(c->handle, volume, sep, pitch);
else
S_StopChannel(cnum);
}
else if (listenmobj && !(splitscreen || splitscreen3 || splitscreen4))
{
// In the case of a single player, he or she always should get updated sound.
audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch,
@ -949,13 +1223,27 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v
listensource.z = camera.z;
listensource.angle = camera.angle;
}
else if (splitscreen && listener == players[secondarydisplayplayer].mo && camera2.chase)
else if ((splitscreen || splitscreen3 || splitscreen4) && listener == players[secondarydisplayplayer].mo && camera2.chase)
{
listensource.x = camera2.x;
listensource.y = camera2.y;
listensource.z = camera2.z;
listensource.angle = camera2.angle;
}
else if ((splitscreen3 || splitscreen4) && listener == players[thirddisplayplayer].mo && camera3.chase)
{
listensource.x = camera3.x;
listensource.y = camera3.y;
listensource.z = camera3.z;
listensource.angle = camera3.angle;
}
else if (splitscreen4 && listener == players[fourthdisplayplayer].mo && camera4.chase)
{
listensource.x = camera4.x;
listensource.y = camera4.y;
listensource.z = camera4.z;
listensource.angle = camera4.angle;
}
else
{
listensource.x = listener->x;

View file

@ -898,7 +898,8 @@ static void I_ShutdownJoystick(void)
joystick_started = 0;
JoyReset(&JoyInfo);
if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick.value == 0)
@ -1050,7 +1051,7 @@ static int joy_open(const char *fname)
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0)
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
@ -1179,7 +1180,8 @@ static void I_ShutdownJoystick2(void)
}
JoyReset(&JoyInfo2);
if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick2.value == 0)
@ -1189,54 +1191,6 @@ static void I_ShutdownJoystick2(void)
}
}
/** \brief Shuts down joystick 3
\return void
*/
static void I_ShutdownJoystick3(void)
{
INT32 i;
event_t event;
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
lastjoy3buttons = lastjoy3hats = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_2JOY1 + i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++)
{
event.data1 = KEY_2HAT1 + i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick3;
for (i = 0; i < JOYAXISSET; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
JoyReset(&JoyInfo3);
if (!joystick_started && !joystick3_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick3.value == 0)
{
DEBFILE("I_Joystick3: SDL's Joystick system has been shutdown\n");
}
}
}
void I_GetJoystick2Events(void)
{
static event_t event = {0,0,0,0};
@ -1382,7 +1336,7 @@ static int joy_open2(const char *fname)
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0)
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
@ -1461,6 +1415,572 @@ static int joy_open2(const char *fname)
}
}
//Joystick3
/** \brief Joystick 3 buttons states
*/
static UINT64 lastjoy3buttons = 0;
/** \brief Joystick 3 hats state
*/
static UINT64 lastjoy3hats = 0;
/** \brief Shuts down joystick 3
\return void
*/
static void I_ShutdownJoystick3(void)
{
INT32 i;
event_t event;
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
lastjoy3buttons = lastjoy3hats = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_3JOY1 + i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++)
{
event.data1 = KEY_3HAT1 + i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick3;
for (i = 0; i < JOYAXISSET; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
JoyReset(&JoyInfo3);
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick3.value == 0)
{
DEBFILE("I_Joystick3: SDL's Joystick system has been shutdown\n");
}
}
}
void I_GetJoystick3Events(void)
{
static event_t event = {0,0,0,0};
INT32 i = 0;
UINT64 joyhats = 0;
#if 0
INT64 joybuttons = 0;
#endif
INT32 axisx, axisy;
if (!joystick3_started)
return;
if (!JoyInfo3.dev) //I_ShutdownJoystick3();
return;
#if 0
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JoyInfo3.buttons - 1; i >= 0; i--)
{
joybuttons <<= 1;
if (SDL_JoystickGetButton(JoyInfo3.dev,i))
joybuttons |= 1;
}
if (joybuttons != lastjoy3buttons)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newbuttons = joybuttons ^ lastjoy3buttons;
lastjoy3buttons = joybuttons;
for (i = 0; i < JOYBUTTONS; i++, j <<= 1)
{
if (newbuttons & j) // button changed state?
{
if (joybuttons & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_3JOY1 + i;
D_PostEvent(&event);
}
}
}
#endif
for (i = JoyInfo3.hats - 1; i >= 0; i--)
{
Uint8 hat = SDL_JoystickGetHat(JoyInfo3.dev, i);
if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i);
if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
}
if (joyhats != lastjoy3hats)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newhats = joyhats ^ lastjoy3hats;
lastjoy3hats = joyhats;
for (i = 0; i < JOYHATS*4; i++, j <<= 1)
{
if (newhats & j) // hat changed state?
{
if (joyhats & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_3HAT1 + i;
D_PostEvent(&event);
}
}
}
// send joystick axis positions
event.type = ev_joystick3;
for (i = JOYAXISSET - 1; i >= 0; i--)
{
event.data1 = i;
if (i*2 + 1 <= JoyInfo3.axises)
axisx = SDL_JoystickGetAxis(JoyInfo3.dev, i*2 + 0);
else axisx = 0;
if (i*2 + 2 <= JoyInfo3.axises)
axisy = SDL_JoystickGetAxis(JoyInfo3.dev, i*2 + 1);
else axisy = 0;
// -32768 to 32767
axisx = axisx/32;
axisy = axisy/32;
if (Joystick3.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2))
event.data2 = -1;
else if (axisx > (JOYAXISRANGE/2))
event.data2 = 1;
else
event.data2 = 0;
if (axisy < -(JOYAXISRANGE/2))
event.data3 = -1;
else if (axisy > (JOYAXISRANGE/2))
event.data3 = 1;
else
event.data3 = 0;
}
else
{
axisx = JoyInfo3.scale?((axisx/JoyInfo3.scale)*JoyInfo3.scale):axisx;
axisy = JoyInfo3.scale?((axisy/JoyInfo3.scale)*JoyInfo3.scale):axisy;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0;
if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0;
#endif
// analog control style , just send the raw data
event.data2 = axisx; // x axis
event.data3 = axisy; // y axis
}
D_PostEvent(&event);
}
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open3(const char *fname)
{
int joyindex = atoi(fname);
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return -1;
}
else
num_joy = SDL_NumJoysticks();
if (num_joy < joyindex)
{
CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i));
I_ShutdownJoystick3();
return -1;
}
}
else
{
JoyReset(&JoyInfo3);
//I_ShutdownJoystick();
//joy_open(fname);
}
num_joy = SDL_NumJoysticks();
if (joyindex <= 0 || num_joy == 0 || JoyInfo3.oldjoy == joyindex)
{
// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname);
if (num_joy != 0)
{
CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i));
}
else
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
if (joyindex <= 0 || num_joy == 0) return 0;
}
JoyInfo3.dev = SDL_JoystickOpen(joyindex-1);
if (!JoyInfo3.dev)
{
CONS_Printf(M_GetText("Couldn't open joystick3: %s\n"), SDL_GetError());
I_ShutdownJoystick3();
return -1;
}
else
{
CONS_Printf(M_GetText("Joystick3: %s\n"), SDL_JoystickName(JoyInfo3.dev));
JoyInfo3.axises = SDL_JoystickNumAxes(JoyInfo3.dev);
if (JoyInfo3.axises > JOYAXISSET*2)
JoyInfo3.axises = JOYAXISSET*2;
/* if (joyaxes < 2)
{
I_OutputMsg("Not enought axes?\n");
I_ShutdownJoystick3();
return 0;
}*/
JoyInfo3.buttons = SDL_JoystickNumButtons(JoyInfo3.dev);
if (JoyInfo3.buttons > JOYBUTTONS)
JoyInfo3.buttons = JOYBUTTONS;
JoyInfo3.hats = SDL_JoystickNumHats(JoyInfo3.dev);
if (JoyInfo3.hats > JOYHATS)
JoyInfo3.hats = JOYHATS;
JoyInfo3.balls = SDL_JoystickNumBalls(JoyInfo3.dev);
//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo3.dev), "pad");
return JoyInfo3.axises;
}
}
//Joystick4
/** \brief Joystick 4 buttons states
*/
static UINT64 lastjoy4buttons = 0;
/** \brief Joystick 4 hats state
*/
static UINT64 lastjoy4hats = 0;
/** \brief Shuts down joystick 4
\return void
*/
static void I_ShutdownJoystick4(void)
{
INT32 i;
event_t event;
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
lastjoy4buttons = lastjoy4hats = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_4JOY1 + i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++)
{
event.data1 = KEY_4HAT1 + i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick4;
for (i = 0; i < JOYAXISSET; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
JoyReset(&JoyInfo4);
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick4.value == 0)
{
DEBFILE("I_Joystick3: SDL's Joystick system has been shutdown\n");
}
}
}
void I_GetJoystick4Events(void)
{
static event_t event = {0,0,0,0};
INT32 i = 0;
UINT64 joyhats = 0;
#if 0
INT64 joybuttons = 0;
#endif
INT32 axisx, axisy;
if (!joystick4_started)
return;
if (!JoyInfo4.dev) //I_ShutdownJoystick4();
return;
#if 0
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JoyInfo4.buttons - 1; i >= 0; i--)
{
joybuttons <<= 1;
if (SDL_JoystickGetButton(JoyInfo4.dev,i))
joybuttons |= 1;
}
if (joybuttons != lastjoy4buttons)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newbuttons = joybuttons ^ lastjoy4buttons;
lastjoy4buttons = joybuttons;
for (i = 0; i < JOYBUTTONS; i++, j <<= 1)
{
if (newbuttons & j) // button changed state?
{
if (joybuttons & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_4JOY1 + i;
D_PostEvent(&event);
}
}
}
#endif
for (i = JoyInfo4.hats - 1; i >= 0; i--)
{
Uint8 hat = SDL_JoystickGetHat(JoyInfo4.dev, i);
if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i);
if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
}
if (joyhats != lastjoy4hats)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newhats = joyhats ^ lastjoy4hats;
lastjoy4hats = joyhats;
for (i = 0; i < JOYHATS*4; i++, j <<= 1)
{
if (newhats & j) // hat changed state?
{
if (joyhats & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_4HAT1 + i;
D_PostEvent(&event);
}
}
}
// send joystick axis positions
event.type = ev_joystick4;
for (i = JOYAXISSET - 1; i >= 0; i--)
{
event.data1 = i;
if (i*2 + 1 <= JoyInfo4.axises)
axisx = SDL_JoystickGetAxis(JoyInfo4.dev, i*2 + 0);
else axisx = 0;
if (i*2 + 2 <= JoyInfo4.axises)
axisy = SDL_JoystickGetAxis(JoyInfo4.dev, i*2 + 1);
else axisy = 0;
// -32768 to 32767
axisx = axisx/32;
axisy = axisy/32;
if (Joystick4.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2))
event.data2 = -1;
else if (axisx > (JOYAXISRANGE/2))
event.data2 = 1;
else
event.data2 = 0;
if (axisy < -(JOYAXISRANGE/2))
event.data3 = -1;
else if (axisy > (JOYAXISRANGE/2))
event.data3 = 1;
else
event.data3 = 0;
}
else
{
axisx = JoyInfo4.scale?((axisx/JoyInfo4.scale)*JoyInfo4.scale):axisx;
axisy = JoyInfo4.scale?((axisy/JoyInfo4.scale)*JoyInfo4.scale):axisy;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0;
if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0;
#endif
// analog control style , just send the raw data
event.data2 = axisx; // x axis
event.data3 = axisy; // y axis
}
D_PostEvent(&event);
}
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open4(const char *fname)
{
int joyindex = atoi(fname);
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return -1;
}
else
num_joy = SDL_NumJoysticks();
if (num_joy < joyindex)
{
CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i));
I_ShutdownJoystick4();
return -1;
}
}
else
{
JoyReset(&JoyInfo4);
//I_ShutdownJoystick();
//joy_open(fname);
}
num_joy = SDL_NumJoysticks();
if (joyindex <= 0 || num_joy == 0 || JoyInfo4.oldjoy == joyindex)
{
// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname);
if (num_joy != 0)
{
CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i));
}
else
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
if (joyindex <= 0 || num_joy == 0) return 0;
}
JoyInfo4.dev = SDL_JoystickOpen(joyindex-1);
if (!JoyInfo4.dev)
{
CONS_Printf(M_GetText("Couldn't open joystick4: %s\n"), SDL_GetError());
I_ShutdownJoystick3();
return -1;
}
else
{
CONS_Printf(M_GetText("Joystick4: %s\n"), SDL_JoystickName(JoyInfo4.dev));
JoyInfo3.axises = SDL_JoystickNumAxes(JoyInfo4.dev);
if (JoyInfo4.axises > JOYAXISSET*2)
JoyInfo4.axises = JOYAXISSET*2;
/* if (joyaxes < 2)
{
I_OutputMsg("Not enought axes?\n");
I_ShutdownJoystick4();
return 0;
}*/
JoyInfo4.buttons = SDL_JoystickNumButtons(JoyInfo4.dev);
if (JoyInfo4.buttons > JOYBUTTONS)
JoyInfo4.buttons = JOYBUTTONS;
JoyInfo4.hats = SDL_JoystickNumHats(JoyInfo4.dev);
if (JoyInfo4.hats > JOYHATS)
JoyInfo4.hats = JOYHATS;
JoyInfo4.balls = SDL_JoystickNumBalls(JoyInfo4.dev);
//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo4.dev), "pad");
return JoyInfo4.axises;
}
}
//
// I_InitJoystick
//
@ -1498,34 +2018,34 @@ void I_InitJoystick2(void)
void I_InitJoystick3(void)
{
//I_ShutdownJoystick3();
I_ShutdownJoystick3();
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (!strcmp(cv_usejoystick3.string, "0") || M_CheckParm("-nojoy"))
return;
/*if (joy_open3(cv_usejoystick3.string) != -1)
if (joy_open3(cv_usejoystick3.string) != -1)
JoyInfo3.oldjoy = atoi(cv_usejoystick3.string);
else
{
cv_usejoystick3.value = 0;
return;
}
joystick3_started = 1;*/
joystick3_started = 1;
}
void I_InitJoystick4(void)
{
//I_ShutdownJoystick4();
I_ShutdownJoystick4();
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (!strcmp(cv_usejoystick3.string, "0") || M_CheckParm("-nojoy"))
return;
/*if (joy_open4(cv_usejoystick4.string) != -1)
if (joy_open4(cv_usejoystick4.string) != -1)
JoyInfo4.oldjoy = atoi(cv_usejoystick4.string);
else
{
cv_usejoystick4.value = 0;
return;
}
joystick4_started = 1;*/
joystick4_started = 1;
}
static void I_ShutdownInput(void)

View file

@ -291,6 +291,25 @@ static INT32 joystick2_started = 0;
*/
SDLJoyInfo_t JoyInfo2;
/** \brief Third joystick up and running
*/
static INT32 joystick3_started = 0;
/** \brief SDL inof about joystick 3
*/
SDLJoyInfo_t JoyInfo3;
/** \brief Fourth joystick up and running
*/
static INT32 joystick4_started = 0;
/** \brief SDL inof about joystick 4
*/
SDLJoyInfo_t JoyInfo4;
#ifdef HAVE_TERMIOS
static INT32 fdmouse2 = -1;
static INT32 mouse2_started = 0;
@ -930,6 +949,28 @@ void I_JoyScale2(void)
JoyInfo2.scale = Joystick2.bGamepadStyle?1:cv_joyscale2.value;
}
void I_JoyScale3(void)
{
#ifdef GP2X
if (JoyInfo3.dev && SDL_JoystickIndex(JoyInfo3.dev) == 0)
Joystick.bGamepadStyle = true;
else
#endif
Joystick3.bGamepadStyle = cv_joyscale3.value==0;
JoyInfo3.scale = Joystick3.bGamepadStyle?1:cv_joyscale3.value;
}
void I_JoyScale4(void)
{
#ifdef GP2X
if (JoyInfo4.dev && SDL_JoystickIndex(JoyInfo4.dev) == 0)
Joystick.bGamepadStyle = true;
else
#endif
Joystick4.bGamepadStyle = cv_joyscale4.value==0;
JoyInfo4.scale = Joystick4.bGamepadStyle?1:cv_joyscale4.value;
}
/** \brief Joystick 1 buttons states
*/
static UINT64 lastjoybuttons = 0;
@ -979,7 +1020,8 @@ static void I_ShutdownJoystick(void)
joystick_started = 0;
JoyReset(&JoyInfo);
if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick.value == 0)
@ -1140,7 +1182,7 @@ static int joy_open(const char *fname)
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0)
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
@ -1273,7 +1315,8 @@ static void I_ShutdownJoystick2(void)
}
JoyReset(&JoyInfo2);
if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick2.value == 0)
@ -1434,7 +1477,7 @@ static int joy_open2(const char *fname)
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0)
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
@ -1457,7 +1500,7 @@ static int joy_open2(const char *fname)
{
JoyReset(&JoyInfo2);
//I_ShutdownJoystick();
//joy_open(fname);
//joy_open2(fname);
}
num_joy = SDL_NumJoysticks();
@ -1517,6 +1560,592 @@ static int joy_open2(const char *fname)
}
}
//Joystick3
/** \brief Joystick 3 buttons states
*/
static UINT64 lastjoy3buttons = 0;
/** \brief Joystick 3 hats state
*/
static UINT64 lastjoy3hats = 0;
/** \brief Shuts down joystick 3
\return void
*/
static void I_ShutdownJoystick3(void)
{
INT32 i;
event_t event;
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
lastjoy3buttons = lastjoy3hats = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_3JOY1 + i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++)
{
event.data1 = KEY_3HAT1 + i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick3;
for (i = 0; i < JOYAXISSET; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
JoyReset(&JoyInfo3);
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick3.value == 0)
{
DEBFILE("I_Joystick3: SDL's Joystick system has been shutdown\n");
}
}
}
void I_GetJoystick3Events(void)
{
static event_t event = {0,0,0,0};
INT32 i = 0;
UINT64 joyhats = 0;
#if 0
INT64 joybuttons = 0;
INT32 axisx, axisy;
#endif
if (!joystick3_started)
return;
if (!JoyInfo3.dev) //I_ShutdownJoystick3();
return;
#if 0
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JoyInfo3.buttons - 1; i >= 0; i--)
{
joybuttons <<= 1;
if (SDL_JoystickGetButton(JoyInfo3.dev,i))
joybuttons |= 1;
}
if (joybuttons != lastjoy3buttons)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newbuttons = joybuttons ^ lastjoy3buttons;
lastjoy3buttons = joybuttons;
for (i = 0; i < JOYBUTTONS; i++, j <<= 1)
{
if (newbuttons & j) // button changed state?
{
if (joybuttons & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_3JOY1 + i;
D_PostEvent(&event);
}
}
}
#endif
for (i = JoyInfo3.hats - 1; i >= 0; i--)
{
Uint8 hat = SDL_JoystickGetHat(JoyInfo3.dev, i);
if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i);
if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
}
if (joyhats != lastjoy3hats)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newhats = joyhats ^ lastjoy3hats;
lastjoy3hats = joyhats;
for (i = 0; i < JOYHATS*4; i++, j <<= 1)
{
if (newhats & j) // hat changed state?
{
if (joyhats & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_3HAT1 + i;
D_PostEvent(&event);
}
}
}
#if 0
// send joystick axis positions
event.type = ev_joystick3;
for (i = JOYAXISSET - 1; i >= 0; i--)
{
event.data1 = i;
if (i*2 + 1 <= JoyInfo3.axises)
axisx = SDL_JoystickGetAxis(JoyInfo3.dev, i*2 + 0);
else axisx = 0;
if (i*2 + 2 <= JoyInfo3.axises)
axisy = SDL_JoystickGetAxis(JoyInfo3.dev, i*2 + 1);
else axisy = 0;
#ifdef _arch_dreamcast // -128 to 127
axisx = axisx*8;
axisy = axisy*8;
#else // -32768 to 32767
axisx = axisx/32;
axisy = axisy/32;
#endif
if (Joystick3.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2))
event.data2 = -1;
else if (axisx > (JOYAXISRANGE/2))
event.data2 = 1;
else
event.data2 = 0;
if (axisy < -(JOYAXISRANGE/2))
event.data3 = -1;
else if (axisy > (JOYAXISRANGE/2))
event.data3 = 1;
else
event.data3 = 0;
}
else
{
axisx = JoyInfo3.scale?((axisx/JoyInfo3.scale)*JoyInfo3.scale):axisx;
axisy = JoyInfo3.scale?((axisy/JoyInfo3.scale)*JoyInfo3.scale):axisy;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0;
if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0;
#endif
// analog control style , just send the raw data
event.data2 = axisx; // x axis
event.data3 = axisy; // y axis
}
D_PostEvent(&event);
}
#endif
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open3(const char *fname)
{
int joyindex = atoi(fname);
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return -1;
}
else
num_joy = SDL_NumJoysticks();
if (num_joy < joyindex)
{
CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickName(i));
I_ShutdownJoystick3();
return -1;
}
}
else
{
JoyReset(&JoyInfo3);
//I_ShutdownJoystick();
//joy_open3(fname);
}
num_joy = SDL_NumJoysticks();
if (joyindex <= 0 || num_joy == 0 || JoyInfo3.oldjoy == joyindex)
{
// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname);
if (num_joy != 0)
{
CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickName(i));
}
else
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
if (joyindex <= 0 || num_joy == 0) return 0;
}
JoyInfo3.dev = SDL_JoystickOpen(joyindex-1);
CONS_Printf(M_GetText("Joystick3: %s\n"), SDL_JoystickName(joyindex-1));
if (!JoyInfo3.dev)
{
CONS_Printf(M_GetText("Couldn't open joystick3: %s\n"), SDL_GetError());
I_ShutdownJoystick3();
return -1;
}
else
{
JoyInfo3.axises = SDL_JoystickNumAxes(JoyInfo3.dev);
if (JoyInfo3.axises > JOYAXISSET*2)
JoyInfo3.axises = JOYAXISSET*2;
/* if (joyaxes < 2)
{
I_OutputMsg("Not enought axes?\n");
I_ShutdownJoystick3();
return 0;
}*/
JoyInfo3.buttons = SDL_JoystickNumButtons(JoyInfo3.dev);
if (JoyInfo3.buttons > JOYBUTTONS)
JoyInfo3.buttons = JOYBUTTONS;
#ifdef DC
JoyInfo3.hats = 0;
#else
JoyInfo3.hats = SDL_JoystickNumHats(JoyInfo3.dev);
if (JoyInfo3.hats > JOYHATS)
JoyInfo3.hats = JOYHATS;
JoyInfo3.balls = SDL_JoystickNumBalls(JoyInfo3.dev);
#endif
//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(SDL_JoystickIndex(JoyInfo3.dev)), "pad");
return JoyInfo3.axises;
}
}
//Joystick4
/** \brief Joystick 4 buttons states
*/
static UINT64 lastjoy4buttons = 0;
/** \brief Joystick 4 hats state
*/
static UINT64 lastjoy4hats = 0;
/** \brief Shuts down joystick 4
\return void
*/
static void I_ShutdownJoystick4(void)
{
INT32 i;
event_t event;
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
lastjoy4buttons = lastjoy4hats = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_4JOY1 + i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++)
{
event.data1 = KEY_4HAT1 + i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick4;
for (i = 0; i < JOYAXISSET; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
JoyReset(&JoyInfo4);
if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started
&& SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (cv_usejoystick4.value == 0)
{
DEBFILE("I_Joystick3: SDL's Joystick system has been shutdown\n");
}
}
}
void I_GetJoystick4Events(void)
{
static event_t event = {0,0,0,0};
INT32 i = 0;
UINT64 joyhats = 0;
#if 0
INT64 joybuttons = 0;
INT32 axisx, axisy;
#endif
if (!joystick4_started)
return;
if (!JoyInfo4.dev) //I_ShutdownJoystick4();
return;
#if 0
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JoyInfo4.buttons - 1; i >= 0; i--)
{
joybuttons <<= 1;
if (SDL_JoystickGetButton(JoyInfo4.dev,i))
joybuttons |= 1;
}
if (joybuttons != lastjoy4buttons)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newbuttons = joybuttons ^ lastjoy4buttons;
lastjoy4buttons = joybuttons;
for (i = 0; i < JOYBUTTONS; i++, j <<= 1)
{
if (newbuttons & j) // button changed state?
{
if (joybuttons & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_4JOY1 + i;
D_PostEvent(&event);
}
}
}
#endif
for (i = JoyInfo4.hats - 1; i >= 0; i--)
{
Uint8 hat = SDL_JoystickGetHat(JoyInfo4.dev, i);
if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i);
if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
}
if (joyhats != lastjoy4hats)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newhats = joyhats ^ lastjoy4hats;
lastjoy4hats = joyhats;
for (i = 0; i < JOYHATS*4; i++, j <<= 1)
{
if (newhats & j) // hat changed state?
{
if (joyhats & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_4HAT1 + i;
D_PostEvent(&event);
}
}
}
#if 0
// send joystick axis positions
event.type = ev_joystick4;
for (i = JOYAXISSET - 1; i >= 0; i--)
{
event.data1 = i;
if (i*2 + 1 <= JoyInfo4.axises)
axisx = SDL_JoystickGetAxis(JoyInfo4.dev, i*2 + 0);
else axisx = 0;
if (i*2 + 2 <= JoyInfo4.axises)
axisy = SDL_JoystickGetAxis(JoyInfo4.dev, i*2 + 1);
else axisy = 0;
#ifdef _arch_dreamcast // -128 to 127
axisx = axisx*8;
axisy = axisy*8;
#else // -32768 to 32767
axisx = axisx/32;
axisy = axisy/32;
#endif
if (Joystick4.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2))
event.data2 = -1;
else if (axisx > (JOYAXISRANGE/2))
event.data2 = 1;
else
event.data2 = 0;
if (axisy < -(JOYAXISRANGE/2))
event.data3 = -1;
else if (axisy > (JOYAXISRANGE/2))
event.data3 = 1;
else
event.data3 = 0;
}
else
{
axisx = JoyInfo4.scale?((axisx/JoyInfo4.scale)*JoyInfo4.scale):axisx;
axisy = JoyInfo4.scale?((axisy/JoyInfo4.scale)*JoyInfo4.scale):axisy;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0;
if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0;
#endif
// analog control style , just send the raw data
event.data2 = axisx; // x axis
event.data3 = axisy; // y axis
}
D_PostEvent(&event);
}
#endif
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open4(const char *fname)
{
int joyindex = atoi(fname);
int num_joy = 0;
int i;
if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return -1;
}
else
num_joy = SDL_NumJoysticks();
if (num_joy < joyindex)
{
CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickName(i));
I_ShutdownJoystick3();
return -1;
}
}
else
{
JoyReset(&JoyInfo4);
//I_ShutdownJoystick();
//joy_open4(fname);
}
num_joy = SDL_NumJoysticks();
if (joyindex <= 0 || num_joy == 0 || JoyInfo4.oldjoy == joyindex)
{
// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname);
if (num_joy != 0)
{
CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy);
for (i = 0; i < num_joy; i++)
CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickName(i));
}
else
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
if (joyindex <= 0 || num_joy == 0) return 0;
}
JoyInfo4.dev = SDL_JoystickOpen(joyindex-1);
CONS_Printf(M_GetText("Joystick4: %s\n"), SDL_JoystickName(joyindex-1));
if (!JoyInfo4.dev)
{
CONS_Printf(M_GetText("Couldn't open joystick4: %s\n"), SDL_GetError());
I_ShutdownJoystick4();
return -1;
}
else
{
JoyInfo4.axises = SDL_JoystickNumAxes(JoyInfo4.dev);
if (JoyInfo4.axises > JOYAXISSET*2)
JoyInfo4.axises = JOYAXISSET*2;
/* if (joyaxes < 2)
{
I_OutputMsg("Not enought axes?\n");
I_ShutdownJoystick4();
return 0;
}*/
JoyInfo4.buttons = SDL_JoystickNumButtons(JoyInfo4.dev);
if (JoyInfo4.buttons > JOYBUTTONS)
JoyInfo4.buttons = JOYBUTTONS;
#ifdef DC
JoyInfo4.hats = 0;
#else
JoyInfo4.hats = SDL_JoystickNumHats(JoyInfo4.dev);
if (JoyInfo4.hats > JOYHATS)
JoyInfo4.hats = JOYHATS;
JoyInfo4.balls = SDL_JoystickNumBalls(JoyInfo4.dev);
#endif
//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(SDL_JoystickIndex(JoyInfo4.dev)), "pad");
return JoyInfo4.axises;
}
}
//
// I_InitJoystick
//
@ -1550,12 +2179,44 @@ void I_InitJoystick2(void)
joystick2_started = 1;
}
void I_InitJoystick3(void)
{
I_ShutdownJoystick3();
if (!strcmp(cv_usejoystick3.string, "0") || M_CheckParm("-nojoy"))
return;
if (joy_open3(cv_usejoystick3.string) != -1)
JoyInfo3.oldjoy = atoi(cv_usejoystick3.string);
else
{
cv_usejoystick3.value = 0;
return;
}
joystick3_started = 1;
}
void I_InitJoystick4(void)
{
I_ShutdownJoystick4();
if (!strcmp(cv_usejoystick4.string, "0") || M_CheckParm("-nojoy"))
return;
if (joy_open4(cv_usejoystick4.string) != -1)
JoyInfo4.oldjoy = atoi(cv_usejoystick4.string);
else
{
cv_usejoystick4.value = 0;
return;
}
joystick4_started = 1;
}
static void I_ShutdownInput(void)
{
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
JoyReset(&JoyInfo);
JoyReset(&JoyInfo2);
JoyReset(&JoyInfo3);
JoyReset(&JoyInfo4);
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}

View file

@ -1893,7 +1893,9 @@ static void ST_overlayDrawer(void)
// This is where we draw all the fun cheese if you have the chasecam off!
if ((stplyr == &players[displayplayer] && !camera.chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))
|| (((splitscreen || splitscreen3 || splitscreen4) && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)
|| (((splitscreen3 || splitscreen4) && stplyr == &players[thirddisplayplayer]) && !camera3.chase)
|| ((splitscreen4 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase))
{
ST_drawFirstPersonHUD();
}