From f22aaca74dd66f90e125ed363ae15659c2f59461 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Tue, 4 Dec 2018 18:21:48 +0100
Subject: [PATCH] - scriptified ASpecialSpot.

This only had two simple native methods so the class is not fully scripted.
---
 src/g_shared/a_specialspot.cpp               | 52 +++++---------------
 src/g_shared/a_specialspot.h                 | 21 ++------
 src/p_actionfunctions.cpp                    |  2 +-
 src/scripting/vmthunks.cpp                   | 35 ++++++++++---
 wadsrc/static/zscript/base.txt               |  9 ----
 wadsrc/static/zscript/shared/specialspot.txt | 34 ++++++++++++-
 6 files changed, 80 insertions(+), 73 deletions(-)

diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp
index 102fc8ba4..310911d5f 100644
--- a/src/g_shared/a_specialspot.cpp
+++ b/src/g_shared/a_specialspot.cpp
@@ -45,7 +45,6 @@
 static FRandom pr_spot ("SpecialSpot");
 
 IMPLEMENT_CLASS(DSpotState, false, false)
-IMPLEMENT_CLASS(ASpecialSpot, false, false)
 TObjPtr<DSpotState*> DSpotState::SpotState;
 
 //----------------------------------------------------------------------------
@@ -57,7 +56,7 @@ TObjPtr<DSpotState*> DSpotState::SpotState;
 struct FSpotList
 {
 	PClassActor *Type;
-	TArray<ASpecialSpot*> Spots;
+	TArray<AActor*> Spots;
 	unsigned Index;
 	int SkipCount;
 	int numcalls;
@@ -80,7 +79,7 @@ struct FSpotList
 	//
 	//----------------------------------------------------------------------------
 
-	bool Add(ASpecialSpot *newspot)
+	bool Add(AActor *newspot)
 	{
 		for(unsigned i = 0; i < Spots.Size(); i++)
 		{
@@ -96,7 +95,7 @@ struct FSpotList
 	//
 	//----------------------------------------------------------------------------
 
-	bool Remove(ASpecialSpot *spot)
+	bool Remove(AActor *spot)
 	{
 		for(unsigned i = 0; i < Spots.Size(); i++)
 		{
@@ -116,13 +115,13 @@ struct FSpotList
 	//
 	//----------------------------------------------------------------------------
 
-	ASpecialSpot *GetNextInList(int skipcounter)
+	AActor *GetNextInList(int skipcounter)
 	{
 		if (Spots.Size() > 0 && ++SkipCount > skipcounter)
 		{
 			SkipCount = 0;
 
-			ASpecialSpot *spot = Spots[Index];
+			AActor *spot = Spots[Index];
 			if (++Index >= Spots.Size()) Index = 0;
 			numcalls++;
 			return spot;
@@ -136,7 +135,7 @@ struct FSpotList
 	//
 	//----------------------------------------------------------------------------
 
-	ASpecialSpot *GetSpotWithMinMaxDistance(double x, double y, double mindist, double maxdist)
+	AActor *GetSpotWithMinMaxDistance(double x, double y, double mindist, double maxdist)
 	{
 		if (Spots.Size() == 0) return NULL;
 		int i = pr_spot() % Spots.Size();
@@ -163,7 +162,7 @@ struct FSpotList
 	//
 	//----------------------------------------------------------------------------
 
-	ASpecialSpot *GetRandomSpot(bool onlyfirst)
+	AActor *GetRandomSpot(bool onlyfirst)
 	{
 		if (Spots.Size() && !numcalls)
 		{
@@ -222,8 +221,7 @@ DSpotState::DSpotState ()
 
 void DSpotState::OnDestroy ()
 {
-	SpotLists.Clear();
-	SpotLists.ShrinkToFit();
+	SpotLists.Reset();
 
 	SpotState = NULL;
 	Super::OnDestroy();
@@ -273,7 +271,7 @@ FSpotList *DSpotState::FindSpotList(PClassActor *type)
 //
 //----------------------------------------------------------------------------
 
-bool DSpotState::AddSpot(ASpecialSpot *spot)
+bool DSpotState::AddSpot(AActor *spot)
 {
 	FSpotList *list = FindSpotList(spot->GetClass());
 	if (list != NULL) return list->Add(spot);
@@ -286,7 +284,7 @@ bool DSpotState::AddSpot(ASpecialSpot *spot)
 //
 //----------------------------------------------------------------------------
 
-bool DSpotState::RemoveSpot(ASpecialSpot *spot)
+bool DSpotState::RemoveSpot(AActor *spot)
 {
 	FSpotList *list = FindSpotList(spot->GetClass());
 	if (list != NULL) return list->Remove(spot);
@@ -311,7 +309,7 @@ void DSpotState::Serialize(FSerializer &arc)
 //
 //----------------------------------------------------------------------------
 
-ASpecialSpot *DSpotState::GetNextInList(PClassActor *type, int skipcounter)
+AActor *DSpotState::GetNextInList(PClassActor *type, int skipcounter)
 {
 	FSpotList *list = FindSpotList(type);
 	if (list != NULL) return list->GetNextInList(skipcounter);
@@ -324,7 +322,7 @@ ASpecialSpot *DSpotState::GetNextInList(PClassActor *type, int skipcounter)
 //
 //----------------------------------------------------------------------------
 
-ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(PClassActor *type, double x, double y, double mindist, double maxdist)
+AActor *DSpotState::GetSpotWithMinMaxDistance(PClassActor *type, double x, double y, double mindist, double maxdist)
 {
 	FSpotList *list = FindSpotList(type);
 	if (list != NULL) return list->GetSpotWithMinMaxDistance(x, y, mindist, maxdist);
@@ -337,34 +335,10 @@ ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(PClassActor *type, double x,
 //
 //----------------------------------------------------------------------------
 
-ASpecialSpot *DSpotState::GetRandomSpot(PClassActor *type, bool onlyonce)
+AActor *DSpotState::GetRandomSpot(PClassActor *type, bool onlyonce)
 {
 	FSpotList *list = FindSpotList(type);
 	if (list != NULL) return list->GetRandomSpot(onlyonce);
 	return NULL;
 }
 
-//----------------------------------------------------------------------------
-//
-//
-//
-//----------------------------------------------------------------------------
-
-void ASpecialSpot::BeginPlay()
-{
-	DSpotState *state = DSpotState::GetSpotState();
-	if (state != NULL) state->AddSpot(this);
-}
-
-//----------------------------------------------------------------------------
-//
-//
-//
-//----------------------------------------------------------------------------
-
-void ASpecialSpot::OnDestroy()
-{
-	DSpotState *state = DSpotState::GetSpotState(false);
-	if (state != NULL) state->RemoveSpot(this);
-	Super::OnDestroy();
-}
diff --git a/src/g_shared/a_specialspot.h b/src/g_shared/a_specialspot.h
index 4bfef3b63..fee1a804b 100644
--- a/src/g_shared/a_specialspot.h
+++ b/src/g_shared/a_specialspot.h
@@ -4,17 +4,6 @@
 #include "actor.h"
 #include "tarray.h"
 
-class ASpecialSpot : public AActor
-{
-	DECLARE_CLASS (ASpecialSpot, AActor)
-
-public:
-
-	void BeginPlay();
-	void OnDestroy() override;
-};
-
-
 struct FSpotList;
 
 
@@ -32,12 +21,12 @@ public:
 	void Tick ();
 	static DSpotState *GetSpotState(bool create = true);
 	FSpotList *FindSpotList(PClassActor *type);
-	bool AddSpot(ASpecialSpot *spot);
-	bool RemoveSpot(ASpecialSpot *spot);
+	bool AddSpot(AActor *spot);
+	bool RemoveSpot(AActor *spot);
 	void Serialize(FSerializer &arc);
-	ASpecialSpot *GetNextInList(PClassActor *type, int skipcounter);
-	ASpecialSpot *GetSpotWithMinMaxDistance(PClassActor *type, double x, double y, double mindist, double maxdist);
-	ASpecialSpot *GetRandomSpot(PClassActor *type, bool onlyonce = false);
+	AActor *GetNextInList(PClassActor *type, int skipcounter);
+	AActor *GetSpotWithMinMaxDistance(PClassActor *type, double x, double y, double mindist, double maxdist);
+	AActor *GetRandomSpot(PClassActor *type, bool onlyonce = false);
 };
 
 
diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp
index 55b57163e..03c9fc834 100644
--- a/src/p_actionfunctions.cpp
+++ b/src/p_actionfunctions.cpp
@@ -3364,7 +3364,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
 {
 	PARAM_ACTION_PROLOGUE(AActor);
 	PARAM_STATE_ACTION	(teleport_state)			
-	PARAM_CLASS		(target_type, ASpecialSpot)	
+	PARAM_CLASS		(target_type, AActor)	
 	PARAM_CLASS		(fog_type, AActor)			
 	PARAM_INT		(flags)						
 	PARAM_FLOAT		(mindist)					
diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp
index 023a9057a..9114b42ed 100644
--- a/src/scripting/vmthunks.cpp
+++ b/src/scripting/vmthunks.cpp
@@ -1885,15 +1885,38 @@ DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyType, P_GetKeyType)
 //
 //=====================================================================================
 
-static DSpotState *GetSpotState()
-{
-	return DSpotState::GetSpotState();
-}
 
-DEFINE_ACTION_FUNCTION_NATIVE(DSpotState, GetSpotState, GetSpotState)
+DEFINE_ACTION_FUNCTION_NATIVE(DSpotState, GetSpotState, DSpotState::GetSpotState)
 {
 	PARAM_PROLOGUE;
-	ACTION_RETURN_OBJECT(DSpotState::GetSpotState());
+	PARAM_BOOL(create);
+	ACTION_RETURN_OBJECT(DSpotState::GetSpotState(create));
+}
+
+static void AddSpot(DSpotState *state, AActor *spot)
+{
+	state->AddSpot(spot);
+}
+
+DEFINE_ACTION_FUNCTION_NATIVE(DSpotState, AddSpot, AddSpot)
+{
+	PARAM_SELF_PROLOGUE(DSpotState);
+	PARAM_OBJECT(spot, AActor);
+	self->AddSpot(spot);
+	return 0;
+}
+
+static void RemoveSpot(DSpotState *state, AActor *spot)
+{
+	state->RemoveSpot(spot);
+}
+
+DEFINE_ACTION_FUNCTION_NATIVE(DSpotState, RemoveSpot, RemoveSpot)
+{
+	PARAM_SELF_PROLOGUE(DSpotState);
+	PARAM_OBJECT(spot, AActor);
+	self->RemoveSpot(spot);
+	return 0;
 }
 
 static AActor *GetNextInList(DSpotState *self, PClassActor *type, int skipcounter)
diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt
index 9e37c0632..9b962367c 100644
--- a/wadsrc/static/zscript/base.txt
+++ b/wadsrc/static/zscript/base.txt
@@ -592,15 +592,6 @@ struct DropItem native
 	native readonly int Amount;
 }
 
-class SpotState : Object native
-{
-	native static SpotState GetSpotState();
-	native SpecialSpot GetNextInList(class<Actor> type, int skipcounter);
-	native SpecialSpot GetSpotWithMinMaxDistance(Class<Actor> type, double x, double y, double mindist, double maxdist);
-	native SpecialSpot GetRandomSpot(class<Actor> type, bool onlyonce);
-	
-}
-
 struct LevelLocals native
 {
 	enum EUDMF
diff --git a/wadsrc/static/zscript/shared/specialspot.txt b/wadsrc/static/zscript/shared/specialspot.txt
index baacd286f..e62e27e7a 100644
--- a/wadsrc/static/zscript/shared/specialspot.txt
+++ b/wadsrc/static/zscript/shared/specialspot.txt
@@ -1,6 +1,36 @@
-
-class SpecialSpot : Actor native
+class SpotState : Object native
 {
+	native static SpotState GetSpotState(bool create = true);
+	native SpecialSpot GetNextInList(class<Actor> type, int skipcounter);
+	native SpecialSpot GetSpotWithMinMaxDistance(Class<Actor> type, double x, double y, double mindist, double maxdist);
+	native SpecialSpot GetRandomSpot(class<Actor> type, bool onlyonce);
+	native void AddSpot(SpecialSpot spot);
+	native void RemoveSpot(SpecialSpot spot);
+	
+}
+
+class SpecialSpot : Actor
+{
+	override void BeginPlay()
+	{
+		let sstate = SpotState.GetSpotState();
+		if (sstate != NULL) sstate.AddSpot(self);
+		Super.BeginPlay();
+	}
+
+	//----------------------------------------------------------------------------
+	//
+	//
+	//
+	//----------------------------------------------------------------------------
+
+	override void OnDestroy()
+	{
+		let sstate = SpotState.GetSpotState(false);
+		if (sstate != NULL) sstate.RemoveSpot(self);
+		Super.OnDestroy();
+	}
+	
 	// Mace spawn spot ----------------------------------------------------------
 
 	// Every mace spawn spot will execute this action. The first one