Jump to content

SexLab Framework Development


Recommended Posts

I reverted to 1.60.2 and the freezes are gone - I think the problem must be related to the new PapyrusUtils - unfortunately there is no source code and no debug version - so I can't jump to DevStudio to see where PapyrusUtils stucks.

Now I try 1.61 with old PapyrusUtils

Link to comment

 

Oh sure I could use your GetAlltags to make a list of it for the player to choose from, I was just wondering if such a function existed actually.

 

 

 

 

Here the function to get all the tags (actually there is also the sorting function, because if tags are not sorted then is a mess to find them.)

 

 

 

 
SexLabFramework Property SexLab Auto
sslAnimationSlots AnimSlots
sslCreatureAnimationSlots CreatureSlots
 

Event OnInit()
  Form SexLabQuestRegistry = Game.GetFormFromFile(0x664FB, "SexLab.esm")
  if SexLabQuestRegistry
    CreatureSlots = SexLabQuestRegistry as sslCreatureAnimationSlots
  else
    log("Could not find SexLab.esm! Check your installation!")
  endIf
  Form SexLabQuestAnimations = Game.GetFormFromFile(0x639DF, "SexLab.esm")
  if SexLabQuestAnimations
    AnimSlots = SexLabQuestAnimations as sslAnimationSlots
  else
    log("Could not find SexLab.esm! Check your installation!")
  endIf
EndEvent
 

String[] Function getAllAnimationTags(int actorsCount=-1, int includeCreatures=-1)
{Scans all the SexLab animations and grab all possible tags. If ActorsCount is specified, then only the animations with the specified actors count are used. If includeCreatures=0 then only human animations are checked, if =1 only creatures.}
  String[] resTags = Utility.CreateStringArray(256)
  int numFoundTags = 0
 
  if includeCreatures!=1
    ; Human animations
    int i = AnimSlots.GetCount(false)
    while i
      i -= 1
      sslBaseAnimation a = AnimSlots.GetBySlot(i)
      if a && a.Registered && a.Enabled && (actorsCount==-1 || actorsCount==a.PositionCount) ; The animation is valid
        String[] animTags = a.getRawTags()
        int t = animTags.length
        while t
          t -= 1
          String tag = animTags[t]
          if tag && resTags.find(tag)==-1
            resTags[numFoundTags] = tag
            numFoundTags += 1
            if numFoundTags==resTags.length
              i = 0
            endIf
          endIf
        endWhile
      endIf
    endWhile
  endIf
  if includeCreatures!=0
    ; Creature animations
    int i = CreatureSlots.GetCount(false)
    while i
      i -= 1
      sslBaseAnimation a = CreatureSlots.GetBySlot(i)
      if a && a.Registered && a.Enabled && (actorsCount==-1 || actorsCount==a.PositionCount) ; The animation is valid
        String[] animTags = a.getRawTags()
        int t = animTags.length
        while t
          t -= 1
          String tag = animTags[t]
          if tag && resTags.find(tag)==-1
            resTags[numFoundTags] = tag
            numFoundTags += 1
            if numFoundTags==resTags.length
              i = 0
            endIf
          endIf
        endWhile
      endIf
    endWhile
  endIf
 
  return sortNumString(numFoundTags, resTags)
EndFunction
 
 

String[] Function sortNumString(int num, String[] arr) global
{Produces an array of strings by sorting the first "num" items of the source array}
  ; Sort the array
  String[] sortedS = Utility.CreateStringArray(num, "")
  ; Sort the tags
  int sToDo = 0
  while sToDo < num
    ; Find the minimum one
    String minS = "~~~~"
    int pos = num
    int selPos = -1
    while pos
      pos -= 1
      if arr[pos]!=""
        if compareStr(arr[pos], minS)
          minS = arr[pos]
          selPos = pos
        endIf
      endIf
    endWhile
    if selPos!=-1
      sortedS[sToDo] = minS + ""
      arr[selPos] = ""
      sToDo += 1
    else
      debug.trace("SSX: CRITICAL! sToDo=" + sToDo + " num=" + num)
      sToDo = num
    endIf
  endWhile
  return sortedS
EndFunction
 
 

bool Function compareStr(String a, String  global
{Compares two strings and returns True if the first string is lower or equal than the second}
  if a==b
    return true
  endIf
 
  ; Go for 3 chars at time, put them in an int to do a quick compare
  int pos = 0
  int l2 = StringUtil.GetLength(
  int max = StringUtil.GetLength(a)
  if max > l2
    max = l2
  endIf
  
  while pos < max
    int va = getStringVal(a, pos)
    int vb = getStringVal(b, pos)
    if va < vb
      return true
    elseIf va > vb
      return false
    endIf
    pos += 3
  endWhile
  return false
EndFunction
 
 

int Function getStringVal(String s, int pos) global
{Returns an Int of the character in the "pos" position of the string of the String}
  int len = StringUtil.GetLength(s)
  int res = 0
  int done = 0
  while pos < len && done < 3
    int v = StringUtil.AsOrd(StringUtil.GetNthChar(s, pos))
    if v > 96 && v<123 ; Letters are between 65 and 90, Skyrim is not case sensitive, so everything should be compared uppercase
      v -= 32
    endIf
    res *= 256
    res += v
    done += 1
    pos += 1
  endWhile
  while done < 3
    res *= 256
    done += 1
  endWhile
  return res
EndFunction


 



 

 

Link to comment

I have no freezes if I use the old 1.60.2 PapyrusUtils with the new Sexlab 1.61b2.

 

Something seems to be broken in the new PapyrusUtils. There is absolutely no indication in any log - the game is simply frozen.

 

In MariaEden 2.0 I have a "Bob the Builder" function that uses JSon Utils and Storage Utils excessively for persistent cell modifications.
 Did you changed the way how form-objects are alocated by form-functions? This could be a reason for freezes.

 

Additionally the automatic free camera feature is defunct.

Link to comment

1.61 Beta 3

What's New In 1.61 Beta 3:

  • Added: NiOverride High Heel handling, bundled into current HDT High Heel handing option in MCM
  • Added: Basic support for Frostfall 3, player exposure is paused during animation.
  • Fixed: Auto TFC
  • Fixed: Orgasm effect camera shake
  • Fixed:  Error log spam when searching animation lists after some have been unregistered
  • Added: API functions for GetAllAnimationTags, GetAllCreatureAnimationTags, GetAllBothAnimationTags, GetAllAnimationTagsInArray
  • Added: API functions for HasCreatureRaceAnimation and HasCreatureRaceKeyAnimation
  • Updated: PapyrusUtil to 3.2 beta with various new functions to accommodate various other things I don't feel like documenting/remembering right now.

 

What's New In 1.61 Beta 2:

  • Many tweaks to animation startup that should (hopefully) fix the async issue for most scenarios. - it is unlikely to ever be perfect, but should be mostly reliable now at least. In case of failure, just press realign actors hotkey to fix it.
  • Added support for suppressing NiOverride High Heels same as HDT High Heels has been previously supported (and improved this version)
  • Added API function for getting the amount of cum applied to a specific region for an actor
  • Added API function to sslThreadModel allowing mods to define a specific starting animation instead of it being random fromn the list
  • Added API function to shuffle an array of animations so it isn't always in t he same order
  • Various tweaks to the positioning of various animations, mostly related to the many bed complaints.
  • Some SKSE plugin CTD fixes for SexLabUtil as suggested by Earen and also carried over into the included StorageUtil build.
  • Hopefully fixed the instant orgasm bug that happens when starting an animation while separate orgasms option is enabled.
  • Various other bug fixes and improvements you probably don't care about and I don't remember.

What's New in 1.61 Beta 1:

  • Toggle option in MCM to have characters walk over to where the scene will take place, rather than teleport directly to it.
  • The cum effect on characters can now "stack" up to two levels, so there is visually more cum when repeating the same type of acts within a short time. Thanks to Vacaliga for the textures.
  • Basic support for creatures to have voices, along with several starting default ones for most basic creatures.
  • To help when using the adjustment hotkeys, there is now an audible sound when adjusting a character
  • When changing which actor you want to adjust in a scene, there is now a more direct visual indication which actor you have selected in addition to the previous notification 
  • Toggle option in MCM to edit a target NPCs gender instead of only the players
  • Toggle option in MCM to pick whether or not newly encountered NPCs should have their starting sex stats seeded or start empty
  • Option in MCM to disable the use bed prompt always, never, or only when victim.
  • MCM button to erase/reset all saved NPC sex stats
  • Some other stuff I've forgotten
  • Various bug fixes

REQUIRES EXISTING 1.60 OR 1.61 beta INSTALL

<download removed, 1.61 official is released, use that instead.>

 

 

Link to comment

SL Beta3 Papyrus utils freezes my game very fast. Again nothing visible in logs - at least not for me.

 

Update: Unfortunately it is no longer possible to use the old Papyrus utils (SortStringArray, FrostUtil).

 

You're literally the only person reporting constant freezes with the beta right now, most others have been reporting improved stability if anything. Which isn't to say you're wrong, just that it's very likely something very specific to your setup, or Maria Eden 2.0 specifically, which I'll admit I don't use or ever test with myself. 

 

If you could narrow it down to specific functions within Maria Eden by removing the most likely elements from it one by one, even if it breaks maria eden overall, until sexlab stops freezing for you, it would be a huge help. If you could even at least simply point me in the right direction of the likely causes within Maria Eden's functions, it would save me a lot of investigation time, especially since I'm completely unfamiliar with it's source code currently, and I assume the options are mostly or all in German. 

Link to comment

 

1.61 Beta 3

What's New In 1.61 Beta 3:

.snip.

  • Added: API functions for GetAllAnimationTags, GetAllCreatureAnimationTags, GetAllBothAnimationTags, GetAllAnimationTagsInArray
  • Added: API functions for HasCreatureRaceAnimation and HasCreatureRaceKeyAnimation

.snip.

 

Whoa. Nice.

Now I have to update the mod I am doing (I was hoping to release it this week) and use the new version, and impose it.

(That was just a joke   :P , right now...)

 

But for sure I will compare the performance of my versions with your, because I am expecting a huge increase in speed because writing these functions directly in SexLab will reduce the number of calls to about one third.

Link to comment

Is the current PapyrusUtil beta available as a separate download? I would like to test current SL beta with Campfire/Frostfall, but do so by overwriting my whole load order with PapyrusUtil beta. Reason for this is that conflicting versions of PapyrusUtil seem to cause some problems in game and Chesko used parts of PapyrusUtil in Campfire.

 

I can of course just swap SL and Campfire places in MO, but I think that letting PapyrusUtil to win all conflicts in my game would be worth to test, seeing that I will likely end up doing that any way to avoid possible problems.

 

 

Link to comment
 
 

 

 

SL Beta3 Papyrus utils freezes my game very fast. Again nothing visible in logs - at least not for me.

 

Update: Unfortunately it is no longer possible to use the old Papyrus utils (SortStringArray, FrostUtil).

 

You're literally the only person reporting constant freezes with the beta right now, most others have been reporting improved stability if anything. Which isn't to say you're wrong, just that it's very likely something very specific to your setup, or Maria Eden 2.0 specifically, which I'll admit I don't use or ever test with myself. 

 

If you could narrow it down to specific functions within Maria Eden by removing the most likely elements from it one by one, even if it breaks maria eden overall, until sexlab stops freezing for you, it would be a huge help. If you could even at least simply point me in the right direction of the likely causes within Maria Eden's functions, it would save me a lot of investigation time, especially since I'm completely unfamiliar with it's source code currently, and I assume the options are mostly or all in German. 

 

 

On every cell change I'll call

function Build(Cell theCell)
	; build cell only once
	if !StorageUtil.FormListHas(none,"MariaBuilder",theCell)
		return
	else
		StorageUtil.FormListRemove(none,"MariaBuilder",theCell)
	endif

	string cname = GetCellFileName(theCell)

	; remove objects
	int i = JsonUtil.FormListCount(cname,"removal")
	while i > 0
		i -= 1
		ObjectReference ref = JsonUtil.FormListGet(cname,"removal",i) as ObjectReference
		if ref
			ref.Disable()
			ref.Delete()
		endif
	endwhile

	; move objects
	i = JsonUtil.FormListCount(cname,"moveobject")
	while i > 0
		i -= 1
		ObjectReference objRef = JsonUtil.FormListGet(cname,"moveobject",i) as ObjectReference
		if objRef
			string posstring = JsonUtil.StringListGet(cname,"moveposition",i)
			string[] p = StringUtil.Split(posstring,",")
			objRef.SetPosition(p[0] as float,p[1] as float,p[2] as float)
			objRef.SetAngle(p[3] as float,p[4] as float,p[5] as float)
			objRef.SetScale(p[6] as float)
		endif
	endwhile

	; create objects
	i = JsonUtil.FormListCount(cname,"addform")
	while i > 0
		i -= 1
		BuildObject(theCell,cname,i)
	endwhile

	; create whores
	i = JsonUtil.StringListCount(cname,"whoreposition")
	while i > 0
		i -= 1
		BuildWhore(theCell,cname,i)
	endwhile
endfunction

The function to build an actor looks like

function BuildWhore(Cell ocell,string cname,int i)
	string posstring = JsonUtil.StringListGet(cname,"whoreposition",i)
	string[] p = StringUtil.Split(posstring,",")
	Actor npc = PlayerRef.PlaceActorAtMe(MariaBuilderWhore,1)
	npc.EnableAI(false)
	npc.SetPosition(p[0] as float,p[1] as float,p[2] as float)
	npc.SetAngle(p[3] as float,p[4] as float,p[5] as float)
	EquipRandomOutfit(npc,"whore")
	Actor pimp = JsonUtil.FormListGet(cname,"whoreowner",i) as Actor
	RegisterWhoreLocal(pimp,npc,pimp != none)
	if !StorageUtil.FormListHas(none,"Pimps",pimp)
		RegisterPimp(ocell,pimp)
	endif
	npc.EnableAI(true)
endfunction

And the function to create objects

function BuildObject(Cell ocell,string cname,int i)
	Form oform = JsonUtil.FormListGet(cname,"addform",i)
	Actor objOwner = JsonUtil.FormListGet(cname,"addowner",i) as Actor
	string posstring = JsonUtil.StringListGet(cname,"addposition",i)
	string[] p = StringUtil.Split(posstring,",")

	Trace("Build " + oform.GetName() + " in " + ocell.GetName())

	ObjectReference objRef = PlayerRef.PlaceAtMe(oform,1,true,true)
	objRef.SetFactionOwner(MariaWhoreFaction)
	objRef.SetActorOwner(PlayerRef.GetActorBase())
	StorageUtil.FormListAdd(none,"MariaBuilderObjects",objRef,false)
	objRef.SetPosition(p[0] as float,p[1] as float,p[2] as float)
	objRef.SetAngle(p[3] as float,p[4] as float,p[5] as float)
	objRef.SetScale(p[6] as float)
	objRef.Enable()
	int oformID = oform.GetFormID()
	if oformID == 0xAA041
		; cage door
		objRef = objRef.PlaceAtMe(Game.GetForm(0xAA043),1,true)
		objRef.SetFactionOwner(none)
		objRef.SetActorOwner(none)
		StorageUtil.FormListAdd(none,"MariaBuilderObjects",objRef,false)
	elseif oformID == 0xCE0AE
		objRef = objRef.PlaceAtMe(Game.GetForm(0xCE0AB),1,true)
		objRef.SetFactionOwner(none)
		objRef.SetActorOwner(none)
		StorageUtil.FormListAdd(none,"MariaBuilderObjects",objRef,false)
	elseif oformID == MariasDanceSpot.GetFormID()
		if objOwner
			RegisterDanceSpot(objOwner,objRef)
		endif
		objRef.GetBaseObject().SetName("DanceSpot")
		RegisterLocalDanceSpot(ocell,objRef)
	elseif oformID == MariasFreakShowSpot.GetFormID()
		if objOwner
			RegisterFreakShowSpot(objOwner,objRef)
		endif
		objRef.GetBaseObject().SetName("RegisterFreakShowSpot")
		RegisterLocalFreakShowSpot(ocell,objRef)
	endif
endfunction

I bet my hat that the problem is located in JsonUtil.FormListGet() - something must be changed in this function

 

 
Link to comment

I bet my hat that the problem is located in JsonUtil.FormListGet() - something must be changed in this function

The handling of forms in JsonUtil changed between beta 2 and beta 3, but there was absolutely zero significant changes for all of JsonUtil between 1.60 and 1.61. The recent change though was more or less just more error checking for whether or not a given json value is formatted like a form value and thus should be parsed as a form or not. This change happened in beta 3, so I have me doubts it'd be the cause if you experienced the same in beta 2.

 

For performance reasons though, I'd highly suggest replacing every loop you're doing using Json/StorageUtil.ListCount() with an actual array loop instead.

 

for example:

string[] movepositions = JsonUtil.FormListToArray(cname, "moveobject")
form[] moveobjects = JsonUtil.FormListToArray(cname, "moveobject")
i = moveobjects.Length
while i > 0
	i -= 1
	ObjectReference objRef = moveobjects[i] as ObjectReference
	if objRef
		string[] p = StringUtil.Split(movepositions[i],",")
		objRef.SetPosition(p[0] as float,p[1] as float,p[2] as float)
		objRef.SetAngle(p[3] as float,p[4] as float,p[5] as float)
		objRef.SetScale(p[6] as float)
	endif
endwhile
Even that though is honestly kinda dirty... you should really just keep a float list that offsets the values each loop instead of a string list to be split, basically same method SexLab uses to store position offset data.

 

If you're really sure that's the cause though, could you send me your relevant .json files so I can examine and test them?

Link to comment
 
 

 

 

I bet my hat that the problem is located in JsonUtil.FormListGet() - something must be changed in this function


The handling of forms in JsonUtil changed between beta 2 and beta 3, but there was absolutely zero significant changes for all of JsonUtil between 1.60 and 1.61. The recent change though was more or less just more error checking for whether or not a given json value is formatted like a form value and thus should be parsed as a form or not. This change happened in beta 3, so I have me doubts it'd be the cause if you experienced the same in beta 2.

For performance reasons though, I'd highly suggest replacing every loop you're doing using Json/StorageUtil.ListCount() with an actual array loop instead.

for example:
string[] movepositions = JsonUtil.FormListToArray(cname, "moveobject")
form[] moveobjects = JsonUtil.FormListToArray(cname, "moveobject")
i = moveobjects.Length
while i > 0
	i -= 1
	ObjectReference objRef = moveobjects[i] as ObjectReference
	if objRef
		string[] p = StringUtil.Split(movepositions[i],",")
		objRef.SetPosition(p[0] as float,p[1] as float,p[2] as float)
		objRef.SetAngle(p[3] as float,p[4] as float,p[5] as float)
		objRef.SetScale(p[6] as float)
	endif
endwhile
Even that though is honestly kinda dirty... you should really just keep a float list that offsets the values each loop instead of a string list to be split, basically same method SexLab uses to store position offset data.

If you're really sure that's the cause though, could you send me your relevant .json files so I can examine and test them?

 

 

Changing to array is only possible if you do not filter null-Forms - this must be alway true:

Form[] formArray = JsonUtil.FormListToArray(cname, "moveobject")

if formArray.Length == JsonUtil.FormListCount(cname, "moveobject")
   ...

 

 

Link to comment

Hi,

 

I am getting compiler errors with Beta 2 and 3. Do I need any other files then provided in the Zip? (I do not use High Heels and Frostfall.)

D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(297,31): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(297,42): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(298,19): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(298,30): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(303,5): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(303,16): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(304,5): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(304,16): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(704,31): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(704,42): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(705,5): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslActorAlias.psc(705,16): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(696,61): variable NiOverride is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(696,72): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(696,91): cannot compare a none to a int (cast missing or types unrelated)
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(696,91): cannot relatively compare variables to None
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(704,20): variable FrostUtil is undefined
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(704,30): none is not a known user-defined type
D:\Steam\steamapps\common\Skyrim\Data\scripts\source\sslSystemConfig.psc(704,50): none is not a known user-defined type
Link to comment

The beta 3 added a Frostfall dependency, which added a Campfire dependency which added a Equipping Overhaul dependency. :P

So you now need the source script of those mods to compile.

 

They are "soft" dependencies.

You can install and run SexLab also if you don't have these mods.

 

But if you need to compile it, then you need the source mods. (Or a fake stub mod for compiling purposes. I do it all the times.)

Oh.

May I vote for independency? :D (I have so much mods already installed and for new users it is complicating installation, frightening them away)

Ehm. Will this be also this way in the final?

If not, I am going for the "uncommenting" way.

 

Relax. You don't need these extra mods if you don't use them.

They are soft dependencies. If they are there, then they are used, if they are not installed, SexLab will just ignore them.

Link to comment

 

They are "soft" dependencies.

You can install and run SexLab also if you don't have these mods.

 

But if you need to compile it, then you need the source mods. (Or a fake stub mod for compiling purposes. I do it all the times.)

 

I know, I though it was clear when I said you need the source scripts to compile, I shouldn't have used the word dependency maybe. :P

Link to comment

Hey there Ashal!

Merry Christmas to you and everyone else in here!

Tested the latest beta and the problem I was having with the 1.60.2 build is still around. Checked it with a fresh install too.

You might remember since you replied in this thread:

http://www.loverslab.com/topic/53418-question-about-facial-animations/

Sadly the problem remains with the latest update too and while i don't see anyone else caring about this (other than that few

people in the thread), it pretty much prevents me from doing any screenshooting done with sexlab. Since I don't want to come

off as an asshole who's demanding things left and right, this is my last go at this one before I abandon all hope.

Thanks for all your hard work and I wish you and everyone a happy new year!

 

I've been having this issue as well. I can't work with the facial animations that come with SL and I generally do them manually. I'm getting the same thing as this guy. Help plz.

 

Link to comment

Is the current PapyrusUtil beta available as a separate download? I would like to test current SL beta with Campfire/Frostfall, but do so by overwriting my whole load order with PapyrusUtil beta. Reason for this is that conflicting versions of PapyrusUtil seem to cause some problems in game and Chesko used parts of PapyrusUtil in Campfire.

 

I can of course just swap SL and Campfire places in MO, but I think that letting PapyrusUtil to win all conflicts in my game would be worth to test, seeing that I will likely end up doing that any way to avoid possible problems.

I would like that as well. I am still working on the older version but like having the newest version separate to avoid the conflicts and general headaches. It is well worth the added entry in MO :)

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