diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index ef6136fdc..17af5c26d 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2721,7 +2721,14 @@ void A_Chase(AActor *self) // A_FaceTracer // //============================================================================= -void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch) +enum FAF_Flags +{ + FAF_BOTTOM = 1, + FAF_MIDDLE = 2, + FAF_TOP = 4, + FAF_NODISTFACTOR = 8, +}; +void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch, angle_t ang_offset, angle_t pitch_offset, int flags) { if (!other) return; @@ -2744,28 +2751,28 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch) { if (self->angle - other_angle < ANGLE_180) { - self->angle -= max_turn; + self->angle -= max_turn + ang_offset; } else { - self->angle += max_turn; + self->angle += max_turn + ang_offset; } } else { if (other_angle - self->angle < ANGLE_180) { - self->angle += max_turn; + self->angle += max_turn + ang_offset; } else { - self->angle -= max_turn; + self->angle -= max_turn + ang_offset; } } } else { - self->angle = other_angle; + self->angle = other_angle + ang_offset; } // [DH] Now set pitch. In order to maintain compatibility, this can be @@ -2776,20 +2783,33 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch) // result is only used in a ratio. double dist_x = other->x - self->x; double dist_y = other->y - self->y; + // Positioning ala missile spawning, 32 units above foot level fixed_t source_z = self->z + 32*FRACUNIT + self->GetBobOffset(); fixed_t target_z = other->z + 32*FRACUNIT + other->GetBobOffset(); + // If the target z is above the target's head, reposition to the middle of - // its body. + // its body. if (target_z >= other->z + other->height) { - target_z = other->z + other->height / 2; + target_z = other->z + (other->height / 2); } + + //Note there is no +32*FRACUNIT on purpose. This is for customization sake. + //If one doesn't want this behavior, just don't use FAF_BOTTOM. + if (flags & FAF_BOTTOM) + target_z = other->z + other->GetBobOffset(); + if (flags & FAF_MIDDLE) + target_z = other->z + (other->height / 2) + other->GetBobOffset(); + if (flags & FAF_TOP) + target_z = other->z + (other->height) + other->GetBobOffset(); + if (!flags & FAF_NODISTFACTOR) + target_z += pitch_offset; + double dist_z = target_z - source_z; double dist = sqrt(dist_x*dist_x + dist_y*dist_y + dist_z*dist_z); - int other_pitch = (int)rad2bam(asin(dist_z / dist)); - + if (max_pitch != 0) { if (self->pitch > other_pitch) @@ -2807,7 +2827,11 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch) { self->pitch = other_pitch; } + if (flags & FAF_NODISTFACTOR) + self->pitch += pitch_offset; } + + // 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) ) @@ -2816,46 +2840,55 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch) } } -void A_FaceTarget (AActor *self, angle_t max_turn, angle_t max_pitch) +void A_FaceTarget(AActor *self, angle_t max_turn, angle_t max_pitch, angle_t ang_offset, angle_t pitch_offset, int flags) { - A_Face(self, self->target, max_turn, max_pitch); + A_Face(self, self->target, max_turn, max_pitch, ang_offset, pitch_offset, flags); } -void A_FaceMaster (AActor *self, angle_t max_turn, angle_t max_pitch) +void A_FaceMaster(AActor *self, angle_t max_turn, angle_t max_pitch, angle_t ang_offset, angle_t pitch_offset, int flags) { - A_Face(self, self->master, max_turn, max_pitch); + A_Face(self, self->master, max_turn, max_pitch, ang_offset, pitch_offset, flags); } -void A_FaceTracer (AActor *self, angle_t max_turn, angle_t max_pitch) +void A_FaceTracer(AActor *self, angle_t max_turn, angle_t max_pitch, angle_t ang_offset, angle_t pitch_offset, int flags) { - A_Face(self, self->tracer, max_turn, max_pitch); + A_Face(self, self->tracer, max_turn, max_pitch, ang_offset, pitch_offset, flags); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(5); ACTION_PARAM_ANGLE(max_turn, 0); ACTION_PARAM_ANGLE(max_pitch, 1); + ACTION_PARAM_ANGLE(ang_offset, 2); + ACTION_PARAM_ANGLE(pitch_offset, 3); + ACTION_PARAM_INT(flags, 4); - A_FaceTarget(self, max_turn, max_pitch); + A_FaceTarget(self, max_turn, max_pitch, ang_offset, pitch_offset, flags); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(5); ACTION_PARAM_ANGLE(max_turn, 0); ACTION_PARAM_ANGLE(max_pitch, 1); + ACTION_PARAM_ANGLE(ang_offset, 2); + ACTION_PARAM_ANGLE(pitch_offset, 3); + ACTION_PARAM_INT(flags, 4); - A_FaceMaster(self, max_turn, max_pitch); + A_FaceMaster(self, max_turn, max_pitch, ang_offset, pitch_offset, flags); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(5); ACTION_PARAM_ANGLE(max_turn, 0); ACTION_PARAM_ANGLE(max_pitch, 1); + ACTION_PARAM_ANGLE(ang_offset, 2); + ACTION_PARAM_ANGLE(pitch_offset, 3); + ACTION_PARAM_INT(flags, 4); - A_FaceTracer(self, max_turn, max_pitch); + A_FaceTracer(self, max_turn, max_pitch, ang_offset, pitch_offset, flags); } //=========================================================================== diff --git a/src/p_enemy.h b/src/p_enemy.h index f5cc387dd..799b4c0ff 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -72,8 +72,8 @@ DECLARE_ACTION(A_FreezeDeathChunks) DECLARE_ACTION(A_BossDeath) void A_Chase(AActor *self); -void A_FaceTarget(AActor *actor, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270); -void A_Face(AActor *self, AActor *other, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270); +void A_FaceTarget(AActor *actor, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270, angle_t ang_offset = 0, angle_t pitch_offset = 0, int flags = 0); +void A_Face(AActor *self, AActor *other, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270, angle_t ang_offset = 0, angle_t pitch_offset = 0, int flags = 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 f0e68d9a5..c03c86596 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -82,9 +82,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, 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_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0); + action native A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0); + action native A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0); action native A_PosAttack(); action native A_Scream(); action native A_SPosAttack(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 074953afe..b4bb4c532 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -447,6 +447,15 @@ enum FTF_CLAMP = 1 << 1, }; +// Flags for A_Face* +enum +{ + FAF_BOTTOM = 1, + FAF_MIDDLE = 2, + FAF_TOP = 4, + FAF_NODISTFACTOR = 8, +}; + // This is only here to provide one global variable for testing. native int testglobalvar;