/*
* 自定义的 trigger_once 触发器 / Custom trigger_once entity
* 作者(Author): Ice Box
* Steam: https://steamcommunity.com/id/ibox666/
* 如需使用此脚本请联系作者 / If you need to use this script, please contact the author
*/

namespace TriggerOnceCustom
{

const int SF_START_OFF = 1 << 0;
const int SF_PASS_ACTIVATOR = 1 << 1;

class CTriggerOnceCustom : ScriptBaseEntity
{
	private bool m_bEnabled = true;
	private bool m_bHasTriggered = false;
	private float m_flDelay = 0.0;
	private string m_szKillTarget = "";
	private EHandle m_hActivator;

	bool KeyValue(const string& in szKey, const string& in szValue)
	{
		if(szKey == "delay")
		{
			m_flDelay = atof(szValue);
			if(m_flDelay < 0)
				m_flDelay = 0.0;
			return true;
		}
		else if(szKey == "killtarget")
		{
			m_szKillTarget = szValue;
			return true;
		}
		else
			return BaseClass.KeyValue(szKey, szValue);
	}

	void Spawn()
	{
		self.pev.movetype = MOVETYPE_NONE;
		self.pev.solid = SOLID_TRIGGER;

		g_EntityFuncs.SetModel(self, self.pev.model);
		g_EntityFuncs.SetSize(self.pev, self.pev.mins, self.pev.maxs);
		g_EntityFuncs.SetOrigin(self, self.pev.origin);

		self.pev.effects |= EF_NODRAW;

		SetTouch(TouchFunction(this.Touch));
		SetUse(UseFunction(this.Use));

		if(self.pev.SpawnFlagBitSet(SF_START_OFF))
		{
			m_bEnabled = false;
		}
		else
		{
			m_bEnabled = true;
		}

		BaseClass.Spawn();
	}

	void Touch(CBaseEntity@ pOther)
	{
		if(!m_bEnabled)
		{
			return;
		}

		if(m_bHasTriggered)
		{
			return;
		}

		if(pOther is null || !pOther.IsPlayer())
		{
			return;
		}

		CBasePlayer@ pPlayer = cast<CBasePlayer@>(pOther);

		if(pPlayer is null || !pPlayer.IsConnected() || !pPlayer.IsAlive())
		{
			return;
		}

		m_bHasTriggered = true;

		m_hActivator = EHandle(pPlayer);

		if(m_flDelay > 0)
		{
			g_Scheduler.SetTimeout(this, "DelayedTrigger", m_flDelay);
		}
		else
		{
			FireTarget();
		}

		m_bEnabled = false;
	}

	void DelayedTrigger()
	{
		FireTarget();
	}

	void FireTarget()
	{
		if(self.pev.target != "" && self.pev.target != self.GetTargetname())
		{
			CBaseEntity@ pActivator = null;

			if(self.pev.SpawnFlagBitSet(SF_PASS_ACTIVATOR))
			{
				@pActivator = m_hActivator.GetEntity();
			}

			g_EntityFuncs.FireTargets(self.pev.target, pActivator, self, USE_TOGGLE, 0.0f);
		}

		if(m_szKillTarget != "")
		{
			CBaseEntity@ pKillEntity = null;
			int killCount = 0;

			while((@pKillEntity = g_EntityFuncs.FindEntityByTargetname(pKillEntity, m_szKillTarget)) !is null)
			{
				g_EntityFuncs.Remove(pKillEntity);
				killCount++;
			}
		}
	}

	void Use(CBaseEntity@ pActivator, CBaseEntity@ pCaller, USE_TYPE useType, float flValue)
	{
		switch(useType)
		{
			case USE_ON:
			{
				m_bEnabled = true;
				SetTouch(TouchFunction(this.Touch));
				break;
			}
			case USE_OFF:
			{
				m_bEnabled = false;
				SetTouch(null);
				break;
			}
			case USE_TOGGLE:
			{
				if(m_bEnabled)
				{
					self.Use(pActivator, pCaller, USE_OFF, flValue);
				}
				else
				{
					self.Use(pActivator, pCaller, USE_ON, flValue);
				}
				break;
			}
			case USE_KILL:
			{
				g_EntityFuncs.Remove(self);
				break;
			}
			case USE_SET:
			{
				if(flValue > 0)
				{
					m_bHasTriggered = false;
					m_bEnabled = true;
					SetTouch(TouchFunction(this.Touch));
				}
				break;
			}
		}
	}

	void UpdateOnRemove()
	{
		m_bEnabled = false;
		SetTouch(null);

		BaseClass.UpdateOnRemove();
	}
}

void Register()
{
	g_CustomEntityFuncs.RegisterCustomEntity("TriggerOnceCustom::CTriggerOnceCustom", "trigger_once_custom");
}

}