jucoking Posted May 3, 2019 Share Posted May 3, 2019 I have attached a script to my quest that should track the days spent in completing the quest. It is as follows: Scriptname CV2_EndingCountdownTimer extends Quest GlobalVariable Property GlobalDays auto ;initial days to complete GlobalVariable Property GlobalTime auto ;counter for hours left Quest Property CV2_MQ auto ;the quest (I used two scripts on same quest while cause I modified a vanilla one) Float endTime1 Float endTime2 Float endTime3 ObjectReference Property Ending1Trig Auto ObjectReference Property Ending2Trig Auto ObjectReference Property Ending3Trig Auto Event OnInit() GlobalTime.SetValue(GlobalDays.GetValue() * 24) endTime1 = Utility.GetCurrentGameTime() + GlobalDays.GetValue() * 96 endTime2 = Utility.GetCurrentGameTime() + GlobalDays.GetValue() * 144 endTime3 = Utility.GetCurrentGameTime() + GlobalDays.GetValue() * 192 CV2_MQ.UpdateCurrentInstanceGlobal(GlobalTime) RegisterForUpdateGameTime(0.50) EndEvent Event OnUpdateGameTime() If Utility.GetCurrentGameTime() < endTime2 Ending1Trig.Enable() UnregisterForUpdateGameTime() RegisterForUpdateGameTime(0.50) ElseIf Utility.GetCurrentGameTime() >= endTime2 && Utility.GetCurrentGameTime() < endTime3 Ending2Trig.Enable() Ending1Trig.Disable() UnregisterForUpdateGameTime() RegisterForUpdateGameTime(0.50) ElseIf Utility.GetCurrentGameTime() >= endTime3 Ending3Trig.Enable() Ending2Trig.Disable() UnregisterForUpdateGameTime() EndIf EndEvent The problem I am having is that the only ending trigger that calls is the last one (the "bad" ending), which is only supposed to call when 8 in-game days have passed. The best ending is supposed to be 4 days and the good ending is supposed to be 6 days. Would anyone help me with this script? Thanks in advance. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted May 3, 2019 Share Posted May 3, 2019 Just some thoughts, take it all with a grain of salt, pepper, sugar or whatever. :unsure: First off, in the OnInit block, I'd assign the result of GetCurrentGameTime to a local variable and use that as the base for all three end timings. If you call it three separate times, each timer will have a different start. You want one start with three separate possible endings.Example: Float CurrentTime = Utility.GetCurrentGameTime() endtime1 = CurrentTime + GlobalDays.GetValue() The second thing is that GetCurrentGameTime returns the DAYS passed rather than the HOURS. This is why you had to multiply by 24 for GlobalTime as that is supposed to store the hours remaining in the quest. But to extend the current time to the desired ending time you should only need to add the desired number of days. Example: Float CurrentTime = Utility.GetCurrentGameTime() endtime1 = CurrentTime + 4 But you have the property GlobalDays which based on the comment text (even tho it is a direct copy from an example script on the wiki) leads me to believe that its value is 4 already as that should be the initial amount of time to complete the quest within.Thus: Float CurrentTime = Utility.GetCurrentGameTime() endtime1 = CurrentTime + GlobalDays.GetValue() ;stored value is four days endtime2 = CurrentTime + GlobalDays.GetValue() + 2.0 ;add two more to get six days total endtime3 = CurrentTime + GlobalDays.GetValue() + 4.0 ;add four more to get eight days total *************************************As far as your update loop goes: You are un-registering for the update after each enabling and re-registering within the first two updates. I am not sure why. Perhaps because you want to make sure that you can get to the 8th day if needed. You need some additional check to make sure this looping stops at the appropriate time and leaves the correct trigger enabled. Perhaps there is a quest stage that can be checked along with the timer? I cannot really make a suggestion as I do not know what else you have at your disposal within this quest. It may be a moot issue as the update will be unregistered automatically when the quest is stopped and whatever status the objects are in at that time should stick. But at first glance it does seem to want to keep going forever until the worst possible ending is achieved. Link to comment Share on other sites More sharing options...
jucoking Posted May 4, 2019 Author Share Posted May 4, 2019 Thanks, Ishara. I have been scripting using this register/unregister method to prevent game bloating and slow down from multiple loops running concurrently. At least that's how I thought it worked, but I'm not much of a scripter so I don't know for sure lol. You were correct in saying that this is how I am getting the script to loop continually in order for it to keep checking the conditions to make sure it is all up-to-date. I'm going to be testing this after applying your suggestions and so far it is looking good. I got the "good" ending to show and all that was showing before was the "bad" ending no matter how many days passed. Thanks so much. Link to comment Share on other sites More sharing options...
ReDragon2013 Posted May 5, 2019 Share Posted May 5, 2019 like IsharaMeradin posted: Utility.GetCurrentGameTime()you could also use a formlist instead of three objectReference CV2_EndingTimerQuestScript Scriptname CV2_EndingTimerQuestScript extends Quest ; CV2_EndingCountdownTimer {should track the days spent in completing the quest} ; https://forums.nexusmods.com/index.php?/topic/7616318-scripted-endings-based-on-days-spent-completing-quest/ ; jucoking wrote: "only ending trigger that calls is the last one (the "bad" ending), which is only supposed to call when 8 in-game days have passed." GlobalVariable PROPERTY GlobalDays auto ; initial days to complete FormList PROPERTY TriggerList auto ; Ending1Trig, Ending2Trig, Ending3Trig Float PROPERTY fTimer auto Hidden ; -- EVENTs -- 1 + "InitQuest" + "Waiting" EVENT OnInit() gotoState("InitQuest") ; ### STATE ### RegisterForSingleUpdateGameTime(0.0) ENDEVENT ;=================================== state InitQuest ;============== EVENT OnUpdateGameTime() myF_Init() gotoState("Waiting") ; ### STATE ### RegisterForSingleUpdateGameTime(0.5) ENDEVENT ;======= endState ;=================================== state Waiting ;============ EVENT OnUpdateGameTime() myF_Update() ENDEVENT ;======= endState ; -- FUNCTIONs -- 2 ;------------------ FUNCTION myF_Init() ;------------------ ; 4 days minimum fTimer = GlobalDays.GetValue() + Utility.GetCurrentGameTime() ; init the endTimer ENDFUNCTION ;-------------------- FUNCTION myF_Update() ;-------------------- float f = Utility.GetCurrentGameTime() int T ;IF (f <= fTimer) ; 0 .. 4 days ; T = -1 IF (f <= fTimer + 2.0) ; 0 .. 6 days T = 0 ; Ending1Trig ELSEIF (f <= fTimer + 4.0) ; >6 .. 8 days T = 1 ; Ending2Trig ELSE ; >8 days T = 2 ; Ending3Trig ENDIF ; -------------------- objectReference oRef int i = TriggerList.GetSize() WHILE (i) i = i - 1 oRef = TriggerList.GetAt(i) as ObjectReference If (oRef) && !oRef.IsDisabled() oRef.Disable() ; disable every trigger point, if needed ENDIF ENDWHILE ; --------------------- ;IF (T >= 0) oRef = TriggerList.GetAt(T) as ObjectReference ; We assume the first formlist entry is "Ending1Trig"! IF ( oRef ) oRef.Enable() ; enable the current trigger after disabling anything ENDIF ;ENDIF ; --------------------- IF (T < 2) && self.IsRunning() RegisterForSingleUpdateGameTime(0.5) ENDIF ENDFUNCTION Link to comment Share on other sites More sharing options...
jucoking Posted May 5, 2019 Author Share Posted May 5, 2019 like IsharaMeradin posted: Utility.GetCurrentGameTime()you could also use a formlist instead of three objectReference CV2_EndingTimerQuestScript Scriptname CV2_EndingTimerQuestScript extends Quest ; CV2_EndingCountdownTimer {should track the days spent in completing the quest} ; https://forums.nexusmods.com/index.php?/topic/7616318-scripted-endings-based-on-days-spent-completing-quest/ ; jucoking wrote: "only ending trigger that calls is the last one (the "bad" ending), which is only supposed to call when 8 in-game days have passed." GlobalVariable PROPERTY GlobalDays auto ; initial days to complete FormList PROPERTY TriggerList auto ; Ending1Trig, Ending2Trig, Ending3Trig Float PROPERTY fTimer auto Hidden ; -- EVENTs -- 1 + "InitQuest" + "Waiting" EVENT OnInit() gotoState("InitQuest") ; ### STATE ### RegisterForSingleUpdateGameTime(0.0) ENDEVENT ;=================================== state InitQuest ;============== EVENT OnUpdateGameTime() myF_Init() gotoState("Waiting") ; ### STATE ### RegisterForSingleUpdateGameTime(0.5) ENDEVENT ;======= endState ;=================================== state Waiting ;============ EVENT OnUpdateGameTime() myF_Update() ENDEVENT ;======= endState ; -- FUNCTIONs -- 2 ;------------------ FUNCTION myF_Init() ;------------------ ; 4 days minimum fTimer = GlobalDays.GetValue() + Utility.GetCurrentGameTime() ; init the endTimer ENDFUNCTION ;-------------------- FUNCTION myF_Update() ;-------------------- float f = Utility.GetCurrentGameTime() int T ;IF (f <= fTimer) ; 0 .. 4 days ; T = -1 IF (f <= fTimer + 2.0) ; 0 .. 6 days T = 0 ; Ending1Trig ELSEIF (f <= fTimer + 4.0) ; >6 .. 8 days T = 1 ; Ending2Trig ELSE ; >8 days T = 2 ; Ending3Trig ENDIF ; -------------------- objectReference oRef int i = TriggerList.GetSize() WHILE (i) i = i - 1 oRef = TriggerList.GetAt(i) as ObjectReference If (oRef) && !oRef.IsDisabled() oRef.Disable() ; disable every trigger point, if needed ENDIF ENDWHILE ; --------------------- ;IF (T >= 0) oRef = TriggerList.GetAt(T) as ObjectReference ; We assume the first formlist entry is "Ending1Trig"! IF ( oRef ) oRef.Enable() ; enable the current trigger after disabling anything ENDIF ;ENDIF ; --------------------- IF (T < 2) && self.IsRunning() RegisterForSingleUpdateGameTime(0.5) ENDIF ENDFUNCTION Ingenious, as usual, ReDragon. I do have one question about this script, though. To test, I am not able to use the "wait" function in-game because it messes with the timer. If I use your script and the FormList, would I be able to "wait" in-game in order to test for the different endings? Link to comment Share on other sites More sharing options...
Recommended Posts