From e27bf3816568d1a42926e3a67a520eace0834b7b Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 23 Jan 2025 18:45:50 -0500 Subject: [PATCH] Added behavior iterator for Actors Renamed Readded to Reinitialize. --- src/playsim/p_mobj.cpp | 2 +- src/scripting/vmiterators.cpp | 89 +++++++++++++++++++++++++++ wadsrc/static/zscript/actors/actor.zs | 10 ++- 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 603d5958ac..82f7a181ed 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -527,7 +527,7 @@ DObject* AActor::AddBehavior(PClass& type) } else { - IFOVERRIDENVIRTUALPTRNAME(b, NAME_Behavior, Readded) + IFOVERRIDENVIRTUALPTRNAME(b, NAME_Behavior, Reinitialize) { VMValue params[] = { b }; VMCall(func, params, 1, nullptr, 0); diff --git a/src/scripting/vmiterators.cpp b/src/scripting/vmiterators.cpp index 32d1ca1f87..1b6eae509e 100644 --- a/src/scripting/vmiterators.cpp +++ b/src/scripting/vmiterators.cpp @@ -388,6 +388,95 @@ DEFINE_ACTION_FUNCTION_NATIVE(DActorIterator, Reinit, ReinitActI) return 0; } +//=========================================================================== +// +// Behavior iterator. This can be created in two ways; +// -Across an Actor's behaviors +// -Across all behaviors of a given type +// +//=========================================================================== + +class DBehaviorIterator : public DObject +{ + DECLARE_ABSTRACT_CLASS(DBehaviorIterator, DObject) + size_t _index; + TArray _behaviors; + +public: + DBehaviorIterator(const AActor& mobj, FName type) + { + TMap::ConstIterator it = { mobj.Behaviors }; + TMap::ConstPair* pair = nullptr; + while (it.NextPair(pair)) + { + auto b = pair->Value; + if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) + continue; + + if (type == NAME_None || b->IsKindOf(type)) + _behaviors.Push(b); + } + + Reinit(); + } + + // TODO: List for all behaviors + + DObject* Next() + { + if (_index >= _behaviors.Size()) + return nullptr; + + return _behaviors[_index++]; + } + + void Reinit() { _index = 0u; } + + void OnDestroy() override + { + _behaviors.Reset(); + Super::OnDestroy(); + } +}; + +IMPLEMENT_CLASS(DBehaviorIterator, true, false); + +static DBehaviorIterator* CreateBehaviorItFromActor(AActor* mobj, PClass* type) +{ + return Create(*mobj, type == nullptr ? NAME_None : type->TypeName); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DBehaviorIterator, CreateFrom, CreateBehaviorItFromActor) +{ + PARAM_PROLOGUE; + PARAM_OBJECT_NOT_NULL(mobj, AActor); + PARAM_CLASS(type, DObject); + ACTION_RETURN_OBJECT(CreateBehaviorItFromActor(mobj, type)); +} + +static DObject* NextBehavior(DBehaviorIterator* self) +{ + return self->Next(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DBehaviorIterator, Next, NextBehavior) +{ + PARAM_SELF_PROLOGUE(DBehaviorIterator); + ACTION_RETURN_OBJECT(self->Next()); +} + +static void ReinitBehavior(DBehaviorIterator* self) +{ + self->Reinit(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DBehaviorIterator, Reinit, ReinitBehavior) +{ + PARAM_SELF_PROLOGUE(DBehaviorIterator); + self->Reinit(); + return 0; +} + DEFINE_FIELD_NAMED(DBlockLinesIterator, cres.line, curline); DEFINE_FIELD_NAMED(DBlockLinesIterator, cres.Position, position); DEFINE_FIELD_NAMED(DBlockLinesIterator, cres.portalflags, portalflags); diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 7861258fe1..ee20183e38 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -78,10 +78,18 @@ class Behavior play abstract readonly Actor Owner; virtual void Initialize() {} - virtual void Readded() {} + virtual void Reinitialize() {} virtual void Tick() {} } +class BehaviorIterator native abstract final +{ + native static BehaviorIterator CreateFrom(Actor mobj, class type = null); + + native Behavior Next(); + native void Reinit(); +} + class Actor : Thinker native { const DEFAULT_HEALTH = 1000;