pepperman35 Posted September 26, 2022 Share Posted September 26, 2022 (edited) Background: I desire to have a set of static street lamps turn on and off depending on the hour of the day. I am using DLC04_StreetLampTilingRemap01 for the ones that are off during the day; and DLC04_StreetLampTilingRemap01On is combined with defaultLightWarm01SpotNS, LightBeamThin01, and DefaultLightCoolFLNS for the ones that are ON during the night. All of these components are parented to a EnableMarker which has the reference ID of FO4_StreetLampEnabler01. I have placed a script on the EnableMarker (i.e., FO4_StreetLampEnabler01) which should control the enabling and disabling the various streetlamps and lights. The script originated from here and was modified by DieFeM in response to Citizenbari’s post. Questions: 1. Is there a way to test the state of the EnableMarker? I am trying to troubleshoot the script and it doesn’t seem that the states (enabled, disabled) are changing. 2. Should the script be placed on the EnableMarker or should I create a default dummy (activator)? 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} ; ;-- Properties -------------------------------------- ; 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} ObjectReference Property FO4_StreetLampEnabler01 Auto Const Mandatory ; ;-- Initialization Event -------------------------------------- ; Event OnInit() ; Is the enabler disabled or enable? If (FO4_StreetLampEnabler01.IsDisabled()) Debug.Trace("TimedLightSwitchScript: OnInit event. The FO4_StreetLampEnabler01 is disabled!") Else Debug.Trace("TimedLightSwitchScript: OnInit event. The FO4_StreetLampEnabler01 is enabled!") endIf If (ShouldLightsBeOff()) Debug.Trace("TimedLightSwitchScript:Initialization event = " + " Lights should be OFF") GoToState("LightsOff") Else Debug.Trace("TimedLightSwitchScript:Initialization event = " + " Lights should be ON") GoToState("LightsOn") EndIf EndEvent ; ;-- States -------------------------------------- ; State LightsOff Event OnBeginState(string asOldState) Debug.Trace("TimedLightSwitchScript:State LightsOff called! Ready to disable = " + " FO4_StreetLampEnabler01") FO4_StreetLampEnabler01.Disable() ; Is the enabler disabled? If (FO4_StreetLampEnabler01.IsDisabled()) Debug.Trace("TimedLightSwitchScript: State LightsOff - The FO4_StreetLampEnabler01 is disabled!") Else Debug.Trace("TimedLightSwitchScript: State LightsOff - The FO4_StreetLampEnabler01 is enables!") endIf RegisterForSingleUpdateGameTimeAt(LightsOnTime) EndEvent Event OnTimerGameTime(int aiTimerID) If (ShouldLightsBeOff()) RegisterForSingleUpdateGameTimeAt(LightsOnTime) Else GoToState("LightsOn") EndIf EndEvent EndState State LightsOn Event OnBeginState(string asOldState) Debug.Trace("TimedLightSwitchScript:State LightsOn called! Ready to enable = " + " FO4_StreetLampEnabler01") FO4_StreetLampEnabler01.Enable() ; Is the enabler disabled? If (FO4_StreetLampEnabler01.IsDisabled()) Debug.Trace("TimedLightSwitchScript: State LightsOn - The FO4_StreetLampEnabler01 is disabled!") Else Debug.Trace("TimedLightSwitchScript: State LightsOn - The FO4_StreetLampEnabler01 is enables!") endIf RegisterForSingleUpdateGameTimeAt(LightsOffTime) EndEvent Event OnTimerGameTime(int aiTimerID) If (ShouldLightsBeOff()) GoToState("LightsOff") Else RegisterForSingleUpdateGameTimeAt(LightsOffTime) EndIf EndEvent EndState ; ;-- Functions -------------------------------------- ; bool Function ShouldLightsBeOff() {Validate the light state based on current time of day} float CurrentTime = GetCurrentHourOfDay() Debug.Trace("TimedLightSwitchScript:Function ShouldLightsBeOff called! CurrentTime = " + CurrentTime) If (CurrentTime >= LightsOffTime) && (CurrentTime < LightsOnTime) Debug.Trace("TimedLightSwitchScript:Function ShouldLightsBeOff called! ShouldLightsBeOff = " + " true") return true Else Debug.Trace("TimedLightSwitchScript:Function ShouldLightsBeOff called! ShouldLightsBeOff = " + " true") return false EndIf Debug.Trace("TimedLightSwitchScript:Function ShouldLightsBeOff called! CurrentTime = " + CurrentTime) EndFunction float Function GetCurrentHourOfDay() global {Returns the current time of day in hours since midnight} float Time = Utility.GetCurrentGameTime() Debug.Trace("TimedLightSwitchScript:Function GetCurrentHourOfDay called! Time = " + Time) 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 StartTimerGameTime(GameTime - CurrentTime) Debug.Trace("TimedLightSwitchScript:Function RegisterForSingleUpdateGameTimeAt called! CurrentTime = " + CurrentTime) EndFunction Edited September 26, 2022 by pepperman35 Link to comment Share on other sites More sharing options...
DieFeM Posted September 27, 2022 Share Posted September 27, 2022 I wonder if the script will still run when the enable marker is disabled, or if the events in that script would still run in the case that the reference containing this script is unloaded. What happens if the enable marker reference is in the unloaded area? Will it just spit a "can not whatever on None object" in the log?because if the reference is in an unloaded area, and not persistent, they'll return as a None I guess. Taking all of that in to account, wouldn't it be appropriate handling the OnLoad and OnUnload events so that the timers are enabled or disabled? Or maybe attach it on a quest, which is always active, unlike a reference, and handle all enable parents from it. Well, there's my two cents. I hope it helps. Link to comment Share on other sites More sharing options...
pepperman35 Posted September 27, 2022 Author Share Posted September 27, 2022 DieFeM, your two cents are always important and valued. The script seems to run when the enable marker is disables; however, the results are similar. I will investigate the log a bit closer as I seem to recall see something along the lines of "can not whatever on None object." I used a similar version of the script on a door (which was an animated window louver) but instead of enabling and disabling a marker it opened and closed the louvers. It seemed to work fine there. I will have to research OnLoad and OnUnload events a bit more as well as attaching this to a quest. You have given me a rudder steer so I will do a bit more sailing. Link to comment Share on other sites More sharing options...
DieFeM Posted September 27, 2022 Share Posted September 27, 2022 I'm glad to help. Link to comment Share on other sites More sharing options...
niston Posted September 30, 2022 Share Posted September 30, 2022 F4MS has this covered btw: Scheduler and ScheduledEnableDisable. Link to comment Share on other sites More sharing options...
pepperman35 Posted September 30, 2022 Author Share Posted September 30, 2022 Thanks niston, I'll take a look at F4MS this weekend. Link to comment Share on other sites More sharing options...
pepperman35 Posted September 30, 2022 Author Share Posted September 30, 2022 (edited) Okay, haven't had a chance to look at niston F4MS but here is what I have done to date 1. Created a trigger volume around the settlement and added this script to control the activation of a master controller. Scriptname FO4_StreetLampTriggerScript extends ObjectReference {script that simply activates the master script when player enters the trigger} Group Required_Properties ObjectReference property myMasterRef auto const EndGroup ;************************************ auto State Active Event OnTriggerEnter(ObjectReference akActionRef) if(akActionRef == game.GetPlayer()) myMasterRef.enable() myMasterRef.activate(myMasterRef) Debug.Notification("Hello, the player has entered the scene") endif EndEvent Event OnTriggerLeave(ObjectReference akActionRef) if(akActionRef == game.GetPlayer()) myMasterRef.disable() Debug.Notification("Hello, the player has left the scene") endif EndEvent EndState ;************************************ State Done ;do nothing Event OnTriggerEnter(ObjectReference akActionRef) ;do nothing EndEvent Event OnTriggerLeave(ObjectReference akActionRef) ;Disable the master activator myMasterRef.disable() EndEvent EndState 2. I added an activated (FO4_StreetLampMaster01) which holds the TimedLightSwitch script. ScriptName FO4_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} ; ;-- Properties -------------------------------------- ; 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} ObjectReference Property FO4_StreetLampOnEnabler01 Auto Const Mandatory ObjectReference Property FO4_StreetLampOffEnabler01 Auto Const Mandatory ; ; Event Handlers ; Event OnLoad() If !IsDisabled() Debug.Notification("This object is loaded, playing animations should work now") If (ShouldLightsBeOff()) GoToState("LightsOff") Else GoToState("LightsOn") EndIf Else Debug.Notification("This object is loaded but disabled - so it doesn't have 3D") Endif EndEvent Event OnUnload() CancelAllTimers() endEvent ; ; States ; State LightsOff Event OnBeginState(string asOldState) FO4_StreetLampOffEnabler01.Enable() FO4_StreetLampOnEnabler01.Disable() RegisterForSingleUpdateGameTimeAt(LightsOnTime) EndEvent Event OnTimerGameTime(int aiTimerID) If (ShouldLightsBeOff()) RegisterForSingleUpdateGameTimeAt(LightsOnTime) Else GoToState("LightsOn") EndIf EndEvent EndState State LightsOn Event OnBeginState(string asOldState) FO4_StreetLampOnEnabler01.Enable() FO4_StreetLampOffEnabler01.Disable() RegisterForSingleUpdateGameTimeAt(LightsOffTime) EndEvent Event OnTimerGameTime(int aiTimerID) If (ShouldLightsBeOff()) GoToState("LightsOff") Else RegisterForSingleUpdateGameTimeAt(LightsOffTime) EndIf EndEvent EndState ; ; Functions ; 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 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 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 StartTimerGameTime(GameTime - CurrentTime) EndFunction Function CancelAllTimers() CancelTimerGameTime() EndFunction Initial testing looks promising. If anyone see any pitfalls with the approach or scripts, I am more than willing to listen and learn. I most certainly appreciated your insights, experience and help as I am but a novice when it comes to scripting. Edited September 30, 2022 by pepperman35 Link to comment Share on other sites More sharing options...
Recommended Posts