View Angles (Part 1 - Redux) (#1002)

* Added ViewAngle/Pitch/Roll properties to actors.

- These are offsets for camera angles that allow turning the camera without affecting aim or movement direction.
- Added A_SetView<Angle/Pitch/Roll>, which will set the view direction.
- Added ABSVIEWANGLES flag, used to make the view absolute instead of an offset.

* Converted functions to be direct-native.
This commit is contained in:
MajorCooke 2020-08-27 12:03:06 -05:00 committed by GitHub
parent c57e669044
commit eaba63e13b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 205 additions and 37 deletions

View file

@ -1039,6 +1039,9 @@ xx(AttackZOffset)
xx(SpawnMask) xx(SpawnMask)
xx(ScoreIcon) xx(ScoreIcon)
xx(ViewHeight) xx(ViewHeight)
xx(ViewAngle)
xx(ViewPitch)
xx(ViewRoll)
xx(FallingScreamMinSpeed) xx(FallingScreamMinSpeed)
xx(FallingScreamMaxSpeed) xx(FallingScreamMaxSpeed)
xx(GruntSpeed) xx(GruntSpeed)

View file

@ -412,6 +412,7 @@ enum ActorFlag8
MF8_RETARGETAFTERSLAM = 0x00000080, // Forces jumping to the idle state after slamming into something MF8_RETARGETAFTERSLAM = 0x00000080, // Forces jumping to the idle state after slamming into something
MF8_RECREATELIGHTS = 0x00000100, // Internal flag that signifies that the light attachments need to be recreated at the MF8_RECREATELIGHTS = 0x00000100, // Internal flag that signifies that the light attachments need to be recreated at the
MF8_STOPRAILS = 0x00000200, // [MC] Prevent rails from going further if an actor has this flag. MF8_STOPRAILS = 0x00000200, // [MC] Prevent rails from going further if an actor has this flag.
MF8_ABSVIEWANGLES = 0x00000400, // [MC] By default view angle/pitch/roll is an offset. This will make it absolute instead.
}; };
// --- mobj.renderflags --- // --- mobj.renderflags ---
@ -845,9 +846,13 @@ public:
} }
// These also set CF_INTERPVIEW for players. // These also set CF_INTERPVIEW for players.
void SetPitch(DAngle p, bool interpolate, bool forceclamp = false); DAngle ClampPitch(DAngle p);
void SetAngle(DAngle ang, bool interpolate); void SetPitch(DAngle p, int fflags);
void SetRoll(DAngle roll, bool interpolate); void SetAngle(DAngle ang, int fflags);
void SetRoll(DAngle roll, int fflags);
void SetViewPitch(DAngle p, int fflags);
void SetViewAngle(DAngle ang, int fflags);
void SetViewRoll(DAngle roll, int fflags);
PClassActor *GetBloodType(int type = 0) const; PClassActor *GetBloodType(int type = 0) const;
@ -961,6 +966,7 @@ public:
DAngle SpriteAngle; DAngle SpriteAngle;
DAngle SpriteRotation; DAngle SpriteRotation;
DRotator Angles; DRotator Angles;
DRotator ViewAngles; // Offsets for cameras
DVector2 Scale; // Scaling values; 1 is normal size DVector2 Scale; // Scaling values; 1 is normal size
double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double.

View file

@ -419,7 +419,6 @@ public:
return mo->FloatVar(NAME_ViewHeight); return mo->FloatVar(NAME_ViewHeight);
} }
void Uncrouch() void Uncrouch()
{ {
if (crouchfactor != 1) if (crouchfactor != 1)

View file

@ -2793,12 +2793,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRefire)
// Set actor's angle (in degrees). // Set actor's angle (in degrees).
// //
//=========================================================================== //===========================================================================
enum
{
SPF_FORCECLAMP = 1, // players always clamp
SPF_INTERPOLATE = 2,
};
DEFINE_ACTION_FUNCTION(AActor, A_SetAngle) DEFINE_ACTION_FUNCTION(AActor, A_SetAngle)
{ {
@ -2810,7 +2804,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetAngle)
AActor *ref = COPY_AAPTR(self, ptr); AActor *ref = COPY_AAPTR(self, ptr);
if (ref != NULL) if (ref != NULL)
{ {
ref->SetAngle(angle, !!(flags & SPF_INTERPOLATE)); ref->SetAngle(angle, flags);
} }
return 0; return 0;
} }
@ -2834,7 +2828,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetPitch)
if (ref != NULL) if (ref != NULL)
{ {
ref->SetPitch(pitch, !!(flags & SPF_INTERPOLATE), !!(flags & SPF_FORCECLAMP)); ref->SetPitch(pitch, flags);
} }
return 0; return 0;
} }
@ -2857,11 +2851,98 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetRoll)
if (ref != NULL) if (ref != NULL)
{ {
ref->SetRoll(roll, !!(flags & SPF_INTERPOLATE)); ref->SetRoll(roll, flags);
} }
return 0; return 0;
} }
//===========================================================================
//
// A_SetViewAngle
//
// Set actor's viewangle (in degrees).
//
//===========================================================================
static void SetViewAngleNative(AActor* self, double angle, int flags, int ptr)
{
AActor *ref = COPY_AAPTR(self, ptr);
if (ref != nullptr)
{
ref->SetViewAngle(angle, flags);
}
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SetViewAngle, SetViewAngleNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(angle);
PARAM_INT(flags);
PARAM_INT(ptr);
SetViewAngleNative(self, angle, flags, ptr);
return 0;
}
//===========================================================================
//
// A_SetViewPitch
//
// Set actor's viewpitch (in degrees).
//
//===========================================================================
static void SetViewPitchNative(AActor* self, double pitch, int flags, int ptr)
{
AActor *ref = COPY_AAPTR(self, ptr);
if (ref != nullptr)
{
ref->SetViewPitch(pitch, flags);
}
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SetViewPitch, SetViewPitchNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(pitch);
PARAM_INT(flags);
PARAM_INT(ptr);
SetViewPitchNative(self, pitch, flags, ptr);
return 0;
}
//===========================================================================
//
// [MC] A_SetViewRoll
//
// Set actor's viewroll (in degrees).
//
//===========================================================================
static void SetViewRollNative(AActor* self, double roll, int flags, int ptr)
{
AActor *ref = COPY_AAPTR(self, ptr);
if (ref != nullptr)
{
ref->SetViewRoll(roll, flags);
}
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SetViewRoll, SetViewRollNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(roll);
PARAM_INT(flags);
PARAM_INT(ptr);
SetViewRollNative(self, roll, flags, ptr);
return 0;
}
//=========================================================================== //===========================================================================
// //
// A_SetUserVar // A_SetUserVar

View file

@ -217,6 +217,12 @@ enum WARPF
WARPF_COPYPITCH = 0x8000, WARPF_COPYPITCH = 0x8000,
}; };
enum SPF
{
SPF_FORCECLAMP = 1, // players always clamp
SPF_INTERPOLATE = 2,
};
enum PCM enum PCM
{ {
PCM_DROPOFF = 1, PCM_DROPOFF = 1,

View file

@ -362,6 +362,7 @@ void AActor::Serialize(FSerializer &arc)
A("renderhidden", RenderHidden) A("renderhidden", RenderHidden)
A("renderrequired", RenderRequired) A("renderrequired", RenderRequired)
A("friendlyseeblocks", friendlyseeblocks) A("friendlyseeblocks", friendlyseeblocks)
A("viewangles", ViewAngles)
A("spawntime", SpawnTime) A("spawntime", SpawnTime)
A("spawnorder", SpawnOrder) A("spawnorder", SpawnOrder)
A("friction", Friction) A("friction", Friction)
@ -3352,13 +3353,13 @@ DEFINE_ACTION_FUNCTION(AActor, SetShade)
return 0; return 0;
} }
void AActor::SetPitch(DAngle p, bool interpolate, bool forceclamp) // [MC] Helper function for Set(View)Pitch.
DAngle AActor::ClampPitch(DAngle p)
{ {
if (player != NULL || forceclamp) // clamp the pitch we set
{ // clamp the pitch we set
DAngle min, max; DAngle min, max;
if (player != NULL) if (player != nullptr)
{ {
min = player->MinPitch; min = player->MinPitch;
max = player->MaxPitch; max = player->MaxPitch;
@ -3369,35 +3370,89 @@ void AActor::SetPitch(DAngle p, bool interpolate, bool forceclamp)
max = 89.; max = 89.;
} }
p = clamp(p, min, max); p = clamp(p, min, max);
return p;
}
void AActor::SetPitch(DAngle p, int fflags)
{
if (player != nullptr || (fflags & SPF_FORCECLAMP))
{
p = ClampPitch(p);
} }
if (p != Angles.Pitch) if (p != Angles.Pitch)
{ {
Angles.Pitch = p; Angles.Pitch = p;
if (player != NULL && interpolate) if (player != nullptr && (fflags & SPF_INTERPOLATE))
{ {
player->cheats |= CF_INTERPVIEW; player->cheats |= CF_INTERPVIEW;
} }
} }
} }
void AActor::SetAngle(DAngle ang, bool interpolate) void AActor::SetAngle(DAngle ang, int fflags)
{ {
if (ang != Angles.Yaw) if (ang != Angles.Yaw)
{ {
Angles.Yaw = ang; Angles.Yaw = ang;
if (player != NULL && interpolate) if (player != nullptr && (fflags & SPF_INTERPOLATE))
{
player->cheats |= CF_INTERPVIEW;
}
}
}
void AActor::SetRoll(DAngle r, int fflags)
{
if (r != Angles.Roll)
{
Angles.Roll = r;
if (player != nullptr && (fflags & SPF_INTERPOLATE))
{ {
player->cheats |= CF_INTERPVIEW; player->cheats |= CF_INTERPVIEW;
} }
} }
} }
void AActor::SetRoll(DAngle r, bool interpolate) void AActor::SetViewPitch(DAngle p, int fflags)
{ {
if (r != Angles.Roll) if (player != NULL || (fflags & SPF_FORCECLAMP))
{ {
Angles.Roll = r; p = ClampPitch(p);
if (player != NULL && interpolate) }
if (p != ViewAngles.Pitch)
{
ViewAngles.Pitch = p;
if (player != nullptr && (fflags & SPF_INTERPOLATE))
{
player->cheats |= CF_INTERPVIEW;
}
}
}
void AActor::SetViewAngle(DAngle ang, int fflags)
{
if (ang != ViewAngles.Yaw)
{
ViewAngles.Yaw = ang;
if (player != nullptr && (fflags & SPF_INTERPOLATE))
{
player->cheats |= CF_INTERPVIEW;
}
}
}
void AActor::SetViewRoll(DAngle r, int fflags)
{
if (r != ViewAngles.Roll)
{
ViewAngles.Roll = r;
if (player != nullptr && (fflags & SPF_INTERPOLATE))
{ {
player->cheats |= CF_INTERPVIEW; player->cheats |= CF_INTERPVIEW;
} }

View file

@ -804,7 +804,17 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor
viewpoint.sector = viewpoint.camera->Sector; viewpoint.sector = viewpoint.camera->Sector;
viewpoint.showviewer = false; viewpoint.showviewer = false;
} }
iview->New.Angles = viewpoint.camera->Angles;
// [MC] Apply the view angles first, which is the offsets. If the absolute isn't desired,
// add the standard angles on top of it.
viewpoint.Angles = viewpoint.camera->ViewAngles;
if (!(viewpoint.camera->flags8 & MF8_ABSVIEWANGLES))
{
viewpoint.Angles += viewpoint.camera->Angles;
}
iview->New.Angles = viewpoint.Angles;
if (viewpoint.camera->player != 0) if (viewpoint.camera->player != 0)
{ {
player = viewpoint.camera->player; player = viewpoint.camera->player;

View file

@ -325,6 +325,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF8, NOFRICTIONBOUNCE, AActor, flags8), DEFINE_FLAG(MF8, NOFRICTIONBOUNCE, AActor, flags8),
DEFINE_FLAG(MF8, RETARGETAFTERSLAM, AActor, flags8), DEFINE_FLAG(MF8, RETARGETAFTERSLAM, AActor, flags8),
DEFINE_FLAG(MF8, STOPRAILS, AActor, flags8), DEFINE_FLAG(MF8, STOPRAILS, AActor, flags8),
DEFINE_FLAG(MF8, ABSVIEWANGLES, AActor, flags8),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -1943,6 +1943,9 @@ DEFINE_FIELD(AActor, RenderRequired)
DEFINE_FIELD(AActor, friendlyseeblocks) DEFINE_FIELD(AActor, friendlyseeblocks)
DEFINE_FIELD(AActor, SpawnTime) DEFINE_FIELD(AActor, SpawnTime)
DEFINE_FIELD(AActor, InventoryID) DEFINE_FIELD(AActor, InventoryID)
DEFINE_FIELD_NAMED(AActor, ViewAngles.Yaw, viewangle)
DEFINE_FIELD_NAMED(AActor, ViewAngles.Pitch, viewpitch)
DEFINE_FIELD_NAMED(AActor, ViewAngles.Roll, viewroll)
DEFINE_FIELD_X(FCheckPosition, FCheckPosition, thing); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, thing);
DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos);

View file

@ -232,6 +232,7 @@ class Actor : Thinker native
native uint8 fountaincolor; native uint8 fountaincolor;
native double CameraHeight; // Height of camera when used as such native double CameraHeight; // Height of camera when used as such
native double CameraFOV; native double CameraFOV;
native double ViewAngle, ViewPitch, ViewRoll;
native double RadiusDamageFactor; // Radius damage factor native double RadiusDamageFactor; // Radius damage factor
native double SelfDamageFactor; native double SelfDamageFactor;
native double StealthAlpha; native double StealthAlpha;
@ -1122,6 +1123,9 @@ class Actor : Thinker native
native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetViewAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetViewPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetViewRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVar(name varname, int value); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVar(name varname, int value);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArray(name varname, int index, int value); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArray(name varname, int index, int value);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVarFloat(name varname, double value); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVarFloat(name varname, double value);