135 lines
3.4 KiB
Plaintext
135 lines
3.4 KiB
Plaintext
Scriptname _00E_BardPlayInstrumentScript extends Actor
|
|
|
|
Sound Property MusicPiece Auto
|
|
|
|
Package Property PlayPackage Auto
|
|
{ The package must have <subject> HasLoaded3D == 1 condition and optionally <subject> GetDisabled == 0 condition (if the reference can be disabled) }
|
|
|
|
Keyword Property LinkedPlayMarkerKeyword Auto
|
|
Spell Property BardPlayTrackerSP Auto
|
|
Bool Property DontRestartTrack Auto
|
|
|
|
Int Property PLAYSTATE_STOPPED = 0 AutoReadOnly
|
|
Int Property PLAYSTATE_PLAYING = 1 AutoReadOnly
|
|
Int Property PLAYSTATE_STOPPING_FADE = 2 AutoReadOnly
|
|
|
|
Int PlayState
|
|
Int MusicInstance
|
|
Float MusicVolume
|
|
|
|
Int WarmupCounter
|
|
Float LastWarmupDistance
|
|
|
|
Event OnPackageStart(Package akNewPackage)
|
|
; Debug.Trace("_00E_BardPlayInstrumentScript, OnPackageStart, " + akNewPackage)
|
|
|
|
If akNewPackage == PlayPackage
|
|
AddSpell(BardPlayTrackerSP, False)
|
|
Else
|
|
RemoveSpell(BardPlayTrackerSP)
|
|
StopMusic()
|
|
EndIf
|
|
EndEvent
|
|
|
|
Event OnBardsLoadGame(string eventName, string strArg, float numArg, Form sender)
|
|
; Debug.Trace("_00E_BardPlayInstrumentScript, OnBardsLoadGame...")
|
|
|
|
If PlayState == PLAYSTATE_PLAYING
|
|
StopMusicInstance()
|
|
RegisterForSingleUpdate(0.25)
|
|
Else ; PlayState == PLAYSTATE_STOPPING_FADE
|
|
StopMusic()
|
|
EndIf
|
|
EndEvent
|
|
|
|
Int Function TickWarmupCounter()
|
|
ObjectReference PlayMarker = GetLinkedRef(LinkedPlayMarkerKeyword)
|
|
If PlayMarker
|
|
Float d = GetDistance(PlayMarker)
|
|
; Is the NPC close to the play marker and kept the same distance from it since the previous tick (doesn't move)?
|
|
If d < 128.0 && (WarmupCounter == 0 || Math.abs(d - LastWarmupDistance) < 1.0)
|
|
LastWarmupDistance = d
|
|
Return WarmupCounter + 1
|
|
EndIf
|
|
EndIf
|
|
|
|
Return 0
|
|
EndFunction
|
|
|
|
Event OnUpdate()
|
|
If PlayState == PLAYSTATE_STOPPED
|
|
Return
|
|
EndIf
|
|
|
|
If MusicInstance != 0 ; Fading
|
|
MusicVolume -= 0.025
|
|
If MusicVolume >= 0.1
|
|
Sound.SetInstanceVolume(MusicInstance, MusicVolume)
|
|
RegisterForSingleUpdate(0.2)
|
|
ElseIf PlayState == PLAYSTATE_PLAYING
|
|
StopMusicInstance()
|
|
RegisterForSingleUpdate(0.1)
|
|
Else ; PlayState == PLAYSTATE_STOPPING_FADE
|
|
StopMusic()
|
|
EndIf
|
|
Else
|
|
If PlayState == PLAYSTATE_PLAYING
|
|
; Wait for the NPC to get close to its linked play marker and stay stationary (more or less) for some time
|
|
WarmupCounter = TickWarmupCounter()
|
|
If WarmupCounter > 4
|
|
MusicInstance = MusicPiece.Play(self)
|
|
MusicVolume = 1.0
|
|
If DontRestartTrack == False
|
|
RegisterForSingleUpdate(2 * 60 + 40) ; 2:40 - roughly the length of the longest "classical" track in Sound\FX\Enderal\Bards
|
|
EndIf
|
|
Else
|
|
RegisterForSingleUpdate(0.25)
|
|
EndIf
|
|
Else ; PlayState == PLAYSTATE_STOPPING_FADE
|
|
StopMusic()
|
|
EndIf
|
|
EndIf
|
|
EndEvent
|
|
|
|
Function StopMusicInstance()
|
|
If MusicInstance != 0
|
|
Int _tempInst = MusicInstance
|
|
MusicInstance = 0
|
|
Sound.StopInstance(_tempInst)
|
|
EndIf
|
|
EndFunction
|
|
|
|
Function StartMusic()
|
|
If PlayState != PLAYSTATE_PLAYING
|
|
PlayState = PLAYSTATE_PLAYING
|
|
RegisterForModEvent("BardsLoadGame", "OnBardsLoadGame")
|
|
StopMusicInstance()
|
|
RegisterForSingleUpdate(0.01)
|
|
EndIf
|
|
EndFunction
|
|
|
|
Function StopMusic()
|
|
If PlayState != PLAYSTATE_STOPPED
|
|
PlayState = PLAYSTATE_STOPPED
|
|
UnregisterForUpdate()
|
|
StopMusicInstance()
|
|
UnregisterForModEvent("BardsLoadGame")
|
|
EndIf
|
|
|
|
WarmupCounter = 0
|
|
EndFunction
|
|
|
|
Function FadeAndStopMusic()
|
|
If PlayState != PLAYSTATE_STOPPED
|
|
If MusicInstance != 0
|
|
PlayState = PLAYSTATE_STOPPING_FADE
|
|
RegisterForSingleUpdate(0.1)
|
|
While PlayState == PLAYSTATE_STOPPING_FADE
|
|
Utility.Wait(0.5)
|
|
EndWhile
|
|
Else
|
|
StopMusic()
|
|
EndIf
|
|
EndIf
|
|
EndFunction
|