//
// Copyright(C) 2014-2015 Samuel Villarreal
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//      Trap Object Classes
//

#include "scripts/common.txt"

//-----------------------------------------------------------------------------
//
// Trap
//
//-----------------------------------------------------------------------------

/*
==============================================================
TurokTrap
==============================================================
*/

class TurokTrap : ScriptObject
{
    kActor @self;
    
    TurokTrap(kActor @actor)
    {
        @self = actor;
    }
    
    /*
    ==============================================================
    MeleeBluntWimpy
    ==============================================================
    */
    
    void MeleeBluntWimpy(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_2", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    MeleeBluntMedium
    ==============================================================
    */
    
    void MeleeBluntMedium(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_5", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    MeleeBluntStrong
    ==============================================================
    */
    
    void MeleeBluntStrong(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_10", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    MeleeBluntVeryHeavy
    ==============================================================
    */
    
    void MeleeBluntVeryHeavy(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_30", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    ScreenShake
    ==============================================================
    */
    
    void ScreenShake(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        Player.Actor().RecoilPitch() = -Math::Deg2Rad(w);
        Player.Actor().Velocity().z = ((w * 0.512f) * 15.0f) * (4 * GAME_DELTA_TIME);
    }
    
    /*
    ==============================================================
    ThumpAndHop
    ==============================================================
    */
    
    void ThumpAndHop(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        Player.Actor().Velocity().z = (-255.0f / (w * 15.0f)) * (4 * GAME_DELTA_TIME);
    }
    
    /*
    ==============================================================
    WeakKnockBack
    ==============================================================
    */
    
    void WeakKnockBack(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.InteractActorsAtPosition(self.GetTransformedVector(kVec3(x, y, z)), "KnockbackTarget", x, y, z, w);
    }
    
    /*
    ==============================================================
    KnockbackTarget
    ==============================================================
    */
    
    void KnockbackTarget(kActor @actor, const float arg1, const float arg2, const float arg3, const float arg4)
    {
        kVec3 org = self.GetTransformedVector(kVec3(arg1, arg2, arg3));
        kVec3 targOrg;
        kVec3 dir;
        float dist;
        
        if(actor is null)
        {
            return;
        }
        
        targOrg = actor.Origin();
        targOrg.z += (actor.Height() * 0.5f);
        
        dir = targOrg - org;
        dist = dir.Unit();
        
        if(dist <= (arg4 * 10.24f) + actor.Radius())
        {
            actor.Velocity() += (dir * 13.824f) * GAME_DELTA_TIME;
            actor.Velocity().z = 10.24f;
            
            actor.PlaySound("sounds/shaders/generic_81_kick_impact.ksnd");
            
            if(actor is Player.Actor().CastToActor())
            {
                Player.Actor().PlayerFlags() |= PF_NOAIRFRICTION;
            }
        }
    }
    
    /*
    ==============================================================
    OnTick
    ==============================================================
    */
    
    void OnTick(void)
    {
    }
    
    /*
    ==============================================================
    OnActivate
    ==============================================================
    */
    
    void OnActivate(void)
    {
        self.AnimState().Blend(anim_trapActivate, 4.0f, 8.0f, 0);
        self.MarkPersistentBit(false);
    }
    
    /*
    ==============================================================
    OnSpawn
    ==============================================================
    */
    
    void OnSpawn(void)
    {
        if(self.AnimState().CheckAnimID(anim_destructibleIdle))
        {
            self.AnimState().Set(anim_trapIdle, 4.0f, ANF_LOOP);
        }
        else
        {
            self.AnimState().Set(anim_trapActivate, 4.0f, ANF_LOOP);
        }
    }
    
    /*
    ==============================================================
    OnRestore
    ==============================================================
    */
    
    void OnRestore(void)
    {
        self.AnimState().Set(anim_trapActivate, 4.0f, ANF_LOOP);
        self.Flags() |= AF_IGNORESOUNDEVENTS|AF_ACTIVATED;
        self.AnimState().SetLastFrame();
    }
};

class TurokTrap2 : ScriptObject
{
    kActor @self;
    bool hasActivated = false;
    TurokTrap2(kActor @actor)
    {
        @self = actor;
		self.Flags() |= AF_CANBETOUCHED;
    }
    
	//------------------------------------------------------------------------------------------------------------------------
	void OnTouch(kActor @theActorThatTouchedMe) {
		if (Debug::IsActorsDisabled()) {
			return;
		}

		//if (!hasActivated) {
		if ((self.Flags() & AF_ACTIVATED) == 0) {
			self.Flags() |= AF_ACTIVATED;
			//hasActivated = true;
			OnActivate();
			
		}
	}
    /*
    ==============================================================
    MeleeBluntWimpy
    ==============================================================
    */
    
    void MeleeBluntWimpy(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_2", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    MeleeBluntMedium
    ==============================================================
    */
    
    void MeleeBluntMedium(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_5", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    MeleeBluntStrong
    ==============================================================
    */
    
    void MeleeBluntStrong(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_10", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    MeleeBluntVeryHeavy
    ==============================================================
    */
    
    void MeleeBluntVeryHeavy(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.MeleeObject("Damage_Blunt_30", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    ScreenShake
    ==============================================================
    */
    
    void ScreenShake(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        Player.Actor().RecoilPitch() = -Math::Deg2Rad(w);
        Player.Actor().Velocity().z = ((w * 0.512f) * 15.0f) * (4 * GAME_DELTA_TIME);
    }
    
    /*
    ==============================================================
    ThumpAndHop
    ==============================================================
    */
    
    void ThumpAndHop(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        Player.Actor().Velocity().z = (-255.0f / (w * 15.0f)) * (4 * GAME_DELTA_TIME);
    }
    
    /*
    ==============================================================
    WeakKnockBack
    ==============================================================
    */
    
    void WeakKnockBack(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        self.InteractActorsAtPosition(self.GetTransformedVector(kVec3(x, y, z)), "KnockbackTarget", x, y, z, w);
    }
    
    /*
    ==============================================================
    KnockbackTarget
    ==============================================================
    */
    
    void KnockbackTarget(kActor @actor, const float arg1, const float arg2, const float arg3, const float arg4)
    {
        kVec3 org = self.GetTransformedVector(kVec3(arg1, arg2, arg3));
        kVec3 targOrg;
        kVec3 dir;
        float dist;
        
        if(actor is null)
        {
            return;
        }
        
        targOrg = actor.Origin();
        targOrg.z += (actor.Height() * 0.5f);
        
        dir = targOrg - org;
        dist = dir.Unit();
        
        if(dist <= (arg4 * 10.24f) + actor.Radius())
        {
            actor.Velocity() += (dir * 13.824f) * GAME_DELTA_TIME;
            actor.Velocity().z = 10.24f;
            
            actor.PlaySound("sounds/shaders/generic_81_kick_impact.ksnd");
            
            if(actor is Player.Actor().CastToActor())
            {
                Player.Actor().PlayerFlags() |= PF_NOAIRFRICTION;
            }
        }
    }
    
    /*
    ==============================================================
    OnTick
    ==============================================================
    */
    
    void OnTick(void)
    {
    }
    
    /*
    ==============================================================
    OnActivate
    ==============================================================
    */
    
    void OnActivate(void)
    {
        self.AnimState().Blend(anim_trapActivate, 4.0f, 8.0f, 0);
        self.MarkPersistentBit(false);
    }
    
    /*
    ==============================================================
    OnSpawn
    ==============================================================
    */
    
    void OnSpawn(void)
    {
		self.AnimState().Set(anim_trapIdle, 4.0f, ANF_LOOP);
        // if(self.AnimState().CheckAnimID(anim_destructibleIdle))
        // {
            // self.AnimState().Set(anim_trapIdle, 4.0f, ANF_LOOP);
        // }
        // else
        // {
            // self.AnimState().Set(anim_trapActivate, 4.0f, ANF_LOOP);
        // }
    }
    
    /*
    ==============================================================
    OnRestore
    ==============================================================
    */
    
    void OnRestore(void)
    {
        self.AnimState().Set(anim_trapActivate, 4.0f, ANF_LOOP);
        self.Flags() |= AF_IGNORESOUNDEVENTS|AF_ACTIVATED;
        self.AnimState().SetLastFrame();
    }
};

//-----------------------------------------------------------------------------
//
// Laser Wall
//
//-----------------------------------------------------------------------------

/*
==============================================================
TurokLaserWall
==============================================================
*/

class TurokLaserWall : ScriptObject
{
    kActor  @m_pSelf;
    uint    m_stateFlags;
    float   m_resetTimer;
    float   m_reTriggerTime;
    
    TurokLaserWall(kActor @actor)
    {
        @m_pSelf = actor;
        m_stateFlags = 0;
        m_resetTimer = 0;
        m_reTriggerTime = 0;
    }
    
    /*
    ==============================================================
    OnTick
    ==============================================================
    */
    
    void OnTick(void)
    {
        if(m_reTriggerTime > 0)
        {
            m_reTriggerTime -= GAME_FRAME_TIME;
            if(m_reTriggerTime <= 0)
            {
                // allow this actor to be triggered again
                m_pSelf.Flags() &= ~AF_ACTIVATED;
                m_reTriggerTime = 0;
            }
            
            return;
        }
        
        if((m_stateFlags & TFF_ACTIVATED) != 0)
        {
            if((m_stateFlags & TFF_MOVING) != 0)
            {
                // if timer is 0, stay lasering
                if(m_resetTimer > 0)
                {
                    m_resetTimer -= GAME_FRAME_TIME;
                    
                    if(m_resetTimer <= 0)
                    {
                        m_stateFlags &= ~(TFF_MOVING|TFF_WAITING);
                        m_pSelf.AnimState().Set(anim_laserWallStop, 4.0f, 0);
                        m_reTriggerTime = float(m_pSelf.SpawnParams(4) * 30);
                    }
                }
            }
            // check timer before laser opens
            else if((m_stateFlags & TFF_WAITING) != 0)
            {
                // decrease timer
                m_resetTimer -= GAME_FRAME_TIME;
                if(m_resetTimer <= 0)
                {
                    // setup timer to keep laser shooting
                    m_stateFlags |= TFF_MOVING;
                    m_resetTimer = float(m_pSelf.SpawnParams(4) * 15);
                    m_pSelf.AnimState().Set(anim_laserWallGo, 4.0f, 0);
                }
            }
        }
        else
        {
            m_stateFlags |= TFF_ACTIVATED;
            m_pSelf.AnimState().Set(anim_laserWallStart, 4.0f, 0);
        }
    }
    
    /*
    ==============================================================
    OnActivate
    ==============================================================
    */
    
    void OnActivate(void)
    {
        if((m_stateFlags & TFF_WAITING) == 0)
        {
            if(m_pSelf.SpawnParams(7) != 0)
            {
                m_stateFlags |= TFF_WAITING;
                m_resetTimer = float(m_pSelf.SpawnParams(7) * 15);
            }
            else
            {
                m_stateFlags |= TFF_MOVING;
                m_resetTimer = float(m_pSelf.SpawnParams(4) * 15);
                m_pSelf.AnimState().Set(anim_laserWallGo, 4.0f, 0);
            }
        }
    }
    
    /*
    ==============================================================
    MeleeVeryWimpy
    ==============================================================
    */
    
    void MeleeVeryWimpy(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        m_pSelf.MeleeObject("Damage_Generic_1", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    OnSpawn
    ==============================================================
    */
    
    void OnSpawn(void)
    {
    }
    
    /*
    ==============================================================
    OnRestore
    ==============================================================
    */
    
    void OnRestore(void)
    {
    }
};

//-----------------------------------------------------------------------------
//
// Laser Wall
//
//-----------------------------------------------------------------------------

/*
==============================================================
TurokLaserWall
==============================================================
*/

class TurokLaserWall2 : ScriptObject
{
    kActor  @m_pSelf;
    uint    m_stateFlags;
    float   m_resetTimer;
    float   m_reTriggerTime;
    
    TurokLaserWall2(kActor @actor)
    {
        @m_pSelf = actor;
        m_stateFlags = 0;
        m_resetTimer = 0;
        m_reTriggerTime = 0;
		m_pSelf.Flags() |= AF_CANBETOUCHED;
    }
    
	//------------------------------------------------------------------------------------------------------------------------
	void OnTouch(kActor @theActorThatTouchedMe) {
		//if (!hasActivated) {
		if ((m_pSelf.Flags() & AF_ACTIVATED) == 0) {
			m_pSelf.Flags() |= AF_ACTIVATED;
			//hasActivated = true;
			OnActivate();
			
		}
	}
    /*
    ==============================================================
    OnTick
    ==============================================================
    */
    
    void OnTick(void)
    {
        if (m_resetTimer > 0)
        {
            m_resetTimer -= GAME_DELTA_TIME;
            if(m_resetTimer <= 0) {
                m_pSelf.Flags() &= ~AF_ACTIVATED;
				m_pSelf.AnimState().Set(anim_laserWallStop, 4.0f, 0);
            }
        }
        
        // if((m_stateFlags & TFF_ACTIVATED) != 0)
        // {
            // if((m_stateFlags & TFF_MOVING) != 0)
            // {
                // // if timer is 0, stay lasering
                // if(m_resetTimer > 0)
                // {
                    // m_resetTimer -= GAME_FRAME_TIME;
                    
                    // if(m_resetTimer <= 0)
                    // {
                        // m_stateFlags &= ~(TFF_MOVING|TFF_WAITING);
                        // m_pSelf.AnimState().Set(anim_laserWallStop, 4.0f, 0);
                        // m_reTriggerTime = float(4 * 30);
                    // }
                // }
            // }
            // // check timer before laser opens
            // else if((m_stateFlags & TFF_WAITING) != 0)
            // {
                // // decrease timer
                // m_resetTimer -= GAME_FRAME_TIME;
                // if(m_resetTimer <= 0)
                // {
                    // // setup timer to keep laser shooting
                    // m_stateFlags |= TFF_MOVING;
                    // m_resetTimer = float(m_pSelf.SpawnParams(4) * 15);
                    // m_pSelf.AnimState().Set(anim_laserWallGo, 4.0f, 0);
                // }
            // }
        // }
        // else
        // {
            // m_stateFlags |= TFF_ACTIVATED;
            // m_pSelf.AnimState().Set(anim_laserWallStart, 4.0f, 0);
        // }
    }
    
    /*
    ==============================================================
    OnActivate
    ==============================================================
    */
    
    void OnActivate(void)
    {
		m_resetTimer = 1.0f;
		m_pSelf.AnimState().Set(anim_laserWallGo, 4.0f, 0);
    }
    
    /*
    ==============================================================
    MeleeVeryWimpy
    ==============================================================
    */
    
    void MeleeVeryWimpy(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        m_pSelf.MeleeObject("Damage_Generic_1", kVec3(x, y, z), w);
    }
    
    /*
    ==============================================================
    OnSpawn
    ==============================================================
    */
    
    void OnSpawn(void)
    {
    }
    
    /*
    ==============================================================
    OnRestore
    ==============================================================
    */
    
    void OnRestore(void)
    {
    }
};