/*-----------------------------------------------------------------------------
	DukeChainsaw
	Author: Brandon Reinhart
-----------------------------------------------------------------------------*/
class DukeChainsaw expands MeleeWeapon;

#exec OBJ LOAD FILE=..\Sounds\dnsWeapn.dfx
#exec AUDIO IMPORT FILE="..\Sounds\Chainsaw\CSawStartHD.wav" NAME="CSawStartHD"
#exec AUDIO IMPORT FILE="..\Sounds\Chainsaw\CSawRunLpHD.wav" NAME="CSawRunLpHD" 
#exec AUDIO IMPORT FILE="..\Sounds\Chainsaw\CSawTrouble.wav" NAME="CSawTrouble"  


var(Animation) WAMEntry SAnimIdleOffSmall[4];
var(Animation) WAMEntry SAnimIdleOffLarge[4];
var(Animation) WAMEntry SAnimEngineStop[4];
var(Animation) WAMEntry SAnimEngineStart[4];
var(Animation) WAMEntry SAnimEngineStartTrouble[4];
var(Animation) WAMEntry SAnimChewFire[4];

var transient float				LargeIdleOffTimer;
var()		vector				HitOffset;
var			bool				bChewItUp;

var			sound				AttackingAmbientSound;
var			sound				IdleAmbientSound;



/*-----------------------------------------------------------------------------
	Damage & Trace
-----------------------------------------------------------------------------*/

simulated function int GetHitDamage( actor Victim, name BoneName )
{
	return 3;
}

simulated function TraceFire( Actor HitInstigator, 
				    optional float HorizError, optional float VertError, 
					optional bool bDontPenetrate, optional bool bEffectsOnly,
					optional bool bNoActors, optional bool bNoMeshAccurate,
					optional bool bNoCreationSounds )
{
	local Actor HitActor;
	local vector Direction;
	local vector StartTrace, EndTrace, BeamStart;
	local vector HitLocation, HitNormal;
	local vector BackHitLocation, BackHitNormal;
	local vector HitMeshBarys;
	local int HitMeshTri;
	local name HitMeshBone;
	local texture HitMeshTex;
	local PointRegion HitRegion;
	local class<Material> HitMat;
	local float MaxMaterialWidth;
	local Pawn PawnOwner;
	local vector X, Y, Z;
	local int HitSurfaceIndex;	


	// Get our trace parameters.
	PawnOwner = Pawn(Owner);
	StartTrace = Owner.Location + PawnOwner.BaseEyeHeight * vect(0,0,1);
	EndTrace = StartTrace + vector(PawnOwner.ViewRotation)*MeleeHitRadius;

	// Trace out to see what we hit.
	HitActor = Trace( 
		HitLocation, HitNormal, EndTrace, StartTrace, !bNoActors, ,
		!bNoMeshAccurate, HitMeshTri, HitMeshBarys, HitMeshBone, HitMeshTex
		);

	if ( HitActor != none )
	{
		// JEP...
		// Find the material if we hit a brush.
		if ( (HitActor != None) && ((HitActor == Level) || HitActor.IsA('Mover')) )
			HitMat = TraceMaterial( EndTrace, StartTrace, HitSurfaceIndex );

		// Hit the material.
		if ( (HitMat != None) && (Level.NetMode != NM_DedicatedServer) )
			//HitMaterial( HitMat, TraceHitCategory, HitLocation, HitNormal, !bNoCreationSounds, HitSurfaceIndex );
			HitMaterial( HitMat, 2, HitLocation, HitNormal, !bNoCreationSounds, HitSurfaceIndex );
		// ...JEP

		// JEP... Notify glass we want to break it, if it was part of the trace (this is a total special case)
		if (HitActor.IsA('BreakableGlass'))
		{
			// Notify the glass that we hit it
			if (BreakableGlass(HitActor).GlassBreakCount > 0)
				BreakableGlass(HitActor).ReplicateBreakGlassDir( HitLocation, vector(PawnOwner.ViewRotation), 30.0f );
			else
				BreakableGlass(HitActor).ReplicateBreakGlass( HitLocation );
		}
		// ...JEP
		else if ( HitActor.IsA('Snatcher') )
		{
			Pawn(HitActor).Died( PawnOwner, class'ChainsawDamage', HitActor.Location );
		}
		else if ( HitActor.IsA('SnatcherCarcass') )
		{
			Pawn(HitActor).Died( PawnOwner, class'ChainsawDamage', HitActor.Location );
		}
		else if ( !bEffectsOnly )
		{
			TraceHit( 
				StartTrace, EndTrace, HitActor, HitLocation, HitNormal, 
				HitMeshTri, HitMeshBarys, HitMeshBone, HitMeshTex, HitInstigator, BeamStart
				);
		}
	}
}

simulated function TraceHit( vector StartTrace, vector EndTrace, Actor HitActor, vector HitLocation, 
				   vector HitNormal, int HitMeshTri, vector HitMeshBarys, name HitMeshBone, 
				   texture HitMeshTex, Actor HitInstigator, vector BeamStart )
				   
{
	local Actor TestHitActor;
	local vector TestHitLocation, TestHitNormal, WaterPoint;
	local HitPackage hit;
	local float HitDamage;

	// 80% chance that we perform near miss l0gic if we hit a wall.
	if ( (HitActor == Level) && (FRand() < 0.8) && (Level.NetMode == NM_Standalone) )
	{
		// Perform an additional trace to see if we had a "near miss"
		TestHitActor = Trace( TestHitLocation, TestHitNormal, EndTrace, StartTrace, true );
		if ( PlayerPawn(TestHitActor) != None )
			TestHitActor.NearMiss();
	}

	if ( IsInWaterRegion(StartTrace) != IsInWaterRegion(HitLocation) )
	{
		WaterPoint = TraceWaterPoint( StartTrace, HitLocation );
		spawn( WaterSplashClass,,,WaterPoint );
	}
//	else if ( IsInWaterRegion(StartTrace) )
//	{
//		// We started in water, create a bubble trace.
//		StartTrace = Owner.Location + CalcDrawOffset() + (FireOffset.X) * X + (FireOffset.Y+8) * Y + (FireOffset.Z-6) * Z;
//		Trail = spawn(class'BubbleTrail',,,StartTrace,PawnOwner.ViewRotation);
//	}

	// Perform extended processing if we don't hit the level and didn't hit ourselves.
	if ( (HitActor != None) && (HitActor != Self) && (HitActor != Owner) && (HitActor != Level) )
	{
		// Set a fake mesh hit bone if we aren't in mesh accurate hit mode.
		if ( !Level.GRI.bMeshAccurateHits )
		{
			if ( HitLocation.Z - HitActor.Location.Z > 0.7 * HitActor.CollisionHeight )
				HitMeshBone = 'head';
			else
				HitMeshBone = 'chest';
		}

		// Calculate the damage.
		HitDamage = GetHitDamage( HitActor, HitMeshBone );

		// Set the damage bone and hurt the target.
		HitActor.TakeHitDamage( HitLocation, HitNormal, HitMeshTri, HitMeshBarys, HitMeshBone, HitMeshTex, HitDamage, HitInstigator, TraceDamageType, normal(EndTrace - StartTrace) );

		// Setup the hit effect.
		SpawnHitPackage( hit, HitActor, HitLocation );
		FillHitPackage( hit, HitDamage, Pawn(Owner), StartTrace, BeamStart );
		DeliverHitPackage( hit );
	}
	else if ( HitActor == Level )
	{
		// Setup the hit effect.
		SpawnHitPackage( hit, Level, HitLocation );
		FillHitPackage( hit, 0, Pawn(Owner), StartTrace, BeamStart );
		DeliverHitPackage( hit );
	}
		if  (HitActor != None)
	{
		ChewItUp( true );
		Super.TraceHit( StartTrace, EndTrace, HitActor, HitLocation, HitNormal, HitMeshTri, HitMeshBarys, HitMeshBone, HitMeshTex, HitInstigator, BeamStart );
	} else 
	 ChewItUp ( false );
	
}
  

function Timer( optional int TimerNum )
{
	if ( TimerNum == 2 )
	{
		AmmoType.UseAmmo(1);
	} else
		TraceFire( Owner );
}


/*-----------------------------------------------------------------------------
	Firing and Input
-----------------------------------------------------------------------------*/

function Fire()
{
//	if ( (PlayerPawn(Owner) != None) && bChewItUp )
//		PlayerPawn(Owner).WeaponShake();
  
	GotoState('Firing');
}

function AltFire()
{
	if (PlayerPawn(Owner).bFrozen)
	return;
	
	GotoState('EngineStop');
}

simulated function Activate()
{
	Super.Activate();

	LargeIdleOffTimer = Level.TimeSeconds;
}

simulated function ChewItUp(bool ChewChew)
{
	local WAMEntry entry;

	if (ChewChew != bChewItUp)
	{
		bChewItUp = ChewChew;
		if (ChewChew && (AnimSequence != 'attackgrind'))
			AnimSequence = 'attackgrind';
		else if (AnimSequence != 'attacksolo') 
			AnimSequence = 'attacksolo';
	}
}



/*-----------------------------------------------------------------------------
	Animation Notifications
-----------------------------------------------------------------------------*/

simulated function WpnFire(optional bool noWait)
{
	local WAMEntry entry;

	// Play the animation.
	if (bChewItUp)
		ActiveWAMIndex = GetRandomWAMEntry(default.SAnimChewFire, entry);
	else
		ActiveWAMIndex = GetRandomWAMEntry(default.SAnimFire, entry);
	PlayWAMEntry(entry, !noWait, 'None');
	
    if ( !bDontPlayOwnerAnimation )
        Pawn(Owner).WpnPlayFire();
    
	ClientSideEffects();
    bDontPlayOwnerAnimation = false;

	if (AmbientSound != AttackingAmbientSound)
		AmbientSound = AttackingAmbientSound;
}

simulated function WpnEngineStart()
{
	local WAMEntry entry;
	if (FRand() < 0.1)
	{
		ActiveWAMIndex = GetRandomWAMEntry(default.SAnimEngineStartTrouble, entry);
		PlayWAMEntry(entry, true, 'None');
	} else {
		ActiveWAMIndex = GetRandomWAMEntry(default.SAnimEngineStart, entry);
		PlayWAMEntry(entry, true, 'None');
	}
}

simulated function WpnEngineStop()
{
	local WAMEntry entry;
	ActiveWAMIndex = GetRandomWAMEntry(default.SAnimEngineStop, entry);
	PlayWAMEntry(entry, true, 'None');
}

simulated function WpnIdleOffSmall()
{
	local WAMEntry entry;
	ActiveWAMIndex = GetRandomWAMEntry(default.SAnimIdleOffSmall, entry);
	PlayWAMEntry(entry, false, 'None');
}

simulated function WpnIdleOffLarge()
{
	local WAMEntry entry;
	ActiveWAMIndex = GetRandomWAMEntry(default.SAnimIdleOffLarge, entry);
	PlayWAMEntry(entry, false, 'None');
}

simulated function WpnIdleOff()
{
	WpnIdleOffSmall();
}

simulated function WpnActivate()
{
	Super.WpnActivate();
	AmbientSound = IdleAmbientSound;
	SetTimer(1.0, true, 2);
	

}

simulated function WpnDeactivated()
{
	Super.WpnDeactivated();
	SetTimer(0.0, false, 2);
	AmbientSound = None;
}



/*-----------------------------------------------------------------------------
	States
-----------------------------------------------------------------------------*/

state Firing
{
	// Allow the weapon to interrupt firing and fire again.
simulated function ForceFire()
	{
		if (!GottaReload())
			Global.Fire();
	}

simulated function Fire() 
	{
		if (!GottaReload())
			GotoState('Firing', 'FireAgain');
	}

Begin:
	// Play the start of firing animation.
	if (bFireStart)
	{
		WpnFireStart();
		FinishAnim();
	}

	// Play the firing animation.
	SetTimer(0.1, true);
	WpnFire();
	FinishAnim();
	SetTimer(0.0, false);
	AmbientSound = IdleAmbientSound;

	// If the fire button is down, fire again.
	if ( CanFire() && ButtonFire() )
		Fire();
	else if ( CanFire() && ButtonAltFire()  )
		AltFire();
	else
	{
		// Play the end of firing animation.
		if (bFireStop)
		{
			WpnFireStop();
			FinishAnim();
		}

		// Perform end of fire l0gic.
		FinishFire();
	}

FireAgain:
	// Play the firing animation.
	SetTimer(0.1, true);
	WpnFire();
	FinishAnim();
	SetTimer(0.0, false);
	AmbientSound = IdleAmbientSound;
	bChewItUp = false;

	// If the fire button is down, fire again.
	if ( CanFire() && ButtonFire() )
		Fire();
	else if ( CanFire() && ButtonAltFire()  )
		AltFire();
	else
	{
		// Play the end of firing animation.
		if (bFireStop)
		{
			WpnFireStop();
			FinishAnim();
		}

		// Perform end of fire l0gic.
		FinishFire();
	}
}

state ClientFiring
{
	// Allow the weapon to interrupt firing and fire again.
	simulated function bool ClientFire()
	{
		if ( CanFire() )
		{
//			bFireStartClient = true;
//			bFireClient = false;
//			bFireStopClient = false;
			return Global.ClientFire();
		} else
			return false;
	}
}

state EngineStart
{
function ForceFire()
	{
//		bForceFire = true;
	}

function ForceAltFire()
	{
//		bForceAltFire = true;
	}

	function Fire() {}

	function AltFire() {}

Begin:
    WpnEngineStart();
	SetTimer(1.0, true, 2);
	AmbientSound = IdleAmbientSound;
	GotoState('Idle');
}

state EngineStop
{
function ForceFire()
	{
//		bForceFire = true;
	}

function ForceAltFire()
	{
//		bForceAltFire = true;
	}

function Fire() {}

function AltFire() {}

Begin:
	AmbientSound = None;
	SetTimer(0.0, false, 2);
    WpnEngineStop();
	GotoState('IdleOff');
}

state IdleOff
{
function ForceFire()
	{
//		bForceFire = true;
	}

function ForceAltFire()
	{
//		bForceAltFire = true;
	}

function Fire() {}

function AltFire()
	{
	if (PlayerPawn(Owner).bFrozen)
	return;
		GotoState('EngineStart');
	}

//	function AnimEnd()
//	{
//		WpnIdleOff();
//	}

//	function bool Deactivate()
//	{
//		GotoState('DownWeapon');
//		return true;
//	}

	simulated function bool PutDown()
	{
		// Go to the down state right away.
		GotoState('DownWeapon');
		return true;
	}

	// Called when the current animation ends.
	simulated function AnimEnd()
	{
		// Play an idle animation.
		WpnIdleOff();
	}

	// Called when the state is entered.
	simulated function BeginState()
	{
		if ( bChangeWeapon )
		{
			// If we have to change weapons, do it!
			PutDown();
			return;
		}

	}
Begin:
	WpnIdleOff();
}

//HMMMMMMMMMMMMMMMMMMMMMM MIXING BAD COPYING FROM WEAPON.UC AND MODIFIYNG DAMPENING GOOD
simulated function PlayNotifySound0() { if ( (Owner == None) || (Instigator == None) ) return; Owner.PlaySound(NotifySounds[0], SLOT_None, Instigator.SoundDampening*15); }
simulated function PlayNotifySound1() { if ( (Owner == None) || (Instigator == None) ) return; Owner.PlaySound(NotifySounds[1], SLOT_None, Instigator.SoundDampening*15); }
simulated function PlayNotifySound2() { if ( (Owner == None) || (Instigator == None) ) return; Owner.PlaySound(NotifySounds[2], SLOT_None, Instigator.SoundDampening*15); }

defaultproperties
{
	 MeleeHitRadius=80.0
     SAnimActivate(0)=(AnimSound=sound'dnGame.DukeChainsaw.CSawStartHD')
	 SAnimDeactivate(0)=(AnimSound=Sound'dnsWeapn.chainsaw.CSawStop')
     SAnimFireStart(0)=(AnimChance=1.0,animSeq=attackstart,AnimRate=1.0)
     SAnimFire(0)=(animSeq=attacksolo)
     SAnimChewFire(0)=(AnimChance=1.0,animSeq=attackgrind,AnimRate=1.0)
     SAnimFireStop(0)=(AnimChance=1.0,animSeq=attackstop,AnimRate=1.0)
     SAnimReload(0)=(animSeq=multienginestart)
     SAnimIdleSmall(0)=(AnimChance=0.200000,animSeq=idlea_on)
     SAnimIdleSmall(1)=(AnimChance=0.200000,animSeq=idleb_on)
     SAnimIdleSmall(2)=(AnimChance=0.200000,animSeq=idlec_on)
     SAnimIdleSmall(3)=(AnimChance=0.200000,animSeq=idled_on)
     SAnimIdleOffSmall(0)=(AnimChance=0.200000,animSeq=idlea_off)
     SAnimIdleOffSmall(1)=(AnimChance=0.200000,animSeq=idleb_off)
     SAnimIdleOffSmall(2)=(AnimChance=0.200000,animSeq=idlec_off)
     SAnimIdleOffSmall(3)=(AnimChance=0.200000,animSeq=idled_off)
     SAnimEngineStop(0)=(AnimChance=1.0,animSeq=enginestop,AnimRate=1.0,AnimSound=Sound'dnsWeapn.chainsaw.CSawStop')
     SAnimEngineStart(0)=(AnimChance=1.0,animSeq=enginestart,AnimRate=1.0,AnimSound=Sound'dnGame.DukeChainsaw.CSawStartHD')
     SAnimEngineStartTrouble(0)=(AnimChance=1.0,animSeq=multienginestart,AnimRate=1.0)

	 ItemName="Chainsaw"
     PlayerViewMesh=Mesh'c_dnWeapon.dukechainsaw'
     PickupViewMesh=Mesh'c_dnWeapon.w_chainsaw'
     ThirdPersonMesh=Mesh'c_dnWeapon.w_chainsaw'
	 Mesh=Mesh'c_dnWeapon.w_chainsaw'
     PickupSound=Sound'Duke3d.urinal.Ahmuch03'
     PlayerViewOffset=(X=2.5,Y=0.512,Z=-6.6)
     Icon=Texture'hud_effects.mitem_chainsaw'
	 PickupIcon=texture'hud_effects.am_chainsaw'
     dnInventoryCategory=0
	 dnCategoryPriority=1
	 PlayerViewScale=0.1
	 PickupViewScale=2.0
	 DrawScale=2.0
	 HitOffset=(Y=4.0,Z=-8.0)
	 bBoneDamage=true

	 IdleAmbientSound=sound'dnsWeapn.Chainsaw.CSawIdleLp'
	 AttackingAmbientSound=sound'dnGame.DukeChainsaw.CSawRunLpHD'

	 AmmoItemClass=class'HUDIndexItem_Chainsaw'
	 AltAmmoItemClass=none

	 AmmoName=class'dnGame.ChainsawFuel'
	 PickupAmmoCount(0)=20

	 bFireStart=true
	 bFireStop=true
	 
	 TraceHitCategory=TH_Chainsaw
	 TraceDamageType=class'ChainsawDamage'

	RunAnim=(AnimSeq=A_Run_1HandGun,AnimChan=WAC_All,AnimRate=1.0,AnimTween=0.1,AnimLoop=true)
    FireAnim=(AnimSeq=T_Melee_Chainsaw_Thrust,AnimChan=WAC_Top,AnimRate=1.0,AnimTween=0.1,AnimLoop=True)
    AltFireAnim=(AnimSeq=T_Melee_Chainsaw_Idle,AnimChan=WAC_Top,AnimRate=1.0,AnimTween=0.1,AnimLoop=true)
    IdleAnim=(AnimSeq=T_Melee_Chainsaw_Idle,AnimChan=WAC_Top,AnimRate=1.0,AnimTween=0.1,AnimLoop=true)
    CrouchIdleAnim=(AnimSeq=T_CrchIdle_GenGun,AnimChan=WAC_Top,AnimRate=1.0,AnimTween=0.1,AnimLoop=true)
    CrouchWalkAnim=(AnimSeq=A_CrchWalk_Pistol,AnimChan=WAC_All,AnimRate=1.0,AnimTween=0.1,AnimLoop=true)
    CrouchFireAnim=(AnimSeq=T_CrchFire_GenGun,AnimChan=WAC_Top,AnimRate=1.0,AnimTween=0.1,AnimLoop=false)
	 
	 CrosshairIndex=1
	 AutoSwitchPriority=2
	 
	 NotifySounds(0)=sound'dnGame.DukeChainsaw.CSawTrouble'
	 NotifySounds(1)=sound'dnGame.DukeChainsaw.CSawTrouble'
	 NotifySounds(2)=sound'dnGame.DukeChainsaw.CSawStartHD'
}
