#6
17th Jan 2021 at 11:15 PM
Posts: 34
Thanks: 436 in 2 Posts
5 Achievements
Disclaimer: I'm learning how modding works for the sims 2, I haven't been at this for long - sorry for the length; this is wordy because it's also my tutorial to myself!
There's some
pre-existing wiki information on this, but I think it's too hard to follow and misses out some crucial bits of info, so here's my take on it:
Quote: Originally posted by jmanlfdI
haven't figured out what the best way to add the pie menu to a Sim is yet. In the meantime, I'll keep trying to find the best way to either add the pie menu to the selected Sim, or add the interaction to the individual objects themselves if I can find a way to do it that wouldn't cause too many conflicts with other mods.
|
For adding to the sim pie menu, I had a look at how
[twojeffs' Smart Beds] works. Twojeffs is a clever cloggs. I figure if you do choose the 'add interaction to sim route', you'd be interested in the proximity object checking too.
In smart beds:
- New pie menu interactions are added to every sim
- If you're standing near a bed, a different pie menu option is added to your sim: this will set your sim's relationship to the nearby bed
So, background knowledge:
- You can dynamically add to a pie menu by calling [Primitive 0x0032] - Add/Change the Action String
- Objects that that have their category set to 0x106:0x56: Plugin Social will have their check tests called every time a sim is clicked or, I assume, whenever the sim is selected to autonomously choose an action to perform. [Source for most of this] (Note: clicked, not moused over)
This calls the BHAV with filename CT - Object Menu with:- Param 0 - ID of sim that was selected
- Param 1 - Whether this interaction was selected autonomously
- When a social action is chosen for that sim, it'll call that social object's CT - Object Menu Command
- Param 0 - ID of sim that was selected (the stack object ID when action string was set)
- Param 1 - The value that was in Temp 0 when the action string was set by your social object
From Example
So let's look how smart beds does it. I'll be using some loose, python-esque pseudocode here to make things clearer while explaining the logic.
Function - Init
Sets the
category to 0x106:0x56: Social Plug In Controller.
Tiny sidenote: It's a little weird to me this only gets set at run time - is there no flag for it editable from the object data file?
Code:
init_object ()
my.category = "Social Plug In Controller"
Function - Main
Idle forever. This is my assumption - if it exits main, the object will get destroyed. We want to prevent that, because otherwise it won't be in the list of socials to add to a sim when the pie menu is being built.
Code:
while (true) # foreveridle (20000) # ticks
CT - Object Menu
Called whenever we're building the pie menu for a sim.
Code:
def check_test (targeted_sim, autonomous):if (autonomous):return false # Do not provide any interactions autonomously
if (targeted_sim != my.object_id)return false # Don't provide interactions when clicking on other sims - we'll only add the interaction when clicking the active sim
# Stuff about vampires omitted...
temp object_category = "Bed"
local max_distance_to_bed = 3 # tiles away sim can be for "Own this bed" interaction to appear
local nearest_bed_id = -1 # Note: not actually initialised in the code
local original_stack_object_id = stack_object_id
stack_object_id = 0
# See if there are beds nearby (within 3 tiles and in the same room) and store nearest one
# Iterate through objects with the "Bed" category
while (set_to_next (next_bed_id, stack_object_id, object_category)): # Set next_bed_id to the next object id of object_category in the stack, after stack_object_idstack_object_ID = next_bed_id
if (stack_object.room != my.room)continue # Don't check other rooms
stack_object_id = get_section_head () # Beds are multi-tile objects, so there's some extra checks in another function to find the lead tile object ID (Also checks other side of the bed - omitted)
temp distance_to_bed = distance (me, stack_object)
if (distance_to_bed < max_distance_to_bed):max_distance_to_bed = distance_to_bed
nearest_bed_id = stack_object_id
# Add pie menu option to own a bed
if (category_is_object_type_of (nearest_bed_id, "Bed")):stack_object_id = original_stack_object_id
add_or_change_action_string (nearest_bed_id, "Adjust.../Bed Ownership.../Own this Bed")
# Add pie menu options that appear regardless
add_or_change_action_string (0x00, "Adjust.../Bed Ownership.../Clear All")
add_or_change_action_string (0x02, "Adjust.../Bed Ownership.../Dude, Where's My Bed?")
return true
CT - Object Menu Command
So here's the clever part: the parameter we passed into add_or_change_action_string gets passed into CT - Object Menu Command if that menu option was selected. That way, we know what interaction to call.
The REALLY clever part: the parameter passed in doesn't just need to enumerate the interaction that was clicked on - we can stick the id for the object we want to interact with in here. This way, we know what to act on too.
Code:
# Clear ownership
if (selected_interaction_parameter == 0x00):clear_ownership ()
return true
# Dude, where's my bed?
if (selected_interaction_parameter == 0x02):run_to_bed ()
return true
# Own this bed
if (if category_is_object_type_of (selected_interaction_parameter, "Bed")): # sanity checkown_this_bed (my_object_id, selected_interaction_parameter)
return true
Example package
Had a go myself: see the attached file.
TL;DR:
You need to mark an object as a social interaction so it can get called when you click on a sim. Set up a CT - Object Menu as a guardian and CT - Object Menu Command as your action function.
Extra research: Setting a pie menu function on another object?
I was googling this, and I think I saw someone on the forums mention it couldn't be done. But I don't understand why yet... maybe because the pie menu display only gets built when you click on the object - so your dynamic menu would get lost. But I would have thought you'd be able to do something like add to the list....
Have a look at
[0x0032]:
Quote:
Because the stack object by default in a check tree is the object that the sim is interacting with, this will just change the pie-menu option for using this object.
However Set-To-Next-Loops can provide a whole new usage to this function. In this example, I will show how multiple stack objects can add menu options to a single object. This is very useful for making patches that allow for plugin upgrades, so that anyone can add to your patches without conflicts. Here is an example of a basic Set-To-Next-Loop with menu options automatically being added
|
I was looking at this, but I don't understand it yet! Anyway, good luck, really like your mod idea.