diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 85c5fb4bc..15206dabd 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -448,7 +448,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) NextToThink = node->NextThinker; if (node->ObjectFlags & OF_JustSpawned) { - node->ObjectFlags &= ~OF_JustSpawned; + // Leave OF_JustSpawn set until after Tick() so the ticker can check it. if (dest != NULL) { // Move thinker from this list to the destination list node->Remove(); @@ -463,7 +463,8 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) if (!(node->ObjectFlags & OF_EuthanizeMe)) { // Only tick thinkers not scheduled for destruction - node->Tick (); + node->Tick(); + node->ObjectFlags &= ~OF_JustSpawned; GC::CheckGC(); } node = NextToThink; diff --git a/src/info.h b/src/info.h index 87e623814..24bbb5fea 100644 --- a/src/info.h +++ b/src/info.h @@ -75,6 +75,7 @@ struct FState BYTE Fullbright:1; // State is fullbright BYTE SameFrame:1; // Ignore Frame (except when spawning actor) BYTE Fast:1; + BYTE NoDelay:1; // Spawn states executes its action normally int ParameterIndex; inline int GetFrame() const @@ -109,6 +110,10 @@ struct FState { return NextState; } + inline bool GetNoDelay() const + { + return NoDelay; + } inline void SetFrame(BYTE frame) { Frame = frame - 'A'; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 4a00a40b6..3d8424adc 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3496,22 +3496,35 @@ void AActor::Tick () } // cycle through states, calling action functions at transitions + assert (state != NULL); + if (ObjectFlags & OF_JustSpawned && state->GetNoDelay()) + { + // For immediately spawned objects with the NoDelay flag set for their + // Spawn state, explicitly set the current state so that it calls its + // action and chains 0-tic states. + int starttics = tics; + SetState(state); + // If the initial state had a duration of 0 tics, let the next state run + // normally. Otherwise, increment tics by 1 so that we don't double up ticks. + if (starttics > 0 && tics >= 0) + { + tics++; + } + } if (tics != -1) { // [RH] Use tics <= 0 instead of == 0 so that spawnstates // of 0 tics work as expected. if (tics <= 0) { - assert (state != NULL); if (state == NULL) { Destroy(); return; } - if (!SetState (state->GetNextState())) + if (!SetState(state->GetNextState())) return; // freed itself } - tics--; } else @@ -3983,13 +3996,6 @@ void AActor::PostBeginPlay () Renderer->StateChanged(this); } PrevAngle = angle; - - // [BL] Run zero-delay spawn states now so that we don't create a tic later - if(tics == 0 && state) - { - if (!SetState (state->GetNextState())) - return; // freed itself - } } void AActor::MarkPrecacheSounds() const diff --git a/src/p_states.cpp b/src/p_states.cpp index aeff2f5b6..cfe455716 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -334,8 +334,8 @@ FStateDefine *FStateDefinitions::FindStateLabelInList(TArray & lis if (create) { FStateDefine def; - def.Label=name; - def.State=NULL; + def.Label = name; + def.State = NULL; def.DefineFlags = SDF_NEXT; return &list[list.Push(def)]; } @@ -351,12 +351,11 @@ FStateDefine *FStateDefinitions::FindStateLabelInList(TArray & lis FStateDefine * FStateDefinitions::FindStateAddress(const char *name) { - FStateDefine * statedef=NULL; - + FStateDefine *statedef = NULL; TArray &namelist = MakeStateNameList(name); + TArray *statelist = &StateLabels; - TArray * statelist = &StateLabels; - for(unsigned i=0;iChildren; @@ -379,7 +378,7 @@ void FStateDefinitions::SetStateLabel (const char *statename, FState *state, BYT //========================================================================== // -// Adds a new state to the curremt list +// Adds a new state to the current list // //========================================================================== @@ -393,6 +392,24 @@ void FStateDefinitions::AddStateLabel (const char *statename) lastlabel = index; } +//========================================================================== +// +// Returns the index a state label points to. May only be called before +// installing states. +// +//========================================================================== + +int FStateDefinitions::GetStateLabelIndex (FName statename) +{ + FStateDefine *std = FindStateLabelInList(StateLabels, statename, false); + if (std == NULL) + { + return -1; + } + assert((size_t)std->State <= StateArray.Size() + 1); + return (int)((ptrdiff_t)std->State - 1); +} + //========================================================================== // // Finds the state associated with the given name @@ -863,6 +880,9 @@ bool FStateDefinitions::AddStates(FState *state, const char *framechars) state->Frame = frame; state->SameFrame = noframe; StateArray.Push(*state); + + // NODELAY flag is not carried past the first state + state->NoDelay = false; } laststate = &StateArray[StateArray.Size() - 1]; laststatebeforelabel = laststate; diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index d1519a260..e39d12ab0 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -91,6 +91,7 @@ public: void SetStateLabel (const char * statename, FState * state, BYTE defflags = SDF_STATE); void AddStateLabel (const char * statename); + int GetStateLabelIndex (FName statename); void InstallStates(FActorInfo *info, AActor *defaults); int FinishStates (FActorInfo *actor, AActor *defaults); diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 5c2d81602..1d643e33c 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -275,6 +275,18 @@ do_stop: state.Fast = true; continue; } + if (sc.Compare("NODELAY")) + { + if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount()) + { + state.NoDelay = true; + } + else + { + sc.ScriptMessage("NODELAY may only be used immediately after Spawn:"); + } + continue; + } if (sc.Compare("OFFSET")) { // specify a weapon offset @@ -338,8 +350,7 @@ do_stop: int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class); int paramstart = paramindex; bool varargs = params[numparams - 1] == '+'; - int varargcount=0; - + int varargcount = 0; if (varargs) {