diff --git a/src/dobject.h b/src/dobject.h index 783b8bb5b..e96b7d6c2 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -205,6 +205,7 @@ enum EObjectFlags OF_JustSpawned = 1 << 8, // Thinker was spawned this tic OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list + OF_StateChanged = 1 << 11, // Used by A_Jump* functions to feed back to SetState() }; template class TObjPtr; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 0dbbf93af..f0fcf9b46 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -482,7 +482,16 @@ bool AActor::SetState (FState *newstate, bool nofunction) { // Check whether the called action function resulted in destroying the actor if (ObjectFlags & OF_EuthanizeMe) + { return false; + } + if (ObjectFlags & OF_StateChanged) + { // The action was an A_Jump-style function that wants to change the next state. + ObjectFlags &= ~OF_StateChanged; + newstate = state; + tics = 0; // make sure we loop and set the new state properly + continue; + } } newstate = newstate->GetNextState(); } while (tics == 0); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index bd6b6f1e4..be9b47173 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -610,7 +610,15 @@ static void DoJump(AActor *self, AActor *stateowner, FState *callingstate, FStat } else if (callingstate == self->state) { - self->SetState(jumpto); + // Rather than using self->SetState(jumpto) to set the state, + // set the state directly. Since this function is only called by + // action functions, which are only called by SetState(), we + // know that somewhere above us in the stack, a SetState() + // call is waiting for us to return. We use the flag OF_StateChanged + // to cause it to bypass the normal next state mechanism and use + // the one we set here instead. + self->state = jumpto; + self->ObjectFlags |= OF_StateChanged; } else { // something went very wrong. This should never happen.