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.
This commit is contained in:
nukeykt 2020-01-30 22:05:34 +09:00 committed by Christoph Oelckers
parent 371b613ebe
commit c8372c233e
9 changed files with 248 additions and 189 deletions

View file

@ -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:

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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));
}

View file

@ -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);