ScriptName footprintsFootstepsScriptPlayer Extends ActiveMagicEffect

footprintsVCScript Property footprintsVCQuest Auto

GlobalVariable Property fp_IsFootprintsDisabled Auto
GlobalVariable Property fp_IsSKSEInstalled Auto

ImpactDataSet[] Property LeftIPDS Auto
ImpactDataSet[] Property RightIPDS Auto
{
	0 - Run, 1 - Walk, 2 - Sprint, 3 - Sneak, 4  - StrafeL, 5  - StrafeR
	6 - Run, 7 - Walk, 8 - Sprint, 9 - Sneak, 10 - StrafeL, 11 - StrafeR (Barefoot)
}

; States
ImpactDataSet CurrLeftIPDS
ImpactDataSet CurrRightIPDS

int RUN = 0
int WALK = 1
int SPRINT = 2
int SNEAK = 3
int L_STRAFE = 4
int R_STRAFE = 5

; Boot Detection
Armor PreviousBoots
Armor CurrentBoots
int BootOffset = 0

; Animation Variables
float fDirection
;float fSpeed

; Strafing
int strafeDir

Actor selfRef
Actor Property playerRef Auto


Event OnEffectStart( Actor target, Actor caster )
    selfRef = target
	If ( !(selfRef && selfRef == playerRef) || fp_IsFootprintsDisabled.GetValue() )
		return
	EndIf
	
	If ( RegisterForAnimationEvent( selfRef, "FootLeft" ) && RegisterForAnimationEvent( selfRef, "FootRight" ) \
		&& RegisterForAnimationEvent( selfRef, "FootSprintLeft" ) && RegisterForAnimationEvent( selfRef, "FootSprintRight" ) \
		&& RegisterForAnimationEvent( selfRef, "JumpUp" ) && RegisterForAnimationEvent( selfRef, "JumpDown" ) )
		
		CurrLeftIPDS = LeftIPDS[0]
		CurrRightIPDS = RightIPDS[0]

		GoToState( "alive" )
	EndIf
EndEvent

Event OnAnimationEvent( ObjectReference akSelfRef, string e )
	If ( (e == "FootLeft" && !selfRef.IsSprinting()) || e == "FootSprintLeft" )
		akSelfRef.PlayImpactEffect( CurrLeftIPDS, "NPC L Calf [LClf]", 0, 0, -1, 128, false, false )
	ElseIf ( (e == "FootRight" && !selfRef.IsSprinting()) || e == "FootSprintRight" )
		akSelfRef.PlayImpactEffect( CurrRightIPDS, "NPC R Calf [RClf]", 0, 0, -1, 128, false, false )
	ElseIf ( e == "JumpUp" || e == "JumpDown" )
		akSelfRef.PlayImpactEffect( CurrLeftIPDS, "NPC L Thigh [LThg]", 0, 0, -1, 128, false, false )
		akSelfRef.PlayImpactEffect( CurrRightIPDS, "NPC R Thigh [RThg]", 0, 0, -1, 128, false, false )
	EndIf
EndEvent


; Non-SKSE / Beginning State
State alive

    Event OnBeginState()
		If ( fp_IsSKSEInstalled.GetValue() )
			Debug.Trace( "~~~~~ Footprints: Switching to SKSE Footprints, SKSE Installed ~~~~~" )
			GoToState( "alive_SKSE" )
			return
		EndIf
		RegisterForSingleUpdate( 2.0 )
    EndEvent

    Event OnUpdate()
		fDirection = selfRef.GetAnimationVariableFloat( "Direction" )
		;fSpeed = selfRef.GetAnimationVariableFloat( "Speed" )
		
		; Set IPDS based on strafe/combat conditions
		SetCurrIPDS()
		
		RegisterForSingleUpdate( 1.0 )
	EndEvent
    
EndState


; SKSE
State alive_SKSE

    Event OnBeginState()
        ; Begin SKSE routine
		BootCheck()
		RegisterForSingleUpdate( 2.0 )
    EndEvent
	
	Event OnUpdate()
		If ( !fp_IsSKSEInstalled.GetValue() )
			;Debug.Trace( "footprintsFootstepsPlayerScript - Switching to non-SKSE state" )
			GoToState( "alive" )
			return
		EndIf
		
		fDirection = selfRef.GetAnimationVariableFloat( "Direction" )
		;fSpeed = selfRef.GetAnimationVariableFloat( "Speed" )

		; Set IPDS based on strafe/combat conditions
		SetCurrIPDS()
		
		RegisterForSingleUpdate( 0.5 )
	EndEvent
	
	Event OnObjectEquipped( Form akBaseObject, ObjectReference akReference )
		If ( !fp_IsSKSEInstalled.GetValue() )
			;Debug.Trace( "footprintsFootstepsPlayerScript - Switching to non-SKSE state" )
			GoToState( "alive" )
			return
		EndIf
		If ( akBaseObject as Armor )
			BootCheck()
		EndIf
	EndEvent
	
	Event OnObjectUnequipped( Form akBaseObject, ObjectReference akReference )
		If ( !fp_IsSKSEInstalled.GetValue() )
			;Debug.Trace( "footprintsFootstepsPlayerScript - Switching to non-SKSE state" )
			GoToState( "alive" )
			return
		EndIf
		If ( akBaseObject as Armor )
			BootCheck()
		EndIf
	EndEvent
	
	bool Function BootCheck()
		;Debug.Trace( "footprintsFootstepsPlayerScript - Boot Check" )
		CurrentBoots = selfRef.GetWornForm(0x00000080) as Armor
		If ( CurrentBoots && (CurrentBoots == PreviousBoots) )
			;Debug.Trace( "footprintsFootstepsPlayerScript - Boots have not changed since last update" )
			return False
		EndIf
		
		If ( !CurrentBoots )
			;Debug.Trace( "footprintsFootstepsPlayerScript - " + selfRef + " is barefoot." )
			BootOffset = 6
		Else
			;Debug.Trace( "footprintsFootstepsPlayerScript - " + selfRef + " is wearing footwear." )
			BootOffset = 0
		EndIf
		
		PreviousBoots = CurrentBoots
		SetCurrIPDS()
		
		return True
	EndFunction

EndState


Function SetCurrIPDS()
	int offset = 0
	
	strafeDir = StrafeDir()
	If ( strafeDir == 0 )
		; Going backward or forward
		If ( selfRef.IsSprinting() )
			;Debug.Trace("-=-=-=-=-= Footprints: Player is Sprinting =-=-=-=-=-")
			offset = SPRINT
		ElseIf ( selfRef.IsRunning() )
			;Debug.Trace("-=-=-=-=-= Footprints: Player is Running =-=-=-=-=-")
			offset = RUN
		ElseIf ( selfRef.IsSneaking() )
			;Debug.Trace("-=-=-=-=-= Footprints: Player is Sneaking =-=-=-=-=-")
			offset = SNEAK
		Else
			;Debug.Trace("-=-=-=-=-= Footprints: Player is Walking =-=-=-=-=-")
			offset = WALK
		EndIf
	ElseIf ( !selfRef.IsRunning() && selfRef.IsWeaponDrawn() )
		; Special Case
		; Player backsteps with right foot
		;Debug.Trace("-=-=-=-=-= Footprints: Player is Weapon Strafing =-=-=-=-=-")
		CurrLeftIPDS = LeftIPDS[WALK + BootOffset]
		CurrRightIPDS = RightIPDS[R_STRAFE + BootOffset]
		return
	Else
		; Regular strafing
		If ( strafeDir == -1 )
			;Debug.Trace("-=-=-=-=-= Footprints: Player is Strafing Left =-=-=-=-=-")
			offset = L_STRAFE
		ElseIf ( strafeDir == 1 )
			;Debug.Trace("-=-=-=-=-= Footprints: Player is Strafing Right =-=-=-=-=-")
			offset = R_STRAFE
		EndIf
	EndIf
	
	offset += BootOffset
	
	CurrLeftIPDS = LeftIPDS[offset]
	CurrRightIPDS = RightIPDS[offset]
EndFunction


int Function StrafeDir()
	fDirection = selfRef.GetAnimationVariableFloat( "Direction" )
	If ( fDirection == 0.25 )
		; Right
		return 1
	ElseIf ( fDirection == 0.75 )
		; Left
		return -1
	EndIf
	; Not Strafing
	return 0
EndFunction


Function ResetIPDS()
	CurrLeftIPDS = LeftIPDS[0]
	CurrRightIPDS = RightIPDS[0]
EndFunction


bool Function BootCheck()

EndFunction


State Dead
	
	Event OnBeginState()
		;Debug.Trace("-=-=-=-=-= Footprints: Player footsteps script dead. =-=-=-=-=-")
	EndEvent

	Event OnAnimationEvent( ObjectReference akSelfRef, string e )

	EndEvent

	Event OnUpdate()

	EndEvent

EndState
