Skyrim Special Edition
0 of 0

File information

Last updated

Original upload

Created by

Seally25

Uploaded by

Seally25

Virus scan

Safe to use

About this mod

"Yet Another" solution to the underfilled soul gem problem, this time using SKSE. Heavily inspired by GIST (Genuinely Intelligent Soul Trap) by opusGlass.

Requirements
Permissions and credits
Changelogs
Donations
YASTM patches the TrapSoul() Papyrus function itself in order to enable "smart" soul trapping. You can split/shrink, displace, and relocate souls to organize your soul gems without worrying about underfills or unnecessary losses just because of a petty soul squatting in a Grand Soul Gem.

Any mod that uses the Papyrus Actor.TrapSoul() function will be able to get the benefits from YASTM with minimal changes to the code (minimal = modified to support soul diversion). Similar to GIST, it uses four primary techniques in order to achieve smart soul trapping, all of which can be disabled as you see fit:

Soul Displacement (Default = ON)
Existing souls can be knocked out of soul gems in order to make room for a larger soul.

Soul Relocation (Default = ON)
Displaced souls can be "re-homed" into another soul gem.

Soul Shrinking (Default = ON, implicitly turns off Soul Splitting if enabled)
If there are no non-fully-filled soul gems with a capacity equal or larger than the soul being trapped, the soul can be shrunk to fit a smaller soul gem.

Soul Splitting (Default = OFF, implicitly turned off if Soul Shrinking is also enabled)
Splits souls instead of simply shrinking them in order to fit smaller soul gems.

  • Grand souls => Greater + Common
  • Greater souls => Common + Common
  • Common souls => Lesser + Lesser
  • Lesser souls => Petty + Petty

Note that grand souls break the pattern due to their true capacity not being double of greater souls, unlike the pattern seen in other soul sizes. This option currently has no equivalent in GIST.

Warning: Soul splitting can be over 4 times slower than standard soul shrinking when tackling the worst case i.e. when Grand souls get split up and all you have are Petty Soul Gems. However, "4 times slower" is still about 2 milliseconds in the release version on my PC (an Intel Core i7 6700k), so it's still not noticeable. With that said, if you already have high script load in your load order, consider turning this off.

Additional Configuration

Soul Diversion (Default = OFF)
If a follower traps a soul, you will get the soul (this feature is actually permanently ON for GIST). More specifically, soul traps made by the player's teammates will act as if the player was the one who cast it. The "teammate" part is to avoid the rare (rare enough that I've yet to see it myself) case where enemies can trap souls for you.

Turning this on will ignore soul gems in the follower's inventory, so make sure you are the one carrying all the unfilled/partially-filled soul gems.

Note: This option is implemented in Papyrus by switching the caster before calling TrapSoul(). This is to give mod authors control over the soul trap target in case they somehow need to customize it. Spell mods that use and don't override magicSoulTrapFXScript (most mods out there) will automatically be compatible. The DLL plugin itself does not recognize this function.

Allow Partially-Filling Soul Gems (Default = ON)
If you disable partially-filling soul gems, soul traps will only max-fill soul gems. Soul displacement and relocation will still operate as usual for partially-filled soul gems before this option is disabled, and so will soul shrinking (since shrunk souls will always max-fill soul gems).

Obviously, it is not recommended to turn this off when soul displacement and relocation are also off, since you can end up with a bunch of partially-filled soul gems you can't do anything about (dropping them will not clear the contained souls anymore*).

*Unless it was a soul gem filled from before this mod was installed.

Preserve Soul Gem Ownership (Default = ON)
There's a rather curious bug present even in the vanilla soul trap. If you fill a soul gem in such a way that the base form of the soul gem changes (max-filling a non-reusable soul gem in vanilla+USSEP will do this), the ownership data of the soul gem is not transferred. So basically, if you steal a soul gem and fill it, you've become the proud owner of the filled soul gem. I call this the fillers keepers bug. This mod fixes this bug, although you can turn it off if you prefer it otherwise.

Profiling (Default = OFF)
Wondering if the mod is dragging down performance? Turn this on and a notification will show up after every soul trap (successful or not) detailing how many fractions of a second (it SHOULD be fractions of a second) it needs to finish. YASTM.log (under My Games/Skyrim Special Edition/SKSE folder) will also receive this message if you've missed it.

The notification requires Scaleform Translation Plus Plus to display correctly if translated. Otherwise the English text will be displayed. If the English version is what you need, you don't need to install this mod.

Additional fixes

Dropping soul gems no longer lose the souls contained inside, in all cases*.

  • USSEP only fixes this for fully-filled non-reusable soul gems.
  • GIST does not preserve Azura's Star/Black Star's contained soul if you drop them.

*This is only fixed for soul gems that are filled after the mod is installed. I make no guarantees for soul gems filled before that.

Soul gems now stack correctly.

The stacking problem, where two partially-filled soul gems with different contained soul sizes may end getting "synced" with each other, occurs because the game stores the soul gem's contained soul sizes as "extra data". However, the base form is still represented by the same form.

USSEP's (rather limited) fix was to add the fully-filled soul gem variant to a field called NAM0 (Linked Soul Gem). The original soul trap function checks this field whenever the found soul gem capacity matched the soul size of the victim, and uses this field to know what soul gem the game needs to add when filling a soul gem. For whatever reason it was never added to the vanilla ESP.

In YASTM, we instead map the soul capacity/contained soul size information by constructing a table generated by configuration files upon game startup. The NAM0 field is no longer used for this purpose, but it has gained a new use: the patch for enchanting/weapon charging references this field to know which soul gem to add to the inventory when you use up a reusable soul gem.

Configuration

In-game


This mod provides an (optional) MCM that allows configuring the soul trap methods in-game:



You can also set these options without an MCM by changing the following global variables in the console:

YASTM_AllowSoulDisplacement
YASTM_AllowSoulRelocation
YASTM_AllowSoulShrinking
YASTM_AllowExtraSoulRelocation
YASTM_DivertTeamMateSoulTrapsToPlayer
YASTM_AllowPartiallyFillingSoulGems
YASTM_AllowSoulSplitting
YASTM_AllowNotifications
YASTM_PreserveOwnership
YASTM_AllowProfiling
YASTM_ShowAllRecipes

Which one is which should be self-explanatory. Values: 1=ON, 0=OFF.

TOML

To be written soon (sorry).

How this mod came to be

This mod is the product of several months of research, design, and coding after I hit a wall with regards to how GIST handled soul gems. Using GIST, any attempt to add support for mod-added soul gems meant having to go down the rabbit hole of modifying the Papyrus source every time.

Instead, this mod allows new soul gems to be supported by supplying a TOML configuration file, (mostly) free from the basic load order issues that plague Skyrim's ESP system. Furthermore, it fixes the stacking issue of soul gems by giving each soul gem size and capacity their own individual base form. Unlike GIST, this fix extends to reusable soul gems.

This mod also fixes the crash that occurs if you try to use a reusable soul gem whose base form is not an empty soul gem. This is the crash that blocks any other mod from even attempting to fix the stacking issue for reusable soul gems.

This mod also makes some changes on how soul gems are filled compared to GIST:

  • Instead of prioritizing unfilled soul gems first, YASTM will try to fit souls into soul gems of the same capacity first and knock out (displace) any existing soul as long as the soul gem is not already fully-filled. If that fails, it will do the same to soul gems of increasing capacity. This means that it will try to get as close to a perfect fill as possible.
  • If soul relocation is disabled, the algorithm will instead prioritize knocking out the smallest-sized soul (so that you lose the least amount of souls) before trying to match the capacity.
  • Soul shrinking (if enabled) only occurs after the above options have been exhausted. Since you're losing soul size anyway, it will prioritize not shrinking the soul more than it has to, so there's no special code path for soul relocation in this case.
  • Reusable soul gems are prioritized over non-reusable ones. This prioritization only happens after soul capacity and contained soul sizes have been considered. Note that GIST does something similar for Azura's Star and Black Star, but only if it can fully fill them. Users can also customize how soul gems are (roughly) prioritized by setting the priority key to "low", "normal", or "high" in the TOML configuration for the soul gem group.
  • If you're wondering how soul relocation is handled, the quick version is that there's actually a queue for souls for each soul trap. Each time a soul has been displaced, the original soul is added to the queue. Each soul processing round pops the largest soul from this queue and the entire process repeats as if it were just another soul. The soul trap only stops when the queue is empty.

Other differences from GIST:

  • GIST automatically diverted soul traps to the player as a side effect of the script assuming the caster of the soul trap is always the player. This is no longer the case in YASTM and this feature is instead provided as an option.
  • GIST's soul trap leveling, such that you need to have certain skills at certain levels to trap larger souls, is removed because I never use it. I may introduce this if enough people really, really want this (and does so in a polite manner).
  • Although most of GIST's options are available in MCM, you cannot change which soul gems can trap white/black souls from in-game and this can only be adjusted by manipulating the TOML configuration files. The soul gem lists cannot be changed dynamically and are actually constructed when the game opens the main menu similar to Spell Perk Item Distributor. Since I do not expect users to change this every 5 minutes or so, along with the amount of investigation and code changes needed to fix this, I don't consider fixing this to be worth the effort.

Questions and Answers

Q: Does this mod require USSEP?
A: No. Every fix to soul trap made in USSEP is now handled by the SKSE code. In fact, the provided script actually reverts USSEP's fixed script to almost* vanilla.

Q: What do you mean by "almost" vanilla?
A: Diverting soul traps to the player is performed in Papyrus. This was a design choice to ensure the soul trap replacement function in SKSE obeys the rule of least surprise. It also gives the option for mod authors to control this aspect on their own terms.

Q: Does this support VR?
A: No, and the nature of how I patched things means it's extremely dangerous to use this on VR without checking what the code looks like on a disassembly level, and in order for me to "make sure" of this I need to actually own Skyrim VR. Which I don't.

If someone wants to test if a simple recompile is enough and/or work on a port, feel free to contact me though.

Q: Can you make an LE version?
A: I don't play Skyrim on LE, so I won't. However, my position on this is similar to my position on VR: contact me if you want to work on a port.

Q: Can this be installed mid-game?
A: As of version 1.3.0, this is safe to install mid-game as long as you keep the option Allow Extra Soul Relocation enabled. Make sure YASTM's magicSoulTrapFXScript.pex wins all conflicts. With this option enabled, the "extra souls", if any exists, will be automatically detected and relocated when filling a soul gem with an extra soul.

If you're already using GIST, install the supplied GIST configuration files before starting your first run with YASTM. With these configuration files, YASTM should now ignore its own added forms in favor of GIST's forms. Keep both "YASTM.esp" and "GIST soul trap.esp" enabled for this playthrough as "YASTM.esp" provides some forms and global variables that the mod needs.

Once you're done with that playthrough, you can uninstall GIST and the GIST configuration files... or YASTM if it turns out you hate it. :(

Q: What are "extra souls"?

A: The base game stores partial soul traps (and max-filled soul traps for soul gems missing the appropriate Linked Soul Gems field) in a separate structure called the ExtraDataList. There are some issues with how the game manages this list, causing stacking problems in the inventory. YASTM and GIST both try to fix the soul gem stacking issue by creating soul gems that differ in their base form, therefore bypassing the various issues caused by this mishandling.

"Extra souls" are what YASTM calls souls that are stored in the ExtraDataList. Since YASTM distinguishes soul gems by their base forms, the extra souls are not normally considered and ignored. From version 1.3.0 onwards, the code will detect and relocate these souls automatically whenever it encounters them while trying to fill a soul gem.

Note: Ownership data, which is how the game knows if you've stolen something, is also stored in this ExtraDataList. As such, there are still occasional problems with it, although its generally less severe.

Q: Can this be uninstalled mid-game?
A: This is NOT safe. You will lose all partially-filled soul gems and any reusable soul gems that are filled at any size (including your precious Azura's Star and Black Star if it's filled to any amount).

Q: Is this multi-threaded?
A: No. I gave up trying to make it multi-threaded after a few hours of thinking and just slapped in a mutex (mutable exclusion) over the soul trap function to avoid race conditions. Due to how I fixed the double soul trap problem (usually happens when both you and a follower with a soul trap weapon tries to soul trap the same enemy) there was no way that I can see to make this multi-threaded that wouldn't inevitably lead to other problems.

Q: What is this ".editorconfig" file? Can I delete it?
A: EditorConfig enforces certain formatting styles to a directory, assuming your text editor in question supports it (I use Visual Studio Code for editing anything that isn't C++ files - note that you will need to install an extension for EditorConfig).

It's provided because the files under Interface/Translations directory require a certain specific encoding (and the guarantee that pressing TAB won't convert it to spaces) in order to work properly. Since it's harmless I decided to include it in the download for convenience in case someone dislikes my notification messages and wants to edit them.

But yes, you can delete it if it annoys you so much. Just make sure that whenever you edit the translation files that its encoding is kept as UTF-16-LE with BOM and that tabs aren't turned into spaces.

Compatibility

Mods that do the following may need to be patched:

  • Mods that reference certain soul gems in a way that is supposed to refer to all variants of a certain soul gem.
  • Mods that modify the soul gem records themselves.
  • Mods that modify the magicSoulTrapFXScript. The loose script provided by this mod should override whatever changes they've made, but whether or not a patch is needed needs to be determined on a case-by-case basis.

Mods Under My Radar

These mods do not conflict:

  • Scrambled Bugs - YASTM doesn't care if you have Scrambled Bug's underfilled soul gems on or off. The code patches entirely different locations, and YASTM will never run the code patched by Scrambled Bugs.

These mods have patches released:

  • Rare Curios (Creation Club) - Adds support for the Flawed Varla Stone.
  • Saints & Seducers (Creation Club) - Adds support for the Soul Tomato.
  • GIST - A special configuration file is now provided for mid-game GIST players. Install it before you start a session with both mods enabled. Let YASTM override GIST's scripts. Actually not thoroughly tested, but it should work(tm).
  • Rustic Soulgems - Patches are out for both sorted and unsorted versions. If you are also using GIST, keep Rustic's GIST patch. My patch is not needed in this particular case, but should be harmless if installed. Rustic Azura's Star does not need a patch.
  • Multilayer Parallax Soulgems - Patches are out and includes missing assets that were in the original's FOMOD but somehow never installed in any configuration whatsoever (thanks to open permissions I can do this). I ... quite frankly can't tell if there's a difference from unpatched (the .nif files have a few bytes worth of difference from their empty counterparts).
  • Tamrielic Culture - Support added for the 4 new soul gems. Numerous crafting recipe versions for the staffs were added so they will recognize the added soul gems, but this will flood the crafting UI with identical-looking recipes. A new compatibility page has been added to the MCM to allow showing these recipes on demand, and another patch is available to add contained soul sizes to the item names so that they'll be distinguishable in the crafting UI. Note that Tamrielic Culture staff recipes have an existing issue where they require enchanting perks that may be disabled by perk mods like Adamant, and fixing this will also need another patch to propagate this to the added recipes. This goes beyond my current patch scope so I will not patch this nightmare myself.
  • Immersive Sounds Compendium - The basic patch conflicts with Rustic Soulgems and Multilayer Parallax Soulgems patches. A combined patch is available in the FOMOD but not individually to keep the number of individual files down. Forward the changes yourself or extract and repackage the folder in the FOMOD if you don't want to use the it.
  • Inigo - Make minor random dialogue for Inigo recognize the added Azura's Star variants.
  • The Hanging Guardians - Add support for new soul gems. Contributed by Nechigawara.
  • Vigilant - Add support for new soul gems. Contributed by Nechigawara.
  • Undeath - Add support for new soul gems. Contributed by Nechigawara.

Third party patches (please forward support to their respective authors)


These mods have patches made but not yet released (awaiting permission from authors):

  • Lucien (only with Rare Curios and/or Saints & Seducers patch) - Similar to Inigo. Added dialogue won't fire for the added soul gem variants.

These mods should be simple to patch, but I haven't gotten around to them yet:

  • Cutting Room Floor - This mod adds the mini-quest where the Vigilants will confiscate Daedric artifacts from you (as long as their Hall hasn't burned down yet). If your Azura's Star or Black Star is not empty, they may not recognize them as Daedric artifacts. Fix looks to be trivial, but may not be. Needs investigation.


Troubleshooting

If you are experiencing crashes when:

  • Soul trapping something.
  • Using a soul gem through enchanting or charging a weapon.

It may be an issue with this mod. If you can spare the time, try to replicate it with the fewest variables possible (new game is preferred, take advantage of console commands to quickly set things up) and give as many details as you can: what soul gems you have/are using, what does the soul gem record look like in xEdit etc. I need to be able to replicate the problem on my machine before I can actually do anything.

Additionally, provide the logs (paste the contents somewhere like Pastebin and link it here). They should be located in your My Games/Skyrim Special Edition/SKSE folder. The YASTM.log is the most important log file here. Now if YASTM.log is empty, something catastrophically wrong has happened and I would also like to see the SKSE.log file (though it probably won't help much).

Note that when reading the TOML configuration files, the plugin performs several sanity checks to make sure the files don't contain unusable garbage. If anything looks wrong, it will not patch the soul trap code at all (the crash fixes will still be applied). The logs will contain details on what went wrong.

When reporting bugs: it's not about being able to explain something well, it's about being specific. There's a major difference between "it's blank" and "YASTM.log file is blank". The person on the other side of the internet does not have access to your eyes and brainwaves. In order for me to help you with your problem, you need to help me see what you're seeing. Also, being rude does not help me see what you see, because it would compel me to not read what you wrote in the first place.

Source Code

See my GitHub page here.

Alternatives

Don't like YASTM? Check these out:

  • GIST - This mod's closest relative and how it all began. The vast majority of GIST's main functionality should already be in YASTM, but if you beg to differ, it's there.
  • Scrambled Bugs - If all you need is to always fully-fill soul gems and don't care for any other fixes, Scrambled Bugs with Underfilled Soul Gems may be what you need. This SKSE/.NET Script Framework mod also comes with a whole host of other useful fixes you may be interested in.
  • Acquisitive Soul Gems Multithreaded - A common staple for those who don't care about soul trap fixes all that much but want something better than vanilla. This is the mod I have the least experience in so I won't say much, but feel free to check it out.

Special Thanks and Credits

  • Bethesda Games Studio - for releasing a game so buggy and yet people around the world still fix things for you.
  • SKSE authors - without whom this mod would never be possible.
  • Ryan-rsm-McKenzie and CommonLibSSE contributors - who formed the backbone of this mod.
  • KernalsEgg - who published the source code for Scrambled Eggchantments so I can use as an example for writing SKSE plugins.
  • powerofthree - whose source code for Spell Perk Item Distributor revealed how to access game data by form ID and mod name, and read them without crashing.
  • SSE Engine Fixes authors - who published the source code that taught me how to use Xbyak for assembly patches. 
  • herumi - whose Xbyak library made patching code in assembly several times easier.
  • marzer - for the TOML parser library.
  • opusGlass - whose mod formed the basic idea of the unreleased Papyrus version of this mod, and for inspiring this work in the first place.

And lastly:

  • Tangtang - a friend who I wasn't around for when they needed me the most. May you stretch your wings and fly to the heavens as you have always yearned for in life. I will always love you.
  • My parents - who know nothing about this mod, but had stuck with me all this time despite everything that had happened.