Difference between revisions of "Light Switch"

From the CreationKit Wiki
Jump to navigation Jump to search
imported>Cipscis
(Added to "Solutions" category)
imported>Jostrus
 
(3 intermediate revisions by 2 users not shown)
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 (GetCurrentHourOfDay() > LightsOffTime)
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()
{Validate the light state based on current time of day}
 
float CurrentTime = GetCurrentHourOfDay()
If (CurrentTime >= LightsOffTime) && (CurrentTime < LightsOnTime)
return true
Else
return false
EndIf
 
EndFunction</source>


==Script Explanation==
==Script Explanation==
Line 91: Line 111:


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_-_Form|OnUpdateGameTime]] called on it.
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_-_Form|OnUpdateGameTime]] called on it.
===ShouldLightsBeOff===
This function validates that the current time of day is within the turn off or turn on range. It presumes that your turn off time is before the turn on time. This used by the [[OnInit]] and the [[OnUpdateGameTime_-_Form|OnUpdateGameTime]] events. It is necessary in case the player does a sleep or wait which causes the game to pass the current and next trigger time. Upon resuming the game will trigger the update and it needs to only switch state if the time is appropriate.


===OnInit===
===OnInit===
Line 100: Line 123:
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.
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.
When that time is reached, the OnUpdateGameTime event is called, validates that the then current time of day requires a state switch, then if so switches the script to the other state, and its OnBeginState event will run.


==Extending This Script==
==Extending This Script==
Line 127: Line 150:


Event OnBeginState()
Event OnBeginState()
Disable()
EnableMarker.Disable()
EndEvent
EndEvent


Line 139: Line 162:


Event OnBeginState()
Event OnBeginState()
Enable()
EnableMarker.Enable()
EndEvent
EndEvent



Latest revision as of 03:56, 1 October 2018


Setup[edit | edit source]

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

  1. LightsOffTime
    • The time at which lights should be turned off. Set to 7:00 am by default.
  2. 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[edit | edit source]

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()
{Validate the light state based on current time of day}

		float CurrentTime = GetCurrentHourOfDay()
		If (CurrentTime >= LightsOffTime) && (CurrentTime < LightsOnTime)
			return true
		Else
			return false
		EndIf

EndFunction

Script Explanation[edit | edit source]

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[edit | edit source]

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[edit | edit source]

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.

ShouldLightsBeOff[edit | edit source]

This function validates that the current time of day is within the turn off or turn on range. It presumes that your turn off time is before the turn on time. This used by the OnInit and the OnUpdateGameTime events. It is necessary in case the player does a sleep or wait which causes the game to pass the current and next trigger time. Upon resuming the game will trigger the update and it needs to only switch state if the time is appropriate.

OnInit[edit | edit source]

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[edit | edit source]

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, validates that the then current time of day requires a state switch, then if so switches the script to the other state, and its OnBeginState event will run.

Extending This Script[edit | edit source]

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[edit | edit source]

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