Jump to content

Help with Papyrus Functions


LivewareCascade

Recommended Posts

Hey Guys, I need some help with a simple(ish) script that I'm writing to control lights. Specifically, to check whether the lights have been built AND then cycle them through on-off states depending on the time of day.

For those of you who have built house mods or location mods, this might be familiar: I'm trying to adapt cipscis/m3rvin's automatic light switch resource, but my script won't compile.

Cipscis/m3rvin's automatic light switch resource

 

The CK wiki link to the script source is here[1]

The Nexusmods link to the compiled script resource is here[2]

 

Basically the script takes two float values corresponding to the time to turn the lights on (say 6PM) and to turn the lights off (say 6AM). When the appropriate time threshold is passed, the script switches between a "lights Off" and "lights On" state. The script is usually attached to an enableparent for the lights, typically an XMarker, and just cycles between states happily.

The problem with this system is that one set of objects is ALWAYS on.

The goal is therefore to write a script that can check that an object reference, which is only enabled when the lights are "crafted" is enabled. And THEN, and ONLY then, to cycle between on off states.

My Script

Normally, you have the objects that show when the lights are ON and those that show when the lights are OFF attached to the SAME XMarker, just with opposite enable states.

My script runs on a controller object which is always enabled. This is intended to be an XMarker.

Two more markers, respectively MarkerLightsOn and MarkerLightsOff act as enableparents for the "lights on" objects and "lights off" objects.

Finally, a last marker - the BuildMarker is enabled or disabled when the object is crafted at a house workbench, like the hearthfire stuff - an item is "crafted", at which point another script attached to that will enable the BuildMarker and promptly remove itself from the players inventory.

I've written the script, but it's failing to compile. I think there's something wrong with the way I've written the LightsBuiltCheck function, but I don't yet know papyrus well enough to troubleshoot appropriately. Could anyone help? The script I've come up with below:

Scriptname BuildableAutomaticLightSwitch extends ObjectReference
{Cipscis and M3rvin's Automatic Light Switch adapted for buildable lights.}
 
float Property LightsOffTime = 6.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 MarkerLightsOn auto
{The marker controlling the "lights on" object references}
ObjectReference Property MarkerLightsOff auto
{The marker controlling the "lights off" object references}

 
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
 
 Function LightsBuiltCheck( ObjectReference BuildMarker)
 {Checks to see if BuildMarker object ref is enabled, and if it is, cycles between the "LightsOn"/"LightsOff" states. If it is disabled, it will go to the LightsNotBuilt State.}
 
 	 If (BuildMarker.IsDisabled())
		If (GetCurrentHourOfDay() > LightsOffTime)
			GoToState("LightsOff")
		Else
			GoToState("LightsOn")
		EndIf
	 Else
		GoToState("LightsNotBuilt")
	 EndIf
	 
EndFunction
 
Event OnInit()

LightsBuiltCheck

EndEvent

State LightsOff
 
	Event OnBeginState()
		Disable(MarkerLightsOn)
		Enable(MarkerLightsOff)
		RegisterForSingleUpdateGameTimeAt(LightsOnTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsOn")
	EndEvent
 
EndState
 
State LightsOn
 
	Event OnBeginState()
		Disable(MarkerLightsOff)
		Enable(MarkerLightsOn)
		RegisterForSingleUpdateGameTimeAt(LightsOffTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsOff")
	EndEvent
 
EndState

State LightsNotBuilt
	Event OnBeginState()
		Disable(MarkerLightsOff)
		Disable(MarkerLightsOn)
		RegisterForSingleUpdateGameTimeAt(LightsOnTime)
		RegisterForSingleUpdateGameTimeAt(LightsOffTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsBuiltCheck")
	EndEvent
 
EndState


Link to comment
Share on other sites

Hi, a couple of things:

 

- there is a space before object reference on LightsBuiltCheck function's parameters, but not sure if that actually causes any issue.

- afaik disable/enable are called Reference.Disable(), and not Disable(Reference), so:

Event OnBeginState()
  MarkerLightsOff.Disable()
  MarkerLightsOn.Enable()
  RegisterForSingleUpdateGameTimeAt(LightsOffTime)
EndEvent

- When you call LightsBuiltCheck in the oninit event it should have the "()":

Event OnInit()
 LightsBuiltCheck()
EndEvent

Not sure if i missed something, the rest looks fine.

btw, the compiler should tell you what lines are the problematic ones.

Edited by FrankFamily
Link to comment
Share on other sites

 

- When you call LightsBuiltCheck in the oninit event it should have the "()":

Event OnInit()
 LightsBuiltCheck()
EndEvent

To expand on this, the function LightsBuiltCheck is written to require a passed in object reference. You'll need to add a new property and point it to the build marker you wish to check. Further more, in the LightsNotBuilt state you send a call to a state called LightsBuiltCheck within the OnUpdateGameTime event. I think you meant to call the function instead of a state that does not exist.

Link to comment
Share on other sites

Hi, a couple of things:

 

- there is a space before object reference on LightsBuiltCheck function's parameters, but not sure if that actually causes any issue.

- afaik disable/enable are called Reference.Disable(), and not Disable(Reference), so:

Event OnBeginState()
  MarkerLightsOff.Disable()
  MarkerLightsOn.Enable()
  RegisterForSingleUpdateGameTimeAt(LightsOffTime)
EndEvent

- When you call LightsBuiltCheck in the oninit event it should have the "()":

Event OnInit()
 LightsBuiltCheck()
EndEvent

Not sure if i missed something, the rest looks fine.

btw, the compiler should tell you what lines are the problematic ones.

 

 

Thanks man, I'm pretty sure the enable/disable syntax is correct on my part because the compiler didn't compile when using your suggestion. However, you were right about both the space and the missing brackets. I've added those in, and the script compiles, but doesn't appear to do anything. Still, it's progress...

 

 

 

 

- When you call LightsBuiltCheck in the oninit event it should have the "()":

Event OnInit()
 LightsBuiltCheck()
EndEvent

To expand on this, the function LightsBuiltCheck is written to require a passed in object reference. You'll need to add a new property and point it to the build marker you wish to check. Further more, in the LightsNotBuilt state you send a call to a state called LightsBuiltCheck within the OnUpdateGameTime event. I think you meant to call the function instead of a state that does not exist.

 

 

I've just seen this - thanks for the feedback Ishara, I'll try this and let you know how I fare.

Link to comment
Share on other sites

Damn, still no luck. In addition to the issues Ishara pointed out, I also fixed the IsDisabled check to an IsEnabled check.

 

The script looks like this now (see below)

 

However, despite compiling and linking it up successfully to the markers, I can't seem to override the enable behaviour of the MarkerLightsOn/LightsOff. Despite me manually enabling/disabling the BuildMarker using the console and waiting till the time change thresholds. Any ideas?

Scriptname BuildableAutomaticLightSwitch extends ObjectReference
{Cipscis and M3rvin's Automatic Light Switch adapted for buildable lights.}
 
float Property LightsOffTime = 6.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 MarkerLightsOn auto
{The marker controlling the "lights on" object references}
ObjectReference Property MarkerLightsOff auto
{The marker controlling the "lights off" object references}
ObjectReference Property BuildMarker auto
{The marker controlling the "lights off" object references}
 
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
 
 Function LightsBuiltCheck()
 {Checks to see if BuildMarker object ref is enabled, and if it is, cycles between the "LightsOn"/"LightsOff" states. If it is disabled, it will go to the LightsNotBuilt State.}
 
 	 If (BuildMarker.IsEnabled())
		If (GetCurrentHourOfDay() > LightsOffTime)
			GoToState("LightsOff")
		Else
			GoToState("LightsOn")
		EndIf
	 Else
		GoToState("LightsNotBuilt")
	 EndIf
	 
EndFunction
 
Event OnInit()

LightsBuiltCheck()

EndEvent

State LightsOff
 
	Event OnBeginState()
		Disable(MarkerLightsOn)
		Enable(MarkerLightsOff)
		RegisterForSingleUpdateGameTimeAt(LightsOnTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsOn")
	EndEvent
 
EndState
 
State LightsOn
 
	Event OnBeginState()
		Disable(MarkerLightsOff)
		Enable(MarkerLightsOn)
		RegisterForSingleUpdateGameTimeAt(LightsOffTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsOff")
	EndEvent
 
EndState

State LightsNotBuilt
	Event OnBeginState()
		Disable(MarkerLightsOff)
		Disable(MarkerLightsOn)
		RegisterForSingleUpdateGameTimeAt(LightsOnTime)
		RegisterForSingleUpdateGameTimeAt(LightsOffTime)
	EndEvent
 
	Event OnUpdateGameTime()
		LightsBuiltCheck()
	EndEvent
 
EndState
Link to comment
Share on other sites

That did it! I think. I'm sorry I doubted you guys:

Scriptname BuildableAutomaticLightSwitch extends ObjectReference
{Cipscis and M3rvin's Automatic Light Switch adapted for buildable lights.}
 
float Property LightsOffTime = 6.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 MarkerLightsOn auto
{The marker controlling the "lights on" object references}
ObjectReference Property MarkerLightsOff auto
{The marker controlling the "lights off" object references}
ObjectReference Property BuildMarker auto
{The marker controlling the "lights off" object references}
 
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
 
 Function LightsBuiltCheck()
 {Checks to see if BuildMarker object ref is enabled, and if it is, cycles between the "LightsOn"/"LightsOff" states. If it is disabled, it will go to the LightsNotBuilt State.}
 
 	 If (BuildMarker.IsEnabled())
		If (GetCurrentHourOfDay() > LightsOffTime)
			GoToState("LightsOff")
		Else
			GoToState("LightsOn")
		EndIf
	 Else
		GoToState("LightsNotBuilt")
	 EndIf
	 
EndFunction
 
Event OnInit()

LightsBuiltCheck()

EndEvent

State LightsOff
 
	Event OnBeginState()
		MarkerLightsOn.Disable(True)
		MarkerLightsOff.Enable(True)
		RegisterForSingleUpdateGameTimeAt(LightsOnTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsOn")
	EndEvent
 
EndState
 
State LightsOn
 
	Event OnBeginState()
		MarkerLightsOff.Disable(True)
		MarkerLightsOn.Enable(True)
		RegisterForSingleUpdateGameTimeAt(LightsOffTime)
	EndEvent
 
	Event OnUpdateGameTime()
		GoToState("LightsOff")
	EndEvent
 
EndState

State LightsNotBuilt
	Event OnBeginState()
		MarkerLightsOn.Disable(True)
		MarkerLightsOff.Disable(True)
		RegisterForSingleUpdateGameTimeAt(LightsOnTime)
		RegisterForSingleUpdateGameTimeAt(LightsOffTime)
	EndEvent
 
	Event OnUpdateGameTime()
		LightsBuiltCheck()
	EndEvent
 
EndState
Link to comment
Share on other sites

  • Recently Browsing   0 members

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