diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 0fd23f73e..37ff5cfaf 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1790,7 +1790,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } else { - CALL_ACTION(A_Wander, self); + A_Wander(self); } } else @@ -1947,7 +1947,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) } else { - CALL_ACTION(A_Wander, self); + A_Wander(self); } } } @@ -2043,7 +2043,34 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ClearLastHeard) // A_Wander // //========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_Wander) +enum ChaseFlags +{ + CHF_FASTCHASE = 1, + CHF_NOPLAYACTIVE = 2, + CHF_NIGHTMAREFAST = 4, + CHF_RESURRECT = 8, + CHF_DONTMOVE = 16, + CHF_NORANDOMTURN = 32, + CHF_NODIRECTIONTURN = 64, + CHF_NOPOSTATTACKTURN = 128, + CHF_STOPIFBLOCKED = 256, +}; + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Wander) +{ + ACTION_PARAM_START(1); + ACTION_PARAM_INT(flags, 0); + + A_Wander(self, flags); +} + +// [MC] I had to move this out from within A_Wander in order to allow flags to +// pass into it. That meant replacing the CALL_ACTION(A_Wander) functions with +// just straight up defining A_Wander in order to compile. Looking around though, +// actors from the games themselves just do a straight A_Chase call itself so +// I saw no harm in it. + +void A_Wander(AActor *self, int flags) { // [RH] Strife probably clears this flag somewhere, but I couldn't find where. // This seems as good a place as any. @@ -2062,28 +2089,30 @@ DEFINE_ACTION_FUNCTION(AActor, A_Wander) } // turn towards movement direction if not there yet - if (self->movedir < DI_NODIR) + if (!(flags & CHF_NODIRECTIONTURN) && (self->movedir < DI_NODIR)) { - self->angle &= (angle_t)(7<<29); + self->angle &= (angle_t)(7 << 29); int delta = self->angle - (self->movedir << 29); if (delta > 0) { - self->angle -= ANG90/2; + self->angle -= ANG90 / 2; } else if (delta < 0) { - self->angle += ANG90/2; + self->angle += ANG90 / 2; } } - if (--self->movecount < 0 || !P_Move (self)) + if (self->movecount >= 0) + self->movecount--; + + if ((!(flags & CHF_NORANDOMTURN) && self->movecount < 0) || !P_Move(self)) { - P_RandomChaseDir (self); + P_RandomChaseDir(self); self->movecount += 5; } } - //========================================================================== // // A_Look2 @@ -2152,7 +2181,7 @@ nosee: //============================================================================= #define CLASS_BOSS_STRAFE_RANGE 64*10*FRACUNIT -void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove) +void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove, int flags) { int delta; @@ -2214,7 +2243,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi { A_FaceTarget(actor); } - else if (actor->movedir < 8) + else if (!(flags & CHF_NODIRECTIONTURN) && actor->movedir < 8) { actor->angle &= (angle_t)(7<<29); delta = actor->angle - (actor->movedir << 29); @@ -2286,7 +2315,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi //CALL_ACTION(A_Look, actor); if (actor->target == NULL) { - if (!dontmove) CALL_ACTION(A_Wander, actor); + if (!dontmove) A_Wander(actor); actor->flags &= ~MF_INCHASE; return; } @@ -2304,10 +2333,15 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi if (actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if (!actor->isFast() && !dontmove) + if (!actor->isFast() && !dontmove && !(flags & CHF_NOPOSTATTACKTURN) && !(flags & CHF_STOPIFBLOCKED)) { P_NewChaseDir (actor); } + //Because P_TryWalk would never be reached if the actor is stopped by a blocking object, + //need to make sure the movecount is reset, otherwise they will just keep attacking + //over and over again. + if (flags & CHF_STOPIFBLOCKED) + actor->movecount = pr_trywalk() & 15; actor->flags &= ~MF_INCHASE; return; } @@ -2465,6 +2499,8 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi if (actor->strafecount) actor->strafecount--; + bool movecheck = P_Move(actor); + // class bosses don't do this when strafing if ((!fastchase || !actor->FastChaseStrafeCount) && !dontmove) { @@ -2474,24 +2510,27 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi FTextureID oldFloor = actor->floorpic; // chase towards player - if (--actor->movecount < 0 || !P_Move (actor)) + if (actor->movecount >= 0) + actor->movecount--; + if (!(flags & CHF_STOPIFBLOCKED)) { - P_NewChaseDir (actor); + if ((!(flags & CHF_NORANDOMTURN) && (actor->movecount < 0)) || !movecheck) + P_NewChaseDir(actor); } // if the move was illegal, reset it // (copied from A_SerpentChase - it applies to everything with CANTLEAVEFLOORPIC!) if (actor->flags2&MF2_CANTLEAVEFLOORPIC && actor->floorpic != oldFloor ) { - if (P_TryMove (actor, oldX, oldY, false)) + if (!(flags & CHF_STOPIFBLOCKED) && P_TryMove(actor, oldX, oldY, false)) { if (nomonsterinterpolation) { actor->PrevX = oldX; actor->PrevY = oldY; } + P_NewChaseDir(actor); } - P_NewChaseDir (actor); } } else if (dontmove && actor->movecount > 0) actor->movecount--; @@ -2652,15 +2691,6 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) // //========================================================================== -enum ChaseFlags -{ - CHF_FASTCHASE = 1, - CHF_NOPLAYACTIVE = 2, - CHF_NIGHTMAREFAST = 4, - CHF_RESURRECT = 8, - CHF_DONTMOVE = 16, -}; - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) { ACTION_PARAM_START(3); @@ -2673,23 +2703,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) if (flags & CHF_RESURRECT && P_CheckForResurrection(self, false)) return; A_DoChase(self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE), - !!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE)); + !!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE), flags); } else // this is the old default A_Chase { - A_DoChase (self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false); + A_DoChase (self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, flags); } } DEFINE_ACTION_FUNCTION(AActor, A_FastChase) { - A_DoChase (self, true, self->MeleeState, self->MissileState, true, true, false); + A_DoChase (self, true, self->MeleeState, self->MissileState, true, true, false, 0); } DEFINE_ACTION_FUNCTION(AActor, A_VileChase) { if (!P_CheckForResurrection(self, true)) - A_DoChase (self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false); + A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase) @@ -2703,13 +2733,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase) // Now that A_Chase can handle state label parameters, this function has become rather useless... A_DoChase(self, false, domelee ? self->MeleeState:NULL, domissile ? self->MissileState:NULL, - playactive, nightmarefast, false); + playactive, nightmarefast, false, 0); } // for internal use void A_Chase(AActor *self) { - A_DoChase (self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false); + A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } //============================================================================= diff --git a/src/p_enemy.h b/src/p_enemy.h index 799b4c0ff..15ac335e0 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -61,7 +61,6 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdis void A_Unblock(AActor *self, bool drop); DECLARE_ACTION(A_Look) -DECLARE_ACTION(A_Wander) DECLARE_ACTION(A_BossDeath) DECLARE_ACTION(A_Pain) DECLARE_ACTION(A_MonsterRail) @@ -72,6 +71,7 @@ DECLARE_ACTION(A_FreezeDeathChunks) DECLARE_ACTION(A_BossDeath) void A_Chase(AActor *self); +void A_Wander(AActor *self, int flags = 0); 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); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index e435a18bf..c1ddfaa55 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -176,7 +176,7 @@ ACTOR Actor native //: Thinker action native A_SkullPop(class skulltype = "BloodySkull"); action native A_CheckPlayerDone(); - action native A_Wander(); + action native A_Wander(int flags = 0); action native A_Look2(); action native A_TossGib(); action native A_SentinelBob(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index cecac6f0b..fa50c55ec 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -79,11 +79,20 @@ const int SXF_ISMASTER = 1 << 27; const int SXF_ISTRACER = 1 << 28; // Flags for A_Chase -const int CHF_FASTCHASE = 1; -const int CHF_NOPLAYACTIVE = 2; -const int CHF_NIGHTMAREFAST = 4; -const int CHF_RESURRECT = 8; -const int CHF_DONTMOVE = 16; +enum +{ + CHF_FASTCHASE = 1, + CHF_NOPLAYACTIVE = 2, + CHF_NIGHTMAREFAST = 4, + CHF_RESURRECT = 8, + CHF_DONTMOVE = 16, + CHF_NORANDOMTURN = 32, + CHF_NODIRECTIONTURN = 64, + CHF_NOPOSTATTACKTURN = 128, + CHF_STOPIFBLOCKED = 256, + + CHF_DONTTURN = CHF_NODIRECTIONTURN | CHF_NOPOSTATTACKTURN | CHF_STOPIFBLOCKED +}; // Flags for A_LookEx const int LOF_NOSIGHTCHECK = 1;