Updated A_FaceVelocity to remove conflicts.

This commit is contained in:
MajorCooke 2016-01-20 15:51:11 -06:00
commit d20a7516c9
3 changed files with 121 additions and 0 deletions

View File

@ -6052,3 +6052,115 @@ 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,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceVelocity)
{
ACTION_PARAM_START(5);
ACTION_PARAM_ANGLE(offset, 0);
ACTION_PARAM_ANGLE(anglelimit, 1);
ACTION_PARAM_ANGLE(pitchlimit, 2);
ACTION_PARAM_INT(flags, 3);
ACTION_PARAM_INT(ptr, 4);
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))
{
angle_t current = mobj->angle;
const angle_t angle = R_PointToAngle2(0, 0, mobj->velx, mobj->vely);
//Done because using anglelimit directly causes a signed/unsigned mismatch.
const angle_t limit = anglelimit;
//Code borrowed from A_Face*.
if (limit > 0 && (absangle(current - angle) > limit))
{
if (current < angle)
{
// [MC] This may appear backwards, but I assure any who
// reads this, it works.
if (current - angle > ANGLE_180)
current += limit + offset;
else
current -= limit + offset;
mobj->SetAngle(current, !!(flags & FVF_INTERPOLATE));
}
else if (current > angle)
{
if (angle - current > ANGLE_180)
current -= limit + offset;
else
current += limit + offset;
mobj->SetAngle(current, !!(flags & FVF_INTERPOLATE));
}
else
mobj->SetAngle(angle + ANGLE_180 + offset, !!(flags & FVF_INTERPOLATE));
}
else
mobj->SetAngle(angle + offset, !!(flags & FVF_INTERPOLATE));
}
if (!(flags & FVF_NOPITCH))
{
fixed_t current = mobj->pitch;
const FVector2 velocity(mobj->velx, mobj->vely);
const fixed_t pitch = R_PointToAngle2(0, 0, (fixed_t)velocity.Length(), -mobj->velz);
fixedvec2 test;
if (pitchlimit > 0)
{
// [MC] angle_t for pitchlimit was required because otherwise
// we would wind up with less than desirable turn rates that didn't
// match that of A_SetPitch. We want consistency. Also, I didn't know
// of a better way to convert from angle_t to fixed_t properly so I
// used this instead.
fixed_t plimit = fixed_t(pitchlimit);
if (abs(current - pitch) > plimit)
{
fixed_t max = 0;
if (current > pitch)
{
max = MIN(plimit, (current - pitch));
current -= max;
}
else //if (current > pitch)
{
max = MIN(plimit, (pitch - current));
current += max;
}
mobj->SetPitch(current, !!(flags & FVF_INTERPOLATE));
}
else
{
mobj->SetPitch(pitch, !!(flags & FVF_INTERPOLATE));
}
}
else
{
mobj->SetPitch(pitch, !!(flags & FVF_INTERPOLATE));
}
}
}

View File

@ -341,6 +341,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, float anglelimit = 0, float pitchlimit = 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

@ -510,6 +510,14 @@ 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,
};
// This is only here to provide one global variable for testing.
native int testglobalvar;