Tutorial:Sims 3 Custom Animations
Contents |
Introduction
This tutorial will cover the process of creating an object with a custom animation. This tutorial assumes that you have basic knowledge of object modding and cloning.
What You'll Need
- Smooth Jazz animation script editor
- S3PE
- S3OC
- Wes Howe's AnimTool
- adult_bodies_4_anim_2010_02_19.rar
- Microsoft® Visual C# Express Edition
- Milkshape 3D
I strongly recommend that you also use my (And Wes's) AnimTool instead of the legacy one in order to avoid hashing errors which are likely due to some magic required for the Animation Name hash.
Figuring Stuff Out Beforehand
In any part of this tutorial, if you see something wrapped in curly braces {}, substitute it with one of the values below. For example, in my case, {YourNamespace} would change to "rothn" (without the quotes).
YourNamespace - This is the namespace that your object's script will use. I generally use my forum username (rothn).
ObjectClass - This is the class that your object's script will use. There can't be multiple classes in the same namespace, so I generally choose a concise description of the object (e.g. AnimTutorial)
ObjectClassHash - This is the Fnv64 hash of your ObjectClass.
AnimName - This is the name of the specific animation that you will play (I used "a2o_test_x")
AnimNameHash - This is the Fnv64 hash of your AnimName. You won't need this if you are using my AnimTool (hosted on MTS)
SourceName - This is a name used for a group of animations (I used "a2o_test.ma")
Setting Up Your Environment
- Create a directory somewhere. You will use this in the development of the object.
- Choose an object to clone.
- Note that if you select an object which doesn't already make use of animations, you will have to do an extra step later in this tutorial.
- Put the package file of your new object in the aforementioned directory.
- Create a new CLR dll project in Visual C#.
- Make sure that the Sims 3 DLL's you're using are the most recent and from the same version of TS3.
- I will not go farther into this topic, as I assume that you are not new to making your own scripted objects.
- Create a new jazz script in Smooth Jazz.
- If you are using my AnimTool, just select Package To Animation, open FullBuild0.package (see below for the path), and export to your object's directory. Skip to step 7
- Open FullBuild0.package in "%ProgramFiles%\Electronic Arts\The Sims 3\GameData\Shared\Packages".
- Choose an animation (S3PE shows the tag CLIP for animations) to base your animation on.
- Right click on that animation, mouse over "Export", and click on "To File".
- Save the file in your object's directory.
- Extract "rigfile.txt" from "adult_bodies_4_anim_2010_02_19.rar" and put it in your object's directory.
- Extract all the contents of "AnimTool.rar", "AnimTool-04a.rar", or "AnimToolV04L.rar" (whichever you downloaded), and put them in your object's directory.
Preparing Your Object
- Open the package file that you created in the previous section in S3PE.
- Select the OBJK resource and press "Edit OBJK".
- If it isn't checked, check the "Script" checkbox, and replace whatever existing text with "{YourNamespace}.{ObjectClass}" (e.g. "rothn.AnimTutorial")
- If the object you cloned is not animated (or if the boxes aren't checked), check the boxes labeled "Sacs", and "Animation".
- Create a new S3SA resource, where the instance is {ObjectClassHash}, the group is 0x00000000, and the name is descriptive of your object (e.g. AnimTutorial.dll).
- If you are using my AnimTool, close S3PE, click on Animation To Package, select the package file that you created in the previous section, and select the animation that you exported earlier. Skip to the next section.
- Enter your object's directory, right click on the animation that you exported from S3PE, and click rename.
- Change the file's name to "S3_6B20C4F3_00000000_{AnimNameHash}_{AnimName}%%+CLIP.animation".
Creating the C# Script
- Go to Visual C# and open up the project that you created in Setting Up Your Environment.
- If you know what you're doing, please look at the code sample below (which references a custom jazz script), and write your own script. Otherwise, please scroll down to step 3.
- If you don't know what you're doing, or you don't want to bother with writing your own script, paste this code into Visual C#.
- Compile the dll, and put it in your object's folder.
- Switch to S3PE and select the S3SA resource that you created in Preparing Your Object.
public bool DoAnimation(InteractionInstance interaction, Sim Actor) { interaction.StandardEntry(); if (Actor.SimDescription.ChildOrAbove) { interaction.AcquireStateMachine("animtutorialjazz"); //interaction.UseAutoParameters(new TraitNames[] { TraitNames.Clumsy, TraitNames.HotHeaded, TraitNames.Unlucky }); interaction.SetActor("x", Actor); //interaction.SetActor("object", this); interaction.EnterSim("Enter"); interaction.AnimateSim("OurAnim"); interaction.AnimateSim("Exit"); } interaction.StandardExit(); return true; }
using System; using System.Collections.Generic; using System.Text; using Sims3.Gameplay; using Sims3.Gameplay.Objects; using Sims3.Gameplay.Objects.Seating; using Sims3.Gameplay.Abstracts; using Sims3.Gameplay.Interfaces; using Sims3.Gameplay.Interactions; using Sims3.Gameplay.Actors; using Sims3.Gameplay.ActorSystems; using Sims3.Gameplay.Autonomy; using Sims3.SimIFace; using Sims3.SimIFace.CustomContent; using Sims3.UI; using Sims3.Gameplay.ObjectComponents; using Sims3.Metadata; using Sims3.SimIFace.Enums; using Sims3.Gameplay.Core; using Sims3.Gameplay.Objects.CookingObjects; namespace {YourNamespace} { public class {ObjectClass} : GameObject, IGameObject, IScriptObject, IScriptLogic, IHasScriptProxy, IObjectUI, IExportableContent { /*[Tunable, TunableComment("Range: Positive integers. Description: Maximum number of Sims that can wait in line.")] private static int kMaximumNumberOfSimsInLine = 0x3; [TunableComment("Range: Positive floats. Description: Amount of Sim minutes a Sim will wait in line before timing out and exiting."), Tunable] public static float kTimeToWaitInLine = 15f; public SimQueue Line = new SimQueue(SimQueue.WaitLocation.HangAroundNearObject, kMaximumNumberOfSimsInLine);*/ protected Sim mRevealingSim; public override void OnStartup() { base.AddInteraction(DoAnimation.Singleton); } public bool RunAnimation(InteractionInstance interaction, Sim Actor) { /*if (!this.Line.WaitForTurn(interaction, SimQueue.WaitBehavior.Default, ~(ExitReason.MidRoutePushRequested | ExitReason.ObjectStateChanged | ExitReason.PlayIdle | ExitReason.MaxSkillPointsReached), kTimeToWaitInLine)) { return false; } if (!Actor.RouteToSlotAndCheckInUse(this, Slots.Hash("Routing"))) { return false; }*/ interaction.StandardEntry(); if (Actor.SimDescription.ChildOrAbove) { interaction.AcquireStateMachine("animtutorialjazz"); //interaction.UseAutoParameters(new TraitNames[] { TraitNames.Clumsy, TraitNames.HotHeaded, TraitNames.Unlucky }); interaction.SetActor("x", Actor); //interaction.SetActor("object", this); interaction.EnterSim("Enter"); interaction.AnimateSim("OurAnim"); } return true; } public bool FinishAnimation(InteractionInstance interaction, Sim Actor) { if (Actor.SimDescription.ChildOrAbove) { interaction.AnimateSim("Exit"); } interaction.StandardExit(); return true; } public class DoAnimation : Interaction<Sim, {ObjectClass}> { // Fields public static readonly InteractionDefinition Singleton = new Definition(); // Methods protected override bool Run() { //base.BeginCommodityUpdates(); base.Target.RunAnimation(this, base.Actor); base.Target.FinishAnimation(this, base.Actor); //base.EndCommodityUpdates(true); return true; } // Nested Types private sealed class Definition : InteractionDefinition<Sim, {ObjectClass}, {ObjectClass}.DoAnimation> { // Methods protected override string GetInteractionName(Sim actor, {ObjectClass} target, InteractionObjectPair iop) { return "Do Animation"; } protected override bool Test(Sim a, {ObjectClass} target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback) { return true; } } [DoesntRequireTuning] private sealed class ForceDefinition : InteractionDefinition<Sim, {ObjectClass}, {ObjectClass}.DoAnimation> { // Methods protected override bool Test(Sim a, {ObjectClass} target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback) { return true; } } } } }
Creating the Animation
- Open Wes Howe's AnimTool.
- Press the "Clip -> SMD" button.
- In the dialog box that comes up, select the .animation file that you renamed in Preparing Your Object.
- Now open up Milkshape 3D
- In Milkshape, import the SMD file that you just created with the AnimTool.
- Note that if you use bones that the animation you exported doesn't, then the animation will not display correctly ingame. Further note that you don't have to set keyframes for every key in your animation. Somehow, the interpolation happens (either ingame or in the AnimTool)
- When you are ready, export the animation from Milkshape 3D as a SMD file, making sure to export as a sequence (not a reference) and taking care to use the same filename that you set in Preparing Your Object, but with the .smd extension rather than the .animation extension.
- Go back to Wes Howe's AnimTool.
- In the textbox labeled "Anim Name", type {AnimName}.
- In the textbox labeled "Source Name", type {SourceName}.
- Now, press SMD -> Clip.
- In the dialog box that comes up, select the .smd file that you exported in Milkshape 3D.
- Since the only difference between the filenames of the .smd file and the .animation file is the extension, the AnimTool will add a .bak00 extension to the original animation file, and your new .animation file will have the name of the original.
- Now, switch back to S3PE, and click "Resource" in the toolbar, mouse over "Import", and click "From file...".
- Select the .animation file and click OK in the dialog box that appears.
Creating the Jazz Script
- Close all instances of S3PE.
- In Smooth Jazz, click "Tools", and then "Options".
- Press "Add", navigate to your object's directory, and double click your object's package file.
- Press "OK".
- In the new jazz script that you created in Smooth Jazz in Setting Up Your Environment, enter the following code.
- Now, press "File", and click "Package All Into..."
- In the file selection dialog, navigate to your object's directory, and select your object's package file.
- If there are any other state machines than "animtutorialjazz" that show up in the export dialog, uncheck the checkboxes next to them.
- Click "Export".
State Machine "animtutorialjazz" { Actor "x" Assign Actor "{SourceName}"."x" as "x" State "Enter" { Properties Public, Entry, Explicit Transitions to "OurAnim" } State "OurAnim" { Transitions to "Exit" Play "{AnimName}" } State "Exit" { Properties Public, Exit, Explicit } }
Finishing Up
- Please test your object, and PM me (rothn) at ModTheSims if you have any questions or if your object's animation will not play.