Scriptname _00E_BardDialogueFunctions extends Quest Conditional Scene Property BardDialogue_Instrumental20 Auto Scene Property BardDialogue_LastSunset Auto Scene Property BardDialogue_LastSunsetInstrumental Auto Scene Property BardDialogue_Song06 Auto Scene Property BardDialogue_Song08 Auto Scene Property BardDialogue_Song09 Auto Scene Property BardDialogue_Song10 Auto Scene Property BardDialogue_Song11 Auto Scene Property BardDialogue_TheAgedMan Auto Scene Property BardDialogue_TheAgedManInstrumental Auto Scene Property BardDialogue_Vatyra Auto Scene Property BardDialogue_VatyraInstrumental Auto Scene Property BardDialogue_WaywardWanderer Auto Scene Property BardDialogue_WaywardWandererInstrumental Auto Scene Property BardDialogue_WelcomeYouDrunkards Auto Scene Property BardDialogue_Whisperwood Auto Scene Property BardDialogue_SongWaageScene Auto ; Added in FS ReferenceAlias Property SingingBard Auto LocationAlias Property Location_Alias Auto Quest Property BardAudience Auto Location Property _00E_DunevilleInteriorLocation auto Location Property _00E_FlusshaimTaverneLocation auto Location Property _00E_SuntempleQuarters auto Location Property _00E_UEEntr_FalseDog_Location auto Location Property BauernkuesteRoterOchseLocation auto Location Property CapitalCityTheFatLeoranLocation auto Location Property SchneefelstaverneInteriorLocation auto Idle Property IdleStop Auto Scene[] BardSongList Int nBardSongsTotal Bool bSongHasQuestAudience = False Bool bQuestAudienceCheering = False Scene NextSongScene = None Scene Property LastSongScene1 Auto Conditional Hidden Scene LastSongScene2 = None Scene LastSongScene3 = None Int Property QUEST_AUDIENCE_CHANCE = 67 AutoReadOnly ;===================================================================================== ; FUNCTIONS ;===================================================================================== Function Setup(Actor akBard, Scene _LastSongScene) bSongHasQuestAudience = False bQuestAudienceCheering = False NextSongScene = None LastSongScene1 = _LastSongScene LastSongScene2 = None LastSongScene3 = None SingingBard.ForceRefTo(akBard) PlayRandomSong(0.1) EndFunction Function PrepareAudience(Int iAudienceInitialStage) ; A song is about to start, prepare the audience. Called from the scenes. SendModEvent("BardSongStarted") If IsQuestAudienceLocation() && iAudienceInitialStage > 0 bSongHasQuestAudience = True If BardAudience.IsRunning() == False && bQuestAudienceCheering == False If iAudienceInitialStage == 10 Int iAudienceRoll = Utility.RandomInt(1, 100) If iAudienceRoll <= QUEST_AUDIENCE_CHANCE If iAudienceRoll < (QUEST_AUDIENCE_CHANCE / 2) ; Roughly a 50% chance it will be the more lively audience iAudienceInitialStage = 20 EndIf Else iAudienceInitialStage = 0 EndIf EndIf If iAudienceInitialStage > 0 BardAudience.SetStage(iAudienceInitialStage) EndIf EndIf EndIf bQuestAudienceCheering = False EndFunction Function OnSongStart(Scene songScene) ; The bard is actually starting to sing or make instrumental sounds. Called from the scenes. NextSongScene = None LastSongScene3 = LastSongScene2 LastSongScene2 = LastSongScene1 LastSongScene1 = songScene EndFunction Function CheerAudience() ; When a song ends normally, time for the audience to cheer. Called from the scenes. SendModEvent("BardSongApplaud") If IsQuestAudienceLocation() && BardAudience.IsRunning() Int iCurrentAudienceStage = BardAudience.GetStage() If iCurrentAudienceStage >= 10 && iCurrentAudienceStage <= 20 BardAudience.SetStage(100) bQuestAudienceCheering = True EndIf EndIf EndFunction Function OnSongEnd() ; When a song ends normally or is interrupted. Called from the scenes. Actor akBard = SingingBard.GetActorRef() ; If akBard is None in OnSongEnd, most likely it's the player just left the cell and the quest is stopping Bool bLongDelay = False If akBard akBard.PlayIdle(IdleStop) EndIf SendModEvent("BardSongEnded") If bSongHasQuestAudience == False && BardAudience.IsRunning() && BardAudience.GetStage() < 100 BardAudience.Stop() EndIf If akBard Float fNextSongDelay If bQuestAudienceCheering ; A longer gap between songs is needed if the quest audience is applauding ; because otherwise the bard fails to properly pick up the "play intrument" animation at the start of the next song fNextSongDelay = Utility.RandomFloat(5.0, 6.0) Else fNextSongDelay = Utility.RandomFloat(1.5, 3.0) EndIf PlayRandomSong(fNextSongDelay) EndIf EndFunction Function PlayRandomSong(Float fDelay) LockNextSongUpdate() If NextSongScene == None BuildSongList(False) PickRandomSongFromSongList() EndIf UnlockNextSongUpdate() RegisterForSingleUpdate(fDelay) EndFunction Function PlayRequestedSong(Scene requestedSongScene) LockNextSongUpdate() If requestedSongScene NextSongScene = requestedSongScene Else BuildSongList(True) PickRandomSongFromSongList() EndIf UnlockNextSongUpdate() RegisterForSingleUpdate(0.1) EndFunction Event OnUpdate() Actor akBard = SingingBard.GetActorRef() If akBard == None Stop() Return EndIf If akBard.IsInDialogueWithPlayer() RegisterForSingleUpdate(1.0) Return EndIf bSongHasQuestAudience = False If NextSongScene NextSongScene.ForceStart() EndIf EndEvent Function BuildSongList(Bool bOnlyVocalSongs) BardSongList = New Scene[16] nBardSongsTotal = 0 Location bardLoc = Location_Alias.GetLocation() If bardLoc == CapitalCityTheFatLeoranLocation || bardLoc == _00E_DunevilleInteriorLocation || bardLoc == _00E_UEEntr_FalseDog_Location ; VT_Gerril AddSongToList(BardDialogue_WaywardWanderer) AddSongToList(BardDialogue_TheAgedMan) AddSongToList(BardDialogue_LastSunset) AddSongToList(BardDialogue_Whisperwood) AddSongToList(BardDialogue_Song06) ; Black Guardian AddSongToList(BardDialogue_Vatyra) AddSongToList(BardDialogue_Song08) ; Wild Mages AddSongToList(BardDialogue_Song09) ; Lost Ones AddSongToList(BardDialogue_Song10) ; Crimson Star AddSongToList(BardDialogue_Song11) ; Winter Sky (Firmament) AddSongToList(BardDialogue_WelcomeYouDrunkards) ElseIf bardLoc == _00E_FlusshaimTaverneLocation || bardLoc == _00E_SuntempleQuarters ; VT_Liliath AddSongToList(BardDialogue_WaywardWanderer) AddSongToList(BardDialogue_TheAgedMan) AddSongToList(BardDialogue_LastSunset) AddSongToList(BardDialogue_Whisperwood) AddSongToList(BardDialogue_Song06) ; Black Guardian AddSongToList(BardDialogue_Vatyra) AddSongToList(BardDialogue_Song08) ; Wild Mages AddSongToList(BardDialogue_Song09) ; Lost Ones AddSongToList(BardDialogue_Song10) ; Crimson Star ElseIf bardLoc == BauernkuesteRoterOchseLocation ; VT_FS_Bard AddSongToList(BardDialogue_Vatyra) AddSongToList(BardDialogue_Song11) ; Winter Sky (Firmament) AddSongToList(BardDialogue_TheAgedMan) AddSongToList(BardDialogue_SongWaageScene) AddSongToList(BardDialogue_Song10) ; Crimson Star AddSongToList(BardDialogue_WelcomeYouDrunkards) ElseIf bardLoc == SchneefelstaverneInteriorLocation ; VT_Lara If bOnlyVocalSongs LastSongScene3 = None ; The list is too short EndIf AddSongToList(BardDialogue_WaywardWanderer) AddSongToList(BardDialogue_Vatyra) AddSongToList(BardDialogue_Song11) ; Winter Sky (Firmament) Else If bardLoc Debug.Notification("ERROR BardDialogue: unsupported location!") Debug.Trace("ERROR BardDialogue: unsupported location (" + bardLoc + ")") EndIf Return EndIf If bOnlyVocalSongs == False AddSongToList(BardDialogue_VatyraInstrumental) AddSongToList(BardDialogue_WaywardWandererInstrumental) AddSongToList(BardDialogue_TheAgedManInstrumental) AddSongToList(BardDialogue_LastSunsetInstrumental) AddSongToList(BardDialogue_Instrumental20) ; Drum Instrumental EndIf EndFunction Function AddSongToList(Scene songScene) If songScene == LastSongScene1 || songScene == LastSongScene2 || songScene == LastSongScene3 Return ; Has been already played recently EndIf If nBardSongsTotal >= BardSongList.Length Debug.Notification("ERROR BardDialogue: out of free slots for songs!") Debug.Trace("ERROR BardDialogue: out of free slots for songs") Return EndIf BardSongList[nBardSongsTotal] = songScene nBardSongsTotal += 1 EndFunction Function PickRandomSongFromSongList() If nBardSongsTotal == 1 NextSongScene = BardSongList[0] ElseIf nBardSongsTotal > 1 NextSongScene = BardSongList[Utility.RandomInt(0, nBardSongsTotal - 1)] Else ; nBardSongsTotal < 1 NextSongScene = None EndIf EndFunction Actor Function GetSingingBardActor() Return SingingBard.GetActorRef() EndFunction Bool Function IsQuestAudienceLocation() Location bardLoc = Location_Alias.GetLocation() If bardLoc == _00E_FlusshaimTaverneLocation || bardLoc == _00E_DunevilleInteriorLocation || bardLoc == _00E_UEEntr_FalseDog_Location Return True Else Return False EndIf EndFunction ;===================================================================================== ; NEXT SONG LOCK ;===================================================================================== Bool bNextSongUpdateLocked = False Function LockNextSongUpdate() While bNextSongUpdateLocked Utility.WaitMenuMode(0.1) EndWhile bNextSongUpdateLocked = True EndFunction Function UnlockNextSongUpdate() bNextSongUpdateLocked = False EndFunction