namespace BP
{
	int lastInstanceID; //Serialize
	int instanceIDResult;
	abstract class ScriptActor : ScriptObject
	{
		kActor@ self;
		int instanceID; //Serialize
		bool hasTicked;
		bool hasDeserialized;
		
		//------------------------------------------------------------------------------------------------------------------------
		ScriptActor(kActor@ actor)
		{
			@self = actor;
			
			lastInstanceID += (lastInstanceID == -1) ? 2 : 1;
			instanceID = lastInstanceID;
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnSpawn() final
		{
			BP_OnSpawn();
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnBeginLevel() final
		{
			BP_OnBeginLevel();
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnLevelLoad(kDictMem@ pDict) final
		{
			BP_OnLevelLoad(@pDict);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnSerialize(kDict& out dict) final
		{
			SERIALIZE_INT(instanceID);
			BP_OnSerialize(dict);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnDeserialize(kDict& in dict) final
		{
			DESERIALIZE_INT(instanceID);
			BP_OnDeserialize(dict);
			hasDeserialized = true;
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnTrigger(kActor@ pInstigator, const int msg) final
		{
			switch (self.TriggerMessageID())
			{
				case TRIGGER_MSG_INSTANCE_ID:
				{
					instanceIDResult = instanceID;
					break;
				}
				case TRIGGER_MSG_GET_SCRIPT:
				{
					@BP::Trigger::scriptResult = @this;
					break;
				}
			}

			BP_OnTrigger(@pInstigator, msg);
			BP::Trigger::OnPost();
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnTick() final
		{
			if (!hasTicked)
			{
				if (self.GameTicks() == 0)
				{
					BP_OnStart();
				}
				if (hasDeserialized)
				{
					BP_OnDeserializeStart();
				}
				hasTicked = true;
			}
			
			BP_OnTick();
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnEndLevel(void) final
		{
			BP_OnEndLevel();
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnPreDamage(kDamageInfo& in dmgInfo) final
		{
			BP_OnPreDamage(dmgInfo);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnDamage(kDamageInfo& in dmgInfo) final
		{
			BP_OnDamage(dmgInfo);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnDeath(kDamageInfo& in dmgInfo) final
		{
			BP_OnDeath(dmgInfo);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnTouch(kActor@ pInstigator) final
		{
			BP_OnTouch(@pInstigator);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void OnCollide(kActor@ pCollider) final
		{
			BP_OnCollide(@pCollider);
		}
		//------------------------------------------------------------------------------------------------------------------------
		private void UserEvent(const float x, const float y, const float z, const float f1, const float f2, const float f3, const float f4) final
		{
			//DebugLog("BP_UserEvent - x: " + x + " y: " + y + " z: " + z + " f1: " + f1 + " f2: " + f2 + " f3: " + f3 + " f4: " + f4);
			BP_UserEvent(x, y, z, f1, f2, f3, f4);
		}
		//------------------------------------------------------------------------------------------------------------------------
		void BP_OnSpawn() {}
		void BP_OnBeginLevel() {}
		void BP_OnEndLevel() {}
		void BP_OnLevelLoad(kDictMem@ pDict) {}
		void BP_OnSerialize(kDict dict) {}
		void BP_OnDeserialize(kDict& in dict) {}
		void BP_OnTrigger(kActor@ pInstigator, const int msg) {}
		void BP_OnTick() {}
		void BP_OnStart() {} //called once before tick and never again even after loading a save game
		void BP_OnDeserializeStart() {} //called once before tick after loading a save game
		void BP_OnPreDamage(kDamageInfo& in dmgInfo) {}
		void BP_OnDamage(kDamageInfo& in dmgInfo) {}
		void BP_OnDeath(kDamageInfo& in dmgInfo) {}
		void BP_OnTouch(kActor@ pInstigator) {}
		void BP_OnCollide(kActor@ pCollider) {}
		void BP_UserEvent(const float x, const float y, const float z, const float f1, const float f2, const float f3, const float f4) {}
		//------------------------------------------------------------------------------------------------------------------------
	};
}
