Difference between revisions of "Light Switch"
imported>Tunaisafish m (→Manual Light Switch: fix enablemarker ref) |
imported>Jostrus (Add logic check for OnInit and Update Timers to validate the swap is necessary. In case of player sleep past trigger times.) |
||
Line 28: | Line 28: | ||
Time *= 24 ; Convert from fraction of a day to number of hours | Time *= 24 ; Convert from fraction of a day to number of hours | ||
Return Time | Return Time | ||
EndFunction | EndFunction | ||
Line 46: | Line 46: | ||
Event OnInit() | Event OnInit() | ||
If ( | If (ShouldLightsBeOff()) | ||
GoToState("LightsOff") | GoToState("LightsOff") | ||
Else | Else | ||
Line 62: | Line 62: | ||
Event OnUpdateGameTime() | Event OnUpdateGameTime() | ||
GoToState("LightsOn") | If (ShouldLightsBeOff()) | ||
RegisterForSingleUpdateGameTimeAt(LightsOnTime) | |||
Else | |||
GoToState("LightsOn") | |||
EndIf | |||
EndEvent | EndEvent | ||
Line 75: | Line 79: | ||
Event OnUpdateGameTime() | Event OnUpdateGameTime() | ||
GoToState("LightsOff") | If (ShouldLightsBeOff()) | ||
GoToState("LightsOff") | |||
Else | |||
RegisterForSingleUpdateGameTimeAt(LightsOffTime) | |||
EndIf | |||
EndEvent | EndEvent | ||
EndState</source> | EndState | ||
bool Function ShouldLightsBeOff() | |||
float CurrentTime = GetCurrentHourOfDay() | |||
If (CurrentTime >= LightsOffTime) && (CurrentTime < LightsOnTime) | |||
return true | |||
Else | |||
return false | |||
EndIf | |||
EndFunction</source> | |||
==Script Explanation== | ==Script Explanation== |
Revision as of 03:39, 1 October 2018
Setup
The script on this page can be used to automatically turn a set of lights on or off depending on the time of day. It contains 2 properties, which have default values but are configurable in the Creation Kit
- LightsOffTime
- The time at which lights should be turned off. Set to 7:00 am by default.
- LightsOnTime
- The time at which lights should be turned on. Set to 6:00 pm by default.
In order to set this script up to be used, you'll need to either create a marker or select one of the lights to be the "master", and set it to be the enable parent of all the other lights. Then, just attach the script below to that marker or master light. If you don't want to use the default values, then either alter them in the script or override them in the Creation Kit.
Script
ScriptName TimedLightSwitch extends ObjectReference
{Controls a set of lights with a master enable parent marker with this
script attached to turn on and off at the times of the day specified
by the properties LightsOffTime and LightsOnTime}
float Property LightsOffTime = 7.0 auto
{The time at which lights should be turned off}
float Property LightsOnTime = 18.0 auto
{The time at which lights 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 (ShouldLightsBeOff())
GoToState("LightsOff")
Else
GoToState("LightsOn")
EndIf
EndEvent
State LightsOff
Event OnBeginState()
Disable()
RegisterForSingleUpdateGameTimeAt(LightsOnTime)
EndEvent
Event OnUpdateGameTime()
If (ShouldLightsBeOff())
RegisterForSingleUpdateGameTimeAt(LightsOnTime)
Else
GoToState("LightsOn")
EndIf
EndEvent
EndState
State LightsOn
Event OnBeginState()
Enable()
RegisterForSingleUpdateGameTimeAt(LightsOffTime)
EndEvent
Event OnUpdateGameTime()
If (ShouldLightsBeOff())
GoToState("LightsOff")
Else
RegisterForSingleUpdateGameTimeAt(LightsOffTime)
EndIf
EndEvent
EndState
bool Function ShouldLightsBeOff()
float CurrentTime = GetCurrentHourOfDay()
If (CurrentTime >= LightsOffTime) && (CurrentTime < LightsOnTime)
return true
Else
return false
EndIf
EndFunction
Script Explanation
This script consists of 2 custom functions, one OnInit event, and two states, each with their own OnBeginState and OnUpdateGameTime events.
The functions are documented within the script, but just in case they're not clear:
GetCurrentHourOfDay
This function uses the Utility script's global function, GetCurrentGameTime, and some mathematical manipulation, to get the current time of the current day as a number between 0.0 and 24.0
RegisterForSingleUpdateGameTimeAt
This function works as a variation of RegisterForSingleUpdateGameTime. The twist is that, while RegisterForSingleUpdateGameTime takes a duration as its parameter, this custom function takes the time at which the update should take place as its parameter.
So, for example, if I were to pass 7.0 as its parameter, then the next time it's 7:00 am in Skyrim, this object will have the native event OnUpdateGameTime called on it.
OnInit
This event should pretty much always be used to set up your script in whatever ways are required that cannot be done when initialising properties or variables. All that's required here is that the correct state is selected depending on the current time in-game when this event runs.
If the lights should be off, then the script enters the "LightsOff" state, whereas if they should be on, then the script enters the "LightsOn" state.
States
The two states are nearly identical, and work sort of like mirror images of one another. Each state, when it begins, changes the enable state of the marker or master light (and therefore all other lights), and registers for a single update in game time at the time at which the state needs to change, as set by the two properties of this script.
When that time is reached, the OnUpdateGameTime event is called, which switches the script to the other state, and its OnBeginState event will run.
Extending This Script
The key functionality in this script is in the states. Specifically, that they both use the OnBeginState native event to set everything that needs to be set, so that the lights can be turned on or off simply by changing the state of the script. By taking advantage of this, it wouldn't be particularly difficult to, say, change the script so that the lights' state is toggled when the scripted object is activated:
Manual Light Switch
ScriptName ManualLightSwitch extends ObjectReference
{Controls a set of lights with a master enable parent
marker (EnableMarker) and a switch with this script
attached to turn on and off when the switch is activated}
ObjectReference Property EnableMarker auto
{The marker set as the enable parent of all the lights}
Event OnInit()
If (EnableMarker.IsDisabled())
GoToState("LightsOff")
Else
GoToState("LightsOn")
EndIf
EndEvent
State LightsOff
Event OnBeginState()
EnableMarker.Disable()
EndEvent
Event OnActivate(ObjectReference akActionRef)
GoToState("LightsOn")
EndEvent
EndState
State LightsOn
Event OnBeginState()
EnableMarker.Enable()
EndEvent
Event OnActivate(ObjectReference akActionRef)
GoToState("LightsOff")
EndEvent
EndState