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!
Ms. Byte (Deceased)
Original Poster
#1 Old 24th Nov 2012 at 6:37 PM Last edited by CmarNYC : 26th Feb 2013 at 3:12 PM.
Default Tutorial: Adding pie menu options to sims
What this tutorial will do:
  • Show you how to add a social interaction to a sim
  • Demonstrate the various features of social interactions: testing whether the interaction should appear, using a path for grouping interactions, handling newly created and reset sims
  • Demonstrate the basics of error trapping
  • Briefly discuss how to find the game code you want to use in your interaction
  • Demonstrate interaction with the user

What you'll need:
  • A working knowledge of C#
  • Microsoft Visual C# Express (or the equivalent) correctly set up for scripting mods - MS Visual C# Express is free from Microsoft, and the tutorial on how to set up a scripting project is here: http://simswiki.info/wiki.php?title...Getting_Started (The "Getting Started" and "Additional Preparations in Visual Studio" sections. Note that you may have to make copies of the game packages in a work folder before extracting .dll files if S3PE won't open them in the Program Files location.)

Let's begin with the bare bones - a very simple interaction which will add the interaction "Show sim names" to all sims, and when used will display the names of the active sim and the sim being clicked on. Here's the complete code:

Code:
using System;
using System.Collections.Generic;
using System.Text;
using Sims3.Gameplay;
using Sims3.Gameplay.Actors;
using Sims3.Gameplay.Autonomy;
using Sims3.Gameplay.EventSystem;
using Sims3.Gameplay.Interactions;
using Sims3.Gameplay.Utilities;
using Sims3.SimIFace;
using Sims3.UI;

namespace cmarXmods
{
    public class DemoClass
    {
        [Tunable]
        protected static bool kInstantiator = false;

        static DemoClass()
        {
            World.OnWorldLoadFinishedEventHandler += new EventHandler(OnWorldLoadFinishedHandler);
        }

        public static void OnWorldLoadFinishedHandler(object sender, System.EventArgs e)
        {
            foreach (Sim sim in Sims3.Gameplay.Queries.GetObjects<Sim>())
            {
                if (sim != null)
                {
                    AddInteractions(sim);
                }
            }
        }

        public static void AddInteractions(Sim sim)
        {
            sim.AddInteraction(ShowNotification.Singleton);
        }

        private sealed class ShowNotification : ImmediateInteraction<Sim, Sim>
        {
            public static readonly InteractionDefinition Singleton = new Definition();
            protected override bool Run()
            {
                StyledNotification.Show(new StyledNotification.Format(base.Actor.Name + " has clicked on " + base.Target.Name,
                            StyledNotification.NotificationStyle.kGameMessagePositive));
                return true;
            }
            [DoesntRequireTuning]
            private sealed class Definition : ImmediateInteractionDefinition<Sim, Sim, ShowNotification>
            {
                protected override string GetInteractionName(Sim a, Sim target, InteractionObjectPair interaction)
                {
                    return "Show sim names";
                }
                protected override bool Test(Sim a, Sim target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback)
                {
                    return true;
                }
            }
        }
    }
}


Let's look at the various parts of this.

The "using" statements should be obvious if you're familiar with C# - they establish shortcuts so you don't have to spell out the full path to the various parts of the game libraries you'll be using.

Code:
namespace cmarXmods


You should always use a unique namespace to avoid any confusion with other mods or the EA code, and it's not a bad idea to use the same one for all or most of your mods, sort of as a brand name.

Code:
        [Tunable]
        protected static bool kInstantiator = false;


What this does is set up a tunable variable associated with your script, which also has to be defined in an XML tuning file just like the tuning files used in tuning mods. This is what forces the game to execute your code - it will find the XML tuning file and invoke your script to define the variable kInstantiator. Later I'll show how to set up the XML.

Code:
        static DemoClass()
        {
            World.OnWorldLoadFinishedEventHandler += new EventHandler(OnWorldLoadFinishedHandler);
        }


Here, the script adds a new event handler to the OnWorldLoadFinished event. This event is fired when your game finishes loading, and in turn your event handler executes.

Code:
        public static void OnWorldLoadFinishedHandler(object sender, System.EventArgs e)
        {
            foreach (Sim sim in Sims3.Gameplay.Queries.GetObjects<Sim>())
            {
                if (sim != null)
                {
                    AddInteractions(sim);
                }
            }
        }


This is the event handler. It iterates through the collection of all the sims in the neighborhood (returned by Sims3.Gameplay.Queries.GetObjects<Sim>()), tests that the sim actually exists, and calls the method to add the interaction.

Code:
        public static void AddInteractions(Sim sim)
        {
            sim.AddInteraction(ShowNotification.Singleton);
        }


And here we add the interaction ShowNotification, which is defined below, to the sim.

Code:
        private sealed class ShowNotification : ImmediateInteraction<Sim, Sim>
        {
            public static readonly InteractionDefinition Singleton = new Definition();
            protected override bool Run()
            {
                StyledNotification.Show(new StyledNotification.Format(base.Actor.Name + " has clicked on " + base.Target.Name,
                            StyledNotification.NotificationStyle.kGameMessagePositive));
                return true;
            }
            [DoesntRequireTuning]
            private sealed class Definition : ImmediateInteractionDefinition<Sim, Sim, ShowNotification>
            {
                protected override string GetInteractionName(Sim actor, Sim target, InteractionObjectPair interaction)
                {
                    return "Show sim names";
                }
                protected override bool Test(Sim actor, Sim target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback)
                {
                    return true;
                }
            }
        }


The interaction definition implements the EA ImmediateInteraction<Sim, Sim> abstract class which inherits from a bunch of other classes. All you really need is to use the format above and substitute your own code in the Run, GetInteractionName, and Test methods.
  • protected override bool Run() - The code you write to do whatever you want your scripted interaction to do goes here. You must return a true or false value. Note that you can refer to the active sim as "base.Actor" and the sim being clicked on as "base.Target".
  • protected override string GetInteractionName(Sim actor, Sim target, InteractionObjectPair interaction) - Here, you return a string with the text you want to show up in the pie menu.
  • protected override bool Test(Sim actor, Sim target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback) - Here, you can test whether your interaction should show up for a particular sim. "actor" is the active sim, "target" is the sim being clicked on. Return true to show the interaction, false to not show it.
Also note that in the line: private sealed class Definition : ImmediateInteractionDefinition<Sim, Sim, ShowNotification> the last parameter (ShowNotification in the example) must refer to the name of your interaction.

And that's it for this very simple example, as far as coding. Now let's talk about packaging it up for use in the game.

After you've saved your project and successfully compiled it using the Release compile option, you should find a .dll in your project's \bin\Release folder. In this example, I've named my project DemoScript, so I find DemoScript.dll in C:\Users\<myname>\Documents\Visual Studio 2008\Projects\DemoScript\DemoScript\bin\Release.

Use S3PE to create a new, empty package. Click Resource/Add. In the Resource Details window that pops up, set the Type to "S3SA 0x073FAA07". Fill in the Group with 0x00000000. Tick "Use resource name" and the Name field should become active. Now refer back to your script and fill in the Name field with the full path of your class - your Namespace and class name separated by a dot. In this case, that's "cmarXmods.DemoClass". Click the FNV64 button and the Instance will be filled in for you. Click Okay and you'll get an empty S3SA resource. Highlight it and click the Grid button at the bottom of the S3PE window, and you'll get another popup. In the Assembly line, click on "Import/Export/View Hex/Edit...", click the down arrow, then click Import. Browse to the .dll file you located in the last paragraph and import it. Click Commit.

Now use Notepad or any text editor to create and save a text file with the following text:

<?xml version="1.0" encoding="utf-8"?>
<base>
<Current_Tuning>
<kInstantiator value="True" />
</Current_Tuning>
</base>

Hopefully you recognize our friend kInstantiator as the tuning variable in the script. This is the tuning XML to go with it. Drag the text file into S3PE and you'll get another Resource Details popup. This time set the type to "_XML 0x0333406C", the Group again to 0x00000000, and again tick Use Resource Name and fill in the name with your full class path and click FNV64. (Or just copy the Instance of the S3SA.) The Instance ID is important - it MUST be the FNV64 hash of the full class path or the game won't find and execute your script.

Save your package, install it, and test. If all goes well, you'll see a new interaction that will display your active and target sims' names in the notification window.

Next: Enhancements to control when the option shows up, handling newly created sims, etc.

Credits: I've learned from so many people in the forums and tutorials. A partial list: Velocitygrass and Buzzler for being very helpful when I was starting out and for providing examples and tutorials. Much of the code I'm using here originally came from them; all I've done is put it together in tutorial form. Twallan for his generally awesome coding I've so often used for guidance, Peter and Inge Jones for s3pe, and everyone in the Modding Discussion forum.
17 users say thanks for this. (Who?)
Advertisement
Ms. Byte (Deceased)
Original Poster
#2 Old 24th Nov 2012 at 6:38 PM Last edited by CmarNYC : 25th Nov 2012 at 5:31 PM. Reason: Adding part 2
Default Making it better - tweaks and enhancements
Now let's get beyond making a script that's functional, and into making one that's a bit more useful.

Error Checking

Anyone who's done any programming knows errors happen - whether they're bugs in your program (very likely) or errors in data (also very likely) or user input (inevitable). Here's a useful set of error code I stole, er, got from Rick via Twallan (to the best of my memory).

Code:
        public static bool Exception(Exception exception)
        {
            try
            {
                return ((IScriptErrorWindow)AppDomain.CurrentDomain.GetData("ScriptErrorWindow")).DisplayScriptError(null, exception);
            }
            catch
            {
                WriteLog(exception);
                return true;
            }
        }
        public static bool WriteLog(Exception exception)
        {
            try
            {
                new ScriptError(null, exception, 0).WriteMiniScriptError();
                return true;
            }
            catch
            {
                return false;
            }
        }


This consists of two methods:
  • public static bool Exception(Exception exception) - The primary error handler; it catches the error and tries to write it to the screen. If this works, you get nice ugly error code all over your game which you can read and then dismiss. If it doesn't work, the next method catches that error.
  • public static bool WriteLog(Exception exception) - Writes error information to a file in your Documents/Sims 3 folder.

By using a try/catch at the places in your code where an error seems most likely, you can both see debugging information which may help you find the problem, and allow the game to continue past an error without crashing. Here's the code adding interactions to the sims with error handling added:

Code:
        public static void OnWorldLoadFinishedHandler(object sender, System.EventArgs e)
        {
            try
            {
                foreach (Sim sim in Sims3.Gameplay.Queries.GetObjects<Sim>())
                {
                    if (sim != null)
                    {
                        AddInteractions(sim);
                    }
                }
            }
            catch (Exception exception)
            {
                Exception(exception);
            }
        }


Making interactions conditional

In real modding practice, there are going to be options that only apply to some sims - only adults, only teens, only horses, etc. It only clutters the pie menu and confuses the user if you add them to the wrong sims. The solution is to add them only to the sims you want. Suppose for some odd reason I only want to add the name-display option to sims who are teens, YA, adults, or elders:

Code:
        public static void AddInteractions(Sim sim)
        {
            if (sim.SimDescription.TeenOrAbove)
            {
                sim.AddInteraction(ShowNotification.Singleton);
            }
        }


I've added a condition in the AddInteractions method to test for age. The Sim.SimDescription class has many useful fields, methods, and properties, including properties for age, gender, species, and many more things you may want to test for.

But now I decide, for some equally odd reason, I only want the option to show up if the active sim is the same age as the target sim (the sim being clicked). This means I want the option to be available for all sims teen or above, but to show or not show depending on who's clicking whom. To do this, I modify the Test method in the interaction definition:

Code:
                protected override bool Test(Sim actor, Sim target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback)
                {
                    return (actor.SimDescription.Age == target.SimDescription.Age);
                }


Now the Test will return true if the two sims are the same age or false if they're different ages. (Or true if the sim clicks him/herself.) If the returned value is false, the option will not show in the pie menu.

Handling newly created sims

During gameplay new sims are born, or created by story progression, or created with a mod like Master Controller. You need to handle that situation by adding your options to them. This creation is called instantiation, and there's a game event that's fired when it happens. In your script, you'll need to add an event handler for that event. First add this line in the main class where it'll persist for the life of the class, to define an event listener:

Code:
private static EventListener sSimInstantiatedListener = null;


Define the event handler method:

Code:
        protected static ListenerAction OnSimInstantiated(Event e)
        {
            try
            {
                Sim sim = e.TargetObject as Sim;
                if (sim != null)
                {
                    AddInteractions(sim);
                }
            }
            catch (Exception exception)
            {
                Exception(exception);
            }
            return ListenerAction.Keep;
        }


Bet you were wondering why I have a separate method for adding interactions! This is why: you can call the same method here. Then add the listener in your OnWorldLoadFinished event handler so your code will be called when a sim is created:

Code:
sSimInstantiatedListener = EventTracker.AddListener(EventTypeId.kSimInstantiated, new ProcessEventDelegate(OnSimInstantiated));


But wait; there's more! Suppose a sim gets reset during gameplay. When this happens, the sim is instantiated and the instantiation event is fired even though the sim isn't newly created and already has your interaction added. In order to avoid having your interaction showing up twice (or more), you need to test whether it already exists for that sim:

Code:
        public static void AddInteractions(Sim sim)
        {
            if (sim.SimDescription.TeenOrAbove)
            {
                foreach (InteractionObjectPair pair in sim.Interactions)
                {
                    if (pair.InteractionDefinition.GetType() == ShowNotification.Singleton.GetType())
                    {
                        return;
                    }
                }
                sim.AddInteraction(ShowNotification.Singleton);
            }
        }


What this does is iterate through all the interactions defined for the sim, and if it finds ShowNotification already there it returns without adding it.

Handling other events

But what about sims that age up from children to teens during gameplay? I want them to have the interaction added too. So let's add a handler for the AgeTransition event:

Code:
private static EventListener sSimAgedUpListener = null;


in the main class, and

Code:
sSimAgedUpListener = EventTracker.AddListener(EventTypeId.kSimAgeTransition, new ProcessEventDelegate(OnSimInstantiated));


in the WorldLoadFinished event handler. In this example I'm using the same event handler ListenerAction as for instantiation since it already does what I want, but it could use a different one if necessary. In the next lesson I'll talk a little more about the available game events.

Defining paths and submenus

Okay, things are getting a little more complicated in my mod and I want to add more than one interaction. (Add more interactions by adding a class and definition for them, and add them to the sim in exactly the same way as the first one. There's no limit I know of to how many interactions can be added in one script.) I want to group my interactions so that the initial pie menu shows "MyStuff Options...", you click on it, and then you get the "Show sim names" option along with any others I may have added. Fortunately this is easy. In the interaction Definition class (inside the interaction class), add an override method for GetPath:

Code:
                public override string[] GetPath(bool bPath)
{
return new string[] { "MyStuff Options..." };
}


What this does is define a path for your interaction - in this case it's "MyStuff Options..." / "Show sim names". If you define more interactions using the same path, those options will show up along with "Show sim names" when you click "MyStuff Options...". Note that GetPath returns a string[] array, so you can define more than one level in your path.

Where to go from here

Languages:

If you choose to add multiple language support to your script, you'll have to make some changes in your code along with constructing STBL files for each language. Fortunately there's an excellent tutorial here: http://simswiki.info/wiki.php?title...ocalized_Coding

References:

Here's another very good tutorial on the basics of scripting, this time with objects: http://simswiki.info/wiki.php?title...Depth_Scripting

And the SimsWiki link for General Modding which covers core and script modding: http://simswiki.info/wiki.php?title..._GeneralModding

Download:
Last, I've attached the complete script used in this tutorial, cleaned up a bit to show some of the refinements in comments and to remove my namespace. This should be useful as a template.

Next: Using game libraries and interacting with the user.
Attached files:
File Type: zip  InteractionDemo.zip (1.6 KB, 243 downloads) - View custom content
Description: Text files of script and xml
Ms. Byte (Deceased)
Original Poster
#3 Old 24th Nov 2012 at 6:38 PM Last edited by CmarNYC : 27th Jan 2013 at 2:28 PM.
Now to dig a little deeper and discuss interactions with the user and examining game code.

User Interactions

Sometimes you'll want to ask the user to select an option, enter a value, or answer a question as part of your scripted action. I'll show you a few simple ways to do this, and where to look for more. All the demo code goes in the Run() definition of the interaction. In the code below I've changed the interaction text to "Show sim information" since we'll be displaying different kinds of information depending on what the user chooses.

The user dialogs below are defined in game code in Sims3.UI. For convenience, you should include the line:

Code:
using Sims3.UI;


in your 'using' statements at the beginning of your code.

Let's start with a basic two button dialog that gives the user two choices:

Code:
                bool whatToShow = TwoButtonDialog.Show("Choose which to show", "Gender", "Gender Preference");
                if (whatToShow)
                {
                    StyledNotification.Show(new StyledNotification.Format(base.Target.Name + " is: " + base.Target.SimDescription.Gender.ToString(),
                                StyledNotification.NotificationStyle.kGameMessagePositive));
                }
                else
                {
                    string genderPref = base.Target.SimDescription.GenderPreferenceIsFemale() ? "Female" : "Male";
                    StyledNotification.Show(new StyledNotification.Format(base.Target.Name + " prefers: " + genderPref,
                                StyledNotification.NotificationStyle.kGameMessagePositive));
                }


In its simplest form, TwoButtonDialog.Show requires a prompt string ("Choose which to show") and labels for the buttons ("Gender" and "Gender Preference"). It returns a boolean you can use in your script - true if the first button is clicked and false if the second button is clicked. It can also be used for a Yes-No dialog.

In case you have three options, there's also a ThreeButtonDialog:

Code:
                ThreeButtonDialog.ButtonPressed b = ThreeButtonDialog.Show("Choose which to show", "Married?", "Number of children", "Number of siblings");
                if (b == ThreeButtonDialog.ButtonPressed.FirstButton)
                {
                    StyledNotification.Show(new StyledNotification.Format(base.Target.Name + " married: " + base.Target.SimDescription.IsMarried.ToString(),
                                StyledNotification.NotificationStyle.kGameMessagePositive));
                }
                if (b == ThreeButtonDialog.ButtonPressed.SecondButton)
                {
                    StyledNotification.Show(new StyledNotification.Format(base.Target.Name + " children: " + base.Target.Genealogy.Children.Count.ToString(),
                                StyledNotification.NotificationStyle.kGameMessagePositive));
                }
                if (b == ThreeButtonDialog.ButtonPressed.ThirdButton)
                {
                    StyledNotification.Show(new StyledNotification.Format(base.Target.Name + " siblings: " + base.Target.Genealogy.GetSiblings().Count.ToString(),
                                StyledNotification.NotificationStyle.kGameMessagePositive));
                }


Note that ThreeButtonDialog returns a ThreeButtonDialog.ButtonPressed enum, which can be tested to find out which button was clicked. This method can also be used to provide two choices and a 'Cancel' button.

If you need the user to enter a value, such as a number, there's a method for that too:

Code:
                string s = StringInputDialog.Show("Text Entry Dialog", "Type something:", "");          //prompt for a string
                string n = StringInputDialog.Show("Text Entry Dialog", "Enter a number:", "", true);    //allow only numbers
                StyledNotification.Show(new StyledNotification.Format("You entered " + s + ", " + n,
                                StyledNotification.NotificationStyle.kGameMessagePositive));


I've included two variations. The first is the simplest form which takes the dialog title text ("Text Entry Dialog"), the prompt text ("Type something:"), and the default text to be displayed when the dialog box pops up (I've left it blank: ""). The second also takes a boolean specifying whether the user input must be numeric. There are other overloads which allow validation and other refinements. And there's also a TwoStringInputDialog method and a ThreeStringInputDialog method that let you prompt for two or three strings.

But what if you need the user to pick from a whole list of options? This gets a bit more complicated - we have to construct a list of type ObjectListPickerInfo and populate it with our options, then use that as an argument to ObjectListPickerDialog.Show(). Below is a very simple example of an outfit-changing dialog that gives the user a choice of which outfit category to change into:

Code:
                List<ObjectListPickerInfo> pick = new List<ObjectListPickerInfo>();
                pick.Add(new ObjectListPickerInfo("Everyday", Sims3.SimIFace.CAS.OutfitCategories.Everyday));
                pick.Add(new ObjectListPickerInfo("Career", Sims3.SimIFace.CAS.OutfitCategories.Career));
                pick.Add(new ObjectListPickerInfo("Swimwear", Sims3.SimIFace.CAS.OutfitCategories.Swimwear));
                pick.Add(new ObjectListPickerInfo("Formal", Sims3.SimIFace.CAS.OutfitCategories.Formalwear));
                object obj = ObjectListPickerDialog.Show(pick);
                Sims3.SimIFace.CAS.OutfitCategories cat = (Sims3.SimIFace.CAS.OutfitCategories) obj;
                base.Target.SwitchToOutfitWithoutSpin(cat);


First, declare the list of type ObjectListPickerInfo, then add elements to it. Each ObjectListPickerInfo element consists of a label and an object which can be of any type you need to use - in this case the Sims3.SimIFace.CAS.OutfitCategories enum. This list gets passed to the ObjectListPickerDialog.Show method which displays the list, lets the user pick one, and returns the object for that list element. Then we cast the returned object back into Sims3.SimIFace.CAS.OutfitCategories and use it to tell the sim which outfit category to change into.

Or you can use ComboSelectionDialog, which works almost the same way but takes a string for the dialog box title, a Dictionary instead of a List, and a default object; and appears in the game as a dropdown list:

Code:
                Dictionary<string, object> dict = new Dictionary<string,object>();
                dict.Add("Everyday", Sims3.SimIFace.CAS.OutfitCategories.Everyday);
                dict.Add("Career", Sims3.SimIFace.CAS.OutfitCategories.Career);
                dict.Add("Swimwear", Sims3.SimIFace.CAS.OutfitCategories.Swimwear);
                dict.Add("Formal", Sims3.SimIFace.CAS.OutfitCategories.Formalwear);
                object obj2 = ComboSelectionDialog.Show("Pick an outfit category", dict, null);
                Sims3.SimIFace.CAS.OutfitCategories cat2 = (Sims3.SimIFace.CAS.OutfitCategories)obj2;
                base.Target.SwitchToOutfitWithoutSpin(cat2);


There are more methods for user interaction than I can get into in this tutorial. Next we'll look at how to find and examine these and other game structures and methods in the game libraries.


Examining Game Code

Where do I get all these wonderful toys? :D

Scripting mods can call on the EA game libraries of classes, methods, properties, etc. to do all kinds of things inside the game. In order to use them, obviously you have to find them and hopefully have some understanding of what they do.

First, some background. Game code comes in two flavors: managed and unmanaged. We can use only the managed code; unmanaged code does a lot of nuts and bolts stuff that's not directly accessible to modders. Managed code is installed on your computer in the form of .dll libraries inside .package files. Presumably when you set up Visual C# Express you extracted the .dll resources and added them to your project as references. (http://simswiki.info/wiki.php?title..._Studio_project) Now we'll look at how to examine the actual code in them.

There are two popular tools for this: .NET Reflector ($95, http://www.reflector.net/), and ILSpy (free, http://ilspy.net/). If you didn't get Reflector back when the price was more reasonable, the choice should be obvious. I'll use ILSpy for my examples, but they work pretty much the same way although Reflector has a slicker interface. (To install ILSpy, download the binaries using the "Download Binaries" button at the top of the main page, and unzip into a folder anyplace convenient. Then run ILSpy.exe.)

To set up the first time, first remove any assemblies listed on the left side of the window. Then open the game assemblies from the same location where you extracted them for use with your scripting projects. You should include mscorlib (the EA mscorlib - make sure it's the one you extracted from the game packages), ScriptCore, SimIFace, Sims3GameplayObjects, Sims3GameplaySystems, Sims3Metadata, System (again the EA version), System.Xml, and UI. When you're done, ILSpy should look like this:



What ILSpy and Reflector do is to decompile the code in the dll libraries back into a readable programming language - in our case, C#. Now it's just a matter of poking around in the code to see what's useful and what we can call in a script. For example, if you expand UI and under that expand Sims3.UI, you'll find the interaction classes used in the examples above, along with a lot of others. By clicking on a class you get a list of the fields, properties, methods, etc. in that class on the right side, which can also be expanded to show actual code.



Remember the game events discussed back in lesson one? The full list is an enum in Sims3GameplaySystems: Sims3.Gameplay.EventSystem.EventTypeID:



One more example - in Sims3GameplaySystems you'll find the Sims3.Gameplay.Actors.Sim class with a long list of useful properties and methods for manipulating sims. One of the properties is the SimDescription class which has its own long list of components. There's also the Genealogy class with information about the sim's family.



It can take a lot of time and patience to find what you're looking for.

One last tip - you'll notice that a lot of the methods and so on are private or protected and MS Visual C# Express won't let you use them. If you need one of these resources, you can create a custom, unprotected dll to use as a reference for your project. There's a discussion here: http://www.modthesims.info/showthread.php?p=3766584

If you have Visual C# Express 2010 or later, you can use Peter Jones' utility here: http://www.den.simlogical.com/denfo...hp?topic=1689.0

Otherwise, you'll probably have to disassemble the dll using ildasm, open it in a text editor, replace all instances of ' private ', ' family ', and ' sealed ' with ' public ', save, and reassemble with ilasm. Instructions on finding ildasm and ilasm are here in Section E: http://www.modthesims.info/showthread.php?t=354419

I've attached the complete script with the interaction examples above. I hope this is useful, and happy scripting!
Screenshots
Attached files:
File Type: zip  InteractionsScriptDemo2.zip (2.0 KB, 128 downloads) - View custom content
Description: Full demo script
Field Researcher
#4 Old 25th Nov 2012 at 8:14 AM
You nailed the reference in the walkthrough and changed it to ShowNotification, but missed the same in the main block of code:

private sealed class Definition : ImmediateInteractionDefinition<Sim, Sim, GoToXCAS>

=)
Ms. Byte (Deceased)
Original Poster
#5 Old 25th Nov 2012 at 1:28 PM
Corrected - thanks!
Instructor
#6 Old 4th Jan 2013 at 8:53 AM Last edited by bella3lek4 : 4th Jan 2013 at 10:43 AM.
Thank you for this tutorial .

But this is not the kind of interaction that i wanted

I wanted A Social Interaction Like ( Amorous Hug ) Or something like it , Where you can add your custom animation & stuff .

Do you have any idea how we can do that ?

I really appreciate it , thanks :D

. I am a 20 years old male ..I'm not a Female .. and my name is not Bella .. as everybody think .
I used to bite .. but i don't do that anymore . Have fun! :)

Ms. Byte (Deceased)
Original Poster
#7 Old 4th Jan 2013 at 2:16 PM
Quote: Originally posted by bella3lek4
Thank you for this tutorial .

But this is not the kind of interaction that i wanted

I wanted A Social Interaction Like ( Amorous Hug ) Or something like it , Where you can add your custom animation & stuff .

Do you have any idea how we can do that ?

I really appreciate it , thanks :D


This tutorial covers the basics of how to add a generic pie menu interaction. The action performed by the interaction could be anything you can code, I imagine including animations. But apparently a true social interaction is more complicated - here's a thread with a summary: http://www.modthesims.info/showthread.php?t=492221

I've never done that and am not planning on doing a tutorial for it.
Instructor
#8 Old 6th Jan 2013 at 5:18 PM
Thank you ,

I will start learning C# after i finish my exams .

i hope i will finally come up with something

. I am a 20 years old male ..I'm not a Female .. and my name is not Bella .. as everybody think .
I used to bite .. but i don't do that anymore . Have fun! :)

Instructor
#9 Old 7th Jan 2013 at 5:31 PM
This Tutorial gave me Headache !

The whole coding thing gave me headache !!!

I am so full of it .
its not working ,

i quit !!!


Some creator should make a tool to simply add an interaction , What it does , what it effects , what animations to play or to import , & so on .

i can't handle this

. I am a 20 years old male ..I'm not a Female .. and my name is not Bella .. as everybody think .
I used to bite .. but i don't do that anymore . Have fun! :)

Forum Resident
#10 Old 7th Jan 2013 at 6:12 PM
I had that headache when I first started. It was my brain trying to comprehend it's own stupidity. Modding only looks easy because the modders are good at it.
Field Researcher
#11 Old 8th Jan 2013 at 4:37 PM
Programming is one of those things that requires a very specific mindset. I'll be immodest for a second and say that I'm at least a decent programmer, but I will say that I am not a programmer by existing trade or career aspiration and I flatly hate it. Game design is so much more fun and interesting than actually going in and digging around with the nuts and bolts, but the sad truth is that they're institutionally linked and you can't have one without the other. All I can say is keep at it. If you get discouraged, back away, play some games, write down some ideas, and come back fresh a day later, a week later, or a month later -- whatever works for you -- and suddenly what looked like Greek will look like fenugreek for cooking with.

I will say it's pretty important to learn at least one programming language (not necessarily C#) before you attempt to do anything that actually involves programming, however. Attempting to self-teach programming without a step-by-step tutorial, by simply going in and playing around with "pure base virtual deconstructors" and whatevertheheckelse, will not teach you anything useful and will teach you all the wrong things. =)

Twallan's framework also has a social action injection system, which you can also look at if you use ILSpy. Twallan even offers to provide NRaas source code to anyone who asks for it. Unfortunately Twallan's framework is purpose-built for his suite of mods and is thus very robust (and by extension extremely hard for a beginner to understand).

Don't be discouraged! Everyone has to start somewhere.
Ms. Byte (Deceased)
Original Poster
#12 Old 14th Jan 2013 at 1:14 PM Last edited by CmarNYC : 26th Jan 2013 at 6:07 PM.
Ahmad, coding is not easy and not something you can pick up in a few hours. If you don't have any programming experience it can take weeks or months to learn the basic principles of how to construct program logic, understanding data types and structures, how function calls work, etc. etc. Just the terminology can be a challenge. Beyond that, it takes experience and a basic talent or detail-oriented mind and lots of patience to become a GOOD programmer. I think too many people come in thinking they can quickly put together something that does what they want.

I'll add that IMO C# is not an easy language to learn, especially for a beginner, since you have to learn the basics of Object Oriented Programming (OOP) in order to have any clue what you're doing. In my working life I was a career applications programmer, and a good one: learned Cobol in school, and used mostly Fortran, Assembly, and Cold Fusion on the job (which tells you how old I am). It still took me weeks to wrap my brain around C# enough to do the most basic useful scripting mods and months to get to the point of being what I'd call really productive.

I'm not saying this to discourage anyone - just so you have realistic expectations. Coding is a skill that takes a lot of work, but it can be tremendously rewarding. Personally, I love every frustrating, aggravating, sometimes tedious, sometimes confusing moment. When that program or script takes shape and starts doing exactly what you want it to do, it feels like creating a beautiful work of art.
Forum Resident
#13 Old 22nd Jan 2013 at 3:22 PM
Creating custom animations is easy compared to this. I couldn't figure it out how to add "FirefighterEmergencySituation.CarryOutChild " to Sims pie menu. Gosh, I also really need that interaction for my movie.
If there is another way to add that interaction please let me know.
Ms. Byte (Deceased)
Original Poster
#14 Old 27th Jan 2013 at 8:41 PM
Have you tried adding it to adult sims the same way you'd add a custom interaction? Although I suspect the firefighter carry interaction will only work in an actual fire. It might be possible to copy the animation calls from the carry interaction definition, though.
Field Researcher
#15 Old 15th Feb 2013 at 8:43 PM
Great tutorial! You wrote it in a very clear, straightforward way that made it easy to follow. I had your example up and running soon after figuring out a minor glitch I made when setting up a VS-compatible project.

Now I just have to learn more about C#. I've been programming for a while, but never got around to learning that language. Well, this is a good excuse to start!
Ms. Byte (Deceased)
Original Poster
#16 Old 16th Feb 2013 at 12:05 AM
Thank you! I had fun learning C# - I hope you do too.

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
Test Subject
#17 Old 26th Feb 2013 at 1:26 PM
Default Problem
hi,

i have a question to your tutorial "Modding - General - Tutorial: Adding pie menu options to sims". I tried it out, but it didnt worked for me... I took your code and created a dll file (before i did the correct setup for VS, i use VS 2010 Express). No errors or something else, so far so good. Then i wrote the XML file, exactly as you wrote it. Finally i created the S3SA file in S3PE with your settings (means correct namespace and classname) and added the XML file to it. Then i saved it as a package-file and put it into the Mods/Packages folder, where all the other packages are... Start the game, chose my family, but after loading and selecting a sim there is no new interaction icon . its all like it was before... where is the mistake?

cheers
Attached files:
File Type: rar  test.rar (3.8 KB, 30 downloads) - View custom content
Ms. Byte (Deceased)
Original Poster
#18 Old 26th Feb 2013 at 3:03 PM Last edited by CmarNYC : 26th Feb 2013 at 3:30 PM.
In VS Express, open your project and expand the project Properties, then open AssemblyInfo.cs. The contents should look something like this: (The AssemblyProduct and AssemblyTitle may be different.)

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Sims3.SimIFace;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DemoClass")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("DemoClass")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: Tunable]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ecdcc8d1-b218-413d-9297-098a2bb6ce5b")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Did you add "using Sims3.SimIFace;" and "[assembly: Tunable]" ? Not having "[assembly: Tunable]" may be causing your problem. It says to do this in the "Pure Scripting" Visual Studio setup instructions but not in the "Creating a game compatible Visual Studio project" - my mistake for not pointing that out. I'm revising the tutorial to say only to use the Pure Scripting instructions to avoid confusion.

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
Test Subject
#19 Old 26th Feb 2013 at 3:39 PM
Default Problem solved
Quote: Originally posted by CmarNYC
In VS Express, open your project and expand the project Properties, then open AssemblyInfo.cs. The contents should look something like this: (The AssemblyProduct and AssemblyTitle may be different.)

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Sims3.SimIFace;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DemoClass")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("DemoClass")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: Tunable]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ecdcc8d1-b218-413d-9297-098a2bb6ce5b")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Did you add "using Sims3.SimIFace;" and "[assembly: Tunable]" ? Not having "[assembly: Tunable]" may be causing your problem. It says to do this in the "Pure Scripting" Visual Studio setup instructions but not in the "Creating a game compatible Visual Studio project" - my mistake for not pointing that out. I'm revising the tutorial to say only to use the Pure Scripting instructions to avoid confusion.


Yeah thats it. Adding "[assembly: Tunable]" and everything is fine thx
Forum Resident
#20 Old 3rd Mar 2013 at 7:35 PM Last edited by Sof_m9 : 20th Apr 2013 at 4:31 AM.
Quote: Originally posted by CmarNYC
Have you tried adding it to adult sims the same way you'd add a custom interaction? Although I suspect the firefighter carry interaction will only work in an actual fire. It might be possible to copy the animation calls from the carry interaction definition, though.


You couldn't possibly test this out? Please? All I can do are custom animations, I'm not understanding at all how to add interactions to pie menus.
Ms. Byte (Deceased)
Original Poster
#21 Old 4th Mar 2013 at 1:46 AM
Quote: Originally posted by Sof_m9
You couldn't possibly test this out? Please? All I can do is custom animations, I'm not understanding at all how to add interactions to pie menus.


Thing is, this is likely to be a considerable project, and one I have no interest in myself.
When I get some spare time and if it turns out to be easy, I'll let you know.

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
Forum Resident
#22 Old 4th Mar 2013 at 4:31 PM
Quote: Originally posted by CmarNYC
Thing is, this is likely to be a considerable project, and one I have no interest in myself.
When I get some spare time and if it turns out to be easy, I'll let you know.


I understand. Thank you.
Test Subject
#23 Old 12th Apr 2013 at 3:04 AM
Default Durp
Argg! Messed up somwhere... Back to square one...
Test Subject
#24 Old 9th Jun 2013 at 6:07 AM
Hi Cmar. The method Definition() in this part of the code:

Code:
public static readonly InteractionDefinition Singleton = new Definition();


I don't have it in VS. I get the error "The type or namespace name 'Definition' could not be found (are you missing a using directive or an assembly reference?)". I think I need to prefix it with Sims3.SimIFace or something, but I don't know which. Can you help me?

Let's Play Sims.
Seabody's Mods - all thoroughly tested to ensure that they work correctly.

I don't make Meshes. I only make XML Tuning Mods.
Ms. Byte (Deceased)
Original Poster
#25 Old 12th Jun 2013 at 12:11 AM
Quote: Originally posted by Seabody
Hi Cmar. The method Definition() in this part of the code:

Code:
public static readonly InteractionDefinition Singleton = new Definition();


I don't have it in VS. I get the error "The type or namespace name 'Definition' could not be found (are you missing a using directive or an assembly reference?)". I think I need to prefix it with Sims3.SimIFace or something, but I don't know which. Can you help me?


Can you upload or post your complete code so I can take a look?

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
Page 1 of 2
Back to top