diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index ddaf5cbde..48c281b14 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -108,8 +108,8 @@ void footprints(int snum); int makepainsounds(int snum, int type); void playerCrouch(int snum); void playerJump(int snum, int fz, int cz); -void playerLookLeft(int snum); -void playerLookRight(int snum); +void applylook(int snum, double factor); +void checklook(int snum, int sb_snum); void playerCenterView(int snum); void playerLookUp(int snum, ESyncBits sb_snum); void playerLookDown(int snum, ESyncBits sb_snum); @@ -232,5 +232,6 @@ void PlayerColorChanged(void); void nonsharedkeys(void); void apply_seasick(player_struct* p, double scalefactor); void calcviewpitch(player_struct* p, int psectlotag, double factor); +void sethorizon(int snum, int sb_snum, double factor, bool frominput = false); END_DUKE_NS diff --git a/source/games/duke/src/input.cpp b/source/games/duke/src/input.cpp index 8af3f0eec..971a09b61 100644 --- a/source/games/duke/src/input.cpp +++ b/source/games/duke/src/input.cpp @@ -669,8 +669,7 @@ void hud_input(int snum) OnEvent(EVENT_TURNAROUND, -1, snum, -1); if (GetGameVarID(g_iReturnVarID, -1, snum) == 0) { - p->one_eighty_count = -1024; - p->one_eighty_target = (p->q16ang + F16(1024)) & 0x7FFFFFF; + p->one_eighty_count = -F16(1024); } } } diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index eee8c125c..63287b0a0 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -387,7 +387,6 @@ void dokneeattack(int snum, int pi, const std::initializer_list & respawnli else { g_player[snum].horizSkew = -48; - g_player[snum].horizRecenter = true; } p->return_to_center = 9; @@ -744,40 +743,150 @@ void playerJump(int snum, int fz, int cz) } } -void playerLookLeft(int snum) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void apply_seasick(player_struct* p, double factor) { - auto p = &ps[snum]; - SetGameVarID(g_iReturnVarID, 0, p->i, snum); - OnEvent(EVENT_LOOKLEFT, p->i, snum, -1); - if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0) + if (isRRRA() && p->SeaSick) { - if (synchronized_input) + if (p->SeaSick < 250) { - p->addlookang(-152); - p->addrotscrnang(24); + if (p->SeaSick >= 180) + p->addrotscrnang(24 * factor); + else if (p->SeaSick >= 130) + p->addrotscrnang(-24 * factor); + else if (p->SeaSick >= 70) + p->addrotscrnang(24 * factor); + else if (p->SeaSick >= 20) + p->addrotscrnang(-24 * factor); } - else - g_player[snum].lookLeft = true; + if (p->SeaSick < 250) + p->addlookang(((krand() & 255) - 128) * factor); } } -void playerLookRight(int snum) +//--------------------------------------------------------------------------- +// +// split off because it can be called from multiple places. +// +//--------------------------------------------------------------------------- + +void applylook(int snum, double factor) { auto p = &ps[snum]; - SetGameVarID(g_iReturnVarID, 0, p->i, snum); - OnEvent(EVENT_LOOKRIGHT, p->i, snum, -1); - if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0) + + p->addrotscrnang(factor * -0.5 * fix16_to_dbl(p->q16rotscrnang)); + if (abs(p->q16rotscrnang) < FRACUNIT) p->q16rotscrnang = 0; + + p->addlookang(factor * -0.25 * fix16_to_dbl(p->q16look_ang)); + if (abs(p->q16look_ang) < FRACUNIT) p->q16look_ang = 0; + + if (g_player[snum].lookLeft) { - if (synchronized_input) - { - p->addlookang(152); - p->addrotscrnang(24); - } - else - g_player[snum].lookRight = true; + p->addlookang(factor * -152); + p->addrotscrnang(factor * 24); } + + if (g_player[snum].lookRight) + { + p->addlookang(factor * 152); + p->addrotscrnang(factor * 24); + } + + if (p->one_eighty_count < 0 && p->on_crane == 0) + { + fixed_t add = fix16_from_dbl(factor * 128); + p->one_eighty_count += add; + if (p->one_eighty_count > 0) + { + // Don't overshoot our target. With variable factor this is possible. + add -= p->one_eighty_count; + p->one_eighty_count = 0; + } + p->q16ang += add; + } + apply_seasick(p, factor); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void checklook(int snum, int sb_snum) +{ + auto p = &ps[snum]; + + g_player[snum].lookLeft = false; + if ((sb_snum & SKB_LOOK_LEFT) && !p->OnMotorcycle) + { + SetGameVarID(g_iReturnVarID, 0, p->i, snum); + OnEvent(EVENT_LOOKLEFT, p->i, snum, -1); + if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0) + { + g_player[snum].lookLeft = true; + } + } + + if ((sb_snum & SKB_LOOK_RIGHT) && !p->OnMotorcycle) + { + SetGameVarID(g_iReturnVarID, 0, p->i, snum); + OnEvent(EVENT_LOOKRIGHT, p->i, snum, -1); + if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0) + { + g_player[snum].lookRight = true; + } + } + p->oq16ang = p->q16ang; + + if (synchronized_input) + applylook(snum, 1); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void sethorizon(int snum, int sb_snum, double factor, bool frominput) +{ + auto p = &ps[snum]; + + // Calculate adjustment as true pitch (Fixed point nath really sucks...) + if (g_player[snum].horizAngleAdjust) + { + double horizAngle = atan2(p->q16horiz - F16(100), F16(128)) * (512. / pi::pi()) +factor * g_player[snum].horizAngleAdjust; + p->q16horiz = F16(100) + int(F16(128) * tan(horizAngle * (pi::pi() / 512.))); + } + else if (p->return_to_center > 0 && (sb_snum & (SKB_LOOK_UP | SKB_LOOK_DOWN)) == 0) // only snap back if no relevant button is pressed. + { + p->return_to_center--; + p->q16horiz += factor * (frominput? 2.016 : 1.) * (F16(33) - (p->q16horiz / 3)); // in P_GetInput this used different factors than in the original code. Hm... + } + + p->q16horiz += int(factor * g_player[snum].horizSkew); + + if (p->aim_mode == 0) + { + // threshold was 5 + if (p->q16horiz > F16(99) && p->q16horiz < F16(101)) p->sethoriz(100); + if (p->q16horizoff > F16(-1) && p->q16horizoff < F16(1)) p->sethorizoff(0); + } + p->q16horiz = clamp(p->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX)); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void playerCenterView(int snum) { auto p = &ps[snum]; @@ -786,17 +895,12 @@ void playerCenterView(int snum) if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0) { p->return_to_center = 9; - if (!synchronized_input) - g_player[snum].horizRecenter = true; } } void horizAngleAdjust(int snum, int delta) { - if (synchronized_input) - ps[snum].addhoriz(delta); - else - g_player[snum].horizAngleAdjust = delta; + g_player[snum].horizAngleAdjust = delta; } void playerLookUp(int snum, ESyncBits sb_snum) diff --git a/source/games/duke/src/player.h b/source/games/duke/src/player.h index 30e7e70b9..c7edceced 100644 --- a/source/games/duke/src/player.h +++ b/source/games/duke/src/player.h @@ -52,7 +52,6 @@ typedef struct fix16_t horizSkew; bool lookLeft; bool lookRight; - bool horizRecenter; } playerdata_t; diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 3a0d24859..dd6e72e36 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -1562,9 +1562,6 @@ static void operateJetpack(int snum, ESyncBits sb_snum, int psectlotag, int fz, p->pycount &= 2047; p->pyoff = sintable[p->pycount] >> 7; - if (!synchronized_input) - g_player[snum].horizSkew = 0; - if (p->jetpack_on < 11) { p->jetpack_on++; @@ -2736,21 +2733,7 @@ void processinput_d(int snum) doubvel = TICSPERFRAME; - if (synchronized_input) - { - p->q16rotscrnang -= (p->q16rotscrnang >> 1); if (p->q16rotscrnang < FRACUNIT) p->q16rotscrnang = 0; - p->q16look_ang -= p->q16look_ang >> 2; if (p->q16look_ang < FRACUNIT) p->q16look_ang = 0; - } - - if (sb_snum & SKB_LOOK_LEFT) - { - playerLookLeft(snum); - } - - if (sb_snum & SKB_LOOK_RIGHT) - { - playerLookRight(snum); - } + checklook(snum,sb_snum); if (p->on_crane >= 0) goto HORIZONLY; @@ -2785,16 +2768,6 @@ void processinput_d(int snum) p->oposz = p->posz; p->opyoff = p->pyoff; - if (synchronized_input) - { - p->oq16ang = p->q16ang; - - if (p->one_eighty_count < 0) - { - p->one_eighty_count += 128; - p->addang(128); - } - } // Shrinking code @@ -2837,7 +2810,7 @@ void processinput_d(int snum) tempang = sb_avel << 1; // this is fixed point! - if (psectlotag == 2) p->angvel = (tempang - (tempang >> 3)) * sgn(doubvel); + if (psectlotag == ST_2_UNDERWATER) p->angvel = (tempang - (tempang >> 3)) * sgn(doubvel); else p->angvel = tempang * sgn(doubvel); p->addang(p->angvel); @@ -3078,35 +3051,17 @@ HORIZONLY: { // aim_down playerAimDown(snum, sb_snum); } - if (synchronized_input) - { - if (p->return_to_center > 0) - if ((sb_snum & (SKB_LOOK_UP | SKB_LOOK_DOWN)) == 0) - { - p->return_to_center--; - p->q16horiz += 33 * FRACUNIT - (p->q16horiz / 3); - } - } + if (p->hard_landing > 0) { - if (!synchronized_input) - g_player[snum].horizSkew = (-(p->hard_landing << 4)) * FRACUNIT; - else - p->addhoriz(-(p->hard_landing << 4)); + g_player[snum].horizSkew = (-(p->hard_landing << 4)) * FRACUNIT; p->hard_landing--; } if (synchronized_input) { - if (p->aim_mode) - p->q16horiz += (sync[snum].q16horz >> 1); - else - { - if (p->q16horiz > F16(95) && p->q16horiz < F16(105)) p->sethoriz(100); - if (p->q16horizoff > F16(-5) && p->q16horizoff < F16(5)) p->sethorizoff(0); - } - - p->q16horiz = clamp(p->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX)); + p->q16horiz += (sync[snum].q16horz >> 1); + sethorizon(snum, sb_snum, 1); } //Shooting code/changes diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index c77d24f7f..f92cacc90 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -35,32 +35,6 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms BEGIN_DUKE_NS -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void apply_seasick(player_struct* p, double scalefactor) -{ - if (isRRRA() && p->SeaSick) - { - if (p->SeaSick < 250) - { - if (p->SeaSick >= 180) - p->addrotscrnang(24*scalefactor); - else if (p->SeaSick >= 130) - p->addrotscrnang(-24*scalefactor); - else if (p->SeaSick >= 70) - p->addrotscrnang(24*scalefactor); - else if (p->SeaSick >= 20) - p->addrotscrnang(-24*scalefactor); - } - if (p->SeaSick < 250) - p->addlookang(((krand() & 255) - 128) * scalefactor); - } -} - //--------------------------------------------------------------------------- // // @@ -3651,26 +3625,7 @@ void processinput_r(int snum) doubvel = TICSPERFRAME; - if (synchronized_input) - { - p->q16rotscrnang -= (p->q16rotscrnang >> 1); if (p->q16rotscrnang < FRACUNIT) p->q16rotscrnang = 0; - p->q16look_ang -= p->q16look_ang >> 2; if (p->q16look_ang < FRACUNIT) p->q16look_ang = 0; - } - - if ((sb_snum & SKB_LOOK_LEFT) && !p->OnMotorcycle) - { - playerLookLeft(snum); - } - - if ((sb_snum & SKB_LOOK_RIGHT) && !p->OnMotorcycle) - { - playerLookRight(snum); - } - - if (synchronized_input) - { - apply_seasick(p, 1); - } + checklook(snum, sb_snum); if (p->on_crane >= 0) goto HORIZONLY; @@ -3705,16 +3660,6 @@ void processinput_r(int snum) p->oposz = p->posz; p->opyoff = p->pyoff; - if (synchronized_input) - { - p->oq16ang = p->q16ang; - - if (p->one_eighty_count < 0) - { - p->one_eighty_count += 128; - p->addang(128); - } - } // Shrinking code @@ -4133,35 +4078,16 @@ HORIZONLY: p->recoil -= d; p->addhoriz(-d); } - if (synchronized_input) - { - if (p->return_to_center > 0) - if ((sb_snum & (SKB_LOOK_UP | SKB_LOOK_DOWN)) == 0) - { - p->return_to_center--; - p->q16horiz += 33 * FRACUNIT - (p->q16horiz / 3); - } - } if (p->hard_landing > 0) { - if (!synchronized_input) - g_player[snum].horizSkew = (-(p->hard_landing << 4)) * FRACUNIT; - else - p->addhoriz(-(p->hard_landing << 4)); + g_player[snum].horizSkew = (-(p->hard_landing << 4)) * FRACUNIT; p->hard_landing--; } if (synchronized_input) { - if (p->aim_mode) - p->q16horiz += (sync[snum].q16horz >> 1); - else - { - if (p->q16horiz > F16(95) && p->q16horiz < F16(105)) p->sethoriz(100); - if (p->q16horizoff > F16(-5) && p->q16horizoff < F16(5)) p->sethorizoff(0); - } - - p->q16horiz = clamp(p->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX)); + p->q16horiz += (sync[snum].q16horz >> 1); + sethorizon(snum, sb_snum, 1); } //Shooting code/changes diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index 4ab6dfdc2..1e17e4eb7 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -92,7 +92,7 @@ struct player_struct // input handles angle and horizon as fixed16 numbers. We need to account for that as well. fixed_t q16ang, q16horiz, q16horizoff, q16rotscrnang, q16look_ang; fixed_t oq16ang, oq16horiz, oq16horizoff, oq16rotscrnang; // These are only needed with synchronous mouse input. - fixed_t one_eighty_target; + fixed_t one_eighty_count; // using a bit field for this to save a bit of space. FixedBitArray gotweapon; @@ -125,7 +125,7 @@ struct player_struct short kickback_pic, got_access, weapon_ang, firstaid_amount; short somethingonplayer, on_crane, i, one_parallax_sectnum; short over_shoulder_on, random_club_frame, fist_incs; - short one_eighty_count, cheat_phase; + short cheat_phase; short dummyplayersprite, extra_extra8, quick_kick; short heat_amount, actorsqu, timebeforeexit, customexitsound; diff --git a/source/games/duke/src/zz_player.cpp b/source/games/duke/src/zz_player.cpp index 1739f6cdd..77cb18435 100644 --- a/source/games/duke/src/zz_player.cpp +++ b/source/games/duke/src/zz_player.cpp @@ -65,6 +65,7 @@ enum inputlock_t static int P_CheckLockedMovement(int const playerNum) { + auto& thisPlayer = g_player[playerNum]; auto const pPlayer = &ps[playerNum]; if (pPlayer->on_crane >= 0) @@ -81,10 +82,13 @@ static int P_CheckLockedMovement(int const playerNum) && pPlayer->kickback_pic < PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay))) return IL_NOTHING; + if (pPlayer->return_to_center > 0) + return IL_NOHORIZ; + return 0; } -static double elapsedInputTicks; +static double elapsedInputTicks = -1; static double scaleAdjustmentToInterval(double x) { @@ -101,7 +105,6 @@ void P_GetInput(int const playerNum) bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - CONTROL_GetInput(&info); @@ -301,71 +304,21 @@ void P_GetInput(int const playerNum) { localInput.q16horz = fix16_clamp(fix16_sadd(localInput.q16horz, input.q16horz), F16(-MAXHORIZVEL), F16(MAXHORIZVEL)); if (!synchronized_input) - pPlayer->q16horiz = fix16_clamp(fix16_sadd(pPlayer->q16horiz, input.q16horz), F16(HORIZ_MIN), F16(HORIZ_MAX)); + pPlayer->q16horiz += input.q16horz; // will be clamped below in sethorizon. } } - if (synchronized_input) return; - - // don't adjust rotscrnang and look_ang if dead. - if (pSprite->extra > 0) + if (!synchronized_input) { - pPlayer->q16rotscrnang = fix16_ssub(pPlayer->q16rotscrnang, fix16_from_dbl(scaleAdjustmentToInterval(fix16_to_dbl(fix16_sdiv(pPlayer->q16rotscrnang, fix16_from_int(2)))))); - - if (pPlayer->q16rotscrnang && !fix16_sdiv(pPlayer->q16rotscrnang, fix16_from_dbl(scaleAdjustmentToInterval(2)))) - pPlayer->q16rotscrnang = fix16_ssub(pPlayer->q16rotscrnang, fix16_from_dbl(scaleAdjustmentToInterval(ksgn(fix16_to_int(pPlayer->q16rotscrnang))))); - - pPlayer->q16look_ang = fix16_ssub(pPlayer->q16look_ang, fix16_from_dbl(scaleAdjustmentToInterval(fix16_to_dbl(fix16_sdiv(pPlayer->q16look_ang, fix16_from_int(4)))))); - - if (pPlayer->q16look_ang && !fix16_sdiv(pPlayer->q16look_ang, fix16_from_dbl(scaleAdjustmentToInterval(4)))) - pPlayer->q16look_ang = fix16_ssub(pPlayer->q16look_ang, fix16_from_dbl(scaleAdjustmentToInterval(ksgn(fix16_to_int(pPlayer->q16look_ang))))); - - if (thisPlayer.lookLeft) + // don't adjust rotscrnang and look_ang if dead. + if (pSprite->extra > 0) { - pPlayer->q16look_ang = fix16_ssub(pPlayer->q16look_ang, fix16_from_dbl(scaleAdjustmentToInterval(152))); - pPlayer->q16rotscrnang = fix16_sadd(pPlayer->q16rotscrnang, fix16_from_dbl(scaleAdjustmentToInterval(24))); - } - if (thisPlayer.lookRight) - { - pPlayer->q16look_ang = fix16_sadd(pPlayer->q16look_ang, fix16_from_dbl(scaleAdjustmentToInterval(152))); - pPlayer->q16rotscrnang = fix16_ssub(pPlayer->q16rotscrnang, fix16_from_dbl(scaleAdjustmentToInterval(24))); + applylook(playerNum, scaleAdjust); } - if (pPlayer->one_eighty_count < 0) - { - pPlayer->one_eighty_count = -fix16_to_int(fix16_abs(GetDeltaQ16Angle(pPlayer->one_eighty_target, pPlayer->q16ang))); - pPlayer->q16ang = fix16_sadd(pPlayer->q16ang, fix16_max(fix16_one, fix16_from_dbl(scaleAdjustmentToInterval(-pPlayer->one_eighty_count / ONEEIGHTYSCALE)))) & 0x7FFFFFF; - } - - apply_seasick(pPlayer, scaleAdjust); + // Do these in the same order as the old code. + calcviewpitch(pPlayer, sectorLotag, scaleAdjust); + sethorizon(playerNum, localInput.bits, scaleAdjust, true); } - // A horiz diff of 128 equal 45 degrees, so we convert horiz to 1024 angle units - - if (thisPlayer.horizAngleAdjust) - { - float const horizAngle - = atan2f(pPlayer->q16horiz - F16(100), F16(128)) * (512.f / fPI) + scaleAdjustmentToInterval(thisPlayer.horizAngleAdjust); - pPlayer->q16horiz = F16(100) + Blrintf(F16(128) * tanf(horizAngle * (fPI / 512.f))); - } - else if (pPlayer->return_to_center > 0) - { - pPlayer->q16horiz = fix16_sadd(pPlayer->q16horiz, fix16_from_dbl(scaleAdjustmentToInterval(fix16_to_dbl(fix16_from_dbl(66.535) - fix16_sdiv(pPlayer->q16horiz, fix16_from_dbl(1.505)))))); - - if (pPlayer->q16horiz >= F16(99) && pPlayer->q16horiz <= F16(101)) - { - pPlayer->q16horiz = F16(100); - pPlayer->return_to_center = 0; - } - - if (pPlayer->q16horizoff >= F16(-1) && pPlayer->q16horizoff <= F16(1)) - pPlayer->q16horizoff = 0; - } - - calcviewpitch(pPlayer, sectorLotag, scaleAdjust); - - if (thisPlayer.horizSkew) - pPlayer->q16horiz = fix16_sadd(pPlayer->q16horiz, fix16_from_dbl(scaleAdjustmentToInterval(thisPlayer.horizSkew))); - - pPlayer->q16horiz = fix16_clamp(pPlayer->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX)); } @@ -572,13 +525,16 @@ void P_GetInputBoat(int playerNum) void GetInput() { - static uint64_t lastCheck; + static double lastCheck; auto const p = &ps[myconnectindex]; updatePauseStatus(); auto now = I_msTimeF(); - elapsedInputTicks = now - lastCheck; + // do not let this become too large - it would create overflows resulting in undefined behavior. The very first tic must not use the timer difference at all because the timer has not been set yet. + // This really needs to have the timer fixed to be robust, doing it ad-hoc here is not really safe. + if (elapsedInputTicks >= 0) elapsedInputTicks = min(now - lastCheck, 10.); + else elapsedInputTicks = 1; lastCheck = now; if (paused)