Jump to content

SexLab Framework Development


Recommended Posts

Posted

I've got a new set of API tools for modders some may find interesting, planning on releasing it tomorrow as v1.55 along with the double MCM fix, I've got it working I just need to clean up and put it through it's paces. 

 

Mods can now create customized ephemeral animations, voices, and expressions that won't show up in the MCM or be searchable by other mods by the normal means, unless they know the identifier for them, useful for crafting specialized or niche scenes. Namely Devious Devices and Zaz could probably find an immediate use for this, but it should also be real useful for any mod that wants to create custom animations pieced together from various other existing animations with different offsets or stage orders.

 

Known internally and via API as "phantom" slots, because I found the more typographically friendly "ephemeral" annoying to type while coding it; Once created the phantom animation/voice/expression will persist so they can be reused without having to recreate them constantly, after 1 hour of real life play time the phantom object will expire and be cleared next time the save is loaded.

 

Here's a quick example I used during testing (function syntax not final)

 

There are two methods of creating a custom animation/voice/expression, one is to create it on the fly.

; // Create and return the ephemeral animation
sslBaseAnimation Custom = SexLab.NewAnimation("MyCustomAnimation")

; // Set the name of the animation, optional but useful for reference
Custom.Name = "THIS IS MY CUSTOM ANIMATION, BITCH!"

; // Add a single female position using 3 different stages of totally different animations
int a1 = Custom.AddPosition(Female)
Custom.AddPositionStage(a1, "Bleagh_FemaleSolo_A1_S1", 0)
Custom.AddPositionStage(a1, "AP_Cowgirl_A1_S3", 0)
Custom.AddPositionStage(a1, "Arrok_ReverseCowgirl_A2_S4", 0)

; // Tell the animation it's done being setup so it can finalize all the stuff it needs to
Custom.PhantomSave()

; // Use the animation in a basic scene
sslThreadModel Thread = SexLab.NewThread()
; // sslThreadModel.AddAnimation() is also new function being added in 1.55, adds a single animaton
; // to the scene on top of any aniamtions that may or may not have already been set in the scene
Thread.AddAnimation(Anim)
Thread.AddActor(PlayerRef)
Thread.StartThread()

Or, using a voice as example this time, there is animation, voice, and expression versions of all these functions. You can get an already created temporary voice if it still exists, and if it doesn't exists create it via callback.

function StartScene()
	; // Get an already created ephemeral voice, or create it via callback if it hasn't been made yet
	; // the 3rd argument here, "self" tells it what script contains the callback event "MyCallback" for creating the voice
	; // if it hasn't already been created, if PlayerTemporaryVoice already exists, it will simply be returned
	sslBaseVoice CustomVoice = SexLab.GetSetVoice("PlayerTemporaryVoice", "MyCallback", self)

	; // Start a basic scene
	sslThreadModel Thread = SexLab.NewThread()
	Thread.AddActor(PlayerRef, Voice = CustomVoice) ; // Assign player the custom ephemeral voice created by MyCallback
	Thread.StartThread()
endFunction

event MyCallback(string token)
	; // Get the voice being created via callback from the SKSE modevent token argument 
	sslBaseVoice Voice = SexLab.GetPhantomVoice(token)

	; // Set the sound markers used by this temporary voice set
	Base.Mild = Game.GetFormFromFile(0x67551, "MyMod.esp") as Sound
	Base.Medium = Game.GetFormFromFile(0x67550, "MyMod.esp") as Sound
	Base.Hot = Game.GetFormFromFile(0x6754F, "MyMod.esp") as Sound
	
	; // Tell the voice it's done being setup so it can finalize all the stuff it needs to
	Voice.PhantomSave(token)
endEvent

That's all I have done so far, but I'm also thinking of adding a "create temporary copy from this", which would look something like this

; // The animation you want to copy
sslBaseAnimation Cowgirl = SexLab.GetAnimationByName("Arrok Cowgirl")
; // Create the copy so you can safely modify it without affecting the original
sslBaseAnimation Custom = SexLab.CopyAnimation("CustomCowgirl", Cowgirl)
Posted

Edit: Are you planning to make persistent functions too?

 

Define persistent functions against existing sexlab functions? 

Posted

Is there a way to register custom sslAnimationSlots or similar? Is that on the roadmap? It would be usable for mods, like Zaz, that register multiple animations and intends to keep the permanent.

 

Do you have any advice on how to best do that on the 1.50+ versions (if possible)?

 

Also, what method would you advice to use as a way to create temporary animations in 1.50+ (not counting new stuff in 1.55 yet, obviously).

Posted

 

Define persistent functions against existing sexlab functions? 

 

 

You wrote that those functions persists for one hour. I want to know if you plan to make the same functions persists as long as the modder wants, ie for the life time of his mod.

 

This could be useful if you want to puzzle your own animations and register them  with SexLab w/o the need to globally register them and so they can't accidently called by other mods.

 

Another question to plan ahead: Will it be possible to have more than 5 stages for each custom animation?

Posted

 

Define persistent functions against existing sexlab functions?

 

You wrote that those functions persists for one hour. I want to know if you plan to make the same functions persists as long as the modder wants, ie for the life time of his mod.

 

This could be useful if you want to puzzle your own animations and register them  with SexLab w/o the need to globally register them and so they can't accidently called by other mods.

 

Another question to plan ahead: Will it be possible to have more than 5 stages for each custom animation?

 

More specifically, it would be good to have a list of current limits.

Posted

 

 

Define persistent functions against existing sexlab functions? 

 

 

You wrote that those functions persists for one hour. I want to know if you plan to make the same functions persists as long as the modder wants, ie for the life time of his mod.

 

This could be useful if you want to puzzle your own animations and register them  with SexLab w/o the need to globally register them and so they can't accidently called by other mods.

 

 

The point of them is to keep them lightweight and only polluting the save for as long as they are needed/used. There is a limited number of slots for animations/expressions/voices, and letting a mod permanently claim one means various mods could end up competing for slots and breaking the other. Since these aren't registered globally, they don't need to be generally searchable, so they don't need to be persistent.

 

The point of the GetSetAnimation|Voice|Expression() function is that the object will exists whenever you need them while avoiding competition over the slots. Maybe you have a use case in mind where that's not good enough, in which case I'll happily alter them as needed or add some kind of MakePermenant() or RegisterGlobally() function, but I can't honestly think of such a case.

 

 

Another question to plan ahead: Will it be possible to have more than 5 stages for each custom animation?

 

Animations can have 128 / ( 4 * Number of Actors ) = floor(Max Stages)

 

So 

 

1 actor = 32 stages

2 actors = 16 stages

3 actors = 10 stages

4 actors = 8 stages 

5 actors = 6 stages

Posted

Okay, I've changed it so now all "temporary" phantom objects so they are now permanent, when creating the object you have to pass it either a form or a reference alias belonging to your mod to serve as it's "owner" Whenever the player loads their save, the objects will have their owners checked, and if they return as none, indicating the owning mod is no longer installed, then the object is cleared out of the slots. You can also convert a phantom object into a globally registered one that shows up in SexLab's MCM.

 

Here's what I expect will be the final syntax for the objects.

; // Gets a previously created phantom object of type identified by token, returns none if not found
sslBaseAnimation function GetPhantomAnimation(string Token)
sslBaseVoice function GetPhantomVoice(string Token)
sslBaseExpression function GetPhantomExpression(string Token)

; // Returns array of object type's belonging to either the OwnerForm or OwnerAlias, must pass atleast one of the two
sslBaseAnimation[] function GetOwnerAnimations(Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseVoice[] function GetOwnerVoices(Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseExpression[] function GetOwnerExpressions(Form OwnerForm = none, ReferenceAlias OwnerAlias = none)

; // Create a new empty object of type identified by token
; // Must pass either OwnerForm or OwnerAlias to identify what mod owns the phantom slot
sslBaseAnimation function NewAnimation(string Token, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseVoice function NewVoice(string Token, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseExpression function NewExpression(string Token, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)

; // Returns the object if it exists, if it does not exist it create an empty object and and send the given callback event to create it
; // Must pass either OwnerForm or OwnerAlias to identify what mod owns the phantom slot
; // The owner form/alias passed muss also contain the callback function
sslBaseAnimation function GetSetAnimation(string Token, string Callback, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseVoice function GetSetVoice(string Token, string Callback, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseExpression function GetSetExpression(string Token, string Callback, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)

; // Creates a copy of the given object under a new phantom slot identified by Token.
; // Must pass either OwnerForm or OwnerAlias to identify what mod owns the phantom slot
sslBaseAnimation function NewAnimationCopy(string Token, sslBaseAnimation CopyFrom, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseVoice function NewVoiceCopy(string Token, sslBaseVoice CopyFrom, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)
sslBaseExpression function NewExpressionCopy(string Token, sslBaseExpression CopyFrom, Form OwnerForm = none, ReferenceAlias OwnerAlias = none)

; // Converts the temporary object identified by token to a normal object of it's type
sslBaseAnimation function RegisterGlobalAnimation(string Token)
sslBaseVoice function RegisterGlobalVoice(string Token)
sslBaseExpression function RegisterGlobalExpression(string Token)

; // Erase the temporary object identified by token
function ReleaseAnimation(string Token)
function ReleaseVoice(string Token)
function ReleaseExpression(string Token)

Any other suggestions before I finalize it and release 1.55?

Posted

For me upgrading to 1.54 burned the lip synch. It's no more working. But If I install 1.54 on a fresh save everything is fine. 

Why the upgrade is breaking something which otherwise is working?

Maybe there is something which could be fixed regarding lip synch in the next 1.55?

Posted

For me upgrading to 1.54 burned the lip synch. It's no more working. But If I install 1.54 on a fresh save everything is fine. 

Why the upgrade won't break something which otherwise is working?

Maybe there is something which could be fixed regarding lip synch in the next 1.55?

 

If you disable and uninstall sexlab and sexlab mods and save the game without them you should clean that save with script cleaner tool. After that install new sexlab and mods and everything works.

1.54 works. I dont know if there is problem somewhere with upgrading but if you do this it will work on your existing saves.

Posted

(snip code)

 

Any other suggestions before I finalize it and release 1.55?

Order of importance to me:

1. If you haven't done so already, set up example code to register animations and everything else you want mods to be able to do. That will help you figure out if your api is where you want it to be, and it will help modders figure out how you want us to use it. It also makes it clear to you when and how you break backward compatibility.

 

2. Clean up how sslAnimationFactories are created. They are still needed for registering animations, and it feels odd that I have to call functions documented as internal (Initialize) to set up my own factory correctly.

 

Having a support function in SexLabFramework to return a factory (or the factory) would make a lot of sense.

 

3. Refactor "Save(int)" to "Finalize(void)" and "Save(int)" or something like that. Let Finalize handle setting up and calculating the last stuff on an animation. Let save handle whatever registering is still left to do (if any).

 

4. Not a suggestion as much as a question, but why introduce temporary objects to begin with? You can already start a new thread and feed it sslBaseAnimations to pick from? If you could do the same with expressions and voices, that is what I would (continue to) use.

 

5. Refactor sslBaseAnimation.SoundFX back into an int or create a setter as a function I can call (taking an int as argument). It's much nicer not to have to fetch resources from SexLab, and not having to copy resources from the factory object.

 

 

For the future:

When it comes to registering new animations, expressions and voices, how about allowing mods to set up their own "resources" variable (similar to sslAnimationSlots) and register their resource variable with SexLab? Zaz could export it's own voices, animations, and expressions, but would itself be responsible for the contents in there. That is, when to remove an animation, when to add another animation and so on.

 

Temporary slots would be up to the mod to handle, but you could of course write support functions to make that job easier.

Posted

 

For me upgrading to 1.54 burned the lip synch. It's no more working. But If I install 1.54 on a fresh save everything is fine. 

Why the upgrade won't break something which otherwise is working?

Maybe there is something which could be fixed regarding lip synch in the next 1.55?

 

If you disable and uninstall sexlab and sexlab mods and save the game without them you should clean that save with script cleaner tool. After that install new sexlab and mods and everything works.

1.54 works. I dont know if there is problem somewhere with upgrading but if you do this it will work on your existing saves.

 

 

Thank I'll try the full clean save, but as a last resource. I've got mods like SD+ which may be tricky to uninstall.

I'll check first if upgrading to next 1.55 fixes the lip synch.

Posted

EDIT: pls ignore the post, it's working correctly in SL (although i don't get it how come different anims are exported in KFs :huh: )

 

 

 

 

tyvm, those new features look so cool!

 

although... i hope i'm not mistaken (tested it on exported KFs in max), but  it seems like some of the HKX in 1.54 got bundled with incorrect names.

 

f.i. Arrok_Cowgirl_A1_S2 - Arrok_Cowgirl_A1_S4 are not the cowgirl anims. i don't remember what it was originally (perhaps rough behind or rough doggy style). arrok cowgirl anims for actor 1 are not present in latest release i think (or i just couldn't find them).

 

ot, does anyone have link to previous SL release? (for anims only) i migrated from 1.39 recently, i know it was properly named there

 

Posted

 

(snip code)

 

Any other suggestions before I finalize it and release 1.55?

2. Clean up how sslAnimationFactories are created. They are still needed for registering animations, and it feels odd that I have to call functions documented as internal (Initialize) to set up my own factory correctly.

 

I've replaced the initialize with a PrepareFactory() function that should be called at the start of an anim/voice/expression loader. For voices and expression factories its just PrepareFactory(void), for animation factories its PrepareFactory(void) or PrepareCreaturesFactory(void). Calling this will initialize the factory and set which Slots script it should connect to.

 

Having a support function in SexLabFramework to return a factory (or the factory) would make a lot of sense.

Since 1.50 removed setup functions and instead opted to let the callback functions just call them directly on the objects themselves (which great greatly speeds up the registration process since it now no longer as to thread lock itself) The factory scripts themselves now do functionally very little. Their only real purpose now is to provide a means of callback for organizational reasons and and some useful read only properties to assist with readability. Both of those are things it really only helps with if they are being used as the parent in a separate script extending the factory.

 

If you wanted to bypass the factory scripts, you could do so relatively easily.

int slot = AnimSlots.Register("MyAnimation")
if slot != -1
	sslBaseAnimation Animation = AnimSlots.GetBySlot(slot)
	; // Stuff the factory normally does for you
	Animation.Initialize()
	Animation.Registry = "MyAnimation"
	Animation.Enabled = true
	; // Register the animation like normal as if in the factory callback event
	Animation.Name = "My Animations Full Name"
	; // no readonly properties without extending factory, would have to define your own or just follow the key
	; // Female = 1, VaginalAnal = 5
	int a1 = Animation.AddPosition(1, addCum = 5) 
	Animation.AddPositionStage(a1, "Missionary_A1_S1")
	Animation.AddTag("Vaginal")
	; // finalize
	Animation.Save(slot)
endIf
 

 

3. Refactor "Save(int)" to "Finalize(void)" and "Save(int)" or something like that. Let Finalize handle setting up and calculating the last stuff on an animation. Let save handle whatever registering is still left to do (if any).

I don't see the point in splitting it up between two functions, in either case you would still have to call one or both at at the end of setup. I could easily make it just Save(void) though, the int passed has no practical purpose beyond simply logging what slot was used to create the animation at the end of it's setup. Purely for debugging purposes for whenever somebody post a debug log complaining about animations not registering.

 

4. Not a suggestion as much as a question, but why introduce temporary objects to begin with? You can already start a new thread and feed it sslBaseAnimations to pick from? If you could do the same with expressions and voices, that is what I would (continue to) use.

because the temporary objects are a separate list from the ones used when generally pulling animations via tags or other search functions. So if you were to say have a sequenced whipping animation you wanted to use in certain scenarios, instead of registering them via the factory scripts you could do it with this new system the temporary sslBaseAnimation will be there when you need it, while keeping it from being used randomly by other mods not intending to use them but wind up selecting them when filtering for animations to use.

 

 

5. Refactor sslBaseAnimation.SoundFX back into an int or create a setter as a function I can call (taking an int as argument). It's much nicer not to have to fetch resources from SexLab, and not having to copy resources from the factory object.

Using the ints force the same 3 sfx in all animaitons, which might not always fit. Making SoundFX a sound marker instead enables custom animations to use their own specialized SFX instead, without having to code in some overly elaborate SoundFX override to make it ignore the int and use something else instead.

 

[

For the future:

When it comes to registering new animations, expressions and voices, how about allowing mods to set up their own "resources" variable (similar to sslAnimationSlots) and register their resource variable with SexLab? Zaz could export it's own voices, animations, and expressions, but would itself be responsible for the contents in there. That is, when to remove an animation, when to add another animation and so on.

 

Temporary slots would be up to the mod to handle, but you could of course write support functions to make that job easier.

There's nothing stopping a mod from just copying what the animation registry and secondary registry quests in SexLab are doing in order to maintain their own separate list. It would be functionally identical and require very little modifications to any copies of sexlab's related slot, factory, and defaults scripts. Threads will accept any sslBaseAnimation, sslBaseVoice, or sslBaseExpression from any quest, sexlab owned or not.

 

And there is little if anything I can think for SexLab to do that would assist with that beyond simply making a dummy Slots quest to serve as an example. I could add a function to have SexLab duplicate any FindByTags() calls and such on registered "additional resources" and combine the results, but I can see little point in not just registering them with the default sexlab global slots at that point, it just becomes pointless overhead.

Posted

Bug report:

Sexlab.IsValidActor returns >0, even if an actor is already in a sexlab scene. DD uses Sexlab's ValidateActor as part of it's routine to determine if it should start new animations for an actor: Before, this also had the benefit of preventing DD from interrupting Sexlab.

 

Worked around for now by comparing against the Sexlab animating faction instead.

Posted

Bug report:

Sexlab.IsValidActor returns >0, even if an actor is already in a sexlab scene. DD uses Sexlab's ValidateActor as part of it's routine to determine if it should start new animations for an actor: Before, this also had the benefit of preventing DD from interrupting Sexlab.

 

Worked around for now by comparing against the Sexlab animating faction instead.

 

 

IsValidActor returns a bool not an int, ValidateActor is the one that returns an int. Only reason they should be returning valid in either case though would be if something screwed up the actors setup process when they were added to the thread, check debug log for such errors and make sure the actors it's happening with don't return -1 with StorageUtil.FormListFind(none, "SexLabActors", ActorRef)

Posted

 

Bug report:

Sexlab.IsValidActor returns >0, even if an actor is already in a sexlab scene. DD uses Sexlab's ValidateActor as part of it's routine to determine if it should start new animations for an actor: Before, this also had the benefit of preventing DD from interrupting Sexlab.

 

Worked around for now by comparing against the Sexlab animating faction instead.

 

 

IsValidActor returns a bool not an int, ValidateActor is the one that returns an int. Only reason they should be returning valid in either case though would be if something screwed up the actors setup process when they were added to the thread, check debug log for such errors and make sure the actors it's happening with don't return -1 with StorageUtil.FormListFind(none, "SexLabActors", ActorRef)

 

The function that is being used is ValidateActor, not IsValidActor. It's too early, haha.

 

I haven't reproduced this issue myself (Haven't had time to play), though several of the beta-testers for my mod came across this issue. Here's a log demonstrating it:

 

 

 

[05/02/2014 - 01:51:23PM] -- SexLab -- Thread[0] - Thread[0]: Entering Making State

[05/02/2014 - 01:51:23PM] -- SexLab -- [sslActorAlias <alias ActorAlias004 on quest SexLabThread00 (13061EEF)>]: Slotted '#392'

[05/02/2014 - 01:51:23PM] -- SexLab -- [sslActorAlias <alias ActorAlias003 on quest SexLabThread00 (13061EEF)>]: Slotted 'Iddra'

[05/02/2014 - 01:51:25PM] -- SexLab -- NOTICE: Found Animations(37): Missionary, Arrok Missionary, Zyn Missionary, AP Bed Missionary, Doggy Style, Arrok DoggyStyle, Zyn DoggyStyle, AP DoggyStyle, Reverse Cowgirl, Arrok Cowgirl, Arrok Reverse Cowgirl, AP Cowgirl, Sideways Fuck, Arrok Sideways Fuck, AP Shoulder, Hugging Fuck, Standing Fuck, Arrok HugFuck, Arrok Standing Fuck, AP Standing, Arrok Anal, Arrok Blowjob, Arrok 69, AP Blowjob, AP Kneeling Blowjob, AP Standing Blowjob, AP Handjob, Boobjob, Arrok Boobjob, AP Boobjob, Arrok Foreplay, Arrok Sitting Foreplay, Arrok Standing Foreplay, Bleagh FootJob, Tribadism, Arrok Lesbian, Zyn Lesbian,

[05/02/2014 - 01:51:25PM] -- SexLab -- Thread[0] - Adjustment Profile: ArrokSideways.Adjust.DarkElfRaceF.NordRaceF

[05/02/2014 - 01:51:29PM] -- SexLab -- Thread[0] - Event Hook: AnimationStart

[05/02/2014 - 01:51:29PM] [Zad]: OnAnimationStart()

[05/02/2014 - 01:51:29PM] GagSFX: OnAnimationStart()

[05/02/2014 - 01:51:29PM] GagSFX: Hooked Controller arg:0 controller is [sslThreadController <SexLabThread00 (13061EEF)>]

[05/02/2014 - 01:51:29PM] GagSFX: actors involved are:

[05/02/2014 - 01:51:29PM] GagSFX:  - #392 [Actor < (00000014)>] Sex is 1

[05/02/2014 - 01:51:29PM] GagSFX: voice left untouched

[05/02/2014 - 01:51:29PM] GagSFX:  - Iddra [WIDeadBodyCleanupScript < (0001B085)>] Sex is 1

[05/02/2014 - 01:51:29PM] GagSFX: voice left untouched

[05/02/2014 - 01:51:29PM] GagSFX: end

[05/02/2014 - 01:51:29PM] [Zad]: Total actors: 2. Participating Actors: 2. Animation: Arrok Sideways Fuck

[05/02/2014 - 01:51:29PM] [Zad]: FindValidAnimations(numActors=2, previousAnim=Arrok Sideways Fuck, permitOral=TRUE, permitVaginal=False,permitAnal=False)

[05/02/2014 - 01:51:29PM] [Zad]: Sexlab Animations Available (Chastity): 11/56(Arrok Blowjob, Arrok 69, AP Blowjob, AP Kneeling Blowjob, AP Standing Blowjob, AP Handjob, AP Skull Fuck, Boobjob, Arrok Boobjob, AP Boobjob, Bleagh FootJob)

[05/02/2014 - 01:51:29PM] [Zad]: Sexlab Animations Available (Aggressive): 1/56(AP Skull Fuck)

[05/02/2014 - 01:51:29PM] [Zad]: Sexlab Animations Available (Foreplay): 3/56(Arrok Foreplay, Arrok Sitting Foreplay, Arrok Standing Foreplay)

[05/02/2014 - 01:51:29PM] [Zad]: Using full chastity animation list.

[05/02/2014 - 01:51:29PM] [Zad]: Overriding animations.

[05/02/2014 - 01:51:29PM] -- SexLab -- Thread[0] - Adjustment Profile: APStandBlowjob.Adjust.DarkElfRaceF.NordRaceF

[05/02/2014 - 01:51:29PM] -- SexLab -- Thread[0] - Event Hook: StageStart

[05/02/2014 - 01:51:29PM] -- SexLab -- Thread[0] - Advancing: Starting Stage: 1

[05/02/2014 - 01:51:40PM] [Zad]: OnUpdateGameTime()

[05/02/2014 - 01:51:41PM] [Zad]: ProcessEvents()

[05/02/2014 - 01:51:41PM] [Zad]: Config Interval:0.500000. Total number of events: 2. Next staggered update in 0.250000

[05/02/2014 - 01:51:41PM] [Zad]: PlayThirdPersonAnimation(#392,[idle <DDZazHornyB (1801B2AA)>],6)

[05/02/2014 - 01:51:41PM] [Zad]: StartThirdPersonAnimation(#392,[idle <DDZazHornyB (1801B2AA)>])

[05/02/2014 - 01:51:41PM] [Zad]: Playing animation for 6 seconds. // This function uses a check for ValidateActor(akActor) < 0

[05/02/2014 - 01:51:44PM] xpoCrimeScanner: (Scanning) OnUpdate

[05/02/2014 - 01:51:44PM] [Zad]: OnUpdateGameTime()

[05/02/2014 - 01:51:44PM] [Zad]: ProcessEvents()

[05/02/2014 - 01:51:44PM] [Zad]: Config Interval:0.500000. Total number of events: 2. Next staggered update in 0.250000

[05/02/2014 - 01:51:44PM] [Zad]: ProcessEffects()

[05/02/2014 - 01:51:44PM] [Zad]: Player is in a sexlab scene. Not starting new vibration effect. // This function compares directly against the faction.

[05/02/2014 - 01:51:46PM] [Zad]: OnUpdateGameTime()

[05/02/2014 - 01:51:47PM] [Zad]: ProcessEvents()

[05/02/2014 - 01:51:47PM] [Zad]: No events to process. Done.

[05/02/2014 - 01:51:47PM] [Zad]: Finished processing events. Re-Polling..

[05/02/2014 - 01:51:47PM] [Zad]: OnUpdateGameTime()

[05/02/2014 - 01:51:47PM] [Zad]: ProcessEvents()

[05/02/2014 - 01:51:47PM] [Zad]: Config Interval:0.500000. Total number of events: 1. Next staggered update in 0.500000

[05/02/2014 - 01:51:47PM] [Zad]: PlayThirdPersonAnimation(#392,[idle <DDZazHornyA (1801AD47)>],10)

[05/02/2014 - 01:51:47PM] [Zad]: Actor already in animating faction.

[05/02/2014 - 01:51:47PM] [Zad]: ProcessEffects()

[05/02/2014 - 01:51:47PM] [Zad]: Player is in a sexlab scene. Not starting new vibration effect.

[05/02/2014 - 01:51:47PM] [Zad]: EndThirdPersonAnimation(#392,[False, False])

[05/02/2014 - 01:51:48PM] [Zad]: ProcessEffects()

[05/02/2014 - 01:51:48PM] [Zad]: Player is in a sexlab scene. Not starting new vibration effect.

[05/02/2014 - 01:51:54PM] [Zad]: OnUpdateGameTime()

[05/02/2014 - 01:51:54PM] [Zad]: ProcessEvents()

[05/02/2014 - 01:51:54PM] [Zad]: No events to process. Done.

[05/02/2014 - 01:51:54PM] [Zad]: Finished processing events. Re-Polling..

[05/02/2014 - 01:51:54PM] [Zad]: OnUpdateGameTime()

[05/02/2014 - 01:51:54PM] [Zad]: ProcessEvents()

[05/02/2014 - 01:51:54PM] [Zad]: Config Interval:0.500000. Total number of events: 2. Next staggered update in 0.250000

[05/02/2014 - 01:51:54PM] [Zad]: PlayThirdPersonAnimation(#392,[idle <DDZazHornyC (1801B2AB)>],8)

[05/02/2014 - 01:51:54PM] [Zad]: StartThirdPersonAnimation(#392,[idle <DDZazHornyC (1801B2AB)>])

[05/02/2014 - 01:51:54PM] [Zad]: Playing animation for 8 seconds. // Another animation started.

 

Relevant code snippet that should be (But is not currently) blocking the animation: 

	if SexLab.ValidateActor(akActor) < 0 || akActor.IsSwimming() || akActor.IsOnMount() || akActor.GetCurrentScene() != none
		Warn("Not playing third person animation: Actor is already in a blocking animation.")
		return
	EndIf

Code snippet that correctly detects sexlab animating status:

	if akActor.IsInFaction(Sexlab.AnimatingFaction)
		libs.Log("Player is in a sexlab scene. Not starting new vibration effect.")
		return false
	EndIf

EDIT: It would appear that my tester had a very fast timescale set in this log: Could that have caused the problem?

Posted

With 1.55 released I've settled on this syntax for the mod owned objects

sslBaseAnimation function NewAnimationObject(string Token, Form Owner)
sslBaseVoice function NewVoiceObject(string Token, Form Owner)
sslBaseExpression function NewExpressionObject(string Token, Form Owner)

sslBaseAnimation function GetSetAnimationObject(string Token, string Callback, Form Owner)
sslBaseVoice function GetSetVoiceObject(string Token, string Callback, Form Owner)
sslBaseExpression function GetSetExpressionObject(string Token, string Callback, Form Owner)

sslBaseAnimation function NewAnimationObjectCopy(string Token, sslBaseAnimation CopyFrom, Form Owner)
sslBaseVoice function NewVoiceObjectCopy(string Token, sslBaseVoice CopyFrom, Form Owner)
sslBaseExpression function NewExpressionObjectCopy(string Token, sslBaseExpression CopyFrom, Form Owner)

sslBaseAnimation function GetAnimationObject(string Token)
sslBaseVoice function GetVoiceObject(string Token)
sslBaseExpression function GetExpressionObject(string Token)

sslBaseAnimation[] function GetOwnerAnimations(Form Owner)
sslBaseVoice[] function GetOwnerVoices(Form Owner)
sslBaseExpression[] function GetOwnerExpressions(Form Owner)

bool function HasAnimationObject(string Token)
bool function HasVoiceObject(string Token)
bool function HasExpressionObject(string Token)

bool function ReleaseAnimationObject(string Token)
bool function ReleaseVoiceObject(string Token)
bool function ReleaseExpressionObject(string Token)

int function ReleaseOwnerAnimations(Form Owner)
int function ReleaseOwnerVoices(Form Owner)
int function ReleaseOwnerExpressions(Form Owner)

sslBaseAnimation function MakeAnimationRegistered(string Token)
sslBaseVoice function MakeVoiceRegistered(string Token)
sslBaseExpression function MakeExpressionRegistered(string Token)

There is also a new set of functions for creating globally registered objects without having to make your own script that extends the factory script

sslBaseAnimation function RegisterAnimation(string Registrar, Form CallbackForm = none, ReferenceAlias CallbackAlias = none)
sslBaseAnimation function RegisterCreatureAnimation(string Registrar, Form CallbackForm = none, ReferenceAlias CallbackAlias = none)
sslBaseVoice function RegisterVoice(string Registrar, Form CallbackForm = none, ReferenceAlias CallbackAlias = none)
sslBaseExpression function RegisterExpression(string Registrar, Form CallbackForm = none, ReferenceAlias CallbackAlias = none)

If you pass it a CallbackForm or CallbackAlias, it will automatically either one for a mod event and send it a callback much the same as the the factory scripts do so you can seperate your registrations that way, or it also simply returns the object after starting the registration, so you can do it all. There is also a set of global functions to serve as the factories readonly properties so you can easily set them after doing an import.

 

Basically there's 3 ways to register GLOBAL animations/voices/expressions now. 4 if you count creating a mod owned object with one of the temporary object functions and then using MakeAnimation/Voice/ExpressionRegistered() to convert it from mod owned to globally registered.

 

Using SexLab's AnimationFactory by extending it without your own script

scriptname MyAnimations extends sslAnimationFactory

function LoadAnimation()
	PrepareFactory()
	RegisterAnimation("MyAnimation")
endFunction

; This callback is automatically registered and sent by sslAnimationFactory
function MyAnimation(int id)
	; // Get the animation we are registering
	sslBaseAnimation a = Create(id)
	a.Name = "My Animation"
	; // Access the female flag from sslAnimationFactory's readonly property
	int a1 = a.AddPosition( Female, addCum = Vaginal )
	a.AddPositionStage(a1, "Missionary_A1_S1", 0)
	; // Other registrations stuff, closed off by a.Save(id)
	a.Save(id)
endFunction

Using the SexLabFramework.RegisterAnimation/Expression/Voice() with a callback on your own script NOT extending the factory

scriptname RegisterAnimations1 extends Quest
; // Get access to the globals for the int flags for better readability
import sslObjectFactory
SexLabFramework property SexLab auto

function LoadAnimation()
	SexLab.RegisterAnimation("MyAnimation", self)
endFunction

; Callback sent to this script by passing self to RegisterAnimation
function MyAnimation(int id)
	; // Get the animation we are registering
	sslBaseAnimation a = SexLab.GetAnimationBySlot(id)
	a.Name = "My Animation"
	; // Access the Female and Vaginal flag from the sslObjectFactory global
	int a1 = a.AddPosition( Female(), addCum = Vaginal() )
	a.AddPositionStage(a1, "Missionary_A1_S1")
	; // Other registrations stuff, closed off by a.Save(id)
	a.Save(id)
endFunction

Using the SexLabFramework.RegisterAnimation/Expression/Voice() with NO callback NOT extending the factory, registering and defining it all at once.
scriptname RegisterAnimations2 extends Quest
; // Get access to the globals for the int flags for better readability
import sslObjectFactory
SexLabFramework property SexLab auto

function LoadAnimation()
	; // Create the empty animation and define it inline.
	sslBaseAnimation a = SexLab.RegisterAnimation("MyAnimation")
	if a != none		
		a.Name = "My Animation"
		; // Access the Female and Vaginal flag from the sslObjectFactory global
		int a1 = a.AddPosition( Female(), addCum = Vaginal() )
		a.AddPositionStage(a1, "Missionary_A1_S1")
		; // Other registrations stuff, closed off by a.Save(id)
		a.Save(id)
	endIf
endFunction

 
 

 

Posted

Can nioverride's

Stopping/Starting/Modifying time controllers (Think pulsing speed of an animation)

function be used in SL? You know, like controlling the animation speed with your mouse wheel... or something else.

Posted

Ive been working alot on aligning animations with new editor and noticed how many of the animations needed position fixing. From characters cliping to schlongs erected so much they are going inside male body etc etc. So after about 6 hours i think i got all the positions fixed. Heres my question: is there some way to export this data and send it to you Ashal ( if ur interested ofc). Then you can use it as base for next realses. I think most of the people would be greatfull for not having to do it themselves.

Posted

I am getting reports that my voice mod does not work after the upgrade from 1.54 to 1.55.

 

I don't have the time to study it right now, so... Were there any changes made to the standard voice factory system?

Posted

Sorry for off-topic - just to know, your mod does work for me with SL 1.55...

I am getting reports that my voice mod does not work after the upgrade from 1.54 to 1.55.

 

I don't have the time to study it right now, so... Were there any changes made to the standard voice factory system?

 

Posted

I honestly don't understand about 90% of what you guys are talking about...but if I understand the 10% then if I change this:

 

function OnEffectStart(actor target, actor caster)
        Utility.Wait(1.0)
            if SexLab.IsActorActive(target)
    ; // masturbate
    actor[] sexActors = new actor[1]
    sexActors[0] = caster
    sslBaseAnimation[] anims
    SexLab.StartSex(sexActors, anims)

 

to this:

 

function OnEffectStart(actor target, actor caster)
        Utility.Wait(1.0)
            if target.IsInFaction(Sexlab.AnimatingFaction)
    ; // masturbate
    actor[] sexActors = new actor[1]
    sexActors[0] = caster
    sslBaseAnimation[] anims
    SexLab.StartSex(sexActors, anims)

 

It should start working again. Do I have at least that much right?

Posted

 

2. Clean up how sslAnimationFactories are created. They are still needed for registering animations, and it feels odd that I have to call functions documented as internal (Initialize) to set up my own factory correctly.

I've replaced the initialize with a PrepareFactory() function that should be called at the start of an anim/voice/expression loader. For voices and expression factories its just PrepareFactory(void), for animation factories its PrepareFactory(void) or PrepareCreaturesFactory(void). Calling this will initialize the factory and set which Slots script it should connect to.

 

Awesome. That way, I don't have to bother with the Slots property anymore. Thanks!

 

 

Having a support function in SexLabFramework to return a factory (or the factory) would make a lot of sense.

Since 1.50 removed setup functions and instead opted to let the callback functions just call them directly on the objects themselves (which great greatly speeds up the registration process since it now no longer as to thread lock itself) The factory scripts themselves now do functionally very little. Their only real purpose now is to provide a means of callback for organizational reasons and and some useful read only properties to assist with readability. Both of those are things it really only helps with if they are being used as the parent in a separate script extending the factory.

 

Thanks! My main point with this was to avoid having to setup a factory instance. If I can just call a single function to set everything up, that work for me as well.

 

 

3. Refactor "Save(int)" to "Finalize(void)" and "Save(int)" or something like that. Let Finalize handle setting up and calculating the last stuff on an animation. Let save handle whatever registering is still left to do (if any).

I don't see the point in splitting it up between two functions, in either case you would still have to call one or both at at the end of setup. I could easily make it just Save(void) though, the int passed has no practical purpose beyond simply logging what slot was used to create the animation at the end of it's setup. Purely for debugging purposes for whenever somebody post a debug log complaining about animations not registering.

 

This was written based on the idea that you were actually going to do something with the passed in variable. If it won't store anything in the Slots or similar, then I'm fine with the design.

 

My rationale for this suggestion was that a function that does the final steps of the initialization and also stores the object does two things. If you want a clean design you should break up such a function into two parts.

 

If Save() was meant to store things, set things up in the Slots, then this is how I'd want to use it. Calling Save() inside "SetupAnim001" would break the use case for mods wanting to construct temporary animations like Prison Overhaul does.

 

Function SetupAnim001(sslBaseAnimation anim)
  ; Set things up here
  Finalize() ; Performs final and necessary calculations
EndFunction

Function Anim001(...) ; callback when registering
  sslBaseAnimation anim = ...
  SetupAnim001(anim)
  Save(id) ; Stores in the slots variable of this factory, or whatever
EndFunction

 

4. Not a suggestion as much as a question, but why introduce temporary objects to begin with? You can already start a new thread and feed it sslBaseAnimations to pick from? If you could do the same with expressions and voices, that is what I would (continue to) use.

because the temporary objects are a separate list from the ones used when generally pulling animations via tags or other search functions. So if you were to say have a sequenced whipping animation you wanted to use in certain scenarios, instead of registering them via the factory scripts you could do it with this new system the temporary sslBaseAnimation will be there when you need it, while keeping it from being used randomly by other mods not intending to use them but wind up selecting them when filtering for animations to use.

 

I understood how it would be used, but not why. You can do this already by just defining your sslBaseAnimation (putting it on an alias iirc). This is what Prison Overhaul does and it works well as far as I can tell.

 

Of course, your development time is your to spend as you please, so I won't argue about it. Just trying to understand if there was some use case I missed, and .... if I should be using the temporary animations when modding.

 

 

5. Refactor sslBaseAnimation.SoundFX back into an int or create a setter as a function I can call (taking an int as argument). It's much nicer not to have to fetch resources from SexLab, and not having to copy resources from the factory object.

Using the ints force the same 3 sfx in all animaitons, which might not always fit. Making SoundFX a sound marker instead enables custom animations to use their own specialized SFX instead, without having to code in some overly elaborate SoundFX override to make it ignore the int and use something else instead.

 

With the changes proposed to the factories (better support for setting up my own), then I don't think this is an issue.

 

 

For the future:

When it comes to registering new animations, expressions and voices, how about allowing mods to set up their own "resources" variable (similar to sslAnimationSlots) and register their resource variable with SexLab? Zaz could export it's own voices, animations, and expressions, but would itself be responsible for the contents in there. That is, when to remove an animation, when to add another animation and so on.

 

Temporary slots would be up to the mod to handle, but you could of course write support functions to make that job easier.

There's nothing stopping a mod from just copying what the animation registry and secondary registry quests in SexLab are doing in order to maintain their own separate list. It would be functionally identical and require very little modifications to any copies of sexlab's related slot, factory, and defaults scripts. Threads will accept any sslBaseAnimation, sslBaseVoice, or sslBaseExpression from any quest, sexlab owned or not.

 

And there is little if anything I can think for SexLab to do that would assist with that beyond simply making a dummy Slots quest to serve as an example. I could add a function to have SexLab duplicate any FindByTags() calls and such on registered "additional resources" and combine the results, but I can see little point in not just registering them with the default sexlab global slots at that point, it just becomes pointless overhead.

 

Fair enough. I think it would be kind of nice to collect all resources in a single object that would then be dropped when the mod was uninstalled. Still, it's easy enough as it is to setup and register new animations, so maybe not worth the effort.

Posted

hi guys :)

 

i just wanted to ask a qoestion .

 

after each sexlab mod i install i must start a new game or the game Crash to Desktop, is this normal?

and if ist not normal what can i do to solve the Problem ?

 

 

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