Pack Making JSON Animations - DonBruce64/MinecraftTransportSimulator GitHub Wiki

Animations are used throughout the MTS JSON structure for things like moving parts, adjusting sound volumes, and animating things. No matter where you find them, they consist of the same parameters and same format.

Animation Parameters

  • animationType – The type of animation this definition will perform. Valid types are rotation, translation, scaling, visibility, inhibitor, and activator. Inhibitors and activators are somewhat unique in that they don't actually cause an animation. Rather, an inhibitor prevents any animations that come after it if the criteria (clamps) are met, and an activator negates the effects of a previous inhibitor if its criteria are met. Combined, these allow for complex logic.
  • variable – The variable to use in animation. Note that this variable must follow the Animation Hierarchy
  • centerPoint – The x, y, z position that this animation should be performed at. If this is rotation animationType, it is the rotation point. If this is a scaling animation, this center point at which to scale the object. For any other type, this may be omitted as it is not used.
  • axis – This is the most complex part of the animation system. In essence, it is the vector about which this part will animate. For translation types, this is simply the direction the part will translate in. For rotation types, this is the axis the rotation is performed around, in a counter-clockwise direction (Right-Hand Rule). For scaling, this defines the three axis of scale to apply. Multiplying the axis by a constant will increase the animation by that factor. For example, using the a door variable will only rotate a door by 1 degree (because the door variable goes from 0 to 1). However, if you multiply the axis by 60, it will then rotate 60 degrees. This can be done for any variable and on any axis.

Note that multi-axis rotation gets a fair bit more complicated. If you only want an object to rotate in one axis, such as a door that's perfectly vertical, you only need to put a 60 in the Y spot and this will rotate the door about the vector pointing in the +Y direction. If you put a -1 in the Y spot, then it will rotate about the -Y direction, which simply means it will be clockwise rather than counter-clockwise.

However, with multiple axis on complex models, you'll find this single-value method won't work, and you'll need to calculate the proper axis. This is done by taking the centerPoint, and a known point along the axis of rotation, and calculating the angles between them for the X, Y, and Z directions. For a two-axis rotation this can be done with some simple math by using the angle you rotated the object by in your editor to get the components.

For a three-axis rotation (a part of a model that whose rotation axis cannot be restricted to a two-dimensional plane) this gets significantly more complex and may not be solve-able by your modeling software. As such, you can manually calculate the vector you need by performing the following steps:

  1. Take note of two points on your model that can be used to form an axis for your rotation. One of these points should be your centerPoint, the other should be a point along the axis of rotation.
  2. Calculate the distance between these points in each the X, Y, and Z axis, then calculate the total distance between the points.
  3. Divide the axis-distances by the total distance, and use these values as your axis. Ff any value is greater than 1, you did Bad Maths!
  4. Multiply these values by your rotation factor to increase the rotation, or change all their signs to make the rotation go the opposite direction.
  5. If worst comes to worst, you can ask the Discord team for help, and grab one of their auto-angle calculators. But make sure your model is done and good before you get this far!

For easier adjustment of translation animations (especially for sound pitch & volume anims), using the graphing website linked below can help speed up the process significantly. -> Linear Translation Function

  • offset – The offset for this animation.
  • clampMin – Sets the lower bound for rotation/translation limits (variable * axis + offset). For Visibility, Inhibitors, and Activators, this will be the lowest value these animationTypes are active.
  • clampMax – Like clampMin, but for the max value.
  • absolute – If true, the absolute value of the variable will be used rather than the actual value. Note that negative movements are still possible via a negative rotation factor or a large negative offset. The following parameters are only valid for variables that go from 0-1.
  • duration – The duration of this animation, in ticks. Causes the animation to be interpolated over the duration for smooth movement. Useful for things like doors made using toggleable collision boxes.
  • forwardsEasing - The type of easing or interpolation to apply on this animation, in the forwards direction. Must have a set duration.
  • reverseEasing - Like forwardsEasing, but for the reverse direction.

The valid easing types are:

Default value is linear. Use easings.net to preview what each easing curve does.

Ease In Ease Out Ease In Out
easeinsine easeoutsine easeinoutsine
easeinquad easeoutquad easeinoutquad
easeincubic easeoutcubic easeinoutcubic
easeinquart easeoutquart easeinoutquart
easeinquint easeoutquint easeinoutquint
easeincirc easeoutcirc easeinoutcirc
easeinback easeoutback easeinoutback
easeinelastic easeoutelastic easeinoutelastic
easeinbounce easeoutbounce easeinoutbounce
  • forwardsDelay – How long this animation waits to start after the variable goes to 1, in ticks. For example, an animation with a forwardsDelay of 20 and a duration of 40 would wait one second before moving, and then take two seconds to move its entire animation.
  • reverseDelay – Like forwardsDelay, but for the end of the animation. This delay is applied when the variable goes from 1 to 0.
  • skipForwardsMovement – If true, this animation will skip the forward movement time specified in the duration and will instantly move to the end of the animation. Useful when you want uni-directional animations. Note that this does not prevent the movement delay from forwardsDelay from applying. However, it will void any reverseDelay.
  • skipReverseMovement – Like skipForwardsMovement, but for the reverse movement.
  • forwardsStartSound – This sound will play when the animation starts its movement forwards. This only happens at the start of the duration, not the start of the delay. Format is packID:soundName.
  • forwardsEndSound – This sound will play when the animation ends its movement forwards. This only happens at the end of the duration, and won't occur if the animation reverses direction beforehand.
  • reverseStartSound – Like forwardsStartSound, but for reverse.
  • reverseEndSound – Like forwardsEndSound, but for reverse.

Animation Hierarchy

The way MTS animates things on objects is simple for some animations. For example, if you choose the throttle animation variable, MTS will return the throttle value of the vehicle. Even if this variable is on a part, there is still only one throttle, so only one value for the variable can be returned. What happens, however, if you want something more specific, such as an engine driveshaft rotation? Sure you can put this in the engine part and MTS will know which engine you mean, but what if you put it on a vehicle with two engines? What if it's on another part? This section elaborates on the process tree MTS uses to come up with a number for animation.

The first thing MTS checks is if the animation has a number on the end of it. If so, MTS will try to get the part of that number as defined in the order of the part slots. So, if you have a variable engine_rotation_2, MTS will attempt to get the second engine and return the value of engine_rotation for that engine. The same goes for things like gun_ammo_1 to get the ammo count of the first gun and propeller_pitch_percent_3 to get the propeller pitch of the third propeller, and part_present_22 to check if the 22nd part is present. If MTS can't find the part with the specified index, it will assume that it simply hasn't been placed yet, and will return a value of 0 for the animation.

If there's no number at the end of the animation, but the animation is placed on a part, MTS will try to get the animation value for that part. So while engine_rotation_2 on the vehicle will get you the rotation of engine 2 on that vehicle, engine_rotation on an engine will get the rotation of that engine. It is important to note that if you put engine_rotation_2 on the PART, then MTS will always return the value of engine 2 as defined on the PART's part slots, NOT the vehicle's part slots. This allows you to reference specific things on parts. An example of this is gun_yaw_1 on a vehicle being a tank turret, but gun_yaw_1 on the turret being the SMG you can place on that turret. This also stacks. You can do part_engine_rotation_1_6, which will first go to part 6, and then find engine 1 on that part.

If MTS can't find the variable for the part, but the part has a parent (the part is a subPart or additionalPart of another part), then MTS will try to get the value of the animation on the parent. This is also the case if you prefix the variable with parent_. This means that you can put an animation such as engine_driveshaft_rotation on a propeller that is and make that propeller dependent on placing the engine. When that happens, and MTS goes to render the propeller, it won't find the driveshaft rotation on it (because it's a propeller) and will go check the engine. It will find it there, and thus the propeller gets the rotation from the engine it's placed on, no matter where that engine is placed on the vehicle and what part slot that engine has. If you want to get the vehicle the part is on and not a specific parent part, use vehicle_ as a prefix. If the part isn't on a vehicle then any variable with this prefix will return 0.

If it hasn't found the value of the variable at this point, it will assume the variable is for the vehicle itself and not any part. This will result in MTS checking all vehicle variables instead, following those rules as applicable.

If a variable is prefixed with !, the value of variable will be set to 1 if it is 0, and 0 if it has any value other than 0.