- Implement new scaled angle change setup and remove enforcement of synchronised input.

This commit is contained in:
Mitchell Richters 2022-12-09 17:55:13 +11:00 committed by Christoph Oelckers
parent 9437ea9622
commit 968d0ae0d2
19 changed files with 89 additions and 46 deletions

View file

@ -178,33 +178,33 @@ void PlayerAngles::applyPitch(float const horz, ESyncBits* actions, double const
// Process mouse input.
if (horz)
{
pActor->spr.Angles.Pitch += DAngle::fromDeg(horz);
activeAngles().Pitch += DAngle::fromDeg(horz);
*actions &= ~SB_CENTERVIEW;
}
// Process keyboard input.
if (auto aiming = !!(*actions & SB_AIM_DOWN) - !!(*actions & SB_AIM_UP))
{
pActor->spr.Angles.Pitch += getTicrateScale(PITCH_AIMSPEED) * scaleAdjust * aiming;
activeAngles().Pitch += getTicrateScale(PITCH_AIMSPEED) * scaleAdjust * aiming;
*actions &= ~SB_CENTERVIEW;
}
if (auto looking = !!(*actions & SB_LOOK_DOWN) - !!(*actions & SB_LOOK_UP))
{
pActor->spr.Angles.Pitch += getTicrateScale(PITCH_LOOKSPEED) * scaleAdjust * looking;
activeAngles().Pitch += getTicrateScale(PITCH_LOOKSPEED) * scaleAdjust * looking;
*actions |= SB_CENTERVIEW;
}
// Do return to centre.
if ((*actions & SB_CENTERVIEW) && !(*actions & (SB_LOOK_UP|SB_LOOK_DOWN)))
{
const auto pitch = abs(pActor->spr.Angles.Pitch);
const auto pitch = abs(activeAngles().Pitch);
const auto scale = pitch > PITCH_CNTRSINEOFFSET ? (pitch - PITCH_CNTRSINEOFFSET).Cos() : 1.;
scaletozero(pActor->spr.Angles.Pitch, PITCH_CENTERSPEED * scale, scaleAdjust);
if (!pActor->spr.Angles.Pitch.Sgn()) *actions &= ~SB_CENTERVIEW;
scaletozero(activeAngles().Pitch, PITCH_CENTERSPEED * scale, scaleAdjust);
if (!activeAngles().Pitch.Sgn()) *actions &= ~SB_CENTERVIEW;
}
// clamp before we finish, even if it's clamped in the drawer.
pActor->spr.Angles.Pitch = ClampViewPitch(pActor->spr.Angles.Pitch);
activeAngles().Pitch = ClampViewPitch(activeAngles().Pitch);
}
@ -217,7 +217,7 @@ void PlayerAngles::applyPitch(float const horz, ESyncBits* actions, double const
void PlayerAngles::applyYaw(float const avel, ESyncBits* actions, double const scaleAdjust)
{
// add player's input
pActor->spr.Angles.Yaw += DAngle::fromDeg(avel);
activeAngles().Yaw += DAngle::fromDeg(avel);
if (*actions & SB_TURNAROUND)
{
@ -240,7 +240,7 @@ void PlayerAngles::applyYaw(float const avel, ESyncBits* actions, double const s
add -= YawSpin;
YawSpin = nullAngle;
}
pActor->spr.Angles.Yaw += add;
activeAngles().Yaw += add;
}
}
@ -336,7 +336,7 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, PlayerAngles& w, P
if (arc.isReading())
{
w.backupViewAngles();
w.resetRenderAngles();
}
}
return arc;

View file

@ -11,6 +11,9 @@ struct PlayerAngles
// Player viewing angles, separate from the camera.
DRotator PrevViewAngles, ViewAngles;
// Player camera angles, not for direct manipulation within the playsim.
DRotator RenderAngles;
// Holder of current yaw spin state for the 180 degree turn.
DAngle YawSpin;
@ -25,13 +28,20 @@ struct PlayerAngles
void doViewYaw(const ESyncBits actions);
// General methods.
void backupViewAngles() { PrevViewAngles = ViewAngles; }
void setActor(DCoreActor* const actor) { pActor = actor; }
// Angle getters.
void initialize(DCoreActor* const actor, const DAngle viewyaw = nullAngle)
{
if ((pActor = actor)) RenderAngles = PrevLerpAngles = pActor->spr.Angles;
PrevViewAngles.Yaw = ViewAngles.Yaw = viewyaw;
}
DAngle getPitchWithView()
{
return pActor->spr.Angles.Pitch + ViewAngles.Pitch;
return ClampViewPitch(pActor->spr.Angles.Pitch + ViewAngles.Pitch);
}
// Render angle functions.
DRotator& activeAngles()
{
return !SyncInput() ? RenderAngles : pActor->spr.Angles;
}
DRotator lerpViewAngles(const double interpfrac)
{
@ -39,7 +49,24 @@ struct PlayerAngles
}
DRotator getRenderAngles(const double interpfrac)
{
return (!SyncInput() ? pActor->spr.Angles : pActor->interpolatedangles(interpfrac)) + lerpViewAngles(interpfrac);
// Get angles and return with clamped off pitch.
auto angles = RenderAngles + lerpViewAngles(interpfrac);
angles.Pitch = ClampViewPitch(angles.Pitch);
return angles;
}
void updateRenderAngles(const double interpfrac)
{
// Apply the current interpolated angle state to the render angles.
const auto lerpAngles = pActor->interpolatedangles(interpfrac);
RenderAngles += lerpAngles - PrevLerpAngles;
PrevLerpAngles = lerpAngles;
}
void resetRenderAngles()
{
// Apply any last remaining ticrate angle updates and reset variables.
RenderAngles += pActor->spr.Angles - PrevLerpAngles;
PrevLerpAngles = pActor->spr.Angles = RenderAngles;
PrevViewAngles = ViewAngles;
}
// Draw code helpers.
@ -84,6 +111,7 @@ private:
};
// Private data which should never be accessed publically.
DRotator PrevLerpAngles;
DCoreActor* pActor;
// Internal angle updater to reduce boilerplate from the public setters.

View file

@ -109,7 +109,7 @@ extern double inputScale;
inline bool SyncInput()
{
return true; //gamesetinput || cl_syncinput || cl_capfps;
return gamesetinput || cl_syncinput || cl_capfps;
}
inline float backendinputscale()

View file

@ -423,6 +423,9 @@ void GameInterface::Ticker()
thinktime.Clock();
for (int i = connecthead; i >= 0; i = connectpoint2[i])
{
// this must be done before the view is backed up.
gPlayer[i].Angles.resetRenderAngles();
viewBackupView(i);
playerProcess(&gPlayer[i]);
}

View file

@ -801,7 +801,8 @@ void playerStart(int nPlayer, int bNewLevel)
auto actor = actSpawnSprite(pStartZone->sector, pStartZone->pos, 6, 1);
assert(actor->hasX());
pPlayer->actor = actor;
pPlayer->Angles.setActor(actor);
pPlayer->Angles = {};
pPlayer->Angles.initialize(pPlayer->actor);
DUDEINFO* pDudeInfo = &dudeInfo[kDudePlayer1 + nPlayer - kDudeBase];
pPlayer->pDudeInfo = pDudeInfo;
playerSetRace(pPlayer, kModeHuman);
@ -1522,8 +1523,6 @@ void ProcessInput(PLAYER* pPlayer)
Item_JumpBoots = 3
};
pPlayer->Angles.backupViewAngles();
DBloodActor* actor = pPlayer->actor;
POSTURE* pPosture = &pPlayer->pPosture[pPlayer->lifeMode][pPlayer->posture];
InputPacket* pInput = &pPlayer->input;

View file

@ -611,6 +611,9 @@ void viewDrawScreen(bool sceneonly)
}
else interpfrac = 1.;
// update render angles.
pPlayer->Angles.updateRenderAngles(interpfrac);
if (cl_interpolate)
{
DoInterpolations(interpfrac);

View file

@ -69,6 +69,9 @@ void GameInterface::Ticker()
ud.cameraactor = nullptr;
everyothertime++;
// this must be done before the view is backed up.
ps[myconnectindex].Angles.resetRenderAngles();
DukeSpriteIterator it;
while (auto ac = it.Next())
{

View file

@ -2700,8 +2700,6 @@ void processinput_d(int snum)
p = &ps[snum];
auto pact = p->GetActor();
p->Angles.backupViewAngles();
ESyncBits& actions = p->sync.actions;
auto sb_fvel = PlayerInputForwardVel(snum);

View file

@ -3214,8 +3214,6 @@ void processinput_r(int snum)
auto p = &ps[snum];
auto pact = p->GetActor();
p->Angles.backupViewAngles();
ESyncBits& actions = p->sync.actions;
auto sb_fvel = PlayerInputForwardVel(snum);

View file

@ -125,7 +125,6 @@ void resetplayerstats(int snum)
p->footprintpal = 0;
p->footprintshade = 0;
p->jumping_toggle = 0;
p->Angles.PrevViewAngles.Pitch = p->Angles.ViewAngles.Pitch = nullAngle;
p->bobcounter = 0;
p->on_ground = 0;
p->player_par = 0;
@ -149,10 +148,6 @@ void resetplayerstats(int snum)
p->heat_on = 0;
p->jetpack_on = 0;
p->holoduke_on = nullptr;
p->Angles.PrevViewAngles.Yaw = p->Angles.ViewAngles.Yaw = (currentLevel->levelNumber & 1)? DAngle90 : -DAngle90;
p->Angles.PrevViewAngles.Roll = p->Angles.ViewAngles.Roll = nullAngle;
p->newOwner =nullptr;
p->jumping_counter = 0;
p->hard_landing = 0;
@ -160,7 +155,6 @@ void resetplayerstats(int snum)
p->fric.X = 0;
p->fric.Y = 0;
p->somethingonplayer = nullptr;
p->Angles.YawSpin = nullAngle;
p->on_crane = nullptr;
@ -622,7 +616,8 @@ void resetpspritevars(int g, const DVector3& startpos, const DAngle startang)
act->spr.pal = ps[j].palookup = ud.user_pals[j];
ps[j].actor = act;
ps[j].Angles.setActor(act);
ps[j].Angles = {};
ps[j].Angles.initialize(ps[j].actor, (currentLevel->levelNumber & 1)? DAngle90 : -DAngle90);
ps[j].frag_ps = j;
act->SetOwner(act);

View file

@ -221,6 +221,9 @@ void displayrooms(int snum, double interpfrac, bool sceneonly)
player_struct* p = &ps[snum];
// update render angles.
p->Angles.updateRenderAngles(interpfrac);
if (automapMode == am_full || !p->insector())
return;

View file

@ -369,6 +369,10 @@ void GameInterface::Ticker()
}
else if (EndLevel == 0)
{
// this must be done before the view is backed up.
PlayerList[nLocalPlayer].Angles.resetRenderAngles();
UpdatePlayerSpriteAngle(&PlayerList[nLocalPlayer]);
inita = inita.Normalized360();
auto& lPlayerVel = sPlayerInput[nLocalPlayer].vel;

View file

@ -156,7 +156,7 @@ uint8_t LoadLevel(MapRecord* map)
for (i = 0; i < kMaxPlayers; i++)
{
PlayerList[i].pActor = nullptr;
PlayerList[i].Angles.setActor(nullptr);
PlayerList[i].Angles = {};
}
g_visibility = 1024;

View file

@ -181,7 +181,7 @@ void InitPlayer()
{
for (int i = 0; i < kMaxPlayers; i++) {
PlayerList[i].pActor = nullptr;
PlayerList[i].Angles.setActor(nullptr);
PlayerList[i].Angles = {};
PlayerList[i].pPlayerPushSect = nullptr;
PlayerList[i].pPlayerViewSect = nullptr;
}
@ -210,7 +210,7 @@ void InitPlayerInventory(int nPlayer)
PlayerList[nPlayer].nLives = kDefaultLives;
PlayerList[nPlayer].pActor = nullptr;
PlayerList[nPlayer].Angles.setActor(nullptr);
PlayerList[nPlayer].Angles = {};
PlayerList[nPlayer].nRun = -1;
PlayerList[nPlayer].nPistolClip = 6;
@ -262,7 +262,7 @@ void RestartPlayer(int nPlayer)
ChangeActorStat(pActor, 0);
plr->pActor = nullptr;
plr->Angles.setActor(nullptr);
plr->Angles = {};
DExhumedActor* pFloorSprite = plr->pPlayerFloorSprite;
if (pFloorSprite != nullptr) {
@ -356,7 +356,8 @@ void RestartPlayer(int nPlayer)
plr->nSeqSize = 0;
plr->pActor = pActor;
plr->Angles.setActor(pActor);
plr->Angles = {};
plr->Angles.initialize(plr->pActor);
plr->bIsMummified = false;
if (plr->invincibility >= 0) {
@ -904,8 +905,6 @@ void AIPlayer::Tick(RunListEvent* ev)
int nAction = PlayerList[nPlayer].nAction;
int nActionB = PlayerList[nPlayer].nAction;
PlayerList[nPlayer].Angles.backupViewAngles();
pPlayerActor->vel.XY() = sPlayerInput[nPlayer].vel;
if (sPlayerInput[nPlayer].nItem > -1)

View file

@ -201,6 +201,10 @@ void DrawView(double interpfrac, bool sceneonly)
auto pDop = pPlayer->pDoppleSprite;
auto nDoppleOldCstat = pDop->spr.cstat;
// update render angles.
pPlayer->Angles.updateRenderAngles(interpfrac);
UpdatePlayerSpriteAngle(pPlayer);
if (nSnakeCam >= 0 && !sceneonly)
{
DExhumedActor* pActor = SnakeList[nSnakeCam].pSprites[0];

View file

@ -1237,6 +1237,9 @@ void drawscreen(PLAYER* pp, double interpfrac, bool sceneonly)
if (cl_sointerpolation) so_dointerpolations(interpfrac);
}
// update render angles.
pp->Angles.updateRenderAngles(interpfrac);
// Get initial player position, interpolating if required.
DVector3 tpos = camerapp->actor->getRenderPos(interpfrac);
DRotator tangles = camerapp->Angles.getRenderAngles(interpfrac);

View file

@ -572,7 +572,7 @@ void TerminateLevel(void)
pp->DoPlayerAction = nullptr;
pp->actor = nullptr;
pp->Angles.setActor(nullptr);
pp->Angles = {};
pp->PlayerUnderActor = nullptr;

View file

@ -2407,7 +2407,8 @@ void InitPlayerSprite(PLAYER* pp, const DVector3& spawnpos, const DAngle startan
pp->actor = actor;
pp->pnum = pnum;
pp->Angles.setActor(actor);
pp->Angles = {};
pp->Angles.initialize(pp->actor);
actor->spr.cstat |= (CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
actor->spr.extra |= (SPRX_PLAYER_OR_ENEMY);

View file

@ -1553,10 +1553,10 @@ void DoPlayerTurnVehicle(PLAYER* pp, float avel, double zz, double floordist)
if (avel != 0)
{
auto sum = pp->actor->spr.Angles.Yaw + DAngle::fromDeg(avel);
auto sum = pp->Angles.activeAngles().Yaw + DAngle::fromDeg(avel);
if (MultiClipTurn(pp, sum, zz, floordist))
{
pp->actor->spr.Angles.Yaw = sum;
pp->Angles.activeAngles().Yaw = sum;
}
}
}
@ -1619,7 +1619,7 @@ void DoPlayerTurnTurret(PLAYER* pp, float avel)
if (fabs(avel) >= FLT_EPSILON)
{
new_ang = pp->actor->spr.Angles.Yaw + DAngle::fromDeg(avel);
new_ang = pp->Angles.activeAngles().Yaw + DAngle::fromDeg(avel);
if (sop->limit_ang_center >= nullAngle)
{
@ -1634,10 +1634,10 @@ void DoPlayerTurnTurret(PLAYER* pp, float avel)
}
}
pp->actor->spr.Angles.Yaw = new_ang;
pp->Angles.activeAngles().Yaw = new_ang;
}
OperateSectorObject(pp->sop, pp->actor->spr.Angles.Yaw, pp->sop->pmid);
OperateSectorObject(pp->sop, pp->Angles.activeAngles().Yaw, pp->sop->pmid);
}
//---------------------------------------------------------------------------
@ -6697,6 +6697,9 @@ void MoveSkipSavePos(void)
{
pp = Player + pnum;
// this must be done before the view is backed up.
pp->Angles.resetRenderAngles();
pp->actor->backuploc();
pp->obob_z = pp->bob_z;
pp->opbob_amt = pp->pbob_amt;
@ -6991,7 +6994,6 @@ void domovethings(void)
// Reset flags used while tying input to framerate
pp->Flags2 &= ~(PF2_INPUT_CAN_AIM|PF2_INPUT_CAN_TURN_GENERAL|PF2_INPUT_CAN_TURN_VEHICLE|PF2_INPUT_CAN_TURN_TURRET);
pp->Angles.backupViewAngles();
// disable synchronised input if set by game.
resetForcedSyncInput();