From c8372c233eba4b820058615a90cdb2e0acd12b27 Mon Sep 17 00:00:00 2001 From: nukeykt Date: Thu, 30 Jan 2020 22:05:34 +0900 Subject: [PATCH] Blood: Tie player input to the frame rate instead of the game tickrate Look up/down and spin180 are a bit broken right now. Big thanks to terminx for similar commit for eduke32. --- source/blood/src/blood.cpp | 27 ++---- source/blood/src/controls.cpp | 152 ++++++++++++++++++++++---------- source/blood/src/controls.h | 5 ++ source/blood/src/map2d.cpp | 10 +-- source/blood/src/map2d.h | 3 +- source/blood/src/network.cpp | 161 ++++++++++------------------------ source/blood/src/network.h | 1 - source/blood/src/player.cpp | 26 ++++++ source/blood/src/view.cpp | 52 ++++++++++- 9 files changed, 248 insertions(+), 189 deletions(-) diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index 9856056f1..862b386e3 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -495,6 +495,7 @@ void StartLevel(GAMEOPTIONS *gameOptions) { STAT_Update(0); EndLevel(); + gInput = {}; gStartNewGame = 0; ready2send = 0; if (gDemo.at0 && gGameStarted) @@ -807,12 +808,9 @@ void ProcessFrame(void) gPlayer[i].input.q16mlook = gFifoInput[gNetFifoTail&255][i].q16mlook; } gNetFifoTail++; - if (!(gFrame&((gSyncRate<<3)-1))) - { - CalcGameChecksum(); - memcpy(gCheckFifo[gCheckHead[myconnectindex]&255][myconnectindex], gChecksum, sizeof(gChecksum)); - gCheckHead[myconnectindex]++; - } + CalcGameChecksum(); + memcpy(gCheckFifo[gCheckHead[myconnectindex]&255][myconnectindex], gChecksum, sizeof(gChecksum)); + gCheckHead[myconnectindex]++; for (int i = connecthead; i >= 0; i = connectpoint2[i]) { if (gPlayer[i].input.keyFlags.quit) @@ -934,7 +932,8 @@ SWITCH switches[] = { { "robust", 8, 0 }, { "skill", 10, 1 }, { "ini", 13, 1 }, - { "f", 15, 1 }, + { "noaim", 14, 0 }, + //{ "f", 15, 1 }, { "control", 16, 1 }, { "vector", 17, 1 }, { "noresend", 22, 0 }, @@ -974,10 +973,7 @@ void ParseOptions(void) bNoDemo = 1; break; case 3: - if (gSyncRate == 1) - gPacketMode = PACKETMODE_2; - else - gPacketMode = PACKETMODE_1; + gPacketMode = PACKETMODE_2; break; case 30: if (OptArgc < 1) @@ -1025,13 +1021,6 @@ void ParseOptions(void) gSkill = 4; break; case 15: - if (OptArgc < 1) - ThrowError("Missing argument"); - gSyncRate = ClipRange(strtoul(OptArgv[0], NULL, 0), 1, 4); - if (gPacketMode == PACKETMODE_1) - gSyncRate = 1; - else if (gPacketMode == PACKETMODE_3) - gSyncRate = 1; break; } } @@ -1249,6 +1238,8 @@ RESTART: OSD_DispatchQueued(); + ctrlGetInput(); + switch (gInputMode) { case kInputMessage: diff --git a/source/blood/src/controls.cpp b/source/blood/src/controls.cpp index 235b7be7f..531a94852 100644 --- a/source/blood/src/controls.cpp +++ b/source/blood/src/controls.cpp @@ -54,7 +54,10 @@ void ctrlTerm(void) int32_t mouseyaxismode = -1; - +int32_t GetTime(void) +{ + return (int32_t)totalclock; +} void GameInterface::set_hud_layout(int layout) { @@ -68,19 +71,31 @@ void GameInterface::set_hud_scale(int scale) } +fix16_t gViewLook, gViewAngle; +float gViewAngleAdjust; +float gViewLookAdjust; +int gViewLookRecenter; + void ctrlGetInput(void) { ControlInfo info; - int forward = 0, strafe = 0; - fix16_t turn = 0; - memset(&gInput, 0, sizeof(gInput)); if (!gGameStarted || gInputMode != kInputGame) { + gInput = {}; CONTROL_GetInput(&info); return; } + GINPUT input = {}; + static double lastInputTicks; + auto const currentHiTicks = timerGetHiTicks(); + double const elapsedInputTicks = currentHiTicks - lastInputTicks; + + lastInputTicks = currentHiTicks; + + auto scaleAdjustmentToInterval = [=](double x) { return x * kTicsPerSec / (1000.0 / elapsedInputTicks); }; + D_ProcessEvents(); bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); @@ -180,15 +195,15 @@ void ctrlGetInput(void) gInput.keyFlags.action = 1; } - gInput.buttonFlags.lookUp = buttonMap.ButtonDown(gamefunc_Look_Up); - gInput.buttonFlags.lookDown = buttonMap.ButtonDown(gamefunc_Look_Down); + gInput.buttonFlags.lookUp |= buttonMap.ButtonDown(gamefunc_Look_Up); + gInput.buttonFlags.lookDown |= buttonMap.ButtonDown(gamefunc_Look_Down); - if (gInput.buttonFlags.lookUp || gInput.buttonFlags.lookDown) + if (buttonMap.ButtonDown(gamefunc_Look_Up) || buttonMap.ButtonDown(gamefunc_Look_Down)) gInput.keyFlags.lookCenter = 1; else { - gInput.buttonFlags.lookUp = buttonMap.ButtonDown(gamefunc_Aim_Up); - gInput.buttonFlags.lookDown = buttonMap.ButtonDown(gamefunc_Aim_Down); + gInput.buttonFlags.lookUp |= buttonMap.ButtonDown(gamefunc_Aim_Up); + gInput.buttonFlags.lookDown |= buttonMap.ButtonDown(gamefunc_Aim_Down); } if (buttonMap.ButtonDown(gamefunc_Center_View)) @@ -197,7 +212,7 @@ void ctrlGetInput(void) gInput.keyFlags.lookCenter = 1; } - gInput.keyFlags.spin180 = buttonMap.ButtonDown(gamefunc_TurnAround); + gInput.keyFlags.spin180 |= buttonMap.ButtonDown(gamefunc_TurnAround); if (buttonMap.ButtonDown(gamefunc_Inventory_Left)) { @@ -268,64 +283,88 @@ void ctrlGetInput(void) gInput.keyFlags.holsterWeapon = 1; } - char run = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); - char run2 = false; // What??? buttonMap.ButtonDown(gamefunc_Run); + int const run = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); + int const run2 = false; // What??? buttonMap.ButtonDown(gamefunc_Run); + int const keyMove = (1 + run) << 10; - gInput.syncFlags.run = run; + gInput.syncFlags.run |= run; - if (buttonMap.ButtonDown(gamefunc_Move_Forward)) - forward += (1+run)<<10; + if (gInput.forward < keyMove && gInput.forward > -keyMove) + { + if (buttonMap.ButtonDown(gamefunc_Move_Forward)) + gInput.forward += keyMove; + + if (buttonMap.ButtonDown(gamefunc_Move_Backward)) + gInput.forward -= keyMove; + } + + if (gInput.strafe < keyMove && gInput.strafe > -keyMove) + { + if (buttonMap.ButtonDown(gamefunc_Turn_Left)) + input.strafe += keyMove; + if (buttonMap.ButtonDown(gamefunc_Turn_Right)) + input.strafe -= keyMove; + } - if (buttonMap.ButtonDown(gamefunc_Move_Backward)) - forward -= (1+run)<<10; char turnLeft = 0, turnRight = 0; if (buttonMap.ButtonDown(gamefunc_Strafe)) { - if (buttonMap.ButtonDown(gamefunc_Turn_Left)) - strafe += (1 + run) << 10; - if (buttonMap.ButtonDown(gamefunc_Turn_Right)) - strafe -= (1 + run) << 10; + if (gInput.strafe < keyMove && gInput.strafe > -keyMove) + { + if (buttonMap.ButtonDown(gamefunc_Turn_Left)) + input.strafe += keyMove; + if (buttonMap.ButtonDown(gamefunc_Turn_Right)) + input.strafe -= keyMove; + } } else { - if (buttonMap.ButtonDown(gamefunc_Strafe_Left)) - strafe += (1 + run) << 10; - if (buttonMap.ButtonDown(gamefunc_Strafe_Right)) - strafe -= (1 + run) << 10; if (buttonMap.ButtonDown(gamefunc_Turn_Left)) turnLeft = 1; if (buttonMap.ButtonDown(gamefunc_Turn_Right)) turnRight = 1; } + static int32_t turnHeldTime; + static int32_t lastInputClock; // MED + int32_t const elapsedTics = (int32_t)totalclock - lastInputClock; + + lastInputClock = (int32_t) totalclock; + if (turnLeft || turnRight) - iTurnCount += 4; + turnHeldTime += elapsedTics; else - iTurnCount = 0; + turnHeldTime = 0; if (turnLeft) - turn -= fix16_from_int(ClipHigh(12 * iTurnCount, gTurnSpeed))>>2; + input.q16turn = fix16_ssub(input.q16turn, fix16_from_float(scaleAdjustmentToInterval(ClipHigh(12 * turnHeldTime, gTurnSpeed)>>2))); if (turnRight) - turn += fix16_from_int(ClipHigh(12 * iTurnCount, gTurnSpeed))>>2; + input.q16turn = fix16_sadd(input.q16turn, fix16_from_float(scaleAdjustmentToInterval(ClipHigh(12 * turnHeldTime, gTurnSpeed)>>2))); - if ((run2 || run) && iTurnCount > 24) - turn <<= 1; + if ((run2 || run) && turnHeldTime > 24) + input.q16turn <<= 1; if (buttonMap.ButtonDown(gamefunc_Strafe)) - strafe = ClipRange(strafe - info.mousex, -2048, 2048); + input.strafe -= info.mousex; else - turn = fix16_clamp(turn + fix16_div(fix16_from_int(info.mousex), F16(32)), F16(-1024)>>2, F16(1024)>>2); + input.q16turn = fix16_sadd(input.q16turn, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - strafe = ClipRange(strafe-(info.dx<<5), -2048, 2048); + input.strafe -= -(info.dx<<5); +#if 0 + if (info.dz < 0) + gInput.mlook = ClipRange((info.dz+127)>>7, -127, 127); + else + gInput.mlook = ClipRange(info.dz>>7, -127, 127); +#endif if (mouseaim) - gInput.q16mlook = fix16_clamp(fix16_div(fix16_from_int(info.mousey), F16(128)), F16(-127)>>2, F16(127)>>2); + input.q16mlook = fix16_sadd(input.q16mlook, fix16_sdiv(fix16_from_int(info.mousey), F16(128))); else - forward = ClipRange(forward - info.mousey, -2048, 2048); + input.forward -= info.mousey; if (!in_mouseflip) - gInput.q16mlook = -gInput.q16mlook; + input.q16mlook = -input.q16mlook; if (inputState.GetKeyStatus(sc_Pause)) // 0xc5 in disassembly { @@ -335,16 +374,37 @@ void ctrlGetInput(void) if (!gViewMap.bFollowMode && gViewMode == 4) { - gViewMap.turn = fix16_to_int(turn<<2); - gViewMap.forward = forward>>8; - gViewMap.strafe = strafe>>8; - turn = 0; - forward = 0; - strafe = 0; + gViewMap.turn += input.q16turn<<2; + gViewMap.forward += input.forward; + gViewMap.strafe += input.strafe; + input.q16turn = 0; + input.forward = 0; + input.strafe = 0; + } + gInput.forward = clamp(gInput.forward + input.forward, -2048, 2048); + gInput.strafe = clamp(gInput.strafe + input.strafe, -2048, 2048); + gInput.q16turn = fix16_sadd(gInput.q16turn, input.q16turn); + gInput.q16mlook = fix16_clamp(fix16_sadd(gInput.q16mlook, input.q16mlook), F16(-127)>>2, F16(127)>>2); + if (gMe && gMe->pXSprite->health != 0) + { + CONSTEXPR int upAngle = 289; + CONSTEXPR int downAngle = -347; + CONSTEXPR double lookStepUp = 4.0*upAngle/60.0; + CONSTEXPR double lookStepDown = -4.0*downAngle/60.0; + gViewAngle = (gViewAngle + input.q16turn + fix16_from_float(scaleAdjustmentToInterval(gViewAngleAdjust))) & 0x7ffffff; + if (gViewLookRecenter) + { + if (gViewLook < 0) + gViewLook = fix16_min(gViewLook+fix16_from_float(scaleAdjustmentToInterval(lookStepDown)), F16(0)); + if (gViewLook > 0) + gViewLook = fix16_max(gViewLook-fix16_from_float(scaleAdjustmentToInterval(lookStepUp)), F16(0)); + } + else + { + gViewLook = fix16_clamp(gViewLook+fix16_from_float(scaleAdjustmentToInterval(gViewLookAdjust)), F16(downAngle), F16(upAngle)); + } + gViewLook = fix16_clamp(gViewLook+(input.q16mlook << 3), F16(downAngle), F16(upAngle)); } - gInput.forward = forward; - gInput.q16turn = turn; - gInput.strafe = strafe; } #if 0 diff --git a/source/blood/src/controls.h b/source/blood/src/controls.h index e7a10b125..47d32d23d 100644 --- a/source/blood/src/controls.h +++ b/source/blood/src/controls.h @@ -106,6 +106,11 @@ struct GINPUT extern GINPUT gInput; extern bool bSilentAim; +extern fix16_t gViewLook, gViewAngle; +extern float gViewAngleAdjust; +extern float gViewLookAdjust; +extern int gViewLookRecenter; + void ctrlInit(); void ctrlGetInput(); diff --git a/source/blood/src/map2d.cpp b/source/blood/src/map2d.cpp index 7f1162178..4516c2dfb 100644 --- a/source/blood/src/map2d.cpp +++ b/source/blood/src/map2d.cpp @@ -231,11 +231,11 @@ void CViewMap::sub_25DB0(spritetype *pSprite) } else { - angle += turn>>3; - x += mulscale24(forward, Cos(angle)); - y += mulscale24(forward, Sin(angle)); - x -= mulscale24(strafe, Cos(angle+512)); - y -= mulscale24(strafe, Sin(angle+512)); + angle += fix16_to_int(turn)>>3; + x += mulscale24(forward>>8, Cos(angle)); + y += mulscale24(forward>>8, Sin(angle)); + x -= mulscale24(strafe>>8, Cos(angle+512)); + y -= mulscale24(strafe>>8, Sin(angle+512)); forward = 0; strafe = 0; turn = 0; diff --git a/source/blood/src/map2d.h b/source/blood/src/map2d.h index ce0e64f9d..29812b09a 100644 --- a/source/blood/src/map2d.h +++ b/source/blood/src/map2d.h @@ -32,7 +32,8 @@ public: int x, y, nZoom; short angle; char bFollowMode; - int forward, turn, strafe; + int forward, strafe; + fix16_t turn; CViewMap(); void sub_25C38(int, int, int, short, char); void sub_25C74(void); diff --git a/source/blood/src/network.cpp b/source/blood/src/network.cpp index 76dab0cd7..42543620e 100644 --- a/source/blood/src/network.cpp +++ b/source/blood/src/network.cpp @@ -64,7 +64,6 @@ int gCheckTail = 0; int gInitialNetPlayers = 0; int gBufferJitter = 1; int gPlayerReady[8]; -int gSyncRate = 1; bool bNoResend = true; bool gRobust = false; bool bOutOfSync = false; @@ -77,21 +76,6 @@ int gNetPort = kNetDefaultPort; const short word_1328AC = 0x214; -struct struct28E3B0 -{ - int at0; - int at4; - int at8; - int atc; - int at10; - int at14; - int at18; - char at1c; - int at1d; -}; - -struct28E3B0 byte_28E3B0; - PKT_STARTGAME gPacketStartGame; #ifndef NETCODE_DISABLE @@ -255,7 +239,6 @@ void sub_79760(void) memset(gCheckHead, 0, sizeof(gCheckHead)); gSendCheckTail = 0; gCheckTail = 0; - memset(&byte_28E3B0, 0, sizeof(byte_28E3B0)); bOutOfSync = 0; gBufferJitter = 1; } @@ -485,16 +468,6 @@ void netGetPackets(void) if (pInput->syncFlags.mlookChange) pInput->q16mlook = GetPacketDWord(pPacket); gNetFifoHead[nPlayer]++; - for (int i = gSyncRate; i > 1; i--) - { - GINPUT *pInput2 = &gFifoInput[gNetFifoHead[nPlayer]&255][nPlayer]; - memcpy(pInput2, pInput, sizeof(GINPUT)); - pInput2->keyFlags.word = 0; - pInput2->useFlags.byte = 0; - pInput2->newWeapon = 0; - pInput2->syncFlags.weaponChange = 0; - gNetFifoHead[nPlayer]++; - } while (pPacket < packet+nSize) { int checkSum[4]; @@ -687,34 +660,6 @@ void netSendEmptyPackets(void) } } -void sub_7AD90(GINPUT *pInput) -{ - byte_28E3B0.at0 |= pInput->syncFlags.byte; - byte_28E3B0.at4 += pInput->forward; - byte_28E3B0.at8 += pInput->q16turn; - byte_28E3B0.atc += pInput->strafe; - byte_28E3B0.at10 |= pInput->buttonFlags.byte; - byte_28E3B0.at14 |= pInput->keyFlags.word; - byte_28E3B0.at18 |= pInput->useFlags.byte; - if (pInput->newWeapon) - byte_28E3B0.at1c = pInput->newWeapon; - byte_28E3B0.at1d = pInput->q16mlook; -} - -void sub_7AE2C(GINPUT *pInput) -{ - pInput->syncFlags.byte = byte_28E3B0.at0; - pInput->forward = byte_28E3B0.at4; - pInput->q16turn = byte_28E3B0.at8; - pInput->strafe = byte_28E3B0.atc; - pInput->buttonFlags.byte = byte_28E3B0.at10; - pInput->keyFlags.word = byte_28E3B0.at14; - pInput->useFlags.byte = byte_28E3B0.at18; - pInput->newWeapon = byte_28E3B0.at1c; - pInput->q16mlook = byte_28E3B0.at1d; - memset(&byte_28E3B0, 0, sizeof(byte_28E3B0)); -} - void netMasterUpdate(void) { if (myconnectindex != connecthead) @@ -789,23 +734,9 @@ void netGetInput(void) for (int p = connecthead; p >= 0; p = connectpoint2[p]) if (gNetFifoHead[myconnectindex]-200 > gNetFifoHead[p]) return; - ctrlGetInput(); - sub_7AD90(&gInput); - if (gNetFifoHead[myconnectindex]&(gSyncRate-1)) - { - GINPUT *pInput1 = &gFifoInput[gNetFifoHead[myconnectindex]&255][myconnectindex]; - GINPUT *pInput2 = &gFifoInput[(gNetFifoHead[myconnectindex]-1)&255][myconnectindex]; - memcpy(pInput1, pInput2, sizeof(GINPUT)); - pInput1->keyFlags.word = 0; - pInput1->useFlags.byte = 0; - pInput1->newWeapon = 0; - pInput1->syncFlags.weaponChange = 0; - gNetFifoHead[myconnectindex]++; - return; - } - GINPUT *pInput = &gFifoInput[gNetFifoHead[myconnectindex]&255][myconnectindex]; - sub_7AE2C(pInput); - memcpy(&gInput, pInput, sizeof(GINPUT)); + GINPUT &input = gFifoInput[gNetFifoHead[myconnectindex]&255][myconnectindex]; + input = gInput; + gInput = {}; gNetFifoHead[myconnectindex]++; if (gGameOptions.nGameType == 0 || numplayers == 1) { @@ -871,30 +802,30 @@ void netGetInput(void) for (int p = connecthead; p >= 0; p = connectpoint2[p]) myMinLag[p] = 0x7fffffff; } - if (gInput.buttonFlags.byte) - gInput.syncFlags.buttonChange = 1; - if (gInput.keyFlags.word) - gInput.syncFlags.keyChange = 1; - if (gInput.useFlags.byte) - gInput.syncFlags.useChange = 1; - if (gInput.newWeapon) - gInput.syncFlags.weaponChange = 1; - if (gInput.q16mlook) - gInput.syncFlags.mlookChange = 1; - PutPacketByte(pPacket, gInput.syncFlags.byte); - PutPacketWord(pPacket, gInput.forward); - PutPacketDWord(pPacket, gInput.q16turn); - PutPacketWord(pPacket, gInput.strafe); + if (input.buttonFlags.byte) + input.syncFlags.buttonChange = 1; + if (input.keyFlags.word) + input.syncFlags.keyChange = 1; + if (input.useFlags.byte) + input.syncFlags.useChange = 1; + if (input.newWeapon) + input.syncFlags.weaponChange = 1; + if (input.q16mlook) + input.syncFlags.mlookChange = 1; + PutPacketByte(pPacket, input.syncFlags.byte); + PutPacketWord(pPacket, input.forward); + PutPacketDWord(pPacket, input.q16turn); + PutPacketWord(pPacket, input.strafe); if (gInput.syncFlags.buttonChange) - PutPacketByte(pPacket, gInput.buttonFlags.byte); + PutPacketByte(pPacket, input.buttonFlags.byte); if (gInput.syncFlags.keyChange) - PutPacketWord(pPacket, gInput.keyFlags.word); + PutPacketWord(pPacket, input.keyFlags.word); if (gInput.syncFlags.useChange) - PutPacketByte(pPacket, gInput.useFlags.byte); + PutPacketByte(pPacket, input.useFlags.byte); if (gInput.syncFlags.weaponChange) - PutPacketByte(pPacket, gInput.newWeapon); + PutPacketByte(pPacket, input.newWeapon); if (gInput.syncFlags.mlookChange) - PutPacketDWord(pPacket, gInput.q16mlook); + PutPacketDWord(pPacket, input.q16mlook); while (gSendCheckTail != gCheckHead[myconnectindex]) { unsigned int *checkSum = gCheckFifo[gSendCheckTail&255][myconnectindex]; @@ -908,30 +839,30 @@ void netGetInput(void) { char *pPacket = packet; PutPacketByte(pPacket, 1); - if (gInput.buttonFlags.byte) - gInput.syncFlags.buttonChange = 1; - if (gInput.keyFlags.word) - gInput.syncFlags.keyChange = 1; - if (gInput.useFlags.byte) - gInput.syncFlags.useChange = 1; - if (gInput.newWeapon) - gInput.syncFlags.weaponChange = 1; - if (gInput.q16mlook) - gInput.syncFlags.mlookChange = 1; - PutPacketByte(pPacket, gInput.syncFlags.byte); - PutPacketWord(pPacket, gInput.forward); - PutPacketDWord(pPacket, gInput.q16turn); - PutPacketWord(pPacket, gInput.strafe); - if (gInput.syncFlags.buttonChange) - PutPacketByte(pPacket, gInput.buttonFlags.byte); - if (gInput.syncFlags.keyChange) - PutPacketWord(pPacket, gInput.keyFlags.word); - if (gInput.syncFlags.useChange) - PutPacketByte(pPacket, gInput.useFlags.byte); - if (gInput.syncFlags.weaponChange) - PutPacketByte(pPacket, gInput.newWeapon); - if (gInput.syncFlags.mlookChange) - PutPacketDWord(pPacket, gInput.q16mlook); + if (input.buttonFlags.byte) + input.syncFlags.buttonChange = 1; + if (input.keyFlags.word) + input.syncFlags.keyChange = 1; + if (input.useFlags.byte) + input.syncFlags.useChange = 1; + if (input.newWeapon) + input.syncFlags.weaponChange = 1; + if (input.q16mlook) + input.syncFlags.mlookChange = 1; + PutPacketByte(pPacket, input.syncFlags.byte); + PutPacketWord(pPacket, input.forward); + PutPacketDWord(pPacket, input.q16turn); + PutPacketWord(pPacket, input.strafe); + if (input.syncFlags.buttonChange) + PutPacketByte(pPacket, input.buttonFlags.byte); + if (input.syncFlags.keyChange) + PutPacketWord(pPacket, input.keyFlags.word); + if (input.syncFlags.useChange) + PutPacketByte(pPacket, input.useFlags.byte); + if (input.syncFlags.weaponChange) + PutPacketByte(pPacket, input.newWeapon); + if (input.syncFlags.mlookChange) + PutPacketDWord(pPacket, input.q16mlook); if (((gNetFifoHead[myconnectindex]-1)&15) == 0) { int t = myMinLag[connecthead]-otherMinLag; diff --git a/source/blood/src/network.h b/source/blood/src/network.h index 96573ea99..b86284e65 100644 --- a/source/blood/src/network.h +++ b/source/blood/src/network.h @@ -62,7 +62,6 @@ extern int gCheckTail; extern int gInitialNetPlayers; extern int gBufferJitter; extern int gPlayerReady[8]; -extern int gSyncRate; extern bool bNoResend; extern bool gRobust; extern bool bOutOfSync; diff --git a/source/blood/src/player.cpp b/source/blood/src/player.cpp index 65eeb5642..21630de5c 100644 --- a/source/blood/src/player.cpp +++ b/source/blood/src/player.cpp @@ -783,6 +783,8 @@ void playerStart(int nPlayer, int bNewLevel) if (pPlayer == gMe) { viewInitializePrediction(); + gViewLook = pPlayer->q16look; + gViewAngle = pPlayer->q16ang; gViewMap.x = pPlayer->pSprite->x; gViewMap.y = pPlayer->pSprite->y; gViewMap.angle = pPlayer->pSprite->ang; @@ -1305,6 +1307,14 @@ void ProcessInput(PLAYER *pPlayer) int nSprite = pPlayer->nSprite; POSTURE *pPosture = &pPlayer->pPosture[pPlayer->lifeMode][pPlayer->posture]; GINPUT *pInput = &pPlayer->input; + + if (pPlayer == gMe && numplayers == 1) + { + gViewAngleAdjust = 0.f; + gViewLookRecenter = false; + gViewLookAdjust = 0.f; + } + pPlayer->isRunning = pInput->syncFlags.run; if (pInput->buttonFlags.byte || pInput->forward || pInput->strafe || pInput->q16turn) pPlayer->restTime = 0; @@ -1424,7 +1434,11 @@ void ProcessInput(PLAYER *pPlayer) speed = 128; pPlayer->spin = min(pPlayer->spin+speed, 0); pPlayer->q16ang += fix16_from_int(speed); + if (pPlayer == gMe && numplayers == 1) + gViewAngleAdjust += float(speed); } + if (pPlayer == gMe && numplayers == 1) + gViewAngleAdjust += float(pSprite->ang - pPlayer->angold); pPlayer->q16ang = (pPlayer->q16ang+fix16_from_int(pSprite->ang-pPlayer->angold))&0x7ffffff; pPlayer->angold = pSprite->ang = fix16_to_int(pPlayer->q16ang); if (!pInput->buttonFlags.jump) @@ -1580,6 +1594,18 @@ void ProcessInput(PLAYER *pPlayer) if (pInput->buttonFlags.lookDown) pPlayer->q16look = fix16_max(pPlayer->q16look-F16(lookStepDown), F16(downAngle)); } + if (pPlayer == gMe && numplayers == 1) + { + if (pInput->buttonFlags.lookUp) + { + gViewLookAdjust += float(lookStepUp); + } + if (pInput->buttonFlags.lookDown) + { + gViewLookAdjust -= float(lookStepDown); + } + gViewLookRecenter = pInput->keyFlags.lookCenter && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown; + } pPlayer->q16look = fix16_clamp(pPlayer->q16look+(pInput->q16mlook<<3), F16(downAngle), F16(upAngle)); pPlayer->q16horiz = fix16_from_float(100.f*tanf(fix16_to_float(pPlayer->q16look)*fPI/1024.f)); } diff --git a/source/blood/src/view.cpp b/source/blood/src/view.cpp index 4584f543e..4d50d3005 100644 --- a/source/blood/src/view.cpp +++ b/source/blood/src/view.cpp @@ -123,6 +123,8 @@ int pcBackground; int gViewMode = 3; int gViewSize = 2; +bool gPrediction = true; + VIEW predict, predictOld; VIEW predictFifo[256]; @@ -289,6 +291,11 @@ void viewInitializePrediction(void) predict.at40 = gMe->zWeapon; predict.at44 = gMe->zWeaponVel; predictOld = predict; + if (numplayers != 1) + { + gViewAngle = predict.at30; + gViewLook = predict.at20; + } } void viewUpdatePrediction(GINPUT *pInput) @@ -301,6 +308,11 @@ void viewUpdatePrediction(GINPUT *pInput) gMe->pSprite->cstat = bakCstat; predictFifo[gPredictTail&255] = predict; gPredictTail++; + if (numplayers != 1) + { + gViewAngle = predict.at30; + gViewLook = predict.at20; + } } void sub_158B4(PLAYER *pPlayer) @@ -312,6 +324,14 @@ void sub_158B4(PLAYER *pPlayer) void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput) { POSTURE *pPosture = &pPlayer->pPosture[pPlayer->lifeMode][predict.at48]; + + if (numplayers > 1 && gPrediction) + { + gViewAngleAdjust = 0.f; + gViewLookRecenter = false; + gViewLookAdjust = 0.f; + } + predict.at70 = pInput->syncFlags.run; predict.at70 = 0; predict.at71 = pInput->buttonFlags.jump; @@ -381,6 +401,8 @@ void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput) predict.at4c = min(predict.at4c+speed, 0); predict.at30 += fix16_from_int(speed); + if (numplayers > 1 && gPrediction) + gViewAngleAdjust += float(speed); } if (!predict.at71) @@ -454,6 +476,18 @@ void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput) if (pInput->buttonFlags.lookDown) predict.at20 = fix16_max(predict.at20-F16(lookStepDown), F16(downAngle)); } + if (numplayers > 1 && gPrediction) + { + if (pInput->buttonFlags.lookUp) + { + gViewLookAdjust += float(lookStepUp); + } + if (pInput->buttonFlags.lookDown) + { + gViewLookAdjust -= float(lookStepDown); + } + gViewLookRecenter = predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown; + } predict.at20 = fix16_clamp(predict.at20+(pInput->q16mlook<<3), F16(downAngle), F16(upAngle)); predict.at24 = fix16_from_float(100.f*tanf(fix16_to_float(predict.at20)*fPI/1024.f)); @@ -871,7 +905,12 @@ void fakeActProcessSprites(void) void viewCorrectPrediction(void) { - if (gGameOptions.nGameType == 0) return; + if (numplayers == 1) + { + gViewLook = gMe->q16look; + gViewAngle = gMe->q16ang; + return; + } spritetype *pSprite = gMe->pSprite; VIEW *pView = &predictFifo[(gNetFifoTail-1)&255]; if (gMe->q16ang != pView->at30 || pView->at24 != gMe->q16horiz || pView->at50 != pSprite->x || pView->at54 != pSprite->y || pView->at58 != pSprite->z) @@ -2970,8 +3009,6 @@ void UpdateDacs(int nPalette, bool bNoTint) } } -bool gPrediction = true; - char otherMirrorGotpic[2]; char bakMirrorGotpic[2]; // int gVisibility; @@ -3150,6 +3187,15 @@ void viewDrawScreen(bool sceneonly) v48 = interpolate(pView->at18, v48, gInterpolate); } } + if (gView == gMe && (numplayers <= 1 || gPrediction) && gView->pXSprite->health != 0 && !VanillaMode()) + { + CONSTEXPR int upAngle = 289; + CONSTEXPR int downAngle = -347; + fix16_t q16look; + cA = gViewAngle; + q16look = gViewLook; + q16horiz = fix16_from_float(100.f * tanf(fix16_to_float(q16look) * fPI / 1024.f)); + } viewUpdateShake(); q16horiz += fix16_from_int(shakeHoriz); cA += fix16_from_int(shakeAngle);