Difference between revisions of "Sims 3:Jazz"
m (→Overview) |
|||
Line 5: | Line 5: | ||
==Overview== | ==Overview== | ||
− | Sequences of animations in The Sims 3 are controlled by [[http://en.wikipedia.org/wiki/Finite-state_machine finite state machines]] defined in jazz scripts. | + | Sequences of animations in The Sims 3 are controlled by [[http://en.wikipedia.org/wiki/Finite-state_machine finite state machines]] defined in jazz scripts. Core game scripts do not directly request animations in most cases, rather they create state machine clients to access the defined state machines, and the state machines are responsible for performing the correct animations. This provides a layer of separation such that the game scripts do not need to understand the details of animations, and some details of what animations do can be changed without having to involve any game script changes. |
===State Machines=== | ===State Machines=== | ||
Line 22: | Line 22: | ||
Internally to the state machine data, there are very few cases where the data contains strings. Most everything is identified by number. However the number is formed by performing [[FNV]] hashing of what would otherwise be the name. In Smooth Jazz, names can be identified as strings enclosed in double quotes (Following typical string escape sequence rules) "name" or can be identified by the number in hex or decimal, such as 0x2f8b3bf4 (FNV-32 hash of "name"). In most cases, either form works. | Internally to the state machine data, there are very few cases where the data contains strings. Most everything is identified by number. However the number is formed by performing [[FNV]] hashing of what would otherwise be the name. In Smooth Jazz, names can be identified as strings enclosed in double quotes (Following typical string escape sequence rules) "name" or can be identified by the number in hex or decimal, such as 0x2f8b3bf4 (FNV-32 hash of "name"). In most cases, either form works. | ||
− | There is one odd quirk. Occasionally, a name is a hash formatted to a string and hashed again. For example "0x2f8b3bf4" used for "name". | + | There is one odd quirk. Occasionally, a name is a hash formatted to a string and hashed again. For example "0x2f8b3bf4" used for "name". This appears to be a bug in the game data, but in the interested of reproducing the data, a name string can be prefixed with an asterisk (*) to indicate that the resulting hash should be formatted as a string and hashed again. |
<name-hash> ::= <opt-qualifier> <name-value> | <name-hash> ::= <opt-qualifier> <name-value> | ||
Line 90: | Line 90: | ||
===Smooth Jazz Usage=== | ===Smooth Jazz Usage=== | ||
− | In addition to the Smooth Jazz Studio interface, Smooth Jazz can be used in a command line context for importing scripts into packages, or exporting scripts from packages. | + | In addition to the Smooth Jazz Studio interface, Smooth Jazz can be used in a command line context for importing scripts into packages, or exporting scripts from packages. For full usage information, run SmoothJazz.exe with the option /help. |
(To be completed later) | (To be completed later) | ||
+ | |||
==Smooth Jazz Block Types== | ==Smooth Jazz Block Types== | ||
===State Machine=== | ===State Machine=== |
Revision as of 12:27, 21 August 2009
- For information on the data format of jazz scripts, see the type entry for Sims_3:0x02D5DF13
Jazz scripts define animation sequences used by The Sims 3. While they are not directly animations, anything that animates in some way involves using a jazz script, even little things like a door opening or closing.
The rest of this article assumes you are working with the jazz data in scripts as used and defined by Smooth Jazz. Smooth Jazz can be downloaded from [Mod The Sims].
Contents |
Overview
Sequences of animations in The Sims 3 are controlled by [finite state machines] defined in jazz scripts. Core game scripts do not directly request animations in most cases, rather they create state machine clients to access the defined state machines, and the state machines are responsible for performing the correct animations. This provides a layer of separation such that the game scripts do not need to understand the details of animations, and some details of what animations do can be changed without having to involve any game script changes.
State Machines
TBD
Smooth Jazz Syntax
This is a preliminary language definition, and is subject to change.
Smooth jazz aims to provide a means to modify the inner workings of the state machine in a simple easy to follow form. Therefore, the language aims to be terse in the most common cases by providing defaults where it makes sense. As a result, some block types can be distilled down to a single line in many cases. The default values will be noted wherever necessary.
For the most part, elements in Smooth Jazz correspond directly to the RCOL chunk definitions from Sims_3:0x02D5DF13. However, a few cases exist where the data is simple enough it only has the short form, and as a result, it appears to be just part of another definition block. A lot of the extraneous details linking between different chunks is hidden by the simplicity of the syntax.
All keywords in Smooth Jazz are case insensitive.
Names in Smooth Jazz
Internally to the state machine data, there are very few cases where the data contains strings. Most everything is identified by number. However the number is formed by performing FNV hashing of what would otherwise be the name. In Smooth Jazz, names can be identified as strings enclosed in double quotes (Following typical string escape sequence rules) "name" or can be identified by the number in hex or decimal, such as 0x2f8b3bf4 (FNV-32 hash of "name"). In most cases, either form works.
There is one odd quirk. Occasionally, a name is a hash formatted to a string and hashed again. For example "0x2f8b3bf4" used for "name". This appears to be a bug in the game data, but in the interested of reproducing the data, a name string can be prefixed with an asterisk (*) to indicate that the resulting hash should be formatted as a string and hashed again.
<name-hash> ::= <opt-qualifier> <name-value> <opt-qualifier> ::= * | <name-value> ::= <number> | <string> <number> ::= <hex-number> | <digits> <hex-number> ::= '0x' <hex-digits>
Animation Priorities
At several points in the state machine scripts, there is a specification for the animation priority. This can be any numeric value, however in most cases it is not necessary to use anything outside a named priority. Here is a list of animation priorities, from highest to lowest. There are also the special values "Broadcast" (-1) and "Default" (-2).
Priority Name | Equivelent Value |
---|---|
Low | 6000 |
LowPlus | 8000 |
Normal | 10000 |
NormalPlus | 15000 |
FacialIdle | 17500 |
High | 20000 |
HighPlus | 25000 |
CarryRight | 30000 |
CarryRightPlus | 35000 |
CarryLeft | 40000 |
CarryLeftPlus | 45000 |
Ultra | 50000 |
UltraPlus | 55000 |
LookAt | 60000 |
Incomplete Research
Some values used in the state machines are still not fully understood. In cases where the understanding is so little to even guess what the value is used for, it appears in the scripts as an "Unknown Value". In most cases, these are just values that were always the same in existing data. As these are understood, the language definition will be updated to reflect the new understanding. Until some of the common unknown values are understood, it is recommended keeping any scripts which include these values in binary form, where the name is unimportant, to avoid errors with future versions.
<unknown-value> ::= Unknown Value <number> = <number>
Comments
Comments in Smooth Jazz follow the C++ style syntax where "//" denotes a comment to the end of the line, "/*" denotes the start of a comment block, and "*/" denotes the end of a comment block.
Smooth Jazz Usage
In addition to the Smooth Jazz Studio interface, Smooth Jazz can be used in a command line context for importing scripts into packages, or exporting scripts from packages. For full usage information, run SmoothJazz.exe with the option /help.
(To be completed later)
Smooth Jazz Block Types
State Machine
<state-machine> ::= State Machine <string> { <state-machine-definition> } <state-machine-definition> ::= <state-machine-fields> <state-definitions> <state-machine-fields> ::= <state-machine-field> | <state-machine-fields> <state-machine-field> <state-machine-field> ::= <actor-definition> | <parameter-definition> | <state-machine-properties> | <state-machine-priority> | <animation-actor-assignment> | <unknown-value> <actor-definition> ::= Actor <name-hash> | Actor <name-hash> = <name-hash> <parameter-definition> ::= Parameter <name-hash> | Parameter <name-hash> = <name-hash> <state-machine-properties> ::= Properties <property-list> <property-list> ::= <property> | <property-list> , <property> <state-machine-priority> ::= Priority <priority-value> <animation-actor-assignment> ::= Assign Actor <name-hash> . <name-hash> as <name-hash> <state-definitions> ::= <state> | <state-definitions> <state>
Parameter and Actor Definitions
In order for the script to communicate with the state machine, it can assign parameters or actors.
An actor is an object which is represented by some sort of mesh or bone data in the world. For example, a sim, a toy box, or occasionally an animation jig. Actors are directly acted on and influenced by the animation clips, but are not used directly by the state machine.
A parameter is some sort of value which the state machine uses for various operations.
In both cases a default value can be assigned, however an actor definition is typically never assigned a default value.
State Machine Properties
Properties influence how the state machine will run. The following are valid properties for state machines.
Default:
Properties 0
Property Name | Usage Notes |
---|---|
UnilateralActor | |
PinAllResources | |
BlendMotionAccumulation | |
HoldAllPoses |
Priority
It is currently unclear what a priority setting on the state machine is for. Presumably it is provided as a default for other priorities within the state machine.
Actor Assignments
Animation clips can reference specific actors, however the name is not always the same as the actor name that the state machine uses. For cases where the name is not the same, actor assignments can be used. The format is the animation clip name and actor name as known by the animation, followed by the actor name as known by the state machine.
Unknown Values
There are presently 5 unknown values for state machines. Of those, only one has ever been seen with a value besides 0.
Value Index | Values Seen | Usage notes |
---|---|---|
0 | 1, 2, 3, 4, 5 | |
1 | 0 | |
2 | 0 | |
3 | 0 | |
4 | 0 |
State
<state> ::= State <name-hash> | State <name-hash> { <state-fields> <decision-graph> } <state-fields> ::= <state-field> | <state-fields> <state-field> <state-field> ::= <state-properties> | <state-transitions> | <unknown-dg-value> | <unknown-value> <state-properties> ::= Properties <state-property-list> <state-property-list> ::= <state-property> | <state-property-list> <state-property> <state-transitions> ::= Transitions to <name-hash> <unknown-dg-value> ::= Unknown Decision Graph Value <number>
Properties
Properties influence how this state can be used by scripts.
Default:
Properties 0
Property Name | Usage Notes |
---|---|
Public | |
Entry | The state is an entry state and can be explicitly set as the current state without using transitions |
Exit | The state is an exit state |
Loop | The state runs as a loop where the state machine will continually be coming back to it through transitions |
OneShot | |
OneShotHold | |
Synchronized | |
Join | |
Explicit |
Unknown Values
There are two unknown values in state definitions, one is explicitly named as an unknown decision graph value, but is always used.
Value Index | Values Seen | Usage notes |
---|---|---|
0 | 2, 3, 4, 5, 6 | The most common value is 6, which is the default if not explicitly given |
*dg | 0 |
Transitions
Any valid transition from this state must be explicitly named. The state machine will only ever follow named transitions, no matter what the request for a new state is and where it comes from.
Decision Graph
<decision-graph> ::= <decision-graph> <decision-graph-node> | <decision-graph-node> | <decision-graph-node> ::= <play> | <stop> | <actor-operation> | <create-prop> | <random> | <select-on-parameter> | <next-state>
The decision graph is the meat of the animation system. Aside from the state machine logic, the decision graph is where the logic of deciding what animations to play comes from. A decision graph can be as simple as playing an animation, or more complex such as picking a random event weighted based off parameters passed into the state machine. Any decision graph node can be nested under nearly any other decision graph node to produce complex actions.
Play
<play> ::= Play <clip-definition> <opt-actor> <opt-play-fields> <clip-definition> ::= <resource-ref> | <string> With Substitution <opt-actor> ::= For <name-hash> | <opt-play-fields> ::= { <play-fields> } | <resource-ref> ::= <name-hash> | <number> : <number> : <name-hash> <play-fields> ::= <play-field> | <play-fields> <play-field> <play-field> ::= <track-mask> | <actor-slot> | <slot-suffix> | <play-flags> | <play-priority> | <blend-in> | <unknown-value> | <decision-graph> <track-mask> ::= Track Mask <resource-ref> <actor-slot> ::= Actor <name-hash> Slot <name-hash> <opt-slot-values> <opt-slot-values> ::= , <number> , <number> | <slot-suffix> ::= Actor <name-hash> Suffix <name-hash> <play-flags> ::= Flags <play-flag-list> <play-flag-list> ::= <play-flag> | <play-flag-list> <play-flag> <play-priority> ::= Priority1 <priority-value> | Priority2 <priority-value> <blend-in> ::= Blend In <number>
Often times the short form of Play can be used, if no additional fields are required beyond the clip name and primary actor.
Animation Clip
Animation clips can be either explicitly named by the clip definition, or formed by substituting parameter values in for parts of the clip name. When the clip is explicitly named, the resource type and group are assumed to be 0x6B20C4F3 and 0, respectively, however the full resource key can be given. When substitution is performed, the type and group for the resource key are taken as the default.
Substitutions work by replacing any part if the string with curly braces with the value of the parameter specified. For example "{age1}2{age2}_greet" would create the clip name by substituting agr1 and age2. If age1 was given as "a" (adult) and age2 as "t" (teen), the clip used would be "a2t_greet".
If an actor is named after the clip, that is taken to be the primary actor for the animation, and the age and species of the the actor are applied to the clip instance to find the animation to use.
Animation clips are named in the resource files based on the age group for the animation. The animation hash codes are always based on the name for adult animations. When a play animation node is encountered, first it will try to load the age specific animation, then if that fails it will attempt to load the generic (adult) animation.
Track Mask
Track masks are used to mask off some or all motion to certain joints in the animation rig. The masks is a resource of type 0x033260E3, which is assumed to be the type of the resource if it is not explicitly requested. It is unclear if what is being masked is this animation, or all other animations
Actor Slot
Actor slot specifies a defined slot for the requested actor. Slots are defined in the appropriate RSLT associated with the actor. There are two additional unknown values which are unknown, and will default to 0.
Not a whole lot is known about this animation option, as it is only used once in all of the game jazz data.
Slot Suffix
An optional suffix can be applied to the animation slots used in an animation. This is typically used for determining which side of the bed a sim is on, or which seat of a car or sofa they are sitting in. The suffix is defined in term of the actor name and a parameter to be used for the substitution.
Priority
A special note should be made for animation priority. The state machine data contains not one, but two animation priority definitions. The first is assumed to be the priority for the animation itself, while it is unclear what the use of the second is.
Blend In
When an animation starts, it can be blended with an existing animation to provide a smooth transition. For example, when a sim runs, the state machine responsible first starts the sim walking, then blends it into a run animation.
Flags
The following flags can be used when playing an animation. Default:
Flags AtEnd
Flag Name | Usage Notes |
---|---|
AtEnd | |
LoopAsNeeded | |
OverridePriority | |
Mirror | |
OverrideMirror | |
OverrideTiming0
TimingMaster |
Both flags have the same value |
OverrideTiming1
TimingSlave |
Both flags have the same value |
TimingIgnored | Shorthand for OverrideTiming0, OverrideTiming1 |
Interruptible | |
ForceBlend | |
UseTimingPriority | |
UseTimingPriorityAsClockMaster | |
BaseClipIsSocial | |
AdditiveClipIsSocial | |
BaseClipIsObjectOnly | |
AdditiveClipIsObjectOnly | |
HoldPose | |
BlendMotionAccumulation |
Stop
<stop> ::= Stop <opt-actor> <opt-stop-fields> <opt-actor> ::= For <name-hash> | <opt-stop-fields> ::= { <stop-fields> } | <stop-fields> ::= <stop-field> | <stop-fields> <stop-field> <stop-field> ::= <stop-flags> | <stop-priority> | <unknown-value> | <decision-graph> <stop-flags> ::= Flags <play-flag-list> <stop-flag-list> ::= <stop-flag> | <stop-flag-list> <stop-flag> <stop-priority> ::= Priority1 <priority-value> | Priority2 <priority-value>
Priority
Stop has two priority fields like Play, it is unclear what they are used for.
Flags
Stop uses the same animation flags as play uses.
Actor Operation
<actor-operation> ::= Actor Operation <actor-op-list> ON <name-hash> <opt-acop-fields> <actor-op-list> ::= <actor-operation> | <actor-op-list> <actor-operation> <opt-acop-fields> ::= { <acop-fields> } | <acop-fields> ::= <acop-field> | <acop-fields> <acop-field> <acop-field> ::= <unknown-value> | <decision-graph>
Operation
Operations can be applied to actors for the purpose of animations. Presently there is only one operation defined.
It is only assumed that multiple operations can be defined for a single actor operation node. Since there is only a single operation defined, all existing exampled assign exactly one operation.
Operation Name | Usage Notes |
---|---|
None | Clear all operations |
SetMirror | Mirror animations for this actor |
Unknown Values
There are three unknown fields on actor operations. None of them have been seen with any value besides 0.
Value Index | Values Seen | Usage notes |
---|---|---|
0 | 0 | |
1 | 0 | |
2 | 0 |
Create Prop
<create-prop> ::= Create Prop <resource-ref> as <name-hash> <opt-prop-fields> <resource-ref> ::= <name-hash> | <number> : <number> : <name-hash> <opt-prop-fields> ::= { <prop-fields> } | <prop-fields> ::= <prop-field> | <prop-fields> <prop-field> <prop-field> ::= <unknown-value> | <decision-graph>
Resource Ref
In most cases, actors are existing objects from the game world which are passed in to the jazz script. However it is possible for the jazz script to create temporary objects for use as props. Examples of this are tools used for repairing items, toy xylophone mallets, and the grim reapers scythe.
The resource reference is the catalog GUID of an object to create. While the object is given as a resource key, the type value is 0x139f7591, which is an otherwise unknown type not present in any data files. A full resource key can be given, but it is unknown if it would work.
Unknown Values
There are five unknown fields in a prop node, none of which have any known value besides 0.
Value Index | Values Seen | Usage notes |
---|---|---|
0 | 0 | |
1 | 0 | |
2 | 0 | |
3 | 0 | |
4 | 0 |
Random
<random> ::= Select Random { <opt-random-flags> <random-selection> } <opt-random-flags> ::= Flags <random-flag-list> | <random-flag-list> ::= <random-flag> | <random-flag-list> , <random-flag> <random-selection> ::= Weight <number> { <decision-graph> }
A random selection is picked based off the weights of all options. If there are two options with weights of 1 and 10, the first option will be picked once for every ten times the second option is picked. Note that this is actually 1 in 11 times, not 1 in 10. Since the weights are important only with relation to other weights, the scale does not matter. The same result would occur if the weights were 10 and 100, 3 and 30, or .2 and 2.
Flags
The following flags can be applied to the process of random selection. Default:
Flags None
Flag Name | Usage Notes |
---|---|
None | No flags |
AvoidRepeats | Pick options that have not been picked yet |
Choices
A choice is defined as a weight, and a list of 0 or more actions to take. The weight is defined as any positive number.
Select on Parameter
<select-on-parameter> ::= Select on Parameter <name-hash> { <sopn-choices> } <sopn-choices> ::= <sopn-choice> | <sopn-choices> <sopn-choice> <sopn-choice> ::= Value <name-hash> { <decision-graph> }
Select on parameter is the jazz version of a switch statement. The value of the parameter is compared to all the choices and the one which matches is selected for the action. However there is no concept of a default action.
Next State
<next-state> ::= Next State <name-hash>
Causes the state machine to transition to the named state. It is unknown if the decision graph continues to be evaluated before the transition, and what happens if multiple next state nodes are encountered.
Sample Script
This sample script illustrates the basics of the syntax.
State Machine "AlarmClock" { Properties UnilateralActor Actor "AlarmClock" Assign Actor "o_alarmclockCheap_Ring.ma"."alarmclockcheap" as 0x0 Assign Actor 0xC63B4209."alarmclockcheap" as 0x0 State "Enter" { Properties Public, Entry, Explicit Transitions to "o_alarmClockCheap" } State "Exit" { Properties Public, Exit, Explicit } State "o_alarmClockCheap" { Transitions to "Ring" Play "o_alarmClockCheap" { Flags AtEnd, BaseClipIsObjectOnly } } State "Ring" { Properties Public, Explicit Transitions to "Exit" } }