Difference between revisions of "Tutorial:Sims 3 In Depth Scripting"

From SimsWiki
Jump to: navigation, search
(Requirements)
m (Methods)
 
Line 63: Line 63:
 
Methods tell Sims 3 what to do when something happens. The game already comes with a variety of methods that you can use to implement into your script. The most common one is WorldEventHandler, TNSMessages, and Interaction methods.
 
Methods tell Sims 3 what to do when something happens. The game already comes with a variety of methods that you can use to implement into your script. The most common one is WorldEventHandler, TNSMessages, and Interaction methods.
 
<br>
 
<br>
Think of methods as steps to solve a math problem or functions. When you do a math problem, you follow certain steps to get to the final outcome. This is essentially the same with methods. They give the game steps on what to do when someone clicks on the object or uses a interaction.
+
Think of methods as steps to solve a math problem or functions. When you do a math problem, you follow certain steps to get to the final outcome. This is essentially the same with methods. They give the game steps on what to do when someone clicks on the object or uses an interaction.
 
=== Interaction Methods ===
 
=== Interaction Methods ===
 
<br>
 
<br>

Latest revision as of 10:46, 9 September 2018

Contents

[edit] Intro

My goal in this guide is to help the complete "noobs" at scripting languages and put them in words that they can describe. A lot of people who have gone through Buzzlers tutorial either didn't understand it or it was too confusing for them. This guide assumes you know absolutely nothing about C# and you really want to learn how to make those cool scripts for objects that you see all the time. This will go over methods, classes, strings, overrides, and more. You should have a very, very basic understanding of the InteliSense system that Visual Studio provides as well as a basic idea of using Reflector.

Because this is in a work in progress, you WILL see typo errors and you WILL see grammar mistakes. It would be awesome if you could correct them for me. You can even add in extra information about a certain method/type/class that you feel should be told to beginners in scripting languages.

[edit] Requirements

[edit] Lets do this!

[edit] Classes

Classes are the building blocks of scripting. They allow you to group up parts of your code and to "derive" parts of code. You will ALWAYS start off your code with a class of some sort.
Still don't understand the concept of a class? Think of them as groups. You group your code together. Similar to how baseball would be under the group of sports. Now, there are a bunch of different types of sports like football, tennis, and volleyball. All of them are sports because they are grouped under sports. It's common knowledge. When you think of baseball, you think of sports. When you think of sports, you think of baseball.

There are a few different types of classes. Here's a chart of them and what you would use them for. These are not all of them. They are just the ones that are commonly used throught Sims 3 scripting.

Type of Class How to use it

class

This is normally used right after the namespace. It is typically followed by a public/private class.

public class

This is used right after you have a class, however a class is not needed to use "public class". You can start off with "public class" right after your namespace. This makes your class accessible by anyone trying to use your code.

private class

This is used for making a class unaccessable by anyone but you. This means that if someone references your DLL they will not be able to use methods inside that class.

public sealed class

This is mainly only used for the Definition class. More on that later.


[edit] Deriving A Class

Deriving a class means that you're basing your class off of another class. Let's take a look at some Sims 3 objects. When you go into reflector and look at the FishTankModern class which is found under Sims3.Gameplay.Objects.Decorations.
When you look at this code you will notice a " : " after FishTankModern. This is telling us to derive, or use, the same exact functions, or methods, that FishTank has. It's really that simple.

Why should I derive off of another class? Object scripting in Sims 3 without deriving will make your life a living hell and Sims 3 popping up a bunch of errors when you try to run it. Like I said, deriving will allow us to use those same functions without having to create that part of code ourselves. Every single object is derived off of GameObject in one way or another. This is the class that allows objects to show interactions, do certain stuff, get the catalog names, etc. If you look at our example of FishTankModern and click on FishTank, Reflector will bring you to the FishTankClass. As you can see, FishTank is also derived off of GameObject. This gives any object derived off of FishTank all the methods of GameObject and FishTank.

I still don't get it... Lets take a look at a Dell computer. Notice how I'm saying a Dell computer? It's not just any type of computer, it's a Dell computer. A Dell computer is the same as a regular computer, but has different/similar/enhanced features. If we were to think of a Dell computer as being derived off of a class, it would be something like "public class DellComputer : Computer". This gives the DellComputer the same features as Computers but will allow us to add in even more methods without having to change Computer.
Now we have not just any type of DellComputer but a DellInspirion. We want the DellInspirion to have the same features as a DellComputer would have but more added to it. We would do "public class DellInspirion : DellComputer". Again, the DellInspirion is a DellComputer and the DellComputer is a Computer. So the DellInspirion would be able to use methods from DellComputer and Computer. You can keep going on with this for ever and ever.

[edit] Methods

Methods tell Sims 3 what to do when something happens. The game already comes with a variety of methods that you can use to implement into your script. The most common one is WorldEventHandler, TNSMessages, and Interaction methods.
Think of methods as steps to solve a math problem or functions. When you do a math problem, you follow certain steps to get to the final outcome. This is essentially the same with methods. They give the game steps on what to do when someone clicks on the object or uses an interaction.

[edit] Interaction Methods


Interactions are the pie menus that show up when you click on a object. When you look at the FishTank class in Reflector you can see some more classes inside the FishTank class. Most of these are the interactions. Looking at the Feed class you can see that it is derived off of Interaction, but it has those weird "greater than or less than" symbols. The best way to learn why you put those symbols in is by looking up at the Interaction class. Going to the Interaction class will show Interaction<TActor, TTarget>. TActor is the person performing the interaction. In our case, it will be a Sim. Simply known as Sim in scripting language. The TTarget will be the object that the player clicks on. That will be MyFishTank. I gave the interaction the name of Hello. So, you should have this:

public class MyFishTank : FishTank
    {
        public sealed class Hello : Interaction<Sim, MyFishTank>
        {

        }
    }

[edit] Run Method

You are now able to add in a Run method. This method tells the game to go ahead and do those "problems". We do this by adding in this code into the Hello sealed class we just created:

public override bool Run()
            {
                return true;
            }


Bool must always return a value of some sort. We simply use true in here.

[edit] Making Run do something

We need to add in something for the game to do now. I used the TNS method. This shows the messages that you see in the upper right hand corner. One of the ways to call a TNS is through ShowTNSIfSelectable. You do not make it as a new method unlike with the Run method. You put this one inside the Run method. Inside that method you call the TNS message by typing in base.Actor.ShowTNSIfSelectable. We cannot leave it just like that and end it there. You need to add in some parameters. The ShowTNSIfSelectable allows us to add in what we want it to show. Upon inspection of this method in Reflector, you can see that it requires us to set a string and a notification style.

Strings in programming simply means text, or words. In this case you put in the string, or text, that you want the TNS message in-game to display. I used "Hi". Notice the quotation marks. This lets game know that it's a string.

We now need to tell the game what type of message to show. I used the kSimIsTalking tip. This shows the Sim that is currently selected when the player performs the interaction. You do this by typing StyledNotification.NotificationStyle.kSimTalking. You should then end up with something similar to this:

public override bool Run()
            {
                base.Actor.ShowTNSIfSelectable("Hi", StyledNotification.NotificationStyle.kSimTalking);
                return true;
            }

So what we now have is a message that will show up saying Hi with the selected Sims portrait.

Can I use different types of "Notification Styles"?
Yep! When you type in StyledNotification.NotificationStyle. you'll notice that it will give you some different options to choose from. These are called enums, or enumerators. They are similar to int, or integers. Instead of using numbers, you use words associated to letters. If you go to the NotificationStyle enum in Reflector you'll see something like this:

public enum NotificationStyle : uint
{
    kCelebrityUpdate = 7,
    kCustom = 6,
    kDebugAlert = 5,
    kGameMessageNegative = 4,
    kGameMessagePositive = 3,
    kSimTalking = 1,
    kSystemMessage = 2
}

You can find more about Integers and Enumerators through some google searching. You won't need to know how to make enums very often in scripting for Sims 3. Because this is a basic guide, I won't go over more about them. However, if you're wanting to make a complex scripting mod then you'd best be off using integers and enumerators.

Why is everything starting with "base"? Good question. When you use "base" you're referring to the Interaction we derived from. If you notice with all interactions run methods in sims 3 will almost always begin with "base". We used based.Actor because Actor is the Sim performing the interaction and we wanted it to show a TNSmessage so we used the Notification method. Experiment with the different classes and methods you can use. The possibilities are endless. It'll take me days to go over every single one.

[edit] OnStartup

This is the method that brings up all of our interactions when it is clicked on. Without this, clicking on the object wouldn't show anything! This one is pretty easy to use. We'll be using this method inside of the MyFishTank class. It does NOT go inside the Hello class we made earlier.
In VS type up "public override" and you should see a box pop-up. That's called IntelliSense. It gives you a list of all the methods and classes that you can use. In that box, look for OnStartup and click on it once you found it. You can also press tab on your keyboard. Remember, this method should go outside of the Hello interaction method and inside the MyFishTank class. You should have something similar to this:

public class MyFishTank : FishTank
    {
        public sealed class Hello : Interaction<Sim, MyFishTank>
        {
            public override bool Run()
            {
                base.Actor.ShowTNSIfSelectable("Hi", StyledNotification.NotificationStyle.kSimTalking);
                return true;
            }
        }
        public override void OnStartup()
        {
            base.OnStartup();
        }
    }


If you used the IntelliSense system, you'll notice that it added in base.OnStartup() into the code. That tells the game to go ahead and open up all the interactions that the FishTank class has. We could remove this if we really wanted too, but I'll keep it and you should always keep it too.
Under base.OnStartup(), type in base.AddInteraction(MyFishTank.Hello.Singleton). I put MyFishTank class before Hello so the game doesn't get mixed up with other interactions. You should do the same thing too. What this will do is add the Hello interaction to our object and show up the Definition class which gives the interaction name in the game. You should now get a error message from VS saying that it doesn't contain a definition for Singleton.

[edit] Definition Class

The Definition class will be derived off of InteractionDefinition. InteractionDefinition class contains some very easy to use methods such as GetInteractionName() which will allow us to name our interaction that would appear in TS3. It also contains GetPath() which you would use if you have a complex scripting mod that adds many different interactions. It will organize them by categories that you define. The other method is Test which you will use to give the requirements that are needed for the interaction to be able to be used. For the beginner portion of this guide, we'll just be using the GetInteractionName() method and the Test() method. Both are required for your interaction to show up in TS3. We'll need to define a new class inside the Hello interaction derived off of InteractionDefinition. The easiest way to do this is the way Sims 3 does it. So inside your Hello interaction go down into a new line and type in this:

public sealed class Definition : InteractionDefinition<Sim, MyFishTank, Hello>


The InteractionDefinition class requires 3 parameters to be used. That is the TActor (in this case, it's the Sim), the TTarget (MyFishTank), and TInteraction (Hello).
We can now add in the Singleton definition that VS is giving us a error about. You just type in this all by itself inside the Hello class:

private readonly InteractionDefinition Singleton = new Definition();


[edit] GetInteractionName

This method is pretty self-explanatory. It gets the name of the interaction that you define. Using it is also very simple. Inside the sealed Definition class start to type in "public override". IntelliSense is very good at providing methods that you can use and even adds in the bits of code that you need according to what you already have. When you type that in, select the GetInteractionName method that has the class names familiar in your code. Once you insert that, delete the return line and replace it with a string such as Hello. You should end up with something like this.

public override string GetInteractionName(Sim actor, MyFishTank target, InteractionObjectPair iop)
                {
                    return "Hello";
                }
[edit] Test

As I had said before, this will "test" to see if we meet the requirements to use this interaction, or to even show it up at all. We could show it up but have it be "greyed out" if we really wanted to tease the player.
Type in "public override" and select the Test method that has MyFishTank as the target. Delete the line inside the method. We'll just simply return !isAutonomous. The "!" means that it is not Autonomous. If you wanted a mod for a child sim but not for any other type of sim you could use !isChild. Of course you'd need to define isChild but that's later in the guide. You should end up with this.

public override bool Test(Sim actor, MyFishTank target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback)
                {
                    return !isAutonomous;
                }

[edit] Compiling


Compiling is putting all of our code together and into a DLL, or S3SA, which the game will use to read. Go under the Build>Build Solution tab. You should end up with some errors if you derived off of FishTank. That is because FishTank requires some certain methods to be inserted into our code. Inside the main class (MyFishTank), add in this:

        [Tunable]
        public static CleanableComponent.Tuning kCleanableTuning = new CleanableComponent.Tuning();

        [Tunable]
        public static FishTank.FishTankTuning kFishTankTuning = new FishTank.FishTankTuning();

        public override CleanableComponent.Tuning CleanableTuning
        {
            get
            {
                return kCleanableTuning;
            }
        }

        public override string SoundLoopName
        {
            get
            {
                return "aquarium_pump_lp";
            }
        }

        public override FishTank.FishTankTuning Tuning
        {
            get
            {
                return kFishTankTuning;
            }
        }

This will get the tuning files that the game needs to read on our FishTank. If we had derived off of FishTankModern then we wouldn't of needed to add in these methods since it already contained them. You should now be able to compile your script. For adding this to your game, refer to Buzzlers tutorial as this tutorial is meant only for scripting. http://modthesims.info/wiki.php?title=Tutorial:Sims_3_Object_Modding#Adding_The_Script_To_The_Package

I highly suggest follow Buzzlers tutorial as it gives more information about the certain types and methods that he uses and why he uses them and how he finds them. You should not have trouble following along after you've done this tutorial.

After that, you can attempt the Intermediate portion of this tutorial which will go over Tunables.
Your final code should end up looking something like this.

using System;
using System.Collections.Generic;
using System.Text;
using Sims3.Gameplay.Objects.Decorations;
using Sims3.Gameplay.Interactions;
using Sims3.Gameplay.Actors;
using Sims3.UI;
using Sims3.Gameplay.Autonomy;
using Sims3.SimIFace;
using Sims3.Gameplay.ObjectComponents;

namespace ScriptTutorial
{
    public class MyFishTank : FishTank
    {
        public sealed class Hello : Interaction<Sim, MyFishTank>
        {
            public static readonly InteractionDefinition Singleton = new Definition();

            public override bool Run()
            {
                base.Actor.ShowTNSIfSelectable("Hi", StyledNotification.NotificationStyle.kSimTalking);
                return true;
            }

            public sealed class Definition : InteractionDefinition<Sim, MyFishTank, Hello>
            {
                public override string GetInteractionName(Sim actor, MyFishTank target, InteractionObjectPair iop)
                {
                    return "Hello";
                }
                public override bool Test(Sim actor, MyFishTank target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback)
                {
                    return !isAutonomous;
                }
            }
        }

        [Tunable]
        public static CleanableComponent.Tuning kCleanableTuning = new CleanableComponent.Tuning();

        [Tunable]
        public static FishTank.FishTankTuning kFishTankTuning = new FishTank.FishTankTuning();

        public override CleanableComponent.Tuning CleanableTuning
        {
            get
            {
                return kCleanableTuning;
            }
        }

        public override string SoundLoopName
        {
            get
            {
                return "aquarium_pump_lp";
            }
        }

        public override FishTank.FishTankTuning Tuning
        {
            get
            {
                return kFishTankTuning;
            }
        }

        public override void OnStartup()
        {
            base.OnStartup();
            base.AddInteraction(Hello.Singleton);
        }
    }
}

Personal tools
Namespaces

Variants
Actions
Navigation
game select
Toolbox