Jump to content

Firing Enable/Disable Script interupted by Wait or Fast Travel


NexBeth

Recommended Posts

I have a script below that works to enable and disable objects (such as fire lights and food plates) based on time of day set in properties. This works well as long as I don't use Wait or Fast. The process of speeding up game time interferes and items that should be shown at a given time, don't show up, or visa versa. I've actually tried a couple of different scripts but the problem occurs in both.

 

I'm not a scripter at all so some help with this, if that is even possible, is appreciated.

 

 

float Property ItemOffTime = 9.0 auto
{The time at which item should be turned off}
float Property ItemOnTime = 8.0 auto
{The time at which item should be turned on}

float Function GetCurrentHourOfDay() global
{Returns the current time of day in hours since midnight}

float Time = Utility.GetCurrentGameTime()
Time -= Math.Floor(Time) ; Remove "previous in-game days passed" bit
Time *= 24 ; Convert from fraction of a day to number of hours
Return Time

EndFunction

Function RegisterForSingleUpdateGameTimeAt(float GameTime)
{Registers for a single UpdateGameTime event at the next occurrence
of the specified GameTime (in hours since midnight)}

float CurrentTime = GetCurrentHourOfDay()
If (GameTime < CurrentTime)
GameTime += 24
EndIf

RegisterForSingleUpdateGameTime(GameTime - CurrentTime)

EndFunction

Event OnInit()

If (GetCurrentHourOfDay() > ItemOffTime)
GoToState("ItemOff")
Else
GoToState("ItemOn")
EndIf

EndEvent

State ItemOff

Event OnBeginState()
Disable()
RegisterForSingleUpdateGameTimeAt(ItemOnTime)
EndEvent

Event OnUpdateGameTime()
GoToState("ItemOn")
EndEvent

EndState

State ItemOn

Event OnBeginState()
Enable()
RegisterForSingleUpdateGameTimeAt(ItemOffTime)
EndEvent

Event OnUpdateGameTime()
GoToState("ItemOff")
EndEvent

EndState

 

 

 

Link to comment
Share on other sites

This is an issue that i encountered in the past with a similar script, and the quick solution was to disable " Wait " and " Fast Travel " for the Player, but it was in an interior cell.

At the end i remove this function and replaced it with another one ( making the Player to activate everything from inside the power plant and... well i don't want to bore you with this ).

I didn't found a solution to this, since i didn't bother myself too much with it.


The problem is that when the script executes, its start with an internal clock that differs from that of the Player when he enters " wait ".

To resolve this the Script needs to detect when the Player enters " wait " and at the end retrive again the time to execute its functions, or " REFRESH ", or " Updating " every X seconds but this will result on putting too much presure on the system ( having a script that is always - continuously running ), the problem is that " Papyrus " and the " Game Engine " has limitations on what you + it can do.


* Although, when i exited and re entered the cell everything was normal ( But this was in my case ).


If anyone has found a solution to this, i'm also interested.

Edited by maxarturo
Link to comment
Share on other sites

Taken from the OnUpdateGameTime wiki page:

 

OnUpdateGameTime may come in much later then you expect if the player is sleeping, waiting, fast traveling, or serving jail time. The event will only be sent once, after the sleep/wait/travel/serve period is over, so you should be prepared to handle hours passing between updates.

Thus if you want things to remain exact, then you need to grab the new current time and compare that to your old current time (i.e. when you started the last register for game time update). If the new is far enough that things should change, change them and then figure out the remainder of time so that the next register will happen when you want it to.

 

in pseudo code

extra time passed = (new current - old current) - original wait time 
While extra time passed > original wait time
  extra time passed -= original wait time
EndWhile
new wait time = original wait time - extra time passed
Register for (new wait time)
Change things as needed
Link to comment
Share on other sites

Try this. I haven't tested it but it should work.

 

 

 

ScriptName EnableDuringInterval extends ObjectReference
{ Script to enable an object only for a certain amount of time each day. }

float Property DisableHour = 9.0 auto

float Property EnableHour = 8.0 auto

Event OnInit()
	OnUpdateGameTime() ; get things started
EndEvent

Event OnUpdateGameTime()
	; get the current hour of the day
	float hour = Utility.GetCurrentGameTime()
	hour = (hour - Math.Floor(hour)) * 24.0

	; determine the proper state and when the next update should happen
	if EnableHour < DisableHour ; enable and disable are during the same day
		if hour < EnableHour
			RegisterForSingleUpdateGameTime(EnableHour - hour)
		elseif hour < DisableHour
			RegisterForSingleUpdateGameTime(DisableHour - hour)
		else ; need to register for enable hour tomorrow
			RegisterForSingleUpdateGameTime(EnableHour - hour + 24.0)
		endif
		if hour >= EnableHour && hour < DisableHour
			Enable()
		else
			Disable()
		endif
	else  ; should be enabled across the midnight boundary
		if hour < DisableHour
			RegisterForSingleUpdateGameTime(DisableHour - hour)
		elseif hour < EnableHour
			RegisterForSingleUpdateGameTime(EnableHour - hour)
		else ; need to register for disable hour tommorrow
			RegisterForSingleUpdateGameTime(DisableHour - hour + 24.0)
		endif
		if hour >= EnableHour || hour < DisableHour
			Enable()
		else
			Disable()
		endif
	endif
EndEvent

 

 

Link to comment
Share on other sites

Thanks for the detailed replies folks. I'll test cdcooley's script right off and see if that does the trick.

 

It sounds like this is somewhat of a complex problem. Will post back with results. Thank you all very much, and cdcooley for writing out a script for me.

Link to comment
Share on other sites

There exist another approach like critter spawning, papyrus code as follow:

 

xyzEDSampleObjectScript

 

Scriptname xyzEDSampleObjectScript extends ObjectReference
; to enable and disable objects (such as fire lights and food plates) based on time of day

; https://forums.nexusmods.com/index.php?/topic/7917108-firing-enabledisable-script-interupted-by-wait-or-fast-travel/

  GlobalVariable PROPERTY GameHour auto     ; use autofill here

  Float PROPERTY fTimeOn  = 8.0 auto        ; {The time at which item should be turned on}
  Float PROPERTY fTimeOff = 9.0 auto        ; {The time at which item should be turned off}

  Bool bRun            ; [default=False]


; -- EVENTs --

;==========================
auto state Waiting
;=================
EVENT OnCellAttach()  ; player go inside the cell of this object
    bRun = TRUE
    myF_Action()
ENDEVENT


EVENT OnCellDetach()  ; player leave the cell of this object
IF ( bRun )
    bRun = False
    UnRegisterForUpdateGameTime()
    myF_Disable()
ENDIF
ENDEVENT


EVENT OnUpdateGameTime()
    Utility.Wait(0.25)            ; wait a bit to give other scripts runtime
    myF_Action()
ENDEVENT
;=======
endState


;==========================
state Done  ; nothing here
;=========
endState


; -- FUNCTIONs -- 2

;---------------------
FUNCTION myF_Disable()
;---------------------
    IF self.IsDisabled()
        ; self is already disabled
    ELSE
        self.Disable(False)        ; no fade effect
    ENDIF
ENDFUNCTION


;--------------------
FUNCTION myF_Action()
;--------------------
IF self.GetBaseObject()
ELSE
    gotoState("Done")                ; ### STATE ###
    RETURN    ; - STOP -    mod has been uninstalled or papyrus stack overflow
ENDIF
;---------------------
    bool bOK = (GameHour.GetValue() >= fTimeOn)         ;  0.00 .. 12.00 .. 23.59   <-- our time range here

    IF (fTimeOn >= fTimeOff)                            ; from 19.00 to 5.00  at night
        bOK = bOK || (GameHour.GetValue() < fTimeOff)
    ELSE                                                ; from  8.00 to 9.00  on days
        bOK = bOK && (GameHour.GetValue() < fTimeOff)
    ENDIF

IF ( bOK )
    IF self.IsDisabled()
        self.Enable(TRUE)    ; fading in
    ENDIF
ELSE
    IF self.IsDisabled()
    ELSE
        self.Disable(TRUE)    ; fading out
    ENDIF
ENDIF

    RegisterForSingleUpdateGameTime(1.0)                ; wait for 1 hour and test again
ENDFUNCTION

 

 

Link to comment
Share on other sites

There exist another approach like critter spawning, papyrus code as follow:

 

 

Will this work on interior as well as ext. cells? Also, you mention critter spawning which is rather random during the time allowed by the script. My applicaton would be precise--needs to come on and go off precisely at specified time. Thanks, ReDragon.

Link to comment
Share on other sites

 

There exist another approach like critter spawning, papyrus code as follow:

 

 

Will this work on interior as well as ext. cells? Also, you mention critter spawning which is rather random during the time allowed by the script. My applicaton would be precise--needs to come on and go off precisely at specified time. Thanks, ReDragon.

 

Seeing ReDragon script, it serves your purpose.
But i can't test it to see if it does the trick, i'm on vacations.
Test it and see...
Link to comment
Share on other sites

ReDragon's script is designed for making sure things happen only when the player is present. The item gets disabled when the player leaves the cell and the re-enable if the player enters at the right time. When entering the cell during the "on" time there will be a slight delay before the state change (which is meant to lighten the script load when a cell loads, but might be distracting if the player leaves while things are on and then returns almost immediately to find them off and just turning on). More importantly the use of a standard 1 hour re-check interval instead of calculating a new check for the appropriate time means it will both use more resources and not guarantee the switch at the right time if the player remains in the cell for multiple hours. (So basically it's a fine script, but the wrong one for this task.)

Link to comment
Share on other sites

cdcooley, thanks very much for responses here especially for writing out that script for me. I've done some preliminary testing and have had no problems. Things go off and on as scheduled. (It's only been about 2 yrs that I've been looking for script that will do this!) I'll start a new game now and see how everything plays together for an in-game test run of my mod.

 

On a personal note, I have spent some time and effort to learn scripting with not much luck. There are some guides and so-forth, but to me it is like a new language. Most of the guides I've seen seem to run through how to set up a specific script for a specific purpose, but they don't really explain the language nor the meaning of the symbols and how to place them. Without understanding that, for me at least I just can't get how to put together proper commands. Aside from that, I find this aspect of modding rather boring too so there is that too that impedes learning I suppose.

 

Thanks all.

Edited by NexBeth
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...