enderalse/scripts/source/_00e_gypsyminstrelscontrolscript.psc
2021-10-06 00:59:59 +02:00

216 lines
7.6 KiB
Plaintext

Scriptname _00E_GypsyMinstrelsControlScript extends Quest Conditional
Int Property WAYPOINT_PERFORM_MARKET = 0 AutoReadOnly
Int Property WAYPOINT_TRAVEL_INN = 1 AutoReadOnly
Int Property WAYPOINT_SANDBOX_INN = 2 AutoReadOnly
Int Property WAYPOINT_TRAVEL_MARKET = 3 AutoReadOnly
Float Property SAFE_TELEPORT_DISTANCE = 4000.0 AutoReadOnly
; TIME_PERFORMANCE_START must be less than TIME_PERFORMANCE_END
; TIME_PERFORMANCE_START and TIME_PERFORMANCE_END must be greater than 0
; Otherwise the curHour check in UpdateWaypoint must be rewritten
Float Property TIME_PERFORMANCE_START = 7.0 AutoReadOnly
Float Property TIME_PERFORMANCE_END = 23.0 AutoReadOnly
Int Property CurrentWaypoint Auto Hidden Conditional
ReferenceAlias Property Alias_LutePlayer Auto
ReferenceAlias Property Alias_Dancer Auto
GlobalVariable Property GameHour Auto
Cell Property InnCell Auto
ObjectReference Property TipBasket Auto
ObjectReference Property TempStorageMarker Auto
Actor Property PlayerRef Auto
MusicType Property ArkMarketGypsyPerformanceSilence Auto
Keyword Property LinkCustom01 Auto
Keyword Property LinkPerformanceSpot Auto
Quest Property MQ12b Auto
Quest Property MQ14 Auto
ObjectReference Property MQ12c_Debris_Level_02_Linker Auto
;=====================================================================================
; EVENTS
;=====================================================================================
Event OnInit()
CurrentWaypoint = -1 ; Force update
RegisterForSingleUpdate(3.0) ; Give a few seconds for the game to warm up at the start
EndEvent
Event OnUpdate()
UpdateWaypoint()
EndEvent
Event OnUpdateGameTime()
UpdateWaypoint()
EndEvent
;=====================================================================================
; FUNCTIONS
;=====================================================================================
Function TriggerUpdate()
RegisterForSingleUpdate(1.0)
EndFunction
Bool IsTipBasketHidden = False
Bool WaypointUpdateLocked = False
; Called from OnUpdate, OnUpdateGameTime and from end events of travel packages
Function UpdateWaypoint()
While WaypointUpdateLocked
Utility.Wait(0.5)
EndWhile
WaypointUpdateLocked = True
If MQ14.GetStage() >= 40
; When we reach the endgame in MQ14, the schedule does not matter anymore
SetNewWaypoint(WAYPOINT_SANDBOX_INN, True, -1.0)
ElseIf MQ12b.GetStage() >= 45 && MQ12c_Debris_Level_02_Linker.IsDisabled()
; When the siege of Ark starts, force the minstrels to the inn and keep them there while the streets are cleaned up from debris and bodies.
Float nextUpdateTime = TIME_PERFORMANCE_START - GameHour.GetValue()
If nextUpdateTime < 0.0
nextUpdateTime += 24.0
EndIf
SetNewWaypoint(WAYPOINT_SANDBOX_INN, True, nextUpdateTime)
Else
; Routine time of day update
Float curHour = GameHour.GetValue()
If curHour >= TIME_PERFORMANCE_START && curHour < TIME_PERFORMANCE_END
RoutineWaypointUpdate(WAYPOINT_PERFORM_MARKET, WAYPOINT_TRAVEL_MARKET, curHour - TIME_PERFORMANCE_START, TIME_PERFORMANCE_END - curHour)
ElseIf curHour >= TIME_PERFORMANCE_END
RoutineWaypointUpdate(WAYPOINT_SANDBOX_INN, WAYPOINT_TRAVEL_INN, curHour - TIME_PERFORMANCE_END, TIME_PERFORMANCE_START - curHour + 24.0)
Else ; curHour < TIME_PERFORMANCE_START
RoutineWaypointUpdate(WAYPOINT_SANDBOX_INN, WAYPOINT_TRAVEL_INN, curHour - TIME_PERFORMANCE_END + 24.0, TIME_PERFORMANCE_START - curHour)
EndIf
EndIf
WaypointUpdateLocked = False
EndFunction
Function RoutineWaypointUpdate(Int iCampWaypoint, Int iTravelWaypoint, Float fMissedStartByHours, Float fNextUpdateTime)
Actor luter = Alias_LutePlayer.GetActorReference()
Bool bTravel = False
Bool bTeleport = False
; If the lute player is not in the intended "camp" location, travel to it.
; But if the start time is missed by a significant margin (probably because of the player sleeping or a quest time skip),
; teleport the minstrels to the "camp" directly, but only if it happens out of sight of the player.
If iCampWaypoint == WAYPOINT_PERFORM_MARKET
ObjectReference performRef = luter.GetLinkedRef(LinkPerformanceSpot)
If luter.GetDistance(performRef) > 256.0
If fMissedStartByHours > 0.6 && PlayerRef.GetDistance(luter) > SAFE_TELEPORT_DISTANCE && PlayerRef.GetDistance(performRef) > SAFE_TELEPORT_DISTANCE
bTeleport = True
Else
bTravel = True
EndIf
EndIf
Else ; iCampWaypoint == WAYPOINT_SANDBOX_INN
If luter.GetParentCell() != InnCell
If fMissedStartByHours > 0.6 && PlayerRef.GetDistance(luter) > SAFE_TELEPORT_DISTANCE && PlayerRef.GetParentCell() != InnCell
bTeleport = True
Else
bTravel = True
EndIf
EndIf
EndIf
If bTravel
If fNextUpdateTime > 0.5
fNextUpdateTime = 0.5 ; Failsafe if the end of the travel package is not triggered for some reason
EndIf
SetNewWaypoint(iTravelWaypoint, False, fNextUpdateTime)
Else
SetNewWaypoint(iCampWaypoint, bTeleport, fNextUpdateTime)
EndIf
EndFunction
Function SetNewWaypoint(Int iNewWaypoint, Bool bDoTeleport, Float fNextUpdateTime)
If fNextUpdateTime >= 0.0
RegisterForSingleUpdateGameTime(fNextUpdateTime + 0.025)
EndIf
If iNewWaypoint != CurrentWaypoint
Actor luter = Alias_LutePlayer.GetActorReference()
Actor dancer = Alias_Dancer.GetActorReference()
Bool bDoMusicReset = (CurrentWaypoint == WAYPOINT_PERFORM_MARKET)
; Teleport destination for the lute player
ObjectReference teleportLuterRef = None
If bDoTeleport
If iNewWaypoint == WAYPOINT_PERFORM_MARKET
teleportLuterRef = luter.GetLinkedRef(LinkPerformanceSpot)
ElseIf iNewWaypoint == WAYPOINT_SANDBOX_INN
teleportLuterRef = luter.GetLinkedRef(LinkCustom01)
EndIf
EndIf
; Teleport destination for the dancer
ObjectReference teleportDancerRef = None
If dancer
If iNewWaypoint == WAYPOINT_PERFORM_MARKET
ObjectReference performRef = dancer.GetLinkedRef(LinkPerformanceSpot)
If bDoTeleport
teleportDancerRef = performRef
ElseIf dancer.GetDistance(performRef) > 256.0 && PlayerRef.GetDistance(dancer) > SAFE_TELEPORT_DISTANCE && PlayerRef.GetDistance(performRef) > SAFE_TELEPORT_DISTANCE
teleportDancerRef = performRef
EndIf
ElseIf iNewWaypoint == WAYPOINT_SANDBOX_INN
If bDoTeleport
teleportDancerRef = teleportLuterRef
ElseIf dancer.GetParentCell() != InnCell && PlayerRef.GetDistance(dancer) > SAFE_TELEPORT_DISTANCE && PlayerRef.GetParentCell() != InnCell
teleportDancerRef = luter.GetLinkedRef(LinkCustom01) ; Yes, luter.GetLinkedRef
EndIf
EndIf
EndIf
; Wait for the lute player to finish his current song (if he's playing)
(luter as _00E_BardPlayInstrumentScript).FadeAndStopMusic()
CurrentWaypoint = iNewWaypoint
If teleportLuterRef
_00E_QuestFunctions.SafeMoveTo(luter, teleportLuterRef)
EndIf
If teleportDancerRef
_00E_QuestFunctions.SafeMoveTo(dancer, teleportDancerRef)
EndIf
luter.EvaluatePackage()
If dancer
dancer.EvaluatePackage()
EndIf
If CurrentWaypoint == WAYPOINT_PERFORM_MARKET
If IsTipBasketHidden
IsTipBasketHidden = False
TipBasket.MoveToMyEditorLocation()
EndIf
Else
If IsTipBasketHidden == False
IsTipBasketHidden = True
TipBasket.MoveTo(TempStorageMarker)
EndIf
EndIf
If bDoMusicReset
; Failsafe remove silence if the lute player alias fails to do this
ArkMarketGypsyPerformanceSilence.Remove()
EndIf
EndIf
EndFunction
Function GroupTravelFailsafe()
If CurrentWaypoint == WAYPOINT_TRAVEL_INN || CurrentWaypoint == WAYPOINT_TRAVEL_MARKET
Actor luter = Alias_LutePlayer.GetActorReference()
Actor dancer = Alias_Dancer.GetActorReference()
If luter && dancer && dancer.GetDistance(luter) >= 1024.0 && dancer.GetDistance(PlayerRef) > 4000.0
_00E_QuestFunctions.SafeMoveTo_NoWait(dancer, luter)
EndIf
EndIf
EndFunction