enderalse/source/scripts/_00E_CombatMusicControl.psc

244 lines
5.8 KiB
Plaintext

Scriptname _00E_CombatMusicControl extends Quest Hidden
MusicType[] ActiveCombatMusics
MusicType[] StoppingCombatMusics
Int StoppingCombatMusicCounter = 0
Int Property COMBAT_MUSIC_LOCK_NONE = 0 AutoReadOnly
Int Property COMBAT_MUSIC_LOCK_START = 1 AutoReadOnly
Int Property COMBAT_MUSIC_LOCK_STOP = 2 AutoReadOnly
Int Property COMBAT_MUSIC_LOCK_FAILSAFE = 3 AutoReadOnly
Int CombatMusicLockLevel = 0 ; = COMBAT_MUSIC_LOCK_NONE
Event OnInit()
; Yes, OnInit() runs in idle quests as well
InitCombatMusic() ; also called from OnPlayerLoadGame() in _00E_PlayerFunctions
EndEvent
Function InitCombatMusic()
RegisterForModEvent("Enderal_CombatStateChanged", "OnCombatStateChange")
If ActiveCombatMusics.Length == 0
ActiveCombatMusics = _NewMusicArray()
EndIf
If StoppingCombatMusics.Length == 0
StoppingCombatMusics = _NewMusicArray()
EndIf
If StoppingCombatMusicCounter > 0 || ActiveCombatMusics[0]
GoToState("CombatMusicTracking")
EndIf
EndFunction
function IsStartingBrawling()
bIsBrawling = true
RegisterForSingleUpdate(1.0)
endfunction
event OnUpdate()
bIsBrawling = false
endevent
Event OnCombatStateChange(string eventName, string bTargetIsPlayer, float fCombatState, Form sender)
return
if bTargetIsPlayer ; start combat or searching
if fCombatState as int == 1 ; combat
if bIsBrawling
bIsBrawling = false
if GetState() == ""
UnregisterForUpdate()
else
StopCombatMusic()
endif
return
endif
; start music
Actor sourceActor = sender as Actor
Int encounterLevel = sourceActor.GetLevel()
If encounterLevel >= 20 || (encounterLevel >= PlayerLevel.GetValue() - 15) || HasKeyword(ActorTypeBoss)
MusicType combatMusic
if _00E_ActorsCombatMusicEpic.HasForm(sourceActor.GetActorBase())
combatMusic = _00E_Music_Combat_Epic
elseif EnderalFunctions.IsInRegion(Wueste)
combatMusic = _00E_Music_Combat_Exotic
else
combatMusic = _00E_Music_Combat_Regular
endif
if StartCombatMusic(combatMusic)
RegisterForSingleUpdate(5.0)
EndIf
EndIf
elseif ! PlayerRef.IsInCombat()
if GetState() == ""
GoToState("CombatMusicTracking")
endif
RegisterForSingleUpdate(2.0)
endif
elseif ! PlayerRef.IsInCombat()
if GetState() == ""
GoToState("CombatMusicTracking")
endif
RegisterForSingleUpdate(2.0)
endif
endEvent
Bool Function StartCombatMusic(MusicType newMusic)
; Debug.Trace(self + ", StartCombatMusic, newMusic = " + newMusic)
Bool result = False
While CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE
Utility.Wait(0.03) ; wait for two frames
EndWhile
CombatMusicLockLevel = COMBAT_MUSIC_LOCK_START
Int Index = _AddUniqueMusicToArray(ActiveCombatMusics, newMusic)
If Index >= 0
ActiveCombatMusics[Index].Add()
result = (Index == 0) ; Is this the first combat music in this fight?
EndIf
StoppingCombatMusicCounter = 0
GoToState("CombatMusicTracking")
CombatMusicLockLevel = COMBAT_MUSIC_LOCK_NONE
Return result
EndFunction
Function StopCombatMusic()
; Debug.Trace(self + ", StopCombatMusic")
While CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE
If CombatMusicLockLevel == COMBAT_MUSIC_LOCK_START || CombatMusicLockLevel == COMBAT_MUSIC_LOCK_STOP
Return
EndIf
Utility.Wait(0.03)
EndWhile
CombatMusicLockLevel = COMBAT_MUSIC_LOCK_STOP
Int Index = 0
While Index < ActiveCombatMusics.Length && ActiveCombatMusics[Index]
ActiveCombatMusics[Index].Remove()
_AddUniqueMusicToArray(StoppingCombatMusics, ActiveCombatMusics[Index])
Index += 1
EndWhile
ActiveCombatMusics = _NewMusicArray()
StoppingCombatMusicCounter = 8
GoToState("CombatMusicTracking")
CombatMusicLockLevel = COMBAT_MUSIC_LOCK_NONE
EndFunction
State CombatMusicTracking
Event OnBeginState()
RegisterForSingleUpdate(0.1)
EndEvent
Event OnEndState()
UnregisterForUpdate()
EndEvent
Event OnUpdate()
RegisterForSingleUpdate(3.5)
If CombatMusicLockLevel > COMBAT_MUSIC_LOCK_NONE || PlayerRef.IsInCombat()
Return
EndIf
If StoppingCombatMusicCounter > 0
CombatMusicLockLevel = COMBAT_MUSIC_LOCK_FAILSAFE
; Debug.Trace(self + ", OnUpdate: failsaving")
Int Index = 0
While Index < StoppingCombatMusics.Length && StoppingCombatMusics[Index]
StoppingCombatMusics[Index].Add()
StoppingCombatMusics[Index].Remove()
Index += 1
EndWhile
StoppingCombatMusicCounter -= 1
If StoppingCombatMusicCounter <= 0
StoppingCombatMusics = _NewMusicArray()
EndIf
CombatMusicLockLevel = COMBAT_MUSIC_LOCK_NONE
ElseIf ActiveCombatMusics[0] ; Failsafe in case StopCombatMusic is not called for whatever reason
StopCombatMusic()
Else
GoToState("")
EndIf
EndEvent
EndState
MusicType[] Function _NewMusicArray()
Return New MusicType[10]
EndFunction
Int Function _AddUniqueMusicToArray(MusicType[] musics, MusicType newMusic)
Int n = musics.Length
Int Index = 0
; Loop through array until we reach the end or newMusic or an empty entry
While Index < n && musics[Index] != newMusic && musics[Index] != None
Index += 1
EndWhile
If Index < n && musics[Index] == None
musics[Index] = newMusic
Return Index
Else
Return -1
EndIf
EndFunction
Function RemoveCombatSoundtracks()
int iIndex = _00E_MUS_AllCombatSoundtracks.GetSize()
while iIndex > 0
iIndex -= 1
MusicType musicToRemove = _00E_MUS_AllCombatSoundtracks.GetAt(iIndex) as MusicType
musicToRemove.Remove()
endwhile
EndFunction
bool bIsBrawling = false
Keyword Property ActorTypeBoss Auto
GlobalVariable Property PlayerLevel Auto
MusicType Property _00E_Music_Combat_Regular Auto
MusicType Property _00E_Music_Combat_Exotic Auto
MusicType Property _00E_Music_Combat_Epic Auto
FormList Property _00E_MUS_AllCombatSoundtracks Auto
FormList Property _00E_ActorsCombatMusicEpic Auto
Form Property Wueste Auto ; Powder Desert
Actor Property PlayerRef Auto