Hi there! You are currently browsing as a guest. Why not create an account? Then you get less ads, can thank creators, post feedback, keep a list of your favourites, and more!
Deceased
Original Poster
#51 Old 6th Aug 2015 at 6:18 AM
Quote: Originally posted by plasticbox
But wouldn't it make sense on the long run when people give their injectors individual names anyway? Right now it's like we're all silently relying on them all being identical ..

I would say only if the author is diverging from the initial injector that Scripthoge wrote, but then I'm pretty ambivalent about it. I guess I got into bad habits from when there were no more than a handful of us doing script modding, but now that it's getting more widespread maybe that's a good idea - not only for the injector, but for any module name. It could cause issues with any module, say two modders both used the filename 'modify_pregnancy.pyo' one would get loaded and the other ignored.

Who has the clout to make an "official specification" for module names? I think I recall someone suggesting something for function names, but since they won't conflict being in separate modules, function names really don't matter much. At least from what I understand of Python namespaces. (Someone feel free to correct me if I'm wrong. I'm not proud. Just ambivalent.)
Advertisement
Pettifogging Legalist!
retired moderator
#52 Old 6th Aug 2015 at 7:29 AM
Quote: Originally posted by scumbumbo
I would say only if the author is diverging from the initial injector that Scripthoge wrote

Yes, that’s what I meant – as long as it’s identical it wouldn’t matter of course =)

Good point about the module names in general. I don’t think there’s a need for a lot of officialness .. I for one have learned a lot more from looking at existing mods or code samples that people post in forums, than from any sort of theoretical/general advice. Since every other script mod I’ve seen cites a certain scumbumbo as their “good example”, maybe simply start naming your modules “scumbumbo_dostuff”? The practice of including creator tags in all sorts of names is common enough, I think, for people to realise it might be a good idea to name theirs “pbox_dostuff” instead, without anyone needing to explicitely tell them that.

Stuff for TS2 · TS3 · TS4 | Please do not PM me with technical questions – we have Create forums for that.

In the kingdom of the blind, do as the Romans do.
One horse disagreer of the Apocalypse
#53 Old 11th Mar 2016 at 12:40 PM
Why isn't there a community edition injector that users are advised to install in their mods folder in the same "breath" as the instructions for resource.cfg? That would save all modders including their own duplicate unless they needed it to do something different.

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Pettifogging Legalist!
retired moderator
#54 Old 11th Mar 2016 at 1:36 PM
Quote: Originally posted by Inge Jones
Why isn't there a community edition injector


If you want that kind of thing, why don't you make it? This is Create, not Request ..

Stuff for TS2 · TS3 · TS4 | Please do not PM me with technical questions – we have Create forums for that.

In the kingdom of the blind, do as the Romans do.
One horse disagreer of the Apocalypse
#55 Old 11th Mar 2016 at 6:28 PM
Ok so been looking at the alternative use of injection in this thread, injecting to a snippet. The example was a simple one, where we just wanted to add to a top level value list. I have to inject to a snippet that looks like this:

Code:
<I c="AffordanceFilter" i="snippet" m="snippets" n="af_Retail_Item_Sold" s="110412">
  <U n="value">
    <V n="default_inclusion" t="exclude_all">
      <U n="exclude_all">
        <L n="include_affordances">
          <T>108686<!--retail_RestockItem--></T>
          <T>111859<!--si_Retail_ClearSign--></T>
          <T>115687<!--retail_RestockItem_Instant--></T>
        </L>
      </U>
    </V>
  </U>
</I>


Not sure how to go about expressing the nestedness?

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Deceased
Original Poster
#56 Old 11th Mar 2016 at 8:16 PM
Quote: Originally posted by Inge Jones
Ok so been looking at the alternative use of injection in this thread, injecting to a snippet. The example was a simple one, where we just wanted to add to a top level value list. I have to inject to a snippet that looks like this:
<snip>
Not sure how to go about expressing the nestedness?

This should be fairly simple, but rather than just figuring this out I'd like to do a, maybe not full blown tutorial, but at least a guide on how I figure these things out. I don't have the time at the moment, but would likely be able to get this done over the weekend at some point - might take more time, it depends largely on how in depth I end up making it.

The short answer is that it's just a matter of tapping into the load_data_into_class_instances method, getting the tuning you want using the key and self._tuned_classes.get() and then using the Python inspect module to dump the various variables in that tuning. In this instance it will be necessary to then use that knowledge gained to dump the variables from the nested tunings, rinse and repeat until we get down to the variable that needs to be modified and since the target variable should just be an ordinary tuple then we can just add to that tuple the items you want to add.
One horse disagreer of the Apocalypse
#57 Old 11th Mar 2016 at 8:36 PM
Thanks for the outline, I may hold off till you do your tut so I can see an example in front of me. I am very grateful to you.

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
One horse disagreer of the Apocalypse
#58 Old 18th Mar 2016 at 6:07 PM
Scumbumbo, did you post the tut somewhere or didn't you get time in the end?

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Deceased
Original Poster
#59 Old 21st Mar 2016 at 8:19 AM
Sorry Inge, still haven't had the time like I thought I would. So far though I did manage to put together a bit of a tool to help inspecting the Python objects live in the game a bit easier. I know that's not much help yet...
One horse disagreer of the Apocalypse
#60 Old 21st Mar 2016 at 1:35 PM
If you have an example one or two lines for the recursion into the keys/tags that might be enough to get me started?

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Deceased
Original Poster
#61 Old 2nd Apr 2016 at 8:17 PM Last edited by scumbumbo : 2nd Apr 2016 at 10:15 PM.
Quote: Originally posted by Inge Jones
If you have an example one or two lines for the recursion into the keys/tags that might be enough to get me started?

Sorry, I've been so busy, but you've reached "Scumbumbo's Project of the Day" status.

And the mini-guide (which turned out to be quite long of course) is written, see the thread for it here.

Try and keep any questions organized, if you have a question about the inspection process itself, ask there - but if you have a question about using the results of the inspection process ask in a new thread or here, whichever seems appropriate.
One horse disagreer of the Apocalypse
#62 Old 2nd Apr 2016 at 10:38 PM
Thank you !

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Lab Assistant
#63 Old 16th Jul 2016 at 1:43 AM
Quote: Originally posted by scumbumbo
There's been a lot of experimentation since this was originally posted, so I thought it might be nice to add a list of important posts from the thread:
Original Message

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:

Code:
import services
import injector

YOURMODNAME_sa_instance_ids = (17608706005782878675, 13258313599595875556, ...etc for all the interactions you're adding)
    
@injector.inject_to(sims.sim.Sim, 'on_add')
def YOURMODNAME_add_super_affordances(original, self):
    original(self)
    sa_list = []
    affordance_manager = services.affordance_manager()
    for sa_id in YOURMODNAME_sa_instance_ids:
        tuning_class = affordance_manager.get(sa_id)
        if not tuning_class is None:
            sa_list.append(tuning_class)
    self._super_affordances = self._super_affordances + tuple(sa_list)

That's all there is to it. You'll also need the injector.py script, but several script mods have this already to get a copy of - e.g. Always Start Lots Pause

Obviously, as much time as I've spent on getting this working, I'd appreciate credit for anyone who uses this.


So is there an actual list of export tunes or super affordances? There are never ending options, it's just confusing.

What is a beginner to do? My Website My TOT My Forum My website
Test Subject
#64 Old 12th Aug 2016 at 12:59 AM
Thank you so much for this! It was easy to follow and I was able to create custom interactions for a custom content object <3
Lab Assistant
#65 Old 14th Oct 2016 at 11:15 AM Last edited by konansock : 14th Oct 2016 at 1:17 PM.
I made a custom interaction for TV but when I tested in game I found that it was also attached to stoves, refrigerators, toilets, bathtubs, computers...So what's the matter about my script? My script goes like this:

import services
import injector
import objects.game_object

REXTVguide_TV_sa_instance_ids = (1956218958,)
REXTVguide_TV_object_ids = (14995, 39355, 77515, 14996, 36924, 39353, 36923, 77551, 77552, 36926, 36925)

@injector.inject_to(objects.game_object.GameObject, 'on_add')
def REXTVguide_TV_add_super_affordances(original, self):
original(self)
sa_list = []
affordance_manager = services.affordance_manager()
for sa_id in REXTVguide_TV_sa_instance_ids:
tuning_class = affordance_manager.get(sa_id)
if not tuning_class is None:
sa_list.append(tuning_class)
self._super_affordances = self._super_affordances + tuple(sa_list)



Just edited it so I can ask if I should also include the Television.py and Pick_channel.py
But they showed up on TV actually. I'm confused
Test Subject
#66 Old 11th Feb 2017 at 7:03 AM Last edited by thewatcheruatu : 11th Feb 2017 at 7:20 AM.
I don't suppose anybody is willing to explain this to me like I'm five? I pretty much just started messing around with modding TS4 today. I mean, I've programmed extensively in other languages, but never Python and never for game modding purposes, and I'm getting a little bleary eyed from looking at XML and code all day. I'm trying to learn, though.

I don't even care right now about the best, most efficient way to do this. For now, I just want to see something work.

As a test, I basically made a straight copy of the tuning file for sim_TalkToSelf, since unless I'm mistaken, it's always available from the active Sim actor's top level context menu. I changed the sim_TalkToImaginaryFriend, updated the instance ID with the decimal version of the 64-bit FNV-1 hash of thewatcheruatu:sim_talktoself with the high bit set, and I think the only thing I changed was for testing purposes, I altered the trait whitelist from the insane trait to the bookworm trait (27916). I mean, it seemed like a pretty foolproof way to test how a custom interaction might work. Oh, and I used s4pe to create an STBL file (as explained here: http://modthesims.info/showthread.php?t=573055) just for the name of the interaction.

Packaged them, put them in the mod directly, was kind of hoping it would just work, and then discovered that I guess I have to script inject custom interactions into the game(?).

Okay, I can do that. So I came to this thread--didn't really care about performance at this point--grabbed injector.pyo, created another script with the following code, compiled it, bundled them in a ts4script archive, and moved it into the mod directory:

Code:
import services
import injector
import sims.sim

interaction_test_sa_instance_ids = (12191329784171701135)

@ injector.inject_to(sims.sim.Sim, 'on_add')


def interaction_test_add_super_affordances(original, self):
    original(self)
    sa_list = []
    affordance_manager = services.affordance_manager()
    for sa_id in interaction_test_sa_instance_ids:
        tuning_class = affordance_manager.get(sa_id)
        if not tuning_class is None:
            sa_list.append(tuning_class)
    self._super_affordances = self._super_affordances + tuple(sa_list)


What this did was cause my game to hang upon attempting to load the world. So I assume I did something wrong.

Would really be appreciative if somebody could give me a nudge in the right direction.

Edit: I tried it again, this time with Deaderpool's code from post #33 in this thread, changing only these two lines:

Code:
sa_instance_ids = (12191329784171701135)
object_ids = (sims.sim.Sim)


Sadly, it still didn't work, but the game didn't hang on load this time. Clearly, I'm missing something that is probably completely obvious.
Instructor
#67 Old 11th Feb 2017 at 1:18 PM
Quote: Originally posted by thewatcheruatu
I don't suppose anybody is willing to explain this to me like I'm five? I pretty much just started messing around with modding TS4 today. I mean, I've programmed extensively in other languages, but never Python and never for game modding purposes, and I'm getting a little bleary eyed from looking at XML and code all day. I'm trying to learn, though.

I don't even care right now about the best, most efficient way to do this. For now, I just want to see something work.

As a test, I basically made a straight copy of the tuning file for sim_TalkToSelf, since unless I'm mistaken, it's always available from the active Sim actor's top level context menu. I changed the sim_TalkToImaginaryFriend, updated the instance ID with the decimal version of the 64-bit FNV-1 hash of thewatcheruatu:sim_talktoself with the high bit set, and I think the only thing I changed was for testing purposes, I altered the trait whitelist from the insane trait to the bookworm trait (27916). I mean, it seemed like a pretty foolproof way to test how a custom interaction might work. Oh, and I used s4pe to create an STBL file (as explained here: http://modthesims.info/showthread.php?t=573055) just for the name of the interaction.

Packaged them, put them in the mod directly, was kind of hoping it would just work, and then discovered that I guess I have to script inject custom interactions into the game(?).

Okay, I can do that. So I came to this thread--didn't really care about performance at this point--grabbed injector.pyo, created another script with the following code, compiled it, bundled them in a ts4script archive, and moved it into the mod directory:

Code:
import services
import injector
import sims.sim

interaction_test_sa_instance_ids = (12191329784171701135)

@ injector.inject_to(sims.sim.Sim, 'on_add')


def interaction_test_add_super_affordances(original, self):
    original(self)
    sa_list = []
    affordance_manager = services.affordance_manager()
    for sa_id in interaction_test_sa_instance_ids:
        tuning_class = affordance_manager.get(sa_id)
        if not tuning_class is None:
            sa_list.append(tuning_class)
    self._super_affordances = self._super_affordances + tuple(sa_list)


What this did was cause my game to hang upon attempting to load the world. So I assume I did something wrong.

Would really be appreciative if somebody could give me a nudge in the right direction.

Edit: I tried it again, this time with Deaderpool's code from post #33 in this thread, changing only these two lines:

Code:
sa_instance_ids = (12191329784171701135)
object_ids = (sims.sim.Sim)


Sadly, it still didn't work, but the game didn't hang on load this time. Clearly, I'm missing something that is probably completely obvious.


sa_instance_ids = (12191329784171701135, )
Test Subject
#68 Old 11th Feb 2017 at 3:07 PM Last edited by thewatcheruatu : 11th Feb 2017 at 3:45 PM.
Quote: Originally posted by azoresman
sa_instance_ids = (12191329784171701135, )


Oh, that's interesting. I guess I needed to read up on tuples in Python.

With that said, I fixed that for both the sa_ids and the object_ids, and sadly, it still isn't working. Is there any easy way to test whether the script it the problem or if it's the interaction tuning file?

Edit: Nevermind. I went back to the code from the very first post in this thread and got it to work this time. I mean, I'd still like to optimize it, so I'll explore that later, and may be back! But at least I know the tuning file is good!
Test Subject
#69 Old 17th Apr 2017 at 12:07 AM
HEllO! I need some help. I would like to make a mod that allows sims to ask for money before or after they woohoo. There is already a current mod for this but it doesnt want to work all the time and i kind of want to end up making a working sim career. I have never done anything in Python before so if someone could sort of mentor and baby step me through the process? Please please?
Test Subject
#70 Old 30th Apr 2017 at 6:49 PM
Hello !, the tutorial is fine and I think this is my only hope the only problem is that there are some things I do not understand: / and I do not know what to do, then I wondered if someone has done a tutorial videos explaining the best Subject, and if it is not so please could you do a tutorial? I will thank you too much: D
Test Subject
#71 Old 15th Nov 2017 at 10:20 PM
I honestly wish this didn't seem so complicated to me. I would love to see the cats and dogs in sims 4 be able to catch and eat the bugs and frogs in game
Test Subject
#72 Old 22nd Nov 2017 at 5:35 AM
Quote: Originally posted by scumbumbo
@blubber - I've written a bit of a tutorial that demonstrates how to build all the XML, SimData and attach the super affordances to an object. It's actually kind of a useful mod, too, I think I'll keep it in my game!

Attached is a zip file containing a PDF tutorial and all the example files. The mod adds an Enable and Disable Testing Cheats pie menu to the lot mailboxes.


I cant get past the STBL 0x220557DA I added the group and 0x00918772618D89D4 as the tutorial says just like in the picture, but the ok button stays dark in s4pe. I click on the stbl drop down tab list and reselect it then it says ok but before I can push it it says there is an unhandled exception in the program and must close. what can I do?
Deceased
Original Poster
#73 Old 22nd Nov 2017 at 10:52 AM Last edited by scumbumbo : 22nd Nov 2017 at 11:04 AM.
Quote: Originally posted by luvmebby
I cant get past the STBL 0x220557DA I added the group and 0x00918772618D89D4 as the tutorial says just like in the picture, but the ok button stays dark in s4pe. I click on the stbl drop down tab list and reselect it then it says ok but before I can push it it says there is an unhandled exception in the program and must close. what can I do?

Make sure you're using the most recent version of s4pe, it should work fine. I've read that you need to use 7zip to decompress the s4pe archive, although I've never had a problem using WinRAR myself it is a known problem with some archive programs not being able to decompress the 7z files.

ETA: Also, in hindsight, that tutorial needs some rewriting. The s4pe string table editing process (after you hopefully get past the step where it's crashing on you) has changed. Also the XML interaction file will need rewriting as there is no longer such a thing as the CommandSuperInteraction class in the game - it will have to be rewritten as an ImmediateSuperInteraction. Maybe I can get to that this weekend after the Thanksgiving holiday.
Test Subject
#74 Old 22nd Nov 2017 at 8:03 PM
Quote: Originally posted by scumbumbo
Make sure you're using the most recent version of s4pe, it should work fine. I've read that you need to use 7zip to decompress the s4pe archive, although I've never had a problem using WinRAR myself it is a known problem with some archive programs not being able to decompress the 7z files.

ETA: Also, in hindsight, that tutorial needs some rewriting. The s4pe string table editing process (after you hopefully get past the step where it's crashing on you) has changed. Also the XML interaction file will need rewriting as there is no longer such a thing as the CommandSuperInteraction class in the game - it will have to be rewritten as an ImmediateSuperInteraction. Maybe I can get to that this weekend after the Thanksgiving holiday.


sounds like a plan, hope you all have a happy thanksgiving this year. I will go ahead and unistall and reinstall s4pe, just to make sure that wasn't the problem. its possible.
Test Subject
#75 Old 25th Nov 2017 at 8:48 PM
Quote: Originally posted by Deaderpool
I was talking to Scumbumbo about this and noticed that when attaching to Sims or Objects through on_add, you are doing it every time they are instanced, which could cause an impact in performance. So, I have been looking into doing a way of doing it once. What I came-up with is injecting into the instance manager right after all the tuning files are loaded. At that point, you can add your affordances to the object tuning files and they'll be there for the rest of the time the game is running. It may cause a slightly longer loading time, but once you're to the main menu, it should not have to be added to the objects again.

The injection works like this:
Code:
sa_instance_ids = (17608706005782878675, 13258313599595875556, ...etc for all the interactions you're adding)
object_ids = (14845, 34680, 40340, 34682, 34684, 34679, 34678, 36369, 36370, 77507, ...blah, blah, whatever objects you want to attach to, which could also be a "Sim" object)

@inject_to(sims4.tuning.instance_manager.InstanceManager, 'load_data_into_class_instances')
def inject_load_data_into_class_instances(original, self):
    try:
        original(self)
        for (key, cls) in self._tuned_classes.items():
            if hasattr(cls, 'guid64') and cls.guid64 in object_ids:
                add_super_affordances_to_object(object_tuning)
    except:
        _write_error_log(traceback.format_exc())
        pass


The add_super_affordances_to_objects method looks very similar to what we already have in the tutorial for adding testing cheats to mailboxes:
Code:
def add_super_affordance_to_object(object_tuning):
    affordance_manager = services.affordance_manager()
    sa_list = []
    for sa_id in sa_instance_ids:
        tuning_class = affordance_manager.get(sa_id)
        if tuning_class is not None:
            sa_list.append(tuning_class)
    if len(sa_list) > 0:
        object_tuning._super_affordances = object_tuning._super_affordances + tuple(sa_list)


I keep getting errors when trying to add STBL 0x220557DA using scumbumbo mailbox tutorial as directed in the early steps. I tried reinstalling S4PE using the correct 7-zip method and still get the error. I want to move forward in the learning process but am stumped here as it closes the program when attempting. If you dont use the add function, what do you use instead?
Page 3 of 5
Back to top