Jump to content

Recommended Posts

Posted (edited)
On 1/20/2021 at 12:20 PM, gargamel9 said:

For a more challenging experience, please make sure to deactivate all quests in your journal, as otherwise quest markers will point you to the exit.
- Compass is still enabled for now, as I don't know how to block it. So is the local map, so you'll have a little help, although thanks to the two levels projecting over one another, the map isn't too useful.

 

The Devious Devices blindfolds blocks both compass and quest marker location when worn.  Perhaps you could make a special blindfold that can only be unlocked using a key you find at the end of the maze?

Edited by ChandraArgentis
Posted
2 hours ago, Seeker999 said:

@gargamel9 I appreciate you following up. I'm sorry, I don't have that log anymore. I would have posted it but it was too big to upload. I'll use spoiler for same reasons as you.
 

  Hide contents

I posted this issue about 2 weeks and 30+ hours of gameplay after exiting the maze. The log would have been created roughly at time of post and as I said, was too big. I looked at my save dates and hours played info to get this info. I admit I cheated a bit with the time variable in the maze and forgot to set it back right away. So maybe it's my bad that the script kept going. Although I didn't think I slowed it down that much.

To keep from bloating my log, I just removed the script,  I'm going to put it back in to see what happens. Game time scale is normal now, so it might still give useful info, especially if it starts over. How much in game time should elapse? Because if it bloats my log too much I'll have to yank it back out. :(

That said, I agree that the ideal is for it to stop running when you exit. I'm not a modder, but I have a couple of ideas on that.

First, if the script is working as intended, then instead of messing with it, can you do a hard set on the water level when you exit? You know the script is supposed to stop at water level = ###, so when you exit the maze and the dialog box pops up, you add a behind the scenes command/small script to set the water level to ###. I'm not a programmer, so excuse my terminology if it's not right. I can't tell from the script what the setting should be to equal the target.

Do you want people to be able to go back into the maze? I don't know what your plans are for APM going forward. If so, then when entering the maze, you could do a hard set for the water level = 0.

If it's possible to do a water level hard set via the console, let me know and I can try it out with the script back in place.

Second, post a request on the modder's discussion forums here and maybe on Nexus to see if anybody has a solution. I wish I could be more helpful, but I just don't have the skills.

Good luck! :thumbsup:

Hey, Seeker999, thanks for those voice packs. Those will definitely come in handy. If only I could download them all in one download :grin:.
Also thanks for your feedback. I suppose we should rule out the timescale thing interfering with the script. Continued in spoiler (for those who did not play APM yet, I strongly advise not to read)
 

Spoiler

In normal timescale it should take something in the order of 3-10 real-time hours for the script to complete. The Idea is that it should be difficult to notice. I never measured it and the water keeps rising long after the first two levels are flooded. So if your timescale lengthens the day (which would be what I would do), this might well go into tens of hours.
The water is moved using a "Translate" function from the starting level to a marker, what complicates things a bit when it comes to that tiny on-exit script you suggested. Not sure how I would do that. I am not much of a programmer myself. I think it would be easier to make the exit script kill the other script and reset the water level, but I don't know how to do that either. So, right now I just hope the script kills itself eventually :grin:. But I'll definitely have to look into this some more. I guess I'll try those forums, though I'd much prefer having a guy I could discuss this over IM or e mail. Philo221 used to help me with stuff like that, but his e-mail provider black-listed my e-mail provider and he doesn't seem to be reading his messages here anymore.
I also don't think I can come up with a console command to move the water. Previously, I tried much simpler ones and they did not work either. There seems to be a different syntax required in the console or something. Or maybe I need to call the script I want to change first, somehow. I stopped trying. It's frustrating how all the information on CK is so fragmented and difficult to find. For now, I am happy it works at all. Please let me know what you find. And where again is this papyrus log located?
Thanks!

 

Posted
19 minutes ago, ChandraArgentis said:

 

The Devious Devices blindfolds blocks both compass and quest marker location when worn.  Perhaps you could make a special blindfold that can only be unlocked using a key you find at the end of the maze?

Thanks for the suggestion! That would be splendid, indeed. Or even better, if I could extract the code out of those and use it without any item at all. I will try, but I'm afraid that my scripting skills aren't far enough advanced yet to do either. The best thing I can hope for is that eventually someone will just send me the script so I can simply paste it in place. Otherwise it'll probably still take a year or two, before I have enough experience. Could you please send me the Item IDs of those blindfolds? I have no idea which ones they are. There are so many DD items...

Posted (edited)
9 hours ago, gargamel9 said:

Thanks for the suggestion! That would be splendid, indeed. Or even better, if I could extract the code out of those and use it without any item at all. I will try, but I'm afraid that my scripting skills aren't far enough advanced yet to do either. The best thing I can hope for is that eventually someone will just send me the script so I can simply paste it in place. Otherwise it'll probably still take a year or two, before I have enough experience. Could you please send me the Item IDs of those blindfolds? I have no idea which ones they are. There are so many DD items...

If you type 'help blindfold' in the console you can get most of the IDs - there's quite a lot.  There's also "The Veil", which is a special one.  If there's an Obsidian or Cursed blindfold, those are quest items and take special things to remove them.  The last two are from Deviously Cursed Loot though, I think.

Edited by ChandraArgentis
Posted (edited)
13 hours ago, gargamel9 said:

The best thing I can hope for is that eventually someone will just send me the script so I can simply paste it in place.

 

Here you go:

the snippet itself is really short:

Function ToggleCompass(bool show)
	float alpha = 0.0
	if show
		alpha = 100.0
	EndIf
	; Log("ToggleCompass: "+UI.GetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder._alpha"))
	UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder._alpha", alpha)
	UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.DirectionRect._alpha", alpha)
	UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.CompassFrame._alpha", alpha)
EndFunction

The parameter should be pretty self-explanatory.

 

DDf has an Active Magic Effect, which probably is casted on the actor when a blindfold gets equipped. While this Active Magic Effect is present, it uses periodic (~5s) OnUpdate() events to make sure nothing else will show the compass.

That's where you could jump on: build your Active Magic Effect, make sure it starts when the PC enters the labyrinth and ends when the PC leaves (eg by filling a ReferenceAlias with the PC which applies the effect or simply using PlayerRef.AddSpell() and PlayerRef.RemoveSpell()).

Bind that script below to that Effect, fill in the PlayerRef property with the PC and you should be good to go.

Spoiler
Scriptname ToggleCompass extends ActiveMagicEffect  

Actor Property PlayerRef Auto
Bool Property Terminate Auto hidden

Event OnEffectStart(Actor akTarget, Actor akCaster)
    If (akTarget == PlayerRef)
        Terminate = False

        ToggleCompass(false)
        RegisterForSingleUpdate(5.0)
    EndIf
EndEvent

Event OnEffectFinish(Actor akTarget, Actor akCaster)
    Terminate = True
    If (akTarget == PlayerRef)
        ToggleCompass(true)
    EndIf
EndEvent

Event OnUpdate()
    If Terminate
        ToggleCompass(true)
    Else
        ToggleCompass(false)
        RegisterForSingleUpdate(5.0)
    EndIf
EndEvent

Function ToggleCompass(bool show)
    float alpha = 0.0
    if show
        alpha = 100.0
    EndIf

    UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder._alpha", alpha)
    UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.DirectionRect._alpha", alpha)
    UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.CompassFrame._alpha", alpha)
EndFunction

 

 

 

I've played around with the CK a bit and built a small ability which should apply the effect. As an ability is always-on, you simply can use PlayerRef.AddSpell() and PlayerRef.RemoveSpell() in one of your other scripts to add to and remove the ability from the PC and while it's present, the compass should be gone ;) 

 

Untested though ? 

ToggleCompass.7z

Edited by Mister X
added example mod
Posted
4 hours ago, ChandraArgentis said:

If you type 'help blindfold' in the console you can get most of the IDs - there's quite a lot.  There's also "The Veil", which is a special one.  If there's an Obsidian or Cursed blindfold, those are quest items and take special things to remove them.  The last two are from Deviously Cursed Loot though, I think.

Thanks for the tip! Since Mister X seems to have provided exactly what I need, for the compass, I only have to figure out how to block the map. This will be awesome. Thanks guys.

Posted
1 hour ago, Mister X said:

 

Here you go:

the snippet itself is really short:

Function ToggleCompass(bool show)
	float alpha = 0.0
	if show
		alpha = 100.0
	EndIf
	; Log("ToggleCompass: "+UI.GetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder._alpha"))
	UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder._alpha", alpha)
	UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.DirectionRect._alpha", alpha)
	UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.CompassFrame._alpha", alpha)
EndFunction

The parameter should be pretty self-explanatory.

 

DDf has an Active Magic Effect, which probably is casted on the actor when a blindfold gets equipped. While this Active Magic Effect is present, it uses periodic (~5s) OnUpdate() events to make sure nothing else will show the compass.

That's where you could jump on: build your Active Magic Effect, make sure it starts when the PC enters the labyrinth and ends when the PC leaves (eg by filling a ReferenceAlias with the PC which applies the effect or simply using PlayerRef.AddSpell() and PlayerRef.RemoveSpell()).

Bind that script below to that Effect, fill in the PlayerRef property with the PC and you should be good to go.

  Reveal hidden contents
Scriptname ToggleCompass extends ActiveMagicEffect  

Actor Property PlayerRef Auto
Bool Property Terminate Auto hidden

Event OnEffectStart(Actor akTarget, Actor akCaster)
    If (akTarget == PlayerRef)
        Terminate = False

        ToggleCompass(false)
        RegisterForSingleUpdate(5.0)
    EndIf
EndEvent

Event OnEffectFinish(Actor akTarget, Actor akCaster)
    Terminate = True
    If (akTarget == PlayerRef)
        ToggleCompass(true)
    EndIf
EndEvent

Event OnUpdate()
    If Terminate
        ToggleCompass(true)
    Else
        ToggleCompass(false)
        RegisterForSingleUpdate(5.0)
    EndIf
EndEvent

Function ToggleCompass(bool show)
    float alpha = 0.0
    if show
        alpha = 100.0
    EndIf

    UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder._alpha", alpha)
    UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.DirectionRect._alpha", alpha)
    UI.SetNumber("HUD Menu", "_root.HUDMovieBaseInstance.CompassShoutMeterHolder.Compass.CompassFrame._alpha", alpha)
EndFunction

 

 

 

I've played around with the CK a bit and built a small ability which should apply the effect. As an ability is always-on, you simply can use PlayerRef.AddSpell() and PlayerRef.RemoveSpell() in one of your other scripts to add to and remove the ability from the PC and while it's present, the compass should be gone ;) 

 

Untested though ? 

ToggleCompass.7z 1.46 kB · 0 downloads

Awesome!  :smiley: Thanks man. I should be able to implement this. So if I understand correctly, the script above does the same thing as your toggle compass ability? In which case I'll probably go with the ability, as I'm afraid of leaving running scripts behind. I seem to have done so in one instance already. You don't have a script or ability that does the same for the map, too, by any chance? I will of course give you credit in the credits. This will bring the experience on a whole new level. Thanks again!

Posted (edited)

@gargamel9

"The script above" is just the base function that in the end hides or shows the compass.

The script in the spoiler is the one that's actually applied to the magic effect in the example mod, which takes care of calling the function.

 

How it works: you apply the ability with Player.AddSpell(ToggleCompassAbility). That then starts the magic effect which holds the script. The script in the end then removes the compass.

To show the compass again, just call Player.RemoveSpell(ToggleCompassAbility)(both times, ToggleCompassAbility of course has to be a filled property)

You only can apply Spells to an Actor via script, not Magic Effects directly, that's why there is the ability which counts as spell ;) Just disassemble the mod with the CK or xEdit, shouldn't be too complicated.

 

And sadly no, for the map I currently don't know, how to do it. I took parts of those snippets from the DDf framework myself ^^ 

 

EDIT: One thing I forgot to mention: the UI script requires SKSE to be installed. So for the compass hiding to work, that's needed. Shouldn'T be a problem though, as SLf already requires it, too ;) 

Edited by Mister X
Posted
3 hours ago, Mister X said:

@gargamel9

"The script above" is just the base function that in the end hides or shows the compass.

The script in the spoiler is the one that's actually applied to the magic effect in the example mod, which takes care of calling the function.

 

How it works: you apply the ability with Player.AddSpell(ToggleCompassAbility). That then starts the magic effect which holds the script. The script in the end then removes the compass.

To show the compass again, just call Player.RemoveSpell(ToggleCompassAbility)(both times, ToggleCompassAbility of course has to be a filled property)

You only can apply Spells to an Actor via script, not Magic Effects directly, that's why there is the ability which counts as spell ;) Just disassemble the mod with the CK or xEdit, shouldn't be too complicated.

 

And sadly no, for the map I currently don't know, how to do it. I took parts of those snippets from the DDf framework myself ^^ 

 

EDIT: One thing I forgot to mention: the UI script requires SKSE to be installed. So for the compass hiding to work, that's needed. Shouldn'T be a problem though, as SLf already requires it, too ;) 

Thanks for the additional info Mister X. I'll try and implement this in the next update. Right after I'm done with my current project, which is a small mod for sending players to Simple Slavery ++, as none of the defeat or alternate end mods I tried work properly in VR, and APM takes too long to complete. Hopefully nothing will interrupt my work again.
As you said SKSE is not an issue, as it is already required by my mods requirements. Though I am considering on cutting down on these. Is there a way to determine whether I am using the assets from one data file or other? I am using a lot of furniture and restraints etc., but I can't really tell whether these are from DD or ZAZ or wherever...

Posted

Heyho @gargamel9,

 

I had fun playing around with the problem and the solution for the map was much simpler than I thought :D 

 

So, here's a little testing mod, that has two hotkeys:

"G" - toggles the compass (uses the script above)

"H" - toggles the map access (the new code, nearly as simple ^^)

If you have questions, eg how to transfer it to your mod, just ask here or PM me 

 

 

As it purely relies on events, it's absolutely lightweight on the engine, too.

The only thing that doesn't work, even though the code for it is there, is closing the map when the map toggle is activated while it's already open. But once you close it, even then you won't be able to see it next time anymore ;) 

 

ToggleExamples.7z

Posted
1 hour ago, Mister X said:

Heyho @gargamel9,

 

I had fun playing around with the problem and the solution for the map was much simpler than I thought :D 

 

So, here's a little testing mod, that has two hotkeys:

"G" - toggles the compass (uses the script above)

"H" - toggles the map access (the new code, nearly as simple ^^)

If you have questions, eg how to transfer it to your mod, just ask here or PM me 

 

 

As it purely relies on events, it's absolutely lightweight on the engine, too.

The only thing that doesn't work, even though the code for it is there, is closing the map when the map toggle is activated while it's already open. But once you close it, even then you won't be able to see it next time anymore ;) 

 

ToggleExamples.7z 2.77 kB · 0 downloads

Now, this is absolutely awesome. Thank you so much Mister X! I can't wait to implement it. And thanks for the help offered. I'll let you know if I run into problems. But from what you are saying, this should be a piece of cake :) You made my day.

Posted
Quote

Known issue: There is a running script which will continue running even after you exit the maze. If I am correct in my assumptions, it should eventually expire, in a couple of hours or so, and then be gone. This has a reason and it is not a bug. I am just not sophisticated enough in script-writing to be able to kill the script upon exiting the maze.



Assuming the quest is named "PerilousMazeQuest" and the attached script is named "PerilousMazeQuestScript"


This is useful if you have a lot of stuff that needs to be done when the player's location changes.

 

On the Quest's Player alias.

Scriptname PerilousMazePlayerAlias extends ReferenceAlias  

Location Property PerilousMazeLocation  Auto  
Quest property PerilousMazeQuest auto

Event OnLocationChange(Location akOldLoc, Location akNewLoc)

	; Do other location change stuff

	; entering from outside PerilousMazeLocation
	if (akOldLoc != PerilousMazeLocation && akNewLoc == PerilousMazeLocation)
		(PerilousMazeQuest as PerilousMazeQuestScript).StartMazeScript()
	Endif

	; Leaving PerilousMazeLocation to someplace else
	if (akOldLoc == PerilousMazeLocation && akNewLoc != PerilousMazeLocation)
		(PerilousMazeQuest as PerilousMazeQuestScript).StopMazeScript()
	Endif
EndEvent

 

Then in the maze script

Scriptname PerilousMazeQuestScript extends Quest

Float Property UpdateInterval  auto
GlobalVariable Property StopMazeScriptGlobal  auto

: Other stuff

Function StartMazeScript()
	StopMazeScriptGlobal.SetValue(0)
	RegisterForSingleUpdate( UpdateInterval )
EndFunction

Function StoptMazeScript()
	StopMazeScriptGlobal.SetValue(1)
	UnregisterForUpdate()
EndFunction
 
Event OnUpdate()
	; Did something go wrong when doing stuff?
	Bool bDidSomethingBreak = False

	If StopMazeScriptGlobal.GetValue() == 0
		; Do stuff here. Putting stuff inside this check keeps the
		; script from doing stuff when the player is outside the
		; maze

		If bDidSomethingBreak == False
			RegisterForSingleUpdate( UpdateInterval )
		Else
			Debug.Notification("PerilousMazeQuestScript OnUpdate exited due to an error")
		EndIf
	EndIf
EndEvent

 

 


Alternatively

 

Scriptname PerilousMazeQuestScript extends Quest

Float Property UpdateInterval  auto
Location Property PerilousMazeLocation  Auto  

: Other stuff

Function StartMazeScript()
  RegisterForSingleUpdate( UpdateInterval )
EndFunction
 
Event OnUpdate()
	; Did something go wrong when doing stuff?
	Bool bDidSomethingBreak = False

	If Game.GetPlayer().GetCurrentLocation() == PerilousMazeLocation
		; Do stuff here. Putting stuff inside this check keeps the
		; script from doing stuff when the player is outside the
		; maze

		If bDidSomethingBreak == False
			RegisterForSingleUpdate( UpdateInterval )
		Else
			Debug.Notification("PerilousMazeQuestScript OnUpdate exited due to an error")
		EndIf
	EndIf
EndEvent

 

Posted
1 hour ago, jbezorg said:



Assuming the quest is named "PerilousMazeQuest" and the attached script is named "PerilousMazeQuestScript"


This is useful if you have a lot of stuff that needs to be done when the player's location changes.

 

On the Quest's Player alias.

Scriptname PerilousMazePlayerAlias extends ReferenceAlias  

Location Property PerilousMazeLocation  Auto  
Quest property PerilousMazeQuest auto

Event OnLocationChange(Location akOldLoc, Location akNewLoc)

	; Do other location change stuff

	; entering from outside PerilousMazeLocation
	if (akOldLoc != PerilousMazeLocation && akNewLoc == PerilousMazeLocation)
		(PerilousMazeQuest as PerilousMazeQuestScript).StartMazeScript()
	Endif

	; Leaving PerilousMazeLocation to someplace else
	if (akOldLoc == PerilousMazeLocation && akNewLoc != PerilousMazeLocation)
		(PerilousMazeQuest as PerilousMazeQuestScript).StopMazeScript()
	Endif
EndEvent

 

Then in the maze script

Scriptname PerilousMazeQuestScript extends Quest

Float Property UpdateInterval  auto
GlobalVariable Property StopMazeScriptGlobal  auto

: Other stuff

Function StartMazeScript()
	StopMazeScriptGlobal.SetValue(0)
	RegisterForSingleUpdate( UpdateInterval )
EndFunction

Function StoptMazeScript()
	StopMazeScriptGlobal.SetValue(1)
	UnregisterForUpdate()
EndFunction
 
Event OnUpdate()
	; Did something go wrong when doing stuff?
	Bool bDidSomethingBreak = False

	If StopMazeScriptGlobal.GetValue() == 0
		; Do stuff here. Putting stuff inside this check keeps the
		; script from doing stuff when the player is outside the
		; maze

		If bDidSomethingBreak == False
			RegisterForSingleUpdate( UpdateInterval )
		Else
			Debug.Notification("PerilousMazeQuestScript OnUpdate exited due to an error")
		EndIf
	EndIf
EndEvent

 

 


Alternatively

 

Scriptname PerilousMazeQuestScript extends Quest

Float Property UpdateInterval  auto
Location Property PerilousMazeLocation  Auto  

: Other stuff

Function StartMazeScript()
  RegisterForSingleUpdate( UpdateInterval )
EndFunction
 
Event OnUpdate()
	; Did something go wrong when doing stuff?
	Bool bDidSomethingBreak = False

	If Game.GetPlayer().GetCurrentLocation() == PerilousMazeLocation
		; Do stuff here. Putting stuff inside this check keeps the
		; script from doing stuff when the player is outside the
		; maze

		If bDidSomethingBreak == False
			RegisterForSingleUpdate( UpdateInterval )
		Else
			Debug.Notification("PerilousMazeQuestScript OnUpdate exited due to an error")
		EndIf
	EndIf
EndEvent

 

Cool! Thanks jbezorg. I think I get the gist of it. I'll try and apply it to my scrip (just a bit afraid of registering events, as I read that can lead to issues, too, but then again, if it's SingleUpdates, I suppose the risk is low/non-existent) It'll be an adventure, but there is definitely a lot I can learn from your examples. Thanks again!
This is really awesome how people help me out with learning :)

Posted (edited)
On 6/25/2021 at 11:42 AM, gargamel9 said:

I'll try and figure something out with the new update, but I have no clue how this can happen. The script is attached to a trigger volume inside the maze. I am very green when it comes to scripting, so I'm not sure if I'll succeed, though.

 

Heyho, I think I know the problem of that script throwing errors:

You're problem is the loop within the WaterRising script.

 

You only check for

While PlaneZCoordinate < TargetZCoordinate

but what if that specific WaterPlane you want to rise already got unloaded before it reaches its highest point?

 

So, I suggest to run said loop only as long as it's actually possible to rise the water:

While PlaneZCoordinate < TargetZCoordinate && WaterPlane.Is3DLoaded()
  ; code to rise water
EndWhile

Like this, it will abort the loop as soon as the WaterPlane gets unloaded, too.

 

I've rebuilt the whole script a bit differently, too. See comments for details ;) 

Spoiler
Scriptname IncrementalWaterRising extends ObjectReference  

import utility
ObjectReference property WaterPlane Auto
Actor property PlayerREF auto
Float property TrSpeed = 1.0 auto
Float property PlaneRiseStep = 0.1 auto
Float property TargetZCoordinate auto
  
Bool AlreadyRising = false ; mutex to avoid multiple rising loops

Event OnTriggerEnter(ObjectReference akTriggerRef)
	If akTriggerRef == PlayerREF && !AlreadyRising
		AlreadyRising = true
		; get current coordinates of plane, no properties as you could forget to change those when changing WaterPlane position
		Float PlaneXCoordinate = WaterPlane.GetPositionX()
		Float PlaneYCoordinate = WaterPlane.GetPositionY()
		Float PlaneZCoordinate = WaterPlane.GetPositionZ()

		; rise water while not high enough and possible
		While PlaneZCoordinate < TargetZCoordinate && WaterPlane.Is3DLoaded()
			PlaneZCoordinate += PlaneRiseStep
			WaterPlane.TranslateTo(PlaneXCoordinate, PlaneYCoordinate, PlaneZCoordinate, 0.0, 0.0, 0.0, TrSpeed)
			; edit at the end, as directly after the check the plane is surely still there when trying to translate. Checking then waiting first could lead to problems
			Utility.Wait(PlaneRiseStep/TrSpeed) ; PlaneRiseStep [units] / TrSpeed [units/s] = X [s] to wait, not MenuMode as it won't rise while in menu
		EndWhile

		AlreadyRising = false
		; If you want to keep it rising when coming back and it did not reach the wanted height, add check before disabling the Trigger
		If PlaneZCoordinate >= TargetZCoordinate
			Self.Disable()
			Self.Delete()
		EndIf
	EndIf
EndEvent

 

 

Edited by Mister X
added mutex to script
Posted
1 hour ago, Mister X said:

 

Heyho, I think I know the problem of that script throwing errors:

You're problem is the loop within the WaterRising script.

 

You only check for

While PlaneZCoordinate < TargetZCoordinate

but what if that specific WaterPlane you want to rise already got unloaded before it reaches its highest point?

 

So, I suggest to run said loop only as long as it's actually possible to rise the water:

While PlaneZCoordinate < TargetZCoordinate && WaterPlane.Is3DLoaded()
  ; code to rise water
EndWhile

Like this, it will abort the loop as soon as the WaterPlane gets unloaded, too.

 

I've rebuilt the whole script a bit differently, too. See comments for details ;) 

  Hide contents
Scriptname IncrementalWaterRising extends ObjectReference  

import utility
ObjectReference property WaterPlane Auto
Actor property PlayerREF auto
Float property TrSpeed = 1.0 auto
Float property PlaneRiseStep = 0.1 auto
Float property TargetZCoordinate auto
  
Bool AlreadyRising = false ; mutex to avoid multiple rising loops

Event OnTriggerEnter(ObjectReference akTriggerRef)
	If akTriggerRef == PlayerREF && !AlreadyRising
		AlreadyRising = true
		; get current coordinates of plane, no properties as you could forget to change those when changing WaterPlane position
		Float PlaneXCoordinate = WaterPlane.GetPositionX()
		Float PlaneYCoordinate = WaterPlane.GetPositionY()
		Float PlaneZCoordinate = WaterPlane.GetPositionZ()

		; rise water while not high enough and possible
		While PlaneZCoordinate < TargetZCoordinate && WaterPlane.Is3DLoaded()
			PlaneZCoordinate += PlaneRiseStep
			WaterPlane.TranslateTo(PlaneXCoordinate, PlaneYCoordinate, PlaneZCoordinate, 0.0, 0.0, 0.0, TrSpeed)
			; edit at the end, as directly after the check the plane is surely still there when trying to translate. Checking then waiting first could lead to problems
			Utility.Wait(PlaneRiseStep/TrSpeed) ; PlaneRiseStep [units] / TrSpeed [units/s] = X [s] to wait, not MenuMode as it won't rise while in menu
		EndWhile

		AlreadyRising = false
		; If you want to keep it rising when coming back and it did not reach the wanted height, add check before disabling the Trigger
		If PlaneZCoordinate >= TargetZCoordinate
			Self.Disable()
			Self.Delete()
		EndIf
	EndIf
EndEvent

 

 

Wow, yet again, awesome. You couldn't make it any easier for me than that. I feel like it's Christmas :) I'll include this in the next update (within a few days-weeks, because I don't like jumping between projects unless a milestone is reached)  And I'll include you in the credits, of course. Thanks again!

Posted

I hope it helps ^^

There still is testing needed though, as I wasn't able to find the WaterRising trigger ingame yet to test the new script functionality ?

Or the exit to see if the Navigation removal works properly ... and gets deactivated again when leaving the labyrinth. Maybe, as additional security layer for that, a CK condition within the ability could help, to only apply the magic effects if the player is in the labyrinth cell ?

 

BTW, it could be useful to run the plugin through the xEdit Quick Cleaner, at least on my end it found quite some ITM records that got removed ;) 

Posted
1 hour ago, Mister X said:

I hope it helps ^^

There still is testing needed though, as I wasn't able to find the WaterRising trigger ingame yet to test the new script functionality ?

Or the exit to see if the Navigation removal works properly ... and gets deactivated again when leaving the labyrinth. Maybe, as additional security layer for that, a CK condition within the ability could help, to only apply the magic effects if the player is in the labyrinth cell ?

 

BTW, it could be useful to run the plugin through the xEdit Quick Cleaner, at least on my end it found quite some ITM records that got removed ;) 

Thanks.
 

Spoiler

The trigger volume is right at the entrance into the maze itself, maze-side (i.e. not in the cistern). It envelops the entire door area, so it's impossible not to trigger it. It also triggers a pop-up message.

As for xEdit, you're probably right, but I have yet to learn how to use that tool. I don't even know what ITM means. I still have a long way to go. ;)

Posted
36 minutes ago, gargamel9 said:

As for xEdit, you're probably right, but I have yet to learn how to use that tool. I don't even know what ITM means. I still have a long way to go.

 

How to use it: Cleaning Plugins - even though it's for the Vanilla master files, the same basic procedure is the same for all other plugins, too.

 

And ITM means "Identical To Master" records, which are changes your plugins makes, without actually changing something. That's just bad practice and in the worst case it can lead to instability.

Basically, as general example, Skyrim may tell "Book X is positioned at position Y". When another mod would move that hypothetic book, that mod normally tells "Book X is positioned at position Z", so it makes a so-called record change. Your mod on the other side unnecessarily tells "Book X is positioned at position Y" AGAIN, which is called an ITM. So your mod wants to move the book without really moving it.

Posted
19 hours ago, gargamel9 said:

Cool! Thanks jbezorg. I think I get the gist of it. I'll try and apply it to my scrip (just a bit afraid of registering events, as I read that can lead to issues, too, but then again, if it's SingleUpdates, I suppose the risk is low/non-existent) It'll be an adventure, but there is definitely a lot I can learn from your examples. Thanks again!
This is really awesome how people help me out with learning :)


No problem!

RegisterForSingleUpdate()  at the end of the block as the last instruction helps eliminate some of the papyrus scripting caveats when you have to do something periodically. 

  • When RegisterForSingleUpdate() is executed the timer for the next call starts then. This prevents the possibility of the script starting another process before the previous one finished unlike RegisterForUpdate(). RegisterForUpdate() will trigger the next OnUpdate event even if the previous one isn't finished. 
  • RegisterForSingleUpdate() lets you adjust the interval on the fly. You'd have to run UnregisterForUpdate() before changing the time with RegisterForUpdate().  

If you have to use RegisterForUpdate()

 

Scriptname PerilousMazeQuestScript extends Quest

Float Property UpdateInterval  auto
GlobalVariable Property StopMazeScriptGlobal  auto

; Private Variables
Bool bDidSomethingBreak = False
Bool bProcessRunning    = False



: Other stuff



Function StartMazeScript()
	StopMazeScriptGlobal.SetValue(0)
	RegisterForUpdate( UpdateInterval )
EndFunction

Function StoptMazeScript()
	StopMazeScriptGlobal.SetValue(1)
	UnregisterForUpdate()
EndFunction


Event OnUpdate()
	If StopMazeScriptGlobal.GetValue() == 0 && bProcessRunning == False
		; We're doing stuff. Lets lock the door and not try to do
		; stuff while we're already doing stuff. Note we lock the
		; door as soon as we're in.
		bProcessRunning    = True

		; Did something go wrong when doing stuff?
		;
		; Note that "bDidSomethingBreak" was moved inside the check
		; because another OnUpdate() event could be called before
		; a previous one has finished resetting it to "False"
		bDidSomethingBreak = False



		; Do stuff here. Putting stuff inside this check keeps the
		; script from doing stuff when the player is outside the
		; maze



		If bDidSomethingBreak == True
			UnregisterForUpdate()
			Debug.Notification("PerilousMazeQuestScript OnUpdate exited due to an error")

			; If we put a "return" here we immediately jump out of the event block and
			; unless "bProcessRunning" is set back to False we can keep the door locked
		EndIf

		; all done. Unlock the door
		bProcessRunning = False
	EndIf
EndEvent

 

Posted
8 hours ago, Mister X said:

 

How to use it: Cleaning Plugins - even though it's for the Vanilla master files, the same basic procedure is the same for all other plugins, too.

 

And ITM means "Identical To Master" records, which are changes your plugins makes, without actually changing something. That's just bad practice and in the worst case it can lead to instability.

Basically, as general example, Skyrim may tell "Book X is positioned at position Y". When another mod would move that hypothetic book, that mod normally tells "Book X is positioned at position Z", so it makes a so-called record change. Your mod on the other side unnecessarily tells "Book X is positioned at position Y" AGAIN, which is called an ITM. So your mod wants to move the book without really moving it.

Cool, thanks. The hand from above keeps on giving :) I'll try this out.
I probably do have some of those ITMs, as sometimes, I accidentally move or touch something in CK, and even after undoing, that little asterisk still persists. Normally I reload the plugin, but sometimes, when I forget to save for a longer period, it would be just too much loss of progress, so I keep the changes. Really annoying.

Posted
44 minutes ago, jbezorg said:


No problem!

RegisterForSingleUpdate()  at the end of the block as the last instruction helps eliminate some of the papyrus scripting caveats when you have to do something periodically. 

  • When RegisterForSingleUpdate() is executed the timer for the next call starts then. This prevents the possibility of the script starting another process before the previous one finished unlike RegisterForUpdate(). RegisterForUpdate() will trigger the next OnUpdate event even if the previous one isn't finished. 
  • RegisterForSingleUpdate() lets you adjust the interval on the fly. You'd have to run UnregisterForUpdate() before changing the time with RegisterForUpdate().  

If you have to use RegisterForUpdate()

 

Scriptname PerilousMazeQuestScript extends Quest

Float Property UpdateInterval  auto
GlobalVariable Property StopMazeScriptGlobal  auto

; Private Variables
Bool bDidSomethingBreak = False
Bool bProcessRunning    = False



: Other stuff



Function StartMazeScript()
	StopMazeScriptGlobal.SetValue(0)
	RegisterForUpdate( UpdateInterval )
EndFunction

Function StoptMazeScript()
	StopMazeScriptGlobal.SetValue(1)
	UnregisterForUpdate()
EndFunction


Event OnUpdate()
	If StopMazeScriptGlobal.GetValue() == 0 && bProcessRunning == False
		; We're doing stuff. Lets lock the door and not try to do
		; stuff while we're already doing stuff. Note we lock the
		; door as soon as we're in.
		bProcessRunning    = True

		; Did something go wrong when doing stuff?
		;
		; Note that "bDidSomethingBreak" was moved inside the check
		; because another OnUpdate() event could be called before
		; a previous one has finished resetting it to "False"
		bDidSomethingBreak = False



		; Do stuff here. Putting stuff inside this check keeps the
		; script from doing stuff when the player is outside the
		; maze



		If bDidSomethingBreak == True
			UnregisterForUpdate()
			Debug.Notification("PerilousMazeQuestScript OnUpdate exited due to an error")

			; If we put a "return" here we immediately jump out of the event block and
			; unless "bProcessRunning" is set back to False we can keep the door locked
		EndIf

		; all done. Unlock the door
		bProcessRunning = False
	EndIf
EndEvent

 

Thanks again jbezorg! Though Master X has provided me with a script I can just copy-paste into the mod, which will likely solve the issue. This will still become very handy at some point, I think. Quite possibly in the mod I'm working on right now. It'll be a treat :) Can't wait to finish it.

Posted (edited)

Hey, I think I might have found a bug.

 

I had to cheat to get to the end of the maze, but when I went through the door I told the woman on the other side of the cage that she had to come and get me, and nothing happened. After that she force greeted me twice without any dialogue to respond with. That and when I first entered the cage I think the message about escaping got cut off.20210816100412_1.jpg.c1a5cb97c7dff8a7c966cae6a237f810.jpg

 

I also tried to just submit but after I was striped nothing happened, the console didn't seem to have any relevant information either.

Edited by AvairyStars
Posted
2 hours ago, AvairyStars said:

Hey, I think I might have found a bug.

 

I had to cheat to get to the end of the maze, but when I went through the door I told the woman on the other side of the cage that she had to come and get me, and nothing happened. After that she force greeted me twice without any dialogue to respond with. That and when I first entered the cage I think the message about escaping got cut off.20210816100412_1.jpg.c1a5cb97c7dff8a7c966cae6a237f810.jpg

 

I also tried to just submit but after I was striped nothing happened, the console didn't seem to have any relevant information either.

Not sure about the missing dialogue (I'll check the files again if something's missing in the package). As for nothing happening after submitting, this is either because Simple Slavery ++ is not installed, as at this point you should be teleported there, or because something went wrong with the savegame. I had this happen to me when I was using a save where I have played around with other mods quite a bit, but it never happens when I use a fresh save. Hopefully the upcoming script cleanup could help. Otherwise I would try loading up an unmodded savegame and see if the problems reoccur.

Posted
2 hours ago, AvairyStars said:

Hey, I think I might have found a bug.

 

I had to cheat to get to the end of the maze, but when I went through the door I told the woman on the other side of the cage that she had to come and get me, and nothing happened. After that she force greeted me twice without any dialogue to respond with. That and when I first entered the cage I think the message about escaping got cut off.20210816100412_1.jpg.c1a5cb97c7dff8a7c966cae6a237f810.jpg

 

I also tried to just submit but after I was striped nothing happened, the console didn't seem to have any relevant information either.

As for the cut-off message, are you using a different font? It seems different to what I am used to. If that's the case, then that's the most likely culprit. The message is very long and just barely fits in the box. In your case, it is clearly overflowing for some reason. I could have put the text in two boxes, but I felt like that would be breaking immersion too much.

Posted (edited)
3 hours ago, AvairyStars said:

After that she force greeted me twice without any dialogue to respond with. That and when I first entered the cage I think the message about escaping got cut off.

 

You're using Sovngarde font. It is slightly bigger than the default Skyrim font and every single message box in the game will be affected - quest journals, pop-up messages, option menus. etc., some more then others. It may lead to parts of text being cut off or overlaping. This is not tied to this mod. You can either disable the font entirely, find a different font mod that has smaller characters or just get used to it.

Edited by belegost

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

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