Scriptname _00E_AnimTest_SC extends Actor

Package[] Property akCustomAnimPackageArray Auto
Bool Property SyncAnimations = False Auto
{ (Optional) If True, sets bIsSynced animation variable to True on the packages' start. By default, False. }

Bool bIsInCombat ; Flag protecting from IdleForceDefaultState spam in combat


;=====================================================================================
;              							EVENTS
;=====================================================================================

Event OnCellAttach()
	; Failsafe resets
	bIsInCombat = False
EndEvent

Event OnPackageStart(Package akNewPackage)
	If IsAnimPackage(akNewPackage)
		RegisterForSleep()
		TriggerAnimationSyncUpdate()
	EndIf
EndEvent

Event OnPackageChange(Package akOldPackage)
	If IsAnimPackage(akOldPackage)
		GoToState("") ; Quit PackageStartUpdate state
		UnregisterForSleep()
		ResetAnimations()
	EndIf
EndEvent

State PackageStartUpdate
	Event OnUpdate()
		If IsInDialogueWithPlayer()
			RegisterForSingleUpdate(3.0)
			Return
		EndIf

		GoToState("")

		If SyncAnimations && Is3DLoaded() && bIsInCombat == False
			SetAnimationVariableBool("bIsSynced", True)
		EndIf
	EndEvent
EndState

Event OnSleepStop(bool abInterrupted)
	If Is3DLoaded()
		Package akCurPackage = GetCurrentPackage()
		If IsAnimPackage(akCurPackage)
			ResetAnimations()
			TriggerAnimationSyncUpdate()
		EndIf
	EndIf
EndEvent

Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
	If bIsInCombat == False
		CombatResetAnimations()
	EndIf
EndEvent

Event OnCombatStateChanged(Actor akTarget, int aeCombatState)
	If aeCombatState != 0
		If bIsInCombat == False
			bIsInCombat = True
			CombatResetAnimations()
		EndIf
	Else ; aeCombatState == 0
		GetCombatState()
		If GetCombatState() == 0
			bIsInCombat = False
		EndIf
	EndIf
EndEvent

Event OnDying(Actor akKiller)
	UnregisterForSleep()
	GoToState("DoNothing")
EndEvent

Event OnDeath(Actor akKiller)
	UnregisterForSleep()
	GoToState("DoNothing")
EndEvent

State DoNothing
	Event OnPackageStart(Package akNewPackage)
		; Do nothing
	EndEvent

	Event OnPackageChange(Package akOldPackage)
		; Do nothing
	EndEvent

	Event OnSleepStop(bool abInterrupted)
		; Do nothing
	EndEvent

	Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
		; Do nothing
	EndEvent

	Event OnCombatStateChanged(Actor akTarget, int aeCombatState)
		; Do nothing
	EndEvent

	Event OnDying(Actor akKiller)
		; Do nothing
	EndEvent

	Event OnDeath(Actor akKiller)
		; Do nothing
	EndEvent
EndState


;=====================================================================================
;              							FUNCTIONS
;=====================================================================================

Bool bCombatResetLocked = False

Function CombatResetAnimations()
	If bCombatResetLocked == False
		bCombatResetLocked = True
		If IsAnimPackage(GetCurrentPackage())
			ResetAnimations()
		EndIf
		Utility.Wait(1.0)
		bCombatResetLocked = False
	EndIf
EndFunction

Function ResetAnimations()
	If SyncAnimations
		SetAnimationVariableBool("bIsSynced", False)
	EndIf
	Debug.SendAnimationEvent(Self, "IdleForceDefaultState")
EndFunction

Bool Function IsAnimPackage(Package akPackage)
	Return (akPackage && akCustomAnimPackageArray.Find(akPackage) >= 0)
EndFunction

Function TriggerAnimationSyncUpdate()
	If SyncAnimations && bIsInCombat == False
		GoToState("PackageStartUpdate")
		RegisterForSingleUpdate(3.0)
	EndIf
EndFunction

Function UpdateFillPackages(Package akFillPackage) ; Version 2.0.8 Update
	Int i = 0
	While i < akCustomAnimPackageArray.Length
		akCustomAnimPackageArray[i] = akFillPackage
		i += 1
	EndWhile

	If Is3DLoaded()
		ResetAnimations()
	EndIf
EndFunction