2023-10-02 00:28:09 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-10-02 04:26:45 +00:00
|
|
|
#include "d_net.h"
|
2023-10-02 00:28:09 +00:00
|
|
|
#include "packet.h"
|
2023-10-29 10:05:44 +00:00
|
|
|
#include "gamestate.h"
|
2023-10-31 03:44:58 +00:00
|
|
|
#include "gamefuncs.h"
|
2023-10-02 00:28:09 +00:00
|
|
|
|
2023-10-02 19:03:59 +00:00
|
|
|
class DCorePlayer : public DObject
|
2023-10-02 00:28:09 +00:00
|
|
|
{
|
2023-10-02 19:03:59 +00:00
|
|
|
DECLARE_CLASS(DCorePlayer, DObject)
|
|
|
|
HAS_OBJECT_POINTERS
|
|
|
|
protected:
|
|
|
|
DCorePlayer() = default;
|
|
|
|
void Clear()
|
|
|
|
{
|
2023-10-31 03:44:58 +00:00
|
|
|
CameraAngles = PrevLerpAngles = PrevViewAngles = ViewAngles = {};
|
|
|
|
PrevStrafeVel = StrafeVel = 0;
|
|
|
|
YawSpin = nullAngle;
|
2023-10-31 04:10:15 +00:00
|
|
|
CameraPos = {};
|
2023-10-02 19:03:59 +00:00
|
|
|
memset(&lastcmd, 0, sizeof(lastcmd));
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
actor = nullptr;
|
|
|
|
pnum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2023-10-31 03:44:58 +00:00
|
|
|
DRotator PrevLerpAngles, CameraAngles;
|
|
|
|
DRotator PrevViewAngles, ViewAngles;
|
|
|
|
double PrevStrafeVel, StrafeVel;
|
|
|
|
DAngle YawSpin;
|
2023-10-31 04:10:15 +00:00
|
|
|
DVector3 CameraPos;
|
2023-10-02 05:05:16 +00:00
|
|
|
ticcmd_t lastcmd, cmd;
|
2023-10-02 02:27:16 +00:00
|
|
|
DCoreActor* actor;
|
2023-10-02 07:44:04 +00:00
|
|
|
uint8_t pnum;
|
2023-10-02 02:27:16 +00:00
|
|
|
|
2023-10-02 19:03:59 +00:00
|
|
|
DCorePlayer(uint8_t p) : pnum(p) {}
|
|
|
|
void OnDestroy() override { if (actor) actor->Destroy(); actor = nullptr; }
|
2023-10-02 19:38:58 +00:00
|
|
|
void Serialize(FSerializer& arc) override;
|
2023-10-31 03:44:58 +00:00
|
|
|
|
|
|
|
// All overridable methods.
|
|
|
|
virtual DCoreActor* GetActor() = 0;
|
2023-11-05 09:54:17 +00:00
|
|
|
virtual bool canSlopeTilt() const { return false; }
|
|
|
|
virtual unsigned getCrouchFlags() const = 0;
|
|
|
|
virtual double GetMaxInputVel() const = 0;
|
2023-10-29 11:35:17 +00:00
|
|
|
virtual const DVector2& GetInputVelocity() const { return actor->vel.XY(); }
|
2023-10-31 03:44:58 +00:00
|
|
|
|
|
|
|
// Angle prototypes.
|
2023-10-29 08:50:25 +00:00
|
|
|
void doPitchInput();
|
|
|
|
void doYawInput();
|
2023-10-29 09:25:43 +00:00
|
|
|
void doViewPitch(const bool climbing = false);
|
2023-10-29 08:50:25 +00:00
|
|
|
void doViewYaw();
|
2023-10-29 11:35:17 +00:00
|
|
|
void doRollInput(const bool bUnderwater);
|
2023-10-31 03:44:58 +00:00
|
|
|
|
|
|
|
// Angle methods.
|
|
|
|
void InitAngles(const DAngle viewyaw = nullAngle)
|
|
|
|
{
|
|
|
|
PrevLerpAngles = CameraAngles = actor->spr.Angles;
|
|
|
|
PrevViewAngles = ViewAngles = { nullAngle, viewyaw, nullAngle };
|
|
|
|
PrevStrafeVel = StrafeVel = 0;
|
|
|
|
YawSpin = nullAngle;
|
|
|
|
}
|
|
|
|
|
|
|
|
DAngle getPitchWithView()
|
|
|
|
{
|
|
|
|
return ClampViewPitch(actor->spr.Angles.Pitch + ViewAngles.Pitch);
|
|
|
|
}
|
|
|
|
|
|
|
|
DRotator getRenderAngles(const double interpfrac)
|
|
|
|
{
|
|
|
|
// Get angles and return with clamped off pitch.
|
|
|
|
auto angles = CameraAngles + interpolatedvalue(PrevViewAngles, ViewAngles, interpfrac);
|
|
|
|
angles.Pitch = ClampViewPitch(angles.Pitch);
|
|
|
|
return angles;
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateCameraAngles(const double interpfrac)
|
|
|
|
{
|
|
|
|
// Apply the current interpolated angle state to the render angles.
|
|
|
|
const auto lerpAngles = interpolatedvalue(actor->PrevAngles, actor->spr.Angles, interpfrac);
|
|
|
|
CameraAngles += lerpAngles - PrevLerpAngles;
|
|
|
|
PrevLerpAngles = lerpAngles;
|
|
|
|
}
|
|
|
|
|
|
|
|
void resetCameraAngles()
|
|
|
|
{
|
|
|
|
if (actor != nullptr)
|
|
|
|
{
|
|
|
|
// Apply any last remaining ticrate angle updates and reset variables.
|
|
|
|
CameraAngles += actor->spr.Angles - PrevLerpAngles;
|
|
|
|
PrevLerpAngles = actor->spr.Angles = CameraAngles;
|
|
|
|
PrevViewAngles = ViewAngles;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw code helpers.
|
|
|
|
auto getCrosshairOffsets(const double interpfrac)
|
|
|
|
{
|
|
|
|
// Set up angles and return as pair with roll as the 2nd object since all callers inevitably need it.
|
|
|
|
const auto viewAngles = interpolatedvalue(PrevViewAngles, ViewAngles, interpfrac);
|
|
|
|
return std::make_pair(DVector2(160, 120 * -viewAngles.Roll.Tan()) * -viewAngles.Yaw.Tan() / tan(r_fov * pi::pi() / 360.), viewAngles.Roll);
|
|
|
|
}
|
2023-11-05 06:37:58 +00:00
|
|
|
|
2023-10-31 03:44:58 +00:00
|
|
|
auto getWeaponOffsets(const double interpfrac)
|
|
|
|
{
|
|
|
|
// Push the Y down a bit since the weapon is at the edge of the screen. Also null roll for now.
|
|
|
|
auto offsets = getCrosshairOffsets(interpfrac); offsets.first.Y *= 4.; offsets.second = nullAngle;
|
|
|
|
return offsets;
|
|
|
|
}
|
2023-10-02 00:28:09 +00:00
|
|
|
};
|
2023-10-02 04:26:45 +00:00
|
|
|
|
2023-10-02 19:03:59 +00:00
|
|
|
extern DCorePlayer* PlayerArray[MAXPLAYERS];
|
2023-10-03 22:27:15 +00:00
|
|
|
|
2023-10-31 03:44:58 +00:00
|
|
|
inline double getTicrateScale(const double value)
|
|
|
|
{
|
|
|
|
return value / GameTicRate;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DAngle getTicrateAngle(const double value)
|
|
|
|
{
|
|
|
|
return DAngle::fromDeg(getTicrateScale(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DAngle getscaledangle(const DAngle angle, const double scale, const DAngle push)
|
|
|
|
{
|
|
|
|
return (angle.Normalized180() * getTicrateScale(scale)) + push;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool scaletozero(DAngle& angle, const double scale, const DAngle push = DAngle::fromDeg(7646143. / 110386328.))
|
|
|
|
{
|
|
|
|
const auto sgn = angle.Sgn();
|
|
|
|
|
|
|
|
if (!sgn || sgn != (angle -= getscaledangle(angle, scale, push * sgn)).Sgn())
|
|
|
|
{
|
|
|
|
angle = nullAngle;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|