- Site Map >
- Modding and Creation >
- Sims 4 Creation >
- Modding Discussion >
- What links an interaction tuning to some python script?
- Site Map >
- Modding and Creation >
- Sims 4 Creation >
- Modding Discussion >
- What links an interaction tuning to some python script?
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 11,006
Thanks: 423043 in 1121 Posts
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.
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 11,006
Thanks: 423043 in 1121 Posts
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.
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
That works well for cheats, although I use it for other purposes by doing a regular interaction first and pushing the command interaction - because the other method didn't use to work. However, EA started using it with Get To Work so it's working fine now and can be used. That's the "do_command" and it's available as part of a standard SuperInteraction. This has the advantage also of being able to specify multiple arguments defined in the XML to the command script, see for instance the "retail_Register_SetPrices_XXXX" interactions, 1AC8B-1AC8F in EP01.
Or if you're asking what script exactly runs as part of a standard interaction to, for example, start an animation... that's much more complex, but it is controlled by the Python scripts and I "kind of" understand what goes on at some stages and I'm "kind of" thoroughly clueless at some of the other stages. So the question would have to be pretty specific for me to answer anything. It's pretty much all in the Python though when it comes to scheduling, testing, setup and execution for the interactions.
Posts: 2,671
Thanks: 62739 in 190 Posts
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
I've never messed with triggering animations in a script, although it should be doable particularly for a one-shot. I think I'd probably try to avoid scripting for that and come at it from a different direction - that direction dependent on exactly what you are trying to accomplish. For instance, if I wanted a sim to do an arm pump or other reaction based on the results of the SimLotto, I could add a loot to them to perform a reaction. The loot itself and the actual reaction animations would all be in XML, all the script would have to do is tell the client to add that loot action to the sim.
On the other hand, if I wanted the results from the script to trigger an animation on an object, perhaps shoot fireworks out of the PC when they jackpot the lotto, I would probably come at it by adding an object state to the object itself and adding a state trigger to the object that then triggers the animation. Again, all of that would be in XML and all I would do in the script is to set the object into that state and let the XML handle the nitty gritty details of the animation itself.
So really, the only reason to turn to scripting is when you are doing something that the XML just plain can't handle, and with a bit of investigation into the tuning descriptions and experience you'll be able to figure out which approach to take. So I'd suggest diving in and we'll help out if needed!
Posts: 11,682
Thanks: 9680 in 11 Posts
What I am not quite decided on is whether I want "restock from storage" as a seperate option added to the restocking signs or whether to simply assume that if the mod is installed that's the automatic preferred action.
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 11,682
Thanks: 9680 in 11 Posts
<L n="basic_extras"> <V t="payment"> <U n="payment"> <V t="base_retail_value" n="cost" /> <U n="cost_modifiers"> <L n="multipliers"> <U> <T n="multiplier">0.75</T> <L n="tests"> <L> <V t="bucks_perks_test"> <U n="bucks_perks_test"> <T n="bucks_perk">112338<!--retailPerks_DescreaseRestockingCost--></T> </U> </V> </L> </L> </U> <U> <T n="multiplier">0.75</T> <L n="tests"> <L> <V t="bucks_perks_test"> <U n="bucks_perks_test"> <T n="bucks_perk">112337<!--retailPerks_DecreaseRestocking_Temporary--></T> </U> </V> </L> </L> </U> </L> </U> <V t="retail" n="source"> <U n="retail"> <E n="funds_category">RESTOCKING</E> </U> </V> <V t="at_end" n="timing"> <U n="at_end"> <E n="criticality">NotCritical</E> </U> </V> </U> </V> </L>
And presumably I'd want to add something to the tests like:
<U> <T n="multiplier">0</T> <L n="tests"> <L> <V t="foodInFreezer_test"> <U n="foodInFreezer_test"> <T n="call my scripted test">>?????<!--and might as well remove the food from freezer in the same script while I am testing--></T> </U> </V> </L> </L> </U>
So I have no idea if I can hook a scripted test into one of these sets of tests, and how to catch the result?
Edit: I think I see an example in a "snippet" xml. I will try doing something with that.
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
Btw, as far as I know (and it's possible this has changed), there's no way to run a command script as a test, only as part of the basic extras. They run at the end of the interaction, but they don't really return anything back to the interaction XML to look at for further testing.
Theoretically it would be possible to add a new test type to the TunableTestSet, but ... well, it's never been actually tried to the best of my knowledge. Probably not necessary for this though, you can search an object's inventory easily in a test.
Posts: 11,682
Thanks: 9680 in 11 Posts
My idea was not to return anything to the rest of the interaction but simply to use the fact of there being stock in the freezer as a cost multiplier (0 in this case, so restocking will be free). While I was testing for the presence of the food, I thought I might as well do the deletion of that item from the freezer at the same time to save me running a script twice. So really the only thing I am left in uncertainty about is whether the boolean return value of the snippet is somehow caught by the xml test. I guess trial and error might answer that if it's not generally known yet.
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
Well there must be at least a true or false implied after running the bucks_perk_test since they won't use the 0.75 cost multiplier unless they have that perk. |
OK, I think I see some of the confusion here... "bucks_perk_test" isn't really a script, it's just the name of a node in the tuning. It does run a Python script internally which returns a true or false result, of course, but when I'm in "XML mode" I don't really think of it as script - it's just a built-in test. All of these tests are described in the Tuning Descriptions, which is a must-read (well, browse at least, you wouldn't want to read it all). If you're using my TDesc browser, then you'll find all of these tests in the "TDescFrag" section under "TunableTestSet" in an easy-to-browse format as the raw file is a pain to look through.
And the test condition there is of course the identity of an xml, so I could have put a snippet xml identity in there, and hope for that to evaluate to true or false in some way. Do you happen to know whether anyone has actually asked the guru outright whether the snippet xml takes on the return value of the snippet it's running - in at least a boolean sense? |
You cannot just take a snippet (or any other XML node) and stick it somewhere and expect it to work. They are in a class hierarchy and that hierarchy specifies what other nodes are valid children of a specific node.
My idea was not to return anything to the rest of the interaction but simply to use the fact of there being stock in the freezer as a cost multiplier (0 in this case, so restocking will be free). While I was testing for the presence of the food, I thought I might as well do the deletion of that item from the freezer at the same time to save me running a script twice. So really the only thing I am left in uncertainty about is whether the boolean return value of the snippet is somehow caught by the xml test. I guess trial and error might answer that if it's not generally known yet. |
In the XML you are referencing, that test you want to add (and you would want to use the inventory test I showed in the earlier screenshot for that as you can't just use your own script for a test) is applying only to the parent nodes of that XML - in this case the "payment" node, so it would only affect the payment and would not be able to remove something from the freezer. If you want to specify that additional effect it would have to be in another area that allows for a delete item tuning, ideally the "outcome" of the interaction and the same test would then need to be repeated there.
I'm just not sure though how you would tell it which object type to delete from the freezer (it may possibly be quite easy, I just haven't researched how it might be done). You may notice that the restocking action doesn't really create a new object, if you look at the outcome it is just changing the object state from "sold" to "for sale". This is why I thought it might be easier to have it be done as a new multi-stage interaction - removing the item from the freezer, carrying it over and restocking.
ETA - I think this may be doable as part of the regular single-stage interaction -- there is an inventory check for "has_object_of_participant_type" which should be the target object of the whole interaction. You would then use a "do_command" in your outcome to perform the actual deletion from the freezer inventory. The difficulty there was that the two variants of the destroy object node want to either destroy a SPECIFIC object (we know the actual object's instance id - which we don't) or the contents of a SPECIFIC inventory object (we know the freezer's actual object id - which, again, we don't).
With the do_command in the outcome we can send it the object id of the target (the item being restocked) and you can then write a script that would search for any freezer on the lot (the inventory is shared so we don't care which one) and remove one item of that object's type from its inventory.
Yup, definitely doable, but a pretty complex choice for a first mod. Sounds like a good idea for one though.
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
As for refering to the interaction from the tuning file, you could just pass the interaction by number (since you're writing the interaction you certainly know it), or if you wanted to generalize it you could use the participant type Affordance maybe (not sure, I haven't played with many of these as that enum doesn't seem to get defined in the unzipped .pyo files - so I dumped it in game to find some interesting things). And here they all are
Posts: 11,682
Thanks: 9680 in 11 Posts
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 11,682
Thanks: 9680 in 11 Posts
I see in your download Tools thread (I couldn't find the browser in your actual downloads for some reason) you say that Tuning tdescs won't load, however they obviously have in the version you are using, as evidenced by your screenshot. That would seem to indicate you *did* update it, but I'll be blowed if I can find any thread with the later version in...
Also some items are picked out in yellow or green what does that mean?
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
Posts: 11,682
Thanks: 9680 in 11 Posts
Oh wrt running a snippet as a test, there *is* a testglobal template for a snippet in the tdescs. But I have also asked the simguru about scripted tests as well, to make sure.
Do they explain somewhere what muid means? I assume its something to do with a unique ID but not sure of the significance of 'm'. I googled and gather it might mean something to do with multi, in which case it's not all that unique lol.
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 2,671
Thanks: 62739 in 190 Posts
Do they explain somewhere what muid means? I assume its something to do with a unique ID but not sure of the significance of 'm'. I googled and gather it might mean something to do with multi, in which case it's not all that unique lol. |
Heads up that with patch 1.6.69 there is a tweak to the format of TDESCs being released by Maxis. Since we know that tuning mods are prone to breakage due to changes made in patches, this new format includes additional data that can be used to more easily resolve incompatible changes made in mods.
For this patch, the following files have been provided:
"1.5.149 - April Patch - TDESCs.zip" : Patch 1.5.149 TDESCs.
"1.5.149 - April Patch - TDESCs + MUIDs.zip" : Patch 1.5.149 TDESCs in the new format.
"1.6.69 - May Patch - TDESCs.zip" : Patch 1.6.69 TDESCs in the old format, so that existing tools used to consume the TDESCs will not be broken.
"1.6.69 - May Patch - TDESCs + MUIDs.zip" : Patch 1.6.69 TDESCs in the new format.
Note that future patches will only supply the TDESCs in the new format.
The 1.5.149 TDESCs are provided in order to take advantage of the new data, which requires you to compare the old TDESCs against the new ones to determine what has changed.
The change involves including metadata in the TDESCs file to make it easier for you to understand how the structure of the tuning has changed. There are two new sets of information in the TDESC files:
== MUIDs ===
Each tunable field now has a MUID attribute. The MUID uniquely identifies the underlying tunable structure of the field. Descriptions are ignored, meaning that two fields that are functionally equivalent but have different descriptions will share the same MUID.
== Version History ==
Each TDESC file may now include a version history. The history provides a change log of the fields in the TDESC from previous versions. Compare the previous version's TDESCs to determine what new items have been added to the version history. You will find some actions recorded predate 1.5.149, you can ignore those changes.
There are two types of actions:
=== kRemove ===
This indicates that a field was removed.
For example, in Career.tdesc:
<Action type="kRemove" old_muid="FF49432F3B0399CD" />
... indicates that a field with that MUID was removed, and is no longer valid tuning for the game. If you reference the previous version of Career.tdesc, you'll notice that that MUID corresponds to a particular field:
<Tunable type="int" name="text" class="TunableLocalizedString" default="0x0" display="Text" muid="FF49432F3B0399CD" description="The prompt's text." Deprecated="False" filter="0" group="General" />
If one of your tuning files specified that field, it must be removed in order for your modded content to properly match the schema. We usually remove fields that are deprecated or non-functional.
=== kRename ===
This indicates that a field was renamed. It provides the old MUID and the new MUID it was renamed to.
For example, in ObjectState.tdesc:
<Action type="kRename" old_muid="894D2902A31E0E27" new_muid="FBB604B5A8C86BFD" />
... indicates that, in the old version of ObjectState.tdesc:
<Tunable type="int" name="display_name" class="TunableLocalizedString" default="0x0" display="Display Name" muid="894D2902A31E0E27" description="A localized string that may NOT require tokens." Deprecated="False" filter="0" group="General" />
was renamed to:
<Tunable type="int" name="enabled" class="TunableLocalizedString" default="0x0" display="Enabled" muid="FBB604B5A8C86BFD" description="The instance's name." Deprecated="False" filter="0" group="General" />
A rename action is not merely about the field's name, but also about its hierarchy. Tunables may be moved in or out of parent nodes, and those are considered rename actions and recorded as such. This is the case in the provided example. Your tuned values will still be valid, but need to be updated to match the new name and hierarchy as appropriate.
Thanks,
SimGuruEugi and SimGuruModSquad
Posts: 11,682
Thanks: 9680 in 11 Posts
However I am having much more trouble getting the meal to be removed/deleted from the retail_fridge inventory. I have identified two possible ways of doing it:
1) via interaction tuning as in line 25913 of Interaction.tdesc eg
<U n="destroy_specified_objects_from_target_inventory"> <V n="count" t="number"> <T n="number">1</T> </V> <E n="inventory_owner"> What do I need for this TunableEnum to say it's the lot's RETAIL_FRIDGE inventory I am wanting? </E> <TdescFragTag n="object_tests" /> (this is meant to be a <L /> list in its final form <U n="success_chance"> don't need any of this as using default <T n="base_chance">100</T> <L n="multipliers" /> </U> </U>
And another way using a script:
import services import sims4 import ui.ui_dialog from objects.components.inventory_enums import InventoryType from ui.ui_dialog_notification import UiDialogNotification, TunableUiDialogNotificationSnippet from ui.ui_dialog import UiDialogResponse from ui.ui_dialog_notification import UiDialogNotification @sims4.commands.Command('ijRSFF.ijRemoveFromFreezer', command_type=sims4.commands.CommandType.Live) def ijRemoveFromFreezer(dish, _connection=None): # note1 = dish.FAILED_PLACEMENT_NOTIFICATION(dish, SingleSimResolver(self.sim_info)) note2 = dish.dialog note1 = dish.definition note1.show_dialog() freezer_inventory = services.active_lot().get_object_inventories(InventoryType.RETAIL_FRIDGE)[0] if freezer_inventory is not None: freezer_inventory.try_destroy_object_by_definition(dish.definition.id) return True
The problem with the xml way is I have failed to understand the tdesc enough to tell it I want the retail-fridge shared inventory. The problem with the script is it doesn't appear to be running - or at least I get no popup notification. What is a good way to prove whether or not a script runs?
"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Posts: 75
Thanks: 547 in 13 Posts
(More specifically, that script destroys the object by setting it's transient property to True, which should destroy the object as soon as the interaction ends.)
Who Posted
|