/*
 * Weapon:  Elite_Weapon
 * The Base of Most Elite Machine Weapons
 * By: *PingFre@K*
 * Copyright 1998-2007 Epic Games, Inc. All Rights Reserved.
*/

class Elite_Weapon extends UTWeapon
	HideDropDown;

/////////////////////////////////////////////////////////////////
// Dual Vars
/////////////////////////////////////////////////////////////////

enum EDualMode
{
	EDM_SingleWeapon,
	EDM_DualEquipping,
	EDM_Dual,
	EDM_Max
};

/** if true, we are a dual Elite_Weapon */
var repnotify EDualMode	DualMode;

var UIRoot.TextureCoordinates DualIconCoordinates;

/** The Left Handed Mesh */
var() editinline UTSkeletalMeshComponent LeftMesh;

var protected UTSkeletalMeshComponent OverlayLeftMesh;
/** timeseconds when last fired */
var float LastFireTime;

/** if the last shot was fired from the left Elite_Weapon*/
var bool bLastFiredLeft;

/** If true this weapon won't play the reload anim */
var bool bLoaded;

var name WeaponDualEqipAnim;

/** Amount of time it takes to equip the left gun */
var float DualEquiptime;

/** Used internally to track which gun to fire */
var int ShotCount;

/** If we become a dual while firing, force return to the active state in order to properly re-initialize */
var bool bForceReturnToActive;

//var bool bFullDualCoolDown;

var MaterialInstanceConstant WeaponMaterialInstance;
var MaterialInstanceConstant LeftWeaponMaterialInstance;
/** Left versions of everything */

/** Muzzle flash PSC and Templates*/
var UTParticleSystemComponent	EliteMachine_MuzzleFlashPSC[2];

/** dynamic light */
var	UTExplosionLight		EliteMachine_MuzzleFlashLight[2];

/** anim played for left mesh when idling */
var name LeftIdleAnim;

/////////////////////////////////////////////////////////////////
// Replication
/////////////////////////////////////////////////////////////////

replication
{
	if (bNetDirty)
		DualMode;
}

/////////////////////////////////////////////////////////////////
// Spread from enforcer
// This allows the spread adjustment for certain weapons
/////////////////////////////////////////////////////////////////

simulated function rotator AddSpread(rotator BaseAim)
{
	return Super.AddSpread(BaseAim);
}

/////////////////////////////////////////////////////////////////
// Dual Equip from Enforcer
// This code will work with most Skeletal Meshes
/////////////////////////////////////////////////////////////////

/**
 * Set the Overlay Meshes
 */
simulated function CreateOverlayMesh()
{
	local UTPawn P;

	if ( WorldInfo.NetMode != NM_Client )
	{
		P = UTPawn(Instigator);
		if ( (P == None) || !P.bUpdateEyeHeight )
		{
			return;
		}
	}

	Super.CreateOverlayMesh();

	if (WorldInfo.NetMode != NM_DedicatedServer && LeftMesh != None && OverlayLeftMesh == None)
	{
		OverlayLeftMesh = new(outer) LeftMesh.Class;
		if (OverlayLeftMesh != None)
		{
			OverlayLeftMesh.SetScale(1.0);
			OverlayLeftMesh.SetOwnerNoSee(LeftMesh.bOwnerNoSee);
			OverlayLeftMesh.SetDepthPriorityGroup(SDPG_Foreground);
			OverlayLeftMesh.SetSkeletalMesh(LeftMesh.SkeletalMesh);
			OverlayLeftMesh.AnimSets = LeftMesh.AnimSets;
			OverlayLeftMesh.SetParentAnimComponent(LeftMesh);
			OverlayLeftMesh.SetFOV(LeftMesh.FOV);
		}
	}
}

/*
  * Adjust weapon equip and fire timings so they match between PC and console
  * This is important so the sounds match up.
*/
simulated function AdjustWeaponTimingForConsole()
{
	Super.AdjustWeaponTimingForConsole();
	DualEquipTime = DualEquipTime/1.1;
}

/*
 * Setup the overlay skins
*/
simulated function SetSkin(Material NewMaterial)
{
	local int i,Cnt;
	Super.SetSkin(NewMaterial);

	if ( LeftMesh != none && NewMaterial == None )	// Clear the materials
	{
		if ( default.Mesh.Materials.Length > 0 )
		{
			Cnt = Default.Mesh.Materials.Length;
			for (i=0;i<Cnt;i++)
			{
				LeftMesh.SetMaterial( i, Default.Mesh.GetMaterial(i) );
			}
		}
		else if (LeftMesh.Materials.Length > 0)
		{
			Cnt = LeftMesh.Materials.Length;
			for ( i=0; i < Cnt; i++ )
			{
				LeftMesh.SetMaterial(i,none);
			}
		}
	}
	else if( LeftMesh != none )
	{
		if ( default.LeftMesh.Materials.Length > 0 || Leftmesh.GetNumElements() > 0 )
		{
			Cnt = default.LeftMesh.Materials.Length > 0 ? default.LeftMesh.Materials.Length : LeftMesh.GetNumElements();
			for ( i=0; i < Cnt; i++ )
			{
				LeftMesh.SetMaterial(i,NewMaterial);
			}
		}
	}

	if( NewMaterial==none )
	{
		WeaponMaterialInstance = MaterialInstanceConstant(Mesh.Materials[0]);
		if(WeaponMaterialInstance == none)
		{
			WeaponMaterialInstance = Mesh.CreateAndSetMaterialInstanceConstant(0);
		}

		// if we have a leftmesh
		if( LeftMesh != none )
		{
			LeftWeaponMaterialInstance = MaterialInstanceConstant(LeftMesh.Materials[0]);
			if(LeftWeaponMaterialInstance == none)
			{
				LeftWeaponMaterialInstance = LeftMesh.CreateAndSetMaterialInstanceConstant(0);
			}
		}
	}
}

/**
 * Extend support to allow for multiple muzzle flashes
 */
simulated function AttachMuzzleFlash()
{
	local int i;

	bMuzzleFlashAttached = true;
	if (MuzzleFlashPSCTemplate != none)
	{
		EliteMachine_MuzzleFlashPSC[0]  = new(Outer) class'UTParticleSystemComponent';
		EliteMachine_MuzzleFlashPSC[1]  = new(Outer) class'UTParticleSystemComponent';

		for (i=0;i<2;i++)
		{
			EliteMachine_MuzzleFlashPSC[i].SetDepthPriorityGroup(SDPG_Foreground);
			EliteMachine_MuzzleFlashPSC[i].DeactivateSystem();
			EliteMachine_MuzzleFlashPSC[i].SetColorParameter('MuzzleFlashColor', MuzzleFlashColor);
		}

		EliteMachine_MuzzleFlashPSC[0].SetFOV(UTSkeletalMeshComponent(Mesh).FOV);
		SkeletalMeshComponent(Mesh).AttachComponentToSocket(EliteMachine_MuzzleFlashPSC[0], MuzzleFlashSocket);
		if (LeftMesh != None)
		{
			EliteMachine_MuzzleFlashPSC[1].SetFOV(LeftMesh.FOV);
			LeftMesh.AttachComponentToSocket(EliteMachine_MuzzleFlashPSC[1], MuzzleFlashSocket);
		}
	}
}

/*
 * Detach weapon from skeletal mesh
 * @param	SkeletalMeshComponent weapon is attached to.
*/
simulated function DetachMuzzleFlash()
{
	bMuzzleFlashAttached = false;
	if (EliteMachine_MuzzleFlashPSC[0] != None)
	{
		SkeletalMeshComponent(Mesh).DetachComponent(EliteMachine_MuzzleFlashPSC[0]);
		EliteMachine_MuzzleFlashPSC[0] = None;
	}
	if (EliteMachine_MuzzleFlashPSC[1] != None)
	{
		if (LeftMesh != None)
		{
			LeftMesh.DetachComponent(EliteMachine_MuzzleFlashPSC[1]);
		}
		EliteMachine_MuzzleFlashPSC[1] = None;
	}
}

/**
 * This function is called from the pawn when the visibility of the weapon changes
 */
simulated function ChangeVisibility(bool bIsVisible)
{
	Super.ChangeVisibility(bIsVisible);

	if (DualMode != EDM_SingleWeapon)
	{
		if (LeftMesh != None)
		{
			LeftMesh.SetHidden(!bIsVisible);
		}
		if (OverlayLeftMesh != none)
		{
			OverlayLeftMesh.SetHidden(!bIsVisible);
		}
	}
}

/*
 * When the Pawn's WeaponOverlay flag changes, handle it here
*/
simulated function SetWeaponOverlayFlags(UTPawn OwnerPawn)
{
	local MaterialInterface InstanceToUse;
	local byte Flags;
	local int i;
	local UTGameReplicationInfo GRI;

	Super.SetWeaponOverlayFlags(OwnerPawn);

	if ( DualMode != EDM_SingleWeapon )
	{
		GRI = UTGameReplicationInfo(WorldInfo.GRI);
		if (GRI != None)
		{
			Flags = OwnerPawn.WeaponOverlayFlags;
			for (i = 0; i < GRI.WeaponOverlays.length; i++)
			{
				if (GRI.WeaponOverlays[i] != None && bool(Flags & (1 << i)))
				{
					InstanceToUse = GRI.WeaponOverlays[i];
					break;
				}
			}
		}

		if (InstanceToUse != none)
		{
			if ( OverlayLeftMesh != none )
			{
				for (i=0;i<OverlayLeftMesh.GetNumElements(); i++)
				{
					OverlayLeftMesh.SetMaterial(i, InstanceToUse);
				}

				if (!OverlayLeftMesh.bAttached)
				{
					AttachComponent(OverlayLeftMesh);
					OverlayLeftMesh.SetHidden(false);
				}
			}
		}
		else if (OverlayLeftMesh != none && OverlayLeftMesh.bAttached)
		{
			OverlayLeftMesh.SetHidden(true);
			DetachComponent(OverlayLeftMesh);
		}
	}
}

/**
 * Turns the MuzzleFlashlight off
 */
simulated event MuzzleFlashOff(int Index)
{
	if ( EliteMachine_MuzzleFlashPSC[Index] != none )
	{
		EliteMachine_MuzzleFlashPSC[Index].DeactivateSystem();
	}
}

simulated event MuzzleFlashTimerLeft()
{
	MuzzleFlashOff(1);
}

simulated event MuzzleFlashTimerRight()
{
	MuzzleFlashOff(0);
}

/**
 * Causes the muzzle flashlight to turn on
 */
simulated event CauseMuzzleFlashLight()
{
	local int Index;

	if ( WorldInfo.bDropDetail )
		return;

	Index = UseLeftBarrel() ? 1 : 0;

	if ( EliteMachine_MuzzleFlashLight[Index] != None )
	{
		EliteMachine_MuzzleFlashLight[Index].ResetLight();
	}
	else if ( MuzzleFlashLightClass != None )
	{
		EliteMachine_MuzzleFlashLight[Index] = new(Outer) MuzzleFlashLightClass;
		if ( Index == 1 )
			LeftMesh.AttachComponentToSocket(EliteMachine_MuzzleFlashLight[Index],MuzzleFlashSocket);
		else
			SkeletalMeshComponent(Mesh).AttachComponentToSocket(EliteMachine_MuzzleFlashLight[Index],MuzzleFlashSocket);
	}
}

/**
 * Causes the muzzle flashlight to turn on and setup a time to
 * turn it back off again.
 */
simulated event CauseMuzzleFlash()
{
	local int Index;
	local UTPawn P;

	if ( WorldInfo.NetMode != NM_Client )
	{
		P = UTPawn(Instigator);
		if ( (P == None) || !P.bUpdateEyeHeight )
		{
			return;
		}
	}
	if ( !bMuzzleFlashAttached )
	{
		AttachMuzzleFlash();
	}
	CauseMuzzleFlashLight();

	if (GetHand() != HAND_Hidden)
	{
		Index = UseLeftBarrel() ? 1 : 0;

		if (EliteMachine_MuzzleFlashPSC[Index] != none)
		{
			EliteMachine_MuzzleFlashPSC[Index].SetTemplate(MuzzleFlashPSCTemplate);
			EliteMachine_MuzzleFlashPSC[Index].SetVectorParameter('MFlashScale',Vect(0.5,0.5,0.5));
			EliteMachine_MuzzleFlashPSC[Index].ActivateSystem();
		}

		// Set when to turn it off.
		if (Index > 0 )
		{
			SetTimer(MuzzleFlashDuration,false,'MuzzleFlashTimerLeft');
		}
		else
		{
			SetTimer(MuzzleFlashDuration,false,'MuzzleFlashTimerRight');
		}
	}
}

simulated event StopMuzzleFlash()
{
	ClearTimer('MuzzleFlashTimerLeft');
	ClearTimer('MuzzleFlashTimerRight');
	MuzzleFlashOff(0);
	MuzzleFlashOff(1);
}

/*
 * On a remote client, watch for a change in bDualMode and if it changes, signal this has become a dual
 * weapon.
*/
simulated event ReplicatedEvent(name VarName)
{
	if (VarName == 'DualMode')
	{
		BecomeDual();
	}
	else
	{
		Super.ReplicatedEvent(VarName);
	}
}

/**
 * Become a dual firing weapon.  Right now this isn't important unless the instigator is the local client.
 * If it is, then show the second mesh and play any needed "Equipping" animations
 */
simulated function BecomeDual()
{
	local UTPawn P;

	IconCoordinates = (DualMode == EDM_SingleWeapon) ? default.IconCoordinates : DualIconCoordinates;
	if ( DualMode == EDM_DualEquipping )
	{
//		MaxAmmoCount = 2 * Default.MaxAmmoCount;       // Double the ammo w/ second pickup
		if (LeftMesh == None)
		{
			LeftMesh = UTSkeletalMeshComponent(new(self) Mesh.Class(Mesh));
			LeftMesh.SetScale3D(Mesh.Scale3D * vect(1,-1,1));
			AttachComponent(LeftMesh);
		}
		P = UTPawn(Instigator);
		if (P != None)
		{
			if (P.WeaponOverlayFlags != 0)
			{
				CreateOverlayMesh();
			}
			SetWeaponOverlayFlags(P);
		}
		SetTimer(DualEquiptime, false, 'DualEquipDone');
		if (P != None)
		{
			if (!Mesh.HiddenGame)
			{
				LeftMesh.SetHidden(false);
				if (WorldInfo.NetMode != NM_DedicatedServer && Instigator.Weapon == self)
				{
					bUsesOffhand = true;
				}
			}

			P.bDualWielding = true;
			if (P.CurrentWeaponAttachment != None)
			{
				P.CurrentWeaponAttachment.SetDualWielding(true);
			}
		}
		if (EliteMachine_MuzzleFlashPSC[1] != None)
		{
			EliteMachine_MuzzleFlashPSC[1].SetFOV(LeftMesh.FOV);
			LeftMesh.AttachComponentToSocket(EliteMachine_MuzzleFlashPSC[1], MuzzleFlashSocket);
		}
		PlayWeaponAnimation( WeaponDualEqipAnim, DualEquiptime,, LeftMesh );
	}
}

simulated function AttachWeaponTo(SkeletalMeshComponent MeshCpnt, optional Name SocketName )
{
	local UTPawn UTP;

	UTP = UTPawn(Instigator);
	if (UTP != None)
	{
		if (DualMode != EDM_SingleWeapon)
		{
			UTP.bDualWielding = true;
			if (UTP.CurrentWeaponAttachment != None)
			{
				UTP.CurrentWeaponAttachment.SetDualWielding(true);
			}
		}
		if(UTP.IsFirstPerson())
		{
			if( LeftMesh != none )
			{
				LeftMesh.SetLightEnvironment(UTP.LightEnvironment);
			}
		}
	}
	Super.AttachWeaponTo(MeshCpnt, SocketName);
}

simulated function DetachWeapon()
{
	if( LeftMesh != none )
	{
		LeftMesh.SetLightEnvironment(None);
	}

	super.DetachWeapon();
}

/**
 * The equip animation is done, notify the weapon and become usuable
 */
simulated function DualEquipDone()
{
	ShotCount = 0;
	DualMode = EDM_Dual;
	BecomeDual();
}

/*
 * Adjust the second weapon
 * This may need changes per weapon
 */
simulated event SetPosition(UTPawn Holder)
{
	local vector OldSmallWeaponsOffset;

	if (LeftMesh != None)
	{
		switch (GetHand())
		{
			case HAND_Left:
				LeftMesh.SetScale3D(default.Mesh.Scale3D);
				break;
			case HAND_Right:
				LeftMesh.SetScale3D(default.Mesh.Scale3D * vect(1,-1,1));
				break;
			default:
				break;
		}
	}

	OldSmallWeaponsOffset = SmallWeaponsOffset;
	if (DualMode != EDM_SingleWeapon)
	{
	    SmallWeaponsOffset.Y = -1.0;
	    PlayerViewOffset.Y = -1.0;
	}

	Super.SetPosition(Holder);
	SmallWeaponsOffset = OldSmallWeaponsOffset;
}

/*
 * Detect that we are trying to pickup another Gun and switch in to dual mode.
 */
function bool DenyPickupQuery(class<Inventory> ItemClass, Actor Pickup)
{
//	if (ItemClass==Class && DualMode != EDM_Dual)
//	{
//		DualMode = EDM_DualEquipping;
//		BecomeDual();			// Handle any animations/effects locally.
//	}

	return super.DenyPickupQuery(ItemClass, Pickup);
}

/**
 * Returns the rate at which the weapon fires.  If in dual mode, 1/2 the rate
 * Or Twice as fast
 * @See Weapon.GetFireInterval()

simulated function float GetFireInterval(byte FireModeNum)
{
	local float FI;

	FI = Super.GetFireInterval(FireModeNum);
	if (FireModeNum == 0 && DualMode == EDM_Dual || FireModeNum == 1 && DualMode == EDM_Dual)
	{
		FI *= 0.5;
	}
	return FI;
}
 */
simulated function InstantFire()
{
	Super.InstantFire();
	LastFireTime = WorldInfo.TimeSeconds;
}

simulated function vector GetEffectLocation()
{
	local vector SocketLocation;

	if (bLastFiredLeft && GetHand() != HAND_Hidden)
	{
		if (LeftMesh!=none && EffectSockets[CurrentFireMode]!='')
		{
			if (!LeftMesh.GetSocketWorldLocationAndrotation(EffectSockets[CurrentFireMode], SocketLocation))
			{
				SocketLocation = Location;
			}
		}
		else if (LeftMesh!=none)
		{
			SocketLocation = LeftMesh.Bounds.Origin + (vect(45,0,0) >> Rotation);
		}
		else
		{
			SocketLocation = Location;
		}

 		return SocketLocation;
	}
	else
	{
		return super.GetEffectLocation();
	}
}

/**
 * By default, we track each shot so that the 2nd weapon will work.  Bursting overrides this function
 */

simulated function TrackShotCount()
{
	ShotCount++;
}

/**
 * I override GetPhysicalFireStartLoc to allow firing to alternate between Left and Right hand.
 */
simulated function vector GetPhysicalFireStartLoc(optional vector AimDir)
{
	local UTPlayerController PC;
	local vector FireStartLoc, HitLocation, HitNormal, FireDir, FireEnd, ProjBox;
	local Actor HitActor;
	local rotator FireRot;
	local class<Projectile> FiredProjectileClass;
	local int TraceFlags;

	if( Instigator != none )
	{
		PC = UTPlayerController(Instigator.Controller);

        if( UseLeftBarrel() )
        {
            PC.WeaponHand = HAND_Left;
        }
        else
        {
            PC.WeaponHand = HAND_Right;
        }


		FireRot = Instigator.GetViewRotation();
		FireDir = vector(FireRot);

		//  Here I reversed what couldn't be reversed fixing which gun the proj comes from first  :)
		if (DualMode == EDM_Dual)
		{
		   if (PC == none || PC.bCenteredWeaponFire || PC.WeaponHand == HAND_Centered || PC.WeaponHand == HAND_Hidden)
         {
			   FireStartLoc = Instigator.GetPawnViewLocation() + (FireDir * FireOffset.X);
		   }
		   else if (PC.WeaponHand == HAND_Left)
		   {
			   FireStartLoc = Instigator.GetPawnViewLocation() + (FireOffset >> FireRot);
		   }
		   else
		   {
			   FireStartLoc = Instigator.GetPawnViewLocation() + ((FireOffset * vect(1,-1,1)) >> FireRot);
		   }
		}
      else
		{
		   if (PC == none || PC.bCenteredWeaponFire || PC.WeaponHand == HAND_Centered || PC.WeaponHand == HAND_Hidden)
         {
			   FireStartLoc = Instigator.GetPawnViewLocation() + (FireDir * FireOffset.X);
		   }
		   else if (PC.WeaponHand == HAND_Left)
		   {
			   FireStartLoc = Instigator.GetPawnViewLocation() + ((FireOffset * vect(1,-1,1)) >> FireRot);
		   }
		   else
		   {
			   FireStartLoc = Instigator.GetPawnViewLocation() + (FireOffset >> FireRot);
		   }
		}

		if ( (PC != None) || (CustomTimeDilation < 1.0) )
		{
			FiredProjectileClass = GetProjectileClass();
			if ( FiredProjectileClass != None )
			{
				FireEnd = FireStartLoc + FireDir * ProjectileSpawnOffset;
				TraceFlags = bCollideComplex ? TRACEFLAG_Bullet : 0;
				if ( FiredProjectileClass.default.CylinderComponent.CollisionRadius > 0 )
				{
					FireEnd += FireDir * FiredProjectileClass.default.CylinderComponent.Translation.X;
					ProjBox = FiredProjectileClass.default.CylinderComponent.CollisionRadius * vect(1,1,0);
					ProjBox.Z = FiredProjectileClass.default.CylinderComponent.CollisionHeight;
					HitActor = Trace(HitLocation, HitNormal, FireEnd, Instigator.Location, true, ProjBox,,TraceFlags);
					if ( HitActor == None )
					{
						HitActor = Trace(HitLocation, HitNormal, FireEnd, FireStartLoc, true, ProjBox,,TraceFlags);
					}
					else
					{
						FireStartLoc = Instigator.Location - FireDir*FiredProjectileClass.default.CylinderComponent.Translation.X;
						FireStartLoc.Z = FireStartLoc.Z + FMin(Instigator.EyeHeight, Instigator.CylinderComponent.CollisionHeight - FiredProjectileClass.default.CylinderComponent.CollisionHeight - 1.0);
						PC.WeaponHand = HAND_Right;
						return FireStartLoc;
					}
				}
				else
				{
					HitActor = Trace(HitLocation, HitNormal, FireEnd, FireStartLoc, true, vect(0,0,0),,TraceFlags);
				}
				PC.WeaponHand = HAND_Right;
				return (HitActor == None) ? FireEnd : HitLocation - 3*FireDir;
			}
		}
		PC.WeaponHand = HAND_Right;
		return FireStartLoc;
	}
	PC.WeaponHand = HAND_Right;
   	return Location;
}

/**
 * Determine which gun to use
 */
simulated function bool UseLeftBarrel()
{
	return ( DualMode == EDM_Dual && (ShotCount % 2 > 0 ) );
}

/**
 * Returns the name of the firing animation
 */

simulated function name GetFireAnim(int FireModeNum)
{
	return WeaponFireAnim[FireModeNum];
}

/**
 * We override PlayFireEffects to reoffset the animation rate.  When in dual mode, all firing speeds
 * are 1/2 but we want the animations to play as normal.
 *
 * @See PlayFireEffects
 */

simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation )
{
	local float Rate;
	// Play Weapon fire animation
	Rate = GetFireInterval(FireModeNum);

	// If we are in dual mode, we want to back it out to the normal speed
	if (DualMode == EDM_Dual)
	{
		Rate *= 2;
	}

	if ( FireModeNum < WeaponFireAnim.Length && WeaponFireAnim[FireModeNum] != '' )
	{
		PlayWeaponAnimation( GetFireAnim(FireModeNum), Rate,, UseLeftBarrel() ? LeftMesh : None );
		PlayArmAnimation( GetFireAnim(FireModeNum), Rate, UseLeftBarrel(),, UseLeftBarrel() ? LeftMesh : None );
		bLastFiredLeft=UseLeftBarrel();
	}

	// Start muzzle flash effect
	CauseMuzzleFlash();
	ShakeView();
	TrackShotCount();
}

/**
 * Look to see if bLoaded (ie: has been brought up once) is true and decide which animation to play
 */

simulated function PlayWeaponEquip()
{
	local name Anim;
	local SoundCue EquipSound;

	// Play the animation for the weapon being put down
	if (bLoaded)
	{
		Anim = WeaponEquipAnim;
		EquipSound = WeaponEquipSnd;
	}

	if ( Anim != '' )
	{
		PlayWeaponAnimation( Anim, GetEquipTime() );
		if ( DualMode == EDM_Dual )
		{
			PlayWeaponAnimation( Anim, GetEquipTime(),,LeftMesh);
		}
	}

	// play any assoicated sound
	if (EquipSound != None)
	{
		WeaponPlaySound(EquipSound);
	}
}

/**
 * Added support for handling the 2nd gun
 */
simulated function PlayWeaponPutDown()
{
	// Play the animation for the weapon being put down
	if ( WeaponPutDownAnim != '' )
	{
		PlayWeaponAnimation( WeaponPutDownAnim, PutDownTime );
		if ( DualMode == EDM_Dual )
		{
			PlayWeaponAnimation( WeaponPutDownAnim, PutDownTime,,LeftMesh);
		}
	}

	// play any associated sound
	if ( WeaponPutDownSnd != None )
		WeaponPlaySound( WeaponPutDownSnd );
}

simulated state WeaponEquipping
{
	simulated function WeaponEquipped()
	{
		if( bWeaponPutDown )
		{
			// if switched to another weapon, put down right away
			PutDownWeapon();
			return;
		}
		else
		{
			GotoState('Active');
		}
	}
	simulated function EndState(Name NextStateName)
	{
		Super.EndState(NextStateName);
		bLoaded = true;
	}
}

simulated state WeaponFiring
{

	simulated function BecomeDual()
	{
		Global.BecomeDual();
		if ( DualMode == EDM_Dual )
		{
			bForceReturnToActive=true;
		}
	}

	/**
	 * We poll the PendingFire in RefireCheckTimer() to insure the switch to Burst Firing
	 * respects the current shot timings
	 */

	simulated function RefireCheckTimer()
	{
		// if switching to another weapon, abort firing and put down right away
		if( bWeaponPutDown )
		{
			PutDownWeapon();
			return;
		}

		if (bForceReturnToActive)
		{
			GotoState('Active');
			return;
		}

		if ( PendingFire(1) )
		{
			SendToFiringState(1);
			return;
		}

		Super.RefireCheckTimer();
	}

	simulated function EndState(name NextStateName)
	{
		if (CurrentFireMode == 0 )
		{
			ShotCount = 0;
		}
		super.EndState(NextStateName);
	}
}

simulated function WeaponReady()
{
	// if switching to another weapon, abort firing and put down right away
	if( bWeaponPutDown )
	{
		PutDownWeapon();
	}
	else
		GotoState('Active');
}

simulated state Active
{
	simulated function int LagRot(int NewValue, int LastValue, float MaxDiff, int Index)
	{
		local int RotDiff;
		local float LeadMag, DeltaTime;

		if ( NewValue ClockWiseFrom LastValue )
		{
			if ( LastValue > NewValue )
			{
				LastValue -= 65536;
			}
		}
		else
		{
			if ( NewValue > LastValue )
			{
				NewValue -= 65536;
			}
		}

		DeltaTime = WorldInfo.TimeSeconds - LastRotUpdate;
		RotDiff = NewValue - LastValue;
		if ( DualMode != EDM_DualEquipping )
		{
			if ( (RotDiff == 0) || (OldRotDiff[Index] == 0) )
			{
				LeadMag = ShouldLagRot() ? OldLeadMag[Index] : 0.0;
				if ( (RotDiff == 0) && (OldRotDiff[Index] == 0) )
				{
					OldMaxDiff[Index] = 0;
				}
			}
			else if ( (RotDiff > 0) == (OldRotDiff[Index] > 0) )
			{
				if (ShouldLagRot())
				{
					MaxDiff = FMin(1, Abs(RotDiff)/(12000*DeltaTime)) * MaxDiff;
					if ( OldMaxDiff[Index] != 0 )
						MaxDiff = FMax(OldMaxDiff[Index], MaxDiff);

					OldMaxDiff[Index] = MaxDiff;
					LeadMag = (NewValue > LastValue) ? -1* MaxDiff : MaxDiff;
				}
				else
				{
					LeadMag = 0;
				}
				if ( DeltaTime < 1/RotChgSpeed )
				{
					LeadMag = (1.0 - RotChgSpeed*DeltaTime)*OldLeadMag[Index] + RotChgSpeed*DeltaTime*LeadMag;
				}
				else
				{
					LeadMag = 0;
				}
			}
			else
			{
				LeadMag = 0;
				OldMaxDiff[Index] = 0;
				if ( DeltaTime < 1/ReturnChgSpeed )
				{
					LeadMag = (1 - ReturnChgSpeed*DeltaTime)*OldLeadMag[Index] + ReturnChgSpeed*DeltaTime*LeadMag;
				}
			}
		}
		else
		{
			LeadMag = 0;
			OldMaxDiff[Index] = 0;
			if ( DeltaTime < 1/ReturnChgSpeed )
			{
				LeadMag = (1 - ReturnChgSpeed*DeltaTime)*OldLeadMag[Index] + ReturnChgSpeed*DeltaTime*LeadMag;
			}
		}
		OldLeadMag[Index] = LeadMag;
		OldRotDiff[Index] = RotDiff;

		return NewValue + LeadMag;
	}

	simulated function bool ShouldLagRot()
	{
		return (DualMode != EDM_Dual);
	}

	simulated event OnAnimEnd(optional AnimNodeSequence SeqNode, optional float PlayedTime, optional float ExcessTime)
	{
		Super.OnAnimEnd(SeqNode, PlayedTime, ExcessTime);

		if (WorldInfo.NetMode != NM_DedicatedServer && DualMode == EDM_Dual)
		{
			PlayWeaponAnimation(LeftIdleAnim, 0.0, true, LeftMesh);
		}
	}

	simulated event BeginState(name PreviousStateName)
	{
		bForceReturnToActive = false;
		Super.BeginState(PreviousStateName);
	}
}

defaultproperties
{
	// First Gun
	Begin Object class=AnimNodeSequence Name=MeshSequenceA
	End Object

	// Second Gun
	Begin Object class=AnimNodeSequence Name=MeshSequenceB
	End Object

	// Weapon SkeletalMesh
	Begin Object Name=FirstPersonMesh
//	   SkeletalMesh=SkeletalMesh''
//	   Materials(0)=Material''
		AnimSets(0)=AnimSet'WP_SniperRifle.Anims.K_WP_SniperRifle_1P_Base'
		Animations=MeshSequenceA
		Scale=1.5
		bForceUpdateAttachmentsInTick=true
		FOV=65
	End Object

	// Pickup staticmesh
	Components.Remove(PickupMesh)
	Begin Object Name=PickupMesh
//		SkeletalMesh=SkeletalMesh''
//		Materials(0)=Material''
	End Object

	WeaponColor=(R=255,G=255,B=255,A=255)
	FireInterval(0)=+0.19

	WeaponFireTypes(0)=EWFT_InstantHit
   FiringStatesArray(1)=Active

   ShotCost(0)=1
	ShotCost(1)=1

	PlayerViewOffset=(X=0.0,Y=0.0,Z=0.0)
	SmallWeaponsOffset=(X=16.0,Y=6.0,Z=-6.0)
	MaxPitchLag=600
	MaxYawLag=800
	RotChgSpeed=3.0
	ReturnChgSpeed=3.0

   WeaponFireAnim(0)="WeaponIdle"
   WeaponFireAnim(1)="WeaponIdle"

// AttachmentClass=Class'EM_XX.'

	InstantHitDamage(0)=42
	Spread(0)=0.0001
	Spread(1)=0.0001

//	InstantHitDamageTypes(0)=Class'EM_XX.'
// InstantHitDamageTypes(1)=None

//	HeadShotDamageType=Class'EM_XX.'
//	HeadShotDamageMult=2.2
//	SlowHeadshotScale=2.2
//	RunningHeadshotScale=2.2
// ZoomLoopCue=SoundCue'A_Vehicle_Nemesis.Cue.A_Vehicle_Nemesis_TurretZoomCue'

	InstantHitMomentum(0)=1000.0

	WeaponFireSnd(0)=None
	ZoomOutSound=SoundCue'A_Vehicle_Scavenger.Scavenger.A_Vehicle_Scavenger_TargetLock_Cue'
	ZoomInSound=SoundCue'A_Vehicle_Nemesis.Cue.A_Vehicle_Nemesis_TurretZoomCue'
   WeaponPutDownSnd=SoundCue'A_Weapon_Sniper.Sniper.A_Weapon_Sniper_Lower_Cue'
   WeaponEquipSnd=None
   PickupSound=None

   LockerRotation=(pitch=0,yaw=0,roll=-16384)

	AimingHelpRadius[0]=20.0
	AimingHelpRadius[1]=12.0

	MaxDesireability=0.63
	AIRating=+0.01
	CurrentRating=+0.7
	bFastRepeater=true
	bInstantHit=true
	bSplashJump=false
	bRecommendSplashDamage=false
	bSniping=true
	bWarnIfInLocker=true
	ShouldFireOnRelease(0)=0
	ShouldFireOnRelease(1)=0
	GroupWeight=0.5
	AimError=600

   AmmoCount=150
   LockerAmmoCount=150
   MaxAmmoCount=500

	MuzzleFlashSocket=MuzzleFlashSocket
   MuzzleFlashPSCTemplate=ParticleSystem'WP_SniperRifle.Effects.P_WP_SniperRifle_MuzzleFlash'
   MuzzleFlashLightClass=class'UTGame.UTRocketMuzzleFlashLight'
	MuzzleFlashDuration=0.33

	IconX=451
	IconY=448
	IconWidth=54
	IconHeight=51
	IconCoordinates=(U=726,V=532,UL=165,VL=51)
	DualIconCoordinates=(U=726,V=532,UL=165,VL=51)
	CrossHairCoordinates=(U=256,V=64,UL=64,VL=64)

	EquipTime=+0.2
	PutDownTime=+0.2

	LeftIdleAnim=WeaponIdle
	WeaponDualEqipAnim=WeaponEquip

	DualEquiptime=1.0
   bLoaded=true
	DualMode=EDM_DualEquipping  //EDM_SingleWeapon
	JumpDamping=1.5

   InventoryGroup=9
	QuickPickGroup=7
	QuickPickWeight=0.8

	DroppedPickupOffsetZ=12.0

	PivotTranslation=(Y=-10.0)

   bZoomedFireMode(0)=0
	bZoomedFireMode(1)=0

   CrosshairScaling=1

// scope multiplyers for FOV
// 3=26.6x 4=20X 5=18x 6.6=12.1x 6.7=11.9x 7.1=11.2x 7.2=11.1x 8=10x
// 10=8x 12=6.6x 15=5.3X 16=5X 24=3.3X 30=2.6X 32=2.5X 40=2X

   ZoomedTargetFOV=4
   ZoomedRate=80.000000

//	HudMaterial=Texture2D''

	WeaponRange=60000.000000
   Priority=0

   bExportMenuData=false
   bUsesOffhand=True

   ItemName=""      // Weapon Switch Name
   PickupMessage=""
   Name=""          // Menu Name
}
