diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5cb1ce673b..796480c9c6 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2726,7 +2726,7 @@ void A_Chase(AActor *self) // A_FaceTracer // //============================================================================= -void A_Face (AActor *self, AActor *other, angle_t max_turn) +void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch) { if (!other) return; @@ -2773,6 +2773,50 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn) self->angle = other_angle; } + // [DH] Now set pitch. In order to maintain compatibility, this can be + // disabled and is so by default. + if (max_pitch <= ANGLE_180) + { + // [DH] Don't need to do proper fixed->double conversion, since the + // result is only used in a ratio. + double dist_x = self->target->x - self->x; + double dist_y = self->target->y - self->y; + double dist_z = self->target->z - self->z; + double dist = sqrt(dist_x*dist_x + dist_y*dist_y + dist_z*dist_z); + + angle_t other_pitch = rad2bam(asin(dist_z / dist)); + + if (max_pitch && (max_pitch < (angle_t)abs(self->pitch - other_pitch))) + { + if (self->pitch > other_pitch) + { + if (self->pitch - other_pitch < ANGLE_180) + { + self->pitch -= max_pitch; + } + else + { + self->pitch += max_pitch; + } + } + else + { + if (other_pitch - self->pitch < ANGLE_180) + { + self->pitch += max_pitch; + } + else + { + self->pitch -= max_pitch; + } + } + } + else + { + self->pitch = other_pitch; + } + } + // This will never work well if the turn angle is limited. if (max_turn == 0 && (self->angle == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) ) { @@ -2780,43 +2824,46 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn) } } -void A_FaceTarget (AActor *self, angle_t max_turn) +void A_FaceTarget (AActor *self, angle_t max_turn, angle_t max_pitch) { - A_Face(self, self->target, max_turn); + A_Face(self, self->target, max_turn, max_pitch); } -void A_FaceMaster (AActor *self, angle_t max_turn) +void A_FaceMaster (AActor *self, angle_t max_turn, angle_t max_pitch) { - A_Face(self, self->master, max_turn); + A_Face(self, self->master, max_turn, max_pitch); } -void A_FaceTracer (AActor *self, angle_t max_turn) +void A_FaceTracer (AActor *self, angle_t max_turn, angle_t max_pitch) { - A_Face(self, self->tracer, max_turn); + A_Face(self, self->tracer, max_turn, max_pitch); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_ANGLE(max_turn, 0); + ACTION_PARAM_ANGLE(max_pitch, 1); - A_FaceTarget(self, max_turn); + A_FaceTarget(self, max_turn, max_pitch); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_ANGLE(max_turn, 0); + ACTION_PARAM_ANGLE(max_pitch, 1); - A_FaceMaster(self, max_turn); + A_FaceMaster(self, max_turn, max_pitch); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_ANGLE(max_turn, 0); + ACTION_PARAM_ANGLE(max_pitch, 1); - A_FaceTracer(self, max_turn); + A_FaceTracer(self, max_turn, max_pitch); } //=========================================================================== diff --git a/src/p_enemy.h b/src/p_enemy.h index 343ba27e94..ff40c7003b 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -72,7 +72,7 @@ DECLARE_ACTION(A_FreezeDeathChunks) DECLARE_ACTION(A_BossDeath) void A_Chase(AActor *self); -void A_FaceTarget (AActor *actor, angle_t max_turn = 0); +void A_FaceTarget (AActor *actor, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270); bool A_RaiseMobj (AActor *, fixed_t speed); bool A_SinkMobj (AActor *, fixed_t speed); diff --git a/src/tables.h b/src/tables.h index aeb2c6991d..929fabf808 100644 --- a/src/tables.h +++ b/src/tables.h @@ -109,5 +109,9 @@ inline double bam2rad(angle_t ang) { return double(ang >> 1) * (PI / ANGLE_90); } +inline angle_t rad2bam(double ang) +{ + return angle_t(ang * (double(1<<30) / PI)) << 1; +} #endif // __TABLES_H__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 7e7a591e1a..eb27583ab3 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -69,9 +69,9 @@ 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(float max_turn = 0); - action native A_FaceTracer(float max_turn = 0); - action native A_FaceMaster(float max_turn = 0); + action native A_FaceTarget(float max_turn = 0, float max_pitch = 270); + action native A_FaceTracer(float max_turn = 0, float max_pitch = 270); + action native A_FaceMaster(float max_turn = 0, float max_pitch = 270); action native A_PosAttack(); action native A_Scream(); action native A_SPosAttack();