OsmelMC Posted November 9, 2020 Posted November 9, 2020 15 minutes ago, Code Serpent said: You could just make additional armoraddons for Argonian and Khajiit texture sets and add those to the armor. This is how the game assigns textures to naked bodies. Look up "NakedHands" in the armoraddons tab of the Creation kit. That's even better because the hands on beasts have different meshes but required other set of skills.
Kharos Posted November 9, 2020 Posted November 9, 2020 On 11/7/2020 at 7:36 PM, Ryu Gabriev said: There's pretty heavy clipping though, when I do. In contrast with the exact same bodytype (Wench Body, btw), regular Armbinder had almost no clipping at all. I should also mention that the Ropebinder, which in practice is the same thing as an elbowbinder (changes the same areas, same pose, etc.) it DOES have a bodyslide conversion and looks fine. I had that too in my game (using CBBE version). Armbinder was looking good on all NPCs that I tried. Elbowbinder was working well on some, but had bad clipping with others. Often the upper arm muscles were clipping out of the elbowbinder. I especially noticed it with female redguards. Not sure if it is caused by racial body morphs or by weight.
Skullered Posted November 9, 2020 Posted November 9, 2020 2 hours ago, Code Serpent said: You could just make additional armoraddons for Argonian and Khajiit texture sets and add those to the armor. This is how the game assigns textures to naked bodies. Look up "NakedHands" in the armoraddons tab of the Creation kit. That's what I did in the file I uploaded, but ideally the game should be replacing those textures automatically, similar to how some vanilla bracers do (Falmer Gauntlets do this, and they don't have a unique armoraddon per race).
Kimy Posted November 9, 2020 Author Posted November 9, 2020 About the Elbowbinder: I am not qualified to create a Bodyslide version if that item, but if a volunteer would like to make one, I'd merge it! 1
zarantha Posted November 10, 2020 Posted November 10, 2020 I've got a partial bodyslide for the SE version, it's just the chest part not the sleeve. I just found out today how to pose in outfit studio. I think i'll play with this after I finish the basic SE conversion. Too bad the pose doesn't seem to save from the short test i did. This was just playing with the clavicle, upper arm, and forearm bones Spoiler Starting test pose: NPC L ForeArm ROT X -.31 ROT Y -.47 ROT Z 0.0 NPC L UpperArm ROT X .42 ROT Y .43 ROT Z -.77 NPC L UpperarmTwist1 ROT X .58 ROT Y -.08 ROT Z .11 NPC L Clavicle ROT X -.36 ROT Y 0.0 ROT Z -.73 OFF X -1.1 OFF Y 4.24 OFF Z 0.0 And if this is not news to anyone, sorry. I'm just so happy to have found a new toy 9 hours ago, Skullered said: -Fixed beast races having human hands with the "Strict Rope Armbinder" Thanks Skullered! Worked great for argonian/khajiit, not so much for the custom race, which uses the khajiit proxy keyword. I'll have to think about that since I like the DagiRaht mod, but that's not a DD issue. So confirming it fixed the issue as far as DD is concerned, and thank you again.
Code Serpent Posted November 10, 2020 Posted November 10, 2020 A small suggestion to add to the pile: Could you add a prompt to give the player the choice on whether or not to equip items onto npcs when trading? Sometimes I just want my companions to carry my metric ton of bondage gear without trying it on.
hungvipbcsok Posted November 10, 2020 Posted November 10, 2020 39 minutes ago, Code Serpent said: A small suggestion to add to the pile: Could you add a prompt to give the player the choice on whether or not to equip items onto npcs when trading? Sometimes I just want my companions to carry my metric ton of bondage gear without trying it on. If you don't mind using other mods then devious lore already have that function. Just select "friend, would you help me with something" and ask her/him to carry DD gears for you. 1
NIND (jimmyyu) Posted November 10, 2020 Posted November 10, 2020 17 hours ago, Kimy said: About the Elbowbinder: I am not qualified to create a Bodyslide version if that item, but if a volunteer would like to make one, I'd merge it! I am interested in doing this, but I have not updated my DD package in a while! in which version was it first included?
Psalam Posted November 10, 2020 Posted November 10, 2020 17 hours ago, Kimy said: About the Elbowbinder: I am not qualified to create a Bodyslide version if that item, but if a volunteer would like to make one, I'd merge it! I may know someone interested in doing this. He wants to know where to find the original assets that would need to be modified.
naaitsab Posted November 10, 2020 Posted November 10, 2020 @Kimy the modification I did to the panel gag also/still allows the plug to be removed (inflatable plug is added as a sperate mesh). As far as I can see now it's not removable. Perhaps you can look into that?
Kimy Posted November 10, 2020 Author Posted November 10, 2020 Here are the resources for the Elbowbinder. The CBBE and the UUNP versions look identical to me, but they'd probably need a separate Bodyslide version? If someone wants to tackle it, it would be awesome! FT_ArmbinderElbowUUNP.7z FT_ArmbinderElbowCBBE.7z 1
Code Serpent Posted November 10, 2020 Posted November 10, 2020 8 hours ago, hungvipbcsok said: If you don't mind using other mods then devious lore already have that function. Just select "friend, would you help me with something" and ask her/him to carry DD gears for you. I know, I made that mod. I just think it should be included in the framework as well. 3
UnEvenSteven Posted November 10, 2020 Posted November 10, 2020 @Kimy Surprised I didn't notice before but the Ebonite versions of the Hobble Straitjackets didn't have "Environment_Mapping" set in the Shader Flags. I know what happened, when I made these new straitjacket variants I cheated and created the leather versions first then simply changed texture and shader settings to create the ebonite versions. Better then creating the new variants twice in Outfit Studio. So I made sure "Environment_Mapping" was set in the Shader Flags for the Ebonite versions, it effects both the CBBE and UUNP versions. It's nothing major just visual, should look better though. These are just the BodySlide meshes found in the ShapeData folder, just let them overwrite the files in whatever final build/release candidate project you have for DD5. EboniteHobbleStraitjacketStuff.7z Another small coat of wax. 1
Kimy Posted November 10, 2020 Author Posted November 10, 2020 2 hours ago, Code Serpent said: I know, I made that mod. I just think it should be included in the framework as well. I will look into it. At this point I don't want to introduce new features requiring more intensive testing. So it might or might not have to wait until 5.1. 1
Code Serpent Posted November 10, 2020 Posted November 10, 2020 49 minutes ago, Kimy said: I will look into it. At this point I don't want to introduce new features requiring more intensive testing. So it might or might not have to wait until 5.1. Alright. Just so I'm clear, I'm thinking of a simple "Yes/No" message box prompt when devices are given to npcs through a trading menu. I'm not suggesting you add in the dialogue system I made in Devious Lore.
VirginMarie Posted November 10, 2020 Posted November 10, 2020 @Kimy Problem I'm trying to solve: Various Devices, randomly, are not actually being replaced when they are replaced by script Testing with DD5 Beta 12 It's most likely a race condition Specific Case: When a certain arousal level is reached, the Virgin Nipple Bell will be replaced with a Virgin Horny Nipple Bell. Vice-versa when arousal goes back down The code has its own mutex so as not to call DD functions in it's own race conditions. The code snippet... ;switch from normal to horny Nipple Bells libs.removeDevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, True, False, True) libs.equipdevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, False, True) ;switch from horny to normal Nipple Bells libs.removeDevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, True, False, True) libs.equipdevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, False, True) Past Scenario with same Case: In the past, when I was testing in a DD4 beta, I had the same change in behavior. The problem was a race condition, and solved by using "skipMutex" I know that the depreciated functions... EquipDevice & removeDevice are now passing to lockDevice & UnlockDevice, but not passing Mutex. Also the new functions are "Bool" and can be checked for success. I've written a test function. The Test runs 2 times using depreciated functions, then another 2 times, using the new functions. It applies a delay, tries 15 times, then lowers the delay, repeating, until breaking point or success without a delay. It also retries once, on a fail, if using the new functions. Here is the code for the test... Spoiler Spoiler ;.......... Test Equip/Remove Device Race Condition Function VirginTestRaceCond() Bool DepFunction = True Int Test = 1 While Test <= 4 Int Try = 1 Float Delay = 0.5 Int DelayCount = 1 Bool Alternate = False Bool Failed = False While ! Failed If Alternate ;switch from normal to horny Nipple Bells If DepFunction libs.removeDevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, True, False, True) ;Utility.Wait(0.1) ;this is here to see if it has impact. In tests its not been needed libs.equipdevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, False, True) Else If libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True) ;worked Else libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True) ;one retry Debug.Trace("[Virgin] UnLockDevice Retry") EndIf ;Utility.Wait(0.1) If libs.LockDevice(Playerref, BellsHInventory) ;worked Else libs.LockDevice(Playerref, BellsHInventory) ;one retry Debug.Trace("[Virgin] LockDevice Retry") EndIf EndIf Alternate = False Else ;switch from horny to normal Nipple Bells If DepFunction libs.removeDevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, True, False, True) ;Utility.Wait(0.1) libs.equipdevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, False, True) Else If libs.UnlockDevice(Playerref, BellsHInventory, destroyDevice = True) ;worked Else libs.UnlockDevice(Playerref, BellsHInventory, destroyDevice = True) ;one retry Debug.Trace("[Virgin] UnLockDevice Retry") EndIf ;Utility.Wait(0.1) If libs.LockDevice(Playerref, BellsInventory) ;worked Else libs.LockDevice(Playerref, BellsInventory) ;one retry Debug.Trace("[Virgin] LockDevice Retry") EndIf 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. (if DD5, one rety is in play)") Debug.Trace("[Virgin] SUCCESS! No Race Condition Occurred after 15 tries even at 0 delay. (if DD5, one rety is in play)") Return EndIf EndIF Try += 1 DelayCount += 1 EndWhile Debug.MessageBox("TESTING Depreciated Function: " + DepFunction + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay) Debug.Trace("[Virgin] TESTING Depreciated Function: " + DepFunction + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay) Test += 1 If Test == 3 DepFunction = False EndIf EndWhile EndFunction The test function was activated after waiting a good 20 seconds after game load. If I don't wait, the test is capable of hanging DD I've confirmed that block_generic keywords are present on each involved inventory device I made sure an arousal increase/decrease could not trigger and interfere with the test, by turning it off Results in the attached Log31. txt Summary of results from log: [11/10/2020 - 01:43:13PM] [Virgin] TESTING Depreciated Function: TRUE / Total Tries to failure: 45 / Delay reached: 0.300000 [11/10/2020 - 01:43:43PM] [Virgin] TESTING Depreciated Function: TRUE / Total Tries to failure: 33 / Delay reached: 0.300000 [11/10/2020 - 01:43:43PM] ============================================================ [11/10/2020 - 01:43:43PM] [Zad] (((ERROR))): LookupDeviceType received invalid keyword None [11/10/2020 - 01:43:43PM] ============================================================ [11/10/2020 - 01:44:08PM] [Virgin] TESTING Depreciated Function: False / Total Tries to failure: 25 / Delay reached: 0.400000 [11/10/2020 - 01:44:34PM] [Virgin] TESTING Depreciated Function: False / Total Tries to failure: 27 / Delay reached: 0.400000 I'm looking for advice on how I can solve this problem. I don't see an obvious path. Log31 - Equip Unequip race condition.log
Kimy Posted November 11, 2020 Author Posted November 11, 2020 I guess the safest way to swap devices using the same DD slot would be checking for UnlockDevice() returning true AND the old -rendered- device actually removed from the slot with !IsEquipped(). The actual removal is done by OnUnequip(), which can indeed complete a tad later than UnlockDevice(). I might look into a function to safely swap devices, but right now I'd suggest trying the above.
VirginMarie Posted November 11, 2020 Posted November 11, 2020 1 hour ago, Kimy said: I might look into a function to safely swap devices, but right now I'd suggest trying the above. That could be good. Most device manipulation in SLaV is Swapping. I would think its very common in other mods too. Maybe you should also "detect" swapping, so people's code as is would take that new safe path. Like, if same slot experiences a remove then equip, in less than X seconds, treat it as a swap. 1 hour ago, Kimy said: I guess the safest way to swap devices using the same DD slot would be checking for UnlockDevice() returning true AND the old -rendered- device actually removed from the slot with !IsEquipped(). The actual removal is done by OnUnequip(), which can indeed complete a tad later than UnlockDevice(). I would think you want to fix this for mods that are not being updated. A new Swap function alone wont help for backward compatibility. This is not a rare edge case. Its guaranteed to happen 1 out of 10, or likely worse as it did not take me much gameplay to notice it. I did not at first, find this with targeted testing. So you can expect it to be relatively widespread. I added IsEquipped to the test function. Log produced attached. Code follows. Comments in code showing lines changed. Spoiler Spoiler ;.......... Test Equip/Remove Device Race Condition Function VirginTestRaceCond() Bool DepFunction = True Int Test = 1 While Test <= 4 Int Try = 1 Float Delay = 0.5 Int DelayCount = 1 Bool Alternate = False Bool Failed = False While ! Failed If Alternate ;switch from normal to horny Nipple Bells If DepFunction libs.removeDevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, True, False, True) ;Utility.Wait(0.1) ;this is here to see if it has impact. In tests its not been needed libs.equipdevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, False, True) Else If libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True) && ! PlayerRef.IsEquipped(BellsRender) ; <-- Changed ;worked Else Utility.Wait(0.1) ; <-- Changed libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True) ;one retry Debug.Trace("[Virgin] UnLockDevice Retry") EndIf ;Utility.Wait(0.1) If libs.LockDevice(Playerref, BellsHInventory) && ! PlayerRef.IsEquipped(BellsHRender) ; <-- Changed ;worked Else Utility.Wait(0.1) ; <-- Changed libs.LockDevice(Playerref, BellsHInventory) ;one retry Debug.Trace("[Virgin] LockDevice Retry") EndIf EndIf Alternate = False Else ;switch from horny to normal Nipple Bells If DepFunction libs.removeDevice(Playerref, BellsHInventory, BellsHRender, libs.zad_DeviousPiercingsNipple, True, False, True) ;Utility.Wait(0.1) libs.equipdevice(Playerref, BellsInventory, BellsRender, libs.zad_DeviousPiercingsNipple, False, True) Else If libs.UnlockDevice(Playerref, BellsHInventory, destroyDevice = True) && ! PlayerRef.IsEquipped(BellsHRender) ; <-- Changed ;worked Else Utility.Wait(0.1) ; <-- Changed libs.UnlockDevice(Playerref, BellsHInventory, destroyDevice = True) ;one retry Debug.Trace("[Virgin] UnLockDevice Retry") EndIf ;Utility.Wait(0.1) If libs.LockDevice(Playerref, BellsInventory) && ! PlayerRef.IsEquipped(BellsRender) ; <-- Changed ;worked Else Utility.Wait(0.1) ; <-- Changed libs.LockDevice(Playerref, BellsInventory) ;one retry Debug.Trace("[Virgin] LockDevice Retry") EndIf 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. (if DD5, one rety is in play)") Debug.Trace("[Virgin] SUCCESS! No Race Condition Occurred after 15 tries even at 0 delay. (if DD5, one rety is in play)") Return EndIf EndIF Try += 1 DelayCount += 1 EndWhile Debug.MessageBox("TESTING Depreciated Function: " + DepFunction + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay) Debug.Trace("[Virgin] TESTING Depreciated Function: " + DepFunction + " / Total Tries to failure: " + Try + " / Delay reached: " + Delay) Test += 1 If Test == 3 DepFunction = False EndIf EndWhile EndFunction I don't know what it's doing, but somehow, when it reaches test 3 (that is when it starts using the new functions instead of the depreciated), it repeatedly gives a message box, and reports the -- [Zad] (((ERROR))): LookupDeviceType received invalid keyword None -- error in the log. I did not let it finish as its a message box for every try (or retry?). Don't know what I can do more at this point, or what my path forward is. Log32 - race condition, added IsEquipped.log
Kharos Posted November 11, 2020 Posted November 11, 2020 18 hours ago, VirginMarie said: added IsEquipped to the test function. Log produced attached. Code follows. It's not nice, but short term, you could try waiting a bit longer to catch cases with heavy script load: Bool isEquipped = true If (libs.UnlockDevice(Playerref, BellsInventory, destroyDevice = True)) isEquipped = PlayerRef.IsEquipped(BellsRender) Int waitCount = 0 While (isEquipped && waitCount < 20) ; or whatever number you are comfortable with instead of 20 Utility.Wait(0.1) isEquipped = PlayerRef.IsEquipped(BellsRender) waitCount = waitCount + 1 EndWhile EndIf If (isEquipped) ; failed to unequip (either UnlockDevice returned false, or Player.IsEquipped was true after trying 20 times) Else ; succeeded EndIf I have used similar ugly code in my FO4 mod when waiting for events doing something. [Edit] It's also very much not nice from an API POV that UnlockDevice returns true but calling LockDevice directly afterwards will then fail. This would catch me off-guard as a developer using the API. @Kimy would it be possible to detect the problem (old rendered device still equipped) in LockDevice and take corrective action there? Or is that not possible because the two cases (device not equipped but old rendered devices still equipped, device actually equipped) will look the same? 1
Kimy Posted November 11, 2020 Author Posted November 11, 2020 I will look into it. The problem is that waiting for completion in LockDevice() before returning will needlessly add delay for the 95% of all device operations that are NOT swaps and therefore have no reason to wait until OnEquipped() is finished. It will require a bit of thought. Btw. your above code sample is pretty much how I planned the safe-swap function anyway.
VirginMarie Posted November 11, 2020 Posted November 11, 2020 42 minutes ago, Kharos said: It's also very much not nice from an API POV that UnlockDevice returns true but calling LockDevice directly afterwards will then fail. This would catch me off-guard as a developer using the API. Yes I know I can do that, but I've already tried a single retry (updated version of the test above), which has DD spitting out that error message box, so I'm going to wait to see if Kimy has a suggestion or solution. Quote @Kimy would it be possible to detect the problem (old rendered device still equipped) in LockDevice and take corrective action there? Or is that not possible because the two cases (device not equipped but old rendered devices still equipped, device actually equipped) will look the same? The problem is broader I believe. The root problem is a race condition and could cause other symptoms beyond swap. Maybe its why DD has that long standing issue of broken devices. Solution I suspect is Mutex. "old rendered device still equipped" is the symptom of the problem, and likely so is the ages old broken device problem. Swap is more than 50% of cases in my mod, hard to believe it could be only 5% in something like DCL.
Kimy Posted November 11, 2020 Author Posted November 11, 2020 It's way less than 5% in DCL. The only feature that does it lots is the prison, and since it's a well known fact that chaining unlock/lock calls for the same device slot is problematic, I designed my features to do it safely. Usually I perform the unequip in one dialogue topic and the equip in the next, which more or less guarantees the old device to be removed before the new one gets put on. The few cases I cannot handle this way, I have always used generous Utility.Wait() delays for. It worked quite ok for the past years, really. *shrug* The normal usecase for DD is locking on a device for the duration of a quest or for the player to escape it on their own, which covers almost everything of what DCL does. Your mod is just full of edge-cases, haha! ?
Kharos Posted November 11, 2020 Posted November 11, 2020 51 minutes ago, Kimy said: I will look into it. The problem is that waiting for completion in LockDevice() before returning will needlessly add delay for the 95% of all device operations that are NOT swaps and therefore have no reason to wait until OnEquipped() is finished. It will require a bit of thought. Btw. your above code sample is pretty much how I planned the safe-swap function anyway. 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 LockDevice 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). [Edit] Fixed confusing use of unlock/lock, sorry!
VirginMarie Posted November 11, 2020 Posted November 11, 2020 34 minutes ago, Kimy said: The normal usecase for DD is locking on a device for the duration of a quest or for the player to escape it on their own, which covers almost everything of what DCL does. Your mod is just full of edge-cases, haha! ? K well, I can tell you that with DD4 (all DD4 versions), swapping was 100% stable in SLaV. 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. Edge case? I think you underestimate how much these "edge cases" in SLAV, are actually normal, well beyond just SLaV. Testing is all about edge cases, its what makes a quality software product. If you don't test for and fix your edge 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 "edge 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.
Kimy Posted November 11, 2020 Author Posted November 11, 2020 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. 2
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now