class UR_Weap_MegaLinkx2 extends UR_Weap_MegaLink;

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

var AnimSet LeftArmAnimSet;

/** 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 MaterialInstanceConstant LeftWeaponMaterialInstance;
/** Left versions of everything */

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

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

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

replication
{
	if (bNetDirty)
		DualMode;
}

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

/**
 * 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.00);
			OverlayLeftMesh.SetOwnerNoSee(LeftMesh.bOwnerNoSee);
			OverlayLeftMesh.SetDepthPriorityGroup(SDPG_Foreground);
			OverlayLeftMesh.SetSkeletalMesh(LeftMesh.SkeletalMesh);
			OverlayLeftMesh.AnimSets = LeftMesh.AnimSets;
			OverlayLeftMesh.SetParentAnimComponent(LeftMesh);
			OverlayLeftMesh.SetFOV(LeftMesh.FOV);
		}
		else
		{
			WarnInternal("Could not create Weapon Overlay mesh for" @ self @ LeftMesh);
		}
	}
}

/**
  * 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);
				}
			}
		/*if(P != none)
		{
			if(P.GetTeamNum() == 1) // blue
			{
				WeaponMaterialInstance.SetVectorParameterValue('Enforcer_Diffuse',MakeLinearColor(0,0.1,2,1));
				WeaponMaterialInstance.SetVectorParameterValue('Enforcer_Spec',MakeLinearColor(0,0,7,1));
				if( LeftWeaponMaterialInstance != none )
				{
					LeftWeaponMaterialInstance.SetVectorParameterValue('Enforcer_Diffuse',MakeLinearColor(0,0.1,2,1));
					LeftWeaponMaterialInstance.SetVectorParameterValue('Enforcer_Spec',MakeLinearColor(0,0,7,1));
				}
			}
			else
			{
				WeaponMaterialInstance.SetVectorParameterValue('Enforcer_Diffuse',MakeLinearColor(1.0,0.0,0.0,1.0));
				WeaponMaterialInstance.SetVectorParameterValue('Enforcer_Spec',MakeLinearColor(7.0,0.0,0.0,1.0));
				if( LeftWeaponMaterialInstance != none )
				{
					LeftWeaponMaterialInstance.SetVectorParameterValue('Enforcer_Diffuse',MakeLinearColor(1.0,0.0,0.0,1.0));
					LeftWeaponMaterialInstance.SetVectorParameterValue('Enforcer_Spec',MakeLinearColor(7.0,0.0,0.0,1.0));
				}
			}
		}*/
	}
}

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

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

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

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

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

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

	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 ( MegaLinkx2_MuzzleFlashPSC[Index] != none )
	{
		MegaLinkx2_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;
	`Log("Inside causemuzzleflashlight "@Index);
	`Log("MegaLinkx2_MuzzleFlashLight "@MegaLinkx2_MuzzleFlashLight[Index]);
	if ( MegaLinkx2_MuzzleFlashLight[Index] != None )
	{
		MegaLinkx2_MuzzleFlashLight[Index].ResetLight();
	}
	else if ( MuzzleFlashLightClass != None )
	{
		MegaLinkx2_MuzzleFlashLight[Index] = new(Outer) MuzzleFlashLightClass;
		if ( Index == 1 )
			LeftMesh.AttachComponentToSocket(MegaLinkx2_MuzzleFlashLight[Index],MuzzleFlashSocket);
		else
			SkeletalMeshComponent(Mesh).AttachComponentToSocket(MegaLinkx2_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 (MegaLinkx2_MuzzleFlashPSC[Index] != none)
		{
			MegaLinkx2_MuzzleFlashPSC[Index].SetTemplate(MuzzleFlashPSCTemplate);
			MegaLinkx2_MuzzleFlashPSC[Index].SetVectorParameter('MFlashScale',Vect(0.5,0.5,0.5));
			MegaLinkx2_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;
		if (LeftMesh == None)
		{
			LeftMesh = UTSkeletalMeshComponent(new(self) Mesh.Class(Mesh));
			LeftMesh.SetScale3D(Mesh.Scale3D * vect(1,-1,1));
			LeftMesh.SetFOV(0.00000);
			`Log("setting fov"@LeftMesh.FOV);
			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 (MegaLinkx2_MuzzleFlashPSC[1] != None)
		{
			MegaLinkx2_MuzzleFlashPSC[1].SetFOV(LeftMesh.FOV);
			LeftMesh.AttachComponentToSocket(MegaLinkx2_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)
			{
				`Log("set dual wielding");
				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;
	//InstantHitDamageTypes[1] = Class'UTGame.UTDmgType_LinkBeam';
	BecomeDual();
}

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 = 0.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
 *
 * @See Weapon.GetFireInterval()
 */
simulated function float GetFireInterval(byte FireModeNum)
{
	local float FI;

	FI = Super.GetFireInterval(FireModeNum);
	if (FireModeNum == 0 && 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++;
}

/**
 * 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 );
		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;
		}
		`Log("become dual");
	}

	/**
	 * 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
{
	//ArmsAnimSet=AnimSet'WP_LinkGun.Anims.K_WP_LinkGun_1P_Base'
	//LeftArmAnimSet=AnimSet'WP_LinkGun.Anims.K_WP_LinkGun_1P_Base'
	ShotCost(0)=0
	ShotCost(1)=0
	DualEquiptime=1.000000
	// First Enforcer
/*	Begin Object class=AnimNodeSequence Name=MeshSequenceA
		bCauseActorAnimEnd=True
		ObjectArchetype=AnimNodeSequence'Engine.Default__AnimNodeSequence'
	End Object

	Begin Object class=AnimNodeSequence Name=MeshSequenceB
		bCauseActorAnimEnd=True
		ObjectArchetype=AnimNodeSequence'Engine.Default__AnimNodeSequence'
	End Object
*/
	Begin Object Name=FirstPersonMesh
      FOV=60.000000
	  //FOV=55.00000
      SkeletalMesh=SkeletalMesh'WP_LinkGun.Mesh.SK_WP_Linkgun_1P'
      Animations=MeshSequenceA
      AnimSets(0)=AnimSet'WP_LinkGun.Anims.K_WP_LinkGun_1P_Base'
      Scale=0.900000
	  bForceUpdateAttachmentsInTick=true
      ObjectArchetype=UTSkeletalMeshComponent'UTGame.Default__UTBeamWeapon:FirstPersonMesh'
   End Object

	// Weapon SkeletalMesh
/*	Begin Object Name=FirstPersonMesh
		SkeletalMesh=SkeletalMesh'WP_LinkGun.Mesh.SK_WP_Linkgun_1P'
		PhysicsAsset=None
		AnimSets(0)=AnimSet'WP_LinkGun.Anims.K_WP_LinkGun_1P_Base'
		Animations=MeshSequenceA
		Scale=2
		FOV=0
		bForceUpdateAttachmentsInTick=true
	End Object
*/	BeamAmmoUsePerSecond = 0
}