XML:TRAM: Difference between revisions

From OniGalore
Jump to navigation Jump to search
m (wording)
 
(111 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{XML_File_Header | type=TRAM | prev=TRAC | next=TRAS | name=Totoro Animation }}
{{XML_File_Header | prev=TRAC | type=TRAM | next=TRAS | name=Totoro Animation}}


__TOC__
{{TOCfloat|side=right}}
==General information==
TRAM files — animation data for characters — are basically made of three chunks:
* Metadata or "header": animation type, state, flags, particle, sounds, etc.
* Animation data: '''pelvis heights, pelvis velocities (root motion)''', bone rotations
* Attack data: damage, self-damage, extents (danger zones for AI awareness) and throws


===Export===
Root motion: a character moves by changing the position of its root bone (pelvis). The animated legs just create the '''illusion for the player''' that they are responsible for the motion.
TRAM files can be extracted '''A) as pure xml''' files or combined '''B) as xml and dae''' files.


For editing the actual animation you will want to use method B.
Bones: Each character has '''19 separate body parts''' which get animated (rotated) relative to each other. Compared to modern games Oni's bone system is [[wp:Deprecation|deprecated]]. The body doesn't get deformed by following animated bones. Oni modders often use the terms mesh and bone interchangeably. Only the pelvis has '''translation''' data (heights and velocities) besides rotations. The hierarchy of the body parts (or bones) is determined by [[XML:TRBS#Standard_TRIA_hierarchy|TRIA]].


While doing the export with ONCC you might see errors such as
The term '''animation''' is often shortened to '''anim''' by modders, following the naming of commands in BSL: chr_wait_animstate, chr_wait_animtype, env_anim, etc.


Cannot find instance 'TRAMKONCOMthrow_rev'
Oni's code and debugging messages tend to spell the word variant as "varient". Blame the programmers for that one. Typically we use the correct spelling here, but OniSplit's XML follows Oni's misspelling, so you may see "varient" creep into the wiki here and there.
Cannot find instance 'TRAMKONCOMthrow_rev'
Cannot find instance 'TRAMKONRIFturn_right'
Cannot find instance 'TRAMKONOKOlev18_ZomStand'
Cannot find instance 'TRAMKONOKOcorner_hide'
Cannot find instance 'TRAMKONPIScorner_hide'
 
Ignore them, those files doesn't exist.


(Someday we should remove them from TRAC.)
TRAMs used in Oni follow a naming pattern. A list of all combat TRAMs in-game and their naming can be found [[Combat moves|here]].


==Open questions==
* If the never-used Thrown type can be applied as type 18 the table looks much more complete. "Restoring" forward tackles (face-to-face, src run + tgt run) can be omitted as the AI would most often stop movement for actual combat?


====Via command line====
* All important header data of STRCOMrun_thw_fw_p and STRCOMrun_thw_fw_pl is identical. That means the engine picks the correct TRAM by using an unknown context, possibly this is similar or part of the distinction of "forward" (face-to-face) and "backward" (face-to-back).
for single file export
: '''Maybe the algorithm checks always tgt's rotation and relative position to src at the same time but for most cases only tgt's rotation (facing) is relevant.'''
onisplit -extract:xml output_path -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname.oni


for merged file export
* Also, STRCOMrun_thw_fw_p(l) routing to Thrown5 and Thrown6 shows that Thrown anim types might be used however we like. A src-tgt-anim-type-pairing might be simply a ''convention''. Well, someone could check the source code...
onisplit -extract:xml output_path '''-anim-merge''' -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname1.oni  path_to\TRAMnameN.oni


* The existence of STRCOMrun_thw_fw_p(_tgt) and STRCOMrun_thw_fw_pl(_t) means that we need extra research to understand the full extent of the throw system.
* The variant pickup system is not clear yet: is a RIFCOM idle and a RIFNAT idle both possible?
** Or do rightpistol, leftpistol, rightrifle and leftrifle variants count as subsets of combat?


====Via Vago====
==Summary of animation lookup logic==
<!--[[Image:Vago_xml_plus_dae_extraction.png|thumb|200px|right|combined extraction of dae and xml]]-->
* First the game builds a pool of anims a character can use. They are loaded from the TRAC file registered in [[ONCC]], including parent TRACs.
* Anims from a child TRAC override those of the parent if their combination of state, type and variant is exactly the same.
* Child TRACs usually omit some anims. For example, Elite Strikers don't have their own run anims, so they use the parent anims of normal Strikers. See [[XML:TRAC|TRAC]] page for details.
* A character always possesses a single animation state. This term derives from state machines, but you only need to know that states are the first point in the decision path determining what anims are actually allowed to play at a given moment.
* Here is the full decision path:
** anim '''state''' check
** event (user input, or engine input for the AI) -> [[XML talk:StNA|context check]] -> anim '''type''' check
** anim '''variant''' check
** TRAC '''weight''' check


When you start '''[[Vago_(tool)|Vago]]''' the "General" tab should be open by default. If not click on it. Then follow the five easy steps.
===Elaboration===
<!-- General tab should be step 1 but i've already another img. If Vago gets updated I will upload a better img. -->
Animations never stop – they flow from one to another. (See the concept of [[wp:Finite-state machine|state machines]] in gaming.) The default case is a character getting spawned and then just standing there: he idles forever. This brings us to the core attributes of every animation: '''type, state, variant'''.


'''Step 1:''' Select "ONI" as ("From") input format.
Now then, the idle animation does not link to a specific follow-up animation – it rather links to a follow-up ''state''.
: Ironically all anims have a <FromState> and a <ToState> field, but no obvious <CurrentState> which can cause confusion on what the current anim's state actually is. This gives us two options of how to think about the situation: either consider <FromState> as usually being the <CurrentState>, or states exist only ''between'' anims and serve as ''transition rules''.


'''Step 2:''' Select "XML" as ("To") output format.
Linking to a follow-up state allows for multiple choices of what specific anim comes next. An anim is picked up randomly from a pool of valid anims. Their probability or <Weight> is determined by the anim listing in the TRAC – the anim collection (see "Weights" section for an explanation of exactly how <Weight> is handled).


'''Step 3:''' Check "Another TRAM" to chose a character animation file.
Anyway, to let an character flow from one anim state to another, the <ToState> is used. Let's say an SBG grenade hits Konoko. The particle's '''damage type''' is '''blownup'''; this and the direction of the incoming damage force an anim of type '''Blownup''' or '''BlownupBehind''' to play, such as TRAMKONOKOblownup1.


'''Step 4:''' Click on "Add" button to chose an ONCC file.
Thus, Konoko falls to her back, going into the FallenBack state. The engine picks up the next anim which has <FromState>FallenBack. Also, receiving damage puts a character into combat mode, so further anims will be of variant Combat. But if the player gives no input, Konoko will remain on the ground, as <ToState>FallenBack creates a loop.


'''Step 5:''' Click on "Convert".
So here's a question: why isn't a getup anim like KONCOMgetup_lt played automatically since it also has <FromState>FallenBack and <Varient>Combat? Answer: it differs in its <Type>. Most [[XML_talk:StNA|anim types are bound to user input]] and therefore are excluded from the automatically created pool of valid anims which can follow.


Now let's consider what happens upon user input. A leftward movement of the mouse tells the engine to use an anim of type StandingTurnLeft. There are two anims with that type, KONOKOcomb_turnlt and KONCOMgetup_lt, but only the latter matches the current <FromState> condition.
: In fact, KONOKOcomb_turnlt has <Varient> Combat – the "comb" here stands for "combat", not "combo". Following Oni's naming convention, the file ''should'' have been named KONCOMturn_lt.


====Via Simple OniSplit GUI====
Knowing this behavior, we can deduce that anim types registered to user input will make the engine ignore all the automatic anims inside the pool, therefore breaking the loop of KONCOMfallen_back. And since KONCOMgetup_lt has <ToState>Standing and Konoko is still in combat mode, the following idle anim must also have <Varient>Combat. So the next anim played will be KON'''COM'''idle1 or KON'''COM'''idle2.
There was a long standing problem with ONCC-TRAM-combined files whereby the textures will be missing.<br>With an older method you couldn't export non-native TRAM which meant to the TRAM had to be registered in the TRAC the ONCC is using.


'''[http://www.paradox.oni2.net/programs/Simple_OniSplit_GUI.zip Simple OniSplit GUI]''' post-edits the dae to fix the missing textures. The character related oni files must be all in one folder. Usually level0_Final folder does the trick.
Konoko will eventually calm down when her ONCC <FightModeTimer> runs down, and then KON'''OKO'''idle1 or KON'''OKO'''idle2 will be played instead. (Actually, the COMidle will continue until a non-combat anim such as running breaks that loop. You won't ever see Konoko drop from combat readiness to her regular idle animation. Instead she will go from combat idle to running, to stopping, then standing at ease.)


Note the fallback behavior of anim lookup: if the engine cannot find an anim for the active variant (or "mode") of the character, it will choose the normal (non-variant-matching) version. Anims can be in the following variants: Combat, LeftPistol, LeftRifle, Panic, RightPistol, RightRifle and Sprint.


'''Step 1:''' Drag and drop TRAM and ONCC into the [http://www.paradox.oni2.net/images/simpleOniSplitGui.png big field.] (One by one. Or simultaneously. The order doesn't matter.)
As for combinations of variants, it's possible, yes, but rarely and only Sprint and one weapon variant at a time.


'''Step 2:''' Hit Convert.
==Weights==
Let's say that we're playing as a Ninja, we are in the state Standing, and we hit the action key to perform a taunt. The engine recognizes the context (no console to interact with), places the character in combat mode, and looks up anims of type Taunt. Since we are in combat mode, the next anim must be of variant Combat if possible. These lookups boil down to two valid possible anims: NINCOMtaunt1 (a spin) and NINCOMtaunt2 (the [[wp:Moonwalk (dance)|moon walk]] Easter egg). The engine picks one of them randomly.


However, NINCOMtaunt1 has a TRAC Weight (probability) of 100 while NINCOMtaunt2 has a TRAC Weight value of just 5. So the chances are quite high that we will not see the moon walk taunt.


===Editing the actual animation===
            <TRACAnimation>
You can load the dae file into an compatible editor. So far the community's favorite is Mod Tool.
                <Weight>100</Weight>
* For correct Mod Tool settings look [[Mod Tool#Animating|HERE]]
                <Animation>TRAMNINCOMtaunt1</Animation>
* Tutorial: <font style="color:#777777">basics of Oni animation editing</font> (todo)
            </TRACAnimation>
<!--* Tutorial: working with rigged models-->
            <TRACAnimation>
                <Weight>5</Weight>
                <Animation>TRAMNINCOMtaunt2</Animation>
            </TRACAnimation>


If there is only one anim to choose from, it will always play no matter what its Weight, even if it is zero. When it comes to multiple anims being a valid choice, the calculation is: weight of anim / sum of all valid anim weights. For NINCOMtaunt2, this means 5 / 105 = 0.047, or a 4.7% chance of a moon walk.


===Import===
==Idle timer==
====Revisited animations====
There's a semi-famous Easter egg where [https://www.youtube.com/watch?v=qbo2Q-VD6dc Konoko will sneeze] if she stands still for a long time. The timer for this is so long that most players never see it unless they step away from the game and leave it running without hitting F1. You might think that the way the sneeze is triggered is to set a low weight for it so that it's very unlikely a repeating idle cycle will choose the anim. But here's the sneeze anim in the TRAC with a Weight of 100:
http://oni.bungie.org/forum/viewtopic.php?id=1433


<s>Condensed knowledge coming soon.</s>
            <TRACAnimation>
                <Weight>100</Weight>
                <Animation>TRAMKONOKOidle_spec3</Animation>
            </TRACAnimation>


What's going on here? All regular idle anims are in fact of '''type Stand''', while Konoko's idle_spec3 anim above is of '''type Idle'''. Anims of '''type Idle''' are played every time the idle animation timer expires.  This is found in ONCC as <IdleAnimation1Timer> and <IdleAnimation2Timer>. These timers are set to 30,000 for every character. The number is in ticks, so if we convert to minutes – 30,000 / 60 / 60 = 8.3̅ – we find that the secret idle anim for Konoko (or any character) will play every 8⅓ minutes.


====Total new animations====
==List of tags, types, and flags==
<s>Coming soon.</s>
Use the search function in your browser to quickly find a tag.
 
 
 
===File structure===
 
TRAM
  |
  +-- header: animation type, state, flags, particle, sounds, etc.
  +-- actual animation: heights, velocities, rotations
  +-- additional data: positions, throw adjustments, selfdamage, attack parts, extents
 
 
===List of tags, types, and flags===
Use the search function of your web browser to quickly find a tag.
 
(work in progress)


{| class="wikitable" width=100%
{| class="wikitable" width=100%
Line 102: Line 106:
| <Type>
| <Type>
| flag
| flag
| Look them up over [[XML:StNA#animation_types|HERE]].
| Look them up over [[XML:StNA#Animation_types|HERE]]. The pool of valid TRAMs (animations a character can choose from) is built from the TRAC files registered in the ONCC. Most of the anim types are connected to player inputs.
|-
|-
| <AimingType>
| <AimingType>
| flag
| flag
| Look them up over [[XML:StNA#animation_types|HERE]].
| Look them up over [[XML:StNA#Animation_types|HERE]]. The pool of valid TRAMs, and therefore TRASs (aiming screens a character can choose from) is built from the TRSC files registered in the ONCC.
:
|-
|-
|valign="top"| <FromState>
|valign="top"| <FromState>
|valign="top"| flag
|valign="top"| flag
| Look them up over [[XML:StNA#animation_states|HERE]].
| [[Image:chr_debug_characters_shows_interpolated_animations.jpg|thumb|400px|right|Primary <FromState> in <Lookup> uses about 8 interpolating frames by default. Use Shortcut's <FromState> to override this frame number.]]
: Somtimes FromState is set to None; in another scenarios one FromState possibility is not enough.
 
:: In those cases Shortcuts are used. They extent the number from what state the animation can be played and under what conditions (replace atomic yes/no).
Look them up over [[XML:StNA#Animation_states|HERE]].
: When FromState is set to None, some default behaviors are ignored and are replaced by Shortcuts.
: Shortcuts extend the number of states from which an animation can be played and under what conditions (replacing this atomic yes/no).
|-
|-
| <ToState>
| <ToState>
| flag
| flag
| Look them up over [[XML:StNA#animation_states|HERE]].
| Look them up over [[XML:StNA#Animation_states|HERE]].
|-
|-
|valign="top"| <Varient>
|valign="top"| <Varient>
|valign="top"| flag
|valign="top"| flag
| "<Varient />" if unused. E.g. that's the case for non-combat animations.
|(misspelled because Oni misspells it) If unused, the tag will simply be "<Varient />", such as for non-combat animations. Otherwise it contains one of these values:
: Combat
: Combat
: LeftPistol
: LeftPistol
Line 131: Line 138:
| <FirstLevel>
| <FirstLevel>
| int16
| int16
|
|Number of first level in which move becomes available to the player ("0" to make it available from the start).
|-
|-
| <Shortcuts>
|valign="top"| <Shortcuts>
| parent tag
|valign="top"| parent tag
|
|
Works as an '''alternative FromState''' collection.
Shortcuts are accepted if their <Shortcut><FromState> value differs from the "primary" <Lookup><FromState> value. In other words, if you want to make a '''Shortcut''' that uses the '''same FromState''' value then you have to set '''primary FromState''' value to '''None'''. By doing that, the hardcoded interpolation frame length of about 8 frames can be overridden.
In the following example, the new interpolation length is 0. This will require the animation to match perfectly with the previous one. For a smooth transition to the next animation, set a suitable value at <Interpolation><End>.
        <Lookup>
            ...
            <FromState>None</FromState>
            ...
            <Shortcuts>
                <Shortcut>
                    <FromState>Standing</FromState>
                    <Length>0</Length>
                    <ReplaceAtomic>no</ReplaceAtomic>
                </Shortcut>
            </Shortcuts>
[[Image:TRAM interpolation - standard case.jpg|thumb|400px|left|Scenario A: hardcoded interpolation of 8 frames. Scenario B: changeable interpolation frame number.]]
|-
|-
| <Shortcut>
| <Shortcut>
Line 143: Line 169:
| <FromState>
| <FromState>
| flag
| flag
| Look them up over [[XML:StNA#animation_types|HERE]].
| Look them up over [[XML:StNA#Animation_types|HERE]].
|-
|-
| <Length>
|valign="top"| <Length>
| int16
|valign="top"| int16
|
|Amount of interpolating frames. While interpolations of rotation are less noticeable, interpolations of different positions can cause drift (i.e. sliding).
 
This is especially observed for transitions from idle to movements and vice versa — basically any combination of animations with different accelerations at start and end. By default, animations without specified Shortcut interpolation give about 8 frames of interpolation. For moves starting or ending in idle, it's better not to use interpolation. Just give the start and end frames the same positions and rotation values as the idle. Interpolations should always be considered a ''last resort''.
 
This drift can be observed even in vanilla animations — most prominently in Konoko's comb_k. Konoko's left foot should be in a fixed position as the animation starts from from Konoko's idle pose. However, the interpolation is causing her left foot to drift noticeably to the right and a bit forward.
 
The reason this happens is because the interpolation "mixes" two animations. When one animation transitions into another via interpolation, part of the animation system continues playing the initial animation, and part of it is playing the follow-up animation, with all the rotations and positions getting linearly interpolated.
|-
|-
|valign="top"| <ReplaceAtomic>
|valign="top"| <ReplaceAtomic>
Line 157: Line 189:
|valign="top"| <Flags>
|valign="top"| <Flags>
|valign="top"| flag
|valign="top"| flag
|
|These are top-level flags on the whole animation. See the other <Flags> for flags on an attack part.
:RuntimeLoaded
:RuntimeLoaded
:::(this bit is not animation related, it is used at runtime to mark that the animation was loaded)
::(This bit is not stored on disk; it is used at runtime to mark that the animation was loaded.)
:Invulnerable
:Invulnerable
:::while playing this animation user is invulnerable to melee damage AND cannot be thrown, PAR3/height still hurts him
::While playing this animation, the player is invulnerable to melee damage and also cannot be thrown, but can still take damage from particles and falls.
:BlockHigh
:BlockHigh
:::if set then while playing this animation user can block high or undefined attacks within some arc which is '''before''' him, so if you set this to some animation where user spins, then he can still be legaly kicked to the @$$ and he can be thrown
::While playing this animation, the player can block high or undefined-height attacks within some arc in front of him. The height of an attack is found under the <Attack> section. If you set this flag on an animation where the player character is spinning, then the character can still be kicked in the back or thrown.
:BlockLow
:BlockLow
:::same as before only it can block low or undefined attacks
::Same as above, only it can block low or undefined-height attacks.
:Attack
:Attack
:::animations with attack part have it, unknown what it does, IMO it turns on soft lock (characters turns with animation a bit in order to hit nearby enemy), but didn't checked
::Unused by the engine.
:DropWeapon
:DropWeapon
:::if user is armed, he drops weapon when he plays this animation
::If the player is armed, he drops his weapon when this animation plays.
:InAir
:InAir
:::something with jumps, didn't checked
::Unused by the engine.
:Atomic
:Atomic
:::whole animation must be played, user cannot interrupt it once it starts
::Unused by the engine. Only the Start and End frames of the Atomic field below matter.
:NoTurn
:NoTurn
:::cannot turn by mouse while performing this animation  
:::Player cannot turn while performing this animation.
:AttackForward
:AttackForward
:::unknown, looks like this is rough info for AI2 about where attack aims from user's point of view -[[User:Loser|Loser]]
::Unused by the engine.
:AttackLeft
:AttackLeft
:::same as above
::Same as above.
:AttackRight
:AttackRight
:::same as above
::Same as above.
:AttackBackward
:AttackBackward
::Same as above.
:Overlay
:Overlay
:::these are not standalone animations, they just overwrite part of already playing one, for example holstering weapon is such an animation
::Not a standalone animation; it just overwrites part of an already-playing one, e.g. the weapon-holstering animation.
:DontInterpolateVelocity
:DontInterpolateVelocity
:::unknown, but maybe it has something to do with X,Y,Z velocities and fact that for example directional jumps take info about direction vector from X-Z velocity part of TRAM (Y vector is in ONCC)
::Unknown, but maybe it has something to do with {x,y,z} velocities and the fact that directional jumps, for example, take information about their direction vector from the {x,z} velocity part of the TRAM (the vertical Y component is in the ONCC).
:ThrowSource
:ThrowSource
:::unknown, throws use it
::Oni expects this flag on all throw source animations.
:::Throws work in animation pairs: whenever a throw source is played, the other character must perform the throw target animation. See throw(n) types:
::::TRAM <TargetType> from [[XML:StNA#Animation types|StNA]] (first <u>used</u> throw starts at #96).
:::Characters have only their own pool of animations available. And since enemy's TRAC might not contain the necessary animation the information must be provided by the throw source TRAC.
::: Since every throw animation must have a throw animation type the ThrowSource flag is actually redundant.
:ThrowTarget
:ThrowTarget
:::if set, then animation can hurt anybody, with its attack part, including teammates. User of TRAM can even hurt himself with "damage part" (user cannot hurt himself with own attack parts). It also allows two (try more, get crash ^_^) attack parts to be executed instead of only one (maybe bug?).
::Animation can hurt anybody with its attack part, including teammates. The player can even hurt himself with the TRAM's damage part (whereas a player cannot hurt himself with his own animation's attack part). It also allows two attack parts to be executed instead of only one (maybe a bug? more than two will result in a crash).
::::-If you set first attack part to be able to deal damage from 1st to 100th frame of TRAM, and second attack part to deal damage within that limit (e.g. from 25th to 41st frame, it can be again from 1 to 100), than first attack part an hurt from 1st to 100th (as usual), but even if it hits, that second one attack part (25th to 41st) can hurt enemy as well during "its lifetime". So two attack parts are allowed to execute. Note that second attack part MUST be executed while first attack part has active "window", otherwise it won't work.
:::If you set the first attack part to be able to deal damage from the 1st to the 100th frame of the TRAM, and the second attack part to deal damage within that range (e.g. from the 25th to the 41st frame), then the first attack part will deal damage from the 1st to the 100th frame (as usual), but even if it hits, that second attack part can hurt the enemy as well during frames 25–41. Note that the second attack part must be executed within the first attack part's active "window", otherwise it won't work.
:RealWorld
:RealWorld
:::It appears this flag was used to create TRAM and OBAN from one animation source. The OBAN is supposed to store pelvis rotations and positions because that way a character can move over obstacles/gaps. The very most of them are used in cutscenes.
::Unused by the engine. It appears this flag was used during the authoring process to create a TRAM and an OBAN from one animation source. The OBAN is supposed to store pelvis rotations and positions, allowing a character to move over obstacles/gaps. The vast majority of TRAMs with this flag are used in cutscenes.
:DoAim
:DoAim
:::forces aim animation (PIS/RIF) if user has weapon
::Applies the aiming animation overlay (PIS/RIF) if the player has a weapon.
:::(used PIS/RIF animation and prone)
:DontAim
:DontAim
:::forces not to aim
::An aiming overlay will not be applied.
:CanPickup
:CanPickup
:::can pickup items in this animations, not like it plays pickup one, but like it "takes" the item if you have this animation on and you collide with item.
::Player can pick up an item during this animation if he intersects with one during his movement.
:Aim360
:Aim360
:::unknown
::Unused by the engine.
:DisableShield
:DisableShield
:::if user had active supershield (chr_super "name" 1), this forces him to disable it (chr_super "name" 0) -[[User:Loser|Loser]]
::If the player has an active [[supershield]], this disables it (the flag is placed on four Mutant Muro attacks: his two supers, the claw-stuck-into-ground move and the sliding "[[wikt:kancho|kancho]]" maneuver; it is also hardcoded to be removed when the Zeus Thunderbolt attack is used).
:NoAIPickup
:NoAIPickup
:::AI2 are not permitted to pick up items with this animations
::AIs are not permitted to pick up items with this animation.
|-
|-
| <Atomic>
| <Atomic>
| parent tag
| parent tag
|
| Animation cannot be interrupted by player between the Start and End frames.
|-
|-
| <Start>
| <Start>
Line 222: Line 258:
| <Invulnerable>
| <Invulnerable>
| parent tag
| parent tag
|
| Character will not take melee damage and cannot be thrown between the Start and End frames.
|-
|-
| <Start>
| <Start>
| int16
| int16
|
| First frame of character being invulnerable.
|-
|-
| <End>
| <End>
| int16
| int16
|
| Last frame of character being invulnerable.
|-
|-
| <Overlay>
| <Overlay>
Line 238: Line 274:
|valign="top"| <UsedBones>
|valign="top"| <UsedBones>
|valign="top"| flag
|valign="top"| flag
| "<UsedBones />" if unsued.
|Simply contains "<UsedBones />" if no bones are involved, otherwise:
:Pelvis
:Pelvis
:LeftThigh
:LeftThigh
Line 260: Line 296:
|valign="top"| <ReplacedBones>
|valign="top"| <ReplacedBones>
|valign="top"| flag
|valign="top"| flag
| "<ReplacedBones />" if unused.
| "<ReplacedBones />" if unused, otherwise:
:Pelvis
:Pelvis
:LeftThigh
:LeftThigh
Line 281: Line 317:
|-
|-
| <DirectAnimations>
| <DirectAnimations>
|
| parent tag
|
|
|-
|-
Line 293: Line 329:
|-
|-
| <Pause>
| <Pause>
|
| parent tag
|  
|  
|-
|-
| <Hard>
| <Hard>
| int16
| int16
|  
| In ticks. The Hard and Soft pause values are ignored if this animation has a direct link (above) to another animation.
|-
|-
| <Soft>
|valign="top"| <Soft>
| int16
|valign="top"| int16
|
| In ticks. As mentioned above, the player cannot enter new inputs during this pause unless this animation is part of a combo animation defined by <DirectAnimations><Link>.
: Examples:
: COMcomb_p, (no pause) COMcomb_p_p
: COMcomb_p, (pause) COMcomb_k
 
The difference between the hard and soft pause is that you can block during the soft pause and not the hard pause.
|-
|-
| <Interpolation>
| <Interpolation>
|
| parent tag
|
|
|-
|-
| <End>
|valign="top"| <End>
| int16
|valign="top"| int16
|
|
* interpolates first X frames of next animation
* if the first follow-up animation is too short, it can continue to play even further (not observed with vanilla anims)
While interpolations with rotations are less noticeable, interpolations of different positions can cause an additional drift.
This was especially observed for transitions of idle to movements and vice versa — basically any combination of animations with different accelerations at the start and end. By default, animations without a specified Shortcut interpolation get about 8 frames of interpolation. For moves starting or ending in idle, it's better not to use interpolation. Just give the start and end frames the same positions and rotation values as the idle. Interpolations should always be considered a ''last resort''.
[[Image:TRAM interpolations - end interpolation bigger than next anim.jpg|thumb|400px|left|"End" interpolation covering multiple follow-up animations.]]
|-
|-
| <Max>
| <Max>
| int16
| int16
|
| unused
|-
|-
| <FinalRotation>
|valign="top"| <FinalRotation>
| float
|valign="top"| float
| final rotation in degrees
|valign="top"| Ending rotation in degrees. (During an animation on the player character, the camera is detached rotation-wise. If this value matches the body's final rotation, it will prevent a "glitchy" re-attaching.)
|-
|-
|valign="top"| <Direction>
|valign="top"| <Direction>
|valign="top"|
|valign="top"|
|
| Used by [[AI#Melee combat behaviors|AI melee system]].
:None
:None
:Forward
:Forward
Line 330: Line 379:
|-
|-
| <Vocalization>
| <Vocalization>
|
| int
|
| ID of one of the [[XML:SNDD#Step 1: Preparing the TRAM|SoundConstants in ONCC]]
|-
|-
| <ActionFrame>
| <ActionFrame>
|
| int
|
| Frame number for any special events associated with this animation: weapon theft via disarm, weapon holstering, Mukade teleporting, items getting handed over to player, etc.
|-
|-
| <Impact>
| <Impact>
| link
| link
| "<Impact />" if unsued.
| "<Impact />" if unused.
|-
|-
| <Particles>
|valign="top"| <Particles>
| parent tag
|valign="top"| parent tag
|
| serves as group element
|-
|-
| <Particle>
|valign="top"| <Particle>
| parent tag
|valign="top"| parent tag
|
| holds individual particle data
|-
|-
| <Start>
|valign="top"| <Start>
|
|valign="top"| int
|
| frame number for particle to start
|-
|-
| <End>
|valign="top"| <End>
|
|valign="top"| int
|
| frame number for particle to end (if the number exceeds frame count of animation, the particle will simply die at the end of the animation)
|-
|-
| <Bone>
|valign="top"| <Bone>
| flag
|valign="top"| flag
|
|
: Pelvis
: LeftThigh
: LeftCalf
: LeftFoot
: RightThigh
: RightCalf
: RightFoot
: Mid
: Chest
: Neck
: Head
: LeftShoulder
: LeftArm
: LeftWrist
: LeftFist
: RightShoulder
: RightArm
: RightFist
|-
|-
| <Name>
|valign="top"| <Name>
| link
|valign="top"| link
|
| particle name in [[XML:ONCC#ONCP:_Oni_Character_Particle_.28Array.29|ONCC-ONCP]]
|-
|-
| <MotionBlur>
| <MotionBlur>
| parent tag
| parent tag
|
|  
|-
|-
| <MotionBlur>
| <MotionBlur>
Line 397: Line 464:
| <Start>
| <Start>
| int16
| int16
|
| Start frame of motion blur sequence
|-
|-
| <End>
| <End>
| int16
| int16
|
| End frame of motion blur sequence
|-
|-
| <Lifetime>
| <Lifetime>
| int8
| int8
|
| Lifetime of each "ghost" in frames.
|-
|-
| <Alpha>
| <Alpha>
| int8
| int8
|
| Transparency of "ghosts".
|-
|-
| <Interval>
| <Interval>
| int8
| int8
|
| Frame interval between each rendered "ghost".
|-
|-
| <Footsteps>
| <Footsteps>
Line 443: Line 510:
| <Name>
| <Name>
| char[32]
| char[32]
| <font color="#777777">OSBD</font>file<font color="#777777">.imp.oni</font> <font color="#777777">(don't use file prefix/suffix)</font>
| <font color="#777777">OSBD</font>file<font color="#777777">.imp.oni</font> <font color="#777777">(don't use resource type's prefix or suffix)</font>
|-
|-
| <Start>
| <Start>
| int16
| int16
| the frame when the sound starts to play
|The frame when the sound starts to play.
|-
|-
| <Heights>
| <Heights>
|
| parent tag
|
|
|-
|-
| <Height>
| <Height>
| float
| float
| absolute position
|Absolute position.
|-
|-
| <Velocities>
| <Velocities>
Line 463: Line 530:
| <Velocity>
| <Velocity>
| 2 x float
| 2 x float
| relative positions
|Relative positions (delta values); the numbers represent the change in position from one frame to another.
|-
|-
| <Rotations>
| <Rotations>
Line 471: Line 538:
| <Bone>
| <Bone>
| parent tag
| parent tag
| There are 19 bone tags. One for each [[TRIA#Bones|body part]].
|There are 19 bone tags, one for each [[TRIA#Bones|body part]].
|-
|-
| <EKey>
| <EKey>
| int8 + 3 * float
| int8 + 3 * float
| for normal animations
|For normal animations. The first value is the number of frames for which the rotation is maintained; the sum of all of these first EKey components always equals the total number of frames for the animation.
|-
|-
|valign="top"| <QKey>
|valign="top"| <QKey>
|valign="top"| int8 + 4 * float
|valign="top"| int8 + 4 * float
| for overlay animations used by [[TRAS|TRAS]]
|For overlay animations used by [[TRAS|TRAS]] aiming screens.


onisplit v0.9.54.0 produces <QKeys> (quaternions) instead of (euler rotations) <EKey> for normal animations
OniSplit v0.9.54.0 produces <QKey>s (quaternions) instead of <EKey>s (Euler rotations) for normal animations.
|-
|-
| <PositionOffset>
| <PositionOffset>
| parent tag
| parent tag
| <PositionOffset> and <Positions> belong together. In the [[OBD:TRAM/raw0x30|binaries]] they are written in the place.
| <PositionOffset> and <Positions> belong together. In the [[OBD:TRAM/raw0x30|binaries]], they are written in place. '''Seems unused; changing them has no effect in-game.'''
|-
|-
| <X>
| <X>
Line 500: Line 567:
|-
|-
| <Position>
| <Position>
| parent tag
| float
|
| seems to be unused (and when checking this with "chr_debug_sphere = 1", the spheres remain unchanged)
|-
|-
| <Height>
| <Height>
Line 509: Line 576:
| <YOffset>
| <YOffset>
| float
| float
| y offset of the vertical extent from character location  
| Y offset of the vertical extent from character location  
|-
|-
| <ThrowSource>
| <ThrowSource>
Line 517: Line 584:
| <TargetAdjustment>
| <TargetAdjustment>
| parent tag
| parent tag
|
| Used to position targets during throws, relative to the position of the character executing the throw.
|-
|-
| <Position>
|valign="top"| <Position>
| 3 * float
|valign="top"| 3 * float
|
| Contains XYZ values, which position the target character at the start of the animation:
*X - Side axis. Negative values move the target to the right and positive values move the target to the left.
*Y - Height axis. Negative values move the target downwards, but cannot make the target go below the floor. Positive values make the target go upwards; this will lift the target's collision sphere off the ground as if they jumped. However if the value is too big, the target will teleport upward and then immediately start falling, interrupting the target animation.
*Z - Forward axis. Negative values move the target backwards and positive values move the target forward.
|-
|-
| <Angle>
| <Angle>
| float
| float
|
| In radians - adjusts the rotation of the target in Oni's Y axis; most of the time (if not always) it's set to ''3.14159274'' radians in vanilla anims, equaling 180 degrees - which effectively rotates the rotates by those 180 degrees; if it was set to 0, the target would face the throw source character with his back.
|-
|-
| <Distance>
| <Distance>
| float
| float
|
| Activation distance. The throw can be triggered if it is within this range. However the value must be greater than the equivalent TRAM in the parent TRAC or else the equivalent TRAM will play when the throw takes place outside of this TRAM's range and within that TRAM's range.
|-
|-
|valign="top"| <TargetType>
|valign="top"| <TargetType>
|valign="top"| flag
|valign="top"| flag
| The flags are part of the [[XML:StNA#animation_types|animation type list]].
| The flags are part of the [[XML:StNA#Animation_types|animation type list]].


(static throws)
(static throws)
Line 541: Line 611:
: Thrown4 = ###COMthrow_bk_k_tgt
: Thrown4 = ###COMthrow_bk_k_tgt
(running throws)
(running throws)
: Thrown4 = ###COMrun_throw_fw_p_tgt
: Thrown5 = ###COMrun_throw_fw_p_tgt
: Thrown6 = ###COMrun_throw_fw_p_tgt
: Thrown6 = ###COMrun_throw_fw_p_tgt
: Thrown7 = ###COMrun_throw_bk_k_tgt
: Thrown7 = ###COMrun_throw_bk_k_tgt
Line 559: Line 629:
----
----
About the naming:
About the naming:
: "fw" = face to face throw
: "fw" = face-to-face throw
: "bk" = thrower is facing victim's back
: "bk" = thrower is facing victim's back
: "throw" inside TRAM names are sometimes shortened with "thr"
: "throw" inside TRAM names is sometimes shortened to "thr"
: "p" can also be missing
: "p"/"k" = triggered by punch or kick button ("p" is sometimes omitted)
|-
|-
| <SelfDamage>
| <SelfDamage>
| parent tag
| parent tag
| "<SelfDamage />" if unused.
|"<SelfDamage />" if unused.
 
Works only with specific, hardcoded AnimTypes (mainly ThrownX, it's unknown if any other types work - that remains to be investigated). Using SelfDamage on an AnimType that wasn't intended for it will cause the game to crash. (ToDo: Checked if <Flag>ThrowTarget is enough to explain this. Modify a simple kick? For more please link to and use talk page.)
 
From a practical standpoint, this means SelfDamage can be used only on ThrowTarget animations.
|-
|-
| <Damage>
| <Damage>
Line 574: Line 648:
| <Points>
| <Points>
| int16
| int16
| damage taken by character
| Damage taken by character.
|-
|-
| <Frame>
| <Frame>
| int16
| int16
| frame of the animation, when damage is dealt
| Frame of the animation when damage is dealt.
|-
|-
| <Attacks>
| <Attacks>
Line 586: Line 660:
|valign="top"| <Attack>
|valign="top"| <Attack>
|valign="top"| parent tag
|valign="top"| parent tag
| Only 2 attack parts per file are allowed. Normally the target gets only one hit. But if the attack frames of both attack parts are overlapping then the target can be [http://oni.bungie.org/community/forum/viewtopic.php?pid=39787#p39787 hit by both of them].
| Only 2 attack parts per file are allowed. Normally the target gets only one hit. But if the attack frame ranges of both attack parts are overlapping, then the target can be [http://oni.bungie.org/forum/viewtopic.php?pid=39787#p39787 hit by both of them].
|-
|-
| <Start>
| <Start>
| int16
| int16
| First frame where damage can be inflicted to an opponent.
| First frame where damage can be inflicted on an opponent.
|-
|-
| <End>
| <End>
| int16
| int16
| Last frame where damage can be inflicted to an opponent.
| Last frame where damage can be inflicted on an opponent.
|-
|-
| <Bones>
| <Bones>
| flag
| flag
| Set here the bones that can inflict damage.
| The bones which can inflict damage.
|-
|-
|valign="top"| <Flags>
|valign="top"| <Flags>
|valign="top"| flag
|valign="top"| flag
|
|These are flags on an attack part, inside an <Attacks><Attack> element. See the previous <Flags> for general flags on the TRAM.
: Unblockable
: Unblockable
: Low - blocker needs to crouch
: Low - Target of attack needs to crouch in order to block this attack.
: High - blocker needs to stand; if Low and High are set then blocker can block from stand and crouch
: High - Blocker needs to stand; if both Low and High are set, blocker can block from both standing and crouching positions.
: HalfDamage - the blocker gets half of the damage
: HalfDamage - Blocker still receives half of the normal damage.
|-
|-
| <Knockback>
| <Knockback>
| float
| float
| Target gets knockbacked by this amount.
| Target gets knocked back by this amount if attack is successful.
|-
|-
| <HitPoints>
| <HitPoints>
| int16
| int16
| damage points
| Damage points inflicted by attack.
|-
|-
| <HitType>
| <HitType>
| flag
| flag
| Animation type for opponent's animation when attack isn't blocked.
| Animation type for opponent's animation when the attack isn't blocked. The flags are part of the [[XML:StNA#Animation types|animation type list]].
|-
|-
| <HitLength>
| <HitLength>
| int16
| int16
| Number of frames for how long should blocking char remain in hit anim when he gots hit.
| Number of frames that the target should remain in his hit animation state when he gets hit. If ≥ 20, Oni automatically upgrades the character to a stagger animation.
|-
|-
| <StunLength>
| <StunLength>
| int16
| int16
| Number in frames for how long should blocking char remain in blocking animation.
| Number of frames that the target should remain in his blocking animation state when he blocks the attack. If ≥ 15, Oni automatically upgrades the character to a block stun.
|-
|-
| <StaggerLength>
| <StaggerLength>
| int16
| int16
| Number of frames for how long should blocking char perform stagger anim after sucessful block.
| Number of frames that the target should perform his stagger animation after a successful block.
|-
|-
| <Extents>
| <Extents>
| parent tag
| parent tag
| Gets calculated by onisplit if there's a dae file referenced in xml.
| Explained below. Automatically calculated by OniSplit if there's a DAE file referenced in the XML.
|-
|-
| <Extent>
| <Extent>
| parent tag
| parent tag
| One tag per frame. In numbers: attack end - attack start + 1. (E.g. start=5; end=6; it makes 2 involved frames.)
| One tag per attack frame. Number of <Extent> tags = <Attack><End> - <Attack><Start> + 1.
|-
|-
| <Angle>
| <Angle>
| float
| float
| In degree.
| In degrees.
|-
|-
| <Length>
| <Length>
Line 658: Line 732:
|valign="top"| <AttackRing>
|valign="top"| <AttackRing>
|valign="top"|  parent tag
|valign="top"|  parent tag
| Contains always 36 <Length> tags, no more, no less. Gets calculated by onisplit if there's a dae file referenced in xml. (The AttackRing was formerly know as horizontal extents.)
| Always contains 36 <Length> tags, explained below. Automatically calculated by OniSplit if there's a DAE file referenced in the XML. (AttackRing was formerly known as "horizontal extents" in older versions of OniSplit.)
|-
|-
|valign="top"| <Length>
|valign="top"| <Length>
|valign="top"| float
|valign="top"| float
| Horizontal extents in 10° intervals. They make a ''zone of danger'' so the AI knows that the animation is harmful there. (It give them the chance to dogde an attack.)
| Horizontal extents, explained below. They create a "danger zone" around the attacker which the AI uses to try to dodge an attack.
|}
|}


==Export==
TRAM files can be extracted '''A) as pure XML''' files or '''B) as a pair of XML and DAE''' files. For editing the actual animation, you will want to use method B. While exporting an ONCC, you might see errors such as:


Cannot find instance 'TRAMKONCOMthrow_rev'
Cannot find instance 'TRAMKONCOMthrow_rev'
Cannot find instance 'TRAMKONRIFturn_right'
Cannot find instance 'TRAMKONOKOlev18_ZomStand'
Cannot find instance 'TRAMKONOKOcorner_hide'
Cannot find instance 'TRAMKONPIScorner_hide'
Ignore them, as those files doesn't exist. (Someday we should remove them from the TRACs.)
===Via command line===
To export a single TRAM:
onisplit -extract:xml output_path -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname.oni
To export merged TRAMs:
onisplit -extract:xml output_path '''-anim-merge''' -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname1.oni  path_to\TRAMnameN.oni
===Via Vago===
[[Image:Vago_xml_plus_dae_extraction.png|thumb|200px|right|Combined extraction of DAE and XML.]]
Change to Characters tab and follow these steps.
'''Step 1:''' Select "TRAM ONI" as input format ("From").


===Extents and XML===
'''Step 2:''' Select "XML / XML & DAE" as output format ("To").
Ever wondered how comes Artificial Intelligence can recognize incoming attack and block or dodge? Extents ( found out by Geyser and fully uncovered by Neo ) are the key.


There are two types of extents -
'''Step 3:''' Tick checkbox "Extract with TRBS / ONCC". It's important this is done before adding a TRAM file.
*'''<Extents>''', its packages store this info:
::<Angle> at which is this extent radiated from character. 0° is in front of character, 180° is in the back
::<Length> of this extent,
::<MinY> minimal height of this extent
::<MaxY> maximal height of this extent
:Length, MinY and MaxY serve for creating invisible area in space which is "dangerous to be in". If AI collides and notices it (refer to notice field in [[MELE]]), it will attempt to block or dodge according to its modifiers in given MELE profile. Again, see fields in [[MELE]].
::: Number of <Extent> is equal to attack frames: <End> minus <Start> plus one (because start frame counts too).
:::: (e.g. TRAMKONCOMkick_low1: <End>30</End> minus <Start>22</Start> plus one = nine <Extent>.)


:These extents are pretty impossible to guess, so leave them until Neo comes up with extent computation ( probably from attack bones and bonetrack rotations ).
'''Step 4:''' Set full path of ONCC or TRBS.
:;BUT
:Always add at least one package, because its Length, MinY and MaxY will be taken as the longest extent, the most maximal Y and the most minimal Y vales. Those are needed, otherwise character won't react to this attack.


*'''<HorizontalExtents>''', its packages store this info:
'''Step 5:''' Add TRAM file.
::36 fields (exactly 36, no more, no less, otherwise it won't compile back into .oni file), which correspond to areas in 10° intervals around character ( so overall 360°, full horizontal circle around character).


::Imagine character. Look at it from above. Make a circle with this character being center of this circle. Now divide this circle with lines after each 10°; and those are horizontal extent lines used by packages ^_^.
'''Step 6:''' Click "Convert".
::Once more 0° is in front of the character, 180° is behind character. Intervals go clockwise. So first package is horizontal extent for 0° line, second package is for horizontal line which is 10° clockwise and so on.


::These extents can be guessed up to some degree. Use common sense, look at Your custom attack and tip which lines are probably intersected by attacking limbs of Your move.
===Via Simple OniSplit GUI===
::Watch out - if attack is frontal ( direct kick forward ), you should worry not only about 0° (directly front), but also about 10°, 20° (a bit to the right) and also about 340°, 350° (a bit to the left).
There was a long-standing problem with combined ONCC/TRAM files where the textures would be missing.<!--[Iritscen: I don't understand this sentence; is it important to keep this historical note?][Paradox: Geyser still didn't release a new OniSplit containing that fix, right?] With an older method you couldn't export non-native TRAM which meant to the TRAM had to be registered in the TRAC the ONCC is using.-->
::Next guess the length (you will get used to the sense of distance soon), write it in, test it with some AI which blocks a lot. If you did it right, Your attack will be often blocked.
::Don't overdo it with horizontal extent length - too long will cause AIs to react too far from you, does not look pretty.


Have extended fun, --[[User:Loser|Loser]] 19:12, 13 July 2010 (UTC)
'''[http://www.paradox.oni2.net/programs/Simple_OniSplit_GUI.zip Simple OniSplit GUI]''' post-edits the DAE to fix missing textures. The character-related .oni files must be all in one folder. Usually the level0_Final folder does the trick.


'''Step 1:''' Drag and drop the TRAM and ONCC into the [http://www.paradox.oni2.net/images/simpleOniSplitGui.png big field.] (One by one or simultaneously; the order doesn't matter.)


'''Step 2:''' Hit "Convert".


===Adding colorful trails===
==Editing 3D data==
Open the xml formated TRAM and search for the "Particles" tag and insert your code.
===Blender===
See the [[Blender]] article for a general tutorial on using the free program to create animations for Oni. It also contains a Blender addon for automating certain tasks, troubleshooting advice, and links to an animation rig that makes animation much easier.


First example: TRAMSTRCOMcomb_p_p.xml
===XSI===
In the past, the community's preferred tool for any 3D modeling and animation was {{ModTool}}. However, this free program was discontinued in 2014, and modders did not want to be tied to an aging (not to mention Windows-only) program. Thus, we have generally moved to using Blender (see next section). The following information is preserved for historical purposes.
----
For the correct Mod Tool settings, see [[Mod Tool#Animating|HERE]].


[[Image:Colorful_contrail_added.png|right|thumb]]
Here are some hints for creating animations when there is no rigging available:
* Use the ONCC model in your 3D editor that will actually make use of the animations. This makes sure that the pelvis height will match and that the character's feet will not float in the air or go through the ground.
* The first frame and last frames should match the probable previous and follow-up animations. This will reduce the necessity for long interpolations.
* When setting keyframes, each body part should have moved. This rule of thumb will give a more natural-looking animation.
* The first body part to be animated is always the pelvis.
* Watch out for pelvis rotations so that the XYZ rotations don't overlap too much, otherwise you will get into a [[wp:Gimbal_lock|gimbal lock]].


        <Particles>
Also see our [http://oni.bungie.org/forum/viewtopic.php?id=1433 OCF thread].
            <Particle>
                <StartFrame>0</StartFrame>
                <EndFrame>12</EndFrame>
                <Bone>LeftFist</Bone>
                <Name>contrail</Name>
            </Particle>
        </Particles>


"contrail" is looked up by the used character class (ONCC) which lunch the actual particle, here it is "h2h_strtrail_e01".
==Import==
onisplit -create output_path path_to\TRAMname.xml


==Common operations on animations by the community==
===Speeding up existing animations===
s10k has created an XmlTools script that allows the speed-up of any existing TRAM by removing frames. More information and download link [http://mods.oni2.net/node/354 here.]


Second example is about two different contrails in one TRAM at same time. The animation is "TRAMSTRCOMpunch_heavy.xml".
==Selected notes on animation types==
===Attacks===
====Extents and XML====
'''As a regular modder you don't need to know how the attack ring and the extents get calculated.''' If you just want to create an attack animation then add an appropriate <Attacks> code block to your XML as seen in the [[#Using OniSplit to calculate extents|section below]].


[[Image:Different_contrails_in_attack.png|right|thumb]]
'''How attack ring (horizontal extents) and extents get calculated'''


        <Particles>
Ever wondered how the AI can recognize incoming attacks and block or dodge them? Extents (found by geyser and fully uncovered by Neo) are the key. Imagine the character looked at from above, and visualize a circle with this character being at the center of the circle. Now divide this circle into 10° segments, and those are the 36 units of horizontal extents (that is, the lateral reach of the attack). The 0° point is directly in front of the character and 180° is behind the character. The segments run clockwise around the character. So the first Extent tag is the horizontal reach on the 0° line, the second tag is for the line 10° clockwise, and so on. Note that a frontal attack like a simple kick could hit a target not only if he's standing at 0° (directly in front), but also at 10° or 20° to the right, and also at 340° and 350° (a bit to the left). When setting these manually, you should guess the inner and outer ranges of the reach of the attacker's bones that have damage attached to them. Test these values with an AI that blocks often. If you did it right, your attack will often be blocked, but if the extent length is too high, the AIs will react when too far from you, which does not look good.
            <Particle>
                <Start>0</Start>
                <End>54</End>
                <Bone>RightWrist</Bone>
                <Name>contrail</Name>
            </Particle>
            <Particle>
                <Start>0</Start>
                <End>54</End>
                <Bone>LeftWrist</Bone>
                <Name>'''contrail_2'''</Name>
            </Particle>
        </Particles>


Note that you need to register the second contrail in the used ONCC as well. Using your own contrail particle is also possible, just insert it's name between the <Type> tags.
There are two types of extents:
*'''<Extents>''' stores this info:
::<Angle> at which this extent radiates from the character.
::<Length> of this extent.
::<MinY> minimum height of this extent.
::<MaxY> maximum height of this extent.
:Length, MinY and MaxY serve to create an invisible area in space which is "dangerous to be in". If an AI intersects with this area and notices it (refer to the Notice field in [[MELE]]), it will attempt to block or dodge according to its modifiers in its MELE profile.
::The number of <Extent>s is equal to the number of attack frames: <End> minus <Start> plus one (because the start frame counts too). For example, for TRAMKONCOMkick_low1: <End>30</End> minus <Start>22</Start> plus 1 = 9 <Extent>s.


            <ONCPParticle>
*'''<AttackRing> (formerly known as <HorizontalExtents>''' stores this info:
                <Name>contrail</Name>
::36 fields (exactly 36, otherwise it won't compile back into a .oni file), which correspond to areas in 10° intervals around the character as described above.
                <Type>h2h_strtrail_e01</Type>
                <BodyPart>-1</BodyPart>
            </ONCPParticle>
            <ONCPParticle>
                <Name>'''contrail_2'''</Name>
                <Type>'''h2h_murtrail_e01'''</Type>
                <BodyPart>-1</BodyPart>
            </ONCPParticle>


==Adding extents to an existing animation==
====Using OniSplit to calculate extents====
Let's say that you want to convert a non-attack animation to a damage-dealing animation. Non-attack TRAMs do not have extents information used to notify the AIs about incoming attacks, so how do you generate this information from the animation?
Let's say that you want to convert a non-attack animation to a damage-dealing animation. Non-attack TRAMs do not have extents information used to notify the AIs about incoming attacks, so how do you generate this information from the animation?
:1. Export the animation to XML with a body attached. If you extract using just "-extract:xml dest_folder TRAMsomething.oni", you'll get the 3D animation data inside the XML (namely, the tags Heights, Velocities, Rotations, PositionOffset, and Positions; for an attack animation, you'll also get Attacks and AttackRing, and inside Attacks' elements, each Attack element will have Extents at the end of it).
:1. Export the animation to XML with a body attached. If you extract using just "-extract:xml dest_folder TRAMsomething.oni", you'll get the 3D animation data inside the XML (namely, the tags Heights, Velocities, Rotations, PositionOffset, and Positions; for an attack animation, you'll also get Attacks and AttackRing, and inside Attacks' elements, each Attack element will have Extents at the end of it).
:However, if you extract this same animation using "-extract:xml dest_folder TRAMsomething.oni '''-anim-body ONCCtramuser.oni'''", the animation data will be placed in a DAE file along with the character model geometry. Be sure to pick a body with a representative size for the character classes that will actually use this TRAM, because the extents will be calculated from it. The XML file will be very short without the 3D data in it. This is how we want the non-attack TRAM to look. We do not know the extents information that should go in Extents or AttackRing, so we just want to add the part that distinguishes a DAE-extracted attack TRAM XML from a DAE-extracted non-attack TRAM XML. That part is the Attacks section, without the Extents under each Attack.
:However, if you extract this same animation using "-extract:xml dest_folder TRAMsomething.oni '''-anim-body ONCCtramuser.oni'''", the animation data will be placed in a DAE file along with the character model geometry. Be sure to pick a body with a size that's representative of the character classes that will actually use this TRAM, because the extents will be calculated from it. The XML file will be very short without the 3D data in it — this is how we want the non-attack TRAM to look. We do not know the extents information that should go in Extents or AttackRing, so we just want to add the part that distinguishes a DAE-extracted attack TRAM XML from a DAE-extracted non-attack TRAM XML. That part is the Attacks section, without the Extents under each Attack.
:2. First, consider whether the TRAM should have something added to its Flags section, like Attack or ThrowTarget.
:2. First, consider whether the TRAM should have something added to its Flags section, like Attack or ThrowTarget.
:3. Now add to the XML of the non-attack TRAM data in the following format (after the <SelfDamage /> section, typically):
:3. Now add to the XML of the non-attack TRAM data in the following format (after the <SelfDamage /> section, typically):
Line 772: Line 852:
:Do not add an AttackRing section after Attacks.
:Do not add an AttackRing section after Attacks.
:4. Import this with "-create dest_folder TRAMsomething.xml". The Extents sections and the AttackRing will be calculated by OniSplit from the attached DAE.
:4. Import this with "-create dest_folder TRAMsomething.xml". The Extents sections and the AttackRing will be calculated by OniSplit from the attached DAE.
:5. If you need this information for a patch mod, run "-extract:xml" on the TRAMsomething.oni you've created, <u>without</u> using "-anim-body". Now you can copy the Extents and AttackRing data to your XML patch. For an example of how the patch should look, see the Domino Knockdowns mod.
:5. If you need this information for a patch mod, run "-extract:xml" on the TRAMsomething.oni you've created <u>without</u> using "-anim-body". Now you can copy the Extents and AttackRing data to your XML patch. For an example of how the patch should look, see the [http://mods.oni2.net/node/311 Domino Knockdowns] mod.
 
===Combos===
The type and order of player input for triggering a given animation type (such as PPK) is hardcoded, and new animation types cannot be created. That being said, Oni has unused combo animation types, such as PKP, PKK, KPK, KPP, etc. that work perfectly fine and can be used to create new combos. To assign an animation type to a specific combo attack, you set a corresponding value in <Lookup><Type>.


<!-- Careful what you post here Paradox, TRAM XML format is changing a little bit in the next Onisplit -->
Setting a value in the <Link> of '''<DirectAnimations>''' will do two things:
# It will increase the time window for player input, meaning the next animation can be executed more easily. (In vanilla Oni, the Crescent Moon Kick has no link in KONCOMcomb_k_k_kfw and therefore is difficult to use.)
# It disables <Interpolation><End> for the next combo anim.
# It enables <Pause><Soft> and <Pause><Hard>.


==Throws==
===Just Frame input===
Throws target animation are registered in the TRAC of the throw initiator (a.k.a. throw source). Target animations are forced onto the other character removing the need to have that animation in target TRAC.
Implemented by Delano762, inspired by the game series Tekken, a Just Frame ("JF") move means that you have to press certain keys (W+K or W+P) at the exact same time, which is more difficult than it might sound. Delano's mod [http://mods.oni2.net/node/353 54000 New Combat Moves for Konoko] has a collection of animations which utilize existing animation states differently to create new moves.


Throw target (TRAM*tgt) animations can cover only up to 256 (0-255) frames.
Example 1:
* new forward kick = TRAMKONCOMkick_fw_JF <FromState>Standing
** key strokes: w + k
* old forward kick = TRAMKONCOMkick_fw <FromState>RunStart
** key strokes: w, k


Example 2:
* new forward punch = TRAMKONCOMpunch_fw_JF <FromState>Standing
** key strokes: w + p
* old forward punch = TRAMKONCOMpunch_fw <FromState>RunStart
** key strokes: w, p


==Fw throws==
Note that these animations are referred to as JF moves, not JF combos. The Crescent Moon Kick, as mentioned above, is an unintentional JF combo found in vanilla Oni.
Situation: you load two chars into Mod Tools and rotate (+/-180°) the throw target char because you want them to stand face to face. When you are done animating, the target animation would need to be reversed again: multiplying the velocities with -1, also the rotation needs a tweak. So far it looks like you need *(-1) for the x rotation and -/+180° (depending on your initial change) for the y rotation.


===Excel macro to tweak fw throws===
===Throws===
* put your files into the "input_and_output" folder
;States
* disable macro security if you don't want to click every time on the macro option button
The first anim state of source (src) and target (tgt) is the "primary" <FromState>. The others <FromState> entries are located in <Shortcut>.  
* close other worksheets first before you run the macro
* if you are not afraid of VBA code you can enter the developer environment by hitting [alt]+[F11], e.g. for extending the attack library with more screenshots and settings
** in that case search for: "LibraryThrows", " LibraryAttack", "Picture", "CBAttackHelp.AddItem"


* [http://dl.dropbox.com/u/139715/OniGalore/TRAM_macro.zip the macro] (for all TRAM except overlay-TRAM), [http://youtu.be/wxzJ8ahjP8k demo vid]
;Types
Throw target animations are registered in the TRAC of the throw initiator (AKA the throw source). Target animations are forced onto the other character. Throw target (TRAM*tgt) animations can only cover up to 256 frames (0-255).  


[[Image:Animation_macro_v4.png|right|thumb]]
The game identifies which Target animation is it supposed to play through the ''ThrownX'' animation types. Each throw, together with its corresponding Target animation, uses one of the 17 available ''ThrownX'' animation types. These types are used in three tags:


* <TargetType> tag in the Source animation,
* <Type> and <AimingType> tags in the Target animation.


==A look on run move complex==
For example, Konoko's forward punch throw / ''KONCOMthrow_fw_p'' uses Thrown1 as its TargetType tag:
Example on Striker's moves, meant as illustration for "what would be needed for new run trams".


            <TargetType>Thrown1</TargetType>
And the corresponding target animation, ''KONCOMthrow_fw_p'', uses Thrown1 in the Type and AimingType tags:
            <Type>Thrown1</Type>
            <AimingType>Thrown1</AimingType>
The ''ThrownX'' anim types work like slots - if you want to add a new throw to the game, you have to assign both the Source and the Target animations the same ThrownX type in the tags listed above. While these "pairs" are organized within vanilla animations according to the Throw Table below, this is nothing more than a convention, and as a result ''ThrownX'' types can be used freely. To give an example, while all Forward Punch Throws in the game seem to use the Thrown1 type, you can swap those types with another throw and they will work just as fine.
The fact that the game has only 17 ''ThrownX'' types is a major limitation - this effectively means that each character can have no more than 17 throws - out of which only 4 are unused by any character in the game. This prevents modders from creating a significant number of throws despite the game allowing great flexibility in creating new throws by mixing Animation States, Animation Types and <Varient> tags.
{{divhide|Throw table for vanilla Oni}}
{| class="wikitable" width=100%
|-
! rowspan=2 width=240 | names
! rowspan=2 width=40 | key combo
! colspan=4 | context
! colspan=2 style="background: #FF0;" | anim type
! rowspan=2 width=400 | image
|-
<!--context-->
! width=40 | varient
! width=60 | src state
! width=60 | tgt state
! width=85 | facing setup<!--tgt position only?(or pelvis rotation?)-->
<!--facing setup tgt rotation relative to src pelvis (or tgt pelvis position?)-->
<!--anim type-->
! width=40 style="background: #FF0;" | src
! width=40 style="background: #FF0;" | tgt
|-
! colspan=9 | normal throws a.k.a. static throws
|- style="vertical-align:top;"
|<!--names--> static throw forward punch
: TRAMKONCOMthrow_fw_p
: TRAMKONCOMthrow_fw_p_tgt
|<!--key combo--> P + ↑
|<!--varient--> COM
|<!--src state--> '''Standing'''
RunStart
|<!--tgt state--> '''Standing'''
Crouch<br>
Stunned
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''ThrowForwardPunch'''
|<!--anim type tgt--> '''Thrown1'''
|<!--image--> [[Image:KONCOMthrow_fw_p.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> static throw forward kick
: TRAMKONCOMthrow_fw_k
: TRAMKONCOMthrow_fw_k_tgt
|<!--key combo--> K + ↑
|<!--varient--> COM
|<!--src state--> '''Standing'''
RunStart
|<!--tgt state--> '''Standing'''
Crouch<br>
Stunned
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''ThrowForwardKick'''
|<!--anim type tgt--> '''Thrown2'''
|<!--image--> [[Image:KONCOMthrow_fw_k.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> static throw backward punch
: TRAMKONCOMthrow_bk
: TRAMKONCOMthrow_bk_tgt
|<!--key combo--> P + ↑
|<!--varient--> COM
|<!--src state--> '''Standing'''
RunStart
|<!--tgt state--> '''Standing'''
Crouch<br>
WalkingLeftDown<br>
WalkingRightDown<br>
Stunned
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''ThrowBackwardPunch'''
|<!--anim type tgt--> '''Thrown3'''
|<!--image--> [[Image:KONCOMthrow_bk.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> static throw backward punch
: TRAMKONCOMthrow_bk_k
: TRAMKONCOMthrow_bk_k_tgt
|<!--key combo--> K + ↑
|<!--varient--> COM
|<!--src state--> '''Standing'''
RunStart
|<!--tgt state--> '''Standing'''
Crouch<br>
WalkingLeftDown<br>
WalkingRightDown<br>
Stunned
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''ThrowBackwardKick'''
|<!--anim type tgt--> '''Thrown4'''
|<!--image--> [[Image:KONCOMthrow_bk_k.jpg|200px]]
|-style="vertical-align:top;"
! colspan=9 | run throws
|-style="vertical-align:top;"
|<!--names--> run throw forward punch
: (forward "lariat")
: TRAMKONCOMrun_throw_fw
: TRAMKONCOMrun_throw_fw_tgt
|<!--key combo--> P + ↑(↑)
|<!--varient--> COM
|<!--src state--> '''<span style="color: silver;">None</span>'''
RunningLeftDown<br>
RunningRightDown
|<!--tgt state--> '''Standing'''
RunningLeftDown<br>
RunningRightDown<br>
Stunned<br>
WalkingLeftDown<br>
WalkingRightDown<br>
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''RunThrowForwardPunch'''
|<!--anim type tgt--> '''Thrown5'''
|<!--image--> [[Image:KONCOMrun_throw_fw.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> run throw forward kick
: TRAMKONCOMrun_thw_fw_k
: TRAMKONCOMrun_thw_fw_k_tgt
|<!--key combo--> K + ↑(↑)
|<!--varient--> COM
|<!--src state-->'''<span style="color: silver;">None</span>'''
RunningLeftDown<br>
RunningRightDown
|<!--tgt state-->'''Standing'''
RunningLeftDown<br>
RunningRightDown<br>
Stunned<br>
WalkingLeftDown<br>
WalkingRightDown
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''RunThrowForwardKick'''
|<!--anim type tgt--> '''Thrown6'''
|<!--image--> [[Image:KONCOMrun_thw_fw_k.jpg|200px]]
<!--
identical headers but
STRCOMrun_thw_fw_p (face-to-face, with righty angle) links to Thrown5
STRCOMrun_thw_fw_pl (face-to-face, with lefty angle) links to Thrown6
-->
|-style="vertical-align:top;"
|<!--names--> run throw backward punch
: (backward "lariat")
: TRAMKONCOMrun_throw_bk
: TRAMKONCOMrun_throw_bk_tgt
|<!--key combo--> P + ↑(↑)
|<!--varient--> COM
|<!--src state-->'''<span style="color: silver;">None</span>'''
RunningLeftDown<br>
RunningRightDown
|<!--tgt state-->'''Standing'''
RunningBackLeftDown<br>
RunningBackRightDown<br>
WalkingRightDown<br>
WalkingLeftDown<br>
Stunned
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''RunThrowBackwardPunch'''
|<!--anim type tgt--> '''Thrown7'''
|<!--image-->
|-style="vertical-align:top;"
|<!--names--> run throw backward kick
: TRAMREDCOMrun_thw_bk_k
: TRAMREDCOMrun_thw_bk_k_tgt
|<!--key combo--> K + ↑(↑)
|<!--varient--> COM
|<!--src state-->'''<span style="color: silver;">None</span>'''
RunningLeftDown<br>
RunningRightDown
|<!--tgt state-->'''Standing'''
RunningBackLeftDown<br>
RunningBackRightDown<br>
Stunned
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''RunThrowBackwardKick'''
|<!--anim type tgt--> '''Thrown8'''
|<!--image--> [[Image:REDCOMrun_thw_bk_k.jpg|200px]]
|-style="vertical-align:top;"
! colspan=9 | catching throws a.k.a. tackle throws
|-style="vertical-align:top;"
|<!--names--> tackle throw backward kick?<br>(never used)
|<!--key combo-->
|<!--varient-->
|<!--src state-->
|<!--tgt state-->
|<!--facing setup-->
|<!--anim type src-->
|<!--anim type tgt--> Thrown9
|<!--image-->
|-style="vertical-align:top;"
|<!--names--> tackle throw backward punch
: TRAMKONCOMrun_tkl_bk_p
: TRAMKONCOMrun_tkl_bk_p_tgt
|<!--key combo--> P + ↑(↑)
|<!--varient--> COM
|<!--src state-->'''<span style="color: silver;">None</span>'''
RunningLeftDown<br>
RunningRightDown
|<!--tgt state-->'''<span style="color: silver;">None</span>'''
RunningLeftDown<br>
RunningRightDown
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''RunThrowBackwardPunch'''
|<!--anim type tgt--> '''Thrown10'''
|<!--image--> [[Image:KONCOMrun_tkl_bk_p.jpg|200px]]
|-style="vertical-align:top;"
! colspan=9 | disarm throws
|-style="vertical-align:top;"
|<!--names--> pistol disarm throw forward punch
: TRAMKONPISthrow_fw_p
: TRAMKONPISthrow_fw_p_tgt
|<!--key combo--> P + ↑
|<!--varient--> PIS
|<!--src state-->'''Standing'''
RunStart
|<!--tgt state-->'''Standing'''
Crouch<br>
Stunned
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''ThrowForwardPunch'''
|<!--anim type tgt--> '''Thrown11'''
|<!--image--> [[Image:KONPISthrow_fw_p.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> pistol disarm throw forward kick
: TRAMKONPISthrow_fw_k
: TRAMKONPISthrow_fw_k_tgt
|<!--key combo--> K + ↑
|<!--varient--> PIS
|<!--src state-->'''Standing'''
RunStart
|<!--tgt state-->'''Standing'''
Crouch<br>
Stunned
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''ThrowForwardKick'''
|<!--anim type tgt--> '''Thrown12'''
|<!--image--> [[Image:KONPISthrow_fw_k.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> pistol disarm throw backward punch
: TRAMKONPISthrow_bk
: TRAMKONPISthrow_bk_tgt
|<!--key combo--> P + ↑
|<!--varient--> PIS
|<!--src state-->'''Standing'''
RunStart
|<!--tgt state-->'''Standing'''
Crouch<br>
WalkingLeftDown<br>
WalkingRightDown<br>
Stunned
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''ThrowBackwardPunch'''
|<!--anim type tgt--> '''Thrown13'''
|<!--image--> [[Image:KONPISthrow_bk.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> (never used)
|<!--key combo-->
|<!--varient-->
|<!--src state-->
|<!--tgt state-->
|<!--facing setup-->
|<!--anim type src-->
|<!--anim type tgt--> Thrown14
|<!--image-->
|-style="vertical-align:top;"
|<!--names--> rifle disarm throw forward punch
: TRAMKONRIFthrow_fw_p
: TRAMKONRIFthrow_fw_p_tgt
|<!--key combo--> P + ↑
|<!--varient--> RIF
|<!--src state-->'''Standing'''
RunStart
|<!--tgt state-->'''Standing'''
Crouch<br>
Stunned
|<!--facing setup--> face-to-'''face'''
|<!--anim type src--> '''ThrowForwardPunch'''
|<!--anim type tgt--> '''Thrown15'''
|<!--image--> [[Image:KONRIFthrow_fw_p.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> rifle disarm throw backward punch
: TRAMKONRIFthrow_bk_p
: TRAMKONRIFthrow_bk_p_tgt
|<!--key combo--> P + ↑
|<!--varient--> RIF
|<!--src state-->'''Standing'''
RunStart
|<!--tgt state-->'''Standing'''
Crouch<br>
Stunned
|<!--facing setup--> face-to-'''back'''
|<!--anim type src--> '''ThrowBackwardPunch'''
|<!--anim type tgt--> '''Thrown16'''
|<!--image--> [[Image:KONRIFthrow_bk_p.jpg|200px]]
|-style="vertical-align:top;"
|<!--names--> (never used)
|<!--key combo-->
|<!--varient-->
|<!--src state-->
|<!--tgt state-->
|<!--facing setup-->
|<!--anim type src-->
|<!--anim type tgt--> Thrown17
|<!--image-->
|}
{{divhide|end}}
;Running disarms
Oni offers support for running disarms (originally noticed [[OBD:BINA/OBJC/MELE/MoveList/Throw|HERE]]), which was taken advantage of by Delano's mod [http://mods.oni2.net/node/353 54000 New Combat Moves for Konoko].
;Forward throws
Scenario: You load two characters into Mod Tool and rotate (+/-180°) the throw target character because you need them to stand face to face as you work on an animation. When you are done animating, the target animation would need to be reversed again. This means multiplying the velocities by -1; the rotation also needs correcting. So it looks like you need *(-1) for the x rotation and -/+180° (depending on your initial change) for the Y rotation.
There is a Blender script implemented within the BlenderOni addon for rotating and adding PositionOffset to a forward throw Target animation. It is capable of adjusting both forward and back throws. The script's old version can be accessed [[Blender/Obsolete scripts#Script for adjusting forward throw targets|HERE]].
===Run animations===
Here's a breakdown of the Striker's run animations, meant as an illustration for what would be needed to make new run TRAMs.


Run cancel:
Run cancel:
Line 807: Line 1,253:
* STRIKEidle1 / another idle animation
* STRIKEidle1 / another idle animation


 
Run ''a minimal cycle'':
Run - ''a minimal cycle'':
* STRIKEidle1 / another idle animation
* STRIKEidle1 / another idle animation
* STRIKErun1stepa
* STRIKErun1stepa
Line 817: Line 1,262:
* STRIKEidle1 / another idle animation
* STRIKEidle1 / another idle animation


Start looking on the image most right.
Follow the images below from right to left.
<gallery>
<gallery>
Image:XML_TRAM_STRIKErunstop.png|STRIKErunstop
Image:XML_TRAM_STRIKErunstop.png|STRIKErunstop
Line 826: Line 1,271:
</gallery>
</gallery>


==List of unused animations==
Here are all the known unused animations. These could be recycled in a new mod.
'''From the original game'''
* KONOKOconsole_punch: What the name says (the engine can use that animation depending on the console's configuration, see [[OBD:BINA/OBJC/CONS|CONS]]) .
* KONOKOlev3_intro: Looks like she's placing something (bomb?) and then running away.
* KONOKOlev4_undress: From an aborted clothes-changing cutscene.
* KONOKOlev16_bomb: Planting a bomb.
* KONCOMsuper_kick: Now used in [[OTA]] as a spawn event, and by the fan-made character [[Shinatama Evolved]].
* KONCOMsuper_punch: KONCOMpunch_heavy but without the shouted attack name, has HalfDamage flag, and does 10 less damage in its first attack part.
* COMPISidle_special1: Comguy checking environment and his gun; meant for a feature that would visually depict an elevation in the AI's level of alertness after, say, hearing a noise.
* STRPISidle_special1: Striker checking his his gun and communicating with an ally (another unused alertness-elevation animation).
* THUGlev1_direct: Thug probably directing a truck driver.
'''From modders'''
[[Image:Female stun.jpg|right|thumb|Char A and Char B performing stun animations.]]
* http://mods.oni2.net/node/376
** StrikerKneeStepKickThrow.zip
** REDCOMjump_fw_crouch--double_flip--dae.zip
** KONprone_getup--dae.zip
** KONRIF_k_bk_throw.zip
** female_stun--dae.zip
==Special effects==
If the scene is overloaded by too many particles (including motion blur), these effects will cease being rendered. So don't overuse effects.
===Color trails===
Open the XML-accompanied TRAM, search for the "Particles" tag, and insert your markup.
First example: TRAMSTRCOMcomb_p_p.xml
[[Image:Colorful_contrail_added.png|right|thumb]]
        <Particles>
            <Particle>
                <StartFrame>0</StartFrame>
                <EndFrame>12</EndFrame>
                <Bone>LeftFist</Bone>
                <Name>contrail</Name>
            </Particle>
        </Particles>
"contrail" is looked up by the character class (ONCC) that emits the actual particle; here it is "h2h_strtrail_e01".


==List of unused animations==
This second example is about creating two different contrails in a TRAM at the same time. The animation is "TRAMSTRCOMpunch_heavy.xml".
Here are all the known unused animations. These could be reintegrated/recycled/whatever....
 
[[Image:Different_contrails_in_attack.png|right|thumb]]
 
        <Particles>
            <Particle>
                <Start>0</Start>
                <End>54</End>
                <Bone>RightWrist</Bone>
                <Name>contrail</Name>
            </Particle>
            <Particle>
                <Start>0</Start>
                <End>54</End>
                <Bone>LeftWrist</Bone>
                <Name>'''contrail_2'''</Name>
            </Particle>
        </Particles>
 
Note that you need to register the second contrail in the ONCC as well. Using your own contrail particle is also possible; just insert its name between the <Type> tags.


===From the original game===
            <ONCPParticle>
* KONOKOconsole_punch          what the name says (the engine can use that animation depending on the console's configuration, see [[OBD:BINA/OBJC/CONS|CONS]])
                <Name>contrail</Name>
* KONOKOlev3_intro looks like she was placing something (bomb?) and then running away
                <Type>h2h_strtrail_e01</Type>
* KONOKOlev4_undress from an official aborted cutscene
                <BodyPart>-1</BodyPart>
* KONOKOlev16_bomb              planting a bomb
            </ONCPParticle>
* KONCOMsuper_kick now used in OTA scripts (mod) as spawn event
            <ONCPParticle>
* KONCOMsuper_punch KONCOMpunch_heavy but without ''attack name shout'', HalfDamage, and makes 10 less damage in first attack part
                <Name>'''contrail_2'''</Name>
* COMPISidle_special1 comguy checking environment and his gun (it's actually used if you wait long enough, isn't it?)
                <Type>'''h2h_murtrail_e01'''</Type>
* STRPISidle_special1 striker showing off his gun, whatever (it's actually used if you wait long enough, isn't it?)
                <BodyPart>-1</BodyPart>
* THUGlev1_direct thug probably directing a truck driver
            </ONCPParticle>


===From modders===
===Motion blur===
Following files are available in DAE (and maybe ONI format).
[[Image:XML_TRAM_willow_kick_with_motion_blur.jpg|thumb|200px]]
Motion blur in Oni works much like ghosting/onion skinning features in any animation software: In the frame range specified by <Start> and <End> an additional instance of body parts specified in <Bones> are rendered for additional extra frames specified by <Lifetime>, with transparency set by <Alpha>, and every <Interval> frames within the frame range.
Example snippet from KONCOMcomb_p_p_k:
        <MotionBlur>
            <MotionBlur>
                <Bones>RightThigh RightCalf RightFoot</Bones>
                <Start>20</Start>
                <End>28</End>
                <Lifetime>4</Lifetime>
                <Alpha>127</Alpha>
                <Interval>1</Interval>
            </MotionBlur>
        </MotionBlur>


[[Image:female_stun.jpg|right|thumb|charA and charB performing stun animations]]
The one noteworthy thing is that you can have multiple motion blur sequences. If you wanted to add an extra motion blur to the above animation, you could do something like this:
        <MotionBlur>
            <MotionBlur>
                <Bones>LeftThigh LeftCalf LeftFoot</Bones>
                <Start>10</Start>
                <End>18</End>
                <Lifetime>4</Lifetime>
                <Alpha>127</Alpha>
                <Interval>1</Interval>
            </MotionBlur>
            <MotionBlur>
                <Bones>RightThigh RightCalf RightFoot</Bones>
                <Start>20</Start>
                <End>28</End>
                <Lifetime>4</Lifetime>
                <Alpha>127</Alpha>
                <Interval>1</Interval>
            </MotionBlur>
        </MotionBlur>


* [https://www.dropbox.com/s/5d6aki276ryb61y/REDCOMjump_fw_crouch--double_flip--dae.zip?dl=0 Fury double flip] (.dae)
===Impact effect===
** note: -
Impact effects – mostly particle – are chosen based on logic written within [[XML:BINA/ONIE#Visual guides: weapon, melee, environment|ONIE]]. Furthermore particles must be registered in [[XML:ONCC|ONCC]]: You probably want to look at ONIA instead of ONCP.
* [https://www.dropbox.com/s/dww2hf1yj6e7wqa/KONenter_prone_mode--oni_and_dae.zip?dl=0 Konoko enters prone mode] (.dae + .oni)
** note: prone mode artefact
* [https://www.dropbox.com/s/3llicjdxbva836p/KONprone_getup--dae.zip?dl=0 Konoko leaves prone mode] (.dae)
** note: prone mode artefact
* [https://www.dropbox.com/s/luf7ayqikcuupo7/female_stun--dae.zip?dl=0 female stun (throw pair)] (.dae)
** note: needs to be slowed down (-> more frames)


[[Image:XML_TRAM_KONCOMkick_fw_with_ninflash1.jpg|thumb|200px]]


{{XML}}
{{XML}}

Latest revision as of 19:01, 29 February 2024

TRAM : Totoro Animation
XML modding tips
  • See HERE to start learning about XML modding.
  • See HERE if you are searching for information on how to handle object coordinates.
  • See HERE for some typical modding errors and their causes.
XML.png
XML

TRAC << Other file types >> TRAS

switch to OBD page

General information

TRAM files — animation data for characters — are basically made of three chunks:

  • Metadata or "header": animation type, state, flags, particle, sounds, etc.
  • Animation data: pelvis heights, pelvis velocities (root motion), bone rotations
  • Attack data: damage, self-damage, extents (danger zones for AI awareness) and throws

Root motion: a character moves by changing the position of its root bone (pelvis). The animated legs just create the illusion for the player that they are responsible for the motion.

Bones: Each character has 19 separate body parts which get animated (rotated) relative to each other. Compared to modern games Oni's bone system is deprecated. The body doesn't get deformed by following animated bones. Oni modders often use the terms mesh and bone interchangeably. Only the pelvis has translation data (heights and velocities) besides rotations. The hierarchy of the body parts (or bones) is determined by TRIA.

The term animation is often shortened to anim by modders, following the naming of commands in BSL: chr_wait_animstate, chr_wait_animtype, env_anim, etc.

Oni's code and debugging messages tend to spell the word variant as "varient". Blame the programmers for that one. Typically we use the correct spelling here, but OniSplit's XML follows Oni's misspelling, so you may see "varient" creep into the wiki here and there.

TRAMs used in Oni follow a naming pattern. A list of all combat TRAMs in-game and their naming can be found here.

Open questions

  • If the never-used Thrown type can be applied as type 18 the table looks much more complete. "Restoring" forward tackles (face-to-face, src run + tgt run) can be omitted as the AI would most often stop movement for actual combat?
  • All important header data of STRCOMrun_thw_fw_p and STRCOMrun_thw_fw_pl is identical. That means the engine picks the correct TRAM by using an unknown context, possibly this is similar or part of the distinction of "forward" (face-to-face) and "backward" (face-to-back).
Maybe the algorithm checks always tgt's rotation and relative position to src at the same time but for most cases only tgt's rotation (facing) is relevant.
  • Also, STRCOMrun_thw_fw_p(l) routing to Thrown5 and Thrown6 shows that Thrown anim types might be used however we like. A src-tgt-anim-type-pairing might be simply a convention. Well, someone could check the source code...
  • The existence of STRCOMrun_thw_fw_p(_tgt) and STRCOMrun_thw_fw_pl(_t) means that we need extra research to understand the full extent of the throw system.
  • The variant pickup system is not clear yet: is a RIFCOM idle and a RIFNAT idle both possible?
    • Or do rightpistol, leftpistol, rightrifle and leftrifle variants count as subsets of combat?

Summary of animation lookup logic

  • First the game builds a pool of anims a character can use. They are loaded from the TRAC file registered in ONCC, including parent TRACs.
  • Anims from a child TRAC override those of the parent if their combination of state, type and variant is exactly the same.
  • Child TRACs usually omit some anims. For example, Elite Strikers don't have their own run anims, so they use the parent anims of normal Strikers. See TRAC page for details.
  • A character always possesses a single animation state. This term derives from state machines, but you only need to know that states are the first point in the decision path determining what anims are actually allowed to play at a given moment.
  • Here is the full decision path:
    • anim state check
    • event (user input, or engine input for the AI) -> context check -> anim type check
    • anim variant check
    • TRAC weight check

Elaboration

Animations never stop – they flow from one to another. (See the concept of state machines in gaming.) The default case is a character getting spawned and then just standing there: he idles forever. This brings us to the core attributes of every animation: type, state, variant.

Now then, the idle animation does not link to a specific follow-up animation – it rather links to a follow-up state.

Ironically all anims have a <FromState> and a <ToState> field, but no obvious <CurrentState> which can cause confusion on what the current anim's state actually is. This gives us two options of how to think about the situation: either consider <FromState> as usually being the <CurrentState>, or states exist only between anims and serve as transition rules.

Linking to a follow-up state allows for multiple choices of what specific anim comes next. An anim is picked up randomly from a pool of valid anims. Their probability or <Weight> is determined by the anim listing in the TRAC – the anim collection (see "Weights" section for an explanation of exactly how <Weight> is handled).

Anyway, to let an character flow from one anim state to another, the <ToState> is used. Let's say an SBG grenade hits Konoko. The particle's damage type is blownup; this and the direction of the incoming damage force an anim of type Blownup or BlownupBehind to play, such as TRAMKONOKOblownup1.

Thus, Konoko falls to her back, going into the FallenBack state. The engine picks up the next anim which has <FromState>FallenBack. Also, receiving damage puts a character into combat mode, so further anims will be of variant Combat. But if the player gives no input, Konoko will remain on the ground, as <ToState>FallenBack creates a loop.

So here's a question: why isn't a getup anim like KONCOMgetup_lt played automatically since it also has <FromState>FallenBack and <Varient>Combat? Answer: it differs in its <Type>. Most anim types are bound to user input and therefore are excluded from the automatically created pool of valid anims which can follow.

Now let's consider what happens upon user input. A leftward movement of the mouse tells the engine to use an anim of type StandingTurnLeft. There are two anims with that type, KONOKOcomb_turnlt and KONCOMgetup_lt, but only the latter matches the current <FromState> condition.

In fact, KONOKOcomb_turnlt has <Varient> Combat – the "comb" here stands for "combat", not "combo". Following Oni's naming convention, the file should have been named KONCOMturn_lt.

Knowing this behavior, we can deduce that anim types registered to user input will make the engine ignore all the automatic anims inside the pool, therefore breaking the loop of KONCOMfallen_back. And since KONCOMgetup_lt has <ToState>Standing and Konoko is still in combat mode, the following idle anim must also have <Varient>Combat. So the next anim played will be KONCOMidle1 or KONCOMidle2.

Konoko will eventually calm down when her ONCC <FightModeTimer> runs down, and then KONOKOidle1 or KONOKOidle2 will be played instead. (Actually, the COMidle will continue until a non-combat anim such as running breaks that loop. You won't ever see Konoko drop from combat readiness to her regular idle animation. Instead she will go from combat idle to running, to stopping, then standing at ease.)

Note the fallback behavior of anim lookup: if the engine cannot find an anim for the active variant (or "mode") of the character, it will choose the normal (non-variant-matching) version. Anims can be in the following variants: Combat, LeftPistol, LeftRifle, Panic, RightPistol, RightRifle and Sprint.

As for combinations of variants, it's possible, yes, but rarely and only Sprint and one weapon variant at a time.

Weights

Let's say that we're playing as a Ninja, we are in the state Standing, and we hit the action key to perform a taunt. The engine recognizes the context (no console to interact with), places the character in combat mode, and looks up anims of type Taunt. Since we are in combat mode, the next anim must be of variant Combat if possible. These lookups boil down to two valid possible anims: NINCOMtaunt1 (a spin) and NINCOMtaunt2 (the moon walk Easter egg). The engine picks one of them randomly.

However, NINCOMtaunt1 has a TRAC Weight (probability) of 100 while NINCOMtaunt2 has a TRAC Weight value of just 5. So the chances are quite high that we will not see the moon walk taunt.

           <TRACAnimation>
               <Weight>100</Weight>
               <Animation>TRAMNINCOMtaunt1</Animation>
           </TRACAnimation>
           <TRACAnimation>
               <Weight>5</Weight>
               <Animation>TRAMNINCOMtaunt2</Animation>
           </TRACAnimation>

If there is only one anim to choose from, it will always play no matter what its Weight, even if it is zero. When it comes to multiple anims being a valid choice, the calculation is: weight of anim / sum of all valid anim weights. For NINCOMtaunt2, this means 5 / 105 = 0.047, or a 4.7% chance of a moon walk.

Idle timer

There's a semi-famous Easter egg where Konoko will sneeze if she stands still for a long time. The timer for this is so long that most players never see it unless they step away from the game and leave it running without hitting F1. You might think that the way the sneeze is triggered is to set a low weight for it so that it's very unlikely a repeating idle cycle will choose the anim. But here's the sneeze anim in the TRAC with a Weight of 100:

           <TRACAnimation>
               <Weight>100</Weight>
               <Animation>TRAMKONOKOidle_spec3</Animation>
           </TRACAnimation>

What's going on here? All regular idle anims are in fact of type Stand, while Konoko's idle_spec3 anim above is of type Idle. Anims of type Idle are played every time the idle animation timer expires. This is found in ONCC as <IdleAnimation1Timer> and <IdleAnimation2Timer>. These timers are set to 30,000 for every character. The number is in ticks, so if we convert to minutes – 30,000 / 60 / 60 = 8.3̅ – we find that the secret idle anim for Konoko (or any character) will play every 8⅓ minutes.

List of tags, types, and flags

Use the search function in your browser to quickly find a tag.

tag type description
<Lookup> parent tag
<Type> flag Look them up over HERE. The pool of valid TRAMs (animations a character can choose from) is built from the TRAC files registered in the ONCC. Most of the anim types are connected to player inputs.
<AimingType> flag Look them up over HERE. The pool of valid TRAMs, and therefore TRASs (aiming screens a character can choose from) is built from the TRSC files registered in the ONCC.
<FromState> flag
Primary <FromState> in <Lookup> uses about 8 interpolating frames by default. Use Shortcut's <FromState> to override this frame number.

Look them up over HERE.

When FromState is set to None, some default behaviors are ignored and are replaced by Shortcuts.
Shortcuts extend the number of states from which an animation can be played and under what conditions (replacing this atomic yes/no).
<ToState> flag Look them up over HERE.
<Varient> flag (misspelled because Oni misspells it) If unused, the tag will simply be "<Varient />", such as for non-combat animations. Otherwise it contains one of these values:
Combat
LeftPistol
LeftRifle
Panic
RightPistol
RightRifle
Sprint
<FirstLevel> int16 Number of first level in which move becomes available to the player ("0" to make it available from the start).
<Shortcuts> parent tag

Works as an alternative FromState collection.

Shortcuts are accepted if their <Shortcut><FromState> value differs from the "primary" <Lookup><FromState> value. In other words, if you want to make a Shortcut that uses the same FromState value then you have to set primary FromState value to None. By doing that, the hardcoded interpolation frame length of about 8 frames can be overridden.

In the following example, the new interpolation length is 0. This will require the animation to match perfectly with the previous one. For a smooth transition to the next animation, set a suitable value at <Interpolation><End>.

       <Lookup>
           ...
           <FromState>None</FromState>
           ...
           <Shortcuts>
               <Shortcut>
                   <FromState>Standing</FromState>
                   <Length>0</Length>
                   <ReplaceAtomic>no</ReplaceAtomic>
               </Shortcut>
           </Shortcuts>
Scenario A: hardcoded interpolation of 8 frames. Scenario B: changeable interpolation frame number.
<Shortcut> parent tag
<FromState> flag Look them up over HERE.
<Length> int16 Amount of interpolating frames. While interpolations of rotation are less noticeable, interpolations of different positions can cause drift (i.e. sliding).

This is especially observed for transitions from idle to movements and vice versa — basically any combination of animations with different accelerations at start and end. By default, animations without specified Shortcut interpolation give about 8 frames of interpolation. For moves starting or ending in idle, it's better not to use interpolation. Just give the start and end frames the same positions and rotation values as the idle. Interpolations should always be considered a last resort.

This drift can be observed even in vanilla animations — most prominently in Konoko's comb_k. Konoko's left foot should be in a fixed position as the animation starts from from Konoko's idle pose. However, the interpolation is causing her left foot to drift noticeably to the right and a bit forward.

The reason this happens is because the interpolation "mixes" two animations. When one animation transitions into another via interpolation, part of the animation system continues playing the initial animation, and part of it is playing the follow-up animation, with all the rotations and positions getting linearly interpolated.

<ReplaceAtomic> flag
yes
no
<Flags> flag These are top-level flags on the whole animation. See the other <Flags> for flags on an attack part.
RuntimeLoaded
(This bit is not stored on disk; it is used at runtime to mark that the animation was loaded.)
Invulnerable
While playing this animation, the player is invulnerable to melee damage and also cannot be thrown, but can still take damage from particles and falls.
BlockHigh
While playing this animation, the player can block high or undefined-height attacks within some arc in front of him. The height of an attack is found under the <Attack> section. If you set this flag on an animation where the player character is spinning, then the character can still be kicked in the back or thrown.
BlockLow
Same as above, only it can block low or undefined-height attacks.
Attack
Unused by the engine.
DropWeapon
If the player is armed, he drops his weapon when this animation plays.
InAir
Unused by the engine.
Atomic
Unused by the engine. Only the Start and End frames of the Atomic field below matter.
NoTurn
Player cannot turn while performing this animation.
AttackForward
Unused by the engine.
AttackLeft
Same as above.
AttackRight
Same as above.
AttackBackward
Same as above.
Overlay
Not a standalone animation; it just overwrites part of an already-playing one, e.g. the weapon-holstering animation.
DontInterpolateVelocity
Unknown, but maybe it has something to do with {x,y,z} velocities and the fact that directional jumps, for example, take information about their direction vector from the {x,z} velocity part of the TRAM (the vertical Y component is in the ONCC).
ThrowSource
Oni expects this flag on all throw source animations.
Throws work in animation pairs: whenever a throw source is played, the other character must perform the throw target animation. See throw(n) types:
TRAM <TargetType> from StNA (first used throw starts at #96).
Characters have only their own pool of animations available. And since enemy's TRAC might not contain the necessary animation the information must be provided by the throw source TRAC.
Since every throw animation must have a throw animation type the ThrowSource flag is actually redundant.
ThrowTarget
Animation can hurt anybody with its attack part, including teammates. The player can even hurt himself with the TRAM's damage part (whereas a player cannot hurt himself with his own animation's attack part). It also allows two attack parts to be executed instead of only one (maybe a bug? more than two will result in a crash).
If you set the first attack part to be able to deal damage from the 1st to the 100th frame of the TRAM, and the second attack part to deal damage within that range (e.g. from the 25th to the 41st frame), then the first attack part will deal damage from the 1st to the 100th frame (as usual), but even if it hits, that second attack part can hurt the enemy as well during frames 25–41. Note that the second attack part must be executed within the first attack part's active "window", otherwise it won't work.
RealWorld
Unused by the engine. It appears this flag was used during the authoring process to create a TRAM and an OBAN from one animation source. The OBAN is supposed to store pelvis rotations and positions, allowing a character to move over obstacles/gaps. The vast majority of TRAMs with this flag are used in cutscenes.
DoAim
Applies the aiming animation overlay (PIS/RIF) if the player has a weapon.
DontAim
An aiming overlay will not be applied.
CanPickup
Player can pick up an item during this animation if he intersects with one during his movement.
Aim360
Unused by the engine.
DisableShield
If the player has an active supershield, this disables it (the flag is placed on four Mutant Muro attacks: his two supers, the claw-stuck-into-ground move and the sliding "kancho" maneuver; it is also hardcoded to be removed when the Zeus Thunderbolt attack is used).
NoAIPickup
AIs are not permitted to pick up items with this animation.
<Atomic> parent tag Animation cannot be interrupted by player between the Start and End frames.
<Start> int16
<End> int16
<Invulnerable> parent tag Character will not take melee damage and cannot be thrown between the Start and End frames.
<Start> int16 First frame of character being invulnerable.
<End> int16 Last frame of character being invulnerable.
<Overlay> parent tag
<UsedBones> flag Simply contains "<UsedBones />" if no bones are involved, otherwise:
Pelvis
LeftThigh
LeftCalf
LeftFoot
RightThigh
RightCalf
RightFoot
Mid
Chest
Neck
Head
LeftShoulder
LeftArm
LeftWrist
LeftFist
RightShoulder
RightArm
RightFist
<ReplacedBones> flag "<ReplacedBones />" if unused, otherwise:
Pelvis
LeftThigh
LeftCalf
LeftFoot
RightThigh
RightCalf
RightFoot
Mid
Chest
Neck
Head
LeftShoulder
LeftArm
LeftWrist
LeftFist
RightShoulder
RightArm
RightFist
<DirectAnimations> parent tag
<Link> link First slot. "<Link />" if unused.
<Link> link Second slot. "<Link />" if unused.
<Pause> parent tag
<Hard> int16 In ticks. The Hard and Soft pause values are ignored if this animation has a direct link (above) to another animation.
<Soft> int16 In ticks. As mentioned above, the player cannot enter new inputs during this pause unless this animation is part of a combo animation defined by <DirectAnimations><Link>.
Examples:
COMcomb_p, (no pause) COMcomb_p_p
COMcomb_p, (pause) COMcomb_k

The difference between the hard and soft pause is that you can block during the soft pause and not the hard pause.

<Interpolation> parent tag
<End> int16
  • interpolates first X frames of next animation
  • if the first follow-up animation is too short, it can continue to play even further (not observed with vanilla anims)

While interpolations with rotations are less noticeable, interpolations of different positions can cause an additional drift.

This was especially observed for transitions of idle to movements and vice versa — basically any combination of animations with different accelerations at the start and end. By default, animations without a specified Shortcut interpolation get about 8 frames of interpolation. For moves starting or ending in idle, it's better not to use interpolation. Just give the start and end frames the same positions and rotation values as the idle. Interpolations should always be considered a last resort.

"End" interpolation covering multiple follow-up animations.
<Max> int16 unused
<FinalRotation> float Ending rotation in degrees. (During an animation on the player character, the camera is detached rotation-wise. If this value matches the body's final rotation, it will prevent a "glitchy" re-attaching.)
<Direction> Used by AI melee system.
None
Forward
Backward
Left
Right
<Vocalization> int ID of one of the SoundConstants in ONCC
<ActionFrame> int Frame number for any special events associated with this animation: weapon theft via disarm, weapon holstering, Mukade teleporting, items getting handed over to player, etc.
<Impact> link "<Impact />" if unused.
<Particles> parent tag serves as group element
<Particle> parent tag holds individual particle data
<Start> int frame number for particle to start
<End> int frame number for particle to end (if the number exceeds frame count of animation, the particle will simply die at the end of the animation)
<Bone> flag
Pelvis
LeftThigh
LeftCalf
LeftFoot
RightThigh
RightCalf
RightFoot
Mid
Chest
Neck
Head
LeftShoulder
LeftArm
LeftWrist
LeftFist
RightShoulder
RightArm
RightFist
<Name> link particle name in ONCC-ONCP
<MotionBlur> parent tag
<MotionBlur> parent tag sequence element
<Bones> flag
Pelvis
LeftThigh
LeftCalf
LeftFoot
RightThigh
RightCalf
RightFoot
Mid
Chest
Neck
Head
LeftShoulder
LeftArm
LeftWrist
LeftFist
RightShoulder
RightArm
RightFist
<Start> int16 Start frame of motion blur sequence
<End> int16 End frame of motion blur sequence
<Lifetime> int8 Lifetime of each "ghost" in frames.
<Alpha> int8 Transparency of "ghosts".
<Interval> int8 Frame interval between each rendered "ghost".
<Footsteps> parent tag
<Footstep> parent tag
<Frame> int16
<Type> flag
Left
Right
<Sounds> parent tag "<Sounds />" if unused.
<Sound> parent tag
<Name> char[32] OSBDfile.imp.oni (don't use resource type's prefix or suffix)
<Start> int16 The frame when the sound starts to play.
<Heights> parent tag
<Height> float Absolute position.
<Velocities> parent tag
<Velocity> 2 x float Relative positions (delta values); the numbers represent the change in position from one frame to another.
<Rotations> parent tag
<Bone> parent tag There are 19 bone tags, one for each body part.
<EKey> int8 + 3 * float For normal animations. The first value is the number of frames for which the rotation is maintained; the sum of all of these first EKey components always equals the total number of frames for the animation.
<QKey> int8 + 4 * float For overlay animations used by TRAS aiming screens.

OniSplit v0.9.54.0 produces <QKey>s (quaternions) instead of <EKey>s (Euler rotations) for normal animations.

<PositionOffset> parent tag <PositionOffset> and <Positions> belong together. In the binaries, they are written in place. Seems unused; changing them has no effect in-game.
<X> int16
<Z> int16
<Positions> parent tag
<Position> float seems to be unused (and when checking this with "chr_debug_sphere = 1", the spheres remain unchanged)
<Height> float vertical extent
<YOffset> float Y offset of the vertical extent from character location
<ThrowSource> parent tag "<ThrowSource />" if unused.
<TargetAdjustment> parent tag Used to position targets during throws, relative to the position of the character executing the throw.
<Position> 3 * float Contains XYZ values, which position the target character at the start of the animation:
  • X - Side axis. Negative values move the target to the right and positive values move the target to the left.
  • Y - Height axis. Negative values move the target downwards, but cannot make the target go below the floor. Positive values make the target go upwards; this will lift the target's collision sphere off the ground as if they jumped. However if the value is too big, the target will teleport upward and then immediately start falling, interrupting the target animation.
  • Z - Forward axis. Negative values move the target backwards and positive values move the target forward.
<Angle> float In radians - adjusts the rotation of the target in Oni's Y axis; most of the time (if not always) it's set to 3.14159274 radians in vanilla anims, equaling 180 degrees - which effectively rotates the rotates by those 180 degrees; if it was set to 0, the target would face the throw source character with his back.
<Distance> float Activation distance. The throw can be triggered if it is within this range. However the value must be greater than the equivalent TRAM in the parent TRAC or else the equivalent TRAM will play when the throw takes place outside of this TRAM's range and within that TRAM's range.
<TargetType> flag The flags are part of the animation type list.

(static throws)

Thrown1 = ###COMthrow_fw_p_tgt
Thrown2 = ###COMthrow_fw_k_tgt
Thrown3 = ###COMthrow_bk_p_tgt
Thrown4 = ###COMthrow_bk_k_tgt

(running throws)

Thrown5 = ###COMrun_throw_fw_p_tgt
Thrown6 = ###COMrun_throw_fw_p_tgt
Thrown7 = ###COMrun_throw_bk_k_tgt
Thrown8 = ###COMrun_throw_bk_k_tgt (not tested)

(tackle throw = catching)

Thrown9 = ###COMrun_tkl_fw_p_tgt (not tested)
Thrown10 = ###COMrun_tkl_bk_p_tgt

(pistol disarms)

Thrown11 = ###PISthrow_fw_p_tgt
Thrown12 = ###PISthrow_fw_k_tgt
Thrown13 = ###PISthrow_bk_p_tgt

(rifle disarm)

Thrown14 = ###PISthrow_bk_k_tgt (not tested)
Thrown15 = ###RIFthrow_fw_p_tgt
Thrown16 = ###RIFthrow_bk_p_tgt
Thrown17 = ###RIF? = (not tested)

About the naming:

"fw" = face-to-face throw
"bk" = thrower is facing victim's back
"throw" inside TRAM names is sometimes shortened to "thr"
"p"/"k" = triggered by punch or kick button ("p" is sometimes omitted)
<SelfDamage> parent tag "<SelfDamage />" if unused.

Works only with specific, hardcoded AnimTypes (mainly ThrownX, it's unknown if any other types work - that remains to be investigated). Using SelfDamage on an AnimType that wasn't intended for it will cause the game to crash. (ToDo: Checked if <Flag>ThrowTarget is enough to explain this. Modify a simple kick? For more please link to and use talk page.)

From a practical standpoint, this means SelfDamage can be used only on ThrowTarget animations.

<Damage> parent tag sequence element
<Points> int16 Damage taken by character.
<Frame> int16 Frame of the animation when damage is dealt.
<Attacks> parent tag
<Attack> parent tag Only 2 attack parts per file are allowed. Normally the target gets only one hit. But if the attack frame ranges of both attack parts are overlapping, then the target can be hit by both of them.
<Start> int16 First frame where damage can be inflicted on an opponent.
<End> int16 Last frame where damage can be inflicted on an opponent.
<Bones> flag The bones which can inflict damage.
<Flags> flag These are flags on an attack part, inside an <Attacks><Attack> element. See the previous <Flags> for general flags on the TRAM.
Unblockable
Low - Target of attack needs to crouch in order to block this attack.
High - Blocker needs to stand; if both Low and High are set, blocker can block from both standing and crouching positions.
HalfDamage - Blocker still receives half of the normal damage.
<Knockback> float Target gets knocked back by this amount if attack is successful.
<HitPoints> int16 Damage points inflicted by attack.
<HitType> flag Animation type for opponent's animation when the attack isn't blocked. The flags are part of the animation type list.
<HitLength> int16 Number of frames that the target should remain in his hit animation state when he gets hit. If ≥ 20, Oni automatically upgrades the character to a stagger animation.
<StunLength> int16 Number of frames that the target should remain in his blocking animation state when he blocks the attack. If ≥ 15, Oni automatically upgrades the character to a block stun.
<StaggerLength> int16 Number of frames that the target should perform his stagger animation after a successful block.
<Extents> parent tag Explained below. Automatically calculated by OniSplit if there's a DAE file referenced in the XML.
<Extent> parent tag One tag per attack frame. Number of <Extent> tags = <Attack><End> - <Attack><Start> + 1.
<Angle> float In degrees.
<Length> float
<MinY> float
<MaxY> float
<AttackRing> parent tag Always contains 36 <Length> tags, explained below. Automatically calculated by OniSplit if there's a DAE file referenced in the XML. (AttackRing was formerly known as "horizontal extents" in older versions of OniSplit.)
<Length> float Horizontal extents, explained below. They create a "danger zone" around the attacker which the AI uses to try to dodge an attack.

Export

TRAM files can be extracted A) as pure XML files or B) as a pair of XML and DAE files. For editing the actual animation, you will want to use method B. While exporting an ONCC, you might see errors such as:

Cannot find instance 'TRAMKONCOMthrow_rev'
Cannot find instance 'TRAMKONCOMthrow_rev'
Cannot find instance 'TRAMKONRIFturn_right'
Cannot find instance 'TRAMKONOKOlev18_ZomStand'
Cannot find instance 'TRAMKONOKOcorner_hide'
Cannot find instance 'TRAMKONPIScorner_hide'

Ignore them, as those files doesn't exist. (Someday we should remove them from the TRACs.)

Via command line

To export a single TRAM:

onisplit -extract:xml output_path -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname.oni

To export merged TRAMs:

onisplit -extract:xml output_path -anim-merge -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname1.oni  path_to\TRAMnameN.oni

Via Vago

Combined extraction of DAE and XML.

Change to Characters tab and follow these steps.

Step 1: Select "TRAM ONI" as input format ("From").

Step 2: Select "XML / XML & DAE" as output format ("To").

Step 3: Tick checkbox "Extract with TRBS / ONCC". It's important this is done before adding a TRAM file.

Step 4: Set full path of ONCC or TRBS.

Step 5: Add TRAM file.

Step 6: Click "Convert".

Via Simple OniSplit GUI

There was a long-standing problem with combined ONCC/TRAM files where the textures would be missing.

Simple OniSplit GUI post-edits the DAE to fix missing textures. The character-related .oni files must be all in one folder. Usually the level0_Final folder does the trick.

Step 1: Drag and drop the TRAM and ONCC into the big field. (One by one or simultaneously; the order doesn't matter.)

Step 2: Hit "Convert".

Editing 3D data

Blender

See the Blender article for a general tutorial on using the free program to create animations for Oni. It also contains a Blender addon for automating certain tasks, troubleshooting advice, and links to an animation rig that makes animation much easier.

XSI

In the past, the community's preferred tool for any 3D modeling and animation was (formerly "XSI") Mod Tool. However, this free program was discontinued in 2014, and modders did not want to be tied to an aging (not to mention Windows-only) program. Thus, we have generally moved to using Blender (see next section). The following information is preserved for historical purposes.


For the correct Mod Tool settings, see HERE.

Here are some hints for creating animations when there is no rigging available:

  • Use the ONCC model in your 3D editor that will actually make use of the animations. This makes sure that the pelvis height will match and that the character's feet will not float in the air or go through the ground.
  • The first frame and last frames should match the probable previous and follow-up animations. This will reduce the necessity for long interpolations.
  • When setting keyframes, each body part should have moved. This rule of thumb will give a more natural-looking animation.
  • The first body part to be animated is always the pelvis.
  • Watch out for pelvis rotations so that the XYZ rotations don't overlap too much, otherwise you will get into a gimbal lock.

Also see our OCF thread.

Import

onisplit -create output_path path_to\TRAMname.xml

Common operations on animations by the community

Speeding up existing animations

s10k has created an XmlTools script that allows the speed-up of any existing TRAM by removing frames. More information and download link here.

Selected notes on animation types

Attacks

Extents and XML

As a regular modder you don't need to know how the attack ring and the extents get calculated. If you just want to create an attack animation then add an appropriate <Attacks> code block to your XML as seen in the section below.

How attack ring (horizontal extents) and extents get calculated

Ever wondered how the AI can recognize incoming attacks and block or dodge them? Extents (found by geyser and fully uncovered by Neo) are the key. Imagine the character looked at from above, and visualize a circle with this character being at the center of the circle. Now divide this circle into 10° segments, and those are the 36 units of horizontal extents (that is, the lateral reach of the attack). The 0° point is directly in front of the character and 180° is behind the character. The segments run clockwise around the character. So the first Extent tag is the horizontal reach on the 0° line, the second tag is for the line 10° clockwise, and so on. Note that a frontal attack like a simple kick could hit a target not only if he's standing at 0° (directly in front), but also at 10° or 20° to the right, and also at 340° and 350° (a bit to the left). When setting these manually, you should guess the inner and outer ranges of the reach of the attacker's bones that have damage attached to them. Test these values with an AI that blocks often. If you did it right, your attack will often be blocked, but if the extent length is too high, the AIs will react when too far from you, which does not look good.

There are two types of extents:

  • <Extents> stores this info:
<Angle> at which this extent radiates from the character.
<Length> of this extent.
<MinY> minimum height of this extent.
<MaxY> maximum height of this extent.
Length, MinY and MaxY serve to create an invisible area in space which is "dangerous to be in". If an AI intersects with this area and notices it (refer to the Notice field in MELE), it will attempt to block or dodge according to its modifiers in its MELE profile.
The number of <Extent>s is equal to the number of attack frames: <End> minus <Start> plus one (because the start frame counts too). For example, for TRAMKONCOMkick_low1: <End>30</End> minus <Start>22</Start> plus 1 = 9 <Extent>s.
  • <AttackRing> (formerly known as <HorizontalExtents> stores this info:
36 fields (exactly 36, otherwise it won't compile back into a .oni file), which correspond to areas in 10° intervals around the character as described above.

Using OniSplit to calculate extents

Let's say that you want to convert a non-attack animation to a damage-dealing animation. Non-attack TRAMs do not have extents information used to notify the AIs about incoming attacks, so how do you generate this information from the animation?

1. Export the animation to XML with a body attached. If you extract using just "-extract:xml dest_folder TRAMsomething.oni", you'll get the 3D animation data inside the XML (namely, the tags Heights, Velocities, Rotations, PositionOffset, and Positions; for an attack animation, you'll also get Attacks and AttackRing, and inside Attacks' elements, each Attack element will have Extents at the end of it).
However, if you extract this same animation using "-extract:xml dest_folder TRAMsomething.oni -anim-body ONCCtramuser.oni", the animation data will be placed in a DAE file along with the character model geometry. Be sure to pick a body with a size that's representative of the character classes that will actually use this TRAM, because the extents will be calculated from it. The XML file will be very short without the 3D data in it — this is how we want the non-attack TRAM to look. We do not know the extents information that should go in Extents or AttackRing, so we just want to add the part that distinguishes a DAE-extracted attack TRAM XML from a DAE-extracted non-attack TRAM XML. That part is the Attacks section, without the Extents under each Attack.
2. First, consider whether the TRAM should have something added to its Flags section, like Attack or ThrowTarget.
3. Now add to the XML of the non-attack TRAM data in the following format (after the <SelfDamage /> section, typically):
       <Attacks>
           <Attack>
               <Start>1</Start>
               <End>10</End>
               <Bones>RightWrist RightFist</Bones>
               <Flags />
               <Knockback>4</Knockback>
               <HitPoints>10</HitPoints>
               <HitType>KnockdownHead</HitType>
               <HitLength>5</HitLength>
               <StunLength>8</StunLength>
               <StaggerLength>0</StaggerLength>
           </Attack>
       </Attacks>
Do not add an AttackRing section after Attacks.
4. Import this with "-create dest_folder TRAMsomething.xml". The Extents sections and the AttackRing will be calculated by OniSplit from the attached DAE.
5. If you need this information for a patch mod, run "-extract:xml" on the TRAMsomething.oni you've created without using "-anim-body". Now you can copy the Extents and AttackRing data to your XML patch. For an example of how the patch should look, see the Domino Knockdowns mod.

Combos

The type and order of player input for triggering a given animation type (such as PPK) is hardcoded, and new animation types cannot be created. That being said, Oni has unused combo animation types, such as PKP, PKK, KPK, KPP, etc. that work perfectly fine and can be used to create new combos. To assign an animation type to a specific combo attack, you set a corresponding value in <Lookup><Type>.

Setting a value in the <Link> of <DirectAnimations> will do two things:

  1. It will increase the time window for player input, meaning the next animation can be executed more easily. (In vanilla Oni, the Crescent Moon Kick has no link in KONCOMcomb_k_k_kfw and therefore is difficult to use.)
  2. It disables <Interpolation><End> for the next combo anim.
  3. It enables <Pause><Soft> and <Pause><Hard>.

Just Frame input

Implemented by Delano762, inspired by the game series Tekken, a Just Frame ("JF") move means that you have to press certain keys (W+K or W+P) at the exact same time, which is more difficult than it might sound. Delano's mod 54000 New Combat Moves for Konoko has a collection of animations which utilize existing animation states differently to create new moves.

Example 1:

  • new forward kick = TRAMKONCOMkick_fw_JF <FromState>Standing
    • key strokes: w + k
  • old forward kick = TRAMKONCOMkick_fw <FromState>RunStart
    • key strokes: w, k

Example 2:

  • new forward punch = TRAMKONCOMpunch_fw_JF <FromState>Standing
    • key strokes: w + p
  • old forward punch = TRAMKONCOMpunch_fw <FromState>RunStart
    • key strokes: w, p

Note that these animations are referred to as JF moves, not JF combos. The Crescent Moon Kick, as mentioned above, is an unintentional JF combo found in vanilla Oni.

Throws

States

The first anim state of source (src) and target (tgt) is the "primary" <FromState>. The others <FromState> entries are located in <Shortcut>.

Types

Throw target animations are registered in the TRAC of the throw initiator (AKA the throw source). Target animations are forced onto the other character. Throw target (TRAM*tgt) animations can only cover up to 256 frames (0-255).

The game identifies which Target animation is it supposed to play through the ThrownX animation types. Each throw, together with its corresponding Target animation, uses one of the 17 available ThrownX animation types. These types are used in three tags:

  • <TargetType> tag in the Source animation,
  • <Type> and <AimingType> tags in the Target animation.

For example, Konoko's forward punch throw / KONCOMthrow_fw_p uses Thrown1 as its TargetType tag:

           <TargetType>Thrown1</TargetType>

And the corresponding target animation, KONCOMthrow_fw_p, uses Thrown1 in the Type and AimingType tags:

           <Type>Thrown1</Type>
           <AimingType>Thrown1</AimingType>

The ThrownX anim types work like slots - if you want to add a new throw to the game, you have to assign both the Source and the Target animations the same ThrownX type in the tags listed above. While these "pairs" are organized within vanilla animations according to the Throw Table below, this is nothing more than a convention, and as a result ThrownX types can be used freely. To give an example, while all Forward Punch Throws in the game seem to use the Thrown1 type, you can swap those types with another throw and they will work just as fine.

The fact that the game has only 17 ThrownX types is a major limitation - this effectively means that each character can have no more than 17 throws - out of which only 4 are unused by any character in the game. This prevents modders from creating a significant number of throws despite the game allowing great flexibility in creating new throws by mixing Animation States, Animation Types and <Varient> tags.


Running disarms

Oni offers support for running disarms (originally noticed HERE), which was taken advantage of by Delano's mod 54000 New Combat Moves for Konoko.

Forward throws

Scenario: You load two characters into Mod Tool and rotate (+/-180°) the throw target character because you need them to stand face to face as you work on an animation. When you are done animating, the target animation would need to be reversed again. This means multiplying the velocities by -1; the rotation also needs correcting. So it looks like you need *(-1) for the x rotation and -/+180° (depending on your initial change) for the Y rotation.

There is a Blender script implemented within the BlenderOni addon for rotating and adding PositionOffset to a forward throw Target animation. It is capable of adjusting both forward and back throws. The script's old version can be accessed HERE.

Run animations

Here's a breakdown of the Striker's run animations, meant as an illustration for what would be needed to make new run TRAMs.

Run cancel:

  • STRIKEidle1 / another idle animation
  • STRIKErun1stepa
  • STRIKErun1stepb
  • STRIKEidle1 / another idle animation

Run – a minimal cycle:

  • STRIKEidle1 / another idle animation
  • STRIKErun1stepa
  • STRIKErunstart
  • STRIKErun_rt
  • STRIKErun_lt (optional)
  • STRIKErunstop
  • STRIKEidle1 / another idle animation

Follow the images below from right to left.

List of unused animations

Here are all the known unused animations. These could be recycled in a new mod.

From the original game

  • KONOKOconsole_punch: What the name says (the engine can use that animation depending on the console's configuration, see CONS) .
  • KONOKOlev3_intro: Looks like she's placing something (bomb?) and then running away.
  • KONOKOlev4_undress: From an aborted clothes-changing cutscene.
  • KONOKOlev16_bomb: Planting a bomb.
  • KONCOMsuper_kick: Now used in OTA as a spawn event, and by the fan-made character Shinatama Evolved.
  • KONCOMsuper_punch: KONCOMpunch_heavy but without the shouted attack name, has HalfDamage flag, and does 10 less damage in its first attack part.
  • COMPISidle_special1: Comguy checking environment and his gun; meant for a feature that would visually depict an elevation in the AI's level of alertness after, say, hearing a noise.
  • STRPISidle_special1: Striker checking his his gun and communicating with an ally (another unused alertness-elevation animation).
  • THUGlev1_direct: Thug probably directing a truck driver.

From modders

Char A and Char B performing stun animations.
  • http://mods.oni2.net/node/376
    • StrikerKneeStepKickThrow.zip
    • REDCOMjump_fw_crouch--double_flip--dae.zip
    • KONprone_getup--dae.zip
    • KONRIF_k_bk_throw.zip
    • female_stun--dae.zip

Special effects

If the scene is overloaded by too many particles (including motion blur), these effects will cease being rendered. So don't overuse effects.

Color trails

Open the XML-accompanied TRAM, search for the "Particles" tag, and insert your markup.

First example: TRAMSTRCOMcomb_p_p.xml

Colorful contrail added.png
       <Particles>
           <Particle>
               <StartFrame>0</StartFrame>
               <EndFrame>12</EndFrame>
               <Bone>LeftFist</Bone>
               <Name>contrail</Name>
           </Particle>
       </Particles>

"contrail" is looked up by the character class (ONCC) that emits the actual particle; here it is "h2h_strtrail_e01".

This second example is about creating two different contrails in a TRAM at the same time. The animation is "TRAMSTRCOMpunch_heavy.xml".

Different contrails in attack.png
       <Particles>
           <Particle>
               <Start>0</Start>
               <End>54</End>
               <Bone>RightWrist</Bone>
               <Name>contrail</Name>
           </Particle>
           <Particle>
               <Start>0</Start>
               <End>54</End>
               <Bone>LeftWrist</Bone>
               <Name>contrail_2</Name>
           </Particle>
       </Particles>

Note that you need to register the second contrail in the ONCC as well. Using your own contrail particle is also possible; just insert its name between the <Type> tags.

           <ONCPParticle>
               <Name>contrail</Name>
               <Type>h2h_strtrail_e01</Type>
               <BodyPart>-1</BodyPart>
           </ONCPParticle>
           <ONCPParticle>
               <Name>contrail_2</Name>
               <Type>h2h_murtrail_e01</Type>
               <BodyPart>-1</BodyPart>
           </ONCPParticle>

Motion blur

XML TRAM willow kick with motion blur.jpg

Motion blur in Oni works much like ghosting/onion skinning features in any animation software: In the frame range specified by <Start> and <End> an additional instance of body parts specified in <Bones> are rendered for additional extra frames specified by <Lifetime>, with transparency set by <Alpha>, and every <Interval> frames within the frame range. Example snippet from KONCOMcomb_p_p_k:

       <MotionBlur>
           <MotionBlur>
               <Bones>RightThigh RightCalf RightFoot</Bones>
               <Start>20</Start>
               <End>28</End>
               <Lifetime>4</Lifetime>
               <Alpha>127</Alpha>
               <Interval>1</Interval>
           </MotionBlur>
       </MotionBlur>

The one noteworthy thing is that you can have multiple motion blur sequences. If you wanted to add an extra motion blur to the above animation, you could do something like this:

       <MotionBlur>
           <MotionBlur>
               <Bones>LeftThigh LeftCalf LeftFoot</Bones>
               <Start>10</Start>
               <End>18</End>
               <Lifetime>4</Lifetime>
               <Alpha>127</Alpha>
               <Interval>1</Interval>
           </MotionBlur>
           <MotionBlur>
               <Bones>RightThigh RightCalf RightFoot</Bones>
               <Start>20</Start>
               <End>28</End>
               <Lifetime>4</Lifetime>
               <Alpha>127</Alpha>
               <Interval>1</Interval>
           </MotionBlur>
       </MotionBlur>

Impact effect

Impact effects – mostly particle – are chosen based on logic written within ONIE. Furthermore particles must be registered in ONCC: You probably want to look at ONIA instead of ONCP.

XML TRAM KONCOMkick fw with ninflash1.jpg