diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7b20c78fe..adedbc5f8 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -467,6 +467,11 @@ void D_ResetTiccmds(void) D_Clearticcmd(textcmds[i]->tic); } +ticcmd_t *D_LocalTiccmd(UINT8 ss) +{ + return &localcmds[ss]; +} + // ----------------------------------------------------------------- // end of extra data function // ----------------------------------------------------------------- diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 4e81621d9..94c7c6827 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -645,7 +645,9 @@ extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; INT32 D_NumPlayers(void); + void D_ResetTiccmds(void); +ticcmd_t *D_LocalTiccmd(UINT8 ss); tic_t GetLag(INT32 node); //UINT8 GetFreeXCmdSize(UINT8 playerid); diff --git a/src/d_main.c b/src/d_main.c index 209e7fb76..b8bb21f2a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -334,7 +334,7 @@ static boolean D_Display(void) if (rendermode == render_soft && !splitscreen) { - R_InterpolateViewRollAngle(rendertimefrac); + R_InterpolateViewRollAngle(rendertimefrac_unpaused); R_CheckViewMorph(); } @@ -558,7 +558,7 @@ static boolean D_Display(void) for (i = 0; i <= splitscreen; i++) { - V_DoPostProcessor(i, &players[displayplayers[i]], postimgparam[i]); + V_DoPostProcessor(i, postimgparam[i]); } } @@ -836,7 +836,14 @@ void D_SRB2Loop(void) rendertimefrac = FRACUNIT; } - rendertimefrac_unpaused = g_time.timefrac; + if (!hu_stopped) + { + rendertimefrac_unpaused = g_time.timefrac; + } + else + { + rendertimefrac_unpaused = FRACUNIT; + } } else { diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b01f87e5a..9e97258cf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -527,7 +527,8 @@ static CV_PossibleValue_t ps_descriptor_cons_t[] = { {1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}}; consvar_t cv_ps_descriptor = {"ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_director = {"director", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +// only there to better keep track of it globally +consvar_t cv_director = {"director", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugdirector = {"debugdirector", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showdirectorhud = {"showdirectorhud", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -987,6 +988,8 @@ void D_RegisterClientCommands(void) { CV_RegisterVar(&cv_turnaxis[i]); CV_RegisterVar(&cv_moveaxis[i]); + CV_RegisterVar(&cv_camturnaxis[i]); + CV_RegisterVar(&cv_camstrafeaxis[i]); CV_RegisterVar(&cv_brakeaxis[i]); CV_RegisterVar(&cv_aimaxis[i]); CV_RegisterVar(&cv_lookaxis[i]); @@ -2237,7 +2240,7 @@ static void Command_View_f(void) return; } - if (demo.freecam) + if (camera[viewnum-1].freecam) return; displayplayerp = &displayplayers[viewnum-1]; diff --git a/src/d_player.h b/src/d_player.h index 6337838bd..b18fea1eb 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -412,8 +412,6 @@ typedef struct player_s // See pflags_t, above. pflags_t pflags; - UINT16 postimgflags; - // playing animation. panim_t panim; diff --git a/src/dehacked.c b/src/dehacked.c index e4b4028ef..54ea4e510 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8542,6 +8542,16 @@ static int lua_enumlib_mariomode_get(lua_State *L) return 1; } +static int lua_enumlib_replayfreecam_get(lua_State *L) +{ + if (dedicated) // huh? + lua_pushboolean(L, false); + else + lua_pushboolean(L, camera[R_GetViewNumber()].freecam); + + return 1; +} + static int lua_enumlib_twodlevel_get(lua_State *L) { lua_pushboolean(L, twodlevel); @@ -9219,7 +9229,7 @@ int LUA_EnumLib(lua_State *L) lua_pushcfunction(L, lua_glib_new_getter); lua_pushliteral(L, "replayfreecam"); - lua_glib_push_bool_getter(L, &demo.freecam); + lua_pushcfunction(L, lua_enumlib_replayfreecam_get); lua_call(L, 2, 0); if (!mathlib) diff --git a/src/doomtype.h b/src/doomtype.h index 429eba77e..174bba5b1 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -342,15 +342,6 @@ union FColorRGBA } ATTRPACK; typedef union FColorRGBA RGBA_t; -typedef enum -{ - POSTIMG_WATER = 1, // Underwater screen effect. - POSTIMG_MOTION = 1<<1, // Unused motion blur effect. - POSTIMG_FLIP = 1<<2, // Flipcam screen effect. - POSTIMG_HEAT = 1<<3, // Heatwave screen effect. - POSTIMG_MIRROR = 1<<4, // encore screen effect. -} postimgflag_t; - typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num) #define LUMPERROR UINT32_MAX @@ -389,6 +380,9 @@ unset_bit_array (bitarray_t * const array, const int value) array[value >> 3] &= ~(1<<(value & 7)); } +#define intsign(n) \ + ((n) < 0 ? -1 : (n) > 0 ? 1 : 0) + typedef UINT64 precise_t; #endif //__DOOMTYPE__ diff --git a/src/g_game.c b/src/g_game.c index f12a72620..b527009db 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -334,11 +334,6 @@ boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; -// save if director is enabled -// so demos can disable it by default and restore it after -static int directorstate = 0; -tic_t directortoggletimer = 0; - static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -358,8 +353,6 @@ void SendWeaponPref2(void); void SendWeaponPref3(void); void SendWeaponPref4(void); -static void G_FixCamera(UINT8 view); - // don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. // chat timer thingy @@ -447,6 +440,20 @@ consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS] = { {"joyaxis4_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL} }; +consvar_t cv_camstrafeaxis[MAXSPLITSCREENPLAYERS] = { + {"joyaxis_camstrafe", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"joyaxis2_camstrafe", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"joyaxis3_camstrafe", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"joyaxis4_camstrafe", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL} +}; + +consvar_t cv_camturnaxis[MAXSPLITSCREENPLAYERS] = { + {"joyaxis_camturn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"joyaxis2_camturn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"joyaxis3_camturn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"joyaxis4_camturn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL} +}; + consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS] = { {"joyaxis_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, {"joyaxis2_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, @@ -719,6 +726,12 @@ INT32 JoyAxis(axis_input_e axissel, UINT8 player) case AXISMOVE: axisval = cv_moveaxis[player-1].value; break; + case AXISCAMTURN: + axisval = cv_camturnaxis[player-1].value; + break; + case AXISCAMSTRAFE: + axisval = cv_camstrafeaxis[player-1].value; + break; case AXISBRAKE: axisval = cv_brakeaxis[player-1].value; break; @@ -812,14 +825,6 @@ boolean InputDown(INT32 gc, UINT8 p) } } -// -// G_BuildTiccmd -// Builds a ticcmd from all of the available inputs -// or reads it from the demo buffer. -// If recording a demo, write it out -// -// set secondaryplayer true to build player 2's ticcmd in splitscreen mode -// INT32 localaiming[MAXSPLITSCREENPLAYERS]; angle_t localangle[MAXSPLITSCREENPLAYERS]; boolean camspin[MAXSPLITSCREENPLAYERS]; @@ -828,42 +833,94 @@ static fixed_t forwardmove[2] = {25<>16, 50<>16}; static fixed_t sidemove[2] = {2<>16, 4<>16}; static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn +// +// G_BuildLocalTiccmd +// extremely basic cut down ticcmd builder +// for spectator and freecam +// this does not make the player move at all but keeps important things working +// +static void G_BuildLocalTiccmd(ticcmd_t *cmd, UINT8 ssplayer, boolean freecam) +{ + boolean moveinput = false; + INT32 axis = 0; + const boolean usejoystick = (cv_usejoystick[(ssplayer-1)].value); + + // check for inputs and return button commands + // for stuff like joining with item button, saltyhop, honking, etc. +#define CHECKINPUT(button, AXIS, buttflag) \ + axis = JoyAxis(AXIS, ssplayer); \ + if (InputDown(button, ssplayer) || (usejoystick && axis > 0)) cmd->buttons |= buttflag; + + CHECKINPUT(gc_fire, AXISFIRE, BT_ATTACK); + CHECKINPUT(gc_drift, AXISDRIFT, BT_DRIFT); + CHECKINPUT(gc_custom1, AXISCUSTOM1, BT_CUSTOM1); + CHECKINPUT(gc_custom2, AXISCUSTOM2, BT_CUSTOM2); + CHECKINPUT(gc_custom3, AXISCUSTOM3, BT_CUSTOM3); + + // we dont need the rest of this if were in freecam state + if (freecam) + { + return; + } + + CHECKINPUT(gc_accelerate, AXISMOVE, BT_ACCELERATE); + CHECKINPUT(gc_brake, AXISBRAKE, BT_BRAKE); + +#undef CHECKINPUT + + moveinput = (InputDown(gc_turnleft, ssplayer) || InputDown(gc_turnright, ssplayer) + || InputDown(gc_aimforward, ssplayer) || InputDown(gc_aimbackward, ssplayer) || + (usejoystick && JoyAxis(AXISAIM, ssplayer) != 0) || (usejoystick && JoyAxis(AXISTURN, ssplayer) != 0)); + + axis = JoyAxis(AXISLOOKBACK, ssplayer); + camspin[ssplayer-1] = (InputDown(gc_lookback, ssplayer) || (usejoystick && axis > 0)); + + // Reset to our spec player if we watch someone else. + if ((moveinput || cmd->buttons) + && displayplayers[0] != consoleplayer && ssplayer == 1) + { + if (cv_director.value) + CV_SetValue(&cv_director, 0); + + displayplayers[0] = consoleplayer; + R_ResetViewInterpolation(0); + camera[0].reset_aiming = true; + } +} + +// +// G_BuildTiccmd +// Builds a ticcmd from all of the available inputs +// or reads it from the demo buffer. +// If recording a demo, write it out +// void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { - const UINT8 forplayer = ssplayer-1; - INT32 laim, th, tspeed, forward, side, axis; //i - const INT32 speed = 1; + INT32 laim, th, tspeed, forward, side, axis; + // these ones used for multiple conditions - boolean turnleft, turnright, mouseaiming; - boolean invertmouse, usejoystick, kbl, rd; - player_t *player; - camera_t *thiscam; + boolean turnleft, turnright; + boolean usejoystick, rd; angle_t lang; static INT32 turnheld[MAXSPLITSCREENPLAYERS]; // for accelerative turning - static boolean keyboard_look[MAXSPLITSCREENPLAYERS]; // true if lookup/down using keyboard static boolean resetdown[MAXSPLITSCREENPLAYERS]; // don't cam reset every frame - const boolean lookaxis = cv_lookaxis[forplayer].value; + if (demo.playback) + return; + + const UINT8 forplayer = (ssplayer-1); + player_t *player = ((ssplayer == 1) ? &players[consoleplayer] : &players[displayplayers[forplayer]]); + + camera_t *thiscam = &camera[forplayer]; + const boolean freecam = camera[forplayer].freecam; + const boolean analogjoystickmove = cv_usejoystick[forplayer].value && !Joystick[forplayer].bGamepadStyle; const boolean gamepadjoystickmove = cv_usejoystick[forplayer].value && Joystick[forplayer].bGamepadStyle; - if (demo.playback) return; - - if (ssplayer == 1) - player = &players[consoleplayer]; - else - player = &players[displayplayers[forplayer]]; - - if (ssplayer == 2) - thiscam = (player->bot == 2 ? &camera[0] : &camera[forplayer]); - else - thiscam = &camera[forplayer]; - lang = localangle[forplayer]; laim = localaiming[forplayer]; th = turnheld[forplayer]; - kbl = keyboard_look[forplayer]; rd = resetdown[forplayer]; switch (ssplayer) @@ -893,25 +950,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) return; } - switch (ssplayer) + // dumbass thing so we can use a few buttons but dont accidentally drive away + if (player->spectator || freecam) { - case 2: - mouseaiming = player->spectator; //(PLAYER2INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook2.value; - invertmouse = cv_invertmouse2.value; - break; - case 3: - mouseaiming = false; - invertmouse = false; - break; - case 4: - mouseaiming = false; - invertmouse = false; - break; - case 1: - default: - mouseaiming = player->spectator; //(PLAYER1INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook.value; - invertmouse = cv_invertmouse.value; - break; + cmd->angleturn = (INT16)(lang >> 16); + G_BuildLocalTiccmd(cmd, ssplayer, freecam); + + // let lua override everything + if (gamestate == GS_LEVEL) + LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd)); + + return; } usejoystick = (analogjoystickmove || gamepadjoystickmove); @@ -945,7 +994,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (th < SLOWTURNTICS) tspeed = cv_turnsmooth.value == 2 ? 2 : 0; // slow turn else - tspeed = speed; + tspeed = 1; cmd->driftturn = 0; @@ -971,7 +1020,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) side += ((axis * sidemove[0]) >> 10); } - if (player->spectator || cv_mouseturn.value) + if (cv_mouseturn.value) { //THIS WORKS WTF???????? cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8))); @@ -1060,54 +1109,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else rd = false; - // spectator aiming shit, ahhhh... - { - INT32 player_invert = invertmouse ? -1 : 1; - INT32 screen_invert = - (player->mo && (player->mo->eflags & MFE_VERTICALFLIP) - && (!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 && player->spectator) - { - kbl = false; - - // looking up/down - laim += (mlooky<<19)*player_invert*screen_invert; - } - - axis = JoyAxis(AXISLOOK, ssplayer); - if (analogjoystickmove && axis != 0 && lookaxis && player->spectator) - laim += (axis<<16) * screen_invert; - - // spring back if not using keyboard neither mouselookin' - if (!kbl && !lookaxis && !mouseaiming) - laim = 0; - - if (player->spectator) - { - if (InputDown(gc_lookup, ssplayer) || (gamepadjoystickmove && axis < 0)) - { - laim += KB_LOOKSPEED * screen_invert; - kbl = true; - } - else if (InputDown(gc_lookdown, ssplayer) || (gamepadjoystickmove && axis > 0)) - { - laim -= KB_LOOKSPEED * screen_invert; - kbl = true; - } - } - - if (InputDown(gc_centerview, ssplayer)) // No need to put a spectator limit on this one though :V - laim = 0; - - // accept no mlook for network games - if (!cv_allowmlook.value) - laim = 0; - - cmd->aiming = G_ClipAimingPitch(&laim); - } + cmd->aiming = G_ClipAimingPitch(&laim); mousex = mousey = mlooky = 0; @@ -1159,7 +1161,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { localangle[forplayer] = lang; localaiming[forplayer] = laim; - keyboard_look[forplayer] = kbl; turnheld[forplayer] = th; resetdown[forplayer] = rd; axis = JoyAxis(AXISLOOKBACK, ssplayer); @@ -1180,8 +1181,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd)); //Reset away view if a command is given. - if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) - && displayplayers[0] != consoleplayer && ssplayer == 1) + if (displayplayers[0] != consoleplayer && ssplayer == 1 + && (cmd->forwardmove || cmd->sidemove || cmd->buttons)) { displayplayers[0] = consoleplayer; G_FixCamera(1); @@ -1373,7 +1374,7 @@ boolean G_Responder(event_t *ev) } } - if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback && !demo.freecam) + if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback) { if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) { @@ -1526,6 +1527,23 @@ boolean G_Responder(event_t *ev) K_ToggleDirector(); } + if (ev->data1 == gamecontrol[gc_freecam][0] || ev->data1 == gamecontrol[gc_freecam][1]) + { + P_ToggleDemoCamera(0); + } + else if (ev->data1 == gamecontrolbis[gc_freecam][0] || ev->data1 == gamecontrolbis[gc_freecam][1]) + { + P_ToggleDemoCamera(1); + } + else if (ev->data1 == gamecontrol3[gc_freecam][0] || ev->data1 == gamecontrol3[gc_freecam][1]) + { + P_ToggleDemoCamera(2); + } + else if (ev->data1 == gamecontrol4[gc_freecam][0] || ev->data1 == gamecontrol4[gc_freecam][1]) + { + P_ToggleDemoCamera(3); + } + return true; case ev_keyup: @@ -1660,7 +1678,7 @@ INT32 G_CountPlayersPotentiallyViewable(boolean active) // Reset camera position, angle and interpolation on a view // after changing state. // -static void G_FixCamera(UINT8 view) +void G_FixCamera(UINT8 view) { player_t *player = &players[displayplayers[view - 1]]; @@ -1706,13 +1724,6 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) viewnum = playersviewable; splitscreen = viewnum-1; - /* Prepare extra views for G_FindView to pass. */ - for (viewd = splits+1; viewd < viewnum; ++viewd) - { - displayplayerp = (&displayplayers[viewd-1]); - (*displayplayerp) = INT32_MAX; - } - R_ExecuteSetViewSize(); } @@ -1733,7 +1744,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) G_FixCamera(viewd); } - if (viewnum == 1 && demo.playback) + if (demo.playback && viewnum == 1) consoleplayer = displayplayers[0]; } @@ -1747,6 +1758,10 @@ void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive) INT32 *displayplayerp, oldview; displayplayerp = &displayplayers[viewnum-1]; oldview = (*displayplayerp); + + // turn off the freecam + camera[viewnum-1].freecam = false; + G_ResetView(viewnum, ( (*displayplayerp) + offset ), onlyactive); // If no other view could be found, go back to what we had. @@ -5747,9 +5762,6 @@ void G_ConfirmRewind(tic_t rewindtime) COM_BufInsertText("renderview on\n"); - if (demo.freecam) - return; // don't touch from there - splitscreen = oldss; displayplayers[0] = olddp1; displayplayers[1] = olddp2; @@ -7164,15 +7176,14 @@ void G_DoPlayDemo(char *defdemoname) //LUA_HookInt(gamemap, HOOK(MapChange)); - displayplayers[0] = consoleplayer = 0; + consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); + memset(displayplayers,0,sizeof(displayplayers)); + memset(camera,0,sizeof(camera)); // reset freecam // Load players that were in-game when the map started p = READUINT8(demobuf.p); - for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) - displayplayers[i] = INT32_MAX; - while (p != 0xFF) { spectator = false; @@ -7288,8 +7299,8 @@ post_compat: players[i].kartweight = kartweight[i]; } - directorstate = cv_director.value; - CV_SetValue(&cv_director, 0); + if (cv_director.value) + CV_SetValue(&cv_director, 0); demo.deferstart = true; } @@ -7854,11 +7865,6 @@ void G_StopDemo(void) { Z_Free(demobuf.buffer); demobuf.buffer = NULL; - if (demo.playback) - { - CV_SetValue(&cv_director, directorstate); - directorstate = 0; - } demo.playback = false; if (demo.title) modeattacking = false; @@ -7866,14 +7872,13 @@ void G_StopDemo(void) demo.timing = false; singletics = false; - demo.freecam = false; - // reset democam shit too: - democam.cam = NULL; - democam.soundmobj = NULL; - democam.localangle = 0; - democam.localaiming = 0; - democam.turnheld = false; - democam.keyboardlook = false; + UINT8 i; + for (i = 0; i < MAXSPLITSCREENPLAYERS; ++i) + { + camera[i].freecam = false; + camera[i].localangle = 0; + camera[i].localaiming = 0; + } CV_SetValue(&cv_playbackspeed, 1); demo.rewinding = false; diff --git a/src/g_game.h b/src/g_game.h index d82946684..bf8bddeaa 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -124,6 +124,8 @@ extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mo extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_camturnaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_camstrafeaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_aimaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_lookaxis[MAXSPLITSCREENPLAYERS]; @@ -195,6 +197,8 @@ typedef enum AXISNONE = 0, AXISTURN, AXISMOVE, + AXISCAMTURN, + AXISCAMSTRAFE, AXISBRAKE, AXISAIM, AXISLOOK, @@ -232,8 +236,6 @@ extern angle_t localangle[MAXSPLITSCREENPLAYERS]; extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed extern boolean camspin[MAXSPLITSCREENPLAYERS]; // SRB2Kart -extern tic_t directortoggletimer; - // // GAME // @@ -447,4 +449,6 @@ INT16 G_TOLFlag(INT32 pgametype); INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer); void G_AddMapToBuffer(INT16 map); +void G_FixCamera(UINT8 view); + #endif diff --git a/src/g_input.c b/src/g_input.c index 1f3c69464..788d50ffb 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -902,6 +902,11 @@ static const char *gamecontrolname[num_gamecontrols] = "custom2", "custom3", "director", + "freecam", + "camfloat", + "camsink", + "strafeleft", + "straferight", }; #define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t)) diff --git a/src/g_input.h b/src/g_input.h index f6e69337d..124734004 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -100,6 +100,11 @@ typedef enum gc_custom2, // Lua scriptable gc_custom3, // Lua scriptable gc_director, + gc_freecam, // Toggle for freecam while ingame + gc_camfloat, // alternative button for raising cam + gc_camsink, // alternative button for sinking + gc_strafeleft, + gc_straferight, num_gamecontrols } gamecontrols_e; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b2877444e..9c186269e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3218,11 +3218,11 @@ static void HWR_DrawSpriteShadow(gl_vissprite_t *spr, GLPatch_t *gpatch) angle_t shadowdir; // Set direction - if (splitscreen && stplyr == &players[displayplayers[1]]) + if (splitscreen && R_GetViewNumber() == 1) shadowdir = localangle[1] + FixedAngle(cv_cam_rotate[1].value); - else if (splitscreen > 1 && stplyr == &players[displayplayers[2]]) + else if (splitscreen > 1 && R_GetViewNumber() == 2) shadowdir = localangle[2] + FixedAngle(cv_cam_rotate[2].value); - else if (splitscreen > 2 && stplyr == &players[displayplayers[3]]) + else if (splitscreen > 2 && R_GetViewNumber() == 3) shadowdir = localangle[3] + FixedAngle(cv_cam_rotate[3].value); else shadowdir = localangle[0] + FixedAngle(cv_cam_rotate[0].value); @@ -5119,8 +5119,11 @@ static void HWR_SetTransformAiming(FTransform *trans) trans->anglex = (float)(gl_aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); } -void HWR_SetTransform(float fpov, player_t *player) +void HWR_SetTransform(float fpov) { + UINT8 viewnum = R_GetViewNumber(); + camera_t *thiscam = &camera[viewnum]; + gl_viewx = FIXED_TO_FLOAT(viewx); gl_viewy = FIXED_TO_FLOAT(viewy); gl_viewz = FIXED_TO_FLOAT(viewz); @@ -5150,15 +5153,15 @@ void HWR_SetTransform(float fpov, player_t *player) atransform.splitscreen = splitscreen; atransform.flip = false; - if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimg & POSTIMG_FLIP) && !(thiscam->postimg & POSTIMG_MIRROR)) atransform.flip = true; atransform.mirror = false; - if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) + if ((thiscam->postimg & POSTIMG_MIRROR) && !(thiscam->postimg & POSTIMG_FLIP)) atransform.mirror = true; atransform.mirrorflip = false; - if ((player->postimgflags & POSTIMG_FLIP) && (player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimg & POSTIMG_FLIP) && (thiscam->postimg & POSTIMG_MIRROR)) atransform.mirrorflip = true; // Set transform. @@ -5225,7 +5228,7 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl // draw normal things in current frame in current incremented stencil buffer area HWR_SetStencilState(HWR_STENCIL_NORMAL, stencil_level); - HWR_SetTransform(fpov, player); + HWR_SetTransform(fpov); HWR_ClearSprites(); HWR_ClearClipper(); @@ -5282,7 +5285,7 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl HWR_DrawSkyBackground(); HWR_SetStencilState(HWR_STENCIL_NORMAL, 0); GL_ClearBuffer(false, false, true, 0);// clear skywall markings from the stencil buffer - HWR_SetTransform(fpov, player);// restore transform + HWR_SetTransform(fpov);// restore transform } gl_collect_skywalls = false; @@ -5729,8 +5732,12 @@ static void HWR_DoPostProcessor(player_t *player) if (splitscreen) // Not supported in splitscreen - someone want to add support? return; + //UINT8 viewnum = R_GetViewNumber(); // see above + //camera_t *thiscam = &camera[viewnum]; + camera_t *thiscam = &camera[0]; + // Drunken vision! WooOOooo~ - if (player->postimgflags & POSTIMG_WATER || player->postimgflags & POSTIMG_HEAT) + if (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; @@ -5742,7 +5749,7 @@ static void HWR_DoPostProcessor(player_t *player) INT32 FREQUENCY; // Modifies the wave. - if (player->postimgflags & POSTIMG_WATER) + if (thiscam->postimg & POSTIMG_WATER) { WAVELENGTH = 5; AMPLITUDE = 20; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 93fbd9c1e..760cce605 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -108,7 +108,7 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl void HWR_ClearSkyDome(void); void HWR_BuildSkyDome(void); -void HWR_SetTransform(float fpov, player_t *player); +void HWR_SetTransform(float fpov); void HWR_ClearClipper(void); void HWR_SetStencilState(int state, int level); diff --git a/src/hardware/hw_portal.c b/src/hardware/hw_portal.c index 27d77af2e..9bb5af40f 100644 --- a/src/hardware/hw_portal.c +++ b/src/hardware/hw_portal.c @@ -160,7 +160,7 @@ static void HWR_RenderPortalSeg(gl_portal_t* portal, SINT8 state) void HWR_RenderPortal(gl_portal_t* portal, gl_portal_t* rootportal, const float fpov, player_t *player, int stencil_level) { // draw portal seg to stencil buffer with increment - HWR_SetTransform(fpov, player); + HWR_SetTransform(fpov); HWR_ClearClipper(); HWR_SetStencilState(HWR_STENCIL_BEGIN, stencil_level); @@ -180,7 +180,7 @@ void HWR_RenderPortal(gl_portal_t* portal, gl_portal_t* rootportal, const float } // remove portal seg from stencil buffer - HWR_SetTransform(fpov, player); + HWR_SetTransform(fpov); HWR_ClearClipper(); HWR_SetStencilState(HWR_STENCIL_REVERSE, stencil_level); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 6cbb46148..7097e36a2 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -26,6 +26,7 @@ #include "i_video.h" #include "i_system.h" +#include "r_fps.h" #include "st_stuff.h" // ST_HEIGHT #include "r_local.h" @@ -2231,7 +2232,7 @@ void HU_DrawSongCredits(void) // void HU_Drawer(void) { - if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1))) + if (cv_vhseffect.value && ((paused && !camera[R_GetViewNumber()].freecam) || (demo.playback && cv_playbackspeed.value > 1))) V_DrawVhsEffect(demo.rewinding); #ifndef NONET diff --git a/src/k_director.c b/src/k_director.c index 611c64701..70fd66bbf 100644 --- a/src/k_director.c +++ b/src/k_director.c @@ -40,25 +40,6 @@ struct directorinfo INT32 boredom[MAXPLAYERS]; // how long has a given position had no credible attackers? } directorinfo; -static boolean K_DirectorIsPlayerAlone(void) -{ - UINT8 pingame = 0; - - // Gotta check how many players are active at this moment. - for (UINT8 i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - pingame++; - - if (pingame >= 2) // we dont need to check further - break; - } - - return (pingame <= 1); -} - static inline boolean race_rules(void) { return gametype == GT_RACE; @@ -71,9 +52,9 @@ static fixed_t ScaleFromMap(fixed_t n, fixed_t scale) boolean K_DirectorIsAvailable(void) { - if ((demo.playback && demo.title) || modeattacking) + if (splitscreen || (demo.playback && demo.title) || modeattacking) return false; - return ((gamestate == GS_LEVEL) && (demo.playback || (players[consoleplayer].spectator && !K_DirectorIsPlayerAlone()))); + return ((gamestate == GS_LEVEL) && ((demo.playback && !camera[0].freecam) || (players[consoleplayer].spectator && (D_NumPlayers() > 1)))); } static boolean K_DirectorIsEnabled(void) @@ -422,10 +403,9 @@ void K_ToggleDirector(void) if (!K_DirectorIsAvailable()) return; - G_AdjustView(1, 1, true); - if (!K_DirectorIsEnabled()) { + G_AdjustView(1, 1, true); directorinfo.cooldown = 0; // switch immediately } diff --git a/src/k_kart.c b/src/k_kart.c index 209f083e1..82bba14ec 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1382,7 +1382,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) dontforcespb = true; // This makes the roulette produce the random noises. - if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player) && !demo.freecam) + if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player)) { #define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->kartstuff[k_itemroulette] / 3) % 8)) for (i = 0; i <= splitscreen; i++) @@ -1416,7 +1416,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) //player->kartstuff[k_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsDisplayPlayer(player) && !demo.freecam) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrole); return; } @@ -1429,7 +1429,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemblinkmode] = 2; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsDisplayPlayer(player) && !demo.freecam) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_dbgsal); return; } @@ -1461,7 +1461,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemamount] = 1; } - if (P_IsDisplayPlayer(player) && !demo.freecam) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); player->kartstuff[k_itemblink] = TICRATE; @@ -7822,7 +7822,7 @@ static void K_initKartHUD(void) // K_GetScreenCoords needs the right view* variables R_SetViewContext(stplyrnum); - R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT, !cv_uncappedhud.value); + R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac_unpaused : FRACUNIT, !cv_uncappedhud.value); } INT32 K_calcSplitFlags(INT32 snapflags) @@ -7832,17 +7832,17 @@ INT32 K_calcSplitFlags(INT32 snapflags) if (splitscreen == 0) return snapflags; - if (stplyr != &players[displayplayers[0]]) + if (stplyrnum != 0) { - if (splitscreen == 1 && stplyr == &players[displayplayers[1]]) + if (splitscreen == 1 && stplyrnum == 1) { splitflags |= V_SPLITSCREEN; } else if (splitscreen > 1) { - if (stplyr == &players[displayplayers[2]] || (splitscreen == 3 && stplyr == &players[displayplayers[3]])) + if (stplyrnum == 2 || (splitscreen == 3 && stplyrnum == 3)) splitflags |= V_SPLITSCREEN; - if (stplyr == &players[displayplayers[1]] || (splitscreen == 3 && stplyr == &players[displayplayers[3]])) + if (stplyrnum == 1 || (splitscreen == 3 && stplyrnum == 3)) splitflags |= V_HORZSCREEN; } } @@ -7962,7 +7962,7 @@ static void K_drawKartStats(void) for (; splitnum < MAXSPLITSCREENPLAYERS; ++splitnum) { - if (stplyr == &players[displayplayers[splitnum]]) + if (stplyrnum == splitnum) break; } @@ -8545,7 +8545,7 @@ static void K_DrawKartPositionNum(INT32 num) else if (splitscreen == 1) // for this splitscreen, we'll use case by case because it's a bit different. { fx = POSI_X; - if (stplyr == &players[displayplayers[0]]) // for player 1: display this at the top right, above the minimap. + if (stplyrnum == 0) // for player 1: display this at the top right, above the minimap. { fy = 30 + cv_posi_yoffset.value; fflags = V_SNAPTOTOP|V_SNAPTORIGHT; @@ -8560,11 +8560,11 @@ static void K_DrawKartPositionNum(INT32 num) } else { - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + if (!(stplyrnum & 1)) // If we are P1 or P3... { fx = POSI_X; fy = POSI_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + fflags = V_SNAPTOLEFT|((stplyrnum == 2) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. flipdraw = true; if (num && num >= 10) fx += W; // this seems dumb, but we need to do this in order for positions above 10 going off screen. @@ -8573,7 +8573,7 @@ static void K_DrawKartPositionNum(INT32 num) { fx = POSI2_X; fy = POSI2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + fflags = V_SNAPTORIGHT|((stplyrnum == 3) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom } } @@ -9522,7 +9522,7 @@ static void K_drawDriftGauge(void) 0, 31, 47, 63, 79, 95, 111, 119, 127, 143, 159, 175, 183, 191, 199, 207, 223, 247 }; - if (demo.playback && demo.freecam) + if (camera[stplyrnum].freecam) return; if (P_MobjWasRemoved(stplyr->mo) || (!splitscreen && !camera->chase)) @@ -9680,7 +9680,7 @@ static void K_drawKartWanted(void) UINT8 *colormap = NULL; INT32 basex = 0, basey = 0; - if (stplyr != &players[displayplayers[0]]) + if (stplyrnum != 0) return; for (i = 0; i < 4; i++) @@ -9877,7 +9877,7 @@ static void K_drawKartMinimap(void) if (gamestate != GS_LEVEL) return; - if (stplyr != &players[displayplayers[0]]) + if (stplyrnum != 0) return; if (minimapinfo.minimap_pic == NULL) @@ -10035,7 +10035,7 @@ static void K_drawKartFinish(void) xval = (SHORT(kp_racefinish[pnum]->width)<kartstuff[k_cardanimation])< x ? xval : x))/TICRATE; - if (splitscreen && stplyr == &players[displayplayers[1]]) + if (splitscreen && stplyrnum == 1) x = -x; V_DrawFixedPatch(x + (STCD_X<>1), @@ -10192,14 +10192,9 @@ static void K_drawKartFirstPerson(void) if (stplyr->spectator || !stplyr->mo || (stplyr->mo->flags2 & MF2_DONTDRAW)) return; - if (stplyr == &players[displayplayers[1]] && splitscreen) - { pn = pnum[1]; tn = turn[1]; dr = drift[1]; } - else if (stplyr == &players[displayplayers[2]] && splitscreen > 1) - { pn = pnum[2]; tn = turn[2]; dr = drift[2]; } - else if (stplyr == &players[displayplayers[3]] && splitscreen > 2) - { pn = pnum[3]; tn = turn[3]; dr = drift[3]; } - else - { pn = pnum[0]; tn = turn[0]; dr = drift[0]; } + pn = pnum[stplyrnum]; + tn = turn[stplyrnum]; + dr = drift[stplyrnum]; if (splitscreen) { @@ -10321,14 +10316,9 @@ static void K_drawKartFirstPerson(void) V_DrawFixedPatch(x, y, scale, splitflags, kp_fpview[target], colmap); - if (stplyr == &players[displayplayers[1]] && splitscreen) - { pnum[1] = pn; turn[1] = tn; drift[1] = dr; } - else if (stplyr == &players[displayplayers[2]] && splitscreen > 1) - { pnum[2] = pn; turn[2] = tn; drift[2] = dr; } - else if (stplyr == &players[displayplayers[3]] && splitscreen > 2) - { pnum[3] = pn; turn[3] = tn; drift[3] = dr; } - else - { pnum[0] = pn; turn[0] = tn; drift[0] = dr; } + pnum[stplyrnum] = pn; + turn[stplyrnum] = tn; + drift[stplyrnum] = dr; } // doesn't need to ever support 4p @@ -10548,7 +10538,7 @@ static void K_drawDistributionDebugger(void) boolean dontforcespb = false; boolean spbrush = false; - if (stplyr != &players[displayplayers[0]]) // only for p1 + if (stplyrnum != 0) // only for p1 return; // The only code duplication from the Kart, just to avoid the actual item function from calculating pingame twice @@ -10612,7 +10602,7 @@ static void K_drawDistributionDebugger(void) static void K_drawCheckpointDebugger(void) { - if (stplyr != &players[displayplayers[0]]) // only for p1 + if (stplyrnum != 0) // only for p1 return; if (stplyr->starpostnum >= (numstarposts - (numstarposts/2))) @@ -10626,22 +10616,18 @@ void K_drawKartHUD(void) { boolean isfreeplay = false; boolean battlefullscreen = false; - boolean freecam = demo.freecam; //disable some hud elements w/ freecam - UINT8 i; + boolean freecam = camera[stplyrnum].freecam; //disable some hud elements w/ freecam // Define the X and Y for each drawn object // This is handled by console/menu values K_initKartHUD(); // Draw that fun first person HUD! Drawn ASAP so it looks more "real". - for (i = 0; i <= splitscreen; i++) - { - if (stplyr == &players[displayplayers[i]] && !camera[i].chase && !freecam) - K_drawKartFirstPerson(); - } + if (!camera[stplyrnum].chase && !freecam) + K_drawKartFirstPerson(); // Draw full screen stuff that turns off the rest of the HUD - if (mapreset && stplyr == &players[displayplayers[0]]) + if (mapreset && stplyrnum == 0) { K_drawChallengerScreen(); return; @@ -10734,7 +10720,7 @@ void K_drawKartHUD(void) } } - if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode + if (!stplyr->spectator && !freecam) // Bottom of the screen elements, don't need in spectate mode { if (!(splitscreen || demo.title)) { diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index f3c01f4eb..708eb8740 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -649,7 +649,7 @@ static int libd_drawOnMinimap(lua_State *L) if (gamestate != GS_LEVEL) return 0; - if (stplyr != &players[displayplayers[0]]) + if (stplyrnum != 0) return 0; AutomapPic = minimapinfo.minimap_pic; diff --git a/src/m_menu.c b/src/m_menu.c index fbe7e0ffb..f096c2131 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -643,23 +643,23 @@ static menuitem_t MISC_ReplayOptionsMenu[] = static tic_t playback_last_menu_interaction_leveltime = 0; static menuitem_t PlaybackMenu[] = { - {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu (Esc)", M_SelectableClearMenus, 0}, + {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu (Esc)", M_SelectableClearMenus, 0}, - {IT_CALL | IT_STRING, "M_PREW", "Rewind ([)", M_PlaybackRewind, 20}, - {IT_CALL | IT_STRING, "M_PPAUSE", "Pause (\\)", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward (])", M_PlaybackFastForward, 52}, - {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame ([)", M_PlaybackRewind, 20}, - {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame (])", M_PlaybackAdvance, 52}, + {IT_CALL | IT_STRING, "M_PREW", "Rewind ([)", M_PlaybackRewind, 20}, + {IT_CALL | IT_STRING, "M_PPAUSE", "Pause (\\)", M_PlaybackPause, 36}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward (])", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame ([)", M_PlaybackRewind, 20}, + {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, + {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame (])", M_PlaybackAdvance, 52}, - {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count (- and =)", M_PlaybackSetViews, 72}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint (1)", M_PlaybackAdjustView, 88}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2 (2)", M_PlaybackAdjustView, 104}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3 (3)", M_PlaybackAdjustView, 120}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4 (4)", M_PlaybackAdjustView, 136}, + {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count (- and =)", M_PlaybackSetViews, 72}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint (1)", M_PlaybackAdjustView, 88}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2 (2)", M_PlaybackAdjustView, 104}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3 (3)", M_PlaybackAdjustView, 120}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4 (4)", M_PlaybackAdjustView, 136}, {IT_CALL | IT_STRING, "M_PVIEWS", "Toggle Free Camera (')", M_PlaybackToggleFreecam, 156}, - {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, + {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, }; typedef enum { @@ -702,8 +702,8 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_CALL, NULL, "Addons...", M_Addons, 8}, - {IT_STRING | IT_CALL, NULL, "Add local skins...", M_LocalSkins, 16}, + {IT_STRING | IT_CALL, NULL, "Addons...", M_Addons, 8}, + {IT_STRING | IT_CALL, NULL, "Add local skins...", M_LocalSkins, 16}, {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 24}, {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 32}, @@ -766,7 +766,7 @@ static menuitem_t SPauseMenu[] = // Pandora's Box will be shifted up if both options are available {IT_CALL | IT_STRING, NULL, "Pandora's Box...", M_PandorasBox, 16}, {IT_CALL | IT_STRING, NULL, "Medal Hints...", M_EmblemHints, 24}, - //{IT_CALL | IT_STRING, NULL, "Level Select...", M_LoadGameLevelSelect, 32}, + //{IT_CALL | IT_STRING, NULL, "Level Select...", M_LoadGameLevelSelect, 32}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,48}, {IT_CALL | IT_STRING, NULL, "Retry", M_Retry, 56}, @@ -1034,13 +1034,13 @@ menuitem_t PlayerMenu[MAXSKINS]; static menuitem_t MP_MainMenu[] = { {IT_HEADER, NULL, "Players", NULL, 0}, - {IT_STRING|IT_CVAR, NULL, "Number of local players", &cv_splitplayers, 10}, + {IT_STRING|IT_CVAR, NULL, "Number of local players", &cv_splitplayers, 10}, - {IT_STRING|IT_KEYHANDLER,NULL, "Player setup...", M_SetupMultiHandler,18}, + {IT_STRING|IT_KEYHANDLER,NULL, "Player setup...", M_SetupMultiHandler, 18}, {IT_HEADER, NULL, "Host a game", NULL, 100-24}, #ifndef NONET - {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_PreStartServerMenu, 110-24}, + {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_PreStartServerMenu, 110-24}, #else {IT_GRAYEDOUT, NULL, "Internet/LAN...", NULL, 110-24}, #endif @@ -1049,11 +1049,11 @@ static menuitem_t MP_MainMenu[] = {IT_HEADER, NULL, "Join a game", NULL, 132-24}, #ifndef NONET #ifndef MASTERSERVER - {IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24}, + {IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24}, #else - {IT_STRING|IT_CALL, NULL, "Internet server browser...",M_PreConnectMenu, 142-24}, + {IT_STRING|IT_CALL, NULL, "Internet server browser...",M_PreConnectMenu, 142-24}, #endif - {IT_STRING|IT_CALL, NULL, "Join last server", M_ConnectLastServer, 150-24}, + {IT_STRING|IT_CALL, NULL, "Join last server", M_ConnectLastServer, 150-24}, {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 158-24}, #else {IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24}, @@ -1149,7 +1149,7 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Saturn Options...", &OP_SaturnDef, 135}, - {IT_SUBMENU|IT_STRING, NULL, "Bird...", &OP_BirdDef, 145}, + {IT_SUBMENU|IT_STRING, NULL, "Bird...", &OP_BirdDef, 145}, {IT_CALL|IT_STRING, NULL, "Local Skin Options...", M_LocalSkinMenu, 155}, }; @@ -1158,13 +1158,13 @@ static menuitem_t OP_ControlsMenu[] = {IT_CALL | IT_STRING, NULL, "Player 1 Controls...", M_Setup1PControlsMenu, 10}, {IT_CALL | IT_STRING, NULL, "Player 2 Controls...", M_Setup2PControlsMenu, 20}, - {IT_CALL | IT_STRING, NULL, "Player 3 Controls...", &M_Setup3PControlsMenu, 30}, - {IT_CALL | IT_STRING, NULL, "Player 4 Controls...", &M_Setup4PControlsMenu, 40}, + {IT_CALL | IT_STRING, NULL, "Player 3 Controls...", &M_Setup3PControlsMenu, 30}, + {IT_CALL | IT_STRING, NULL, "Player 4 Controls...", &M_Setup4PControlsMenu, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 60}, + {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 60}, - {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 80}, - {IT_STRING | IT_CVAR, NULL, "Digital turn easing", &cv_turnsmooth, 90}, + {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 80}, + {IT_STRING | IT_CVAR, NULL, "Digital turn easing", &cv_turnsmooth, 90}, }; static const char* OP_ControlsTooltips[] = @@ -1182,6 +1182,7 @@ static menuitem_t OP_AllControlsMenu[] = { {IT_SUBMENU|IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def, 0}, {IT_CALL|IT_STRING, NULL, "Reset to defaults", M_ResetControls, 8}, + //{IT_SPACE, NULL, NULL, NULL, 0}, {IT_HEADER, NULL, "Gameplay Controls", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, @@ -1194,26 +1195,37 @@ static menuitem_t OP_AllControlsMenu[] = {IT_CONTROL, NULL, "Aim Forward", M_ChangeControl, gc_aimforward }, {IT_CONTROL, NULL, "Aim Backward", M_ChangeControl, gc_aimbackward}, {IT_CONTROL, NULL, "Look Backward", M_ChangeControl, gc_lookback }, - {IT_HEADER, NULL, "Miscelleanous Controls", NULL, 0}, + + {IT_HEADER, NULL, "Miscellaneous Controls", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, {IT_CONTROL, NULL, "Chat", M_ChangeControl, gc_talkkey }, - //{IT_CONTROL, NULL, "Team Chat", M_ChangeControl, gc_teamkey }, + //{IT_CONTROL, NULL, "Team Chat", M_ChangeControl, gc_teamkey }, {IT_CONTROL, NULL, "Show Rankings", M_ChangeControl, gc_scores }, - {IT_CONTROL, NULL, "Change Viewpoint", M_ChangeControl, gc_viewpoint }, - {IT_CONTROL, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, - {IT_CONTROL, NULL, "Toggle First-Person", M_ChangeControl, gc_camtoggle }, {IT_CONTROL, NULL, "Pause", M_ChangeControl, gc_pause }, {IT_CONTROL, NULL, "Screenshot", M_ChangeControl, gc_screenshot }, {IT_CONTROL, NULL, "Toggle GIF Recording", M_ChangeControl, gc_recordgif }, {IT_CONTROL, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu }, {IT_CONTROL, NULL, "Developer Console", M_ChangeControl, gc_console }, - {IT_HEADER, NULL, "Spectator Controls", NULL, 0}, + + {IT_HEADER, NULL, "Camera Controls", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, - {IT_CONTROL, NULL, "Become Spectator", M_ChangeControl, gc_spectate }, + {IT_CONTROL, NULL, "Toggle Freecam", M_ChangeControl, gc_freecam }, {IT_CONTROL, NULL, "Look Up", M_ChangeControl, gc_lookup }, {IT_CONTROL, NULL, "Look Down", M_ChangeControl, gc_lookdown }, {IT_CONTROL, NULL, "Center View", M_ChangeControl, gc_centerview }, + {IT_CONTROL, NULL, "Float", M_ChangeControl, gc_camfloat }, + {IT_CONTROL, NULL, "Sink", M_ChangeControl, gc_camsink }, + {IT_CONTROL, NULL, "Change Viewpoint", M_ChangeControl, gc_viewpoint }, + {IT_CONTROL, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, + {IT_CONTROL, NULL, "Strafe Left", M_ChangeControl, gc_strafeleft }, + {IT_CONTROL, NULL, "Strafe Right", M_ChangeControl, gc_straferight}, + //{IT_CONTROL, NULL, "Toggle First-Person", M_ChangeControl, gc_camtoggle }, + + {IT_HEADER, NULL, "Spectator Controls", NULL, 0}, + {IT_SPACE, NULL, NULL, NULL, 0}, + {IT_CONTROL, NULL, "Become Spectator", M_ChangeControl, gc_spectate }, {IT_CONTROL, NULL, "Toggle Director", M_ChangeControl, gc_director }, + {IT_HEADER, NULL, "Custom Lua Actions", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, {IT_CONTROL, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 }, @@ -1223,90 +1235,126 @@ static menuitem_t OP_AllControlsMenu[] = static menuitem_t OP_Joystick1Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup1PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[0] , 20}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[0] , 25}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[0] , 30}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[0] , 35}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[0] , 40}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[0] , 45}, - {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[0] , 50}, - {IT_STRING | IT_CVAR, NULL, "Spec. Look Up/Down" , &cv_lookaxis[0] , 55}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[0] , 60}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[0] , 65}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[0] , 70}, - {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[0] , 75}, - {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[0] , 80}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup1PJoystickMenu , 0}, - {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[0] , 90}, - {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[0] , 95}, - {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[0] , 100}, + {IT_HEADER, NULL, "Gameplay Controls", NULL, 7}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[0] , 15}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[0] , 20}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[0] , 25}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[0] , 30}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[0] , 35}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[0] , 40}, + {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[0] , 45}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[0] , 50}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[0] , 55}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[0] , 60}, + + {IT_HEADER, NULL, "Camera Controls", NULL, 67}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[0] , 75}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_camturnaxis[0] , 80}, + {IT_STRING | IT_CVAR, NULL, "Strafe Left/Right" , &cv_camstrafeaxis[0] , 85}, + + {IT_HEADER, NULL, "Deadzones", NULL, 92}, + {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[0] , 100}, + {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[0] , 105}, + + {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, + {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[0] , 120}, + {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[0] , 125}, + {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[0] , 130}, }; static menuitem_t OP_Joystick2Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup2PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[1] , 20}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[1] , 25}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[1] , 30}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[1] , 35}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[1] , 40}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[1] , 45}, - {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[1] , 50}, - {IT_STRING | IT_CVAR, NULL, "Spec. Look Up/Down" , &cv_lookaxis[1] , 55}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[1] , 60}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[1] , 65}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[1] , 70}, - {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[1] , 75}, - {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[1] , 80}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup2PJoystickMenu , 10}, - {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[1] , 90}, - {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[1] , 95}, - {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[1] , 100}, + {IT_HEADER, NULL, "Gameplay Controls", NULL, 7}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[1] , 15}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[1] , 20}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[1] , 25}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[1] , 30}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[1] , 35}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[1] , 40}, + {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[1] , 45}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[1] , 50}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[1] , 55}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[1] , 60}, + + {IT_HEADER, NULL, "Camera Controls", NULL, 67}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[1] , 75}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_camturnaxis[1] , 80}, + {IT_STRING | IT_CVAR, NULL, "Strafe Left/Right" , &cv_camstrafeaxis[1] , 85}, + + {IT_HEADER, NULL, "Deadzones", NULL, 92}, + {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[1] , 100}, + {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[1] , 105}, + + {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, + {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[1] , 120}, + {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[1] , 125}, + {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[1] , 130}, }; static menuitem_t OP_Joystick3Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup3PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[2] , 20}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[2] , 25}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[2] , 30}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[2] , 35}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[2] , 40}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[2] , 45}, - {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[2] , 50}, - {IT_STRING | IT_CVAR, NULL, "Spec. Look Up/Down" , &cv_lookaxis[2] , 55}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[2] , 60}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[2] , 65}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[2] , 70}, - {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[2] , 75}, - {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[2] , 80}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup3PJoystickMenu , 10}, - {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[2] , 90}, - {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[2] , 95}, - {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[2] , 100}, + {IT_HEADER, NULL, "Gameplay Controls", NULL, 7}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[2] , 15}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[2] , 20}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[2] , 25}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[2] , 30}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[2] , 35}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[2] , 40}, + {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[2] , 45}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[2] , 50}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[2] , 55}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[2] , 60}, + + {IT_HEADER, NULL, "Camera Controls", NULL, 67}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[2] , 75}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_camturnaxis[2] , 80}, + {IT_STRING | IT_CVAR, NULL, "Strafe Left/Right" , &cv_camstrafeaxis[2] , 85}, + + {IT_HEADER, NULL, "Deadzones", NULL, 92}, + {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[2] , 100}, + {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[2] , 105}, + + {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, + {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[2] , 120}, + {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[2] , 125}, + {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[2] , 130}, }; static menuitem_t OP_Joystick4Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup4PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[3] , 20}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[3] , 25}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[3] , 30}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[3] , 35}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[3] , 40}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[3] , 45}, - {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[3] , 50}, - {IT_STRING | IT_CVAR, NULL, "Spec. Look Up/Down" , &cv_lookaxis[3] , 55}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[3] , 60}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[3] , 65}, - {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[3] , 70}, - {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[3] , 75}, - {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[3] , 80}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup4PJoystickMenu , 10}, - {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[3] , 90}, - {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[3] , 95}, - {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[3] , 100}, + {IT_HEADER, NULL, "Gameplay Controls", NULL, 7}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[3] , 15}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[3] , 20}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[3] , 25}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[3] , 30}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[3] , 35}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[3] , 40}, + {IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[3] , 45}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[3] , 50}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[3] , 55}, + {IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[3] , 60}, + + {IT_HEADER, NULL, "Camera Controls", NULL, 67}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[3] , 75}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_camturnaxis[3] , 80}, + {IT_STRING | IT_CVAR, NULL, "Strafe Left/Right" , &cv_camstrafeaxis[3] , 85}, + + {IT_HEADER, NULL, "Deadzones", NULL, 92}, + {IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[3] , 100}, + {IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[3] , 105}, + + {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, + {IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[3] , 120}, + {IT_STRING | IT_CVAR, NULL, "Set LED to skin color" , &cv_gamepadled[3] , 125}, + {IT_STRING | IT_CVAR, NULL, "Flash LED on powerups" , &cv_ledpowerup[3] , 130}, }; static menuitem_t OP_JoystickSetMenu[] = @@ -4020,19 +4068,19 @@ boolean M_Responder(event_t *ev) // switch viewpoints: case '1': // viewpoint for p1 (also f12) // maximum laziness: - if (!demo.freecam) + if (!camera[0].freecam) G_AdjustView(1, 1, true); break; case '2': // viewpoint for p2 - if (!demo.freecam) + if (!camera[1].freecam) G_AdjustView(2, 1, true); break; case '3': // viewpoint for p3 - if (!demo.freecam) + if (!camera[2].freecam) G_AdjustView(3, 1, true); break; case '4': // viewpoint for p4 - if (!demo.freecam) + if (!camera[3].freecam) G_AdjustView(4, 1, true); break; @@ -4259,19 +4307,19 @@ boolean M_DemoResponder(event_t *ev) // switch viewpoints: case '1': // viewpoint for p1 (also f12) // maximum laziness: - if (!demo.freecam) + if (!camera[0].freecam) G_AdjustView(1, 1, true); break; case '2': // viewpoint for p2 - if (!demo.freecam) + if (!camera[1].freecam) G_AdjustView(2, 1, true); break; case '3': // viewpoint for p3 - if (!demo.freecam) + if (!camera[2].freecam) G_AdjustView(3, 1, true); break; case '4': // viewpoint for p4 - if (!demo.freecam) + if (!camera[3].freecam) G_AdjustView(4, 1, true); break; @@ -7654,8 +7702,7 @@ static void M_PlaybackAdvance(INT32 choice) static void M_PlaybackSetViews(INT32 choice) { - - if (demo.freecam) + if (camera[0].freecam || camera[1].freecam || camera[2].freecam || camera[3].freecam) return; // not here. if (choice > 0) @@ -7685,19 +7732,10 @@ static void M_PlaybackToggleFreecam(INT32 choice) splitscreen = 0; R_ExecuteSetViewSize(); - P_InitCameraCmd(); // init camera controls - if (!demo.freecam) // toggle on + UINT8 i; + for (i = 0; i <= splitscreen; ++i) { - demo.freecam = true; - democam.cam = &camera[0]; // this is rather useful - } - else // toggle off - { - demo.freecam = false; - // reset democam vars: - democam.cam = NULL; - democam.turnheld = false; - democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway + P_ToggleDemoCamera(i); } } @@ -12066,12 +12104,12 @@ static void M_Setup1PControlsMenu(INT32 choice) // Unhide P1-only controls OP_AllControlsMenu[15].status = IT_CONTROL; // Chat OP_AllControlsMenu[16].status = IT_CONTROL; // Rankings - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_CONTROL; // Pause - OP_AllControlsMenu[21].status = IT_CONTROL; // Screenshot - OP_AllControlsMenu[22].status = IT_CONTROL; // GIF - OP_AllControlsMenu[23].status = IT_CONTROL; // System Menu - OP_AllControlsMenu[24].status = IT_CONTROL; // Console + OP_AllControlsMenu[17].status = IT_CONTROL; // Pause + OP_AllControlsMenu[18].status = IT_CONTROL; // Screenshot + OP_AllControlsMenu[19].status = IT_CONTROL; // GIF + OP_AllControlsMenu[20].status = IT_CONTROL; // System Menu + OP_AllControlsMenu[21].status = IT_CONTROL; // Console + OP_AllControlsMenu[37].status = IT_CONTROL; // Director M_SetupNextMenu(&OP_AllControlsDef); } @@ -12089,12 +12127,12 @@ static void M_Setup2PControlsMenu(INT32 choice) // Hide P1-only controls OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console + OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Pause + OP_AllControlsMenu[18].status = IT_GRAYEDOUT2; // Screenshot + OP_AllControlsMenu[19].status = IT_GRAYEDOUT2; // GIF + OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // System Menu + OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Console + OP_AllControlsMenu[37].status = IT_GRAYEDOUT2; // Director M_SetupNextMenu(&OP_AllControlsDef); } @@ -12112,12 +12150,12 @@ static void M_Setup3PControlsMenu(INT32 choice) // Hide P1-only controls OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console + OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Pause + OP_AllControlsMenu[18].status = IT_GRAYEDOUT2; // Screenshot + OP_AllControlsMenu[19].status = IT_GRAYEDOUT2; // GIF + OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // System Menu + OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Console + OP_AllControlsMenu[37].status = IT_GRAYEDOUT2; // Director M_SetupNextMenu(&OP_AllControlsDef); } @@ -12135,12 +12173,12 @@ static void M_Setup4PControlsMenu(INT32 choice) // Hide P1-only controls OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console + OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Pause + OP_AllControlsMenu[18].status = IT_GRAYEDOUT2; // Screenshot + OP_AllControlsMenu[19].status = IT_GRAYEDOUT2; // GIF + OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // System Menu + OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Console + OP_AllControlsMenu[37].status = IT_GRAYEDOUT2; // Director M_SetupNextMenu(&OP_AllControlsDef); } @@ -12396,55 +12434,26 @@ static void M_ResetControlsResponse(INT32 ch) G_Controldefault(setupcontrolplayer); // Setup gamepad option defaults (yucky) - switch (setupcontrolplayer) + for (UINT8 j = 0; j < MAXSPLITSCREENPLAYERS; j++) { - case 4: - CV_StealthSet(&cv_usejoystick[3], cv_usejoystick[3].defaultvalue); - CV_StealthSet(&cv_turnaxis[3], cv_turnaxis[3].defaultvalue); - CV_StealthSet(&cv_moveaxis[3], cv_moveaxis[3].defaultvalue); - CV_StealthSet(&cv_brakeaxis[3], cv_brakeaxis[3].defaultvalue); - CV_StealthSet(&cv_aimaxis[3], cv_aimaxis[3].defaultvalue); - CV_StealthSet(&cv_lookaxis[3], cv_lookaxis[3].defaultvalue); - CV_StealthSet(&cv_fireaxis[3], cv_fireaxis[3].defaultvalue); - CV_StealthSet(&cv_driftaxis[3], cv_driftaxis[3].defaultvalue); - CV_StealthSet(&cv_lookbackaxis[3], cv_lookbackaxis[3].defaultvalue); - break; - case 3: - CV_StealthSet(&cv_usejoystick[2], cv_usejoystick[2].defaultvalue); - CV_StealthSet(&cv_turnaxis[2], cv_turnaxis[2].defaultvalue); - CV_StealthSet(&cv_moveaxis[2], cv_moveaxis[2].defaultvalue); - CV_StealthSet(&cv_brakeaxis[2], cv_brakeaxis[2].defaultvalue); - CV_StealthSet(&cv_aimaxis[2], cv_aimaxis[2].defaultvalue); - CV_StealthSet(&cv_lookaxis[2], cv_lookaxis[2].defaultvalue); - CV_StealthSet(&cv_fireaxis[2], cv_fireaxis[2].defaultvalue); - CV_StealthSet(&cv_driftaxis[2], cv_driftaxis[2].defaultvalue); - CV_StealthSet(&cv_lookbackaxis[2], cv_lookbackaxis[2].defaultvalue); - break; - case 2: - CV_StealthSet(&cv_usejoystick[1], cv_usejoystick[1].defaultvalue); - CV_StealthSet(&cv_turnaxis[1], cv_turnaxis[1].defaultvalue); - CV_StealthSet(&cv_moveaxis[1], cv_moveaxis[1].defaultvalue); - CV_StealthSet(&cv_brakeaxis[1], cv_brakeaxis[1].defaultvalue); - CV_StealthSet(&cv_aimaxis[1], cv_aimaxis[1].defaultvalue); - CV_StealthSet(&cv_lookaxis[1], cv_lookaxis[1].defaultvalue); - CV_StealthSet(&cv_fireaxis[1], cv_fireaxis[1].defaultvalue); - CV_StealthSet(&cv_driftaxis[1], cv_driftaxis[1].defaultvalue); - CV_StealthSet(&cv_lookbackaxis[1], cv_lookbackaxis[1].defaultvalue); - break; - case 1: - default: - CV_StealthSet(&cv_usejoystick[0], cv_usejoystick[0].defaultvalue); - CV_StealthSet(&cv_turnaxis[0], cv_turnaxis[0].defaultvalue); - CV_StealthSet(&cv_moveaxis[0], cv_moveaxis[0].defaultvalue); - CV_StealthSet(&cv_brakeaxis[0], cv_brakeaxis[0].defaultvalue); - CV_StealthSet(&cv_aimaxis[0], cv_aimaxis[0].defaultvalue); - CV_StealthSet(&cv_lookaxis[0], cv_lookaxis[0].defaultvalue); - CV_StealthSet(&cv_fireaxis[0], cv_fireaxis[0].defaultvalue); - CV_StealthSet(&cv_driftaxis[0], cv_driftaxis[0].defaultvalue); - CV_StealthSet(&cv_lookbackaxis[0], cv_lookbackaxis[0].defaultvalue); - break; - } + if (setupcontrolplayer != j) + continue; + CV_StealthSet(&cv_usejoystick[j], cv_usejoystick[j].defaultvalue); + CV_StealthSet(&cv_turnaxis[j], cv_turnaxis[j].defaultvalue); + CV_StealthSet(&cv_camturnaxis[j], cv_camturnaxis[j].defaultvalue); + CV_StealthSet(&cv_camstrafeaxis[j], cv_camstrafeaxis[j].defaultvalue); + CV_StealthSet(&cv_moveaxis[j], cv_moveaxis[j].defaultvalue); + CV_StealthSet(&cv_brakeaxis[j], cv_brakeaxis[j].defaultvalue); + CV_StealthSet(&cv_aimaxis[j], cv_aimaxis[j].defaultvalue); + CV_StealthSet(&cv_lookaxis[j], cv_lookaxis[j].defaultvalue); + CV_StealthSet(&cv_fireaxis[j], cv_fireaxis[j].defaultvalue); + CV_StealthSet(&cv_driftaxis[j], cv_driftaxis[j].defaultvalue); + CV_StealthSet(&cv_lookbackaxis[j], cv_lookbackaxis[j].defaultvalue); + CV_StealthSet(&cv_custom1axis[j], cv_custom1axis[j].defaultvalue); + CV_StealthSet(&cv_custom2axis[j], cv_custom2axis[j].defaultvalue); + CV_StealthSet(&cv_custom3axis[j], cv_custom3axis[j].defaultvalue); + } S_StartSound(NULL, sfx_s224); } diff --git a/src/p_local.h b/src/p_local.h index 0c699c35d..fb2f31485 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -78,11 +78,26 @@ void P_UnlinkThinker(thinker_t *thinker); // // P_USER // + typedef struct camera_s { boolean chase; + boolean freecam; + + angle_t localangle; + INT32 localaiming; + angle_t aiming; + // Freecam: A button was held since entering from menu, so don't move camera + UINT8 button_a_held; + + // Freecam: aiming needs to be reset after switching from chasecam + boolean reset_aiming; + + // Hold up/down to pan the camera vertically + SINT8 dpad_y_held; + // Things used by FS cameras. fixed_t viewheight; angle_t startangle; @@ -112,22 +127,21 @@ typedef struct camera_s // SRB2Kart: camera pans while drifting fixed_t pan; + + // postproccess effects + UINT8 postimg; } camera_t; -// demo freecam or something before i commit die -struct demofreecam_s { - - camera_t *cam; // this is useful when the game is paused, notably - mobj_t *soundmobj; // mobj to play sound from, used in s_sound - - angle_t localangle; // keeps track of the cam angle for cmds - angle_t localaiming; // ditto with aiming - boolean turnheld; // holding turn button for gradual turn speed - boolean keyboardlook; // keyboard look +// post process types +enum +{ + POSTIMG_WATER = 1, // Underwater screen effect. + POSTIMG_MOTION = 1<<1, // Unused motion blur effect. + POSTIMG_FLIP = 1<<2, // Flipcam screen effect. + POSTIMG_HEAT = 1<<3, // Heatwave screen effect. + POSTIMG_MIRROR = 1<<4, // encore screen effect. }; -extern struct demofreecam_s democam; - extern camera_t camera[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_still[MAXSPLITSCREENPLAYERS]; @@ -137,6 +151,8 @@ extern consvar_t cv_cam_rotate[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_rotspeed[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_timeover[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_freecam_speed; + extern consvar_t cv_tilting; extern consvar_t cv_quaketilt; extern consvar_t cv_tiltsmoothing; @@ -153,10 +169,11 @@ void P_AddPlayerScore(player_t *player, UINT32 amount); void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); -void P_DemoCameraMovement(camera_t *cam); +//void P_DemoCameraMovement(camera_t *cam, UINT8 num); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); void P_ResetLocalCamAiming(player_t *player); -void P_InitCameraCmd(void); +void P_ToggleDemoCamera(UINT8 viewnum); +void P_CalcChasePostImg(player_t *player, camera_t *thiscam); boolean P_PlayerInPain(player_t *player); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_ResetPlayer(player_t *player); diff --git a/src/p_maputl.c b/src/p_maputl.c index 3c91dc922..13dd85592 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -296,7 +296,7 @@ void P_CameraLineOpening(line_t *linedef) { frontfloor = sectors[front->camsec].floorheight; frontceiling = sectors[front->camsec].ceilingheight; - if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) + if (sectors[front->camsec].f_slope) frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera[0].x, camera[0].y); if (sectors[front->camsec].c_slope) frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera[0].x, camera[0].y); @@ -306,7 +306,7 @@ void P_CameraLineOpening(line_t *linedef) { frontfloor = sectors[front->heightsec].floorheight; frontceiling = sectors[front->heightsec].ceilingheight; - if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) + if (sectors[front->heightsec].f_slope) frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera[0].x, camera[0].y); if (sectors[front->heightsec].c_slope) frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera[0].x, camera[0].y); @@ -316,11 +316,12 @@ void P_CameraLineOpening(line_t *linedef) frontfloor = P_CameraGetFloorZ(mapcampointer, front, tmx, tmy, linedef); frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tmx, tmy, linedef); } + if (back->camsec >= 0) { backfloor = sectors[back->camsec].floorheight; backceiling = sectors[back->camsec].ceilingheight; - if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) + if (sectors[back->camsec].f_slope) frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera[0].x, camera[0].y); if (sectors[back->camsec].c_slope) frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera[0].x, camera[0].y); @@ -329,7 +330,7 @@ void P_CameraLineOpening(line_t *linedef) { backfloor = sectors[back->heightsec].floorheight; backceiling = sectors[back->heightsec].ceilingheight; - if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) + if (sectors[back->heightsec].f_slope) frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera[0].x, camera[0].y); if (sectors[back->heightsec].c_slope) frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera[0].x, camera[0].y); @@ -340,104 +341,111 @@ void P_CameraLineOpening(line_t *linedef) backceiling = P_CameraGetCeilingZ(mapcampointer, back, tmx, tmy, linedef); } + fixed_t thingtop = mapcampointer->z + mapcampointer->height; + + if (frontceiling < backceiling) { - fixed_t thingtop = mapcampointer->z + mapcampointer->height; - - if (frontceiling < backceiling) - { - opentop = frontceiling; - highceiling = backceiling; - } - else - { - opentop = backceiling; - highceiling = frontceiling; - } - - if (frontfloor > backfloor) - { - openbottom = frontfloor; - lowfloor = backfloor; - } - else - { - openbottom = backfloor; - lowfloor = frontfloor; - } - - // Check for fake floors in the sector. - if (front->ffloors || back->ffloors) - { - ffloor_t *rover; - fixed_t highestceiling = highceiling; - fixed_t lowestceiling = opentop; - fixed_t highestfloor = openbottom; - fixed_t lowestfloor = lowfloor; - fixed_t delta1, delta2; - - // Check for frontsector's fake floors - if (front->ffloors) - for (rover = front->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) - continue; - - topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tmx, tmy, linedef); - - delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < lowestceiling && delta1 >= delta2) - lowestceiling = bottomheight; - else if (bottomheight < highestceiling && delta1 >= delta2) - highestceiling = bottomheight; - - if (topheight > highestfloor && delta1 < delta2) - highestfloor = topheight; - else if (topheight > lowestfloor && delta1 < delta2) - lowestfloor = topheight; - } - - // Check for backsectors fake floors - if (back->ffloors) - for (rover = back->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) - continue; - - topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tmx, tmy, linedef); - - delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < lowestceiling && delta1 >= delta2) - lowestceiling = bottomheight; - else if (bottomheight < highestceiling && delta1 >= delta2) - highestceiling = bottomheight; - - if (topheight > highestfloor && delta1 < delta2) - highestfloor = topheight; - else if (topheight > lowestfloor && delta1 < delta2) - lowestfloor = topheight; - } - - if (highestceiling < highceiling) - highceiling = highestceiling; - - if (highestfloor > openbottom) - openbottom = highestfloor; - - if (lowestceiling < opentop) - opentop = lowestceiling; - - if (lowestfloor > lowfloor) - lowfloor = lowestfloor; - } - openrange = opentop - openbottom; - return; + opentop = frontceiling; + highceiling = backceiling; } + else + { + opentop = backceiling; + highceiling = frontceiling; + } + + if (frontfloor > backfloor) + { + openbottom = frontfloor; + lowfloor = backfloor; + } + else + { + openbottom = backfloor; + lowfloor = frontfloor; + } + + // Check for fake floors in the sector. + if (front->ffloors || back->ffloors) + { + ffloor_t *rover; + fixed_t highestceiling = highceiling; + fixed_t lowestceiling = opentop; + fixed_t highestfloor = openbottom; + fixed_t lowestfloor = lowfloor; + fixed_t delta1, delta2; + + // Check for frontsector's fake floors + if (front->ffloors) + { + for (rover = front->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) + continue; + + topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tmx, tmy, linedef); + + delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); + delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + + if (bottomheight < lowestceiling && delta1 >= delta2) + lowestceiling = bottomheight; + else if (bottomheight < highestceiling && delta1 >= delta2) + highestceiling = bottomheight; + + if (topheight > highestfloor && delta1 < delta2) + highestfloor = topheight; + else if (topheight > lowestfloor && delta1 < delta2) + lowestfloor = topheight; + } + } + + // Check for backsectors fake floors + if (back->ffloors) + { + for (rover = back->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) + continue; + + topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tmx, tmy, linedef); + + delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); + delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + + if (bottomheight < lowestceiling && delta1 >= delta2) + lowestceiling = bottomheight; + else if (bottomheight < highestceiling && delta1 >= delta2) + highestceiling = bottomheight; + + if (topheight > highestfloor && delta1 < delta2) + highestfloor = topheight; + else if (topheight > lowestfloor && delta1 < delta2) + lowestfloor = topheight; + } + } + + if (highestceiling < highceiling) + highceiling = highestceiling; + + if (highestfloor > openbottom) + openbottom = highestfloor; + + if (lowestceiling < opentop) + opentop = lowestceiling; + + if (lowestfloor > lowfloor) + lowfloor = lowestfloor; + } + + openrange = opentop - openbottom; + return; } void P_LineOpening(line_t *linedef, mobj_t *mobj) @@ -466,40 +474,39 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) I_Assert(front != NULL); I_Assert(back != NULL); - { // Set open and high/low values here - fixed_t frontheight, backheight; + // Set open and high/low values here + fixed_t frontheight, backheight; - frontheight = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); + frontheight = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); + backheight = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); - if (frontheight < backheight) - { - opentop = frontheight; - highceiling = backheight; - opentopslope = front->c_slope; - } - else - { - opentop = backheight; - highceiling = frontheight; - opentopslope = back->c_slope; - } + if (frontheight < backheight) + { + opentop = frontheight; + highceiling = backheight; + opentopslope = front->c_slope; + } + else + { + opentop = backheight; + highceiling = frontheight; + opentopslope = back->c_slope; + } - frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef); + backheight = P_GetFloorZ(mobj, back, tmx, tmy, linedef); - if (frontheight > backheight) - { - openbottom = frontheight; - lowfloor = backheight; - openbottomslope = front->f_slope; - } - else - { - openbottom = backheight; - lowfloor = frontheight; - openbottomslope = back->f_slope; - } + if (frontheight > backheight) + { + openbottom = frontheight; + lowfloor = backheight; + openbottomslope = front->f_slope; + } + else + { + openbottom = backheight; + lowfloor = frontheight; + openbottomslope = back->f_slope; } if (mobj) @@ -508,29 +515,33 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // Check for collision with front side's midtexture if Effect 4 is set if (linedef->flags & ML_EFFECT4 - && !linedef->polyobj // don't do anything for polyobjects! ...for now - ) { + && !linedef->polyobj) // don't do anything for polyobjects! ...for now + { side_t *side = &sides[linedef->sidenum[0]]; fixed_t textop, texbottom, texheight; fixed_t texmid, delta1, delta2; INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid - if (texnum) { + if (texnum) + { // Get the midtexture's height texheight = textures[texnum]->height << FRACBITS; // Set texbottom and textop to the Z coordinates of the texture's boundaries + if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) // "infinite" repeat { - if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat - texbottom = openbottom + side->rowoffset; - textop = opentop + side->rowoffset; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { - texbottom = openbottom + side->rowoffset; - textop = texbottom + texheight*(side->repeatcnt+1); - } else { - textop = opentop + side->rowoffset; - texbottom = textop - texheight*(side->repeatcnt+1); - } + texbottom = openbottom + side->rowoffset; + textop = opentop + side->rowoffset; + } + else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + { + texbottom = openbottom + side->rowoffset; + textop = texbottom + texheight*(side->repeatcnt+1); + } + else + { + textop = opentop + side->rowoffset; + texbottom = textop - texheight*(side->repeatcnt+1); } texmid = texbottom+(textop-texbottom)/2; @@ -538,10 +549,13 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta1 = abs(mobj->z - texmid); delta2 = abs(thingtop - texmid); - if (delta1 > delta2) { // Below + if (delta1 > delta2) // Below + { if (opentop > texbottom) opentop = texbottom; - } else { // Above + } + else // Above + { if (openbottom < textop) openbottom = textop; } @@ -549,9 +563,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) } // Check for fake floors in the sector. - if (front->ffloors || back->ffloors - || linedef->polyobj - ) + if (front->ffloors || back->ffloors || linedef->polyobj) { ffloor_t *rover; @@ -567,6 +579,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) for (rover = front->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; + if (!(rover->flags & FF_EXISTS)) continue; @@ -584,7 +597,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF { - if (bottomheight < lowestceiling) { + if (bottomheight < lowestceiling) + { lowestceiling = bottomheight; ceilingslope = *rover->b_slope; } @@ -594,7 +608,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF { - if (topheight > highestfloor) { + if (topheight > highestfloor) + { highestfloor = topheight; floorslope = *rover->t_slope; } @@ -624,7 +639,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF { - if (bottomheight < lowestceiling) { + if (bottomheight < lowestceiling) + { lowestceiling = bottomheight; ceilingslope = *rover->b_slope; } @@ -634,7 +650,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF { - if (topheight > highestfloor) { + if (topheight > highestfloor) + { highestfloor = topheight; floorslope = *rover->t_slope; } @@ -650,29 +667,35 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta1 = abs(mobj->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2))); delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2))); - if (polysec->floorheight < lowestceiling && delta1 >= delta2) { + + if (polysec->floorheight < lowestceiling && delta1 >= delta2) + { lowestceiling = polysec->floorheight; ceilingslope = NULL; } else if (polysec->floorheight < highestceiling && delta1 >= delta2) highestceiling = polysec->floorheight; - if (polysec->ceilingheight > highestfloor && delta1 < delta2) { + if (polysec->ceilingheight > highestfloor && delta1 < delta2) + { highestfloor = polysec->ceilingheight; floorslope = NULL; } else if (polysec->ceilingheight > lowestfloor && delta1 < delta2) lowestfloor = polysec->ceilingheight; } + if (highestceiling < highceiling) highceiling = highestceiling; - if (highestfloor > openbottom) { + if (highestfloor > openbottom) + { openbottom = highestfloor; openbottomslope = floorslope; } - if (lowestceiling < opentop) { + if (lowestceiling < opentop) + { opentop = lowestceiling; opentopslope = ceilingslope; } diff --git a/src/p_mobj.c b/src/p_mobj.c index b198056af..abb82c5f4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3144,7 +3144,7 @@ static boolean P_CameraCheckHeat(camera_t *thiscam) sector_t *sector; fixed_t halfheight; - if (!thiscam) + if (!thiscam || !thiscam->subsector) return false; halfheight = thiscam->z + (thiscam->height >> 1); @@ -3182,7 +3182,7 @@ static boolean P_CameraCheckWater(camera_t *thiscam) sector_t *sector; fixed_t halfheight; - if (!thiscam) + if (!thiscam || !thiscam->subsector) return false; halfheight = thiscam->z + (thiscam->height >> 1); @@ -3235,16 +3235,23 @@ void P_DestroyRobots(void) } // the below is chasecam only, if you're curious. check out P_CalcPostImg in p_user.c for first person -static void P_CalcChasePostImg(player_t *player, camera_t *thiscam) +void P_CalcChasePostImg(player_t *player, camera_t *thiscam) { const boolean flipcam = (player->pflags & PF_FLIPCAM && !(player->pflags & PF_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP); - UINT16 postimgflags = 0; - UINT8 i; + UINT8 postimgtype = 0; if (encoremode) - postimgflags |= POSTIMG_MIRROR; + postimgtype |= POSTIMG_MIRROR; if (flipcam) - postimgflags |= POSTIMG_FLIP; + postimgtype |= POSTIMG_FLIP; + +#ifdef HWRENDER + if (rendermode == render_opengl && splitscreen) + { + thiscam->postimg = postimgtype; + return; + } +#endif if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist { @@ -3259,27 +3266,20 @@ static void P_CalcChasePostImg(player_t *player, camera_t *thiscam) // Are we in water? if (P_CameraCheckWater(&dummycam)) - postimgflags |= POSTIMG_WATER; - if (P_CameraCheckHeat(&dummycam)) - postimgflags |= POSTIMG_HEAT; + postimgtype |= POSTIMG_WATER; + else if (P_CameraCheckHeat(&dummycam)) + postimgtype |= POSTIMG_HEAT; } else { // Are we in water? if (P_CameraCheckWater(thiscam)) - postimgflags |= POSTIMG_WATER; - if (P_CameraCheckHeat(thiscam)) - postimgflags |= POSTIMG_HEAT; + postimgtype |= POSTIMG_WATER; + else if (P_CameraCheckHeat(thiscam)) + postimgtype |= POSTIMG_HEAT; } - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - - players[displayplayers[i]].postimgflags = postimgflags; - break; - } + thiscam->postimg = postimgtype; } // P_CameraThinker @@ -10624,7 +10624,9 @@ void P_SpawnPlayer(INT32 playernum) if (multiplayer && demo.playback) ; // Don't mess with spectator values since the demo setup handles them already. else if (!G_GametypeHasSpectators()) + { p->spectator = false; + } else if (netgame && p->jointime <= 1 && pcount) { p->spectator = true; @@ -10656,7 +10658,9 @@ void P_SpawnPlayer(INT32 playernum) SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } else // Otherwise, never spectator. + { p->spectator = false; + } } if (G_GametypeHasTeams()) @@ -10761,6 +10765,30 @@ void P_SpawnPlayer(INT32 playernum) P_SetScale(karmahitbox, mobj->scale); } } + + // TODO: handle splitscreen + // Spectators can switch to freecam. This should be + // disabled when they enter the race, or when the level + // changes. + if (!demo.playback) + { + if (!p->spectator) + { + if (playernum == consoleplayer) + camera[0].freecam = false; + else if (splitscreen) + { + for (i = 1; i <= splitscreen; i++) + { + if (playernum == displayplayers[i]) + { + camera[i].freecam = false; + break; + } + } + } + } + } } void P_AfterPlayerSpawn(INT32 playernum) @@ -10803,15 +10831,18 @@ void P_AfterPlayerSpawn(INT32 playernum) SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle); - for (i = 0; i <= splitscreen; i++) + if (p->spectator == false) { - if (!camera[i].chase) - continue; + for (i = 0; i <= splitscreen; i++) + { + if (!camera[i].chase) + continue; - if (displayplayers[i] != playernum) - continue; + if (displayplayers[i] != playernum) + continue; - P_ResetCamera(p, &camera[i]); + P_ResetCamera(p, &camera[i]); + } } if (CheckForReverseGravity) diff --git a/src/p_setup.c b/src/p_setup.c index 3b2ed7714..ad85df4b6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2464,6 +2464,8 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam) cam->angle = FixedAngle((fixed_t)thing->angle << FRACBITS); cam->subsector = R_PointInSubsector(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) } + + cam->chase = false; // tell camera to reset its position next tic } static void P_InitCamera(void) @@ -2472,9 +2474,13 @@ static void P_InitCamera(void) if (!dedicated) { - if (!demo.freecam) for (i = 0; i <= splitscreen; i++) + { + if (camera[i].freecam) + continue; + P_SetupCamera(displayplayers[i], &camera[i]); + } // Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) diff --git a/src/p_tick.c b/src/p_tick.c index 6996b4d4d..25934a0f1 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -400,7 +400,12 @@ static void P_DeviceRumbleTick(void) continue; } - if (player->mo == NULL) + if (camera[i].freecam) + { + continue; + } + + if (P_MobjWasRemoved(player->mo)) { continue; } @@ -464,7 +469,20 @@ void P_RunChaseCameras(void) for (i = 0; i <= splitscreen; i++) { if (camera[i].chase) - P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false); + { + player_t *p = &players[displayplayers[i]]; + camera_t *cam = &camera[i]; + + if (p->mo && p->kartstuff[k_throwdir] != 0) + { + if (p->speed < 6 * p->mo->scale && abs(cam->dpad_y_held) < 2*TICRATE) + cam->dpad_y_held += intsign(p->kartstuff[k_throwdir]); + } + else + cam->dpad_y_held = 0; + + P_MoveChaseCamera(p, cam, false); + } } } @@ -545,8 +563,8 @@ void P_Ticker(boolean run) timeinmap = (timeinmap-1) & ~3; G_PreviewRewind(leveltime); } - else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause! - P_DemoCameraMovement(democam.cam); + else + P_RunChaseCameras(); // special case: allow freecam to MOVE during pause! return; } @@ -639,10 +657,7 @@ void P_Ticker(boolean run) PS_STOP_TIMING(ps_lua_thinkframe_time); } - // Run shield positioning - //P_RunShields(); P_RunOverlays(); - P_RunShadows(); P_UpdateSpecials(); diff --git a/src/p_user.c b/src/p_user.c index 17f778ad3..f31190343 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1054,6 +1054,15 @@ boolean P_IsDisplayPlayer(const player_t *player) for (i = 0; i <= splitscreen; i++) // DON'T skip P1 { + if (camera[i].freecam) + { + // Freecam still techically has a player in + // displayplayers. But since the camera is + // detached, it would be weird if sounds were + // heard from that player's perspective. + continue; + } + if (player == &players[displayplayers[i]]) return true; } @@ -2096,7 +2105,7 @@ static void P_SpectatorMovement(player_t *player) { ticcmd_t *cmd = &player->cmd; - player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); + player->mo->angle = (angle_t)(cmd->angleturn<<16 /* not FRACBITS */); ticruned++; if (!(cmd->angleturn & TICCMD_RECEIVED)) @@ -2262,6 +2271,7 @@ static void P_MovePlayer(player_t *player) } } + // have to keep this crap for synch reasons if (player->spectator) { P_SpectatorMovement(player); @@ -3109,6 +3119,9 @@ consvar_t cv_cam_timeover[MAXSPLITSCREENPLAYERS] = { {"cam4_timeover", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}, }; +static CV_PossibleValue_t freecam_speed_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; +consvar_t cv_freecam_speed = {"freecam_speed", "1", CV_SAVE, freecam_speed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_tilting = {"tilting", "Off", CV_SAVE|CV_CALL, CV_OnOff, Bird_menu_Onchange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_quaketilt = {"quaketilt", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_tiltsmoothing = {"tiltsmoothing", "32", CV_SAVE, CV_Natural, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -3122,61 +3135,92 @@ fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42, -42, -42, -42}; #define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode) -// Heavily simplified version of G_BuildTicCmd that only takes the local first player's control input and converts it to readable ticcmd_t -// we then throw that ticcmd garbage in the camera and make it move - -// redefine this static fixed_t forwardmove[2] = {25<>16, 50<>16}; static fixed_t sidemove[2] = {2<>16, 4<>16}; static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn +static fixed_t strafemove[2] = {25<>16, 50<>16}; // faster! -static ticcmd_t cameracmd; - -struct demofreecam_s democam; - -// called by m_menu to reinit cam input every time it's toggled -void P_InitCameraCmd(void) +void P_ToggleDemoCamera(UINT8 viewnum) { - memset(&cameracmd, 0, sizeof(ticcmd_t)); // initialize cmd + camera_t *cam = &camera[viewnum]; + + // dont toggle freecam when in spec + // special case since only non splitscreen can change viewpoints + if ((!splitscreen && players[consoleplayer].spectator) || players[displayplayers[viewnum]].spectator) + { + cam->freecam = false; + return; + } + + if (!cam->freecam) // toggle on + { + cam->freecam = true; + cam->button_a_held = 2; + cam->reset_aiming = true; + + // get rid of some hud elements + if (displayplayers[0] != consoleplayer) + { + displayplayers[0] = consoleplayer; + } + } + else // toggle off + { + cam->freecam = false; + G_FixCamera(viewnum+1); + } } -static ticcmd_t *P_CameraCmd(camera_t *cam) +static ticcmd_t cameracmd[MAXSPLITSCREENPLAYERS]; +static ticcmd_t *P_CameraCmd(camera_t *cam, UINT8 num) { - INT32 laim, th, tspeed, forward, side, axis; //i - const INT32 speed = 1; + INT32 laim, forward, side, axis; + // these ones used for multiple conditions - boolean turnleft, turnright, mouseaiming; - boolean invertmouse, lookaxis, usejoystick, kbl; + boolean turnleft, turnright; + boolean strafeleft, straferight; + boolean usejoystick; angle_t lang; - INT32 player_invert; - INT32 screen_invert; + const UINT8 forplayer = num+1; - ticcmd_t *cmd = &cameracmd; + SINT8 player_invert = cv_invertmouse.value ? -1 : 1; // who tf uses two mice? - (void)cam; + memset(&cameracmd[num], 0, sizeof(ticcmd_t)); // initialize cmd - if (!demo.playback) - return cmd; // empty cmd, no. + ticcmd_t *cmd = &cameracmd[num]; - lang = democam.localangle; - laim = democam.localaiming; - th = democam.turnheld; - kbl = democam.keyboardlook; + lang = cam->localangle; + laim = cam->localaiming; - G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver + switch (forplayer) + { + case 2: + G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); + break; + case 3: + G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1); + break; + case 4: + G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1); + break; + case 1: + default: + G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver + break; + } cmd->angleturn = (INT16)(lang >> 16); cmd->aiming = G_ClipAimingPitch(&laim); - mouseaiming = true; - invertmouse = cv_invertmouse.value; - lookaxis = cv_lookaxis[0].value; + const boolean analogjoystickmove = cv_usejoystick[num].value && !Joystick[num].bGamepadStyle; + const boolean gamepadjoystickmove = cv_usejoystick[num].value && Joystick[num].bGamepadStyle; - usejoystick = true; - turnright = InputDown(gc_turnright, 1); - turnleft = InputDown(gc_turnleft, 1); + usejoystick = (analogjoystickmove || gamepadjoystickmove); - axis = JoyAxis(AXISTURN, 1); + turnright = InputDown(gc_turnright, forplayer); + turnleft = InputDown(gc_turnleft, forplayer); + + axis = JoyAxis(AXISCAMTURN, forplayer); if (encoremode) { @@ -3186,87 +3230,119 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) axis = -axis; } - if (axis != 0) + if (usejoystick && 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) - th += 1; - else - th = 0; - - if (th < SLOWTURNTICS) - tspeed = 2; // slow turn - else - tspeed = speed; - // let movement keys cancel each other out if (turnright && !(turnleft)) { - cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed])); + cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[1])); side += sidemove[1]; } else if (turnleft && !(turnright)) { - cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed])); + cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[1])); side -= sidemove[1]; } + straferight = InputDown(gc_straferight, forplayer); + strafeleft = InputDown(gc_strafeleft, forplayer); + + axis = JoyAxis(AXISCAMSTRAFE, forplayer); + + if (encoremode) + { + straferight ^= strafeleft; // swap these using three XORs + strafeleft ^= straferight; + straferight ^= strafeleft; + axis = -axis; + } + + if (usejoystick && axis != 0) + { + straferight = straferight || (axis > 0); + strafeleft = strafeleft || (axis < 0); + } + + // let strafe keys cancel each other out + if (straferight && !(strafeleft)) + { + side += strafemove[1]; + } + else if (strafeleft && !(straferight)) + { + side -= strafemove[1]; + } + cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8))); - axis = JoyAxis(AXISMOVE, 1); - if (InputDown(gc_accelerate, 1) || (usejoystick && axis > 0)) - cmd->buttons |= BT_ACCELERATE; - axis = JoyAxis(AXISBRAKE, 1); - if (InputDown(gc_brake, 1) || (usejoystick && axis > 0)) - cmd->buttons |= BT_BRAKE; - axis = JoyAxis(AXISAIM, 1); - if (InputDown(gc_aimforward, 1) || (usejoystick && axis < 0)) + axis = JoyAxis(AXISAIM, forplayer); + if (InputDown(gc_aimforward, forplayer) || (usejoystick && axis < 0)) forward += forwardmove[1]; - if (InputDown(gc_aimbackward, 1) || (usejoystick && axis > 0)) + if (InputDown(gc_aimbackward, forplayer) || (usejoystick && axis > 0)) forward -= forwardmove[1]; - // fire with any button/key - axis = JoyAxis(AXISFIRE, 1); - if (InputDown(gc_fire, 1) || (usejoystick && axis > 0)) + axis = JoyAxis(AXISFIRE, forplayer); + if (InputDown(gc_fire, forplayer) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; - // spectator aiming shit, ahhhh... - player_invert = invertmouse ? -1 : 1; - screen_invert = 1; // nope + // drift with any button/key + axis = JoyAxis(AXISDRIFT, forplayer); + if (InputDown(gc_drift, forplayer) || (usejoystick && axis > 0)) + cmd->buttons |= BT_DRIFT; - // mouse look stuff (mouse look is not the same as mouse aim) - kbl = false; + // float and sink + axis = JoyAxis(AXISMOVE, forplayer); + if (InputDown(gc_accelerate, forplayer) || (usejoystick && axis > 0)) + cmd->buttons |= BT_ACCELERATE; + axis = JoyAxis(AXISBRAKE, forplayer); + if (InputDown(gc_brake, forplayer) || (usejoystick && axis > 0)) + cmd->buttons |= BT_BRAKE; - // looking up/down - laim += (mlooky<<19)*player_invert*screen_invert; + axis = JoyAxis(AXISLOOK, forplayer); - axis = JoyAxis(AXISLOOK, 1); + laim += (mlooky<<19)*player_invert; - // spring back if not using keyboard neither mouselookin' - if (!kbl && !lookaxis && !mouseaiming) - laim = 0; - - if (InputDown(gc_lookup, 1) || (axis < 0)) + if (InputDown(gc_lookup, forplayer) || (usejoystick && axis < 0)) { - laim += KB_LOOKSPEED * screen_invert; - kbl = true; + laim += KB_LOOKSPEED; } - else if (InputDown(gc_lookdown, 1) || (axis > 0)) + else if (InputDown(gc_lookdown, forplayer) || (usejoystick && axis > 0)) { - laim -= KB_LOOKSPEED * screen_invert; - kbl = true; + laim -= KB_LOOKSPEED; } - if (InputDown(gc_centerview, 1)) // No need to put a spectator limit on this one though :V + if (InputDown(gc_centerview, forplayer)) // No need to put a spectator limit on this one though :V + { laim = 0; + cam->reset_aiming = false; + } - cmd->aiming = G_ClipAimingPitch(&laim); + //if (cam->reset_aiming || ((cmd->buttons & BT_DRIFT) && !cam->button_a_held)) + if (cam->reset_aiming) + { + INT32 aiming = laim; + INT32 smooth = FixedMul(ANGLE_11hh / 4, FCOS(laim)); + + if (abs(smooth) < abs(aiming)) + { + laim -= (angle_t)(smooth * intsign(aiming)); + } + else + { + laim = 0; + cam->reset_aiming = false; // completely smoothed out + } + } + + if (!cam->reset_aiming) + { + cmd->aiming = G_ClipAimingPitch(&laim); + } mousex = mousey = mlooky = 0; @@ -3288,69 +3364,130 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) lang += (cmd->angleturn<<16); - democam.localangle = lang; - democam.localaiming = laim; - democam.turnheld = th; - democam.keyboardlook = kbl; + cam->localangle = lang; + if (!cam->reset_aiming) + { + cam->localaiming = laim; + } return cmd; } -void P_DemoCameraMovement(camera_t *cam) +static void P_DemoCameraMovement(camera_t *cam, UINT8 num) { ticcmd_t *cmd; angle_t thrustangle; - mobj_t *awayviewmobj_hack; player_t *lastp; + const UINT8 forplayer = num+1; - // update democam stuff with what we got here: - democam.cam = cam; - democam.localangle = cam->angle; - democam.localaiming = cam->aiming; + cam->localangle = cam->angle; + cam->localaiming = cam->aiming; // first off we need to get button input - cmd = P_CameraCmd(cam); + cmd = P_CameraCmd(cam, num); - cam->aiming = cmd->aiming<angle = cmd->angleturn<<16; + // make sure we dont aim away during reset + if (!cam->reset_aiming) + { + cam->aiming = cmd->aiming << FRACBITS; + } + + cam->angle = cmd->angleturn << 16; // camera movement: + if (!cam->button_a_held) + { + fixed_t spd = 32*mapobjectscale*cv_freecam_speed.value; + int dir = ((cmd->buttons & BT_ACCELERATE || InputDown(gc_camfloat, forplayer)) ? 1 : 0) + ((cmd->buttons & BT_BRAKE || InputDown(gc_camsink, forplayer)) ? -1 : 0); - if (cmd->buttons & BT_ACCELERATE) - cam->z += 32*mapobjectscale; - else if (cmd->buttons & BT_BRAKE) - cam->z -= 32*mapobjectscale; + switch (dir) + { + case 1: + cam->z += spd; + break; + + case -1: + cam->z -= spd; + break; + } + } + + if (!(cmd->buttons & (BT_ACCELERATE | BT_DRIFT) || InputDown(gc_camfloat, forplayer)) && cam->button_a_held) + { + cam->button_a_held--; + } // if you hold item, you will lock on to displayplayer. (The last player you were ""f12-ing"") - if (cmd->buttons & BT_ATTACK) + // this feels kinda pointless for ingame freecam so keep it for replays only + if (demo.playback && cmd->buttons & BT_ATTACK) { lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot. + + const fixed_t dist = R_PointToDist2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); - cam->aiming = R_PointToAngle2(0, cam->z, R_PointToDist2(cam->x, cam->y, lastp->mo->x, lastp->mo->y), lastp->mo->z + lastp->mo->scale*128*P_MobjFlip(lastp->mo)); // This is still unholy. Aim a bit above their heads. + cam->aiming = R_PointToAngle2(0, cam->z, dist, lastp->mo->z + lastp->mo->scale*128*P_MobjFlip(lastp->mo)); // This is still unholy. Aim a bit above their heads. + cam->reset_aiming = false; + } + + if (InputDown(gc_centerview, forplayer)) // No need to put a spectator limit on this one though :V + { + cam->aiming = 0; + cam->reset_aiming = false; + } + + // After switching to democam, the vertical angle of + // chasecam is inherited. This is intentional because it + // creates a smooth transition. However, moving + // forward/back will have a slope. So, as long as democam + // controls haven't been used to alter the vertical angle, + // slowly reset it to flat. + //if (cam->reset_aiming || ((cmd->buttons & BT_DRIFT) && !cam->button_a_held)) + if (cam->reset_aiming) + { + INT32 aiming = cam->aiming; + INT32 smooth = FixedMul(ANGLE_11hh / 4, FCOS(cam->aiming)); + + if (abs(smooth) < abs(aiming)) + { + cam->aiming -= smooth * intsign(aiming); + } + else + { + cam->aiming = 0; + cam->reset_aiming = false; // completely smoothed out + } } cam->momx = cam->momy = cam->momz = 0; if (cmd->forwardmove != 0) { + fixed_t spd = cmd->forwardmove*mapobjectscale*cv_freecam_speed.value; thrustangle = cam->angle >> ANGLETOFINESHIFT; - cam->x += FixedMul(cmd->forwardmove*mapobjectscale, FINECOSINE(thrustangle)); - cam->y += FixedMul(cmd->forwardmove*mapobjectscale, FINESINE(thrustangle)); - cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming)); + cam->x += FixedMul(spd, FINECOSINE(thrustangle)); + cam->y += FixedMul(spd, FINESINE(thrustangle)); + if (!cam->reset_aiming) + { + cam->z += FixedMul(spd, AIMINGTOSLOPE(cam->aiming)); + } + // momentums are useless here, directly add to the coordinates // this.......... doesn't actually check for floors and walls and whatnot but the function to do that is a pure mess so fuck that. // besides freecam going inside walls sounds pretty cool on paper. } - // awayviewmobj hack; this is to prevent us from hearing sounds from the player's perspective + // cmd->strafemove -- cant really add stuff to ticcmd struct so im reusing this + if (cmd->sidemove != 0) // was disabled in practice anyways, since sidemove was suppressed + { + //False I fixed this shit - Nep + fixed_t spd = cmd->sidemove*mapobjectscale*cv_freecam_speed.value; - awayviewmobj_hack = P_SpawnMobj(cam->x, cam->y, cam->z, MT_THOK); - awayviewmobj_hack->tics = 2; - awayviewmobj_hack->flags2 |= MF2_DONTDRAW; - - democam.soundmobj = awayviewmobj_hack; + thrustangle = (cam->angle-ANGLE_90) >> ANGLETOFINESHIFT; + cam->x += FixedMul(spd, FINECOSINE(thrustangle)); + cam->y += FixedMul(spd, FINESINE(thrustangle)); + } // update subsector to avoid crashes; cam->subsector = R_PointInSubsector(cam->x, cam->y); @@ -3361,7 +3498,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) tic_t tries = 0; fixed_t x, y, z; - if (demo.freecam) + if (thiscam->freecam) return; // do not reset the camera there. if (!player->mo) @@ -3400,6 +3537,8 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) thiscam->radius = 20*FRACUNIT; thiscam->height = 16*FRACUNIT; + thiscam->reset_aiming = true; + while (!P_MoveChaseCamera(player,thiscam,true) && ++tries < 2*TICRATE); } @@ -3623,8 +3762,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall mobj_t *mo; fixed_t f1, f2; - democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we - // We probably shouldn't move the camera if there is no player or player mobj somehow if (!player || !player->mo) return true; @@ -3633,12 +3770,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) return true; - if (demo.freecam) - { - P_DemoCameraMovement(thiscam); - return true; - } - if (thiscam == &camera[1]) // Camera 2 { num = 1; @@ -3656,6 +3787,16 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall num = 0; } + if (thiscam->freecam || player->spectator) + { + P_DemoCameraMovement(thiscam, num); + P_CalcChasePostImg(player, thiscam); + return true; + } + + if (paused || P_AutoPause()) + return true; + if (player == &players[consoleplayer]) { plyrnum = 0; @@ -3739,6 +3880,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall focusaiming = player->aiming; } + if (abs(thiscam->dpad_y_held) >= 2*TICRATE) + { + focusaiming += ANGLE_45 * intsign(thiscam->dpad_y_held) * P_MobjFlip(mo); + } + if (P_CameraThinker(player, thiscam, resetcalled)) return true; @@ -4072,14 +4218,90 @@ boolean P_SpectatorJoinGame(player_t *player) return false; } -// the below is first person only, if you're curious. check out P_CalcChasePostImg in p_mobj.c for chasecam -static void P_CalcPostImg(player_t *player) +static boolean P_CameraCheckHeatFirstperson(player_t *player, sector_t *sector, fixed_t pviewheight) { - sector_t *sector = player->mo->subsector->sector; - INT16 typeflag = 0; + if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1) + return true; + + if (sector->ffloors) + { + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (pviewheight >= P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y)) + continue; + + if (pviewheight <= P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y)) + continue; + + if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) + return true; + } + } + + return false; +} + +static boolean P_CameraCheckWaterFirstperson(player_t *player, sector_t *sector, fixed_t pviewheight) +{ + if (sector->ffloors) + { + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKPLAYER) + continue; + + if (pviewheight >= P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y)) + continue; + + if (pviewheight <= P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y)) + continue; + + return true; + } + } + + return false; +} + +// the below is first person only, if you're curious. check out P_CalcChasePostImg in p_mobj.c for chasecam +static void P_CalcPostImg(player_t *player, camera_t *thiscam) +{ + sector_t *sector = NULL; + UINT8 postimgtype = 0; //INT32 *param; - fixed_t pviewheight; - UINT8 i; + fixed_t pviewheight = 0; + + /*for (i = 0; i <= splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + { + param = &postimgparam[i]; + break; + } + }*/ + + if (encoremode) // srb2kart + postimgtype |= POSTIMG_MIRROR; + + if (player->mo->eflags & MFE_VERTICALFLIP) + postimgtype |= POSTIMG_FLIP; + +#ifdef HWRENDER + if (rendermode == render_opengl && splitscreen) + { + thiscam->postimg = postimgtype; + return; + } +#endif + + sector = player->mo->subsector->sector; if (player->mo->eflags & MFE_VERTICALFLIP) pviewheight = player->mo->z + player->mo->height - player->viewheight; @@ -4092,88 +4314,25 @@ static void P_CalcPostImg(player_t *player) pviewheight = player->awayviewmobj->z + 20*FRACUNIT; } - /*for (i = 0; i <= splitscreen; i++) - { - if (player == &players[displayplayers[i]]) - { - param = &postimgparam[i]; - break; - } - }*/ - - // see if we are in heat (no, not THAT kind of heat...) - - if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1) - typeflag |= POSTIMG_HEAT; - else if (sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight; - fixed_t bottomheight; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; - - if (pviewheight >= topheight || pviewheight <= bottomheight) - continue; - - if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) - typeflag |= POSTIMG_HEAT; - } - } - // see if we are in water (water trumps heat) - if (sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight; - fixed_t bottomheight; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKPLAYER) - continue; - - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; - - if (pviewheight >= topheight || pviewheight <= bottomheight) - continue; - - typeflag |= POSTIMG_WATER; - } - } - - if (encoremode) // srb2kart - typeflag |= POSTIMG_MIRROR; - - if (player->mo->eflags & MFE_VERTICALFLIP) - typeflag |= POSTIMG_FLIP; + if (P_CameraCheckWaterFirstperson(player, sector, pviewheight)) + postimgtype |= POSTIMG_WATER; + // see if we are in heat (no, not THAT kind of heat...) + else if (P_CameraCheckHeatFirstperson(player, sector, pviewheight)) + postimgtype |= POSTIMG_HEAT; // Motion blur // unused /*if (player->speed > (35<speed - 32)/4; if (*param > 5) *param = 5; }*/ - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - - players[displayplayers[i]].postimgflags = typeflag; - break; - } + thiscam->postimg = postimgtype; } void P_DoTimeOver(player_t *player) @@ -4958,7 +5117,7 @@ void P_PlayerAfterThink(player_t *player) if (!thiscam->chase) // bob view only if looking through the player's eyes { P_CalcHeight(player); - P_CalcPostImg(player); + P_CalcPostImg(player, thiscam); } else { diff --git a/src/r_bsp.c b/src/r_bsp.c index db6a4378d..66861c49a 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -263,21 +263,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, mobj_t *pviewmobj = viewplayer->mo; INT32 heightsec; boolean underwater; - UINT8 i; - - for (i = 0; i <= splitscreen; i++) - { - if (viewplayer != &players[displayplayers[i]]) - continue; - - if (!camera[i].chase) - continue; + UINT8 i = R_GetViewNumber(); + if (viewplayer == &players[displayplayers[i]] && camera[i].chase) heightsec = R_PointInSubsector(camera[i].x, camera[i].y)->sector->heightsec; - break; - } - - if (i > splitscreen && pviewmobj) + else if (i > splitscreen && viewmobj) heightsec = R_PointInSubsector(pviewmobj->x, pviewmobj->y)->sector->heightsec; else return sec; diff --git a/src/r_fps.h b/src/r_fps.h index 5ac6cfe90..563989fa6 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -37,6 +37,10 @@ enum viewcontext_e VIEWCONTEXT_SKY4 }; +extern enum viewcontext_e viewcontext; + +#define R_GetViewNumber() ((viewcontext - VIEWCONTEXT_PLAYER1) & 3) + typedef struct { fixed_t x; fixed_t y; diff --git a/src/r_main.c b/src/r_main.c index ba60d2553..20461b4a6 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -839,13 +839,10 @@ void R_ApplyViewMorph(void) vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width); } -static inline int intsign(int n) { - return n < 0 ? -1 : n > 0 ? 1 : 0; -} - angle_t R_ViewRollAngle(const player_t *player) { angle_t roll = 0; + const UINT8 viewnum = R_GetViewNumber(); if (gamestate != GS_LEVEL) { @@ -864,7 +861,7 @@ angle_t R_ViewRollAngle(const player_t *player) if (cv_tilting.value) { - if (!player->spectator && !demo.freecam) + if (!player->spectator && !camera[viewnum].freecam) roll += player->tilt; if (cv_actionmovie.value) @@ -1089,7 +1086,7 @@ static void R_SetupCommonFrame(player_t * player, subsector_t * subsector) else newview->sector = R_PointInSubsector(newview->x, newview->y)->sector; - R_InterpolateView(R_UsingFrameInterpolation() ? (demo.playback && demo.freecam) ? rendertimefrac_unpaused : rendertimefrac : FRACUNIT, false); + R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac_unpaused : FRACUNIT, false); } static void R_SetupAimingFrame(player_t *player, camera_t *thiscam) @@ -1235,9 +1232,14 @@ void R_SetupFrame(int s, boolean skybox) thiscam->reset = false; } - if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off - else if (player->playerstate == PST_DEAD || player->exiting) + if (player->spectator) + { + // Free flying spectator uses demo freecam. This + // requires chasecam to be enabled. + chasecam = true; + } + + if (player->playerstate == PST_DEAD || player->exiting) chasecam = true; // force chasecam on if (chasecam && (thiscam && !thiscam->chase)) @@ -1266,7 +1268,7 @@ void R_SetupFrame(int s, boolean skybox) R_SetupCommonFrame(player, subsector); } - else if (!player->spectator && (thiscam && chasecam)) // use outside cam view + else if (thiscam && chasecam) // use outside cam view { viewmobj = NULL; @@ -1562,6 +1564,8 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam_timeover[i]); } + CV_RegisterVar(&cv_freecam_speed); + CV_RegisterVar(&cv_tilting); CV_RegisterVar(&cv_quaketilt); CV_RegisterVar(&cv_tiltsmoothing); diff --git a/src/r_things.c b/src/r_things.c index 1cca7bbed..a17ee94a9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -584,7 +584,7 @@ void R_DrawMaskedColumn(column_t *column) basetexturemid = dc_texturemid; - if (!column || column == 0) + if (column == NULL) return; for (; column->topdelta != 0xff ;) diff --git a/src/s_sound.c b/src/s_sound.c index 453778027..7904ae90e 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -456,11 +456,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) memset(&listener[i], 0, sizeof (listener[i])); listenmobj[i] = NULL; - if (i == 0 && democam.soundmobj) - { - listenmobj[i] = democam.soundmobj; - } - else if (player->awayviewtics) + if (player->awayviewtics) { listenmobj[i] = player->awayviewmobj; } @@ -469,7 +465,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) listenmobj[i] = player->mo; } - if (origin && origin == listenmobj[i]) + if (origin && origin == listenmobj[i] && !camera[i].freecam) { itsUs = true; } @@ -719,12 +715,6 @@ void S_UpdateSounds(void) memset(&listener[i], 0, sizeof (listener[i])); listenmobj[i] = NULL; - if (i == 0 && democam.soundmobj) - { - listenmobj[i] = democam.soundmobj; - continue; - } - if (player->awayviewtics) { listenmobj[i] = player->awayviewmobj; @@ -780,6 +770,9 @@ void S_UpdateSounds(void) for (i = splitscreen; i >= 0; i--) { + if (camera[i].freecam) + continue; + if (c->origin != listenmobj[i]) continue; diff --git a/src/st_stuff.c b/src/st_stuff.c index 8b431b2f0..f99c19fd3 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -53,6 +53,9 @@ UINT16 objectsdrawn = 0; +// dumb fade thing for director toggle +tic_t directortoggletimer = 0; + // // STATUS BAR DATA // @@ -651,6 +654,25 @@ static void ST_drawLevelTitle(void) V_DrawLevelTitle(ttlnumxpos+12, bary+6, V_SNAPTOBOTTOM, actnum); } +// returns the actual button name for any gamecontrol +// if unbound is set, it returns "Unbound" as a string should there be no button bound to a gamecontrol +// if gamectrl is set, it adds an extra "-" for cases where theres also a hardcoded button like accelerate +static const char *ST_GetButtonName(INT32 control, const char *inputtext, boolean unbound, boolean gamectrl) +{ + static char buttname[32] = ""; + const char *butt1 = (gamecontrol[control][0] != 0 ? G_KeynumToString(gamecontrol[control][0]) : NULL); + const char *butt2 = (gamecontrol[control][1] != 0 ? G_KeynumToString(gamecontrol[control][1]) : NULL); // alternative bind + + if (butt1 == NULL && butt2 == NULL) // not bound to a button + snprintf(buttname, 32, (unbound ? "%s - %s" : (gamectrl ? "-%s - %s" : "%s - %s")), (unbound ? "Unbound" : ""), inputtext); + else if (butt1 != NULL && butt2 != NULL) // bound to two buttons + snprintf(buttname, 32, "%s/%s - %s", butt1, butt2, inputtext); + else // bound to only one + snprintf(buttname, 32, (gamectrl ? "-%s - %s" : "%s - %s"), (butt1 != NULL ? butt1 : butt2 != NULL ? butt2 : ""), inputtext); + + return buttname; +} + // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // @@ -702,7 +724,7 @@ static void ST_overlayDrawer(void) V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_SNAPTOBOTTOM|V_HUDTRANS|V_ALLOWLOWERCASE, player_names[stplyr-players]); } } - else if (!demo.title && !demo.freecam) + else if (!demo.title && !camera[stplyrnum].freecam) { if (!splitscreen) { @@ -713,7 +735,7 @@ static void ST_overlayDrawer(void) { char name[MAXPLAYERNAME+12]; - INT32 y = (stplyr == &players[displayplayers[0]]) ? 4 : BASEVIDHEIGHT/2-12; + INT32 y = (stplyrnum == 0) ? 4 : BASEVIDHEIGHT/2-12; sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]); V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name); } @@ -775,26 +797,16 @@ static void ST_overlayDrawer(void) { V_DrawString(2, BASEVIDHEIGHT-50, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -")); V_DrawString(2, BASEVIDHEIGHT-40, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, itemtxt); - V_DrawString(2, BASEVIDHEIGHT-30, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, M_GetText("Accelerate - Float")); - V_DrawString(2, BASEVIDHEIGHT-20, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, M_GetText("Brake - Sink")); - - char directortoggle[32] = {0}; - const char *item1 = gamecontrol[gc_director][0] != 0 ? G_KeynumToString(gamecontrol[gc_director][0]) : NULL; - const char *item2 = gamecontrol[gc_director][1] != 0 ? G_KeynumToString(gamecontrol[gc_director][1]) : NULL; - - if (item1 != NULL && item2 != NULL) - snprintf(directortoggle, 32, "%s/%s - Toggle Director", item1, item2); - else - snprintf(directortoggle, 32, "%s - Toggle Director", item1 != NULL ? item1 : item2 != NULL ? item2 : "Not Bound"); - - V_DrawString(2, BASEVIDHEIGHT-10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, directortoggle); + V_DrawString(2, BASEVIDHEIGHT-30, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, va("Accelerate %s", ST_GetButtonName(gc_camfloat, "Float", false, true))); + V_DrawString(2, BASEVIDHEIGHT-20, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, va("Brake %s", ST_GetButtonName(gc_camsink, "Sink", false, true))); + V_DrawString(2, BASEVIDHEIGHT-10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, ST_GetButtonName(gc_director, "Toggle Director", true, false)); } else { V_DrawString(2, BASEVIDHEIGHT-40, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -")); V_DrawString(2, BASEVIDHEIGHT-30, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, itemtxt); - V_DrawString(2, BASEVIDHEIGHT-20, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, M_GetText("Accelerate - Float")); - V_DrawString(2, BASEVIDHEIGHT-10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, M_GetText("Brake - Sink")); + V_DrawString(2, BASEVIDHEIGHT-20, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, va("Accelerate %s", ST_GetButtonName(gc_camfloat, "Float", false, true))); + V_DrawString(2, BASEVIDHEIGHT-10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_HUDTRANSHALF, va("Brake %s", ST_GetButtonName(gc_camsink, "Sink", false, true))); } } } diff --git a/src/st_stuff.h b/src/st_stuff.h index 250db1e7f..d289e64ce 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -23,6 +23,8 @@ // STATUS BAR // +extern tic_t directortoggletimer; + // Called by main loop. void ST_Ticker(void); diff --git a/src/v_video.c b/src/v_video.c index 987a40a03..da2b0677a 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3175,7 +3175,7 @@ INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; // Perform a particular image postprocessing function. // -void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) +void V_DoPostProcessor(INT32 view, INT32 param) { #if NUMSCREENS < 5 // do not enable image post processing for ARM, SH and MIPS CPUs @@ -3194,7 +3194,9 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) if (view < 0 || view > 3 || view > splitscreen) return; - if (!player->postimgflags) + camera_t *thiscam = &camera[view]; + + if (!thiscam->postimg) return; if ((view == 1 && splitscreen == 1) || view >= 2) @@ -3210,7 +3212,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) UINT8 *tmpscr = screens[4]; UINT8 *srcscr = screens[0]; - if (player->postimgflags & POSTIMG_WATER) + if (thiscam->postimg & POSTIMG_WATER) { INT32 y; // Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic @@ -3269,22 +3271,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) tmpscr = srcscr; srcscr = tmp; } - - /*if (player->postimgflags & POSTIMG_MOTION) // Motion Blur! - { - INT32 x, y; - - // TODO: Add a postimg_param so that we can pick the translucency level... - UINT8 *transme = transtables + ((param-1)<postimgflags & POSTIMG_HEAT) // Heat wave + else if (thiscam->postimg & POSTIMG_HEAT) // Heat wave { INT32 y; @@ -3331,7 +3318,21 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) srcscr = tmp; } - if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) // Flip the screen upside-down + /*if (thiscam->postimg & POSTIMG_MOTION) // Motion Blur! + { + INT32 x, y; + + // TODO: Add a postimg_param so that we can pick the translucency level... + UINT8 *transme = transtables + ((param-1)<postimg & POSTIMG_FLIP) && !(thiscam->postimg & POSTIMG_MIRROR)) // Flip the screen upside-down { INT32 y, y2; @@ -3342,7 +3343,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) tmpscr = srcscr; srcscr = tmp; } - else if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) // Flip the screen on the x axis + else if ((thiscam->postimg & POSTIMG_MIRROR) && !(thiscam->postimg & POSTIMG_FLIP)) // Flip the screen on the x axis { INT32 y, x, x2; @@ -3354,7 +3355,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) tmpscr = srcscr; srcscr = tmp; } - else if ((player->postimgflags & POSTIMG_MIRROR) && (player->postimgflags & POSTIMG_FLIP)) // Flip the screen upside-down and on the x axis + else if ((thiscam->postimg & POSTIMG_MIRROR) && (thiscam->postimg & POSTIMG_FLIP)) // Flip the screen upside-down and on the x axis { INT32 y, x; diff --git a/src/v_video.h b/src/v_video.h index dfab7dfde..2513825c2 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -256,7 +256,7 @@ char V_GetSkincolorChar(INT32 color); typedef struct player_s player_t; -void V_DoPostProcessor(INT32 view, player_t *player, INT32 param); +void V_DoPostProcessor(INT32 view, INT32 param); void V_DrawPatchFill(patch_t *pat);