class CrosshairGameController_Tech_Round extends BaseTechCrosshairController
{
	private var m_root : weak< inkWidget >;
	private editable var m_leftPart : inkImageRef;
	private editable var m_rightPart : inkImageRef;
	private var offsetLeftRight : Float;
	default offsetLeftRight = .8;
	private var offsetLeftRightExtra : Float;
	default offsetLeftRightExtra = 1.2;
	private var latchVertical : Float;
	default latchVertical = 40.0;
	private editable var m_topPart : inkImageRef;
	private editable var m_bottomPart : inkImageRef;
	private editable var m_horiPart : inkWidgetRef;
	private editable var m_vertPart : inkWidgetRef;
	private var m_chargeBar : weak< inkCanvas >;
	private var m_chargeBarFG : weak< inkRectangle >;
	private var m_chargeBarBG : weak< inkRectangle >;
	private var m_chargeBarMG : weak< inkRectangle >;
	private var m_centerPart : weak< inkWidget >;
	private var m_crosshair : weak< inkWidget >;
	private var m_bottom_hip_bar : weak< inkWidget >;
	private var m_realFluffText_1 : weak< inkText >;
	private var m_realFluffText_2 : weak< inkText >;
	private var m_bufferedSpread : Vector2;
	private var m_weaponlocalBB : weak< IBlackboard >;
	private var m_bbcharge : CallbackHandle;
	private var m_bbmagazineAmmoCapacity : CallbackHandle;
	private var m_bbmagazineAmmoCount : CallbackHandle;
	private var m_bbcurrentFireMode : CallbackHandle;
	private var m_currentAmmo : Int32;
	default m_currentAmmo = 2;
	private var m_currentMaxAmmo : Int32;
	default m_currentMaxAmmo = 2;
	private var m_maxSupportedAmmo : Int32;
	default m_maxSupportedAmmo = 8;
	private var m_currentFireMode : gamedataTriggerMode;
	private var m_orgSideSize : Vector2;
	private var m_sidesScale : Float;
	private var m_chargeAnimationProxy : inkAnimProxy;
	private var m_bbNPCStatsInfo : CallbackHandle;
	private var m_currentObstructedTargetBBID : CallbackHandle;
	private var m_potentialVisibleTarget : weak< GameObject >;
	private var m_potentialObstructedTarget : weak< GameObject >;
	private var m_useVisibleTarget : Bool;
	default m_useVisibleTarget = true;
	editable var m_horizontalMinSpread : Float;
	default m_horizontalMinSpread = 0;
	editable var m_verticalMinSpread : Float;
	default m_verticalMinSpread = 0;
	editable var m_gameplaySpreadMultiplier : Float;
	default m_gameplaySpreadMultiplier = 1;
	private var m_stateADS : Bool;
	default m_stateADS = false;

	protected event OnInitialize()
	{
		m_root = ( ( inkWidget )( GetRootWidget() ) );
		if( m_rootWidget )
		{
			m_rootWidget.SetOpacity( 0.0 );
		}
		m_chargeBar = ( ( inkCanvas )( GetWidget( 'chargeBar' ) ) );
		m_chargeBarBG = ( ( inkRectangle )( GetWidget( 'chargeBar/chargeBarBG' ) ) );
		m_chargeBarMG = ( ( inkRectangle )( GetWidget( 'chargeBar/chargeBarMG' ) ) );
		m_chargeBarFG = ( ( inkRectangle )( GetWidget( 'chargeBar/chargeBarFG' ) ) );
		m_crosshair = ( ( inkCanvas )( GetWidget( 'reticle' ) ) );
		m_bottom_hip_bar = ( ( inkWidget )( GetWidget( 'bottom_hip_bar' ) ) );
		m_realFluffText_1 = ( ( inkText )( GetWidget( 'realFluffText_1' ) ) );
		m_realFluffText_2 = ( ( inkText )( GetWidget( 'realFluffText_2' ) ) );
		m_orgSideSize = inkImageRef.GetSize( m_leftPart );
		m_sidesScale = 1.0;
		m_chargeBar.SetVisible( false );
		super.OnInitialize();
	}

	protected event OnUninitialize()
	{
		super.OnUninitialize();
	}

	protected event OnPreIntro()
	{
		var m_uiBlackboard : IBlackboard;
		super.OnPreIntro();
		GetRootWidget().SetOpacity( 0.0 );
		m_weaponlocalBB = GetWeaponLocalBlackboard();
		if( m_targetBB )
		{
			m_currentObstructedTargetBBID = m_targetBB.RegisterDelayedListenerEntityID( GetAllBlackboardDefs().UI_TargetingInfo.CurrentObstructedTarget, this, 'OnCurrentObstructedTarget' );
			OnCurrentObstructedTarget( m_targetBB.GetEntityID( GetAllBlackboardDefs().UI_TargetingInfo.CurrentObstructedTarget ) );
		}
		if( m_weaponlocalBB )
		{
			m_bbcharge = m_weaponlocalBB.RegisterListenerFloat( GetAllBlackboardDefs().Weapon.Charge, this, 'OnChargeChanged' );
			m_bbmagazineAmmoCount = m_weaponlocalBB.RegisterListenerUint( GetAllBlackboardDefs().Weapon.MagazineAmmoCount, this, 'OnAmmoCountChanged' );
			m_bbmagazineAmmoCapacity = m_weaponlocalBB.RegisterListenerUint( GetAllBlackboardDefs().Weapon.MagazineAmmoCapacity, this, 'OnAmmoCapacityChanged' );
			m_bbcurrentFireMode = m_weaponlocalBB.RegisterListenerVariant( GetAllBlackboardDefs().Weapon.TriggerMode, this, 'OnTriggerModeChanged' );
		}
		m_uiBlackboard = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_NPCNextToTheCrosshair );
		if( m_uiBlackboard )
		{
			m_bbNPCStatsInfo = m_uiBlackboard.RegisterListenerVariant( GetAllBlackboardDefs().UI_NPCNextToTheCrosshair.NameplateData, this, 'OnNPCStatsChanged' );
		}
		OnChargeChanged( 0.0 );
	}

	protected event OnPreOutro()
	{
		if( m_targetBB )
		{
			m_targetBB.UnregisterDelayedListener( GetAllBlackboardDefs().UI_TargetingInfo.CurrentObstructedTarget, m_currentObstructedTargetBBID );
		}
		if( m_weaponlocalBB )
		{
			m_weaponlocalBB.UnregisterListenerFloat( GetAllBlackboardDefs().Weapon.Charge, m_bbcharge );
			m_weaponlocalBB.UnregisterListenerUint( GetAllBlackboardDefs().Weapon.MagazineAmmoCount, m_bbmagazineAmmoCount );
			m_weaponlocalBB.UnregisterListenerUint( GetAllBlackboardDefs().Weapon.MagazineAmmoCapacity, m_bbmagazineAmmoCapacity );
			m_weaponlocalBB.UnregisterListenerVariant( GetAllBlackboardDefs().Weapon.TriggerMode, m_bbcurrentFireMode );
		}
		super.OnPreOutro();
	}

	protected function OnTriggerModeChanged( value : Variant )
	{
		var record : TriggerMode_Record;
		record = ( ( TriggerMode_Record )value );
		m_currentFireMode = record.Type();
		if( m_currentFireMode == gamedataTriggerMode.Charge && !( m_stateADS ) )
		{
			m_chargeBar.SetVisible( true );
			m_bottom_hip_bar.SetVisible( false );
		}
		else
		{
			m_chargeBar.SetVisible( false );
			m_bottom_hip_bar.SetVisible( true );
		}
	}

	protected function OnAmmoCountChanged( value : Uint32 )
	{
		m_currentAmmo = ( ( Int32 )( value ) );
	}

	protected function OnAmmoCapacityChanged( value : Uint32 )
	{
		m_currentMaxAmmo = ( ( Int32 )( value ) );
	}

	protected function OnChargeChanged( charge : Float )
	{
		var actualMaxValue : Float;
		var playbackOptions : inkAnimOptions;
		var weaponObject : WeaponObject;
		weaponObject = ( ( WeaponObject )( GetWeaponItemObject() ) );
		actualMaxValue = GetCurrentChargeLimit();
		m_chargeBar.SetVisible( charge > 0.0 );
		m_bottom_hip_bar.SetVisible( charge > 0.0 );
		m_realFluffText_1.SetVisible( charge > 0.0 );
		m_realFluffText_2.SetVisible( charge > 0.0 );
		m_chargeBarFG.SetSize( Vector2( charge * 3.0, 6.0 ) );
		m_chargeBarBG.SetSize( Vector2( WeaponObject.GetBaseMaxChargeThreshold( weaponObject ) * 3.0, 6.0 ) );
		m_chargeBarMG.SetSize( Vector2( WeaponObject.GetFullyChargedThreshold( weaponObject ) * 3.0, 6.0 ) );
		if( charge >= actualMaxValue )
		{
			if( !( m_chargeAnimationProxy ) )
			{
				playbackOptions.loopInfinite = true;
				playbackOptions.loopType = inkanimLoopType.Cycle;
				m_chargeAnimationProxy = PlayLibraryAnimation( 'chargeMax', playbackOptions );
			}
		}
		else
		{
			if( m_chargeAnimationProxy )
			{
				m_chargeAnimationProxy.Stop();
				m_chargeAnimationProxy = NULL;
				m_chargeBar.SetOpacity( 1.0 );
				m_crosshair.SetOpacity( 1.0 );
			}
		}
	}

	public export override function GetIntroAnimation( firstEquip : Bool ) : inkAnimProxy
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( 0.0 );
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetDuration( 0.25 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		OnShow();
		return m_rootWidget.PlayAnimation( anim );
	}

	public export override function GetOutroAnimation() : inkAnimProxy
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( 1.0 );
		alphaInterpolator.SetEndTransparency( 0.0 );
		alphaInterpolator.SetDuration( 0.25 );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		OnHide();
		return m_rootWidget.PlayAnimation( anim );
	}

	protected event OnBulletSpreadChanged( spread : Vector2 )
	{
		super.OnBulletSpreadChanged( spread );
		m_bufferedSpread = spread;
		inkImageRef.SetMargin( m_leftPart, inkMargin( -( spread.X ) * offsetLeftRight, 0.0, 0.0, 0.0 ) );
		inkImageRef.SetMargin( m_rightPart, inkMargin( spread.X * offsetLeftRight, 0.0, 0.0, 0.0 ) );
		inkWidgetRef.SetSize( m_vertPart, 3.0, ( spread.Y * 2.0 ) + latchVertical );
		inkWidgetRef.SetSize( m_horiPart, spread.X * 2.0, 3.0 );
		inkImageRef.SetMargin( m_topPart, inkMargin( 0.0, -( spread.Y ), 0.0, 0.0 ) );
		inkImageRef.SetMargin( m_bottomPart, inkMargin( 0.0, spread.Y, 0.0, 0.0 ) );
	}

	protected function ColapseCrosshair( full : Bool, duration : Float )
	{
		var anim : inkAnimDef;
		var marginInterpolator : inkAnimMargin;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( m_root.GetOpacity() );
		alphaInterpolator.SetEndTransparency( 0.0 );
		alphaInterpolator.SetDuration( duration );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		m_root.StopAllAnimations();
		m_root.PlayAnimation( anim );
		anim = new inkAnimDef;
		marginInterpolator = new inkAnimMargin;
		marginInterpolator.SetStartMargin( inkImageRef.GetMargin( m_leftPart ) );
		marginInterpolator.SetEndMargin( inkMargin( 0.0, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetDuration( duration );
		marginInterpolator.SetType( inkanimInterpolationType.Linear );
		marginInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( marginInterpolator );
		inkImageRef.StopAllAnimations( m_leftPart );
		inkImageRef.PlayAnimation( m_leftPart, anim );
		anim = new inkAnimDef;
		marginInterpolator = new inkAnimMargin;
		marginInterpolator.SetStartMargin( inkImageRef.GetMargin( m_rightPart ) );
		marginInterpolator.SetEndMargin( inkMargin( 0.0, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetDuration( duration );
		marginInterpolator.SetType( inkanimInterpolationType.Linear );
		marginInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( marginInterpolator );
		inkImageRef.StopAllAnimations( m_rightPart );
		inkImageRef.PlayAnimation( m_rightPart, anim );
		anim = new inkAnimDef;
		marginInterpolator = new inkAnimMargin;
		marginInterpolator.SetStartMargin( inkImageRef.GetMargin( m_bottomPart ) );
		marginInterpolator.SetEndMargin( inkMargin( 0.0, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetDuration( duration );
		marginInterpolator.SetType( inkanimInterpolationType.Linear );
		marginInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( marginInterpolator );
		inkImageRef.StopAllAnimations( m_bottomPart );
		inkImageRef.PlayAnimation( m_bottomPart, anim );
		if( m_centerPart )
		{
			m_centerPart.SetVisible( false );
		}
		if( full )
		{
			HideCenterPart( duration );
		}
	}

	protected function ExpandCrosshair( full : Bool, duration : Float )
	{
		var anim : inkAnimDef;
		var marginInterpolator : inkAnimMargin;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( m_root.GetOpacity() );
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetDuration( duration );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		m_root.PlayAnimation( anim );
		anim = new inkAnimDef;
		marginInterpolator = new inkAnimMargin;
		marginInterpolator.SetStartMargin( inkMargin( 0.0, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetEndMargin( inkMargin( -( m_bufferedSpread.X ) * offsetLeftRight, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetDuration( duration );
		marginInterpolator.SetType( inkanimInterpolationType.Linear );
		marginInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( marginInterpolator );
		inkImageRef.PlayAnimation( m_leftPart, anim );
		anim = new inkAnimDef;
		marginInterpolator = new inkAnimMargin;
		marginInterpolator.SetStartMargin( inkMargin( 0.0, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetEndMargin( inkMargin( m_bufferedSpread.X * offsetLeftRight, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetDuration( duration );
		marginInterpolator.SetType( inkanimInterpolationType.Linear );
		marginInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( marginInterpolator );
		inkImageRef.PlayAnimation( m_rightPart, anim );
		anim = new inkAnimDef;
		marginInterpolator = new inkAnimMargin;
		marginInterpolator.SetStartMargin( inkMargin( 0.0, 0.0, 0.0, 0.0 ) );
		marginInterpolator.SetEndMargin( inkMargin( 0.0, m_bufferedSpread.Y, 0.0, 0.0 ) );
		marginInterpolator.SetDuration( duration );
		marginInterpolator.SetType( inkanimInterpolationType.Linear );
		marginInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( marginInterpolator );
		inkImageRef.PlayAnimation( m_bottomPart, anim );
		if( m_centerPart )
		{
			m_centerPart.SetVisible( true );
		}
		if( full )
		{
			ShowCenterPart( duration );
		}
	}

	private function ShowCenterPart( duration : Float )
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		if( m_centerPart )
		{
			alphaInterpolator.SetStartTransparency( m_centerPart.GetOpacity() );
		}
		alphaInterpolator.SetEndTransparency( 1.0 );
		alphaInterpolator.SetDuration( duration );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		if( m_centerPart )
		{
			m_centerPart.PlayAnimation( anim );
		}
	}

	private function HideCenterPart( duration : Float )
	{
		var anim : inkAnimDef;
		var alphaInterpolator : inkAnimTransparency;
		anim = new inkAnimDef;
		alphaInterpolator = new inkAnimTransparency;
		alphaInterpolator.SetStartTransparency( m_centerPart.GetOpacity() );
		alphaInterpolator.SetEndTransparency( 0.0 );
		alphaInterpolator.SetDuration( duration );
		alphaInterpolator.SetType( inkanimInterpolationType.Linear );
		alphaInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( alphaInterpolator );
		m_centerPart.PlayAnimation( anim );
	}

	private function OnShow()
	{
		switch( GetCrosshairState() )
		{
			case gamePSMCrosshairStates.Safe:
				ShowCenterPart( 0.25 );
			break;
			default:
				ExpandCrosshair( true, 0.25 );
			break;
		}
	}

	private function OnHide()
	{
		switch( GetCrosshairState() )
		{
			case gamePSMCrosshairStates.Safe:
				HideCenterPart( 0.25 );
			break;
			default:
				ColapseCrosshair( true, 0.25 );
			break;
		}
	}

	protected override function OnState_Safe()
	{
		ColapseCrosshair( false, 0.1 );
	}

	protected override function OnState_HipFire()
	{
		var anim : inkAnimDef;
		var sizeInterpolator : inkAnimSize;
		m_stateADS = false;
		anim = new inkAnimDef;
		sizeInterpolator = new inkAnimSize;
		sizeInterpolator.SetStartSize( Vector2( m_orgSideSize.X / 2.0, m_orgSideSize.Y / 2.0 ) );
		sizeInterpolator.SetEndSize( m_orgSideSize );
		sizeInterpolator.SetDuration( 0.1 );
		sizeInterpolator.SetType( inkanimInterpolationType.Linear );
		sizeInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		anim.AddInterpolator( sizeInterpolator );
		inkImageRef.PlayAnimation( m_leftPart, anim );
		inkImageRef.PlayAnimation( m_rightPart, anim );
		inkImageRef.PlayAnimation( m_bottomPart, anim );
		ExpandCrosshair( true, 0.1 );
	}

	protected override function OnState_Aim()
	{
		m_stateADS = true;
		ColapseCrosshair( false, 0.1 );
	}

	protected override function OnState_Reload()
	{
		ColapseCrosshair( false, 0.25 );
	}

	protected override function OnState_Sprint()
	{
		ColapseCrosshair( false, 0.1 );
	}

	protected override function OnState_GrenadeCharging()
	{
		ColapseCrosshair( false, 0.1 );
	}

	protected override function OnState_Scanning()
	{
		ColapseCrosshair( true, 0.1 );
	}

	protected event OnCurrentAimTarget( entId : EntityID )
	{
		m_potentialVisibleTarget = ( ( GameObject )( GameInstance.FindEntityByID( GetGame(), entId ) ) );
		OnTargetsChanged();
	}

	protected event OnCurrentObstructedTarget( entId : EntityID )
	{
		m_potentialObstructedTarget = ( ( GameObject )( GameInstance.FindEntityByID( GetGame(), entId ) ) );
		OnTargetsChanged();
	}

	private function OnTargetsChanged()
	{
		var newTarget : weak< GameObject >;
		var revealRequest : gameVisionModeSystemRevealIdentifier;
		revealRequest.sourceEntityId = GetOwnerEntity().GetEntityID();
		revealRequest.reason = 'TechWeapon';
		if( m_potentialVisibleTarget )
		{
			newTarget = m_potentialVisibleTarget;
			m_useVisibleTarget = true;
		}
		else if( m_potentialObstructedTarget && m_potentialObstructedTarget.HasRevealRequest( revealRequest ) )
		{
			newTarget = m_potentialObstructedTarget;
			m_useVisibleTarget = false;
		}
		if( newTarget != m_targetEntity )
		{
			RegisterTargetCallbacks( false );
			m_targetEntity = newTarget;
			RegisterTargetCallbacks( true );
			UpdateCrosshairGUIState( true );
		}
	}

	protected override function ApplyCrosshairGUIState( state : CName, aimedAtEntity : Entity )
	{
		m_root.SetState( state );
		inkImageRef.SetState( m_leftPart, state );
		inkImageRef.SetState( m_rightPart, state );
		inkImageRef.SetState( m_bottomPart, state );
		m_chargeBarBG.SetState( state );
		m_chargeBarFG.SetState( state );
	}

	protected override function GetDistanceToTarget() : Float
	{
		var targetBBID : BlackboardID_EntityID;
		var distanceBBID : BlackboardID_Float;
		var targetID : EntityID;
		var distance : Float;
		distance = 0.0;
		if( m_useVisibleTarget )
		{
			targetBBID = GetAllBlackboardDefs().UI_TargetingInfo.CurrentVisibleTarget;
			distanceBBID = GetAllBlackboardDefs().UI_TargetingInfo.VisibleTargetDistance;
		}
		else
		{
			targetBBID = GetAllBlackboardDefs().UI_TargetingInfo.CurrentObstructedTarget;
			distanceBBID = GetAllBlackboardDefs().UI_TargetingInfo.ObstructedTargetDistance;
		}
		targetID = m_targetBB.GetEntityID( targetBBID );
		if( EntityID.IsDefined( targetID ) )
		{
			distance = m_targetBB.GetFloat( distanceBBID );
		}
		return distance;
	}

}

