Jump to content

Sexlab LightMeUp


Recommended Posts

Posted

Just an idea but wouldn't it be more simple and give you more control over the resulting lighting setup to place actor independent dynamic light sources at specific positions relative to SL's scene center marker? I know nothing about lighting but there are some mods that make torches droppable so dynamically placeable, magic effect independent light sources seem to exist.

Posted
17 minutes ago, user_no_3453 said:

Just an idea but wouldn't it be more simple and give you more control over the resulting lighting setup to place actor independent dynamic light sources at specific positions relative to SL's scene center marker? I know nothing about lighting but there are some mods that make torches droppable so dynamically placeable, magic effect independent light sources seem to exist.

That sounds great and as you say, way simpler. If you could link me an example that would be very helpful. This is what I wanted to do in the first place but couldn't figure out how.

 

Edit: don't worry if you have no examples, you've given me enough to figure something out

Posted
5 minutes ago, Yinkle said:

That sounds great and as you say, way simpler. If you could link me an example that would be very helpful

Here is one: https://www.nexusmods.com/skyrimspecialedition/mods/14490?

 

Just checked and that mod seems to use Actor.PlaceAtMe(Torch01, ...) where Torch01 is the regular Skyrim torch which seems to be just a regular light source so maybe adding your mesh to a new light source in the CK and using PlaceAtMe to place an instance of it into the world would suffice?

Posted

ahh. we could use placeatme on items with varied offsets and boom nice lighting.

Using the SL marker would be better though

 

Posted
3 hours ago, Yinkle said:

I can't imagine why this mod would cause a crash unless the mesh was bad-  it works fine here. Not much help I know! Have you made sure your version of SOS has the right .dll file for your version of SKSE?

I'm thinking it's an armor I flagged as revealing that wasn't meant to. Doubt this is your mod's fault at all. Will check after work. 

Posted

version 2.0 uploaded: 5 actor independent lights placed at the scene now! The script could probably be done better but it seems to work ok :)

Posted

Hello Yinkle, nice to see this keeps going. There are two things that might be improved about the script.

 

Most notably, a disabled reference is still in the save, you have to Delete it as well (and for best practice set the property containing it to None afterwards so the reference is no longer linked to from anywhere, otherwise the engine might not actually delete it until the property is filled with something else).

 

Secondly if there is more than one NPC scene running, the lights from the second scene to start will override the lights from the first scene and therefore the first ones will not be disabled.

 

I have quickly thrown together a script that should be more robust but it's entirely untested and also more complex. If you want to put in the effort you can try it out, see if it works as intended or needs some more adjustments, change the placement offsets or similar and use as you see fit but please don't feel pressurized to use it.

Spoiler

The script gets the 5 lights as an array "atLights" which you can fill from the CK. Keep in mind though that property values are baked into save games so changing the lights in the CK after running the script will not work without a clean save or without renaming the property (in the entire script so it is treated as a new property). Also if you want a number of lights different from 5, the size of the "aobLights" array would need to be adjusted accordingly.


Scriptname SL_LightsAliasScript extends ReferenceAlias


SexLabFramework Property SexLab Auto
Actor Property PlayerRef Auto
Light[] Property atLights Auto  ; array with all 5 lights


; SexLab can run up to 15 scenes in parallel, so we have 15 different slots for lighting setups, corresponding to the thread ids.

; True for scene slots for which the lights have been placed
Bool[] abLightsPlaced
; True for scene slot that are currently being cleaned up
Bool[] abSceneLocks
; the light references placed in the world. the first 5 slots are for the first light setup, the next five for the second, etc.
ObjectReference[] aobLights


; Changed from OnPlayerLoadGame once all necessary initialization steps for the
; current script version have been done. Don't change value here.
Int iCurrentVersion = 0


event OnInit()
	OnPlayerLoadGame()
endevent

event OnPlayerLoadGame()
	if iCurrentVersion < 1
		RegisterForModEvent("HookAnimationStart", "SLSceneStart")
		RegisterForModEvent("HookAnimationEnding", "SLSceneEnd")
	
		abLightsPlaced = new Bool[15]
		abSceneLocks = new Bool[15]
		aobLights = new ObjectReference[75]  ; 5 lights x 15 scenes
		
		iCurrentVersion = 1
	;elseif iCurrentVersion < 2  ; uncomment for future initialization code changes
	;	; NEW INIT CODE GOES HERE
	;	iCurrentVersion = 2
	endif
endevent

event SLSceneStart(int threadID, bool hasPlayer)
	; make sure the old lights are cleaned up properly
	if abLightsPlaced[threadID]
		RemoveLights(threadID)
	endif
	
	; CenterRef is a property of sslThreadModel which sslThreadController inherits
	ObjectReference obSceneCenter = SexLab.GetController(threadID).CenterRef
	if !obSceneCenter
		return
	endif
	
	float[] fPosition = new float[3]
	float[] fRotation = new float[3]

	; SpawnerTask should work more fluidly than placing the objects separately
	int iSpawner = SpawnerTask.Create()
	if iSpawner > 0
		; prepares the spawner
		int i = 0
		while i < atLights.Length
			SpawnerTask.AddSpawn(iSpawner, aobLights[i], obSceneCenter, fPosition, fRotation)
			i += 1
		endwhile
		
		; actually place the lights
		ObjectReference[] aobSceneLights = SpawnerTask.Run(iSpawner)
		
		; copy created objects to the array where we keep track of them
		int baseIndex = threadID * atLights.Length
		i = atLights.Length
		while i > 0
			i -= 1
			aobLights[baseIndex + i] = aobSceneLights[i]
		endwhile
		
		abLightsPlaced[threadID] = true
	endif	
endevent

event SLSceneEnd(int threadID, bool hasPlayer)
	RemoveLights(threadID)
endevent

function RemoveLights(int threadID)
	if threadID >= 0 && threadID < abLightsPlaced.Length
		
		; If RemoveLights is called from SLSceneStart while it is still running
		; from SLSceneEnd, we wait here until the cleaning is finished so we
		; don't overwrite the old lights in our list and then clean the new ones.
		int iTimeout = 25
		while abSceneLocks[threadID] && iTimeout > 0
			Utility.WaitMenuMode(0.2)
			iTimeout -= 1
		endwhile
		abSceneLocks[threadID] = true
		
		if abLightsPlaced[threadID]
			int baseIndex = threadID * atLights.Length
			
			; first disable all as quickly as possible so they are no longer visible
			int i = atLights.Length
			while i > 0
				i -= 1
				aobLights[baseIndex + i].DisableNoWait()
			endwhile
			
			; now delete them properly
			i = atLights.Length
			while i > 0
				i -= 1
				aobLights[baseIndex + i].Delete()
				aobLights[baseIndex + i] = None
			endwhile
			
			abLightsPlaced[threadID] = false
		endif
		
		abSceneLocks[threadID] = false
	endif
endfunction

 

 

Posted
16 minutes ago, user_no_3453 said:

Hello Yinkle, nice to see this keeps going. There are two things that might be improved about the script.

 

Most notably, a disabled reference is still in the save, you have to Delete it as well (and for best practice set the property containing it to None afterwards so the reference is no longer linked to from anywhere, otherwise the engine might not actually delete it until the property is filled with something else).

 

Secondly if there is more than one NPC scene running, the lights from the second scene to start will override the lights from the first scene and therefore the first ones will not be disabled.

 

I have quickly thrown together a script that should be more robust but it's entirely untested and also more complex. If you want to put in the effort you can try it out, see if it works as intended or needs some more adjustments, change the placement offsets or similar and use as you see fit but please don't feel pressurized to use it.

  Reveal hidden contents

The script gets the 5 lights as an array "atLights" which you can fill from the CK. Keep in mind though that property values are baked into save games so changing the lights in the CK after running the script will not work without a clean save or without renaming the property (in the entire script so it is treated as a new property). Also if you want a number of lights different from 5, the size of the "aobLights" array would need to be adjusted accordingly.



Scriptname SL_LightsAliasScript extends ReferenceAlias


SexLabFramework Property SexLab Auto
Actor Property PlayerRef Auto
Light[] Property atLights Auto  ; array with all 5 lights


; SexLab can run up to 15 scenes in parallel, so we have 15 different slots for lighting setups, corresponding to the thread ids.

; True for scene slots for which the lights have been placed
Bool[] abLightsPlaced
; True for scene slot that are currently being cleaned up
Bool[] abSceneLocks
; the light references placed in the world. the first 5 slots are for the first light setup, the next five for the second, etc.
ObjectReference[] aobLights


; Changed from OnPlayerLoadGame once all necessary initialization steps for the
; current script version have been done. Don't change value here.
Int iCurrentVersion = 0


event OnInit()
	OnPlayerLoadGame()
endevent

event OnPlayerLoadGame()
	if iCurrentVersion < 1
		RegisterForModEvent("HookAnimationStart", "SLSceneStart")
		RegisterForModEvent("HookAnimationEnding", "SLSceneEnd")
	
		abLightsPlaced = new Bool[15]
		abSceneLocks = new Bool[15]
		aobLights = new ObjectReference[75]  ; 5 lights x 15 scenes
		
		iCurrentVersion = 1
	;elseif iCurrentVersion < 2  ; uncomment for future initialization code changes
	;	; NEW INIT CODE GOES HERE
	;	iCurrentVersion = 2
	endif
endevent

event SLSceneStart(int threadID, bool hasPlayer)
	; make sure the old lights are cleaned up properly
	if abLightsPlaced[threadID]
		RemoveLights(threadID)
	endif
	
	; CenterRef is a property of sslThreadModel which sslThreadController inherits
	ObjectReference obSceneCenter = SexLab.GetController(threadID).CenterRef
	if !obSceneCenter
		return
	endif
	
	float[] fPosition = new float[3]
	float[] fRotation = new float[3]

	; SpawnerTask should work more fluidly than placing the objects separately
	int iSpawner = SpawnerTask.Create()
	if iSpawner > 0
		; prepares the spawner
		int i = 0
		while i < atLights.Length
			SpawnerTask.AddSpawn(iSpawner, aobLights[i], obSceneCenter, fPosition, fRotation)
			i += 1
		endwhile
		
		; actually place the lights
		ObjectReference[] aobSceneLights = SpawnerTask.Run(iSpawner)
		
		; copy created objects to the array where we keep track of them
		int baseIndex = threadID * atLights.Length
		i = atLights.Length
		while i > 0
			i -= 1
			aobLights[baseIndex + i] = aobSceneLights[i]
		endwhile
		
		abLightsPlaced[threadID] = true
	endif	
endevent

event SLSceneEnd(int threadID, bool hasPlayer)
	RemoveLights(threadID)
endevent

function RemoveLights(int threadID)
	if threadID >= 0 && threadID < abLightsPlaced.Length
		
		; If RemoveLights is called from SLSceneStart while it is still running
		; from SLSceneEnd, we wait here until the cleaning is finished so we
		; don't overwrite the old lights in our list and then clean the new ones.
		int iTimeout = 25
		while abSceneLocks[threadID] && iTimeout > 0
			Utility.WaitMenuMode(0.2)
			iTimeout -= 1
		endwhile
		abSceneLocks[threadID] = true
		
		if abLightsPlaced[threadID]
			int baseIndex = threadID * atLights.Length
			
			; first disable all as quickly as possible so they are no longer visible
			int i = atLights.Length
			while i > 0
				i -= 1
				aobLights[baseIndex + i].DisableNoWait()
			endwhile
			
			; now delete them properly
			i = atLights.Length
			while i > 0
				i -= 1
				aobLights[baseIndex + i].Delete()
				aobLights[baseIndex + i] = None
			endwhile
			
			abLightsPlaced[threadID] = false
		endif
		
		abSceneLocks[threadID] = false
	endif
endfunction

 

 

This is fabulous! Thank you so much for helping in the effort to improve the script.

Edit: I'll need to spend some time looking at your changes, hopefully I'll upload a new version tomorrow :)

Posted
On 2/8/2019 at 7:14 PM, user_no_3453 said:

Hello Yinkle, nice to see this keeps going. There are two things that might be improved about the script.

 

Most notably, a disabled reference is still in the save, you have to Delete it as well (and for best practice set the property containing it to None afterwards so the reference is no longer linked to from anywhere, otherwise the engine might not actually delete it until the property is filled with something else).

 

Secondly if there is more than one NPC scene running, the lights from the second scene to start will override the lights from the first scene and therefore the first ones will not be disabled.

 

I have quickly thrown together a script that should be more robust but it's entirely untested and also more complex. If you want to put in the effort you can try it out, see if it works as intended or needs some more adjustments, change the placement offsets or similar and use as you see fit but please don't feel pressurized to use it.

  Reveal hidden contents

The script gets the 5 lights as an array "atLights" which you can fill from the CK. Keep in mind though that property values are baked into save games so changing the lights in the CK after running the script will not work without a clean save or without renaming the property (in the entire script so it is treated as a new property). Also if you want a number of lights different from 5, the size of the "aobLights" array would need to be adjusted accordingly.



Scriptname SL_LightsAliasScript extends ReferenceAlias


SexLabFramework Property SexLab Auto
Actor Property PlayerRef Auto
Light[] Property atLights Auto  ; array with all 5 lights


; SexLab can run up to 15 scenes in parallel, so we have 15 different slots for lighting setups, corresponding to the thread ids.

; True for scene slots for which the lights have been placed
Bool[] abLightsPlaced
; True for scene slot that are currently being cleaned up
Bool[] abSceneLocks
; the light references placed in the world. the first 5 slots are for the first light setup, the next five for the second, etc.
ObjectReference[] aobLights


; Changed from OnPlayerLoadGame once all necessary initialization steps for the
; current script version have been done. Don't change value here.
Int iCurrentVersion = 0


event OnInit()
	OnPlayerLoadGame()
endevent

event OnPlayerLoadGame()
	if iCurrentVersion < 1
		RegisterForModEvent("HookAnimationStart", "SLSceneStart")
		RegisterForModEvent("HookAnimationEnding", "SLSceneEnd")
	
		abLightsPlaced = new Bool[15]
		abSceneLocks = new Bool[15]
		aobLights = new ObjectReference[75]  ; 5 lights x 15 scenes
		
		iCurrentVersion = 1
	;elseif iCurrentVersion < 2  ; uncomment for future initialization code changes
	;	; NEW INIT CODE GOES HERE
	;	iCurrentVersion = 2
	endif
endevent

event SLSceneStart(int threadID, bool hasPlayer)
	; make sure the old lights are cleaned up properly
	if abLightsPlaced[threadID]
		RemoveLights(threadID)
	endif
	
	; CenterRef is a property of sslThreadModel which sslThreadController inherits
	ObjectReference obSceneCenter = SexLab.GetController(threadID).CenterRef
	if !obSceneCenter
		return
	endif
	
	float[] fPosition = new float[3]
	float[] fRotation = new float[3]

	; SpawnerTask should work more fluidly than placing the objects separately
	int iSpawner = SpawnerTask.Create()
	if iSpawner > 0
		; prepares the spawner
		int i = 0
		while i < atLights.Length
			SpawnerTask.AddSpawn(iSpawner, aobLights[i], obSceneCenter, fPosition, fRotation)
			i += 1
		endwhile
		
		; actually place the lights
		ObjectReference[] aobSceneLights = SpawnerTask.Run(iSpawner)
		
		; copy created objects to the array where we keep track of them
		int baseIndex = threadID * atLights.Length
		i = atLights.Length
		while i > 0
			i -= 1
			aobLights[baseIndex + i] = aobSceneLights[i]
		endwhile
		
		abLightsPlaced[threadID] = true
	endif	
endevent

event SLSceneEnd(int threadID, bool hasPlayer)
	RemoveLights(threadID)
endevent

function RemoveLights(int threadID)
	if threadID >= 0 && threadID < abLightsPlaced.Length
		
		; If RemoveLights is called from SLSceneStart while it is still running
		; from SLSceneEnd, we wait here until the cleaning is finished so we
		; don't overwrite the old lights in our list and then clean the new ones.
		int iTimeout = 25
		while abSceneLocks[threadID] && iTimeout > 0
			Utility.WaitMenuMode(0.2)
			iTimeout -= 1
		endwhile
		abSceneLocks[threadID] = true
		
		if abLightsPlaced[threadID]
			int baseIndex = threadID * atLights.Length
			
			; first disable all as quickly as possible so they are no longer visible
			int i = atLights.Length
			while i > 0
				i -= 1
				aobLights[baseIndex + i].DisableNoWait()
			endwhile
			
			; now delete them properly
			i = atLights.Length
			while i > 0
				i -= 1
				aobLights[baseIndex + i].Delete()
				aobLights[baseIndex + i] = None
			endwhile
			
			abLightsPlaced[threadID] = false
		endif
		
		abSceneLocks[threadID] = false
	endif
endfunction

 

 

I've made a new version incorporating your contribution.There was one issue that took a bit of hunting down- you'd used the aobLights array instead of the atLights in the spawnertask.addspawn thing. Anyhow it's all good and working nicely now, I'll upload the new version shortly.

 

Posted

@Yinkle I accidentally figured out what made me crash. When adding the ESL header to one of my mods it did the same thing while giving some error about SoS, which doesn't seem to have anything to do with either mod. The only way I fixed my mod crashing the same way was to make it a light master in the CK. Trying in XEdit didn't work.

 

Still no idea why this is only affecting me. :(

Posted
18 hours ago, pburnt said:

Still no idea why this is only affecting me.

Therein at least lies a clue? Must be something up with your setup. Are you having the same issue on a new game?

Posted
10 hours ago, Yinkle said:

Therein at least lies a clue? Must be something up with your setup. Are you having the same issue on a new game?

Dunno. I rolled back my own mod to a regular esp. Tried studying what Arthmoor had to say about light plugins for any clues but got lost in the techno-babble. Really don't want to start a new game cuz I'm just getting to the point of playing some new mods that came out that I haven't tried yet. I'll bug you about it some other time. :lol:

Posted

@pburnt In my experience there is some kind of bug with SOS that can cause CTDs when loading a game if the load order for esl flagged files has changed between the save and now. I assume the problem is related to the code that adds the 52 armor slot to all body armors because I could reliably get around the CTDs by loading the game in the last functioning configuration, using "Clean schlongified amors" from the SOS MCM, saving and only then doing the load order changes that previously caused the crash.

 

@Yinkle Sorry about the issue with the arrays, I should have chosen more distinct names which would have made it obvious and I forgot about the lighting checks but it seems you got everything working flawlessly now. I have dimmed the light for my personal use but agree with what you wrote earlier that it won't be worth the extra complexity to introduce multiple sets of lights or expose light fade values to papyrus through a dll plugin, especially since the mod so far doesn't need a configuration menu. It might be a good idea though to add a note about self-adjusting the fade values back to the main page somewhere more prominent than the old version spoilers. And thanks for the mod, it does add a lot.

Posted
52 minutes ago, user_no_3453 said:

@pburnt In my experience there is some kind of bug with SOS that can cause CTDs when loading a game if the load order for esl flagged files has changed between the save and now. I assume the problem is related to the code that adds the 52 armor slot to all body armors because I could reliably get around the CTDs by loading the game in the last functioning configuration, using "Clean schlongified amors" from the SOS MCM, saving and only then doing the load order changes that previously caused the crash.

 

@Yinkle Sorry about the issue with the arrays, I should have chosen more distinct names which would have made it obvious and I forgot about the lighting checks but it seems you got everything working flawlessly now. I have dimmed the light for my personal use but agree with what you wrote earlier that it won't be worth the extra complexity to introduce multiple sets of lights or expose light fade values to papyrus through a dll plugin, especially since the mod so far doesn't need a configuration menu. It might be a good idea though to add a note about self-adjusting the fade values back to the main page somewhere more prominent than the old version spoilers. And thanks for the mod, it does add a lot.

I added a note about changing the fade values to the mod description and thanks again for your help.

Posted
12 hours ago, user_no_3453 said:

@pburnt In my experience there is some kind of bug with SOS that can cause CTDs when loading a game if the load order for esl flagged files has changed between the save and now. I assume the problem is related to the code that adds the 52 armor slot to all body armors because I could reliably get around the CTDs by loading the game in the last functioning configuration, using "Clean schlongified amors" from the SOS MCM, saving and only then doing the load order changes that previously caused the crash.

I'll try it out. Thanks for your help even if it doesn't work. :D

 

Edit: It worked! Even my mod will mod will load as esl now. I wasn't aware of the quirk with SoS and light plugins. Thank you very much!

Posted
On 2/19/2019 at 9:17 AM, Serenna187 said:

Does it use the standard vanilla torch,or the more fancy dragonborn variant that actually casts shadows? item id (00036343)

Neither, it uses the vanilla torch.nif as a base for the custom nif file. the actual light sources have nothing to do with torches. You can edit these to your own taste in xedit/ck :)

Posted
1 hour ago, Yinkle said:

Neither, it uses the vanilla torch.nif as a base for the custom nif file. the actual light sources have nothing to do with torches. You can edit these to your own taste in xedit/ck :)

I'm aware,i just wanted to mention that the dragonborn variant has a different light source that actually casts dynamic shadows,which might be preferable over the non-shadow regular one

Posted
29 minutes ago, Serenna187 said:

I'm aware,i just wanted to mention that the dragonborn variant has a different light source that actually casts dynamic shadows,which might be preferable over the non-shadow regular one

I'm not sure you get the point here! This mod is meant as a starting point and the idea is that folk can edit the lights to taste using xedit or the CK. If you want to change the lights, please do, just don't request your preference to be set as the standard.

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...