diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 3701a7b910..1174119d8e 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2671,7 +2671,7 @@ void A_Chase(AActor *self) // A_FaceTarget // //============================================================================= -void A_FaceTarget (AActor *self) +void A_FaceTarget (AActor *self, angle_t max_turn) { if (!self->target) return; @@ -2683,18 +2683,54 @@ void A_FaceTarget (AActor *self) } self->flags &= ~MF_AMBUSH; - self->angle = R_PointToAngle2 (self->x, self->y, - self->target->x, self->target->y); - - if (self->target->flags & MF_SHADOW) + + angle_t target_angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y); + + // 0 means no limit. Also, if we turn in a single step anyways, no need to go through the algorithms. + // It also means that there is no need to check for going past the target. + if (max_turn && (max_turn < abs(self->angle - target_angle))) + { + if (self->angle > target_angle) + { + if (self->angle - target_angle < ANGLE_180) + { + self->angle -= max_turn; + } + else + { + self->angle += max_turn; + } + } + else + { + if (target_angle - self->angle < ANGLE_180) + { + self->angle += max_turn; + } + else + { + self->angle -= max_turn; + } + } + } + else + { + self->angle = target_angle; + } + + // This will never work well if the turn angle is limited. + if (max_turn == 0 && (self->angle == target_angle) && self->target->flags & MF_SHADOW) { self->angle += pr_facetarget.Random2() << 21; } } -DEFINE_ACTION_FUNCTION(AActor, A_FaceTarget) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) { - A_FaceTarget(self); + ACTION_PARAM_START(1); + ACTION_PARAM_ANGLE(max_turn, 0); + + A_FaceTarget(self, max_turn); } //=========================================================================== diff --git a/src/p_enemy.h b/src/p_enemy.h index 86261dd45c..e3e83be6cb 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -69,7 +69,7 @@ DECLARE_ACTION(A_FreezeDeathChunks) DECLARE_ACTION(A_BossDeath) void A_Chase(AActor *self); -void A_FaceTarget (AActor *actor); +void A_FaceTarget (AActor *actor, angle_t max_turn = 0); bool A_RaiseMobj (AActor *, fixed_t speed); bool A_SinkMobj (AActor *, fixed_t speed); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 1b9719463e..7ef500d0a8 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -61,7 +61,7 @@ ACTOR Actor native //: Thinker action native A_XScream(); action native A_Look(); action native A_Chase(state melee = "*", state missile = "none", int flags = 0); - action native A_FaceTarget(); + action native A_FaceTarget(float max_turn = 0); action native A_PosAttack(); action native A_Scream(); action native A_SPosAttack();