/*
 * Class:  Elite_Bio_Attach
 * By: James Bishop A.K.A. *PingFre@K*
 * Copyright 1998-2009 Epic Games, Inc. All Rights Reserved.
*/
class Elite_Sniper_Rifle extends Elite_Weapon
	dependson(MutEM_XX);

/** Used for Range Display */
var float TargetRange;

var() int SniperRecoil;

// Sniper Stuff *****************************************************

var class<UTDamageType> HeadShotDamageType;
var float HeadShotDamageMult;

var Texture2D SideMaterial;
var Texture2D HudMaterial;

/** headshot scale factor when moving slowly or stopped */
var float SlowHeadshotScale;

/** headshot scale factor when running or falling */
var float RunningHeadshotScale;

/** Zoom minimum time*/
var bool bAbortZoom;

/** sound while the zoom is in progress */
var audiocomponent ZoomLoop;
var soundcue ZoomLoopCue;

/** Whether the standard crosshair should be displayed */
var bool bDisplayCrosshair;

/** tracks number of zoom started calls before zoom is ended */
var int ZoomCount;

var float	FadeTime;

simulated function PostBeginPlay()
{
	super.PostBeginPlay();
	
   if ( class'MutEM_XX'.default.Config_Sniper_Rifle.bDoubles )
   {
   BecomeDual();
   }

	if ( Role == ROLE_Authority )
		SetTimer(class'MutEM_XX'.default.Config_Sniper_Rifle.fFireInterval * 2, true, 'AmmoRegen');
		
	FireInterval[0]=class'MutEM_XX'.default.Config_Sniper_Rifle.fFireInterval;

	AmmoCount=class'MutEM_XX'.default.Config_Sniper_Rifle.iAmmoCount;
	LockerAmmoCount=class'MutEM_XX'.default.Config_Sniper_Rifle.iAmmoCount;
	MaxAmmoCount=class'MutEM_XX'.default.Config_Sniper_Rifle.iMaxAmmo;

	InstantHitDamage[0]=class'MutEM_XX'.default.Config_Sniper_Rifle.iDamage;
	InstantHitMomentum[0]=class'MutEM_XX'.default.Config_Sniper_Rifle.iMomentum;

	ZoomedTargetFOV=class'MutEM_XX'.default.Config_Sniper_Rifle.iZoomFOV;
	ZoomedRate=class'MutEM_XX'.default.Config_Sniper_Rifle.iZoomRate;

	HeadShotDamageMult=class'MutEM_XX'.default.Config_Sniper_Rifle.fHeadShotDmgMult;
	SlowHeadshotScale=class'MutEM_XX'.default.Config_Sniper_Rifle.fSlowHeadshotScale;
	RunningHeadshotScale=class'MutEM_XX'.default.Config_Sniper_Rifle.fRunningHeadshotScale;

	AimingHelpRadius[0]=class'MutEM_XX'.default.Config_Sniper_Rifle.iPriHelpRadius;
	AimError=class'MutEM_XX'.default.Config_Sniper_Rifle.iAimError;
	ShotCost[0]=class'MutEM_XX'.default.Config_Sniper_Rifle.iShotCost;
	
	AIRating=class'MutEM_XX'.default.Config_Sniper_Rifle.fAIRating;
	MaxDesireability=class'MutEM_XX'.default.Config_Sniper_Rifle.fAIRating;
	CurrentRating=class'MutEM_XX'.default.Config_Sniper_Rifle.fAIRating;

   SniperRecoil=class'MutEM_XX'.default.Config_Sniper_Rifle.iSniperRecoil;
}

function AmmoRegen()
{
   if ( class'MutEM_XX'.default.Config_Sniper_Rifle.bAmmoRegeneration )
   {
	   if ( Instigator != None && !IsFiring() && AmmoCount < class'MutEM_XX'.default.Config_Sniper_Rifle.iMaxAmmo )
	   {
		   AddAmmo(1);
	   }
   }
}

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

/////////////////////////////////////////////////////////////////////////
//  Sniper Stuff
/////////////////////////////////////////////////////////////////////////

simulated function DrawZoomedOverlay( HUD H )
{
//Crosshair
	local float ScaleX, ScaleY, StartX;
	local float OldOrgX, OldOrgY, OldClipX, OldClipY;
   local Vector X,Y,Z;
   local vector HitLocation, HitNormal;
   local float Scale;

	// ... They ignore the safe region.
	OldOrgX = H.Canvas.OrgX;
	OldOrgY = H.Canvas.OrgY;
	OldClipX = H.Canvas.ClipX;
	OldClipY = H.Canvas.ClipY;
	H.Canvas.OrgX = 0.0;
	H.Canvas.OrgY = 0.0;
	H.Canvas.ClipX = H.Canvas.SizeX;
	H.Canvas.ClipY = H.Canvas.SizeY;

	bDisplayCrosshair = false;  // whether to display the crosshair while zooming - for aligning crosshairs

	ScaleY = H.Canvas.ClipY/768.0;
	ScaleX = ScaleY;
	StartX = 0.5*H.Canvas.ClipX - 512.0*ScaleX;

//Display Different color if damage can hurt you or out of range
   if (TargetRange >= 1100 && TargetRange < 100000)
   {
   H.Canvas.DrawColor.R = 255;
	H.Canvas.DrawColor.G = 255;
	H.Canvas.DrawColor.B = 255;
   }

   else
   {
   H.Canvas.DrawColor.R = 255; //Red
	H.Canvas.DrawColor.G = 0;
	H.Canvas.DrawColor.B = 0;
   }

//Random Numbers
   H.Canvas.SetPos(10,60);
      H.Canvas.DrawText(""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19));
   H.Canvas.SetPos(30,80);
      H.Canvas.DrawText(""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19));

//Side Text
	H.Canvas.SetPos(10,100);
        H.Canvas.DrawText("©2008 Elite Machines");

	H.Canvas.SetPos(10,120);
        H.Canvas.DrawText("Redeem Machine");

//Side Image
   H.Canvas.SetPos(10,140);
        H.Canvas.DrawTexture(SideMaterial, 1);

//Zoom Multiplier Display
   scale = PlayerController(Instigator.Controller).DefaultFOV/PlayerController(Instigator.Controller).DesiredFOV;
   H.Canvas.SetPos(10,195);
        H.Canvas.DrawText("X"$int(Scale)$"."$int(10 * scale - 10 * int(Scale)));

//Multi-Color Range Display - Measure in Unreal Units
   H.Canvas.SetPos(10,215);
      GetViewAxes(X,Y,Z);
      Trace(HitLocation, HitNormal, Instigator.Location + (X * 100001), Instigator.Location, true);
      TargetRange = VSize(Instigator.Location + Instigator.BaseEyeHeight * vect(0,0,1) - HitLocation);

   if (TargetRange > 100000)
   {
   TargetRange = 0;
   H.Canvas.DrawText("Range:"@TargetRange$" UU ");
   }
   else
   {
   H.Canvas.DrawText("Range:"@TargetRange$" UU ");
   }

// More Random Numbers
   H.Canvas.SetPos(30,235);
      H.Canvas.DrawText(""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19));
   H.Canvas.SetPos(10,255);
      H.Canvas.DrawText(""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19)$""$Rand(19));

//Display Different color if damage can hurt you or out of range
   if (TargetRange >= 1100 && TargetRange < 100000)
   {
   H.Canvas.DrawColor.R = 0;
	H.Canvas.DrawColor.G = 255;
	H.Canvas.DrawColor.B = 0;
   }

   else
   {
   H.Canvas.DrawColor.R = 255; //Red
	H.Canvas.DrawColor.G = 0;
	H.Canvas.DrawColor.B = 0;
   }

	// Draw the crosshair
	// Draw the 4 corners
	H.Canvas.SetPos(StartX, 0.0);
	H.Canvas.DrawTile(HudMaterial, 512.0 * ScaleX, 384.0 * ScaleY, 2, 0, 510, 383);

	H.Canvas.SetPos(H.Canvas.ClipX*0.5, 0.0);
	H.Canvas.DrawTile(HudMaterial, 512.0 * ScaleX, 384.0 * ScaleY, 510, 0, -510, 383);

	H.Canvas.SetPos(StartX, H.Canvas.ClipY*0.5);
	H.Canvas.DrawTile(HudMaterial, 512.0 * ScaleX, 384.0 * ScaleY, 2, 383, 510, -383);

	H.Canvas.SetPos(H.Canvas.ClipX*0.5, H.Canvas.ClipY*0.5);
	H.Canvas.DrawTile(HudMaterial, 512.0 * ScaleX, 384.0 * ScaleY, 510, 383, -510, -383);

	if ( StartX > 0 )
	{
		// Draw the Horizontal Borders
		H.Canvas.SetPos(0.0, 0.0);
		H.Canvas.DrawTile(HudMaterial, StartX, 384.0 * ScaleY, 1, 0, 3, 383);

		H.Canvas.SetPos(H.Canvas.ClipX - StartX, 0.0);
		H.Canvas.DrawTile(HudMaterial, StartX, 384.0 * ScaleY, 4, 0, -3, 383);

		H.Canvas.SetPos(0.0, H.Canvas.ClipY*0.5);
		H.Canvas.DrawTile(HudMaterial, StartX, 384.0 * ScaleY, 1, 383, 3, -383);

		H.Canvas.SetPos(H.Canvas.ClipX - StartX, H.Canvas.ClipY*0.5);
		H.Canvas.DrawTile(HudMaterial, StartX, 384.0 * ScaleY, 4, 383, -3, -383);
	}

	// restore the canvas parameters
	H.Canvas.OrgX = OldOrgX;
	H.Canvas.OrgY = OldOrgY;
	H.Canvas.ClipX = OldClipX;
	H.Canvas.ClipY = OldClipY;
}

/** Called when zooming starts
 * @param PC - cast of Instigator.Controller for convenience
 */
simulated function StartZoom(UTPlayerController PC)
{    
//    local ElitePawn UP;
    
	ZoomCount++;
	if (ZoomCount == 1 && !IsTimerActive('Gotozoom') && IsActiveWeapon() && HasAmmo(0))
	{
/*        if( !Instigator.IsFirstPerson() )
        {
            bBehindViewPriorToZoom = true;
            UP = ElitePawn( Instigator );
            if ( UP != None )
            {
                UP.ToggleCamera();
            }
        }
        else { bBehindViewPriorToZoom = false; }
*/
		bDisplayCrosshair = false;
		PlayWeaponAnimation( 'WeaponZoomIn',0.2 );
		PlayArmAnimation( 'WeaponZoomIn',0.2 );
		bAbortZoom = false;
		SetTimer( 0.2, false, 'Gotozoom' );
	}
}

simulated function EndFire(Byte FireModeNum)
{
	local UTPlayerController PC;

	// Don't bother performing if this is a dedicated server

	if (WorldInfo.NetMode != NM_DedicatedServer)
	{
		PC = UTPlayerController(Instigator.Controller);
		if (PC != None && LocalPlayer(PC.Player) != none && FireModeNum < bZoomedFireMode.Length && bZoomedFireMode[FireModeNum] != 0 )
		{
			if(GetZoomedState() == ZST_NotZoomed && ZoomCount != 0)
			{
				if(bAbortZoom)
				{
					ClearTimer('Gotozoom');
					LeaveZoom();
				}
				else
				{
					bAbortZoom=true;
				}
			}
			if(ZoomLoop != none)
			{
				ZoomLoop.Stop();
				ZoomLoop = none;
			}
		}
	}
	super.EndFire(FireModeNum);
}

/** Called when zooming ends
 * @param PC - cast of Instigator.Controller for convenience
 */
simulated function EndZoom(UTPlayerController PC)
{
	PlaySound(ZoomOutSound, true);
	bAbortZoom = false;
	if (IsTimerActive('Gotozoom'))
	{
		ClearTimer('Gotozoom');
	}
	SetTimer(0.001,false,'LeaveZoom');

}

simulated function LeaveZoom()
{
	local UTPlayerController PC;

	bAbortZoom = false;
	PC = UTPlayerController(Instigator.Controller);
	if (PC != none)
	{
		PC.EndZoom();
	}
	ZoomCount = 0;
	if(Instigator.IsFirstPerson())
	{
		ChangeVisibility(true);
	}
    
	PlayWeaponAnimation('WeaponZoomOut',0.3);
	PlayArmAnimation('WeaponZoomOut',0.3);
	SetTimer(0.3,false,'RestartCrosshair');
//    if( bBehindViewPriorToZoom )
//    {
//        SetTimer(0.0001,false,'RestartBehindView');
//    }
}

simulated function ChangeVisibility(bool bIsVisible)
{
	super.Changevisibility(bIsvisible);
	if(bIsVisible)
	{
		PlayArmAnimation('WeaponZoomOut',0.00001); // to cover zooms ended while in 3p
	}
}
/*
simulated function RestartBehindView()
{
   local UTPlayerController PC;
   local ElitePawn UP;


    PC = UTPlayerController(Instigator.Controller);
    if (PC != None)
    {
        if(Instigator.IsFirstPerson())
        {
            UP = ElitePawn( Instigator );
            if ( UP != None )
            {
                UP.ToggleCamera();
            }
        }
    }
}
*/
simulated function RestartCrosshair()
{
	bDisplayCrosshair = true;
}

simulated function PutDownWeapon()
{
	ClearTimer('GotoZoom');
	ClearTimer('StopZoom');
	LeaveZoom();
	super.PutDownWeapon();
}

simulated function bool DenyClientWeaponSet()
{
	// don't autoswitch while zoomed
	return (GetZoomedState() != ZST_NotZoomed);
}

simulated function HolderEnteredVehicle()
{
	ClearTimer('GotoZoom');
	ClearTimer('StopZoom');
	PlayWeaponAnimation('WeaponZoomOut', 0.3);
}

simulated function Gotozoom()
{
	local UTPlayerController PC;

	PC = UTPlayerController(Instigator.Controller);
	if (GetZoomedState() == ZST_NotZoomed)
	{
		PC.FOVAngle = 40;
		Super.StartZoom(PC);
		ChangeVisibility(false);
		if (bAbortZoom) // stop the zoom after 1 tick
		{
			SetTimer(0.0001, false, 'StopZoom');
		}
		else
		{
			if(ZoomLoop == none)
			{
				ZoomLoop = CreateAudioComponent(ZoomLoopCue, false, true);
			}
			if(ZoomLoop != none)
			{
				ZoomLoop.Play();
			}
		}
	}

}

simulated function StopZoom()
{
	local UTPlayerController PC;

	if (WorldInfo.NetMode != NM_DedicatedServer)
	{
		PC = UTPlayerController(Instigator.Controller);
		if (PC != None && LocalPlayer(PC.Player) != none)
		{
			PC.StopZoom();
		}
	}
}

simulated function ProcessInstantHit( byte FiringMode, ImpactInfo Impact )
{
	local float Scaling;
	local int HeadDamage;

	if( (Role == Role_Authority) && !bUsingAimingHelp )
	{
		if (Instigator == None || VSize(Instigator.Velocity) < Instigator.GroundSpeed * Instigator.CrouchedPct)
		{
			Scaling = SlowHeadshotScale;
		}
		else
		{
			Scaling = RunningHeadshotScale;
		}

		HeadDamage = InstantHitDamage[FiringMode]* HeadShotDamageMult;
		if ( (UTPawn(Impact.HitActor) != None && UTPawn(Impact.HitActor).TakeHeadShot(Impact, HeadShotDamageType, HeadDamage, Scaling, Instigator.Controller)) ||
			(UTVehicleBase(Impact.HitActor) != None && UTVehicleBase(Impact.HitActor).TakeHeadShot(Impact, HeadShotDamageType, HeadDamage, Scaling, Instigator.Controller)) )
		{
			SetFlashLocation(Impact.HitLocation);
			return;
		}
	}

   if (Instigator != None)
   {
	   Instigator.AddVelocity( Normal(Instigator.Location - Impact.HitLocation) * class'MutEM_XX'.default.Config_Sniper_Rifle.iSniperRecoil / Instigator.Mass,
	   Instigator.Location,
	   InstantHitDamageTypes[0] );
   }

	super.ProcessInstantHit( FiringMode, Impact );
}

simulated function DrawWeaponCrosshair( Hud HUD )
{
	local EZoomState ZoomState;
	local float FadeValue;
	local UTPlayerController PC;

	ZoomState = GetZoomedState();

	if ( ZoomState != ZST_NotZoomed )
	{
		if ( ZoomState > ZST_ZoomingOut )
		{
			DrawZoomedOverlay(HUD);
		}
		else
		{
			FadeValue = 255 * ( 1.0 - (WorldInfo.TimeSeconds - ZoomFadeTime)/FadeTime);
			HUD.Canvas.DrawColor.A = FadeValue;
			HUD.Canvas.SetPos(0,0);
			HUD.Canvas.DrawTile( Texture2D 'EngineResources.Black', HUD.Canvas.SizeX, HUD.Canvas.SizeY, 0.0, 0.0, 16, 16);
		}
	}
	if( bDisplayCrosshair )
	{
		PC = UTPlayerController(Instigator.Controller);
		if ( (PC == None) || PC.bNoCrosshair )
		{
			return;
		}
		super.DrawWeaponCrosshair(HUD);
	}
}

// Must preload textures
simulated function PreloadTextures(bool bForcePreload)
{
	Super.PreloadTextures(bForcePreload);

	if (HUDMaterial != None)
	{
		HUDMaterial.bForceMiplevelsToBeResident = bForcePreload;
	}
	if (SideMaterial != None)
	{
		SideMaterial.bForceMiplevelsToBeResident = bForcePreload;
	}
}

//-----------------------------------------------------------------
// AI Interface

function float SuggestAttackStyle()
{
    return -0.4;
}

function float SuggestDefenseStyle()
{
    return 0.2;
}

function float GetAIRating()
{
	local UTBot B;
	local float ZDiff, dist, Result;

	B = UTBot(Instigator.Controller);
	if ( B == None )
		return AIRating;
	if ( B.IsShootingObjective() )
		return AIRating - 0.15;
	if ( B.Enemy == None )
		return AIRating;

	if ( B.Stopped() )
		result = AIRating + 0.1;
	else
		result = AIRating - 0.1;
	if ( Vehicle(B.Enemy) != None )
		result -= 0.2;
	ZDiff = Instigator.Location.Z - B.Enemy.Location.Z;
	if ( ZDiff < -200 )
		result += 0.1;
	dist = VSize(B.Enemy.Location - Instigator.Location);
	if ( dist > 2000 )
	{
		if ( !B.LineOfSightTo(B.Enemy) )
			result = result - 0.15;
		return ( FMin(2.0,result + (dist - 2000) * 0.0002) );
	}
	if ( !B.LineOfSightTo(B.Enemy) )
		return AIRating - 0.1;

	return result;
}

function bool RecommendRangedAttack()
{
	local UTBot B;

	B = UTBot(Instigator.Controller);
	if ( (B == None) || (B.Enemy == None) )
		return true;

	return ( VSize(B.Enemy.Location - Instigator.Location) > 2000 * (1 + FRand()) );
}

defaultproperties
{
	// Weapon SkeletalMesh
	Begin Object Name=FirstPersonMesh
	   SkeletalMesh=SkeletalMesh'WP_SniperRifle.Mesh.SK_WP_SniperRifle_1P'
      Materials(0)=Material'EM_XX_Content.Deemer_Final'  //Material'EM_XX_Content.Tiger_Final'
		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'EM_XX_Content.Mesh.Tiger_3P'
		Materials(0)=Material'EM_XX_Content.Deemer_Final'  //Material'EM_XX_Content.Tiger_Final'
	End Object
	
   SniperRecoil=0

   HudMaterial=Texture2D'EM_XX_Content.Scope512'
   SideMaterial=Texture2D'EM_XX_Content.steeldev'

   HeadShotDamageType=Class'EM_XX.Elite_Sniper_HeadShot'
   HeadShotDamageMult=2.000000

   AmmoCount=10
   LockerAmmoCount=10
   MaxAmmoCount=420
   
	EquipTime=+0.2
	PutDownTime=+0.2
	
	DualMode=EDM_DualEquipping

   ShotCost(1)=0
   bZoomedFireMode(1)=1
   AttachmentClass=Class'EM_XX.Elite_Sniper_Attach'
	WeaponFireSnd(0)=SoundCue'EM_XX_Content.z_ImprovedShot2'
   WeaponEquipSnd=SoundCue'A_Weapon_Sniper.Sniper.A_Weapon_Sniper_Raise_Cue'
   WeaponColor=(B=0,G=180,R=255,A=255)
   MuzzleFlashLightClass=Class'UTGame.UTStingerMuzzleFlashLight'
   FireInterval(0)=1.000000
   InstantHitDamageTypes(0)=Class'EM_XX.Elite_Sniper_BodyShot'

   MuzzleFlashPSCTemplate=EM_XX_Content.Tiger_Muz

   Priority=900.5
   AIRating=1.560000
   ItemName="Elite Sniper Rifle"
   PickupMessage="Elite Sniper Rifle"
   PickupSound=SoundCue'A_Pickups.Weapons.Cue.A_Pickup_Weapons_Sniper_Cue'
   bExportMenuData=True
   DroppedPickupMesh=PickupMesh
   PickupFactoryMesh=PickupMesh
   Name="Elite_Sniper_Rifle"
}
