Jump to content

Devious Devices Framework Development/Beta


Recommended Posts

Technical Question: Can I reuse the rendered device ARMO form for multiple inventory devices? I'm planning on adding a "Cursed Item" system (that should be separate and compatible with Cursed Loot) to devious lore where there player can find enchanted devices. But I'll need to make copies of the devices with several different enchantments and effect magnitudes, and it'd be a massive pain to have to make multiple and identical rendered device forms for each enchanted device.

Link to comment
On 4/12/2023 at 5:16 PM, Kimy said:

localization

 

Megnéztem az ESM lokalizálás dolgot...  Nekem az ESM használatával dolgozó honosító programmal nem készít "strings" fájlokat. Érdekes, hogy vannak.

(Egyszerűen csak átcsomagolja, mint bármelyik másikat.)

 

 

I checked the ESM localization thing... For me, the localization program working using ESM does not create "strings" files. It's interesting that there are.

Link to comment
9 hours ago, Code Serpent said:

Technical Question: Can I reuse the rendered device ARMO form for multiple inventory devices? I'm planning on adding a "Cursed Item" system (that should be separate and compatible with Cursed Loot) to devious lore where there player can find enchanted devices. But I'll need to make copies of the devices with several different enchantments and effect magnitudes, and it'd be a massive pain to have to make multiple and identical rendered device forms for each enchanted device.

The rendered item is the one that is actually worn by the player. So that should contain the "device keywords" for a "wornhaskeyword" condition and has most of the enchantments on it. DD seems to have a mix of attached enchantments to the inventory item and the rendered one.

 

So you will need to take both in consideration depending on the type of enchantment you want to implement.

Link to comment
13 hours ago, naaitsab said:

There isn't any (reliable) way to get the object script from the player as far as I know. Like objectreference device = (libs.getwornbykeyword(belt)) as objectreference

 

What you can do as it's probably for your story driven mod is to make a custom version of the device script. referencing the original script. Like for example the zadBeltScript. Then reference to your quest script, using a conditional value. So on your quest mod you can set the value to say 10.0 and the device will instead of looking to the internal script property value look to that value. Or you can use a global but I find those a bit messy personally. I think the most important one is to customize the device script. 

 

Thanks for the input. The method you described is what I used for my mod already, yeah: I just made devices with a custom script that allows unlock if specific quest stages are done. But that method has always bothered me because it's an ugly workaround, and it means I have to duplicate every device I want to use. I was hoping a scripting wizard in here might know of a way, but I'll make do if there isn't.

 

On another note, I came up with an mechanic I think is interesting that might be fun to put in DD itself (spoiler tagged since it'll be in part 2 of Trappings):

Spoiler

I figured out a fairly clean way to make equipping e.g. hoods actually mute/morph the sounds the player hears, simulating in a simplified way the muffling of sound when you would wear something like earplugs, headphones or, you know, a hood over your head. It works through the SoundCategory script's SetVolume and SetFrequency functions. You'll note the wiki page note about persisting through game sessions / reloads, which is undesirable, but I think this can be worked around by having a monitor script on the player that resets the modifiers when it detects a game load. When a muffling device is equipped, it calls the monitor script to change the volume/frequency, and on unequip calls the monitor script to reset the modifiers. Proof of concept video:

 

This would essentially be a kind of hearing counterpart to the blindfold mechanic. You can do fun stuff like muffle in-game sounds (AudioCategorySFX/AudioCategoryVOC) while keeping Sexlab sounds (SexLabAudioSFX/SexLabAudioVoice) at the same volume (or slightly louder/distorted). You could also think of tying it to the gag mechanic, where being mute complicates communication further.

 

Or you could just make everyone have high-pitched inhaled-some-helium voices, I suppose :classic_laugh:

If there's interest I can post the scripts or make a little proof of concept mod for it.

Link to comment
24 minutes ago, Frayed said:

 

Thanks for the input. The method you described is what I used for my mod already, yeah: I just made devices with a custom script that allows unlock if specific quest stages are done. But that method has always bothered me because it's an ugly workaround, and it means I have to duplicate every device I want to use. I was hoping a scripting wizard in here might know of a way, but I'll make do if there isn't.

 

On another note, I came up with an mechanic I think is interesting that might be fun to put in DD itself (spoiler tagged since it'll be in part 2 of Trappings):

  Reveal hidden contents

I figured out a fairly clean way to make equipping e.g. hoods actually mute/morph the sounds the player hears, simulating in a simplified way the muffling of sound when you would wear something like earplugs, headphones or, you know, a hood over your head. It works through the SoundCategory script's SetVolume and SetFrequency functions. You'll note the wiki page note about persisting through game sessions / reloads, which is undesirable, but I think this can be worked around by having a monitor script on the player that resets the modifiers when it detects a game load. When a muffling device is equipped, it calls the monitor script to change the volume/frequency, and on unequip calls the monitor script to reset the modifiers. Proof of concept video:

 

This would essentially be a kind of hearing counterpart to the blindfold mechanic. You can do fun stuff like muffle in-game sounds (AudioCategorySFX/AudioCategoryVOC) while keeping Sexlab sounds (SexLabAudioSFX/SexLabAudioVoice) at the same volume (or slightly louder/distorted). You could also think of tying it to the gag mechanic, where being mute complicates communication further.

 

Or you could just make everyone have high-pitched inhaled-some-helium voices, I suppose :classic_laugh:

If there's interest I can post the scripts or make a little proof of concept mod for it.

What I can remember from online discussions before is that the player's container (aka inventory) is handled in such a way that the objectreferences have issues. Whilst referencing the items itself would not be terribly difficult using SKSE but the attached scripts and even more it's properties. that's another story :P Skyrim itself is brittle enough as it is so for reliably sake I would suggest sticking to the method I described and you are already using. But I also second the question if anyone else has a solution that works without all kinds of loops or extra frameworks.

 

 

I quite like the idea of the hood, if it just mutes or muffles (MCM slider?) all sound and music it's not overly distracting and does just enough to make it not annoying. Unlike earlier idea's that added some weird randomly playing sounds. Save consistency and possible bloating would be something to look out for. But that could be handled with a magic effect linked to the hood.

Link to comment
On 4/17/2023 at 9:37 PM, Frayed said:

I've got a question I've long been trying to figure out: how do I get a reference to the specific script running on a devious device? Say the player has an armbinder equipped with a 0% escape chance, and I want to increase the escape chance to 10% if they interact with some object in the world. To do this I need a reference not just to a zadequipscript, but to that specific zadequipscript. What is the best way to get it?

 

I've tried a couple of ways already: adding the _Inventory device as a zadequipscript property, casting the ObjectReference of a _Inventory device into a zadequipscript, and a few more variations, but unless I am mistaken, none of them seem to work as I think they should: I can get a zadequipscript and change its escape chance, but for the player the chance seems to remain at 0%. There is a function GetWornRenderedDeviceByKeyword in the zadlibs with a comment "; This is a waaaaay faster version of getting the script instance of a given slot.", but it returns an Armor, not a zadequipscript, and I can't cast it to a zadequipscript either. I think on a fundamental level I just don't quite understand how Skyrim handles instances of items in inventories. Would sure be useful to know, though.

It is important to realize what is difference between the objectreference and other forms, like armor or weapon, etc... Basically, Armor is like template. When you use the template to create ingame object, the created object will be stored to objectreference. This means you canever get object reference from armor itself. There is allways single Armor, but many object references created by it.  Basically, most of the things/items you see in the game are object references (or specifically, object, where object reference, well, reference them). So if you want to get actually object reference, you might do following things

  • Using quest: You can change alias conditions so it search closes object references and fill them in aliases. Question is if this will work for items which are in container (like player inventory)
  • You can use other mods which adds such functionality. Again, didn't test it and its possible that it will not work if objects 3D is not loaded. Example is powerofthree's Papyrus Extender or SkyPal
  • Most complicated way, but only one I know is somehow working is that you update the script of the object reference. This i what I did in unforgiving devices. You will create new container, and update script in such way that if event OnContainerIsChanged is called and the target container is our special container, it will return itself to some intermediate variable on other script. Then you can create function which just moves the armor from player to the special container, and back. After some time, it will return value which was used by event on device.

But, it is important to note that even if you get the object reference of device, changing the values will not do what you thing it will. Inventory devices in DD are implemented in such way that they are constantly being deleted and created. So if you change the escape chance, your change will last only untill player try to interact with device. If player for example try to drop the device on ground, the framework just deletes the device and locks player in new one.

Link to comment
8 hours ago, ihatemykite said:

It is important to realize what is difference between the objectreference and other forms, like armor or weapon, etc... Basically, Armor is like template. When you use the template to create ingame object, the created object will be stored to objectreference. This means you canever get object reference from armor itself. There is allways single Armor, but many object references created by it.  Basically, most of the things/items you see in the game are object references (or specifically, object, where object reference, well, reference them). So if you want to get actually object reference, you might do following things

  • Using quest: You can change alias conditions so it search closes object references and fill them in aliases. Question is if this will work for items which are in container (like player inventory)
  • You can use other mods which adds such functionality. Again, didn't test it and its possible that it will not work if objects 3D is not loaded. Example is powerofthree's Papyrus Extender or SkyPal
  • Most complicated way, but only one I know is somehow working is that you update the script of the object reference. This i what I did in unforgiving devices. You will create new container, and update script in such way that if event OnContainerIsChanged is called and the target container is our special container, it will return itself to some intermediate variable on other script. Then you can create function which just moves the armor from player to the special container, and back. After some time, it will return value which was used by event on device.

But, it is important to note that even if you get the object reference of device, changing the values will not do what you thing it will. Inventory devices in DD are implemented in such way that they are constantly being deleted and created. So if you change the escape chance, your change will last only untill player try to interact with device. If player for example try to drop the device on ground, the framework just deletes the device and locks player in new one.

 

20 hours ago, naaitsab said:

What I can remember from online discussions before is that the player's container (aka inventory) is handled in such a way that the objectreferences have issues. Whilst referencing the items itself would not be terribly difficult using SKSE but the attached scripts and even more it's properties. that's another story :P Skyrim itself is brittle enough as it is so for reliably sake I would suggest sticking to the method I described and you are already using. But I also second the question if anyone else has a solution that works without all kinds of loops or extra frameworks.

 

I quite like the idea of the hood, if it just mutes or muffles (MCM slider?) all sound and music it's not overly distracting and does just enough to make it not annoying. Unlike earlier idea's that added some weird randomly playing sounds. Save consistency and possible bloating would be something to look out for. But that could be handled with a magic effect linked to the hood.

 

Thank you both, that does clear things up. I'll have to do it another way then especially considering that last bit. I can probably do something similar to what I did before. I'll have to duplicate some devices, but I suppose it also gives me some freedom for more custom behaviour.

 

For the hoods: making the muffle amount an MCM slider should be very much doable. Never did that before, but I can peek and copy what the blindfold code does. I don't think there's any inherent risk of save bloating since there's only two scripts involved. I'll just post what I have now for clarity. One on the device itself:

Spoiler
Scriptname FrayEarplugScript extends ObjectReference
{On equip of an item with this script, calls the FrayEarplugsMonitorScript to change the volume and frequency of sounds within its Dampen and Louden categories.
On unequip, resets the sound categories back to their previous values.}

Actor Property PlayerRef Auto

FrayEarplugsMonitorScript Property MonitorScriptOnPlayerRefAlias Auto
{Reference to the monitor script attached to the player alias in the Earplugs Monitor quest.}
  
float Property dampenFrequencyFactor = 1.0 Auto 
{Factor to modify the frequencies of "dampen" SoundCategories}
float Property dampenVolumeFactor = 1.0 Auto
{Factor to modify the volumes of "dampen" SoundCategories}
float Property loudenFrequencyFactor = 1.0 Auto
{Factor to modify the frequencies of "louden" SoundCategories}
float Property loudenVolumeFactor = 1.0 Auto
{Factor to modify the volumes of "louden" SoundCategories}
  
Sound Property FrayEQ2NeutralNoiseLPSound Auto
{The looping sound that acts as "White noise".}
  
Int LoopSoundInstance
  
Function OnEquipped(actor akActor)
    if akActor == PlayerRef
        ;Debug.MessageBox("Modifying sound category frequencies and volumes to simulate earplugs")
        MonitorScriptOnPlayerRefAlias.SetSoundCategoryModifiersForEarplugEquip( \
            frequencyDampen = dampenFrequencyFactor,            \
            volumeDampen        = dampenVolumeFactor,               \
            frequencyLouden = loudenFrequencyFactor,            \
            volumeLouden        = loudenVolumeFactor)
        LoopSoundInstance = FrayEQ2NeutralNoiseLPSound.Play(PlayerRef)
    Else
        ; Nothing for now: no functionality atm for equipping earplugs on NPCs.
    EndIf
EndFunction
  
Function OnUnequipped(actor akActor)
    If akActor == PlayerRef
        ;Debug.MessageBox("Resetting sound category modifications back to normal")
        MonitorScriptOnPlayerRefAlias.ResetSoundCategoryModifiersForEarplugUnequip()
        Sound.StopInstance(LoopSoundInstance)
    Else
        ; Nothing for now: no functionality atm for equipping earplugs on NPCs.
    EndIf
EndFunction

and one on the monitor script, which is just attached to a player alias on a start game enabled hidden quest:

Spoiler
Scriptname FrayEarplugsMonitorScript extends ReferenceAlias
{The earplug mechanic works by manipulating frequency and volume of SoundCategories, but these changes persist through game loads.
 This is undesired functionality for earplugs: the changes should only be active while the earplugs are worn.
 This script monitors for game loads, and if no earplugs are worn on the loaded save, resets the SoundCategories.}

Actor Property PlayerRef Auto
Keyword Property FrayEarplugs Auto
SoundCategory[] Property CategoriesToDampen Auto
SoundCategory[] Property CategoriesToLouden Auto

Event OnPlayerLoadGame()
    If !PlayerRef.WornHasKeyword(FrayEarplugs)
        ResetSoundCategoryModifiersForEarplugUnequip()
    EndIf
EndEvent
  
Function SetSoundCategoryModifiersForEarplugEquip(float frequencyDampen = 1.0, float volumeDampen = 1.0, float frequencyLouden = 1.0, float volumeLouden = 1.0)
        ;Debug.MessageBox(self + ": Modifying sound categories" + frequencyDampen + " " + volumeDampen + " " + frequencyLouden + " "+ volumeLouden)        
  
        ; Set modifiers for dampened sounds
        int i = CategoriesToDampen.Length
        While i > 0
            i -= 1
            CategoriesToDampen.SetFrequency(frequencyDampen) 
 
            CategoriesToDampen.SetVolume(volumeDampen) 
 
            ;Debug.MessageBox("Set sound category" + CategoriesToDampen + " to frequency " + frequencyDampen + " and volume " + volumeDampen)    
 
        EndWhile 
   
        ; Set modifiers for loudened sounds 
 
        i = CategoriesToLouden.Length 
 
        While i > 0 
 
            i -= 1 
 
            CategoriesToLouden.SetFrequency(frequencyLouden) 
 
            CategoriesToLouden.SetVolume(volumeLouden) 
 
            ;Debug.MessageBox("Set sound catergory" + CategoriesToLouden + " to frequency " + frequencyLouden + " and volume " + volumeLouden)    
 
        EndWhile 
 
EndFunction 
   
Function ResetSoundCategoryModifiersForEarplugUnequip() 
 
    ;Debug.MessageBox(self + ": Resetting sound category modifications back to normal") 
 
    SetSoundCategoryModifiersForEarplugEquip(1.0, 1.0, 1.0, 1.0) 
 
EndFunction 

(They're called earplug script for the moment since that's what I originally had in mind, but naming and such can always change.)

Edited by Frayed
Link to comment
33 minutes ago, Frayed said:

 

 

Thank you both, that does clear things up. I'll have to do it another way then especially considering that last bit. I can probably do something similar to what I did before. I'll have to duplicate some devices, but I suppose it also gives me some freedom for more custom behaviour.

 

For the hoods: making the muffle amount an MCM slider should be very much doable. Never did that before, but I can peek and copy what the blindfold code does. I don't think there's any inherent risk of save bloating since there's only two scripts involved. I'll just post what I have now for clarity. One on the device itself:

  Reveal hidden contents
Scriptname FrayEarplugScript extends ObjectReference
{On equip of an item with this script, calls the FrayEarplugsMonitorScript to change the volume and frequency of sounds within its Dampen and Louden categories.
On unequip, resets the sound categories back to their previous values.}

Actor Property PlayerRef Auto

FrayEarplugsMonitorScript Property MonitorScriptOnPlayerRefAlias Auto
{Reference to the monitor script attached to the player alias in the Earplugs Monitor quest.}
  
float Property dampenFrequencyFactor = 1.0 Auto 
{Factor to modify the frequencies of "dampen" SoundCategories}
float Property dampenVolumeFactor = 1.0 Auto
{Factor to modify the volumes of "dampen" SoundCategories}
float Property loudenFrequencyFactor = 1.0 Auto
{Factor to modify the frequencies of "louden" SoundCategories}
float Property loudenVolumeFactor = 1.0 Auto
{Factor to modify the volumes of "louden" SoundCategories}
  
Sound Property FrayEQ2NeutralNoiseLPSound Auto
{The looping sound that acts as "White noise".}
  
Int LoopSoundInstance
  
Function OnEquipped(actor akActor)
    if akActor == PlayerRef
        ;Debug.MessageBox("Modifying sound category frequencies and volumes to simulate earplugs")
        MonitorScriptOnPlayerRefAlias.SetSoundCategoryModifiersForEarplugEquip( \
            frequencyDampen = dampenFrequencyFactor,            \
            volumeDampen        = dampenVolumeFactor,               \
            frequencyLouden = loudenFrequencyFactor,            \
            volumeLouden        = loudenVolumeFactor)
        LoopSoundInstance = FrayEQ2NeutralNoiseLPSound.Play(PlayerRef)
    Else
        ; Nothing for now: no functionality atm for equipping earplugs on NPCs.
    EndIf
EndFunction
  
Function OnUnequipped(actor akActor)
    If akActor == PlayerRef
        ;Debug.MessageBox("Resetting sound category modifications back to normal")
        MonitorScriptOnPlayerRefAlias.ResetSoundCategoryModifiersForEarplugUnequip()
        Sound.StopInstance(LoopSoundInstance)
    Else
        ; Nothing for now: no functionality atm for equipping earplugs on NPCs.
    EndIf
EndFunction

and one on the monitor script, which is just attached to a player alias on a start game enabled hidden quest:

  Reveal hidden contents
Scriptname FrayEarplugsMonitorScript extends ReferenceAlias
{The earplug mechanic works by manipulating frequency and volume of SoundCategories, but these changes persist through game loads.
 This is undesired functionality for earplugs: the changes should only be active while the earplugs are worn.
 This script monitors for game loads, and if no earplugs are worn on the loaded save, resets the SoundCategories.}

Actor Property PlayerRef Auto
Keyword Property FrayEarplugs Auto
SoundCategory[] Property CategoriesToDampen Auto
SoundCategory[] Property CategoriesToLouden Auto

Event OnPlayerLoadGame()
    If !PlayerRef.WornHasKeyword(FrayEarplugs)
        ResetSoundCategoryModifiersForEarplugUnequip()
    EndIf
EndEvent
  
Function SetSoundCategoryModifiersForEarplugEquip(float frequencyDampen = 1.0, float volumeDampen = 1.0, float frequencyLouden = 1.0, float volumeLouden = 1.0)
        ;Debug.MessageBox(self + ": Modifying sound categories" + frequencyDampen + " " + volumeDampen + " " + frequencyLouden + " "+ volumeLouden)        
  
        ; Set modifiers for dampened sounds
        int i = CategoriesToDampen.Length
        While i > 0
            i -= 1
            CategoriesToDampen.SetFrequency(frequencyDampen) 
 
            CategoriesToDampen.SetVolume(volumeDampen) 
 
            ;Debug.MessageBox("Set sound category" + CategoriesToDampen + " to frequency " + frequencyDampen + " and volume " + volumeDampen)    
 
        EndWhile 
   
        ; Set modifiers for loudened sounds 
 
        i = CategoriesToLouden.Length 
 
        While i > 0 
 
            i -= 1 
 
            CategoriesToLouden.SetFrequency(frequencyLouden) 
 
            CategoriesToLouden.SetVolume(volumeLouden) 
 
            ;Debug.MessageBox("Set sound catergory" + CategoriesToLouden + " to frequency " + frequencyLouden + " and volume " + volumeLouden)    
 
        EndWhile 
 
EndFunction 
   
Function ResetSoundCategoryModifiersForEarplugUnequip() 
 
    ;Debug.MessageBox(self + ": Resetting sound category modifications back to normal") 
 
    SetSoundCategoryModifiersForEarplugEquip(1.0, 1.0, 1.0, 1.0) 
 
EndFunction 

(They're called earplug script for the moment since that's what I originally had in mind, but naming and such can always change.)

If it works on LE and SE and can be set/disabled (dampen 0% is off approach?) by the user I think it would make a fine addition to the framework.

 

 

A while ago there where also some things posted that reduced the view to nearby only while wearing a blindfold. Not sure what become of that? 

Link to comment
On 3/20/2023 at 11:16 PM, kaxat said:

 

I understand the skepticism. I shared it. In the linked thread my first couple posts were helping Leakim ease his SMP load a little bit. I suspected the frame rate would gradually rise. I was wrong.

I have experienced SMP overload in the past. With 50-100 SMP clothes in the area my FPS would drop to around 40. As the NPCs would leave it would gradually return to 60. This issue has different symptoms. I suddenly go from 60FPS to less than 1FPS. It is instantaneous. And the instant I unequipped those boots I jumped back to 60 FPS. I did try an smp reset with the boots still on. That did nothing. As luck would have it I had this issue occur with only one SMP clothing item in the area (those boots) + SMP physics on the player. And again <1 FPS until I unequipped those boots. Suddenly 60 FPS.

 

If you are interested in replicating this issue I want to note a few details that might be important:

  • We are both using the latest version of FSMP. Personally I enabled the AVX512 extensions but not CUDA.
  • The issue does not usually happen instantly when the boots are equipped. It can take a minute or two after the boots are equipped. When it does happen you will know. The game becomes unplayable.
  • We are both using 3BA versions of the models and the 3BA body. But it does not matter whether the actor is in CBPC mode.
  • Leakim switched to the old .xml file a while ago and the issue went away.

If you need me to do more testing just ask. I will test the prisoner chains. It is possible those cause this too.

 

This is probably more of an SMP bug than anything else. A tweak to your mod might prevent FSMP from experiencing the bug. But as I understand it FSMP limits its CPU time to only 30% of the frame render time. That percent can be altered in its config. I do not believe it should cause such a drastic plummet in FPS when it is working properly.

I experienced your issue yesterday. I'd actually been having this issue for a while but was unable to pinpoint it until yesterday with @Corsec's help. @zarantha for the meantime, can you provide the corresponding DD 5.2-beta10 RC1 xml file for Iron Chain Harness (Ankles) in your troubleshooting post?

 

For clarification, I'm using DD SE 5.2 with the latest patches available on the troubleshooting post. FSMP 1.50.8-rc1, AVX2, no CUDA. Issue appears inconsistently, encountered via Corsec's SPID mod distribution of items to NPCs.

Edited by Gyra
Link to comment
6 hours ago, Gyra said:

I experienced your issue yesterday. I'd actually been having this issue for a while but was unable to pinpoint it until yesterday with @Corsec's help. @zarantha for the meantime, can you provide the corresponding DD 5.2-beta10 RC1 xml file for Iron Chain Harness (Ankles) in your troubleshooting post?

 

For clarification, I'm using DD SE 5.2 with the latest patches available on the troubleshooting post. FSMP 1.50.8-rc1, AVX2, no CUDA. Issue appears inconsistently, encountered via Corsec's SPID mod distribution of items to NPCs.

 

I still don't see how that one is a problem when ankle chains aren't. i basically copy/pasted the ankle chains stuff into that xml.

I've updated the post with the xml, even if i don't see the point. It's under the 5.2 spoiler. It will be use at your own risk.

 

One question tho - I use AVX because I've got an intel chip. Are you AMD or Intel, and have you tried AVX1, no CUDA?

I also don't use that SPID. Do you see an issue if the harness ankle chains aren't distributed that way?

 

Also, FSMP updated again to fix a random CTD. You might want to grab it.

  • Version 1.50.9-rc1

    • (Released in test version) fix: fix random CTD introduced in 1.50.8-rc1
Edited by zarantha
Link to comment
2 hours ago, zarantha said:

I still don't see how that one is a problem when ankle chains aren't. i basically copy/pasted the ankle chains stuff into that xml.

I've updated the post with the xml, even if i don't see the point. It's under the 5.2 spoiler. It will be use at your own risk.

 

One question tho - I use AVX because I've got an intel chip. Are you AMD or Intel, and have you tried AVX1, no CUDA?

I also don't use that SPID. Do you see an issue if the harness ankle chains aren't distributed that way?

 

Also, FSMP updated again to fix a random CTD. You might want to grab it.

I've grabbed the newest FSMP version today, but it shouldn't be relevant to this issue based on its release notes. Anyway, I really can't say much else than what leakim found in that post of theirs

 

SPID is likely not the cause of the issue given leakim's findings. 

 

I can certainly hold off on switching the .xml. However, given the arbitrary circumstances in which this bug appears in my game, I don't anticipate being able to report back any time soon. I'm also straight-up assuming changing from AVX2 to AVX/AVX1 won't make a difference. Using AMD. Like I said, issue is inconsistent on my setup. I've got NPCs affected by Corsec's SPID that wear these ankle chains with no issues at all. Like with leakim's findings, and as reflected in my game, we've identified a potential and specific cause outside Skyrim, but not specifically why it happens inside Skyrim. But if the xml really is the culprit, it'd be better to have a bandaid solution while y'all work to link them chains again.

Edited by Gyra
Link to comment
  • 2 weeks later...

Prior to moving to DD to DAR based setup courtesy of @Roggvir, I've tried to run DD on a pure Nemesis based setup, which I hot-swapped from the working FNIS one - and achieved a reasonable amount of success.

 

I've created a new folder for Nemesis output in MO2, deactivated FNIS, generated everything, and ran into three problems:
- arms popping out of devices when in combat and sprinting
- npcs playing regular turning animations with flailing arms, instead of the needed ones when being locked into devices.


Turning off Nemesis and turning FNIS with its output back on makes this go away, so this is the Nemesis-DD exclusive behaviour. 

 

After snooping around logs, I've found that nemesis doesn't like the following:

WARNING(1003): Alternate animation file doesn't exist. Current alternate animation file will not work | Mod: DD | Animation File: abc5_npc_turnleft90.hkx
WARNING(1003): Alternate animation file doesn't exist. Current alternate animation file will not work | Mod: DD2 | Animation File: hbc0_bow_sprint.hkx
WARNING(1003): Alternate animation file doesn't exist. Current alternate animation file will not work | Mod: DD | Animation File: abc0_dw_sprintforwardsword.hkx


... etc, there's a lot of those - mostly sprint and npc turn-related.

 

So, the first problem I was able to fix using the idea I've found somewhere here, so big props to @zarantha who recommended it, iirc. Go to the Nemesis github, download the ZIP of the main branch. From that zip, grab the /test environment/behavior templates/ and /test environment/alternate animation/ folders, overwrite your installed Nemesis with them (do remember to create a backup first, naturally). and recreate behaviours. Those are a bit newer than what the Nexus install comes with, and that will fix the player hands popping thing - well, at least it did for me.

 

Wasn't able to fix bound combat, the implementation is a little proprietary, so poor Nemesis is struggling with it - you'd probably have to somehow patch and recompile zadBoundCombatScript, i'd wager, I lack the necessary programming chops to do that. 

 

The NPC turn animations, I've ticked the Nemesis patch "turn animations don't affect upper body" and created a ESP for myself that turned off the idle turning animations on NPCs. One of those things helped, so now it behaves almost the same as my FNIS install did.

 

I've attached a homemade patch with the templates from Nemesis Github, and the ESP I made, let this overwrite your Nemesis install, re-generate the behaviours, and test for yourself.
 
Gettin' all the goodies from TDM, like procedural leaning, and the rest of stuff from Nemesis based mods doesn't feel like a bad trade off. However, this is still very 2021 - in 2023, the alternate animations should be done with DAR/OAR anyways, and bound combat works like a charm there. Can't recommend it enough: 

Nemesis compatibility patch.7z

Link to comment
On 3/24/2023 at 5:14 PM, naaitsab said:

Yes, it's "DeviceActorOrgasm"

 

You can get the "SendModEvent" from the main script (zadLibs.psc) to see what events are used.

Trying to implement this in my sgo4 fork, but im having issues. Unsure how modevents work and how to hook into them. here is a code snippet of what i currently have

 

Event OnInit()

	;; handle sexlab events.

	self.UnregisterForModEvent("SexLabOrgasm")
	self.RegisterForModEvent("SexLabOrgasm","OnModEvent_SexLabOrgasm")
	
	;; handle DD events.

	self.UnregisterForModEvent("DeviceActorOrgasm")
	self.RegisterForModEvent("DeviceActorOrgasm","OnModEvent_DeviceActorOrgasm")	

	;; handle DD Ex events.

	self.UnregisterForModEvent("DeviceActorOrgasmEx")
	self.RegisterForModEvent("DeviceActorOrgasmEx","OnModEvent_DeviceActorOrgasmEx")

	Return
EndEvent

Function OnModEvent_DeviceActorOrgasm(Form Whom)
	Debug.Notification("DD orgasm detected.)
EndFunction

Function OnModEvent_DeviceActorOrgasmEx(Int loc_handle,Form Whom)
	Debug.Notification("DD Orgasmex detected)
EndFunction

Through this setup the mod properly catches SexlabOrgasm events, but seems to completely miss both DeviceActorOrgasm and DeviceActorOrgasmEx. Is there any further property linking that needs to be done? or do you literally only have to slap in a registerformodevent?

To test orgasm i simply set max arousal in aroused redux puppeteer and equipped plugs/piercings. waited a few times, but not getting any messages outside of regular dd.

 

Any help would be appreciated.

Link to comment
31 minutes ago, Murphiee said:

 

Any help would be appreciated.

You need to define the function differently.

 

On every game load you need to re-register the events to start with. Otherwise they can get unloaded in the save. So using a script attached to the playerref alias using the on save load is the preferred way to go. Then define the events with their own custom name.

 

RegisterForModEvent("DeviceActorOrgasm", "MyOnOrgasm")

RegisterForModEvent("DeviceEdgedActor", "MyOnEdged")

 

Then outside of the "load loop" define the names as events.

 

Event MyOnOrgasm(string eventName, string argString, float argNum, form sender)
    ;do things here when triggered
EndEvent

 

Event MyOnEdged(string eventName, string argString, float argNum, form sender)
    ;do things here when triggered
EndEvent

Edited by naaitsab
Link to comment
On 5/4/2023 at 8:03 PM, krzzp said:

Prior to moving to DD to DAR based setup courtesy of @Roggvir, I've tried to run DD on a pure Nemesis based setup, which I hot-swapped from the working FNIS one - and achieved a reasonable amount of success.

 

I've created a new folder for Nemesis output in MO2, deactivated FNIS, generated everything, and ran into three problems:
- arms popping out of devices when in combat and sprinting
- npcs playing regular turning animations with flailing arms, instead of the needed ones when being locked into devices.


Turning off Nemesis and turning FNIS with its output back on makes this go away, so this is the Nemesis-DD exclusive behaviour. 

 

After snooping around logs, I've found that nemesis doesn't like the following:

WARNING(1003): Alternate animation file doesn't exist. Current alternate animation file will not work | Mod: DD | Animation File: abc5_npc_turnleft90.hkx
WARNING(1003): Alternate animation file doesn't exist. Current alternate animation file will not work | Mod: DD2 | Animation File: hbc0_bow_sprint.hkx
WARNING(1003): Alternate animation file doesn't exist. Current alternate animation file will not work | Mod: DD | Animation File: abc0_dw_sprintforwardsword.hkx


... etc, there's a lot of those - mostly sprint and npc turn-related.

 

So, the first problem I was able to fix using the idea I've found somewhere here, so big props to @zarantha who recommended it, iirc. Go to the Nemesis github, download the ZIP of the main branch. From that zip, grab the /test environment/behavior templates/ and /test environment/alternate animation/ folders, overwrite your installed Nemesis with them (do remember to create a backup first, naturally). and recreate behaviours. Those are a bit newer than what the Nexus install comes with, and that will fix the player hands popping thing - well, at least it did for me.

 

Wasn't able to fix bound combat, the implementation is a little proprietary, so poor Nemesis is struggling with it - you'd probably have to somehow patch and recompile zadBoundCombatScript, i'd wager, I lack the necessary programming chops to do that. 

 

The NPC turn animations, I've ticked the Nemesis patch "turn animations don't affect upper body" and created a ESP for myself that turned off the idle turning animations on NPCs. One of those things helped, so now it behaves almost the same as my FNIS install did.

 

I've attached a homemade patch with the templates from Nemesis Github, and the ESP I made, let this overwrite your Nemesis install, re-generate the behaviours, and test for yourself.
 
Gettin' all the goodies from TDM, like procedural leaning, and the rest of stuff from Nemesis based mods doesn't feel like a bad trade off. However, this is still very 2021 - in 2023, the alternate animations should be done with DAR/OAR anyways, and bound combat works like a charm there. Can't recommend it enough: 

Nemesis compatibility patch.7z 17.85 kB · 5 downloads

Regarding the NPC turning animation, I might give a some help. From my understanding, issue is caused by 2 things

  • Some animations on some females use male animation. Because of that, you will also have to specify male animations, even if you don't intend to use devices on males. I solved it by creating another folder called male next to female folder, and copied all the animations to it. It might also be possible to just don't use female/male folder. Having all animation in priority folder might be enough.
  • Most importantly, the turning animation doesn't exist. The animation that plays when NPC turns is called npc_turnleftxxx.hkx. There are total of 8 animations of this type. I just used the default idle animation as replacement. This way, if npc turns, it will looks like they are spinning without moving. That is still IMO better then broken animation. Alternatively there is some kind of turning animation in DD called abc0_mt_turnleftxx.hkx. But the animation was not working that well when transitioning from standing idle to turning, so I instead just used standing idle for turning.

 

image.png.a3154d7167c5c479c9932c48391fb064.png

Edited by ihatemykite
Link to comment
10 hours ago, ihatemykite said:
  • Some animations on some females use male animation. Because of that, you will also have to specify male animations, even if you don't intend to use devices on males. I solved it by creating another folder called male next to female folder, and copied all the animations to it. It might also be possible to just don't use female/male folder. Having all animation in priority folder might be enough.

Ah, that explains it, thanks! Yeah, that seems like a good method - I'll test that out!

 

 

10 hours ago, ihatemykite said:
  • Most importantly, the turning animation doesn't exist. The animation that plays when NPC turns is called npc_turnleftxxx.hkx. There are total of 8 animations of this type. I just used the default idle animation as replacement. This way, if npc turns, it will looks like they are spinning without moving. That is still IMO better then broken animation. Alternatively there is some kind of turning animation in DD called abc0_mt_turnleftxx.hkx. But the animation was not working that well when transitioning from standing idle to turning, so I instead just used standing idle for turning.

 

I must've accidentally arrived at the same conclusion, haha - good to know know the science behind that, thanks ?

The nemesis patch only affects the combat movements, i wonder if it can be somehow applied to the regular animations as well, but I got a bit lost trying to look through all the bones management in the behaviour patch.

 

I went with a bit of a... heavy handed approach, and just turned them off entirely via ESP which I attached ? I'll look into replacing them with idles, sure seems like a much better idea rather then chopping off bits!

Screenshot 2023-05-08 180313.png

Link to comment

Found a bug in the Trip function in zadlibs. The animation selection there missed the possibility of straitjackets and would just not play any animation if wearing it. Here's my edited code to fix it.

 

Function Trip(actor akActor)
    ; this should delay any anims if there is a menu open
    Utility.Wait(0.1)
    ; don't play anims if the actor is already in one.
    If IsAnimating(akActor)
        return
    EndIf    
    ; don't play the animation in combat if it's the player
    if akActor == playerref && playerref.IsInCombat() 
        return 
    Endif
    ; use PlayThirdPersonAnimation instead of StartThirdPersonAnimation for non-looping animation
    ; alternatively EndThirdPersonAnimation can be called manually if termination is conditional
    If !akActor.WornHasKeyword(zad_DeviousHeavyBondage)
        PlayThirdPersonAnimation(akActor, "ft_fall_over_reg_1", 5, true)
    Elseif akActor.WornHasKeyword(zad_DeviousArmBinder) || akActor.WornHasKeyword(zad_DeviousStraitJacket)
        PlayThirdPersonAnimation(akActor, "ft_fall_over_armbinder_1", 5, true)
    Elseif akActor.WornHasKeyword(zad_DeviousArmBinderElbow)
        PlayThirdPersonAnimation(akActor, "ft_fall_over_elbowbinder_1", 5, true)
    Elseif akActor.WornHasKeyword(zad_DeviousYokeBB)
        PlayThirdPersonAnimation(akActor, "ft_fall_over_bbyoke_1", 5, true)
    Elseif akActor.WornHasKeyword(zad_DeviousCuffsFront)
        PlayThirdPersonAnimation(akActor, "ft_fall_over_frontcuffs_1", 5, true)    
    Elseif akActor.WornHasKeyword(zad_DeviousYoke)
        PlayThirdPersonAnimation(akActor, "ft_fall_over_yoke_1", 5, true)
    EndIf
    SexlabMoan(akActor)
EndFunction

Link to comment

So the OnSleepStop event seems to always trigger the messageboxes. Which after a while can become quite tedious.

There was a system to use the setting in the MCM to set the display chance, as that value currently is not in use by anything else.

 

It seems to be disabled when looking in the ZadBQ00 script. I would like to purpose to reinstate the user-setting. It also links the animation event more to the text to only trigger the horny animation on 2 highest arousal messages. The MCM default is 10% which might be a bit low. Perhaps set it default to 33%?

 

From:

Spoiler
Event OnSleepStop(bool abInterrupted)
	libs.Log("OnSleepStop()")
	if abInterrupted
		return
	EndIf
	actor akActor = libs.PlayerRef
	if !HasBelt(akActor)
		return
	Endif
	int arousal = Aroused.GetActorExposure(akActor)
	int chance = 5
	Message tmp
	if arousal >= libs.ArousalThreshold("Desperate")
		chance += 45
		tmp = zad_eventSleepStopDesperate
	elseIf arousal >= libs.ArousalThreshold("Horny")
		chance += 25
		tmp = zad_eventSleepStopHorny
	elseIf arousal >= libs.ArousalThreshold("Desire")
		chance += 10
		tmp = zad_eventSleepStopDesire
	else
		tmp = zad_eventSleepStopContent
	Endif
	; if Utility.RandomInt() <= libs.config.BaseMessageChance
	; 	tmp.Show()
	; EndIf
	tmp.Show()
	libs.PlayThirdPersonAnimation(akActor, libs.AnimSwitchKeyword(akActor, "Horny01"), utility.RandomInt(5,9))
EndEvent

 

 

To:

Spoiler
Event OnSleepStop(bool abInterrupted)
	libs.Log("OnSleepStop()")
	if abInterrupted
		return
	EndIf
	actor akActor = libs.PlayerRef
	if !HasBelt(akActor)
		return
	Endif
	int arousal = Aroused.GetActorExposure(akActor)
	int chance = 5
	Message tmp
	if arousal >= libs.ArousalThreshold("Desperate")
		chance += 45
		tmp = zad_eventSleepStopDesperate
	elseIf arousal >= libs.ArousalThreshold("Horny")
		chance += 25
		tmp = zad_eventSleepStopHorny
	elseIf arousal >= libs.ArousalThreshold("Desire")
		chance += 10
		tmp = zad_eventSleepStopDesire
	else
		tmp = zad_eventSleepStopContent
	Endif
	if Utility.RandomInt() <= libs.config.BaseMessageChance
		tmp.Show()
		if arousal >= libs.ArousalThreshold("Horny")
			libs.PlayThirdPersonAnimation(akActor, libs.AnimSwitchKeyword(akActor, "Horny01"), utility.RandomInt(5,9))
		endif
	EndIf
EndEvent

 

 

Link to comment
4 hours ago, chaimhewast said:

It also looks like that event also has a "chance" variable that could get removed. No sense in declaring a variable and adding to it if you're not going to use it.

Or it could be used to boost the chance of it showing. Which I think was the original idea.

"if Utility.RandomInt() <= (libs.config.BaseMessageChance + chance)"

 

But as it's the same message again and again I don't see the added benefits, it still get's annoying over time. Or we need more messages/animations.

Link to comment
On 5/8/2023 at 7:21 PM, ihatemykite said:

Regarding the NPC turning animation, I might give a some help. From my understanding, issue is caused by 2 things

  • Some animations on some females use male animation. Because of that, you will also have to specify male animations, even if you don't intend to use devices on males. I solved it by creating another folder called male next to female folder, and copied all the animations to it. It might also be possible to just don't use female/male folder. Having all animation in priority folder might be enough.
  • Most importantly, the turning animation doesn't exist. The animation that plays when NPC turns is called npc_turnleftxxx.hkx. There are total of 8 animations of this type. I just used the default idle animation as replacement. This way, if npc turns, it will looks like they are spinning without moving. That is still IMO better then broken animation. Alternatively there is some kind of turning animation in DD called abc0_mt_turnleftxx.hkx. But the animation was not working that well when transitioning from standing idle to turning, so I instead just used standing idle for turning.

 

image.png.a3154d7167c5c479c9932c48391fb064.png

Could you please explain which idle file name used (or at least how to find them) and where to put these file in? 

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