Jump to content

Recommended Posts

Posted (edited)
22 hours ago, MannySauce said:

Some questions I've been sitting on:

 

- How girthy can a script be? Is there a line count limit or recommended max?
- Does subroutines have a limit on how many you can have in a single script?
- If you use "return" inside a subroutine, does that exit the subroutine or the script?

 

Good questions.

- How girthy can a script be? Is there a line count limit or recommended max?
I don't have a firm number, however a few things to keep in mind. The script gets parsed each time it is loaded; so if you have e.g. ScriptA "call" ScriptB that, say, "calls" ScriptA, ScriptA would end up being parsed twice. And parsing a script scales linearly with length. I've taken steps to speed that up, but there it is.

 

That said, the parsing occurs in the SKSE plugin and a fairly heavily processed string[] is returned as a result. While the native limit of 127 elements in a list is fixed, much like with PapyrusUtil, the plugin generates a std::vector<std::string> which can translated back to the Papyrus VM as much larger. I'm not exactly sure how much larger, however, I suspect it would be something like INT32_MAX elements.

 

Each line in an SLTScript has a number of "tokens". So if you have a line like:

msg_notify "Foo" "Bar"

that would count as 3 tokens. The "heavily" processed result means each line of SLTScript results in something like (tokenCount + 4) elements in the returned list. So roughly speaking you would be looking at a max of INT32_MAX/(tokenCout + 4) lines in an SLTScript before you would end up with a string[] being generated that was too big.

 

Complicating things further, however, are two other factors: max string size and fun with joins.

 

Max string size in the Papyrus VM appears to be 64k, so any single token can be no larger than that. This gets exacerbated when using string interpolation as what appears to be a small string could balloon depending on the variables you used.

 

And when you use debug flags, I often took the shortcut of using a string[] join to turn a string[] into a formatted string for display purposes. Depending on which flag you use, and what your script is doing, enabling a debug flag could theoretically break your script. But again, I'm assuming 64k length strings are going to be unlikely.

 

For comparison purposes, the 'sltr_test_scripts' package contains a total of (currently) 13 scripts, with the largest weighing in at 546 lines, the second at 415, and the third at 240. The rest are near or below 100 lines of code. The total lines of code come to 1,763.

 

They total 49.6k in size, uncompressed on disk. They take about 1 minute 30 seconds to run when I start the script while leaving the Helgen cave at the start of the game while Hadgar is blathering. A portion of that time is just a result of needing to parse 13 files instead of just 1, not to mention there are some util_wait calls which of course force additional time.

 

- Does subroutines have a limit on how many you can have in a single script?

First, I'm going to toss out some nomenclature. For purposes of discussion here:
- a REQUEST is a single request to run a script as a result of a trigger
- a SCRIPT is just one script in a REQUEST
- a SEQUENCE (I will never use this term again) is the set of SCRIPTs that are run as a result of a REQUEST
- a SEQUENCE will only be 1 long if the initial SCRIPT never attempts to "call" another SCRIPT

 

I store subroutine info (and goto label info, and other bits and bobs) in various string[], int[], and Form[] for each REQUEST. I use PapyrusUtil to manage them. That means those lists are shared across all SCRIPTS that are run as part of the SEQUENCE. In the vast majority of cases that distinction won't matter because your SEQUENCE will be 1 long. But each time you use "call", I push the previous set of values onto the lists to free up the working area for the current SCRIPT.

 

That said, based on the same calculations above about std::vector<std::string> and the max size being INT32_MAX, you have access to INT32_MAX subroutine targets (or goto labels, etc.) for any one REQUEST. And each time a script completes in SEQUENCE, it's reserved slots are freed, so it's not like you burn through them. It's just a stack.

 

- If you use "return" inside a subroutine, does that exit the subroutine or the script?

"return" always exits the script. If you ScriptA "calls" ScriptB and in ScriptB, you call gosub and are in a subroutine, and you encounter "return", ScriptB will immediately stop and control will return to ScriptA. And of course if it happened in ScriptA the entire request completes.

Edited by hextun
Posted

v131 is served, pipin' hot!

 

New bits:

- Added new trigger filters for SexLab and OStim: Partner Race, Partner Role, Partner Gender. Keep in mind that I have not yet removed the "Partner" options from the standard "Race" filter, to give folks a chance to get comfy with the new option and not break existing triggers, but you *can* accidentally cause your trigger not to fire if you use conflicting values

- Added "actor_race_type" to get the "Player, Humanoid, Undead, Creature" value that is used in the "Race/Partner Race" filters

- Made a little MCM performance improvement :)

 

I'm still trying to figure out how to better ship cross-operational scripts for OStim and SexLab and/or to mark the scripts such that it is obvious which framework you are using. It was brought to my attention that folks might choose to have both frameworks in their game at the same time, so I'm not (yet) inclined to try to create a merged API that works against one or the other.

Posted

I'm taking a crack at lists, maps, and lists of maps. Based on current plans:

 

- there will be a new "map" type, peered with e.g. int, float, bool, string, label, Form

- maps will only be able to map non-list, non-map values; no maps of lists, no maps of maps

- there will be new "list" types for each base type, currently including maps

- lists, because every member has to have the same type, will require a declaration step

  - can you guess what it will look like?

  - if you guessed: "int[] $thisIsAListVar[]" you win... something

    - maps being what they are, you'll use "map[] $listOfMaps" to make a .. you know... list of maps

- assigning a non-matching type to a list will make a best effort to coerce the type (i.e. "23" to 23 for storing in an int[]) but will set the value to the default, falsy, value if it can't

- maps will use curly brace notation, i.e. "$mapVar{yourKey}"

- and the 0th map in a list of maps would be "$myListOfMaps[0]{yourKey}"

- standard "set" will work when setting an actual indexed variable 

  - "set $listVar[0] 23"

  - "set $mapVar{yourKey} 23"

- to reference the variable as a whole, use the brackets without an index

  - "some_function_that_wants_a_list $listVar[]"

  - "another_function_but_wants_a_map $mapVar{}"

- if you want to access the map variable stored in a list, whether in whole or a keyed value, you MUST index the list

  - "$listVar[12]{}" ; works

  - "$listVar[12]{yourKey}" ; also works

  - "$listVar[]{}" ; why do?

  - "$listVar[]{yourKey}" ; what mean?

- I don't have plans for list or map literals, so if a function wants a list as a parameter, you will need to push things into a list var and pass the list var (same with map)

- there will, however, be a "set[]" and "set{}" function that will let you set multiple values to your list or map at once (THIS IS STILL A LITTLE FLUID; FUNCTIONALITY WILL BE THERE, JUST NOT SURE OF SYNTAX;  IN FACT, DON'T TAKE ANY OF THIS SYNTAX AS GOSPEL JUST YET; WHY AM I SHOUTING?)

  - "set[] $listVar 1 2 3 4"

  - "set{} $mapVar "key" "val" "key2" "val2""

- not sure what all operations I will have, but should have things like append to list, remove from list, add to map, unmap from map, and so on

 

I have updated the GetVarScope() function to now retrieve not just scope and name, but properly parsed scope, name, target extension scope, list index, and map key. And I have updated the existing functionality to make use of the new return value. Which is to say the regression tests pass but new functionality isn't enabled. Just the preliminary step.

 

Assuming I get this working tolerably, this would be among the final language features I would expect to add (i.e. in terms of modifications to syntax/grammar; NOT in terms of expanding the function library). 

 

I also have a couple of (highly premature, experimental) ideas on how to give you the ability to dynamically call any script, any function via SLTScript. If it pans out, I can't promise it won't look kludgy, *but* it would allow you to ping anything you can reach in Papyrus with a function call. If I can get *THAT* working... so much opens up for you. But... lots of work between here and heaven.

 

Posted

Hello, would it be possible to add independent race filters?
This would allow for example having argonians be abused by nords in windhelm, orcs abusing non orcs guests, nords abusing elves in conquered stormcloack cities, and so on

Posted

image.png.32d30fe0dda9b1f484edbbbe98e3bcbe.png

 

:D

 

Yes, I'm about to commit changes to add map support. I've got some more bits and bobs, but I could stop here and you'd have yer maps.. arrr.. not sure why I'm all of a sudden piratey, arrr, me buckos.. or somesuch nonsense. ninjas > pirates anyway... sorry one piece fans.. *ducks head to avoid violent backlash*

 

Posted

Up, up and away, in my beautiful v132... wouldn't you like to try, my beautiful v132... (with apologies to 'The 5th Dimension')

 

v132 is up and ready for your grubby little mitts :) and why might you want v132? (doesn't v132 just sort of roll off the tongue btw? vee-wun-thir-tee-toooooooooo... mmm... sounds)

 

*ahem* right... v132 has MAPS.. and is savegame compatible :D

 

Here are some map related things you can now do:

; this variable is currently just a string
set $varIsNotMapButWillBeShortly "test"

; make any variable a map by using a map key when assigning to it
set $varIsNotMapButWillBeShortly{a_key} = "foo"
; now it has map key 'a_key' with value "foo"

; you can, of course, use variables instead of literals for map keys
set $keyVar "a_key"
set $value $varIsNotMapButWillBeShortly{$keyVar} 
; now $value has value "foo"

; you can copy a map to another map
mapcopy $mapVarCopy $varIsNotMapButWillBeShortly
; this is copy-by-value, so the two maps are fully independent; altering one does not affect the other
set $varIsNotMapButWillBeShortly{a_key} "bar"
; $mapVarCopy{a_key} is still "foo"

; you can unset a key
mapunset $mapVarCopy $keyVar ; this could have been the "a_key" string literal, too

; and you can check if a map has a key
maphaskey $mapVarCopy $keyVar
; $$ is false, because we just unset it

; and you can also clear all key/value pairs if you want to start over
mapclear $varIsNotMapButWillBeShortly
; $varIsNotMapButWillBeShortly is now empty

; if you later use the map variable as an assignment target, it will cease to be a map
set $mapVarCopy{$keyVar} "foo"
set $mapVarCopy "testing"
; $mapVarCopy is no longer a map, it is a string, so things like mapcopy, maphaskey, etc. will no longer work with it

 

As an interesting quirk of the map implementation, I realized what I should have done with string interpolation all along. So now you can also (and I encourage it) use $-prefixes for variables in your string interpolation:

i.e. $"A message with value {$mapVarCopy{$keyVar}}" should return "A message with value foo". Without the $-prefix, it will assume you are specifying a variable and prefix it anyway.

 

My reasoning is simple. It makes sense you might wish to use a string literal as a map key. But it makes literally zero sense to use a string literal, inside a variable expansion block, inside an interpolated string. Just skip the interpolation block.

 

This ability to use the variable interpolation blocks without $-prefixed variable names is now considered deprecated and will be altered in the future. For now, it remains supported.

 

As a further result of this, the escape sequence for opening curly brace is still '{{' in an interpolated string, to prevent using it to start an interpolation block, but the trailing } no longer should be escaped. mea culpa.

 

I'm still examining lists. I'm hoping they don't become a slog or a type explosion. Have to see. Anyhow, have fun. :)

Posted

I should point out that you cannot have any whitespace inside your variable names, anywhere, including maps.

 

So while this works as expected: $mapvar{$mapkey}

 

This will fail and you will be upset: $mapvar{ $mapkey }

 

I am using a very simple parser at the moment, so whitespace, while *ignored* in that you can add as much whitespace between tokens as you like, is still *important* because it is what defines what the tokens are.

Posted

Next task is actually going to be a change to make the tokenizer smarter; better support for whitespace in things like the map key block and such. Current approach is kludgey.

Posted
On 7/1/2025 at 7:05 AM, Fraying9981 said:

Thanks for the detailed explanation.

I'm actually looking for sth simpler: actor says text, but no audio or lip sync is needed. A bit like when mods dont have voice files.

A dialogue line if you prefer.

 

Hiya, I was just wondering, where you able to successfully create a trigger for this where NPCs can trigger sound files mid sex?

Posted
12 minutes ago, kamithemoon said:

Hiya, I was just wondering, where you able to successfully create a trigger for this where NPCs can trigger sound files mid sex?

 

Nope but i think there is an example somewhere in the readme

Posted
3 hours ago, Fraying9981 said:

 

Nope but i think there is an example somewhere in the readme

I can only read one language, computer language is an entirely other beast to me.  :classic_sad:

I was just hoping someone had already made a functional trigger that I then could use my limited understanding to adjust it to my needs.

Posted
22 hours ago, Somecrazydude said:

Would it be possible to execute triggers based on the Sexlab stats? A trigger activating when the Actor has had Oral Sex 10 times for example?

 

Right now, no. There isn't currently an exposed SLTScript binding that would let you retrieve skill levels for a SexLab Actor.

 

That said, if such a function were available, there isn't a specific trigger for "SexLab Actor Reached New Skill Level", but you could use the "On SexLab End" event and check the skill level (again, assuming it was bound).

 

If there was one thing I could use help on, it would be adding to the function libraries; the reason I created the extensibility was to let others be able to add to the SLTR function libraries available. That and adding new triggers. Basically anything to do with integrating with other mods. 

 

I have a (increasingly large) backlog of "todo" items to expand things, but I'm closing in on being as feature complete on the SLTScript language features as I plan to be, which would mean a more or less full time pivot to expanding the function set, trigger sets, and general mod integration.

 

In other words, "no, but good idea, I'll make a note to add that, thanks:. :)

 

Posted
On 7/16/2025 at 9:06 AM, Fraying9981 said:

 

thanks. I installed a UI mod. bars are not moving. so i take it doesn't work

 

Was this issue (stamina damage not affecting UI bars) resolved for you?

Posted
11 hours ago, kamithemoon said:

I can only read one language, computer language is an entirely other beast to me.  :classic_sad:

I was just hoping someone had already made a functional trigger that I then could use my limited understanding to adjust it to my needs.

 

Hi @kamithemoon! The post @Fraying9981 is referring to is here: 

 

It is lengthy, and goes into some technical depth, so feel free to read it, but I'll ask here for you first:

 

- are you wanting to play something like a sound effect (i.e. like the example use of snd_play found in the "Heart beat(A).sltscript" script that is shipped with the mod)? These are TYPICALLY (but I can't guarantee ALWAYS) going to be 'SOND' records in an .esp or .esm and are usually pretty easy (from what I can tell) to get an editorID or formID out of xedit for them.

- OR are you wanting to play dialog (i.e. actually hear an NPC speak lines of text)? that is doable, but there are pitfalls around it and it's a somewhat tougher thing to do with risks in some cases because forcing speech to run can also run scripts and set flags (not always but it can happen), so you'd have to be careful

Posted (edited)
3 hours ago, hextun said:

 

Hi @kamithemoon! The post @Fraying9981 is referring to is here: 

 

It is lengthy, and goes into some technical depth, so feel free to read it, but I'll ask here for you first:

 

- are you wanting to play something like a sound effect (i.e. like the example use of snd_play found in the "Heart beat(A).sltscript" script that is shipped with the mod)? These are TYPICALLY (but I can't guarantee ALWAYS) going to be 'SOND' records in an .esp or .esm and are usually pretty easy (from what I can tell) to get an editorID or formID out of xedit for them.

- OR are you wanting to play dialog (i.e. actually hear an NPC speak lines of text)? that is doable, but there are pitfalls around it and it's a somewhat tougher thing to do with risks in some cases because forcing speech to run can also run scripts and set flags (not always but it can happen), so you'd have to be careful

Hiya, its the later.  Specifically, I want the PC and or NPCs to play specific dialogue with lines of text.  I'm hoping to use this to make them context aware of which sex act they're in and to say lines of dialogue accordingly.

 

I saw that this could cause issues, especially if another dialogue is being run simultaneously, which makes sense.  But if SexLab triggers could point to a dialogue text, then perhaps that particular dialogue could be conditioned in the esp in such a way as to avoid the potential pitfalls and CTDs.  I'm also fine with using the invisible actors method so the dialogue isn't attached to the character in question directly.  It would probably be a lot of work any how to detect if a character's throat was occupied and to only mumble in such a case.  Although, if such detection were possible, it would be super cool.

 

The only mod I know of that adds mid-sex dialogue is Sexist Guards.  For the PC, this is mid rape protests and uses an invisible actor.  For NPCs, they're mid rape dialogue and I'm actually not sure if it comes directly from the NPC or also uses an invisible actor.  Both sets of dialogue comes from the esp and has text.

Edited by kamithemoon
Posted

noobie question since I clearly dont know what im doing. What is wrong with this script? It is not equipping anything, nor returning error to console.

 

rnd_list "ZaZAnimationPack.esm:159069" "ZaZAnimationPack.esm:159070"
set $1 $$
item_equip $player $1 1 0
actor_qnnu $player
util_waitforend $player
item_unequipex $player $1 0
item_remove $player $1 1 1
actor_qnnu $player

 

Posted
29 minutes ago, PenBoozerX said:

noobie question since I clearly dont know what im doing. What is wrong with this script? It is not equipping anything, nor returning error to console.

 

rnd_list "ZaZAnimationPack.esm:159069" "ZaZAnimationPack.esm:159070"
set $1 $$
item_equip $player $1 1 0
actor_qnnu $player
util_waitforend $player
item_unequipex $player $1 0
item_remove $player $1 1 1
actor_qnnu $player

 

 

When I introduced scoping (i.e. $global.varname, $target.varname, $thread.varname, $local.varname (and $varname, which defaults to $local.varname), I moved the special variables to the 'system' scope. So your script needs to be written using e.g. $system.player as opposed to $player.

 

https://github.com/lynnpye/sl_triggers/wiki/Scripts#special-scopes for the specific list of available "special" variables, and, more generally, the wiki is available for documentation overall. :)

Posted

Hmm... let's see... status, status, status... right... *ahem*

 

ATTENTION K-MART SHOPPERS. THERE IS A BLUE LIGHT SPECIAL IN AISLE 4... wait... wrong status... *cough*

 

v133 is coming along. I have implemented the loosened whitespace requirements for map key blocks. So my previous warning about needing to do this:

  $mapvar{$keyvarInMap{$keyvar}}}

when maybe it would be more readable to do this:

  $mapvar{ $keyvarInMap{ $keyvar } } }

will no longer hold true. Meaning you can do the latter. I prefer the latter. Laaaaaa-tter. weird word.

 

I'm eyeballing lists for this one too, and debating creating a SexLab expansion add-on; a separate downloadable function library to flesh out as many SexLab API bindings as I can (or seems realistic; or reasonable; or risque; or risible; or... some other r-word... alliteration is fun!). Though said expansion/add-on/funclib, being not part of an official release, would not need to be tied to a specific version. So I've got that goin' for me which is nice.

 

Hope your weekends go well. Ta for now.

Posted

set $updateInfo[0] "v133 is up"

set $updateInfo[1] "Can you guess what it includes?"

set $updateInfo[2] "No hints!"

 

Expand-o the hidey block to see the changeloggishness:

Spoiler
Savegame compatibility: Should be savegame compatible

Note: Reminder that logging output is all sent to <My Documents>\My Games\Skyrim Special Edition\SKSE\sl-triggers.log 
    (or whichever folder you have your SKSE logs directed to)

enhancement: loosened variable syntax requirements; within a map key block (i.e. inside the '{}'), you can have whitespace padding around the key value being used
    ; previously, the whitespace around $key would have caused a parse failure:
        $var{ $key }
    NOTE: The parser will make a best effort but if you run into problems, report the error and, in the meantime, devolve to removing surrounding whitespace within map key blocks
enhancement: new data type, lists (see the wiki for full information)
        ; allows for list indexed variable access
        $listvar[0] = "foo"
        ; along with list specific new functions
        listcount $listvar ; returns count of elements
        listclear $listvar ; removes all elements
        listadd $listvar "foo" ; adds the value, coercing to the list data type
    unlike other variable types, assigning to a list uses the list data type, not the source data type
    you may also declare a list in advance, to force the data type before use
        int[] $listvar
        ; forces listvar to be an int[]
enhancement: new function, mapkeys
    returns the list of keys for a map
        set $mapvar{apple} "fruit"
        set $mapvar{cherry} "fruit"
        set $mapkeylist resultfrom mapkeys $mapvar
        ; $mapkeylist contains "apple", and "cherry"
enhancement: util_waitforkbd, sl_waitforkbd, ostim_waitforkbd, deb_msg, msg_notify, msg_console, rnd_list modified to OPTIONALLY accept EITHER the original parameter set OR to accept a single list containing the necessary values
    ; so you could either do the usual method
    util_waitforkbd 70 71 72
    ; or, if you needed to, use a list
    int[] $keylist
    listadd $keylist 70
    listadd $keylist 71
    listadd $keylist 72
    util_waitforkbd $keylist
    ; obviously in this example, the first method would be preferable, but if you need to build a list and then pass it in, this gives you that freedom

 

 

If you guessed "lists", you win!

 

Unlike maps, which can hold multiple different types of data (i.e. $mapval{key1} = "foo", $mapval{key2} = 43, and the types are retained), lists have a specific data type they hold, based either on what type was initially assigned to it, or if you declare it to be of a type.

 

Unlike other data types, where what you are assigning determines the type for the variable, with lists, the type of the list determines how the data gets coerced. So if you assign "one" to an int[] list, the value will be '0' because that's what Papyrus gives you when trying to convert a non-numeric string to an int.

 

Also, some functions that can take variadic arguments have been changed:

- they still accept the original method of passing multiple individual values

- but if you pass only one value and that variable is a list type, it will instead use the values in the list

 

; suppose you want to use rnd_list, and depending on circumstances you want to have different sets of options available
; previously you had to hard-code all possible combinations of options and use conditional checks to determine which instance of rnd_list to call
rnd_list "optional 1" "optional 2"
rnd_list "optional 1" "optional 3" "optional 4"

; now, you can build your list as needed, retain it for later, modify it, and reuse it
string[] $optlist
set $optlist[0] "optional 1"
if $somecondition
  listadd $optlist "optional 2"
else
  listadd $optlist "optional 3" "optional 4"
endif
rnd_list $optlist

 

This is new code, a new feature, so I'm going to give this a little time to cook and see how things work out in the field before declaring SLTR out of beta, but we're close. :)

 

Posted

I just noticed that the MCM display is hitting the 128 option limit per page. I'm making a LOT of use of extra options for spacing so I'll look into reducing that, or give the option for selecting sections per page or something.

Posted
28 minutes ago, bandetlol said:

Can someone explain how to make a script that scans if an item is equipped in a slot and if not adds an item and equips it?

 

Keep in mind that a script, when run, has a "target", an Actor that the script uses as the target for $system.self. The following script uses $system.self, meaning if run on an NPC, it would work for them as well.

 

$formId contains the relative FormID, or editorId (preferred, actually, if you have it) for the item to be added.

$system.self is the Actor the script is run on

It calls actor_iswearing to determine if the targeted Actor is wearing the item specified by $formId

And it uses that result to determine whether to call item_adduse, which first adds the item and then uses it (which will equip things like worn items).

 

set $formId "whatevermod.esp:0x800"
; or if you have the editorId, you could use it instead, like:
; set $formId "itemEditorId"

actor_iswearing $system.self $formId

if $$
	; item_adduse first calls AddItem() then EquipItem()
	; see this comment from CreationKit:Actor:EquipItem
	;   If the calling actor does not have akItem, they will be given one. It is best, however, to add the item with AddItem (), then equip it as the item might not otherwise register as equipped.
	;   https://ck.uesp.net/wiki/EquipItem_-_Actor
	item_adduse $system.self $formId 1 1
endif

 

Note that there is no mention of a specific slot; unless you're talking about held items where right vs left hand might matter, everything else presumably has a default slot or slots that it takes up. It just becomes a matter of whether they have the item worn or not.

 

There is additional logic that could be performed if, for example, you wanted to also check if the target already has the item and thus whether to add it or not or just equip the item from inventory.

 

And if you want the script to only ever affect the player, regardless of whom it targets, change the uses of "$system.self" to "$system.player". Just keep in mind if run multiple times, multiple copies of the item will end up added to inventory.

Posted (edited)
1 hour ago, hextun said:

 

Keep in mind that a script, when run, has a "target", an Actor that the script uses as the target for $system.self. The following script uses $system.self, meaning if run on an NPC, it would work for them as well.

 

$formId contains the relative FormID, or editorId (preferred, actually, if you have it) for the item to be added.

$system.self is the Actor the script is run on

It calls actor_iswearing to determine if the targeted Actor is wearing the item specified by $formId

And it uses that result to determine whether to call item_adduse, which first adds the item and then uses it (which will equip things like worn items).

 

set $formId "whatevermod.esp:0x800"
; or if you have the editorId, you could use it instead, like:
; set $formId "itemEditorId"

actor_iswearing $system.self $formId

if $$
	; item_adduse first calls AddItem() then EquipItem()
	; see this comment from CreationKit:Actor:EquipItem
	;   If the calling actor does not have akItem, they will be given one. It is best, however, to add the item with AddItem (), then equip it as the item might not otherwise register as equipped.
	;   https://ck.uesp.net/wiki/EquipItem_-_Actor
	item_adduse $system.self $formId 1 1
endif

 

Note that there is no mention of a specific slot; unless you're talking about held items where right vs left hand might matter, everything else presumably has a default slot or slots that it takes up. It just becomes a matter of whether they have the item worn or not.

 

There is additional logic that could be performed if, for example, you wanted to also check if the target already has the item and thus whether to add it or not or just equip the item from inventory.

 

And if you want the script to only ever affect the player, regardless of whom it targets, change the uses of "$system.self" to "$system.player". Just keep in mind if run multiple times, multiple copies of the item will end up added to inventory.

 

I have several use cases for it that I did in old sl triggers

1. equipping cum meshes after sex i.e. the ones from babodialogue or https://kemono.cr/patreon/user/42557848/post/117736349

2. equipping a random DD item from a list. I.e. a list of collars.

 

for #1 your solution would work for me fine (and it would be improved by what you mentioned by equipping the existing one so if you could add that logic I would appreciate it)

for #2, the slot list would be helpful instead of just scanning for a specific item, so I could see for example if something was in slot 40 or whatever don't try because I don't know what exactly would be in slot 40, have any solution for that?

 

in my previous uses i just dealt with the duplicates lol

Edited by bandetlol

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