Jump to content

Recommended Posts

Posted (edited)

Found a solution. If I save the cache under the new key ".SlaveTatsCache.cache" instead of ".SlaveTats.cache" in the JDB, it works. Is this perhaps a name clash, there already exists a JFormDB with name ".SlaveTats.applied" ? Maybe both types cannot be mixed. 

 

Ps: I did a bit of testing, and this really seems to be the reason. If I do a

		int st = JDB::solveObj(".SlaveTats");
		_log_jcontainer(st, "");
		int stc = JDB::solveObj(".SlaveTatsCache");
		_log_jcontainer(stc, "");

I see that ".SlaveTats" is a "JFormMap" (expecting Form keys), while the latter is a normal "JMap" (expecting String keys).  I guess that the original Papyrus SlaveTats has the same problem, this is probably one of the reasons why it's so slow, it reads each time the cache is acquired the json cache file anew.

 

Theoratically the following would work: JDB::solveObjSetter(".SlaveTats.cache", formMap, true); and formMap something like { CacheActor -> cache ), but this would be nonsense

Edited by nopse0
Posted
On 8/24/2024 at 5:02 AM, duy123a said:

Because I can't? Not everyone is developer. That's why I ask him to help me with that.

Be nice to everyone and don't be a jerk.

There's instructions provided to compile it yourself.

 

as you refuse to update to a modern version of the game, you really aught to get used to the reality that both out-of-the-box support for your version of the game is not guaranteed, and that mod developers have no obligation to provide binaries for a version they do not support.

 

My suggestion still holds true: if you want a 1.5.97 version, compile the mod yourself.

Posted

btw does this mod hold the most updated version here or I should compile it for 1.6170 too?

Posted
5 hours ago, Sicumbaka said:

btw does this mod hold the most updated version here or I should compile it for 1.6170 too?

You mean 1.6.1170 ? Yes, that's what I am using

Posted (edited)
28 minutes ago, DuskWanderer said:

I'm getting a crash on load from the newest version. Wasn't an issue with the 0.0.1-ae build. Here's the log.

crash-2024-08-26-03-54-12.log 305.48 kB · 0 downloads

Thank you. I didn't have a closer look yet, but I suppose that I have to add null pointer checks everywhere a RE::Actor* is passed as a parameter. Only problem is, what do I do if I get a null pointer ? obviously, I can' throw an exception :). Good, that I uploaded the Debug version of the DLL, makes it easy to follow stacktraces. But after everything is fixed and working, I will upload the Release version, which is much faster and causes no lag at all.

Edited by nopse0
Posted (edited)
12 hours ago, VeraDra said:

There's instructions provided to compile it yourself.

 

as you refuse to update to a modern version of the game, you really aught to get used to the reality that both out-of-the-box support for your version of the game is not guaranteed, and that mod developers have no obligation to provide binaries for a version they do not support.

 

My suggestion still holds true: if you want a 1.5.97 version, compile the mod yourself.

Hi! Building the vr version isn't that easy. When I built Ponzi's OverlayManager, I noticed that you have to copy "openvr.h" from https://github.com/ValveSoftware/openvr/blob/master/headers/openvr.h into the OverlayManager\extern\CommonLibSSE-NG\include folder, otherwise you get compile errors ("missing header ..."), how shall a user know that, thats totally undocumented (rant to CommonLibSSE-NG!!!)! Since this is time consuming, and I don't have SkyrimVR or a VR headset to test it, I refuse to do that :).

But once you have installed VisualStudio, it's relatively easy to build the project, VisualStudio has builtin support for vckg and cmake. Just follow the instructions in the README.md (I copied that from a powerofthree project). Ps: And you would also have to change from CommonLibSSE, what I am using, to CommonLibSSE-NG, because the initialization code Ponzi used

			auto patch = REL::Module::get().version().patch();

			logger::info("Patch: {}, VR: {}", patch, REL::Module::IsVR());

			std::string pluginName{ "JContainers64" };

			if (REL::Module::IsVR()) {
				pluginName = "JContainersVR";
			} else if (patch == 659) {
				pluginName = "JContainersGOG";
			}

			logger::info("JContainers Plugin Name: {}", pluginName);

doesn't work with CommonLibSSE, because CommonLibSSE has no REL::Module::IsVR() function, and the version returned by CommonLibSSE by REL::Module::get().version() has no patch() function.

Edited by nopse0
Posted

Do I need to overwrite the original Slave Tats mod to use this one?

Posted (edited)

Since I installed the upgrade from 0.0.1 I get CTD on game load I'm using "AE version" On skyrim: 1.6.6406.6

I deleted the slavetats cache also removed all overlays from my character to see if it maybe loads. Does this have to do with Race Menu or the version of Skyrim?

1.6.6406.6 Is considered AE, didn't have CTD with 0.0.1 and it was also AE.

 

EDIT: I also have this mod: I recently added its fairly new: RaceMenu Selector of Skins - Unique Player Character . I had it installed with 0.0.1 AE also and didn't CTD.

 

Here's the log.

Spoiler
SkyrimSE v1.6.640
trainwreck v1.4.0
 
Unhandled exception "EXCEPTION_ACCESS_VIOLATION" at 0x7FF934FF8C41 SlaveTatsNG.dll+00E8C41 slavetats_ng::skee_wrapper::NiOverride::HasOverlays
 
PROBABLE CALL STACK:
[0 ] 0x7FF934FF8C41 SlaveTatsNG.dll+00E8C41 slavetats_ng::skee_wrapper::NiOverride::HasOverlays
[C:\Build\SlaveTatsNG\include\nioverride_wrapper.h:243]
mov rax,[rax]
[1 ] 0x7FF934FF21B8 SlaveTatsNG.dll+00E21B8 slavetats_ng::synchronize_tattoos
[C:\Build\SlaveTatsNG\src\overlays.cpp:254]
movzx eax,al
[2 ] 0x7FF93500C123 SlaveTatsNG.dll+00FC123 slavetats_ng::overlays::papyrus::synchronize_tattoos
[C:\Build\SlaveTatsNG\src\papyrus_overlays.cpp:31]
add rsp,20h
[3 ] 0x7FF93500FDE3 SlaveTatsNG.dll+00FFDE3 std::invoke<bool (__cdecl*&)(RE::StaticFunctionTag *,RE::Actor *,bool),RE::StaticFunctionTag *,RE::Actor *,bool>
[C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\include\type_traits:1714]
add rsp,30h
[4 ] 0x7FF935012C59 SlaveTatsNG.dll+0102C59 std::_Func_impl_no_alloc<bool (__cdecl*)(RE::StaticFunctionTag *,RE::Actor *,bool),bool,RE::StaticFunctionTag *,RE::Actor *,bool>::_Do_call
[C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\include\functional:876]
add rsp,20h
[5 ] 0x7FF935011E28 SlaveTatsNG.dll+0101E28 std::_Func_class<bool,RE::StaticFunctionTag *,RE::Actor *,bool>::operator()
[C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\include\functional:920]
add rsp,30h
[6 ] 0x7FF93501020C SlaveTatsNG.dll+010020C std::invoke<std::function<bool __cdecl(RE::StaticFunctionTag *,RE::Actor *,bool)> const &,RE::StaticFunctionTag *,RE::Actor *,bool>
[C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\include\type_traits:1714]
add rsp,20h
[7 ] 0x7FF93500E300 SlaveTatsNG.dll+00FE300 RE::BSScript::Impl::CallbackImpl<std::function<bool __cdecl(RE::StaticFunctionTag *,RE::Actor *,bool)> const &,std::tuple<RE::Actor *,bool>,0,1,RE::StaticFunctionTag *>
[C:\Build\SlaveTatsNG\extern\CommonLibSSE\include\RE\N\NativeFunction.h:22]
add rsp,30h
[8 ] 0x7FF93500E17F SlaveTatsNG.dll+00FE17F RE::BSScript::Impl::CallBack<std::function<bool __cdecl(RE::StaticFunctionTag *,RE::Actor *,bool)> const &,std::tuple<RE::Actor *,bool>,RE::StaticFunctionTag *>
[C:\Build\SlaveTatsNG\extern\CommonLibSSE\include\RE\N\NativeFunction.h:31]
add rsp,30h
[9 ] 0x7FF935012687 SlaveTatsNG.dll+0102687 RE::BSScript::NativeFunction<0,bool __cdecl(RE::StaticFunctionTag *,RE::Actor *,bool),bool,RE::StaticFunctionTag *,RE::Actor *,bool>::MarshallAndDispatch
[C:\Build\SlaveTatsNG\extern\CommonLibSSE\include\RE\N\NativeFunction.h:106]
mov [rsp+74h],al
[10] 0x7FF79D478015 SkyrimSE.exe+1378015
test al,al
[11] 0x7FF935082656 SlaveTatsNG.dll+0172656 REL::invoke<enum RE::BSScript::IFunction::CallResult (__cdecl RE::BSScript::NF_util::NativeFunctionBase::*)(RE::BSTSmartPointer<RE::BSScript::Stack,RE::BSTSmartPointerIntrusiveRefCount> const &,RE::BSScript::ErrorLogger *,RE::BSScript::Internal::VirtualMachine *,bool),RE::BSScript::NF_util::NativeFunctionBase *,RE::BSTSmartPointer<RE::BSScript::Stack,RE::BSTSmartPointerIntrusiveRefCount> const &,RE::BSScript::ErrorLogger * &,RE::BSScript::Internal::VirtualMachine * &,bool &>
[C:\Build\SlaveTatsNG\extern\CommonLibSSE\include\REL\Relocation.h:183]
add rsp,68h
[12] 0x7FF935082224 SlaveTatsNG.dll+0172224 REL::Relocation<enum RE::BSScript::IFunction::CallResult (__cdecl RE::BSScript::NF_util::NativeFunctionBase::*)(RE::BSTSmartPointer<RE::BSScript::Stack,RE::BSTSmartPointerIntrusiveRefCount> const &,RE::BSScript::ErrorLogger *,RE::BSScript::Internal::VirtualMachine *,bool)>::operator()<RE::BSScript::NF_util::NativeFunctionBase *,RE::BSTSmartPointer<RE::BSScript::Stack,RE::BSTSmartPointerIntrusiveRefCount> const &,RE::BSScript::ErrorLogger * &,RE::BSScript::Internal::VirtualMachine * &,bool &>
[C:\Build\SlaveTatsNG\extern\CommonLibSSE\include\REL\Relocation.h:272]
add rsp,58h
[13] 0x7FF935081D6D SlaveTatsNG.dll+0171D6D RE::BSScript::NF_util::NativeFunctionBase::Call
[C:\Build\SlaveTatsNG\extern\CommonLibSSE\src\RE\N\NativeFunctionBase.cpp:111]

add rsp,40h

 

Edited by Sorrow_421
Posted (edited)

It's always the same error in all crashlogs, C:\Build\SlaveTatsNG\include\nioverride_wrapper.h:243 :

image.png.308925637ca3eaf8f6dea6e5e1834213.png

And this simply calls the "HasOverlays" function of the skee (RaceMenu) reflection interface.

 

I wouldn't have expected this, because I simply translated the SlaveTats code to C++

 

bool function synchronize_tattoos(Actor target, bool silent = false) global
    int i
    int idx
    int entry
    string area
    int slot
    string path
    int color
    int glow
    bool gloss
    string bump
    float alpha

    Debug.Trace("SlaveTats: Beginning synchronization for " + target.GetLeveledActorBase().GetName())

    if SKSE.GetPluginVersion("skee") < 1 && SKSE.GetPluginVersion("NiOverride") < 1
        notify("SlaveTats requires NiOverride, RaceMenu, or SKEE.", silent)
        return true
    endif

    if NiOverride.HasOverlays(target) != true
        NiOverride.AddOverlays(target)
        Utility.Wait(0.5)
        if NiOverride.HasOverlays(target) != true
            notify("Target is not compatible with overlays.", silent)
            return true
        endif
    endif

 

And the SlaveTats.pex is old, very old, so the SKEE plugin must contain this HasOverlays function, or else why doesn't SlaveTats.pex crashes when it calls this function. I don't understand this atm., perhaps a look at the skee sources helps.

 

Maybe the initialization of the skee reflection interface fails. The code looks like thisimage.png.4bcc35603ba6d71c0e14bd91aee57cce.png

 

So, if it fails, there should be a "skee interface map not found" or an "skee override or overlay interface too old" error in SlaveTatsNG.log (in My Games\Skyrim Special Edition\SKSE). Can anyone with this crash post the SlaveTatsNG.log ?

 

Edit: 

 

Oh, it becomes clearer, I compiled my code with the "skee-modders-resource-v0-4-19-16", but RaceMenu-v0-4-19-16 is for Skyrim 1.6.1170, if I look at the Nexus page of RaceMenu. They must have changed the structure of the reflection interface, so that what I get doesn't fit the header file I compiled my code with. That's very, very ugly, because I don't know when they have changed their interfaces, and how many different versions of SlaveTatsNG I would have to build (if their is no abstraction of the skee interface I could use).

 

Edit (2):

 

The big api change in RaceMenu was the commit from expired6978 on Jun 7, 2023:

 

image.png.3b46846198263bb2d2a6f16cf4e1cf6d.png

 

So principally I have to handle two cases, RaceMenu before and after Jun 7, 2023

 

Edit (3):

 

It seems that Ponzi already does this in OverlayManager, he has tables of the RaceMenu addresses for 97, 640 and 659 (Wow, really great work!) in his "LegacyOverrideInterface", I will try to use this in my code

 

 

 

 

Edited by nopse0
Posted

Do I need to overwrite the original Slave Tats mod to use this one?

Posted
35 minutes ago, Sicumbaka said:

Do I need to overwrite the original Slave Tats mod to use this one?

Yes, the SlaveTats.pex has been changed, it now calls my native functions, so my mod must overwrite SlaveTats. And the orginal SlaveTats is still needed because of the MCM

Posted
39 minutes ago, TikiWikiTam said:

I notice it has "se" available in the downloads section but the title says ae, has this been updated to be compatible with 1.5?

I build the se version, but it will CTD, see crash logs above. This is because of the RaceMenu plugin I am using. It's reflection interface is different for different Skyrim versions (!). Why haven't they done something like JContainers, that you pass in a function name and a function pointer template, and then get back the function address. That is what I would call a reflection interface, not what RaceMenu has done, that is total junk! So I have to do it the old way, get the base address of the RaceMenu DLL, and then get the function addresses via version dependent address tables. Luckily, Ponzi has the knowledge for that :). I will upload a (hopefully) working version soon. 

Posted
6 hours ago, nopse0 said:

I build the se version, but it will CTD, see crash logs above. This is because of the RaceMenu plugin I am using. It's reflection interface is different for different Skyrim versions (!). Why haven't they done something like JContainers, that you pass in a function name and a function pointer template, and then get back the function address. That is what I would call a reflection interface, not what RaceMenu has done, that is total junk! So I have to do it the old way, get the base address of the RaceMenu DLL, and then get the function addresses via version dependent address tables. Luckily, Ponzi has the knowledge for that :). I will upload a (hopefully) working version soon. 

 

Thank you! 

Posted

I'm running Skyrim AE 1.6.1170 and used Vortex to install -- and reinstall -- SlaveTatsNG-0.2.0-all-in-one.7z.  Unfortunately, SKSE throws the following error:

 

image.png.0ac1b953f000efef8dba8be659f258c7.png

 

I did not experience any problems with SlaveTatsNG-0.1.1-ae.7z.  (And many thanks.  SlaveTatsNG is indeed lightning fast.)

Posted
2 hours ago, Maidenslayer said:

I'm running Skyrim AE 1.6.1170 and used Vortex to install -- and reinstall -- SlaveTatsNG-0.2.0-all-in-one.7z.  Unfortunately, SKSE throws the following error:

 

image.png.0ac1b953f000efef8dba8be659f258c7.png

 

I did not experience any problems with SlaveTatsNG-0.1.1-ae.7z.  (And many thanks.  SlaveTatsNG is indeed lightning fast.)

This is strange, I tested it on 1.6.1170 and 1.5.97 (used the full downgrade patcher from Nexus and created a new portable mo2 instance), and it both worked fine for me. Maybe the binary is corrupt (don't believe this, though, 7z uses checksums), try redownload and reinstall. Sure you didn't accidentally installed the 0.1.1-se version I had uploaded, this would explain it ?

Posted

Per my message above regarding this error:

 

image.png.0ac1b953f000efef8dba8be659f258c7.png

 

I re-installed SKSE 2.2.6 and SlaveTatsNG-0.1.1-ae.7z but got the same error.

 

Bear with me (as I'm trying to debug this out as well).

 

You said " used the full downgrade patcher from Nexus".  Were you running SKSE 2.2.6 -- or maybe an earlier version like SKSE 2.2.5 -- when testing?

 

I noticed that CommonLibSSE-NG v3.7.0 was released on May 13, 2023.  (I assume you are using this version.)

 

However, SKSE 2.2.6 was released on January 17, 2024 -- seven months later.  I'm leery when CommonLibSSE-NG's author says their code is 1.6.629+ compatible when it could not have been tested on the latest version when compiled.

 

Again, thanks for investigating.  I look forward to future enhancements.

Posted (edited)
1 hour ago, MellowDrama said:

What does "doesnt send mod events" actually mean?

SlaveTats sends mod events other mods can listen for in synchronize_tattoos when tattoos were added or removed. Sending simple mod events from C++ (with just a string and a number field would be no problem, the SKSE api for that is public (the headers for the public api of SKSE are contained in ComonLibSSE), but the api for the complex events, where you can add additional fields with "Push", like SlaveTats does, is private, you would have to directly use the SKSE sources to do that.

image.png.4a5510ade8b41bf761d102999418cf15.png

 

Ps: Much of what SlaveTats does, could be done more efficiently in C++, e.g. if slavetats needs an array of tattoos, it puts the tattoos into temporary JMap's, and the JMap's into a JArray, in C++ you would use a struct or a class for the objects, and a vector for the array. But I don't try to optimize or change anything in the SlaveTats code, because a) it's highly complex (spagetti? - no, that's too hard, I think you cannot do it much better in Papyrus) and difficult to understand, and b) it is well tested and bug free.

Edited by nopse0
Posted

I believe this mod removes SCOE overlays after Sexlab scene finishes. Tested with this off and this off and FastTats on and the overlay remains, just when turning this on, cum overlays are removed.

 

Wish I could be of more help with that.

Posted (edited)
11 hours ago, AechRO said:

I believe this mod removes SCOE overlays after Sexlab scene finishes. Tested with this off and this off and FastTats on and the overlay remains, just when turning this on, cum overlays are removed.

 

Wish I could be of more help with that.

Darn! Not sure if this is true, but I have one idea. I thought that I had solved all concurrency problems, by letting the SlaveTats functions be executed by the Skyrim main thread. But doesn't SexLab start a thread for each sex scene ?, and are these threads running parallel to the Skyrim main thread ?, and are the cum overlays applied by these SexLab threads ?

 

Edit: No, I had a look at SCO_CumHandler.psc from cum overlays, and I think the problem simply is, that what it does isn't synchronized with SlaveTats, i.e. it uses "NiOverride.GetNodeOverrideString" in the "GetEmptySlot" function to find a free overlay slot, and then in "ApplyOverlay" puts its cum texture into this slot with "NiOverride.SetNodeOverrideString". But in the meantime SlaveTats may also have detected this slot as free, and is using/clearing it (though this would only explain that SCO overwrites SlaveTats tattoos, not the other direction, that SlaveTats overwrites SCO, I don't understand this). The simplest solution would be, to change SCO, so that it applies it's overlays with SlaveTats. I already patched Bathing in Skyrim and Spank that Ass, which also directly apply overlays, to use SlaveTats instead of applying the overlays themself. Maybe I should try to do the same for SCO, and then upload the patches.

 

Edit: I think this concurrency problem always existed, but before, SlaveTats was so slow with all it's native JContainer calls and wait(0.01) calls, that SCO was long done with its things, before SlaveTat started to do anything at all.

Edited by nopse0

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