#include "scripts/animations.txt"
#include "scripts/common.txt"
#include "scripts/BP_common.txt"

bool lastHideWeapon = false;

class TurokWeapon : ScriptObjectWeapon
{
    kWeapon @self;
	int lastAnimID;
	//------------------------------------------------------------------------------------------------------------------------
    TurokWeapon(kWeapon @actor)
    {
        @self = actor;
		lastAnimID = -1;
    }
	//------------------------------------------------------------------------------------------------------------------------
    ~TurokWeapon()
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		bool hideWeapon = ((Player.Actor().PlayerFlags() & (1 << 30)) != 0) || IsMenuOpen() || IsWeaponDisabled();
		
		switch(self.AnimState().PlayingID())
		{
			case anim_weaponSwapIn:
			{
				if (lastAnimID != anim_weaponSwapIn)
				{
					if (!hideWeapon)
						PlaySoundWeaponReady();
					OnWeaponReady();
				}
				self.AnimState().ChangeSpeed(1.9f);
				break;
			}
			case anim_weaponSwapOut:
			{
				self.AnimState().ChangeSpeed(1.9f);
				break;
			}
			default:
			{
				break;
			}
		}
		
		//check for hide weapon playerflag or menu open flag
		bool isHiding = (self.Flags() & AF_NODRAW) != 0;
		if (isHiding != hideWeapon)
		{
			if (hideWeapon)
			{
				self.Flags() |= AF_NODRAW;
			}
			else
			{
				self.Flags() &= ~AF_NODRAW;
			}
		}
		
		lastAnimID = self.AnimState().PlayingID();
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnSpawn(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
	// Returns true if can begin firing a weapon
	//------------------------------------------------------------------------------------------------------------------------
	bool CheckBeginFire()
	{
		bool canBeginFire = !IsMenuOpen() && !IsWeaponDisabled();
		if (!canBeginFire)
		{
			if (self.AnimState().PlayingID() != anim_weaponIdle)
			{
				self.AnimState().Set(anim_weaponIdle, 4.0f, ANF_LOOP);
			}
		}
		return canBeginFire;
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnLower(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnRaise(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnHoldster(void)
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnWeaponReady()
    {
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
//is also adon rifle and hummer (underwater weapon)
final class TurokKnife : TurokWeapon
{   
	bool setModel;
	int type;
	
	int rifleShotsFired;
	//------------------------------------------------------------------------------------------------------------------------
    TurokKnife(kWeapon @actor)
    {
        super(actor);
		type = GetPlayerCharacter();
		rifleShotsFired = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		if (!setModel)
		{
			setModel = true;
			if (type == PLAYER_CHAR_ADON)
			{
				self.RenderModel().SetModel("models/adon_arm.bin", "anims/dyn_rifle_anim.bin");
				self.RenderModel().Offset() = kVec3(0.0f, 50.0f, 0.0f);
				self.AnimState().SetLastFrame();
			}
			else if (type == PLAYER_CHAR_HUMMER)
			{
				self.RenderModel().SetModel("models/dyn_monster_hummer01_new.bin", "anims/weapon_empty.bin");
				self.RenderModel().Offset() = kVec3(-57.167f, -8.6f, -80.784f);
				//self.RenderModel().Offset() = kVec3(-175.0f, -50.0f, -130.0f);
				self.AnimState().SetLastFrame();
			}
		}
		
		if (type == PLAYER_CHAR_HUMMER)
		{
			kPuppet @src = self.Owner().Actor();
			src.Pitch() = Math::Clampf(src.Pitch(), Math::Deg2Rad(-20.0f), Math::Deg2Rad(25.0f));
		}
		
		TurokWeapon::OnTick();
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire()
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();
		
        kPuppet @src = self.Owner().Actor();
		if (type == PLAYER_CHAR_TUROK)
		{    
			if (src.InWater())
			{
				self.AnimState().Blend(anim_weaponAttackUnderwater, 4.0f, 4.0f, 0);
				self.PlaySound("sounds/shaders/underwater_swim_2.ksnd");
				return;
			}
			
			int rnd = Math::RandMax(100);
			
			if(rnd <= 32)
			{
				self.AnimState().Blend(anim_weaponAttack1, 4.0f, 4.0f, 0);
				self.PlaySound("sounds/shaders/knife_swish_2.ksnd");
			}
			else if(rnd <= 64)
			{
				self.AnimState().Blend(anim_weaponAttack2, 4.0f, 4.0f, 0);
				self.PlaySound("sounds/shaders/knife_swish_1.ksnd");
			}
			else
			{
				self.AnimState().Blend(anim_weaponAttack3, 4.0f, 4.0f, 0);
				self.PlaySound("sounds/shaders/knife_swish_3.ksnd");
			}
		}
		else if (type == PLAYER_CHAR_ADON)
		{    
		    self.AnimState().Set(anim_weaponFire, 1.0f, 0);
			rifleShotsFired = 0;
		}
		else if (type == PLAYER_CHAR_HUMMER)
		{    
		    self.AnimState().Set(anim_weaponFire, 1.0f, 0);
		}
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
		if (type == PLAYER_CHAR_ADON)
		{
			switch(rifleShotsFired)
			{
			case 0:
				if(self.AnimState().PlayTime() >= 0.0f)
				{
					FireRifleShot();
				}
				break;
				
			case 1:
				if(self.AnimState().PlayTime() >= 0.33f)
				{
					FireRifleShot();
				}
				break;
				
			case 2:
				if(self.AnimState().PlayTime() >= 0.66f)
				{
					FireRifleShot();
				}
				break;
			}
		}
    }
	//------------------------------------------------------------------------------------------------------------------------
	void FireRifleShot()
	{
		self.PlaySound("sounds/shaders/machine_gun_shot_2.ksnd");
		self.FireProjectile("fx/BP_Player_Adon_Rifle.kfx", 30.24f, 15.6f, -10.24f);
		self.Owner().Actor().LoudNoiseAlert();
		//self.Owner().Actor().RecoilPitch() = -0.02416609786450863f;
		rifleShotsFired++;
	}
	//------------------------------------------------------------------------------------------------------------------------
    void KnifeAttack1(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        kPuppet @src = self.Owner().Actor();
        
        TurokPlayer @p = cast<TurokPlayer@>(src.ScriptObject().obj);
        p.m_vBloodVector = kVec3(0, (w * GAME_SCALE), 0);
        p.m_vBloodVector.z += (GAME_SCALE * 3);
        
        p.m_vStabVector = (kVec3(0, (w * GAME_SCALE), 0) * src.Rotation());
        p.m_vStabVector += src.Origin();
        p.m_vStabVector.z += (GAME_SCALE * 3);
        
        src.InteractActorsAtPosition(p.m_vStabVector, "KnifeAttack", 0, w);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void KnifeAttack2(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        kPuppet @src = self.Owner().Actor();
        
        TurokPlayer @p = cast<TurokPlayer@>(src.ScriptObject().obj);
        p.m_vBloodVector = kVec3(0, (w * GAME_SCALE), 0);
        p.m_vBloodVector.z += (GAME_SCALE * 3);
        
        p.m_vStabVector = (kVec3(0, (w * GAME_SCALE), 0) * src.Rotation());
        p.m_vStabVector += src.Origin();
        p.m_vStabVector.z += (GAME_SCALE * 3);
        
        src.InteractActorsAtPosition(p.m_vStabVector, "KnifeAttack", 1, w);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void KnifeAttack3(kActor @instigator, const float w, const float x, const float y, const float z)
    {
        kPuppet @src = self.Owner().Actor();
        
        TurokPlayer @p = cast<TurokPlayer@>(src.ScriptObject().obj);
        p.m_vBloodVector = kVec3(0, (w * GAME_SCALE), 0);
        p.m_vBloodVector.z += (GAME_SCALE * 3);
        
        p.m_vStabVector = (kVec3(0, (w * GAME_SCALE), 0) * src.Rotation());
        p.m_vStabVector += src.Origin();
        p.m_vStabVector.z += (GAME_SCALE * 3);
        
        src.InteractActorsAtPosition(p.m_vStabVector, "KnifeAttack", 2, w);
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokBow : TurokWeapon
{   
	float maxChargeTime = 0.32f; //0.7f;
    TurokBow(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.PlaySound("sounds/shaders/bow_stretch.ksnd");
        self.AnimState().Blend(anim_weaponFire, 4.0f, 6.0f, ANF_LOOP); //20.0f
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
        float time = Math::Minf(self.AnimState().PlayTime(), maxChargeTime);
        kPuppet @src = self.Owner().Actor();
        kVec3 origin = src.Origin();
        kQuat rotation = src.Rotation();
        kVec3 fxVelocity;
		kVec3 actorVelocity;
        origin.z += (5*GAME_SCALE);
        origin += (kVec3(0.07f*GAME_SCALE, 2.9f*GAME_SCALE, -0.6f*GAME_SCALE) * rotation);
		float chargeVelocityScale = 500 * time / maxChargeTime;
		fxVelocity = kVec3(0, chargeVelocityScale * 15, 0) * rotation;
		actorVelocity = kVec3(0, 480 + (chargeVelocityScale * 4), 0) * rotation;
		//actorVelocity = kVec3(0, 960 + (chargeVelocityScale * 8), 0) * rotation;
        fxVelocity *= GAME_DELTA_TIME;
        actorVelocity *= GAME_DELTA_TIME;
		
        if (self.Owner().HasAltAmmo())
        {
            Game.SpawnFx("fx/BP_Player_Arrow_Explosive.kfx", src, fxVelocity, origin, rotation);
            self.PlaySound("sounds/shaders/arrow_fly_tek.ksnd");
        }
        else
        {
            self.PlaySound("sounds/shaders/arrow_fly_normal.ksnd");
			kActor @arrowActor = ActorFactory.Spawn("BP_ArrowProjectile", origin.x, origin.y, origin.z, src.Yaw(), src.SectorIndex());
			BP_ArrowProjectile @projActor = cast<BP_ArrowProjectile@>(arrowActor.ScriptObject().obj);
			projActor.Setup(fxVelocity, actorVelocity);
        }
        
        self.PlaySound("sounds/shaders/bow_twang.ksnd");
        self.AnimState().Set(anim_weaponFireCharged, 4.0f, ANF_NOINTERRUPT);
        
        self.Owner().ConsumeAmmo(1);
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokPistol : TurokWeapon
{   
    TurokPistol(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
		Game.PlaySound("sounds/shaders/ready_pistol.ksnd");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.FireProjectile("fx/bullet_shell.kfx", 10.24f, 27.64f, -10.24f, true);
        self.FireProjectile("fx/weffect_pistol.kfx", 6.656f-0.5f, 29.69f, -3.58f-0.5f, true);
        self.FireProjectile("fx/BP_Player_Pistol.kfx", 13.107f, 25.6f, -10.24f);
            
        self.PlaySound("sounds/shaders/pistol_shot.ksnd");
        self.AnimState().Set(anim_weaponFire, 3.4f, 0);
        
        self.RunFxEvent("GunFire");
        
        self.Owner().Actor().LoudNoiseAlert();
        self.Owner().Actor().RecoilPitch() = -0.02094395086169243f;
        self.Owner().ConsumeAmmo(1);
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokShotgun : TurokWeapon
{   
    bool bShotgunReload;
    bool bEjectShotgunShell;
    bool bFiredExpslosiveShells;
	
	float speedMul = 0.65f;
	//------------------------------------------------------------------------------------------------------------------------
    TurokShotgun(kWeapon @actor)
    {
        bShotgunReload = false;
        bEjectShotgunShell = false;
        bFiredExpslosiveShells = false;

        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
		Game.PlaySound("sounds/shaders/ready_shotgun.ksnd");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        bFiredExpslosiveShells = Player.HasAltAmmo();
        self.FireProjectile("fx/weffect_riotshotgun.kfx", 6.656f-1.0f, 29.69f, -2.7648f+0.85f);
        
        if(bFiredExpslosiveShells)
        {
            self.FireProjectile("fx/BP_Player_Shotgun_Explosive.kfx", 12.28f, 25.6f, -7.168f);
            //self.FireProjectile("fx/shotgun_explosive.kfx", 12.28f, 25.6f, -7.168f);
        }
        else
        {
			self.FireProjectile("fx/BP_Player_Pump_Shotgun.kfx", 12.28f, 25.6f, -7.168f);
            //self.FireProjectile("fx/shotgun.kfx", 12.28f, 25.6f, -7.168f);
        }
		        
        self.PlaySound("sounds/shaders/riot_shotgun_shot.ksnd");
        self.RunFxEvent("GunFire");
        self.AnimState().Set(anim_weaponFire, 4.0f * speedMul, 0);
        
        bShotgunReload = true;
        bEjectShotgunShell = true;
        
        self.Owner().Actor().LoudNoiseAlert();
        self.Owner().Actor().RecoilPitch() = -0.03926990926265717f;
        self.Owner().ConsumeAmmo(1);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        if(bShotgunReload && self.AnimState().PlayTime() >= 0.5f * speedMul)
        {
            self.PlaySound("sounds/shaders/ready_shotgun.ksnd");
            bShotgunReload = false;
        }
        
        if(bEjectShotgunShell && self.AnimState().PlayTime() >= 0.6f * speedMul)
        {
            if(bFiredExpslosiveShells)
            {
                self.FireProjectile("fx/shotgun_shell_explosive.kfx", 11.26f, 27.648f, -8.192f, true);
            }
            else
            {
                self.FireProjectile("fx/shotgun_shell.kfx", 11.26f, 27.648f, -8.192f, true);
            }
            
            bFiredExpslosiveShells = false;
            bEjectShotgunShell = false;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokAutoShotgun : TurokWeapon
{   
    bool bShotgunReload;
    bool bFiredExpslosiveShells;
    bool bCycleBarrel;
    float spinBarrelAngle;
	//------------------------------------------------------------------------------------------------------------------------
    TurokAutoShotgun(kWeapon @actor)
    {
        bShotgunReload = false;
        bFiredExpslosiveShells = false;
        bCycleBarrel = false;
        spinBarrelAngle = 0;

        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.FireProjectile("fx/weffect_riotshotgun.kfx", 6.656f-0.5f, 29.69f, -1.9456f-0.75f);
        if(self.Owner().HasAltAmmo())
        {
            self.FireProjectile("fx/BP_Player_Shotgun_Explosive.kfx", 12.28f, 25.6f, -7.168f);
            self.FireProjectile("fx/shotgun_shell_explosive.kfx", 14.336f, 27.648f, -12.288f, true);
        }
        else
        {
			self.FireProjectile("fx/BP_Player_Shotgun.kfx", 12.28f, 25.6f, -7.168f);
			self.FireProjectile("fx/shotgun_shell.kfx", 14.336f, 27.648f, -12.288f, true);
        }

        
        self.PlaySound("sounds/shaders/riot_shotgun_shot.ksnd");
        self.RunFxEvent("GunFire");
        self.AnimState().Set(anim_weaponFire, 4.0f, 0);
        
        bShotgunReload = true;
        bCycleBarrel = true;
        spinBarrelAngle = Math::Deg2Rad(36.0f);
        
        self.Owner().Actor().LoudNoiseAlert();
        self.Owner().Actor().RecoilPitch() = -0.02617993950843811f;
        self.Owner().ConsumeAmmo(1);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        if(bShotgunReload && self.AnimState().PlayTime() >= 0.0125f)
        {
            self.PlaySound("sounds/shaders/reload_auto_shotgun.ksnd");
            bShotgunReload = false;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		TurokWeapon::OnTick();
        if(bCycleBarrel)
        {
            if(spinBarrelAngle > 0)
            {
                spinBarrelAngle -= (0.1f*GAME_FRAME_TIME);
            }
            else
            {
                spinBarrelAngle = 0;
                bCycleBarrel = true;
            }
            
            self.RenderModel().SetRotationOffset(1, spinBarrelAngle, 1, 0, 0);
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokRifle : TurokWeapon
{   
    int rifleShotsFired;
	//------------------------------------------------------------------------------------------------------------------------
    TurokRifle(kWeapon @actor)
    {
        rifleShotsFired = 0;
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 1.0f, 0);
        rifleShotsFired = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
	void FireShot()
	{
		self.PlaySound("sounds/shaders/rifle_shot.ksnd");
		self.FireProjectile("fx/bullet_shell.kfx", 11.26f, 27.64f, -8.192f, true);
		self.FireProjectile("fx/weffect_assaultrifle.kfx", 5.12f+0.35f, 29.69f, -3.584f-0.5f);
		self.FireProjectile("fx/BP_Player_Rifle.kfx", 10.24f, 25.6f, -10.24f);
		self.RunFxEvent("GunFire");
		self.Owner().Actor().LoudNoiseAlert();
		self.Owner().Actor().RecoilPitch() = -0.02416609786450863f;
		self.Owner().ConsumeAmmo(1);
		rifleShotsFired++;
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        switch(rifleShotsFired)
        {
        case 0:
            if(self.AnimState().PlayTime() >= 0.0f)
            {
				FireShot();
            }
            break;
            
        case 1:
            if(self.AnimState().PlayTime() >= 0.33f)
            {
				FireShot();
            }
            break;
            
        case 2:
            if(self.AnimState().PlayTime() >= 0.66f)
            {
				FireShot();
            }
            break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokPulseRifle : TurokWeapon
{   
    float pulseRifleFireTime;
	//------------------------------------------------------------------------------------------------------------------------
    TurokPulseRifle(kWeapon @actor)
    {
        pulseRifleFireTime = 0;
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Blend(anim_weaponFireLoop, 4.0f, 4.0f, ANF_LOOP);
        pulseRifleFireTime = -0.08f;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        float playTime = self.AnimState().PlayTime();
    
        if((playTime - pulseRifleFireTime) >= 0.16f)
        {
            self.PlaySound("sounds/shaders/machine_gun_shot_2.ksnd");
			
			self.FireProjectile("fx/BP_Player_Pulse.kfx", 10.24f, -40.96f, -9.216f);
			
            self.Owner().Actor().LoudNoiseAlert();
            self.Owner().Actor().RecoilPitch() = -0.01963495463132858f;
            self.Owner().ConsumeAmmo(1);
            
            pulseRifleFireTime = playTime;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
        self.AnimState().Blend(anim_weaponIdle, 4.0f, 4.0f, ANF_LOOP);
        pulseRifleFireTime = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokMinigun : TurokWeapon
{   
    bool bCycleMiniBarrel;
    bool bCycleMiniBarrel2;
    bool bMiniGunRampUp;
    bool bMiniGunRampUp2;
    float miniGunFireTime;
    float miniGunCycleSpeed;
    float miniGunBarrelAngle;
    float miniGunCycleSpeed2;
    float miniGunBarrelAngle2;
	float spinTime;
	float spinTime2;
	bool hasDualUpgrade;
	bool setNewModel;
	int playingSound;
	//------------------------------------------------------------------------------------------------------------------------
    TurokMinigun(kWeapon @actor)
    {
        bCycleMiniBarrel = false;
        bMiniGunRampUp = false;
        miniGunFireTime = 0;
        miniGunCycleSpeed = 0;
        miniGunBarrelAngle = 0;
        miniGunCycleSpeed2 = 0;
        miniGunBarrelAngle2 = 0;
		spinTime = 0.05f;
		spinTime2 = 0.05f;
        bCycleMiniBarrel2 = false;
        bMiniGunRampUp2 = false;
		playingSound = 0;
		CheckWeaponUpgrade();
		
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void CheckWeaponUpgrade()
	{
		weaponUpgraded = false;
		hasDualUpgrade = GetWeaponUpgrade(WUF_DUALMINIGUN);
		if (hasDualUpgrade)
		{
			setNewModel = true;
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Blend(anim_weaponFireLoop, 4.0f, 4.0f, ANF_LOOP);

        bCycleMiniBarrel = true;
        bMiniGunRampUp = true;
        bCycleMiniBarrel2 = true;
        bMiniGunRampUp2 = true;
        miniGunFireTime = 0;
		spinTime = Math::RandRange(0.04f, 0.06f);
		spinTime2 = Math::RandRange(0.04f, 0.06f);
		self.StopLoopingSounds();
		playingSound = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        float playTime = self.AnimState().PlayTime();
    
        if ((playTime - miniGunFireTime) >= 0.09f)
        {
            self.FireProjectile("fx/weffect_minigun.kfx", 4.608f, 25.696f, -3.1744f);
            self.FireProjectile("fx/BP_Player_Minigun.kfx", 11.192f, 25.6f, -10.24f);
            self.FireProjectile("fx/bullet_shell.kfx", 11.26f, 27.648f, -8.192f, true);
			if (hasDualUpgrade)
			{
				self.FireProjectile("fx/BP_Player_Minigun.kfx", -11.192f, 25.6f, -10.24f);
				self.FireProjectile("fx/bullet_shell2.kfx", -11.26f, 27.648f, -8.192f, true);
				self.FireProjectile("fx/weffect_minigun2.kfx", -4.608f, 25.696f, -3.1744f);
				self.Owner().ConsumeAmmo(50);
			}
			else
			{
				self.Owner().ConsumeAmmo(30);
			}

			if (playingSound != 2) //not shooting
			{
				self.StopLoopingSounds();
				self.PlaySound("sounds/shaders/BP_Minigun_Shot.ksnd");
				playingSound = 2;
			}

            self.Owner().Actor().LoudNoiseAlert();
            self.Owner().Actor().RecoilPitch() = -0.02094395086169243f;
            
            miniGunFireTime = playTime;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
        self.StopLoopingSounds();
		playingSound = 0;
        self.AnimState().Blend(anim_weaponIdle, 4.0f, 4.0f, ANF_LOOP);
        
        miniGunFireTime = 0;
        bMiniGunRampUp = false;
        bMiniGunRampUp2 = false;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		TurokWeapon::OnTick();
		if (weaponUpgraded)
		{
			CheckWeaponUpgrade();
		}
		
		if (playingSound == 2 && !self.Owner().HasAmmo(TW_WEAPON_MINIGUN)) //is shooting with no ammo then play spin sound
		{
			self.StopLoopingSounds();
			self.PlaySound("sounds/shaders/BP_Minigun_Spin.ksnd");
			playingSound = 1;
		}
		
		if (setNewModel)
		{
			setNewModel = false;
			if (hasDualUpgrade)
			{
				self.RenderModel().SetModel("models/dyn_dual_minigun.bin", "anims/dyn_dual_minigun_anim.bin");
				self.AnimState().SetLastFrame();
			}
		}
		
        if (bCycleMiniBarrel)
        {
            float time = (spinTime * GAME_FRAME_TIME);
            
            if (bMiniGunRampUp)
            {
                miniGunCycleSpeed = (40.0f - miniGunCycleSpeed) * time + miniGunCycleSpeed;
            }
            else
            {
                miniGunCycleSpeed = (0 - miniGunCycleSpeed) * time + miniGunCycleSpeed;
            }
            
            if (miniGunCycleSpeed < 0.01f)
            {
                miniGunCycleSpeed = 0;
                bCycleMiniBarrel = false;
            }
            
            miniGunBarrelAngle += miniGunCycleSpeed * (1.0f / 60.0f);
            self.RenderModel().SetRotationOffset(1, miniGunBarrelAngle, 0, 1, 0);
        }
		
        if (bCycleMiniBarrel2)
        {
            float time = (spinTime2 * GAME_FRAME_TIME);
            
            if (bMiniGunRampUp2)
            {
                miniGunCycleSpeed2 = (40.0f - miniGunCycleSpeed2) * time + miniGunCycleSpeed2;
            }
            else
            {
                miniGunCycleSpeed2 = (0 - miniGunCycleSpeed2) * time + miniGunCycleSpeed2;
            }
            
            if (miniGunCycleSpeed2 < 0.01f)
            {
                miniGunCycleSpeed2 = 0;
                bCycleMiniBarrel2 = false;
            }
            
            miniGunBarrelAngle2 += miniGunCycleSpeed2 * (1.0f / 60.0f);
			if (hasDualUpgrade)
			{
				self.RenderModel().SetRotationOffset(3, miniGunBarrelAngle2, 0, 1, 0);
			}
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnLower(void)
    {
		TurokWeapon::OnLower();
        miniGunCycleSpeed = 0;
        miniGunCycleSpeed2 = 0;
        bCycleMiniBarrel = false;
        bCycleMiniBarrel2 = false;
        self.RenderModel().SetRotationOffset(1, 0, 0, 1, 0);
		if (hasDualUpgrade)
		{
			self.RenderModel().SetRotationOffset(3, 0, 0, 1, 0);
		}
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnHoldster(void)
    {
        miniGunCycleSpeed = 0;
        miniGunCycleSpeed2 = 0;
        bCycleMiniBarrel = false;
        bMiniGunRampUp = false;
        bCycleMiniBarrel2 = false;
        bMiniGunRampUp2 = false;
        self.RenderModel().SetRotationOffset(1, 0, 0, 1, 0);
		if (hasDualUpgrade)
		{
			self.RenderModel().SetRotationOffset(3, 0, 0, 1, 0);
		}
        self.StopLoopingSounds();
		playingSound = 0;
        //self.PlaySound("sounds/shaders/minigun_stop.ksnd");
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokGrenadeLauncher : TurokWeapon
{   
    TurokGrenadeLauncher(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
		Game.PlaySound("sounds/shaders/ready_grenade_launcher.ksnd");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 4.0f, 0);
        self.PlaySound("sounds/shaders/grenade_launch.ksnd");
        
        self.FireProjectile("fx/BP_Player_Grenade.kfx", 18.432f, 25.696f, -5.12f);
        // self.FireProjectile("fx/grenade.kfx", 18.432f, 25.696f, -5.12f);
        self.FireProjectile("fx/weffect_grenadelauncher.kfx", 10.3424f, 25.696f, -0.512f);
        
        self.Owner().Actor().LoudNoiseAlert();
        self.Owner().Actor().RecoilPitch() = -0.03490658476948738f;
        self.Owner().ConsumeAmmo(1);
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokAlienRifle : TurokWeapon
{   
    TurokAlienRifle(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
		Game.PlaySound("sounds/shaders/ready_tek_weapon_1.ksnd");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 4.0f, 0);
        self.PlaySound("sounds/shaders/tek_weapon_1.ksnd");
        
		self.FireProjectile("fx/BP_Player_PlasmaShotgun.kfx", 4.096f, 25.696f, -14.336f);
        // self.FireProjectile("fx/BP_Player_Plasma.kfx", 4.096f, 25.696f, -14.336f);
        // self.FireProjectile("fx/BP_Player_PlasmaLeft.kfx", 4.096f, 25.696f, -14.336f);
        // self.FireProjectile("fx/BP_Player_PlasmaRight.kfx", 4.096f, 25.696f, -14.336f);
        self.Owner().ConsumeAmmo(4);
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokRocketLauncher : TurokWeapon
{   
    TurokRocketLauncher(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
		Game.PlaySound("sounds/shaders/ready_missile_launcher.ksnd");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 2.0f, 0);
        self.PlaySound("sounds/shaders/missile_launch.ksnd");
        self.PlaySound("sounds/shaders/reload_missile_launcher.ksnd");
        
		self.FireProjectile("fx/BP_Player_Rocket.kfx", 4.096f, 25.696f, -14.336f);
        
        self.Owner().Actor().LoudNoiseAlert();
        self.Owner().ConsumeAmmo(1);
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokAccelerator : TurokWeapon
{   
    float acceleratorCycleSpeed;
    float acceleratorSpinAngle;
    int chargeStep;
    float speedMul = 0.5f;
	//------------------------------------------------------------------------------------------------------------------------
    TurokAccelerator(kWeapon @actor)
    {
        acceleratorCycleSpeed = 4.0f;
        acceleratorSpinAngle = 0;
        chargeStep = 0;
        
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Blend(anim_weaponFire, 4.0f * speedMul, 40.0f * speedMul, ANF_LOOP);
        chargeStep = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
        float t = self.AnimState().PlayTime();
		self.RunFxEvent("AcceleratorChargeEnd");

        if(t >= 4.0f * speedMul)
        {
            self.PlaySound("sounds/shaders/generic_194.ksnd");
            self.FireProjectile("fx/BP_Player_ShockwaveE.kfx", 4.096f, 25.696f, -14.336f);
            self.Owner().ConsumeAmmo(25);
        }
        else if(t >= 3.0f * speedMul)
        {
            self.PlaySound("sounds/shaders/generic_193.ksnd");
            self.FireProjectile("fx/BP_Player_ShockwaveD.kfx", 4.096f, 25.696f, -14.336f);
            self.Owner().ConsumeAmmo(18);
        }
        else if(t >= 2.0f * speedMul)
        {
            self.PlaySound("sounds/shaders/generic_192.ksnd");
            self.FireProjectile("fx/BP_Player_ShockwaveC.kfx", 4.096f, 25.696f, -14.336f);
            self.Owner().ConsumeAmmo(10);
        }
        else if(t >= 1.0f * speedMul)
        {
            self.PlaySound("sounds/shaders/generic_191.ksnd");
            self.FireProjectile("fx/BP_Player_ShockwaveB.kfx", 4.096f, 25.696f, -14.336f);
            self.Owner().ConsumeAmmo(4);
        }
        else
        {
            self.PlaySound("sounds/shaders/generic_190.ksnd");
            self.FireProjectile("fx/BP_Player_ShockwaveA.kfx", 4.096f, 25.696f, -14.336f);
            self.Owner().ConsumeAmmo(2);
        }
        
        chargeStep = 0;
        
        self.StopLoopingSounds();
        self.Owner().Actor().LoudNoiseAlert();
        self.AnimState().Blend(anim_weaponFireCharged, 4.0f * speedMul, 4.0f * speedMul, ANF_NOINTERRUPT);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		TurokWeapon::OnTick();
        if(self.AnimState().PlayingID() == anim_weaponFire)
        {
            switch(chargeStep)
            {
            case 0:
                if(self.AnimState().PlayTime() >= 0.0f)
                {
					self.RunFxEvent("AcceleratorCharge1");
                    self.PlaySound("sounds/shaders/generic_160.ksnd");
                    chargeStep++;
                }
                break;
            case 1:
                if(self.AnimState().PlayTime() >= 1.0f * speedMul)
                {
					self.RunFxEvent("AcceleratorCharge2");
                    self.PlaySound("sounds/shaders/generic_161.ksnd");
                    chargeStep++;
                }
                break;
            case 2:
                if(self.AnimState().PlayTime() >= 2.0f * speedMul)
                {
					self.RunFxEvent("AcceleratorCharge3");
                    self.PlaySound("sounds/shaders/generic_162.ksnd");
                    chargeStep++;
                }
                break;
            case 3:
                if(self.AnimState().PlayTime() >= 3.0f * speedMul)
                {
					self.RunFxEvent("AcceleratorCharge4");
                    self.PlaySound("sounds/shaders/generic_163.ksnd");
                    chargeStep++;
                }
                break;
            case 4:
                if(self.AnimState().PlayTime() >= 4.0f * speedMul)
                {
					self.RunFxEvent("AcceleratorCharge5");
                    self.PlaySound("sounds/shaders/generic_164.ksnd");
                    chargeStep++;
                }
                break;
            }
        }
        
        switch(self.AnimState().PlayingID())
        {
        case anim_weaponSwapOut:
            acceleratorCycleSpeed = 4;
            self.RenderModel().SetRotationOffset(1, 0, 0, 1, 0);
            break;
            
        case anim_weaponIdle:
        case anim_weaponWalk:
        case anim_weaponRun:
        case anim_weaponFireCharged:
            acceleratorCycleSpeed = (2 - acceleratorCycleSpeed) * 0.025f + acceleratorCycleSpeed;
            acceleratorSpinAngle += acceleratorCycleSpeed * (1.0f / 120.0f);
            self.RenderModel().SetRotationOffset(1, acceleratorSpinAngle, 0, 1, 0);
            break;
            
        case anim_weaponFire:
            acceleratorCycleSpeed = (20 - acceleratorCycleSpeed) * (0.01f*GAME_FRAME_TIME) + acceleratorCycleSpeed;
            acceleratorSpinAngle += acceleratorCycleSpeed * (1.0f / 120.0f);
            self.RenderModel().SetRotationOffset(1, acceleratorSpinAngle, 0, 1, 0);
            break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnLower(void)
    {
		TurokWeapon::OnLower();
        acceleratorCycleSpeed = 4;
        acceleratorSpinAngle = 0;
        self.RenderModel().SetRotationOffset(1, 0, 0, 1, 0);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnHoldster(void)
    {
        acceleratorCycleSpeed = 4;
        acceleratorSpinAngle = 0;
        self.RenderModel().SetRotationOffset(1, 0, 0, 1, 0);
        self.StopSound();
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokFusionCannon : TurokWeapon
{   
    bool bFiredFusion;
	//------------------------------------------------------------------------------------------------------------------------
    TurokFusionCannon(kWeapon @actor)
    {
        bFiredFusion = false;
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void PlaySoundWeaponReady()
	{
		Game.PlaySound("sounds/shaders/ready_tek_weapon_2.ksnd");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnRaise(void)
    {
		TurokWeapon::OnRaise();
        self.RenderModel().HideSection(3, 1, false);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnLower(void)
    {
		TurokWeapon::OnLower();
        self.RenderModel().HideSection(3, 1, true);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnPostBeginLevel(void)
    {
        self.RenderModel().HideSection(3, 1, true);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 4.0f, 0);
		
        bFiredFusion = false;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		TurokWeapon::OnTick();
        int animID = self.AnimState().PlayingID();
        
        if(animID == anim_weaponFire)
        {
			if (self.AnimState().TrackTime() <= 0.5f)
			{
				self.AnimState().ChangeSpeed(0.2f);
			}
			else
			{
				self.AnimState().ChangeSpeed(3.0f);
			}
			
            if(!bFiredFusion && self.AnimState().TrackTime() >= 0.65f)
            {
                bFiredFusion = true;
				self.PlaySound("sounds/shaders/tek_weapon_2.ksnd");
                
                if(Game.GetCurrentMapID() == 0)
                {
                    self.FireProjectile("fx/projectile_fusionshot_defect.kfx", 4.096f, 25.6f, -14.336f);
                }
                else
                {
                    self.FireProjectile("fx/BP_Player_Fusion.kfx", 4.096f, 25.6f, -14.336f);
                }
                
                self.Owner().Actor().LoudNoiseAlert();
                self.Owner().ConsumeAmmo(1);
            }
        }
        else if(animID == anim_weaponSwapOut)
        {
            if(self.AnimState().TrackTime() >= 0.3f)
            {
                self.RenderModel().HideSection(3, 1, true);
            }
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokChrono : TurokWeapon
{
	float chronoChargeTime;
    TurokChrono(kWeapon @actor)
    {
        chronoChargeTime = 0.0f;
        super(actor);
    }
	
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Blend(anim_weaponFire, 4.0f, 60.0f, ANF_LOOP);
        chronoChargeTime = 0;
    }
    
    void OnEndFire(void)
    {
		TurokWeapon::OnEndFire();
        float t = self.AnimState().PlayTime() + chronoChargeTime;
    
        if(t >= 1.0f)
        {
			self.FireProjectile("fx/BP_Player_Chronscepter2.kfx", 4.096f, 25.6f, -14.336f);
            self.PlaySound("sounds/shaders/shockwave_weapon_fire.ksnd");
            self.AnimState().Blend(anim_weaponFireCharged, 4.0f, 4.0f, 0);
            self.Owner().Actor().LoudNoiseAlert();
            self.Owner().ConsumeAmmo(1);
            chronoChargeTime = 0;
        }
        else
        {
            self.AnimState().Blend(anim_weaponIdle, 4.0f, 8.0f, 0);
        }
    }
    
    void OnTick(void)
    {
		TurokWeapon::OnTick();
        switch(self.AnimState().PlayingID())
        {
        case anim_weaponFireCharged:
            if((self.AnimState().flags & ANF_STOPPED) != 0)
            {
                self.AnimState().Blend(anim_weaponIdle, 4.0f, 8.0f, 0);
            }
            break;
        }
    }
	
	//------------------------------------------------------------------------------------------------------------------------
    // TurokChrono(kWeapon @actor)
    // {
        // super(actor);
    // }
	// //------------------------------------------------------------------------------------------------------------------------
    // void OnBeginFire(void)
    // {
		// if (!CheckBeginFire())
			// return;
		// TurokWeapon::OnBeginFire();

		// if (GetPlayerChronoUpgrade())
		// {
			// self.FireProjectile("fx/BP_Player_Chronscepter.kfx", 4.096f, 25.6f, -14.336f);
			// self.PlaySound("sounds/shaders/shockwave_weapon_fire.ksnd");
			// self.AnimState().Blend(anim_weaponFireCharged, 2.0f, 4.0f, 0);
			// self.Owner().Actor().LoudNoiseAlert();
			// self.Owner().ConsumeAmmo(1);
		// }
		// else
		// {
			// self.FireProjectile("fx/BP_Player_Chrono.kfx", 30.096f, 5.6f, -14.336f);
			// self.PlaySound("sounds/shaders/BP_Chrono_Fire.ksnd");
			// self.AnimState().Blend(anim_weaponFireCharged, 0.8f, 4.0f, 0);
			// self.Owner().Actor().LoudNoiseAlert();
			// self.Owner().ConsumeAmmo(1);
		// }
    // }
	// //------------------------------------------------------------------------------------------------------------------------
    // void OnTick(void)
    // {
		// TurokWeapon::OnTick();
        // switch(self.AnimState().PlayingID())
        // {
        // case anim_weaponFireCharged:
            // if((self.AnimState().flags & ANF_STOPPED) != 0)
            // {
                // self.AnimState().Blend(anim_weaponIdle, 4.0f, 8.0f, 0);
            // }
            // break;
        // }
    // }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokBowRope : TurokWeapon
{   
	//------------------------------------------------------------------------------------------------------------------------
    TurokBowRope(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void OnRaise()
	{
		TurokWeapon::OnRaise();
		self.RunFxEvent("RopeBow");
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.PlaySound("sounds/shaders/bow_stretch.ksnd");
        self.AnimState().Blend(anim_weaponFire, 4.0f, 20.0f, ANF_LOOP);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
        float time = self.AnimState().PlayTime();
        kPuppet @src = self.Owner().Actor();
        kVec3 origin = src.Origin();
        kQuat rotation = src.Rotation();
        kVec3 velocity;
        
        origin.z += (5*GAME_SCALE);
        origin += (kVec3(0.07f*GAME_SCALE, 2.9f*GAME_SCALE, -0.6f*GAME_SCALE) * rotation);
        velocity = kVec3(0.0f, (384.0f * Math::Minf(time, 1.4f) / 1.4f) * 15.0f, 0.0f) * rotation;
        velocity *= GAME_DELTA_TIME;
		
		kActor @arrowActor = ActorFactory.Spawn("BP_RopeProjectile", origin.x, origin.y, origin.z, src.Yaw(), src.SectorIndex());
		BP_RopeProjectile @projActor = cast<BP_RopeProjectile@>(arrowActor.ScriptObject().obj);
		projActor.Setup(velocity);
		
		self.PlaySound("sounds/shaders/arrow_fly_normal.ksnd");
        self.PlaySound("sounds/shaders/bow_twang.ksnd");
        self.AnimState().Set(anim_weaponFireCharged, 4.0f, ANF_NOINTERRUPT);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnTick(void)
    {
		TurokWeapon::OnTick();
		if (self.GameTicks() == 0)
		{
			self.RunFxEvent("RopeBow");
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class AdonPulse : TurokWeapon
{   
    float pulseRifleFireTime;
	float lastShotTime;
	//------------------------------------------------------------------------------------------------------------------------
    AdonPulse(kWeapon @actor)
    {
        pulseRifleFireTime = 0;
		lastShotTime = 0.0f;
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

		self.RenderModel().SetTexture(0, 1);
        self.AnimState().Blend(anim_weaponFireLoop, 4.0f, 4.0f, ANF_LOOP);
        pulseRifleFireTime = -0.08f;
		if (lastShotTime <= 0.0f)
		{
			FireShot();
		}
    }
	//------------------------------------------------------------------------------------------------------------------------
	void FireShot()
	{
		lastShotTime = 1.0f;
		
        kPuppet @src = self.Owner().Actor();
        kVec3 origin = src.Origin();
        kQuat rotation = src.Rotation();
        kVec3 velocity;
        
        origin.z += (5*GAME_SCALE);
        origin += (kVec3(0.07f*GAME_SCALE, 2.9f*GAME_SCALE, -0.6f*GAME_SCALE) * rotation);
        velocity = kVec3(0.0f, 384.0f * 15.0f, 0.0f) * rotation;
        velocity *= GAME_DELTA_TIME;
		
		self.PlaySound("sounds/shaders/BP_Adon_Grapple.ksnd");
		//self.FireProjectile("fx/BP_Adon_Grapple.kfx", 10.24f, -10.96f, -9.216f);
		kActor @arrowActor = ActorFactory.Spawn("BP_AdonRopeProjectile", origin.x, origin.y, origin.z, src.Yaw(), src.SectorIndex());
		BP_AdonRopeProjectile @projActor = cast<BP_AdonRopeProjectile@>(arrowActor.ScriptObject().obj);
		projActor.Setup(velocity);
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        float playTime = self.AnimState().PlayTime();
        if ((playTime - pulseRifleFireTime) >= 0.5f)
        {
			FireShot();
            pulseRifleFireTime = playTime;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
		self.RenderModel().SetTexture(0, 0);
        self.AnimState().Blend(anim_weaponIdle, 4.0f, 4.0f, ANF_LOOP);
        pulseRifleFireTime = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnRaise(void)
    {
		TurokWeapon::OnRaise();
		lastShotTime = 0.0f;
    }
	//------------------------------------------------------------------------------------------------------------------------
	void OnTick()
	{
		TurokWeapon::OnTick();
		lastShotTime -= GAME_DELTA_TIME;
	}
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class AdonShotgun : TurokWeapon
{   
	//------------------------------------------------------------------------------------------------------------------------
    AdonShotgun(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

		self.PlaySound("sounds/shaders/BP_Adon_Shotgun.ksnd");
        self.FireProjectile("fx/BP_Player_Adon_Shotgun.kfx", 12.28f, 25.6f, -7.168f);
		self.Owner().ConsumeAmmo(1);
        self.AnimState().Set(anim_weaponFire, 2.4f, 0);
        self.Owner().Actor().LoudNoiseAlert();
        //self.Owner().Actor().RecoilPitch() = -0.03926990926265717f;
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class AdonRocketLauncher : TurokWeapon
{   
    AdonRocketLauncher(kWeapon @actor)
    {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 2.0f, 0);
        self.PlaySound("sounds/shaders/missile_launch.ksnd");
		self.FireProjectile("fx/BP_Player_Adon_Rocket.kfx", 4.096f, 5.696f, -14.336f);
		self.Owner().ConsumeAmmo(1);
        self.Owner().Actor().LoudNoiseAlert();
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class AdonHand : TurokWeapon
{   
	bool hasAltAmmo;
	bool isFiring;
	int shots;
	//------------------------------------------------------------------------------------------------------------------------
    AdonHand(kWeapon @actor)
    {
        super(actor);
		hasAltAmmo = false;
		isFiring = false;
		shots = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

		self.AnimState().Blend(anim_weaponFire, 1.0f, 4.0f, ANF_LOOP);
		self.AnimState().SetLastFrame();
		self.PlaySound("sounds/shaders/adon_hand.ksnd");
		self.RenderModel().SetTexture(0, 2);
		isFiring = true;
    }
	//------------------------------------------------------------------------------------------------------------------------
	void OnFire()
	{
		if (self.GameTicks() % 3 == 0)
		{
			self.FireProjectile("fx/BP_Player_Adon_Hand.kfx", 24.096f, 25.696f, -14.336f);
			self.Owner().Actor().LoudNoiseAlert();
			shots++;
			if (shots == 3)
			{
				shots = 0;
				self.Owner().ConsumeAmmo(Player.HasAltAmmo() ? 30 : 1);
			}
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnEndFire(void)
    {
		isFiring = false;
		self.RenderModel().SetTexture(0, 0);
        self.StopLoopingSounds();
        self.AnimState().Blend(anim_weaponFireCharged, 4.0f, 4.0f, ANF_NOINTERRUPT);
	}
	//------------------------------------------------------------------------------------------------------------------------
	void OnTick()
	{
		TurokWeapon::OnTick();
		if (isFiring && !Player.HasAmmo(17) && !Player.HasAltAmmo())
		{
			self.StopLoopingSounds();
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
final class TurokFreezeGun : TurokWeapon
{   
    int rifleShotsFired;
	//bool consumeAmmo;
	//------------------------------------------------------------------------------------------------------------------------
    TurokFreezeGun(kWeapon @actor)
    {
        rifleShotsFired = 0;
		//consumeAmmo = false;
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
    void OnBeginFire(void)
    {
		if (!CheckBeginFire())
			return;
		TurokWeapon::OnBeginFire();

        self.AnimState().Set(anim_weaponFire, 1.0f, 0);
        rifleShotsFired = 0;
    }
	//------------------------------------------------------------------------------------------------------------------------
	void FireShot()
	{
		//self.PlaySound("sounds/shaders/rifle_shot.ksnd");
		//self.FireProjectile("fx/bullet_shell.kfx", 11.26f, 27.64f, -8.192f, true);
		//self.FireProjectile("fx/weffect_assaultrifle.kfx", 5.12f+0.35f, 29.69f, -3.584f-0.5f);
		//self.FireProjectile("fx/BP_Player_Rifle.kfx", 10.24f, 25.6f, -10.24f);
		//self.PlaySound("sounds/shaders/shockwave_weapon_fire.ksnd");
		self.PlaySound("sounds/shaders/freeze2.ksnd");
		self.FireProjectile("fx/BP_Player_Freeze.kfx", -1.24f, 25.6f, -25.24f);
		
		//self.RunFxEvent("GunFire");
		self.Owner().Actor().LoudNoiseAlert();
		//self.Owner().Actor().RecoilPitch() = -0.02416609786450863f;
		//if (consumeAmmo)
		self.Owner().ConsumeAmmo(1);
		//consumeAmmo = !consumeAmmo;
		rifleShotsFired++;
	}
	//------------------------------------------------------------------------------------------------------------------------
    void OnFire(void)
    {
        switch(rifleShotsFired)
        {
        case 0:
            if(self.AnimState().PlayTime() >= 0.0f)
            {
				FireShot();
            }
            break;
            
        case 1:
            if(self.AnimState().PlayTime() >= 0.33f)
            {
				// FireShot();
            }
            break;
            
        case 2:
            if(self.AnimState().PlayTime() >= 0.66f)
            {
				// FireShot();
            }
            break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
}
//========================================================================================================================
