diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index c3cba6433..e71b701ea 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1792,7 +1792,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } else { - CALL_ACTION(A_Wander, self); + A_Wander(self); } } else @@ -1952,7 +1952,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) } else { - CALL_ACTION(A_Wander, self); + A_Wander(self); } } } @@ -2051,50 +2051,77 @@ DEFINE_ACTION_FUNCTION(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) { PARAM_ACTION_PROLOGUE; + PARAM_INT_OPT(flags) { flags = 0; } + A_Wander(self, flags); + return 0; +} +// [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. self->flags4 &= ~MF4_INCOMBAT; if (self->flags5 & MF5_INCONVERSATION) - return 0; + return; if (self->flags4 & MF4_STANDSTILL) - return 0; + return; if (self->reactiontime != 0) { self->reactiontime--; - return 0; + return; } // 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; } - return 0; + return; } - //========================================================================== // // A_Look2 @@ -2165,8 +2192,8 @@ nosee: // //============================================================================= #define CLASS_BOSS_STRAFE_RANGE 64*10*FRACUNIT - -void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove) + +void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove, int flags) { int delta; @@ -2228,7 +2255,7 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele { 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); @@ -2300,7 +2327,7 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele //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; } @@ -2318,10 +2345,15 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele 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; } @@ -2478,7 +2510,7 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele if (actor->strafecount) actor->strafecount--; - + // class bosses don't do this when strafing if ((!fastchase || !actor->FastChaseStrafeCount) && !dontmove) { @@ -2488,24 +2520,23 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele FTextureID oldFloor = actor->floorpic; // chase towards player - if (--actor->movecount < 0 || !P_Move (actor)) + if ((--actor->movecount < 0 && !(flags & CHF_NORANDOMTURN)) || (!P_Move(actor) && !(flags & CHF_STOPIFBLOCKED))) { - P_NewChaseDir (actor); + 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--; @@ -2666,15 +2697,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) { PARAM_ACTION_PROLOGUE; @@ -2686,22 +2708,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) { if ((flags & CHF_RESURRECT) && P_CheckForResurrection(self, false)) return 0; - + A_DoChase(stack, 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(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false); + A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, flags); } return 0; } DEFINE_ACTION_FUNCTION(AActor, A_FastChase) -{ +{ PARAM_ACTION_PROLOGUE; - A_DoChase(stack, self, true, self->MeleeState, self->MissileState, true, true, false); - return 0; + A_DoChase(stack, self, true, self->MeleeState, self->MissileState, true, true, false, 0); + return 0; } DEFINE_ACTION_FUNCTION(AActor, A_VileChase) @@ -2709,9 +2731,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileChase) PARAM_ACTION_PROLOGUE; if (!P_CheckForResurrection(self, true)) { - A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false); + A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } - return 0; + return 0; } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase) @@ -2725,14 +2747,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase) // Now that A_Chase can handle state label parameters, this function has become rather useless... A_DoChase(stack, self, false, domelee ? self->MeleeState : NULL, domissile ? self->MissileState : NULL, - playactive, nightmarefast, false); + playactive, nightmarefast, false, 0); return 0; } // for internal use void A_Chase(VMFrameStack *stack, AActor *self) -{ - A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false); +{ + A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } //============================================================================= diff --git a/src/p_enemy.h b/src/p_enemy.h index 2b6b7fe5e..8b78b1cac 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) @@ -70,10 +69,11 @@ DECLARE_ACTION(A_Scream) DECLARE_ACTION(A_FreezeDeath) DECLARE_ACTION(A_FreezeDeathChunks) void A_BossDeath(AActor *self); - + +void A_Wander(AActor *self, int flags = 0); void A_Chase(VMFrameStack *stack, AActor *self); void A_FaceTarget(AActor *actor); -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, fixed_t z_add = 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, fixed_t z_add = 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 1f7efd895..2d46b7c8d 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -144,7 +144,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 1fd824989..e5733e033 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_NORANDOMTURN | CHF_NOPOSTATTACKTURN | CHF_STOPIFBLOCKED +}; // Flags for A_LookEx const int LOF_NOSIGHTCHECK = 1;