Scriptname _00E_Game_TalentCooldownSC extends ActiveMagicEffect {Script that controls the individual cooldown of talents, rather than have all of them trigger a global cooldown.} Sound Property UISkillsFocus auto _00E_Game_TalentControlSC Player Shout[] CooldownShouts Float[] CooldownTimes Shout CurrentShout Bool ShoutIsCoolingDown Bool ShoutEquipLocked = False Float LastTimeElapsed Float Property IdleUpdatePeriod = 30.0 AutoReadOnly ;===================================================================================== ; EVENTS ;===================================================================================== Event OnEffectStart(Actor akTarget, Actor akCaster) LockEquipUpdates() CooldownShouts = New Shout[128] CooldownTimes = New Float[128] LastTimeElapsed = 0.0 Player = Game.GetPlayer() as _00E_Game_TalentControlSC CurrentShout = Player.GetEquippedShout() UnlockEquipUpdates() Player.RegisterCooldownMagicEffect(self) EndEvent Event OnUpdate() If Player.GetVoiceRecoveryTime() <= 0.0 && ShoutIsCoolingDown && (ShoutEquipLocked == False) ShoutIsCoolingDown = False UISkillsFocus.Play(Player) EndIf ; Protection against the GetTimeElapsed timer getting stuck Float curTimeElapsed = GetTimeElapsed() If LastTimeElapsed == curTimeElapsed Player.RefreshCooldownSpell() Else LastTimeElapsed = curTimeElapsed RegisterNextUpdate(ResetLastTimeElapsed = False) EndIf EndEvent Event OnObjectEquipped(Form equippedObject, ObjectReference reference) ; Is it a shout being equipped? Shout equippedShout = equippedObject as Shout If !equippedShout Return EndIf LockEquipUpdates() ; Save the old shout's cooldown If CurrentShout SaveShoutRecoveryTime(CurrentShout, Player.GetVoiceRecoveryTime()) EndIf ; Restore the newly equipped shout's cooldown ; Due to the Waits and stuff above, it's better to get the equipped shout again. equippedShout = Player.GetEquippedShout() If equippedShout && equippedShout != CurrentShout CurrentShout = equippedShout Float recoveryTime = 0.0 Int Index = FindShoutIndex(equippedShout) If Index >= 0 recoveryTime = CooldownTimes[Index] - GetTimeElapsed() If recoveryTime < 0.0 recoveryTime = 0.0 EndIf EndIf Player.SetVoiceRecoveryTime(recoveryTime) EndIf UnlockEquipUpdates() EndEvent ;===================================================================================== ; FUNCTIONS ;===================================================================================== Function LockEquipUpdates() While ShoutEquipLocked Utility.WaitMenuMode(0.1) EndWhile ShoutEquipLocked = True EndFunction Function UnlockEquipUpdates() RegisterNextUpdate() ShoutEquipLocked = False EndFunction Int Function FindShoutIndex(Shout s) Int Index = 0 Int nShouts = CooldownShouts.Length While Index < nShouts && CooldownShouts[Index] If CooldownShouts[Index] == s Return Index Else Index += 1 EndIf EndWhile Return -1 EndFunction Int Function FindShoutOrNoneIndex(Shout s) Int Index = 0 Int nShouts = CooldownShouts.Length While Index < nShouts && CooldownShouts[Index] != s && CooldownShouts[Index] Index += 1 EndWhile If Index >= nShouts Debug.Notification("_00E_Game_TalentCooldownSC has run out of free shout slots") Return -1 EndIf Return Index EndFunction Function SaveShoutRecoveryTime(Shout targetShout, Float recoveryTime) Int Index If recoveryTime > 0.0 Index = FindShoutOrNoneIndex(targetShout) If Index >= 0 CooldownShouts[Index] = targetShout ; In case it's None CooldownTimes[Index] = recoveryTime + GetTimeElapsed() EndIf Else ; recoveryTime < 0.0 Index = FindShoutIndex(targetShout) If Index >= 0 CooldownTimes[Index] = 0 EndIf EndIf EndFunction Function RegisterNextUpdate(Bool ResetLastTimeElapsed = True) If ResetLastTimeElapsed LastTimeElapsed = -1 EndIf Float recoveryTime = Player.GetVoiceRecoveryTime() ShoutIsCoolingDown = (recoveryTime > 0.0) If recoveryTime > 0.0 && recoveryTime < IdleUpdatePeriod RegisterForSingleUpdate(recoveryTime) Else RegisterForSingleUpdate(IdleUpdatePeriod) EndIf EndFunction ; Called from _00E_Game_TalentCooldownSC Function OnShoutCast() RegisterNextUpdate() EndFunction Function SetShoutRecoveryTime(Shout targetShout, Float newRecoveryTime) If !targetShout Debug.Trace("_00E_Game_TalentCooldownSC: SetShoutRecoveryTime got empty targetShout") Return EndIf LockEquipUpdates() If CurrentShout == targetShout Player.SetVoiceRecoveryTime(newRecoveryTime) Else SaveShoutRecoveryTime(targetShout, newRecoveryTime) EndIf UnlockEquipUpdates() EndFunction