This should be a useful addition to the collective arsenal, allowing the ability to add interactions for sims without requiring overriding the _super_affordances tuning in the object_sim resource. This allows for multiple mods to add interactions for sims without conflict.

treelife brought this up recently in a thread, although I believe that was in reference to objects. This method works for just sims, but should be able to be adapted to objects as well. A sim is just a special object after all, the only difficulty with objects may be to identify the proper object to add the affordances to, but that shouldn't be too major. There had been a thread about this earlier, and although it was agreed that scripting might be a good idea to overcome conflicts, I don't know that anyone made much progress at it. It seemed straightforward, but without knowing how all the internals actually worked it wasn't at all.

After a lot of false tries, and a lot of poking through the source, and a lot of examing the outputs from vars() on objects, I finally had some success. Turns out it is actually fairly easy! The super affordance tuning classes available to a sim are stored as a tuple in the sim object called _super_affordances. All that remained was to find a way to query the affordance manager to get the tuning classes we want to add to the sim.

There may be a better way to do this, but I'm just relieved to have figured this method out in the short span of 10 or 15 hours worth of work.

First, create the XML for all the interactions, pie menu categories, etc. Create a tuple of all the instance ids for all of your interactions - the numbers you would normally add to the _super_affordances list in the XML. Then a little bit of Python, injected into the sims on_add() method will do the trick:

Thanks so much! I've been working all day trying to figure out how to do exactly this. Took a break to see if by some miracle anyone else figured it out, and alas!

Here's a slightly modified version to add interactions to any game object. Just add the IDs of the objects you want to the object_ids tuple (for example, I included the IDs of all the computers in the game).

This should be a useful addition to the collective arsenal, allowing the ability to add interactions for sims without requiring overriding the _super_affordances tuning in the object_sim resource. This allows for multiple mods to add interactions for sims without conflict.

treelife brought this up recently in a thread, although I believe that was in reference to objects. This method works for just sims, but should be able to be adapted to objects as well. A sim is just a special object after all, the only difficulty with objects may be to identify the proper object to add the affordances to, but that shouldn't be too major. There had been a thread about this earlier, and although it was agreed that scripting might be a good idea to overcome conflicts, I don't know that anyone made much progress at it. It seemed straightforward, but without knowing how all the internals actually worked it wasn't at all.

After a lot of false tries, and a lot of poking through the source, and a lot of examing the outputs from vars() on objects, I finally had some success. Turns out it is actually fairly easy! The super affordance tuning classes available to a sim are stored as a tuple in the sim object called _super_affordances. All that remained was to find a way to query the affordance manager to get the tuning classes we want to add to the sim.

There may be a better way to do this, but I'm just relieved to have figured this method out in the short span of 10 or 15 hours worth of work.

First, create the XML for all the interactions, pie menu categories, etc. Create a tuple of all the instance ids for all of your interactions - the numbers you would normally add to the _super_affordances list in the XML. Then a little bit of Python, injected into the sims on_add() method will do the trick:

and could I get the "interaction" to play a python method rather than an animation? (like start/end a function)

Yeah, I just uploaded a mod that java7nerd and I made tonight, the Pregnancy Mega Mod that does just that using the CommandSuperInteraction tunings. It will send the script the target of the interaction, a sim ID or object ID as an argument. There's also a "do_command" tuning available to regular SuperInteractions which would allow for animation and so forth to be added. I'm planning on using that for a future lottery mod.

Yeah, I just uploaded a mod that java7nerd and I made tonight, the Pregnancy Mega Mod that does just that using the CommandSuperInteraction tunings. It will send the script the target of the interaction, a sim ID or object ID as an argument. There's also a "do_command" tuning available to regular SuperInteractions which would allow for animation and so forth to be added. I'm planning on using that for a future lottery mod.

you're seriously amazing! I have no idea how you all produce mods so fast and still do such an excellent job. in any case, thanks for helping me

Please forgive my ignorance when it comes to Python, I must be missing something obvious... Before I tried to use this for a massive spread of things, I did a very simple one to one test. Part of one of my mods has me adding my own file instance 17302112734137328986 to the super affordances in the object_telescope file 14981. It's the only affordance that gets added to that file. When I do that just in the XML files, it works no problem.

So I stripped the 14981 file out of my XML package. I used the object code from this thread as such:
import services
import injector

I included the injector file, I tried it with and without the final commas in the lists, and I tried it both with the .py files in Scripts subfolder and also with it all compiled and zipped. But it doesn't actually work in the game. Can someone tell me where I've gone wrong?

Please forgive my ignorance when it comes to Python, I must be missing something obvious...

The obvious only becomes obvious with experience, so no forgiveness is necessary. The problem is that the injector.inject_to line doesn't see the GameObject object unless you import the file it's contained in. Add a line to the imports in your code above:

import objects.game_object

Everything should start to come together after that. And yes, since you're only using one interaction and one object, you are correct that you need the comma at the end of the lists in order to make them tuples - that threw me for a loop the first time I ran into it myself.

@Aren - Can you update the code in your post above to include that import line when you get the chance?

When trying to add custom interactions to gardening plants, it didnâ€™t work to just use the (adapted) code posted by Aren above; I got a bunch of exceptions like

Quote:

File "C:\Users\User\Documents\Electronic Arts\The Sims 4\Mods\pbox_kindergarden\Scripts\pbox_kindergarden.py", line 17, in pbox_kindergarden_add_super_affordances
for sa_id in pbox_kindergarden_sa_instance_ids: TypeError: 'int' object is not iterable

and the objects in question also disappeared on load, no matter what they were (for testing purposes I also tried with other stuff but plants). Adding the same interaction to the same objects by way of a manual override (adding them in to the object XML and overriding that) did work, however.

When I use the script posted by @graycurse in this Feedback thread as a basis, it does work. That one seems to do some more elaborate error catching or something? .. I canâ€™t say I really understand exactly WHY it works:

When I use the script posted by @graycurse as a basis, it does work. That one seems to do some more elaborate error catching or something? .. I canâ€™t say I really understand exactly WHY it works

Can someone perhaps explain where the crucial difference is?

In Python, the parenthesis are not what makes a tuple a tuple, they are really just a decorative convention to kind of comment that "this is supposed to be a tuple". The commas are what make a tuple.

Code:

#in other words....
pbox_kindergarden_sa_instance_ids = (11045034422696481829)
# is really just the same thing as
pbox_kindergarden_sa_instance_ids = 11045034422696481829

Since the result is not a tuple, just a plain integer, it's not iterable.

graycurse adds a test to see if the instance_ids variable contains just an integer object and, if it does, skips the iteration of the tuple. That's one fix, and it's 100% perfectly acceptable. Another fix would be to just use the original code and make the instance_ids variable a true tuple containing a single integer by using the comma after the value:

Code:

# this is a true tuple and is iterable
pbox_kindergarden_sa_instance_ids = (11045034422696481829, )

I feel this makes the code a little cleaner and easier to read as it avoids the need for the test and a separate function (the separate function is just to avoid code duplication and is a good thing for graycurse's method, it doesn't change how the assignment acts or anything, just encapsulates it rather than repeating the assignment twice in the if/else block).

So, use what you like - both should work fine! But if you do use graycurse's method, for clarity you should probably remove the parenthesis around the assignment of the single int to make it clear that it's just a single int and not a tuple.

EDIT - And since I'm planning on playing today and not doing any modding at all (yeah, that'll happen) I think I'm going to have my geeky programmer/author sim write a new mystery book, The Curse of the Missing Tuple

Aaah thanks very much for the explanation =). The non-tupleness might have resolved itself if I had added the other interactions (which I didnt do since the whole thing didn't work) .. but if it had, Iâ€™d never have realised what the issue was. Live and learn!

Yeah, tupleness threw me for a loop as I was first learning to get this working, which bears the question "Why use a tuple at all, why not just a list?"

The primary reason is for speed. A tuple is immutable, you can't append an item to a tuple like you can a list, so it can be stored and used by Python a bit faster. Since this function is going to get called a LOT during the game (every single time for every single object that is put on a lot), speed is important. This is just one of the reasons why EA used a tuple to store all the SA instances (instanced objects, not instance ids - important difference) in the object, so it can be quickly searched - they didn't anticipate we'd be wanting to add items to it!

This is also why at the end we have to convert the sa_list (which had to be a list as we need to append to it) to a tuple in order to add it to the original tuple and then reassign the whole shebang over the original tuple. We can't just append to the tuple, we have to replace the whole thing. Read that through a few times and it should make sense!

The technique for adding an affordance to the sim object also works for adding SAs to the _phone_affordances of a sim. Just change the last line of the script in the first post to reference self._phone_affordances If you need an example, check out the Change Career Branch mod which uses this tactic.

Is there a way to generate basic cheat command executing interactions (CommandSuperInteraction) purely from code? Does someone have some code lying around that does that as an example? I tried figuring out the XML stuff, but no matter what I do, it won't accept my STBL strings and I can't get the interaction to show up. The game complains "T:\InGame\Gameplay\Scripts\Server\sims\self_interactions.py", line 560, in _get_interaction_name
AttributeError: 'NoneType' object has no attribute 'localized_category' although I think my ids should be correct, but who knows. It's not exactly a specific error.. STBL debugging sucks..

Your code seems pretty close, but it still requires the working XML for an interaction which I just can't figure out. There are nice tutorials for Sims 3: http://modthesims.info/wiki.php?tit...ocalized_Coding but as I wrote above, I can't figure it out for Sims 4 even if I set up my STBL stuff in a similar way to that tutorial. And I got Python code to run nicely so if I could just do it from there..

Is there a way to generate basic cheat command executing interactions (CommandSuperInteraction) purely from code? Does someone have some code lying around that does that as an example?

It could probably be done, but it's easier with the XML. Basically the alternative would be to generate all the tuning in script which is not at all fun. I'm playing with that now to improve the text input dialog calls from Python as, for that case, doing it with code is easier than creating some kind of XML interaction to control the text inputs. I'm planning on posting where I got stuck with that later tonight, but I did make some good progress.

But for what it sounds like what you're wanting, just calling a script command from the UI, it's easier with the XML. I'll try and come up with a good example and spend some time on doing a tutorial if folks think it would be helpful.

The technique for adding an affordance to the sim object also works for adding SAs to the _phone_affordances of a sim. Just change the last line of the script in the first post to reference self._phone_affordances If you need an example, check out the Change Career Branch mod which uses this tactic.

Was looking through the sim.py file for something totally unrelated, but noticed something else that should also be useable: self._relation_panel_affordances should also be a target for adding SAs to the relationship panel. Haven't tried it, but it appears that it should work.