Welcome to
Mod The Sims
Online: 1367
News:
Have an account? Sign in:
pass:
If you don't have an account, why not sign up now? It's free!
Other sites: SimsWiki
Reply  Replies: 92 (Who?), Viewed: 86425 times.
Search this Thread
Old 26th Nov 2017, 12:13 PM #76
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


Quote:
Originally Posted by luvmebby
I keep getting errors when trying to add STBL 0x220557DA

Ok, the exception you are posting is a bug in s4pe itself - it seems to happen if you have non-numeric information in either the Group or Instance fields. I was able to get that error to throw by putting a space after the 0x00000000 in Group (entered "0x00000000 " instead of "0x00000000"), so be careful that the numbers are typed precisely as shown with no extra spaces or other letters. You should then be able to get past this without an error.

Of course, the tutorial still won't work - I haven't had a chance to update it yet.

ETA - Actually the exception I generated is slightly different but it is similar in concept - gotta make sure those numbers are correctly formatted until they fix that. I'm reporting it to s4pe team.
Old 26th Nov 2017, 3:10 PM #77
CmarNYC
Ms. Byte



Join Date: Jul 2009
Posts: 5,345
Thanks: 43525 in 63 Posts
25 Achievements

View My Journal


Quote:
Originally Posted by luvmebby
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?


That error suggests that you don't have a recognizable hex number in one or more of the TGI fields when trying to add the STBL. I tried the tutorial and didn't get an error. Could you please post a screenshot of the Resource Details popup along with the error so I can see exactly what you entered?

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Old 27th Nov 2017, 12:08 AM #78
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


The tutorial has been updated for the latest game and S4PE changes.
Old 25th Jan 2018, 8:32 PM #79
xavierm
Test Subject

Join Date: Jan 2018
Posts: 3


Hey guys,

Is some of you ever had lastexeption error log while adding superaffordance to objects?

The injector i use for the sim itself work really well but i having some issue to injecting interacton to computer
Code:

import services
import injector
import objects.game_object

wjpcomputer_sa_instance_ids = (13185967255977241388, 16238112778709694730, )
wjpcomputer_object_ids = (14845, 34680, 40340, 34682, 34684, 34679, 34678, 36369, 36370, 77507, )

@injector.inject_to(objects.game_object.GameObject, 'on_add')
def wjpcomputer_add_super_affordances(original, self):
original(self)

if not self.guid64 in wjpcomputer_object_ids: //the line 12 who cause conflict
return

sa_list = []
affordance_manager = services.affordance_manager()
for sa_id in wjpcomputer_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)


In theory it's working i can see my interaction on the computer the interaction work well but i'm stuck with those errors pop up every 5-10 secs and slow down the game drastically .

File ".\CompSuperA.py", line 12, in wjpcomputer_add_super_affordances
AttributeError: 'Jig' object has no attribute 'guid64'

I'm kind a noob in python i'm better with the xml file any help would be very appreciated!! Thanks!
Old 26th Jan 2018, 3:15 AM #80
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


Quote:
Originally Posted by xavierm
In theory it's working i can see my interaction on the computer the interaction work well but i'm stuck with those errors pop up every 5-10 secs and slow down the game drastically .

File ".\CompSuperA.py", line 12, in wjpcomputer_add_super_affordances
AttributeError: 'Jig' object has no attribute 'guid64'

What's happening is that a Jig object is being loaded onto the lot that doesn't have a guid64. I've seen this happen with objects or interactions that are created on the fly by the game, they don't have a guid64 (or in XML speak, an "instance ID"). Two ways you could fix that, either check to see the guid64 attribute exists using hasattr(self, 'guid64') before trying to test it, or redo the code to add the superaffordances to the actual object tuning at load instead of adding it to the objects as they are loaded onto the lot. The second method is vastly preferable as it will only run once as the game starts, something like this:
Code:
import services
from sims4.tuning.instance_manager import InstanceManager
from sims4.resources import Types
from injector import inject_to

def add_super_affordances_to_objects(self):
    wjpcomputer_sa_instance_ids = (13185967255977241388, 16238112778709694730)
    wjpcomputer_object_ids = (14845, 34680, 40340, 34682, 34684, 34679, 34678, 36369, 36370, 77507)
    affordance_manager = services.affordance_manager()
    
    # Get a list of all the superaffordance tuning instances first
    sa_list = []
    for sa_id in wjpcomputer_sa_instance_ids:
        key = sims4.resources.get_resource_key(sa_id, Types.INTERACTION)
        sa_tuning = affordance_manager.get(key)
        if not sa_tuning is None:
            sa_list.append(sa_tuning)
    sa_tuple = tuple(sa_list)

    # Add the tuple of superaffordance tunings to each of the objects
    for obj_id in wjpcomputer_object_ids:
        key = sims4.resources.get_resource_key(obj_id, Types.OBJECT)
        obj_tuning = self._tuned_classes.get(key)
        if not obj_tuning is None:
            obj_tuning._super_affordances = obj_tuning._super_affordances + sa_tuple

# After class instance data is loaded at startup, call our function
#   to add all the required superafordances to the objects
@inject_to(InstanceManager, 'load_data_into_class_instances')
def load_data_into_class_instances(original, self):
    original(self)
    if self.TYPE == Types.OBJECT:
        add_super_affordances_to_objects(self)
Old 29th Jan 2018, 4:32 AM #81
xavierm
Test Subject

Join Date: Jan 2018
Posts: 3


Thanks a lot!

I would like to use your technique to inject affordances to a sim. is it possible? I tryed many options but still unsuccessful at this time. I think i'm close but something is missing:

Code:

import services
from sims.sim import Sim
from sims4.resources import Types
from injector import inject_to

def add_super_affordances_to_objects(self):
wjpsims_sa_instance_ids = (15457246327094184977, 17709353295582841546, 10704380331120406141, 15421753369241220122, 14011747039628836317, 13528898888471733218, 15116289188983357572, 18154468906577769099, 10841939712105188712, 14555147986889676928, 10598527989307607484, 17613162279974342394)
affordance_manager = services.affordance_manager()

# Get a list of all the superaffordance tuning instances first
sa_list = []
for sa_id in wjpsims_sa_instance_ids:
key = sims4.resources.get_resource_key(sa_id, Types.INTERACTION)
sa_tuning = affordance_manager.get(key)
if not sa_tuning is None:
sa_list.append(sa_tuning)
self._super_affordances = self._super_affordances + tuple(sa_list)

# After class instance data is loaded at startup, call our function
# to add all the required superafordances to the objects
@inject_to(Sim, 'load_data_into_class_instances')
def load_data_into_class_instances(original, self):
original(self)
add_super_affordances_to_objects(self)
Old 29th Jan 2018, 9:50 AM #82
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


Quote:
Originally Posted by xavierm
I would like to use your technique to inject affordances to a sim. is it possible? I tryed many options but still unsuccessful at this time.

Adding to the super affordances for a Sim object is exactly the same process. In your code you are trying to inject_to the load_data_into_class_instances() method of the Sim class, but that class doesn't have that method. The load_data_into_class_instances() method is part of the InstanceManager.

Instead, keep the load_data_into_class_instances() injection the same as before, but in add_super_affordances_to_objects() you should change the wjpcomputer_object_ids to point to the instance IDs for the object_sim tuning (14965) instead of the list of computer objects. Since it's not a list of objects we can remove the for loop for the object ids and just get the object_sim.

So, using the SA values from your code, the new code might look something like:
Code:
import services
from sims4.tuning.instance_manager import InstanceManager
from sims4.resources import Types
from injector import inject_to

def add_super_affordances_to_objects(self):
    wjpsims_sa_instance_ids = (15457246327094184977, 17709353295582841546, 10704380331120406141, 15421753369241220122, 14011747039628836317, 13528898888471733218, 15116289188983357572, 18154468906577769099, 10841939712105188712, 14555147986889676928, 10598527989307607484, 17613162279974342394)
    wjpsims_object_sim_id = 14965
    affordance_manager = services.affordance_manager()

    # Get a list of all the superaffordance tuning instances first
    sa_list = []
    for sa_id in wjpsims_sa_instance_ids:
        key = sims4.resources.get_resource_key(sa_id, Types.INTERACTION)
        sa_tuning = affordance_manager.get(key)
        if not sa_tuning is None:
            sa_list.append(sa_tuning)
    sa_tuple = tuple(sa_list)

    # Add the tuple of superaffordance tunings to the object_sim tuning
    key = sims4.resources.get_resource_key(wjpsims_object_sim_id, Types.OBJECT)
    object_sim = self._tuned_classes.get(key)
    object_sim._super_affordances += sa_tuple

# After class instance data is loaded at startup, call our function
#   to add all the required superafordances to the objects
@inject_to(InstanceManager, 'load_data_into_class_instances')
def load_data_into_class_instances(original, self):
    original(self)
    if self.TYPE == Types.OBJECT:
        add_super_affordances_to_objects(self)
Old 29th Jan 2018, 4:36 PM #83
xavierm
Test Subject

Join Date: Jan 2018
Posts: 3


Quote:
Originally Posted by scumbumbo
Adding to the super affordances for a Sim object is exactly the same process. In your code you are trying to inject_to the load_data_into_class_instances() method of the Sim class, but that class doesn't have that method. The load_data_into_class_instances() method is part of the InstanceManager.

Instead, keep the load_data_into_class_instances() injection the same as before, but in add_super_affordances_to_objects() you should change the wjpcomputer_object_ids to point to the instance IDs for the object_sim tuning (14965) instead of the list of computer objects. Since it's not a list of objects we can remove the for loop for the object ids and just get the object_sim.

So, using the SA values from your code, the new code might look something like:
Code:
import services
from sims4.tuning.instance_manager import InstanceManager
from sims4.resources import Types
from injector import inject_to

def add_super_affordances_to_objects(self):
    wjpsims_sa_instance_ids = (15457246327094184977, 17709353295582841546, 10704380331120406141, 15421753369241220122, 14011747039628836317, 13528898888471733218, 15116289188983357572, 18154468906577769099, 10841939712105188712, 14555147986889676928, 10598527989307607484, 17613162279974342394)
    wjpsims_object_sim_id = 14965
    affordance_manager = services.affordance_manager()

    # Get a list of all the superaffordance tuning instances first
    sa_list = []
    for sa_id in wjpsims_sa_instance_ids:
        key = sims4.resources.get_resource_key(sa_id, Types.INTERACTION)
        sa_tuning = affordance_manager.get(key)
        if not sa_tuning is None:
            sa_list.append(sa_tuning)
    sa_tuple = tuple(sa_list)

    # Add the tuple of superaffordance tunings to the object_sim tuning
    key = sims4.resources.get_resource_key(wjpsims_object_sim_id, Types.OBJECT)
    object_sim = self._tuned_classes.get(key)
    object_sim._super_affordances += sa_tuple

# After class instance data is loaded at startup, call our function
#   to add all the required superafordances to the objects
@inject_to(InstanceManager, 'load_data_into_class_instances')
def load_data_into_class_instances(original, self):
    original(self)
    if self.TYPE == Types.OBJECT:
        add_super_affordances_to_objects(self)


(EDIT)

Thanks again! Here the code who worked for me;

Code:

import services
from sims4.tuning.instance_manager import InstanceManager
import sims4.resources
from sims4.resources import Types
from injector import inject_to

def add_super_affordances_to_objects(self):
    wjpsims_sa_instance_ids = (10598527989307607484, 17613162279974342394)
    wjpsims_object_sim_id = 14965
    affordance_manager = services.affordance_manager()

    # Get a list of all the superaffordance tuning instances first
    sa_list = []
    for sa_id in wjpsims_sa_instance_ids:
        key = sims4.resources.get_resource_key(sa_id, Types.INTERACTION)
        sa_tuning = affordance_manager.get(key)
        if not sa_tuning is None:
            sa_list.append(sa_tuning)
    sa_tuple = tuple(sa_list)

    # Add the tuple of superaffordance tunings to the object_sim tuning
    key = sims4.resources.get_resource_key(wjpsims_object_sim_id, Types.OBJECT)
    object_sim = self._tuned_classes.get(key)
    object_sim._super_affordances += sa_tuple

# After class instance data is loaded at startup, call our function
#   to add all the required superafordances to the objects
@inject_to(InstanceManager, 'load_data_into_class_instances')
def load_data_into_class_instances(original, self):
    original(self)
    if self.TYPE == Types.OBJECT:
        add_super_affordances_to_objects(self)


i only add the import sims4.resources to make the code working.
Last edited by xavierm : 29th Jan 2018 at 6:54 PM.
Old 4th Feb 2018, 8:28 PM #84
insiderw
Test Subject

Join Date: Jun 2014
Posts: 21


May I ask a super basic question here (super noob)? Is YOURMODNAME some random thing I just put into python script, or is it something that should be defined in xml file? I know my interaction tuning (new super affordance) works, because I've added it to an object's clone, but I wanted to add it to all objects, hence me being here. I used Aren's template for my script, but the option doesn't show in game, so I was wondering where I messed up.
Old 5th Feb 2018, 4:16 AM #85
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


Quote:
Originally Posted by insiderw
May I ask a super basic question here (super noob)? Is YOURMODNAME some random thing I just put into python script, or is it something that should be defined in xml file?

Just some random thing, like a comment. Totally not needed, each script runs in a separate namespace so if two script mods share the same variable name there shouldn't be a conflict.
Old 5th Feb 2018, 8:16 AM #86
insiderw
Test Subject

Join Date: Jun 2014
Posts: 21


Quote:
Originally Posted by scumbumbo
Just some random thing, like a comment. Totally not needed, each script runs in a separate namespace so if two script mods share the same variable name there shouldn't be a conflict.


Thank you so much for clarification! Basically I wanted to add a SimRay interaction to objects, sort of like DeathRay mod added one for sims. Unfortunately I still failed to make the script work (using both original code and code from post #82), but I have no experience with proper coding other than some xml tweaking, so I guess I'm back to overriding object tunings.
Old 5th Jul 2018, 10:40 AM #87
THA
Lab Assistant

Join Date: Dec 2013
Posts: 81


You should rewrite this tutorial using sims 4 studios since everything we need to make it are in one program, cause following the tutorial has me all over the place and we can extract tuning directly in s4s!
Old 5th Jul 2018, 1:34 PM #88
Inge Jones
One horse disagreer of the Apocalypse

Join Date: Sep 2004
Posts: 11,219
Thanks: 9135 in 18 Posts
20 Achievements


Careful with the "should"s...

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Old 5th Jul 2018, 8:07 PM #89
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


I've been made aware that the Modding Toolbox by @Fogity is no longer available on Dropbox and I can't find the PM I was sure he'd sent me that I could make it available to folks if he was no longer around. I'm in the process of writing an updated version, might take a couple of hours to get it all nice and neat, but will make it (w/ source code) available here on MTS.
Last edited by scumbumbo : 5th Jul 2018 at 8:24 PM.
Old 6th Jul 2018, 1:06 AM #90
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


I've created a new version of Fogity's Modding Toolbox and added it to the Modding Tools forum section here.
Old 24th Jul 2018, 5:08 PM
ixamy
This message has been deleted by ixamy. Reason: Delete
Old 26th Oct 2018, 6:59 PM #91
RedFaction
Test Subject

Join Date: Oct 2013
Posts: 3


Does this thread cover only SA injection or it could be used to inject anything ?

For instance if I modify an object _part_data, could it be done easily or we need to develop a brand new script each time we need to inject a different tag ?

Considering how easy it is to modify an XML comparing to develop a script to inject stuff, would it be a good idea to develop some kind of XML merger tool which merges the EA original XML file with any custom modification before running the game ?

There used to be a Mod Organizer for Skyrim which did kind of that thing.
It's a user interface listing all mods you had installed, and telling you which modify the same entries, which are compatible, which are not and will override themselves and so on.
It was great because your mods were never installed. They were stored in a specific folder waiting for the game to start.
Upon start, Mod Organizer created a virtual mod environment, taking all vanilla files and applying the mods in the order you told him to.
Doing so you ensure both compatibility with vanilla files update and mods which change the same file (except if they change the same part of a single file of course).

Illustration of Mod Organizer for those interested :



Well maybe all of this is totally irrelevant, sorry if it's the case
Old 4th Nov 2018, 8:01 AM #92
scumbumbo
Original Poster

Theorist

Join Date: May 2012
Posts: 2,431
Thanks: 46353 in 83 Posts
22 Achievements


Quote:
Originally Posted by RedFaction
Does this thread cover only SA injection or it could be used to inject anything ?

Sorry for the late reply on this, I'd been planning to attend to your question for a few days now. Many things can be changed in the XML as the game loads using these injections. The technique can be basically as simple as that used for the super affordances or it can be quite a bit more complex. It just depends on the data being altered and how that data is stored.

I've never looked into modifying an object tuning's _part_data info, but it should be completely doable. The main approach is to use the Python inspect package on the relevant data in the game to see what is there, then inspecting further until you find exactly what you want to change. Then finally you can create a script that injects into the load_data_into_class_instances method to make those changes at game load.

I have an example of an investigative process to determine how to inject some data (adding an affordance filter) in the thread for The Inspector.

D3OI is also a very useful tool that I've written for the game which allows you to shift-click (if you have enable debug cheats mod installed) an object in the game and retrieve some basic information about it, or dump more complete info into a file. It's a nice quickie tool to have in the arsenal, but The Inspector above is much more powerful.

Quote:
Considering how easy it is to modify an XML comparing to develop a script to inject stuff, would it be a good idea to develop some kind of XML merger tool which merges the EA original XML file with any custom modification before running the game ?

I'd given some thought to that previously, as I'm sure others have, and there are some inherent problems with trying to merge XML in that manner. It's certainly "theoretically" doable, but creating something that can intelligently choose when to merge, when to add data, or when and how to throw out conflicting data is quite a task. I for one would not have any interest in trying to support such a program and the continual problems that would arise for the players attempting to use a merger without full knowledge of what they are doing. Within hours you would be guaranteed to be getting requests to help them combine mod "X" and "Y" which, when they attempt to merge them, causes all of their pets to have monkey heads where their tails should be.
Old 5th Nov 2018, 12:31 AM #93
RedFaction
Test Subject

Join Date: Oct 2013
Posts: 3


Quote:
Originally Posted by scumbumbo
creating something that can intelligently choose when to merge, when to add data, or when and how to throw out conflicting data is quite a task.

I was thinking of giving instructions to that program :

Instead of modifying directly the XML, you create an instructions XML in which you put modifications instructions (such as add, del, or mod), followed by a destination tag and a value.
Next, instead of running the game through its executable, you run it through the tool which behaves like a mod organizer :
1. It takes EA original XMLs
2. It gathers all modifications XML (created by modders)
3. It follows their instructions to add/del/mod the EA original XML content
4. It notifies the user if two or several files are modifying the same values
5. It creates the virtual merged mods folder (which is our EA mods folder)
6. It runs the game
Quote:
Originally Posted by scumbumbo
I for one would not have any interest in trying to support such a program and the continual problems that would arise for the players attempting to use a merger without full knowledge of what they are doing

Mods are not really merged.
Instead of putting them in the EA mods folder, you put them in the tools mods folder.
Then, the tool creates the EA mods folder with the merged files, but the original unmerged mods are still stored separately in the tool mods folder.
If you add or remove mods, or if you change the mods order through the tool interface, then it updates the EA mods folder accordingly.
Quote:
Originally Posted by scumbumbo
Within hours you would be guaranteed to be getting requests to help them combine mod "X" and "Y" which, when they attempt to merge them, causes all of their pets to have monkey heads where their tails should be.

From my point of you the virtual merge doesn't bring more issues that there is now.

Let's say you want to play with 2 incompatible mods which both modifies the same XML entry :
1. If the mods are XML mods : the last mod will overwrite the first one with no warning
2. If the mods are using a script to inject XML : again the last one will overwrite the first one with no warning
3. If we have a XML merger : the last will still overwrite the first, but the tool will be able to notify it

And the other way around is also true : if two mods modify the same ressource, but are compatibles thanks to a script (because they don't modify the same XML entries), then there is no reason it won't work using a merger, because XML instructions will point to different destinations.

The difference is that, still from my modest point of view , it looks way easier to create an instructions XML than a dedicated python script.

Anyway this is how we dealt with this problem in Skyrim
Maybe it's a bit difficult to figure the thing out if you hadn't the chance to play this wonderful game ^^
Reply


Section jump:


Powered by MariaDB Some icons by http://dryicons.com.