A_FaceVelocity(offset, flags, ptr)

- Changes the caller's angle and pitch according to the direction of velocity they're travelling.
- FVF_NOPITCH and FVF_NOANGLE disable changing of pitch/angle respectively and should be counted as mutually exclusive, or the function does nothing.
- FVF_INTERPOLATE - Interpolate's the angle and pitch changes.
- FVF_RESETPITCH will, if there's no z velocity, reset the pitch to 0. Otherwise, the pitch remains unchanged.
This commit is contained in:
MajorCooke 2015-11-25 01:44:19 -06:00
parent 466d56a77a
commit 75855dc64a
3 changed files with 61 additions and 0 deletions

View file

@ -5930,4 +5930,55 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
{
ACTION_JUMP(block);
}
}
//===========================================================================
//
// A_FaceVelocity(angle offset, bool pitch, ptr)
//
// Sets the actor('s pointer) to face the direction of travel.
//===========================================================================
enum FVFlags
{
FVF_NOPITCH = 1 << 0,
FVF_INTERPOLATE = 1 << 1,
FVF_NOANGLE = 1 << 2,
FVF_RESETPITCH = 1 << 3,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceVelocity)
{
ACTION_PARAM_START(3);
ACTION_PARAM_FIXED(offset, 0)
ACTION_PARAM_INT(flags, 1);
ACTION_PARAM_INT(ptr, 2);
AActor *mobj = COPY_AAPTR(self, ptr);
//Need an actor.
if (!mobj || ((flags & FVF_NOPITCH) && (flags & FVF_NOANGLE)))
{
ACTION_SET_RESULT(false);
return;
}
//Don't bother calculating this if we don't have any horizontal movement.
if (!(flags & FVF_NOANGLE) && (mobj->velx != 0 || mobj->vely != 0))
{
fixed_t vx = mobj->x + mobj->velx, vy = mobj->y + mobj->vely;
angle_t angle = R_PointToAngle2(mobj->x, mobj->y, vx, vy) + offset;
mobj->SetAngle(angle, !!(flags & FVF_INTERPOLATE));
}
if (!(flags & FVF_NOPITCH))
{
//Reset pitch to 0 if specified.
if (mobj->velz == 0 && (flags & FVF_RESETPITCH))
mobj->pitch = 0;
else
{
FVector2 velocity(mobj->velx, mobj->vely);
fixed_t pitch = R_PointToAngle2(0, 0, (fixed_t)velocity.Length(), mobj->velz);
mobj->SetPitch(-pitch, !!(flags & FVF_INTERPOLATE));
}
}
}

View file

@ -340,6 +340,7 @@ ACTOR Actor native //: Thinker
action native A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT);
action native A_CheckSightOrRange(float distance, state label, bool two_dimension = false);
action native A_CheckRange(float distance, state label, bool two_dimension = false);
action native A_FaceVelocity(float offset = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
action native A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0);
action native A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0);

View file

@ -495,6 +495,15 @@ enum
CBF_SETONPTR = 1 << 4, //Sets the pointer change on the actor doing the checking instead of self.
};
//Flags for A_FaceVelocity
enum
{
FVF_NOPITCH = 1 << 0,
FVF_INTERPOLATE = 1 << 1,
FVF_NOANGLE = 1 << 2,
FVF_RESETPITCH = 1 << 3,
};
// This is only here to provide one global variable for testing.
native int testglobalvar;