Jump to content

ActorBase templates for naked bandit bug


Recommended Posts

Posted

Hi, if someone is skilled enough, I believe a DLL plugin would be the solution to the infamous naked bandit bug, resulting from capturing and stripping spawned NPCs.

 

We would need a pool of a minimum of 128 unique ActorBase for which to clone the spawned character ActorBase into it with this kind of code:

 

Spoiler

ActorBase sourceBase = akBandit.GetLeveledActorBase()
ActorBase targetBase = FollowerTemplate

targetBase.SetName(sourceBase.GetName())
targetBase.SetRace(sourceBase.GetRace())
targetBase.SetSex(sourceBase.GetSex())
targetBase.SetHeight(sourceBase.GetHeight())
targetBase.SetWeight(sourceBase.GetWeight())
targetBase.SetHairColor(sourceBase.GetHairColor())
targetBase.SetVoiceType(sourceBase.GetVoiceType())
targetBase.SetSkin(sourceBase.GetSkin())
targetBase.SetClass(sourceBase.GetClass())
targetBase.SetCombatStyle(sourceBase.GetCombatStyle())

 

Then one would need to copy other info and especially head parts before using system calls to copy the facegen mesh and textures and efit the mesh with the correct face texture (to avoid the potato face and black face bugs).

 

If anyone is interested, I am available to discuss more.

Posted (edited)
On 7/28/2026 at 4:18 PM, TrollAutokill said:

Hi, if someone is skilled enough, I believe a DLL plugin would be the solution to the infamous naked bandit bug, resulting from capturing and stripping spawned NPCs.

 

We would need a pool of a minimum of 128 unique ActorBase for which to clone the spawned character ActorBase into it with this kind of code:

 

  Reveal hidden contents

ActorBase sourceBase = akBandit.GetLeveledActorBase()
ActorBase targetBase = FollowerTemplate

targetBase.SetName(sourceBase.GetName())
targetBase.SetRace(sourceBase.GetRace())
targetBase.SetSex(sourceBase.GetSex())
targetBase.SetHeight(sourceBase.GetHeight())
targetBase.SetWeight(sourceBase.GetWeight())
targetBase.SetHairColor(sourceBase.GetHairColor())
targetBase.SetVoiceType(sourceBase.GetVoiceType())
targetBase.SetSkin(sourceBase.GetSkin())
targetBase.SetClass(sourceBase.GetClass())
targetBase.SetCombatStyle(sourceBase.GetCombatStyle())

 

Then one would need to copy other info and especially head parts before using system calls to copy the facegen mesh and textures and efit the mesh with the correct face texture (to avoid the potato face and black face bugs).

 

If anyone is interested, I am available to discuss more.

Yes. This is very close to the implementation approach I’m currently using.

  • Prepare a pool of unique ActorBase slots
  • Copy Race, Sex, Voice, Class, CombatStyle, etc. from GetLeveledActorBase()
  • Additionally copy HeadParts, FaceData, and Tint data
  • Copy FaceGen NIF/DDS files and update texture paths inside the NIF

The main difference is that the current mod copies TESNPC data directly in the DLL instead of using Papyrus Set...() functions, and uses a built-in NIF patcher rather than an external command-line tool.

I’ll summarize the current progress and post another reply.

Edited by oys051
Posted (edited)

image.png.b541c8b6a6100a553232fde2912ff4e9.png

Target bandit NPC

image.png.debf1166e8de8551cbdd8686e046b0d0.png

Cloned and added to the ESP slot

image.png.747420b20c6e31f410ff613708517107.png

Respawn test with actorbase

 

I'm currently developing a plugin(DLL) and ESP with guidance from the DoM author, with AI assisting the process.

Current structure

- A pool of independent NPC slots is prepared in the ESP. The idea was inspired by the BaF mod.


- When DoM captures a bandit, the DLL copies the bandit’s face, body shape, sex, and voice into one of those slots.


- New NPC reference is then created from the slot ActorBase and passed to DoM.


- Equipment, factions, commands, and slave registration are handled entirely by DoM/PAH.


- The original bandit’s shared ActorBase and default outfit are left untouched, preventing naked bandits from appearing.


- Appearance and slot state are preserved through SKSE serialization data and FaceGen files, and any slot currently in use remains locked. In other words, only the bandit’s appearance is copied into an independent ActorBase, while the original shared base is preserved.


- Unique NPCs are excluded from this mod. The target is limited to spawned NPCs such as bandits and Forsworn.


Technical details
- CloneBase

This is handled by a native function. It copies the original NPC data into an empty ActorBase slot, creates a new Actor, and stores the cloned NPC information in the ESP-managed slot.
 

- NifSkope CLI

NifSkope CLI is not used. Instead, a built-in NIF patcher was implemented directly in the DLL. When an NPC is cloned and the FaceGen NIF is captured, the internal paths and IDs are automatically changed to match the FaceGen data for the slot managed by the ESP, then saved. (The NIF-related functionality is almost identical to what the author suggested.)


Current test results
 

Slot-based slave persistence is working successfully.
After checking newly spawned versions of the original NPC, their ActorBase data was different from the clone’s, and they did not appear naked. The remaining work is expanding the slave slot pool and performing stability tests.


Current issue: Interaction and faction-related bugs occur when transferring slaves between DoM-PAH-HSH-AYGAS, and these still need to be fix.

Future plans
1.Move slaves between DoM, PAH, HSH, and AYGAS, observe how they react to events, and perform long-term stability testing.
2.Gradually increase the number of slots during testing, with a final goal of preparing around 128 (or more) slave templates. There is currently only one test slot.
3.Keep any occupied slot permanently locked unless the slave leaves DoM or is freed due to another mod or a bug, or the slave’s body is completely removed from Tamriel while still enslaved.

Testing is currently being done on the latest 8.4.1b version, but while coding this, I started wondering whether it might have been better to target a stable release instead.
Older versions also include DoM source files, so porting it should not be too difficult, but time is the main issue.

AI is being used as an assistant, but this work is still quite complicated.


Any advice on missing parts or areas that need improvement would be greatly appreciated.

Edited by oys051
Posted (edited)

I am not sure why you need a DOM interface. Would it be easier to just provide an ActorBase clone function? And maybe a release actor base function for when the actor is deleted.

 

 If you want to detect captured slaves you just need a few factions, you shouldn't care about stable release or not, should you?

 

Excuse my naive comments, I am not familiar with DLL.

Edited by TrollAutokill
Posted

That’s perfectly fine — your suggestion is very helpful.
 

I agreed, a full DOM-specific interface maybe unnecessary. the dll can provide a generic clonebase/cloneactor function and detect the relevant slave factions.
 

The DOM hook was used only to guarantee that cloning occurs at the exact capture point, before the original shared actorbase can be modified. if the factions are applied early enough, faction detection would be a cleaner solution.
 

also, there is no need to reclaim the slot immediately when a slave is transferred or released; the cloned actorbase can remain permanently reserved. which factions would you recommend detecting?

Posted (edited)
50 minutes ago, oys051 said:

That’s perfectly fine — your suggestion is very helpful.
 

I agreed, a full DOM-specific interface maybe unnecessary. the dll can provide a generic clonebase/cloneactor function and detect the relevant slave factions.
 

The DOM hook was used only to guarantee that cloning occurs at the exact capture point, before the original shared actorbase can be modified. if the factions are applied early enough, faction detection would be a cleaner solution.
 

also, there is no need to reclaim the slot immediately when a slave is transferred or released; the cloned actorbase can remain permanently reserved. which factions would you recommend detecting?

For DOM that's DOMActorFaction once captured otherwise there is a being captured faction (as in PAH) but it's very short lived. Hence why I would let PAH or DOM handle the cloning. If no valid ActorBase template is found then we can fall back to the old naked bandit solution.

 

Many thanks for looking into that.

Edited by TrollAutokill
Posted

Good. That clarifies.

I will not use faction polling as the capture trigger. PAH or DOM should call the generic clone utility directly from their existing capture/cloning path.

DOM-Actorfaction can then be used only to identify actors already captured by DOM and to retain their reserved ActorBase slots.
If no valid or free template is available, the function can return None so DOM/PAH can fall back to the existing cloning method, with a warning in the log.
Transfers to HSH or AYGAS will retain the same ActorBase and will not allocate another slot.

I’ll adjust the direction slightly and test it again.

And this..

1 hour ago, TrollAutokill said:

And maybe a release actor base function for when the actor is deleted.


I had forgotten something important, but this also seems possible to implement.
 

The mod currently being tested already has the foundation for the relevant function, so it only needs to be extended.
However, for safety, captured and cloned bandits will become unique NPCs, and I will add a branch that protects normal unique NPCs while only performing the final cleanup on managed unique NPCs.
 

I’ll report the results again after testing.

Posted (edited)

Here are the DEV results.

Following advice, I did not implement a dedicated DLL-side DOM interface. Instead, DOM and PAHE call the minimal NoeActorClone API directly at their existing capture/cloning points. Their existing factions are preserved and used for ownership and state tracking, rather than being used as the sole trigger for cloning.
 

- A captured bandit was confirmed to use only 1 NPC slot embedded in the ESP while moving between DOM-PAH-HSH-AYGAS.


- Bandit enslavement worked successfully, and spawning an actor from the cloned ActorBase produced no naked bandit bug at all. As mentioned earlier, captured bandits are treated as unique NPCs for stability.


- Automatically loading slave FaceGen data for this mod was more difficult to implement than expected, so 0B multiple dummy FaceGen files are used to build each ActorBase face. The current test version contains 16 slots. Since 128 slots may be too restrictive, the finished version is planned to include 1024.


-Slot deletion has not been implemented yet. Slot release must be handled very safely, and this decision may be better left to careful consideration by the DOM developer. An MCM option for easily managing slot release and reset functions is also being considered.


Please also advise whether 1024 templates would be excessive or reasonable. It is very unlikely, but guidance would also be helpful on what should happen if every slot is occupied and a 1025th slave is created.
 

An early test build will be uploaded here for direct testing. also attach the relevant source code used in the script. (Mod must be placed below DoM in the load order.) Since the core DOM/PAH flow is naturally better understood by its developer, please test it and report any problems found. 


Test commands can be checked in the console:

F10 - Prints the crosshair NPC’s reference/base FormID, resolved leveled base, appearance source, FaceGen paths, and other related information to the console.

(Makes no changes.)

F11 - Selects an empty slot from the ESP and copies the target NPC ActorBase’s FaceGen information into it.

Locks the slot as reserved. (Please use this carefully.)

F12 - Spawns an actor from the prepared cloned ActorBase. (F11 must be used first.)

 

 

Edited by Thrallmaster
Posted (edited)
2 hours ago, Thrallmaster said:

Here are the DEV results.

Following advice, I did not implement a dedicated DLL-side DOM interface. Instead, DOM and PAHE call the minimal NoeActorClone API directly at their existing capture/cloning points. Their existing factions are preserved and used for ownership and state tracking, rather than being used as the sole trigger for cloning.
 

- A captured bandit was confirmed to use only 1 NPC slot embedded in the ESP while moving between DOM-PAH-HSH-AYGAS.


- Bandit enslavement worked successfully, and spawning an actor from the cloned ActorBase produced no naked bandit bug at all. As mentioned earlier, captured bandits are treated as unique NPCs for stability.


- Automatically loading slave FaceGen data for this mod was more difficult to implement than expected, so 0B multiple dummy FaceGen files are used to build each ActorBase face. The current test version contains 16 slots. Since 128 slots may be too restrictive, the finished version is planned to include 1024.


-Slot deletion has not been implemented yet. Slot release must be handled very safely, and this decision may be better left to careful consideration by the DOM developer. An MCM option for easily managing slot release and reset functions is also being considered.


Please also advise whether 1024 templates would be excessive or reasonable. It is very unlikely, but guidance would also be helpful on what should happen if every slot is occupied and a 1025th slave is created.
 

An early test build will be uploaded here for direct testing. also attach the relevant source code used in the script. (Mod must be placed below DoM in the load order.) Since the core DOM/PAH flow is naturally better understood by its developer, please test it and report any problems found. 


Test commands can be checked in the console:

F10 - Prints the crosshair NPC’s reference/base FormID, resolved leveled base, appearance source, FaceGen paths, and other related information to the console.

(Makes no changes.)

F11 - Selects an empty slot from the ESP and copies the target NPC ActorBase’s FaceGen information into it.

Locks the slot as reserved. (Please use this carefully.)

F12 - Spawns an actor from the prepared cloned ActorBase. (F11 must be used first.)

 

Stable_Captives_16Slot_Preseed_Controlled_Test.7z 734.66 kB · 0 downloads

I believe 1024 is both reasonable and excessive, in fact it might just be the right number.

 

I will see if I can implement it in next DOM update.

Edited by TrollAutokill
Posted (edited)
3 hours ago, TrollAutokill said:

I believe 1024 is both reasonable and excessive, in fact it might just be the right number.

 

I will see if I can implement it in next DOM update.

Im sorry but, later found a bug in the version I uploaded, along with a few parts that had not been fully fixed.

I’ve uploaded a new file here.

The F11/F12 functions have been removed for now because they appeared to cause DLL interference.
Please let me know if these functions are absolutely necessary. For the time being, slaves will need to be captured directly.


The plugin has been reworked to minimize interference with other mods as much as possible. It now handles only slot assignment, slot locking, and slot release (planned), while slave management is handled entirely by DoM,/PAHE/HSH/AYGAS.

 

To temporarily reset the test slots, completely exit the game, then delete the following from MO2’s Overwrite folder:


SKSE/Plugins/NoeActorClone/SlotLeases.bin

meshes/actors/character/FaceGenData/FaceGeom/NoeActorClone.esp/*.nif (all)

textures/actors/character/FaceGenData/FaceTint/NoeActorClone.esp/*.dds (all)
SKSE/Plugins/NoeActorClone/FaceGenCache/ (all files)

 

Stable_Captives_DOM_16Slot_CloneBase_Test2.7z

Edited by Thrallmaster
Posted (edited)
10 hours ago, Thrallmaster said:

Im sorry but, later found a bug in the version I uploaded, along with a few parts that had not been fully fixed.

I’ve uploaded a new file here.

The F11/F12 functions have been removed for now because they appeared to cause DLL interference.
Please let me know if these functions are absolutely necessary. For the time being, slaves will need to be captured directly.


The plugin has been reworked to minimize interference with other mods as much as possible. It now handles only slot assignment, slot locking, and slot release (planned), while slave management is handled entirely by DoM,/PAHE/HSH/AYGAS.

 

To temporarily reset the test slots, completely exit the game, then delete the following from MO2’s Overwrite folder:


SKSE/Plugins/NoeActorClone/SlotLeases.bin

meshes/actors/character/FaceGenData/FaceGeom/NoeActorClone.esp/*.nif (all)

textures/actors/character/FaceGenData/FaceTint/NoeActorClone.esp/*.dds (all)
SKSE/Plugins/NoeActorClone/FaceGenCache/ (all files)

 

Stable_Captives_DOM_16Slot_CloneBase_Test2.7z 734.24 kB · 1 download

It would be good to have flags when cloning the ActorBase to choose if the inventory items and outfit should be copied.

 

Usually DOM copies them from the original actor, but Skyrim has a tendency to push the inventory and outfits on spawned characters every once in a while.

 

So if they aren't copied that would solve the re-equip problem. Two problems solved in one go.

Edited by TrollAutokill
Posted
8 hours ago, TrollAutokill said:

It would be good to have flags when cloning the ActorBase to choose if the inventory items and outfit should be copied.

 

Usually DOM copies them from the original actor, but Skyrim has a tendency to push the inventory and outfits on spawned characters every once in a while.

 

So if they aren't copied that would solve the re-equip problem. Two problems solved in one go.


I have finished implementing the flags that control whether inventory items and outfits are copied, expanded the slot count to 1024, and completed some simple testing.

 

DLL copies the ActorBase outfit only when flag 2 is enabled. Inventory is Actor-reference data, so DOM should run its existing inventory-copy function only when flag 1 is enabled.

The included test integration currently uses cloneFlags = 0 (naked).  And only need to connect future MCM options to values 0–3.

For more details, please refer to API5_FLAGS_FOR_DOM_PAHE.txt included in the zip archive.

Since the safe slave-release feature no longer seems necessary with 1024 available slots, I will postpone its implementation indefinitely.


Next, I plan to add a slot-reset function and complete the remaining cleanup and finishing project.
For now, please continue testing with this file and report any bugs or suggestions.

Stable_Captives_API5_Flags_1024Slot_Test.zip

Posted
7 hours ago, Thrallmaster said:


I have finished implementing the flags that control whether inventory items and outfits are copied, expanded the slot count to 1024, and completed some simple testing.

 

DLL copies the ActorBase outfit only when flag 2 is enabled. Inventory is Actor-reference data, so DOM should run its existing inventory-copy function only when flag 1 is enabled.

The included test integration currently uses cloneFlags = 0 (naked).  And only need to connect future MCM options to values 0–3.

For more details, please refer to API5_FLAGS_FOR_DOM_PAHE.txt included in the zip archive.

Since the safe slave-release feature no longer seems necessary with 1024 available slots, I will postpone its implementation indefinitely.


Next, I plan to add a slot-reset function and complete the remaining cleanup and finishing project.
For now, please continue testing with this file and report any bugs or suggestions.

Stable_Captives_API5_Flags_1024Slot_Test.zip 1.65 MB · 0 downloads

 

This sounds very promising thanks.

 

I've spent the last couple of days setting up a game to test how ....

 

https://www.nexusmods.com/skyrimspecialedition/mods/123963

 

...might help with the outfit issue - I am sure that @TrollAutokill must be sick of the sight of my posts by now and explaining obvious techie stuff to the great unwashed!- but that may be now be both 'overkill' and maybe unnecessary 😏

 

Only mentioning it here in case that mod author had any tricks up his sleeve that might be of use to you, but really looking forward to seeing how this progresses

 

DQW 

Posted
20 hours ago, Thrallmaster said:


Since the safe slave-release feature no longer seems necessary with 1024 available slots, I will postpone its implementation indefinitely.

I believe you're underestimating our compulsive slaver friends, 1024 can happen quickly.

 

I would just have a 1024 flag array with a circular counter. If the counter reaches 1024 start again at 0 to find a free ActorBase if it goes back to it's starting value the array is full and the function should return None.

 

When cloning an ActorBase set the corresponding flag to true (used) before doing the copy. When releasing an ActorBase, just set the corresponding flag to false (not used), and that's it.

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
×
×
  • Create New...