Jump to content

Devious Devices Framework Development/Beta


Recommended Posts

9 minutes ago, Kharos said:

Yeah, I fully agree about waiting in UnlockDevice()/LockDevice(), it will make code that (un)locks multiple devices really slow which is definitively not something that we want. That's why I asked if it is possible to instead recognize the 1% case in the UnlockDevice that follows the UnlockDevice and do some additional corrective action (e.g. unequip the rendered device that conflicts with the new one that we want to equip).

Not sure if you have seen my post on the last page (it was the last on that page, so it was easy to overlook), but yes, I was thinking about a solution pretty similar to the code snippet you posted. The problem a the heart of that race condition is the old rendered device not yet taken off before LockDevice() tries to put the new device in, which will then fail because of the slot still being "occupied" (DD checks for that). There are some ways I can check for such a "device unlock in progress" state, and there is one idea I have that might solve this issue very reliably, exploiting the circumstance that this problem can occur for the player character ONLY. UnlockDevice() performs all the unlock operations for NPCs, because OnUnequipped() never gets fired for NPCs. I need to think it through, first. :) 

Link to comment
42 minutes ago, VirginMarie said:

K well, I can tell you that with DD4 (all DD4 versions), swapping was 100% stable. It's because I used the mutex everywhere. And if I ran only my mod for DD content, the ages old broken device syndrome was non existent. 

 

Edges case? I think you underestimate how much these "edges cases" in SLAV, are actually normal, well beyond just SLaV. Testing is all about edges cases, its what makes a quality software product. If you don't test for and fix your edges cases, it's called alpha software.

 

I'm doing a full playthrough to test new non-DD related things, but with DD5 still installed, and DCL is there to create more "edges cases" (from SLaV's perspective, yes, what DCL can impact are MY edge cases). And I can tell you I've seen a certain behavior which we no longer talk about, that you've deemed just an unimportant "edge case", recreate from a common DCL scene, 2 out of 5 times now. 

Not sure which part of me acknowledging that the race condition problem is real you overlooked. I am on it, okay? Your mod is a good test case for the exact reason you mentioned: It's a big collection of edge cases. I get the idea that yours is not the only mod doing device swaps. I even said mine does it, too. You just do it way more often than most others, apparently.

 

The upcoming SwapDevices() function will be able to handle swaps safely (at least that's the goal), and WITHOUT having to use mutex code for the ~95% of cases when device operations aren't swaps. It's not that I am not working on your reports, so I am not sure why you need to be so pushy?

Link to comment
36 minutes ago, Kimy said:

Not sure if you have seen my post on the last page (it was the last on that page, so it was easy to overlook), but yes, I was thinking about a solution pretty similar to the code snippet you posted. The problem a the heart of that race condition is the old rendered device not yet taken off before LockDevice() tries to put the new device in, which will then fail because of the slot still being "occupied" (DD checks for that). There are some ways I can check for such a "device unlock in progress" state, and there is one idea I have that might solve this issue very reliably, exploiting the circumstance that this problem can occur for the player character ONLY. UnlockDevice() performs all the unlock operations for NPCs, because OnUnequipped() never gets fired for NPCs. I need to think it through, first. :) 

Ok, that sounds really promising. I assume that there are good reasons to keep two code paths, instead of just handling NPCs and PC identically in UnlockDevice() and fully getting rid of the event? Well... that's an obvious question so the answer is probably "yes indeed", sorry :classic_laugh:.

 

36 minutes ago, VirginMarie said:

If you don't test for and fix your edge cases, it's called alpha software.

Hmm... how do I say this in a diplomatic way... you may not intend that, but you really come over as talking down from the high horse here. In my personal experience people are usually more happy to help me when I refrain from doing that.

 

[Edit] Reading that again I failed to be diplomatic. Basically I want to say that my first reaction reading your post was a strong feeling that it will make matters worse, not better.

Link to comment
1 minute ago, Kharos said:

Ok, that sounds really promising. I assume that there are good reasons to keep two code paths, instead of just handling NPCs and PC identically in UnlockDevice() and fully getting rid of the event? Well... that's an obvious question so the answer is probably "yes indeed", sorry :classic_laugh:.

Unfortunately, there is a reason. It's called "Skyrim being Skyrim". The problem is an engine bug which makes equip states for gear on NPCs wonky at best (that's polite for "it doesn't work"), so the OnUnequipped() events aren't firing for NPCs after calling UnlockDevice(), because the engine thinks that this device isn't equipped at all. So yes, a whole lot of code had to be written to deal with that and still remain largely backwards-compatible with older DD versions, e.g. the RemoveDevice() events a lot of mods use to do stuff when a device is removed.

Link to comment

 

45 minutes ago, Kimy said:

I am on it, okay?

Okay. Did not realize it. Otherwise I'd not be pushing.

 

I do think there are edge cases that are not a straight forward swap, that all mods can experience, that can have the same problem and be impacted.

Example: DCL equips a gag, then SLaV replaces it with a gag at the same time. SLaV would not be using Swap, maybe.

 

I think the issue is broader on a root cause basis, but don't know if it's too rare to need to deal with. The suggestion I made earlier, where you "detect" that it's a swap, if doable, would be a broader solution, and make it backwards compatible too. I will say no more on this unless I find a SLaV use case that recreates the problem where I can't use the new Swap.

Link to comment
42 minutes ago, Kimy said:

Unfortunately, there is a reason. It's called "Skyrim being Skyrim". The problem is an engine bug which makes equip states for gear on NPCs wonky at best (that's polite for "it doesn't work"), so the OnUnequipped() events aren't firing for NPCs after calling UnlockDevice(), because the engine thinks that this device isn't equipped at all. So yes, a whole lot of code had to be written to deal with that and still remain largely backwards-compatible with older DD versions, e.g. the RemoveDevice() events a lot of mods use to do stuff when a device is removed.

So... it is possible that I am not making sense here with my limited knowledge, or that I am misunderstanding what you write above, or that I am misunderstanding the current implementation. But if I understand you correctly you are saying that the current implementation uses an alternate code path for NPCs that does not depend on unequip events because these events are unreliable for NPCs.

 

My question about having two code paths was basically the other way around: If you already have an alternate code path for NPCs that does not depend on unequip events, is there a good reason to keep the code path that depends on these events for the PC? Naively thinking it would seem to be easier to have a single code path (e.g. less code == less bugs). Also if I understand you correctly the edge case is mainly because the event is happening async to the UnlockDevice()/LockDevice() call; would this mean that the NPC code path will not have the edge case?

Link to comment
7 minutes ago, Kharos said:

If you already have an alternate code path for NPCs that does not depend on unequip events, is there a good reason to keep the code path that depends on these events for the PC?

From the comments in the DD code, its because the NPC path is freaking slow, and the goal was to make it faster.

Link to comment
1 hour ago, Kharos said:

My question about having two code paths was basically the other way around: If you already have an alternate code path for NPCs that does not depend on unequip events, is there a good reason to keep the code path that depends on these events for the PC?

Yes, there is. There are some events called by OnUnequipped() that were working for the player in DD4 and prior, that I absolutely wanted to keep working in DD5. Otherwise all sorts of things would have broken in existing mods. It would non-trivial to keep these events working without having that separate path through OnUnequipped(), so that's the solution I went with.

Link to comment

What was decided on for the 1st person glove textures?

For SE, with the full beta 9 upgraded to beta 12, I am not getting the 1st person catsuit (body/gloves/long gloves) textures swapped. I do have the SSE Engine Fixes, which is supposed to fix 1st person texture swapping for females in SE. No change if I disable engine fixes or roll back to beta 9. I'm thinking about adding in texture swaps, since it looks like. Since I think I recall a mention that this is working in LE, I'm just noting it for now. I might try texture sets later.

 

Noticed a couple straitjacket outfits with duplicate names in inventory, I would not be surprised to see it for all colors and not just white. Any idea why the topless is showing the wrong inventory name? Console shows the same name that inventory does.

 

xx00083F - White Ebonite Straitjacket Dress (Open) - straitjacket open, dress top showing
    zadx_StraitJacketHobbleDressEboniteWhiteOpenInventory - White Ebonite Straitjacket Dress (Open)
xx04E2F0 - White Ebonite Straitjacket Dress (Open) - straitjacket open, no dress top
    zadx_StraitJacketLatexDressToplessWhiteInventory - White Ebonite Straitjacket Dress (Topless)
xx000847 - White Leather Straitjacket Dress (Open) - straitjacket open, dress top showing
    zadx_StraitJacketHobbleDressLeatherWhiteOpenInventory - White Leather Straitjacket Dress (Open)
xx04E2FC - White Leather Straitjacket Dress (Open) - straitjacket open, no dress top
    zadx_StraitJacketLeatherDressToplessWhiteInventory - White Leather Straitjacket Dress (Topless)

 

image.png.b57a9e475297cb0f4367fee9a025af41.png

 

Rubber socks and catsuit gloves were invisible in SE, I added bodyslides in SE to fix that. Might just be a mesh conversion issue if it's showing for everyone else.

Link to comment

Btw one glorious idea i just had about armbinder (and maybe some other restraints) that i'm not sure how possible it is... If it would have a tightness property that would also effect how it looks. At 0 tightness it would be easy to struggle free and at 100 impossible, and it would visually match the current elbow binder if not a little tighter.

 

One could make devices that loosen over time, not every second updates but something once every 1 game hour perhaps because i know model updates could be expensive. It's a nice alternative to timed devices and "brings devices alive" more kind of. There could even be mechanics to tighten them more after put on, and none of this would mean any gear swapping.

 

DD itself has critical failure chance for struggling that "tightens device more", now you would actually see the effect and it would be more interactive.

Link to comment

Found out that the penis piercings in For Him had missing textures after reading the SE thread of For Him.

 

Here's a fix for that:

 

-Fixed PA piercing textures not being included.

-Changed PA piercings to use texture sets instead of multiple meshes.

-Removed schlong from PA meshes, as it isn't even rendered in-game.

-Deleted redundant PA mesh files following texture sets change.

 

 

DD_For_Him_WIP.7z

Link to comment
18 hours ago, zarantha said:

What was decided on for the 1st person glove textures?

For SE, with the full beta 9 upgraded to beta 12, I am not getting the 1st person catsuit (body/gloves/long gloves) textures swapped. I do have the SSE Engine Fixes, which is supposed to fix 1st person texture swapping for females in SE. No change if I disable engine fixes or roll back to beta 9. I'm thinking about adding in texture swaps, since it looks like. Since I think I recall a mention that this is working in LE, I'm just noting it for now. I might try texture sets later.

 

Noticed a couple straitjacket outfits with duplicate names in inventory, I would not be surprised to see it for all colors and not just white. Any idea why the topless is showing the wrong inventory name? Console shows the same name that inventory does.

 

xx00083F - White Ebonite Straitjacket Dress (Open) - straitjacket open, dress top showing
    zadx_StraitJacketHobbleDressEboniteWhiteOpenInventory - White Ebonite Straitjacket Dress (Open)
xx04E2F0 - White Ebonite Straitjacket Dress (Open) - straitjacket open, no dress top
    zadx_StraitJacketLatexDressToplessWhiteInventory - White Ebonite Straitjacket Dress (Topless)
xx000847 - White Leather Straitjacket Dress (Open) - straitjacket open, dress top showing
    zadx_StraitJacketHobbleDressLeatherWhiteOpenInventory - White Leather Straitjacket Dress (Open)
xx04E2FC - White Leather Straitjacket Dress (Open) - straitjacket open, no dress top
    zadx_StraitJacketLeatherDressToplessWhiteInventory - White Leather Straitjacket Dress (Topless)

 

Rubber socks and catsuit gloves were invisible in SE, I added bodyslides in SE to fix that. Might just be a mesh conversion issue if it's showing for everyone else.

For the time being, I left the original solution (using individual meshes) in the beta, which, if I got the discussion right, is supposed to work in any case, fixes installed or not.

 

Either way, there shouldn't be texture issues anymore, so not sure what's going on there?

Link to comment
15 hours ago, Zaflis said:

Btw one glorious idea i just had about armbinder (and maybe some other restraints) that i'm not sure how possible it is... If it would have a tightness property that would also effect how it looks. At 0 tightness it would be easy to struggle free and at 100 impossible, and it would visually match the current elbow binder if not a little tighter.

 

One could make devices that loosen over time, not every second updates but something once every 1 game hour perhaps because i know model updates could be expensive. It's a nice alternative to timed devices and "brings devices alive" more kind of. There could even be mechanics to tighten them more after put on, and none of this would mean any gear swapping.

 

DD itself has critical failure chance for struggling that "tightens device more", now you would actually see the effect and it would be more interactive.

I can't seamlessly scale meshes at run time like that, and also this would break the animations (which need to 100% fit the device worn), so I don't think this is feasible. However, I did implement a DD feature that allows implementing devices like this using a workaround that swaps devices, so you can exchange e.g. a loose armbinder for the elbow one and vice versa. DCL 9 will ship with that device. :)

Link to comment
21 minutes ago, Kimy said:

For the time being, I left the original solution (using individual meshes) in the beta, which, if I got the discussion right, is supposed to work in any case, fixes installed or not.

 

Either way, there shouldn't be texture issues anymore, so not sure what's going on there?

 

That's the safest way, separate 1stPerson meshes are pretty much guaranteed to work unless the mesh is missing. Don't forget to grab the 1stPerson meshes for Paw Mittens, I know it's been hectic for you lately so just a reminder.

Link to comment

Pretty sure that's a false positive. I can't imagine what kind of file in that archive could even transmit malware. Virustotal shows zero issues with this file (I just checked it, just to make sure).

 

On top of that, I wouldn't remotely know where I could get malware from, considering that I am not using Windows for anything but working on Skyrim mods. :D

Link to comment

Devious Devices 5 Beta 13


- Added: New API function SwapDevices() that can safely swap out a worn device to replace with one of the same type. If no conflicting devices are worn, the function behaves like LockDevice()
- Changed: LockDevice() will now use SwapDevices() when called with force = true, to facilitate safe swapping.
- Changed: Added a small delay to StartValidDDAnimation() before starting the animation, to make SexLab less likely to hiccup.
- Changed: Added a feature to detect device swaps (replacing a DD device in the same device slot) in progress and make sure the removal operation completes before trying to equip the new device.

 

Delta Patch for upgrading from Beta 1:

 

Devious Devices 5 LE Beta Delta Patch Beta 1 to Beta 13.7z

 

Delta Patch for upgrading from Beta 9:

 

Devious Devices 5 LE Beta Delta Patch Beta 9 to Beta 13.7z

 

Devious Devices 5 Beta 9 Download link (full release):
 
https://mega.nz/file/jJtw3arB#wqgkLIOs8qnCPZ0Nw-fHNMXnt0fpQsBBOxhs1JEZZgE

 

Link to comment
3 hours ago, UnEvenSteven said:

 

That's the safest way, separate 1stPerson meshes are pretty much guaranteed to work unless the mesh is missing. Don't forget to grab the 1stPerson meshes for Paw Mittens, I know it's been hectic for you lately so just a reminder.

 

I will merge that for the next release and/or the final version. Thanks for the reminder! :)

Link to comment
33 minutes ago, Kimy said:

Pretty sure that's a false positive. I can't imagine what kind of file in that archive could even transmit malware. Virustotal shows zero issues with this file (I just checked it, just to make sure).

Not getting virus warning for Beta 9 to 13.

 

Release notes looking promising.

Link to comment

Haha, well, happy Friday 13th everyone! Second one of the year, in the year 2020.

I noticed the Hooked Elbow Shackles currently are not working for me while other variations work just fine. Not sure if it's an issue with my setup or a universal problem. Can someone else take a quick look and see if it's working as expected for them?

Link to comment
26 minutes ago, Calashaur said:

Haha, well, happy Friday 13th everyone! Second one of the year, in the year 2020.

 

Wasn't the entire year so far kinda an ongoing Friday 13th?

 

26 minutes ago, Calashaur said:

I noticed the Hooked Elbow Shackles currently are not working for me while other variations work just fine. Not sure if it's an issue with my setup or a universal problem. Can someone else take a quick look and see if it's working as expected for them?

 

This device (as in all variants of it) is still in development. It has a few issues, namely with the animation set, that right now, I don't have the slightest clue how to fix. Among things because I am not an animator. Honestly, if anybody out there has some idea, I am all ears.

Link to comment

@KimyRace Condition Test, with Beta 13

  • similar test, this time 6 Tests, 2 for Swap, 2 for Lock, and 2 for Depreciated, reducing delay until failure
  • code is below
Spoiler
Spoiler

 

 


;.......... Test Equip/Remove Device Race Condition
Function VirginTestRaceCond()
	String TestFunctionType = "Swap"
	Int Test = 1
	While Test <= 6
		Int Try = 1
		Float Delay = 0.5
		Int DelayCount = 1
		Bool Alternate = False ;Alternating between the 2 devices
		Bool Failed = False
		While ! Failed
			If Alternate
				;switch from normal to horny Nipple Bells
				If TestFunctionType == "Depreciated"
					libs.removeDevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, True, False, True)
					libs.equipdevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, False, True)
				ElseIf TestFunctionType == "Lock"
					libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True)
					;libs.LockDevice(Playerref, BellsHInventory, True)
					libs.LockDevice(Playerref, BellsHInventory)
				ElseIf TestFunctionType == "Swap"
					libs.SwapDevices(Playerref, BellsHInventory, libs.zad_DeviousPiercingsNipple, True, False)
				EndIf
				Alternate = False
			Else	
				;switch from horny to normal Nipple Bells
				If TestFunctionType == "Depreciated"
					libs.removeDevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, True, False, True)
					libs.equipdevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, False, True)
				ElseIf TestFunctionType == "Lock"
					libs.UnlockDevice(Playerref, BellsHInventory, destroyDevice = True)
					;libs.LockDevice(Playerref, BellsInventory, True)
					libs.LockDevice(Playerref, BellsInventory)
				ElseIf TestFunctionType == "Swap"
					libs.SwapDevices(Playerref, BellsInventory, libs.zad_DeviousPiercingsNipple, True, False)
				EndIf
				Alternate = True
			EndIf
			Utility.Wait(Delay)
			If libs.isWearingDeviceType(PlayerRef, libs.zad_DeviousPiercingsNipple)
				;no fail
			Else
				Failed = True
			EndIf
			If DelayCount > 15
				DelayCount = 1
				Delay = Delay - 0.1
				If Delay < 0
					Debug.MessageBox("SUCCESS! No Race Condition Occurred after 15 tries even at 0 delay")
					Debug.Trace("[Virgin] SUCCESS! No Race Condition Occurred after 15 tries even at 0 delay")
				EndIf
			EndIF
			Try += 1
			DelayCount += 1
		EndWhile
		Debug.MessageBox("TESTING Function: " + TestFunctionType + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay)
		Debug.Trace("[Virgin] TESTING Function: " + TestFunctionType + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay)
		Test += 1
		If Test == 3
			TestFunctionType = "Lock"
		ElseIf Test == 5
			TestFunctionType = "Depreciated"
		EndIf
	EndWhile
EndFunction

 

 

 

From attached Log 33

[11/13/2020 - 12:05:41AM] [Virgin] TESTING Function: Swap / Total Tries to failure: 37 / Delay reached: 0.300000
[11/13/2020 - 12:07:36AM] [Virgin] TESTING Function: Swap / Total Tries to failure: 39 / Delay reached: 0.300000
[11/13/2020 - 12:07:43AM] [Virgin] TESTING Function: Lock / Total Tries to failure: 2 / Delay reached: 0.500000
[11/13/2020 - 12:07:54AM] [Virgin] TESTING Function: Lock / Total Tries to failure: 3 / Delay reached: 0.500000
[11/13/2020 - 12:07:58AM] [Virgin] TESTING Function: Depreciated / Total Tries to failure: 5 / Delay reached: 0.500000
[11/13/2020 - 12:08:03AM] [Virgin] TESTING Function: Depreciated / Total Tries to failure: 2 / Delay reached: 0.500000
 

I've tried many other variations of this test, and this was the best I could get each of the 3 function types to perform. For example "forced" was no better. There are many variations I have not tested too. 

 

Maybe you can spot something wrong with the test itself. Try using it maybe. But unless I'm missing something, the results are not good. To summarize...

  • Swap works best, but will consistently fail without some delay from the calling mod. The Depreciated functions worked as well as that in beta 12
  • Lock and Depreciated both fail very easily, now, both significantly worse than beta 12
  • I have no delay with DD4 (using what is now depreciated of course), and it never fails, because mutex

 

Log33 - race condition, beta 13.log

Link to comment

I see!
No clue on how to help but it looks pretty cool, so looking forward to whatever solutions that may come. ?

 

I also noticed that the Transparent Restrictive Corset appears as the same as the White Ebonite Restrictive Corset in my game rather than being transparent like before. Ran bodyslide and such so not sure if there is something else that I have set up incorrectly.

Link to comment
8 hours ago, VirginMarie said:

@KimyRace Condition Test, with Beta 13

  • similar test, this time 6 Tests, 2 for Swap, 2 for Lock, and 2 for Depreciated, reducing delay until failure
  • code is below
  Hide contents
Spoiler

 

 



;.......... Test Equip/Remove Device Race Condition
Function VirginTestRaceCond()
	String TestFunctionType = "Swap"
	Int Test = 1
	While Test <= 6
		Int Try = 1
		Float Delay = 0.5
		Int DelayCount = 1
		Bool Alternate = False ;Alternating between the 2 devices
		Bool Failed = False
		While ! Failed
			If Alternate
				;switch from normal to horny Nipple Bells
				If TestFunctionType == "Depreciated"
					libs.removeDevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, True, False, True)
					libs.equipdevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, False, True)
				ElseIf TestFunctionType == "Lock"
					libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True)
					;libs.LockDevice(Playerref, BellsHInventory, True)
					libs.LockDevice(Playerref, BellsHInventory)
				ElseIf TestFunctionType == "Swap"
					libs.SwapDevices(Playerref, BellsHInventory, libs.zad_DeviousPiercingsNipple, True, False)
				EndIf
				Alternate = False
			Else	
				;switch from horny to normal Nipple Bells
				If TestFunctionType == "Depreciated"
					libs.removeDevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, True, False, True)
					libs.equipdevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, False, True)
				ElseIf TestFunctionType == "Lock"
					libs.UnlockDevice(Playerref, BellsHInventory, destroyDevice = True)
					;libs.LockDevice(Playerref, BellsInventory, True)
					libs.LockDevice(Playerref, BellsInventory)
				ElseIf TestFunctionType == "Swap"
					libs.SwapDevices(Playerref, BellsInventory, libs.zad_DeviousPiercingsNipple, True, False)
				EndIf
				Alternate = True
			EndIf
			Utility.Wait(Delay)
			If libs.isWearingDeviceType(PlayerRef, libs.zad_DeviousPiercingsNipple)
				;no fail
			Else
				Failed = True
			EndIf
			If DelayCount > 15
				DelayCount = 1
				Delay = Delay - 0.1
				If Delay < 0
					Debug.MessageBox("SUCCESS! No Race Condition Occurred after 15 tries even at 0 delay")
					Debug.Trace("[Virgin] SUCCESS! No Race Condition Occurred after 15 tries even at 0 delay")
				EndIf
			EndIF
			Try += 1
			DelayCount += 1
		EndWhile
		Debug.MessageBox("TESTING Function: " + TestFunctionType + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay)
		Debug.Trace("[Virgin] TESTING Function: " + TestFunctionType + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay)
		Test += 1
		If Test == 3
			TestFunctionType = "Lock"
		ElseIf Test == 5
			TestFunctionType = "Depreciated"
		EndIf
	EndWhile
EndFunction

 

 

 

From attached Log 33

[11/13/2020 - 12:05:41AM] [Virgin] TESTING Function: Swap / Total Tries to failure: 37 / Delay reached: 0.300000
[11/13/2020 - 12:07:36AM] [Virgin] TESTING Function: Swap / Total Tries to failure: 39 / Delay reached: 0.300000
[11/13/2020 - 12:07:43AM] [Virgin] TESTING Function: Lock / Total Tries to failure: 2 / Delay reached: 0.500000
[11/13/2020 - 12:07:54AM] [Virgin] TESTING Function: Lock / Total Tries to failure: 3 / Delay reached: 0.500000
[11/13/2020 - 12:07:58AM] [Virgin] TESTING Function: Depreciated / Total Tries to failure: 5 / Delay reached: 0.500000
[11/13/2020 - 12:08:03AM] [Virgin] TESTING Function: Depreciated / Total Tries to failure: 2 / Delay reached: 0.500000
 

I've tried many other variations of this test, and this was the best I could get each of the 3 function types to perform. For example "forced" was no better. There are many variations I have not tested too. 

 

Maybe you can spot something wrong with the test itself. Try using it maybe. But unless I'm missing something, the results are not good. To summarize...

  • Swap works best, but will consistently fail without some delay from the calling mod. The Depreciated functions worked as well as that in beta 12
  • Lock and Depreciated both fail very easily, now, both significantly worse than beta 12
  • I have no delay with DD4 (using what is now depreciated of course), and it never fails, because mutex

 

Log33 - race condition, beta 13.log 161.53 kB · 0 downloads

Yes, there is actually something wrong with your test itself.

 

Looking at the code, your test doesn't actually test for swap failure, but for whether or not it can detect the equipped rendered device after the swap within a given time. This result is irrelevant to what we actually want to test, because the delay after the final equip doesn't tell us anything about whether or not the function actually succeeded. It just tells us whether the operations of the final equip function have yet concluded, or not. Since DD uses non-latent OnEquipped()/OnUnequipped() events to actually perform the operation, checking for completion right after calling LockDevice() or even SwapDevice() is more or less guaranteed to fail your test, so these results are 100% to be expected.

 

What we do know thanks to your test is that the newly equipped device needs at least 0.3 or 0.5 seconds respectively to get actually equipped after calling LockDevice(). That's interesting knowledge, but as I said, not relevant to what we want to know. We want to know if the SWAP works, not how long the non-latent part of the operation minimally takes to complete.

 

The correct way to test it is using a sufficiently large delay AFTER the swap, never decrease it, and then check if the CORRECT rendered device is worn at the end of the operation (the one you swapped in), and not just its type (which could report false positives).

 

It's what I did to test it, btw. I wrote some code to perform 20 consecutive swaps with a short delay between the swaps (but not between UnlockDevice() and LockDevice()). The log did not show a single failure. I also tested SwapDevices() in the same way with a 100% success rate.

 

PS: Also testing EquipDevice() versus LockDevice() is irrelevant, because in DD5, EquipDevice() just maps to LockDevice() anyway. The additional parameters in EquipDevice() are ignored.

Link to comment

@Kimy  Semi-random question - Would you be willing to add in SLIF compatibility to DD and DCL in the future, if not this release?

 

These are the lines SLIF modifies in your scripts.

Spoiler

DD / zadLibs.psc

 

Original:

Function SetNodeHidden(Actor akActor, bool isFemale, string nodeName, bool value, string modkey = "DDi")
    if value
        XPMSELib.SetNodeScale(akActor, isFemale, nodeName, 0.01, modkey)
    else
        XPMSELib.SetNodeScale(akActor, isFemale, nodeName, 1.0, modkey)
    endif
EndFunction

 

 

Modified:

Function SetNodeHidden(Actor akActor, bool isFemale, string nodeName, bool value, string modkey = "DDi")
    if Game.GetModbyName("SexLab Inflation Framework.esp") != 255
        if value
            SLIF_Main.hideNode(akActor, "Devious Devices Integration", nodeName, 0.01, modkey)
        else
            SLIF_Main.showNode(akActor, "Devious Devices Integration", nodeName)
        endif
    else
        if value
            XPMSELib.SetNodeScale(akActor, isFemale, nodeName, 0.01, modkey)
        else
            XPMSELib.SetNodeScale(akActor, isFemale, nodeName, 1.0, modkey)
        endif
    endif
EndFunction

 

 

DCL / dcur_clocktickScript.psc

 

Original:

Function SetMorphValue(Actor akActor, float value, string MorphName = "PregnancyBelly")    
    If value != 0.0
        NiOverride.SetBodyMorph(akActor, MorphName, "DCL", value)
    Else        
        ; ok, don't ask me why clearning the morph isn't working, so we're just setting it to a minimal value and carry on...
        NiOverride.SetBodyMorph(akActor, MorphName, "DCL", 0.01)
    ;    NiOverride.ClearBodyMorph(akActor, MorphName, "DCL")
    EndIf    
    NiOverride.UpdateModelWeight(akActor)
EndFunction

 

 

Updated (it was still using clearbodymorph, figured your change needed to be forwarded):

Function SetMorphValue(Actor akActor, float value, string MorphName = "PregnancyBelly")    
    If Game.GetModbyName("SexLab Inflation Framework.esp") != 255
        If value != 0.0
            SLIF_Morph.morph(akActor, "Deviously Cursed Loot", MorphName, value, "DCL")
        Else
            SLIF_Morph.unregisterMorph(akActor, MorphName, "Deviously Cursed Loot")
        EndIf
    Else
        If value != 0.0
            NiOverride.SetBodyMorph(akActor, MorphName, "DCL", value)
        Else        
        ; ok, don't ask me why clearing the morph isn't working, so we're just setting it to a minimal value and carry on...
        NiOverride.SetBodyMorph(akActor, MorphName, "DCL", 0.01)
    ;    NiOverride.ClearBodyMorph(akActor, MorphName, "DCL")
        EndIf    
        NiOverride.UpdateModelWeight(akActor)
    EndIf
EndFunction

 

Link to comment

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

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use