Jump to content

Recommended Posts

Posted (edited)

Eh man, this is like the funniest update description for an update I have ever read! AHahahah! "Small, but very efficient optimization. Runs about a 100 times faster now". 

 

Yeah like it was going like the speed of light before right, easy stuff. Ya know..... How it is bruh... Shiiiittt...  Eh... I just decided to make it 100 times faster than light.... What can you do.... I mean ya get me right?

I mean it goes faster now than dark energy does! It has no shift it stays a "Gamma" ray all the way. It registers tattoos before the call is made. 

Yo you made my day. Epic stuff.

Edited by Sorrow_421
Posted (edited)

I uploaded a new version. In the old version, "NiOverride::ApplyNodeOverrides(a_target);" was called once per overlay slot (except for externally used slots). This is fatal, because this function takes almost 1 ms (!!!). I am calling it now only once in synchronize_tattoos. For me, this reduced  the time of synchronize_tattoos, simple_add_tattoo and simple_remove_tattoo from 120 ms (noticable lag) to 2 ms.

 

Why takes  NiOverride::ApplyNodeOverrides so long ? Well, in the NiOverride::Apply functions ShaderProperties are edited (that's how NiOverride works). And for this the BSGeometry* of a NiAVObject* is traversed. Either these BSGeometry* trees are gigantic (they contain the same structures you see in NifSkope), or the apply functions are somehow synchronized with the frame rate (the time difference 120 : 2 suggests the latter)

Edited by nopse0
Posted (edited)
8 minutes ago, Sorrow_421 said:

Eh man, this is like the funniest update description for an update I have ever read! AHahahah! "Small, but very efficient optimization. Runs about a 100 times faster now". 

 

Yeah like it was going like the speed of light before right, easy stuff. Ya know..... How it is bruh... Shiiiittt...  Eh... I just decided to make it 100 times faster than light.... What can you do.... I mean ya get me right?

I mean it goes faster now than dark energy does! It has no shift it stays a "Gamma" ray all the way. It registers tattoos before the call is made. 

Yo you made my day. Epic stuff.

Explained it above, small change, but very big difference (with small I mean code size, just had to change a few lines)

Edited by nopse0
Posted
On 8/28/2024 at 10:03 PM, nopse0 said:

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.

Can you give me an example of something that the mod events are needed for?

Posted
2 hours ago, Ricardo-Evans said:

+1, I also want to know the mods affected by it

I don't know of any mods using the SlaveTats mod events or the activate/deactivate_magic functions. But, who knows, there are thousands of mods, so I wanted to clearly state this, so that nobody is disappointed who needs that.

Posted
On 8/26/2024 at 7:31 AM, nopse0 said:

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.

Hi, I don't really know the technical stuff, does this mean that 1) It doesn't work on VR 2) that you will not make a VR patch?

Posted
1 hour ago, bruhfrman said:

Hi, I don't really know the technical stuff, does this mean that 1) It doesn't work on VR 2) that you will not make a VR patch?

No, it should work now on VR. I migrated to CommonLibSSE-NG, which is a "all-in-one" DLL, which should run on everything (at least it claims so, I tested myself on 1.6.1170 and 1.5.97 and it worked fine, so I am quite optimistic, that this is really so).

Posted (edited)
20 minutes ago, Unknown22923 said:

Old bug, did you update to the latest version?

Yes, external overlays were not detected and removed in versions < 0.3. It may also be that you have overlays applied with SlaveTats texture paths ("actors\character\slavetats\...") which aren't contained in the SlaveTats JContainer database of applied tattoos. Then SlaveTats thinks this are removed tattoos, and removes them (FastTats screwed up JContainers, I think)

Edited by nopse0
Posted (edited)
7 hours ago, Unknown22923 said:

Old bug, did you update to the latest version?

Yeah now it only seems to be breast veins that get removed on any overlay being added via slavetats or other mods. It's weird its the only thing that gets removed now. 

Edited by eclipsed7774
Posted
2 hours ago, eclipsed7774 said:

Yeah now it only seems to be breast veins that get removed on any overlay being added via slavetats or other mods. It's weird its the only thing that gets removed now. 

Not sure what breast veins you refer to but the one from Being a cow (BAC) works fine for me, did you remember to add more iNumOverlays in your SKSE64.ini or nioverride.ini ?

Posted (edited)
2 hours ago, Unknown22923 said:

Not sure what breast veins you refer to but the one from Being a cow (BAC) works fine for me, did you remember to add more iNumOverlays in your SKSE64.ini or nioverride.ini ?

Yeah, I'm talking about the veins from Pema's mod its pretty much the only one for slavetats or racemenu

 

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

Yeah, I'm talking about the veins from Pema's mod its pretty much the only one for slavetats or racemenu

 

One thing which may be helpful, skee has console commands. With "skee help" you can see a list of the commands.

 

skee dump overrides     - dumps the applied overrides to skee64.log

skee dump overlays       - dumps the applied overlays to skee64.log

 

I think there is also a command to dump what is attached to the skeleton

 

 

Edited by nopse0
Posted
19 hours ago, nopse0 said:

Yes, external overlays were not detected and removed in versions < 0.3. It may also be that you have overlays applied with SlaveTats texture paths ("actors\character\slavetats\...") which aren't contained in the SlaveTats JContainer database of applied tattoos. Then SlaveTats thinks this are removed tattoos, and removes them (FastTats screwed up JContainers, I think)

Oh I thought cuz SL fame framework (I think SLS) can see if you have tats on your body and give you reputation for whatever the tat is.

That wouldn't be affected?

Posted (edited)
6 hours ago, MellowDrama said:

Oh I thought cuz SL fame framework (I think SLS) can see if you have tats on your body and give you reputation for whatever the tat is.

That wouldn't be affected?

Not sure how you mean that. I had a look into "SLSF_Monitor.psc", and it simply calls "SlaveTats.Query_applied_tattoos", so Sexual Fame Framework sees exactly the same as SlaveTats. If SlaveTats doesn't know about a tatto, then SLSF also doesn't know about it. What I wanted to say in my comment above, is, that the SlaveTats JContainer database (what you see in the MCM) may not be in sync with what you currently have on your body (I _think_ (I have no proof for that), that this is possible, if you have run FastTats before, or, maybe, because the Papyrus SlaveTats corrupted its own database because of concurrency problems)

Edited by nopse0
Posted

Hiya, VR player here and I can say that with this mod installed, SkyrimVR will not boot up.  Took a bit of trouble shooting before I was able to track it down to this mod but I can't boot into SkyrimVR unless I disable this mod.

Posted (edited)
7 hours ago, kamithemoon said:

Hiya, VR player here and I can say that with this mod installed, SkyrimVR will not boot up.  Took a bit of trouble shooting before I was able to track it down to this mod but I can't boot into SkyrimVR unless I disable this mod.

More information would be nice. Does it fail immediately when the DLL's are loaded (dialog box from skse), or later on, when my plugin initializes (CTD) ? In the first case, CommonLibSSE-NG doesn't keep what it promises, in the latter case probably the addresses for the skee64.dll (RaceMenu) used on VR are missing:

Spoiler

image.png.f21ff68b61145a1df434906ac38d99a0.png

Spoiler

                    static inline std::array<int, 12> _offsets97{
                        0xBE160,
                        0xBE090,
                        0xBE2F0,
                        0xBD9E0,
                        0xBD780,
                        0xBDC30,
                        0x99D80,
                        0x9A1D0,
                        0x99D30,
                        0x99760,
                        0x99780,
                        0x997A0
                    };

                    static inline std::array<int, 12> _offsets640{
                        0xCA230,
                        0xCA160,
                        0xCA3C0,
                        0xC9AD0,
                        0xC9860,
                        0xC9D20,
                        0xA5940,
                        0xA5CA0,
                        0xA5930,
                        0xA5350,
                        0xA53D0,
                        0xA53F0
                    };

                    static inline std::array<int, 12> _offsets659{
                        0xCA390,
                        0xCA2C0,
                        0xCA520,
                        0xC9C30,
                        0xC99C0,
                        0xC9E80,
                        0xA5AA0,
                        0xA5E00,
                        0xA5A90,
                        0xA54B0,
                        0xA5530,
                        0xA5550
                    };

If someone finds out, what version number skyrim vr has, and the function addresses of the skee64.dll (with a hex editor, visual studio, or so) used on vr, I could add them.

 

What also is version specific, is the name of the JContainers DLL:

Spoiler

image.png.490ad6e31245bedbd5778061ac400df7.png

Upload SlaveTatsNG.log (in a spoiler or so)

Edited by nopse0
Posted

Oh, I'd love to help VR troubleshooting, if you could please walk me through on how to get the information you need.

 

What happens with this installed on a VR game is that it will hang while booting rather then CTD.  I can see it in task manager that Skyrim will start at 5% my computer's resources then immediately drop to 0% and will do nothing further.  Without this mod, I'll start at 5% resources, ramp up to about 14% then the game will start.

Posted
On 8/28/2024 at 1:03 PM, nopse0 said:

spagetti? - no, that's too hard, I think you cannot do it much better in Papyrus

 

Got that right. The whole process of writing SlaveTats was repeatedly stubbing my toe on Papyrus's inability to properly abstract things, and being forced to do something silly to work around it.

Posted (edited)
4 hours ago, murfk said:

 

Got that right. The whole process of writing SlaveTats was repeatedly stubbing my toe on Papyrus's inability to properly abstract things, and being forced to do something silly to work around it.

Yes, but don't worry. I was very surprised, JContainers is mega efficient, the JContainer calls take almost no time at all. I noticed that in my optimization comment above, I have 120 overlay slots, and synchronize_tattoos took 120 ms, then I changed the code, so that NiOverride::ApplyNodeOverrides is called only once in synchronize_tattoos, instead of once per overlay slot, and the time reduced to 2 ms (so the 10000 or so JContainer calls take only 1 ms). So, I think, it's not needed to replace the JContainer data structures with C++ structures, the time you win by doing so is minimal.

Edited by nopse0
Posted
On 9/4/2024 at 12:55 PM, nopse0 said:

More information would be nice. Does it fail immediately when the DLL's are loaded (dialog box from skse), or later on, when my plugin initializes (CTD) ? In the first case, CommonLibSSE-NG doesn't keep what it promises, in the latter case probably the addresses for the skee64.dll (RaceMenu) used on VR are missing:

  Reveal hidden contents

image.png.f21ff68b61145a1df434906ac38d99a0.png

  Reveal hidden contents

                    static inline std::array<int, 12> _offsets97{
                        0xBE160,
                        0xBE090,
                        0xBE2F0,
                        0xBD9E0,
                        0xBD780,
                        0xBDC30,
                        0x99D80,
                        0x9A1D0,
                        0x99D30,
                        0x99760,
                        0x99780,
                        0x997A0
                    };

                    static inline std::array<int, 12> _offsets640{
                        0xCA230,
                        0xCA160,
                        0xCA3C0,
                        0xC9AD0,
                        0xC9860,
                        0xC9D20,
                        0xA5940,
                        0xA5CA0,
                        0xA5930,
                        0xA5350,
                        0xA53D0,
                        0xA53F0
                    };

                    static inline std::array<int, 12> _offsets659{
                        0xCA390,
                        0xCA2C0,
                        0xCA520,
                        0xC9C30,
                        0xC99C0,
                        0xC9E80,
                        0xA5AA0,
                        0xA5E00,
                        0xA5A90,
                        0xA54B0,
                        0xA5530,
                        0xA5550
                    };

If someone finds out, what version number skyrim vr has, and the function addresses of the skee64.dll (with a hex editor, visual studio, or so) used on vr, I could add them.

 

What also is version specific, is the name of the JContainers DLL:

  Reveal hidden contents

image.png.490ad6e31245bedbd5778061ac400df7.png

Upload SlaveTatsNG.log (in a spoiler or so)

Well for a start, I believe the dll used in vr is skeevr.dll not skee64.dll

 

I am willing to help and have imhex and visual studio, but how can I find the addresses?

Posted (edited)
7 hours ago, segaegae said:

Well for a start, I believe the dll used in vr is skeevr.dll not skee64.dll

 

I am willing to help and have imhex and visual studio, but how can I find the addresses?

Can you post the log "C:\users\<your name>\Documents\My Games\Skyrim Special Edition\SKSE\SlaveTatsNG.log" ? It prints out some information about the game version, and DLL's it finds, and what addresses it uses.

 

My idea to find out the addresses (never did this though, don't know if this is feasible), would be that you have both, a supported version and vr, installed. First look in one of the supported versions, what's at the known address offsets (hex dump bytes and/or dissassembly) and try to spot a significant byte sequence of the function, and then try to find the same byte sequence in the vr version (I don't know if the in memory offsets are the same as the offsets in the DLL file, so I think the best would be to search the byte sequence in memory starting from the base address of the loaded DLL). And then, if you have found the byte sequence, you have to find out where the function actually starts (maybe one can see this in the disassembler, or perhaps, if you are lucky, and the same compiler and optimization options were used, the offset from the byte sequence to the start of the function is the same).

 

You can set breakpoints with Visual Studio (perhaps in the function, where I add the offsets to the base address of the DLL to get the function addresses), but you have to fork a new thread to execute the code where you want to set the breakpoint (the Skyrim threads don't support catching breakpoint exceptions). For example I did this in the simple_add_tattoo function:

		fail_t simple_add_tattoo(RE::StaticFunctionTag*, RE::Actor* a_target, RE::BSFixedString a_section, RE::BSFixedString a_name, int a_color,
			bool a_last = true, bool a_silent = false, float a_alpha = 1.0f)
		{
			fail_t result = false;
			std::thread t1
			{
				[&] {
					result = ng::simple_add_tattoo(a_target, a_section.c_str(), a_name.c_str(), a_color, a_last, a_silent, a_alpha);
					logger::info("result is {}", result);
				}
			};
			t1.join();
			return result;
		}

 

Then you can set a breakpoint in the line with ng::simple_add_tattoo (or in any function called by it), and the visual studio debugger stops there.

 

Or, on second thought, much easier, write a program which calls the NIOverride functions, we want the addresses of, surround it with the fork and join thread pattern from above, so that you can set breakpoints in it, and then switch to dissasembly, and single step the assembler instructions until you get into the skeevr.dll, note the address, note the offset to the dll base address, and, voilas, done.

 

Edit: Forget it, we cannot call functions, we don't know the addresses of (that's the problem), only the Papyrus VM knows them, because SKEE registered them there)

 

Edit: I tried a while to support the old override and overlay plugin interface, which is used in the VR skee version, and finally gave up. Because the variant class which is used in the old interface for passing in and returning different types of values doesn't contain virtual methods you could override, (and to make things worse, it even uses a global string table from SKEE), so you would have to use a variant class with exactly the same memory layout as the variant class from the skee sources. So the only chance is getting the addresses of the low level functions without the variant stuff.

 

Maybe expired6978 can merge his changes he made in the master branch when he changed the override and overlay plugin interface to the new version into the vr branch, and release a new skeevr version.

 

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...