XML talk:TRAM: Difference between revisions

From OniGalore
Jump to navigation Jump to search
m (→‎Parts of page in need of updating: marking motion blur item as completed; a couple suggested changes to Paradox's words to try to clarify, please correct me if I'm wrong)
m (yoink)
Tag: Blanking
Line 1: Line 1:
==Parts of page in need of updating==
I've placed the "update" template on this article for the following reasons:
*<strike>The Vago documentation is for v0.8 and is obsolete.</strike>
*<strike>The part about Blender just says that it's theoretically possible to use the program for animations! Link to a modern tutorial please.</strike>
*<strike>The part about extents says that Neo will have to make OniSplit calculate them automatically; doesn't it do that now?</strike>
:: Yes, it does. I compared a pure XML extraction against a round-tripped XML-DAE-extraction: The DAE companioned XML gets extracted with no attack ring and extents, so for this test XML and DAE can converted straight back to ONI file format and re-extracted as pure XML. Conclusion: OniSplit creates attack ring and extents from DAE data, IMHO the new attack ring and extents match the original data not perfectly but still pretty good. '''--Paradox'''
*<strike>The "Excel macro" should be rewritten as stand-alone application. Also, its support for XSI should be dropped in favor of blender.</strike>
:: That's the theory. Until OniX is ... ahem ... a game changer, there will be probably no demand for this. A similar note was added on the non-talk page. '''--Paradox'''
*This talk page needs an updating too! The material should be incorporated into the article or deleted.
--[[User:Iritscen|Iritscen]] ([[User talk:Iritscen|talk]]) 00:12, 17 March 2021 (CET)


Additionally to the updates, I'd say the TRAM page should be marked "complete" when following things are done:
* <strike>motion blur (mini tutorial?)</strike>
* impact effects (mini tutorial?)
* TRAM picking mechanism: it gets easier to explain this mechanism if we differentiate between pool construction and pool usage
* throw pair animation table
* a simple tutorial to let a modder warm up with animations in Blender (it's okay if it rather resembles "round trip") since this page is about the file type itself (therefore: import and export)
--[[User:Paradox-01|paradox-01]] ([[User talk:Paradox-01|talk]]) 16:53, 15 March 2023 (CET)
==Throw pair animation table==
This is like the player's combat animation table - but for modders.
Source and target anim types (pairs) aren't named in an intuitive pattern: Using "forward" and "backward" in throw names can be ambiguous for newbies. For example Konoko can throw a foe seemingly '''backwards''' by her '''throw forward kick''' (TRAMKONCOMthrow_fw_k). Therefore we should also describe throws how "source" and "target" are facing each other.
The first anim state of source (src) and target (tgt) is the "primary" <FromState>. The others <FromState> entries are located in <Shortcut>.
ToDo: Add explanations for each section. Split table to have header for each section.
{| 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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
<!--
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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
|-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|400px]]
|-style="vertical-align:top;"
|<!--names--> (never used)
|<!--key combo-->
|<!--varient-->
|<!--src state-->
|<!--tgt state-->
|<!--facing setup-->
|<!--anim type src-->
|<!--anim type tgt--> Thrown17
|<!--image-->
|}
Looks like there was/is support for [[OBD:BINA/OBJC/MELE/MoveList/Throw|running disarms]]. Though unused types for new Thrown''N'' would be needed.
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 ommitted 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 unkown context, possibly this is similar or part of the distiction 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...
==Variants==
Further research needed.
* 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 (varient [sic]) pickup system is not clear yet: is a RIFCOM idle and a RIFNAT idle both possible?
** Or do rightpistole, leftpistol, rightrifle and leftrifle variants count as subsets of combat?
==TRAM picking mechanism==
: Older brain dump.
Animations never stop, they flow from one to another. (See also: concept of state machines in gaming.)
The default case is a character getting spawned and then just standing there, he idles.
This brings us to the core attributes of an animation: '''type, state, variant'''. (In XML it is varient. [sic])
:Theoretically you could recycle all attribute and build your own animation system, but that would not much practical.
:The prone mode mod is an exception, in the context of the existing system it can be considered a logical expansion where BSL handles the transition.
Now then, the idle animation does not link to a specific followup animation - or for short "anim" - it rather links to a state being followed.
: Ironically all anims have a <FromState> and a <ToState>, but no obvious <CurrentState> which can cause confusion on what the current anim actually is.
: This gives us two options of how to think of the situation: either consider <FromState> being usually the <CurrentState>, or states exist only between anims and serve as transition rules.
Linking to a followup '''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 TRAC''' - the anim collection.
The Ninja's Moonwalk anim (taunt2) has only a 5/(100+5)*100 = 4,76 % chance of getting picked.
            <TRACAnimation>
                <Weight>100</Weight>
                <Animation>TRAMNINCOMtaunt1</Animation>
            </TRACAnimation>
            <TRACAnimation>
                <Weight>5</Weight>
                <Animation>TRAMNINCOMtaunt2</Animation>
            </TRACAnimation>
There's also a rare chance that Mai will sneeze if she stands for a long time.
Here's the sneeze anim with Weight 100, but the real chance of getting picked is still low. Why?
            <TRACAnimation>
                <Weight>100</Weight>
                <Animation>TRAMKONOKOidle_spec3</Animation>
            </TRACAnimation>
That's because all '''idle anims''' are in fact of '''type Stand''' while Konoko's '''idle_spec3''' is of '''type Idle'''.
The chance of idle type anims to be picked up is determined by ONCC values in <IdleAnimation1Timer> and <IdleAnimation2Timer>.
Anyway, to let an character flow from one anim state to another the <ToState> is used.
Let's say a SBG grenade hits Konoko. The particle's '''damage type''' is '''blownup''', this and the direction of damage force an anim of type '''Blownup''' or '''BlownupBehind''' to play like TRAMKONOKOblownup1.
This all simply means she falls to her back, going into the FallenBack state. The engine picks up next anim with <FromState>FallenBack.
Also, '''receiving damage''' puts the character into '''Combat mode''' so further anims will be of variant Combat.
But if the player gives no input Mai will remain on the ground as <ToState>FallenBack creates a loop.
Question: Why is KONCOMgetup_lt not played automatically since it also has <FromState>FallenBack and <Varient>Combat?
It differs in its <Type>. Obviously most [[XML_talk:StNA|anim types are bound to user input]] and therefor are excluded from the automatically created pool of valid anims to follow.
A left mouse turn tells the engine to use an anim of type StandingTurnLeft.
This is true for KONOKOcomb_turnlt and KONCOMgetup_lt but only the latter matches the current <FromState> condition.
: KONOKOcomb_turnlt has in fact <Varient>Combat, comb stands here for combat, not combo. Following Oni's naming convention, the file should have been named KONCOMturn_lt.
Knowing this behavior we can deduce that anims types registered to user input will make the engine ignore all the automatic anims inside the pool, therefor breaking the loop of KONCOMfallen_back.
Since KONCOMgetup_lt has <ToState>Standing and Konoko is still in Combat mode the following idle anim must also have <Varient>Combat.
So, next anim played will be KON'''COM'''idle1 or KON'''COM'''idle2.
Konoko will eventually calm down when her ONCC<FightModeTimer> run down and then KON'''OKO'''idle1 or KON'''OKO'''idle2 will be played.
Actually the COMidle will continue until an non-combat anim will break that loop.
That is the fallback behavior of anims getting picked: if the engine cannot find an anim for an active variant (or "mode") it will choose the normal (non-variant) 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.
[...]
==Problem with exporting a textured character with non-native TRAC animation==
This problem occurs with OniSplit v0.9.99.0 and earlier.
There are basically two commands:
OniSplit -extract:dae outputPath -anim:TRAMname.oni inputPath/ONCCorTRBSname.oni
OniSplit -extract:xml outputPath -anim-body:inputPath/ONCCorTRBS.oni inputPath/TRAMname.oni
First one cannot export TRAMs that aren't listed in character's TRAC.
The second cannot export characters with textures at all.
A textual comparison with WinMerge reveals that the outputs of native TRAMs are almost the same.
[[Image:comparing_different_anim_exports_in_winmerge.png|right|thumb]]
Except the chunks of <library_images>, <library_effects> and <library_materials> are missing in the second dae.
It follows <visual_scene> where the id has a different name which is not that interesting.
Inside, there are <instance_geometry> nodes which are pretty much empty for the second dae.
I restored only a few bones. Proof of concept.
In other words: for a complete textured and animated character you need to post-edit the dae which is actually xml code.
If we doesn't get Neo to fix it we will have to export the character twice automatically and let the OniSplit GUI provide the final dae.
I added a "Repair character textures" option to "Simple OniSplit GUI", though that feature wasn't tested very much.
==old==
===how convert dae to xml / oni ...===
====... using batch files====
'''[http://mods.oni2.net/system/files/dae_xml_oni_help.zip Download]''' this modding ''environment'' so you know that the following lines are about.
Before you can run those files you need to put your source files into the "input_folder".
"dae + xml(not 41) to oni.bat" will generate files with '''Q'''Keys.
"dae to xml(41).bat" will generate files with '''E'''Keys.
====... using the Windows address bar====
If you use the windows address bar you should have onisplit always alongside your essential modding folders to have short commands like
: onisplit41 -create:tram output_folder input_folder/*.dae
We want to type as less as necessary, don't we? =)
====... using onisplit GUI====
Keep in mind that the GUI is only a mask for onisplit. New onisplit versions - v0.52.9.0 or newer don't have the command -create:tram.
====normal animations====
You can convert such animation by choosing one of the two methods. (normal = no overlay anims)
: - To create QKeyed-animation you need a helper xml file to be placed alongside the dae animation file.
: - EKeyed-animations don't need a helper xml file but edits afterwards the creation.
In any case the amount of needed hand work is quite the same for both methods.
QKeyed-animation refuse to become edited. There's somehow a bug like Samer pointed out on the forums. (Is this still the case? - 5th Dec 2011) But that's not so tragic. You can edit the dae or the xml helper file and then merge them into an oni file again.
Like EdT said an advantage of the xml helper method is that you can breakdown a single dae file into smaller pieces. It's a comfortable way to create multiple animations from one source. E.g. you make combo animations in one dae - let's say punch (p), kick '''[[XML:StNA#animation_types|(pk)]]''', punch (pkp) - then you make 3 xml helpers. First file goes from frame 0 to 40, second file from 41 to 86, and third file from 77 to 140. The dae file has 120 frames but not the 3 oni files that will be created.
Some lines for the hypothetical second combo animation:
    <DaeImport>
            <Path>TRAM######combo.dae</Path>
            <Start>41</Start>
            <End>78</End>
        </DaeImport>
        <Lookup>
            <Type>PK</Type>
            <AimingType>PK</AimingType>
            <FromState>Standing</FromState>
            <ToState>Standing</ToState>
            <Varient>Combat</Varient>
            <FirstLevel>0</FirstLevel>
            <Shortcuts />
        </Lookup>
        <Flags>Attack</Flags>
Don't forget to add types, variants, particle etc. to your xml file before you convert it to the oni format.
====testing the created files====
Either put them into an AE package or create a plugin.
[[#..._using_batch_files|There's]] a batch file available that create level0 plugins. Put the created plugin files in your GameDataFolder and run the game.

Revision as of 07:04, 10 October 2023