<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.oni2.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vortice</id>
	<title>OniGalore - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.oni2.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vortice"/>
	<link rel="alternate" type="text/html" href="https://wiki.oni2.net/Special:Contributions/Vortice"/>
	<updated>2026-04-06T10:43:32Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=User:Paradox-01/South_Africa_Syndicate_HQ&amp;diff=43863</id>
		<title>User:Paradox-01/South Africa Syndicate HQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=User:Paradox-01/South_Africa_Syndicate_HQ&amp;diff=43863"/>
		<updated>2025-01-23T01:01:40Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains dead or broken links.}}&lt;br /&gt;
Had an [[User:Paradox-01/Accessible_sniper_tower|alternate version of accessible sniper tower]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:South_Africa_Syndicate_HQ.png|Draft 1&lt;br /&gt;
Image:South_Africa_Syndicate_HQ_collage.png|Draft 2 (lost)&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Backup===&lt;br /&gt;
Draft 1:&lt;br /&gt;
* https://assets.adobe.com/public/b7f2d20e-5e8c-439e-46ef-5db4ba5f2c5c&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding projects‎]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Blender&amp;diff=43862</id>
		<title>Blender</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Blender&amp;diff=43862"/>
		<updated>2025-01-22T22:43:34Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: History of Modding with Blender}}&lt;br /&gt;
Blender is a free and open-source program used for 3D modeling, animating, rigging, texturing, video editing, digital drawing, etc. It is the community&#039;s current 3D software of choice for modding Oni.&lt;br /&gt;
&lt;br /&gt;
==History of modding with Blender==&lt;br /&gt;
[[Mod Tool|XSI Mod Tool 7.5]], a free version of Autodesk Softimage from 2009, had the fewest problems in handling Oni&#039;s assets and animations, it was relatively easy to learn and use. Up until 2019, it was Oni community&#039;s 3D program of choice.&lt;br /&gt;
&lt;br /&gt;
Blender at that time had a notoriously bad user interface and couldn&#039;t handle DAE files very well. [[#Oni-specific_issues_with_Blender|Besides other problems]], most importantly the expected rotation order and up-axis were different between XSI and Blender.&lt;br /&gt;
&lt;br /&gt;
After an interface overhaul in version 2.80 Blender&#039;s user-friendliness and [http://oni.bungie.org/forum/viewtopic.php?pid=52588#p52588 support for vertex shading in DAE] was improved. At the same time more and more users had problems to run XSI on their PCs.&lt;br /&gt;
&lt;br /&gt;
By 2019 demands got louder to support Blender made animations. [[OniSplit]] received an update (&amp;lt;tt&amp;gt;-blender&amp;lt;/tt&amp;gt;) so it could read such animations. Also, rigging was never fully figured out in XSI so between 2020 and 2022 an [[Using the Rigify animation rig|animation rig]] tailor-fit for making Oni animations - alongside a new addon named [[BlenderOni]] - was created. It was the last nail in the coffin of XSI.&lt;br /&gt;
&lt;br /&gt;
==Tutorials and resources==&lt;br /&gt;
With the abundance of tutorials for Blender on YouTube, creating our own introductory material would be reinventing the wheel. So instead we recommend watching some of the tutorials listed below and trying to make small personal projects in order to get familiar with Blender, such as modeling simple objects like teddy bears or tables.&lt;br /&gt;
&lt;br /&gt;
General Blender basics:&lt;br /&gt;
* [https://www.youtube.com/watch?v=RG8qK5zPqgM Wolf&#039;s 45-Minute Crash Course for Blender Virgins] (don&#039;t be misled by the silly name - this is one of the best Blender basics tutorials out there; it&#039;s also good if you know your basics already and you want to find out if you&#039;ve missed anything)&lt;br /&gt;
&lt;br /&gt;
Modelling:&lt;br /&gt;
* [https://www.youtube.com/watch?v=1jHUY3qoBu8 Learn Low Poly Modeling in Blender 2.83 (Imphenzia)]&lt;br /&gt;
&lt;br /&gt;
Rigging:&lt;br /&gt;
* [https://www.youtube.com/watch?v=vKgH5zXIYmM Rigify (CGDive)]&lt;br /&gt;
&lt;br /&gt;
Documentation:&lt;br /&gt;
* Blender has excellent documentation, available [https://docs.blender.org/manual/en/dev/modeling/meshes/editing/face/index.html HERE]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
[[Image:Blender_2.8_Python_Tooltips.png|thumb]]&lt;br /&gt;
You may want to go to the preferences and switch on &#039;&#039;&#039;Python Tooltips&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Contrary to what you might expect, the &#039;&#039;&#039;Developer Extras&#039;&#039;&#039; do not give you additional Python functionality per se. Instead this option enables experimental Blender features.&lt;br /&gt;
&lt;br /&gt;
Related videos:&lt;br /&gt;
* [https://www.youtube.com/watch?v=XqX5wh4YeRw&amp;amp;t=46s Python Crash Course for Blender! (Curtis Holt)]&lt;br /&gt;
* [https://www.youtube.com/watch?v=uahfuypQQ04 Blender 2.8 Addon Development Tutorial for Beginners (Jayanam)]&lt;br /&gt;
&lt;br /&gt;
==Animation rig with IK and FK==&lt;br /&gt;
Currently we have an animation rig available in the form of a Blender scene available [http://mods.oni2.net/node/388 HERE]. The rig was made by Geyser and Delano762, and a tutorial on how to use it is available [[Using the Rigify animation rig|HERE]]. The rig is based on the Rigify plugin for Blender and serves as the &#039;&#039;&#039;community&#039;s modern tool to create new character animations for Oni&#039;&#039;&#039;, featuring both Forward and Inverse Kinematics – an enormous improvement over the previous FK-only method of animating.&lt;br /&gt;
&lt;br /&gt;
This rig is intended to be used together with [[#BlenderOni|BlenderOni]], a Blender addon designed as a companion tool for it – &#039;&#039;&#039;without it, the rig is extremely difficult to set up, to the point of being almost useless.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The rig has the following capabilities (which come with Rigify by default, unless otherwise noted):&lt;br /&gt;
* Snapping to Oni animations through bone constraints controlled by the Z location of the objects in the Pose Matching layer (added feature)&lt;br /&gt;
* Inverse and Forward Kinematics (IK and FK)&lt;br /&gt;
* Snapping between IK and FK chains&lt;br /&gt;
* Function to snap IK hand controller rotation to the wrist bone, integrated into rig_ui.py (added feature)&lt;br /&gt;
* IK joint poles for specifying limb joints (elbows and knees) should be facing&lt;br /&gt;
* Sliders specifying how much the neck, head and FK limbs should retain their world space rotation – that is, Neck Follow, Head Follow and FK Limb Follow&lt;br /&gt;
* IK foot pivoting controllers around toes and the heel&lt;br /&gt;
* Root bone&lt;br /&gt;
&lt;br /&gt;
===Tutorial for creating animation rig===&lt;br /&gt;
If you want to create the above rig, and learn a bit about rigs, IK/FK, Rigify, Blender, bone layers, bone constraints, scripts, issues with Oni models and animations such as the rotation order being incompatible with Blender, see [[Creating an animation rig in Blender]].&lt;br /&gt;
&lt;br /&gt;
==BlenderOni==&lt;br /&gt;
BlenderOni is a Blender addon intended as an integral companion tool for the fan-made animation rig for Blender. It contains functionalities that automate a lot of operations necessary for the rig to function and be used properly. However, the vast majority of the addon&#039;s options can also be used for general Blender purposes.&lt;br /&gt;
&lt;br /&gt;
For more information on BlenderOni, please check its documentation page available [[BlenderOni|HERE]].&lt;br /&gt;
&lt;br /&gt;
==Blender-specific OniSplit information==&lt;br /&gt;
For detailed instructions on how to convert Oni assets to Blender-readable files, please check [[Importing_character_models#Blender-specific_OniSplit_information| Blender-specific OniSplit information.]]&lt;br /&gt;
&lt;br /&gt;
==Oni-specific issues with Blender==&lt;br /&gt;
===Fixing texture mapping of DAE files===&lt;br /&gt;
Replace all instances of &amp;lt;technique&amp;gt; with &amp;lt;technique sid=&amp;quot;common&amp;quot;&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Rotation order===&lt;br /&gt;
The previous XSI process allowed us to get to work pretty quickly: you could simply export any animation from Oni as a COLLADA file using OniSplit, then import it to XSI and it would work (mostly) without any quirks. That is not the case with Blender. If you import any Oni animation into Blender as it is, the rotations will be all wrong.&lt;br /&gt;
&lt;br /&gt;
That&#039;s because Oni&#039;s rotations are stored in XYZ Euler rotation order, while Blender&#039;s XYZ is actually ZYX despite being called &amp;quot;XYZ&amp;quot;; this is because Blender reads the Euler angles [https://docs.blender.org/manual/en/latest/advanced/appendices/rotations.html from the bottom of the hierarchy] rather than the top. In other words, Oni reads XYZ starting with X, while Blender starts with Z.&lt;br /&gt;
&lt;br /&gt;
You can demonstrate this by simply switching the rotation order of the body parts from XYZ to ZYX, as shown below. The image on the left shows KONCOMcomb_p imported to Blender without any adjustments, with the rotation order set to Blender&#039;s default &amp;quot;XYZ&amp;quot;, while the image on the right shows the same animation after switching the rotation order to ZYX.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! KONCOMcomb_p in Blender&#039;s XYZ !! KONCOMcomb_p in ZYX&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:ARB KONCOMcomb p XYZ.png|500px|frameless]]&lt;br /&gt;
| [[Image:ARB KONCOMcomb p ZYX.png|500px|frameless]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Because of this, geyser implemented the &#039;&#039;&#039;-blender&#039;&#039;&#039; argument in OniSplit, which solves this problem by converting Oni assets&#039; rotation order from XYZ to quaternions and then to ZYX, and vice versa when exporting assets from Blender to Oni. So that conversion flow looks as follows:&lt;br /&gt;
&lt;br /&gt;
*From Oni to Blender:&lt;br /&gt;
XYZ → Quaternions → ZYX&lt;br /&gt;
&lt;br /&gt;
*From Blender to Oni:&lt;br /&gt;
ZYX → Quaternions → XYZ&lt;br /&gt;
&lt;br /&gt;
To summarize: &#039;&#039;&#039;Always use the -blender argument when you&#039;re exporting assets from Oni to Blender&#039;&#039;&#039;, otherwise you can expect the problem shown in the above screenshots.&lt;br /&gt;
&lt;br /&gt;
===Differing up-axis===&lt;br /&gt;
To be expanded on later: Oni&#039;s &amp;quot;up&amp;quot; axis is Y, Blender&#039;s is Z.&lt;br /&gt;
&lt;br /&gt;
===Units===&lt;br /&gt;
To be expanded on later: Oni&#039;s units are in the imperial system, not the metric one, though the 0.1-meter unit used by OniSplit is a good approximation of Oni&#039;s actual world unit of 4 inches.&lt;br /&gt;
&lt;br /&gt;
===Lack of textures on animated models===&lt;br /&gt;
&#039;&#039;&#039;Currently there is no option in OniSplit for exporting animated models with textures in a way that Blender will import.&#039;&#039;&#039; While you don&#039;t need textures for animating, they are very useful, particularly in the case of Oni; the models are low-detail to a point where you can lose sense of which direction elbows and knees are facing if you don&#039;t have the textures on. &lt;br /&gt;
&lt;br /&gt;
Because there is no option to export animated models with textures, &#039;&#039;&#039;the current workaround for that is to import an unanimated model with textures, then import an animated model,&#039;&#039;&#039; and either copy materials from the unanimated model to the animated one (the faster method), or set the materials on the animated model manually in the Shading tab.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Copying materials&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:ABR_Copying_materials.png|200px|frameless|center]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Alpha transparency issue===&lt;br /&gt;
You will also most likely need to set the Shading settings on some of the body parts of a non-animated model in order to fix alpha transparency issues (much like in XSI); specifically, you&#039;ll need to connect the Alpha parameter of the Base Color node to any parameter in Principled BSDF that will work, such as Emission Strength (this should be set up differently as that&#039;s technically incorrect, but I don&#039;t know how to do so at this moment).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Konoko upon importing to Blender !! Fixed transparency&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:ABR Konoko broken alpha.png|200px|frameless|center]] || [[Image:ABR_Konoko_fixed_alpha.png|200px|frameless|center]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Wanted==&lt;br /&gt;
Except for sounds, textures and text-oriented resources, Blender has the potential to be THE editor for Oni. Its powerful Python support is very useful for customization.&lt;br /&gt;
&lt;br /&gt;
Additional imports/exports, XML/.oni file creation and configurations should be automated, and customization should be used to streamline workflows as much as possible. Tools in the form of addons should allow users to be artists instead of coders, speeding up development of the actual projects.&lt;br /&gt;
&lt;br /&gt;
A successful modding community requires not one of these points, but all of them: documentation, tools and tutorials.&lt;br /&gt;
&lt;br /&gt;
===Level editor===&lt;br /&gt;
* core geometry&lt;br /&gt;
* pathfinding&lt;br /&gt;
* &amp;quot;furniture&amp;quot; (OFGA) creation/placement&lt;br /&gt;
* editing of CJBO&lt;br /&gt;
* special gunk flag placement&lt;br /&gt;
* basic level shading (vertex shading)&lt;br /&gt;
* advanced level shading for OniX?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OFGA library&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Objects that are used pretty often should be provided either by Blender Asset Browser or by a customized solution.&lt;br /&gt;
* Blender Asset Browser video demo: https://www.youtube.com/watch?v=gJC0y6HqyAU&lt;br /&gt;
&lt;br /&gt;
===BSL editor===&lt;br /&gt;
Most events in Oni are fired using trigger volumes. There should be an editor to open the code of a trigger volume as soon as it&#039;s selected in Blender.&lt;br /&gt;
&lt;br /&gt;
Also, character functions should editable when you select a character.&lt;br /&gt;
&lt;br /&gt;
The editor should be context-sensitive to:&lt;br /&gt;
* level geometry: atmosphere, save points, win level, lose level&lt;br /&gt;
* objects: scripting of static and animated objects (cutscene editor)&lt;br /&gt;
* particle scripting&lt;br /&gt;
* character: after selecting a character there should be a button visible to edit the ONCC, TRBS, animations and textures (GIMP/Photoshop).&lt;br /&gt;
&lt;br /&gt;
===Character editor===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Character library&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There should be a way to place characters or character placeholders so that character collections (BINACHAR) can be saved to disk based on their positioning in the level model.&lt;br /&gt;
&lt;br /&gt;
===Animation editor===&lt;br /&gt;
The core would be BlenderOni that is called as soon as a user chooses to create or edit an animation. It could be extended to edit TRAC.&lt;br /&gt;
&lt;br /&gt;
===Particle editor===&lt;br /&gt;
A particle editor has been always missing in the community.&lt;br /&gt;
&lt;br /&gt;
===Testing and publishing support===&lt;br /&gt;
There should be some linking to Vago and AEI for package creation and quick starting of levels for testing.&lt;br /&gt;
&lt;br /&gt;
A secondary Oni installation could serve as a developer environment where only one level is present at a time. With OniX, it could be made possible to skip the menu UI and automatically load the current project.&lt;br /&gt;
 &lt;br /&gt;
[[Category:Bi-platform modding tools]][[Category:Completed modding tools]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Graphics&amp;diff=43861</id>
		<title>Graphics</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Graphics&amp;diff=43861"/>
		<updated>2025-01-22T22:33:32Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Occlusion -&amp;gt; Raycasting}}&lt;br /&gt;
Here are explanations of various aspects of Oni&#039;s graphical code.&lt;br /&gt;
&lt;br /&gt;
==Environment mapping==&lt;br /&gt;
:Wikipedia: [[wp:Reflection mapping|Environment mapping]]&lt;br /&gt;
It&#039;s a technique to simulate reflectivity: the diffuse texture is mapped using regular texture coordinates (UVs), and there&#039;s an additional texture layer, the UVs for which are generated from the vertex normals and the orientation of the object in space (and, ideally, the orientation of the camera). While env mapping is the most advanced shader in Oni, it&#039;s about the worst implementation of env mapping there ever was (the projection is planar and the camera angle is not taken into account at all).&lt;br /&gt;
&lt;br /&gt;
==Fog==&lt;br /&gt;
:See [[BSL:Frustum_and_fog]] on how to alter fog using [[BSL]].&lt;br /&gt;
:&#039;&#039;In mid-to-late 1990s games, when processing power was not enough to render far viewing distances, clipping was employed. However, the effect could be very distracting since bits and pieces of [objects] would flicker in and out of view instantly; by applying a medium-ranged fog, the clipped polygons would fade in more realistically from the haze.&#039;&#039; — [[wp:Distance fog|&amp;quot;Distance fog&amp;quot;]], Wikipedia&lt;br /&gt;
:&#039;&#039;For more technical information on fog and on frustum-based space (or whatever it&#039;s called), see [https://learn.microsoft.com/en-us/previous-versions/ms537113(v=vs.85)?redirectedfrom=MSDN here] and [https://learn.microsoft.com/en-us/windows/win32/direct3d9/pixel-fog?redirectedfrom=MSDN here] and [https://web.archive.org/web/20130520191527/http://cs.fit.edu/~wds/classes/graphics/PTOC/ptoc/ elsewhere].&lt;br /&gt;
&lt;br /&gt;
The frustum (see below) defines a set of coordinates in which the near plane is at &amp;lt;tt&amp;gt;Z = 0&amp;lt;/tt&amp;gt; and the far plane at &amp;lt;tt&amp;gt;Z = 1&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;X = -1&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;X = 1&amp;lt;/tt&amp;gt; correspond to the left and right side of the frustum; the top and bottom of the frustum are planes with &amp;lt;tt&amp;gt;Y = -a&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Y = a&amp;lt;/tt&amp;gt;, with &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; the aspect ratio of the screen).&lt;br /&gt;
&lt;br /&gt;
The important thing for fog is &amp;lt;tt&amp;gt;Z&amp;lt;/tt&amp;gt; (the depth coordinate in frustum-based space). Every pixel of every object within the frustum is blended with a color (the fog color), depending on the amount &amp;lt;tt&amp;gt;f&amp;lt;/tt&amp;gt; of fog in front of that pixel. The default fog color is 25% gray.&lt;br /&gt;
&lt;br /&gt;
For &amp;lt;tt&amp;gt;f &amp;lt; 0&amp;lt;/tt&amp;gt;, there is no fog in front of the object and the pixel retains its original color. For &amp;lt;tt&amp;gt;f &amp;gt; 1&amp;lt;/tt&amp;gt; the object is completely fogged and the pixel has the color of the fog. For &amp;lt;tt&amp;gt;0 &amp;lt; f &amp;lt; 1&amp;lt;/tt&amp;gt;, the color is interpolated linearly between the original pixel color and that of the fog.&lt;br /&gt;
&lt;br /&gt;
The value of &amp;lt;tt&amp;gt;f&amp;lt;/tt&amp;gt; is taken to be &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; on the fog&#039;s &amp;quot;start&amp;quot; plane and &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; on the fog&#039;s &amp;quot;end&amp;quot; plane and is interpolated/extrapolated linearly elsewhere, in the frustum-based coordinates. The natural order is: near clip plane, fog &amp;quot;start&amp;quot; plane, fog &amp;quot;end&amp;quot; plane, far clip plane.&lt;br /&gt;
&lt;br /&gt;
The conversion formulas between &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt; (units of distance from the camera) and &amp;lt;tt&amp;gt;Z&amp;lt;/tt&amp;gt; (percentage of frustum depth) are:&lt;br /&gt;
:&amp;lt;tt&amp;gt;Z = z_f * ( z - z_n ) / [ z * ( z_f - z_n ) ]&amp;lt;/tt&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;z = z_n * z_f / [ z_f - Z * ( z_f - z_n )]&amp;lt;/tt&amp;gt;&lt;br /&gt;
By default, &amp;lt;tt&amp;gt;z_f&amp;lt;/tt&amp;gt; is 10,000 world units and &amp;lt;tt&amp;gt;z_n&amp;lt;/tt&amp;gt; is 4, so &amp;lt;tt&amp;gt;Z = 0.925&amp;lt;/tt&amp;gt; corresponds roughly to &amp;lt;tt&amp;gt;z = 53.07&amp;lt;/tt&amp;gt; world units (or 5.307 m, or 17.411 ft).&lt;br /&gt;
&lt;br /&gt;
==Frustum==&lt;br /&gt;
:See [[BSL:Frustum_and_fog|Frustum and fog]] on how to alter the far clip plane and field-of-view (FOV) using [[BSL]].&lt;br /&gt;
:&#039;&#039;In 3D computer graphics, the viewing frustum or view frustum is the region of space in the modeled world that may appear on the screen; it is the field of view of the notional camera. The exact shape of this region varies depending on what kind of camera lens is being simulated, but typically it is a frustum of a rectangular pyramid (hence the name). The planes that cut the frustum perpendicular to the viewing direction are called the near plane and the far plane. Objects closer to the camera than the near plane or beyond the far plane are not drawn.&#039;&#039; — [[wp:Viewing frustum|&amp;quot;Viewing frustum&amp;quot;]], Wikipedia&lt;br /&gt;
&lt;br /&gt;
;Field of view (FOV)&lt;br /&gt;
:Oni defines the vertical field-of-view (FOV), i.e., the angle between the top and bottom planes of the frustum as measured at the camera&#039;s location, and its default value is 45°. On a 4:3 screen, the corresponding horizontal viewing angle is &#039;&#039;&#039;2 * arctan(4/3 * tan(45° / 2)) = 57.8224°&#039;&#039;&#039;&lt;br /&gt;
;Widescreen FOV&lt;br /&gt;
:On a 16:9 or 16:10 screen, the horizontal viewing angle for a vertical FOV of 45° is larger: &#039;&#039;&#039;2 * arctan(16/9 * tan(45° / 2)) = 72.73435°&#039;&#039;&#039; and &#039;&#039;&#039;2 * arctan(16/10 * tan(45° / 2)) = 67.0682°&#039;&#039;&#039;, respectively. This causes insufficient frustum culling in some of Oni&#039;s cutscenes (intro sequences of {{C|2}}, {{C|11}}, and {{C|14}} for example). A quick way to fix this is to bring the horizontal viewing angle down to the supposed &#039;&#039;&#039;57.8224°&#039;&#039;&#039; during the cutscene: the 4:3 viewport will then effectively be trimmed vertically rather than extended sideways. On 16:9 and 16:10 screens, the corrected vertical FOV will be &#039;&#039;&#039;2 * arctan(3/4 * tan(45° / 2)) = 34.515877°&#039;&#039; and &#039;&#039;2 * arctan(5/6 * tan(45° / 2)) = 38.0871°&#039;&#039;&#039;, respectively. Remember to set it back to 45° after the cutscene to fully enjoy the extended viewport. (Note that the [[AE]] contains patches for some of these cutscenes.)&lt;br /&gt;
&lt;br /&gt;
==Occlusion==&lt;br /&gt;
A game never needs to draw all the objects in a scene at all times. Whole parts of the scene (polygons, meshes or groups of objects) can thus be &amp;quot;culled&amp;quot; (i.e. killed, not drawn).&lt;br /&gt;
&lt;br /&gt;
An object (polygon, mesh) can be culled for several reasons, including the following:&lt;br /&gt;
*it&#039;s outside of the camera&#039;s field of view (view frustum culling)&lt;br /&gt;
*it&#039;s within the camera&#039;s field of view, but it&#039;s hidden by other objects (occlusion culling)&lt;br /&gt;
&lt;br /&gt;
Culling speeds up the drawing process, but runtime detection of objects that need to be culled also takes time... One generally adopts a hierarchical subdivision of the scene, whereby the children (subparts) of a large object are automatically culled if their parent (the large object) is detected as hidden or out of sight.&lt;br /&gt;
&lt;br /&gt;
Oni&#039;s solution is the combination of two algorithms: oct trees and ray casting.&lt;br /&gt;
&lt;br /&gt;
;Oct trees&lt;br /&gt;
:Unlike the more common &amp;quot;visibility groups&amp;quot; placed manually by the level designer, Oni uses an automatic partition of the visible space into smaller and smaller cubes, until each &amp;quot;leaf&amp;quot; cube holds no more than a certain small number of polygons (see [[OTLF]] for details). Environment polygons (as well as characters, particles, etc) will only be drawn if they are in a leaf node of the oct tree, and if that leaf node is detected as visible. The detection of whether a leaf node is visible is done with ray casting. &lt;br /&gt;
&lt;br /&gt;
;Ray-casting&lt;br /&gt;
:Wikipedia: [[wp:Ray casting|Ray casting]]&lt;br /&gt;
[[Image:Ray-casting failure.jpg|thumb|right|If you&#039;ve ever thought that you briefly saw flashes of color while turning the camera, now you know why. Wherever a polygon is not rendered, the level&#039;s skybox will be visible.]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s an original algorithm that achieves both view frustum and occlusion culling. During each frame, 16-20 rays (depending on graphics quality) are shot from the camera into the environment, distributed randomly in the frustum. Along the path of each ray, the engine first determines the relevant leaf node of the oct tree (either by navigating the oct tree or using the information on the neighbors of the previously traversed leaf node), and then the ray is tested for collision with non-transparent environment quads intersecting that node (if the ray is stopped by a quad, then its further path is ignored). Quads thus detected with collision will be drawn. An overview of the algorithm is presented in the paper [http://oni.bungie.org/archives/brent_gdc00.html An Algorithm for Hidden Surface Complexity Reduction and Collision Detection Based On Oct Trees] by [[Credits|Brent H. Pease]] (note that figure 1 and 2 are mixed up).&lt;br /&gt;
:Just a side note: the ray-casting feature which handles occlusion/frustum is not to be confused with the common term &amp;quot;[[wp:Ray tracing (graphics)|ray-tracing]]&amp;quot;, a CG rendering method where a ray is cast for every rendered pixel, achieving a high degree of photorealism. This method is very CPU-intensive and is typically used only for still images, short video sequences or CG movies such as Pixar&#039;s &#039;&#039;Cars&#039;&#039;. Implementations of real-time ray-tracing for gaming are underway, but still need to be complemented with the standard [[wp:Scanline rendering|scanline rendering]] and [[wp:Rasterisation|rasterisation]] approaches for performance reasons.&lt;br /&gt;
Pease acknowledges that even ray-casting was too CPU-intensive until they lowered the number of rays being emitted and started altering their emission angles even when the camera remained still, in order to catch any polygons that the first emission of rays missed; this is why distant polygons, when suddenly revealed by the camera, sometimes are culled at first (pictured, right) and then appear a moment later: because the rays didn&#039;t hit them on the first pass. A distant face in the environment can be accidentally culled if it&#039;s only visible through a narrow slit, because the rays have a low probability of passing through the slit and hitting the objects behind it. A similar problem occurs when modders experiment with outdoor levels that have uneven ground (natural terrain): many of the ground polygons will be culled, making the map look like there are holes everywhere.&lt;br /&gt;
&lt;br /&gt;
==LOD==&lt;br /&gt;
Oni uses the graphics quality slider in Options to help determine what level of detail (LOD) at which to render characters. Each character has up to 5 LODs, though one 3D model can be used in as many of the 5 slots as desired. The first step in determining which LOD to draw each character at is to consult [[XML:ONCC#&amp;lt;LODConstants&amp;gt;|this table]] found in the character&#039;s ONCC.&lt;br /&gt;
&lt;br /&gt;
After that distance-from-camera filter is applied, Oni counts the total polygons of all characters in the scene (henceforth &amp;quot;TPCS&amp;quot;). If TPCS is not above the maximum character polys in the scene (&amp;quot;MCPS&amp;quot;) which is allowed by the game&#039;s graphics quality setting, the game then experiments with raising the LOD of all characters one level at a time, stopping when it would pass MCPS. If TPCS is starting off above MCPS, it lowers all characters&#039; LOD one level at a time until it gets below that limit.&lt;br /&gt;
&lt;br /&gt;
For reference, here is the table of MCPS by graphics quality level: (1500, 2200, 3000, 3400, 4000). Note that there is no consideration at all for how many &amp;lt;u&amp;gt;environmental&amp;lt;/u&amp;gt; polys are in the scene.&lt;br /&gt;
&lt;br /&gt;
Next, iterating over each character from closest to farthest, the LOD of that character is raised by 1 as long as this won&#039;t raise TPCS over MCPS. Thus Oni seeks towards the maximum detail level that it can use for each character, prioritizing the closest ones. As a special consideration, if the closest character is below Medium LOD, it is raised to Medium regardless of MCPS, and the second-closest character is raised to Low if it was Super-Low.&lt;br /&gt;
&lt;br /&gt;
Once the desired LOD is determined for a character, they will be switched to it immediately if they are not standing still (which would make the switch too noticeable). If they are moving, the game waits several frames to make sure the new LOD is continuously being requested by the above algorithms and then they are switched. The goal is to avoid a character rapidly switching back and forth between LODs.&lt;br /&gt;
&lt;br /&gt;
After all the above considerations, one more: if a cutscene is playing, every character is guaranteed a minimum LOD of Low so that no one will be rendered at Super-Low detail.&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine docs]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=XML:TRAM&amp;diff=43859</id>
		<title>XML:TRAM</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=XML:TRAM&amp;diff=43859"/>
		<updated>2025-01-22T22:13:16Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{XML_File_Header | prev=TRAC | type=TRAM | next=TRAS | name=Totoro Animation}}&lt;br /&gt;
{{update|This article contains links to the now defunct Oni Central Forum. Sections: List of Tags near &amp;lt;Attack&amp;gt;, Editing 3D Data}}&lt;br /&gt;
{{TOCfloat|side=right}}&lt;br /&gt;
&lt;br /&gt;
==General information==&lt;br /&gt;
TRAM files — animation data for characters — are basically made of three chunks:&lt;br /&gt;
* Metadata or &amp;quot;header&amp;quot;: animation type, state, flags, particle, sounds, etc.&lt;br /&gt;
* Animation data: &#039;&#039;&#039;pelvis heights, pelvis velocities (root motion)&#039;&#039;&#039;, bone rotations&lt;br /&gt;
* Attack data: damage, self-damage, extents (danger zones for AI awareness) and throws&lt;br /&gt;
&lt;br /&gt;
Root motion: a character moves by changing the position of its root bone (pelvis). The animated legs just create the &#039;&#039;&#039;illusion for the player&#039;&#039;&#039; that they are responsible for the motion.&lt;br /&gt;
&lt;br /&gt;
Bones: Each character has &#039;&#039;&#039;19 separate body parts&#039;&#039;&#039; which get animated (rotated) relative to each other. Compared to modern games Oni&#039;s bone system is [[wp:Deprecation|deprecated]]. The body doesn&#039;t get deformed by following animated bones. Oni modders often use the terms mesh and bone interchangeably. Only the pelvis has &#039;&#039;&#039;translation&#039;&#039;&#039; data (heights and velocities) besides rotations. The hierarchy of the body parts (or bones) is determined by [[XML:TRBS#Standard_TRIA_hierarchy|TRIA]].&lt;br /&gt;
&lt;br /&gt;
The term &#039;&#039;&#039;animation&#039;&#039;&#039; is often shortened to &#039;&#039;&#039;anim&#039;&#039;&#039; by modders, following the naming of commands in BSL: chr_wait_animstate, chr_wait_animtype, env_anim, etc.&lt;br /&gt;
&lt;br /&gt;
Oni&#039;s code and debugging messages tend to spell the word variant as &amp;quot;varient&amp;quot;. Blame the programmers for that one. Typically we use the correct spelling here, but OniSplit&#039;s XML follows Oni&#039;s misspelling, so you may see &amp;quot;varient&amp;quot; creep into the wiki here and there.&lt;br /&gt;
&lt;br /&gt;
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]].&lt;br /&gt;
&lt;br /&gt;
==Open questions==&lt;br /&gt;
* If the never-used Thrown type can be applied as type 18 the table looks much more complete. &amp;quot;Restoring&amp;quot; forward tackles (face-to-face, src run + tgt run) can be omitted as the AI would most often stop movement for actual combat?&lt;br /&gt;
&lt;br /&gt;
* 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 &amp;quot;forward&amp;quot; (face-to-face) and &amp;quot;backward&amp;quot; (face-to-back).&lt;br /&gt;
: &#039;&#039;&#039;Maybe the algorithm checks always tgt&#039;s rotation and relative position to src at the same time but for most cases only tgt&#039;s rotation (facing) is relevant.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* 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 &#039;&#039;convention&#039;&#039;. Well, someone could check the source code...&lt;br /&gt;
&lt;br /&gt;
* 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.&lt;br /&gt;
* The variant pickup system is not clear yet: is a RIFCOM idle and a RIFNAT idle both possible?&lt;br /&gt;
** Or do rightpistol, leftpistol, rightrifle and leftrifle variants count as subsets of combat?&lt;br /&gt;
&lt;br /&gt;
==Summary of animation lookup logic==&lt;br /&gt;
* 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.&lt;br /&gt;
* Anims from a child TRAC override those of the parent if their combination of state, type and variant is exactly the same.&lt;br /&gt;
* Child TRACs usually omit some anims. For example, Elite Strikers don&#039;t have their own run anims, so they use the parent anims of normal Strikers. See [[XML:TRAC|TRAC]] page for details.&lt;br /&gt;
* 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.&lt;br /&gt;
* Here is the full decision path:&lt;br /&gt;
** anim &#039;&#039;&#039;state&#039;&#039;&#039; check&lt;br /&gt;
** event (user input, or engine input for the AI) -&amp;gt; [[XML talk:StNA|context check]] -&amp;gt; anim &#039;&#039;&#039;type&#039;&#039;&#039; check&lt;br /&gt;
** anim &#039;&#039;&#039;variant&#039;&#039;&#039; check&lt;br /&gt;
** TRAC &#039;&#039;&#039;weight&#039;&#039;&#039; check&lt;br /&gt;
&lt;br /&gt;
===Elaboration===&lt;br /&gt;
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: &#039;&#039;&#039;type, state, variant&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now then, the idle animation does not link to a specific follow-up animation – it rather links to a follow-up &#039;&#039;state&#039;&#039;.&lt;br /&gt;
: Ironically all anims have a &amp;lt;FromState&amp;gt; and a &amp;lt;ToState&amp;gt; field, but no obvious &amp;lt;CurrentState&amp;gt; which can cause confusion on what the current anim&#039;s state actually is. This gives us two options of how to think about the situation: either consider &amp;lt;FromState&amp;gt; as usually being the &amp;lt;CurrentState&amp;gt;, or states exist only &#039;&#039;between&#039;&#039; anims and serve as &#039;&#039;transition rules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;Weight&amp;gt; is determined by the anim listing in the TRAC – the anim collection (see {{SectionLink||Weights}} for an explanation of exactly how &amp;lt;Weight&amp;gt; is handled).&lt;br /&gt;
&lt;br /&gt;
Anyway, to let an character flow from one anim state to another, the &amp;lt;ToState&amp;gt; is used. Let&#039;s say an SBG grenade hits Konoko. The particle&#039;s &#039;&#039;&#039;damage type&#039;&#039;&#039; is &#039;&#039;&#039;blownup&#039;&#039;&#039;; this and the direction of the incoming damage force an anim of type &#039;&#039;&#039;Blownup&#039;&#039;&#039; or &#039;&#039;&#039;BlownupBehind&#039;&#039;&#039; to play, such as TRAMKONOKOblownup1.&lt;br /&gt;
&lt;br /&gt;
Thus, Konoko falls to her back, going into the FallenBack state. The engine picks up the next anim which has &amp;lt;FromState&amp;gt;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 &amp;lt;ToState&amp;gt;FallenBack creates a loop.&lt;br /&gt;
&lt;br /&gt;
So here&#039;s a question: why isn&#039;t a getup anim like KONCOMgetup_lt played automatically since it also has &amp;lt;FromState&amp;gt;FallenBack and &amp;lt;Varient&amp;gt;Combat? Answer: it differs in its &amp;lt;Type&amp;gt;. 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.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;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 &amp;lt;FromState&amp;gt; condition.&lt;br /&gt;
: In fact, KONOKOcomb_turnlt has &amp;lt;Varient&amp;gt; Combat – the &amp;quot;comb&amp;quot; here stands for &amp;quot;combat&amp;quot;, not &amp;quot;combo&amp;quot;. Following Oni&#039;s naming convention, the file &#039;&#039;should&#039;&#039; have been named KONCOMturn_lt.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;ToState&amp;gt;Standing and Konoko is still in combat mode, the following idle anim must also have &amp;lt;Varient&amp;gt;Combat. So the next anim played will be KON&#039;&#039;&#039;COM&#039;&#039;&#039;idle1 or KON&#039;&#039;&#039;COM&#039;&#039;&#039;idle2.&lt;br /&gt;
&lt;br /&gt;
Konoko will eventually calm down when her ONCC &amp;lt;FightModeTimer&amp;gt; runs down, and then KON&#039;&#039;&#039;OKO&#039;&#039;&#039;idle1 or KON&#039;&#039;&#039;OKO&#039;&#039;&#039;idle2 will be played instead. (Actually, the COMidle will continue until a non-combat anim such as running breaks that loop. You won&#039;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.)&lt;br /&gt;
&lt;br /&gt;
Note the fallback behavior of anim lookup: if the engine cannot find an anim for the active variant (or &amp;quot;mode&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
As for combinations of variants, it&#039;s possible, yes, but rarely and only Sprint and one weapon variant at a time.&lt;br /&gt;
&lt;br /&gt;
==Weights==&lt;br /&gt;
Let&#039;s say that we&#039;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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;TRACAnimation&amp;gt;&lt;br /&gt;
                &amp;lt;Weight&amp;gt;100&amp;lt;/Weight&amp;gt;&lt;br /&gt;
                &amp;lt;Animation&amp;gt;TRAMNINCOMtaunt1&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/TRACAnimation&amp;gt;&lt;br /&gt;
            &amp;lt;TRACAnimation&amp;gt;&lt;br /&gt;
                &amp;lt;Weight&amp;gt;5&amp;lt;/Weight&amp;gt;&lt;br /&gt;
                &amp;lt;Animation&amp;gt;TRAMNINCOMtaunt2&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/TRACAnimation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Idle timer==&lt;br /&gt;
There&#039;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&#039;s very unlikely a repeating idle cycle will choose the anim. But here&#039;s the sneeze anim in the TRAC with a Weight of 100:&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;TRACAnimation&amp;gt;&lt;br /&gt;
                &amp;lt;Weight&amp;gt;100&amp;lt;/Weight&amp;gt;&lt;br /&gt;
                &amp;lt;Animation&amp;gt;TRAMKONOKOidle_spec3&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/TRACAnimation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What&#039;s going on here? All regular idle anims are in fact of &#039;&#039;&#039;type Stand&#039;&#039;&#039;, while Konoko&#039;s idle_spec3 anim above is of &#039;&#039;&#039;type Idle&#039;&#039;&#039;. Anims of &#039;&#039;&#039;type Idle&#039;&#039;&#039; are played every time the idle animation timer expires.  This is found in ONCC as &amp;lt;IdleAnimation1Timer&amp;gt; and &amp;lt;IdleAnimation2Timer&amp;gt;. 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.&lt;br /&gt;
&lt;br /&gt;
==List of tags, types, and flags==&lt;br /&gt;
Use the search function in your browser to quickly find a tag.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=100%&lt;br /&gt;
|width=120px| &#039;&#039;&#039;tag&#039;&#039;&#039;&lt;br /&gt;
|width=100px| &#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;description&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Lookup&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Type&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| 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.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;AimingType&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| 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.&lt;br /&gt;
:&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;FromState&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| [[Image:chr_debug_characters_shows_interpolated_animations.jpg|thumb|400px|right|Primary &amp;lt;FromState&amp;gt; in &amp;lt;Lookup&amp;gt; uses about 8 interpolating frames by default. Use Shortcut&#039;s &amp;lt;FromState&amp;gt; to override this frame number.]]&lt;br /&gt;
&lt;br /&gt;
Look them up over [[XML:StNA#Animation_states|HERE]].&lt;br /&gt;
: When FromState is set to None, some default behaviors are ignored and are replaced by Shortcuts.&lt;br /&gt;
: Shortcuts extend the number of states from which an animation can be played and under what conditions (replacing this atomic yes/no).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ToState&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Look them up over [[XML:StNA#Animation_states|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Varient&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|(misspelled because Oni misspells it) If unused, the tag will simply be &amp;quot;&amp;lt;Varient /&amp;gt;&amp;quot;, such as for non-combat animations. Otherwise it contains one of these values:&lt;br /&gt;
: Combat&lt;br /&gt;
: LeftPistol&lt;br /&gt;
: LeftRifle&lt;br /&gt;
: Panic&lt;br /&gt;
: RightPistol&lt;br /&gt;
: RightRifle&lt;br /&gt;
: Sprint&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;FirstLevel&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|Number of first level in which move becomes available to the player (&amp;quot;0&amp;quot; to make it available from the start).&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Shortcuts&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| parent tag&lt;br /&gt;
|&lt;br /&gt;
Works as an &#039;&#039;&#039;alternative FromState&#039;&#039;&#039; collection.&lt;br /&gt;
&lt;br /&gt;
Shortcuts are accepted if their &amp;lt;Shortcut&amp;gt;&amp;lt;FromState&amp;gt; value differs from the &amp;quot;primary&amp;quot; &amp;lt;Lookup&amp;gt;&amp;lt;FromState&amp;gt; value. In other words, if you want to make a &#039;&#039;&#039;Shortcut&#039;&#039;&#039; that uses the &#039;&#039;&#039;same FromState&#039;&#039;&#039; value then you have to set &#039;&#039;&#039;primary FromState&#039;&#039;&#039; value to &#039;&#039;&#039;None&#039;&#039;&#039;. By doing that, the hardcoded interpolation frame length of about 8 frames can be overridden.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;Interpolation&amp;gt;&amp;lt;End&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;Lookup&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
            &amp;lt;FromState&amp;gt;None&amp;lt;/FromState&amp;gt;&lt;br /&gt;
            ...&lt;br /&gt;
            &amp;lt;Shortcuts&amp;gt;&lt;br /&gt;
                &amp;lt;Shortcut&amp;gt;&lt;br /&gt;
                    &amp;lt;FromState&amp;gt;Standing&amp;lt;/FromState&amp;gt;&lt;br /&gt;
                    &amp;lt;Length&amp;gt;0&amp;lt;/Length&amp;gt;&lt;br /&gt;
                    &amp;lt;ReplaceAtomic&amp;gt;no&amp;lt;/ReplaceAtomic&amp;gt;&lt;br /&gt;
                &amp;lt;/Shortcut&amp;gt;&lt;br /&gt;
            &amp;lt;/Shortcuts&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:TRAM interpolation - standard case.jpg|thumb|400px|left|Scenario A: hardcoded interpolation of 8 frames. Scenario B: changeable interpolation frame number.]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Shortcut&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;FromState&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Look them up over [[XML:StNA#Animation_types|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Length&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| int16&lt;br /&gt;
|Amount of interpolating frames. While interpolations of rotation are less noticeable, interpolations of different positions can cause drift (i.e. sliding).&lt;br /&gt;
&lt;br /&gt;
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&#039;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 &#039;&#039;last resort&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This drift can be observed even in vanilla animations — most prominently in Konoko&#039;s comb_k. Konoko&#039;s left foot should be in a fixed position as the animation starts from from Konoko&#039;s idle pose. However, the interpolation is causing her left foot to drift noticeably to the right and a bit forward.&lt;br /&gt;
&lt;br /&gt;
The reason this happens is because the interpolation &amp;quot;mixes&amp;quot; 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.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ReplaceAtomic&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
: yes&lt;br /&gt;
: no&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|These are top-level flags on the whole animation. See the other &amp;lt;Flags&amp;gt; for flags on an attack part.&lt;br /&gt;
:RuntimeLoaded&lt;br /&gt;
::(This bit is not stored on disk; it is used at runtime to mark that the animation was loaded.)&lt;br /&gt;
:Invulnerable&lt;br /&gt;
::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.&lt;br /&gt;
:BlockHigh&lt;br /&gt;
::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 &amp;lt;Attack&amp;gt; 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.&lt;br /&gt;
:BlockLow&lt;br /&gt;
::Same as above, only it can block low or undefined-height attacks.&lt;br /&gt;
:Attack&lt;br /&gt;
::Unused by the engine.&lt;br /&gt;
:DropWeapon&lt;br /&gt;
::If the player is armed, he drops his weapon when this animation plays.&lt;br /&gt;
:InAir&lt;br /&gt;
::Unused by the engine.&lt;br /&gt;
:Atomic&lt;br /&gt;
::Unused by the engine. Only the Start and End frames of the Atomic field below matter.&lt;br /&gt;
:NoTurn&lt;br /&gt;
:::Player cannot turn while performing this animation.&lt;br /&gt;
:AttackForward&lt;br /&gt;
::Unused by the engine.&lt;br /&gt;
:AttackLeft&lt;br /&gt;
::Same as above.&lt;br /&gt;
:AttackRight&lt;br /&gt;
::Same as above.&lt;br /&gt;
:AttackBackward&lt;br /&gt;
::Same as above.&lt;br /&gt;
:Overlay&lt;br /&gt;
::Not a standalone animation; it just overwrites part of an already-playing one, e.g. the weapon-holstering animation.&lt;br /&gt;
:DontInterpolateVelocity&lt;br /&gt;
::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).&lt;br /&gt;
:ThrowSource&lt;br /&gt;
::Oni expects this flag on all throw source animations.&lt;br /&gt;
:::Throws work in animation pairs: whenever a throw source is played, the other character must perform the throw target animation. See throw(n) types:&lt;br /&gt;
::::TRAM &amp;lt;TargetType&amp;gt; from [[XML:StNA#Animation types|StNA]] (first &amp;lt;u&amp;gt;used&amp;lt;/u&amp;gt; throw starts at #96).&lt;br /&gt;
:::Characters have only their own pool of animations available. And since enemy&#039;s TRAC might not contain the necessary animation the information must be provided by the throw source TRAC. &lt;br /&gt;
::: Since every throw animation must have a throw animation type the ThrowSource flag is actually redundant.&lt;br /&gt;
:ThrowTarget&lt;br /&gt;
::Animation can hurt anybody with its attack part, including teammates. The player can even hurt himself with the TRAM&#039;s damage part (whereas a player cannot hurt himself with his own animation&#039;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).&lt;br /&gt;
:::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&#039;s active &amp;quot;window&amp;quot;, otherwise it won&#039;t work.&lt;br /&gt;
:RealWorld&lt;br /&gt;
::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.&lt;br /&gt;
:DoAim&lt;br /&gt;
::Applies the aiming animation overlay (PIS/RIF) if the player has a weapon.&lt;br /&gt;
:DontAim&lt;br /&gt;
::An aiming overlay will not be applied.&lt;br /&gt;
:CanPickup&lt;br /&gt;
::Player can pick up an item during this animation if he intersects with one during his movement.&lt;br /&gt;
:Aim360&lt;br /&gt;
::Unused by the engine.&lt;br /&gt;
:DisableShield&lt;br /&gt;
::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 &amp;quot;[[wikt:kancho|kancho]]&amp;quot; maneuver; it is also hardcoded to be removed when the Zeus Thunderbolt attack is used).&lt;br /&gt;
:NoAIPickup&lt;br /&gt;
::AIs are not permitted to pick up items with this animation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Atomic&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| Animation cannot be interrupted by player between the Start and End frames.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Invulnerable&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| Character will not take melee damage and cannot be thrown between the Start and End frames.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| First frame of character being invulnerable.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Last frame of character being invulnerable.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Overlay&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;UsedBones&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|Simply contains &amp;quot;&amp;lt;UsedBones /&amp;gt;&amp;quot; if no bones are involved, otherwise:&lt;br /&gt;
:Pelvis&lt;br /&gt;
:LeftThigh&lt;br /&gt;
:LeftCalf&lt;br /&gt;
:LeftFoot&lt;br /&gt;
:RightThigh&lt;br /&gt;
:RightCalf&lt;br /&gt;
:RightFoot&lt;br /&gt;
:Mid&lt;br /&gt;
:Chest&lt;br /&gt;
:Neck&lt;br /&gt;
:Head&lt;br /&gt;
:LeftShoulder&lt;br /&gt;
:LeftArm&lt;br /&gt;
:LeftWrist&lt;br /&gt;
:LeftFist&lt;br /&gt;
:RightShoulder&lt;br /&gt;
:RightArm&lt;br /&gt;
:RightFist&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ReplacedBones&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| &amp;quot;&amp;lt;ReplacedBones /&amp;gt;&amp;quot; if unused, otherwise:&lt;br /&gt;
:Pelvis&lt;br /&gt;
:LeftThigh&lt;br /&gt;
:LeftCalf&lt;br /&gt;
:LeftFoot&lt;br /&gt;
:RightThigh&lt;br /&gt;
:RightCalf&lt;br /&gt;
:RightFoot&lt;br /&gt;
:Mid&lt;br /&gt;
:Chest&lt;br /&gt;
:Neck&lt;br /&gt;
:Head&lt;br /&gt;
:LeftShoulder&lt;br /&gt;
:LeftArm&lt;br /&gt;
:LeftWrist&lt;br /&gt;
:LeftFist&lt;br /&gt;
:RightShoulder&lt;br /&gt;
:RightArm&lt;br /&gt;
:RightFist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;DirectAnimations&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Link&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| First slot. &amp;quot;&amp;lt;Link /&amp;gt;&amp;quot; if unused.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Link&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| Second slot. &amp;quot;&amp;lt;Link /&amp;gt;&amp;quot; if unused.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Pause&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Hard&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| In ticks. The Hard and Soft pause values are ignored if this animation has a direct link (above) to another animation.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Soft&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| int16&lt;br /&gt;
| 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 &amp;lt;DirectAnimations&amp;gt;&amp;lt;Link&amp;gt;.&lt;br /&gt;
: Examples:&lt;br /&gt;
: COMcomb_p, (no pause) COMcomb_p_p&lt;br /&gt;
: COMcomb_p, (pause) COMcomb_k&lt;br /&gt;
&lt;br /&gt;
The difference between the hard and soft pause is that you can block during the soft pause and not the hard pause.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Interpolation&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;End&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| int16&lt;br /&gt;
|&lt;br /&gt;
* interpolates first X frames of next animation&lt;br /&gt;
* if the first follow-up animation is too short, it can continue to play even further (not observed with vanilla anims)&lt;br /&gt;
&lt;br /&gt;
While interpolations with rotations are less noticeable, interpolations of different positions can cause an additional drift.&lt;br /&gt;
&lt;br /&gt;
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&#039;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 &#039;&#039;last resort&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:TRAM interpolations - end interpolation bigger than next anim.jpg|thumb|400px|left|&amp;quot;End&amp;quot; interpolation covering multiple follow-up animations.]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Max&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| unused&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;FinalRotation&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| float&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| Ending rotation in degrees. (During an animation on the player character, the camera is detached rotation-wise. If this value matches the body&#039;s final rotation, it will prevent a &amp;quot;glitchy&amp;quot; re-attaching.)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Direction&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|&lt;br /&gt;
| Used by [[AI#Melee combat behaviors|AI melee system]].&lt;br /&gt;
:None&lt;br /&gt;
:Forward&lt;br /&gt;
:Backward&lt;br /&gt;
:Left&lt;br /&gt;
:Right&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Vocalization&amp;gt;&lt;br /&gt;
| int&lt;br /&gt;
| ID of one of the [[XML:SNDD#Step 1: Preparing the TRAM|SoundConstants in ONCC]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ActionFrame&amp;gt;&lt;br /&gt;
| int&lt;br /&gt;
| 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.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Impact&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| &amp;quot;&amp;lt;Impact /&amp;gt;&amp;quot; if unused.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Particles&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| parent tag&lt;br /&gt;
| serves as group element&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Particle&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| parent tag&lt;br /&gt;
| holds individual particle data&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Start&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| int&lt;br /&gt;
| frame number for particle to start&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;End&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| int&lt;br /&gt;
| 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)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Bone&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
: Pelvis &lt;br /&gt;
: LeftThigh &lt;br /&gt;
: LeftCalf &lt;br /&gt;
: LeftFoot &lt;br /&gt;
: RightThigh &lt;br /&gt;
: RightCalf &lt;br /&gt;
: RightFoot &lt;br /&gt;
: Mid &lt;br /&gt;
: Chest &lt;br /&gt;
: Neck &lt;br /&gt;
: Head &lt;br /&gt;
: LeftShoulder &lt;br /&gt;
: LeftArm &lt;br /&gt;
: LeftWrist &lt;br /&gt;
: LeftFist &lt;br /&gt;
: RightShoulder &lt;br /&gt;
: RightArm &lt;br /&gt;
: RightFist&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Name&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| particle name in [[XML:ONCC#ONCP:_Oni_Character_Particle_.28Array.29|ONCC-ONCP]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| sequence element&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Bones&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
: Pelvis &lt;br /&gt;
: LeftThigh &lt;br /&gt;
: LeftCalf &lt;br /&gt;
: LeftFoot &lt;br /&gt;
: RightThigh &lt;br /&gt;
: RightCalf &lt;br /&gt;
: RightFoot &lt;br /&gt;
: Mid &lt;br /&gt;
: Chest &lt;br /&gt;
: Neck &lt;br /&gt;
: Head &lt;br /&gt;
: LeftShoulder &lt;br /&gt;
: LeftArm &lt;br /&gt;
: LeftWrist &lt;br /&gt;
: LeftFist &lt;br /&gt;
: RightShoulder &lt;br /&gt;
: RightArm &lt;br /&gt;
: RightFist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Start frame of motion blur sequence&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| End frame of motion blur sequence&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Lifetime&amp;gt;&lt;br /&gt;
| int8&lt;br /&gt;
| Lifetime of each &amp;quot;ghost&amp;quot; in frames. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Alpha&amp;gt;&lt;br /&gt;
| int8&lt;br /&gt;
| Transparency of &amp;quot;ghosts&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Interval&amp;gt;&lt;br /&gt;
| int8&lt;br /&gt;
| Frame interval between each rendered &amp;quot;ghost&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Footsteps&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Footstep&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Frame&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Type&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
: Left&lt;br /&gt;
: Right&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Sounds&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| &amp;quot;&amp;lt;Sounds /&amp;gt;&amp;quot; if unused.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Sound&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Name&amp;gt;&lt;br /&gt;
| char[32]&lt;br /&gt;
| &amp;lt;font color=&amp;quot;#777777&amp;quot;&amp;gt;OSBD&amp;lt;/font&amp;gt;file&amp;lt;font color=&amp;quot;#777777&amp;quot;&amp;gt;.imp.oni&amp;lt;/font&amp;gt; &amp;lt;font color=&amp;quot;#777777&amp;quot;&amp;gt;(don&#039;t use resource type&#039;s prefix or suffix)&amp;lt;/font&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|The frame when the sound starts to play.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Heights&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Height&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
|Absolute position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Velocities&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Velocity&amp;gt;&lt;br /&gt;
| 2 x float&lt;br /&gt;
|Relative positions (delta values); the numbers represent the change in position from one frame to another.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotations&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Bone&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|There are 19 bone tags, one for each [[TRIA#Bones|body part]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;EKey&amp;gt;&lt;br /&gt;
| int8 + 3 * float&lt;br /&gt;
|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.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;QKey&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| int8 + 4 * float&lt;br /&gt;
|For overlay animations used by [[TRAS|TRAS]] aiming screens.&lt;br /&gt;
&lt;br /&gt;
OniSplit v0.9.54.0 produces &amp;lt;QKey&amp;gt;s (quaternions) instead of &amp;lt;EKey&amp;gt;s (Euler rotations) for normal animations.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;PositionOffset&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| &amp;lt;PositionOffset&amp;gt; and &amp;lt;Positions&amp;gt; belong together. In the [[OBD:TRAM/raw0x30|binaries]], they are written in place. &#039;&#039;&#039;Seems unused; changing them has no effect in-game.&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;X&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Z&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Positions&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| seems to be unused (and when checking this with &amp;quot;chr_debug_sphere = 1&amp;quot;, the spheres remain unchanged)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Height&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| vertical extent&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;YOffset&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| Y offset of the vertical extent from character location &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ThrowSource&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| &amp;quot;&amp;lt;ThrowSource /&amp;gt;&amp;quot; if unused.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;TargetAdjustment&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| Used to position targets during throws, relative to the position of the character executing the throw.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Position&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| 3 * float&lt;br /&gt;
| Contains XYZ values, which position the target character at the start of the animation:&lt;br /&gt;
*X - Side axis. Negative values move the target to the right and positive values move the target to the left.&lt;br /&gt;
*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&#039;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.&lt;br /&gt;
*Z - Forward axis. Negative values move the target backwards and positive values move the target forward.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Angle&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| In radians - adjusts the rotation of the target in Oni&#039;s Y axis; most of the time (if not always) it&#039;s set to &#039;&#039;3.14159274&#039;&#039; 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.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Distance&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| 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&#039;s range and within that TRAM&#039;s range.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;TargetType&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| The flags are part of the [[XML:StNA#Animation_types|animation type list]].&lt;br /&gt;
&lt;br /&gt;
(static throws)&lt;br /&gt;
: Thrown1 = ###COMthrow_fw_p_tgt&lt;br /&gt;
: Thrown2 = ###COMthrow_fw_k_tgt&lt;br /&gt;
: Thrown3 = ###COMthrow_bk_p_tgt&lt;br /&gt;
: Thrown4 = ###COMthrow_bk_k_tgt&lt;br /&gt;
(running throws)&lt;br /&gt;
: Thrown5 = ###COMrun_throw_fw_p_tgt&lt;br /&gt;
: Thrown6 = ###COMrun_throw_fw_p_tgt&lt;br /&gt;
: Thrown7 = ###COMrun_throw_bk_k_tgt&lt;br /&gt;
: Thrown8 = ###COMrun_throw_bk_k_tgt (not tested)&lt;br /&gt;
(tackle throw = catching)&lt;br /&gt;
: Thrown9 = ###COMrun_tkl_fw_p_tgt (not tested)&lt;br /&gt;
: Thrown10 = ###COMrun_tkl_bk_p_tgt&lt;br /&gt;
(pistol disarms)&lt;br /&gt;
: Thrown11 = ###PISthrow_fw_p_tgt&lt;br /&gt;
: Thrown12 = ###PISthrow_fw_k_tgt&lt;br /&gt;
: Thrown13 = ###PISthrow_bk_p_tgt&lt;br /&gt;
(rifle disarm)&lt;br /&gt;
: Thrown14 = ###PISthrow_bk_k_tgt (not tested)&lt;br /&gt;
: Thrown15 = ###RIFthrow_fw_p_tgt&lt;br /&gt;
: Thrown16 = ###RIFthrow_bk_p_tgt&lt;br /&gt;
: Thrown17 = ###RIF? = (not tested)&lt;br /&gt;
----&lt;br /&gt;
About the naming:&lt;br /&gt;
: &amp;quot;fw&amp;quot; = face-to-face throw&lt;br /&gt;
: &amp;quot;bk&amp;quot; = thrower is facing victim&#039;s back&lt;br /&gt;
: &amp;quot;throw&amp;quot; inside TRAM names is sometimes shortened to &amp;quot;thr&amp;quot;&lt;br /&gt;
: &amp;quot;p&amp;quot;/&amp;quot;k&amp;quot; = triggered by punch or kick button (&amp;quot;p&amp;quot; is sometimes omitted)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;SelfDamage&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&amp;quot;&amp;lt;SelfDamage /&amp;gt;&amp;quot; if unused.&lt;br /&gt;
&lt;br /&gt;
Works only with specific, hardcoded AnimTypes (mainly ThrownX, it&#039;s unknown if any other types work - that remains to be investigated). Using SelfDamage on an AnimType that wasn&#039;t intended for it will cause the game to crash. (ToDo: Checked if &amp;lt;Flag&amp;gt;ThrowTarget is enough to explain this. Modify a simple kick? For more please link to and use talk page.)&lt;br /&gt;
&lt;br /&gt;
From a practical standpoint, this means SelfDamage can be used only on ThrowTarget animations.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Damage&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| sequence element&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Points&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Damage taken by character.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Frame&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Frame of the animation when damage is dealt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Attacks&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Attack&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| parent tag&lt;br /&gt;
| 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].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| First frame where damage can be inflicted on an opponent.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Last frame where damage can be inflicted on an opponent.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Bones&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| The bones which can inflict damage.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|These are flags on an attack part, inside an &amp;lt;Attacks&amp;gt;&amp;lt;Attack&amp;gt; element. See the previous &amp;lt;Flags&amp;gt; for general flags on the TRAM.&lt;br /&gt;
: Unblockable&lt;br /&gt;
: Low - Target of attack needs to crouch in order to block this attack.&lt;br /&gt;
: High - Blocker needs to stand; if both Low and High are set, blocker can block from both standing and crouching positions.&lt;br /&gt;
: HalfDamage - Blocker still receives half of the normal damage.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Knockback&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| Target gets knocked back by this amount if attack is successful.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;HitPoints&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Damage points inflicted by attack.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;HitType&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Animation type for opponent&#039;s animation when the attack isn&#039;t blocked. The flags are part of the [[XML:StNA#Animation types|animation type list]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;HitLength&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| 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.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;StunLength&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| 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.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;StaggerLength&amp;gt;&lt;br /&gt;
| int16&lt;br /&gt;
| Number of frames that the target should perform his stagger animation after a successful block.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Extents&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| Explained below. Automatically calculated by OniSplit if there&#039;s a DAE file referenced in the XML.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Extent&amp;gt;&lt;br /&gt;
| parent tag&lt;br /&gt;
| One tag per attack frame. Number of &amp;lt;Extent&amp;gt; tags = &amp;lt;Attack&amp;gt;&amp;lt;End&amp;gt; - &amp;lt;Attack&amp;gt;&amp;lt;Start&amp;gt; + 1.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Angle&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| In degrees.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Length&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;MinY&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;MaxY&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;AttackRing&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|  parent tag&lt;br /&gt;
| Always contains 36 &amp;lt;Length&amp;gt; tags, explained below. Automatically calculated by OniSplit if there&#039;s a DAE file referenced in the XML. (AttackRing was formerly known as &amp;quot;horizontal extents&amp;quot; in older versions of OniSplit.)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Length&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| float&lt;br /&gt;
| Horizontal extents, explained below. They create a &amp;quot;danger zone&amp;quot; around the attacker which the AI uses to try to dodge an attack.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Export==&lt;br /&gt;
TRAM files can be extracted &#039;&#039;&#039;A) as pure XML&#039;&#039;&#039; files or &#039;&#039;&#039;B) as a pair of XML and DAE&#039;&#039;&#039; files. For editing the actual animation, you will want to use method B. While exporting an ONCC, you might see errors such as:&lt;br /&gt;
&lt;br /&gt;
 Cannot find instance &#039;TRAMKONCOMthrow_rev&#039;&lt;br /&gt;
 Cannot find instance &#039;TRAMKONCOMthrow_rev&#039;&lt;br /&gt;
 Cannot find instance &#039;TRAMKONRIFturn_right&#039;&lt;br /&gt;
 Cannot find instance &#039;TRAMKONOKOlev18_ZomStand&#039;&lt;br /&gt;
 Cannot find instance &#039;TRAMKONOKOcorner_hide&#039;&lt;br /&gt;
 Cannot find instance &#039;TRAMKONPIScorner_hide&#039;&lt;br /&gt;
&lt;br /&gt;
Ignore them, as those files doesn&#039;t exist. (Someday we should remove them from the TRACs.)&lt;br /&gt;
&lt;br /&gt;
===Via command line===&lt;br /&gt;
To export a single TRAM:&lt;br /&gt;
 onisplit -extract:xml output_path -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname.oni&lt;br /&gt;
&lt;br /&gt;
To export merged TRAMs:&lt;br /&gt;
 onisplit -extract:xml output_path &#039;&#039;&#039;-anim-merge&#039;&#039;&#039; -anim-body:path_to\TRBS_or_ONCCname.oni path_to\TRAMname1.oni  path_to\TRAMnameN.oni&lt;br /&gt;
&lt;br /&gt;
===Via Vago===&lt;br /&gt;
[[Image:Vago_xml_plus_dae_extraction.png|thumb|200px|right|Combined extraction of DAE and XML.]]&lt;br /&gt;
&lt;br /&gt;
Change to Characters tab and follow these steps.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 1:&#039;&#039;&#039; Select &amp;quot;TRAM ONI&amp;quot; as input format (&amp;quot;From&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 2:&#039;&#039;&#039; Select &amp;quot;XML / XML &amp;amp; DAE&amp;quot; as output format (&amp;quot;To&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 3:&#039;&#039;&#039; Tick checkbox &amp;quot;Extract with TRBS / ONCC&amp;quot;. It&#039;s important this is done before adding a TRAM file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 4:&#039;&#039;&#039; Set full path of ONCC or TRBS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 5:&#039;&#039;&#039; Add TRAM file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 6:&#039;&#039;&#039; Click &amp;quot;Convert&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Via Simple OniSplit GUI===&lt;br /&gt;
There was a long-standing problem with combined ONCC/TRAM files where the textures would be missing.&amp;lt;!--[Iritscen: I don&#039;t understand this sentence; is it important to keep this historical note?][Paradox: Geyser still didn&#039;t release a new OniSplit containing that fix, right?] With an older method you couldn&#039;t export non-native TRAM which meant to the TRAM had to be registered in the TRAC the ONCC is using.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[http://www.paradox.oni2.net/programs/Simple_OniSplit_GUI.zip Simple OniSplit GUI]&#039;&#039;&#039; 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.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 1:&#039;&#039;&#039; 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&#039;t matter.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 2:&#039;&#039;&#039; Hit &amp;quot;Convert&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Editing 3D data==&lt;br /&gt;
===Blender===&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===XSI===&lt;br /&gt;
In the past, the community&#039;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.&lt;br /&gt;
----&lt;br /&gt;
For the correct Mod Tool settings, see [[Mod Tool#Animating|HERE]].&lt;br /&gt;
&lt;br /&gt;
Here are some hints for creating animations when there is no rigging available:&lt;br /&gt;
* 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&#039;s feet will not float in the air or go through the ground. &lt;br /&gt;
* The first frame and last frames should match the probable previous and follow-up animations. This will reduce the necessity for long interpolations.&lt;br /&gt;
* When setting keyframes, each body part should have moved. This rule of thumb will give a more natural-looking animation.&lt;br /&gt;
* The first body part to be animated is always the pelvis.&lt;br /&gt;
* Watch out for pelvis rotations so that the XYZ rotations don&#039;t overlap too much, otherwise you will get into a [[wp:Gimbal_lock|gimbal lock]].&lt;br /&gt;
&lt;br /&gt;
Also see our [http://oni.bungie.org/forum/viewtopic.php?id=1433 OCF thread].&lt;br /&gt;
&lt;br /&gt;
==Import==&lt;br /&gt;
 onisplit -create output_path path_to\TRAMname.xml&lt;br /&gt;
&lt;br /&gt;
==Common operations on animations by the community==&lt;br /&gt;
===Speeding up existing animations===&lt;br /&gt;
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.]&lt;br /&gt;
&lt;br /&gt;
==Selected notes on animation types==&lt;br /&gt;
===Attacks===&lt;br /&gt;
====Extents and XML====&lt;br /&gt;
&#039;&#039;&#039;As a regular modder you don&#039;t need to know how the attack ring and the extents get calculated.&#039;&#039;&#039; If you just want to create an attack animation then add an appropriate &amp;lt;Attacks&amp;gt; code block to your XML as seen under {{SectionLink||Using OniSplit to calculate extents}}.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How attack ring (horizontal extents) and extents get calculated&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
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&#039;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&#039;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.&lt;br /&gt;
&lt;br /&gt;
There are two types of extents:&lt;br /&gt;
*&#039;&#039;&#039;&amp;lt;Extents&amp;gt;&#039;&#039;&#039; stores this info:&lt;br /&gt;
::&amp;lt;Angle&amp;gt; at which this extent radiates from the character.&lt;br /&gt;
::&amp;lt;Length&amp;gt; of this extent.&lt;br /&gt;
::&amp;lt;MinY&amp;gt; minimum height of this extent.&lt;br /&gt;
::&amp;lt;MaxY&amp;gt; maximum height of this extent.&lt;br /&gt;
:Length, MinY and MaxY serve to create an invisible area in space which is &amp;quot;dangerous to be in&amp;quot;. 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.&lt;br /&gt;
::The number of &amp;lt;Extent&amp;gt;s is equal to the number of attack frames: &amp;lt;End&amp;gt; minus &amp;lt;Start&amp;gt; plus one (because the start frame counts too). For example, for TRAMKONCOMkick_low1: &amp;lt;End&amp;gt;30&amp;lt;/End&amp;gt; minus &amp;lt;Start&amp;gt;22&amp;lt;/Start&amp;gt; plus 1 = 9 &amp;lt;Extent&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&amp;lt;AttackRing&amp;gt; (formerly known as &amp;lt;HorizontalExtents&amp;gt;&#039;&#039;&#039; stores this info:&lt;br /&gt;
::36 fields (exactly 36, otherwise it won&#039;t compile back into a .oni file), which correspond to areas in 10° intervals around the character as described above.&lt;br /&gt;
&lt;br /&gt;
====Using OniSplit to calculate extents====&lt;br /&gt;
Let&#039;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?&lt;br /&gt;
:1. Export the animation to XML with a body attached. If you extract using just &amp;quot;-extract:xml dest_folder TRAMsomething.oni&amp;quot;, you&#039;ll get the 3D animation data inside the XML (namely, the tags Heights, Velocities, Rotations, PositionOffset, and Positions; for an attack animation, you&#039;ll also get Attacks and AttackRing, and inside Attacks&#039; elements, each Attack element will have Extents at the end of it).&lt;br /&gt;
:However, if you extract this same animation using &amp;quot;-extract:xml dest_folder TRAMsomething.oni &#039;&#039;&#039;-anim-body ONCCtramuser.oni&#039;&#039;&#039;&amp;quot;, 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&#039;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.&lt;br /&gt;
:2. First, consider whether the TRAM should have something added to its Flags section, like Attack or ThrowTarget.&lt;br /&gt;
:3. Now add to the XML of the non-attack TRAM data in the following format (after the &amp;lt;SelfDamage /&amp;gt; section, typically):&lt;br /&gt;
        &amp;lt;Attacks&amp;gt;&lt;br /&gt;
            &amp;lt;Attack&amp;gt;&lt;br /&gt;
                &amp;lt;Start&amp;gt;1&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;End&amp;gt;10&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;Bones&amp;gt;RightWrist RightFist&amp;lt;/Bones&amp;gt;&lt;br /&gt;
                &amp;lt;Flags /&amp;gt;&lt;br /&gt;
                &amp;lt;Knockback&amp;gt;4&amp;lt;/Knockback&amp;gt;&lt;br /&gt;
                &amp;lt;HitPoints&amp;gt;10&amp;lt;/HitPoints&amp;gt;&lt;br /&gt;
                &amp;lt;HitType&amp;gt;KnockdownHead&amp;lt;/HitType&amp;gt;&lt;br /&gt;
                &amp;lt;HitLength&amp;gt;5&amp;lt;/HitLength&amp;gt;&lt;br /&gt;
                &amp;lt;StunLength&amp;gt;8&amp;lt;/StunLength&amp;gt;&lt;br /&gt;
                &amp;lt;StaggerLength&amp;gt;0&amp;lt;/StaggerLength&amp;gt;&lt;br /&gt;
            &amp;lt;/Attack&amp;gt;&lt;br /&gt;
        &amp;lt;/Attacks&amp;gt;&lt;br /&gt;
:Do not add an AttackRing section after Attacks.&lt;br /&gt;
:4. Import this with &amp;quot;-create dest_folder TRAMsomething.xml&amp;quot;. The Extents sections and the AttackRing will be calculated by OniSplit from the attached DAE.&lt;br /&gt;
:5. If you need this information for a patch mod, run &amp;quot;-extract:xml&amp;quot; on the TRAMsomething.oni you&#039;ve created &amp;lt;u&amp;gt;without&amp;lt;/u&amp;gt; using &amp;quot;-anim-body&amp;quot;. 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.&lt;br /&gt;
&lt;br /&gt;
===Combos===&lt;br /&gt;
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 &amp;lt;Lookup&amp;gt;&amp;lt;Type&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Setting a value in the &amp;lt;Link&amp;gt; of &#039;&#039;&#039;&amp;lt;DirectAnimations&amp;gt;&#039;&#039;&#039; will do two things:&lt;br /&gt;
# 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.)&lt;br /&gt;
# It disables &amp;lt;Interpolation&amp;gt;&amp;lt;End&amp;gt; for the next combo anim.&lt;br /&gt;
# It enables &amp;lt;Pause&amp;gt;&amp;lt;Soft&amp;gt; and &amp;lt;Pause&amp;gt;&amp;lt;Hard&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Just Frame input===&lt;br /&gt;
Implemented by Delano762, inspired by the game series Tekken, a Just Frame (&amp;quot;JF&amp;quot;) 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&#039;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.&lt;br /&gt;
&lt;br /&gt;
Example 1:&lt;br /&gt;
* new forward kick = TRAMKONCOMkick_fw_JF &amp;lt;FromState&amp;gt;Standing&lt;br /&gt;
** key strokes: w + k&lt;br /&gt;
* old forward kick = TRAMKONCOMkick_fw &amp;lt;FromState&amp;gt;RunStart&lt;br /&gt;
** key strokes: w, k&lt;br /&gt;
&lt;br /&gt;
Example 2:&lt;br /&gt;
* new forward punch = TRAMKONCOMpunch_fw_JF &amp;lt;FromState&amp;gt;Standing&lt;br /&gt;
** key strokes: w + p&lt;br /&gt;
* old forward punch = TRAMKONCOMpunch_fw &amp;lt;FromState&amp;gt;RunStart&lt;br /&gt;
** key strokes: w, p&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
===Throws===&lt;br /&gt;
;States&lt;br /&gt;
The first anim state of source (src) and target (tgt) is the &amp;quot;primary&amp;quot; &amp;lt;FromState&amp;gt;. The others &amp;lt;FromState&amp;gt; entries are located in &amp;lt;Shortcut&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
;Types&lt;br /&gt;
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). &lt;br /&gt;
&lt;br /&gt;
The game identifies which Target animation is it supposed to play through the &#039;&#039;ThrownX&#039;&#039; animation types. Each throw, together with its corresponding Target animation, uses one of the 17 available &#039;&#039;ThrownX&#039;&#039; animation types. These types are used in three tags:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;TargetType&amp;gt; tag in the Source animation,&lt;br /&gt;
* &amp;lt;Type&amp;gt; and &amp;lt;AimingType&amp;gt; tags in the Target animation.&lt;br /&gt;
&lt;br /&gt;
For example, Konoko&#039;s forward punch throw / &#039;&#039;KONCOMthrow_fw_p&#039;&#039; uses Thrown1 as its TargetType tag:&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;TargetType&amp;gt;Thrown1&amp;lt;/TargetType&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the corresponding target animation, &#039;&#039;KONCOMthrow_fw_p&#039;&#039;, uses Thrown1 in the Type and AimingType tags:&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;Type&amp;gt;Thrown1&amp;lt;/Type&amp;gt;&lt;br /&gt;
            &amp;lt;AimingType&amp;gt;Thrown1&amp;lt;/AimingType&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;ThrownX&#039;&#039; 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 &amp;quot;pairs&amp;quot; are organized within vanilla animations according to the Throw Table below, this is nothing more than a convention, and as a result &#039;&#039;ThrownX&#039;&#039; 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.&lt;br /&gt;
&lt;br /&gt;
The fact that the game has only 17 &#039;&#039;ThrownX&#039;&#039; 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 &amp;lt;Varient&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
 {{divhide|Throw table for vanilla Oni}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=100%&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 width=240 | names&lt;br /&gt;
! rowspan=2 width=40 | key combo&lt;br /&gt;
! colspan=4 | context&lt;br /&gt;
! colspan=2 style=&amp;quot;background: #FF0;&amp;quot; | anim type&lt;br /&gt;
! rowspan=2 width=400 | image&lt;br /&gt;
|-&lt;br /&gt;
&amp;lt;!--context--&amp;gt;&lt;br /&gt;
! width=40 | varient&lt;br /&gt;
! width=60 | src state&lt;br /&gt;
! width=60 | tgt state&lt;br /&gt;
! width=85 | facing setup&amp;lt;!--tgt position only?(or pelvis rotation?)--&amp;gt;&lt;br /&gt;
&amp;lt;!--facing setup tgt rotation relative to src pelvis (or tgt pelvis position?)--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--anim type--&amp;gt;&lt;br /&gt;
! width=40 style=&amp;quot;background: #FF0;&amp;quot; | src&lt;br /&gt;
! width=40 style=&amp;quot;background: #FF0;&amp;quot; | tgt&lt;br /&gt;
|-&lt;br /&gt;
! colspan=9 | normal throws a.k.a. static throws&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; static throw forward punch&lt;br /&gt;
: TRAMKONCOMthrow_fw_p&lt;br /&gt;
: TRAMKONCOMthrow_fw_p_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowForwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown1&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMthrow_fw_p.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; static throw forward kick&lt;br /&gt;
: TRAMKONCOMthrow_fw_k&lt;br /&gt;
: TRAMKONCOMthrow_fw_k_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; K + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowForwardKick&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown2&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMthrow_fw_k.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; static throw backward punch&lt;br /&gt;
: TRAMKONCOMthrow_bk&lt;br /&gt;
: TRAMKONCOMthrow_bk_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowBackwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown3&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMthrow_bk.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; static throw backward punch&lt;br /&gt;
: TRAMKONCOMthrow_bk_k&lt;br /&gt;
: TRAMKONCOMthrow_bk_k_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; K + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowBackwardKick&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown4&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMthrow_bk_k.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
! colspan=9 | run throws&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; run throw forward punch&lt;br /&gt;
: (forward &amp;quot;lariat&amp;quot;)&lt;br /&gt;
: TRAMKONCOMrun_throw_fw&lt;br /&gt;
: TRAMKONCOMrun_throw_fw_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑(↑)&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt; &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: silver;&amp;quot;&amp;gt;None&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt; &#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;RunThrowForwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown5&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMrun_throw_fw.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; run throw forward kick&lt;br /&gt;
: TRAMKONCOMrun_thw_fw_k&lt;br /&gt;
: TRAMKONCOMrun_thw_fw_k_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; K + ↑(↑)&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: silver;&amp;quot;&amp;gt;None&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingRightDown&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;RunThrowForwardKick&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown6&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMrun_thw_fw_k.jpg|200px]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
identical headers but&lt;br /&gt;
STRCOMrun_thw_fw_p (face-to-face, with righty angle) links to Thrown5&lt;br /&gt;
STRCOMrun_thw_fw_pl (face-to-face, with lefty angle) links to Thrown6&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; run throw backward punch&lt;br /&gt;
: (backward &amp;quot;lariat&amp;quot;)&lt;br /&gt;
: TRAMKONCOMrun_throw_bk&lt;br /&gt;
: TRAMKONCOMrun_throw_bk_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑(↑)&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: silver;&amp;quot;&amp;gt;None&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningBackLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningBackRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;RunThrowBackwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown7&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt;&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; run throw backward kick&lt;br /&gt;
: TRAMREDCOMrun_thw_bk_k&lt;br /&gt;
: TRAMREDCOMrun_thw_bk_k_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; K + ↑(↑)&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: silver;&amp;quot;&amp;gt;None&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningBackLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningBackRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;RunThrowBackwardKick&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown8&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:REDCOMrun_thw_bk_k.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
! colspan=9 | catching throws a.k.a. tackle throws&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; tackle throw backward kick?&amp;lt;br&amp;gt;(never used)&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt;&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt;&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; Thrown9&lt;br /&gt;
|&amp;lt;!--image--&amp;gt;&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; tackle throw backward punch&lt;br /&gt;
: TRAMKONCOMrun_tkl_bk_p&lt;br /&gt;
: TRAMKONCOMrun_tkl_bk_p_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑(↑)&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; COM&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: silver;&amp;quot;&amp;gt;None&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: silver;&amp;quot;&amp;gt;None&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunningLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
RunningRightDown&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;RunThrowBackwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown10&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONCOMrun_tkl_bk_p.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
! colspan=9 | disarm throws&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; pistol disarm throw forward punch&lt;br /&gt;
: TRAMKONPISthrow_fw_p&lt;br /&gt;
: TRAMKONPISthrow_fw_p_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; PIS&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowForwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown11&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONPISthrow_fw_p.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; pistol disarm throw forward kick&lt;br /&gt;
: TRAMKONPISthrow_fw_k&lt;br /&gt;
: TRAMKONPISthrow_fw_k_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; K + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; PIS&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowForwardKick&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown12&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONPISthrow_fw_k.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; pistol disarm throw backward punch&lt;br /&gt;
: TRAMKONPISthrow_bk&lt;br /&gt;
: TRAMKONPISthrow_bk_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; PIS&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingLeftDown&amp;lt;br&amp;gt;&lt;br /&gt;
WalkingRightDown&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowBackwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown13&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONPISthrow_bk.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; (never used)&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt;&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt;&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; Thrown14&lt;br /&gt;
|&amp;lt;!--image--&amp;gt;&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; rifle disarm throw forward punch&lt;br /&gt;
: TRAMKONRIFthrow_fw_p&lt;br /&gt;
: TRAMKONRIFthrow_fw_p_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; RIF&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;face&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowForwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown15&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONRIFthrow_fw_p.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; rifle disarm throw backward punch&lt;br /&gt;
: TRAMKONRIFthrow_bk_p&lt;br /&gt;
: TRAMKONRIFthrow_bk_p_tgt&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt; P + ↑&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt; RIF&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
RunStart&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&#039;&#039;&#039;Standing&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crouch&amp;lt;br&amp;gt;&lt;br /&gt;
Stunned&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt; face-to-&#039;&#039;&#039;back&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt; &#039;&#039;&#039;ThrowBackwardPunch&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; &#039;&#039;&#039;Thrown16&#039;&#039;&#039;&lt;br /&gt;
|&amp;lt;!--image--&amp;gt; [[Image:KONRIFthrow_bk_p.jpg|200px]]&lt;br /&gt;
|-style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;lt;!--names--&amp;gt; (never used)&lt;br /&gt;
|&amp;lt;!--key combo--&amp;gt;&lt;br /&gt;
|&amp;lt;!--varient--&amp;gt;&lt;br /&gt;
|&amp;lt;!--src state--&amp;gt;&lt;br /&gt;
|&amp;lt;!--tgt state--&amp;gt;&lt;br /&gt;
|&amp;lt;!--facing setup--&amp;gt;&lt;br /&gt;
|&amp;lt;!--anim type src--&amp;gt;&lt;br /&gt;
|&amp;lt;!--anim type tgt--&amp;gt; Thrown17&lt;br /&gt;
|&amp;lt;!--image--&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
{{divhide|end}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Running disarms&lt;br /&gt;
Oni offers support for running disarms (originally noticed [[OBD:BINA/OBJC/MELE/MoveList/Throw|HERE]]), which was taken advantage of by Delano&#039;s mod [http://mods.oni2.net/node/353 54000 New Combat Moves for Konoko].&lt;br /&gt;
&lt;br /&gt;
;Forward throws&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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&#039;s old version can be accessed [[Blender/Obsolete scripts#Script for adjusting forward throw targets|HERE]].&lt;br /&gt;
&lt;br /&gt;
===Run animations===&lt;br /&gt;
Here&#039;s a breakdown of the Striker&#039;s run animations, meant as an illustration for what would be needed to make new run TRAMs.&lt;br /&gt;
&lt;br /&gt;
Run cancel:&lt;br /&gt;
* STRIKEidle1 / another idle animation&lt;br /&gt;
* STRIKErun1stepa&lt;br /&gt;
* STRIKErun1stepb&lt;br /&gt;
* STRIKEidle1 / another idle animation&lt;br /&gt;
&lt;br /&gt;
Run – &#039;&#039;a minimal cycle&#039;&#039;:&lt;br /&gt;
* STRIKEidle1 / another idle animation&lt;br /&gt;
* STRIKErun1stepa&lt;br /&gt;
* STRIKErunstart&lt;br /&gt;
* STRIKErun_rt&lt;br /&gt;
* STRIKErun_lt (optional)&lt;br /&gt;
* STRIKErunstop&lt;br /&gt;
* STRIKEidle1 / another idle animation&lt;br /&gt;
&lt;br /&gt;
Follow the images below from right to left.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:XML_TRAM_STRIKErunstop.png|STRIKErunstop&lt;br /&gt;
Image:XML_TRAM_STRIKErun_lt.png|STRIKErun_lt&lt;br /&gt;
Image:XML_TRAM_STRIKErun_rt.png|STRIKErun_rt&lt;br /&gt;
Image:XML_TRAM_STRIKErunstart.png|STRIKErunstart&lt;br /&gt;
Image:XML_TRAM_STRIKErun1stepa.png|STRIKErun1stepa&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==List of unused animations==&lt;br /&gt;
Here are all the known unused animations, with links to videos of them where applicable. These could be recycled in a new mod.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;From the original game&#039;&#039;&#039;&lt;br /&gt;
* KONOKOconsole_punch: What the name says (the engine can use that animation depending on the console&#039;s configuration, see [[OBD:BINA/OBJC/CONS|CONS]]) .&lt;br /&gt;
* KONOKOlev3_intro: Looks like she&#039;s placing something (bomb?) and then running away.&lt;br /&gt;
* [https://www.youtube.com/watch?v=dszw2vmlmzw KONOKOlev4_undress]: From an aborted clothes-changing cutscene.&lt;br /&gt;
* KONOKOlev16_bomb: Planting a bomb.&lt;br /&gt;
* KONCOMsuper_kick: Now used in [[OTA]] as a spawn event, and by the fan-made character [[Shinatama Evolved]].&lt;br /&gt;
* KONCOMsuper_punch: KONCOMpunch_heavy but without the shouted attack name, has HalfDamage flag, and does 10 less damage in its first attack part.&lt;br /&gt;
* [https://www.youtube.com/watch?v=CRuZq_uYOQk COMPISidle_special1]: Comguy checking environment and his gun; meant for a feature that would visually depict an elevation in the AI&#039;s level of alertness after, say, hearing a noise.&lt;br /&gt;
* STRPISidle_special1 (see above link): Striker checking his his gun and communicating with an ally (another unused alertness-elevation animation).&lt;br /&gt;
* THUGlev1_direct: Thug probably directing a truck driver.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;From modders&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:Female stun.jpg|right|thumb|Char A and Char B performing stun animations.]]&lt;br /&gt;
&lt;br /&gt;
* http://mods.oni2.net/node/376&lt;br /&gt;
** StrikerKneeStepKickThrow.zip&lt;br /&gt;
** REDCOMjump_fw_crouch--double_flip--dae.zip&lt;br /&gt;
** KONprone_getup--dae.zip&lt;br /&gt;
** KONRIF_k_bk_throw.zip&lt;br /&gt;
** female_stun--dae.zip&lt;br /&gt;
&lt;br /&gt;
==Special effects==&lt;br /&gt;
If the scene is overloaded by too many particles (including motion blur), these effects will cease being rendered. So don&#039;t overuse effects.&lt;br /&gt;
&lt;br /&gt;
===Color trails===&lt;br /&gt;
Open the XML-accompanied TRAM, search for the &amp;quot;Particles&amp;quot; tag, and insert your markup.&lt;br /&gt;
&lt;br /&gt;
First example: TRAMSTRCOMcomb_p_p.xml&lt;br /&gt;
&lt;br /&gt;
[[Image:Colorful_contrail_added.png|right|thumb]]&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;Particles&amp;gt;&lt;br /&gt;
            &amp;lt;Particle&amp;gt;&lt;br /&gt;
                &amp;lt;StartFrame&amp;gt;0&amp;lt;/StartFrame&amp;gt;&lt;br /&gt;
                &amp;lt;EndFrame&amp;gt;12&amp;lt;/EndFrame&amp;gt;&lt;br /&gt;
                &amp;lt;Bone&amp;gt;LeftFist&amp;lt;/Bone&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;contrail&amp;lt;/Name&amp;gt;&lt;br /&gt;
            &amp;lt;/Particle&amp;gt;&lt;br /&gt;
        &amp;lt;/Particles&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;contrail&amp;quot; is looked up by the character class (ONCC) that emits the actual particle; here it is &amp;quot;h2h_strtrail_e01&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This second example is about creating two different contrails in a TRAM at the same time. The animation is &amp;quot;TRAMSTRCOMpunch_heavy.xml&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Different_contrails_in_attack.png|right|thumb]]&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;Particles&amp;gt;&lt;br /&gt;
            &amp;lt;Particle&amp;gt;&lt;br /&gt;
                &amp;lt;Start&amp;gt;0&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;End&amp;gt;54&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;Bone&amp;gt;RightWrist&amp;lt;/Bone&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;contrail&amp;lt;/Name&amp;gt;&lt;br /&gt;
            &amp;lt;/Particle&amp;gt;&lt;br /&gt;
            &amp;lt;Particle&amp;gt;&lt;br /&gt;
                &amp;lt;Start&amp;gt;0&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;End&amp;gt;54&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;Bone&amp;gt;LeftWrist&amp;lt;/Bone&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;&#039;&#039;&#039;contrail_2&#039;&#039;&#039;&amp;lt;/Name&amp;gt;&lt;br /&gt;
            &amp;lt;/Particle&amp;gt;&lt;br /&gt;
        &amp;lt;/Particles&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;Type&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;ONCPParticle&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;contrail&amp;lt;/Name&amp;gt;&lt;br /&gt;
                &amp;lt;Type&amp;gt;h2h_strtrail_e01&amp;lt;/Type&amp;gt;&lt;br /&gt;
                &amp;lt;BodyPart&amp;gt;-1&amp;lt;/BodyPart&amp;gt;&lt;br /&gt;
            &amp;lt;/ONCPParticle&amp;gt;&lt;br /&gt;
            &amp;lt;ONCPParticle&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;&#039;&#039;&#039;contrail_2&#039;&#039;&#039;&amp;lt;/Name&amp;gt;&lt;br /&gt;
                &amp;lt;Type&amp;gt;&#039;&#039;&#039;h2h_murtrail_e01&#039;&#039;&#039;&amp;lt;/Type&amp;gt;&lt;br /&gt;
                &amp;lt;BodyPart&amp;gt;-1&amp;lt;/BodyPart&amp;gt;&lt;br /&gt;
            &amp;lt;/ONCPParticle&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motion blur===&lt;br /&gt;
[[Image:XML_TRAM_willow_kick_with_motion_blur.jpg|thumb|200px]]&lt;br /&gt;
Motion blur in Oni works much like ghosting/onion skinning features in any animation software: In the frame range specified by &amp;lt;Start&amp;gt; and &amp;lt;End&amp;gt; an additional instance of body parts specified in &amp;lt;Bones&amp;gt; are rendered for additional extra frames specified by &amp;lt;Lifetime&amp;gt;, with transparency set by &amp;lt;Alpha&amp;gt;, and every &amp;lt;Interval&amp;gt; frames within the frame range.&lt;br /&gt;
Example snippet from KONCOMcomb_p_p_k:&lt;br /&gt;
        &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
            &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
                &amp;lt;Bones&amp;gt;RightThigh RightCalf RightFoot&amp;lt;/Bones&amp;gt;&lt;br /&gt;
                &amp;lt;Start&amp;gt;20&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;End&amp;gt;28&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;Lifetime&amp;gt;4&amp;lt;/Lifetime&amp;gt;&lt;br /&gt;
                &amp;lt;Alpha&amp;gt;127&amp;lt;/Alpha&amp;gt;&lt;br /&gt;
                &amp;lt;Interval&amp;gt;1&amp;lt;/Interval&amp;gt;&lt;br /&gt;
            &amp;lt;/MotionBlur&amp;gt;&lt;br /&gt;
        &amp;lt;/MotionBlur&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
        &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
            &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
                &amp;lt;Bones&amp;gt;LeftThigh LeftCalf LeftFoot&amp;lt;/Bones&amp;gt;&lt;br /&gt;
                &amp;lt;Start&amp;gt;10&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;End&amp;gt;18&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;Lifetime&amp;gt;4&amp;lt;/Lifetime&amp;gt;&lt;br /&gt;
                &amp;lt;Alpha&amp;gt;127&amp;lt;/Alpha&amp;gt;&lt;br /&gt;
                &amp;lt;Interval&amp;gt;1&amp;lt;/Interval&amp;gt;&lt;br /&gt;
            &amp;lt;/MotionBlur&amp;gt;&lt;br /&gt;
            &amp;lt;MotionBlur&amp;gt;&lt;br /&gt;
                &amp;lt;Bones&amp;gt;RightThigh RightCalf RightFoot&amp;lt;/Bones&amp;gt;&lt;br /&gt;
                &amp;lt;Start&amp;gt;20&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;End&amp;gt;28&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;Lifetime&amp;gt;4&amp;lt;/Lifetime&amp;gt;&lt;br /&gt;
                &amp;lt;Alpha&amp;gt;127&amp;lt;/Alpha&amp;gt;&lt;br /&gt;
                &amp;lt;Interval&amp;gt;1&amp;lt;/Interval&amp;gt;&lt;br /&gt;
            &amp;lt;/MotionBlur&amp;gt;&lt;br /&gt;
        &amp;lt;/MotionBlur&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Impact effect===&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
[[Image:XML_TRAM_KONCOMkick_fw_with_ninflash1.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
{{XML}}&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Creating_an_animation_rig_in_Blender&amp;diff=43858</id>
		<title>Creating an animation rig in Blender</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Creating_an_animation_rig_in_Blender&amp;diff=43858"/>
		<updated>2025-01-22T20:11:04Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Summary -&amp;gt; SoftImage XSI, Things to know -&amp;gt; Brief overview on TRAMs}}&lt;br /&gt;
This tutorial shows you how to create the [http://mods.oni2.net/node/388 animation rig for Blender] (made by geyser) from scratch, with some improvements.&lt;br /&gt;
&lt;br /&gt;
The purpose of this rig is to give us much better tools to animate, compared to our [http://oni.bungie.org/forum/viewtopic.php?pid=23698#p23698 previous process in Softimage XSI] by EdT, which allowed us to animate exclusively with Forward Kinematics. While FK may work for simple, short animations done on characters with a small amount of bones, it does not work well for Oni characters and animations, as it&#039;s too labor-intensive and inefficient.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;If you are looking for information on how to use the rig, please refer to the article on that available [[Using_the_Rigify_animation_rig|HERE]].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Prerequisite tutorials==&lt;br /&gt;
I highly recommend watching the tutorials below if you feel you&#039;re lacking knowledge in any of these subjects:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
General Blender basics:&lt;br /&gt;
* [https://www.youtube.com/watch?v=RG8qK5zPqgM Wolf&#039;s 45-Minute Crash Course for Blender Virgins]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Blender Character Rigging overview showing that you can create a Rigify rig in less than a minute at 5:43, and also rig a character while at it:&lt;br /&gt;
* [https://www.youtube.com/watch?v=f2pTkW-1JkE&amp;amp;t=343s Character Rigging – Blender 2.80 Fundamentals]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Practical and intuitive explanation of what Inverse and Forward Kinematics (IK/FK) are – this is explained in Maya, but same principles apply in every 3D editing program including Blender:&lt;br /&gt;
* [https://www.youtube.com/watch?v=p6PYKyxR0aY Animating with IK and FK]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basics of using Rigify:&lt;br /&gt;
* [https://www.youtube.com/watch?v=vKgH5zXIYmM Rigify Tutorial #08 – Posing the Rigify rig] by CGDive&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rigify Bone Groups and Layers:&lt;br /&gt;
* [https://www.youtube.com/watch?v=5FK4jDCAOkk Rigify Tutorial 7-1: Rigify Bone Groups and Layers (Overview)] by CGDive&lt;br /&gt;
* [https://www.youtube.com/watch?v=JZZHCmKFcMs Rigify Tutorial 7-2: Rigify Bone Groups and Layers (Practice)] by CGDive&lt;br /&gt;
* [https://www.youtube.com/watch?v=2XldUB2eT-o Rigify Tutorial 7-3: Rigify Bone Groups and Layers (Advanced)] by CGDive&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Changing Rigify Custom Shapes and Widgets:&lt;br /&gt;
* [https://www.youtube.com/watch?v=beVtWATcw9U Rigify – Custom Shapes/Widgets] by CGDive&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Blender custom properties and &#039;&#039;&#039;drivers&#039;&#039;&#039; (drivers in the rig described here are used to set the influence of its controllers&#039; bone constraints through the Pose1 and Pose2 bone locations):&lt;br /&gt;
* [https://www.youtube.com/watch?v=_197jQFh22E Custom properties and drivers in blender made easy] by Pierrick Picaut&lt;br /&gt;
&lt;br /&gt;
===Tracking constraint tutorials===&lt;br /&gt;
These explain constraints like Damped Track which are used by Rigify – you can skip this if you want, but it might give you a better idea of how Rigify&#039;s MCH (Mechanical) layers work, or come in handy in the distant future; other than that, you don&#039;t need to know them to animate for Oni:&lt;br /&gt;
* [https://www.youtube.com/watch?v=aGBOu-dNZ-w Tracking Constraints – Blender 2.80 Fundamentals]&lt;br /&gt;
* [https://www.youtube.com/watch?v=5FK4jDCAOkk Camera Track To vs Damped Track Constraints | Pros &amp;amp; Cons Explained With Examples | Blender] by 5 minutes Blender&lt;br /&gt;
&lt;br /&gt;
==Things to know before starting==&lt;br /&gt;
There are several things worth knowing before you start creating the rig.&lt;br /&gt;
&lt;br /&gt;
===Tools and relevant tutorials===&lt;br /&gt;
[[Image:Cmder.png|200px|right|thumb|Screenshot showing Cmder&#039;s capabilities within the context of modding Oni.]]&lt;br /&gt;
* [http://mods.oni2.net/node/38 &#039;&#039;&#039;Current version of OniSplit.&#039;&#039;&#039;] This is the tool needed to import and export assets out of Oni. &#039;&#039;&#039;DO NOT USE OniSplit GUI or Vago for importing Oni assets into Blender&#039;&#039;&#039; – neither of these weren&#039;t updated in a long time, and thus they don&#039;t support OniSplit&#039;s v0.9.99.2 -blender option. You can still use them for other purposes though, such as sounds and converting .oni files to XMLs, etc.&lt;br /&gt;
* [https://cmder.app/ &#039;&#039;&#039;Cmder&#039;&#039;&#039;] (Windows only) – because OniSplit is a command line tool, it is highly recommended to get any upgrade to Windows&#039; Command Prompt. As shown in the screenshot on the right, Cmder allows you to start it from the context menu in any selected folder, and it also remembers your most recently used commands, vastly improving your workflow when you&#039;re forced to use any command line tools.&lt;br /&gt;
* [https://docs.blender.org/manual/en/2.81/addons/rigging/rigify.html &#039;&#039;&#039;Rigify&#039;&#039;&#039;] – it&#039;s a plugin for Blender designed to automate a lot of rigging work. The rig described here is generated using Rigify.&lt;br /&gt;
* [https://docs.google.com/document/d/175uJGklYASAgrFjxuUG4-kJRDoMTjjP7GvNxSj1GscU/edit &#039;&#039;&#039;Oni-Blender tutorial&#039;&#039;&#039;] by EdT. Please read this in entirety to know likely-to-happen issues and refer to this as your guide for OniSplit commands relating to Blender.&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?pid=23230#p23230 &#039;&#039;&#039;Brief overview on creating TRAMs&#039;&#039;&#039;] by EdT – while this was written with XSI in mind, this is still relevant as the process for preparing the XML files for Oni is still the same. Also the next post in that thread, called &#039;&#039;&#039;Brief walk through on modifying a TRAM,&#039;&#039;&#039; is an example of that overview put into practice.&lt;br /&gt;
&lt;br /&gt;
===Assorted issues in Blender===&lt;br /&gt;
Please refer to [[Blender#Oni-specific_issues_with_Blender|THIS]] section of the &amp;quot;Blender&amp;quot; article for issues that you will run into while Oni modding.&lt;br /&gt;
&lt;br /&gt;
==Overview of the rig==&lt;br /&gt;
Here is an overview of how the rig works: As stated before, our previous animating process was limited to FK only, which is inefficient for Oni. So instead we desperately needed an IK/FK capable rig, to which we would be able to snap a character, so we could animate him/her.&lt;br /&gt;
&lt;br /&gt;
At the same time, the rig would have to be capable of the opposite thing – snapping itself to the animated character. That&#039;s because most often the way we start out with making a new animation is copying the first or last frame of the preceding animation. This functionality has been implemented, and is called Pose Matching. The way it works is simple – it uses bone constraints in rig controller bones targeting the character model in order to snap the rig to the model.&lt;br /&gt;
&lt;br /&gt;
The rig uploaded on Oni Mod Depot contains three Konokos by default: One T-Posed Konoko and two animated ones, all stored in their own collections. The T-Posed Konoko is there because it was easiest to build the rig off a T-Pose, while the remaining two ones, stored in Pose 1 and Pose 2 collections, is where you are supposed to store your animated characters, to which you can Pose Match, and thus check if Pose Matching works as intended.&lt;br /&gt;
&lt;br /&gt;
Because Oni does not store its animations in form of an armature, but rather as locations and rotations of 19 objects organized in a parent-child relationship, this forces us to use the earlier mentioned object and bone constraints. This is also creates a big problem: in order to animate, rotation and location data from the 19 character body parts have to be transformed onto the rig, and then the body parts have to be constrained to the rig. Once you are done animating and you want to export your animation, you have to do the reverse: transform the animation from the rig onto the 19 body parts, and then disable the constraints. This is quite inconvenient, because all of the constraints (and there&#039;s a lot of them) in both the body parts and rig have to be turned on and off.&lt;br /&gt;
&lt;br /&gt;
The general workflow of making animations using this rig is the following, assuming you want to make a single animation (i.e. you don&#039;t want to make a throw animation):&lt;br /&gt;
&lt;br /&gt;
# Open up a Blender scene containing the rig.&lt;br /&gt;
# Delete either the model in Pose1 or Pose2.&lt;br /&gt;
# (OPTIONAL) Assuming you want to animate a different character, delete the T-posed model.&lt;br /&gt;
## Import your desired character with textures using -noanim.&lt;br /&gt;
# Import the animation you are using as a starting point.&lt;br /&gt;
## If you did point 3, apply the textures on the animated model.&lt;br /&gt;
# Using the RigBoneConstraintTargetSetter script available [[Blender/Obsolete scripts#Rig bone constraint target setting script|HERE]], set the targets of the rig&#039;s bone constraints to be the body parts of the animation you&#039;ve imported.&lt;br /&gt;
# Using the Pose Matching functionality, constrain the rig to the imported animation (Set the IK-FK sliders on rig limbs to 1, as Pose Matching works only through FK controllers)&lt;br /&gt;
# For each frame that you want to remain in your animation, while having all the bones selected (or the ones you want), press Ctrl+A, select Apply Visual Transform to Pose and keyframe it.&lt;br /&gt;
# Disable bone constraints on the rig using the BoneConstraintEnabler script available [[Blender/Obsolete scripts#Script for enabling.2Fdisabling bone constraints in the selected armature|HERE]]. &lt;br /&gt;
# &#039;&#039;&#039;Make your animation.&#039;&#039;&#039;&lt;br /&gt;
# Once your animation is ready, use the Visual Transformer script available [[Blender/Obsolete scripts#Visual transformer script|HERE]] to bake the rig keyframes into the character model.&lt;br /&gt;
# Using the ObjectConstraintEnabler script available [[Blender/Obsolete scripts#Script for enabling.2Fdisabling constraints in selected objects|HERE]], disable the object constraints on the character model. &#039;&#039;&#039;The character model should now be animated and have the needed rotations and locations.&lt;br /&gt;
# Export the animation as a DAE.&lt;br /&gt;
&lt;br /&gt;
==Importing animations and preparing the Blender scene==&lt;br /&gt;
&#039;&#039;&#039;The actual tutorial starts here.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For detailed explanation of the required OniSplit commands, please refer to the &#039;&#039;&#039;Oni-Blender Tutorial by EdT&#039;&#039;&#039; listed in the &#039;&#039;&#039;Tools and relevant tutorials&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:ARB SceneUponImportingKonokos.png|400px|right|thumb|The expected result by the end of this section.]]&lt;br /&gt;
&lt;br /&gt;
# Using OniSplit, export any character you want as a DAE (-extract:dae) using -noanim (T-Pose) and -blender arguments. &lt;br /&gt;
## As per EdT&#039;s &#039;&#039;&#039;Oni-Blender Tutorial&#039;&#039;&#039;, you should get &amp;lt;mark&amp;gt;&amp;lt;tt&amp;gt;AnimationDaeWriter: custom axis conversion&amp;lt;/tt&amp;gt;&amp;lt;/mark&amp;gt; in OniSplit output if you&#039;ve used the -blender argument. If you didn&#039;t get that on the output, it means something most likely went wrong and you won&#039;t be able to import the model into Blender (or you will be able to import it but it will be wrong).&lt;br /&gt;
## Assuming you wanted a textured model and thus you&#039;ve exported an ONCC, you should now get a &#039;&#039;&#039;DAE file&#039;&#039;&#039; and an &#039;&#039;&#039;&#039;&#039;images&#039;&#039;&#039;&#039;&#039; folder containing the textures for it.&lt;br /&gt;
# Using OniSplit, export any two animations as an XML (-extract:xml) using -anim-body (lets you specify the character you want) and -blender arguments.&lt;br /&gt;
## You should get &#039;&#039;&#039;one DAE and an XML file for each animation, totalling four files.&#039;&#039;&#039; &lt;br /&gt;
# Open up Blender and set your scene&#039;s frame rate to 60 FPS. If you don&#039;t, the keyframes of the imported animations will get tightened up together, because Blender&#039;s default scene frame rate is 24 FPS.&lt;br /&gt;
# Import the -noanim model into Blender first (&#039;&#039;&#039;MAKE SURE YOU CHECK THE &#039;&#039;Import Unit&#039;&#039; BOX&#039;&#039;&#039;, otherwise you will import the model with arbitrary units which will break everything and will be basically unadjustable later)&lt;br /&gt;
# Import the animations into Blender (&#039;&#039;&#039;ALSO MAKE SURE YOU CHECK THE &#039;&#039;Import Unit&#039;&#039; BOX EACH TIME&#039;&#039;&#039;)&lt;br /&gt;
# At this point the -noanim/T-posed model in the scene should have no suffix in its body part names, while the animated models should have &#039;&#039;.001&#039;&#039; and &#039;&#039;.002&#039;&#039; suffixes. This is intended; the T-posed model will serve for building the metarig and editing the rig once it&#039;s generated, while the animated models are needed for pose matching purposes, where the suffixes are useful for setting up the bone constraints.&lt;br /&gt;
# Create three new collections in the Outliner, name them &#039;&#039;T-pose&#039;&#039;, &#039;&#039;Pose 1&#039;&#039; and &#039;&#039;Pose 2&#039;&#039;. These three collections allow you to quickly hide the respective models from the Viewport using the eye icon in the Outliner.&lt;br /&gt;
## Move the T-Posed model to &#039;&#039;T-pose&#039;&#039;, and move &#039;&#039;.001&#039;&#039; and &#039;&#039;.002&#039;&#039; animated models to &#039;&#039;Pose 1&#039;&#039; and &#039;&#039;Pose 2&#039;&#039; collections respectively.&lt;br /&gt;
# If you&#039;ve imported the textured model, [[Blender#Lack of textures on animated models|apply textures to the animated models]] and [[Blender#Alpha transparency issue|fix the alpha transparency issue]].&lt;br /&gt;
# At this point, your scene should look as shown in the screenshot on the right.&lt;br /&gt;
# You can hide the Pose 1 and Pose 2 collections – they won&#039;t be changed in this tutorial anymore.&lt;br /&gt;
&lt;br /&gt;
==Adjusting T-posed model&#039;s Z location==&lt;br /&gt;
At this moment the T-posed model is sunk to the ground. That&#039;s because the pelvis location is set to 0,0,0. All of the animations in Oni have their heights adjusted [[XML:TRAM#List_of_tags.2C_types.2C_and_flags|(through the &amp;lt;Height&amp;gt; tags)]] so that the pelvis is roughly at Z ~ 0.9, so that the characters appear standing on the floor instead of, again, sinking into it. For this reason, we want to adjust the position of the pelvis so that the feet soles are aligned with the floor.&lt;br /&gt;
&lt;br /&gt;
[[Image:PelvisZLocation.png|400px|right|thumb|The expected result by the end of this section.]]&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;10&amp;quot;&amp;gt;Adjust the Z position of the T-posed model&#039;s Pelvis in one of the two ways:&amp;lt;/li&amp;gt;&lt;br /&gt;
## Simply switch to Front Orthographic view (Num 1) and move the Pelvis along the Z axis so that the feet soles are roughly aligned with the floor. This will work, but if you want 100% accuracy, use the method below.&lt;br /&gt;
## The 3D Cursor snapping method:&lt;br /&gt;
### Select one of the feet in Object mode.&lt;br /&gt;
### Switch to Edit mode.&lt;br /&gt;
### Select one of the lowest-reaching vertices on the foot and Snap Cursor to Active. (Shift + S, 3)&lt;br /&gt;
### Switch back to object mode.&lt;br /&gt;
### Select the Pelvis.&lt;br /&gt;
### Snap Selection to Cursor. (Shift+S, 8)&lt;br /&gt;
### Set the X and Y locations of the pelvis to 0.&lt;br /&gt;
### Invert the Z location of the pelvis.&lt;br /&gt;
### The pelvis should be now at Z ~ 0.9 with feet soles perfectly aligned with the floor.&lt;br /&gt;
# At this point, your scene should look as shown in the screenshot on the right.&lt;br /&gt;
&lt;br /&gt;
==Creating the Rigify metarig and adding limb flexion==&lt;br /&gt;
This part describes how to create a Rigify metarig and how to adjust it so that it matches the T-posed model body parts.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;12&amp;quot;&amp;gt;Before you proceed to create the rig, you need to add small rotations to the limbs, which will allow Rigify to know in which direction the elbows and knees are going to bend. Otherwise, the rig will not function properly.&amp;lt;/li&amp;gt;&lt;br /&gt;
## Add the following Z rotations to the respective body parts in accordance with the list below:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Z rotation !! Bones&lt;br /&gt;
|-&lt;br /&gt;
| -5 || &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;right_thigh &amp;lt;li&amp;gt;left_thigh &amp;lt;li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| -10 || &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;right_calf &amp;lt;li&amp;gt;left_calf &amp;lt;li&amp;gt;right_wrist &amp;lt;li&amp;gt;left_wrist &amp;lt;/ul&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 5 || &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;right_biceps &amp;lt;li&amp;gt;left_biceps &amp;lt;li&amp;gt; right_handfist &amp;lt;li&amp;gt;left_handfist &amp;lt;li&amp;gt;right_foot &amp;lt;li&amp;gt;left_foot&amp;lt;/ul&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;13&amp;quot;&amp;gt;Enable Rigify in Blender if you haven&#039;t already – you can do that by going to Edit / Preferences / Addons and looking it up, as Rigify comes with by Blender by default.&amp;lt;/li&amp;gt;&lt;br /&gt;
# Add a Basic Human Metarig  to the scene. ( Add Menu / Armature / Basic / Basic Human (Meta-Rig) )&lt;br /&gt;
## Scale the rig by 10 or so that it&#039;s roughly the size of the character.&lt;br /&gt;
## Apply the scale. ( Object / Apply / Scale )&lt;br /&gt;
# Go to Metarig&#039;s Object Data Properties tab and:&lt;br /&gt;
## Open Viewport Display,&lt;br /&gt;
## Check &#039;&#039;In Front&#039;&#039; box to make the metarig easier to select when your Viewport is in Solid or Material Preview shading modes,&lt;br /&gt;
## Check the &#039;&#039;Axes&#039;&#039; box to see the local axes of each bones – this makes their rolls easier to understand.&lt;br /&gt;
# Remove the following bones from the Metarig:&lt;br /&gt;
*pelvis.L&lt;br /&gt;
*pelvis.R&lt;br /&gt;
*breast.L&lt;br /&gt;
*breast.R&lt;br /&gt;
*spine.005&lt;br /&gt;
*spine.006&lt;br /&gt;
# &amp;lt;li value=&amp;quot;17&amp;quot;&amp;gt;Go to Edit mode, select Bone Properties tab and change the &#039;&#039;Connected&#039;&#039; box of the following Metarig&#039;s bones accordingly to the below table:&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bone || Connected&lt;br /&gt;
|-&lt;br /&gt;
| spine.003 || Disable&lt;br /&gt;
|-&lt;br /&gt;
| spine.004 || Enable&lt;br /&gt;
|-&lt;br /&gt;
| shoulder.l || Enable&lt;br /&gt;
|-&lt;br /&gt;
| shoulder.r || Enable&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;18&amp;quot;&amp;gt;The default Rigify bone layer order is highly unergonomic. For this reason, reassign the following bones to bone layers in accordance with the table below. You can reassign bones&#039; bone layers by selecting them and pressing M. Make sure you have enabled User Tooltips in Preferences / Interface – that way when you move your cursor over the layer box, a tooltip will display the layer number.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bones !! Bone layer&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;spine &amp;lt;li&amp;gt;spine.001 &amp;lt;li&amp;gt;spine.002 &amp;lt;li&amp;gt;spine.003 &amp;lt;li&amp;gt;spine.004 &amp;lt;li&amp;gt;shoulder.l &amp;lt;li&amp;gt;shoulder.r &amp;lt;/ul&amp;gt; || 8&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;upper_arm.L &amp;lt;li&amp;gt;forearm.L &amp;lt;li&amp;gt;hand.L &amp;lt;/ul&amp;gt; || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;upper_arm.R &amp;lt;li&amp;gt;forearm.R &amp;lt;li&amp;gt;hand.R &amp;lt;/ul&amp;gt; || 16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;thigh.L &amp;lt;li&amp;gt;shin.L &amp;lt;li&amp;gt;foot.L &amp;lt;li&amp;gt;toe.L &amp;lt;li&amp;gt;heel.02.L &amp;lt;/ul&amp;gt; || 4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;thigh.R &amp;lt;li&amp;gt;shin.R &amp;lt;li&amp;gt;foot.R &amp;lt;li&amp;gt;toe.R &amp;lt;li&amp;gt;heel.02.R &amp;lt;/ul&amp;gt; || 20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;19&amp;quot;&amp;gt;Go to Pose mode, select Bone Properties tab and open the Rigify Type box.&amp;lt;/li&amp;gt;&lt;br /&gt;
# Set &#039;&#039;Limb Segments&#039;&#039; and &#039;&#039;B-Bone Segments&#039;&#039; to 1 on the bones listed below. Because Oni uses rigid body parts, Limb Segments and Bendy bones are not needed.&lt;br /&gt;
* upper_arm.L&lt;br /&gt;
* upper_arm.R&lt;br /&gt;
* thigh.L&lt;br /&gt;
* thigh.R&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;20&amp;quot;&amp;gt; Disable &#039;&#039;Assign Tweak Layers&#039;&#039; checkbox on the bones listed below.&amp;lt;/li&amp;gt;&lt;br /&gt;
* upper_arm.L&lt;br /&gt;
* upper_arm.R&lt;br /&gt;
* thigh.L&lt;br /&gt;
* thigh.R&lt;br /&gt;
* spine&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;21&amp;quot;&amp;gt; Remove &#039;&#039;rig type&#039;&#039; on the &#039;&#039;spine.004&#039;&#039; bone.&amp;lt;/li&amp;gt;&lt;br /&gt;
# Set &#039;&#039;rig type&#039;&#039; on the &#039;&#039;spine.003&#039;&#039; bone to &#039;&#039;spines.super_head&#039;&#039;. &lt;br /&gt;
# Enable the &#039;&#039;Connect chain&#039;&#039; checkbox on the &#039;&#039;spine.003&#039;&#039; bone.&lt;br /&gt;
# Disable the &#039;&#039;Widget&#039;&#039; checkbox on the &#039;&#039;shoulder.L&#039;&#039; and &#039;&#039;shoulder.R bones&#039;&#039;.&lt;br /&gt;
# Set &#039;&#039;pivot_position&#039;&#039; on the &#039;&#039;spine&#039;&#039; bone to 1.&lt;br /&gt;
# Enable the &#039;&#039;Custom Pivot Control&#039;&#039; checkbox on the &#039;&#039;spine&#039;&#039; bone.&lt;br /&gt;
# Assign Tweak Layer of spine.003 to 9.&lt;br /&gt;
# Assign FK layers for the following bones in accordance with the table below:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bones !! Bone layer&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;spine &amp;lt;li&amp;gt;spine.003&amp;lt;/ul&amp;gt; || 9&lt;br /&gt;
|-&lt;br /&gt;
| upper_arm.L || 1&lt;br /&gt;
|-&lt;br /&gt;
| upper_arm.R || 17&lt;br /&gt;
|-&lt;br /&gt;
| thigh.L &amp;lt;/ul&amp;gt; || 5&lt;br /&gt;
|-&lt;br /&gt;
| thigh.R &amp;lt;/ul&amp;gt; || 21&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;29&amp;quot;&amp;gt;Now you need to adjust the metarig&#039;s bones so that they match up with character body parts. In order to reduce the amount of needed work, switch to Edit Mode and check the X-Axis Mirror either in Options or the Tool tab.&amp;lt;/li&amp;gt;&lt;br /&gt;
# Switch to Object mode and using the Snapping Cursor to Active, and Snapping Selection to Cursor in the Snap menu (Shift + S), keep snapping cursor to model&#039;s body parts, selecting the Metarig, switching to Edit mode, selecting the appropriate bone and snapping it to 3D Cursor. &#039;&#039;&#039;I believe it is intuitive which bones should be snapped to which body parts, therefore there is no need for a table describing that, with the exception of hints on what should be done about spine.004, hand.L, hand.R, toe.L, toe.R, heel.02.L and heel.02.R.&#039;&#039;&#039;&lt;br /&gt;
## There is actually nothing you need to do about the heel bones, leave them as they are.&lt;br /&gt;
## Snap the tails of spine.004, hand.L and hand.R to their heads and move them along the axis they&#039;re pointing at, to some whatever point that makes sense to you, e.g. furthest reaching vertex on the hand. No need to be precise here, and thus snapping – just move the tail so that it is roughly where you want it to be.&lt;br /&gt;
## In order to keep the toe bones aligned and properly positioned, do the following for each toe bone:&lt;br /&gt;
### Select the foot in object mode,&lt;br /&gt;
### Snap cursor to the furthest and lowest reaching vertex on the foot,&lt;br /&gt;
### Copy the X location of that vertex,&lt;br /&gt;
### Snap the bone to cursor,&lt;br /&gt;
### Paste the X location to the bone&#039;s head,&lt;br /&gt;
### Snap bone&#039;s tail to the head,&lt;br /&gt;
### Move the head along the Y axis by some amount will make it easy to select but not too big.&lt;br /&gt;
# In edit mode, set the following rolls for the Metarig bones as described below (if you don&#039;t, body parts, mainly shoulders, will get badly rotated after constraining them to the rig after its generation):&lt;br /&gt;
## shoulder.L, 90 degrees,&lt;br /&gt;
## shoulder.R, -90 degrees,&lt;br /&gt;
## &#039;&#039;All&#039;&#039; other bones, 0 degrees.&lt;br /&gt;
# Now we have to set up how our Rigify rig layers will be named and set up. Go to the Object Data Properties tab, open up Rigify Layer Names, and set the table according to the screenshot below, marked as Point 32.&lt;br /&gt;
# The metarig is now correctly adjusted. Your scene should look as shown in the screenshot below, marked as Point 33.&lt;br /&gt;
# We highly recommend to save your project here and to continue your work in a new file (i.e. save, then save as a new file and continue your work on the new file), so that you can revert to the version you had until now and adjust the Metarig if needed. You can skip this, work on a single file, adjust the metarig, delete your current rig and generate a new one, but it may or may not be less convenient to rename.&lt;br /&gt;
# Generate the rig. Congratulations, you have generated the rig and can move to constraining the character to it. Your scene should look as shown in the screenshot below, marked as Point 35. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:RigifyLayerNames.png|300px|frameless]] || [[Image:Metarig.png|400px|frameless]] || [[Image:Rig.png|400px|frameless]]&lt;br /&gt;
|-&lt;br /&gt;
! Point 32, Rigify layer names for the rig !! Point 33, fully adjusted Metarig. !! Point 35, generated rig.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Constraining the character to the rig and adding the Axis Correction Empties==&lt;br /&gt;
Now we get to constrain the character to the rig and later edit the rig. Unfortunately, there&#039;s even more work in editing the rig than with the metarig.&lt;br /&gt;
# &amp;lt;li value=&amp;quot;36&amp;quot;&amp;gt;Hide the metarig, it won&#039;t be needed anymore.&amp;lt;/li&amp;gt;&lt;br /&gt;
# On the Pelvis of the T-posed character, add two Copy Rotation object constraints with the settings according to the table below. &amp;quot;x&amp;quot; means there&#039;s nothing set.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Setting !! Copy Rotation !! Copy Rotation.001&lt;br /&gt;
|-&lt;br /&gt;
| Target || rig || x&lt;br /&gt;
|-&lt;br /&gt;
| Order || ZYX Euler || Default&lt;br /&gt;
|-&lt;br /&gt;
| Mix || Replace || After Original&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;37&amp;quot;&amp;gt;Copy the constraints to all of the remaining body parts.&amp;lt;/li&amp;gt;&lt;br /&gt;
# At this point, the character is folded into Oni&#039;s default pose, described [[Importing_character_models#Oni.27s_default_orientation|HERE.]] This is hard to work with, so disable all of the object constraints with the ObjectConstraintEnabler script available [[Blender/Obsolete scripts#Script for enabling.2Fdisabling constraints in selected objects|HERE]]. We will also fix the folded pose in a moment.&lt;br /&gt;
# Add a &#039;&#039;Copy Location&#039;&#039; constraint to the &#039;&#039;Pelvis&#039;&#039; and:&lt;br /&gt;
## Set the &#039;&#039;Target to &#039;&#039;rig&#039;&#039;,&lt;br /&gt;
## Set the &#039;&#039;Bone to ORG-spine&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;li value=&amp;quot;40&amp;quot;&amp;gt;Now we need to fix the folded pose. This is done through a set of Empties with specified rotations, which are added to the rotation of each body part through the &#039;&#039;Copy Rotation.001&#039;&#039; constraint (this is also why the Mix of that constraint was set to &#039;&#039;After Original&#039;&#039;).&amp;lt;/li&amp;gt;&lt;br /&gt;
## Create a new collection in the Outliner called &amp;quot;&#039;&#039;Axis Correction Empties&#039;&#039;&amp;quot;.&lt;br /&gt;
## Add six Arrows Empties, all with their Name showing in the Viewport Display. (Object Properties / Viewport Display / Name)&lt;br /&gt;
## Name the empties and place them in the proposed arbitrary positions using cursor snapping, and set their rotations according to the table below – you can place them however you want, as their location does not influence the rig in any way, however, proper placement makes them easy to edit if needed. It&#039;s also proposed to place the empties one meter either in front or behind the given body part.&lt;br /&gt;
&lt;br /&gt;
[[Image:AxisCorrectionEmptyPlacement.png|200px|right|thumb|Proposed Axis Correction Empties&#039; placement]]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Empty !! Body Part !! In front of or behind? || X rotation || Y rotation || Z rotation&lt;br /&gt;
|-&lt;br /&gt;
| ACFeet || Either foot || Behind || -90 || -52.5 || 90&lt;br /&gt;
|-&lt;br /&gt;
| ACHandL || left_handfist || Behind || 180 || 0 || 90&lt;br /&gt;
|-&lt;br /&gt;
| ACHandR || right_handfist || Behind || 0 || 0 || 90&lt;br /&gt;
|-&lt;br /&gt;
| ACLimbs || neck || Behind || -90 || 0 || 90&lt;br /&gt;
|-&lt;br /&gt;
| ACPelvis || pelvis || Front || 90 || 8.6 || 90&lt;br /&gt;
|-&lt;br /&gt;
| ACSpine || mid || Front || 90 || 0 || 90&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
::#&amp;lt;li value=&amp;quot;4&amp;quot;&amp;gt; In your Viewport, open the Viewport Overlay and enable Relationship Lines. These are the lines that will show you lines from constrained objects to their targets. They will give you a better sense of how body parts are copying rotations from the Empties you are about to make. You can also turn Relationship Lines off at any point if they&#039;re making the scene hard to read.&amp;lt;/li&amp;gt;&lt;br /&gt;
::# Set the &#039;&#039;Bones&#039;&#039; of &#039;&#039;Copy Rotation&#039;&#039; and &#039;&#039;Targets&#039;&#039; of &#039;&#039;Copy Rotation.001&#039;&#039; constraints in character&#039;s body parts in accordance with the table below. The table may be intimidating, but it should be logical enough and easy to copy and paste the targets and bones – all of the body parts get targeted to a corresponding ORG bone in the rig through &#039;&#039;Copy Rotation&#039;&#039; and get their Axis Correction rotation added through &#039;&#039;Copy Rotation.001&#039;&#039; set to appropriate empty.&lt;br /&gt;
&lt;br /&gt;
[[Image:RigCharacterConstrained.png|600px|right|thumb|Expected result by the end of this header]]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Body part !! Copy Rotation / Bone !! Copy Rotation.001 / Target&lt;br /&gt;
|-&lt;br /&gt;
| pelvis || ORG-spine || ACPelvis&lt;br /&gt;
|-&lt;br /&gt;
| mid || ORG-spine.001 || ACSpine&lt;br /&gt;
|-&lt;br /&gt;
| chest || ORG-spine.002 || ACSpine&lt;br /&gt;
|-&lt;br /&gt;
| neck || ORG-spine.003 || ACSpine&lt;br /&gt;
|-&lt;br /&gt;
| head || ORG-spine.004 || ACSpine&lt;br /&gt;
|-&lt;br /&gt;
| right_shoulder || ORG-shoulder.R || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| right_biceps || ORG-upper_arm.R || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| right_wrist || ORG-forearm.R || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| right_handfist || ORG-hand.R || ACHandR&lt;br /&gt;
|-&lt;br /&gt;
| left_shoulder || ORG-shoulder.L || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| left_biceps || ORG-upper_arm.L || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| left_wrist || ORG-forearm.L || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| left_handfist || ORG-hand.L || ACHandL&lt;br /&gt;
|-&lt;br /&gt;
| right_thigh || ORG-thigh.R || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| right_calf || ORG-shin.R || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| right_foot || ORG-foot.R || ACFeet&lt;br /&gt;
|-&lt;br /&gt;
| left_thigh || ORG-thigh.L || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| left_calf || ORG-shin.L || ACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| left_foot || ORG-foot.L || ACFeet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;41&amp;quot;&amp;gt;Enable the object constraints in the character body parts using the ObjectConstraintEnabler script.&amp;lt;/li&amp;gt;&lt;br /&gt;
# At this point, you should be able to pose the character, as shown in the screenshot on the right.&lt;br /&gt;
&lt;br /&gt;
==Removing and editing the rig bones==&lt;br /&gt;
There are still things to do; if you play around posing your character, you will find out the spine behaviour to be somewhat lackluster, and lacking control over the mid and chest bones. This will now be addressed, and later, bone constraints need to be added to rig controller bones. Let&#039;s start off with deleting all the controller bones we don&#039;t need.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;43&amp;quot;&amp;gt;Select the rig, go to Object Data Properties, Viewport Display and enable In Front. The rig will now always render in front of the character, making it easier to select.&amp;lt;/li&amp;gt;&lt;br /&gt;
# In Edit mode, go to Object Data Properties tab / Skeleton, select Layer 29 (the DEF/Deform) and delete all bones in it.&lt;br /&gt;
# Select layer 28, and move the root bone to layer 24 (Change Bone Layer, default shortcut is M)&lt;br /&gt;
# Remove the bones listed below from the rig. Keep in mind it&#039;s possible to enable just one layer at a time for your convenience. For the record, we will not be editing MCH or ORG layers until later, so you can ignore their layers for now. &#039;&#039;&#039;IMPORTANT NOTE: Be sure to not delete tweak_spine.001 accidentally, as it&#039;s necessary for the rig to function properly.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bone !! Layer&lt;br /&gt;
|-&lt;br /&gt;
| tweak_spine || Torso&lt;br /&gt;
|-&lt;br /&gt;
| tweak_spine.002 || Torso&lt;br /&gt;
|-&lt;br /&gt;
| tweak_spine.003 || Torso (Tweak)&lt;br /&gt;
|-&lt;br /&gt;
| spine_fk.001 || Torso (Tweak)&lt;br /&gt;
|-&lt;br /&gt;
| spine_fk.002 || Torso (Tweak)&lt;br /&gt;
|-&lt;br /&gt;
| upper_arm_tweak.L || Arm.L (IK)&lt;br /&gt;
|-&lt;br /&gt;
| forearm_tweak.L || Arm.L (IK)&lt;br /&gt;
|-&lt;br /&gt;
| hand_tweak.L || Arm.L (IK)&lt;br /&gt;
|-&lt;br /&gt;
| upper_arm_tweak.R || Arm.R (IK)&lt;br /&gt;
|-&lt;br /&gt;
| forearm_tweak.R || Arm.R (IK)&lt;br /&gt;
|-&lt;br /&gt;
| hand_tweak.R || Arm.R (IK)&lt;br /&gt;
|-&lt;br /&gt;
| thigh_tweak.L || Leg.L (IK)&lt;br /&gt;
|-&lt;br /&gt;
| shin_tweak.L || Leg.L (IK)&lt;br /&gt;
|-&lt;br /&gt;
| foot_tweak.L || Leg.L (IK)&lt;br /&gt;
|-&lt;br /&gt;
| thigh_tweak.R || Leg.R (IK)&lt;br /&gt;
|-&lt;br /&gt;
| shin_tweak.R || Leg.R (IK)&lt;br /&gt;
|-&lt;br /&gt;
| foot_tweak.R || Leg.R (IK)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;47&amp;quot;&amp;gt;Using 3D Cursor snapping, snap &#039;&#039;torso&#039;&#039; and &#039;&#039;torso_pivot&#039;&#039; bones to the &#039;&#039;mid&#039;&#039; body part.&amp;lt;/li&amp;gt;&lt;br /&gt;
##Since &#039;&#039;torso&#039;&#039; and &#039;&#039;torso_pivot&#039;&#039; are of the same size, etc. and thus are overlapping each other, feel free to move their tails a bit in the appropriate axis. This applies to all overlapping bones in the rig – if they overlap, move the tail in the axis parallel to the bone.&lt;br /&gt;
#Reparent &#039;&#039;shoulder.L&#039;&#039; and &#039;&#039;shoulder.R&#039;&#039; bones from &#039;&#039;ORG-spine.003&#039;&#039; to &#039;&#039;ORG-spine.002&#039;&#039;.&lt;br /&gt;
# Controller bones are now adjusted, and we can move on to ORG and MCH layers. Select the ORG layer (31), reparent the bones and set their &#039;&#039;Connected&#039;&#039; box according to the table below. &#039;&#039;&#039;x&#039;&#039;&#039; means no change is needed.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bone !! Parent !! Connected&lt;br /&gt;
|-&lt;br /&gt;
| ORG-spine || root || x&lt;br /&gt;
|-&lt;br /&gt;
| ORG-spine.001 || ORG-spine || Yes&lt;br /&gt;
|-&lt;br /&gt;
| ORG-spine.002 || ORG-spine.001 || Yes&lt;br /&gt;
|-&lt;br /&gt;
| ORG-shoulder.L || ORG-spine.002 || x&lt;br /&gt;
|-&lt;br /&gt;
| ORG-shoulder.R || ORG-spine.002 || x&lt;br /&gt;
|-&lt;br /&gt;
| ORG-upper_arm.L || x || No&lt;br /&gt;
|-&lt;br /&gt;
| ORG-upper_arm.R || x || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;50&amp;quot;&amp;gt;Select the MCH layer (3) and remove the following bones:&amp;lt;/li&amp;gt;&lt;br /&gt;
#*MCH-thigh_tweak.L&lt;br /&gt;
#*MCH-thigh_tweak.R&lt;br /&gt;
#*MCH-shin_tweak.L&lt;br /&gt;
#*MCH-shin_tweak.R&lt;br /&gt;
#*MCH-foot_tweak.L&lt;br /&gt;
#*MCH-foot_tweak.R&lt;br /&gt;
# Snap &#039;&#039;MCH-torso.parent&#039;&#039; and &#039;&#039;MCH-torso_pivot&#039;&#039; to the &#039;&#039;mid&#039;&#039; body part. (You can also snap them to &#039;&#039;MCH-spine&#039;&#039; or &#039;&#039;MCH-spine.001&#039;&#039; bones as they&#039;re snapped to &#039;&#039;mid&#039;&#039; as well)&lt;br /&gt;
# With X-Axis mirror enabled, select the MCH-forearm_ik.R bone and extrude it perpendicularly to the axis of the arm. You should now have the MCH-forearm_ik.R.001 and MCH-forearm_ik.L.001 bones. These bones are needed for the wrist snapping function which we&#039;ll implement later.&lt;br /&gt;
&lt;br /&gt;
==Editing the bone constraints of ORG and MCH bone layers==&lt;br /&gt;
Now&#039;s the time to edit and add bone constraints.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;53&amp;quot;&amp;gt;Switch to Pose mode and add a &#039;&#039;Copy Rotation&#039;&#039; bone constraint to MCH-forearm_ik.R.001 and MCH-forearm_ik.L.001 bones that you&#039;ve added in previous points, targeting MCH-forearm_ik.R and MCH-forearm_ik.L bones (i.e. for the &#039;&#039;MCH-forearm_ik.R.001&#039;&#039;, &#039;&#039;Target&#039;&#039; is &#039;&#039;rig&#039;&#039;, while &#039;&#039;Bone&#039;&#039; should be set to &#039;&#039;MCH-forearm_ik.R.001&#039;&#039;)&amp;lt;/li&amp;gt;&lt;br /&gt;
# Select the ORG layer.&lt;br /&gt;
# Add bone constraints in accordance to the table below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bone !! Bone Constraint !! Target !! Target/Bone&lt;br /&gt;
|-&lt;br /&gt;
| ORG-spine || Copy Transforms || rig || MCH-WGT-hips&lt;br /&gt;
|-&lt;br /&gt;
| ORG-spine.001 || Copy Rotation || rig || tweak_spine.001&lt;br /&gt;
|-&lt;br /&gt;
| ORG-spine.002 || Copy Transforms || rig || MCH-WGT-chest&lt;br /&gt;
|}&lt;br /&gt;
#&amp;lt;li value=&amp;quot;55&amp;quot;&amp;gt;Delete the &#039;&#039;Stretch to&#039;&#039; bone constraint from &#039;&#039;ORG-spine.003&#039;&#039;.&amp;lt;/li&amp;gt;&lt;br /&gt;
#Set the &#039;&#039;Bone&#039;&#039; in the &#039;&#039;Copy Transforms&#039;&#039; bone constraint in &#039;&#039;ORG-spine.003&#039;&#039; to &#039;&#039;neck&#039;&#039;.&lt;br /&gt;
#Select the MCH layer.&lt;br /&gt;
# Select the MCH-pivot bone.&lt;br /&gt;
## Set the Influence of the Copy Transforms bone constraint to 1.&lt;br /&gt;
## Add a Copy Rotation bone constraint, set it to rig / ORG-spine.002 and set its influence to 0.5.&lt;br /&gt;
# Select the MCH-spine.001 bone, and set the Influence of the Copy Transforms bone constraint to 0.&lt;br /&gt;
# Select the MCH-spine.002 bone.&lt;br /&gt;
## Set the Influence of the Copy Transforms bone constraint to 1.&lt;br /&gt;
## Add a Copy Location bone constraint, and set it to rig / ORG-spine.002.&lt;br /&gt;
# Select the MCH-STR-neck bone.&lt;br /&gt;
## Set the Rotation of the Stretch To bone constraint from Swing to XZ.&lt;br /&gt;
## Add a Damped Track bone constraint.&lt;br /&gt;
### Move it to the top of the bone constraint list.&lt;br /&gt;
### Set it to rig / head.&lt;br /&gt;
### Set the Track Axis to Y if it isn&#039;t already.&lt;br /&gt;
# For both MCH-upper_arm_ik_stretch.L and MCH-upper_arm_ik_stretch.R bones, do the following:&lt;br /&gt;
## Set the Rotation of the Stretch To bone constraint from Swing to XZ.&lt;br /&gt;
## Add a Damped Track bone constraint.&lt;br /&gt;
### Move it to the top of the bone constraint list.&lt;br /&gt;
### Set it to rig / hand_ik (.L or .R appropriately if it&#039;s a right or left hand).&lt;br /&gt;
### Set the Track Axis to Y if it isn&#039;t already.&lt;br /&gt;
# For both MCH-thigh_ik_stretch.L and MCH-thigh_ik_stretch.R bones, do the following:&lt;br /&gt;
## Set the Rotation of the Stretch To bone constraint from Swing to XZ.&lt;br /&gt;
## Add a Damped Track bone constraint.&lt;br /&gt;
### Move it to the top of the bone constraint list.&lt;br /&gt;
### Set it to rig / MCH-foot_roll (.L or .R appropriately if it&#039;s a right or left leg).&lt;br /&gt;
### Set the Track Axis to Y if it isn&#039;t already.&lt;br /&gt;
# Disable the &#039;&#039;Stretch&#039;&#039; checkbox in both of the IK bone constraints in the following bones:&lt;br /&gt;
#*MCH-forearm_ik.L&lt;br /&gt;
#*MCH-forearm_ik.R&lt;br /&gt;
#*MCH-shin_ik.L&lt;br /&gt;
#*MCH-shin_ik.R&lt;br /&gt;
&lt;br /&gt;
==Changing custom shapes of rig controller bones==&lt;br /&gt;
We&#039;re getting close to the end. There&#039;s still a bit of work to do, but all that remains relates to the rig controller bones in Pose mode.&lt;br /&gt;
This short header will focus on changing the shapes of the controller bones – these changes are purely visual and have no functional effect on the rig, however, they do make it more more ergonomic and easier to read.&lt;br /&gt;
[[Image:Rig After Editing Custom Shapes.png|200px|right|thumb|Rig&#039;s expected state at point 69.]]&lt;br /&gt;
#&amp;lt;li value=&amp;quot;65&amp;gt;Switch over to all other bone layers except the MCH and ORG layers – all that was related to them is now done.&amp;lt;/li&amp;gt;&lt;br /&gt;
#Select the tweak_spine.001 bone:&lt;br /&gt;
## Set the Custom Object to WGT-rig_thigh_parent.L – this will make it much more easier to read.&lt;br /&gt;
## Set the Scale to 1.5.&lt;br /&gt;
## Disable the &#039;&#039;Scale to Bone Length&#039;&#039; checkbox.&lt;br /&gt;
# Select the spine_fk bone:&lt;br /&gt;
## Disable the &#039;&#039;Scale to Bone Length&#039;&#039; checkbox.&lt;br /&gt;
## Set the Scale to 0.&lt;br /&gt;
#For both hand_ik.R and hand_ik.L bones, disable the &#039;&#039;Scale to Bone Length&#039;&#039; checkbox.&lt;br /&gt;
#For both foot_ik.R and foot_ik.L bones, do the following:&lt;br /&gt;
## Disable the &#039;&#039;Scale to Bone Length&#039;&#039; checkbox.&lt;br /&gt;
## Set the Scale to 2.&lt;br /&gt;
#For both toe.R and toe.L, set the scale to 0. At this point, the rig should look as shown in the screenshot on the right.&lt;br /&gt;
&lt;br /&gt;
==Editing the rig_ui.py script==&lt;br /&gt;
Now we&#039;ll need to edit the Rig Layers panel a bit and add the wrist snapping functionality by putting three code snippets into rig_ui.py and running it.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;71&amp;quot;&amp;gt; Go to the Scripting tab and select the rig_ui.py script.&lt;br /&gt;
#Right at the start of the script you will see the &amp;lt;code&amp;gt;rig_id&amp;lt;/code&amp;gt; field. Copy its value and save it in some text editor, as you&#039;ll be pasting it in the next few steps. &lt;br /&gt;
#Find the following line (use another text editor if you can&#039;t find it in Blender&#039;s Text Editor):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;        props.bones = &#039;[&amp;quot;upper_arm_ik.L&amp;quot;, &amp;quot;upper_arm_ik_target.L&amp;quot;, &amp;quot;hand_ik.L&amp;quot;]&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the following code snippet below it – this will add a button and functionality for the wrist snapping on the &#039;&#039;&#039;left&#039;&#039;&#039; arm – using the MCH-forearm_ik.L.001 bone that was created in points 52 and 53.&lt;br /&gt;
Also, replace &amp;lt;code&amp;gt;&#039;&#039;&#039;YOURRIGID&#039;&#039;&#039;&amp;lt;/code&amp;gt; with your &amp;lt;code&amp;gt;rig_id&amp;lt;/code&amp;gt; from point 71.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            group2 = group1.row(align=True)&lt;br /&gt;
            props = group2.operator(&#039;pose.rigify_generic_snap_YOURRIGID&#039;, text=&#039;IK wrist (hand.L)&#039;, icon=&#039;SNAP_ON&#039;)&lt;br /&gt;
            props.output_bones = &#039;[&amp;quot;hand_ik.L&amp;quot;]&#039;&lt;br /&gt;
            props.input_bones = &#039;[&amp;quot;MCH-forearm_ik.L.001&amp;quot;]&#039;&lt;br /&gt;
            props.ctrl_bones = &#039;[&amp;quot;MCH-forearm_ik.L.001&amp;quot;]&#039;&lt;br /&gt;
            props.tooltip = &#039;IK hand to wrist&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;74&amp;quot;&amp;gt; Find the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;        props.bones = &#039;[&amp;quot;upper_arm_ik.R&amp;quot;, &amp;quot;hand_ik.R&amp;quot;, &amp;quot;upper_arm_ik_target.R&amp;quot;]&#039; &amp;lt;/pre&amp;gt;&lt;br /&gt;
Add the following code snippet below it – this will add a button and functionality for the wrist snapping on the &#039;&#039;&#039;right&#039;&#039;&#039; arm. Also, replace &amp;lt;code&amp;gt;&#039;&#039;&#039;YOURRIGID&#039;&#039;&#039;&amp;lt;/code&amp;gt; with your &amp;lt;code&amp;gt;rig_id&amp;lt;/code&amp;gt; from point 71.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            group2 = group1.row(align=True)&lt;br /&gt;
            props = group2.operator(&#039;pose.rigify_generic_snap_YOURRIGID&#039;, text=&#039;IK wrist (hand.R)&#039;, icon=&#039;SNAP_ON&#039;)&lt;br /&gt;
            props.output_bones = &#039;[&amp;quot;hand_ik.R&amp;quot;]&#039;&lt;br /&gt;
            props.input_bones = &#039;[&amp;quot;MCH-forearm_ik.R.001&amp;quot;]&#039;&lt;br /&gt;
            props.ctrl_bones = &#039;[&amp;quot;MCH-forearm_ik.R.001&amp;quot;]&#039;&lt;br /&gt;
            props.tooltip = &#039;IK hand to wrist&#039;&lt;br /&gt;
            if is_selected({&#039;upper_arm_ik.R&#039;, &#039;hand_ik.R&#039;, &#039;upper_arm_parent.R&#039;, &#039;upper_arm_ik_target.R&#039;}):&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;75&amp;quot;&amp;gt; Find the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;        row.prop(context.active_object.data, &#039;layers&#039;, index=8, toggle=True, text=&#039;Torso&#039;) &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change it to the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        row.prop(context.active_object.data, &#039;layers&#039;, index=9, toggle=True, text=&#039;Pose Matching&#039;)&lt;br /&gt;
&lt;br /&gt;
        row = col.row()&lt;br /&gt;
        row.separator()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;76&amp;quot;&amp;gt; Find the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;        row.prop(context.active_object.data, &#039;layers&#039;, index=9, toggle=True, text=&#039;Torso (Tweak)&#039;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change it to the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;        row.prop(context.active_object.data, &#039;layers&#039;, index=8, toggle=True, text=&#039;Torso&#039;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IKWrist.png|200px|right|thumb|Rig&#039;s expected state at point 80.]]&lt;br /&gt;
[[Image:ModifiedRigLayers.png|200px|right|thumb|Rig&#039;s expected state at point 80, with hand_ik.R selected, showing the newly added IK wrist snapping functionality.]]&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;77&amp;quot;&amp;gt;Find the following code:&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        row.prop(context.active_object.data, &#039;layers&#039;, index=21, toggle=True, text=&#039;Leg.R (FK)&#039;)&lt;br /&gt;
&lt;br /&gt;
        row = col.row()&lt;br /&gt;
        row.separator()&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Remove the &amp;lt;code&amp;gt;row = col.row()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;row.seperator()&amp;lt;/code&amp;gt; lines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;78&amp;quot;&amp;gt; Find the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;        row.prop(context.active_object.data, &#039;layers&#039;, index=28, toggle=True, text=&#039;Root&#039;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Change the value of &amp;lt;code&amp;gt;index&amp;lt;/code&amp;gt; to 24. Index is the layer number, and Root should be layer 24, not 28. &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;79&amp;quot;&amp;gt;We recommend backing up your file at this point.&lt;br /&gt;
#Run the script, and move to the Layout tab. Your rig should look as shown in the screenshots on the right.&lt;br /&gt;
&lt;br /&gt;
==Adding the Rigify Axis Correction Empties==&lt;br /&gt;
Before we add the Pose Matching functionality, we need to create Axis Correction Empties that will account for Rigify&#039;s axis orientation.&lt;br /&gt;
#&amp;lt;li value=&amp;quot;81&amp;quot;&amp;gt;Switch to Object Mode.&lt;br /&gt;
#Duplicate the &#039;&#039;Axis Correction Empties&#039;&#039; collection and rename it to &#039;&#039;Rigify Axis Correction Empties&#039;&#039;&lt;br /&gt;
## Rename the ACPelvis.001 to RACHead and move it in the global Z axis so that it is aligned with the head along the Y axis (or 3D cursor snap it)&lt;br /&gt;
## Rename the remaining empties in the newly-made collection by removing the &#039;&#039;.001&#039;&#039; suffix and changing the &#039;&#039;AC&#039;&#039; prefix to &#039;&#039;RAC&#039;&#039;.&lt;br /&gt;
## Set the rotations of the empties according to the table below:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Empty !!  X rotation || Y rotation || Z rotation&lt;br /&gt;
|-&lt;br /&gt;
| RACFeet || 38.1 || 90 || 0&lt;br /&gt;
|-&lt;br /&gt;
| RACHandL ||  -180 || 0 || 90&lt;br /&gt;
|-&lt;br /&gt;
| RACHandR || 0 || 0 || -90&lt;br /&gt;
|-&lt;br /&gt;
| RACHead || -90 || -90 || 0&lt;br /&gt;
|-&lt;br /&gt;
| RACLimbs || 90 || 90 || 0&lt;br /&gt;
|-&lt;br /&gt;
| RACSpine || 180 || -90 || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Adding bone constraints to rig controller bones and drivers==&lt;br /&gt;
This is the final section of this tutorial. Now we just have to add the Pose Matching functionality, so we can constrain the rig to imported animations in Pose 1 and Pose 2 collections. We do that by adding two new bones to the rig, bone constraints to the rig controller bones and then drivers which will control the influence of the bone constraints through the Z location of the newly added bones. We will also &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;83&amp;quot;&amp;gt;Select the rig, go to Edit mode and select the Pose Matching layer.&lt;br /&gt;
#Add a new bone named &#039;&#039;Pose1&#039;&#039;. &lt;br /&gt;
#Set its transforms as listed below (or make it as big as you want, this is purely a visual/ergonomic matter):&lt;br /&gt;
#*Head X,Y,Z: 1,0,0&lt;br /&gt;
#*Tail X,Y,Z: 1,0,1&lt;br /&gt;
#Duplicate the bone and rename it to &#039;&#039;Pose2&#039;&#039;.&lt;br /&gt;
#Set its transforms as listed below (it will be simply mirrored along the X axis)&lt;br /&gt;
#*Head X,Y,Z: -1,0,0&lt;br /&gt;
#*Tail X,Y,Z: -1,0,1&lt;br /&gt;
#Switch to Pose mode.&lt;br /&gt;
#For both Pose1 and Pose2 bones, select them, go to Bone Properties tab, Viewport Display, Custom Shape and set the Custom Object to WGT-rig_shoulder.L.&lt;br /&gt;
##You can also set the Scale to 10 and disable the &#039;&#039;Scale to Bone Length&#039;&#039; checkbox for them if you want.&lt;br /&gt;
#For now, move both Pose 1 and Pose 2 in Global Z axis so that they are below the &amp;quot;floor&amp;quot; (XY plane).&lt;br /&gt;
#Select the Torso layer and all of the FK layers in the Rig Layers panel.&lt;br /&gt;
#Select the &#039;&#039;hips&#039;&#039; bone.&lt;br /&gt;
##Add &#039;&#039;three&#039;&#039; Copy Rotation bone constraints, and move the one without the suffix to the bottom of the list (so the order of the bone constraints going from the top to bottom is &#039;&#039;Copy Rotation.001&#039;&#039;, &#039;&#039;Copy Rotation.002&#039;&#039;, &#039;&#039;Copy Rotation&#039;&#039;). &#039;&#039;Copy Rotation.001&#039;&#039; and &#039;&#039;Copy Rotation.002&#039;&#039; will be used for pose matching, &#039;&#039;Copy Rotation&#039;&#039; will be used for axis correction.&lt;br /&gt;
##In the &#039;&#039;Copy Rotation&#039;&#039; constraint, set the &#039;&#039;Mix&#039;&#039; to &#039;&#039;After Original&#039;&#039;. &lt;br /&gt;
#Now we&#039;ll have to add the drivers controlling the influence of each Copy Rotation constraint. As shown in Pierrick Picaut&#039;s tutorial, you can do that by right clicking on the Influence value and pressing &#039;&#039;Add Driver&#039;&#039; (same applies to any other property in any other constraint). Once you add a driver, you can edit it either through &#039;&#039;Edit Driver&#039;&#039; or through the Driver Editor – both are selectable within the same menu.&lt;br /&gt;
##Add a driver to the &#039;&#039;Influence&#039;&#039; of each &#039;&#039;Copy Rotation&#039;&#039; constraint in accordance with the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Copy Rotation.001 !! Copy Rotation.002 !! Copy Rotation&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
*Driver Type: &#039;&#039;Scripted Expression&#039;&#039; (default setting)&lt;br /&gt;
*Expression: &#039;&#039;var&#039;&#039;&lt;br /&gt;
*Amount of input variables: one (default setting)&lt;br /&gt;
*Input Variable type: &#039;&#039;Transform Channel&#039;&#039; (default setting)&lt;br /&gt;
*Input Variable name: &#039;&#039;var&#039;&#039; (default setting)&lt;br /&gt;
*Object: &#039;&#039;rig&#039;&#039;&lt;br /&gt;
*Bone: &#039;&#039;Pose1&#039;&#039;&lt;br /&gt;
*Type: &#039;&#039;Z Location&#039;&#039;&lt;br /&gt;
*Space: &#039;&#039;World Space&#039;&#039; (default setting)&lt;br /&gt;
||&lt;br /&gt;
Same settings as in Copy Rotation.001, with the exception of:&lt;br /&gt;
*Bone: &#039;&#039;Pose2&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*Driver Type: &#039;&#039;Scripted Expression&#039;&#039; (default setting)&lt;br /&gt;
*Expression: &#039;&#039;max(var1,var2)&#039;&#039; (press Enter to get rid of the invalid expression error, if you have it)&lt;br /&gt;
*Amount of input variables: two (&#039;&#039;&#039;press &#039;&#039;Add Input Variable&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
First input variable:&lt;br /&gt;
*Input Variable type: &#039;&#039;Transform Channel&#039;&#039; (default setting)&lt;br /&gt;
*Input Variable name: &#039;&#039;var1&#039;&#039;&lt;br /&gt;
*Object: &#039;&#039;rig&#039;&#039;&lt;br /&gt;
*Bone: &#039;&#039;Pose1&#039;&#039;&lt;br /&gt;
*Type: &#039;&#039;Z Location&#039;&#039;&lt;br /&gt;
*Space: &#039;&#039;World Space&#039;&#039; (default setting)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Second input variable:&lt;br /&gt;
*Input Variable type: &#039;&#039;Transform Channel&#039;&#039; (&#039;&#039;&#039;be sure to change it to this&#039;&#039;&#039;, added variables have &#039;&#039;Single Property&#039;&#039; set as default)&lt;br /&gt;
*Input Variable name: &#039;&#039;var2&#039;&#039;&lt;br /&gt;
*Object: &#039;&#039;rig&#039;&#039;&lt;br /&gt;
*Bone: &#039;&#039;Pose2&#039;&#039;&lt;br /&gt;
*Type: &#039;&#039;Z Location&#039;&#039;&lt;br /&gt;
*Space: &#039;&#039;World Space&#039;&#039; (default setting)&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;94&amp;quot;&amp;gt;You can check if the drivers are working by moving Pose1 and Pose2 bones along global Z axis and checking if the Influence of Copy Rotation bone constraints in &#039;&#039;hips&#039;&#039; or Input Variable values in their drivers change.&lt;br /&gt;
#Copy the bone constraints from the &#039;&#039;hips&#039;&#039; bone to the following bones:&lt;br /&gt;
#*tweak_spine.001&lt;br /&gt;
#*chest&lt;br /&gt;
#*shoulder.R&lt;br /&gt;
#*shoulder.L&lt;br /&gt;
#*neck&lt;br /&gt;
#*head&lt;br /&gt;
#*upper_arm_fk.R&lt;br /&gt;
#*upper_arm_fk.L&lt;br /&gt;
#*forearm_fk.R&lt;br /&gt;
#*forearm_fk.L&lt;br /&gt;
#*hand_fk.R&lt;br /&gt;
#*hand_fk.L&lt;br /&gt;
#*thigh_fk.R&lt;br /&gt;
#*thigh_fk.L&lt;br /&gt;
#*shin_fk.R&lt;br /&gt;
#*shin_fk.L&lt;br /&gt;
#*foot_fk.L&lt;br /&gt;
#*foot_fk.R&lt;br /&gt;
#Unfortunately, because Blender at this moment does not copy drivers when copying bone constraints, the bone constraints you&#039;ve just copied are lacking the drivers. Because of this, you have to copy the drivers manually – simply right click on the &#039;&#039;Influence&#039;&#039; value of &#039;&#039;Copy Rotation&#039;&#039; constraint, press &#039;&#039;Copy Driver&#039;&#039;, and go through all bones in the upper list and &#039;&#039;Paste Driver&#039;&#039; onto the Influence of the &#039;&#039;Copy Rotation&#039;&#039; in each bone. &#039;&#039;&#039;Do this for all three &#039;&#039;Copy Rotation&#039;&#039; bone constraints.&#039;&#039;&#039;&lt;br /&gt;
#Add two &#039;&#039;Copy Location&#039;&#039; constraints to &#039;&#039;torso&#039;&#039; and &#039;&#039;torso_pivot&#039;&#039; bones, and make sure they&#039;re named &#039;&#039;Copy Location.001&#039;&#039; and &#039;&#039;Copy Location.002&#039;&#039;.&lt;br /&gt;
#Copy Influence Drivers from any of the bones in point 96 and paste them into the &#039;&#039;Influence&#039;&#039; of &#039;&#039;Copy Location&#039;&#039; constraints in &#039;&#039;torso&#039;&#039; and &#039;&#039;torso_pivot&#039;&#039;, in accordance with the numbers of bone constraints (e.g. copy the driver from &#039;&#039;hips&#039;&#039;&#039; &#039;&#039;Copy Rotation.001&#039;&#039; Influence and paste it into Influence of &#039;&#039;Copy Location.001&#039;&#039; in &#039;&#039;torso&#039;&#039; and &#039;&#039;torso_pivot&#039;&#039;).&lt;br /&gt;
#Set the &#039;&#039;Copy Rotation&#039;&#039; constraints&#039; Axis correction &#039;&#039;Target&#039;&#039; in accordance with the table below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bone !! Copy Rotation target&lt;br /&gt;
|-&lt;br /&gt;
| hips || RACSpine&lt;br /&gt;
|-&lt;br /&gt;
| tweak_spine.001 || RACHead&lt;br /&gt;
|-&lt;br /&gt;
| chest || RACSpine&lt;br /&gt;
|-&lt;br /&gt;
| neck || RACHead&lt;br /&gt;
|-&lt;br /&gt;
| head || RACHead&lt;br /&gt;
|-&lt;br /&gt;
| shoulder.R  || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| shoulder.L || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| upper_arm_fk.R || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| upper_arm_fk.L || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| forearm_fk.R || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| forearm_fk.L || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| hand_fk.R  || RACHandL&lt;br /&gt;
|-&lt;br /&gt;
| hand_fk.L || RACHandR&lt;br /&gt;
|-&lt;br /&gt;
| thigh_fk.R || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| thigh_fk.L || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| shin_fk.R || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| shin_fk.L || RACLimbs&lt;br /&gt;
|-&lt;br /&gt;
| foot_fk.R || RACFeet&lt;br /&gt;
|-&lt;br /&gt;
| foot_fk.L || RACFeet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Image:RigFinished.png|200px|right|thumb|Finished rig showing the pose matching functionality.]]&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;li value=&amp;quot;100&amp;quot;&amp;gt; Select any FK (green) bone and set the IK-FK slider to 1. Do this for all four limbs. This has to be done because pose matching works only through FK.&lt;br /&gt;
# Using the [[Blender/Obsolete scripts#Rig bone constraint target setting script|RigBoneConstraintTargetSetter script]], set the targets for the &#039;&#039;Copy Rotation.001&#039;&#039; and &#039;&#039;Copy Rotation.002&#039;&#039; bone constraints. You can do that by having the rig in Pose mode, going to the Scripting tab, copying and pasting the script, and running it with &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt; value set to 1, and then set to 2.&lt;br /&gt;
# If you didn&#039;t get any errors, move one of the Pose bones in the global Z axis above the XY plane – the T-posed character should now snap to one of the animations in the &#039;&#039;Pose&#039;&#039; collections, as shown in the screenshot on the right.&lt;br /&gt;
# Congratulations! The rig is now ready to be used.&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Introduction_to_modding&amp;diff=43857</id>
		<title>Introduction to modding</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Introduction_to_modding&amp;diff=43857"/>
		<updated>2025-01-22T19:35:32Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Modding Resources -&amp;gt; Tutorial Lair, Tutorial Character Classes}}&lt;br /&gt;
This page provides an introduction to modding that does not assume that you have prior modding experience or knowledge of the Oni engine. Links to more technical parts of the wiki are interspersed below or can be accessed directly from the wiki&#039;s Main Page.&lt;br /&gt;
{{TOClimit}}&lt;br /&gt;
&lt;br /&gt;
==What is modding?==&lt;br /&gt;
[[Image:No easy button.png|150px|right]]&lt;br /&gt;
Modifying, or &amp;quot;modding&amp;quot;, a game is generally easier than creating one, because you might only be changing some of the game&#039;s existing elements, or creating a limited amount of new data. Nevertheless, modding can be an intimidating field to get into. Our community does not have the polished modding tools of the big engines like Unreal (but we&#039;re getting better). You should have a [[wikt:DIY|DIY]] personality and a high tolerance for technical details. We do not yet have any modding solutions with a big red button that says &amp;quot;easy&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Modding your first game is always the hardest, but after that you can more easily pick up new ones. If you take things one step at a time, you can learn a lot from Oni about how to make games in general; in fact, many game developers started out as modders. Additionally, there are lots of different ways for someone to mod; whether your interest is in coding, art, sound, 3D modeling, or general game design, there&#039;s something for you to do, and collaborating with others to divide the work according to your abilities can lead to a memorable, rewarding creative experience.&lt;br /&gt;
&lt;br /&gt;
* Go to the {{OMD}} to see what kinds of mods are available, or;&lt;br /&gt;
* Install the [[Anniversary Edition]] to try out the mods, or;&lt;br /&gt;
* Continue reading to get an overview of the game engine.&lt;br /&gt;
&lt;br /&gt;
==What engine does Oni run on?==&lt;br /&gt;
Oni runs on a custom engine that could be built for Windows, the Macintosh and the PlayStation 2 (console games are not easily modded, so we don&#039;t work with the PS2 version of Oni). The engine consists of various subsystems, some of which have colorful animé-related names like [[wp:Akira|Akira]] (environment), [[wp:Motoko Kusanagi|Motoko]] (graphics) and [[wp:My Neighbor Totoro|Totoro]] (animation).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the game was rushed to completion during a change of ownership, and it was not possible for the developers to release any tools or information to aid the fans in modding. Thus, fans had to explore the wild jungle of the raw game data and create modding tools through reverse-engineering. It took over seven years to unlock most of the game&#039;s secrets, but we can now mod almost all types of data effectively, allowing us to create entirely new levels and characters.&lt;br /&gt;
&lt;br /&gt;
Altogether, we have identified over 100 types of resources (often called &amp;quot;file types&amp;quot; on this wiki, and &amp;quot;tags&amp;quot; in many other game modding communities) in the game data, however we only directly edit about half of these. It may sound intimidating at first, but depending on the kind of modding you want to do, you might be able to start working with only a little knowledge of the engine.&lt;br /&gt;
&lt;br /&gt;
* Go to [[Oni]] for the full story on Oni&#039;s development, or;&lt;br /&gt;
* Go to [[History of Oni modding]] to read about the community&#039;s accomplishments up until now, or;&lt;br /&gt;
* Continue reading to learn about the game data files.&lt;br /&gt;
&lt;br /&gt;
==How is the game data structured?==&lt;br /&gt;
A game can be compared to a theater play: in both cases, you have &amp;lt;u&amp;gt;stages&amp;lt;/u&amp;gt;, &amp;lt;u&amp;gt;scripts&amp;lt;/u&amp;gt;, &amp;lt;u&amp;gt;actors&amp;lt;/u&amp;gt;, and &amp;lt;u&amp;gt;music&amp;lt;/u&amp;gt;. A level is built so that when the player performs certain actions or reaches certain locations on the &#039;&#039;&#039;stage&#039;&#039;&#039;, further events are set in motion according to the &#039;&#039;&#039;script&#039;&#039;&#039;. The player interacts with [[wp:Artificial intelligence in video games|AI]] &#039;&#039;&#039;actors&#039;&#039;&#039; along the way. &#039;&#039;&#039;Music&#039;&#039;&#039; will often play dynamically behind all this, changing along with the flow of events.&lt;br /&gt;
&lt;br /&gt;
In Oni&#039;s case, the stages, actors and music (and other sounds) are all packed together into files inside GameDataFolder/ that end in &amp;quot;.dat&amp;quot;, &amp;quot;.raw&amp;quot;, and, on Macs, &amp;quot;.sep&amp;quot;. The level0_Final files provide resources for all levels, and when you load a Chapter, an additional set of data files provide the level-specific resources for that Chapter (e.g. level12_Final for Chapter 10). The scripts are stored in separate plain-text files ending in &amp;quot;.bsl&amp;quot; inside GameDataFolder/IGMD/. The player&#039;s progress is stored in persist.dat next to the Oni application.&lt;br /&gt;
&lt;br /&gt;
* Go to [[Oni (folder)]] for information on each file, or;&lt;br /&gt;
* Go to [[Game data terminology]] to learn the precise terms for Oni&#039;s data, or;&lt;br /&gt;
* Continue reading to learn the general process of modding.&lt;br /&gt;
&lt;br /&gt;
==What is the workflow for modding?==&lt;br /&gt;
The general order of events in creating a mod is (1) unpacking the resources you wish to edit, (2) editing them, and (3) re-packing them as Oni level data. You can rely on the Anniversary Edition Installer to re-pack your data; you simply create the mod package in the format that the AEI requires. If you are only creating a script mod, then you don&#039;t need to unpack any data, but you&#039;ll still need to know how to place your script(s) in a mod package.&lt;br /&gt;
&lt;br /&gt;
===Data unpacking===&lt;br /&gt;
The game data cannot be edited easily until our tools convert it into something more modder-friendly. You will usually start by using OniSplit to break level data files (those .dat/.raw(/.sep) files) into their component resources, which are saved as .oni files. Then you will need to convert those resources into something editable. The editable format you arrive at will depend on the kind of data you&#039;re editing. It might be plain text, XML, PNG, Collada, WAV, etc. The editors which you&#039;ll use on this data will be third-party programs suited for each file format.&lt;br /&gt;
&lt;br /&gt;
===Third-party tools===&lt;br /&gt;
If you are scripting, then you might need nothing more than a text editor. For editing textures, you might only need a free bitmap editor. For creating levels or characters, you&#039;ll need a full 3D modeling package. Since Oni doesn&#039;t have modern 3D graphics, you won&#039;t need to know as much about modeling/texturing as you would with a modern game, and there are free modelers available. Our recommendations for tools will be found under the subsections of &amp;quot;Modding resources&amp;quot; below.&lt;br /&gt;
&lt;br /&gt;
===Community tools===&lt;br /&gt;
Besides OniSplit, two of the key fan-made tools are Vago and XmlTools. Vago is a GUI for OniSplit which is much more user-friendly than using OniSplit on the command line. [[XmlTools]] is a technical tool that few modders need to use, but it allows the creation of patches (partial changes to a single resource which can stack on top of each other). Both tools can be installed from within the AE Installer. Once installed, they are found in AE/Tools/ alongside OniSplit.&lt;br /&gt;
&lt;br /&gt;
===Mod creation===&lt;br /&gt;
To see how mods normally look and how they&#039;re distributed and installed, you should download the [[Anniversary Edition]] and install some mods. You can then look at the packages that have been downloaded to AE/AEInstaller/packages/.&lt;br /&gt;
&lt;br /&gt;
* Go to [[OniSplit]]&#039;s page to learn how to unpack and reassemble the game data, or;&lt;br /&gt;
* Go to [[Vago]]&#039;s page to learn how to use this OniSplit GUI, or;&lt;br /&gt;
* Go to [[Making a mod package]] to learn how to assemble a mod, or;&lt;br /&gt;
* Continue reading to learn about the types of modding you can perform.&lt;br /&gt;
&lt;br /&gt;
==Which resources should I be modding?==&lt;br /&gt;
Oni assembles its game world from the scripts in the IGMD folder, the game data in the .dat/.raw(/.sep) files in GameDataFolder, and [[persist.dat]]. It&#039;s easy to read the BSL scripts since they&#039;re plain-text, but how do you find the resource in the game data that you want to edit? Look under &amp;quot;Modding resources&amp;quot; below for a link to the XML database, which explains the function and location of each resource type.&lt;br /&gt;
&lt;br /&gt;
===Editing scripts===&lt;br /&gt;
The easiest kind of modding is scripting. Scripts are written in a unique language called BSL and stored as plain-text files with the suffix .bsl in sub-folders inside GameDataFolder/IGMD/. Scripts take a lifeless level and spawn characters in it, give it a logical flow of events, drive the cutscenes, make the AIs perform certain roles, and alter the level&#039;s appearance.&lt;br /&gt;
&lt;br /&gt;
Scripting is the easiest way to mod because you can modify BSL files using a text editor. It&#039;s quick and easy to see the results of your work (just reload the level), and you have lots of accessible examples to learn from. That being said, scripts sometimes reference game resources in technical ways, so you will have to learn how certain data types work in order to script effectively.&lt;br /&gt;
&lt;br /&gt;
* Go to the [[BSL]] namespace to start learning about scripting, or;&lt;br /&gt;
* Continue reading to learn what&#039;s involved with editing binary resources.&lt;br /&gt;
&lt;br /&gt;
===Modding resources===&lt;br /&gt;
Broadly speaking, Oni&#039;s resources can be broken down as: &#039;&#039;&#039;environments&#039;&#039;&#039; (architecture, triggers, furniture), &#039;&#039;&#039;characters&#039;&#039;&#039; (class data, instance lists, 3D models), &#039;&#039;&#039;weapons&#039;&#039;&#039; (ditto), &#039;&#039;&#039;text&#039;&#039;&#039; (diary pages, objectives, subtitles), and &#039;&#039;&#039;sound&#039;&#039;&#039; (music, voice-overs, and sound effects). However, new levels do not require all this data to be made from scratch. You might decide to re-use a level or some of its resources, or make a new level populated with existing characters, etc.&lt;br /&gt;
&lt;br /&gt;
* Go to the [[XML]] namespace to get a simple introduction to the types of game data and learn the (relatively) user-friendly XML modding technique, or;&lt;br /&gt;
* Go to the [[OBD]] namespace to learn more technical details about the game data, or;&lt;br /&gt;
* Continue reading to start down the path to modding specific kinds of resources.&lt;br /&gt;
&lt;br /&gt;
====Environments====&lt;br /&gt;
Levels are usually built in [[SketchUp tutorials and tips|SketchUp]]. The open-source tool [[Blender]] can be used for levels, objects, characters and animations. Formerly we preferred to do that work in [[Mod Tool]], but the community&#039;s support for Blender has continued to improve and it is now our modeler of choice.&lt;br /&gt;
&lt;br /&gt;
* Tutorial: [http://oni.bungie.org/forum/viewtopic.php?id=2087 Creating the Lair]&lt;br /&gt;
* Tutorial: [[Authoring custom camera animations]]&lt;br /&gt;
&lt;br /&gt;
====Textures====&lt;br /&gt;
Modders have their own preferred bitmap editors for changing/creating textures. On one end of the scale are expensive programs such as Photoshop, and on the other end are free editors like [https://www.gimp.org/ Gimp] and [https://www.getpaint.net/ Paint.NET].&lt;br /&gt;
&lt;br /&gt;
Textures always have dimensions of &amp;quot;power of 2&amp;quot;: typically 32, 64, 128 or 256 pixels on a side. Mac Oni supports a maximum of 1024x1024 textures. Windows Oni supports textures up to 512x512.&lt;br /&gt;
&lt;br /&gt;
These textures can be static, animated, transparent or have a reflection map (usually used for armor). Splashscreens (chapter start screens), win-level and lose-level screens are actually composite images made up of smaller textures due to Oni&#039;s limitation in texture size.&lt;br /&gt;
&lt;br /&gt;
* Tutorial: [[Modifying textures]]&lt;br /&gt;
&lt;br /&gt;
====Characters====&lt;br /&gt;
[[Image:Female stun.jpg|right|300px]]&lt;br /&gt;
Characters in Oni are built with a 19-part skeleton. This skeleton is the same for all humanoid characters and simply tells Oni how the individual parts with their own geometry and textures are assembled. You cannot really compare this with the modern game industry&#039;s use of the term &amp;quot;skeleton&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
A character&#039;s attributes are defined by their character class file which links also to the animation list that defines their moveset. The high modularity of character data allows Oni to share many resources between characters (especially animation collections and particles).&lt;br /&gt;
&lt;br /&gt;
* Tutorial: [http://oni.bungie.org/forum/viewtopic.php?id=2423 Adding character classes]&lt;br /&gt;
* Tutorial: [[Importing character models]]&lt;br /&gt;
* Tutorial: [[OBD talk:TRAM|Tweaking an individual animation]]&lt;br /&gt;
* Tutorial: [[Adding spawnable characters|Adding spawnable characters to a level]]&lt;br /&gt;
&lt;br /&gt;
====Weapons====&lt;br /&gt;
* Tutorial: [[Importing weapon models]]&lt;br /&gt;
&lt;br /&gt;
====Text====&lt;br /&gt;
The text-based resource types are fairly easy to edit as long as you don&#039;t get confused by the IDs which they use to link to each other. The main textual resources are the pages you can view in the [[Data Comlink]] and the consoles you read in-game. The textual resource types are listed here: [[OBD:File types/Interface#List]].&lt;br /&gt;
&lt;br /&gt;
====Sound and music====&lt;br /&gt;
Instructions on importing sounds, and links to conversion tools, can be found [[XML:SNDD|HERE]].&lt;br /&gt;
&lt;br /&gt;
==Need some inspiration?==&lt;br /&gt;
To get ideas, play some existing mods (which you can install with the [[AE]]), or look at the pages below.&lt;br /&gt;
* [[Modding brainstorms]]&lt;br /&gt;
* [[Review criticisms]]&lt;br /&gt;
* [[Animation ideas]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Mod_Tool&amp;diff=43856</id>
		<title>Mod Tool</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Mod_Tool&amp;diff=43856"/>
		<updated>2025-01-22T19:24:00Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Selected Wisdom}}&lt;br /&gt;
Autodesk&#039;s Mod Tool used to be the main choice for modders when working on level and character models (at least in Windows, since it&#039;s Windows-only). It was a free and accessible program, but has long since been discontinued. Nowadays, modders are encouraged to use [[Blender]] instead.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;&amp;quot;&lt;br /&gt;
|width=&amp;quot;200px&amp;quot;|&lt;br /&gt;
;sub pages&lt;br /&gt;
: [[Mod_Tool/Scripting]]&lt;br /&gt;
: [[Mod_Tool/Rigging]]&lt;br /&gt;
: [[Mod_Tool/OniTools_addon]]&lt;br /&gt;
: [[Mod_Tool/Oni_level_rebuilder]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Full name: &amp;quot;Autodesk Softimage Mod Tool&amp;quot;. Usually we just call it &amp;quot;Mod Tool&amp;quot; or &amp;quot;XSI&amp;quot;, the old name of the program.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Download&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Get it from [https://www.moddb.com/downloads/autodesk-softimage-mod-tool-75 Mod DB].&#039;&#039;&#039;&lt;br /&gt;
* It&#039;s no longer possible to download Softimage from Autodesk because the [https://www.autodesk.com/products/softimage/overview software was discontinued] by Autodesk in favor of their major software packages Maya and 3ds Max.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Newer Windows installations usually require .NET 2.0 to be installed before the XSI installer can fully run.&#039;&#039;&#039;&lt;br /&gt;
: Downloading and installing .Net 2.0 manually from the internet might not work.&lt;br /&gt;
: &#039;&#039;&#039;Therefore use the Windows search and look for &amp;quot;features&amp;quot;.&#039;&#039;&#039; (Enable/disable Windows features.)&lt;br /&gt;
: From the Windows feature page install &#039;&#039;&#039;&amp;quot;.NET framework 3.5 (includes .NET 2.0 and 3.0)&amp;quot;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
There are various ways to extend Mod Tool&#039;s range of functions: scripts (.vbs, .js), toolbars (.xsitb) and addons (.xsiaddon). They can be created on one&#039;s own and also shared with other users.&lt;br /&gt;
&lt;br /&gt;
===Extensions===&lt;br /&gt;
&#039;&#039;&#039;links&#039;&#039;&#039;&lt;br /&gt;
* [https://www.si-community.com/community/viewtopic.php?f=35&amp;amp;t=796 &amp;quot;Roadkill&amp;quot; UV Tool]&lt;br /&gt;
* [http://web.archive.org/web/20121001104022/http://www.xsidatabase.com:80/content/drag_and_drop_obj_files_jscript drag and drop support for OBJ files] &lt;br /&gt;
* [https://www.si-community.com/community/viewtopic.php?f=35&amp;amp;t=797 OBJ exporter]&lt;br /&gt;
* [http://mods.oni2.net/node/210 OBJ + OFGA exporter] for Oni&lt;br /&gt;
** might need the regular OBJ exporter to be installed first&lt;br /&gt;
* [http://mods.oni2.net/node/210 adjusting existing fw throws] [https://www.youtube.com/watch?v=vDTPYfvMf4M (instructions)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;how to bind scripts to buttons (embedded code or .vbs / .js)&#039;&#039;&#039;&lt;br /&gt;
* You can enable/disable the Main Shelf over &amp;quot;View&amp;quot; &amp;gt; &amp;quot;Optional Panels&amp;quot; &amp;gt; &amp;quot;Main Shelf&amp;quot;. Then click the &amp;quot;Custom&amp;quot; tab.&lt;br /&gt;
* A) Right-click the free gray space, click on &amp;quot;Customize Toolbar...&amp;quot;. Select &amp;quot;Toolbar Widgets&amp;quot; &amp;gt; &amp;quot;Script Button&amp;quot;.&lt;br /&gt;
:* Enter your code and make sure you selected the correct Scripting Language. Click okay when you are done.&lt;br /&gt;
* B) You can also drag&#039;n&#039;drop your script file directly onto the free gray space.&lt;br /&gt;
:* A new window pops up, check the settings and click okay when done.&lt;br /&gt;
* Right-click the Main Shelf and use the &amp;quot;Save&amp;quot; option. (&amp;quot;Save As&amp;quot; let you save the Main Shelf as toolbar file.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;how to install toolbars (.xsitb)&#039;&#039;&#039;&lt;br /&gt;
* creation: goto &amp;quot;View&amp;quot; &amp;gt; &amp;quot;New custom toolbar&amp;quot;&lt;br /&gt;
:* Now you can add buttons like in Main Shelf. Remember to save your changes. (Right-click, &amp;quot;Save As&amp;quot;.)&lt;br /&gt;
* &#039;&#039;&#039;installation:&#039;&#039;&#039; Drag&#039;n&#039;drop the xsitb file onto the viewport (it&#039;s simply the window where you can see 3D objects).&lt;br /&gt;
* access: goto &amp;quot;View&amp;quot; &amp;gt; &amp;quot;Toolbars&amp;quot;&lt;br /&gt;
* deletion: goto &amp;quot;View&amp;quot; &amp;gt; &amp;quot;Manage...&amp;quot; Check a toolbar and click Delete button.&lt;br /&gt;
:* The file will remain with a new file suffix &amp;quot;.bak&amp;quot; You can restore this backup if you remove the &amp;quot;.bak&amp;quot; from the name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;how to install add-ons (.xsiaddon)&#039;&#039;&#039;&lt;br /&gt;
* A) drag&#039;n&#039;drop the file into the so-called viewport (it&#039;s simply the window where you can see 3D objects), then restart Mod Tool&lt;br /&gt;
* B) if drag and drop doesn&#039;t work, goto &amp;quot;File&amp;quot; &amp;gt; &amp;quot;Add-On&amp;quot; &amp;gt; &amp;quot;Install&amp;quot;&lt;br /&gt;
:* Then click on the &amp;quot;...&amp;quot; button to search for the file. When you found it, click the &amp;quot;Install&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;building add-ons (&amp;lt;nowiki&amp;gt;http://softimage.wiki.softimage.com/sdkdocs/cus_addons_WalkthroughBuildinganAddon.htm&amp;lt;/nowiki&amp;gt;, dead link)&#039;&#039;&#039;&lt;br /&gt;
* Building an add-on file needs more effort than the other &#039;extensions&#039; but for the end user it&#039;s best because it can hold all other files: toolbars, plugins (scripts), etc.&lt;br /&gt;
** The user can install a newer version of the addon by repeating the installation with the new file: it&#039;s unnecessary to remove the old version.&lt;br /&gt;
* File &amp;gt; Add-On &amp;gt; Package... doesn&#039;t work with ModTool &amp;quot;Add-Ons cannot be created with Softimage Demo Version.&amp;quot;&lt;br /&gt;
* Images and any other files can be put into any folder of the add-on.&lt;br /&gt;
** Let&#039;s say you have an addon called &amp;quot;my_stuff&amp;quot;, a subfolder &amp;quot;images&amp;quot; and an image called &amp;quot;test.png&amp;quot;. The image can be accessed via:&lt;br /&gt;
:: &#039;&#039;&#039;&#039;&#039;XSIUtils.ResolvePath(&amp;quot;$XSI_USERHOME/&amp;quot;) &amp;amp; &amp;quot;Addons\&#039;&#039;&#039;my_stuff\images\test.png&amp;quot;&#039;&#039;&lt;br /&gt;
* The problem with embedded code: commands like &#039;&#039;CreatePrim&#039;&#039; can call an property page (PPG).&lt;br /&gt;
** Those popups can be disabled. Search for &amp;quot;disabling PPG popups&amp;quot; on this page.&lt;br /&gt;
* &#039;&#039;&#039;Putting scripts simply into folders doesn&#039;t work, they must be &amp;quot;plugins&amp;quot;, the file extension can be the same e.g. &amp;quot;vbs&amp;quot;&#039;&#039;&#039;.&lt;br /&gt;
** A script function can run on another computer if it is found as command, and plugin register new commands.&lt;br /&gt;
** E.g. you can use those commands in your toolbar&#039;s script buttons.&lt;br /&gt;
* Example of turning a function into a command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;function with arguments as it is&#039;&#039;&#039;&lt;br /&gt;
 &#039; this function can only be used inside the script where it was defined&lt;br /&gt;
 &lt;br /&gt;
 function simple_math (a, b, operator)&lt;br /&gt;
 	if operator = &amp;quot;+&amp;quot; then&lt;br /&gt;
  		simple_math = a + b&lt;br /&gt;
 	elseif operator = &amp;quot;-&amp;quot; then&lt;br /&gt;
 		simple_math = a - b&lt;br /&gt;
 	elseif operator = &amp;quot;/&amp;quot; then&lt;br /&gt;
 		simple_math = a / b&lt;br /&gt;
 	elseif operator = &amp;quot;x&amp;quot; then&lt;br /&gt;
 		simple_math = a * b&lt;br /&gt;
 	else&lt;br /&gt;
 		logmessage &amp;quot;The used operator is not allowed. Choose one of the following:&amp;quot; &amp;amp; vbCrlf &amp;amp; &amp;quot;+ - / x&amp;quot;&lt;br /&gt;
 	end if&lt;br /&gt;
 end function&lt;br /&gt;
 &lt;br /&gt;
 &#039; example of usage&lt;br /&gt;
 result = simple_math(5, 3, &amp;quot;+&amp;quot;)&lt;br /&gt;
 logmessage result&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; the same function as command&#039;&#039;&#039;&lt;br /&gt;
 &#039; the command simple_math can now be used in any script&lt;br /&gt;
 &lt;br /&gt;
 function XSILoadPlugin( in_reg )&lt;br /&gt;
 	in_reg.Author = &amp;quot;your_name&amp;quot;&lt;br /&gt;
 	in_reg.Name = &amp;quot;simple_mathPlugin&amp;quot;&lt;br /&gt;
 	in_reg.Email = &amp;quot;&amp;quot;&lt;br /&gt;
 	in_reg.URL = &amp;quot;&amp;quot;&lt;br /&gt;
 	in_reg.Major = 1&lt;br /&gt;
 	in_reg.Minor = 0&lt;br /&gt;
 &lt;br /&gt;
 	in_reg.RegisterCommand &amp;quot;simple_math&amp;quot;,&amp;quot;simple_math&amp;quot;&lt;br /&gt;
 	&#039;RegistrationInsertionPoint - do not remove this line&lt;br /&gt;
 &lt;br /&gt;
 	XSILoadPlugin = true&lt;br /&gt;
 end function&lt;br /&gt;
 &lt;br /&gt;
 function XSIUnloadPlugin( in_reg )&lt;br /&gt;
 	dim strPluginName&lt;br /&gt;
 	strPluginName = in_reg.Name&lt;br /&gt;
 	Application.LogMessage strPluginName &amp;amp; &amp;quot; has been unloaded.&amp;quot;,siVerbose&lt;br /&gt;
 	XSIUnloadPlugin = true&lt;br /&gt;
 end function&lt;br /&gt;
 &lt;br /&gt;
 function simple_math_Init( in_ctxt )&lt;br /&gt;
 	dim oCmd&lt;br /&gt;
 	set oCmd = in_ctxt.Source&lt;br /&gt;
 	oCmd.Description = &amp;quot;&amp;quot;&lt;br /&gt;
 	oCmd.ReturnValue = true&lt;br /&gt;
 &lt;br /&gt;
 	dim oArgs&lt;br /&gt;
 	set oArgs = oCmd.Arguments&lt;br /&gt;
 	oArgs.Add &amp;quot;a&amp;quot;,siArgumentInput,&amp;quot;0&amp;quot;&lt;br /&gt;
 	oArgs.Add &amp;quot;b&amp;quot;,siArgumentInput,&amp;quot;0&amp;quot;&lt;br /&gt;
 	oArgs.Add &amp;quot;operator&amp;quot;,siArgumentInput,&amp;quot;0&amp;quot;&lt;br /&gt;
 	simple_math_Init = true&lt;br /&gt;
 end function&lt;br /&gt;
 &lt;br /&gt;
 function simple_math_Execute( a, b, operator )&lt;br /&gt;
 	&#039; convert to double&lt;br /&gt;
 	a = cdbl(a)&lt;br /&gt;
 	b = cdbl(b)&lt;br /&gt;
 	&lt;br /&gt;
 	if operator = &amp;quot;+&amp;quot; then&lt;br /&gt;
 		simple_math_Execute = a + b&lt;br /&gt;
 	elseif operator = &amp;quot;-&amp;quot; then&lt;br /&gt;
 		simple_math_Execute = a - b&lt;br /&gt;
 	elseif operator = &amp;quot;/&amp;quot; then&lt;br /&gt;
 		simple_math_Execute = a / b&lt;br /&gt;
 	elseif operator = &amp;quot;x&amp;quot; then&lt;br /&gt;
 		simple_math_Execute = a * b&lt;br /&gt;
 	else&lt;br /&gt;
 		logmessage &amp;quot;The used operator is not allowed. Choose one of the following:&amp;quot; &amp;amp; vbCrlf &amp;amp; &amp;quot;+ - / x&amp;quot;&lt;br /&gt;
 	end if&lt;br /&gt;
 end function&lt;br /&gt;
&lt;br /&gt;
==Selected wisdom==&lt;br /&gt;
We&#039;ve also a [http://oni.bungie.org/forum/viewtopic.php?id=1229 tutorial thread on OCF.]&lt;br /&gt;
&lt;br /&gt;
Hotkey list can be found [http://www.keyxl.com/aaacbe0/415/SoftImage-XSI-keyboard-shortcuts.htm here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Visibility===&lt;br /&gt;
* show/hide grid: [G]&lt;br /&gt;
* display polygon normals: click the eye symbol, select &amp;quot;Polygon Normals&amp;quot; (now you know the polygons &#039;&#039;up and down&#039;&#039;)&lt;br /&gt;
* display triangle count: click the eye symbole, select &amp;quot;Selection Info&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Camera navigation===&lt;br /&gt;
* reset view: [R]&lt;br /&gt;
* zoom camera: [Scrolling]&lt;br /&gt;
* move camera: [S] + [LClick] + [MoveMouse]&lt;br /&gt;
* rotate camera: [S] + [RClick] + [MoveMouse]&lt;br /&gt;
* pan camera:  [S] + [MClick] + [MoveMouse]&lt;br /&gt;
* move camera mode: [Z]&lt;br /&gt;
* rotate camera mode: [O]&lt;br /&gt;
* pan camera mode: [P]&lt;br /&gt;
* use camera mode move/rotate/pan with: [LClick] + [MoveMouse]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Mesh===&lt;br /&gt;
* scale mode: [X]&lt;br /&gt;
* rotate mode: [C]&lt;br /&gt;
* translate mode [V]&lt;br /&gt;
* manipulate tool: [B] (a gray box appears with gray balls at the corners)&lt;br /&gt;
** drag inside the object to move it&lt;br /&gt;
** drag an edge to rotate it&lt;br /&gt;
** drag a ball to scale it&lt;br /&gt;
* object selection mode: [Space]&lt;br /&gt;
* extracting a polygon from an object: select polygon, right-click, &amp;quot;Extract Polygons (Delete)&amp;quot;&lt;br /&gt;
* copying an polygon from an object: select polygon, right-click, &amp;quot;Extract Polygons (Keep)&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;merging two objects&#039;&#039;&#039;: select object A, then goto Model &amp;gt; Modify &amp;gt; Poly. Mesh &amp;gt; Boolean &amp;gt; Union, select object B&lt;br /&gt;
: (this makes a copy of object B and attaches it to A, the &#039;&#039;&#039;merged objects (A) must be freezed&#039;&#039;&#039; before the original object B can be removed)&lt;br /&gt;
* filling a hole: select all edges surrounding the hole and choose one of the following methods&lt;br /&gt;
** A) goto Model &amp;gt; Modify &amp;gt; Poly. Mesh &amp;gt; Weld Boundary Points/Edges&lt;br /&gt;
** B) goto Model &amp;gt; Modify &amp;gt; Poly. Mesh &amp;gt; Bridge Boundary Points/Edges (if blue lines appear try to disable the checkbox &amp;quot;Angle &amp;gt; 90&amp;quot;)&lt;br /&gt;
* merging two objects at blue lines: merge the objects at first, then proceed with the point above &amp;quot;filling a hole&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;merging two objects with UVs&#039;&#039;&#039;: Create &amp;gt; Poly. Mesh &amp;gt; [https://web.archive.org/web/20160225163131/http://cryrid.com/images/temp/XSI/merge_materials.jpg Merge]&lt;br /&gt;
** extracted Oni characters have their materials and hence textures directly grouped under the mesh (see Explorer)&lt;br /&gt;
** when adding (merging) a new part to the existing mesh, the materials/textures will be grouped under (Explorer again) mesh &amp;gt; Polygon Mesh &amp;gt; Clusters &amp;gt; ...&lt;br /&gt;
** Samer reported that saving the file via fbx solves a problem when trying to convert TRBS&lt;br /&gt;
** one would need to move the content by hand in the explorer to bypass the fbx&lt;br /&gt;
* hiding some objects/polygons: select object/polygon and hit [H], use [Control] + [H] to unhide all&lt;br /&gt;
* mirroring an object: select object, Modify &amp;gt; Poly. Mesh &amp;gt; Symmetrize Polygons&lt;br /&gt;
* working with symmetry mode (look below at &amp;quot;Low poly modeling&amp;quot; section for other possibilities with symmetry)&lt;br /&gt;
** select object, Property &amp;gt; Symmetry Map (YZ/XZ/XY) (press [W] to preview symmetry plane)&lt;br /&gt;
** click on Sym buttom (in Transform area) to enable/disable symmetry mode&lt;br /&gt;
** changing the Symmetry plane: Explorer [8] &amp;gt; unfold object &amp;gt; Polygon Mesh &amp;gt; Cluster &amp;gt; delete SymmetryMapCls; then add a new symmetry plane&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Low poly modeling====&lt;br /&gt;
* select edge loop: while being in selection mode Edge, press [Alt] + [MClick]&lt;br /&gt;
* modify point/edge/polygon: [M]&lt;br /&gt;
** press left mouse button and hold it, move mouse to translate point/edge/polygon freely&lt;br /&gt;
:: if axes symbol is active you can left-click a component and the translate axes pop up&lt;br /&gt;
:: if magnet symbol is active the translation will be limited by the surrounded components&lt;br /&gt;
:: if point symbol is active then only points can be selected, moving one point onto another will weld them&lt;br /&gt;
&lt;br /&gt;
* By the way, combining edge loop with component selection [M] and active magnet gives an interesting effect: a line of edges will mimic the shape of their neighbor edges as closer the selected edges comes to the neighbors.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;getting images into Mod Tool that serve as modeling reference:&#039;&#039;&#039;&lt;br /&gt;
** click where you can set the view mode (e.g. to &amp;quot;Wireframe&amp;quot;), select &#039;&#039;&#039;&amp;quot;Rotoscope&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
** in the appearing window at &amp;quot;Image Placement&amp;quot; choose &amp;quot;Fixed&amp;quot; so that the image will be zoomed when you zoom on the object&lt;br /&gt;
** choose an image by clicking the button &amp;quot;New&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;symmetry in modeling:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You could make A) only one half of an object or B) selected polygons and then mirror and merge the parts.&lt;br /&gt;
* A) select object, [Alt] + [RClick] object, Symmetrize Polygons&lt;br /&gt;
* B) select polygons, [RClick] one of them, Symmetrize Polygons&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Or you start with a half object and create a mirrored clone. You can then work on the original mesh. (In Schematics the cloned mesh will have a red &amp;quot;Cl&amp;quot; and a trapezoid shape as symbol.)&lt;br /&gt;
* select object then goto Edit &amp;gt; Duplicate/Instantiate &amp;gt; Clone Single&lt;br /&gt;
* scale X or one of the other axes to -1&lt;br /&gt;
* make any modification on the original mesh, the clone will adept them&lt;br /&gt;
* eventually merge cloned and original mesh, freeze them to make changes final&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Exchange meshes in hierarchies====&lt;br /&gt;
Let&#039;s say you loaded an Oni character with his 19 body parts into the scene, something is wrong and you want to fix it.&lt;br /&gt;
&lt;br /&gt;
To destroy the hierarchy you must be sure the model is not animated. If there are keyframes the model will be one big mess after breaking the hierarchical links.&lt;br /&gt;
&lt;br /&gt;
So, save the model with the settings &amp;quot;Selection Only [X]&amp;quot; and &amp;quot;Animation [ ]&amp;quot;. Then reload the model.&lt;br /&gt;
&lt;br /&gt;
Next, disable the red &amp;quot;Auto&amp;quot; button under &amp;quot;Animation&amp;quot; (if enabled). Keyframes affects also the creation of hierarchies, that&#039;s why we don&#039;t want new keyframes.&lt;br /&gt;
&lt;br /&gt;
Now you can safely exchange, move and rotate meshes and their centers, and eventually rebuild the hierarchy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Material and texture===&lt;br /&gt;
[[Image:apply_new_main_texture_in_Mod_Tool.png|thumb|200px|right|how to apply a new main texture]]&lt;br /&gt;
[[Image:apply_new_polygon_cluster_texture_in_Mod_Tool.png|thumb|200px|right|how to apply a new polygon cluster texture]]&lt;br /&gt;
* objects use the scene material by default, objects need their own material if they should have individual textures&lt;br /&gt;
* selecting a material and surface: Model &amp;gt; Material &amp;gt; Phong (simply close the windows that pops up)&lt;br /&gt;
* connecting the texture with the material:&lt;br /&gt;
** [7] to open Render Tree&lt;br /&gt;
** in first column: &amp;quot;Texture&amp;quot;&lt;br /&gt;
** in second column: drag&#039;n&#039;drop &amp;quot;Image&amp;quot; into the free space&lt;br /&gt;
** click and hold the red point of &amp;quot;Image&amp;quot;, then move it to &amp;quot;Phong&amp;quot; and release the mouse click&lt;br /&gt;
** choose &amp;quot;diffuse&amp;quot; as illumination mode (for instance &amp;quot;ambient&amp;quot; won&#039;t work - the texture would be visible in Mod Tool but Onisplit can&#039;t use it)&lt;br /&gt;
* now &amp;quot;Image&amp;quot; can be double-clicked (the Texture Editor will pop up), in the section &amp;quot;Image&amp;quot; click on &amp;quot;New&amp;quot; to choose an image&lt;br /&gt;
* to change textures &#039;&#039;&#039;don&#039;t drag and drop textures directly one meshes&#039;&#039;&#039;, this creates textures layers which are ignored by OniSplit&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Projection and UV===&lt;br /&gt;
&#039;&#039;&#039;getting started&#039;&#039;&#039;&lt;br /&gt;
* in section &amp;quot;Texture Projection&amp;quot; click on &amp;quot;New&amp;quot;, choose a projection similar to the mesh shape (planar / cylindrical / cubic / spherical)&lt;br /&gt;
* select the object&lt;br /&gt;
* Texture editor: [Alt]+[7] (open it while being in selection mode &amp;quot;Object&amp;quot; or &amp;quot;Polygon&amp;quot;, otherwise the UVs aren&#039;t shown)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;modify single/all UVs&#039;&#039;&#039;&lt;br /&gt;
* rotate 90°: [R]&lt;br /&gt;
* rotate: [C]&lt;br /&gt;
* scale: [X]&lt;br /&gt;
* scale height only: [X], then [Shift] + [MClick] + [MoveMouse]&lt;br /&gt;
* scale length only: [X], then [Shift] + [RClick] + [MoveMouse]&lt;br /&gt;
* move: [V]&lt;br /&gt;
* tearing single UV parts: [Control] + [T], then move [V]&lt;br /&gt;
* heal (re-connect) selected UV parts: click on the plus symbol (the parts should be very near to each other, best if the points are on same spot)&lt;br /&gt;
* snap function for move tool: Snap &amp;gt; Enable Snapping; check &amp;quot;Points&amp;quot; (if not already active)&lt;br /&gt;
* relax (smooth warped UVs): [Control] + [R] (usually pressing several times that combination)&lt;br /&gt;
* a new projection can also be applied to currently selected UV parts&lt;br /&gt;
* freeze object to &#039;&#039;bake&#039;&#039; projections (green lines in the 3D view will disappear)&lt;br /&gt;
* getting a picture of the UV: apply first a black texture then enter the Texture Editor [Alt] + [7], Edit &amp;gt; Stamp UV Mesh [Shift] + [S], save the texture&lt;br /&gt;
&lt;br /&gt;
Things to test:&lt;br /&gt;
* https://vimeo.com/67783125&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Rendering===&lt;br /&gt;
Rendering doesn&#039;t work well on my PCs.--[[User:Paradox-01|paradox-01]] ([[User talk:Paradox-01|talk]]) 01:09, 9 March 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Especially PNG, it works one time. But as soon as I import another dae the next render will fail.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, for creating a object library we might use blender. Nice thing is, it can also render in the background when called from CMD. This means you could keep working in XSI and render images in blender at the same time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
example of a batch file:&lt;br /&gt;
 cd C:\Program Files\Blender Foundation\Blender&lt;br /&gt;
 blender -b --python C:\Users\Paradox-01\Desktop\blender-out\pythonScript.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
example of a render script:&lt;br /&gt;
 import bpy&lt;br /&gt;
 &lt;br /&gt;
 # delete blender default cube object&lt;br /&gt;
 bpy.ops.object.mode_set(mode=&#039;OBJECT&#039;)&lt;br /&gt;
 bpy.ops.object.select_by_type(type=&#039;MESH&#039;)&lt;br /&gt;
 bpy.ops.object.delete(use_global=False)&lt;br /&gt;
 &lt;br /&gt;
 # load new object&lt;br /&gt;
 bpy.ops.wm.collada_import(filepath = &amp;quot;C:/Oni/r.dae&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 # render settings&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.resolution_x = 900&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.resolution_y = 900&lt;br /&gt;
 # default resolution percentage seems to be 50 &lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.resolution_percentage = 100&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.use_antialiasing = True&lt;br /&gt;
 # 5 | 8 | 11 | 16&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.antialiasing_samples = &amp;quot;8&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 #TGA IRIS JPEG MOVIE IRIZ RAWTGA&lt;br /&gt;
 #AVIRAW AVIJPEG PNG BMP FRAMESERVER&lt;br /&gt;
 #no gif ? could be created by more code, maybe merging single frames of jpgs&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.image_settings.file_format = &#039;JPEG&#039;&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.image_settings.quality = 100&lt;br /&gt;
 &lt;br /&gt;
 # file suffix is overwritten by file_formate&lt;br /&gt;
 #bpy.data.scenes[&#039;Scene&#039;].render.filepath = &#039;C:/Oni/renders/test.jpg&#039;&lt;br /&gt;
 bpy.data.scenes[&#039;Scene&#039;].render.filepath = &#039;C:/Oni/renders/test&#039;&lt;br /&gt;
 &lt;br /&gt;
 # start render&lt;br /&gt;
 bpy.ops.render.render( write_still=True )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animating===&lt;br /&gt;
[[Image:Scale_animations_in_Mod_Tool_Animation_Editor_DopeSheet.png|thumb|200px|right|an animation that got scaled down from 116 to 58 frames]]&lt;br /&gt;
&lt;br /&gt;
* preparing ModTool to save animations Oni can use: File &amp;gt; Preferences... &amp;gt; Preferences &amp;gt; Tools &amp;gt; Output Format&lt;br /&gt;
** Frame Step: 1&lt;br /&gt;
** Frame Format: Custom framerate&lt;br /&gt;
** &#039;&#039;&#039;Frame Rate: 60&#039;&#039;&#039;&lt;br /&gt;
* for real-time playback click on &amp;quot;Playback&amp;quot; option button and then &amp;quot;Real-Time Playback&amp;quot;&lt;br /&gt;
* opening the Animation Editor : [0]&lt;br /&gt;
* opening the DopeSheet: from any other Animation Editor, Editor &amp;gt; DopeSheet&lt;br /&gt;
* &#039;&#039;&#039;making an animation shorter or longer:&#039;&#039;&#039; in DopeSheet click Region button (arrow with rectangle), click and hold to select keyframes, at selection edge a) [shift] plus left-click and move mouse or b) middle-click and move mouse&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Issues when saving and sharing animation files (*.dae, *.exp)====&lt;br /&gt;
That what you currently see in Mod Tool and that what you get when saving data can be different.&lt;br /&gt;
&lt;br /&gt;
1) *.dae files might save data differently than expected.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Rotation flips&#039;&#039; might appear.&lt;br /&gt;
&lt;br /&gt;
2) *.exp and *.dae save data differently.&lt;br /&gt;
&lt;br /&gt;
*.exp files store the frames as they are.&lt;br /&gt;
&lt;br /&gt;
*.dae file store their actions (rotations/translation/...) in seconds and eventually depend on what framerate a Modder uses.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Following scenario: a modder wants to share an animation as *.exp and another modder wants to use that animation.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Modder A uses 30 fps in his settings and exports an *.exp that is 58 frame long.&lt;br /&gt;
&lt;br /&gt;
Modder B uses 60 fps in his setting and imports the *.exp, to his surprise the animation is 116 frames long. What now?&lt;br /&gt;
&lt;br /&gt;
If Modder B saves the *.exp under a new name would not help, the frames will be still the same.&lt;br /&gt;
&lt;br /&gt;
Instead Modder B could scale the animation. The way to do so is described in the [[#Animating|Animating]] section, &amp;quot;making an animation shorter or longer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Modder B scales the animation and saves it as dae.&lt;br /&gt;
&lt;br /&gt;
Now he wants to see if it worked. He opens a new scene [Strg]+[N] and loads the dae.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary of issue-holding aspects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Frames Per Second (FPS)&#039;&#039;&#039;&lt;br /&gt;
When you share *.dae files with other Modders be sure that the output formate is 60 fps. Different framerates among modders can cause confusion.&lt;br /&gt;
&lt;br /&gt;
Dae file store their actions (rotation/translation/...) in seconds.&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;float_array count=&amp;quot;10&amp;quot; id=&amp;quot;pelvis_rotation_x_ANGLE-anim-input-array&amp;quot;&amp;gt;&lt;br /&gt;
     0.000000 0.166833 0.333667 0.500500 0.600600 0.934267 1.267933 1.601600 1.768433 1.935267&lt;br /&gt;
 &amp;lt;/float_array&amp;gt;&lt;br /&gt;
&lt;br /&gt;
action at [s] * framerate [f/s] = frame [f]&lt;br /&gt;
&lt;br /&gt;
In this example the last rotation occurs at 1.935267s.&lt;br /&gt;
&lt;br /&gt;
: Modder A uses 30 fps, his last frame is 58.&lt;br /&gt;
: Modder B uses 60 fps, his last frame is 116. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Euler rotations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
you will get [[wikipedia:Bézier_curve|BEZIER]] (cubic) interpolation instead of LINEAR if you use&lt;br /&gt;
: &amp;quot;Convert Quarternion Rotation to Euler&amp;quot; &lt;br /&gt;
: &amp;quot;Spline Interpolation&amp;quot; in the animation (fcurve) editor&lt;br /&gt;
&lt;br /&gt;
Those smooth the rotations.&lt;br /&gt;
&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Quaternion rotations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Don&#039;t use this.&lt;br /&gt;
&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Make Rotation Keys Continuous&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Animation mixer====&lt;br /&gt;
This could help with creating cutscenes and complex animations (e.g. run cycles for FILM files).&lt;br /&gt;
&lt;br /&gt;
Open the animation mixer with [Alt]+[0].&lt;br /&gt;
&lt;br /&gt;
Further information over [http://web.archive.org/web/20170103065301/http://softimage.wiki.softimage.com/xsidocs/nla_mixer.htm#Rdw10200 HERE.]&lt;br /&gt;
&lt;br /&gt;
Here are a few videos:&lt;br /&gt;
* &#039;&#039;&#039;https://www.youtube.com/watch?v=-xC31Q7zpM0&#039;&#039;&#039;&lt;br /&gt;
* https://www.youtube.com/watch?v=njLrAIpDOFU&lt;br /&gt;
* https://www.youtube.com/watch?v=PRDZaEo5CGo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Sounds=====&lt;br /&gt;
Within the animation mixer also sounds can be added.&lt;br /&gt;
&lt;br /&gt;
Further information over [http://web.archive.org/web/20170102120711/http://softimage.wiki.softimage.com/xsidocs/audio_LoadingAudioFilesintheAnimationMixer.htm#Rdy36984 HERE.]&lt;br /&gt;
&lt;br /&gt;
This could be used to synchronize sounds effect with physical actions in the scene.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Scripting===&lt;br /&gt;
* open the Script Editor: [Alt] + [4]&lt;br /&gt;
* run the current code in the Script Editor window: [F5]&lt;br /&gt;
* clear the log: Edit &amp;gt; Clear History Log&lt;br /&gt;
* Actions from button embedded code will be logged.&lt;br /&gt;
* Actions from code files that are linked in a button won&#039;t be logged. (This results in a performance boost.)&lt;br /&gt;
* Logged stuff will be rewritten if you change the script language. (File &amp;gt; Preferences...) &lt;br /&gt;
* You can also change the language by right-click the white script box and click on &amp;quot;Set to JScript&amp;quot; or &amp;quot;Set to VBScript&amp;quot;.&lt;br /&gt;
* Python can be added as script language if you install it on your PC.&lt;br /&gt;
* Right-clicking the white script box gives you also access to a few code piece, e.g. &amp;quot;Syntax Help&amp;quot; &amp;gt; &amp;quot;If..Else&amp;quot; or &amp;quot;Catch Error&amp;quot;.&lt;br /&gt;
* Mark code you want to disable (&amp;quot;Comment Out&amp;quot;) or enable (&amp;quot;Comment Remove&amp;quot;).&lt;br /&gt;
* You can save your code to a file via &amp;quot;File&amp;quot; &amp;gt; &amp;quot;Save As...&amp;quot; or &amp;quot;Save Selection&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Links&#039;&#039;&#039;&lt;br /&gt;
* [http://web.archive.org/web/20160803061035/http://softimage.wiki.softimage.com/index.php?title=Scripting_Tips_and_Tricks_%28XSISDK%29 xsi wiki page about scripting]&lt;br /&gt;
* &#039;&#039;&#039;[http://web.archive.org/web/20170616035120/http://softimage.wiki.softimage.com/sdkdocs/scriptsdb/scriptsdb/scrdb_vbscript.htm many vbscript examples]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[https://ss64.com/vb/ vbs commands]&#039;&#039;&#039;&lt;br /&gt;
* [https://web.archive.org/web/20070510173452/https://www.activexperts.com/activmonitor/windowsmanagement/adminscripts/filesfolders/files/ objFSO/objWSHShell: Scripts to manage Files] (replace &amp;quot;Wscript.Echo&amp;quot; with &amp;quot;logmessage&amp;quot;)&lt;br /&gt;
* [https://web.archive.org/web/20150504221146/http://activexperts.com/activmonitor/windowsmanagement/adminscripts/other/textfiles/ objFSO/objWSHShell: Scripts to manage Text Files]&lt;br /&gt;
* [http://web.archive.org/web/20080905102848/http://www.kxcad.net/softimage_xsi/Softimage_XSI_Documentation/script_basics_IncludingExternalScripts.htm using external scripts]&lt;br /&gt;
* [https://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_om/XSIUIToolkit.html,topicNumber=si_om_XSIUIToolkit_html progress bar and open file dialog&amp;lt;!-- (hm, InitialDirectory code for quick save idea ?)--&amp;gt;]&lt;br /&gt;
&amp;lt;!--* [http://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=files/cus_ppg_FileBrowserWidget.htm,topicNumber=d30e11980,hash=WS34BA39B437A993419C80CAB58E3BEFA1-0059 text box]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes about polygon extraction&#039;&#039;&#039;&lt;br /&gt;
* a grid of 9 polygons (ID 0 to 8) &lt;br /&gt;
* you extract the middle polygon (ID 4)&lt;br /&gt;
* grid&#039;s polygon of ID 8 will change to ID 4&lt;br /&gt;
* if you now extract 5th, the 7th gets the ID&lt;br /&gt;
* now the ID order is: 0, 1, 2, 3, 6, 5, 4&lt;br /&gt;
* this means that an automatic extraction of several polygons requires two changes in the code&lt;br /&gt;
* 1) the ID array of selected polygons must be sorted&lt;br /&gt;
* 2) the extraction must start with the last ID to avoid ID shift during the process (see code pieces)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Some basics of VBScript&#039;&#039;&#039;&lt;br /&gt;
* In VBS you declare variables only as a variant e.g. &amp;quot;dim PolygonCount&amp;quot;. Mod Tool decides what type it becomes when it uses the variable the first time.&lt;br /&gt;
* You can put &amp;quot;option explicit&amp;quot; at the start of your script. Then you will be forced to declare all variables with &amp;quot;dim&amp;quot;. That looks quite unnecessary but help to find mistakes for example if you mistyped a variable somewhere in a long script.&lt;br /&gt;
&lt;br /&gt;
* The commands are not case-sensitive, e.g. you can write &amp;quot;LogMessage&amp;quot; or &amp;quot;logmessage&amp;quot;.&lt;br /&gt;
* Vbs functions can be found [https://web.archive.org/web/20150707131602/https://www.w3schools.com/vbscript/vbscript_ref_functions.asp HERE.]&lt;br /&gt;
&lt;br /&gt;
 &#039; while it is possible to use + in strings,&lt;br /&gt;
 &#039; you should actually use &amp;amp; only for strings&lt;br /&gt;
 &#039; and + only for numbers&lt;br /&gt;
 &lt;br /&gt;
 logmessage &amp;quot;How about ... &amp;quot; + &amp;quot;a riddle?&amp;quot;&lt;br /&gt;
 logmessage &amp;quot;Where can you find following phrase in Oni? &amp;quot; &amp;amp; &amp;quot;The day is mine !!&amp;quot;&lt;br /&gt;
 logmessage &amp;quot;Did you know that Bungie likes to hide sevens? The digits of the year 2032 add up to &amp;quot; &amp;amp; cstr(2 + 0 + 3 + 2) &amp;amp; &amp;quot;.&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : How about ... a riddle?&lt;br /&gt;
 &#039; INFO : Where can you find following phrase in Oni? The day is mine !!&lt;br /&gt;
 &#039; INFO : Did you know that Bungie likes to hide sevens? The digits of the year 2032 add up to 7.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;More tips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* You can replace each &amp;quot;logmessage&amp;quot; with a variable. In that case don&#039;t forget the = sign.&lt;br /&gt;
* Selection(0) means that from all selected objects the first one is taken.&lt;br /&gt;
* Use a loop to get all objects.&lt;br /&gt;
&lt;br /&gt;
 for each n in selection&lt;br /&gt;
 	logmessage n&lt;br /&gt;
 next&lt;br /&gt;
&lt;br /&gt;
* In order to shorten the code you might want to set script objects.&lt;br /&gt;
: The command to create a standard cube is &#039;&#039;CreatePrim &amp;quot;Cube&amp;quot;, &amp;quot;MeshSurface&amp;quot;&#039;&#039;&lt;br /&gt;
: If you use &#039;&#039;&#039;&#039;&#039;set name = &#039;&#039;&#039;&#039;&#039; the cube or other object will be available under that &#039;&#039;name&#039;&#039;.&lt;br /&gt;
: Then you can use any valid method or property with that &#039;&#039;name&#039;&#039;.&lt;br /&gt;
: Example:&lt;br /&gt;
 &lt;br /&gt;
 set c = CreatePrim (&amp;quot;Cube&amp;quot;, &amp;quot;MeshSurface&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 logmessage selection(0).name&lt;br /&gt;
 logmessage selection(0).length.value&lt;br /&gt;
 logmessage c.name&lt;br /&gt;
 logmessage c.length.value&lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : cube&lt;br /&gt;
 &#039; INFO : 8&lt;br /&gt;
 &#039; INFO : cube&lt;br /&gt;
 &#039; INFO : 8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Some ModTool commands in vbs language that might be interesting for Oni related stuff&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
| width=50% valign=top | LogMessage &amp;lt;nowiki&amp;gt;[string | var | object]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| A command to log information. It requires a string or a variable. Example:&lt;br /&gt;
: LogMessage &amp;quot;The object&#039;s name is: &amp;quot; &amp;amp; selection(0).Name&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection.count&lt;br /&gt;
| Logs the number of selected objects.&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).Name&lt;br /&gt;
| Logs the object name.&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).Materials(0).Name&lt;br /&gt;
| Logs the material name.&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).Materials(0).Library.name&lt;br /&gt;
| Logs the material library name.&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).Materials(0).shaders(0).name&lt;br /&gt;
| Logs the material shader (e.g. phong).&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| logmessage selection(0).Materials(0).CurrentImageClip.source.filename.value&lt;br /&gt;
| Logs absolute path of the texture. Output example:&lt;br /&gt;
: &#039;&#039;C:\Users\RRM\Desktop\TV_tex.png&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| logmessage selection(0).Materials(0).CurrentImageClip.source.Parameters(&amp;quot;XRes&amp;quot;).Value&amp;lt;br&amp;gt;logmessage selection(0).Material.CurrentImageClip.source.Parameters(&amp;quot;YRes&amp;quot;).Value&lt;br /&gt;
| Logs the horizontal (X) and vertical (Y) pixel length of the texture. Output example:&lt;br /&gt;
: &#039;&#039;512&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).sclx.value&amp;lt;br&amp;gt;logmessage selection(0).scly.value&amp;lt;br&amp;gt;logmessage selection(0).sclz.value&lt;br /&gt;
|valign=top| Logs object&#039;s scaling (X, Y, Z).&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).rotx.value&amp;lt;br&amp;gt;logmessage selection(0).roty.value&amp;lt;br&amp;gt;logmessage selection(0).rotz.value&lt;br /&gt;
|valign=top| Logs object&#039;s rotation (X, Y, Z).&lt;br /&gt;
|-&lt;br /&gt;
| logmessage selection(0).posx.value&amp;lt;br&amp;gt;logmessage selection(0).posy.value&amp;lt;br&amp;gt;logmessage selection(0).posz.value&lt;br /&gt;
|valign=top| Logs object&#039;s position (X, Y, Z).&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| logmessage selection(0).rotorder.value&lt;br /&gt;
| Logs object&#039;s rotation order. Oni characters have ZYX as rotation order.&lt;br /&gt;
:0 = XYZ&lt;br /&gt;
:1 = XZY&lt;br /&gt;
:2 = YXZ&lt;br /&gt;
:3 = YZX&lt;br /&gt;
:4 = ZXY&lt;br /&gt;
:5 = ZYX&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| SelectObj &amp;lt;nowiki&amp;gt;[string | var]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| select one or more objects. Comma serves as separator. Example:&lt;br /&gt;
: SelectObj &amp;quot;grid,grid1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| ToggleSelection &amp;lt;nowiki&amp;gt;[string | var]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| Adds one or more objects from current selection. If the objects are already selected then they become subtracted from the selection. Example:&lt;br /&gt;
: ToggleSelection &amp;quot;grid2,grid3&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| [https://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_cmds/SelectAllUsingFilter.html,topicNumber=si_cmds_SelectAllUsingFilter_html SelectAllUsingFilter] &amp;lt;nowiki&amp;gt;[SelFilter], [CheckComponentVisibility], [AffectSelectionList], [CheckObjectSelectability]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Selects everything that matches the filter and other options. Example:&lt;br /&gt;
: SelectAllUsingFilter &amp;quot;object&amp;quot;, siCheckComponentVisibility &lt;br /&gt;
:: selects all roots, lights, cameras, and geometry (meshes)&lt;br /&gt;
: SelectAllUsingFilter &amp;quot;geometry&amp;quot;, siCheckComponentVisibility&lt;br /&gt;
:: selects all geometry (meshes)&lt;br /&gt;
|-&lt;br /&gt;
| DeselectAll&lt;br /&gt;
| deselects everything&lt;br /&gt;
|-&lt;br /&gt;
|valign=top| DeleteObj &amp;lt;nowiki&amp;gt;[string | var]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| Deletes one or more objects. Comma used as separator. Example:&lt;br /&gt;
: DeleteObj &amp;quot;grid&amp;quot;&lt;br /&gt;
: DeleteObj &amp;quot;grid,grid1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| FreezeObj&lt;br /&gt;
| Makes all changes final. But saving those changes is still necessary. (Click on key symbol so it gets red.)&lt;br /&gt;
|-&lt;br /&gt;
| [https://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_cmds/Translate.html,topicNumber=si_cmds_Translate_html Translate] &amp;lt;nowiki&amp;gt;[InputObjs], [X], [Y], [Z], [Delta], [RefMode], [Center], [AxesFilter], [Snap], [SnapReference], [SnapFilter], [SplitLocalComponents], [PropTagOnly], [Pivot], [PivotX], [PivotY], [PivotZ], [ConstructionMode], [SlideComponents]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| see link&lt;br /&gt;
|-&lt;br /&gt;
| [https://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_cmds/Rotate.html,topicNumber=si_cmds_Rotate_html Rotate] &amp;lt;nowiki&amp;gt;[InputObjs], [X], [Y], [Z], [Delta], [RefMode], [Center], [AxesFilter], [Reference], [SplitLocalComponents], [PropTagOnly], [Pivot], [PivotX], [PivotY], [PivotZ], [ConstructionMode], [SlideComponents]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| see link&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Code pieces (VB Script)====&lt;br /&gt;
Remember that you can use the search function of your web browser.&lt;br /&gt;
&lt;br /&gt;
If you see absolute paths adapt them so that the code works on your system too.&lt;br /&gt;
&lt;br /&gt;
([[Mod_Tool/Scripting|Here]]&#039;s another page for math related code pieces.)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|width=33%| [1] creating and extending an array&lt;br /&gt;
|width=33%| [2] check selection mode&lt;br /&gt;
| [3] getting the IDs of selected polygons plus sorting them&lt;br /&gt;
|-&lt;br /&gt;
| [4] converting euler rotations (in degrees) to quaternions&lt;br /&gt;
| [5] converting quaternions to euler rotations (in degrees)&lt;br /&gt;
| [6] get and set values of the playcontrol (timeline)&lt;br /&gt;
|-&lt;br /&gt;
| [7] get keyframes&lt;br /&gt;
| [8] message box&lt;br /&gt;
| [9] input box&lt;br /&gt;
|-&lt;br /&gt;
| [10] getting the desktop path&lt;br /&gt;
| [11] selecting a folder&lt;br /&gt;
| [12] selecting a file of a specific type&lt;br /&gt;
|-&lt;br /&gt;
| [13] reading out environment variables&lt;br /&gt;
| [14] check if file exist&lt;br /&gt;
| [15] check if folder exist + create folder&lt;br /&gt;
|-&lt;br /&gt;
| [16] write xml file&lt;br /&gt;
| [17] read xml file&lt;br /&gt;
| [18] read xml file (attribute/content-based)&lt;br /&gt;
|-&lt;br /&gt;
| [19] create txt file + write lines&lt;br /&gt;
| [20] read txt file&lt;br /&gt;
| [21] check onisplit version&lt;br /&gt;
|-&lt;br /&gt;
| [22] call CMD, e.g. to use onisplit&lt;br /&gt;
| [23] building forms in ModTool&lt;br /&gt;
| [24] UserDataBlob&lt;br /&gt;
|-&lt;br /&gt;
| [25] getting the position of points (with selection mode point)&lt;br /&gt;
| [26] getting the position of points (with selection mode object)&lt;br /&gt;
| [27] getting and setting the position of points (without selection)&lt;br /&gt;
|-&lt;br /&gt;
| [28] getting the rotation and position of selected objects&lt;br /&gt;
| [29] getting the rotation and position of not selected objects&lt;br /&gt;
| [30] decrypting merged integer flags&lt;br /&gt;
|-&lt;br /&gt;
| [31] disabling PPG popups&lt;br /&gt;
| [32] disabling logmessages&lt;br /&gt;
| [33] getting bounding box values&lt;br /&gt;
|-&lt;br /&gt;
| [34] open an explorer window&lt;br /&gt;
| [35] working with hierarchies&lt;br /&gt;
| [36] drag and drop (DnD) support for specific oni files&lt;br /&gt;
|-&lt;br /&gt;
| [37] dae export&lt;br /&gt;
| [38] fbx export&lt;br /&gt;
| [39] import an image clip only once&lt;br /&gt;
|-&lt;br /&gt;
| [40] layers&lt;br /&gt;
| [41] onisplit update&lt;br /&gt;
| [42] get vertex color&lt;br /&gt;
|-&lt;br /&gt;
| [43] get all used textures&lt;br /&gt;
| [44] get global point position&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[1] creating and extending an array&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; creating an array&lt;br /&gt;
 &#039; () sets the number of array items&lt;br /&gt;
 redim nums (3)&lt;br /&gt;
 for i = 0 to 3&lt;br /&gt;
 	nums(i) = (i)&lt;br /&gt;
 next&lt;br /&gt;
 &lt;br /&gt;
 logmessage &amp;quot;output all items&amp;quot;&lt;br /&gt;
 for each n in nums&lt;br /&gt;
 	logmessage n&lt;br /&gt;
 next&lt;br /&gt;
 logmessage &amp;quot;first array item holds: &amp;quot; &amp;amp; lbound(nums)&lt;br /&gt;
 logmessage &amp;quot;last array item holds: &amp;quot; &amp;amp; ubound(nums)&lt;br /&gt;
 logmessage &amp;quot;-------------------------------------&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; extending an array&lt;br /&gt;
 &#039; use &amp;quot;preserve&amp;quot; to keep the old content&lt;br /&gt;
 &#039; find next higher value&lt;br /&gt;
 plus_one = ubound(nums) + 1&lt;br /&gt;
 redim preserve nums (plus_one)&lt;br /&gt;
 nums(plus_one) = 4&lt;br /&gt;
 &lt;br /&gt;
 for each n in nums&lt;br /&gt;
 	logmessage n&lt;br /&gt;
 next&lt;br /&gt;
 logmessage &amp;quot;first array item holds: &amp;quot; &amp;amp; lbound(nums)&lt;br /&gt;
 logmessage &amp;quot;last array item holds: &amp;quot; &amp;amp; ubound(nums)&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : output all items&lt;br /&gt;
 &#039; INFO : 0&lt;br /&gt;
 &#039; INFO : 1&lt;br /&gt;
 &#039; INFO : 2&lt;br /&gt;
 &#039; INFO : 3&lt;br /&gt;
 &#039; INFO : first array item holds: 0&lt;br /&gt;
 &#039; INFO : last array item holds: 3&lt;br /&gt;
 &#039; INFO : -------------------------------------&lt;br /&gt;
 &#039; INFO : 0&lt;br /&gt;
 &#039; INFO : 1&lt;br /&gt;
 &#039; INFO : 2&lt;br /&gt;
 &#039; INFO : 3&lt;br /&gt;
 &#039; INFO : 4&lt;br /&gt;
 &#039; INFO : first array item holds: 0&lt;br /&gt;
 &#039; INFO : last array item holds: 4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[2] check selection mode &#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 checkfilter&lt;br /&gt;
 &#039;use sub to make use of the exit command&lt;br /&gt;
 &lt;br /&gt;
 sub checkfilter&lt;br /&gt;
 	Select Case Selection.Filter.Name&lt;br /&gt;
 	&#039;caution: case-sensitive&lt;br /&gt;
 &lt;br /&gt;
 	Case &amp;quot;object&amp;quot;&lt;br /&gt;
 		logmessage &amp;quot;object mode&amp;quot;&lt;br /&gt;
 	Case &amp;quot;Edge&amp;quot;&lt;br /&gt;
 		logmessage &amp;quot;edge mode&amp;quot;&lt;br /&gt;
 	Case &amp;quot;Vertex&amp;quot;&lt;br /&gt;
 		logmessage &amp;quot;point mode&amp;quot;&lt;br /&gt;
 	Case &amp;quot;Polygon&amp;quot;&lt;br /&gt;
 		logmessage &amp;quot;polygon mode&amp;quot;&lt;br /&gt;
 	Case Else&lt;br /&gt;
 		logmessage &amp;quot;unknown mode&amp;quot;&lt;br /&gt;
 		exit sub&lt;br /&gt;
 	End Select&lt;br /&gt;
 end sub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[3] getting the IDs of selected polygons plus sorting them&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 poly_count = Selection(0).SubComponent.ComponentCollection.count&lt;br /&gt;
 logmessage &amp;quot;poly_count: &amp;quot; &amp;amp; poly_count&lt;br /&gt;
 redim selected (poly_count)&lt;br /&gt;
 logmessage &amp;quot;Show ID as it is.&amp;quot;&lt;br /&gt;
 for i=0 to poly_count - 1&lt;br /&gt;
 	&#039; build ID array&lt;br /&gt;
 	selected(i) = Selection(0).SubComponent.ComponentCollection(i).index&lt;br /&gt;
 	logmessage selected(i)&lt;br /&gt;
 next&lt;br /&gt;
 &lt;br /&gt;
 &#039; change sort order by replacing &amp;quot;&amp;gt;&amp;quot; with &amp;quot;&amp;lt;&amp;quot;&lt;br /&gt;
 For i = 0 To poly_count - 1&lt;br /&gt;
 	For j = 0 To poly_count - 1&lt;br /&gt;
 		If selected(i) &amp;gt; selected(j) Then&lt;br /&gt;
 			tmp = selected(i)&lt;br /&gt;
 			selected(i) = selected(j)&lt;br /&gt;
 			selected(j) = tmp&lt;br /&gt;
 		End If&lt;br /&gt;
 	Next&lt;br /&gt;
 Next&lt;br /&gt;
 logmessage &amp;quot;Show sorted ID.&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 for i=0 to poly_count - 1&lt;br /&gt;
 	logmessage selected(i)&lt;br /&gt;
 next&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[4] converting euler rotations (in degrees) to quaternions&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 dim x, y, z, dRotation, qRotation&lt;br /&gt;
 x = 90&lt;br /&gt;
 y = 0&lt;br /&gt;
 z = 0&lt;br /&gt;
 &lt;br /&gt;
 set dRotation = XSIMath.CreateRotation(XSIMath.DegreesToRadians(x), XSIMath.DegreesToRadians(y), XSIMath.DegreesToRadians(z)) &lt;br /&gt;
 set qRotation = XSIMath.CreateQuaternion() &lt;br /&gt;
 &lt;br /&gt;
 	dRotation.GetQuaternion (qRotation) &lt;br /&gt;
 	LogMessage qRotation.W&lt;br /&gt;
 	LogMessage qRotation.X&lt;br /&gt;
 	LogMessage qRotation.Y&lt;br /&gt;
 	LogMessage qRotation.Z&lt;br /&gt;
 	&#039; INFO : 0,707106781186548&lt;br /&gt;
 	&#039; INFO : 0,707106781186547&lt;br /&gt;
 	&#039; INFO : 0&lt;br /&gt;
 	&#039; INFO : 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[5] converting quaternions to euler rotations (in degrees)&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 dim qW, qX, qY, qZ, qRotation, x, y, z&lt;br /&gt;
 &lt;br /&gt;
 	qW = 0.707106781186548&lt;br /&gt;
 	qX = 0.707106781186547&lt;br /&gt;
 	qY = 0&lt;br /&gt;
 	qZ = 0&lt;br /&gt;
 &lt;br /&gt;
 set qRotation = XSIMath.CreateQuaternion (qW, qX , qY, qZ)&lt;br /&gt;
 &lt;br /&gt;
 	qRotation.GetXYZAngleValues x, y, z&lt;br /&gt;
 	logmessage XSIMath.RadiansToDegrees(x)&lt;br /&gt;
 	logmessage XSIMath.RadiansToDegrees(y)&lt;br /&gt;
 	logmessage XSIMath.RadiansToDegrees(z)&lt;br /&gt;
 	&#039; INFO : 89,9999999999999&lt;br /&gt;
 	&#039; INFO : 0&lt;br /&gt;
 	&#039; INFO : 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[6] get and set values of the playcontrol (timeline)&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; timeline variables (tl)&lt;br /&gt;
 dim tlStart, tlEnd, tlCurrent&lt;br /&gt;
 &lt;br /&gt;
 &#039; get values&lt;br /&gt;
 tlStart = GetValue (&amp;quot;PlayControl.In&amp;quot;)&lt;br /&gt;
 tlEnd = GetValue (&amp;quot;PlayControl.Out&amp;quot;)&lt;br /&gt;
 tlCurrent = GetValue (&amp;quot;PlayControl.Current&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &#039; set values&lt;br /&gt;
 SetValue (&amp;quot;PlayControl.In&amp;quot;), 7&lt;br /&gt;
 SetValue (&amp;quot;PlayControl.Out&amp;quot;), 70&lt;br /&gt;
 SetValue (&amp;quot;PlayControl.Current&amp;quot;), 14&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[7] get keyframes&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; keyframe counting code like &amp;quot;selection(0).rotx.Source.Keys.count&amp;quot; will produce an error if no keys exist&lt;br /&gt;
 &#039; that&#039;s why we need to catch possible errors for each counting&lt;br /&gt;
 &lt;br /&gt;
 on error resume next&lt;br /&gt;
 	logmessage &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;X rotation keys: &amp;quot; &amp;amp; selection(0).rotx.Source.Keys.count&lt;br /&gt;
 	for each k in selection(0).rotx.Source.Keys&lt;br /&gt;
 		logmessage &amp;quot;index: &amp;quot; &amp;amp; k.index &amp;amp; &amp;quot; // time: &amp;quot; &amp;amp; k.time &amp;amp; &amp;quot; // value: &amp;quot; &amp;amp; k.value&lt;br /&gt;
 	next&lt;br /&gt;
 if err &amp;lt;&amp;gt; 0 then&lt;br /&gt;
 	logmessage &amp;quot;no X rotation keys&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 on error goto 0&lt;br /&gt;
 &lt;br /&gt;
 on error resume next&lt;br /&gt;
 	logmessage &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;Y rotation keys: &amp;quot; &amp;amp; selection(0).roty.Source.Keys.count&lt;br /&gt;
 	for each k in selection(0).roty.Source.Keys&lt;br /&gt;
 		logmessage &amp;quot;index: &amp;quot; &amp;amp; k.index &amp;amp; &amp;quot; // time: &amp;quot; &amp;amp; k.time &amp;amp; &amp;quot; // value: &amp;quot; &amp;amp; k.value&lt;br /&gt;
 	next&lt;br /&gt;
 if err &amp;lt;&amp;gt; 0 then&lt;br /&gt;
 	logmessage &amp;quot;no Y rotation keys&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 on error goto 0&lt;br /&gt;
 &lt;br /&gt;
 on error resume next&lt;br /&gt;
 	logmessage &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;Z rotation keys: &amp;quot; &amp;amp; selection(0).rotz.Source.Keys.count&lt;br /&gt;
 	for each k in selection(0).rotz.Source.Keys&lt;br /&gt;
 		logmessage &amp;quot;index: &amp;quot; &amp;amp; k.index &amp;amp; &amp;quot; // time: &amp;quot; &amp;amp; k.time &amp;amp; &amp;quot; // value: &amp;quot; &amp;amp; k.value&lt;br /&gt;
 	next&lt;br /&gt;
 if err &amp;lt;&amp;gt; 0 then&lt;br /&gt;
 	logmessage &amp;quot;no Z rotation keys&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 on error goto 0&lt;br /&gt;
 &lt;br /&gt;
 on error resume next&lt;br /&gt;
 	logmessage &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;X position keys: &amp;quot; &amp;amp; selection(0).posx.Source.Keys.count&lt;br /&gt;
 	for each k in selection(0).posx.Source.Keys&lt;br /&gt;
 		logmessage &amp;quot;index: &amp;quot; &amp;amp; k.index &amp;amp; &amp;quot; // time: &amp;quot; &amp;amp; k.time &amp;amp; &amp;quot; // value: &amp;quot; &amp;amp; k.value&lt;br /&gt;
 	next&lt;br /&gt;
 if err &amp;lt;&amp;gt; 0 then&lt;br /&gt;
 	logmessage &amp;quot;no X position keys&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 on error goto 0&lt;br /&gt;
 &lt;br /&gt;
 on error resume next&lt;br /&gt;
 	logmessage &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;Y position keys: &amp;quot; &amp;amp; selection(0).posy.Source.Keys.count&lt;br /&gt;
 	for each k in selection(0).posy.Source.Keys&lt;br /&gt;
 		logmessage &amp;quot;index: &amp;quot; &amp;amp; k.index &amp;amp; &amp;quot; // time: &amp;quot; &amp;amp; k.time &amp;amp; &amp;quot; // value: &amp;quot; &amp;amp; k.value&lt;br /&gt;
 	next&lt;br /&gt;
 if err &amp;lt;&amp;gt; 0 then&lt;br /&gt;
 	logmessage &amp;quot;no Y position keys&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 on error goto 0&lt;br /&gt;
 &lt;br /&gt;
 on error resume next&lt;br /&gt;
 	logmessage &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;Z position keys: &amp;quot; &amp;amp; selection(0).posz.Source.Keys.count&lt;br /&gt;
 	for each k in selection(0).posz.Source.Keys&lt;br /&gt;
 		logmessage &amp;quot;index: &amp;quot; &amp;amp; k.index &amp;amp; &amp;quot; // time: &amp;quot; &amp;amp; k.time &amp;amp; &amp;quot; // value: &amp;quot; &amp;amp; k.value&lt;br /&gt;
 	next&lt;br /&gt;
 if err &amp;lt;&amp;gt; 0 then&lt;br /&gt;
 	logmessage &amp;quot;no Z position keys&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 on error goto 0&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; output example (0 rot keys, 2 pos keys):&lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : --------------------------------------------------&lt;br /&gt;
 &#039; INFO : no X rotation keys&lt;br /&gt;
 &#039; INFO : --------------------------------------------------&lt;br /&gt;
 &#039; INFO : no Y rotation keys&lt;br /&gt;
 &#039; INFO : --------------------------------------------------&lt;br /&gt;
 &#039; INFO : no Z rotation keys&lt;br /&gt;
 &#039; INFO : --------------------------------------------------&lt;br /&gt;
 &#039; INFO : X position keys: 2&lt;br /&gt;
 &#039; INFO : index: 0 // time: 2 // value: 5,14534318031942&lt;br /&gt;
 &#039; INFO : index: 1 // time: 6 // value: 8,2411504340802&lt;br /&gt;
 &#039; INFO : --------------------------------------------------&lt;br /&gt;
 &#039; INFO : Y position keys: 2&lt;br /&gt;
 &#039; INFO : index: 0 // time: 2 // value: 0,365325291829147&lt;br /&gt;
 &#039; INFO : index: 1 // time: 6 // value: 1,11923927115289&lt;br /&gt;
 &#039; INFO : --------------------------------------------------&lt;br /&gt;
 &#039; INFO : Z position keys: 2&lt;br /&gt;
 &#039; INFO : index: 0 // time: 2 // value: 1,96103417177471&lt;br /&gt;
 &#039; INFO : index: 1 // time: 6 // value: 1,88564277384233&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[8] message box&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 [https://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_om/XSIUIToolkit.MsgBox.html,topicNumber=si_om_XSIUIToolkit_MsgBox_html msgbox] &amp;quot;message&amp;quot;, , &amp;quot;title&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[9] input box&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 logmessage inputbox (&amp;quot;message&amp;quot;, &amp;quot;title&amp;quot; , &amp;quot;pre-entered content&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[10] getting the desktop path&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; this can be useful for &#039;&#039;default locations&#039;&#039; like when selecting a folder&lt;br /&gt;
 DesktopPath = CreateObject(&amp;quot;WScript.Shell&amp;quot;).SpecialFolders(&amp;quot;Desktop&amp;quot;)&lt;br /&gt;
 logmessage DesktopPath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[11] selecting a folder&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; the default path is in this case my desktop&lt;br /&gt;
 &#039; to make it work on other systems, you would need the code of &amp;quot;getting the desktop path&amp;quot; section and replace my path with the &#039;&#039;DesktopPath&#039;&#039;&lt;br /&gt;
 logmessage XSIUIToolkit.PickFolder(&amp;quot;C:\Users\RMM\Desktop\&amp;quot;, &amp;quot;title&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[12] selecting a file of a specific type&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 set oFileBrowser = XSIUIToolkit.FileBrowser&lt;br /&gt;
 oFileBrowser.DialogTitle = &amp;quot;Select an image file (png/tga/jpg)&amp;quot; &lt;br /&gt;
 &#039; (default folder)&lt;br /&gt;
 oFileBrowser.InitialDirectory = &amp;quot;c:\&amp;quot;&lt;br /&gt;
 oFileBrowser.Filter = &amp;quot;JPEG (*.jpg)|*.jpg|PNG (*.png)|*.png| Targa (*.tga)|*.tga||&amp;quot;&lt;br /&gt;
 oFileBrowser.ShowOpen&lt;br /&gt;
 If oFileBrowser.FilePathName &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
 	logmessage &amp;quot;User selected &amp;quot; &amp;amp; oFileBrowser.FilePathName&lt;br /&gt;
 Else&lt;br /&gt;
 	logmessage &amp;quot;User pressed cancel&amp;quot;&lt;br /&gt;
 End If&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[13] reading out environment variables&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; some infos about env vars: [http://web.archive.org/web/20170309190841/http://softimage.wiki.softimage.com/xsidocs/config_envirovars.htm (1)], [http://web.archive.org/web/20180416194626/http://softimage.wiki.softimage.com/xsidocs/EnvVars_SettingandUsingEnvironmentVariables.htm (2)], [http://web.archive.org/web/20170617095054/http://softimage.wiki.softimage.com/xsidocs/EnvVars_EnvironmentVariableReference.htm (3)]&lt;br /&gt;
 &#039; those variables are stored inside the setenv.bat, two disadvantages:&lt;br /&gt;
 &#039; adding or editing those vars appears to not work in vbs or I just did it wrong&lt;br /&gt;
 &#039; anyway, new vars can only be read out after app restart&lt;br /&gt;
 &#039; therefore let&#039;s concentrate on reading out existing ones and then how to create our own via txt files (example: &amp;lt;nowiki&amp;gt;https://dl.dropbox.com/u/139715/OniGalore/ModToolScript/Oni_env_vars.txt Oni_env_vars.txt&amp;lt;/nowiki&amp;gt; (dead link))&lt;br /&gt;
 &#039; code for reading out:&lt;br /&gt;
 logmessage XSIUtils.ResolvePath(&amp;quot;$SI_HOME/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[14] check if file exist&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 Set objFSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 If objFSO.FileExists (&amp;quot;C:\folder\file.txt&amp;quot;) then&lt;br /&gt;
 	logmessage &amp;quot;File exists.&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
 	logmessage &amp;quot;File doesn&#039;t exist.&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[15] check if folder exist + create folder&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 dim strDirectory&lt;br /&gt;
 strDirectory = &amp;quot;C:\test&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 Set objFSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 If objFSO.FolderExists(strDirectory) Then&lt;br /&gt;
    Set objFolder = objFSO.GetFolder(strDirectory)&lt;br /&gt;
    logmessage strDirectory &amp;amp; &amp;quot; already exists&amp;quot;&lt;br /&gt;
 Else&lt;br /&gt;
    Set objFolder = objFSO.CreateFolder(strDirectory)&lt;br /&gt;
    logmessage &amp;quot;created folder &amp;quot; &amp;amp; strDirectory&lt;br /&gt;
 End If&lt;br /&gt;
 &lt;br /&gt;
 &#039; ### or simply:&lt;br /&gt;
 dir = &amp;quot;C:\test&amp;quot;&lt;br /&gt;
 XSIUtils.EnsureFolderExists (dir)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[16] write xml file&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 FolderName = CreateObject(&amp;quot;WScript.Shell&amp;quot;).SpecialFolders(&amp;quot;Desktop&amp;quot;)&lt;br /&gt;
 FileName = &amp;quot;test&amp;quot;&lt;br /&gt;
 FilePath = FolderName &amp;amp; &amp;quot;\OBAN&amp;quot; &amp;amp; FileName &amp;amp; &amp;quot;.xml&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 Set oFS = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 Set objXMLFile = oFS.OpenTextFile(FilePath, 2, True, 0)&lt;br /&gt;
 &lt;br /&gt;
 &#039; quote sign in a string needs two quote signs&lt;br /&gt;
 objXMLFile.WriteLine &amp;quot;&amp;lt;?xml version=&amp;quot;&amp;quot;1.0&amp;quot;&amp;quot; encoding=&amp;quot;&amp;quot;utf-8&amp;quot;&amp;quot;?&amp;gt;&amp;quot;&lt;br /&gt;
 objXMLFile.WriteLine &amp;quot;&amp;lt;Oni&amp;gt;&amp;quot;&lt;br /&gt;
 objXMLFile.WriteLine &amp;quot;...&amp;quot;&lt;br /&gt;
 objXMLFile.Close&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[17] read xml file&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 Set xmlDoc = CreateObject( &amp;quot;Microsoft.XMLDOM&amp;quot; )&lt;br /&gt;
 xmlDoc.Async = &amp;quot;False&amp;quot;&lt;br /&gt;
 path = &amp;quot;C:\Users\RRM\Oni\AE\AEInstaller\vanilla\level19_Final\BINACJBOWeapon.xml&amp;quot;&lt;br /&gt;
 xmlDoc.Load( path )&lt;br /&gt;
 &lt;br /&gt;
 Set colPosition = xmlDoc.selectNodes( &amp;quot;Oni/Objects/WEAP/Header/Position&amp;quot; )&lt;br /&gt;
 Set colRotation = xmlDoc.selectNodes( &amp;quot;Oni/Objects/WEAP/Header/Rotation&amp;quot; )&lt;br /&gt;
 Set colClass =    xmlDoc.selectNodes( &amp;quot;Oni/Objects/WEAP/OSD/Class&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
 loop_count = xmlDoc.selectNodes( &amp;quot;Oni/Objects/WEAP&amp;quot;).length&lt;br /&gt;
 &lt;br /&gt;
 logmessage &amp;quot;found &amp;quot; &amp;amp; loop_count &amp;amp; &amp;quot; weapons:&amp;quot;&lt;br /&gt;
 logmessage &amp;quot;================&amp;quot;&lt;br /&gt;
 for i=0 to loop_count - 1&lt;br /&gt;
 &lt;br /&gt;
 	&#039;split string into pices as array, space is used as seperator by default&lt;br /&gt;
 	&#039;element 0 = X; element 1 = Y; element 2 = Z&lt;br /&gt;
 	pos = split(colPosition.item(i).text)&lt;br /&gt;
 	rot = split(colRotation.item(i).text)&lt;br /&gt;
 	&lt;br /&gt;
 	&#039; Mod Tool wants comma instead of point for decimal seperator&lt;br /&gt;
 	pos(0) = replace (pos(0), &amp;quot;.&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
 	pos(1) = replace (pos(1), &amp;quot;.&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
 	pos(2) = replace (pos(2), &amp;quot;.&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
 	&lt;br /&gt;
 	rot(0) = replace (rot(0), &amp;quot;.&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
 	rot(1) = replace (rot(1), &amp;quot;.&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
 	rot(2) = replace (rot(2), &amp;quot;.&amp;quot;, &amp;quot;,&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 	logmessage colClass.item(i).text&lt;br /&gt;
 	logmessage pos(0) &amp;amp; &amp;quot; &amp;quot; &amp;amp; pos(1) &amp;amp; &amp;quot; &amp;quot; &amp;amp; pos(2)&lt;br /&gt;
 	logmessage rot(0) &amp;amp; &amp;quot; &amp;quot; &amp;amp; rot(1) &amp;amp; &amp;quot; &amp;quot; &amp;amp; rot(2)&lt;br /&gt;
 	logmessage &amp;quot;----------------&amp;quot;&lt;br /&gt;
 next&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : found 2 weapons:&lt;br /&gt;
 &#039; INFO : ================&lt;br /&gt;
 &#039; INFO : w5_sbg&lt;br /&gt;
 &#039; INFO : 23,16747 84,8193359 757,1958&lt;br /&gt;
 &#039; INFO : 0 0 0&lt;br /&gt;
 &#039; INFO : ----------------&lt;br /&gt;
 &#039; INFO : w4_psm&lt;br /&gt;
 &#039; INFO : 18,1105652 84,8193359 749,121&lt;br /&gt;
 &#039; INFO : 0 0 0&lt;br /&gt;
 &#039; INFO : ----------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[18] read xml file (attribute/content-based)&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 Set xmlDoc = CreateObject( &amp;quot;Microsoft.XMLDOM&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
 &#039; tells the program to wait until the file was loaded conpletely&lt;br /&gt;
 xmlDoc.Async = &amp;quot;False&amp;quot;&lt;br /&gt;
 xmlDoc.Load( &amp;quot;C:\Users\RRM\Oni\AE\AEInstaller\vanilla\level0_Final\BINAEINOimpact_effects.xml&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; example 1 (&#039;&#039;&#039;we use this one&#039;&#039;&#039;)&lt;br /&gt;
 &#039; nodes only with a certain attribute and conent will be collected&lt;br /&gt;
 &lt;br /&gt;
 &#039; content-based search: node [child_node = &#039;content&#039;]&lt;br /&gt;
 &#039; attribute-based search: node [@attribute_name = &#039;attribute_value&#039;]&lt;br /&gt;
 &lt;br /&gt;
 &#039; if things get too long an underscore _ can be used to make a linebreak&lt;br /&gt;
 &#039;&#039;&#039;set w1_tap = xmlDoc.selectNodes _&#039;&#039;&#039;&lt;br /&gt;
 	&#039;&#039;&#039;( &amp;quot;Oni/ImpactEffects/Impact[@Name = &#039;w1_tap&#039;]/Material[@Name = &#039;Unbreak_Glass&#039;]/ImpactEffect [Component = &#039;Damage&#039;]&amp;quot; )&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; example 2&lt;br /&gt;
 &#039; use &amp;quot;or&amp;quot; for a search of various material&lt;br /&gt;
 &#039;set w1_tap = xmlDoc.selectNodes _&lt;br /&gt;
 &#039;	( &amp;quot;Oni/ImpactEffects/Impact/Material[@Name = &#039;Default&#039; or @Name = &#039;Character&#039;]/ImpactEffect&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; example 3&lt;br /&gt;
 &#039; use (|) for a search of various content, e.g. &#039;&#039;&amp;lt;ImpactEffect&amp;gt;&amp;lt;Modifier&amp;gt;Light&#039;&#039; plus &#039;&#039;&amp;lt;ImpactEffect&amp;gt;&amp;lt;Modifier&amp;gt;Medium&#039;&#039;&lt;br /&gt;
 &#039;set w1_tap = xmlDoc.selectNodes _&lt;br /&gt;
 &#039;	( &amp;quot;Oni/ImpactEffects/Impact/Material/(ImpactEffect [Modifier = &#039;Light&#039;] | ImpactEffect [Modifier = &#039;Medium&#039;])&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 for each element in w1_tap&lt;br /&gt;
 	logmessage &amp;quot;Impact: &amp;quot; &amp;amp; element.parentNode.parentNode.getAttribute(&amp;quot;Name&amp;quot;)&lt;br /&gt;
 	logmessage &amp;quot;Material: &amp;quot; &amp;amp; element.parentNode.getAttribute(&amp;quot;Name&amp;quot;)&lt;br /&gt;
 	&lt;br /&gt;
 	&#039; outputs &amp;quot;tag name: tag content&amp;quot;&lt;br /&gt;
 	logmessage element.childNodes(0).nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; element.childNodes(0).text&lt;br /&gt;
 	logmessage element.childNodes(1).nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; element.childNodes(1).text&lt;br /&gt;
 	logmessage &amp;quot;-----------------------------------&amp;quot;&lt;br /&gt;
 	&lt;br /&gt;
 	&#039;check for sounds&lt;br /&gt;
 	if element.childNodes(2).childNodes.length = 0 then&lt;br /&gt;
 		logmessage &amp;quot;sound not present&amp;quot;&lt;br /&gt;
 	else&lt;br /&gt;
 		logmessage &amp;quot;sound is present&amp;quot;&lt;br /&gt;
 		logmessage &amp;quot;-----------------------------------&amp;quot;&lt;br /&gt;
 		logmessage element.childNodes(2).childNodes(0).nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; element.childNodes(2).childNodes(0).text&lt;br /&gt;
 		logmessage element.childNodes(2).childNodes(1).nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; element.childNodes(2).childNodes(1).text&lt;br /&gt;
 		logmessage element.childNodes(2).childNodes(2).nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; element.childNodes(2).childNodes(2).text&lt;br /&gt;
 		logmessage element.childNodes(2).childNodes(3).nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; element.childNodes(2).childNodes(3).text&lt;br /&gt;
 	end if&lt;br /&gt;
 	logmessage &amp;quot;-----------------------------------&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 	&#039; check for particle&lt;br /&gt;
 	if element.childNodes(3).childNodes.length = 0 then&lt;br /&gt;
  		logmessage &amp;quot;no particle present&amp;quot;&lt;br /&gt;
 	else&lt;br /&gt;
 		logmessage &amp;quot;number of particle: &amp;quot; &amp;amp; element.childNodes(3).childNodes.length&lt;br /&gt;
 		for each particle_section in element.childNodes(3).childNodes&lt;br /&gt;
 			logmessage &amp;quot;-----------------------------------&amp;quot;&lt;br /&gt;
 			for each particle_tag in particle_section.childnodes&lt;br /&gt;
 				logmessage particle_tag.nodename &amp;amp; &amp;quot;: &amp;quot; &amp;amp; particle_tag.text&lt;br /&gt;
 			next		&lt;br /&gt;
 		next	&lt;br /&gt;
 	end if&lt;br /&gt;
 	logmessage &amp;quot;===================================&amp;quot;&lt;br /&gt;
 next&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : Impact: w1_tap&lt;br /&gt;
 &#039; INFO : Material: Unbreak_Glass&lt;br /&gt;
 &#039; INFO : Component: Damage&lt;br /&gt;
 &#039; INFO : Modifier: Any&lt;br /&gt;
 &#039; INFO : -----------------------------------&lt;br /&gt;
 &#039; INFO : sound not present&lt;br /&gt;
 &#039; INFO : -----------------------------------&lt;br /&gt;
 &#039; INFO : number of particle: 2&lt;br /&gt;
 &#039; INFO : -----------------------------------&lt;br /&gt;
 &#039; INFO : Name: d__GLASSCRACK&lt;br /&gt;
 &#039; INFO : Orientation: 0&lt;br /&gt;
 &#039; INFO : Location: 4&lt;br /&gt;
 &#039; INFO : Decal1: false&lt;br /&gt;
 &#039; INFO : Decal2: true&lt;br /&gt;
 &#039; INFO : -----------------------------------&lt;br /&gt;
 &#039; INFO : Name: w1_tap_x03&lt;br /&gt;
 &#039; INFO : Orientation: 0&lt;br /&gt;
 &#039; INFO : Location: 1&lt;br /&gt;
 &#039; INFO : Offset: -1&lt;br /&gt;
 &#039; INFO : ===================================&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[] remove xml nodes&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Set objXMLDoc = CreateObject(&amp;quot;Microsoft.XMLDOM&amp;quot;) &lt;br /&gt;
 objXMLDoc.async = False &lt;br /&gt;
 &lt;br /&gt;
 Dim XMLFile&lt;br /&gt;
 XMLFile = &amp;quot;C:\Softimage\Softimage_Mod_Tool_7.5\OniLevels\ONLV\test\ONLVAirport.xml&amp;quot;&lt;br /&gt;
 objXMLDoc.load(XMLFile) &lt;br /&gt;
 Set nodes = objXMLDoc.selectNodes(&amp;quot;Oni/CRSA/*&amp;quot;)&lt;br /&gt;
 For Each node In nodes&lt;br /&gt;
     node.parentNode.removeChild(node)&lt;br /&gt;
 Next&lt;br /&gt;
 &lt;br /&gt;
 objXMLDoc.Save(XMLFile)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[19] create txt file + write lines&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 txt_location = &amp;quot;C:\Softimage\Softimage_Mod_Tool_7.5\test.txt&amp;quot;&lt;br /&gt;
 Set fso = CreateObject (&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 Set wText = fso.CreateTextFile (txt_location, 1)&lt;br /&gt;
 wText.WriteLine &amp;quot;I&#039;m a test file.&amp;quot;&lt;br /&gt;
 wText.WriteLine &amp;quot;Yo!&amp;quot;&lt;br /&gt;
 wText.Close&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[20] read txt file&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 Set objFileToRead = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;).OpenTextFile(&amp;quot;C:\Softimage\Softimage_Mod_Tool_7.5\test.txt&amp;quot;, 1)&lt;br /&gt;
 &lt;br /&gt;
 do while not objFileToRead.AtEndOfStream&lt;br /&gt;
     strLine = objFileToRead.ReadLine()&lt;br /&gt;
     logmessage strLine&lt;br /&gt;
 loop&lt;br /&gt;
 &#039; INFO : I&#039;m a test file.&lt;br /&gt;
 &#039; INFO : Yo!&lt;br /&gt;
 &lt;br /&gt;
 objFileToRead.Close&lt;br /&gt;
 Set objFileToRead = Nothing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[21] check onisplit version&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 Set objFSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 logmessage objFSO.GetFileVersion(&amp;quot;F:\Program Files (x86)\Oni\Edition\install\onisplit.exe&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &#039; result looks like this:&lt;br /&gt;
 &#039; INFO : 0.9.59.0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[22] call CMD, e.g. to lunch onisplit or the game&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; relative path&lt;br /&gt;
 &lt;br /&gt;
 &#039; the &amp;quot;GameDataFolder&amp;quot; isn&#039;t inside the &amp;quot;install&amp;quot; folder&lt;br /&gt;
 &#039; so we will use ..\ to go one folder backwards&lt;br /&gt;
 &lt;br /&gt;
 &#039; additional quote signs tells the program where the &lt;br /&gt;
 &#039; paths strings start and end in case the path contains spaces&lt;br /&gt;
 &lt;br /&gt;
 &#039; if you are going to use the xml file right after its extraction (which is likely)&lt;br /&gt;
 &#039; then the &amp;quot;/wait&amp;quot; argument inside the onisplit_action string is important&lt;br /&gt;
 &#039; without it the code would continue and might try to read the not existing xml file and produce an error&lt;br /&gt;
 &lt;br /&gt;
 onisplit_location = &amp;quot;F:\Program Files (x86)\Oni\Edition\install&amp;quot;&lt;br /&gt;
 input_folder = &amp;quot;&amp;quot;&amp;quot;..\GameDataFolder\level19_Final\ONLVcompound.oni&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 output_folder = &amp;quot;&amp;quot;&amp;quot;..\GameDataFolder&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 onisplit_action = &amp;quot;cmd /C start /wait OniSplit.exe -extract:xml &amp;quot; &amp;amp; output_folder &amp;amp; &amp;quot; &amp;quot; &amp;amp; input_folder&lt;br /&gt;
 logmessage &amp;quot;relative path: &amp;quot; &amp;amp; onisplit_action&lt;br /&gt;
 &#039; expected logmessage:&lt;br /&gt;
 &#039; INFO : relative path: cmd /C start OniSplit.exe -extract:xml &amp;quot;..\GameDataFolder&amp;quot; &amp;quot;..\GameDataFolder\level19_Final\ONLVcompound.oni&amp;quot;&lt;br /&gt;
 XSIUtils.LaunchProcess onisplit_action, 1, onisplit_location&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; absolute path&lt;br /&gt;
 &lt;br /&gt;
 &#039;adapt paths so it works on your computer&lt;br /&gt;
 onisplit_location = &amp;quot;F:\Program Files (x86)\Oni\Edition\install&amp;quot;&lt;br /&gt;
 input_folder = &amp;quot;&amp;quot;&amp;quot;F:\Program Files (x86)\Oni\Edition\GameDataFolder\level19_Final\ONLVcompound.oni&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 output_folder = &amp;quot;&amp;quot;&amp;quot;F:\Program Files (x86)\Oni\Edition\GameDataFolder&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 onisplit_action = &amp;quot;cmd /C start /wait OniSplit.exe -extract:xml &amp;quot; &amp;amp; output_folder &amp;amp; &amp;quot; &amp;quot; &amp;amp; input_folder&lt;br /&gt;
 logmessage &amp;quot;absolute path: &amp;quot; &amp;amp; onisplit_action&lt;br /&gt;
 &#039; expected logmessage:&lt;br /&gt;
 &#039; &amp;lt;small&amp;gt;INFO : absolute path: cmd /C start OniSplit.exe -extract:xml &amp;quot;F:\Program Files (x86)\Oni\Edition\GameDataFolder&amp;quot; &amp;quot;F:\Program Files (x86)\Oni\Edition\GameDataFolder\level19_Final\ONLVcompound.oni&amp;quot;&amp;lt;/small&amp;gt;&lt;br /&gt;
 XSIUtils.LaunchProcess onisplit_action, 1, onisplit_location&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &#039; you can also lunch bat files&lt;br /&gt;
 &lt;br /&gt;
 onibat = &amp;quot;cmd /C start run_wind.bat&amp;quot;&lt;br /&gt;
 onilocation = &amp;quot;F:\Program Files (x86)\Oni\Edition&amp;quot;&lt;br /&gt;
 XSIUtils.LaunchProcess onibat, 0, onilocation&lt;br /&gt;
&lt;br /&gt;
 &#039; alternative to cmd: call onisplit via winmgmts&lt;br /&gt;
 &lt;br /&gt;
 &#039; slightly modified code from [https://devblogs.microsoft.com/scripting/how-can-i-start-a-process-and-then-wait-for-the-process-to-end-before-terminating-the-script/ that site]&lt;br /&gt;
 &#039; &#039;&#039;logmessage &amp;quot;onisplit finished.&amp;quot;&#039;&#039; will be executed after the conversion finished, there should be also an delay of 3 seconds to support very slow computers &lt;br /&gt;
 &#039; if you are going to use this method consider to extent the code to check if input file and output directory exist&lt;br /&gt;
 osp_loca = &amp;quot;C:\OniAE\Edition\install\OniSplit.exe&amp;quot;&lt;br /&gt;
 osp_action = &amp;quot;-extract:xml&amp;quot;&lt;br /&gt;
 osp_output = &amp;quot;&amp;quot;&amp;quot;C:\OniAE\Edition\GameDataFolder&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 osp_input = &amp;quot;&amp;quot;&amp;quot;C:\OniAE\Edition\GameDataFolder\level1_Final\AKEVEnvWarehouse.oni&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 osp_total = osp_loca &amp;amp; &amp;quot; &amp;quot; &amp;amp; osp_action &amp;amp; &amp;quot; &amp;quot; &amp;amp; osp_output &amp;amp; &amp;quot; &amp;quot; &amp;amp; osp_input&lt;br /&gt;
 logmessage osp_total&lt;br /&gt;
 &lt;br /&gt;
 strComputer = &amp;quot;.&amp;quot;&lt;br /&gt;
 Set objWMIService = GetObject(&amp;quot;winmgmts:\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2:Win32_Process&amp;quot;)&lt;br /&gt;
 objWMIService.Create osp_total, null, null, intProcessID&lt;br /&gt;
 Set objWMIService = GetObject(&amp;quot;winmgmts:\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &#039; wait 3 second to find event - should be enough time for single actions on a slow computer&lt;br /&gt;
 Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _&lt;br /&gt;
     (&amp;quot;Select * From __InstanceDeletionEvent Within 3 Where TargetInstance ISA &#039;Win32_Process&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 Do Until i = 1&lt;br /&gt;
     Set objLatestProcess = colMonitoredProcesses.NextEvent&lt;br /&gt;
     If objLatestProcess.TargetInstance.ProcessID = intProcessID Then&lt;br /&gt;
         i = 1&lt;br /&gt;
     End If&lt;br /&gt;
 Loop&lt;br /&gt;
 logmessage &amp;quot;onisplit finished.&amp;quot;&lt;br /&gt;
 &#039; now you can work with the extracted xml file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:XSI_Mod_Tool_PPG.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[23] building a form (PPG)&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 dim oPSet, oPPGLayout, oItem, PPG_exist&lt;br /&gt;
 &lt;br /&gt;
 &#039; set check value to 0&lt;br /&gt;
 PPG_exist = 0&lt;br /&gt;
 &lt;br /&gt;
 &#039; check if PPG exists&lt;br /&gt;
 for each prop in ActiveProject.ActiveScene.Root.Properties&lt;br /&gt;
 	logmessage prop.name&lt;br /&gt;
 	if instr(1, prop.name, &amp;quot;my_new_PPG&amp;quot;) &amp;gt; 0 then&lt;br /&gt;
 		PPG_exist = 1&lt;br /&gt;
 		logmessage &amp;quot;found &amp;quot; &amp;amp; &amp;quot;&amp;quot;&amp;quot;&amp;quot; &amp;amp; prop.name &amp;amp; &amp;quot;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 	end if&lt;br /&gt;
 next&lt;br /&gt;
 &lt;br /&gt;
 &#039; create PPG if it doesn&#039;t exist&lt;br /&gt;
 if PPG_exist = 0 then&lt;br /&gt;
 	set oPSet = ActiveSceneRoot.AddProperty(&amp;quot;CustomProperty&amp;quot;, false, &amp;quot;my_new_PPG&amp;quot;)&lt;br /&gt;
 	set oPPGLayout = oPSet.PPGLayout&lt;br /&gt;
 	&lt;br /&gt;
 	&#039; setup PPG parameters&lt;br /&gt;
 	&#039; ###################################################################################&lt;br /&gt;
 	&#039; create checkbox and remove key symboles by setting parameter &amp;quot;Animatable&amp;quot; to false&lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;Check1&amp;quot;, siBool, 0, , , false&lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;Check2&amp;quot;, siBool, 0, , , false&lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;Check3&amp;quot;, siBool, 1, , , false&lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;Check4&amp;quot;, siBool, 1, , , false&lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;text1&amp;quot;, siString&lt;br /&gt;
 	&#039; last parameter of &amp;quot;int1&amp;quot; is set to ReadOnly&lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;int1&amp;quot;, siInt2, , , , false, 1 &lt;br /&gt;
 	oPSet.AddParameter3 &amp;quot;int2&amp;quot;, siInt2, , , , false, 0&lt;br /&gt;
 	&lt;br /&gt;
 	&#039; add PPG items&lt;br /&gt;
 	&#039; ###################################################################################&lt;br /&gt;
 	oPPGLayout.AddItem &amp;quot;text1&amp;quot;, &amp;quot;Hi there!&amp;quot;&lt;br /&gt;
 	oPPGLayout.AddItem &amp;quot;int1&amp;quot;, &amp;quot;number 1&amp;quot;&lt;br /&gt;
 	oPPGLayout.AddItem &amp;quot;int2&amp;quot;, &amp;quot;number 2&amp;quot;&lt;br /&gt;
 	oPPGLayout.AddGroup &amp;quot;4 checkboxes&amp;quot;, true&lt;br /&gt;
 	oPPGLayout.AddRow&lt;br /&gt;
 		oPPGLayout.AddItem &amp;quot;Check1&amp;quot;, &amp;quot;C1&amp;quot;&lt;br /&gt;
 		oPPGLayout.AddItem &amp;quot;Check3&amp;quot;, &amp;quot;C3&amp;quot;&lt;br /&gt;
 	oPPGLayout.EndRow&lt;br /&gt;
 	oPPGLayout.AddRow&lt;br /&gt;
 		oPPGLayout.AddItem &amp;quot;Check2&amp;quot;, &amp;quot;C2&amp;quot;&lt;br /&gt;
 		oPPGLayout.AddItem &amp;quot;Check4&amp;quot;, &amp;quot;C4&amp;quot;&lt;br /&gt;
 	oPPGLayout.EndRow&lt;br /&gt;
 	oPPGLayout.EndGroup&lt;br /&gt;
 	&lt;br /&gt;
 	oPPGLayout.AddButton(&amp;quot;log_values&amp;quot;, &amp;quot;log PPG values&amp;quot;).setAttribute siUICX, 120&lt;br /&gt;
 	&lt;br /&gt;
 	oPPGLayout.Logic = &amp;quot;sub log_values_OnClicked&amp;quot; &amp;amp; vbCrlf &amp;amp; _&lt;br /&gt;
 	&amp;quot;		logmessage &amp;quot;&amp;quot;text 1 = &amp;quot;&amp;quot; &amp;amp; getvalue(&amp;quot;&amp;quot;my_new_PPG.text1&amp;quot;&amp;quot;)&amp;quot; &amp;amp; vbCrlf &amp;amp; _&lt;br /&gt;
 	&amp;quot;		logmessage &amp;quot;&amp;quot;number 1 = &amp;quot;&amp;quot; &amp;amp; getvalue(&amp;quot;&amp;quot;my_new_PPG.int1&amp;quot;&amp;quot;)&amp;quot; &amp;amp; vbCrlf &amp;amp; _&lt;br /&gt;
 	&amp;quot;		logmessage &amp;quot;&amp;quot;C1 = &amp;quot;&amp;quot; &amp;amp; getvalue(&amp;quot;&amp;quot;my_new_PPG.Check1&amp;quot;&amp;quot;)&amp;quot; &amp;amp; vbCrlf &amp;amp; _&lt;br /&gt;
 	&amp;quot;	end sub&amp;quot;&lt;br /&gt;
 	&lt;br /&gt;
 	oPPGLayout.Language = &amp;quot;VBScript&amp;quot; &#039;Optional because this is the default&lt;br /&gt;
 &lt;br /&gt;
 	&#039; open PPG&lt;br /&gt;
 	InspectObj oPSet		&lt;br /&gt;
 else&lt;br /&gt;
 	&#039; open that PPG if it already exist&lt;br /&gt;
 	InspectObj &amp;quot;my_new_PPG&amp;quot;&lt;br /&gt;
 end if &lt;br /&gt;
&lt;br /&gt;
 &#039; set values from outside the PPG&lt;br /&gt;
 setvalue &amp;quot;my_new_PPG.text1&amp;quot;, &amp;quot;any text could stand here&amp;quot;&lt;br /&gt;
 setvalue &amp;quot;my_new_PPG.int1&amp;quot;, &amp;quot;42&amp;quot;&lt;br /&gt;
 setvalue &amp;quot;my_new_PPG.check1&amp;quot;, true&lt;br /&gt;
 &lt;br /&gt;
 &#039; get values from outside the PPG&lt;br /&gt;
 logmessage getvalue(&amp;quot;my_new_PPG.text1&amp;quot;)&lt;br /&gt;
 logmessage getvalue(&amp;quot;my_new_PPG.int1&amp;quot;)&lt;br /&gt;
 logmessage getvalue(&amp;quot;my_new_PPG.check1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:XSI_Mod_Tool_UserDataBlob.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[24] UserDataBlob&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; you can attach data to objects, e.g. new properties for the scene root or Oni Trigger Volumes&lt;br /&gt;
 &#039; the so-called &amp;quot;UserDataBlob&amp;quot; can&#039;t be saved in *.dae, so save the whole scene to keep your progress&lt;br /&gt;
 &lt;br /&gt;
 &#039; check if my property exist&lt;br /&gt;
 found_my_prop = 0&lt;br /&gt;
 set oProps = ActiveProject.ActiveScene.Root&lt;br /&gt;
 logmessage &amp;quot;root name: &amp;quot; &amp;amp; ActiveProject.ActiveScene.Root&lt;br /&gt;
 for each prop in oProps.Properties&lt;br /&gt;
 	&#039; remove apostroph in line beneath to log all root properties&lt;br /&gt;
  	&#039;LogMessage prop.Name&lt;br /&gt;
 	if instr(1, prop.Name, &amp;quot;my_prop&amp;quot;) = 1 then&lt;br /&gt;
 		found_my_prop = 1&lt;br /&gt;
 	end if&lt;br /&gt;
 next&lt;br /&gt;
 &lt;br /&gt;
 &#039; prop doesn&#039;t exist, create it&lt;br /&gt;
 if found_my_prop = 0 then&lt;br /&gt;
 	&#039; create property (must also have content, in this case &amp;quot;yes&amp;quot;)&lt;br /&gt;
 	oProps.AddProperty( &amp;quot;UserDataBlob&amp;quot;, , &amp;quot;my_prop&amp;quot; ).value = &amp;quot;yes&amp;quot;&lt;br /&gt;
 	logmessage &amp;quot;created my new prop&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 &lt;br /&gt;
 &#039; prop exists, change/read its value&lt;br /&gt;
 if found_my_prop = 1 then&lt;br /&gt;
 	&#039; change property&lt;br /&gt;
 	oProps.Properties( &amp;quot;my_prop&amp;quot; ).value = &amp;quot;no&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 	&#039; read property&lt;br /&gt;
 	logmessage oProps.Properties( &amp;quot;my_prop&amp;quot; ).value&lt;br /&gt;
 	&#039; if you want to read a property from another script be sure that it was already created&lt;br /&gt;
 	&#039; reuse code under &amp;quot;check if my property exist&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[25] getting the position of points (with selection mode point)&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; a point must be selected&lt;br /&gt;
 &#039; gets xyz position of first selected point of the first selected object&lt;br /&gt;
 logmessage Selection(0).SubComponent.ComponentCollection(0).position.x&lt;br /&gt;
 logmessage Selection(0).SubComponent.ComponentCollection(0).position.y&lt;br /&gt;
 logmessage Selection(0).SubComponent.ComponentCollection(0).position.z&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[26] getting the position of points (with selection mode object)&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; an object must be selected&lt;br /&gt;
 &#039; gets xyz position of point 0 of the first selected object&lt;br /&gt;
 logmessage selection(0).activeprimitive.geometry.Points(0).Position.x&lt;br /&gt;
 logmessage selection(0).activeprimitive.geometry.Points(0).Position.y&lt;br /&gt;
 logmessage selection(0).activeprimitive.geometry.Points(0).Position.z&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[27] getting and setting the position of points (without selection) right after object creation&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; point positions are relative to the object&#039;s center&lt;br /&gt;
 &#039; to get the absolute point positions add center to point&lt;br /&gt;
 &#039; to set the absolute point positions subtract center from point&lt;br /&gt;
 &lt;br /&gt;
 set oRoot = application.activeproject.activescene.root&lt;br /&gt;
 set oObj = oRoot.addgeometry( &amp;quot;Cube&amp;quot;, &amp;quot;MeshSurface&amp;quot;, &amp;quot;test&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
 &#039; to test our code move center to somewhere else&lt;br /&gt;
 Translate oObj, 9, 11, 13, siRelative, siGlobal, siCtr, siXYZ, , , , , , , , , , 0&lt;br /&gt;
 SaveKey oObj &amp;amp; &amp;quot;.kine.local.posx,&amp;quot; &amp;amp; oObj &amp;amp; &amp;quot;.kine.local.posy,&amp;quot; &amp;amp; oObj &amp;amp; &amp;quot;.kine.local.posz&amp;quot;, 1, , , , True&lt;br /&gt;
 &lt;br /&gt;
 FreezeObj oObj&lt;br /&gt;
 set oGeometry = oObj.activeprimitive.geometry&lt;br /&gt;
 aPositions = oGeometry.Points.PositionArray&lt;br /&gt;
 &#039; get old position&lt;br /&gt;
 &#039;                                         (xyz, point)&lt;br /&gt;
 logmessage &amp;quot;old point 0 posx: &amp;quot; &amp;amp; aPositions(0, 0) + GetValue(oObj &amp;amp; &amp;quot;.kine.global.posx&amp;quot;)&lt;br /&gt;
 logmessage &amp;quot;old point 0 posy: &amp;quot; &amp;amp; aPositions(1, 0) + GetValue(oObj &amp;amp; &amp;quot;.kine.global.posy&amp;quot;)&lt;br /&gt;
 logmessage &amp;quot;old point 0 posz: &amp;quot; &amp;amp; aPositions(2, 0) + GetValue(oObj &amp;amp; &amp;quot;.kine.global.posz&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &#039; set new position&lt;br /&gt;
 aPositions(0, 0) = -7 - GetValue(oObj &amp;amp; &amp;quot;.kine.global.posx&amp;quot;)&lt;br /&gt;
 aPositions(1, 0) = -7 - GetValue(oObj &amp;amp; &amp;quot;.kine.global.posy&amp;quot;)&lt;br /&gt;
 aPositions(2, 0) = -7 - GetValue(oObj &amp;amp; &amp;quot;.kine.global.posz&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &#039; update the array&lt;br /&gt;
 oGeometry.Points.PositionArray = aPositions&lt;br /&gt;
 &#039; get new position&lt;br /&gt;
 logmessage &amp;quot;new point 0 posx: &amp;quot; &amp;amp; aPositions(0, 0) + GetValue(oObj &amp;amp; &amp;quot;.kine.global.posx&amp;quot;)&lt;br /&gt;
 logmessage &amp;quot;new point 0 posy: &amp;quot; &amp;amp; aPositions(1, 0) + GetValue(oObj &amp;amp; &amp;quot;.kine.global.posy&amp;quot;)&lt;br /&gt;
 logmessage &amp;quot;new point 0 posz: &amp;quot; &amp;amp; aPositions(2, 0) + GetValue(oObj &amp;amp; &amp;quot;.kine.global.posz&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : old point 0 posx: -4&lt;br /&gt;
 &#039; INFO : old point 0 posy: -4&lt;br /&gt;
 &#039; INFO : old point 0 posz: -4&lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : new point 0 posx: -7&lt;br /&gt;
 &#039; INFO : new point 0 posy: -7&lt;br /&gt;
 &#039; INFO : new point 0 posz: -7&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[28] getting the scaling, rotation and position of selected objects&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 logmessage &amp;quot;mesh name: &amp;quot; &amp;amp; selection(0)&lt;br /&gt;
 logmessage selection(0).sclx.value&lt;br /&gt;
 logmessage selection(0).scly.value&lt;br /&gt;
 logmessage selection(0).sclz.value&lt;br /&gt;
 logmessage selection(0).rotx.value&lt;br /&gt;
 logmessage selection(0).roty.value&lt;br /&gt;
 logmessage selection(0).rotz.value&lt;br /&gt;
 logmessage selection(0).posx.value&lt;br /&gt;
 logmessage selection(0).posy.value&lt;br /&gt;
 logmessage selection(0).posz.value&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[29] getting the scaling, rotation, and position of not selected objects&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; GetValue(&amp;quot;NAME.kine.global.rotx&amp;quot;)&lt;br /&gt;
 &#039; NAME must be the exact mesh name&lt;br /&gt;
 &#039; let&#039;s say you want the data of one character&#039;s pelvis&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.sclx&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.scly&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.sclz&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.rotx&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.roty&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.rotz&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.posx&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.posy&amp;quot;)&lt;br /&gt;
 logmessage GetValue(&amp;quot;pelvis.kine.global.posz&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[30] decrypting merged integer flags&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; for example the [[XML:BINA/OBJC/TRGV|BINACJBOTrigger Volume.xml]] file has flags as strings for the &amp;lt;Flags&amp;gt; tag&lt;br /&gt;
 &#039; and integer values for the &amp;lt;Teams&amp;gt; tag whereby the values are merged to one value&lt;br /&gt;
 &#039; so if &amp;lt;Teams&amp;gt; tag holds &amp;quot;101&amp;quot; we have to think what flags it holds, the flags can be broken down with following code&lt;br /&gt;
 &lt;br /&gt;
 &#039; x: hypothetical value of &amp;lt;Teams&amp;gt;&lt;br /&gt;
 x=101&lt;br /&gt;
 &#039; 101 = 64 + 32 + 4 + 1&lt;br /&gt;
 &lt;br /&gt;
 x_255&lt;br /&gt;
 sub x_255&lt;br /&gt;
 	if x &amp;gt; 255 then&lt;br /&gt;
 		msgbox &amp;quot;Flags bigger than 255 are not allowed.&amp;quot;, ,&amp;quot;error&amp;quot;&lt;br /&gt;
 		exit sub&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 128 and x &amp;lt;= 255 then&lt;br /&gt;
 		logmessage &amp;quot;128&amp;quot;&lt;br /&gt;
 		x = x - 128&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 64 and x &amp;lt; 128 then&lt;br /&gt;
 		logmessage &amp;quot;64&amp;quot;&lt;br /&gt;
 		x = x - 64&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 32 and x &amp;lt; 64 then&lt;br /&gt;
 		logmessage &amp;quot;32&amp;quot;&lt;br /&gt;
 		x = x - 32&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 16 and x &amp;lt; 32 then&lt;br /&gt;
 		logmessage &amp;quot;16&amp;quot;&lt;br /&gt;
 		x = x - 16&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 8 and x &amp;lt; 16 then&lt;br /&gt;
 		logmessage &amp;quot;8&amp;quot;&lt;br /&gt;
 		x = x - 8&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 4 and x &amp;lt; 8 then&lt;br /&gt;
 		logmessage &amp;quot;4&amp;quot;&lt;br /&gt;
 		x = x - 4&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x &amp;gt;= 2 and x &amp;lt; 4 then&lt;br /&gt;
 		logmessage &amp;quot;2&amp;quot;&lt;br /&gt;
 		x = x - 2&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x = 2 then&lt;br /&gt;
 		logmessage &amp;quot;2&amp;quot;&lt;br /&gt;
 		x = x - 2&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x = 1 then&lt;br /&gt;
 		logmessage &amp;quot;1&amp;quot;&lt;br /&gt;
 		x = x - 1&lt;br /&gt;
 	end if&lt;br /&gt;
 	if x = 0 then&lt;br /&gt;
 		logmessage &amp;quot;finished check&amp;quot;&lt;br /&gt;
 	end if&lt;br /&gt;
 end sub&lt;br /&gt;
 &lt;br /&gt;
 &#039; INFO : 64&lt;br /&gt;
 &#039; INFO : 32&lt;br /&gt;
 &#039; INFO : 4&lt;br /&gt;
 &#039; INFO : 1&lt;br /&gt;
 &#039; INFO : finished check&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[31] disabling PPG popups&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; for example if code of a script button creates numerous objects in one go, the same number of property pages (PPG) can appear&lt;br /&gt;
 &#039; for user convenience those PPG popups can be disabled&lt;br /&gt;
 &lt;br /&gt;
 &#039; disable PPG popup&lt;br /&gt;
 Preferences.SetPreferenceValue &amp;quot;Interaction.autoinspect&amp;quot;, false&lt;br /&gt;
 &lt;br /&gt;
 &#039; creates the cube mesh but no PPG will show up&lt;br /&gt;
 CreatePrim &amp;quot;Cube&amp;quot;, &amp;quot;MeshSurface&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &#039; enable PPG popup again&lt;br /&gt;
 Preferences.SetPreferenceValue &amp;quot;Interaction.autoinspect&amp;quot;, true&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[32] disabling logmessages&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; msglogverbos is probably already set to false by default&lt;br /&gt;
 &#039; could be set at the start of a final script to increase performance&lt;br /&gt;
 setvalue &amp;quot;preferences.scripting.msglogverbose&amp;quot;, false&lt;br /&gt;
 setvalue &amp;quot;preferences.scripting.msglog&amp;quot;, false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[33] getting bounding box values&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; this could be useful to create a bounding box for [[XML:OFGA|OFGA files]]&lt;br /&gt;
 &lt;br /&gt;
 &#039; let&#039;s get the bounding box of a simple cylinder&lt;br /&gt;
 &#039; the output values will be absolute positions&lt;br /&gt;
 CreatePrim &amp;quot;Cylinder&amp;quot;, &amp;quot;MeshSurface&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 dim xmin, ymin, zmin, xmax, ymax, zmax&lt;br /&gt;
 dim list&lt;br /&gt;
 &#039;if you use SelectionList the objects will be treated as one single object&lt;br /&gt;
 &#039;set list = GetValue( &amp;quot;SelectionList&amp;quot; )&lt;br /&gt;
 set list = GetValue( selection(0) )&lt;br /&gt;
 GetBBox list, TRUE, xmin, ymin, zmin, xmax, ymax, zmax&lt;br /&gt;
 LogMessage &amp;quot;Lower Bound: &amp;quot; &amp;amp; xmin &amp;amp; &amp;quot; / &amp;quot; &amp;amp; ymin &amp;amp; &amp;quot; / &amp;quot; &amp;amp; zmin&lt;br /&gt;
 LogMessage &amp;quot;Upper Bound: &amp;quot; &amp;amp; xmax &amp;amp; &amp;quot; / &amp;quot; &amp;amp; ymax &amp;amp; &amp;quot; / &amp;quot; &amp;amp; zmax&lt;br /&gt;
 &lt;br /&gt;
 &#039; expected output:&lt;br /&gt;
 &#039; INFO : Lower Bound: -1 / -2 / -1&lt;br /&gt;
 &#039; INFO : Upper Bound: 1 / 2 / 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[34] open an explorer window&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; this could be used open an output folder ...&lt;br /&gt;
 strPath = &amp;quot;[http://web.archive.org/web/20150212074443/http://support.microsoft.com/kb/152457 explorer.exe /e],&amp;quot; &amp;amp; XSIUtils.ResolvePath(&amp;quot;$SI_HOME/&amp;quot;)&lt;br /&gt;
 Set objShell = CreateObject(&amp;quot;Wscript.Shell&amp;quot;)&lt;br /&gt;
 objShell.Run strPath&lt;br /&gt;
 &lt;br /&gt;
 &#039; to select a generated file inside the folder:&lt;br /&gt;
 strPath = &amp;quot;explorer.exe /select,&amp;quot; &amp;amp; &amp;quot;C:\folder\test.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:XSI_Mod_Tool_SelectNeighborObj_obj_5.png|thumb|SelectNeighborObj obj 5]]&lt;br /&gt;
 &#039; &#039;&#039;&#039;[35] working with hierarchies&#039;&#039;&#039; &lt;br /&gt;
 &lt;br /&gt;
 &#039; let&#039;s be sure we have an object selected&lt;br /&gt;
 if selection.count &amp;gt; 0 and typename(selection(0)) = &amp;quot;X3DObject&amp;quot; then&lt;br /&gt;
  &lt;br /&gt;
 	&#039; the object itself&lt;br /&gt;
 	logmessage selection(0)&lt;br /&gt;
 	&lt;br /&gt;
 	&lt;br /&gt;
 	&#039; the parent object&lt;br /&gt;
 	logmessage selection(0).parent&lt;br /&gt;
 	&lt;br /&gt;
 	&lt;br /&gt;
 	&#039; the children&lt;br /&gt;
 	for each n in selection(0).FindChildren( , , , 0 )&lt;br /&gt;
 		logmessage n&lt;br /&gt;
 	next&lt;br /&gt;
 	&#039; the 4the parameter of FindChildren can be set to 0 or 1&lt;br /&gt;
 	&#039; with 0 you get all direct children&lt;br /&gt;
 	&#039; with 1 you get everything located under that object no matter how deep the level&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 	&#039; count all objects&lt;br /&gt;
 	logmessage &amp;quot;children: &amp;quot; &amp;amp; selection(0).FindChildren( , , , 1).count&lt;br /&gt;
 	&#039; caution: if the 3rd parameter is set to siMeshFamily&lt;br /&gt;
 	&#039; then the selected object will be also counted&lt;br /&gt;
 &lt;br /&gt;
 	&#039; find the root object of the hierarchy, any object could be selected&lt;br /&gt;
 	SelectNeighborObj selection(0), 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 	&#039; go through the hierarchy in different directions&lt;br /&gt;
 	&#039; SelectNeighborObj [parameter1], [parameter2], [parameter3], [parameter4]&lt;br /&gt;
 	&#039; options of the second parameters&lt;br /&gt;
 	&#039; 0 go one level up&lt;br /&gt;
 	&#039; 1 go one level down&lt;br /&gt;
 	&#039; 2 go to next silbing&lt;br /&gt;
 	&#039; 3 go to previous silbing&lt;br /&gt;
 	&#039; 4 go to highest level&lt;br /&gt;
 	&#039; 5 go to deepest level of current selected obj&lt;br /&gt;
 	&#039; 5: if there are more than one children, the path goes always for the first (left) child (see image)&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 	&#039; select the hierarchy as a whole &lt;br /&gt;
 	SelectObj &amp;quot;left_thigh&amp;quot;, &amp;quot;TREE&amp;quot;, true&lt;br /&gt;
 	&#039; first parameter could be any object of the hierarchy&lt;br /&gt;
 	&#039; after using this the selection of an Oni character will be &amp;quot;B:pelvis&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
 	msgbox &amp;quot;no object was selected&amp;quot;	&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[36] drag and drop support for specific oni files&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 function XSILoadPlugin( in_reg )&lt;br /&gt;
 	in_reg.Author = &amp;quot;&amp;quot;&lt;br /&gt;
 	in_reg.Name = &amp;quot;Oni drag and drop support&amp;quot;&lt;br /&gt;
 	in_reg.Email = &amp;quot;&amp;quot;&lt;br /&gt;
 	in_reg.URL = &amp;quot;&amp;quot;&lt;br /&gt;
 	in_reg.Major = 1&lt;br /&gt;
 	in_reg.Minor = 0&lt;br /&gt;
 &lt;br /&gt;
 	in_reg.RegisterEvent &amp;quot;support_oni_DnD&amp;quot;,siOnDragAndDrop&lt;br /&gt;
  	&#039;RegistrationInsertionPoint - do not remove this line&lt;br /&gt;
 &lt;br /&gt;
 	XSILoadPlugin = true&lt;br /&gt;
 end function&lt;br /&gt;
 &lt;br /&gt;
 function XSIUnloadPlugin( in_reg )&lt;br /&gt;
 	dim strPluginName&lt;br /&gt;
 	strPluginName = in_reg.Name&lt;br /&gt;
 	Application.LogMessage strPluginName &amp;amp; &amp;quot; has been unloaded.&amp;quot;,siVerbose&lt;br /&gt;
 	XSIUnloadPlugin = true&lt;br /&gt;
 end function&lt;br /&gt;
 &lt;br /&gt;
 function support_oni_DnD_OnEvent( in_ctxt )&lt;br /&gt;
 	Set objFSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 	FullFilePath = in_ctxt.GetAttribute(&amp;quot;DragSource&amp;quot;)&lt;br /&gt;
  	FileExt = objFSO.GetExtensionName(FullFilePath)&lt;br /&gt;
 	FileName = objFSO.GetBaseName(FullFilePath)&lt;br /&gt;
 &lt;br /&gt;
  	if instr(LCase(FileExt), &amp;quot;oni&amp;quot;) = 1 then&lt;br /&gt;
  		in_ctxt.SetAttribute &amp;quot;DragSourceSupported&amp;quot;, true&lt;br /&gt;
  &lt;br /&gt;
  		&#039; next line prevents the code from being repeated&lt;br /&gt;
 	 	if in_ctxt.GetAttribute(&amp;quot;DragAndDropAction&amp;quot;) = 1 then&lt;br /&gt;
 &lt;br /&gt;
 			logmessage &amp;quot;What I&#039;m supposed to do with that oni?&amp;quot;&lt;br /&gt;
 			&#039; do more stuff here&lt;br /&gt;
 			&#039; ..................&lt;br /&gt;
 			&#039; e.g. telling onisplit to extract the oni&lt;br /&gt;
 &lt;br /&gt;
 		end if&lt;br /&gt;
 	end if&lt;br /&gt;
 &lt;br /&gt;
 	support_oni_DnD_OnEvent = true&lt;br /&gt;
 end function&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mod Tool has its own drag and drop event handler for dae and xml file.&lt;br /&gt;
&lt;br /&gt;
If we succeed in modifying and shipping that new file, we could finally trigger scripts with those files and process them.&lt;br /&gt;
&lt;br /&gt;
The original file can be found at:&lt;br /&gt;
 logmessage XSIUtils.ResolvePath(&amp;quot;$XSI_HOME/&amp;quot;) &amp;amp; &amp;quot;Application\DSScripts\Model.vbs&amp;quot;&lt;br /&gt;
 &#039; C:\Softimage\Softimage_Mod_Tool_7.5\Application\DSScripts\&#039;&#039;&#039;Model.vbs&#039;&#039;&#039;&lt;br /&gt;
A backup of the original file can be found here: &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/ModToolScript/Model.vbs&amp;lt;/nowiki&amp;gt; (dead link)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are two issues that can be fixed by modifying this file.&lt;br /&gt;
* import of xml files created by onisplit&lt;br /&gt;
* import of dae and xml files with relative path from a html page&lt;br /&gt;
&lt;br /&gt;
Relative file pathes will be transformed to absolute pathes whereby an unwanted &amp;quot;file:///&amp;quot; is added.&lt;br /&gt;
&lt;br /&gt;
A solution to is to transform the path again.&lt;br /&gt;
&lt;br /&gt;
 if instr(in_Filename,&amp;quot;file:///&amp;quot;) = 1 then&lt;br /&gt;
 	in_Filename = replace(in_Filename, &amp;quot;file:///&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
Following function is always triggered, so we will modify it.&lt;br /&gt;
 sub ImportDotXSIProc( in_Filename, in_Parent )&lt;br /&gt;
 	&amp;lt;font style=&amp;quot;color:#DD0000&amp;quot;&amp;gt;if instr(in_Filename,&amp;quot;file:///&amp;quot;) = 1 then&lt;br /&gt;
 		in_Filename = replace(in_Filename, &amp;quot;file:///&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 	end if&lt;br /&gt;
 	Set objFSO = CreateObject(&amp;quot;Scripting.FileSystem&amp;lt;Object&amp;quot;)&lt;br /&gt;
 	FileExt = objFSO.GetExtensionName(in_Filename)&amp;lt;/font&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 	if application.license = &amp;quot;Avid 3D&amp;quot; then&lt;br /&gt;
 		SIImportDotXSIFile in_Filename, in_Parent&lt;br /&gt;
 	else&lt;br /&gt;
 		Set oFS = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;) &lt;br /&gt;
 		&amp;lt;font style=&amp;quot;color:#DD0000&amp;quot;&amp;gt;if oFS.FileExists(in_Filename) = True then&lt;br /&gt;
 			if FileExt = &amp;quot;xml&amp;quot; then&lt;br /&gt;
 				&#039; is this an Oni xml file ?&lt;br /&gt;
 		 		Set xmlDoc = CreateObject(&amp;quot;Microsoft.XMLDOM&amp;quot;)&lt;br /&gt;
 				xmlDoc.Async = &amp;quot;False&amp;quot;&lt;br /&gt;
 				xmlDoc.Load(in_Filename)&lt;br /&gt;
 				if xmlDoc.selectNodes(&amp;quot;Oni&amp;quot;).length &amp;gt; 0 then&lt;br /&gt;
 					logmessage &amp;quot;Oni xml file detected&amp;quot;&lt;br /&gt;
 					read_xml &amp;quot;OFGA&amp;quot;, in_Filename&lt;br /&gt;
 				end if&lt;br /&gt;
 				exit sub&lt;br /&gt;
 			end if&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The lines in red has been added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[37] dae export&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 set oProps = ActiveProject.ActiveScene.Root.Properties&lt;br /&gt;
 if typename (oProps.find(&amp;quot;ExportCrosswalkOptions&amp;quot;)) = &amp;quot;Nothing&amp;quot; then&lt;br /&gt;
 	logmessage &amp;quot;Export settings not set&amp;quot;&lt;br /&gt;
 	CreateExportCrosswalkOptions , &amp;quot;ExportCrosswalkOptions&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
 	logmessage &amp;quot;Export settings present&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
 &lt;br /&gt;
 &#039; sets the extension to dae&lt;br /&gt;
 SetValue &amp;quot;ExportCrosswalkOptions.Format&amp;quot;, 1&lt;br /&gt;
 &#039; set export path and file name&lt;br /&gt;
 SetValue &amp;quot;ExportCrosswalkOptions.Filename&amp;quot;, CreateObject(&amp;quot;WScript.Shell&amp;quot;).SpecialFolders(&amp;quot;Desktop&amp;quot;) &amp;amp; &amp;quot;\export_test.dae&amp;quot;&lt;br /&gt;
 &#039; selection only&lt;br /&gt;
 SetValue &amp;quot;ExportCrosswalkOptions.ExportSelectionOnly&amp;quot;, True&lt;br /&gt;
 &#039; export&lt;br /&gt;
 ExportCrosswalk &amp;quot;ExportCrosswalkOptions&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[38] fbx export&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 FBXExportLights (false)&lt;br /&gt;
 FBXExportSelection (true)&lt;br /&gt;
 &#039; mark FBXExport and hit F1 to get more options&lt;br /&gt;
 FBXExport (CreateObject(&amp;quot;WScript.Shell&amp;quot;).SpecialFolders(&amp;quot;Desktop&amp;quot;) &amp;amp; &amp;quot;\export_test.fbx&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[39] import an image clip only once&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 image_path =  &amp;quot;C:\Users\RRM\Desktop\white_512_512.tga&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 Set FSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 image_clip = FSO.GetBaseName(image_path) &amp;amp; &amp;quot;_&amp;quot; &amp;amp; FSO.GetExtensionName(image_path)&lt;br /&gt;
 logmessage image_clip&lt;br /&gt;
 &lt;br /&gt;
 if not typename(ActiveProject.ActiveScene.ImageClips(image_clip)) = &amp;quot;Nothing&amp;quot; then&lt;br /&gt;
 	logmessage &amp;quot;found image clip&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
 	logmessage &amp;quot;image clip not yet present, going to import ...&amp;quot;&lt;br /&gt;
 	&lt;br /&gt;
 	SICreateImageClip image_path&lt;br /&gt;
  	&#039; or as script object:&lt;br /&gt;
 	&#039;set oImage = AddImageSource (image_path)&lt;br /&gt;
 	&#039;set oImageClip = AddImageClip (oImage)&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[40] layers&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ModTool_layers.png|thumb|200px|right|how to access scene layers]]&lt;br /&gt;
&lt;br /&gt;
To access scene layers switch from Main Control Panel (MCP) to Keying Panel/Layers (KP/L) and then click &amp;quot;Scene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
After the user became used to layers, they can help to organize work in a scene. This is especially interesting for some scripting tasks like getting TRGV/FURN data for xml files.&lt;br /&gt;
&lt;br /&gt;
 &#039; get current layer&lt;br /&gt;
 GetCurrentLayer CurrentLayer&lt;br /&gt;
 logmessage CurrentLayer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; create a new layer named &amp;quot;FurnLayer&amp;quot; if it doesn&#039;t already exist&lt;br /&gt;
 &#039; make new layer the current layer&lt;br /&gt;
 if typename(ActiveProject.ActiveScene.Layers(&amp;quot;FurnLayer&amp;quot;)) = &amp;quot;Nothing&amp;quot; then&lt;br /&gt;
 	SICreateLayer , &amp;quot;FurnLayer&amp;quot;, FurnLayer&lt;br /&gt;
 	SetCurrentLayer FurnLayer&lt;br /&gt;
 else&lt;br /&gt;
 	SetCurrentLayer &amp;quot;Layers.FurnLayer&amp;quot;&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; get objects in FurnLayer and count objects&lt;br /&gt;
 &#039; exit sub if there are no objects&lt;br /&gt;
 SelectMembers &amp;quot;Layers.FurnLayer&amp;quot;&lt;br /&gt;
 if selection.count = 0 then&lt;br /&gt;
 	MsgBox &amp;quot;No OFGA data found to export.&amp;quot;, , &amp;quot;Export canceled&amp;quot;&lt;br /&gt;
 	exit sub&lt;br /&gt;
 end if&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
 &#039; if there are Furn objects&lt;br /&gt;
 for each obj in selection&lt;br /&gt;
 	&#039; do something e.g. create xml&lt;br /&gt;
 next&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[41] onisplit update&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039; this downloads and unzips the last attachment from the [http://mods.oni2.net/node/38 onisplit page]&lt;br /&gt;
 output_dir = &amp;quot;F:\test\&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &#039; get onisplit link ################################################&lt;br /&gt;
 set xmlhttp = createobject (&amp;quot;msxml2.xmlhttp.3.0&amp;quot;)&lt;br /&gt;
 xmlhttp.open &amp;quot;get&amp;quot;, &amp;quot;http://mods.oni2.net/node/38/index.html&amp;quot;, false&lt;br /&gt;
 xmlhttp.send&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;webtext = xmlhttp.responseText&lt;br /&gt;
 webtext = replace(replace(webtext, vbcr,&amp;quot;&amp;quot;),vblf,&amp;quot;&amp;quot;)&lt;br /&gt;
 webtext = split(webtext, &amp;quot;&amp;lt;table class=&amp;quot;&amp;quot;sticky-enabled&amp;quot;&amp;quot;&amp;gt; &amp;lt;thead&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Attachment&amp;lt;/th&amp;gt;&amp;quot; )(1)&lt;br /&gt;
 webtext = split(webtext, &amp;quot;&amp;lt;/td&amp;gt; &amp;lt;/tr&amp;gt;&amp;lt;/tbody&amp;gt;&amp;lt;/table&amp;gt;&amp;quot;) (0)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 link_start = instrrev(webtext, &amp;quot;http&amp;quot;)&lt;br /&gt;
 link_end = instrrev(webtext, &amp;quot;.zip&amp;quot;&amp;quot; type&amp;quot;) + 4 &#039; + zip&lt;br /&gt;
 &#039; mid (text, begin, length)&lt;br /&gt;
 link = mid(webtext, link_start, link_end - link_start)&lt;br /&gt;
 logmessage &amp;quot;last link in attachment: &amp;quot; &amp;amp; link&lt;br /&gt;
 &lt;br /&gt;
 dim xHttp: Set xHttp = createobject(&amp;quot;Microsoft.XMLHTTP&amp;quot;)&lt;br /&gt;
 dim bStrm: Set bStrm = createobject(&amp;quot;Adodb.Stream&amp;quot;)&lt;br /&gt;
 xHttp.Open &amp;quot;GET&amp;quot;, link, False&lt;br /&gt;
 xHttp.Send&lt;br /&gt;
 &lt;br /&gt;
 &#039; get file name ###################################################&lt;br /&gt;
 hdr = xHttp.getResponseHeader(&amp;quot;Content-Disposition&amp;quot;)&lt;br /&gt;
 hdr = replace (hdr, &amp;quot;attachment; filename=&amp;quot;&amp;quot;&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 hdr = replace (hdr, &amp;quot;&amp;quot;&amp;quot;&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
 logmessage hdr&lt;br /&gt;
 &lt;br /&gt;
 &#039; save file #######################################################&lt;br /&gt;
 filename = output_dir &amp;amp; hdr&lt;br /&gt;
 with bStrm&lt;br /&gt;
 	.type = 1 &#039;//binary&lt;br /&gt;
 	.open&lt;br /&gt;
 	.write xHttp.responseBody&lt;br /&gt;
 	.savetofile filename, 2 &#039;//overwrite&lt;br /&gt;
 end with&lt;br /&gt;
 &lt;br /&gt;
 &#039; extract file ####################################################&lt;br /&gt;
 &lt;br /&gt;
 UnzipFile filename, output_dir&lt;br /&gt;
 &lt;br /&gt;
 Function UnzipFile(ZipFile, ExtractTo)&lt;br /&gt;
 	Set fso = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 	If NOT fso.FolderExists(ExtractTo) Then&lt;br /&gt;
 		fso.CreateFolder(ExtractTo)&lt;br /&gt;
 	End If&lt;br /&gt;
 	set objShell = CreateObject(&amp;quot;Shell.Application&amp;quot;)&lt;br /&gt;
 	set FilesInZip=objShell.NameSpace(ZipFile).items&lt;br /&gt;
 	objShell.NameSpace(ExtractTo).CopyHere(FilesInZip)&lt;br /&gt;
 	Set fso = Nothing&lt;br /&gt;
 	Set objShell = Nothing&lt;br /&gt;
 End Function&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[42] get vertex color&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 set oGeometry = selection(0).activeprimitive.geometry&lt;br /&gt;
 set oTriangles = oGeometry.Triangles&lt;br /&gt;
 &lt;br /&gt;
 for each oTriangle in oTriangles&lt;br /&gt;
    logmessage oTriangle.Name &lt;br /&gt;
 &lt;br /&gt;
    for each oVertex in oTriangle.Points&lt;br /&gt;
        set oColor = oVertex.Color&lt;br /&gt;
        logmessage vbTab &amp;amp; &amp;quot;RGBA(&amp;quot; &amp;amp; _&lt;br /&gt;
           oColor.red &amp;amp; &amp;quot;,&amp;quot; &amp;amp; _&lt;br /&gt;
           oColor.green &amp;amp; &amp;quot;,&amp;quot; &amp;amp; _&lt;br /&gt;
           oColor.blue &amp;amp; &amp;quot;,&amp;quot; &amp;amp; _&lt;br /&gt;
           oColor.alpha &amp;amp; &amp;quot;)&amp;quot;&lt;br /&gt;
    next&lt;br /&gt;
 next&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039;[43] get all used textures&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 DeleteAllUnusedMaterials&lt;br /&gt;
 DeleteUnusedImageClips&lt;br /&gt;
 &#039;DeleteUnusedImageSources&lt;br /&gt;
 for each i in Application.ActiveProject.ActiveScene.ExternalFiles&lt;br /&gt;
 	if i.filetype = &amp;quot;Pictures&amp;quot; then&lt;br /&gt;
 		logmessage i&lt;br /&gt;
 	end if&lt;br /&gt;
 next&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &#039; &#039;&#039;&#039; [44] get global point position&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 set oObj = selection(0)&lt;br /&gt;
 set oTrans = oObj.Kinematics.Local.Transform &lt;br /&gt;
 set oPoint0 = oObj.ActivePrimitive.Geometry.Points(0)&lt;br /&gt;
 set oPoint7 = oObj.ActivePrimitive.Geometry.Points(7)&lt;br /&gt;
 set oPos0 = oPoint0.Position&lt;br /&gt;
 set oPos7 = oPoint7.Position&lt;br /&gt;
 &lt;br /&gt;
 &#039; scaling must be frozen to 1 before we can calculate the size from local values&lt;br /&gt;
 ResetTransform selection(0), siCtr, siScl, siXYZ&lt;br /&gt;
 &lt;br /&gt;
 logmessage &amp;quot;local p0: &amp;quot;&amp;amp; oPos0.X &amp;amp; &amp;quot; &amp;quot; &amp;amp; oPos0.Y &amp;amp; &amp;quot; &amp;quot; &amp;amp; oPos0.Z&lt;br /&gt;
 set oGlobalPos0 = XSIMath.MapObjectPositionToWorldSpace( oTrans, oPos0)&lt;br /&gt;
 logmessage &amp;quot;global p0: &amp;quot;&amp;amp; oGlobalPos0.X &amp;amp; &amp;quot; &amp;quot; &amp;amp; oGlobalPos0.Y &amp;amp; &amp;quot; &amp;quot; &amp;amp; oGlobalPos0.Z&lt;br /&gt;
 &lt;br /&gt;
 logmessage &amp;quot;local p7: &amp;quot;&amp;amp; oPos7.X &amp;amp; &amp;quot; &amp;quot; &amp;amp; oPos7.Y &amp;amp; &amp;quot; &amp;quot; &amp;amp; oPos7.Z&lt;br /&gt;
 set oGlobalPos7 = XSIMath.MapObjectPositionToWorldSpace( oTrans, oPos7)&lt;br /&gt;
 logmessage &amp;quot;global p7: &amp;quot;&amp;amp; oGlobalPos7.X &amp;amp; &amp;quot; &amp;quot; &amp;amp; oGlobalPos7.Y &amp;amp; &amp;quot; &amp;quot; &amp;amp; oGlobalPos7.Z&lt;br /&gt;
  &lt;br /&gt;
 logmessage &amp;quot;size: &amp;quot; &amp;amp;		oPos7.X - oPos0.X &amp;amp; &amp;quot; &amp;quot; &amp;amp; _&lt;br /&gt;
 							oPos7.Y - oPos0.Y &amp;amp; &amp;quot; &amp;quot; &amp;amp; _&lt;br /&gt;
 							oPos7.Z - oPos0.Z&lt;br /&gt;
 &#039; with a rotation of: -3,8792 16,4039 -13,5017&lt;br /&gt;
 &#039; INFO : local p0: -4 -4 -4&lt;br /&gt;
 &#039; INFO : local p7: 4 4 4&lt;br /&gt;
 &#039; INFO : global p0: -5,74764582364017 -3,00250371537919 -2,43916767056426 &#039; TRGV start point&lt;br /&gt;
 &#039; INFO : global p7: 5,74764582364017 3,00250371537919 2,43916767056426&lt;br /&gt;
 &#039; INFO : size: 8 8 8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Interactive Creative Environment (ICE)===&lt;br /&gt;
* [[wikipedia:Autodesk_Softimage#ICE_Interactive_Creative_Environment|ICE]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tutorials:&#039;&#039;&#039;&lt;br /&gt;
* https://www.youtube.com/watch?v=ioMQ2rBVO4g&lt;br /&gt;
* http://dot3d.blogspot.com/2009/10/softimage-ice-tree-building-step-by.html&lt;br /&gt;
* [https://www.si-community.com/community/viewtopic.php?f=41&amp;amp;t=1707 an ICE tutorial thread]&lt;br /&gt;
* [https://download.autodesk.com/global/docs/softimage2013/en_us/userguide/index.html?url=files/ICE_trees_DebuggingICETrees.htm,topicNumber=d30e269791 ICE trees Debugging]&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;https://support.solidangle.com/display/SItoAUG/ICE&amp;lt;/nowiki&amp;gt; (dead link)&lt;br /&gt;
&lt;br /&gt;
==Wanted knowledge==&lt;br /&gt;
* How to set up particles in Mod Tool? We still need an Oni particle editor!&lt;br /&gt;
* How to rig models and then extract the animation data?&lt;br /&gt;
* How to make complex new UV maps?&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]][[Category:Outdated modding tools]][[Category:Windows-only modding tools]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=User:Vortice&amp;diff=43855</id>
		<title>User:Vortice</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=User:Vortice&amp;diff=43855"/>
		<updated>2025-01-22T19:16:16Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Created page with &amp;quot;I&amp;#039;m an idiot without any noticeable contribution to society. For now.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m an idiot without any noticeable contribution to society. For now.&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Modding_errors&amp;diff=43854</id>
		<title>Modding errors</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Modding_errors&amp;diff=43854"/>
		<updated>2025-01-22T18:53:18Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: FAQ -&amp;gt; Why are body parts overlapping}}&lt;br /&gt;
You might want to use the browser&#039;s search function to quickly find an error message.&lt;br /&gt;
{{TOClimit|3}}&lt;br /&gt;
&lt;br /&gt;
==Frequently asked questions==&lt;br /&gt;
[[Image:modding_errors.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*Why does Oni crash on game start?&lt;br /&gt;
::What were you working on? A [[#... due to overloaded animation|character animation]]?&lt;br /&gt;
*Why does Oni crash while loading a level?&lt;br /&gt;
::What were you working on? A [[#... due to missing files|game level]]?&lt;br /&gt;
*Why does a character have black body parts?&lt;br /&gt;
::You&#039;re probably [[#Missing character texture (TXMP)|missing a texture]].&lt;br /&gt;
*Why does a character have white body parts?&lt;br /&gt;
::You are using a mod with bgra32 textures and an old engine that doesn&#039;t support bgra32.&lt;br /&gt;
* Why can&#039;t I convert character animations?&lt;br /&gt;
::See [[#TRAM-related|HERE]] if you use &amp;quot;-create:tram&amp;quot;.&lt;br /&gt;
* Why are all body parts overlapping in the DAE file?&lt;br /&gt;
::Because the part hierarchy isn&#039;t correct. Read more [https://web.archive.org/web/20160225191109/http://oni.bungie.org/forum/viewtopic.php?pid=31310#p31310 here].&lt;br /&gt;
&lt;br /&gt;
==Visual errors based on settings==&lt;br /&gt;
===Black splashscreens but normal gameplay===&lt;br /&gt;
Those screens (all TXMBs) are black if the user has a lower resolution than the screen. Oni&#039;s vanilla splashscreens are 640x480 but the [[AE]]&#039;s &amp;quot;HD Screens&amp;quot; package bumps them up to 1024x768, which is where players usually encounter this problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This problem is fixed by [[Daodan DLL]] v3.5 or newer and the [[FERAL|Mac Intel build]] v1.2 or newer.&lt;br /&gt;
&lt;br /&gt;
==Binary errors==&lt;br /&gt;
===Crash while starting Oni===&lt;br /&gt;
====... due to overloaded animation====&lt;br /&gt;
Animations with more than 107 keys per bone crash the game. You can import animations with more than 107 frames if the keys cover multiple frames.&lt;br /&gt;
: For example 12 frames &#039;&#039;&amp;lt;EKey&amp;gt;&amp;lt;font style=&amp;quot;color:#00AA00&amp;quot;&amp;gt;&#039;&#039;&#039;12&#039;&#039;&#039;&amp;lt;/font&amp;gt; -156.628983 -14.6175327 -78.3831558&amp;lt;/EKey&amp;gt;&#039;&#039;&lt;br /&gt;
Such ranges and EKeys are produced by older OniSplit versions. See [[#TRAM-related|HERE]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You shouldn&#039;t encounter this bug anymore with OniSplit v0.9.56.0 or newer.&lt;br /&gt;
&lt;br /&gt;
===Crash while loading a level===&lt;br /&gt;
====... due to improper textures====&lt;br /&gt;
Textures&#039; x and y (pixel) dimensions must be a power of two: 512, 256, 128, 64, etc.&lt;br /&gt;
&lt;br /&gt;
====... due to missing files====&lt;br /&gt;
Generally it can be said that Oni complains when an instance is missing that is referenced by another instance. For instance:&lt;br /&gt;
* AKEVs don&#039;t tolerate missing textures.&lt;br /&gt;
* ONVLs and ONCCs don&#039;t tolerate missing variants (ONCVs).&lt;br /&gt;
&lt;br /&gt;
====... due to triangle limit====&lt;br /&gt;
* with too many triangles, Oni crashes after ~90% of the loading process; the triangle limit is ~520,000 (500,000 to be on the safe side).&lt;br /&gt;
&lt;br /&gt;
===Crash while playing===&lt;br /&gt;
====... due to missing files====&lt;br /&gt;
If you encounter a crash when spawning a character or when you cycle through all characters with F8, then check if the crashing character has a TRMA file.&lt;br /&gt;
&lt;br /&gt;
===Non-crash errors===&lt;br /&gt;
These errors are visible inside the game and don&#039;t cause a crash when they appear.&lt;br /&gt;
&lt;br /&gt;
====Multiple savegame names for same level number====&lt;br /&gt;
The Load Game menu can show additional savegame names if any new ONLV is provided in another level0 plugin.  As a quick test, you should use a plugin name which comes alphabetically before &amp;quot;level0_Final&amp;quot;, such as &amp;quot;level0_Addin&amp;quot;. If you choose a name like &amp;quot;level0_More&amp;quot;, the new savegame will be appended after all &amp;quot;_Final&amp;quot; ONLDs, and also a clone appears:&lt;br /&gt;
&lt;br /&gt;
: &amp;quot;_Final&amp;quot; list&lt;br /&gt;
: new savegame name from &amp;quot;_More&amp;quot;&lt;br /&gt;
: cloned savegame name of the slot meant to be overwritten&lt;br /&gt;
&lt;br /&gt;
====Multiple TXMBs====&lt;br /&gt;
A level can start with multiple TXMBs, visible one by one, although there was just one BSL command calling for one. This is caused by using additional plugins, because files with the same name can stack.&lt;br /&gt;
&lt;br /&gt;
====Missing character texture (TXMP)====&lt;br /&gt;
The texture is either missing, or the texture name and the link in [[OBD:TRMA|TRMA]] do not match.&lt;br /&gt;
&lt;br /&gt;
====Distorted colors in textures (TXMP)====&lt;br /&gt;
[[Image:color_spectrum_test.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
Why do my source and re-extracted textures look okay but in-game the colors are distorted? The &amp;quot;[[OBD_talk:TXMP#0x_00_10_00_00|little endian data]]&amp;quot; flag in the level data file is missing. The flag will be added by OniSplit v0.9.56.0 or later when you import it, or you can create the TXMP via an XML file and ensure that the flag is present before import.&lt;br /&gt;
&lt;br /&gt;
====Missing animation collection (TRAC)====&lt;br /&gt;
&lt;br /&gt;
====Missing 3D model (TRBS)====&lt;br /&gt;
&lt;br /&gt;
====Distorted 3D model (TRBS)====&lt;br /&gt;
[[Image:XSI_Konoko_Ref.png|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
When creating the 3D model in Mod Tool, you have to watch out for the naming and order of the body parts.&lt;br /&gt;
* If you use OniSplit v0.9.58.0 or lower, the naming of body parts must be absolutely correct.&lt;br /&gt;
* If you use higher versions, the naming is unimportant but the order matters. The order can be easily changed in the Schematic [9]. Then go to Edit &amp;gt; [http://edt.oni2.net/images/schematic.jpg Reorder Nodes Tool] [I] and move an object to its new position.&lt;br /&gt;
&lt;br /&gt;
====Non-working combos (TRAM)====&lt;br /&gt;
Situation: When you create combos, you want to test your moves in-game. Sometimes each move actually works (tested via chr_animate) but the combo does not.&lt;br /&gt;
&lt;br /&gt;
Requirements to prevent that bug:&lt;br /&gt;
* &amp;lt;Attacks&amp;gt; and &amp;lt;HorizontalExtents&amp;gt; data is needed&lt;br /&gt;
** &#039;&#039;&#039;Note:&#039;&#039;&#039; With OniSplit v0.9.55.0 or newer, HorizontalExtents (now named &amp;quot;[[XML:TRAM#List_of_tags.2C_types.2C_and_flags|AttackRing]]&amp;quot;) is calculated automatically.&lt;br /&gt;
* Correct links to the Direct Animations tag&lt;br /&gt;
* Correct links inside the character&#039;s animation collection (TRAC)&lt;br /&gt;
&lt;br /&gt;
==Developer Mode error messages==&lt;br /&gt;
===Animation errors===&lt;br /&gt;
&#039;&#039;throwtarget was NULL&#039;&#039; - The throw target animation was not found.&lt;br /&gt;
&lt;br /&gt;
===BSL errors===&lt;br /&gt;
*&#039;&#039;Func &amp;quot;main&amp;quot;, File &amp;quot;(called from engine)&amp;quot;, Line 0: semantic error, &#039;&#039;&#039;function&#039;&#039;&#039; &amp;quot;main&amp;quot; &#039;&#039;&#039;does not exist&#039;&#039;&#039;&#039;&#039;, then either the function &amp;quot;main&amp;quot; wasn&#039;t found in any BSL file (this can also happen with any other function), or the BSL file has too many commands in it (see [[#BSL_commands_per_file_limitation|here]]). If it&#039;s the latter, split your BSL file into more BSL files (creating additional functions if necessary).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;test.bsl&amp;quot;, Line 3: semantic error, &#039;&#039;&#039;Identifier&#039;&#039;&#039; &amp;quot;main&amp;quot; already declared&#039;&#039; - In this example, there are multiple &amp;quot;main&amp;quot; functions; the last occurrence of main() can be found in the file &amp;quot;test.bsl&amp;quot; at line 3.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;main.bsl&amp;quot;, Line 1: Illegal token, got &amp;quot;func&amp;quot; expected &amp;quot;;&amp;quot;&#039;&#039; - A previous variable declaration didn&#039;t end with a semicolon.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SLiSchedule_Task_Find FAILED [IMPORTANT]&#039;&#039; - The game will freeze after about 5 instances of this message. Caused by calling too many BSL functions in parallel (using fork) in a very short amount of time.&lt;br /&gt;
&lt;br /&gt;
====Mistyped variable====&lt;br /&gt;
Typing &#039;&#039;chr_lod 4&#039;&#039; will produce this error: &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: Illegal token, got &amp;quot;0&amp;quot; expected &amp;quot;;&amp;quot;&#039;&#039;. That&#039;s because &amp;quot;chr_lod&amp;quot; is a variable and you need to use the equals symbol to set a variable. The correct use of this variable would be &#039;&#039;chr_lod = 4&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Mistyped function====&lt;br /&gt;
Typing &#039;&#039;killled_griffen = 1&#039;&#039; will produce &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: semantic error, symbol &amp;quot;killed_griffen&amp;quot; is not a variable (function most likely)&#039;&#039;. That&#039;s because &amp;quot;killed_griffen&amp;quot; is a function, and you simply list values (parameters) after function names, with no equals symbol. The correct use of this function is: &#039;&#039;killed_griffen 1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Another incorrect example: Typing &#039;&#039;chr_givepowerup = 0 ammo 1&#039;&#039; will produce:&lt;br /&gt;
: &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: semantic error, symbole &amp;quot;chr_givepowerup&amp;quot; is not a variable (function most likely)&#039;&#039;  &lt;br /&gt;
: &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: Illegal token, got &amp;quot;ammo&amp;quot; expected &amp;quot;;&amp;quot;&#039;&#039;&lt;br /&gt;
The correct use of this function is &#039;&#039;chr_givepowerup 0 ammo 1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====BSL commands per file limitation====&lt;br /&gt;
The engine has some kind of limit on how many BSL commands can occur in a single BSL file. When you pass the limit, you&#039;ll get errors in the developer console like this: &amp;quot;Func &amp;quot;main&amp;quot;, File &amp;quot;(called from engine)&amp;quot;, Line 0: semantic error, function &amp;quot;main&amp;quot; does not exist.&amp;quot; (it can also be a function other than &amp;quot;main&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
For an example, extract these files and place them in IGMD/EnvWarehouse to experience the problem: [http://script10k.oni2.net/wikifiles/main_not_working_without_commenting_commands.zip], [http://script10k.oni2.net/wikifiles/main_not_working_without_commenting_commands(functions_splitted).zip], [http://script10k.oni2.net/wikifiles/main_splitted_in_two_files.zip]&lt;br /&gt;
&lt;br /&gt;
In all these BSL files, the message &amp;quot;This message should appear on the beginning&amp;quot; should appear when you load level 1. However for &amp;quot;main_not_working_without_commenting_commands&amp;quot; it doesn&#039;t work unless you comment out the 5th line of the BSL file. The &amp;quot;main_not_working_without_commenting_commands(functions_split)&amp;quot; script is the same, but in this one the &amp;quot;main&amp;quot; function is split into two functions, which is still not enough for the error to go away. The scripts in &amp;quot;main_split_in_two_files&amp;quot; are the same BSL as previously, but the two functions are split into two different files: &amp;quot;main.bsl&amp;quot; and &amp;quot;continuation.bsl&amp;quot;. In this case the script works as expected, and the message &amp;quot;This message should appear on the beginning&amp;quot; appears on level load.&lt;br /&gt;
&lt;br /&gt;
So if you experience the error &amp;quot;Function &amp;quot;x&amp;quot; does not exist.&amp;quot; when in fact it does, try spreading your functions across more BSL files and it should fix the problem.&lt;br /&gt;
&lt;br /&gt;
==OniSplit error messages==&lt;br /&gt;
===TRAM-related===&lt;br /&gt;
* &#039;&#039;COLLADA error: duplicate id light&#039;&#039; - Maybe your DAE file has more than one root scene. In this case, you can right-click the model (which selects all 19 bones), then go to the Crosswalk settings, check &amp;quot;Selection Only&amp;quot;, and save the file.&lt;br /&gt;
* &#039;&#039;.dae files cannot be imported as TRAM&#039;&#039; - Newer OniSplit versions doesn&#039;t seem to support &amp;quot;-create:tram&amp;quot; any longer. If you use that command, download an older version like  v0.9.41.0 from Mod Depot.&lt;br /&gt;
* If TRAM*tgt has more than 256 (0-255) frames, you&#039;ll see:&lt;br /&gt;
&lt;br /&gt;
 Parametername: Value too large for Byte&lt;br /&gt;
   at Oni.BinaryWriter.WriteByte(Int32 value)&lt;br /&gt;
   at Oni.Totoro.AnimationDatWriter.WriteRotations(List`1 rotations, Int32 frameSize)&lt;br /&gt;
   at Oni.Totoro.AnimationDatWriter.WriteAnimation()&lt;br /&gt;
   at Oni.Xml.XmlImporter.ReadAnimation()&lt;br /&gt;
   at Oni.Xml.XmlImporter.Import(String filePath, String outputDirPath)&lt;br /&gt;
   at Oni.Program.ExecuteTasks(String[] args, String outputDirPath, Set`1 importedFiles, Queue`1 taskQueue)&lt;br /&gt;
   at Oni.Program.CreateGeneric(String[] args)&lt;br /&gt;
   at Oni.Program.Execute(String[] args)&lt;br /&gt;
   at Oni.Program.Main(String[] args)&lt;br /&gt;
&lt;br /&gt;
===TRBS===&lt;br /&gt;
In DAE files, if a bone has a point cluster, OniSplit v0.9.94.0 fails to convert the file.&lt;br /&gt;
&lt;br /&gt;
==AE Installer==&lt;br /&gt;
===Blank mod list===&lt;br /&gt;
Your user account probably doesn&#039;t have the necessary rights that the AE Installer needs. In Windows, this can happen if you have Oni installed on an &#039;&#039;old&#039;&#039; hard drive which is now wired to your new system. Add &amp;quot;full control&amp;quot; to your account by right-clicking the Oni folder, choosing Properties, and going to the Security tab.&lt;br /&gt;
&lt;br /&gt;
==XSI/Mod Tool errors==&lt;br /&gt;
===Corrupted DAE files===&lt;br /&gt;
Situation: &#039;&#039;I cannot load my DAE file into XSI. It give me an &amp;quot;Unspecified Failure&amp;quot;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Possible cause: When you create the DAE file, there are file paths are stored inside it. If a path contains an illegal character, XSI cannot load the file.&lt;br /&gt;
&lt;br /&gt;
Solution: Make sure the paths use only letters of the [[wikipedia:English_alphabet|English alphabet]].&lt;br /&gt;
&lt;br /&gt;
===Object with test texture===&lt;br /&gt;
If the texture&#039;s file name contains a &amp;quot;#&amp;quot;, ModTool fails to apply that texture and use its rainbow-colored test image instead.&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=OniSplit&amp;diff=43853</id>
		<title>OniSplit</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=OniSplit&amp;diff=43853"/>
		<updated>2025-01-22T18:50:25Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Commands -&amp;gt; Levels}}&lt;br /&gt;
{{TOCfloat|side=right}}&lt;br /&gt;
{{Hatnote|Before reading this page, it&#039;s a good idea to be familiar with basic Oni [[game data terminology]].}}&lt;br /&gt;
&#039;&#039;&#039;OniSplit&#039;&#039;&#039;, written by [[User_talk:Neo|Neo]], is an integral part of the [[Anniversary Edition]] and an essential modding tool on its own. It is a command line tool which can import and export almost all kinds of Oni game data, including textures, sound, 3D models, level geometry and combat animations. Its name comes from its original purpose, which was breaking Oni&#039;s level data files into individual resources. Later, the ability to convert those resources&#039; data between Oni&#039;s format and standard file formats was added. OniSplit incorporates the latest [[OBD|knowledge about Oni&#039;s game data]], and it is currently the community&#039;s main modding tool.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Subpages:&#039;&#039; [[/Change_log|Change log]] (past versions), [[/WIP|WIP notes]] (upcoming versions)&lt;br /&gt;
&lt;br /&gt;
==Getting it==&lt;br /&gt;
===Download links===&lt;br /&gt;
* Latest release of OniSplit: [http://mods.oni2.net/node/38 v0.9.99.2] ([https://websvn.illy.bz/dl.php?repname=Oni2&amp;amp;path=%2FOniSplit%2F&amp;amp;isdir=1 source code])&lt;br /&gt;
* The current GUI for OniSplit is [[Vago (tool)|Vago]]. &#039;&#039;&#039;You should try the GUI to see if it does what you need before working with OniSplit on the command line.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
*Windows: [https://dotnet.microsoft.com/en-us/download/dotnet-framework .NET framework]&lt;br /&gt;
*macOS: [https://www.mono-project.com/download/stable/ Mono framework]&lt;br /&gt;
&lt;br /&gt;
==Workflow==&lt;br /&gt;
OniSplit is used in up to four different stages when modding:&lt;br /&gt;
{|&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|&amp;lt;span style=&amp;quot;font-size:150%&amp;quot;&amp;gt;&#039;&#039;&#039;OUT&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|&#039;&#039;Exporting&#039;&#039; - using the &amp;lt;tt&amp;gt;-export&amp;lt;/tt&amp;gt; command, a [[Dat|level data file]] is broken into its component resources, .oni files.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;border-style: solid; border-width: 0 0 1px 0&amp;quot;|&#039;&#039;Extracting&#039;&#039; - using the &amp;lt;tt&amp;gt;-extract&amp;lt;/tt&amp;gt; commands, .oni files are converted to standard-format files that can be edited in various third-party programs.&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|&amp;lt;center&amp;gt;&amp;lt;span style=&amp;quot;font-size:150%&amp;quot;&amp;gt;&#039;&#039;&#039;IN&#039;&#039;&#039;&amp;lt;/span&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
|&#039;&#039;Creating&#039;&#039; - using the &amp;lt;tt&amp;gt;-create&amp;lt;/tt&amp;gt; commands, standard-format files are converted into .oni files.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;Importing&#039;&#039; - using the &amp;lt;tt&amp;gt;-import&amp;lt;/tt&amp;gt; command, a folder of .oni files is combined into a level data file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that &amp;quot;extracting&amp;quot; refers to a conversion from one format to another, but &amp;quot;exporting&amp;quot; only refers to the creation of .oni files from a .dat file. When exporting, no conversion or re-formatting is taking place; the data is simply being copied out of a .dat (any connected binary data in .raw/.sep files will be concatenated to the data from the .dat when making the .oni).&lt;br /&gt;
&lt;br /&gt;
==Beginner&#039;s tips==&lt;br /&gt;
{{Divhide|show=yes|For users new to the command line or to OniSplit}}&lt;br /&gt;
In Windows, there are several options through which you can use OniSplit - out of which it is recommended to get Vago and CMDer:&lt;br /&gt;
* [[Vago (tool)|Vago]] is a GUI for OniSplit which allows you to handle all general conversions, save your sessions as project files, input manual commands if needed, and more. The two downsides of it is that it doesn&#039;t support Blender yet, forcing the users input commands manually, which in turn are not stored upon ending the session.&lt;br /&gt;
* [https://cmder.app/ CMDer] is an excellent alternative to cmd.exe. It can be customized to allow starting it from any folder you pick with the context menu, and it also stores the most recently used commands after ending the session. Currently it is highly useful for Blender-related operations.&lt;br /&gt;
* Command Prompt/cmd.exe. Windows&#039; default command line interpreter, it&#039;s a poor choice as it does not store most recently used commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On Macs, the command line is found in the Terminal app (/Applications/Utilities) (press Command-Spacebar and type &amp;quot;Terminal&amp;quot; to get there faster).&lt;br /&gt;
&lt;br /&gt;
===OniSplit syntax===&lt;br /&gt;
The basic syntax is:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Windows&#039;&#039;&#039;||&amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;background:rgb(235,235,235); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;OniSplit.exe&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-create:trbs&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(255,156,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;C:\Games\Oni\SomeFolder&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-normals&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(156,255,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;C:\Games\Oni\Modding\TRBSMyNewChar.dae&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Mac&#039;&#039;&#039;||&amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;background:rgb(235,235,235); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;mono OniSplit.exe&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-create:trbs&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(255,156,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;/Games/Oni/SomeFolder&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-normals&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(156,255,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;/Games/Oni/Modding/TRBSMyNewChar.dae&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how it breaks down:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;width:130px&amp;quot;|&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(235,235,235); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Invocation&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|Windows can refer to the program directly, but Macs use Mono to run the .NET app; note also that if OniSplit.exe is not in the Command Prompt/Terminal&#039;s current directory, you must provide the full path to it or set the path variable.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Option&#039;&#039;&#039;&amp;lt;/span&amp;gt;||The command.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(255,156,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Path to folder&#039;&#039;&#039;&amp;lt;/span&amp;gt;||Whether destination or source, the path which is a folder comes first. &amp;lt;u&amp;gt;Use the full path to the folder (starting from &amp;quot;C:\&amp;quot;, or &amp;quot;/&amp;quot; on Macs).&amp;lt;/u&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Option flags&#039;&#039;&#039;&amp;lt;/span&amp;gt;||The flags that can optionally go with this command, separated by spaces.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(156,255,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Path to file&#039;&#039;&#039;&amp;lt;/span&amp;gt;||Whether destination or source, the path of the file comes second. &amp;lt;u&amp;gt;Use the full path to the file (starting from &amp;quot;C:\&amp;quot;, or &amp;quot;/&amp;quot; on Macs).&amp;lt;/u&amp;gt; One exception to this parameter being a file is when using &amp;lt;tt&amp;gt;-create&amp;lt;/tt&amp;gt; to make a level, in which case this is where you supply the source folder.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===CLI tips===&lt;br /&gt;
*Command line interfaces (CLI) usually supply an auto-complete feature to save on typing. If you&#039;ve typed enough of a file/folder name to identify it, press the Tab key and the rest should fill in. In Windows, you may not get the right path name autocompleted on the first try if there are multiple possible autocompletions based on the names in that directory, so keep pressing Tab to cycle through all possibilities. On Macs, if you have not typed enough of the name to narrow it down to a single autocompletion, you will hear an error sound.  Double-tap Tab to see a list of possible autocompletions, then keep typing until you have narrowed it down to one of those and then hit Tab to fill in the rest of its name.&lt;br /&gt;
&lt;br /&gt;
*Note that you can also drag files/folders into the window and the path will magically appear; in cases where you don&#039;t need to use a wildcard, this is the fastest way to build an OniSplit command.&lt;br /&gt;
&lt;br /&gt;
===Wildcards===&lt;br /&gt;
Wildcards can be used to supply patterns to CLI programs. The wildcard is simply the &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt; character. For instance:&lt;br /&gt;
 OniSplit.exe -export:TRAM* &amp;lt;destination&amp;gt; &amp;lt;source .dat&amp;gt;&lt;br /&gt;
will export all the TRAMs in the source .dat into the destination folder. Using &amp;quot;TRAMKON*&amp;quot; would export all of Konoko&#039;s animations.&lt;br /&gt;
&lt;br /&gt;
===Spaces in paths===&lt;br /&gt;
Command line interfaces (CLI) do not recognize spaces as a possible part of a path name because spaces are what separate the terms in your commands. The best course of action is to not use paths with spaces in their names! But if you must, you can use quotes to tell the CLI that a certain string is a single path:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;C:\Games\Oni\&amp;gt;&#039;&#039;&#039;OniSplit.exe -list &amp;quot;My Mod Folder\level5_Final.dat&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This works in the Mac Terminal too, but you can also use the escape character, &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;. Also, other characters like &amp;lt;tt&amp;gt;(&amp;lt;/tt&amp;gt; need to be escaped as well if you do not use quotes:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;MyMac%&#039;&#039;&#039; mono OniSplit.exe -list My\ Mods\ \(In\ Progress\)/level5_Final.dat&lt;br /&gt;
&lt;br /&gt;
But as mentioned, the best practice is to not use any characters besides the alphabet and numbers. It makes your life simpler, and if you ask for help on the forum with a command, no one wants to have to read your long path with lots of spaces or escaped characters in it ;-)&lt;br /&gt;
&lt;br /&gt;
===Reading the commands below===&lt;br /&gt;
*The following commands should be complete, but the current list can be obtained by calling OniSplit with the &amp;lt;tt&amp;gt;-help&amp;lt;/tt&amp;gt; option. You should also use &amp;lt;tt&amp;gt;-version&amp;lt;/tt&amp;gt; to make sure you&#039;re using the latest version, the number of which is given in the &amp;quot;Download links&amp;quot; section above.&lt;br /&gt;
&lt;br /&gt;
*Sample usages are given after certain commands. These are in DOS style, so if you are on a Mac, simply flip the &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;s to &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;s and make &amp;quot;C:\&amp;quot; into a leading &amp;quot;/&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Optional flags are listed in square brackets simply to indicate that they&#039;re optional; don&#039;t enter the brackets when typing a command.&lt;br /&gt;
&lt;br /&gt;
Note that only the .dat file from a level&#039;s data files is mentioned. The .raw and .sep files will be accessed by OniSplit as necessary when working with the .dat file that you gave the name of.&lt;br /&gt;
{{Divhide|end}}&lt;br /&gt;
&lt;br /&gt;
==Commands==&lt;br /&gt;
===Conversion between .dat and .oni===&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;width:430px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-list &amp;lt;file name&amp;gt;&amp;lt;/code&amp;gt;||Lists the named resources contained in a .dat (see [[OBD:File types/Naming|HERE]] for info on unnamed resources)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-export &amp;lt;destination directory&amp;gt; &amp;lt;dat file&amp;gt;&amp;lt;/code&amp;gt;||Breaks .dat file into .oni files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-export:&amp;lt;pattern&amp;gt; &amp;lt;destination directory&amp;gt; &amp;lt;dat file&amp;gt;&amp;lt;/code&amp;gt;||Exports named resource (wildcards also allowed) from .dat file&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-import &amp;lt;source directory&amp;gt; &amp;lt;new dat file&amp;gt;&amp;lt;/code&amp;gt;||Compiles level files from source directory using the name you supply for the .dat file; tries to get target file format from source SNDD, but it&#039;s better to use the :sep or :nosep variants below&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&amp;lt;span style=&amp;quot;padding-left:20px&amp;quot;&amp;gt;To create level5_Final.dat/.raw[/.sep] from the files in MyNewLevel\: &amp;lt;code&amp;gt;OniSplit.exe -import C:\Oni\MyNewLevel\ C:\Oni\GameDataFolder\level5_Final.dat&amp;lt;/code&amp;gt;&amp;lt;span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-import:sep &amp;lt;source directory&amp;gt; &amp;lt;new dat file&amp;gt;&amp;lt;/code&amp;gt;||Imports target file (.dat) from source directory; uses .dat/.raw/.sep format (Mac and PC Demo)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-import:nosep &amp;lt;source directory&amp;gt; &amp;lt;new dat file&amp;gt;&amp;lt;/code&amp;gt;||Imports target file (.dat) from source directory; uses .dat/.raw format (PC retail)&lt;br /&gt;
|}&lt;br /&gt;
:Note that &amp;lt;tt&amp;gt;-import&amp;lt;/tt&amp;gt; will search subdirectories too. If you find having hundreds or thousand of files .oni in one directory to be unmanageable you can always group them in subdirectories any way you like. The only exception is that a subdirectory named &amp;quot;noimport&amp;quot; or &amp;quot;_noimport&amp;quot; is always ignored.&lt;br /&gt;
&lt;br /&gt;
===Management of .oni files===&lt;br /&gt;
Sometimes you want to move some .oni files out of a larger folder of .onis. You could do this manually, but OniSpit knows which files depend on others. It will also look for those dependencies in subfolders beneath the level of the file you supply the name of. The filename field supports wildcards. This is mostly used by the [[AE]] Installer rather than modders themselves.&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-deps &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Displays a list of .oni files that the specified .oni file depends on&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-copy &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Copies .oni file and its dependencies; skips file if it already exists at destination&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-move &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Moves an .oni file and its dependencies; skips file if it already exists at destination&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-move:overwrite &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Moves an .oni file and its dependencies; overwrites any existing .oni files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-move:delete &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Moves an .oni file and its dependencies; doesn&#039;t overwrite; deletes source files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Conversion between .oni/.dat and 3rd party formats===&lt;br /&gt;
====Textures====&lt;br /&gt;
Unless mentioned otherwise, source filenames support wildcards. See [[Modifying textures|HERE]] for a detailed tutorial. The &amp;lt;tt&amp;gt;-extract&amp;lt;/tt&amp;gt; commands can work with .oni files (a single file or several files if you use the wildcard), or rip all the TXMPs from a .dat file.&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:dds &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts all textures (TXMP) from a Oni .dat/.oni file into DDS files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:tga &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts all textures (TXMP) from a Oni .dat/.oni file into TGA files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:png &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts all textures (TXMP) from a Oni .dat/.oni file into PNG files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:txmp &amp;lt;destination directory&amp;gt;&amp;lt;br&amp;gt;[-genmipmaps] [-nouwrap] [-novwrap]&amp;lt;br&amp;gt;&amp;lt;nowiki&amp;gt;[-format:bgr32|bgra32|bgr555|bgra5551|bgra4444|dxt1]&amp;lt;/nowiki&amp;gt;&amp;lt;br&amp;gt;[-envmap:texture_name] &amp;lt;image file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|valign=top|Creates .oni file from image file (PNG, TGA, or DDS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Models====&lt;br /&gt;
[[M3GM]]s, [[ONWC]]s, [[ONCC]]s can be exported to the Wavefront .obj and COLLADA .dae formats. For details see [[Importing character models]] and [[Importing weapon models]]. The generic &amp;lt;tt&amp;gt;-extract&amp;lt;/tt&amp;gt; commands can work with .oni files (a single file, or several files if you use the wildcard), or rip all the TXMP from a .dat file. TRBS and ONCC support additional &amp;lt;tt&amp;gt;-noanim&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-anim&amp;lt;/tt&amp;gt; options for &amp;lt;tt&amp;gt;-extract:dae&amp;lt;/tt&amp;gt;; see [[Importing character models]] for details. Imported geometry must only contain triangles.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;width:540px&amp;quot;|&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:obj &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts 3D data in .oni file (or all M3GM, ONWC and ONCC instances in a .dat) into Wavefront OBJ files&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:dae &amp;lt;destination directory&amp;gt; [-noanim] &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts 3D data in .oni file (or all M3GM, ONWC and ONCC instances in a .dat) into Collada DAE files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:m3gm &amp;lt;destination directory&amp;gt; [-tex:texture_name] &amp;lt;OBJ file&amp;gt;&amp;lt;/code&amp;gt;||Creates a M3GM .oni from an .obj file&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:trbs &amp;lt;destination directory&amp;gt; [-cel] [-normals] &amp;lt;DAE file&amp;gt;&amp;lt;/code&amp;gt;||Creates a TRBS .oni from a .dae file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note on -noanim parameter: Normally OniSplit exports the character with an idle animation. If you use -noanim the character is exported in &amp;quot;I&amp;quot; pose, also the pelvis has the coordinates x=0, y=0, z=0.&lt;br /&gt;
&lt;br /&gt;
====Levels====&lt;br /&gt;
OniSplit can convert AKEV files (level geometry) and the associated file types to and from DAE format:&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:dae &amp;lt;destination directory&amp;gt; &amp;lt;AKEV.oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts 3D data in AKEV and related resources from dependencies into Collada file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next two steps are used on a folder in which you have placed the DAE and XML-formatted instances of the required files, as well as textures in TGA format. See [https://web.archive.org/web/20201127180431/http://oni.bungie.org/forum/viewtopic.php?id=1515 HERE] for details.&lt;br /&gt;
{|&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-create &amp;lt;destination directory&amp;gt;&amp;lt;br&amp;gt;[-genmipmaps] [-format:dxt1]&amp;lt;br&amp;gt;&amp;lt;source directory&amp;gt;&amp;lt;/code&amp;gt;||Converts all AKEV and related instances to .oni files&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-import:nosep &amp;lt;source directory&amp;gt;&amp;lt;br&amp;gt;&amp;lt;target file name&amp;gt;.dat&amp;lt;/code&amp;gt;||The standard command for creating .dat/.raw files from .oni files (remember to use the import:sep option on Mac!)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Sounds====&lt;br /&gt;
The sounds in Windows Oni are stored in WAV format, and on Macs are stored in AIFF format. This also means creating each of your SNDD files in both formats in order to work on both platforms.&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:wav &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Rips sound data from an SNDD .oni file (or all SNDDs from a .dat) as .wav files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:aif &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Rips sound data from an SNDD .oni file (or all SNDDs from a .dat) as .aif files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Text====&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:txt &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Rips text data from a SUBT .oni file (or all SUBTs from a .dat) as .txt files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:subt &amp;lt;destination directory&amp;gt; &amp;lt;TXT file&amp;gt;&amp;lt;/code&amp;gt;||Creates a SUBT .oni file from a .txt file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====XML====&lt;br /&gt;
One of the latest features is conversion of .oni files to and from an XML file, or an XML metafile and related 3rd-party format files. XML files are easier to read and edit.&lt;br /&gt;
::Currently XML export/import is limited to files that do not have raw/sep parts. 2-way conversion is known to work for [[BINA]], [[CONS]], [[DOOR]], [[DPge]], [[FILM]], [[HPge]], [[IGHH]], [[IPge]], [[M3GM]], [[OBAN]], [[ONCC]], [[ONCV]], [[ONLD]], [[ONLV]], [[ONGS]], [[ONSK]], [[ONVL]], [[ONWC]], [[OPge]], [[OSBD]], [[PSpc]], [[PSpL]], [[PSUI]], [[TRAC]], [[TRAM]], [[TRIG]], [[TRGE]], [[TRMA]], [[TRSC]], [[TXMB]], [[TXMP]], [[WMCL]], [[WMDD]], [[WMM_]], [[WPge]].&lt;br /&gt;
:::For detailed examples and tutorials, see [[XML|HERE]]&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:xml &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts .oni file and all related resources to XML files and 3rd-party formats&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create &amp;lt;destination directory&amp;gt; &amp;lt;XML file&amp;gt;&amp;lt;/code&amp;gt;||Creates an .oni file from an XML file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Blender support====&lt;br /&gt;
[[Blender]] by default has a number of issues with most of Oni&#039;s assets, however, OniSplit allows exporting them to Blender-readable files with the &amp;lt;tt&amp;gt;-blender&amp;lt;/tt&amp;gt; flag.&lt;br /&gt;
&lt;br /&gt;
For more detailed information on how to use the &amp;lt;tt&amp;gt;-blender&amp;lt;/tt&amp;gt; flag, please check [[Importing_character_models#Blender-specific_OniSplit_information|Blender specific OniSplit information]]. &lt;br /&gt;
&lt;br /&gt;
[[Category:Completed modding tools]][[Category:Bi-platform modding tools]][[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=SketchUp_tutorials_and_tips&amp;diff=43852</id>
		<title>SketchUp tutorials and tips</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=SketchUp_tutorials_and_tips&amp;diff=43852"/>
		<updated>2025-01-22T18:47:29Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Tutorials}}&lt;br /&gt;
&lt;br /&gt;
==Tutorials==&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
! Tutorial&lt;br /&gt;
! Author&lt;br /&gt;
! Link&lt;br /&gt;
! Status&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| How to make a simple level&lt;br /&gt;
| [[User:Lukas Kreator|Lukas Kreator]]&lt;br /&gt;
| [https://web.archive.org/web/20190712222844/http://oni.bungie.org/forum/viewtopic.php?pid=35324 Oni Central Forum]&lt;br /&gt;
| Finished, but outdated&lt;br /&gt;
| Replaced by the tutorial below&lt;br /&gt;
|-&lt;br /&gt;
| Creating the Lair - A level tutorial&lt;br /&gt;
| [[User:EdT|EdT]]&lt;br /&gt;
| [https://web.archive.org/web/20201029114347/http://oni.bungie.org/forum/viewtopic.php?id=2087 Oni Central Forum]&lt;br /&gt;
| Finished&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
&amp;lt;small&amp;gt;([[User:EdT|EdT]]: You are welcome to put some tips here, about the doors and lasers for example...)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Faces===&lt;br /&gt;
Faces are made when you draw a rectangle, a triangle or a polygon. For example, a cube has 6 faces, because it is made of 6 squares. You could also consider the faces inside the cube, if it is hollow. Faces with no textures show in SketchUp as white or blue. White means it is a &amp;quot;front face&amp;quot;, blue means it is a &amp;quot;back face&amp;quot;. Oni will not draw back faces, and you cannot collide with them. You can flip the faces using Right Click -&amp;gt; Invert Faces, after selecting one or more faces. I suggest that you first invert back faces, and then texture the level. In old versions of OniSplit, back faces have to be textured too, in order for the level to be converted to AKEV successfully.&lt;br /&gt;
&lt;br /&gt;
===Stairs===&lt;br /&gt;
[[Image:Stairs with invisible ramp.png|thumb]]&lt;br /&gt;
If you want to make stairs, make the steps very small or make a ramp over it with an invisible texture. You can use [http://iritscen.oni2.net/wiki/Lukas%20Kreator-Invisible512px.png this all-transparent texture]. The stairs should then look like the image on the right.&lt;br /&gt;
&lt;br /&gt;
===Rotating geometry===&lt;br /&gt;
Some things may be rotated when you try to load your level in Oni. This seems to happen when the user groups stuff together and forgets to ungroup them later. There are two ways to fix it:&lt;br /&gt;
* Load your level in XSI Tools and export the .dae from there. Does not work always.&lt;br /&gt;
* Try to find what is grouped and ungroup it.&lt;br /&gt;
&lt;br /&gt;
===Yellow faces===&lt;br /&gt;
A weird phenomenon happened when an user from OCF (Delano762) was making a new level. There were yellow faces on some places. It is currently unknown what these are, but they seem to have been generated when he converted a Counter Strike map to a COLLADA .dae through a tool. According to him, he was unable to change the texture of these faces if he selected all faces in the level at the same time, but he could change them back to the default texture one at a time.&lt;br /&gt;
&lt;br /&gt;
===Common errors===&lt;br /&gt;
* If your level was converted successfully by OniSplit, but when you try to play it, Oni crashes after about 10% of loading the level, this means there are textures in the model that were not included in the level folder.  For example, the model uses TXMPtexture, but TXMPtexture.oni is missing from the level files.&lt;br /&gt;
* If you cannot convert your level to AKEV because OniSplit throws an error, you could be missing textures on some faces. Back faces also have to be textured, as far as I know. &lt;br /&gt;
** Note: This does not occur with the latest OniSplit, if a face does not have a texture, OniSplit will assign TXMPnotfoundtex to that face. So there is no need to assign textures to back faces. - [[User:EdT|EdT]]&lt;br /&gt;
* Sometimes OniSplit may throw an error similar to this: &amp;quot;Unsupported primitive type &amp;quot;&amp;lt;something&amp;gt;&amp;quot; found in geometry &amp;quot;mesh&amp;lt;number&amp;gt;-geometry&amp;quot;, ignoring&amp;quot;. I usually ignore this, because I don&#039;t know any case in wich this was a problem. Please, correct me if I&#039;m wrong.&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Using_the_Rigify_animation_rig&amp;diff=43851</id>
		<title>Using the Rigify animation rig</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Using_the_Rigify_animation_rig&amp;diff=43851"/>
		<updated>2025-01-22T18:45:47Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update notice w/ summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Required Tools and commands -&amp;gt; Brief overview on TRAMs.}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This article is intended to explain the workflow of using the [http://mods.oni2.net/node/388 Rigify-based animation rig for Blender] (made by geyser) for the purpose of making Oni animations, and also how to use it, and what are the Oni-specific additions to it that we&#039;ve made.&lt;br /&gt;
&lt;br /&gt;
==Prerequisite tutorials==&lt;br /&gt;
As this rig is now intented to be used together with BlenderOni, it is necessary to be familiar with either:&lt;br /&gt;
* [[BlenderOni|BlenderOni&#039;s documentation,]]&lt;br /&gt;
* [https://www.youtube.com/watch?v=pA_Y8QBCvPI BlenderOni&#039;s explanatory video,] particularly time ranges from 0:00 - 3:07 and 21:24 - 48:05 (that&#039;s part 1 and 3 of the video).&lt;br /&gt;
&lt;br /&gt;
Besides that, I highly recommend watching the tutorials below if you feel you&#039;re lacking knowledge in any of these subjects:&lt;br /&gt;
&lt;br /&gt;
General Blender basics:&lt;br /&gt;
&lt;br /&gt;
* [https://www.youtube.com/watch?v=RG8qK5zPqgM Wolf&#039;s 45-Minute Crash Course for Blender Virgins]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Practical and intuitive explanation of what Inverse and Forward Kinematics (IK/FK) are - this is explained in Maya, but same principles apply in every 3D editing program including Blender:&lt;br /&gt;
* [https://www.youtube.com/watch?v=p6PYKyxR0aY Animating with IK and FK]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basics of using Rigify - &#039;&#039;&#039;all you need to know about animating with Rigify is stored in the video below.&#039;&#039;&#039; There is no point in making a tutorial on how to use the rig controllers themselves here - it&#039;s all in the video below:&lt;br /&gt;
&lt;br /&gt;
* [https://www.youtube.com/watch?v=vKgH5zXIYmM Rigify Tutorial #08 - Posing the Rigify rig] by CGDive&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(OPTIONAL) Tutorial on how to create the rig described here - this is strictly optional; the only practical reason to make your own rig is for the purpose of adjusting its controllers to a specific character, however, the advantage that you get out of that is purely visual and a marginal one at that - if you&#039;ve built your rig for Konoko, there&#039;s nothing stopping you from using it on a TCTF SWAT - the limb controllers will be only slightly out of place, which doesn&#039;t impact animating in any way. So ultimately you may want to go through this if you want to learn how this rig works, find this rig confusing, or even just for the bunch of great Youtube tutorials linked in that tutorial.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s worth noting that a huge part of this article is in fact copy-pasted from this tutorial.&lt;br /&gt;
&lt;br /&gt;
* [[Creating_an_animation_rig_in_Blender|Creating an animation rig in Blender]]&lt;br /&gt;
&lt;br /&gt;
==Required tools and commands==&lt;br /&gt;
There are several things worth knowing before you start using the rig, tools to get and tutorials to have ready to reference for commands.&lt;br /&gt;
&lt;br /&gt;
===Tools and relevant tutorials===&lt;br /&gt;
* &#039;&#039;&#039;[[BlenderOni|BlenderOni]]&#039;&#039;&#039; - this Blender addon is an integral companion tool for this rig - it contains a number of scripts which automate a lot of operations required to make any use out of the rig. Without those scripts, these operations (e.g. constraining the model to the rig and vice versa) would have to be done manually, which takes a ridiculous amount of time.&lt;br /&gt;
[[Image:Cmder.png|200px|right|thumb|Screenshot showing Cmder&#039;s capabilities within the context of modding Oni]]&lt;br /&gt;
* [http://mods.oni2.net/node/38 &#039;&#039;&#039;Current version of OniSplit.&#039;&#039;&#039;] This is the tool needed to import and export assets out of Oni. &#039;&#039;&#039;DO NOT USE OniSplit GUI or Vago for importing Oni assets into Blender&#039;&#039;&#039; - neither of these weren&#039;t updated in a long time, and thus they don&#039;t support OniSplit&#039;s v0.9.99.2 -blender option. You can still use them for other purposes though, such as sounds and converting .oni files to XMLs, etc.&lt;br /&gt;
* [https://docs.google.com/document/d/175uJGklYASAgrFjxuUG4-kJRDoMTjjP7GvNxSj1GscU/edit &#039;&#039;&#039;Oni-Blender tutorial&#039;&#039;&#039;] by EdT. Please read this in entirety to know likely-to-happen issues and refer to this as your guide for OniSplit commands relating to Blender.&lt;br /&gt;
* [https://web.archive.org/web/20211202215118/http://oni.bungie.org/forum/viewtopic.php?pid=23230#p23230 &#039;&#039;&#039;Brief overview on creating TRAMs&#039;&#039;&#039;] by EdT - while this was written with XSI in mind, this is still relevant as the process for preparing the XML files for Oni is still the same. Also the next post in that thread, called &#039;&#039;&#039;Brief walk through on modifying a TRAM,&#039;&#039;&#039; is an example of that overview put into practice.&lt;br /&gt;
&lt;br /&gt;
===Optional tools and tutorials===&lt;br /&gt;
* [https://cmder.app/ &#039;&#039;&#039;Cmder&#039;&#039;&#039;] (Windows only) - because OniSplit is a command line tool, it is highly recommended to get any upgrade to Windows&#039; Command Prompt. As shown in the screenshot on the right, Cmder allows you to start it from the context menu in any selected folder, and it also remembers your most recently used commands, vastly improving your workflow when you&#039;re forced to use any command line tools.&lt;br /&gt;
* [https://docs.blender.org/manual/en/2.81/addons/rigging/rigify.html &#039;&#039;&#039;Rigify documentation&#039;&#039;&#039;] - it&#039;s a plugin for Blender designed to automate a lot of rigging work. The rig described here is generated using Rigify. Take a look if you&#039;re interested and want to learn more, but you don&#039;t have to know Rigify&#039;s documentation to use this rig.&lt;br /&gt;
&lt;br /&gt;
==General workflow of animating for Oni using Rigify==&lt;br /&gt;
The most common way to animate characters is to create an armature (also known as a rig) to which the character model is constrained, usually through vertex weights specifying how much a given vertex is controlled by the given controller on a scale from 0 to 1, with all weights summing up to 1. The rig contains a number of controller bones that allow to animate more easily. Then, the animations are usually imported into the game along with the armatures, therefore the animation is stored along with the armature. An example of a game storing animations this way is Halo: Combat Evolved.&lt;br /&gt;
&lt;br /&gt;
Oni character models are divided into 19 rigid body parts organized in a parent-child relation, with the pelvis bone being the root bone, which effectively forms an FK rig. The animations are stored in TRAM files, containing rotation data for each of the 19 body parts, and also location data for the pelvis. There is no armature stored within the game files, therefore in order to use a rig on Oni characters, it is necessary to constrain each of the 19 body parts to the rig bones individually instead of mesh vertices. Also, this automatically means that Oni&#039;s way of storing animations is a destructive one - the data stored in the rig bones that are not direct functional equivalents to Oni character body parts will get lost once the animation is baked into body parts with Visual Transform.&lt;br /&gt;
&lt;br /&gt;
The general workflow of making animations using this rig is the following, assuming you want to make a single animation (i.e. you don&#039;t want to make a throw animation):&lt;br /&gt;
&lt;br /&gt;
# Open up a Blender scene containing the rig.&lt;br /&gt;
# Delete either the model in Pose1 or Pose2.&lt;br /&gt;
# (OPTIONAL) Assuming you want to animate a different character, delete the T-posed model.&lt;br /&gt;
## Import your desired character with textures using -noanim.&lt;br /&gt;
# Import the animation you are using as a starting point. For more detailed information on how to import an Oni animation to Blender, see the next header.&lt;br /&gt;
## If you did point 3, apply the textures on the animated model.&lt;br /&gt;
# Using the &#039;&#039;Set Rig Bone Constraint Targets&#039;&#039; option in BlenderOni, set the targets of the rig&#039;s bone constraints to be the body parts of the animation you&#039;ve imported.&lt;br /&gt;
# Using the Pose Matching functionality, constrain the rig to the imported animation (Set the IK-FK sliders on rig limbs to 1, as Pose Matching works only through FK controllers)&lt;br /&gt;
# For each frame that you want to remain in your animation, while having all the bones selected (or the ones you want), either:&lt;br /&gt;
## Press Ctrl+A, select &#039;&#039;Apply Visual Transform&#039;&#039; to Pose and keyframe it,&lt;br /&gt;
## Or use the &#039;&#039;Bone Visual Transformer&#039;&#039; option in BlenderOni to bake frames within a specified frame range.&lt;br /&gt;
# Disable bone constraints on the rig using the &#039;&#039;Bone Constraint Switch&#039;&#039; option in BlenderOni. &lt;br /&gt;
# &#039;&#039;&#039;Make your animation.&#039;&#039;&#039;&lt;br /&gt;
# Once your animation is ready, use the &#039;&#039;Object Visual Transformer&#039;&#039; option in BlenderOni to bake the rig keyframes into the character model.&lt;br /&gt;
# Using the &#039;&#039;Object Constraint Switch&#039;&#039; option in BlenderOni, disable the object constraints on the character model. &#039;&#039;&#039;The character model should now be animated and have the needed rotations and locations.&lt;br /&gt;
# Export the animation as a DAE.&lt;br /&gt;
&lt;br /&gt;
==Importing Oni animations to Blender==&lt;br /&gt;
This header describes how to import Oni animations to Blender.&lt;br /&gt;
&lt;br /&gt;
For detailed explanation of the required OniSplit commands, please refer to the &#039;&#039;&#039;Oni-Blender Tutorial by EdT&#039;&#039;&#039; listed in the &#039;&#039;&#039;Tools and relevant tutorials&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Assuming the character you want to animate isn&#039;t in your rig file, then using OniSplit, export any character you want as a DAE (-extract:dae) using -noanim and -blender arguments. &lt;br /&gt;
## As per EdT&#039;s &#039;&#039;&#039;Oni-Blender Tutorial&#039;&#039;&#039;, you should get &amp;lt;mark&amp;gt;&amp;lt;tt&amp;gt;AnimationDaeWriter: custom axis conversion&amp;lt;/tt&amp;gt;&amp;lt;/mark&amp;gt; in OniSplit output if you&#039;ve used the -blender argument. If you didn&#039;t get that on the output, it means something most likely went wrong and you won&#039;t be able to import the model into Blender (or you will be able to import it but it will be wrong).&lt;br /&gt;
## Assuming you wanted a textured model and thus you&#039;ve exported an ONCC, you should now get a &#039;&#039;&#039;DAE file&#039;&#039;&#039; and an &#039;&#039;&#039;&#039;&#039;images&#039;&#039;&#039;&#039;&#039; folder containing the textures for it.&lt;br /&gt;
# Using OniSplit, export the animation you want as an XML (-extract:xml) using -anim-body (lets you specify the character you want) and -blender arguments.&lt;br /&gt;
## You should get &#039;&#039;&#039;one DAE and one XML file for the animation.&#039;&#039;&#039; &lt;br /&gt;
# Open up a Blender scene containing the rig.&lt;br /&gt;
# Delete either the model either in Pose1 or Pose2 collection. &lt;br /&gt;
# Import the animation into Blender (&#039;&#039;&#039;MAKE SURE YOU CHECK THE &#039;&#039;Import Unit&#039;&#039; BOX EACH TIME&#039;&#039;&#039;, otherwise you will import the model with arbitrary units which will break everything and will be basically unadjustable later))&lt;br /&gt;
# Import the -noanim model into Blender (&#039;&#039;&#039;ALSO MAKE SURE YOU CHECK THE &#039;&#039;Import Unit&#039;&#039; BOX&#039;&#039;&#039;)&lt;br /&gt;
# Move the animated model to either Pose1 or Pose2 collection.&lt;br /&gt;
# If you&#039;ve imported the textured model, [[Blender#Lack_of_textures_on_animated_models|apply textures to the animated models and fix the alpha transparency issue]].&lt;br /&gt;
&lt;br /&gt;
==Added functionalities==&lt;br /&gt;
This header describes functionalities added to the rig by geyser that are not normally present in Rigify.&lt;br /&gt;
&lt;br /&gt;
===Pose matching===&lt;br /&gt;
The way we do animations is we almost universally start by copying the first or last frame of the preceeding animation. For this reason, we needed functionality that would allow us to snap the rig to an animated Oni character. The way it works, it that it uses bone constraints in rig controller bones targeting the character model in order to snap the rig to the model. The influence of the bone constraints is controlled through the Z location of Pose1 and Pose2 bones in the Pose Matching layer, which is done through drivers.&lt;br /&gt;
&lt;br /&gt;
To snap the rig to the animation in one of the Pose collections, simply move the appropriate Pose bone above the XY plane while in Pose mode.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pose1 and Pose2 below the XY plane !! Rig snapped to the animation in Pose 1 collection !! Rig snapped to the animation in Pose 2 collection&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:Unposed.png|300px|frameless|center]] || [[Image:Pose1.png|300px|frameless|center]] || [[Image:Pose2.png|300px|frameless|center]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Wrist snapping===&lt;br /&gt;
Often when using the IK handles for the arms you will find out that most of the time, you will need the hand to have the same rotation as the forearm. Normally this would mean that you would have to rotate the hands all the time, because IK handles are mainly moved around, and rotated later. For this reason, the wrist snapping functionality was implemented - you can simply copy the rotation of the forearm to the hand by pressing the &amp;quot;IK wrist&amp;quot; button.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Both of the hands after just moving them around... !! Effects of using the IK Wrist button&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:IK Wrist Example1.png|500px|frameless|center]] || [[Image:IK Wrist Example2.png|500px|frameless|center]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43850</id>
		<title>Creating a level</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43850"/>
		<updated>2025-01-22T18:40:56Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Update Template w summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{update|This article contains links to the now defunct Oni Central Forum. Sections: Vertex Coloring -&amp;gt; Level-wide Shading, Links to Forum Tutorials}}&lt;br /&gt;
This page covers level creation from scratch. See [[Modifying an existing level]] if you want to change a vanilla level in the game.&lt;br /&gt;
&lt;br /&gt;
==Level releases and resources==&lt;br /&gt;
===Fan-made levels===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable autosort by-column-3&amp;quot;&lt;br /&gt;
!Date&lt;br /&gt;
!Name&lt;br /&gt;
!Level number&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Oni 2 Angel Studios Tour&lt;br /&gt;
|32&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Green Room&lt;br /&gt;
|26&lt;br /&gt;
|-&lt;br /&gt;
|2019/09/16&lt;br /&gt;
|[https://web.archive.org/web/20240527004257/http://oniforum.bungie.org/viewtopic.php?id=2965 Omega Tournament]&lt;br /&gt;
|31&lt;br /&gt;
|-&lt;br /&gt;
|2016/02/13&lt;br /&gt;
|[https://web.archive.org/web/20160224173743/http://oni.bungie.org/forum/viewtopic.php?id=2947 AI Battle]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2014/01/19&lt;br /&gt;
|[https://web.archive.org/web/20211202225410/http://oni.bungie.org/forum/viewtopic.php?id=2698 Wilderness Preserve]&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|2013/09/07&lt;br /&gt;
|[https://web.archive.org/web/20201127180732/http://oni.bungie.org/forum/viewtopic.php?id=2656 Island]&lt;br /&gt;
|29&lt;br /&gt;
|-&lt;br /&gt;
|2013/07/12&lt;br /&gt;
|[https://web.archive.org/web/20201127175459/http://oni.bungie.org/forum/viewtopic.php?id=2640 City]&lt;br /&gt;
|28&lt;br /&gt;
|-&lt;br /&gt;
|2013/06/01&lt;br /&gt;
|[https://web.archive.org/web/20201029102326/http://oni.bungie.org/forum/viewtopic.php?id=2619 Fight Club]&lt;br /&gt;
|25&lt;br /&gt;
|-&lt;br /&gt;
|2012/05/12&lt;br /&gt;
|[https://web.archive.org/web/20220701102842/http://oni.bungie.org/forum/viewtopic.php?id=2357 Old China]&lt;br /&gt;
|24&lt;br /&gt;
|-&lt;br /&gt;
|2012/03/18&lt;br /&gt;
|[https://web.archive.org/web/20211202220454/http://oni.bungie.org/forum/viewtopic.php?id=2302 Boss Battle]&lt;br /&gt;
|23&lt;br /&gt;
|-&lt;br /&gt;
|2012/02/12&lt;br /&gt;
|[https://web.archive.org/web/20201029113554/http://oni.bungie.org/forum/viewtopic.php?id=2271 De Dust Deluxe]&lt;br /&gt;
|22&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/23&lt;br /&gt;
|[https://web.archive.org/web/20201029114415/http://oni.bungie.org/forum/viewtopic.php?id=2242 Parkour Challenge 2]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/16&lt;br /&gt;
|[https://web.archive.org/web/20211205145843/http://oni.bungie.org/forum/viewtopic.php?id=2235 Parkour Challenge]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/25&lt;br /&gt;
|[https://web.archive.org/web/20201029103607/http://oni.bungie.org/forum/viewtopic.php?id=2001 Mini-Partenon]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2011/10/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113340/http://oni.bungie.org/forum/viewtopic.php?id=2024 Muro&#039;s Lair - Preview]&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113724/http://oni.bungie.org/forum/viewtopic.php?id=1957 Hexagon]&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|2011/06/23&lt;br /&gt;
|[https://web.archive.org/web/20201029104928/http://oni.bungie.org/forum/viewtopic.php?id=1938 Junkyard]&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|2011/05/01&lt;br /&gt;
|[http://mods.oni2.net/node/178 Arena of Hurt (OZG)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/08&lt;br /&gt;
|[https://web.archive.org/web/20210117150652/http://oni.bungie.org/forum/viewtopic.php?id=1736 Arena of Hurt (OTA)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/06&lt;br /&gt;
|[https://web.archive.org/web/20201029105217/http://oni.bungie.org/forum/viewtopic.php?pid=50565#p50565 Martian Colony] AKA &amp;quot;Silly World&amp;quot;&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2010/02/15&lt;br /&gt;
|[https://web.archive.org/web/20201029113916/http://oni.bungie.org/forum/viewtopic.php?id=1506 Maze]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2008/09/16&lt;br /&gt;
|[http://mods.oni2.net/node/4 Arena of Pain]&lt;br /&gt;
|30&lt;br /&gt;
|-&lt;br /&gt;
|2024/05/20&lt;br /&gt;
|[https://gamebanana.com/mods/514707 Kitsune: Chapter 1]&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Forum tutorials on level creation===&lt;br /&gt;
* &#039;&#039;&#039;[https://web.archive.org/web/20201029114347/http://oni.bungie.org/forum/viewtopic.php?id=2087 &amp;quot;Creating the Lair - A level tutorial&amp;quot;]&#039;&#039;&#039;&lt;br /&gt;
* [https://web.archive.org/web/20201127172559/http://oni.bungie.org/forum/viewtopic.php?pid=53026 &amp;quot;Creating a Custom Oni Level (s10k video tutorials)&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201127180431/http://oni.bungie.org/forum/viewtopic.php?id=1515 &amp;quot;Creating new levels&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201029114358/http://oni.bungie.org/forum/viewtopic.php?pid=33838 &amp;quot;Create levels with pathfinding grids&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20210117145338/http://oni.bungie.org/forum/viewtopic.php?id=2000 &amp;quot;More questions about levels&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201029103906/http://oni.bungie.org/forum/viewtopic.php?pid=37252#p37252 &amp;quot;Modding Existing levels - Beta&amp;quot; (&amp;quot;Moveable furniture&amp;quot; post)]&lt;br /&gt;
&lt;br /&gt;
===Wiki pages on level creation===&lt;br /&gt;
* [[Creating a level]] (you are here)&lt;br /&gt;
* [[Modifying an existing level]]&lt;br /&gt;
* [[New levels]]&amp;lt;!--notes and comments by geyser that should be revisited / merged with this page--&amp;gt;&lt;br /&gt;
* [[Lightmapping levels]]&lt;br /&gt;
&lt;br /&gt;
===Free asset sources===&lt;br /&gt;
* [http://vk.com/gameready Various game meshes]&lt;br /&gt;
* [http://web.archive.org/web/20230601050258/http://tutorialsforblender3d.com/Textures/Textures_index.html Various game textures]&lt;br /&gt;
* [https://www.textures.com Various game textures]&lt;br /&gt;
&lt;br /&gt;
==Engine limitations==&lt;br /&gt;
First you should be aware of the limitations that Oni will place on your level.&lt;br /&gt;
&lt;br /&gt;
* The triangle limit of a game level is approx. 520,000 (consider it 500,000 to be on the safe side).&lt;br /&gt;
* {{ModTool}} can save DAE files with a maximum of 64,000 triangles per object.&lt;br /&gt;
* When polygons are too tightly packed, the camera will look at too many of them and glitches will appear. The limit on visible GQs (Gunk Quads) is 8,192 (2&amp;lt;sup&amp;gt;13&amp;lt;/sup&amp;gt;), and higher numbers will cause render bugs and produce the console error message &amp;quot;Exceeded max visible GQs &#039;&#039;number&#039;&#039;&amp;quot;. There are limited solutions to this:&lt;br /&gt;
** Decrease the &#039;&#039;&#039;gs_farclipplane_set&#039;&#039;&#039; value.&lt;br /&gt;
** Hide objects via &#039;&#039;&#039;[[#.3CModel.3E|env_show]]&#039;&#039;&#039;.&lt;br /&gt;
** Hide objects by &#039;&#039;level design&#039;&#039;. For example, departments in a building could be quite detailed because the view of the other departments/rooms is blocked by walls.&lt;br /&gt;
* The camera can look at 2,049 transparent textures at once; one more, and Oni crashes.&lt;br /&gt;
* Characters are visible &#039;&#039;only&#039;&#039; within world coordinates {-4,099, -4,099, -4,099} to {4,099, 4,099, 4,099}.&lt;br /&gt;
* Geometry stops outside of (roughly) world coordinates -4,228 to 4,228 on the X and Z axes (vertical axis not tested).&lt;br /&gt;
* &#039;&#039;&#039;chr_debug_spheres = 1&#039;&#039;&#039; visualizes the collision spheres of characters, so you can check if they will fit through an entrance.&lt;br /&gt;
&lt;br /&gt;
==3D tools==&lt;br /&gt;
===Problems when using multiple different tools===&lt;br /&gt;
Re-saving a DAE file in &#039;&#039;&#039;Mod Tool&#039;&#039;&#039; which was originally made in &#039;&#039;&#039;SketchUp&#039;&#039;&#039; can result in a surprising change in size within Oni. This is due to a difference in the specification of a scale unit.&lt;br /&gt;
&lt;br /&gt;
: For example, the SketchUp DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.0254000&amp;quot; name=&amp;quot;inch&amp;quot; /&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: And the re-saved Mod Tool DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.1&amp;quot; name=&amp;quot;decimetre&amp;quot;&amp;gt;&amp;lt;/unit&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case you&#039;ll need to open the new DAE in a text editor and change the length specification back.&lt;br /&gt;
&lt;br /&gt;
===Sketchup===&lt;br /&gt;
If you are working with Sketchup check out this pages:&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?id=2003 &amp;quot;Sketchup tutorials for making levels&amp;quot;]&lt;br /&gt;
* [[SketchUp tutorials and tips]]&lt;br /&gt;
&lt;br /&gt;
===Blender===&lt;br /&gt;
&#039;&#039;&#039;Scaling&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as Mod Tool and SketchUp: Caution with scaling: See [[#Problems when using multiple different tools|here]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pathfinding&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Be sure to uncheck automatic triangle creation when exporting (BNV) geometry used for pathfinding. Ghost (&#039;&#039;doors&#039;&#039;) must be quads. &lt;br /&gt;
&lt;br /&gt;
==Setting up a workflow==&lt;br /&gt;
If not noted differentely you need OniSplit v0.9.82.0 or a newer version. Onisplit can be downloaded [http://mods.oni2.net/node/38 HERE] (it also comes with the [[AE]] and is found in the Tools directory of the installation).&lt;br /&gt;
&lt;br /&gt;
The level import demo files can be downloaded [http://mods.oni2.net/node/299 HERE].&lt;br /&gt;
&lt;br /&gt;
First, put &#039;&#039;&#039;OniSplit.exe&#039;&#039;&#039; into the second &#039;&#039;&#039;lab&#039;&#039;&#039; folder alongside the XML files.&lt;br /&gt;
&lt;br /&gt;
Look at the file &#039;&#039;&#039;build.cmd&#039;&#039;&#039;. These are the two important lines:&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:level out lab.xml&lt;br /&gt;
 OniSplit.exe -import:pc out level3_Final.dat&lt;br /&gt;
&lt;br /&gt;
The first line creates the *.oni files from a master.xml file, in this case &#039;&#039;&#039;lab.xml&#039;&#039;&#039;. Once finalized, the resulting .oni files can be put into a new [[Making a mod package|AE package]].&lt;br /&gt;
&lt;br /&gt;
The second line creates level archives which can be used for fast tests. They don&#039;t require you to install a package through the AE Installer.&lt;br /&gt;
&lt;br /&gt;
Instead of &amp;quot;-nosep&amp;quot; you can now also use &amp;quot;-pc&amp;quot; for the import. Macs, however, do use &amp;quot;-sep&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
If the game crashes while loading at ~90% progress, be sure that the texture&#039;s x and y dimensions are powers of two: 64, 128, 256, 512….&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading at ~50-60% progress, be sure that the BINACJBOCharacters or AISA file has a player character defined.&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading ~5-10% progress, check if all your textures were inside the &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
:You can extract the AKEV file to XML, then search for the [[XML:AKEV#TXMA|TXMP Array]].&lt;br /&gt;
&lt;br /&gt;
:[http://mods.oni2.net/system/files/AKEV_texture_checker.txt THIS] script checks which textures are missing by comparing the AKEV*.xml with its *.oni files folder. Change the two paths so that it works for you: Alt+4, insert code, then F5.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;TXMP_marker_door&amp;quot; and &amp;quot;TXMP_marker_ghost&amp;quot; will be missing in the demo&#039;s &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
You can add this between the other two lines in build.cmd to prevent a crash.&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
;Polygon&lt;br /&gt;
:A polygon is a shape defined by points (vertices) in space. Polygons are the most fundamental building block in games. Oni uses only shapes with 3 and 4 points (triangles and quads). Other games might also use N-gons, shapes with more points.&lt;br /&gt;
;Face&lt;br /&gt;
:The &#039;&#039;&#039;surface of a polygon&#039;&#039;&#039; is also named face. The &#039;&#039;&#039;direction&#039;&#039;&#039; of a face in &#039;&#039;&#039;defined by its normal&#039;&#039;&#039;. If an object seems to have a hole, it might be that the polygon just has a &#039;&#039;&#039;flipped normal&#039;&#039;&#039; and is therefore wrongly rendered (displayed on screen).&lt;br /&gt;
;Normal&lt;br /&gt;
:Faces and even vertices themselves have directions. The normals of vertices determine how smooth or sharp edges will appear.&lt;br /&gt;
;Vertex (plural&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt; vertices)&lt;br /&gt;
:A point within a polygon.&lt;br /&gt;
:Vertex colors radiate from one vertex to another vertex, whereby their different color values blend into each other so that gradients can appear. &lt;br /&gt;
;Edge&lt;br /&gt;
:A line of two points within a polygon.&lt;br /&gt;
;Tris (triangles)&lt;br /&gt;
:Polygons made of 3 points.&lt;br /&gt;
;Quads&lt;br /&gt;
:Polygons made of 4 points. Planes. Rectangles.&lt;br /&gt;
:Internally, all quads get converted into two triangles and will affect the maximum triangle count accordingly.&lt;br /&gt;
;Level&lt;br /&gt;
:The term &amp;quot;level&amp;quot; is often used to shorten &amp;quot;level map&amp;quot; (buildings and terrain).&lt;br /&gt;
;Geometry&lt;br /&gt;
:Level geometry can be objects made of tris and/or quads.&lt;br /&gt;
:Oni differentiates between basically 3 types of level geometry:&lt;br /&gt;
:* Static objects (sometimes also named AKEV core geometry)&lt;br /&gt;
:* Animated objects&lt;br /&gt;
:* Pushable objects (not used in the original game)&lt;br /&gt;
;Static geometry&lt;br /&gt;
:* &#039;&#039;&#039;Unique level geometry with no functions&#039;&#039;&#039; (AKEV core geometry such as buildings and streets).&lt;br /&gt;
:* &#039;&#039;&#039;Repeating objects&#039;&#039;&#039; are flagged as &#039;&#039;&#039;furniture (FURN)&#039;&#039;&#039; although they can be outdoor objects such as boxes and containers. &amp;lt;!--Oni&#039;s story plays out most often inside buildings. So, there you go. --&amp;gt;FURN objects were used to be imported by an object collection, an CJBO. Nowadays, furniture collections can be used (again) for imports, but the individual objects are stored as OFGA files. This modularity is known in many game editors (like the Unreal Engine Editor). So, &#039;&#039;&#039;OFGA are nothing else than &amp;quot;game assets&amp;quot;.&#039;&#039;&#039; The drawback of OFGA is that they &#039;&#039;&#039;will not import with any vertex shading&#039;&#039;&#039;. Only their &#039;&#039;&#039;geometries&#039;&#039;&#039;, attached &#039;&#039;&#039;particle&#039;&#039;&#039; and &#039;&#039;&#039;gunk flags&#039;&#039;&#039; get copied into final (baked) level geometry.&lt;br /&gt;
:* &#039;&#039;&#039;Objects with actual functions&#039;&#039;&#039; (CJBO such as doors, consoles, triggers)&lt;br /&gt;
:** Some types of CJBO (spawn lists of weapons, characters, powerups and of course flags and patrol paths) are not considered as level geometry.&lt;br /&gt;
;[[XML:AKEV#AGQG|Gunk flags]]&lt;br /&gt;
:Properties directly associated with the polygons. Among others, these can be: Transparent, TwoSided, NoCollision, Invisible, NoObjectCollision, NoCharacterCollision, NoDecals, Furniture, Impassable.&lt;br /&gt;
;Baking&lt;br /&gt;
:When a level gets baked, all geometries get merged.&lt;br /&gt;
:*Unique level geometry will have vertex painting.&lt;br /&gt;
:*Objects derived from already compiled oni-files (shared classes) will have no vertex painting.&lt;br /&gt;
:*Animated and pushable objects will have no vertex shading.&lt;br /&gt;
;Vertex shading&lt;br /&gt;
:Vertex colors (vector data) can be painted onto core geometry.&lt;br /&gt;
:They are used as a rudimentary form of lightmapping (pixel data).&lt;br /&gt;
:Having vertex shading is still better than having no vertex shading at all. It makes the level appear more lifelike.&lt;br /&gt;
;Lightmapping&lt;br /&gt;
:In other games, lights and shadows are added to level geometry with lightmapping.&lt;br /&gt;
:There were experiments to bring lightmaps back to Oni. The technique come with a major drawback though. It doubles the triangle count and adds many textures.&lt;br /&gt;
;In-game&lt;br /&gt;
:When you are &amp;quot;inside&amp;quot; the game, running or playing it.&lt;br /&gt;
&lt;br /&gt;
==Level construction==&lt;br /&gt;
&#039;&#039;&#039;Visible environment&#039;&#039;&#039;&lt;br /&gt;
* A &#039;&#039;&#039;level map&#039;&#039;&#039; consists of visible geometry: terrain and buildings. This is also named the &#039;&#039;&#039;environment&#039;&#039;&#039; or for short &#039;&#039;&#039;env&#039;&#039;&#039;.&lt;br /&gt;
** Use &#039;&#039;&#039;quads&#039;&#039;&#039; of approximately 10 up to 20 meters in size to construct env geometry.&lt;br /&gt;
* Anything other than floors and simple walls will be made of triangles.&lt;br /&gt;
** Geometry from CJBO works best with triangles. Quads might show holes in-game.&lt;br /&gt;
&#039;&#039;&#039;Invisible pathfinding&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;AIs&#039;&#039;&#039; (or non-player characters, NPCs) need &#039;&#039;&#039;pathfinding&#039;&#039;&#039; data, usually shortened as &#039;&#039;&#039;bnv&#039;&#039;&#039;.&lt;br /&gt;
** Pathfinding data can be described as geometry, therefore as rooms. These &#039;&#039;&#039;bnv rooms&#039;&#039;&#039; are made of &#039;&#039;&#039;floors&#039;&#039;&#039; and are connected by &#039;&#039;&#039;ghost&#039;&#039;&#039; quads which work like doors. AIs can move from one room to another room only by passing a ghost. Therefore, ghosts have the same width as rooms in open terrain.&lt;br /&gt;
*** Use floor quads of approximately 10 meters in size to construct BNV floors.&lt;br /&gt;
*** Put ghost quads exactly on the edges of BNV floors with an angle of 90 degree.&lt;br /&gt;
&#039;&#039;&#039;Support for [[XML:BINA/ONIE|effects]]&#039;&#039;&#039;&lt;br /&gt;
* Effects such as decals that indicate damaged environment need level textures to be registered in [[XML:BINA/TMBD|TMBD]]. Make sure not to replace existing texture entries but to add your own so that the other levels remain unaffected.&lt;br /&gt;
&#039;&#039;&#039;Level logic&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BSL scripts bring levels fully to life. The logic is mostly event driven whereby different checkpoints and conditions must be reached.&lt;br /&gt;
* Checkpoints are actually [[XML:BINA/OBJC/TRGV|trigger volumes]] that can recognize entering and exiting characters.&lt;br /&gt;
* The second most important source of events are [[XML:BINA/OBJC/CHAR|character (script) functions]], especially the die function of enemies.&lt;br /&gt;
** To support good and less good players alike, NPC characters can feature the UpgradeDifficulty flag. Also, BSL scripts can detect the current [[BSL:Game_status|difficulty level]].&lt;br /&gt;
* [[XML:BINA/OBJC/TRIG|Laser triggers]] are mostly used to control [[XML:BINA/OBJC/TURR|turrets]]. [[XML:BINA/OBJC/CONS|Consoles]], triggers and [[XML:DOOR|door]] unlocking are used to set up very simple &amp;quot;riddles”.&lt;br /&gt;
* The creation of cut scenes is time-consuming quality work. Due to missing tools for streamlined workflows, it is totally okay for you to skip this.&lt;br /&gt;
** New synchronized FILM, OBAN and TRAM files are required for cut scenes. Not to mention sound files for dialog.&lt;br /&gt;
&lt;br /&gt;
==The master XML file==&lt;br /&gt;
&#039;&#039;The project file for level creation.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;master XML&#039;&#039;&#039; file&#039;s &#039;&#039;&#039;name determines&#039;&#039;&#039; the &#039;&#039;&#039;BSL folder name&#039;&#039;&#039; and the &#039;&#039;&#039;AKEV and ONLV file names&#039;&#039;&#039; in the output folder. File paths in the XML can be either absolute or relative.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mandatory files&#039;&#039;&#039; for level import:&lt;br /&gt;
* &#039;&#039;level_environment&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_bnv&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_textures.tga/jpg/png&#039;&#039;&lt;br /&gt;
* Character.xml or AISA with player&lt;br /&gt;
* ONSK name in &amp;lt;Sky&amp;gt; (in Windows, this can be a fake name; does the Mac need actual ONSK files?)&lt;br /&gt;
* ONLD file for the new level; read [[Making_a_mod_package#Mod_Info.cfg|HERE]] about making sure your level is unlocked (accessible on the Load Game screen)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Level SharedPath=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| The master XML file can link to other XML files. Most of them will be [[OBD:BINA/OBJC#OBJC_types|BINACJBO]] files. The file type is declared inside the file, so the file name itself doesn&#039;t have to contain the type. Ergo, &amp;quot;BINACJBOCharacter.xml&amp;quot; can be given a simpler name like &amp;quot;Character.xml&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some resources used by those XML files can be found in a &#039;&#039;&#039;shared&#039;&#039;&#039; folder. OniSplit copies textures and &amp;quot;physics&amp;quot; objects into the output folder; furniture objects will be integrated into the AKEV. Unused resources in the shared folder will be ignored. That way the final level archive or AE package contains only the necessary files, saving disk space for the end user.&lt;br /&gt;
&lt;br /&gt;
In the demo are various subfolders in the &#039;&#039;&#039;shared&#039;&#039;&#039; folder: consoles, doors, furniture, triggers and turrets. These file types do not need their file prefixes: CONS, DOOR, TRIG and OFGA. OniSplit will recognize them nonetheless.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Common mistake:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CJBO files &#039;&#039;&#039;need relative paths to the resource instead of just file names&#039;&#039;&#039;. Taking consoles, for example: a standard export to XML gives you &amp;quot;console_data&amp;quot;. But to use the shared resources these must be paths like &amp;quot;&#039;&#039;&#039;consoles/console_data.oni&#039;&#039;&#039;&amp;quot; as they are stored in &#039;&#039;&#039;shared/console/&#039;&#039;&#039;. Note how the demoed &#039;&#039;&#039;shared&#039;&#039;&#039; folder is placed next to the [http://mods.oni2.net/node/299 project (&amp;quot;lab&amp;quot;)] folder and the XML master file points to it using &amp;quot;../shared&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Environment&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Model&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Used to import level geometry and static objects. See [[#&amp;lt;Model&amp;gt;|HERE]] for detailed information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Node Id=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| informational (space for notes)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Can be used with BSL commands such as ...&lt;br /&gt;
: [[#&amp;lt;Model&amp;gt;|env_show ID 1]] (use 0 to hide)&lt;br /&gt;
: [[#Breakable glass with BSL recognition|env_broken ID1 [ID2]]] (if a second ID is supplied then objects in the range ID1..ID2 get counted; &amp;quot;3001 3018&amp;quot; would cover 18 objects)&lt;br /&gt;
: [[#Texture exchange|env_texswap ID texture]] (no file prefix/suffix allowed)&lt;br /&gt;
: [[#env_shade|env_shade ID ID R G B]]&lt;br /&gt;
Static objects store their ID in [[XML:AKEV#IDXA_.28quad_group_id.29|one of AKEV&#039;s IDXA instances]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Rooms&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| For detailed information see [[#&amp;lt;Rooms&amp;gt;|HERE]].&lt;br /&gt;
&lt;br /&gt;
For a Google SketchUp BNV tutorial see [http://oni.bungie.org/forum/viewtopic.php?pid=36760#p36760 HERE].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. BNV data, used to create pathfinding.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Textures&amp;gt; {{Anchor|textures_tag}}&lt;br /&gt;
| -&lt;br /&gt;
| With OniSplit v0.9.94.0+ you can use attributes to set the default import formats and max dimensions. For example:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Textures with a dimension that isn&#039;t a power of two (2&amp;lt;sup&amp;gt;x&amp;lt;/sup&amp;gt;) and textures larger than 512px on a side will be resized. For example, 2003x2000 will become 512x512. (What would 257x255 become?)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Texture Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| TXMP file name to generate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Flags&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Optional tag. For list of flags see [[XML:TXMP|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Format&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
:DXT1&lt;br /&gt;
:BGR&lt;br /&gt;
:RGBA&lt;br /&gt;
:BGR555&lt;br /&gt;
:BGRA5551&lt;br /&gt;
:BGRA4444&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Image&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.tga/jpg file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Sky&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| ONSKfile.oni (without file pre- and suffix)&lt;br /&gt;
&lt;br /&gt;
The import doesn&#039;t work with an empty tag. &amp;lt;Sky&amp;gt;clear&amp;lt;/Sky&amp;gt; helps here; any other fictional name will also do.&lt;br /&gt;
&lt;br /&gt;
For detailed information see [[XML:ONSK|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Import&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to an OBJC (collection) file. Supported collection files for &amp;lt;Import&amp;gt; are:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[#Furniture.xml|Furniture.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[#Physics.xml|Physics.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
The following two collection files are &#039;&#039;&#039;NOT&#039;&#039;&#039; supported. You need to copy them as regular pre-compiled *.oni files into your mod package:&lt;br /&gt;
: [[XML:BINA/OBJC/MELE|Melee.xml]] (overrides global MELE; not used in vanilla levels)&lt;br /&gt;
: [[XML:BINA/OBJC/CMBT|Combat.xml]] (overrides global CMBT?; not used in vanilla levels)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Inside&#039;&#039;&#039; the following three supported collection files, provide links to pre-compiled (*.oni) class files: console, door and furniture collections. Use relative paths such as:&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;consoles/&#039;&#039;&#039;console_data&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;doors/&#039;&#039;&#039;TCdouble&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;furniture/&#039;&#039;&#039;V_tctf_bigvan&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you are unsure about the folder structure refer back to the [http://mods.oni2.net/node/299 level import demo].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Films&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.xml file. OniSplit creates a [[XML:FILM|FILM]] file from it. Used for characters in cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Cameras&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Camera Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. OniSplit creates an OBAN file from it. Used for cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Name for the OBAN file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a trimmed-down version of the master file &#039;&#039;&#039;lab.xml&#039;&#039;&#039; from the demo. It&#039;s meant to give you a first impression. We might upload a smaller demo someday with all features nonetheless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Level SharedPath=&amp;quot;../shared&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Environment&amp;gt;&lt;br /&gt;
            &amp;lt;Model&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bomber_window.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;/Model&amp;gt;&lt;br /&gt;
            &amp;lt;Rooms&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Rooms&amp;gt;&lt;br /&gt;
            &amp;lt;Textures&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;bgra4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
            &amp;lt;/Textures&amp;gt;&lt;br /&gt;
        &amp;lt;/Environment&amp;gt;&lt;br /&gt;
        &amp;lt;Sky&amp;gt;sunset&amp;lt;/Sky&amp;gt;&lt;br /&gt;
        &amp;lt;Objects&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Character.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Furniture.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;TriggerVolume.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Physics.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Objects&amp;gt;&lt;br /&gt;
        &amp;lt;Films&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun01.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun02.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Films&amp;gt;&lt;br /&gt;
        &amp;lt;Cameras&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam01.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam01&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam02.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam02&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
        &amp;lt;/Cameras&amp;gt;&lt;br /&gt;
    &amp;lt;/Level&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Model&amp;gt;===&lt;br /&gt;
This tag is mandatory (it must be present to avoid errors); the model section contains one import path to the AKEV (level) geometry (*.dae) and can contain additional import paths for exceptions (*.dae).&lt;br /&gt;
&lt;br /&gt;
Data from the demo:&lt;br /&gt;
&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;env_show&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The motorcycle has here scripting ID 9. You can show and hide the object with the BSL command &#039;&#039;&#039;env_show&#039;&#039;&#039;, where the second parameter means true or false. &#039;&#039;&#039;Never use 0 as an ID&#039;&#039;&#039; because it won&#039;t work.&lt;br /&gt;
&lt;br /&gt;
 env_show 9 1&lt;br /&gt;
 env_show 9 0&lt;br /&gt;
&lt;br /&gt;
EdT demonstrates env_show [https://www.youtube.com/watch?v=Em6wa5JTQNM here]. Note how the objects have collision.&lt;br /&gt;
&lt;br /&gt;
The last vanilla level (Syndicate Mountain Compound) has a big satellite dish platform that can be made hidden. Obviously, such objects/areas can be made to have pathfinding too.&lt;br /&gt;
&lt;br /&gt;
;More possible applications of env_show:&lt;br /&gt;
* ground/ceiling/objects for cutscenes that become partially destroyed&lt;br /&gt;
* destructible walls like in Deus Ex: Human Revolution (trigger volume, replacing punch anim with punch-through-wall anim)&lt;br /&gt;
* grids in front of ventilation shafts (a small door object could be an alternative)&lt;br /&gt;
** at the moment this can&#039;t be done because characters can&#039;t sneak under the top edge of the opening (the characters collision spheres are too big)&lt;br /&gt;
* managing object groups with trigger volumes (save multiple objects in one DAE file)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- atm, the effort is not worth the work&lt;br /&gt;
&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/TV_triggered_env_show.png&amp;lt;/nowiki&amp;gt; (dead link)&lt;br /&gt;
: edit: replace 0 by 25&lt;br /&gt;
&lt;br /&gt;
If the objects appear to flicker then we could replace the hide_all_object_groups() function with individual TV exit functions.&lt;br /&gt;
&lt;br /&gt;
 func hide_all_object_groups&lt;br /&gt;
 {&lt;br /&gt;
 	# env_show id [1|0]&lt;br /&gt;
 	env_show 1 0&lt;br /&gt;
 	env_show 2 0&lt;br /&gt;
 	# ...&lt;br /&gt;
 	env_show 25 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func show_object_group (int grpA, int grpB, int grpC, int grpD, int grpE, int grpF, int grpG, int grpH)&lt;br /&gt;
 {&lt;br /&gt;
 	env_show (grpA, 1)&lt;br /&gt;
 	env_show (grpB, 1)&lt;br /&gt;
 	env_show (grpC, 1)&lt;br /&gt;
 	env_show (grpD, 1)&lt;br /&gt;
 	env_show (grpE, 1)&lt;br /&gt;
 	env_show (grpF, 1)&lt;br /&gt;
 	env_show (grpG, 1)&lt;br /&gt;
 	env_show (grpH, 1)&lt;br /&gt;
 &lt;br /&gt;
 	# missing arguments are taken to be 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_25_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 &lt;br /&gt;
 	# show object group of entered TV and of neighboring TVs&lt;br /&gt;
 	# (center, north, north east, east, east south, south, south west, west, west north)&lt;br /&gt;
 	# there&#039;s a limit of 8 arguments per function&lt;br /&gt;
 	show_object_group 25 1 2 3 4 5 6 7&lt;br /&gt;
 	show_object_group 8&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # other examples&lt;br /&gt;
 func TV_6_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 0 0 00 0 00 00 00 00&lt;br /&gt;
 	show_object_group 22&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_20_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 20 21 6 19&lt;br /&gt;
 }&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Import of object groups====&lt;br /&gt;
&#039;&#039;&#039;Mod Tool versus SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The meaning and behavior of &amp;quot;groups&amp;quot; greatly differs in these two programs.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In SketchUp&#039;&#039;&#039; you can group objects which enables you to easily duplicate all objects inside a group and to scale/rotate/translate them all together.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In Mod Tool&#039;&#039;&#039; grouped objects are still loose, and duplicating a group won&#039;t duplicate the objects. To achieve the same effect as in SketchUp, you have to create a hierarchy where any one object is the &amp;quot;parent&amp;quot; and all others the &amp;quot;children&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Google SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a group, select two or more objects, right-click on the selection and choose &amp;quot;make group&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:ModTool_can_import_objs_in_hierarchies.jpg|right|thumb|Mod Tool can import objects in hierarchies to Oni.]]&lt;br /&gt;
&#039;&#039;&#039;Mod Tool&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either use the Explorer (A) or the Schematics (B) to create a hierarchy.&lt;br /&gt;
&lt;br /&gt;
:(A) In the Explorer window, drag and drop one or more objects onto another one.&lt;br /&gt;
&lt;br /&gt;
:(B) Open the constrain tab at the right side. Select parent object, click &amp;quot;Parent&amp;quot;, click the child object(s). Check the result in the Schematics window.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Mod Tool: caution when saving to DAE!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:A normal selection won&#039;t do. You have to select the object tree to successfully save a hierarchy. This is the same way that you do it with Oni characters.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=====Import of smart object groups=====&lt;br /&gt;
Let&#039;s say there are two groups. If an edit is made to one mesh, the clone in the other group is instantly changed the same way.&lt;br /&gt;
&lt;br /&gt;
So that&#039;s a smart group. In SketchUp this is named &amp;quot;component&amp;quot;. In Mod Tool it&#039;s named ???.&lt;br /&gt;
:(Can be imported from SketchUp DAE file but causes a crash when re-saving. I guess a script is needed to do the job.)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Breakable glass with BSL recognition====&lt;br /&gt;
Broken environmental objects can be recognized by the BSL command &#039;&#039;env_broken (ID_1, ID_N)&#039;&#039;. However, this requires additional code to work.&lt;br /&gt;
&lt;br /&gt;
An example is the training level. Let&#039;s determine how we can set up such a thing.&lt;br /&gt;
&lt;br /&gt;
First we need a [[XML:BINA/OBJC/TRGV|trigger volume]] like in level 1.&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;TRGV Id=&amp;quot;11495&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Locked&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-714.6615 -298 -555.2073&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;0 0 0&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;tv75&amp;lt;/Name&amp;gt;&lt;br /&gt;
                &amp;lt;Scripts&amp;gt;&lt;br /&gt;
                    &amp;lt;Entry&amp;gt;&amp;lt;/Entry&amp;gt;&lt;br /&gt;
                    &amp;lt;Inside&amp;gt;targets_gone&amp;lt;/Inside&amp;gt;&lt;br /&gt;
                    &amp;lt;Exit&amp;gt;&amp;lt;/Exit&amp;gt;&lt;br /&gt;
                &amp;lt;/Scripts&amp;gt;&lt;br /&gt;
                &amp;lt;Teams&amp;gt;255&amp;lt;/Teams&amp;gt;&lt;br /&gt;
                &amp;lt;Size&amp;gt;400 31 270&amp;lt;/Size&amp;gt;&lt;br /&gt;
                &amp;lt;TriggerVolumeId&amp;gt;75&amp;lt;/TriggerVolumeId&amp;gt;&lt;br /&gt;
                &amp;lt;ParentId&amp;gt;0&amp;lt;/ParentId&amp;gt;&lt;br /&gt;
                &amp;lt;Notes&amp;gt;&amp;lt;/Notes&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;PlayerOnly&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/TRGV&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need some BSL code.&lt;br /&gt;
&lt;br /&gt;
 var int inside_target_function;&lt;br /&gt;
 &lt;br /&gt;
 func void enter_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint enter_target_function&lt;br /&gt;
    inside_target_function = 1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void exit_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint exit_target_function&lt;br /&gt;
    inside_target_function = 0;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_are_not_gone(void)&lt;br /&gt;
 {&lt;br /&gt;
 	# CB: turn off the trigger volume and sleep for a second&lt;br /&gt;
 	# so as not to cause hideous performance loss&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	sleep 60&lt;br /&gt;
 	trigvolume_enable tv75 1&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_gone(string ai_name)&lt;br /&gt;
 {&lt;br /&gt;
 	if (inside_target_function eq 0)&lt;br /&gt;
 	{	&lt;br /&gt;
 		enter_target_function() # catch other &amp;quot;targets_gone&amp;quot; functions to let them do nothing&lt;br /&gt;
 &lt;br /&gt;
 		var int num_broken = env_broken(3001, 3018);&lt;br /&gt;
 		# if you only one target use scheme: env_broke(3001, 3001)&lt;br /&gt;
 &lt;br /&gt;
 		if (num_broken eq 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_gone();&lt;br /&gt;
 		}&lt;br /&gt;
 	&lt;br /&gt;
 		if (num_broken &amp;lt; 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_not_gone(); # to set check interval to one second&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		exit_target_function&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func targets_are_gone&lt;br /&gt;
 {&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	# [...]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
;Explanation:&lt;br /&gt;
&lt;br /&gt;
Player enters the TV, targets_gone() gets triggered. The variable &amp;quot;inside_target_function&amp;quot; should be 0 by default, so we will enter the &amp;quot;if&amp;quot; block. Next, we can assume that the player didn&#039;t destroy all glass objects, so &amp;quot;num_broken&amp;quot; will be less than 18; thus, targets_are_not_gone() gets called.&lt;br /&gt;
&lt;br /&gt;
The TV function targets_gone() &#039;&#039;would&#039;&#039; be triggered every frame, but targets_are_not_gone() creates a delay between checks: the TV gets deactivated for 60 frames. Then the TV becomes enabled again and will start anew until all glass objects got destroyed or player left the TV.&lt;br /&gt;
&lt;br /&gt;
In this case the targets_gone() function will do nothing because &amp;quot;inside_target_function&amp;quot; was set to 1 by the first call.&lt;br /&gt;
&lt;br /&gt;
targets_are_gone() eventually disables the TV to prevent memory overflow; this function also contains all the things (&amp;quot;[...]&amp;quot;) that you want to happen after the glass target is broken.&lt;br /&gt;
&lt;br /&gt;
====Texture exchange====&lt;br /&gt;
BSL command supported on Windows and Mac:&lt;br /&gt;
: env_texswap ID texture&lt;br /&gt;
&lt;br /&gt;
Might be useful to switch on/off static and animated textures. (News broadcast screen: running or off or smashed. Lava stream: flowing or stagnating or cooled down. Etc.)&lt;br /&gt;
&lt;br /&gt;
A similar effect can be achieved by showing/hiding geometries with different textures as EdT has demonstrated in a private test. That way it should also be possible to have different vertex coloring for an area.&lt;br /&gt;
&lt;br /&gt;
====Vertex coloring====&lt;br /&gt;
Vertex colors can be edited manually in Blender by setting up following 3 things:&lt;br /&gt;
* Properties Panel &amp;gt; Data &amp;gt; Color Attributes&amp;lt;!--only tested with Face Corner, Byte Color--&amp;gt;&lt;br /&gt;
* 3D viewport (left top) &amp;gt; change work mode to Vertex Paint&lt;br /&gt;
* 3D viewport (right top) &amp;gt; change to Viewport Shading to Solid mode (under the dropdown menu you can choose &amp;quot;flat&amp;quot; to have full saturation)&lt;br /&gt;
&lt;br /&gt;
{{divhide|Mod Tool}}&lt;br /&gt;
&lt;br /&gt;
[http://web.archive.org/web/20170529111607/http://softimage.wiki.softimage.com/xsidocs/tex_vcolor_CreatingColoratVerticesCAVMaps.htm SoftImage documentation.] Observation: The sniper tower from level 19 Syndicate Mountain Compound can be isolated and re-imported as it is. It will appear quite dark.&lt;br /&gt;
&lt;br /&gt;
If we remove &amp;quot;_color&amp;quot; from the object, the shadows will be gone next time we import the tower.&lt;br /&gt;
&lt;br /&gt;
Mod Tool: Explorer [8]&lt;br /&gt;
&lt;br /&gt;
 Object&lt;br /&gt;
  |&lt;br /&gt;
  +-- Polygon Mesh&lt;br /&gt;
        |&lt;br /&gt;
        +-- Cluster&lt;br /&gt;
              |&lt;br /&gt;
              +-- Polygon&lt;br /&gt;
              |     |&lt;br /&gt;
              |     +-- [...]&lt;br /&gt;
              |&lt;br /&gt;
              +-- NodeProperties&lt;br /&gt;
                    |&lt;br /&gt;
                    +-- &#039;&#039;&#039;_color&#039;&#039;&#039;&lt;br /&gt;
                    +-- texcoord (Explicit UVWs)&lt;br /&gt;
                          |&lt;br /&gt;
                          +-- Vertex_Color_Def&lt;br /&gt;
&lt;br /&gt;
So, how do we modify that data?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Single object shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If there&#039;s already a vertex color property, you can use Shift + W to activate the Paint Vertex Color Tool. With Control + W you can change the brush color. R + Hold Click + Move Mouse let you change the brush size. The more vertices (points) you have, the more detailed you can make the shadows/colors. But keep in mind that too many polygons can destroy collision, making characters fall through the ground.&lt;br /&gt;
&lt;br /&gt;
If there&#039;s no vertex color property, the first usage of Shift + W will create that property. But you can also manually create it via Property &amp;gt; Color under Vertices Map.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Level-wide shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:light_test_modtool.png|right|thumb]]&lt;br /&gt;
[[Image:light_test_ingame.png|right|thumb]]&lt;br /&gt;
&lt;br /&gt;
To get general shading/lighting you can set up light sources. &amp;quot;Infinite&amp;quot; lights are useful for global lighting, while &amp;quot;Light Box&amp;quot;, &amp;quot;Point&amp;quot;, &amp;quot;Neon&amp;quot; and &amp;quot;Spot&amp;quot; are more suitable as local light sources. They can be accessed via Primitives &amp;gt; Light.&lt;br /&gt;
&lt;br /&gt;
By default, a Mod Tool scene has one Infinite light, but it doesn&#039;t shine in every direction so you might want to add more Infinite lights. Let&#039;s say one Infinite light for each direction (+X, -X, +Y, -Y, +Z, -Z) with an intensity of circa 0.25 (night) or 0.75 (day).&lt;br /&gt;
&lt;br /&gt;
The illumination of those lights can be integrated into the vertex color property. There&#039;s some information [https://web.archive.org/web/20201029114108/http://oni.bungie.org/forum/viewtopic.php?pid=29089#p29089 on OCF here]; the quoted information is in triplicate, so don&#039;t get confused by that: at first it&#039;s detailed, then summarized, then as a checklist.&lt;br /&gt;
&lt;br /&gt;
Basically, you can go with the checklist:&lt;br /&gt;
&lt;br /&gt;
* Property &amp;gt; Color At Vertices Map&lt;br /&gt;
* Property &amp;gt; Render Map&lt;br /&gt;
* In render map property page, under Sampling select Vertices Only&lt;br /&gt;
* Under Surface Color, choose Enable, then in the box below select Vertex _Color; if that option does not appear, click on the New button next to it&lt;br /&gt;
* Under Map, select Illumination only&lt;br /&gt;
* Finally, click on the button Regenerate Maps...&lt;br /&gt;
&lt;br /&gt;
This must be done for all objects separately.&lt;br /&gt;
&lt;br /&gt;
: [http://mods.oni2.net/system/files/vertex_color_script.txt There&#039;s a script here]&amp;lt;!--http://mods.oni2.net/node/352--&amp;gt; which can apply vertex color and render maps to all &#039;&#039;&#039;selected&#039;&#039;&#039; objects. Load it into the script editor with Alt + 4 and hit F5 to run it. (Be sure the script&#039;s language was set to VBScript.)&lt;br /&gt;
: The variable &amp;quot;overwrite_VC&amp;quot; can be changed.&lt;br /&gt;
:: With &amp;quot;1&amp;quot; all existing CAV maps of selected objects will be overwritten. This can take some time.&lt;br /&gt;
:: With &amp;quot;0&amp;quot; only selected objects without CAV maps will be the script&#039;s target.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes on ModTool view modes&#039;&#039;&#039;&lt;br /&gt;
* &amp;quot;Constant&amp;quot; let you see the colors of the vertex coloring only.&lt;br /&gt;
* &amp;quot;Textured Decal&amp;quot; let you see object textures only.&lt;br /&gt;
* &amp;quot;Shaded&amp;quot; let you see the illumination only.&lt;br /&gt;
* &amp;quot;Textured&amp;quot; let you see the textured object with illumination and vertex coloring.&lt;br /&gt;
{{divhide|end}}&lt;br /&gt;
&lt;br /&gt;
=====env_shade=====&lt;br /&gt;
If you use &#039;&#039;&#039;env_shade&#039;&#039;&#039;, use it with caution. It completely overwrites the vertex coloring.&lt;br /&gt;
&lt;br /&gt;
 # BSL command&lt;br /&gt;
 # env_shade obj_id obj_id R G B&lt;br /&gt;
 &lt;br /&gt;
 # examples&lt;br /&gt;
 env_shade 7 7			# object 7 will be black&lt;br /&gt;
 env_shade 7 7 0 0 0		# object 7 will be black&lt;br /&gt;
 env_shade 7 7 .31 .999 .5	# object 7 will be quite green&lt;br /&gt;
 env_shade 7 10 1 1 1		# object 7, 8, 9, 10 lose all their shading&lt;br /&gt;
&lt;br /&gt;
====Baked lightmaps====&lt;br /&gt;
A drawback of this method, AKA shadow maps, is the high number of [[XML:BINA/TMBD|TMBD]] changes and new textures for every wall, requiring a lot of memory. How to create shadow maps:&lt;br /&gt;
&lt;br /&gt;
* https://web.archive.org/web/20121105081823/http://www.game-artist.net/forums/support-tech-discussion/5622-burning-shadows-onto-texture-xsi.html&lt;br /&gt;
&amp;lt;!-- http://caffeineabuse.blogspot.de/2008/12/cast-shadow-only-lights-in-xsi.html might be also interesting --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on map options:&lt;br /&gt;
* &amp;quot;Surface color and illumination&amp;quot;: outputs used texture with added shadows&lt;br /&gt;
** Can be used to replace original texture&lt;br /&gt;
* &amp;quot;Illumination only&amp;quot;: output a texture that only contains the shadows&lt;br /&gt;
** Can be used on a new overlying, transparent surface&lt;br /&gt;
&lt;br /&gt;
====Standalone lightmaps====&lt;br /&gt;
With this approach there are two meshes, whereby the shadow effects on one mesh get drawn in front of the regular level texture.&lt;br /&gt;
&lt;br /&gt;
Compared to the &amp;quot;baked lightmaps&amp;quot; method, this needs more polygons of course. And these polygons are transparent, which is a problem with Oni&#039;s limited rendering ability for such textures. However, standalone lightmaps only need a few new textures if used wisely.&lt;br /&gt;
&lt;br /&gt;
Read [[Lightmapping levels]] to learn more.&lt;br /&gt;
&lt;br /&gt;
[[Image:Oni_Lightmaps_double_polygon_method.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Rooms&amp;gt;===&lt;br /&gt;
The Rooms tag is mandatory. It contains an import path to BNV and ghosts (*.dae) which are used to create pathfinding grids. For information on the binary data behind this, see [[OBD:AKVA|HERE]].&lt;br /&gt;
&lt;br /&gt;
Sample code from the master XML file:&lt;br /&gt;
 &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fundamentals&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;BNVs&#039;&#039;&#039; are &#039;&#039;&#039;volumes&#039;&#039;&#039; (sometimes also named &#039;&#039;&#039;rooms&#039;&#039;&#039;) that have a pathfinding grid assigned to them.&lt;br /&gt;
* For practical reasons you only need &#039;&#039;&#039;floors and ramps&#039;&#039;&#039; to build a BNV. (As seen [http://edt.oni2.net/images/Hideout_BNV.jpg HERE.])&lt;br /&gt;
** A BNV polygon can consist of 3 or more points, but it&#039;s recommended to use &#039;&#039;&#039;shapes with 4 points&#039;&#039;&#039; because the other shapes usually waste more grid space. At the moment you can import only &#039;&#039;&#039;[[wikt:convex|convex]]&#039;&#039;&#039; shapes.&lt;br /&gt;
* Secondly, there are so called &#039;&#039;&#039;ghosts&#039;&#039;&#039; (vertical quads) that connect &#039;&#039;&#039;neighboring BNVs&#039;&#039;&#039;. AI can only transit from BNV to another through ghosts.&lt;br /&gt;
: OniSplit gives error messages for ghosts that don&#039;t have 2 neighboring BNVs, for example:&lt;br /&gt;
 BNV Builder: Ghost &#039;grid2&#039; has no adjacencies at &amp;lt;-72,41 1,999 -166,6&amp;gt; and &amp;lt;-71 1,999 -168,21&amp;gt;, ignoring&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tolerance values&#039;&#039;&#039;&lt;br /&gt;
* Horizontal distance from room to ghost: 1&lt;br /&gt;
* Vertical distance from room to ghost: 18&lt;br /&gt;
* Ghost&#039;s horizontal dimension must be greater than 0&lt;br /&gt;
* Under optimal circumstances, pathfinding works on a plane that is +4 world units above or -0.5 below the pathfinding grid&lt;br /&gt;
* Normally characters can&#039;t pass over low vertical walls such as stairs/curbs if those don&#039;t have a ramp under them; near ground level (Y=0) is an exception where characters are allowed to step on a plane that is 4 world units above pathfinding grid; higher planes need a ramp&lt;br /&gt;
* Maximum angle of ramp you can go on is 70°; higher angles will make characters fall through to their death (in those cases you might want to add invisible walls/boxes to prevent them from touching the ramp)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;More notes on PF processing&#039;&#039;&#039;&lt;br /&gt;
* Actually, BNV and ghosts can have any name and don&#039;t need any texture.&lt;br /&gt;
* During pathfinding calculation, OniSplit creates a new folder called &amp;quot;temp&amp;quot; and a subfolder &amp;quot;grids&amp;quot;. There is a file named &amp;quot;&#039;&#039;levelname&#039;&#039;_grids.dae&amp;quot;. That file contains rooms with textures called &amp;quot;bnv_grid_&#039;&#039;N&#039;&#039;.tga&amp;quot; which mark obstacles in the pathfinding grid. Ghosts will have a transparent texture &amp;quot;&#039;&#039;&#039;_marker_ghost&#039;&#039;&#039;.tga&amp;quot;. You also get these when you export a level. Transparent ghosts make it easier to see the rest of your level if you have many of those planes.&lt;br /&gt;
* In Mod Tool, ghosts and rooms can be grouped under a null object. Right-click the null object to select all its children, then use &amp;quot;Selection Only [x]&amp;quot; as your saving option. That way all the planes can be quickly saved to a *.dae file.&lt;br /&gt;
* You can influence the pathfinding creation of dangerous zones using danger quads. Read about those [[#Marker textures|HERE]].&lt;br /&gt;
* Another kind of influence is the [[#&amp;lt;Model&amp;gt;|gunk flag]] IgnoreGrid. It can be used to tell OniSplit to ignore the object during pathfinding creation. The grids in that place will be white.&lt;br /&gt;
&lt;br /&gt;
[[Image:Pathfinding_grid.jpg|thumb|200px|right|&#039;&#039;&#039;ai2_showgrids = 1&#039;&#039;&#039; in action]]&lt;br /&gt;
&#039;&#039;&#039;BSL commands&#039;&#039;&#039;&lt;br /&gt;
* chr_show_bnv = 1&lt;br /&gt;
:: shows number of BNVs the player is standing on&lt;br /&gt;
* ai2_showgrids = 1&lt;br /&gt;
:: shows pathfinding grids&lt;br /&gt;
* ai2_chump&lt;br /&gt;
:: spawns a friendly Striker that follows the player if possible, makes also pathfinding grids visible&lt;br /&gt;
* ai2_chump_stop = 1&lt;br /&gt;
:: Striker stops following you&lt;br /&gt;
* ai2_chump_stop = 0&lt;br /&gt;
:: Striker follows you again&lt;br /&gt;
&lt;br /&gt;
====Pathfinding on uneven ground====&lt;br /&gt;
Pathfinding works on slightly uneven ground as long as the polygons are 0.5 world units beneath or 4 world units above the BNV.&lt;br /&gt;
&lt;br /&gt;
For greater surface irregularities, we can use a trick:&lt;br /&gt;
* The problematic polygons must be saved to a DAE file and then referenced in the model section as an individual object.&lt;br /&gt;
* Then the &amp;lt;GunkFlags&amp;gt; tag needs to be &#039;&#039;&#039;&#039;&#039;GridIgnore&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Additionally we create a plane (invisible if necessary) under the object so that Oni doesn&#039;t think there&#039;s a hole.&lt;br /&gt;
* The ghosts must be taller than the highest polygon to be walked on. (This has been tested up to a height of 2,000 world units.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms of too-small ghosts&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A) AI can&#039;t run at all.&lt;br /&gt;
&lt;br /&gt;
B) AI loses PF ability if the tracked enemy performs animations that are outside of the pathfinding volume. Here&#039;s a video (&amp;lt;nowiki&amp;gt;https://youtu.be/vfKPzP5hiCo&amp;lt;/nowiki&amp;gt;, dead link) showing these symptoms.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Missing boundaries&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say you have a BNV, tall ghosts, and a GridIgnore-flagged hill with trees and bushes and stuff.&lt;br /&gt;
&lt;br /&gt;
Why do AIs run up against the trees?&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; There are no red/orange grids that limit the AI&#039;s movement. Normally, objects will produce red pathfinding squares around them. But objects that are 20 world units above the BNV are ignored just like objects with the IgnoreGrid flag.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Add simple geometries like &#039;&#039;_marker_impassable fences&#039;&#039; or danger quads near the BNV.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Disappearing AIs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The ground is sometimes not solid, and the player and AIs are falling through it.&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; On GridIgnore-flagged uneven ground, AIs can fall through it when they are out of the player&#039;s view.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Use either &#039;&#039;&#039;chr_lock_active &#039;&#039;AI_name&#039;&#039;&#039;&#039;&#039; or &#039;&#039;&#039;chr_all_active = 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Debugging====&lt;br /&gt;
&#039;&#039;&#039;(OniSplit v0.9.93.0+)&#039;&#039;&#039;&lt;br /&gt;
[[Image:OniBrowser.jpg|thumb|200px|right|OniBrowser displaying level geometry plus PF and ghosts.]]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;env_show_ghostgqs = 1&#039;&#039;&#039; makes the ghost quads visible&lt;br /&gt;
** The original ghost quads can&#039;t be seen; per Neo, &amp;quot;they are not included in the octtree and bsp tree&amp;quot;&lt;br /&gt;
** To see them you must use the -debug option in the level creation command (available with OniSplit &#039;&#039;&#039;v0.9.93.0+&#039;&#039;&#039;)&lt;br /&gt;
 OniSplit.exe -create:level &#039;&#039;output_folder&#039;&#039; &#039;&#039;&#039;-debug&#039;&#039;&#039; &#039;&#039;input_folder&#039;&#039;/&#039;&#039;master_xml_file&#039;&#039;.xml&lt;br /&gt;
&lt;br /&gt;
Not all debugging/testing needs to be done in Oni. There is also a [http://mods.oni2.net/node/256 program] (Windows only) which can display the whole level.&lt;br /&gt;
&lt;br /&gt;
For example you can load an AKEV*.oni, select the level name, and use the hotkeys [B] and [P] to display BNVs and ghosts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bug prevention:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
After all testing is done, you should compile the level a last time without the -debug option.&lt;br /&gt;
&lt;br /&gt;
AIs appear to have trouble shooting through ghost quads that got registered in the octtree/BSP tree as seen here (&amp;lt;nowiki&amp;gt;https://www.youtube.com/watch?v=-ZugVBgBVKc&amp;lt;/nowiki&amp;gt;, dead link).&lt;br /&gt;
&lt;br /&gt;
====When OniSplit fails to connect PF quads====&lt;br /&gt;
[[Image:Pathfinding_creation__merge_polygons_to_fix_connections.jpg|thumb|200px|right|Fixed PF in compound level after underground construction...]]&lt;br /&gt;
It can help to merge polygons to one object and merge their edges. These become white. (Outer edges are blue.)&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Textures&amp;gt;===&lt;br /&gt;
====...used for exceptions====&lt;br /&gt;
The [[#textures_tag|textures tag]] is mandatory.&lt;br /&gt;
&lt;br /&gt;
AKEV textures will be imported by the master XML file automatically; you don&#039;t need to add them to that file.&lt;br /&gt;
&lt;br /&gt;
: With OniSplit v0.9.82-93.0, the textures&#039; formats will be DXT1 and (for transparent ones) BGRA4444.&lt;br /&gt;
: With OniSplit v0.9.94.0+ the textures&#039; formats will be BGR and (for transparent ones) RGBA.&lt;br /&gt;
&lt;br /&gt;
To change the default texture import format, use the Texture&#039;&#039;&#039;s&#039;&#039;&#039; tag. (Possible with OniSplit v0.9.94.0+.)&lt;br /&gt;
&lt;br /&gt;
To change the format/flag/gunk flag of a specific texture, use the Texture tag.&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&lt;br /&gt;
          &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;TwoSided&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;BGRA4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
          &amp;lt;/Textures&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use the gunk flag &amp;quot;TwoSided&amp;quot; to make surfaces visible from both sides.&lt;br /&gt;
* If the texture comes with the gunk flag &amp;quot;NoCollision&amp;quot; then all objects with that texture will have no collision. Characters would fall through it.&lt;br /&gt;
&lt;br /&gt;
Transparency and no collision together would make sense for a water-like substance. The Vago Biotech level uses this approach for the area with green toxic waste.&lt;br /&gt;
&lt;br /&gt;
[[Image:making_a_surface_transparent_and_twosided.png|thumb|200px|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures.png|thumb|200px|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;&amp;lt;br&amp;gt;one object with multiple textures, one per polygon cluster]]&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures_ingame.png|thumb|200px|right|&#039;&#039;&#039;Figure 3&#039;&#039;&#039;&amp;lt;br&amp;gt;blue: two-sided&amp;lt;br&amp;gt;glass: two-sided and transparent&amp;lt;br&amp;gt;random metal: no flag (one-sided)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TwoSided and transparent objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s also possible to set this in Mod Tool. For TwoSided-ness, use one image source for diffuse and transparency. (It won&#039;t work with two image sources even if both sources use the same image.)&lt;br /&gt;
&lt;br /&gt;
For transparency you must additionally use the three checkboxes:&lt;br /&gt;
* Transparency: Enable&lt;br /&gt;
* Transparency: Use Alpha&lt;br /&gt;
* Transparency: Invert&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;Figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Regular textures====&lt;br /&gt;
OniSplit automatically imports textures of objects in the [[#&amp;lt;Model&amp;gt;|&amp;lt;Model&amp;gt; section]]. Those objects could be considered as AKEV core geometry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;One texture per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Furniture and Physics objects are allowed to have only one texture per object. AKEV core geometry can have one texture or multiple textures – that&#039;s up to you to decide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multiple textures per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question:&#039;&#039;&#039; How do we apply multiple textures to an AKEV core object?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Answer:&#039;&#039;&#039; Assuming you are using Mod Tool the procedure will be as follows. Repeat this for each cluster you create (except for projection). See also &#039;&#039;&#039;Figure 2 and 3&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Select some polygons&lt;br /&gt;
* Go to Material &amp;gt; Phong&lt;br /&gt;
* Hit [7] to open Render Tree&lt;br /&gt;
* Add a texture and connect &amp;quot;Image&amp;quot; with &amp;quot;Phong&amp;quot;, choose &amp;quot;diffuse&amp;quot; as illumination mode&lt;br /&gt;
* Double-click &amp;quot;Image&amp;quot; to open Material page&lt;br /&gt;
* In the Texture Projection section, click on &amp;quot;New&amp;quot; and choose a suitable projection&lt;br /&gt;
** Do this only if there isn&#039;t a projection in the &amp;quot;Texture_Coordinates_AUTO&amp;quot; cluster yet&lt;br /&gt;
** OniSplit processes only one texture projection, see &#039;&#039;&#039;Figure 4&#039;&#039;&#039;&lt;br /&gt;
* Choose the texture and UV, then fine-tune the UV via Alt + 7&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_multiple_textures_one_projection.png|thumb|200px|right|&#039;&#039;&#039;Figure 4&#039;&#039;&#039;&amp;lt;br&amp;gt;use only one texture projection per object]]&lt;br /&gt;
&lt;br /&gt;
Caution: textures will be fixed to one set of flags. You can&#039;t use the same texture A for a one-sided cluster/object B and a two-sided cluster/object C. You would need to create a differently-named clone of that texture and apply that to cluster/object C.&lt;br /&gt;
&lt;br /&gt;
====Marker textures====&lt;br /&gt;
Marker textures are used to import certain objects with special flags. Import those objects alongside [[#&amp;lt;Model&amp;gt;|AKEV core]] geometry.&lt;br /&gt;
&lt;br /&gt;
Marker textures aren&#039;t imported automatically. Add those textures to the final package or plugin yourself, e.g. with some sort of script.&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
The flags Transparent, TwoSided and NoOcclusion are only set if the same texture source is used for diffuse and transparency and if transparency setting are enabled. See the subsection under &amp;quot;[[#...used for exceptions|...used for exceptions]]&amp;quot; called &amp;quot;TwoSided and transparent objects&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Danger quads&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pathfinding grids have different colored squares with different meanings.&lt;br /&gt;
* white/gray - clear space&lt;br /&gt;
* green light - near wall&lt;br /&gt;
* green - semi-passable&lt;br /&gt;
* green dark - stairs&lt;br /&gt;
* blue very light - border 1&lt;br /&gt;
* blue light - border 2&lt;br /&gt;
* blue - border 3&lt;br /&gt;
* blue dark - border 4&lt;br /&gt;
* &#039;&#039;&#039;orange - danger&#039;&#039;&#039;&lt;br /&gt;
* red - impassable&lt;br /&gt;
&lt;br /&gt;
For detailed information on colors, see [[OBD_talk:AKVA/0x24#EFFECTS_of_various_pathfinding_grid_tile_types|HERE]].&lt;br /&gt;
&lt;br /&gt;
Normally, OniSplit decide how to color the grids. But it&#039;s possible to add your own danger quads to fine-tune zones of higher danger. Those orange areas will be generated with the 4 different blue borders around it.&lt;br /&gt;
&lt;br /&gt;
Danger quads must have &amp;quot;&#039;&#039;&#039;_marker_danger&#039;&#039;&#039;&amp;quot; as texture name.&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided NoCollision Invisible NoOcclusion Danger&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;_marker_barrier&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!-- Originally this is only used for level-bounding invisible walls? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided(double-check) Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLLISION (boxes)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
AIs can get stuck in detailed geometry. This can be prevented with collision boxes. In-game the box will be invisible, but has collision so characters can&#039;t get through. The pathfinding grid will be red where it comes in contact with the box; the red is followed by a light green and then regular green.&lt;br /&gt;
&lt;br /&gt;
[[XML:OFGA|OFGAs]] use the COLLISION texture. Onisplit doesn&#039;t automatically apply gunk flags to it. You need to use XML tags for that. Typically it would be &amp;lt;GunkFlags&amp;gt;Invisible NoObjectCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Normally, characters can&#039;t move on stairs because they contain vertical rises. In this case you can use a sloping quad that is above or inside the staircases. It&#039;s possible to set the desired flags in the &amp;lt;Model&amp;gt; section, but doing so and exporting these self-made stair ramps is wasted time. Simply apply _marker_stairs to that quad and characters will be able to move on that surface.&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Stairs Transparent TwoSided Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
This has no effect on pathfinding creation. Regularly-textured stair geometry (which intersects the marker quad) will be flagged as NoCharacterCollision.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
texture: &#039;&#039;&#039;_marker_impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Transparent TwoSided (&amp;lt;-double-check this) Invisible NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Impassable walls are very similar to collision boxes except that particles can also collide with them. The pathfinding grids will be also red, light green, and green.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Blackness a.k.a. jello fix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_blackness&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: TwoSided NoCollision&lt;br /&gt;
&lt;br /&gt;
Simply black walls. No effect on pathfinding creation. The purpose of these walls in Oni is to block out areas outside of a level&#039;s outermost wall so that the Jello-cam cannot show the player other parts of the level when it escapes a wall. See [[Jello-cam]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Doors&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_door&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: DoorFrame Transparent TwoSided NoCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Don&#039;t use this.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Objects&amp;gt;===&lt;br /&gt;
Information on regular object lists can be looked up here:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
====Furniture.xml====&lt;br /&gt;
The AKEV core geometry is more or less the overall structure of the level while this furniture file adds standard objects (e.g. crates and desks) to it.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| - &lt;br /&gt;
| This tag marks the file as BINACJBO.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Furniture&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| This tag marks the file as FURN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Header&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag. Ignore it. Those flags were used in the past.&lt;br /&gt;
:None&lt;br /&gt;
:Locked&lt;br /&gt;
:PlacedInGame&lt;br /&gt;
:Temporary&lt;br /&gt;
:Gunk&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;OSD&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Class&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to a &#039;&#039;&#039;pre-compiled [[XML:OFGA|OFGA]] (*.oni) file&#039;&#039;&#039;. Use it as part of a relative path. Make sure that the OFGA comes with the files it needs: M3GM and TXMP.&lt;br /&gt;
&lt;br /&gt;
An OFGA can hold multiple M3GMs. That 3D content will then be integrated into the AKEV.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Particle&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| This name gets written into &amp;lt;Tag&amp;gt; inside ONLV (ENVP section) and can be used with BSL commands, e.g. you can take control over a particle via &#039;&#039;&#039;particle BSL_name start&#039;&#039;&#039;. For more commands, see [[XML:BINA/OBJC/PART#BSL_support|HERE]].&lt;br /&gt;
&lt;br /&gt;
Take care with the naming of new OFGA files. The particle name will be composed of 2 parts separated by an &amp;quot;_&amp;quot; underscore. When one tag is empty, the final name will contain an underscore nonetheless. &#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Example&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Objects&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Furniture&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Gunk&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-62.692 -29 108.35&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;181.522 356.021 178.114&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Class&amp;gt;furniture/V_tctf_bigvan.oni&amp;lt;/Class&amp;gt;&lt;br /&gt;
                &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/Furniture&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Objects&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Physics.xml====&lt;br /&gt;
This file is for objects with &amp;quot;physics&amp;quot;. Unlike AKEV core geometry or furniture, these objects can be animated.&lt;br /&gt;
&lt;br /&gt;
: A small video tutorial on [https://www.youtube.com/watch?v=CFNseg_2UxA how to create a simple animated object]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Physics&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Object Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Use a unique name for each object.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Tested with BSL command...&lt;br /&gt;
:obj_create ID [ID]&lt;br /&gt;
:obj_kill ID [ID]&lt;br /&gt;
:env_anim ID [ID]&lt;br /&gt;
:env_setanim ID [ID]&lt;br /&gt;
The scripting ID will be stored in the ONLV&#039;s OBOA instance.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;Object setup flags&lt;br /&gt;
:None&lt;br /&gt;
:InUse&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoGravity&lt;br /&gt;
:FaceCollision&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Physics&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag for an Object.&lt;br /&gt;
:None&lt;br /&gt;
:Static&lt;br /&gt;
:Linear&lt;br /&gt;
:Animated&lt;br /&gt;
:Newton (used with &amp;lt;Flags&amp;gt; FaceCollision to [https://www.youtube.com/watch?v=YICB7qugrtc make an object pushable])&lt;br /&gt;
:: For a pushable object don&#039;t use import sub-tags such as animation name, flags, etc. Just use &amp;lt;Import Path=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt; or &amp;lt;Import Url=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Scale&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects.&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;Import Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Import Url=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| This tag comes in two variants. It doesn&#039;t matter what variant you use.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag of Animation. For more information on those flags look [[XML:OBAN|OBAN]] page.&lt;br /&gt;
&lt;br /&gt;
;Object animation flags&lt;br /&gt;
:None&lt;br /&gt;
:Loop&lt;br /&gt;
:PingPong&lt;br /&gt;
:RandomStart&lt;br /&gt;
:AutoStart&lt;br /&gt;
:Local&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the end of an OBAN from a *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the start of an OBAN from a *.dae file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The XML code for physics can be written in two styles.&lt;br /&gt;
*The &#039;&#039;&#039;first style&#039;&#039;&#039; mimics the original structure found in extracted ONLV instances. This makes it &#039;&#039;&#039;easier to edit old levels and reimport them&#039;&#039;&#039; into the game.&lt;br /&gt;
*The &#039;&#039;&#039;second style&#039;&#039;&#039; was created with structured data (nested objects) in mind and is &#039;&#039;&#039;suited for totally new levels&#039;&#039;&#039; where animated objects must be created in a 3D editor at first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        &amp;lt;Object&amp;gt;&lt;br /&gt;
            &amp;lt;Geometry&amp;gt;M3GMDishBase.oni&amp;lt;/Geometry&amp;gt;&lt;br /&gt;
            &amp;lt;Animation&amp;gt;OBANDishBase.oni&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;Physics&amp;gt;Animated&amp;lt;/Physics&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;201&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Position&amp;gt;-197.729141 128.46283 -2501.46387&amp;lt;/Position&amp;gt;&lt;br /&gt;
            &amp;lt;Rotation&amp;gt;0.7071067 -1.545431E-08 1.545431E-08 0.7071068&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;Scale&amp;gt;2.109375&amp;lt;/Scale&amp;gt;&lt;br /&gt;
            &amp;lt;Name&amp;gt;object_DishBase&amp;lt;/Name&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 2&#039;&#039;&#039;&lt;br /&gt;
:For documentation purposes, the file here has been trimmed down.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Object Name=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;8&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Flags&amp;gt;FaceCollision&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;Import Url=&amp;quot;motorcycle/export.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;AutoStart&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;End&amp;gt;880&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02_stop&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Start&amp;gt;881&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, OniSplit takes the file &amp;quot;export.dae&amp;quot;, looks at the parts it contains, and creates geometry files from it.&lt;br /&gt;
* M3GMhubs_rear.oni&lt;br /&gt;
* M3GMhubs.oni&lt;br /&gt;
* M3GMmotorcycle.oni&lt;br /&gt;
It&#039;s convenient that hierarchies are supported here.&lt;br /&gt;
&lt;br /&gt;
The motorcycle is made of 3 parts so 3 object animations ([[XML:OBAN|OBAN]]) will be created up to frame 880. Then OniSplit creates 3 more OBANs starting from frame 881.&lt;br /&gt;
&lt;br /&gt;
The reason for the interruption at frame 880 is probably to give Barabas a little more camera time in the cutscene.&lt;br /&gt;
&lt;br /&gt;
;Notes about BSL usage:&lt;br /&gt;
&lt;br /&gt;
The Vago Lab cutscene script uses the motorcycle objects and animations like this:&lt;br /&gt;
 	env_show 8 0		# hide static motorcycle parts or else they would be visible&lt;br /&gt;
 	env_show 9 0		# while Konoko is still riding her animated motorcycle&lt;br /&gt;
 	env_show 10 0		# the static motorcycle is separated into objects 8, 9 and 10&lt;br /&gt;
 &lt;br /&gt;
 	# Static and animated objects are totally independent from each other.&lt;br /&gt;
 	# They are stored in different arrays so their script IDs can use the same numbers.&lt;br /&gt;
 &lt;br /&gt;
 	obj_create 8 10		# create all animation-ready motorcycle parts&lt;br /&gt;
 	env_anim 8 10		# animate those parts (not necessary if OBAN flag is &amp;quot;AutoStart&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 	# The first animations would loop because of &amp;quot;AutoStart&amp;quot;, so get the&lt;br /&gt;
 	# right timing to apply the other animations. &amp;quot;motorcycle02_stop&amp;quot;&lt;br /&gt;
 	# and the others will not loop because they don&#039;t have &amp;quot;AutoStart&amp;quot;.&lt;br /&gt;
 	env_setanim 8 hubs_stop&lt;br /&gt;
 	env_setanim 9 hubs_rear_stop&lt;br /&gt;
 	env_setanim 10 motorcycle02_stop&lt;br /&gt;
 &lt;br /&gt;
 	obj_kill 8 10		# delete all animated parts&lt;br /&gt;
 	env_show 9 1		# show static motorcycle model where Konoko parks her bike&lt;br /&gt;
&lt;br /&gt;
====Corpses.xml====&lt;br /&gt;
An empty Corpse element (&amp;lt;Corpse /&amp;gt;) is treated as unused and placed at the end of the array. If no such empty elements are provided, OniSplit automatically adds 5. OniSplit also ensures that there are at least 20 corpses in the array.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Corpses&amp;gt;&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Corpse&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Class&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| [[XML:ONCC|ONCC]]&#039;&#039;name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Transforms&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| There are 19 &amp;lt;Matrix&amp;gt; for each &amp;lt;Transforms&amp;gt; (which represents a body part).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Matrix&amp;gt;&lt;br /&gt;
| matrix&lt;br /&gt;
| Float 3x3 + float x3 for the last 3 values (X Y Z position). For more information about the matrix, see [[OBD:CRSA]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Bounding box of the whole corpse. Optional; if not provided, OniSplit will generate an approximate one. Currently it doesn&#039;t try to locate the ONCC to compute an exact bounding box.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Min&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Max&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Trimmed example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Corpses&amp;gt;&lt;br /&gt;
        &amp;lt;Corpse&amp;gt;&lt;br /&gt;
            &amp;lt;Class&amp;gt;generic_male_1&amp;lt;/Class&amp;gt;&lt;br /&gt;
            &amp;lt;Transforms&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.36488995 0.04620622 -0.9299034 -0.05580434 -0.9980576 -0.02769538 -0.9293768 0.04178688 0.366759717 -215.667755 1.603917 92.85312&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.2961557 -0.185628444 0.936928 -0.368288517 -0.9272724 -0.06730227 0.8812806 -0.32512787 -0.342981815 -216.51889 1.64218426 93.189&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.407847315 0.156575248 0.8995248 -0.238757968 -0.9326179 0.2705892 0.8812805 -0.3251278 -0.342982143 -215.239883 0.8405094 97.23532&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.439697325 0.467113584 0.767118752 0.0248355754 -0.8601105 0.5095029 0.8978026 -0.204975232 -0.389789373 -213.6234 1.46109009 100.80056&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.717241049 -0.179043233 0.673430443 0.4761817 -0.579636 -0.6612664 0.5087397 0.794962764 -0.3304816 -214.81662 1.56564879 92.5172348&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.3398023 0.1672905 0.925498843 0.7910236 -0.5831365 -0.185023025 0.5087395 0.7949628 -0.330481827 -211.71907 0.792413354 95.42558&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.1283634 0.227430075 0.965297 0.804142356 -0.59352535 0.032904774 0.5804117 0.7720126 -0.259073079 -210.372269 1.45546341 99.0937653&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.285799921 0.06851995 -0.955836535 -0.240357026 -0.970681965 0.00228381017 -0.927656651 0.230394751 0.2938901 -216.284851 1.5839076 91.29168&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.312039882 0.04875436 -0.948817253 -0.176752359 -0.9842264 0.00755515043 -0.9334825 0.1700632 0.31573534 -216.689789 1.68287766 89.9359055&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.356412441 -0.5390179 -0.763170958 0.0404523835 -0.82494843 0.5637587 -0.933452547 0.170058519 0.315826446 -217.422012 1.7979821 87.70907&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.101782769 -0.247171819 -0.9636112 0.5426916 -0.8256094 0.154451028 -0.8337422 -0.507223248 0.2181709 -217.747284 1.30605173 87.0125656&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.8154478 -0.150626346 0.558888733 -0.1200991 0.9885643 0.09119747 -0.566234052 0.00724477554 -0.8242127 -217.7402 2.065678 88.15346&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.4593738 -0.326781839 0.825947642 0.8874048 -0.1284554 0.442732215 -0.0385793857 0.9363295 0.348996729 -219.093979 1.81561315 89.08131&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9545983 -0.13777709 0.26412034 0.295387268 -0.322961926 0.899134 -0.0385792255 0.9363296 0.348996431 -220.3681 0.9092429 91.37218&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9715769 -0.0362956524 0.233924776 0.0276728421 -0.9988148 -0.0400396362 0.2351007 -0.0324283168 0.9714299 -222.775482 0.56178683 92.03825&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.979860842 -0.192433611 0.0533096045 0.193336874 0.9810555 -0.0122905634 -0.0499345176 0.0223497637 0.9985025 -216.8387 1.90143847 87.84845&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.863898 -0.399280578 0.3070101 0.171117 -0.340619326 -0.9244986 0.4737078 0.851207137 -0.225936681 -215.211975 1.58196676 87.93695&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.4673251 -0.0255063027 0.883717656 0.746463835 -0.524209559 -0.4098731 0.4737075 0.851207256 -0.225936785 -212.815842 0.47451216 88.78848&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.216871262 -0.007893051 0.976168454 0.3751846 0.9238389 -0.0758833 -0.9012231 0.3827002 0.203315422 -211.637314 0.410188764 91.0171051&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
            &amp;lt;/Transforms&amp;gt;&lt;br /&gt;
            &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
                &amp;lt;Min&amp;gt;-219.731216 -2.258905 84.47974&amp;lt;/Min&amp;gt;&lt;br /&gt;
                &amp;lt;Max&amp;gt;-207.518463 4.49535131 104.023239&amp;lt;/Max&amp;gt;&lt;br /&gt;
            &amp;lt;/BoundingBox&amp;gt;&lt;br /&gt;
        &amp;lt;/Corpse&amp;gt;&lt;br /&gt;
    &amp;lt;/Corpses&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[[Image:ONLV_CRSA_XSI_aided_import.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
:Some related information can be found at [[Authoring custom camera animations]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
For indirect import, see [http://oni.bungie.org/forum/viewtopic.php?id=2657 HERE] (OniTools v7.1.5+) on how to get corpse data.&lt;br /&gt;
&lt;br /&gt;
When you process your XML master file, use OniSplit version 0.9.94.0+. Older OniSplit versions like 0.9.86.0 may generate ONLV files that are not re-packable with newer versions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;(Export)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With Neo&#039;s matrix-to-Euler code, the rotations can be recovered from CRSA. But due to the character&#039;s hierarchy, things get messy again (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/CRSA_to_Mod_Tool_wip.png&amp;lt;/nowiki&amp;gt;, dead link). (WIP code (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/temp/CRSA_to_Mod_Tool.txt&amp;lt;/nowiki&amp;gt;, dead link))&lt;br /&gt;
&lt;br /&gt;
A workaround might be to save characters without animations, destroy their hierarchy, apply the local rotations / global translation and glue everything together again.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Modding_errors&amp;diff=43849</id>
		<title>Modding errors</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Modding_errors&amp;diff=43849"/>
		<updated>2025-01-22T06:36:04Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Frequently asked questions */Fixed broken link.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You might want to use the browser&#039;s search function to quickly find an error message.&lt;br /&gt;
{{TOClimit|3}}&lt;br /&gt;
==Frequently asked questions==&lt;br /&gt;
[[Image:modding_errors.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*Why does Oni crash on game start?&lt;br /&gt;
::What were you working on? A [[#... due to overloaded animation|character animation]]?&lt;br /&gt;
*Why does Oni crash while loading a level?&lt;br /&gt;
::What were you working on? A [[#... due to missing files|game level]]?&lt;br /&gt;
*Why does a character have black body parts?&lt;br /&gt;
::You&#039;re probably [[#Missing character texture (TXMP)|missing a texture]].&lt;br /&gt;
*Why does a character have white body parts?&lt;br /&gt;
::You are using a mod with bgra32 textures and an old engine that doesn&#039;t support bgra32.&lt;br /&gt;
* Why can&#039;t I convert character animations?&lt;br /&gt;
::See [[#TRAM-related|HERE]] if you use &amp;quot;-create:tram&amp;quot;.&lt;br /&gt;
* Why are all body parts overlapping in the DAE file?&lt;br /&gt;
::Because the part hierarchy isn&#039;t correct. Read more [https://web.archive.org/web/20160225191109/http://oni.bungie.org/forum/viewtopic.php?pid=31310#p31310 here].&lt;br /&gt;
&lt;br /&gt;
==Visual errors based on settings==&lt;br /&gt;
===Black splashscreens but normal gameplay===&lt;br /&gt;
Those screens (all TXMBs) are black if the user has a lower resolution than the screen. Oni&#039;s vanilla splashscreens are 640x480 but the [[AE]]&#039;s &amp;quot;HD Screens&amp;quot; package bumps them up to 1024x768, which is where players usually encounter this problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This problem is fixed by [[Daodan DLL]] v3.5 or newer and the [[FERAL|Mac Intel build]] v1.2 or newer.&lt;br /&gt;
&lt;br /&gt;
==Binary errors==&lt;br /&gt;
===Crash while starting Oni===&lt;br /&gt;
====... due to overloaded animation====&lt;br /&gt;
Animations with more than 107 keys per bone crash the game. You can import animations with more than 107 frames if the keys cover multiple frames.&lt;br /&gt;
: For example 12 frames &#039;&#039;&amp;lt;EKey&amp;gt;&amp;lt;font style=&amp;quot;color:#00AA00&amp;quot;&amp;gt;&#039;&#039;&#039;12&#039;&#039;&#039;&amp;lt;/font&amp;gt; -156.628983 -14.6175327 -78.3831558&amp;lt;/EKey&amp;gt;&#039;&#039;&lt;br /&gt;
Such ranges and EKeys are produced by older OniSplit versions. See [[#TRAM-related|HERE]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You shouldn&#039;t encounter this bug anymore with OniSplit v0.9.56.0 or newer.&lt;br /&gt;
&lt;br /&gt;
===Crash while loading a level===&lt;br /&gt;
====... due to improper textures====&lt;br /&gt;
Textures&#039; x and y (pixel) dimensions must be a power of two: 512, 256, 128, 64, etc.&lt;br /&gt;
&lt;br /&gt;
====... due to missing files====&lt;br /&gt;
Generally it can be said that Oni complains when an instance is missing that is referenced by another instance. For instance:&lt;br /&gt;
* AKEVs don&#039;t tolerate missing textures.&lt;br /&gt;
* ONVLs and ONCCs don&#039;t tolerate missing variants (ONCVs).&lt;br /&gt;
&lt;br /&gt;
====... due to triangle limit====&lt;br /&gt;
* with too many triangles, Oni crashes after ~90% of the loading process; the triangle limit is ~520,000 (500,000 to be on the safe side).&lt;br /&gt;
&lt;br /&gt;
===Crash while playing===&lt;br /&gt;
====... due to missing files====&lt;br /&gt;
If you encounter a crash when spawning a character or when you cycle through all characters with F8, then check if the crashing character has a TRMA file.&lt;br /&gt;
&lt;br /&gt;
===Non-crash errors===&lt;br /&gt;
These errors are visible inside the game and don&#039;t cause a crash when they appear.&lt;br /&gt;
&lt;br /&gt;
====Multiple savegame names for same level number====&lt;br /&gt;
The Load Game menu can show additional savegame names if any new ONLV is provided in another level0 plugin.  As a quick test, you should use a plugin name which comes alphabetically before &amp;quot;level0_Final&amp;quot;, such as &amp;quot;level0_Addin&amp;quot;. If you choose a name like &amp;quot;level0_More&amp;quot;, the new savegame will be appended after all &amp;quot;_Final&amp;quot; ONLDs, and also a clone appears:&lt;br /&gt;
&lt;br /&gt;
: &amp;quot;_Final&amp;quot; list&lt;br /&gt;
: new savegame name from &amp;quot;_More&amp;quot;&lt;br /&gt;
: cloned savegame name of the slot meant to be overwritten&lt;br /&gt;
&lt;br /&gt;
====Multiple TXMBs====&lt;br /&gt;
A level can start with multiple TXMBs, visible one by one, although there was just one BSL command calling for one. This is caused by using additional plugins, because files with the same name can stack.&lt;br /&gt;
&lt;br /&gt;
====Missing character texture (TXMP)====&lt;br /&gt;
The texture is either missing, or the texture name and the link in [[OBD:TRMA|TRMA]] do not match.&lt;br /&gt;
&lt;br /&gt;
====Distorted colors in textures (TXMP)====&lt;br /&gt;
[[Image:color_spectrum_test.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
Why do my source and re-extracted textures look okay but in-game the colors are distorted? The &amp;quot;[[OBD_talk:TXMP#0x_00_10_00_00|little endian data]]&amp;quot; flag in the level data file is missing. The flag will be added by OniSplit v0.9.56.0 or later when you import it, or you can create the TXMP via an XML file and ensure that the flag is present before import.&lt;br /&gt;
&lt;br /&gt;
====Missing animation collection (TRAC)====&lt;br /&gt;
&lt;br /&gt;
====Missing 3D model (TRBS)====&lt;br /&gt;
&lt;br /&gt;
====Distorted 3D model (TRBS)====&lt;br /&gt;
[[Image:XSI_Konoko_Ref.png|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
When creating the 3D model in Mod Tool, you have to watch out for the naming and order of the body parts.&lt;br /&gt;
* If you use OniSplit v0.9.58.0 or lower, the naming of body parts must be absolutely correct.&lt;br /&gt;
* If you use higher versions, the naming is unimportant but the order matters. The order can be easily changed in the Schematic [9]. Then go to Edit &amp;gt; [http://edt.oni2.net/images/schematic.jpg Reorder Nodes Tool] [I] and move an object to its new position.&lt;br /&gt;
&lt;br /&gt;
====Non-working combos (TRAM)====&lt;br /&gt;
Situation: When you create combos, you want to test your moves in-game. Sometimes each move actually works (tested via chr_animate) but the combo does not.&lt;br /&gt;
&lt;br /&gt;
Requirements to prevent that bug:&lt;br /&gt;
* &amp;lt;Attacks&amp;gt; and &amp;lt;HorizontalExtents&amp;gt; data is needed&lt;br /&gt;
** &#039;&#039;&#039;Note:&#039;&#039;&#039; With OniSplit v0.9.55.0 or newer, HorizontalExtents (now named &amp;quot;[[XML:TRAM#List_of_tags.2C_types.2C_and_flags|AttackRing]]&amp;quot;) is calculated automatically.&lt;br /&gt;
* Correct links to the Direct Animations tag&lt;br /&gt;
* Correct links inside the character&#039;s animation collection (TRAC)&lt;br /&gt;
&lt;br /&gt;
==Developer Mode error messages==&lt;br /&gt;
===Animation errors===&lt;br /&gt;
&#039;&#039;throwtarget was NULL&#039;&#039; - The throw target animation was not found.&lt;br /&gt;
&lt;br /&gt;
===BSL errors===&lt;br /&gt;
*&#039;&#039;Func &amp;quot;main&amp;quot;, File &amp;quot;(called from engine)&amp;quot;, Line 0: semantic error, &#039;&#039;&#039;function&#039;&#039;&#039; &amp;quot;main&amp;quot; &#039;&#039;&#039;does not exist&#039;&#039;&#039;&#039;&#039;, then either the function &amp;quot;main&amp;quot; wasn&#039;t found in any BSL file (this can also happen with any other function), or the BSL file has too many commands in it (see [[#BSL_commands_per_file_limitation|here]]). If it&#039;s the latter, split your BSL file into more BSL files (creating additional functions if necessary).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;test.bsl&amp;quot;, Line 3: semantic error, &#039;&#039;&#039;Identifier&#039;&#039;&#039; &amp;quot;main&amp;quot; already declared&#039;&#039; - In this example, there are multiple &amp;quot;main&amp;quot; functions; the last occurrence of main() can be found in the file &amp;quot;test.bsl&amp;quot; at line 3.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;main.bsl&amp;quot;, Line 1: Illegal token, got &amp;quot;func&amp;quot; expected &amp;quot;;&amp;quot;&#039;&#039; - A previous variable declaration didn&#039;t end with a semicolon.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SLiSchedule_Task_Find FAILED [IMPORTANT]&#039;&#039; - The game will freeze after about 5 instances of this message. Caused by calling too many BSL functions in parallel (using fork) in a very short amount of time.&lt;br /&gt;
&lt;br /&gt;
====Mistyped variable====&lt;br /&gt;
Typing &#039;&#039;chr_lod 4&#039;&#039; will produce this error: &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: Illegal token, got &amp;quot;0&amp;quot; expected &amp;quot;;&amp;quot;&#039;&#039;. That&#039;s because &amp;quot;chr_lod&amp;quot; is a variable and you need to use the equals symbol to set a variable. The correct use of this variable would be &#039;&#039;chr_lod = 4&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Mistyped function====&lt;br /&gt;
Typing &#039;&#039;killled_griffen = 1&#039;&#039; will produce &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: semantic error, symbol &amp;quot;killed_griffen&amp;quot; is not a variable (function most likely)&#039;&#039;. That&#039;s because &amp;quot;killed_griffen&amp;quot; is a function, and you simply list values (parameters) after function names, with no equals symbol. The correct use of this function is: &#039;&#039;killed_griffen 1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Another incorrect example: Typing &#039;&#039;chr_givepowerup = 0 ammo 1&#039;&#039; will produce:&lt;br /&gt;
: &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: semantic error, symbole &amp;quot;chr_givepowerup&amp;quot; is not a variable (function most likely)&#039;&#039;  &lt;br /&gt;
: &#039;&#039;Func &amp;quot;(null)&amp;quot;, File &amp;quot;(called from console)&amp;quot;, Line 1: Illegal token, got &amp;quot;ammo&amp;quot; expected &amp;quot;;&amp;quot;&#039;&#039;&lt;br /&gt;
The correct use of this function is &#039;&#039;chr_givepowerup 0 ammo 1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====BSL commands per file limitation====&lt;br /&gt;
The engine has some kind of limit on how many BSL commands can occur in a single BSL file. When you pass the limit, you&#039;ll get errors in the developer console like this: &amp;quot;Func &amp;quot;main&amp;quot;, File &amp;quot;(called from engine)&amp;quot;, Line 0: semantic error, function &amp;quot;main&amp;quot; does not exist.&amp;quot; (it can also be a function other than &amp;quot;main&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
For an example, extract these files and place them in IGMD/EnvWarehouse to experience the problem: [http://script10k.oni2.net/wikifiles/main_not_working_without_commenting_commands.zip], [http://script10k.oni2.net/wikifiles/main_not_working_without_commenting_commands(functions_splitted).zip], [http://script10k.oni2.net/wikifiles/main_splitted_in_two_files.zip]&lt;br /&gt;
&lt;br /&gt;
In all these BSL files, the message &amp;quot;This message should appear on the beginning&amp;quot; should appear when you load level 1. However for &amp;quot;main_not_working_without_commenting_commands&amp;quot; it doesn&#039;t work unless you comment out the 5th line of the BSL file. The &amp;quot;main_not_working_without_commenting_commands(functions_split)&amp;quot; script is the same, but in this one the &amp;quot;main&amp;quot; function is split into two functions, which is still not enough for the error to go away. The scripts in &amp;quot;main_split_in_two_files&amp;quot; are the same BSL as previously, but the two functions are split into two different files: &amp;quot;main.bsl&amp;quot; and &amp;quot;continuation.bsl&amp;quot;. In this case the script works as expected, and the message &amp;quot;This message should appear on the beginning&amp;quot; appears on level load.&lt;br /&gt;
&lt;br /&gt;
So if you experience the error &amp;quot;Function &amp;quot;x&amp;quot; does not exist.&amp;quot; when in fact it does, try spreading your functions across more BSL files and it should fix the problem.&lt;br /&gt;
&lt;br /&gt;
==OniSplit error messages==&lt;br /&gt;
===TRAM-related===&lt;br /&gt;
* &#039;&#039;COLLADA error: duplicate id light&#039;&#039; - Maybe your DAE file has more than one root scene. In this case, you can right-click the model (which selects all 19 bones), then go to the Crosswalk settings, check &amp;quot;Selection Only&amp;quot;, and save the file.&lt;br /&gt;
* &#039;&#039;.dae files cannot be imported as TRAM&#039;&#039; - Newer OniSplit versions doesn&#039;t seem to support &amp;quot;-create:tram&amp;quot; any longer. If you use that command, download an older version like  v0.9.41.0 from Mod Depot.&lt;br /&gt;
* If TRAM*tgt has more than 256 (0-255) frames, you&#039;ll see:&lt;br /&gt;
&lt;br /&gt;
 Parametername: Value too large for Byte&lt;br /&gt;
   at Oni.BinaryWriter.WriteByte(Int32 value)&lt;br /&gt;
   at Oni.Totoro.AnimationDatWriter.WriteRotations(List`1 rotations, Int32 frameSize)&lt;br /&gt;
   at Oni.Totoro.AnimationDatWriter.WriteAnimation()&lt;br /&gt;
   at Oni.Xml.XmlImporter.ReadAnimation()&lt;br /&gt;
   at Oni.Xml.XmlImporter.Import(String filePath, String outputDirPath)&lt;br /&gt;
   at Oni.Program.ExecuteTasks(String[] args, String outputDirPath, Set`1 importedFiles, Queue`1 taskQueue)&lt;br /&gt;
   at Oni.Program.CreateGeneric(String[] args)&lt;br /&gt;
   at Oni.Program.Execute(String[] args)&lt;br /&gt;
   at Oni.Program.Main(String[] args)&lt;br /&gt;
&lt;br /&gt;
===TRBS===&lt;br /&gt;
In DAE files, if a bone has a point cluster, OniSplit v0.9.94.0 fails to convert the file.&lt;br /&gt;
&lt;br /&gt;
==AE Installer==&lt;br /&gt;
===Blank mod list===&lt;br /&gt;
Your user account probably doesn&#039;t have the necessary rights that the AE Installer needs. In Windows, this can happen if you have Oni installed on an &#039;&#039;old&#039;&#039; hard drive which is now wired to your new system. Add &amp;quot;full control&amp;quot; to your account by right-clicking the Oni folder, choosing Properties, and going to the Security tab.&lt;br /&gt;
&lt;br /&gt;
==XSI/Mod Tool errors==&lt;br /&gt;
===Corrupted DAE files===&lt;br /&gt;
Situation: &#039;&#039;I cannot load my DAE file into XSI. It give me an &amp;quot;Unspecified Failure&amp;quot;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Possible cause: When you create the DAE file, there are file paths are stored inside it. If a path contains an illegal character, XSI cannot load the file.&lt;br /&gt;
&lt;br /&gt;
Solution: Make sure the paths use only letters of the [[wikipedia:English_alphabet|English alphabet]].&lt;br /&gt;
&lt;br /&gt;
===Object with test texture===&lt;br /&gt;
If the texture&#039;s file name contains a &amp;quot;#&amp;quot;, ModTool fails to apply that texture and use its rainbow-colored test image instead.&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Modifying_textures&amp;diff=43848</id>
		<title>Modifying textures</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Modifying_textures&amp;diff=43848"/>
		<updated>2025-01-22T06:32:12Z</updated>

		<summary type="html">&lt;p&gt;Vortice: Fixed a broken link.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here are some brief instructions on how to modify the texture maps.  You might want make new skins for a character or even a new outfit for Konoko!&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Extract TXMP&#039;&#039;&#039; (Texture maps)&lt;br /&gt;
:1) Make a folder for the textures to go into (&amp;quot;tex_folder&amp;quot; below).&lt;br /&gt;
:2) You will need to &#039;cd&#039; (change directory in the terminal) to AE/AEInstaller/vanilla/.&lt;br /&gt;
:3) To extract all the TXMPs, use the following command:&lt;br /&gt;
:onisplit -extract:png tex_folder level0_Final.dat&lt;br /&gt;
&lt;br /&gt;
:For example:&lt;br /&gt;
:PC users: onisplit -extract:png tex_folder level0_Final.dat (Or you can use -extract:tga to get the files in Targa format)&lt;br /&gt;
:Mac users: mono onisplit.exe -extract:png tex_folder level0_Final.dat&lt;br /&gt;
:3) Now all the TXMPs from Oni (over 2,000) will be located in the Oni/TXMPfiles&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Modify TXMP&#039;&#039;&#039;&lt;br /&gt;
:1) Currently, many of Oni&#039;s texture maps are 64x64, or 128x128; unmodded, Oni supports textures up to 256x256, but the current patched version of Oni for Windows supports 512x512, and the patched version of Oni for macOS supports up to 1024x1024.&lt;br /&gt;
:2) Use your favorite graphic editor to make your changes.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Create TXMP*.oni files&#039;&#039;&#039;&lt;br /&gt;
For most image files you can use the following command:&lt;br /&gt;
:PC: onisplit -create:txmp destination_directory options source_image_file&lt;br /&gt;
:Mac: mono onisplit.exe -create:txmp destination_directory options source_image_file&lt;br /&gt;
 &lt;br /&gt;
: The source_image_file can be dds or tga. &amp;quot;Color indexed&amp;quot; and &amp;quot;black and white&amp;quot; tga files are not supported currently. Other image file formats (png, jpg, bmp, tif) may work depending on Mono/.NET support for them. onisplit will automatically prepend TXMP to the output file name if the source file name does not start with TXMP already.&lt;br /&gt;
 &lt;br /&gt;
:Options can be&lt;br /&gt;
:-nouwrap - set the &amp;quot;U wrapping disabled&amp;quot; flag&lt;br /&gt;
:-nowwrap - set the &amp;quot;V wrapping disabled&amp;quot; flag&lt;br /&gt;
:-format:bgr555 (or dxt1) for most of the stuff&lt;br /&gt;
:-format:bgr32 for skyboxes&lt;br /&gt;
:-format:bgra4444 for transparent/reflective stuff (in a couple of places bgra5551 is used but probably it&#039;s not big deal if bgra4444 is used instead)&lt;br /&gt;
:-genmipmaps - generate mipmaps if they are not already present in the source file and if the source file is not dxt1 compressed&lt;br /&gt;
:-envmap - envmap used for reflectivity&lt;br /&gt;
 &lt;br /&gt;
:Here is an example&lt;br /&gt;
:PC: onsplit -create:txmp dest_dir -format:bgr555 -genmipmaps TXMPSTR_EASY_1%2FSTRbicepR.tga&lt;br /&gt;
:Mac: mono onisplit.exe -create:txmp dest_dir -format:bgr555 -genmipmaps TXMPSTR_EASY_1%2FSTRbicepR.tga&lt;br /&gt;
 &lt;br /&gt;
:To batch process a folder you can use this command;&lt;br /&gt;
:PC: onisplit -create:txmp dest_dir -format:bgr555 -genmipmaps folder_of_images\*.tga&lt;br /&gt;
:Mac: mono onisplit.exe -create:txmp dest_dir -format:bgr555 -genmipmaps folder_of_images/*.tga&lt;br /&gt;
 &lt;br /&gt;
:For image files that use an envmap (Such as Striker armor, Ninja armor, Elite armor, Konoko&#039;s face, weapons), you will need to include the name of the envmap:&lt;br /&gt;
:PC: onisplit -create:txmp dest_dir -format:bgra4444 -genmipmaps -envmap:envmapname imagefile.tga&lt;br /&gt;
:Mac: mono onisplit.exe -create:txmp dest_dir -format:bgra4444 -genmipmaps -envmap:envmapname imagefile.tga&lt;br /&gt;
 &lt;br /&gt;
:3) Once you have created the TXMP*.oni file, you will need to put it in the level0_Final folder and then recompile the level.&lt;br /&gt;
&lt;br /&gt;
:4) Play the game and see how your new texture maps look.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXMP &amp;amp; XML&#039;&#039;&#039;&lt;br /&gt;
:Extracting a texture with -extract:xml produces an xml file and one or more tga files. The xml file will contains texture options like format and flags and a list of tga file names.&lt;br /&gt;
:* options for &amp;lt;Flags&amp;gt; (more than one are separated by a double space) : None  HasMipMaps  DisableUWrap  DisableVWrap  AnimUseLocalTime  AnimBackToBack  AnimRandom  AnimIgnoreGlobalTime  ShieldEffect  InvisibilityEffect  DaodanEffect&lt;br /&gt;
:* options for &amp;lt;Format&amp;gt; : ARGB4444 / RGB555 / ARGB5551 / RGB888 / DXT1&lt;br /&gt;
: More than one tga file is produced for animated textures and the filenames look like TXMPsmoke_001.tga, TXMPsmoke_002.tga etc.&lt;br /&gt;
:Using the -create option with such an xml file will produce a normal TXMP.oni file but without the need to specify additional parameters on the command line like with -create:txmp. This comes in handy if you want to edit a bunch of textures:&lt;br /&gt;
&lt;br /&gt;
:* put all the xml and tga files in a single directory&lt;br /&gt;
:* edit tga image files as you need&lt;br /&gt;
:* in the directory you can run the command: onisplit -create oni *.xml to create all TXMP.oni files in the subdirectory oni.&lt;br /&gt;
&lt;br /&gt;
:Tip:&lt;br /&gt;
:The exported xml file does not contain the width and height of the texture, this is obtained from the tga file. If you resize the tga file the texture will be resized too.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reflective textures&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:Keep in mind, Oni simulates reflectivity using textures and alpha channels.&lt;br /&gt;
&lt;br /&gt;
:To see how a reflective texture is made, extract TXMPSTR_HARD_1%2FSTRchest.oni as XML.  You will get a TGA and XML file.&lt;br /&gt;
:Open the TGA file in a photo editor and it has an alpha channel. The alpha channel determines what part of the texture is reflective.  Black in the alpha channel means no reflectivity, gray to white is increasing amounts of reflectivity.&lt;br /&gt;
&lt;br /&gt;
:Now in the XML file, there are 2 properties you will be concerned with:&lt;br /&gt;
:&amp;lt;Format&amp;gt;ARGB4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
:&amp;lt;EnvMap&amp;gt;TXMPstrikerarmor&amp;lt;/EnvMap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:The &amp;lt;Format&amp;gt; is how the texture will be saved.  In this case, the striker&#039;s chest texture was originally saved with an alpha channel.  Now there are 3 formats that can have an alpha channel:&lt;br /&gt;
&lt;br /&gt;
:ARGB4444 = 4,096 colors, alpha 16 colors&lt;br /&gt;
:ARGB5551 = 32,768 colors, alpha 2 colors&lt;br /&gt;
:ARGB8888 = 16,777,216 colors, alpha 256 colors (Note: this one requires the Oni engine to be patched and not many have the patched version)&lt;br /&gt;
&lt;br /&gt;
:The &amp;lt;EnvMap&amp;gt; refers to what texture is used to simulate reflectivity. There are 4 envmap files that are used for characters:&lt;br /&gt;
:TXMPstrikerarmor&lt;br /&gt;
:TXMPenvksface&lt;br /&gt;
:TXMPenvksarmor&lt;br /&gt;
:TXMPSUPER_REFLECT&lt;br /&gt;
&lt;br /&gt;
:You might want to extract this file as xml to see its properties.&lt;br /&gt;
&lt;br /&gt;
:Once you make your texture that has an alpha channel, use the XML file to convert it back to .oni file.&lt;br /&gt;
(from here: https://web.archive.org/web/20160226055825/http://oni.bungie.org/forum/viewtopic.php?pid=19297#p19297, to be edited and completed)&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=OniSplit&amp;diff=43847</id>
		<title>OniSplit</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=OniSplit&amp;diff=43847"/>
		<updated>2025-01-22T06:28:03Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Levels */Fixed broken forum link.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOCfloat|side=right}}&lt;br /&gt;
{{Hatnote|Before reading this page, it&#039;s a good idea to be familiar with basic Oni [[game data terminology]].}}&lt;br /&gt;
&#039;&#039;&#039;OniSplit&#039;&#039;&#039;, written by [[User_talk:Neo|Neo]], is an integral part of the [[Anniversary Edition]] and an essential modding tool on its own. It is a command line tool which can import and export almost all kinds of Oni game data, including textures, sound, 3D models, level geometry and combat animations. Its name comes from its original purpose, which was breaking Oni&#039;s level data files into individual resources. Later, the ability to convert those resources&#039; data between Oni&#039;s format and standard file formats was added. OniSplit incorporates the latest [[OBD|knowledge about Oni&#039;s game data]], and it is currently the community&#039;s main modding tool.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Subpages:&#039;&#039; [[/Change_log|Change log]] (past versions), [[/WIP|WIP notes]] (upcoming versions)&lt;br /&gt;
&lt;br /&gt;
==Getting it==&lt;br /&gt;
===Download links===&lt;br /&gt;
* Latest release of OniSplit: [http://mods.oni2.net/node/38 v0.9.99.2] ([https://websvn.illy.bz/dl.php?repname=Oni2&amp;amp;path=%2FOniSplit%2F&amp;amp;isdir=1 source code])&lt;br /&gt;
* The current GUI for OniSplit is [[Vago (tool)|Vago]]. &#039;&#039;&#039;You should try the GUI to see if it does what you need before working with OniSplit on the command line.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Requirements===&lt;br /&gt;
*Windows: [https://dotnet.microsoft.com/en-us/download/dotnet-framework .NET framework]&lt;br /&gt;
*macOS: [https://www.mono-project.com/download/stable/ Mono framework]&lt;br /&gt;
&lt;br /&gt;
==Workflow==&lt;br /&gt;
OniSplit is used in up to four different stages when modding:&lt;br /&gt;
{|&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|&amp;lt;span style=&amp;quot;font-size:150%&amp;quot;&amp;gt;&#039;&#039;&#039;OUT&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|&#039;&#039;Exporting&#039;&#039; - using the &amp;lt;tt&amp;gt;-export&amp;lt;/tt&amp;gt; command, a [[Dat|level data file]] is broken into its component resources, .oni files.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;border-style: solid; border-width: 0 0 1px 0&amp;quot;|&#039;&#039;Extracting&#039;&#039; - using the &amp;lt;tt&amp;gt;-extract&amp;lt;/tt&amp;gt; commands, .oni files are converted to standard-format files that can be edited in various third-party programs.&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|&amp;lt;center&amp;gt;&amp;lt;span style=&amp;quot;font-size:150%&amp;quot;&amp;gt;&#039;&#039;&#039;IN&#039;&#039;&#039;&amp;lt;/span&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
|&#039;&#039;Creating&#039;&#039; - using the &amp;lt;tt&amp;gt;-create&amp;lt;/tt&amp;gt; commands, standard-format files are converted into .oni files.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;Importing&#039;&#039; - using the &amp;lt;tt&amp;gt;-import&amp;lt;/tt&amp;gt; command, a folder of .oni files is combined into a level data file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that &amp;quot;extracting&amp;quot; refers to a conversion from one format to another, but &amp;quot;exporting&amp;quot; only refers to the creation of .oni files from a .dat file. When exporting, no conversion or re-formatting is taking place; the data is simply being copied out of a .dat (any connected binary data in .raw/.sep files will be concatenated to the data from the .dat when making the .oni).&lt;br /&gt;
&lt;br /&gt;
==Beginner&#039;s tips==&lt;br /&gt;
{{Divhide|show=yes|For users new to the command line or to OniSplit}}&lt;br /&gt;
In Windows, there are several options through which you can use OniSplit - out of which it is recommended to get Vago and CMDer:&lt;br /&gt;
* [[Vago (tool)|Vago]] is a GUI for OniSplit which allows you to handle all general conversions, save your sessions as project files, input manual commands if needed, and more. The two downsides of it is that it doesn&#039;t support Blender yet, forcing the users input commands manually, which in turn are not stored upon ending the session.&lt;br /&gt;
* [https://cmder.app/ CMDer] is an excellent alternative to cmd.exe. It can be customized to allow starting it from any folder you pick with the context menu, and it also stores the most recently used commands after ending the session. Currently it is highly useful for Blender-related operations.&lt;br /&gt;
* Command Prompt/cmd.exe. Windows&#039; default command line interpreter, it&#039;s a poor choice as it does not store most recently used commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On Macs, the command line is found in the Terminal app (/Applications/Utilities) (press Command-Spacebar and type &amp;quot;Terminal&amp;quot; to get there faster).&lt;br /&gt;
&lt;br /&gt;
===OniSplit syntax===&lt;br /&gt;
The basic syntax is:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Windows&#039;&#039;&#039;||&amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;background:rgb(235,235,235); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;OniSplit.exe&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-create:trbs&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(255,156,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;C:\Games\Oni\SomeFolder&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-normals&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(156,255,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;C:\Games\Oni\Modding\TRBSMyNewChar.dae&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Mac&#039;&#039;&#039;||&amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;background:rgb(235,235,235); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;mono OniSplit.exe&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-create:trbs&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(255,156,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;/Games/Oni/SomeFolder&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;-normals&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;background:rgb(156,255,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;/Games/Oni/Modding/TRBSMyNewChar.dae&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how it breaks down:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;width:130px&amp;quot;|&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(235,235,235); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Invocation&#039;&#039;&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
|Windows can refer to the program directly, but Macs use Mono to run the .NET app; note also that if OniSplit.exe is not in the Command Prompt/Terminal&#039;s current directory, you must provide the full path to it or set the path variable.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Option&#039;&#039;&#039;&amp;lt;/span&amp;gt;||The command.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(255,156,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Path to folder&#039;&#039;&#039;&amp;lt;/span&amp;gt;||Whether destination or source, the path which is a folder comes first. &amp;lt;u&amp;gt;Use the full path to the folder (starting from &amp;quot;C:\&amp;quot;, or &amp;quot;/&amp;quot; on Macs).&amp;lt;/u&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(175,175,255); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Option flags&#039;&#039;&#039;&amp;lt;/span&amp;gt;||The flags that can optionally go with this command, separated by spaces.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;background:rgb(156,255,156); border-radius:0.33em; padding:0.15em&amp;quot;&amp;gt;&#039;&#039;&#039;Path to file&#039;&#039;&#039;&amp;lt;/span&amp;gt;||Whether destination or source, the path of the file comes second. &amp;lt;u&amp;gt;Use the full path to the file (starting from &amp;quot;C:\&amp;quot;, or &amp;quot;/&amp;quot; on Macs).&amp;lt;/u&amp;gt; One exception to this parameter being a file is when using &amp;lt;tt&amp;gt;-create&amp;lt;/tt&amp;gt; to make a level, in which case this is where you supply the source folder.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===CLI tips===&lt;br /&gt;
*Command line interfaces (CLI) usually supply an auto-complete feature to save on typing. If you&#039;ve typed enough of a file/folder name to identify it, press the Tab key and the rest should fill in. In Windows, you may not get the right path name autocompleted on the first try if there are multiple possible autocompletions based on the names in that directory, so keep pressing Tab to cycle through all possibilities. On Macs, if you have not typed enough of the name to narrow it down to a single autocompletion, you will hear an error sound.  Double-tap Tab to see a list of possible autocompletions, then keep typing until you have narrowed it down to one of those and then hit Tab to fill in the rest of its name.&lt;br /&gt;
&lt;br /&gt;
*Note that you can also drag files/folders into the window and the path will magically appear; in cases where you don&#039;t need to use a wildcard, this is the fastest way to build an OniSplit command.&lt;br /&gt;
&lt;br /&gt;
===Wildcards===&lt;br /&gt;
Wildcards can be used to supply patterns to CLI programs. The wildcard is simply the &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt; character. For instance:&lt;br /&gt;
 OniSplit.exe -export:TRAM* &amp;lt;destination&amp;gt; &amp;lt;source .dat&amp;gt;&lt;br /&gt;
will export all the TRAMs in the source .dat into the destination folder. Using &amp;quot;TRAMKON*&amp;quot; would export all of Konoko&#039;s animations.&lt;br /&gt;
&lt;br /&gt;
===Spaces in paths===&lt;br /&gt;
Command line interfaces (CLI) do not recognize spaces as a possible part of a path name because spaces are what separate the terms in your commands. The best course of action is to not use paths with spaces in their names! But if you must, you can use quotes to tell the CLI that a certain string is a single path:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;C:\Games\Oni\&amp;gt;&#039;&#039;&#039;OniSplit.exe -list &amp;quot;My Mod Folder\level5_Final.dat&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This works in the Mac Terminal too, but you can also use the escape character, &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;. Also, other characters like &amp;lt;tt&amp;gt;(&amp;lt;/tt&amp;gt; need to be escaped as well if you do not use quotes:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;MyMac%&#039;&#039;&#039; mono OniSplit.exe -list My\ Mods\ \(In\ Progress\)/level5_Final.dat&lt;br /&gt;
&lt;br /&gt;
But as mentioned, the best practice is to not use any characters besides the alphabet and numbers. It makes your life simpler, and if you ask for help on the forum with a command, no one wants to have to read your long path with lots of spaces or escaped characters in it ;-)&lt;br /&gt;
&lt;br /&gt;
===Reading the commands below===&lt;br /&gt;
*The following commands should be complete, but the current list can be obtained by calling OniSplit with the &amp;lt;tt&amp;gt;-help&amp;lt;/tt&amp;gt; option. You should also use &amp;lt;tt&amp;gt;-version&amp;lt;/tt&amp;gt; to make sure you&#039;re using the latest version, the number of which is given in the &amp;quot;Download links&amp;quot; section above.&lt;br /&gt;
&lt;br /&gt;
*Sample usages are given after certain commands. These are in DOS style, so if you are on a Mac, simply flip the &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;s to &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;s and make &amp;quot;C:\&amp;quot; into a leading &amp;quot;/&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Optional flags are listed in square brackets simply to indicate that they&#039;re optional; don&#039;t enter the brackets when typing a command.&lt;br /&gt;
&lt;br /&gt;
Note that only the .dat file from a level&#039;s data files is mentioned. The .raw and .sep files will be accessed by OniSplit as necessary when working with the .dat file that you gave the name of.&lt;br /&gt;
{{Divhide|end}}&lt;br /&gt;
&lt;br /&gt;
==Commands==&lt;br /&gt;
===Conversion between .dat and .oni===&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;width:430px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-list &amp;lt;file name&amp;gt;&amp;lt;/code&amp;gt;||Lists the named resources contained in a .dat (see [[OBD:File types/Naming|HERE]] for info on unnamed resources)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-export &amp;lt;destination directory&amp;gt; &amp;lt;dat file&amp;gt;&amp;lt;/code&amp;gt;||Breaks .dat file into .oni files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-export:&amp;lt;pattern&amp;gt; &amp;lt;destination directory&amp;gt; &amp;lt;dat file&amp;gt;&amp;lt;/code&amp;gt;||Exports named resource (wildcards also allowed) from .dat file&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-import &amp;lt;source directory&amp;gt; &amp;lt;new dat file&amp;gt;&amp;lt;/code&amp;gt;||Compiles level files from source directory using the name you supply for the .dat file; tries to get target file format from source SNDD, but it&#039;s better to use the :sep or :nosep variants below&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|&amp;lt;span style=&amp;quot;padding-left:20px&amp;quot;&amp;gt;To create level5_Final.dat/.raw[/.sep] from the files in MyNewLevel\: &amp;lt;code&amp;gt;OniSplit.exe -import C:\Oni\MyNewLevel\ C:\Oni\GameDataFolder\level5_Final.dat&amp;lt;/code&amp;gt;&amp;lt;span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-import:sep &amp;lt;source directory&amp;gt; &amp;lt;new dat file&amp;gt;&amp;lt;/code&amp;gt;||Imports target file (.dat) from source directory; uses .dat/.raw/.sep format (Mac and PC Demo)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-import:nosep &amp;lt;source directory&amp;gt; &amp;lt;new dat file&amp;gt;&amp;lt;/code&amp;gt;||Imports target file (.dat) from source directory; uses .dat/.raw format (PC retail)&lt;br /&gt;
|}&lt;br /&gt;
:Note that &amp;lt;tt&amp;gt;-import&amp;lt;/tt&amp;gt; will search subdirectories too. If you find having hundreds or thousand of files .oni in one directory to be unmanageable you can always group them in subdirectories any way you like. The only exception is that a subdirectory named &amp;quot;noimport&amp;quot; or &amp;quot;_noimport&amp;quot; is always ignored.&lt;br /&gt;
&lt;br /&gt;
===Management of .oni files===&lt;br /&gt;
Sometimes you want to move some .oni files out of a larger folder of .onis. You could do this manually, but OniSpit knows which files depend on others. It will also look for those dependencies in subfolders beneath the level of the file you supply the name of. The filename field supports wildcards. This is mostly used by the [[AE]] Installer rather than modders themselves.&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-deps &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Displays a list of .oni files that the specified .oni file depends on&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-copy &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Copies .oni file and its dependencies; skips file if it already exists at destination&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-move &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Moves an .oni file and its dependencies; skips file if it already exists at destination&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-move:overwrite &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Moves an .oni file and its dependencies; overwrites any existing .oni files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-move:delete &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Moves an .oni file and its dependencies; doesn&#039;t overwrite; deletes source files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Conversion between .oni/.dat and 3rd party formats===&lt;br /&gt;
====Textures====&lt;br /&gt;
Unless mentioned otherwise, source filenames support wildcards. See [[Modifying textures|HERE]] for a detailed tutorial. The &amp;lt;tt&amp;gt;-extract&amp;lt;/tt&amp;gt; commands can work with .oni files (a single file or several files if you use the wildcard), or rip all the TXMPs from a .dat file.&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:dds &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts all textures (TXMP) from a Oni .dat/.oni file into DDS files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:tga &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts all textures (TXMP) from a Oni .dat/.oni file into TGA files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:png &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts all textures (TXMP) from a Oni .dat/.oni file into PNG files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:txmp &amp;lt;destination directory&amp;gt;&amp;lt;br&amp;gt;[-genmipmaps] [-nouwrap] [-novwrap]&amp;lt;br&amp;gt;&amp;lt;nowiki&amp;gt;[-format:bgr32|bgra32|bgr555|bgra5551|bgra4444|dxt1]&amp;lt;/nowiki&amp;gt;&amp;lt;br&amp;gt;[-envmap:texture_name] &amp;lt;image file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|valign=top|Creates .oni file from image file (PNG, TGA, or DDS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Models====&lt;br /&gt;
[[M3GM]]s, [[ONWC]]s, [[ONCC]]s can be exported to the Wavefront .obj and COLLADA .dae formats. For details see [[Importing character models]] and [[Importing weapon models]]. The generic &amp;lt;tt&amp;gt;-extract&amp;lt;/tt&amp;gt; commands can work with .oni files (a single file, or several files if you use the wildcard), or rip all the TXMP from a .dat file. TRBS and ONCC support additional &amp;lt;tt&amp;gt;-noanim&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-anim&amp;lt;/tt&amp;gt; options for &amp;lt;tt&amp;gt;-extract:dae&amp;lt;/tt&amp;gt;; see [[Importing character models]] for details. Imported geometry must only contain triangles.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;width:540px&amp;quot;|&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:obj &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts 3D data in .oni file (or all M3GM, ONWC and ONCC instances in a .dat) into Wavefront OBJ files&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:dae &amp;lt;destination directory&amp;gt; [-noanim] &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts 3D data in .oni file (or all M3GM, ONWC and ONCC instances in a .dat) into Collada DAE files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:m3gm &amp;lt;destination directory&amp;gt; [-tex:texture_name] &amp;lt;OBJ file&amp;gt;&amp;lt;/code&amp;gt;||Creates a M3GM .oni from an .obj file&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:trbs &amp;lt;destination directory&amp;gt; [-cel] [-normals] &amp;lt;DAE file&amp;gt;&amp;lt;/code&amp;gt;||Creates a TRBS .oni from a .dae file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note on -noanim parameter: Normally OniSplit exports the character with an idle animation. If you use -noanim the character is exported in &amp;quot;I&amp;quot; pose, also the pelvis has the coordinates x=0, y=0, z=0.&lt;br /&gt;
&lt;br /&gt;
====Levels====&lt;br /&gt;
OniSplit can convert AKEV files (level geometry) and the associated file types to and from DAE format:&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:dae &amp;lt;destination directory&amp;gt; &amp;lt;AKEV.oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts 3D data in AKEV and related resources from dependencies into Collada file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next two steps are used on a folder in which you have placed the DAE and XML-formatted instances of the required files, as well as textures in TGA format. See [https://web.archive.org/web/20201127180431/http://oni.bungie.org/forum/viewtopic.php?id=1515 HERE] for details.&lt;br /&gt;
{|&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-create &amp;lt;destination directory&amp;gt;&amp;lt;br&amp;gt;[-genmipmaps] [-format:dxt1]&amp;lt;br&amp;gt;&amp;lt;source directory&amp;gt;&amp;lt;/code&amp;gt;||Converts all AKEV and related instances to .oni files&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;code&amp;gt;-import:nosep &amp;lt;source directory&amp;gt;&amp;lt;br&amp;gt;&amp;lt;target file name&amp;gt;.dat&amp;lt;/code&amp;gt;||The standard command for creating .dat/.raw files from .oni files (remember to use the import:sep option on Mac!)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Sounds====&lt;br /&gt;
The sounds in Windows Oni are stored in WAV format, and on Macs are stored in AIFF format. This also means creating each of your SNDD files in both formats in order to work on both platforms.&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:wav &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Rips sound data from an SNDD .oni file (or all SNDDs from a .dat) as .wav files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:aif &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Rips sound data from an SNDD .oni file (or all SNDDs from a .dat) as .aif files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Text====&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:txt &amp;lt;destination directory&amp;gt; &amp;lt;dat/oni file&amp;gt;&amp;lt;/code&amp;gt;||Rips text data from a SUBT .oni file (or all SUBTs from a .dat) as .txt files&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create:subt &amp;lt;destination directory&amp;gt; &amp;lt;TXT file&amp;gt;&amp;lt;/code&amp;gt;||Creates a SUBT .oni file from a .txt file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====XML====&lt;br /&gt;
One of the latest features is conversion of .oni files to and from an XML file, or an XML metafile and related 3rd-party format files. XML files are easier to read and edit.&lt;br /&gt;
::Currently XML export/import is limited to files that do not have raw/sep parts. 2-way conversion is known to work for [[BINA]], [[CONS]], [[DOOR]], [[DPge]], [[FILM]], [[HPge]], [[IGHH]], [[IPge]], [[M3GM]], [[OBAN]], [[ONCC]], [[ONCV]], [[ONLD]], [[ONLV]], [[ONGS]], [[ONSK]], [[ONVL]], [[ONWC]], [[OPge]], [[OSBD]], [[PSpc]], [[PSpL]], [[PSUI]], [[TRAC]], [[TRAM]], [[TRIG]], [[TRGE]], [[TRMA]], [[TRSC]], [[TXMB]], [[TXMP]], [[WMCL]], [[WMDD]], [[WMM_]], [[WPge]].&lt;br /&gt;
:::For detailed examples and tutorials, see [[XML|HERE]]&lt;br /&gt;
{|&lt;br /&gt;
|&amp;lt;code&amp;gt;-extract:xml &amp;lt;destination directory&amp;gt; &amp;lt;oni file&amp;gt;&amp;lt;/code&amp;gt;||Extracts .oni file and all related resources to XML files and 3rd-party formats&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;-create &amp;lt;destination directory&amp;gt; &amp;lt;XML file&amp;gt;&amp;lt;/code&amp;gt;||Creates an .oni file from an XML file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Blender support====&lt;br /&gt;
[[Blender]] by default has a number of issues with most of Oni&#039;s assets, however, OniSplit allows exporting them to Blender-readable files with the &amp;lt;tt&amp;gt;-blender&amp;lt;/tt&amp;gt; flag.&lt;br /&gt;
&lt;br /&gt;
For more detailed information on how to use the &amp;lt;tt&amp;gt;-blender&amp;lt;/tt&amp;gt; flag, please check [[Importing_character_models#Blender-specific_OniSplit_information|Blender specific OniSplit information]]. &lt;br /&gt;
&lt;br /&gt;
[[Category:Completed modding tools]][[Category:Bi-platform modding tools]][[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=SketchUp_tutorials_and_tips&amp;diff=43846</id>
		<title>SketchUp tutorials and tips</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=SketchUp_tutorials_and_tips&amp;diff=43846"/>
		<updated>2025-01-22T06:26:03Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Tutorials */Fixed broken forum links.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Tutorials==&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
! Tutorial&lt;br /&gt;
! Author&lt;br /&gt;
! Link&lt;br /&gt;
! Status&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| How to make a simple level&lt;br /&gt;
| [[User:Lukas Kreator|Lukas Kreator]]&lt;br /&gt;
| [https://web.archive.org/web/20190712222844/http://oni.bungie.org/forum/viewtopic.php?pid=35324 Oni Central Forum]&lt;br /&gt;
| Finished, but outdated&lt;br /&gt;
| Replaced by the tutorial below&lt;br /&gt;
|-&lt;br /&gt;
| Creating the Lair - A level tutorial&lt;br /&gt;
| [[User:EdT|EdT]]&lt;br /&gt;
| [https://web.archive.org/web/20201029114347/http://oni.bungie.org/forum/viewtopic.php?id=2087 Oni Central Forum]&lt;br /&gt;
| Finished&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
&amp;lt;small&amp;gt;([[User:EdT|EdT]]: You are welcome to put some tips here, about the doors and lasers for example...)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Faces===&lt;br /&gt;
Faces are made when you draw a rectangle, a triangle or a polygon. For example, a cube has 6 faces, because it is made of 6 squares. You could also consider the faces inside the cube, if it is hollow. Faces with no textures show in SketchUp as white or blue. White means it is a &amp;quot;front face&amp;quot;, blue means it is a &amp;quot;back face&amp;quot;. Oni will not draw back faces, and you cannot collide with them. You can flip the faces using Right Click -&amp;gt; Invert Faces, after selecting one or more faces. I suggest that you first invert back faces, and then texture the level. In old versions of OniSplit, back faces have to be textured too, in order for the level to be converted to AKEV successfully.&lt;br /&gt;
&lt;br /&gt;
===Stairs===&lt;br /&gt;
[[Image:Stairs with invisible ramp.png|thumb]]&lt;br /&gt;
If you want to make stairs, make the steps very small or make a ramp over it with an invisible texture. You can use [http://iritscen.oni2.net/wiki/Lukas%20Kreator-Invisible512px.png this all-transparent texture]. The stairs should then look like the image on the right.&lt;br /&gt;
&lt;br /&gt;
===Rotating geometry===&lt;br /&gt;
Some things may be rotated when you try to load your level in Oni. This seems to happen when the user groups stuff together and forgets to ungroup them later. There are two ways to fix it:&lt;br /&gt;
* Load your level in XSI Tools and export the .dae from there. Does not work always.&lt;br /&gt;
* Try to find what is grouped and ungroup it.&lt;br /&gt;
&lt;br /&gt;
===Yellow faces===&lt;br /&gt;
A weird phenomenon happened when an user from OCF (Delano762) was making a new level. There were yellow faces on some places. It is currently unknown what these are, but they seem to have been generated when he converted a Counter Strike map to a COLLADA .dae through a tool. According to him, he was unable to change the texture of these faces if he selected all faces in the level at the same time, but he could change them back to the default texture one at a time.&lt;br /&gt;
&lt;br /&gt;
===Common errors===&lt;br /&gt;
* If your level was converted successfully by OniSplit, but when you try to play it, Oni crashes after about 10% of loading the level, this means there are textures in the model that were not included in the level folder.  For example, the model uses TXMPtexture, but TXMPtexture.oni is missing from the level files.&lt;br /&gt;
* If you cannot convert your level to AKEV because OniSplit throws an error, you could be missing textures on some faces. Back faces also have to be textured, as far as I know. &lt;br /&gt;
** Note: This does not occur with the latest OniSplit, if a face does not have a texture, OniSplit will assign TXMPnotfoundtex to that face. So there is no need to assign textures to back faces. - [[User:EdT|EdT]]&lt;br /&gt;
* Sometimes OniSplit may throw an error similar to this: &amp;quot;Unsupported primitive type &amp;quot;&amp;lt;something&amp;gt;&amp;quot; found in geometry &amp;quot;mesh&amp;lt;number&amp;gt;-geometry&amp;quot;, ignoring&amp;quot;. I usually ignore this, because I don&#039;t know any case in wich this was a problem. Please, correct me if I&#039;m wrong.&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Using_the_Rigify_animation_rig&amp;diff=43845</id>
		<title>Using the Rigify animation rig</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Using_the_Rigify_animation_rig&amp;diff=43845"/>
		<updated>2025-01-22T06:15:08Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Tools and relevant tutorials */Fixed broken forum link to archive&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
This article is intended to explain the workflow of using the [http://mods.oni2.net/node/388 Rigify-based animation rig for Blender] (made by geyser) for the purpose of making Oni animations, and also how to use it, and what are the Oni-specific additions to it that we&#039;ve made.&lt;br /&gt;
&lt;br /&gt;
==Prerequisite tutorials==&lt;br /&gt;
As this rig is now intented to be used together with BlenderOni, it is necessary to be familiar with either:&lt;br /&gt;
* [[BlenderOni|BlenderOni&#039;s documentation,]]&lt;br /&gt;
* [https://www.youtube.com/watch?v=pA_Y8QBCvPI BlenderOni&#039;s explanatory video,] particularly time ranges from 0:00 - 3:07 and 21:24 - 48:05 (that&#039;s part 1 and 3 of the video).&lt;br /&gt;
&lt;br /&gt;
Besides that, I highly recommend watching the tutorials below if you feel you&#039;re lacking knowledge in any of these subjects:&lt;br /&gt;
&lt;br /&gt;
General Blender basics:&lt;br /&gt;
&lt;br /&gt;
* [https://www.youtube.com/watch?v=RG8qK5zPqgM Wolf&#039;s 45-Minute Crash Course for Blender Virgins]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Practical and intuitive explanation of what Inverse and Forward Kinematics (IK/FK) are - this is explained in Maya, but same principles apply in every 3D editing program including Blender:&lt;br /&gt;
* [https://www.youtube.com/watch?v=p6PYKyxR0aY Animating with IK and FK]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basics of using Rigify - &#039;&#039;&#039;all you need to know about animating with Rigify is stored in the video below.&#039;&#039;&#039; There is no point in making a tutorial on how to use the rig controllers themselves here - it&#039;s all in the video below:&lt;br /&gt;
&lt;br /&gt;
* [https://www.youtube.com/watch?v=vKgH5zXIYmM Rigify Tutorial #08 - Posing the Rigify rig] by CGDive&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(OPTIONAL) Tutorial on how to create the rig described here - this is strictly optional; the only practical reason to make your own rig is for the purpose of adjusting its controllers to a specific character, however, the advantage that you get out of that is purely visual and a marginal one at that - if you&#039;ve built your rig for Konoko, there&#039;s nothing stopping you from using it on a TCTF SWAT - the limb controllers will be only slightly out of place, which doesn&#039;t impact animating in any way. So ultimately you may want to go through this if you want to learn how this rig works, find this rig confusing, or even just for the bunch of great Youtube tutorials linked in that tutorial.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s worth noting that a huge part of this article is in fact copy-pasted from this tutorial.&lt;br /&gt;
&lt;br /&gt;
* [[Creating_an_animation_rig_in_Blender|Creating an animation rig in Blender]]&lt;br /&gt;
&lt;br /&gt;
==Required tools and commands==&lt;br /&gt;
There are several things worth knowing before you start using the rig, tools to get and tutorials to have ready to reference for commands.&lt;br /&gt;
&lt;br /&gt;
===Tools and relevant tutorials===&lt;br /&gt;
* &#039;&#039;&#039;[[BlenderOni|BlenderOni]]&#039;&#039;&#039; - this Blender addon is an integral companion tool for this rig - it contains a number of scripts which automate a lot of operations required to make any use out of the rig. Without those scripts, these operations (e.g. constraining the model to the rig and vice versa) would have to be done manually, which takes a ridiculous amount of time.&lt;br /&gt;
[[Image:Cmder.png|200px|right|thumb|Screenshot showing Cmder&#039;s capabilities within the context of modding Oni]]&lt;br /&gt;
* [http://mods.oni2.net/node/38 &#039;&#039;&#039;Current version of OniSplit.&#039;&#039;&#039;] This is the tool needed to import and export assets out of Oni. &#039;&#039;&#039;DO NOT USE OniSplit GUI or Vago for importing Oni assets into Blender&#039;&#039;&#039; - neither of these weren&#039;t updated in a long time, and thus they don&#039;t support OniSplit&#039;s v0.9.99.2 -blender option. You can still use them for other purposes though, such as sounds and converting .oni files to XMLs, etc.&lt;br /&gt;
* [https://docs.google.com/document/d/175uJGklYASAgrFjxuUG4-kJRDoMTjjP7GvNxSj1GscU/edit &#039;&#039;&#039;Oni-Blender tutorial&#039;&#039;&#039;] by EdT. Please read this in entirety to know likely-to-happen issues and refer to this as your guide for OniSplit commands relating to Blender.&lt;br /&gt;
* [https://web.archive.org/web/20211202215118/http://oni.bungie.org/forum/viewtopic.php?pid=23230#p23230 &#039;&#039;&#039;Brief overview on creating TRAMs&#039;&#039;&#039;] by EdT - while this was written with XSI in mind, this is still relevant as the process for preparing the XML files for Oni is still the same. Also the next post in that thread, called &#039;&#039;&#039;Brief walk through on modifying a TRAM,&#039;&#039;&#039; is an example of that overview put into practice.&lt;br /&gt;
&lt;br /&gt;
===Optional tools and tutorials===&lt;br /&gt;
* [https://cmder.app/ &#039;&#039;&#039;Cmder&#039;&#039;&#039;] (Windows only) - because OniSplit is a command line tool, it is highly recommended to get any upgrade to Windows&#039; Command Prompt. As shown in the screenshot on the right, Cmder allows you to start it from the context menu in any selected folder, and it also remembers your most recently used commands, vastly improving your workflow when you&#039;re forced to use any command line tools.&lt;br /&gt;
* [https://docs.blender.org/manual/en/2.81/addons/rigging/rigify.html &#039;&#039;&#039;Rigify documentation&#039;&#039;&#039;] - it&#039;s a plugin for Blender designed to automate a lot of rigging work. The rig described here is generated using Rigify. Take a look if you&#039;re interested and want to learn more, but you don&#039;t have to know Rigify&#039;s documentation to use this rig.&lt;br /&gt;
&lt;br /&gt;
==General workflow of animating for Oni using Rigify==&lt;br /&gt;
The most common way to animate characters is to create an armature (also known as a rig) to which the character model is constrained, usually through vertex weights specifying how much a given vertex is controlled by the given controller on a scale from 0 to 1, with all weights summing up to 1. The rig contains a number of controller bones that allow to animate more easily. Then, the animations are usually imported into the game along with the armatures, therefore the animation is stored along with the armature. An example of a game storing animations this way is Halo: Combat Evolved.&lt;br /&gt;
&lt;br /&gt;
Oni character models are divided into 19 rigid body parts organized in a parent-child relation, with the pelvis bone being the root bone, which effectively forms an FK rig. The animations are stored in TRAM files, containing rotation data for each of the 19 body parts, and also location data for the pelvis. There is no armature stored within the game files, therefore in order to use a rig on Oni characters, it is necessary to constrain each of the 19 body parts to the rig bones individually instead of mesh vertices. Also, this automatically means that Oni&#039;s way of storing animations is a destructive one - the data stored in the rig bones that are not direct functional equivalents to Oni character body parts will get lost once the animation is baked into body parts with Visual Transform.&lt;br /&gt;
&lt;br /&gt;
The general workflow of making animations using this rig is the following, assuming you want to make a single animation (i.e. you don&#039;t want to make a throw animation):&lt;br /&gt;
&lt;br /&gt;
# Open up a Blender scene containing the rig.&lt;br /&gt;
# Delete either the model in Pose1 or Pose2.&lt;br /&gt;
# (OPTIONAL) Assuming you want to animate a different character, delete the T-posed model.&lt;br /&gt;
## Import your desired character with textures using -noanim.&lt;br /&gt;
# Import the animation you are using as a starting point. For more detailed information on how to import an Oni animation to Blender, see the next header.&lt;br /&gt;
## If you did point 3, apply the textures on the animated model.&lt;br /&gt;
# Using the &#039;&#039;Set Rig Bone Constraint Targets&#039;&#039; option in BlenderOni, set the targets of the rig&#039;s bone constraints to be the body parts of the animation you&#039;ve imported.&lt;br /&gt;
# Using the Pose Matching functionality, constrain the rig to the imported animation (Set the IK-FK sliders on rig limbs to 1, as Pose Matching works only through FK controllers)&lt;br /&gt;
# For each frame that you want to remain in your animation, while having all the bones selected (or the ones you want), either:&lt;br /&gt;
## Press Ctrl+A, select &#039;&#039;Apply Visual Transform&#039;&#039; to Pose and keyframe it,&lt;br /&gt;
## Or use the &#039;&#039;Bone Visual Transformer&#039;&#039; option in BlenderOni to bake frames within a specified frame range.&lt;br /&gt;
# Disable bone constraints on the rig using the &#039;&#039;Bone Constraint Switch&#039;&#039; option in BlenderOni. &lt;br /&gt;
# &#039;&#039;&#039;Make your animation.&#039;&#039;&#039;&lt;br /&gt;
# Once your animation is ready, use the &#039;&#039;Object Visual Transformer&#039;&#039; option in BlenderOni to bake the rig keyframes into the character model.&lt;br /&gt;
# Using the &#039;&#039;Object Constraint Switch&#039;&#039; option in BlenderOni, disable the object constraints on the character model. &#039;&#039;&#039;The character model should now be animated and have the needed rotations and locations.&lt;br /&gt;
# Export the animation as a DAE.&lt;br /&gt;
&lt;br /&gt;
==Importing Oni animations to Blender==&lt;br /&gt;
This header describes how to import Oni animations to Blender.&lt;br /&gt;
&lt;br /&gt;
For detailed explanation of the required OniSplit commands, please refer to the &#039;&#039;&#039;Oni-Blender Tutorial by EdT&#039;&#039;&#039; listed in the &#039;&#039;&#039;Tools and relevant tutorials&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Assuming the character you want to animate isn&#039;t in your rig file, then using OniSplit, export any character you want as a DAE (-extract:dae) using -noanim and -blender arguments. &lt;br /&gt;
## As per EdT&#039;s &#039;&#039;&#039;Oni-Blender Tutorial&#039;&#039;&#039;, you should get &amp;lt;mark&amp;gt;&amp;lt;tt&amp;gt;AnimationDaeWriter: custom axis conversion&amp;lt;/tt&amp;gt;&amp;lt;/mark&amp;gt; in OniSplit output if you&#039;ve used the -blender argument. If you didn&#039;t get that on the output, it means something most likely went wrong and you won&#039;t be able to import the model into Blender (or you will be able to import it but it will be wrong).&lt;br /&gt;
## Assuming you wanted a textured model and thus you&#039;ve exported an ONCC, you should now get a &#039;&#039;&#039;DAE file&#039;&#039;&#039; and an &#039;&#039;&#039;&#039;&#039;images&#039;&#039;&#039;&#039;&#039; folder containing the textures for it.&lt;br /&gt;
# Using OniSplit, export the animation you want as an XML (-extract:xml) using -anim-body (lets you specify the character you want) and -blender arguments.&lt;br /&gt;
## You should get &#039;&#039;&#039;one DAE and one XML file for the animation.&#039;&#039;&#039; &lt;br /&gt;
# Open up a Blender scene containing the rig.&lt;br /&gt;
# Delete either the model either in Pose1 or Pose2 collection. &lt;br /&gt;
# Import the animation into Blender (&#039;&#039;&#039;MAKE SURE YOU CHECK THE &#039;&#039;Import Unit&#039;&#039; BOX EACH TIME&#039;&#039;&#039;, otherwise you will import the model with arbitrary units which will break everything and will be basically unadjustable later))&lt;br /&gt;
# Import the -noanim model into Blender (&#039;&#039;&#039;ALSO MAKE SURE YOU CHECK THE &#039;&#039;Import Unit&#039;&#039; BOX&#039;&#039;&#039;)&lt;br /&gt;
# Move the animated model to either Pose1 or Pose2 collection.&lt;br /&gt;
# If you&#039;ve imported the textured model, [[Blender#Lack_of_textures_on_animated_models|apply textures to the animated models and fix the alpha transparency issue]].&lt;br /&gt;
&lt;br /&gt;
==Added functionalities==&lt;br /&gt;
This header describes functionalities added to the rig by geyser that are not normally present in Rigify.&lt;br /&gt;
&lt;br /&gt;
===Pose matching===&lt;br /&gt;
The way we do animations is we almost universally start by copying the first or last frame of the preceeding animation. For this reason, we needed functionality that would allow us to snap the rig to an animated Oni character. The way it works, it that it uses bone constraints in rig controller bones targeting the character model in order to snap the rig to the model. The influence of the bone constraints is controlled through the Z location of Pose1 and Pose2 bones in the Pose Matching layer, which is done through drivers.&lt;br /&gt;
&lt;br /&gt;
To snap the rig to the animation in one of the Pose collections, simply move the appropriate Pose bone above the XY plane while in Pose mode.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pose1 and Pose2 below the XY plane !! Rig snapped to the animation in Pose 1 collection !! Rig snapped to the animation in Pose 2 collection&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:Unposed.png|300px|frameless|center]] || [[Image:Pose1.png|300px|frameless|center]] || [[Image:Pose2.png|300px|frameless|center]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Wrist snapping===&lt;br /&gt;
Often when using the IK handles for the arms you will find out that most of the time, you will need the hand to have the same rotation as the forearm. Normally this would mean that you would have to rotate the hands all the time, because IK handles are mainly moved around, and rotated later. For this reason, the wrist snapping functionality was implemented - you can simply copy the rotation of the forearm to the hand by pressing the &amp;quot;IK wrist&amp;quot; button.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Both of the hands after just moving them around... !! Effects of using the IK Wrist button&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:IK Wrist Example1.png|500px|frameless|center]] || [[Image:IK Wrist Example2.png|500px|frameless|center]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43844</id>
		<title>Creating a level</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43844"/>
		<updated>2025-01-22T04:12:39Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Vertex coloring */Broken forum link to archive&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page covers level creation from scratch. See [[Modifying an existing level]] if you want to change a vanilla level in the game.&lt;br /&gt;
&lt;br /&gt;
==Level releases and resources==&lt;br /&gt;
===Fan-made levels===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable autosort by-column-3&amp;quot;&lt;br /&gt;
!Date&lt;br /&gt;
!Name&lt;br /&gt;
!Level number&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Oni 2 Angel Studios Tour&lt;br /&gt;
|32&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Green Room&lt;br /&gt;
|26&lt;br /&gt;
|-&lt;br /&gt;
|2019/09/16&lt;br /&gt;
|[https://web.archive.org/web/20240527004257/http://oniforum.bungie.org/viewtopic.php?id=2965 Omega Tournament]&lt;br /&gt;
|31&lt;br /&gt;
|-&lt;br /&gt;
|2016/02/13&lt;br /&gt;
|[https://web.archive.org/web/20160224173743/http://oni.bungie.org/forum/viewtopic.php?id=2947 AI Battle]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2014/01/19&lt;br /&gt;
|[https://web.archive.org/web/20211202225410/http://oni.bungie.org/forum/viewtopic.php?id=2698 Wilderness Preserve]&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|2013/09/07&lt;br /&gt;
|[https://web.archive.org/web/20201127180732/http://oni.bungie.org/forum/viewtopic.php?id=2656 Island]&lt;br /&gt;
|29&lt;br /&gt;
|-&lt;br /&gt;
|2013/07/12&lt;br /&gt;
|[https://web.archive.org/web/20201127175459/http://oni.bungie.org/forum/viewtopic.php?id=2640 City]&lt;br /&gt;
|28&lt;br /&gt;
|-&lt;br /&gt;
|2013/06/01&lt;br /&gt;
|[https://web.archive.org/web/20201029102326/http://oni.bungie.org/forum/viewtopic.php?id=2619 Fight Club]&lt;br /&gt;
|25&lt;br /&gt;
|-&lt;br /&gt;
|2012/05/12&lt;br /&gt;
|[https://web.archive.org/web/20220701102842/http://oni.bungie.org/forum/viewtopic.php?id=2357 Old China]&lt;br /&gt;
|24&lt;br /&gt;
|-&lt;br /&gt;
|2012/03/18&lt;br /&gt;
|[https://web.archive.org/web/20211202220454/http://oni.bungie.org/forum/viewtopic.php?id=2302 Boss Battle]&lt;br /&gt;
|23&lt;br /&gt;
|-&lt;br /&gt;
|2012/02/12&lt;br /&gt;
|[https://web.archive.org/web/20201029113554/http://oni.bungie.org/forum/viewtopic.php?id=2271 De Dust Deluxe]&lt;br /&gt;
|22&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/23&lt;br /&gt;
|[https://web.archive.org/web/20201029114415/http://oni.bungie.org/forum/viewtopic.php?id=2242 Parkour Challenge 2]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/16&lt;br /&gt;
|[https://web.archive.org/web/20211205145843/http://oni.bungie.org/forum/viewtopic.php?id=2235 Parkour Challenge]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/25&lt;br /&gt;
|[https://web.archive.org/web/20201029103607/http://oni.bungie.org/forum/viewtopic.php?id=2001 Mini-Partenon]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2011/10/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113340/http://oni.bungie.org/forum/viewtopic.php?id=2024 Muro&#039;s Lair - Preview]&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113724/http://oni.bungie.org/forum/viewtopic.php?id=1957 Hexagon]&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|2011/06/23&lt;br /&gt;
|[https://web.archive.org/web/20201029104928/http://oni.bungie.org/forum/viewtopic.php?id=1938 Junkyard]&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|2011/05/01&lt;br /&gt;
|[http://mods.oni2.net/node/178 Arena of Hurt (OZG)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/08&lt;br /&gt;
|[https://web.archive.org/web/20210117150652/http://oni.bungie.org/forum/viewtopic.php?id=1736 Arena of Hurt (OTA)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/06&lt;br /&gt;
|[https://web.archive.org/web/20201029105217/http://oni.bungie.org/forum/viewtopic.php?pid=50565#p50565 Martian Colony] AKA &amp;quot;Silly World&amp;quot;&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2010/02/15&lt;br /&gt;
|[https://web.archive.org/web/20201029113916/http://oni.bungie.org/forum/viewtopic.php?id=1506 Maze]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2008/09/16&lt;br /&gt;
|[http://mods.oni2.net/node/4 Arena of Pain]&lt;br /&gt;
|30&lt;br /&gt;
|-&lt;br /&gt;
|2024/05/20&lt;br /&gt;
|[https://gamebanana.com/mods/514707 Kitsune: Chapter 1]&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Forum tutorials on level creation===&lt;br /&gt;
* &#039;&#039;&#039;[https://web.archive.org/web/20201029114347/http://oni.bungie.org/forum/viewtopic.php?id=2087 &amp;quot;Creating the Lair - A level tutorial&amp;quot;]&#039;&#039;&#039;&lt;br /&gt;
* [https://web.archive.org/web/20201127172559/http://oni.bungie.org/forum/viewtopic.php?pid=53026 &amp;quot;Creating a Custom Oni Level (s10k video tutorials)&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201127180431/http://oni.bungie.org/forum/viewtopic.php?id=1515 &amp;quot;Creating new levels&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201029114358/http://oni.bungie.org/forum/viewtopic.php?pid=33838 &amp;quot;Create levels with pathfinding grids&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20210117145338/http://oni.bungie.org/forum/viewtopic.php?id=2000 &amp;quot;More questions about levels&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201029103906/http://oni.bungie.org/forum/viewtopic.php?pid=37252#p37252 &amp;quot;Modding Existing levels - Beta&amp;quot; (&amp;quot;Moveable furniture&amp;quot; post)]&lt;br /&gt;
&lt;br /&gt;
===Wiki pages on level creation===&lt;br /&gt;
* [[Creating a level]] (you are here)&lt;br /&gt;
* [[Modifying an existing level]]&lt;br /&gt;
* [[New levels]]&amp;lt;!--notes and comments by geyser that should be revisited / merged with this page--&amp;gt;&lt;br /&gt;
* [[Lightmapping levels]]&lt;br /&gt;
&lt;br /&gt;
===Free asset sources===&lt;br /&gt;
* [http://vk.com/gameready Various game meshes]&lt;br /&gt;
* [http://web.archive.org/web/20230601050258/http://tutorialsforblender3d.com/Textures/Textures_index.html Various game textures]&lt;br /&gt;
* [https://www.textures.com Various game textures]&lt;br /&gt;
&lt;br /&gt;
==Engine limitations==&lt;br /&gt;
First you should be aware of the limitations that Oni will place on your level.&lt;br /&gt;
&lt;br /&gt;
* The triangle limit of a game level is approx. 520,000 (consider it 500,000 to be on the safe side).&lt;br /&gt;
* {{ModTool}} can save DAE files with a maximum of 64,000 triangles per object.&lt;br /&gt;
* When polygons are too tightly packed, the camera will look at too many of them and glitches will appear. The limit on visible GQs (Gunk Quads) is 8,192 (2&amp;lt;sup&amp;gt;13&amp;lt;/sup&amp;gt;), and higher numbers will cause render bugs and produce the console error message &amp;quot;Exceeded max visible GQs &#039;&#039;number&#039;&#039;&amp;quot;. There are limited solutions to this:&lt;br /&gt;
** Decrease the &#039;&#039;&#039;gs_farclipplane_set&#039;&#039;&#039; value.&lt;br /&gt;
** Hide objects via &#039;&#039;&#039;[[#.3CModel.3E|env_show]]&#039;&#039;&#039;.&lt;br /&gt;
** Hide objects by &#039;&#039;level design&#039;&#039;. For example, departments in a building could be quite detailed because the view of the other departments/rooms is blocked by walls.&lt;br /&gt;
* The camera can look at 2,049 transparent textures at once; one more, and Oni crashes.&lt;br /&gt;
* Characters are visible &#039;&#039;only&#039;&#039; within world coordinates {-4,099, -4,099, -4,099} to {4,099, 4,099, 4,099}.&lt;br /&gt;
* Geometry stops outside of (roughly) world coordinates -4,228 to 4,228 on the X and Z axes (vertical axis not tested).&lt;br /&gt;
* &#039;&#039;&#039;chr_debug_spheres = 1&#039;&#039;&#039; visualizes the collision spheres of characters, so you can check if they will fit through an entrance.&lt;br /&gt;
&lt;br /&gt;
==3D tools==&lt;br /&gt;
===Problems when using multiple different tools===&lt;br /&gt;
Re-saving a DAE file in &#039;&#039;&#039;Mod Tool&#039;&#039;&#039; which was originally made in &#039;&#039;&#039;SketchUp&#039;&#039;&#039; can result in a surprising change in size within Oni. This is due to a difference in the specification of a scale unit.&lt;br /&gt;
&lt;br /&gt;
: For example, the SketchUp DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.0254000&amp;quot; name=&amp;quot;inch&amp;quot; /&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: And the re-saved Mod Tool DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.1&amp;quot; name=&amp;quot;decimetre&amp;quot;&amp;gt;&amp;lt;/unit&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case you&#039;ll need to open the new DAE in a text editor and change the length specification back.&lt;br /&gt;
&lt;br /&gt;
===Sketchup===&lt;br /&gt;
If you are working with Sketchup check out this pages:&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?id=2003 &amp;quot;Sketchup tutorials for making levels&amp;quot;]&lt;br /&gt;
* [[SketchUp tutorials and tips]]&lt;br /&gt;
&lt;br /&gt;
===Blender===&lt;br /&gt;
&#039;&#039;&#039;Scaling&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as Mod Tool and SketchUp: Caution with scaling: See [[#Problems when using multiple different tools|here]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pathfinding&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Be sure to uncheck automatic triangle creation when exporting (BNV) geometry used for pathfinding. Ghost (&#039;&#039;doors&#039;&#039;) must be quads. &lt;br /&gt;
&lt;br /&gt;
==Setting up a workflow==&lt;br /&gt;
If not noted differentely you need OniSplit v0.9.82.0 or a newer version. Onisplit can be downloaded [http://mods.oni2.net/node/38 HERE] (it also comes with the [[AE]] and is found in the Tools directory of the installation).&lt;br /&gt;
&lt;br /&gt;
The level import demo files can be downloaded [http://mods.oni2.net/node/299 HERE].&lt;br /&gt;
&lt;br /&gt;
First, put &#039;&#039;&#039;OniSplit.exe&#039;&#039;&#039; into the second &#039;&#039;&#039;lab&#039;&#039;&#039; folder alongside the XML files.&lt;br /&gt;
&lt;br /&gt;
Look at the file &#039;&#039;&#039;build.cmd&#039;&#039;&#039;. These are the two important lines:&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:level out lab.xml&lt;br /&gt;
 OniSplit.exe -import:pc out level3_Final.dat&lt;br /&gt;
&lt;br /&gt;
The first line creates the *.oni files from a master.xml file, in this case &#039;&#039;&#039;lab.xml&#039;&#039;&#039;. Once finalized, the resulting .oni files can be put into a new [[Making a mod package|AE package]].&lt;br /&gt;
&lt;br /&gt;
The second line creates level archives which can be used for fast tests. They don&#039;t require you to install a package through the AE Installer.&lt;br /&gt;
&lt;br /&gt;
Instead of &amp;quot;-nosep&amp;quot; you can now also use &amp;quot;-pc&amp;quot; for the import. Macs, however, do use &amp;quot;-sep&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
If the game crashes while loading at ~90% progress, be sure that the texture&#039;s x and y dimensions are powers of two: 64, 128, 256, 512….&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading at ~50-60% progress, be sure that the BINACJBOCharacters or AISA file has a player character defined.&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading ~5-10% progress, check if all your textures were inside the &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
:You can extract the AKEV file to XML, then search for the [[XML:AKEV#TXMA|TXMP Array]].&lt;br /&gt;
&lt;br /&gt;
:[http://mods.oni2.net/system/files/AKEV_texture_checker.txt THIS] script checks which textures are missing by comparing the AKEV*.xml with its *.oni files folder. Change the two paths so that it works for you: Alt+4, insert code, then F5.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;TXMP_marker_door&amp;quot; and &amp;quot;TXMP_marker_ghost&amp;quot; will be missing in the demo&#039;s &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
You can add this between the other two lines in build.cmd to prevent a crash.&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
;Polygon&lt;br /&gt;
:A polygon is a shape defined by points (vertices) in space. Polygons are the most fundamental building block in games. Oni uses only shapes with 3 and 4 points (triangles and quads). Other games might also use N-gons, shapes with more points.&lt;br /&gt;
;Face&lt;br /&gt;
:The &#039;&#039;&#039;surface of a polygon&#039;&#039;&#039; is also named face. The &#039;&#039;&#039;direction&#039;&#039;&#039; of a face in &#039;&#039;&#039;defined by its normal&#039;&#039;&#039;. If an object seems to have a hole, it might be that the polygon just has a &#039;&#039;&#039;flipped normal&#039;&#039;&#039; and is therefore wrongly rendered (displayed on screen).&lt;br /&gt;
;Normal&lt;br /&gt;
:Faces and even vertices themselves have directions. The normals of vertices determine how smooth or sharp edges will appear.&lt;br /&gt;
;Vertex (plural&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt; vertices)&lt;br /&gt;
:A point within a polygon.&lt;br /&gt;
:Vertex colors radiate from one vertex to another vertex, whereby their different color values blend into each other so that gradients can appear. &lt;br /&gt;
;Edge&lt;br /&gt;
:A line of two points within a polygon.&lt;br /&gt;
;Tris (triangles)&lt;br /&gt;
:Polygons made of 3 points.&lt;br /&gt;
;Quads&lt;br /&gt;
:Polygons made of 4 points. Planes. Rectangles.&lt;br /&gt;
:Internally, all quads get converted into two triangles and will affect the maximum triangle count accordingly.&lt;br /&gt;
;Level&lt;br /&gt;
:The term &amp;quot;level&amp;quot; is often used to shorten &amp;quot;level map&amp;quot; (buildings and terrain).&lt;br /&gt;
;Geometry&lt;br /&gt;
:Level geometry can be objects made of tris and/or quads.&lt;br /&gt;
:Oni differentiates between basically 3 types of level geometry:&lt;br /&gt;
:* Static objects (sometimes also named AKEV core geometry)&lt;br /&gt;
:* Animated objects&lt;br /&gt;
:* Pushable objects (not used in the original game)&lt;br /&gt;
;Static geometry&lt;br /&gt;
:* &#039;&#039;&#039;Unique level geometry with no functions&#039;&#039;&#039; (AKEV core geometry such as buildings and streets).&lt;br /&gt;
:* &#039;&#039;&#039;Repeating objects&#039;&#039;&#039; are flagged as &#039;&#039;&#039;furniture (FURN)&#039;&#039;&#039; although they can be outdoor objects such as boxes and containers. &amp;lt;!--Oni&#039;s story plays out most often inside buildings. So, there you go. --&amp;gt;FURN objects were used to be imported by an object collection, an CJBO. Nowadays, furniture collections can be used (again) for imports, but the individual objects are stored as OFGA files. This modularity is known in many game editors (like the Unreal Engine Editor). So, &#039;&#039;&#039;OFGA are nothing else than &amp;quot;game assets&amp;quot;.&#039;&#039;&#039; The drawback of OFGA is that they &#039;&#039;&#039;will not import with any vertex shading&#039;&#039;&#039;. Only their &#039;&#039;&#039;geometries&#039;&#039;&#039;, attached &#039;&#039;&#039;particle&#039;&#039;&#039; and &#039;&#039;&#039;gunk flags&#039;&#039;&#039; get copied into final (baked) level geometry.&lt;br /&gt;
:* &#039;&#039;&#039;Objects with actual functions&#039;&#039;&#039; (CJBO such as doors, consoles, triggers)&lt;br /&gt;
:** Some types of CJBO (spawn lists of weapons, characters, powerups and of course flags and patrol paths) are not considered as level geometry.&lt;br /&gt;
;[[XML:AKEV#AGQG|Gunk flags]]&lt;br /&gt;
:Properties directly associated with the polygons. Among others, these can be: Transparent, TwoSided, NoCollision, Invisible, NoObjectCollision, NoCharacterCollision, NoDecals, Furniture, Impassable.&lt;br /&gt;
;Baking&lt;br /&gt;
:When a level gets baked, all geometries get merged.&lt;br /&gt;
:*Unique level geometry will have vertex painting.&lt;br /&gt;
:*Objects derived from already compiled oni-files (shared classes) will have no vertex painting.&lt;br /&gt;
:*Animated and pushable objects will have no vertex shading.&lt;br /&gt;
;Vertex shading&lt;br /&gt;
:Vertex colors (vector data) can be painted onto core geometry.&lt;br /&gt;
:They are used as a rudimentary form of lightmapping (pixel data).&lt;br /&gt;
:Having vertex shading is still better than having no vertex shading at all. It makes the level appear more lifelike.&lt;br /&gt;
;Lightmapping&lt;br /&gt;
:In other games, lights and shadows are added to level geometry with lightmapping.&lt;br /&gt;
:There were experiments to bring lightmaps back to Oni. The technique come with a major drawback though. It doubles the triangle count and adds many textures.&lt;br /&gt;
;In-game&lt;br /&gt;
:When you are &amp;quot;inside&amp;quot; the game, running or playing it.&lt;br /&gt;
&lt;br /&gt;
==Level construction==&lt;br /&gt;
&#039;&#039;&#039;Visible environment&#039;&#039;&#039;&lt;br /&gt;
* A &#039;&#039;&#039;level map&#039;&#039;&#039; consists of visible geometry: terrain and buildings. This is also named the &#039;&#039;&#039;environment&#039;&#039;&#039; or for short &#039;&#039;&#039;env&#039;&#039;&#039;.&lt;br /&gt;
** Use &#039;&#039;&#039;quads&#039;&#039;&#039; of approximately 10 up to 20 meters in size to construct env geometry.&lt;br /&gt;
* Anything other than floors and simple walls will be made of triangles.&lt;br /&gt;
** Geometry from CJBO works best with triangles. Quads might show holes in-game.&lt;br /&gt;
&#039;&#039;&#039;Invisible pathfinding&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;AIs&#039;&#039;&#039; (or non-player characters, NPCs) need &#039;&#039;&#039;pathfinding&#039;&#039;&#039; data, usually shortened as &#039;&#039;&#039;bnv&#039;&#039;&#039;.&lt;br /&gt;
** Pathfinding data can be described as geometry, therefore as rooms. These &#039;&#039;&#039;bnv rooms&#039;&#039;&#039; are made of &#039;&#039;&#039;floors&#039;&#039;&#039; and are connected by &#039;&#039;&#039;ghost&#039;&#039;&#039; quads which work like doors. AIs can move from one room to another room only by passing a ghost. Therefore, ghosts have the same width as rooms in open terrain.&lt;br /&gt;
*** Use floor quads of approximately 10 meters in size to construct BNV floors.&lt;br /&gt;
*** Put ghost quads exactly on the edges of BNV floors with an angle of 90 degree.&lt;br /&gt;
&#039;&#039;&#039;Support for [[XML:BINA/ONIE|effects]]&#039;&#039;&#039;&lt;br /&gt;
* Effects such as decals that indicate damaged environment need level textures to be registered in [[XML:BINA/TMBD|TMBD]]. Make sure not to replace existing texture entries but to add your own so that the other levels remain unaffected.&lt;br /&gt;
&#039;&#039;&#039;Level logic&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BSL scripts bring levels fully to life. The logic is mostly event driven whereby different checkpoints and conditions must be reached.&lt;br /&gt;
* Checkpoints are actually [[XML:BINA/OBJC/TRGV|trigger volumes]] that can recognize entering and exiting characters.&lt;br /&gt;
* The second most important source of events are [[XML:BINA/OBJC/CHAR|character (script) functions]], especially the die function of enemies.&lt;br /&gt;
** To support good and less good players alike, NPC characters can feature the UpgradeDifficulty flag. Also, BSL scripts can detect the current [[BSL:Game_status|difficulty level]].&lt;br /&gt;
* [[XML:BINA/OBJC/TRIG|Laser triggers]] are mostly used to control [[XML:BINA/OBJC/TURR|turrets]]. [[XML:BINA/OBJC/CONS|Consoles]], triggers and [[XML:DOOR|door]] unlocking are used to set up very simple &amp;quot;riddles”.&lt;br /&gt;
* The creation of cut scenes is time-consuming quality work. Due to missing tools for streamlined workflows, it is totally okay for you to skip this.&lt;br /&gt;
** New synchronized FILM, OBAN and TRAM files are required for cut scenes. Not to mention sound files for dialog.&lt;br /&gt;
&lt;br /&gt;
==The master XML file==&lt;br /&gt;
&#039;&#039;The project file for level creation.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;master XML&#039;&#039;&#039; file&#039;s &#039;&#039;&#039;name determines&#039;&#039;&#039; the &#039;&#039;&#039;BSL folder name&#039;&#039;&#039; and the &#039;&#039;&#039;AKEV and ONLV file names&#039;&#039;&#039; in the output folder. File paths in the XML can be either absolute or relative.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mandatory files&#039;&#039;&#039; for level import:&lt;br /&gt;
* &#039;&#039;level_environment&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_bnv&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_textures.tga/jpg/png&#039;&#039;&lt;br /&gt;
* Character.xml or AISA with player&lt;br /&gt;
* ONSK name in &amp;lt;Sky&amp;gt; (in Windows, this can be a fake name; does the Mac need actual ONSK files?)&lt;br /&gt;
* ONLD file for the new level; read [[Making_a_mod_package#Mod_Info.cfg|HERE]] about making sure your level is unlocked (accessible on the Load Game screen)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Level SharedPath=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| The master XML file can link to other XML files. Most of them will be [[OBD:BINA/OBJC#OBJC_types|BINACJBO]] files. The file type is declared inside the file, so the file name itself doesn&#039;t have to contain the type. Ergo, &amp;quot;BINACJBOCharacter.xml&amp;quot; can be given a simpler name like &amp;quot;Character.xml&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some resources used by those XML files can be found in a &#039;&#039;&#039;shared&#039;&#039;&#039; folder. OniSplit copies textures and &amp;quot;physics&amp;quot; objects into the output folder; furniture objects will be integrated into the AKEV. Unused resources in the shared folder will be ignored. That way the final level archive or AE package contains only the necessary files, saving disk space for the end user.&lt;br /&gt;
&lt;br /&gt;
In the demo are various subfolders in the &#039;&#039;&#039;shared&#039;&#039;&#039; folder: consoles, doors, furniture, triggers and turrets. These file types do not need their file prefixes: CONS, DOOR, TRIG and OFGA. OniSplit will recognize them nonetheless.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Common mistake:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CJBO files &#039;&#039;&#039;need relative paths to the resource instead of just file names&#039;&#039;&#039;. Taking consoles, for example: a standard export to XML gives you &amp;quot;console_data&amp;quot;. But to use the shared resources these must be paths like &amp;quot;&#039;&#039;&#039;consoles/console_data.oni&#039;&#039;&#039;&amp;quot; as they are stored in &#039;&#039;&#039;shared/console/&#039;&#039;&#039;. Note how the demoed &#039;&#039;&#039;shared&#039;&#039;&#039; folder is placed next to the [http://mods.oni2.net/node/299 project (&amp;quot;lab&amp;quot;)] folder and the XML master file points to it using &amp;quot;../shared&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Environment&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Model&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Used to import level geometry and static objects. See [[#&amp;lt;Model&amp;gt;|HERE]] for detailed information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Node Id=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| informational (space for notes)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Can be used with BSL commands such as ...&lt;br /&gt;
: [[#&amp;lt;Model&amp;gt;|env_show ID 1]] (use 0 to hide)&lt;br /&gt;
: [[#Breakable glass with BSL recognition|env_broken ID1 [ID2]]] (if a second ID is supplied then objects in the range ID1..ID2 get counted; &amp;quot;3001 3018&amp;quot; would cover 18 objects)&lt;br /&gt;
: [[#Texture exchange|env_texswap ID texture]] (no file prefix/suffix allowed)&lt;br /&gt;
: [[#env_shade|env_shade ID ID R G B]]&lt;br /&gt;
Static objects store their ID in [[XML:AKEV#IDXA_.28quad_group_id.29|one of AKEV&#039;s IDXA instances]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Rooms&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| For detailed information see [[#&amp;lt;Rooms&amp;gt;|HERE]].&lt;br /&gt;
&lt;br /&gt;
For a Google SketchUp BNV tutorial see [http://oni.bungie.org/forum/viewtopic.php?pid=36760#p36760 HERE].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. BNV data, used to create pathfinding.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Textures&amp;gt; {{Anchor|textures_tag}}&lt;br /&gt;
| -&lt;br /&gt;
| With OniSplit v0.9.94.0+ you can use attributes to set the default import formats and max dimensions. For example:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Textures with a dimension that isn&#039;t a power of two (2&amp;lt;sup&amp;gt;x&amp;lt;/sup&amp;gt;) and textures larger than 512px on a side will be resized. For example, 2003x2000 will become 512x512. (What would 257x255 become?)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Texture Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| TXMP file name to generate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Flags&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Optional tag. For list of flags see [[XML:TXMP|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Format&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
:DXT1&lt;br /&gt;
:BGR&lt;br /&gt;
:RGBA&lt;br /&gt;
:BGR555&lt;br /&gt;
:BGRA5551&lt;br /&gt;
:BGRA4444&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Image&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.tga/jpg file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Sky&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| ONSKfile.oni (without file pre- and suffix)&lt;br /&gt;
&lt;br /&gt;
The import doesn&#039;t work with an empty tag. &amp;lt;Sky&amp;gt;clear&amp;lt;/Sky&amp;gt; helps here; any other fictional name will also do.&lt;br /&gt;
&lt;br /&gt;
For detailed information see [[XML:ONSK|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Import&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to an OBJC (collection) file. Supported collection files for &amp;lt;Import&amp;gt; are:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[#Furniture.xml|Furniture.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[#Physics.xml|Physics.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
The following two collection files are &#039;&#039;&#039;NOT&#039;&#039;&#039; supported. You need to copy them as regular pre-compiled *.oni files into your mod package:&lt;br /&gt;
: [[XML:BINA/OBJC/MELE|Melee.xml]] (overrides global MELE; not used in vanilla levels)&lt;br /&gt;
: [[XML:BINA/OBJC/CMBT|Combat.xml]] (overrides global CMBT?; not used in vanilla levels)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Inside&#039;&#039;&#039; the following three supported collection files, provide links to pre-compiled (*.oni) class files: console, door and furniture collections. Use relative paths such as:&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;consoles/&#039;&#039;&#039;console_data&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;doors/&#039;&#039;&#039;TCdouble&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;furniture/&#039;&#039;&#039;V_tctf_bigvan&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you are unsure about the folder structure refer back to the [http://mods.oni2.net/node/299 level import demo].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Films&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.xml file. OniSplit creates a [[XML:FILM|FILM]] file from it. Used for characters in cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Cameras&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Camera Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. OniSplit creates an OBAN file from it. Used for cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Name for the OBAN file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a trimmed-down version of the master file &#039;&#039;&#039;lab.xml&#039;&#039;&#039; from the demo. It&#039;s meant to give you a first impression. We might upload a smaller demo someday with all features nonetheless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Level SharedPath=&amp;quot;../shared&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Environment&amp;gt;&lt;br /&gt;
            &amp;lt;Model&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bomber_window.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;/Model&amp;gt;&lt;br /&gt;
            &amp;lt;Rooms&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Rooms&amp;gt;&lt;br /&gt;
            &amp;lt;Textures&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;bgra4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
            &amp;lt;/Textures&amp;gt;&lt;br /&gt;
        &amp;lt;/Environment&amp;gt;&lt;br /&gt;
        &amp;lt;Sky&amp;gt;sunset&amp;lt;/Sky&amp;gt;&lt;br /&gt;
        &amp;lt;Objects&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Character.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Furniture.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;TriggerVolume.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Physics.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Objects&amp;gt;&lt;br /&gt;
        &amp;lt;Films&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun01.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun02.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Films&amp;gt;&lt;br /&gt;
        &amp;lt;Cameras&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam01.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam01&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam02.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam02&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
        &amp;lt;/Cameras&amp;gt;&lt;br /&gt;
    &amp;lt;/Level&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Model&amp;gt;===&lt;br /&gt;
This tag is mandatory (it must be present to avoid errors); the model section contains one import path to the AKEV (level) geometry (*.dae) and can contain additional import paths for exceptions (*.dae).&lt;br /&gt;
&lt;br /&gt;
Data from the demo:&lt;br /&gt;
&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;env_show&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The motorcycle has here scripting ID 9. You can show and hide the object with the BSL command &#039;&#039;&#039;env_show&#039;&#039;&#039;, where the second parameter means true or false. &#039;&#039;&#039;Never use 0 as an ID&#039;&#039;&#039; because it won&#039;t work.&lt;br /&gt;
&lt;br /&gt;
 env_show 9 1&lt;br /&gt;
 env_show 9 0&lt;br /&gt;
&lt;br /&gt;
EdT demonstrates env_show [https://www.youtube.com/watch?v=Em6wa5JTQNM here]. Note how the objects have collision.&lt;br /&gt;
&lt;br /&gt;
The last vanilla level (Syndicate Mountain Compound) has a big satellite dish platform that can be made hidden. Obviously, such objects/areas can be made to have pathfinding too.&lt;br /&gt;
&lt;br /&gt;
;More possible applications of env_show:&lt;br /&gt;
* ground/ceiling/objects for cutscenes that become partially destroyed&lt;br /&gt;
* destructible walls like in Deus Ex: Human Revolution (trigger volume, replacing punch anim with punch-through-wall anim)&lt;br /&gt;
* grids in front of ventilation shafts (a small door object could be an alternative)&lt;br /&gt;
** at the moment this can&#039;t be done because characters can&#039;t sneak under the top edge of the opening (the characters collision spheres are too big)&lt;br /&gt;
* managing object groups with trigger volumes (save multiple objects in one DAE file)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- atm, the effort is not worth the work&lt;br /&gt;
&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/TV_triggered_env_show.png&amp;lt;/nowiki&amp;gt; (dead link)&lt;br /&gt;
: edit: replace 0 by 25&lt;br /&gt;
&lt;br /&gt;
If the objects appear to flicker then we could replace the hide_all_object_groups() function with individual TV exit functions.&lt;br /&gt;
&lt;br /&gt;
 func hide_all_object_groups&lt;br /&gt;
 {&lt;br /&gt;
 	# env_show id [1|0]&lt;br /&gt;
 	env_show 1 0&lt;br /&gt;
 	env_show 2 0&lt;br /&gt;
 	# ...&lt;br /&gt;
 	env_show 25 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func show_object_group (int grpA, int grpB, int grpC, int grpD, int grpE, int grpF, int grpG, int grpH)&lt;br /&gt;
 {&lt;br /&gt;
 	env_show (grpA, 1)&lt;br /&gt;
 	env_show (grpB, 1)&lt;br /&gt;
 	env_show (grpC, 1)&lt;br /&gt;
 	env_show (grpD, 1)&lt;br /&gt;
 	env_show (grpE, 1)&lt;br /&gt;
 	env_show (grpF, 1)&lt;br /&gt;
 	env_show (grpG, 1)&lt;br /&gt;
 	env_show (grpH, 1)&lt;br /&gt;
 &lt;br /&gt;
 	# missing arguments are taken to be 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_25_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 &lt;br /&gt;
 	# show object group of entered TV and of neighboring TVs&lt;br /&gt;
 	# (center, north, north east, east, east south, south, south west, west, west north)&lt;br /&gt;
 	# there&#039;s a limit of 8 arguments per function&lt;br /&gt;
 	show_object_group 25 1 2 3 4 5 6 7&lt;br /&gt;
 	show_object_group 8&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # other examples&lt;br /&gt;
 func TV_6_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 0 0 00 0 00 00 00 00&lt;br /&gt;
 	show_object_group 22&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_20_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 20 21 6 19&lt;br /&gt;
 }&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Import of object groups====&lt;br /&gt;
&#039;&#039;&#039;Mod Tool versus SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The meaning and behavior of &amp;quot;groups&amp;quot; greatly differs in these two programs.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In SketchUp&#039;&#039;&#039; you can group objects which enables you to easily duplicate all objects inside a group and to scale/rotate/translate them all together.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In Mod Tool&#039;&#039;&#039; grouped objects are still loose, and duplicating a group won&#039;t duplicate the objects. To achieve the same effect as in SketchUp, you have to create a hierarchy where any one object is the &amp;quot;parent&amp;quot; and all others the &amp;quot;children&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Google SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a group, select two or more objects, right-click on the selection and choose &amp;quot;make group&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:ModTool_can_import_objs_in_hierarchies.jpg|right|thumb|Mod Tool can import objects in hierarchies to Oni.]]&lt;br /&gt;
&#039;&#039;&#039;Mod Tool&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either use the Explorer (A) or the Schematics (B) to create a hierarchy.&lt;br /&gt;
&lt;br /&gt;
:(A) In the Explorer window, drag and drop one or more objects onto another one.&lt;br /&gt;
&lt;br /&gt;
:(B) Open the constrain tab at the right side. Select parent object, click &amp;quot;Parent&amp;quot;, click the child object(s). Check the result in the Schematics window.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Mod Tool: caution when saving to DAE!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:A normal selection won&#039;t do. You have to select the object tree to successfully save a hierarchy. This is the same way that you do it with Oni characters.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=====Import of smart object groups=====&lt;br /&gt;
Let&#039;s say there are two groups. If an edit is made to one mesh, the clone in the other group is instantly changed the same way.&lt;br /&gt;
&lt;br /&gt;
So that&#039;s a smart group. In SketchUp this is named &amp;quot;component&amp;quot;. In Mod Tool it&#039;s named ???.&lt;br /&gt;
:(Can be imported from SketchUp DAE file but causes a crash when re-saving. I guess a script is needed to do the job.)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Breakable glass with BSL recognition====&lt;br /&gt;
Broken environmental objects can be recognized by the BSL command &#039;&#039;env_broken (ID_1, ID_N)&#039;&#039;. However, this requires additional code to work.&lt;br /&gt;
&lt;br /&gt;
An example is the training level. Let&#039;s determine how we can set up such a thing.&lt;br /&gt;
&lt;br /&gt;
First we need a [[XML:BINA/OBJC/TRGV|trigger volume]] like in level 1.&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;TRGV Id=&amp;quot;11495&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Locked&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-714.6615 -298 -555.2073&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;0 0 0&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;tv75&amp;lt;/Name&amp;gt;&lt;br /&gt;
                &amp;lt;Scripts&amp;gt;&lt;br /&gt;
                    &amp;lt;Entry&amp;gt;&amp;lt;/Entry&amp;gt;&lt;br /&gt;
                    &amp;lt;Inside&amp;gt;targets_gone&amp;lt;/Inside&amp;gt;&lt;br /&gt;
                    &amp;lt;Exit&amp;gt;&amp;lt;/Exit&amp;gt;&lt;br /&gt;
                &amp;lt;/Scripts&amp;gt;&lt;br /&gt;
                &amp;lt;Teams&amp;gt;255&amp;lt;/Teams&amp;gt;&lt;br /&gt;
                &amp;lt;Size&amp;gt;400 31 270&amp;lt;/Size&amp;gt;&lt;br /&gt;
                &amp;lt;TriggerVolumeId&amp;gt;75&amp;lt;/TriggerVolumeId&amp;gt;&lt;br /&gt;
                &amp;lt;ParentId&amp;gt;0&amp;lt;/ParentId&amp;gt;&lt;br /&gt;
                &amp;lt;Notes&amp;gt;&amp;lt;/Notes&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;PlayerOnly&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/TRGV&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need some BSL code.&lt;br /&gt;
&lt;br /&gt;
 var int inside_target_function;&lt;br /&gt;
 &lt;br /&gt;
 func void enter_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint enter_target_function&lt;br /&gt;
    inside_target_function = 1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void exit_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint exit_target_function&lt;br /&gt;
    inside_target_function = 0;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_are_not_gone(void)&lt;br /&gt;
 {&lt;br /&gt;
 	# CB: turn off the trigger volume and sleep for a second&lt;br /&gt;
 	# so as not to cause hideous performance loss&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	sleep 60&lt;br /&gt;
 	trigvolume_enable tv75 1&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_gone(string ai_name)&lt;br /&gt;
 {&lt;br /&gt;
 	if (inside_target_function eq 0)&lt;br /&gt;
 	{	&lt;br /&gt;
 		enter_target_function() # catch other &amp;quot;targets_gone&amp;quot; functions to let them do nothing&lt;br /&gt;
 &lt;br /&gt;
 		var int num_broken = env_broken(3001, 3018);&lt;br /&gt;
 		# if you only one target use scheme: env_broke(3001, 3001)&lt;br /&gt;
 &lt;br /&gt;
 		if (num_broken eq 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_gone();&lt;br /&gt;
 		}&lt;br /&gt;
 	&lt;br /&gt;
 		if (num_broken &amp;lt; 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_not_gone(); # to set check interval to one second&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		exit_target_function&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func targets_are_gone&lt;br /&gt;
 {&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	# [...]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
;Explanation:&lt;br /&gt;
&lt;br /&gt;
Player enters the TV, targets_gone() gets triggered. The variable &amp;quot;inside_target_function&amp;quot; should be 0 by default, so we will enter the &amp;quot;if&amp;quot; block. Next, we can assume that the player didn&#039;t destroy all glass objects, so &amp;quot;num_broken&amp;quot; will be less than 18; thus, targets_are_not_gone() gets called.&lt;br /&gt;
&lt;br /&gt;
The TV function targets_gone() &#039;&#039;would&#039;&#039; be triggered every frame, but targets_are_not_gone() creates a delay between checks: the TV gets deactivated for 60 frames. Then the TV becomes enabled again and will start anew until all glass objects got destroyed or player left the TV.&lt;br /&gt;
&lt;br /&gt;
In this case the targets_gone() function will do nothing because &amp;quot;inside_target_function&amp;quot; was set to 1 by the first call.&lt;br /&gt;
&lt;br /&gt;
targets_are_gone() eventually disables the TV to prevent memory overflow; this function also contains all the things (&amp;quot;[...]&amp;quot;) that you want to happen after the glass target is broken.&lt;br /&gt;
&lt;br /&gt;
====Texture exchange====&lt;br /&gt;
BSL command supported on Windows and Mac:&lt;br /&gt;
: env_texswap ID texture&lt;br /&gt;
&lt;br /&gt;
Might be useful to switch on/off static and animated textures. (News broadcast screen: running or off or smashed. Lava stream: flowing or stagnating or cooled down. Etc.)&lt;br /&gt;
&lt;br /&gt;
A similar effect can be achieved by showing/hiding geometries with different textures as EdT has demonstrated in a private test. That way it should also be possible to have different vertex coloring for an area.&lt;br /&gt;
&lt;br /&gt;
====Vertex coloring====&lt;br /&gt;
Vertex colors can be edited manually in Blender by setting up following 3 things:&lt;br /&gt;
* Properties Panel &amp;gt; Data &amp;gt; Color Attributes&amp;lt;!--only tested with Face Corner, Byte Color--&amp;gt;&lt;br /&gt;
* 3D viewport (left top) &amp;gt; change work mode to Vertex Paint&lt;br /&gt;
* 3D viewport (right top) &amp;gt; change to Viewport Shading to Solid mode (under the dropdown menu you can choose &amp;quot;flat&amp;quot; to have full saturation)&lt;br /&gt;
&lt;br /&gt;
{{divhide|Mod Tool}}&lt;br /&gt;
&lt;br /&gt;
[http://web.archive.org/web/20170529111607/http://softimage.wiki.softimage.com/xsidocs/tex_vcolor_CreatingColoratVerticesCAVMaps.htm SoftImage documentation.] Observation: The sniper tower from level 19 Syndicate Mountain Compound can be isolated and re-imported as it is. It will appear quite dark.&lt;br /&gt;
&lt;br /&gt;
If we remove &amp;quot;_color&amp;quot; from the object, the shadows will be gone next time we import the tower.&lt;br /&gt;
&lt;br /&gt;
Mod Tool: Explorer [8]&lt;br /&gt;
&lt;br /&gt;
 Object&lt;br /&gt;
  |&lt;br /&gt;
  +-- Polygon Mesh&lt;br /&gt;
        |&lt;br /&gt;
        +-- Cluster&lt;br /&gt;
              |&lt;br /&gt;
              +-- Polygon&lt;br /&gt;
              |     |&lt;br /&gt;
              |     +-- [...]&lt;br /&gt;
              |&lt;br /&gt;
              +-- NodeProperties&lt;br /&gt;
                    |&lt;br /&gt;
                    +-- &#039;&#039;&#039;_color&#039;&#039;&#039;&lt;br /&gt;
                    +-- texcoord (Explicit UVWs)&lt;br /&gt;
                          |&lt;br /&gt;
                          +-- Vertex_Color_Def&lt;br /&gt;
&lt;br /&gt;
So, how do we modify that data?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Single object shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If there&#039;s already a vertex color property, you can use Shift + W to activate the Paint Vertex Color Tool. With Control + W you can change the brush color. R + Hold Click + Move Mouse let you change the brush size. The more vertices (points) you have, the more detailed you can make the shadows/colors. But keep in mind that too many polygons can destroy collision, making characters fall through the ground.&lt;br /&gt;
&lt;br /&gt;
If there&#039;s no vertex color property, the first usage of Shift + W will create that property. But you can also manually create it via Property &amp;gt; Color under Vertices Map.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Level-wide shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:light_test_modtool.png|right|thumb]]&lt;br /&gt;
[[Image:light_test_ingame.png|right|thumb]]&lt;br /&gt;
&lt;br /&gt;
To get general shading/lighting you can set up light sources. &amp;quot;Infinite&amp;quot; lights are useful for global lighting, while &amp;quot;Light Box&amp;quot;, &amp;quot;Point&amp;quot;, &amp;quot;Neon&amp;quot; and &amp;quot;Spot&amp;quot; are more suitable as local light sources. They can be accessed via Primitives &amp;gt; Light.&lt;br /&gt;
&lt;br /&gt;
By default, a Mod Tool scene has one Infinite light, but it doesn&#039;t shine in every direction so you might want to add more Infinite lights. Let&#039;s say one Infinite light for each direction (+X, -X, +Y, -Y, +Z, -Z) with an intensity of circa 0.25 (night) or 0.75 (day).&lt;br /&gt;
&lt;br /&gt;
The illumination of those lights can be integrated into the vertex color property. There&#039;s some information [https://web.archive.org/web/20201029114108/http://oni.bungie.org/forum/viewtopic.php?pid=29089#p29089 on OCF here]; the quoted information is in triplicate, so don&#039;t get confused by that: at first it&#039;s detailed, then summarized, then as a checklist.&lt;br /&gt;
&lt;br /&gt;
Basically, you can go with the checklist:&lt;br /&gt;
&lt;br /&gt;
* Property &amp;gt; Color At Vertices Map&lt;br /&gt;
* Property &amp;gt; Render Map&lt;br /&gt;
* In render map property page, under Sampling select Vertices Only&lt;br /&gt;
* Under Surface Color, choose Enable, then in the box below select Vertex _Color; if that option does not appear, click on the New button next to it&lt;br /&gt;
* Under Map, select Illumination only&lt;br /&gt;
* Finally, click on the button Regenerate Maps...&lt;br /&gt;
&lt;br /&gt;
This must be done for all objects separately.&lt;br /&gt;
&lt;br /&gt;
: [http://mods.oni2.net/system/files/vertex_color_script.txt There&#039;s a script here]&amp;lt;!--http://mods.oni2.net/node/352--&amp;gt; which can apply vertex color and render maps to all &#039;&#039;&#039;selected&#039;&#039;&#039; objects. Load it into the script editor with Alt + 4 and hit F5 to run it. (Be sure the script&#039;s language was set to VBScript.)&lt;br /&gt;
: The variable &amp;quot;overwrite_VC&amp;quot; can be changed.&lt;br /&gt;
:: With &amp;quot;1&amp;quot; all existing CAV maps of selected objects will be overwritten. This can take some time.&lt;br /&gt;
:: With &amp;quot;0&amp;quot; only selected objects without CAV maps will be the script&#039;s target.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes on ModTool view modes&#039;&#039;&#039;&lt;br /&gt;
* &amp;quot;Constant&amp;quot; let you see the colors of the vertex coloring only.&lt;br /&gt;
* &amp;quot;Textured Decal&amp;quot; let you see object textures only.&lt;br /&gt;
* &amp;quot;Shaded&amp;quot; let you see the illumination only.&lt;br /&gt;
* &amp;quot;Textured&amp;quot; let you see the textured object with illumination and vertex coloring.&lt;br /&gt;
{{divhide|end}}&lt;br /&gt;
&lt;br /&gt;
=====env_shade=====&lt;br /&gt;
If you use &#039;&#039;&#039;env_shade&#039;&#039;&#039;, use it with caution. It completely overwrites the vertex coloring.&lt;br /&gt;
&lt;br /&gt;
 # BSL command&lt;br /&gt;
 # env_shade obj_id obj_id R G B&lt;br /&gt;
 &lt;br /&gt;
 # examples&lt;br /&gt;
 env_shade 7 7			# object 7 will be black&lt;br /&gt;
 env_shade 7 7 0 0 0		# object 7 will be black&lt;br /&gt;
 env_shade 7 7 .31 .999 .5	# object 7 will be quite green&lt;br /&gt;
 env_shade 7 10 1 1 1		# object 7, 8, 9, 10 lose all their shading&lt;br /&gt;
&lt;br /&gt;
====Baked lightmaps====&lt;br /&gt;
A drawback of this method, AKA shadow maps, is the high number of [[XML:BINA/TMBD|TMBD]] changes and new textures for every wall, requiring a lot of memory. How to create shadow maps:&lt;br /&gt;
&lt;br /&gt;
* https://web.archive.org/web/20121105081823/http://www.game-artist.net/forums/support-tech-discussion/5622-burning-shadows-onto-texture-xsi.html&lt;br /&gt;
&amp;lt;!-- http://caffeineabuse.blogspot.de/2008/12/cast-shadow-only-lights-in-xsi.html might be also interesting --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on map options:&lt;br /&gt;
* &amp;quot;Surface color and illumination&amp;quot;: outputs used texture with added shadows&lt;br /&gt;
** Can be used to replace original texture&lt;br /&gt;
* &amp;quot;Illumination only&amp;quot;: output a texture that only contains the shadows&lt;br /&gt;
** Can be used on a new overlying, transparent surface&lt;br /&gt;
&lt;br /&gt;
====Standalone lightmaps====&lt;br /&gt;
With this approach there are two meshes, whereby the shadow effects on one mesh get drawn in front of the regular level texture.&lt;br /&gt;
&lt;br /&gt;
Compared to the &amp;quot;baked lightmaps&amp;quot; method, this needs more polygons of course. And these polygons are transparent, which is a problem with Oni&#039;s limited rendering ability for such textures. However, standalone lightmaps only need a few new textures if used wisely.&lt;br /&gt;
&lt;br /&gt;
Read [[Lightmapping levels]] to learn more.&lt;br /&gt;
&lt;br /&gt;
[[Image:Oni_Lightmaps_double_polygon_method.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Rooms&amp;gt;===&lt;br /&gt;
The Rooms tag is mandatory. It contains an import path to BNV and ghosts (*.dae) which are used to create pathfinding grids. For information on the binary data behind this, see [[OBD:AKVA|HERE]].&lt;br /&gt;
&lt;br /&gt;
Sample code from the master XML file:&lt;br /&gt;
 &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fundamentals&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;BNVs&#039;&#039;&#039; are &#039;&#039;&#039;volumes&#039;&#039;&#039; (sometimes also named &#039;&#039;&#039;rooms&#039;&#039;&#039;) that have a pathfinding grid assigned to them.&lt;br /&gt;
* For practical reasons you only need &#039;&#039;&#039;floors and ramps&#039;&#039;&#039; to build a BNV. (As seen [http://edt.oni2.net/images/Hideout_BNV.jpg HERE.])&lt;br /&gt;
** A BNV polygon can consist of 3 or more points, but it&#039;s recommended to use &#039;&#039;&#039;shapes with 4 points&#039;&#039;&#039; because the other shapes usually waste more grid space. At the moment you can import only &#039;&#039;&#039;[[wikt:convex|convex]]&#039;&#039;&#039; shapes.&lt;br /&gt;
* Secondly, there are so called &#039;&#039;&#039;ghosts&#039;&#039;&#039; (vertical quads) that connect &#039;&#039;&#039;neighboring BNVs&#039;&#039;&#039;. AI can only transit from BNV to another through ghosts.&lt;br /&gt;
: OniSplit gives error messages for ghosts that don&#039;t have 2 neighboring BNVs, for example:&lt;br /&gt;
 BNV Builder: Ghost &#039;grid2&#039; has no adjacencies at &amp;lt;-72,41 1,999 -166,6&amp;gt; and &amp;lt;-71 1,999 -168,21&amp;gt;, ignoring&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tolerance values&#039;&#039;&#039;&lt;br /&gt;
* Horizontal distance from room to ghost: 1&lt;br /&gt;
* Vertical distance from room to ghost: 18&lt;br /&gt;
* Ghost&#039;s horizontal dimension must be greater than 0&lt;br /&gt;
* Under optimal circumstances, pathfinding works on a plane that is +4 world units above or -0.5 below the pathfinding grid&lt;br /&gt;
* Normally characters can&#039;t pass over low vertical walls such as stairs/curbs if those don&#039;t have a ramp under them; near ground level (Y=0) is an exception where characters are allowed to step on a plane that is 4 world units above pathfinding grid; higher planes need a ramp&lt;br /&gt;
* Maximum angle of ramp you can go on is 70°; higher angles will make characters fall through to their death (in those cases you might want to add invisible walls/boxes to prevent them from touching the ramp)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;More notes on PF processing&#039;&#039;&#039;&lt;br /&gt;
* Actually, BNV and ghosts can have any name and don&#039;t need any texture.&lt;br /&gt;
* During pathfinding calculation, OniSplit creates a new folder called &amp;quot;temp&amp;quot; and a subfolder &amp;quot;grids&amp;quot;. There is a file named &amp;quot;&#039;&#039;levelname&#039;&#039;_grids.dae&amp;quot;. That file contains rooms with textures called &amp;quot;bnv_grid_&#039;&#039;N&#039;&#039;.tga&amp;quot; which mark obstacles in the pathfinding grid. Ghosts will have a transparent texture &amp;quot;&#039;&#039;&#039;_marker_ghost&#039;&#039;&#039;.tga&amp;quot;. You also get these when you export a level. Transparent ghosts make it easier to see the rest of your level if you have many of those planes.&lt;br /&gt;
* In Mod Tool, ghosts and rooms can be grouped under a null object. Right-click the null object to select all its children, then use &amp;quot;Selection Only [x]&amp;quot; as your saving option. That way all the planes can be quickly saved to a *.dae file.&lt;br /&gt;
* You can influence the pathfinding creation of dangerous zones using danger quads. Read about those [[#Marker textures|HERE]].&lt;br /&gt;
* Another kind of influence is the [[#&amp;lt;Model&amp;gt;|gunk flag]] IgnoreGrid. It can be used to tell OniSplit to ignore the object during pathfinding creation. The grids in that place will be white.&lt;br /&gt;
&lt;br /&gt;
[[Image:Pathfinding_grid.jpg|thumb|200px|right|&#039;&#039;&#039;ai2_showgrids = 1&#039;&#039;&#039; in action]]&lt;br /&gt;
&#039;&#039;&#039;BSL commands&#039;&#039;&#039;&lt;br /&gt;
* chr_show_bnv = 1&lt;br /&gt;
:: shows number of BNVs the player is standing on&lt;br /&gt;
* ai2_showgrids = 1&lt;br /&gt;
:: shows pathfinding grids&lt;br /&gt;
* ai2_chump&lt;br /&gt;
:: spawns a friendly Striker that follows the player if possible, makes also pathfinding grids visible&lt;br /&gt;
* ai2_chump_stop = 1&lt;br /&gt;
:: Striker stops following you&lt;br /&gt;
* ai2_chump_stop = 0&lt;br /&gt;
:: Striker follows you again&lt;br /&gt;
&lt;br /&gt;
====Pathfinding on uneven ground====&lt;br /&gt;
Pathfinding works on slightly uneven ground as long as the polygons are 0.5 world units beneath or 4 world units above the BNV.&lt;br /&gt;
&lt;br /&gt;
For greater surface irregularities, we can use a trick:&lt;br /&gt;
* The problematic polygons must be saved to a DAE file and then referenced in the model section as an individual object.&lt;br /&gt;
* Then the &amp;lt;GunkFlags&amp;gt; tag needs to be &#039;&#039;&#039;&#039;&#039;GridIgnore&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Additionally we create a plane (invisible if necessary) under the object so that Oni doesn&#039;t think there&#039;s a hole.&lt;br /&gt;
* The ghosts must be taller than the highest polygon to be walked on. (This has been tested up to a height of 2,000 world units.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms of too-small ghosts&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A) AI can&#039;t run at all.&lt;br /&gt;
&lt;br /&gt;
B) AI loses PF ability if the tracked enemy performs animations that are outside of the pathfinding volume. Here&#039;s a video (&amp;lt;nowiki&amp;gt;https://youtu.be/vfKPzP5hiCo&amp;lt;/nowiki&amp;gt;, dead link) showing these symptoms.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Missing boundaries&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say you have a BNV, tall ghosts, and a GridIgnore-flagged hill with trees and bushes and stuff.&lt;br /&gt;
&lt;br /&gt;
Why do AIs run up against the trees?&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; There are no red/orange grids that limit the AI&#039;s movement. Normally, objects will produce red pathfinding squares around them. But objects that are 20 world units above the BNV are ignored just like objects with the IgnoreGrid flag.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Add simple geometries like &#039;&#039;_marker_impassable fences&#039;&#039; or danger quads near the BNV.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Disappearing AIs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The ground is sometimes not solid, and the player and AIs are falling through it.&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; On GridIgnore-flagged uneven ground, AIs can fall through it when they are out of the player&#039;s view.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Use either &#039;&#039;&#039;chr_lock_active &#039;&#039;AI_name&#039;&#039;&#039;&#039;&#039; or &#039;&#039;&#039;chr_all_active = 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Debugging====&lt;br /&gt;
&#039;&#039;&#039;(OniSplit v0.9.93.0+)&#039;&#039;&#039;&lt;br /&gt;
[[Image:OniBrowser.jpg|thumb|200px|right|OniBrowser displaying level geometry plus PF and ghosts.]]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;env_show_ghostgqs = 1&#039;&#039;&#039; makes the ghost quads visible&lt;br /&gt;
** The original ghost quads can&#039;t be seen; per Neo, &amp;quot;they are not included in the octtree and bsp tree&amp;quot;&lt;br /&gt;
** To see them you must use the -debug option in the level creation command (available with OniSplit &#039;&#039;&#039;v0.9.93.0+&#039;&#039;&#039;)&lt;br /&gt;
 OniSplit.exe -create:level &#039;&#039;output_folder&#039;&#039; &#039;&#039;&#039;-debug&#039;&#039;&#039; &#039;&#039;input_folder&#039;&#039;/&#039;&#039;master_xml_file&#039;&#039;.xml&lt;br /&gt;
&lt;br /&gt;
Not all debugging/testing needs to be done in Oni. There is also a [http://mods.oni2.net/node/256 program] (Windows only) which can display the whole level.&lt;br /&gt;
&lt;br /&gt;
For example you can load an AKEV*.oni, select the level name, and use the hotkeys [B] and [P] to display BNVs and ghosts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bug prevention:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
After all testing is done, you should compile the level a last time without the -debug option.&lt;br /&gt;
&lt;br /&gt;
AIs appear to have trouble shooting through ghost quads that got registered in the octtree/BSP tree as seen here (&amp;lt;nowiki&amp;gt;https://www.youtube.com/watch?v=-ZugVBgBVKc&amp;lt;/nowiki&amp;gt;, dead link).&lt;br /&gt;
&lt;br /&gt;
====When OniSplit fails to connect PF quads====&lt;br /&gt;
[[Image:Pathfinding_creation__merge_polygons_to_fix_connections.jpg|thumb|200px|right|Fixed PF in compound level after underground construction...]]&lt;br /&gt;
It can help to merge polygons to one object and merge their edges. These become white. (Outer edges are blue.)&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Textures&amp;gt;===&lt;br /&gt;
====...used for exceptions====&lt;br /&gt;
The [[#textures_tag|textures tag]] is mandatory.&lt;br /&gt;
&lt;br /&gt;
AKEV textures will be imported by the master XML file automatically; you don&#039;t need to add them to that file.&lt;br /&gt;
&lt;br /&gt;
: With OniSplit v0.9.82-93.0, the textures&#039; formats will be DXT1 and (for transparent ones) BGRA4444.&lt;br /&gt;
: With OniSplit v0.9.94.0+ the textures&#039; formats will be BGR and (for transparent ones) RGBA.&lt;br /&gt;
&lt;br /&gt;
To change the default texture import format, use the Texture&#039;&#039;&#039;s&#039;&#039;&#039; tag. (Possible with OniSplit v0.9.94.0+.)&lt;br /&gt;
&lt;br /&gt;
To change the format/flag/gunk flag of a specific texture, use the Texture tag.&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&lt;br /&gt;
          &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;TwoSided&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;BGRA4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
          &amp;lt;/Textures&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use the gunk flag &amp;quot;TwoSided&amp;quot; to make surfaces visible from both sides.&lt;br /&gt;
* If the texture comes with the gunk flag &amp;quot;NoCollision&amp;quot; then all objects with that texture will have no collision. Characters would fall through it.&lt;br /&gt;
&lt;br /&gt;
Transparency and no collision together would make sense for a water-like substance. The Vago Biotech level uses this approach for the area with green toxic waste.&lt;br /&gt;
&lt;br /&gt;
[[Image:making_a_surface_transparent_and_twosided.png|thumb|200px|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures.png|thumb|200px|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;&amp;lt;br&amp;gt;one object with multiple textures, one per polygon cluster]]&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures_ingame.png|thumb|200px|right|&#039;&#039;&#039;Figure 3&#039;&#039;&#039;&amp;lt;br&amp;gt;blue: two-sided&amp;lt;br&amp;gt;glass: two-sided and transparent&amp;lt;br&amp;gt;random metal: no flag (one-sided)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TwoSided and transparent objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s also possible to set this in Mod Tool. For TwoSided-ness, use one image source for diffuse and transparency. (It won&#039;t work with two image sources even if both sources use the same image.)&lt;br /&gt;
&lt;br /&gt;
For transparency you must additionally use the three checkboxes:&lt;br /&gt;
* Transparency: Enable&lt;br /&gt;
* Transparency: Use Alpha&lt;br /&gt;
* Transparency: Invert&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;Figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Regular textures====&lt;br /&gt;
OniSplit automatically imports textures of objects in the [[#&amp;lt;Model&amp;gt;|&amp;lt;Model&amp;gt; section]]. Those objects could be considered as AKEV core geometry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;One texture per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Furniture and Physics objects are allowed to have only one texture per object. AKEV core geometry can have one texture or multiple textures – that&#039;s up to you to decide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multiple textures per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question:&#039;&#039;&#039; How do we apply multiple textures to an AKEV core object?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Answer:&#039;&#039;&#039; Assuming you are using Mod Tool the procedure will be as follows. Repeat this for each cluster you create (except for projection). See also &#039;&#039;&#039;Figure 2 and 3&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Select some polygons&lt;br /&gt;
* Go to Material &amp;gt; Phong&lt;br /&gt;
* Hit [7] to open Render Tree&lt;br /&gt;
* Add a texture and connect &amp;quot;Image&amp;quot; with &amp;quot;Phong&amp;quot;, choose &amp;quot;diffuse&amp;quot; as illumination mode&lt;br /&gt;
* Double-click &amp;quot;Image&amp;quot; to open Material page&lt;br /&gt;
* In the Texture Projection section, click on &amp;quot;New&amp;quot; and choose a suitable projection&lt;br /&gt;
** Do this only if there isn&#039;t a projection in the &amp;quot;Texture_Coordinates_AUTO&amp;quot; cluster yet&lt;br /&gt;
** OniSplit processes only one texture projection, see &#039;&#039;&#039;Figure 4&#039;&#039;&#039;&lt;br /&gt;
* Choose the texture and UV, then fine-tune the UV via Alt + 7&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_multiple_textures_one_projection.png|thumb|200px|right|&#039;&#039;&#039;Figure 4&#039;&#039;&#039;&amp;lt;br&amp;gt;use only one texture projection per object]]&lt;br /&gt;
&lt;br /&gt;
Caution: textures will be fixed to one set of flags. You can&#039;t use the same texture A for a one-sided cluster/object B and a two-sided cluster/object C. You would need to create a differently-named clone of that texture and apply that to cluster/object C.&lt;br /&gt;
&lt;br /&gt;
====Marker textures====&lt;br /&gt;
Marker textures are used to import certain objects with special flags. Import those objects alongside [[#&amp;lt;Model&amp;gt;|AKEV core]] geometry.&lt;br /&gt;
&lt;br /&gt;
Marker textures aren&#039;t imported automatically. Add those textures to the final package or plugin yourself, e.g. with some sort of script.&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
The flags Transparent, TwoSided and NoOcclusion are only set if the same texture source is used for diffuse and transparency and if transparency setting are enabled. See the subsection under &amp;quot;[[#...used for exceptions|...used for exceptions]]&amp;quot; called &amp;quot;TwoSided and transparent objects&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Danger quads&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pathfinding grids have different colored squares with different meanings.&lt;br /&gt;
* white/gray - clear space&lt;br /&gt;
* green light - near wall&lt;br /&gt;
* green - semi-passable&lt;br /&gt;
* green dark - stairs&lt;br /&gt;
* blue very light - border 1&lt;br /&gt;
* blue light - border 2&lt;br /&gt;
* blue - border 3&lt;br /&gt;
* blue dark - border 4&lt;br /&gt;
* &#039;&#039;&#039;orange - danger&#039;&#039;&#039;&lt;br /&gt;
* red - impassable&lt;br /&gt;
&lt;br /&gt;
For detailed information on colors, see [[OBD_talk:AKVA/0x24#EFFECTS_of_various_pathfinding_grid_tile_types|HERE]].&lt;br /&gt;
&lt;br /&gt;
Normally, OniSplit decide how to color the grids. But it&#039;s possible to add your own danger quads to fine-tune zones of higher danger. Those orange areas will be generated with the 4 different blue borders around it.&lt;br /&gt;
&lt;br /&gt;
Danger quads must have &amp;quot;&#039;&#039;&#039;_marker_danger&#039;&#039;&#039;&amp;quot; as texture name.&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided NoCollision Invisible NoOcclusion Danger&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;_marker_barrier&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!-- Originally this is only used for level-bounding invisible walls? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided(double-check) Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLLISION (boxes)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
AIs can get stuck in detailed geometry. This can be prevented with collision boxes. In-game the box will be invisible, but has collision so characters can&#039;t get through. The pathfinding grid will be red where it comes in contact with the box; the red is followed by a light green and then regular green.&lt;br /&gt;
&lt;br /&gt;
[[XML:OFGA|OFGAs]] use the COLLISION texture. Onisplit doesn&#039;t automatically apply gunk flags to it. You need to use XML tags for that. Typically it would be &amp;lt;GunkFlags&amp;gt;Invisible NoObjectCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Normally, characters can&#039;t move on stairs because they contain vertical rises. In this case you can use a sloping quad that is above or inside the staircases. It&#039;s possible to set the desired flags in the &amp;lt;Model&amp;gt; section, but doing so and exporting these self-made stair ramps is wasted time. Simply apply _marker_stairs to that quad and characters will be able to move on that surface.&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Stairs Transparent TwoSided Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
This has no effect on pathfinding creation. Regularly-textured stair geometry (which intersects the marker quad) will be flagged as NoCharacterCollision.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
texture: &#039;&#039;&#039;_marker_impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Transparent TwoSided (&amp;lt;-double-check this) Invisible NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Impassable walls are very similar to collision boxes except that particles can also collide with them. The pathfinding grids will be also red, light green, and green.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Blackness a.k.a. jello fix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_blackness&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: TwoSided NoCollision&lt;br /&gt;
&lt;br /&gt;
Simply black walls. No effect on pathfinding creation. The purpose of these walls in Oni is to block out areas outside of a level&#039;s outermost wall so that the Jello-cam cannot show the player other parts of the level when it escapes a wall. See [[Jello-cam]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Doors&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_door&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: DoorFrame Transparent TwoSided NoCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Don&#039;t use this.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Objects&amp;gt;===&lt;br /&gt;
Information on regular object lists can be looked up here:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
====Furniture.xml====&lt;br /&gt;
The AKEV core geometry is more or less the overall structure of the level while this furniture file adds standard objects (e.g. crates and desks) to it.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| - &lt;br /&gt;
| This tag marks the file as BINACJBO.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Furniture&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| This tag marks the file as FURN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Header&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag. Ignore it. Those flags were used in the past.&lt;br /&gt;
:None&lt;br /&gt;
:Locked&lt;br /&gt;
:PlacedInGame&lt;br /&gt;
:Temporary&lt;br /&gt;
:Gunk&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;OSD&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Class&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to a &#039;&#039;&#039;pre-compiled [[XML:OFGA|OFGA]] (*.oni) file&#039;&#039;&#039;. Use it as part of a relative path. Make sure that the OFGA comes with the files it needs: M3GM and TXMP.&lt;br /&gt;
&lt;br /&gt;
An OFGA can hold multiple M3GMs. That 3D content will then be integrated into the AKEV.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Particle&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| This name gets written into &amp;lt;Tag&amp;gt; inside ONLV (ENVP section) and can be used with BSL commands, e.g. you can take control over a particle via &#039;&#039;&#039;particle BSL_name start&#039;&#039;&#039;. For more commands, see [[XML:BINA/OBJC/PART#BSL_support|HERE]].&lt;br /&gt;
&lt;br /&gt;
Take care with the naming of new OFGA files. The particle name will be composed of 2 parts separated by an &amp;quot;_&amp;quot; underscore. When one tag is empty, the final name will contain an underscore nonetheless. &#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Example&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Objects&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Furniture&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Gunk&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-62.692 -29 108.35&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;181.522 356.021 178.114&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Class&amp;gt;furniture/V_tctf_bigvan.oni&amp;lt;/Class&amp;gt;&lt;br /&gt;
                &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/Furniture&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Objects&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Physics.xml====&lt;br /&gt;
This file is for objects with &amp;quot;physics&amp;quot;. Unlike AKEV core geometry or furniture, these objects can be animated.&lt;br /&gt;
&lt;br /&gt;
: A small video tutorial on [https://www.youtube.com/watch?v=CFNseg_2UxA how to create a simple animated object]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Physics&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Object Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Use a unique name for each object.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Tested with BSL command...&lt;br /&gt;
:obj_create ID [ID]&lt;br /&gt;
:obj_kill ID [ID]&lt;br /&gt;
:env_anim ID [ID]&lt;br /&gt;
:env_setanim ID [ID]&lt;br /&gt;
The scripting ID will be stored in the ONLV&#039;s OBOA instance.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;Object setup flags&lt;br /&gt;
:None&lt;br /&gt;
:InUse&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoGravity&lt;br /&gt;
:FaceCollision&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Physics&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag for an Object.&lt;br /&gt;
:None&lt;br /&gt;
:Static&lt;br /&gt;
:Linear&lt;br /&gt;
:Animated&lt;br /&gt;
:Newton (used with &amp;lt;Flags&amp;gt; FaceCollision to [https://www.youtube.com/watch?v=YICB7qugrtc make an object pushable])&lt;br /&gt;
:: For a pushable object don&#039;t use import sub-tags such as animation name, flags, etc. Just use &amp;lt;Import Path=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt; or &amp;lt;Import Url=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Scale&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects.&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;Import Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Import Url=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| This tag comes in two variants. It doesn&#039;t matter what variant you use.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag of Animation. For more information on those flags look [[XML:OBAN|OBAN]] page.&lt;br /&gt;
&lt;br /&gt;
;Object animation flags&lt;br /&gt;
:None&lt;br /&gt;
:Loop&lt;br /&gt;
:PingPong&lt;br /&gt;
:RandomStart&lt;br /&gt;
:AutoStart&lt;br /&gt;
:Local&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the end of an OBAN from a *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the start of an OBAN from a *.dae file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The XML code for physics can be written in two styles.&lt;br /&gt;
*The &#039;&#039;&#039;first style&#039;&#039;&#039; mimics the original structure found in extracted ONLV instances. This makes it &#039;&#039;&#039;easier to edit old levels and reimport them&#039;&#039;&#039; into the game.&lt;br /&gt;
*The &#039;&#039;&#039;second style&#039;&#039;&#039; was created with structured data (nested objects) in mind and is &#039;&#039;&#039;suited for totally new levels&#039;&#039;&#039; where animated objects must be created in a 3D editor at first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        &amp;lt;Object&amp;gt;&lt;br /&gt;
            &amp;lt;Geometry&amp;gt;M3GMDishBase.oni&amp;lt;/Geometry&amp;gt;&lt;br /&gt;
            &amp;lt;Animation&amp;gt;OBANDishBase.oni&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;Physics&amp;gt;Animated&amp;lt;/Physics&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;201&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Position&amp;gt;-197.729141 128.46283 -2501.46387&amp;lt;/Position&amp;gt;&lt;br /&gt;
            &amp;lt;Rotation&amp;gt;0.7071067 -1.545431E-08 1.545431E-08 0.7071068&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;Scale&amp;gt;2.109375&amp;lt;/Scale&amp;gt;&lt;br /&gt;
            &amp;lt;Name&amp;gt;object_DishBase&amp;lt;/Name&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 2&#039;&#039;&#039;&lt;br /&gt;
:For documentation purposes, the file here has been trimmed down.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Object Name=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;8&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Flags&amp;gt;FaceCollision&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;Import Url=&amp;quot;motorcycle/export.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;AutoStart&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;End&amp;gt;880&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02_stop&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Start&amp;gt;881&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, OniSplit takes the file &amp;quot;export.dae&amp;quot;, looks at the parts it contains, and creates geometry files from it.&lt;br /&gt;
* M3GMhubs_rear.oni&lt;br /&gt;
* M3GMhubs.oni&lt;br /&gt;
* M3GMmotorcycle.oni&lt;br /&gt;
It&#039;s convenient that hierarchies are supported here.&lt;br /&gt;
&lt;br /&gt;
The motorcycle is made of 3 parts so 3 object animations ([[XML:OBAN|OBAN]]) will be created up to frame 880. Then OniSplit creates 3 more OBANs starting from frame 881.&lt;br /&gt;
&lt;br /&gt;
The reason for the interruption at frame 880 is probably to give Barabas a little more camera time in the cutscene.&lt;br /&gt;
&lt;br /&gt;
;Notes about BSL usage:&lt;br /&gt;
&lt;br /&gt;
The Vago Lab cutscene script uses the motorcycle objects and animations like this:&lt;br /&gt;
 	env_show 8 0		# hide static motorcycle parts or else they would be visible&lt;br /&gt;
 	env_show 9 0		# while Konoko is still riding her animated motorcycle&lt;br /&gt;
 	env_show 10 0		# the static motorcycle is separated into objects 8, 9 and 10&lt;br /&gt;
 &lt;br /&gt;
 	# Static and animated objects are totally independent from each other.&lt;br /&gt;
 	# They are stored in different arrays so their script IDs can use the same numbers.&lt;br /&gt;
 &lt;br /&gt;
 	obj_create 8 10		# create all animation-ready motorcycle parts&lt;br /&gt;
 	env_anim 8 10		# animate those parts (not necessary if OBAN flag is &amp;quot;AutoStart&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 	# The first animations would loop because of &amp;quot;AutoStart&amp;quot;, so get the&lt;br /&gt;
 	# right timing to apply the other animations. &amp;quot;motorcycle02_stop&amp;quot;&lt;br /&gt;
 	# and the others will not loop because they don&#039;t have &amp;quot;AutoStart&amp;quot;.&lt;br /&gt;
 	env_setanim 8 hubs_stop&lt;br /&gt;
 	env_setanim 9 hubs_rear_stop&lt;br /&gt;
 	env_setanim 10 motorcycle02_stop&lt;br /&gt;
 &lt;br /&gt;
 	obj_kill 8 10		# delete all animated parts&lt;br /&gt;
 	env_show 9 1		# show static motorcycle model where Konoko parks her bike&lt;br /&gt;
&lt;br /&gt;
====Corpses.xml====&lt;br /&gt;
An empty Corpse element (&amp;lt;Corpse /&amp;gt;) is treated as unused and placed at the end of the array. If no such empty elements are provided, OniSplit automatically adds 5. OniSplit also ensures that there are at least 20 corpses in the array.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Corpses&amp;gt;&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Corpse&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Class&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| [[XML:ONCC|ONCC]]&#039;&#039;name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Transforms&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| There are 19 &amp;lt;Matrix&amp;gt; for each &amp;lt;Transforms&amp;gt; (which represents a body part).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Matrix&amp;gt;&lt;br /&gt;
| matrix&lt;br /&gt;
| Float 3x3 + float x3 for the last 3 values (X Y Z position). For more information about the matrix, see [[OBD:CRSA]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Bounding box of the whole corpse. Optional; if not provided, OniSplit will generate an approximate one. Currently it doesn&#039;t try to locate the ONCC to compute an exact bounding box.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Min&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Max&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Trimmed example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Corpses&amp;gt;&lt;br /&gt;
        &amp;lt;Corpse&amp;gt;&lt;br /&gt;
            &amp;lt;Class&amp;gt;generic_male_1&amp;lt;/Class&amp;gt;&lt;br /&gt;
            &amp;lt;Transforms&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.36488995 0.04620622 -0.9299034 -0.05580434 -0.9980576 -0.02769538 -0.9293768 0.04178688 0.366759717 -215.667755 1.603917 92.85312&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.2961557 -0.185628444 0.936928 -0.368288517 -0.9272724 -0.06730227 0.8812806 -0.32512787 -0.342981815 -216.51889 1.64218426 93.189&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.407847315 0.156575248 0.8995248 -0.238757968 -0.9326179 0.2705892 0.8812805 -0.3251278 -0.342982143 -215.239883 0.8405094 97.23532&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.439697325 0.467113584 0.767118752 0.0248355754 -0.8601105 0.5095029 0.8978026 -0.204975232 -0.389789373 -213.6234 1.46109009 100.80056&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.717241049 -0.179043233 0.673430443 0.4761817 -0.579636 -0.6612664 0.5087397 0.794962764 -0.3304816 -214.81662 1.56564879 92.5172348&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.3398023 0.1672905 0.925498843 0.7910236 -0.5831365 -0.185023025 0.5087395 0.7949628 -0.330481827 -211.71907 0.792413354 95.42558&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.1283634 0.227430075 0.965297 0.804142356 -0.59352535 0.032904774 0.5804117 0.7720126 -0.259073079 -210.372269 1.45546341 99.0937653&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.285799921 0.06851995 -0.955836535 -0.240357026 -0.970681965 0.00228381017 -0.927656651 0.230394751 0.2938901 -216.284851 1.5839076 91.29168&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.312039882 0.04875436 -0.948817253 -0.176752359 -0.9842264 0.00755515043 -0.9334825 0.1700632 0.31573534 -216.689789 1.68287766 89.9359055&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.356412441 -0.5390179 -0.763170958 0.0404523835 -0.82494843 0.5637587 -0.933452547 0.170058519 0.315826446 -217.422012 1.7979821 87.70907&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.101782769 -0.247171819 -0.9636112 0.5426916 -0.8256094 0.154451028 -0.8337422 -0.507223248 0.2181709 -217.747284 1.30605173 87.0125656&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.8154478 -0.150626346 0.558888733 -0.1200991 0.9885643 0.09119747 -0.566234052 0.00724477554 -0.8242127 -217.7402 2.065678 88.15346&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.4593738 -0.326781839 0.825947642 0.8874048 -0.1284554 0.442732215 -0.0385793857 0.9363295 0.348996729 -219.093979 1.81561315 89.08131&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9545983 -0.13777709 0.26412034 0.295387268 -0.322961926 0.899134 -0.0385792255 0.9363296 0.348996431 -220.3681 0.9092429 91.37218&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9715769 -0.0362956524 0.233924776 0.0276728421 -0.9988148 -0.0400396362 0.2351007 -0.0324283168 0.9714299 -222.775482 0.56178683 92.03825&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.979860842 -0.192433611 0.0533096045 0.193336874 0.9810555 -0.0122905634 -0.0499345176 0.0223497637 0.9985025 -216.8387 1.90143847 87.84845&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.863898 -0.399280578 0.3070101 0.171117 -0.340619326 -0.9244986 0.4737078 0.851207137 -0.225936681 -215.211975 1.58196676 87.93695&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.4673251 -0.0255063027 0.883717656 0.746463835 -0.524209559 -0.4098731 0.4737075 0.851207256 -0.225936785 -212.815842 0.47451216 88.78848&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.216871262 -0.007893051 0.976168454 0.3751846 0.9238389 -0.0758833 -0.9012231 0.3827002 0.203315422 -211.637314 0.410188764 91.0171051&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
            &amp;lt;/Transforms&amp;gt;&lt;br /&gt;
            &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
                &amp;lt;Min&amp;gt;-219.731216 -2.258905 84.47974&amp;lt;/Min&amp;gt;&lt;br /&gt;
                &amp;lt;Max&amp;gt;-207.518463 4.49535131 104.023239&amp;lt;/Max&amp;gt;&lt;br /&gt;
            &amp;lt;/BoundingBox&amp;gt;&lt;br /&gt;
        &amp;lt;/Corpse&amp;gt;&lt;br /&gt;
    &amp;lt;/Corpses&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[[Image:ONLV_CRSA_XSI_aided_import.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
:Some related information can be found at [[Authoring custom camera animations]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
For indirect import, see [http://oni.bungie.org/forum/viewtopic.php?id=2657 HERE] (OniTools v7.1.5+) on how to get corpse data.&lt;br /&gt;
&lt;br /&gt;
When you process your XML master file, use OniSplit version 0.9.94.0+. Older OniSplit versions like 0.9.86.0 may generate ONLV files that are not re-packable with newer versions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;(Export)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With Neo&#039;s matrix-to-Euler code, the rotations can be recovered from CRSA. But due to the character&#039;s hierarchy, things get messy again (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/CRSA_to_Mod_Tool_wip.png&amp;lt;/nowiki&amp;gt;, dead link). (WIP code (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/temp/CRSA_to_Mod_Tool.txt&amp;lt;/nowiki&amp;gt;, dead link))&lt;br /&gt;
&lt;br /&gt;
A workaround might be to save characters without animations, destroy their hierarchy, apply the local rotations / global translation and glue everything together again.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43843</id>
		<title>Creating a level</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43843"/>
		<updated>2025-01-22T04:05:10Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Forum tutorials on level creation */Fixed broken forum links to archive.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page covers level creation from scratch. See [[Modifying an existing level]] if you want to change a vanilla level in the game.&lt;br /&gt;
&lt;br /&gt;
==Level releases and resources==&lt;br /&gt;
===Fan-made levels===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable autosort by-column-3&amp;quot;&lt;br /&gt;
!Date&lt;br /&gt;
!Name&lt;br /&gt;
!Level number&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Oni 2 Angel Studios Tour&lt;br /&gt;
|32&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Green Room&lt;br /&gt;
|26&lt;br /&gt;
|-&lt;br /&gt;
|2019/09/16&lt;br /&gt;
|[https://web.archive.org/web/20240527004257/http://oniforum.bungie.org/viewtopic.php?id=2965 Omega Tournament]&lt;br /&gt;
|31&lt;br /&gt;
|-&lt;br /&gt;
|2016/02/13&lt;br /&gt;
|[https://web.archive.org/web/20160224173743/http://oni.bungie.org/forum/viewtopic.php?id=2947 AI Battle]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2014/01/19&lt;br /&gt;
|[https://web.archive.org/web/20211202225410/http://oni.bungie.org/forum/viewtopic.php?id=2698 Wilderness Preserve]&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|2013/09/07&lt;br /&gt;
|[https://web.archive.org/web/20201127180732/http://oni.bungie.org/forum/viewtopic.php?id=2656 Island]&lt;br /&gt;
|29&lt;br /&gt;
|-&lt;br /&gt;
|2013/07/12&lt;br /&gt;
|[https://web.archive.org/web/20201127175459/http://oni.bungie.org/forum/viewtopic.php?id=2640 City]&lt;br /&gt;
|28&lt;br /&gt;
|-&lt;br /&gt;
|2013/06/01&lt;br /&gt;
|[https://web.archive.org/web/20201029102326/http://oni.bungie.org/forum/viewtopic.php?id=2619 Fight Club]&lt;br /&gt;
|25&lt;br /&gt;
|-&lt;br /&gt;
|2012/05/12&lt;br /&gt;
|[https://web.archive.org/web/20220701102842/http://oni.bungie.org/forum/viewtopic.php?id=2357 Old China]&lt;br /&gt;
|24&lt;br /&gt;
|-&lt;br /&gt;
|2012/03/18&lt;br /&gt;
|[https://web.archive.org/web/20211202220454/http://oni.bungie.org/forum/viewtopic.php?id=2302 Boss Battle]&lt;br /&gt;
|23&lt;br /&gt;
|-&lt;br /&gt;
|2012/02/12&lt;br /&gt;
|[https://web.archive.org/web/20201029113554/http://oni.bungie.org/forum/viewtopic.php?id=2271 De Dust Deluxe]&lt;br /&gt;
|22&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/23&lt;br /&gt;
|[https://web.archive.org/web/20201029114415/http://oni.bungie.org/forum/viewtopic.php?id=2242 Parkour Challenge 2]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/16&lt;br /&gt;
|[https://web.archive.org/web/20211205145843/http://oni.bungie.org/forum/viewtopic.php?id=2235 Parkour Challenge]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/25&lt;br /&gt;
|[https://web.archive.org/web/20201029103607/http://oni.bungie.org/forum/viewtopic.php?id=2001 Mini-Partenon]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2011/10/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113340/http://oni.bungie.org/forum/viewtopic.php?id=2024 Muro&#039;s Lair - Preview]&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113724/http://oni.bungie.org/forum/viewtopic.php?id=1957 Hexagon]&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|2011/06/23&lt;br /&gt;
|[https://web.archive.org/web/20201029104928/http://oni.bungie.org/forum/viewtopic.php?id=1938 Junkyard]&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|2011/05/01&lt;br /&gt;
|[http://mods.oni2.net/node/178 Arena of Hurt (OZG)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/08&lt;br /&gt;
|[https://web.archive.org/web/20210117150652/http://oni.bungie.org/forum/viewtopic.php?id=1736 Arena of Hurt (OTA)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/06&lt;br /&gt;
|[https://web.archive.org/web/20201029105217/http://oni.bungie.org/forum/viewtopic.php?pid=50565#p50565 Martian Colony] AKA &amp;quot;Silly World&amp;quot;&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2010/02/15&lt;br /&gt;
|[https://web.archive.org/web/20201029113916/http://oni.bungie.org/forum/viewtopic.php?id=1506 Maze]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2008/09/16&lt;br /&gt;
|[http://mods.oni2.net/node/4 Arena of Pain]&lt;br /&gt;
|30&lt;br /&gt;
|-&lt;br /&gt;
|2024/05/20&lt;br /&gt;
|[https://gamebanana.com/mods/514707 Kitsune: Chapter 1]&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Forum tutorials on level creation===&lt;br /&gt;
* &#039;&#039;&#039;[https://web.archive.org/web/20201029114347/http://oni.bungie.org/forum/viewtopic.php?id=2087 &amp;quot;Creating the Lair - A level tutorial&amp;quot;]&#039;&#039;&#039;&lt;br /&gt;
* [https://web.archive.org/web/20201127172559/http://oni.bungie.org/forum/viewtopic.php?pid=53026 &amp;quot;Creating a Custom Oni Level (s10k video tutorials)&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201127180431/http://oni.bungie.org/forum/viewtopic.php?id=1515 &amp;quot;Creating new levels&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201029114358/http://oni.bungie.org/forum/viewtopic.php?pid=33838 &amp;quot;Create levels with pathfinding grids&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20210117145338/http://oni.bungie.org/forum/viewtopic.php?id=2000 &amp;quot;More questions about levels&amp;quot;]&lt;br /&gt;
* [https://web.archive.org/web/20201029103906/http://oni.bungie.org/forum/viewtopic.php?pid=37252#p37252 &amp;quot;Modding Existing levels - Beta&amp;quot; (&amp;quot;Moveable furniture&amp;quot; post)]&lt;br /&gt;
&lt;br /&gt;
===Wiki pages on level creation===&lt;br /&gt;
* [[Creating a level]] (you are here)&lt;br /&gt;
* [[Modifying an existing level]]&lt;br /&gt;
* [[New levels]]&amp;lt;!--notes and comments by geyser that should be revisited / merged with this page--&amp;gt;&lt;br /&gt;
* [[Lightmapping levels]]&lt;br /&gt;
&lt;br /&gt;
===Free asset sources===&lt;br /&gt;
* [http://vk.com/gameready Various game meshes]&lt;br /&gt;
* [http://web.archive.org/web/20230601050258/http://tutorialsforblender3d.com/Textures/Textures_index.html Various game textures]&lt;br /&gt;
* [https://www.textures.com Various game textures]&lt;br /&gt;
&lt;br /&gt;
==Engine limitations==&lt;br /&gt;
First you should be aware of the limitations that Oni will place on your level.&lt;br /&gt;
&lt;br /&gt;
* The triangle limit of a game level is approx. 520,000 (consider it 500,000 to be on the safe side).&lt;br /&gt;
* {{ModTool}} can save DAE files with a maximum of 64,000 triangles per object.&lt;br /&gt;
* When polygons are too tightly packed, the camera will look at too many of them and glitches will appear. The limit on visible GQs (Gunk Quads) is 8,192 (2&amp;lt;sup&amp;gt;13&amp;lt;/sup&amp;gt;), and higher numbers will cause render bugs and produce the console error message &amp;quot;Exceeded max visible GQs &#039;&#039;number&#039;&#039;&amp;quot;. There are limited solutions to this:&lt;br /&gt;
** Decrease the &#039;&#039;&#039;gs_farclipplane_set&#039;&#039;&#039; value.&lt;br /&gt;
** Hide objects via &#039;&#039;&#039;[[#.3CModel.3E|env_show]]&#039;&#039;&#039;.&lt;br /&gt;
** Hide objects by &#039;&#039;level design&#039;&#039;. For example, departments in a building could be quite detailed because the view of the other departments/rooms is blocked by walls.&lt;br /&gt;
* The camera can look at 2,049 transparent textures at once; one more, and Oni crashes.&lt;br /&gt;
* Characters are visible &#039;&#039;only&#039;&#039; within world coordinates {-4,099, -4,099, -4,099} to {4,099, 4,099, 4,099}.&lt;br /&gt;
* Geometry stops outside of (roughly) world coordinates -4,228 to 4,228 on the X and Z axes (vertical axis not tested).&lt;br /&gt;
* &#039;&#039;&#039;chr_debug_spheres = 1&#039;&#039;&#039; visualizes the collision spheres of characters, so you can check if they will fit through an entrance.&lt;br /&gt;
&lt;br /&gt;
==3D tools==&lt;br /&gt;
===Problems when using multiple different tools===&lt;br /&gt;
Re-saving a DAE file in &#039;&#039;&#039;Mod Tool&#039;&#039;&#039; which was originally made in &#039;&#039;&#039;SketchUp&#039;&#039;&#039; can result in a surprising change in size within Oni. This is due to a difference in the specification of a scale unit.&lt;br /&gt;
&lt;br /&gt;
: For example, the SketchUp DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.0254000&amp;quot; name=&amp;quot;inch&amp;quot; /&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: And the re-saved Mod Tool DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.1&amp;quot; name=&amp;quot;decimetre&amp;quot;&amp;gt;&amp;lt;/unit&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case you&#039;ll need to open the new DAE in a text editor and change the length specification back.&lt;br /&gt;
&lt;br /&gt;
===Sketchup===&lt;br /&gt;
If you are working with Sketchup check out this pages:&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?id=2003 &amp;quot;Sketchup tutorials for making levels&amp;quot;]&lt;br /&gt;
* [[SketchUp tutorials and tips]]&lt;br /&gt;
&lt;br /&gt;
===Blender===&lt;br /&gt;
&#039;&#039;&#039;Scaling&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as Mod Tool and SketchUp: Caution with scaling: See [[#Problems when using multiple different tools|here]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pathfinding&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Be sure to uncheck automatic triangle creation when exporting (BNV) geometry used for pathfinding. Ghost (&#039;&#039;doors&#039;&#039;) must be quads. &lt;br /&gt;
&lt;br /&gt;
==Setting up a workflow==&lt;br /&gt;
If not noted differentely you need OniSplit v0.9.82.0 or a newer version. Onisplit can be downloaded [http://mods.oni2.net/node/38 HERE] (it also comes with the [[AE]] and is found in the Tools directory of the installation).&lt;br /&gt;
&lt;br /&gt;
The level import demo files can be downloaded [http://mods.oni2.net/node/299 HERE].&lt;br /&gt;
&lt;br /&gt;
First, put &#039;&#039;&#039;OniSplit.exe&#039;&#039;&#039; into the second &#039;&#039;&#039;lab&#039;&#039;&#039; folder alongside the XML files.&lt;br /&gt;
&lt;br /&gt;
Look at the file &#039;&#039;&#039;build.cmd&#039;&#039;&#039;. These are the two important lines:&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:level out lab.xml&lt;br /&gt;
 OniSplit.exe -import:pc out level3_Final.dat&lt;br /&gt;
&lt;br /&gt;
The first line creates the *.oni files from a master.xml file, in this case &#039;&#039;&#039;lab.xml&#039;&#039;&#039;. Once finalized, the resulting .oni files can be put into a new [[Making a mod package|AE package]].&lt;br /&gt;
&lt;br /&gt;
The second line creates level archives which can be used for fast tests. They don&#039;t require you to install a package through the AE Installer.&lt;br /&gt;
&lt;br /&gt;
Instead of &amp;quot;-nosep&amp;quot; you can now also use &amp;quot;-pc&amp;quot; for the import. Macs, however, do use &amp;quot;-sep&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
If the game crashes while loading at ~90% progress, be sure that the texture&#039;s x and y dimensions are powers of two: 64, 128, 256, 512….&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading at ~50-60% progress, be sure that the BINACJBOCharacters or AISA file has a player character defined.&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading ~5-10% progress, check if all your textures were inside the &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
:You can extract the AKEV file to XML, then search for the [[XML:AKEV#TXMA|TXMP Array]].&lt;br /&gt;
&lt;br /&gt;
:[http://mods.oni2.net/system/files/AKEV_texture_checker.txt THIS] script checks which textures are missing by comparing the AKEV*.xml with its *.oni files folder. Change the two paths so that it works for you: Alt+4, insert code, then F5.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;TXMP_marker_door&amp;quot; and &amp;quot;TXMP_marker_ghost&amp;quot; will be missing in the demo&#039;s &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
You can add this between the other two lines in build.cmd to prevent a crash.&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
;Polygon&lt;br /&gt;
:A polygon is a shape defined by points (vertices) in space. Polygons are the most fundamental building block in games. Oni uses only shapes with 3 and 4 points (triangles and quads). Other games might also use N-gons, shapes with more points.&lt;br /&gt;
;Face&lt;br /&gt;
:The &#039;&#039;&#039;surface of a polygon&#039;&#039;&#039; is also named face. The &#039;&#039;&#039;direction&#039;&#039;&#039; of a face in &#039;&#039;&#039;defined by its normal&#039;&#039;&#039;. If an object seems to have a hole, it might be that the polygon just has a &#039;&#039;&#039;flipped normal&#039;&#039;&#039; and is therefore wrongly rendered (displayed on screen).&lt;br /&gt;
;Normal&lt;br /&gt;
:Faces and even vertices themselves have directions. The normals of vertices determine how smooth or sharp edges will appear.&lt;br /&gt;
;Vertex (plural&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt; vertices)&lt;br /&gt;
:A point within a polygon.&lt;br /&gt;
:Vertex colors radiate from one vertex to another vertex, whereby their different color values blend into each other so that gradients can appear. &lt;br /&gt;
;Edge&lt;br /&gt;
:A line of two points within a polygon.&lt;br /&gt;
;Tris (triangles)&lt;br /&gt;
:Polygons made of 3 points.&lt;br /&gt;
;Quads&lt;br /&gt;
:Polygons made of 4 points. Planes. Rectangles.&lt;br /&gt;
:Internally, all quads get converted into two triangles and will affect the maximum triangle count accordingly.&lt;br /&gt;
;Level&lt;br /&gt;
:The term &amp;quot;level&amp;quot; is often used to shorten &amp;quot;level map&amp;quot; (buildings and terrain).&lt;br /&gt;
;Geometry&lt;br /&gt;
:Level geometry can be objects made of tris and/or quads.&lt;br /&gt;
:Oni differentiates between basically 3 types of level geometry:&lt;br /&gt;
:* Static objects (sometimes also named AKEV core geometry)&lt;br /&gt;
:* Animated objects&lt;br /&gt;
:* Pushable objects (not used in the original game)&lt;br /&gt;
;Static geometry&lt;br /&gt;
:* &#039;&#039;&#039;Unique level geometry with no functions&#039;&#039;&#039; (AKEV core geometry such as buildings and streets).&lt;br /&gt;
:* &#039;&#039;&#039;Repeating objects&#039;&#039;&#039; are flagged as &#039;&#039;&#039;furniture (FURN)&#039;&#039;&#039; although they can be outdoor objects such as boxes and containers. &amp;lt;!--Oni&#039;s story plays out most often inside buildings. So, there you go. --&amp;gt;FURN objects were used to be imported by an object collection, an CJBO. Nowadays, furniture collections can be used (again) for imports, but the individual objects are stored as OFGA files. This modularity is known in many game editors (like the Unreal Engine Editor). So, &#039;&#039;&#039;OFGA are nothing else than &amp;quot;game assets&amp;quot;.&#039;&#039;&#039; The drawback of OFGA is that they &#039;&#039;&#039;will not import with any vertex shading&#039;&#039;&#039;. Only their &#039;&#039;&#039;geometries&#039;&#039;&#039;, attached &#039;&#039;&#039;particle&#039;&#039;&#039; and &#039;&#039;&#039;gunk flags&#039;&#039;&#039; get copied into final (baked) level geometry.&lt;br /&gt;
:* &#039;&#039;&#039;Objects with actual functions&#039;&#039;&#039; (CJBO such as doors, consoles, triggers)&lt;br /&gt;
:** Some types of CJBO (spawn lists of weapons, characters, powerups and of course flags and patrol paths) are not considered as level geometry.&lt;br /&gt;
;[[XML:AKEV#AGQG|Gunk flags]]&lt;br /&gt;
:Properties directly associated with the polygons. Among others, these can be: Transparent, TwoSided, NoCollision, Invisible, NoObjectCollision, NoCharacterCollision, NoDecals, Furniture, Impassable.&lt;br /&gt;
;Baking&lt;br /&gt;
:When a level gets baked, all geometries get merged.&lt;br /&gt;
:*Unique level geometry will have vertex painting.&lt;br /&gt;
:*Objects derived from already compiled oni-files (shared classes) will have no vertex painting.&lt;br /&gt;
:*Animated and pushable objects will have no vertex shading.&lt;br /&gt;
;Vertex shading&lt;br /&gt;
:Vertex colors (vector data) can be painted onto core geometry.&lt;br /&gt;
:They are used as a rudimentary form of lightmapping (pixel data).&lt;br /&gt;
:Having vertex shading is still better than having no vertex shading at all. It makes the level appear more lifelike.&lt;br /&gt;
;Lightmapping&lt;br /&gt;
:In other games, lights and shadows are added to level geometry with lightmapping.&lt;br /&gt;
:There were experiments to bring lightmaps back to Oni. The technique come with a major drawback though. It doubles the triangle count and adds many textures.&lt;br /&gt;
;In-game&lt;br /&gt;
:When you are &amp;quot;inside&amp;quot; the game, running or playing it.&lt;br /&gt;
&lt;br /&gt;
==Level construction==&lt;br /&gt;
&#039;&#039;&#039;Visible environment&#039;&#039;&#039;&lt;br /&gt;
* A &#039;&#039;&#039;level map&#039;&#039;&#039; consists of visible geometry: terrain and buildings. This is also named the &#039;&#039;&#039;environment&#039;&#039;&#039; or for short &#039;&#039;&#039;env&#039;&#039;&#039;.&lt;br /&gt;
** Use &#039;&#039;&#039;quads&#039;&#039;&#039; of approximately 10 up to 20 meters in size to construct env geometry.&lt;br /&gt;
* Anything other than floors and simple walls will be made of triangles.&lt;br /&gt;
** Geometry from CJBO works best with triangles. Quads might show holes in-game.&lt;br /&gt;
&#039;&#039;&#039;Invisible pathfinding&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;AIs&#039;&#039;&#039; (or non-player characters, NPCs) need &#039;&#039;&#039;pathfinding&#039;&#039;&#039; data, usually shortened as &#039;&#039;&#039;bnv&#039;&#039;&#039;.&lt;br /&gt;
** Pathfinding data can be described as geometry, therefore as rooms. These &#039;&#039;&#039;bnv rooms&#039;&#039;&#039; are made of &#039;&#039;&#039;floors&#039;&#039;&#039; and are connected by &#039;&#039;&#039;ghost&#039;&#039;&#039; quads which work like doors. AIs can move from one room to another room only by passing a ghost. Therefore, ghosts have the same width as rooms in open terrain.&lt;br /&gt;
*** Use floor quads of approximately 10 meters in size to construct BNV floors.&lt;br /&gt;
*** Put ghost quads exactly on the edges of BNV floors with an angle of 90 degree.&lt;br /&gt;
&#039;&#039;&#039;Support for [[XML:BINA/ONIE|effects]]&#039;&#039;&#039;&lt;br /&gt;
* Effects such as decals that indicate damaged environment need level textures to be registered in [[XML:BINA/TMBD|TMBD]]. Make sure not to replace existing texture entries but to add your own so that the other levels remain unaffected.&lt;br /&gt;
&#039;&#039;&#039;Level logic&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BSL scripts bring levels fully to life. The logic is mostly event driven whereby different checkpoints and conditions must be reached.&lt;br /&gt;
* Checkpoints are actually [[XML:BINA/OBJC/TRGV|trigger volumes]] that can recognize entering and exiting characters.&lt;br /&gt;
* The second most important source of events are [[XML:BINA/OBJC/CHAR|character (script) functions]], especially the die function of enemies.&lt;br /&gt;
** To support good and less good players alike, NPC characters can feature the UpgradeDifficulty flag. Also, BSL scripts can detect the current [[BSL:Game_status|difficulty level]].&lt;br /&gt;
* [[XML:BINA/OBJC/TRIG|Laser triggers]] are mostly used to control [[XML:BINA/OBJC/TURR|turrets]]. [[XML:BINA/OBJC/CONS|Consoles]], triggers and [[XML:DOOR|door]] unlocking are used to set up very simple &amp;quot;riddles”.&lt;br /&gt;
* The creation of cut scenes is time-consuming quality work. Due to missing tools for streamlined workflows, it is totally okay for you to skip this.&lt;br /&gt;
** New synchronized FILM, OBAN and TRAM files are required for cut scenes. Not to mention sound files for dialog.&lt;br /&gt;
&lt;br /&gt;
==The master XML file==&lt;br /&gt;
&#039;&#039;The project file for level creation.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;master XML&#039;&#039;&#039; file&#039;s &#039;&#039;&#039;name determines&#039;&#039;&#039; the &#039;&#039;&#039;BSL folder name&#039;&#039;&#039; and the &#039;&#039;&#039;AKEV and ONLV file names&#039;&#039;&#039; in the output folder. File paths in the XML can be either absolute or relative.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mandatory files&#039;&#039;&#039; for level import:&lt;br /&gt;
* &#039;&#039;level_environment&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_bnv&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_textures.tga/jpg/png&#039;&#039;&lt;br /&gt;
* Character.xml or AISA with player&lt;br /&gt;
* ONSK name in &amp;lt;Sky&amp;gt; (in Windows, this can be a fake name; does the Mac need actual ONSK files?)&lt;br /&gt;
* ONLD file for the new level; read [[Making_a_mod_package#Mod_Info.cfg|HERE]] about making sure your level is unlocked (accessible on the Load Game screen)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Level SharedPath=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| The master XML file can link to other XML files. Most of them will be [[OBD:BINA/OBJC#OBJC_types|BINACJBO]] files. The file type is declared inside the file, so the file name itself doesn&#039;t have to contain the type. Ergo, &amp;quot;BINACJBOCharacter.xml&amp;quot; can be given a simpler name like &amp;quot;Character.xml&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some resources used by those XML files can be found in a &#039;&#039;&#039;shared&#039;&#039;&#039; folder. OniSplit copies textures and &amp;quot;physics&amp;quot; objects into the output folder; furniture objects will be integrated into the AKEV. Unused resources in the shared folder will be ignored. That way the final level archive or AE package contains only the necessary files, saving disk space for the end user.&lt;br /&gt;
&lt;br /&gt;
In the demo are various subfolders in the &#039;&#039;&#039;shared&#039;&#039;&#039; folder: consoles, doors, furniture, triggers and turrets. These file types do not need their file prefixes: CONS, DOOR, TRIG and OFGA. OniSplit will recognize them nonetheless.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Common mistake:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CJBO files &#039;&#039;&#039;need relative paths to the resource instead of just file names&#039;&#039;&#039;. Taking consoles, for example: a standard export to XML gives you &amp;quot;console_data&amp;quot;. But to use the shared resources these must be paths like &amp;quot;&#039;&#039;&#039;consoles/console_data.oni&#039;&#039;&#039;&amp;quot; as they are stored in &#039;&#039;&#039;shared/console/&#039;&#039;&#039;. Note how the demoed &#039;&#039;&#039;shared&#039;&#039;&#039; folder is placed next to the [http://mods.oni2.net/node/299 project (&amp;quot;lab&amp;quot;)] folder and the XML master file points to it using &amp;quot;../shared&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Environment&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Model&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Used to import level geometry and static objects. See [[#&amp;lt;Model&amp;gt;|HERE]] for detailed information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Node Id=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| informational (space for notes)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Can be used with BSL commands such as ...&lt;br /&gt;
: [[#&amp;lt;Model&amp;gt;|env_show ID 1]] (use 0 to hide)&lt;br /&gt;
: [[#Breakable glass with BSL recognition|env_broken ID1 [ID2]]] (if a second ID is supplied then objects in the range ID1..ID2 get counted; &amp;quot;3001 3018&amp;quot; would cover 18 objects)&lt;br /&gt;
: [[#Texture exchange|env_texswap ID texture]] (no file prefix/suffix allowed)&lt;br /&gt;
: [[#env_shade|env_shade ID ID R G B]]&lt;br /&gt;
Static objects store their ID in [[XML:AKEV#IDXA_.28quad_group_id.29|one of AKEV&#039;s IDXA instances]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Rooms&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| For detailed information see [[#&amp;lt;Rooms&amp;gt;|HERE]].&lt;br /&gt;
&lt;br /&gt;
For a Google SketchUp BNV tutorial see [http://oni.bungie.org/forum/viewtopic.php?pid=36760#p36760 HERE].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. BNV data, used to create pathfinding.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Textures&amp;gt; {{Anchor|textures_tag}}&lt;br /&gt;
| -&lt;br /&gt;
| With OniSplit v0.9.94.0+ you can use attributes to set the default import formats and max dimensions. For example:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Textures with a dimension that isn&#039;t a power of two (2&amp;lt;sup&amp;gt;x&amp;lt;/sup&amp;gt;) and textures larger than 512px on a side will be resized. For example, 2003x2000 will become 512x512. (What would 257x255 become?)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Texture Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| TXMP file name to generate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Flags&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Optional tag. For list of flags see [[XML:TXMP|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Format&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
:DXT1&lt;br /&gt;
:BGR&lt;br /&gt;
:RGBA&lt;br /&gt;
:BGR555&lt;br /&gt;
:BGRA5551&lt;br /&gt;
:BGRA4444&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Image&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.tga/jpg file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Sky&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| ONSKfile.oni (without file pre- and suffix)&lt;br /&gt;
&lt;br /&gt;
The import doesn&#039;t work with an empty tag. &amp;lt;Sky&amp;gt;clear&amp;lt;/Sky&amp;gt; helps here; any other fictional name will also do.&lt;br /&gt;
&lt;br /&gt;
For detailed information see [[XML:ONSK|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Import&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to an OBJC (collection) file. Supported collection files for &amp;lt;Import&amp;gt; are:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[#Furniture.xml|Furniture.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[#Physics.xml|Physics.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
The following two collection files are &#039;&#039;&#039;NOT&#039;&#039;&#039; supported. You need to copy them as regular pre-compiled *.oni files into your mod package:&lt;br /&gt;
: [[XML:BINA/OBJC/MELE|Melee.xml]] (overrides global MELE; not used in vanilla levels)&lt;br /&gt;
: [[XML:BINA/OBJC/CMBT|Combat.xml]] (overrides global CMBT?; not used in vanilla levels)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Inside&#039;&#039;&#039; the following three supported collection files, provide links to pre-compiled (*.oni) class files: console, door and furniture collections. Use relative paths such as:&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;consoles/&#039;&#039;&#039;console_data&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;doors/&#039;&#039;&#039;TCdouble&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;furniture/&#039;&#039;&#039;V_tctf_bigvan&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you are unsure about the folder structure refer back to the [http://mods.oni2.net/node/299 level import demo].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Films&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.xml file. OniSplit creates a [[XML:FILM|FILM]] file from it. Used for characters in cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Cameras&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Camera Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. OniSplit creates an OBAN file from it. Used for cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Name for the OBAN file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a trimmed-down version of the master file &#039;&#039;&#039;lab.xml&#039;&#039;&#039; from the demo. It&#039;s meant to give you a first impression. We might upload a smaller demo someday with all features nonetheless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Level SharedPath=&amp;quot;../shared&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Environment&amp;gt;&lt;br /&gt;
            &amp;lt;Model&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bomber_window.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;/Model&amp;gt;&lt;br /&gt;
            &amp;lt;Rooms&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Rooms&amp;gt;&lt;br /&gt;
            &amp;lt;Textures&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;bgra4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
            &amp;lt;/Textures&amp;gt;&lt;br /&gt;
        &amp;lt;/Environment&amp;gt;&lt;br /&gt;
        &amp;lt;Sky&amp;gt;sunset&amp;lt;/Sky&amp;gt;&lt;br /&gt;
        &amp;lt;Objects&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Character.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Furniture.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;TriggerVolume.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Physics.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Objects&amp;gt;&lt;br /&gt;
        &amp;lt;Films&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun01.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun02.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Films&amp;gt;&lt;br /&gt;
        &amp;lt;Cameras&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam01.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam01&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam02.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam02&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
        &amp;lt;/Cameras&amp;gt;&lt;br /&gt;
    &amp;lt;/Level&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Model&amp;gt;===&lt;br /&gt;
This tag is mandatory (it must be present to avoid errors); the model section contains one import path to the AKEV (level) geometry (*.dae) and can contain additional import paths for exceptions (*.dae).&lt;br /&gt;
&lt;br /&gt;
Data from the demo:&lt;br /&gt;
&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;env_show&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The motorcycle has here scripting ID 9. You can show and hide the object with the BSL command &#039;&#039;&#039;env_show&#039;&#039;&#039;, where the second parameter means true or false. &#039;&#039;&#039;Never use 0 as an ID&#039;&#039;&#039; because it won&#039;t work.&lt;br /&gt;
&lt;br /&gt;
 env_show 9 1&lt;br /&gt;
 env_show 9 0&lt;br /&gt;
&lt;br /&gt;
EdT demonstrates env_show [https://www.youtube.com/watch?v=Em6wa5JTQNM here]. Note how the objects have collision.&lt;br /&gt;
&lt;br /&gt;
The last vanilla level (Syndicate Mountain Compound) has a big satellite dish platform that can be made hidden. Obviously, such objects/areas can be made to have pathfinding too.&lt;br /&gt;
&lt;br /&gt;
;More possible applications of env_show:&lt;br /&gt;
* ground/ceiling/objects for cutscenes that become partially destroyed&lt;br /&gt;
* destructible walls like in Deus Ex: Human Revolution (trigger volume, replacing punch anim with punch-through-wall anim)&lt;br /&gt;
* grids in front of ventilation shafts (a small door object could be an alternative)&lt;br /&gt;
** at the moment this can&#039;t be done because characters can&#039;t sneak under the top edge of the opening (the characters collision spheres are too big)&lt;br /&gt;
* managing object groups with trigger volumes (save multiple objects in one DAE file)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- atm, the effort is not worth the work&lt;br /&gt;
&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/TV_triggered_env_show.png&amp;lt;/nowiki&amp;gt; (dead link)&lt;br /&gt;
: edit: replace 0 by 25&lt;br /&gt;
&lt;br /&gt;
If the objects appear to flicker then we could replace the hide_all_object_groups() function with individual TV exit functions.&lt;br /&gt;
&lt;br /&gt;
 func hide_all_object_groups&lt;br /&gt;
 {&lt;br /&gt;
 	# env_show id [1|0]&lt;br /&gt;
 	env_show 1 0&lt;br /&gt;
 	env_show 2 0&lt;br /&gt;
 	# ...&lt;br /&gt;
 	env_show 25 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func show_object_group (int grpA, int grpB, int grpC, int grpD, int grpE, int grpF, int grpG, int grpH)&lt;br /&gt;
 {&lt;br /&gt;
 	env_show (grpA, 1)&lt;br /&gt;
 	env_show (grpB, 1)&lt;br /&gt;
 	env_show (grpC, 1)&lt;br /&gt;
 	env_show (grpD, 1)&lt;br /&gt;
 	env_show (grpE, 1)&lt;br /&gt;
 	env_show (grpF, 1)&lt;br /&gt;
 	env_show (grpG, 1)&lt;br /&gt;
 	env_show (grpH, 1)&lt;br /&gt;
 &lt;br /&gt;
 	# missing arguments are taken to be 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_25_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 &lt;br /&gt;
 	# show object group of entered TV and of neighboring TVs&lt;br /&gt;
 	# (center, north, north east, east, east south, south, south west, west, west north)&lt;br /&gt;
 	# there&#039;s a limit of 8 arguments per function&lt;br /&gt;
 	show_object_group 25 1 2 3 4 5 6 7&lt;br /&gt;
 	show_object_group 8&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # other examples&lt;br /&gt;
 func TV_6_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 0 0 00 0 00 00 00 00&lt;br /&gt;
 	show_object_group 22&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_20_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 20 21 6 19&lt;br /&gt;
 }&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Import of object groups====&lt;br /&gt;
&#039;&#039;&#039;Mod Tool versus SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The meaning and behavior of &amp;quot;groups&amp;quot; greatly differs in these two programs.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In SketchUp&#039;&#039;&#039; you can group objects which enables you to easily duplicate all objects inside a group and to scale/rotate/translate them all together.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In Mod Tool&#039;&#039;&#039; grouped objects are still loose, and duplicating a group won&#039;t duplicate the objects. To achieve the same effect as in SketchUp, you have to create a hierarchy where any one object is the &amp;quot;parent&amp;quot; and all others the &amp;quot;children&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Google SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a group, select two or more objects, right-click on the selection and choose &amp;quot;make group&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:ModTool_can_import_objs_in_hierarchies.jpg|right|thumb|Mod Tool can import objects in hierarchies to Oni.]]&lt;br /&gt;
&#039;&#039;&#039;Mod Tool&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either use the Explorer (A) or the Schematics (B) to create a hierarchy.&lt;br /&gt;
&lt;br /&gt;
:(A) In the Explorer window, drag and drop one or more objects onto another one.&lt;br /&gt;
&lt;br /&gt;
:(B) Open the constrain tab at the right side. Select parent object, click &amp;quot;Parent&amp;quot;, click the child object(s). Check the result in the Schematics window.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Mod Tool: caution when saving to DAE!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:A normal selection won&#039;t do. You have to select the object tree to successfully save a hierarchy. This is the same way that you do it with Oni characters.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=====Import of smart object groups=====&lt;br /&gt;
Let&#039;s say there are two groups. If an edit is made to one mesh, the clone in the other group is instantly changed the same way.&lt;br /&gt;
&lt;br /&gt;
So that&#039;s a smart group. In SketchUp this is named &amp;quot;component&amp;quot;. In Mod Tool it&#039;s named ???.&lt;br /&gt;
:(Can be imported from SketchUp DAE file but causes a crash when re-saving. I guess a script is needed to do the job.)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Breakable glass with BSL recognition====&lt;br /&gt;
Broken environmental objects can be recognized by the BSL command &#039;&#039;env_broken (ID_1, ID_N)&#039;&#039;. However, this requires additional code to work.&lt;br /&gt;
&lt;br /&gt;
An example is the training level. Let&#039;s determine how we can set up such a thing.&lt;br /&gt;
&lt;br /&gt;
First we need a [[XML:BINA/OBJC/TRGV|trigger volume]] like in level 1.&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;TRGV Id=&amp;quot;11495&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Locked&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-714.6615 -298 -555.2073&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;0 0 0&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;tv75&amp;lt;/Name&amp;gt;&lt;br /&gt;
                &amp;lt;Scripts&amp;gt;&lt;br /&gt;
                    &amp;lt;Entry&amp;gt;&amp;lt;/Entry&amp;gt;&lt;br /&gt;
                    &amp;lt;Inside&amp;gt;targets_gone&amp;lt;/Inside&amp;gt;&lt;br /&gt;
                    &amp;lt;Exit&amp;gt;&amp;lt;/Exit&amp;gt;&lt;br /&gt;
                &amp;lt;/Scripts&amp;gt;&lt;br /&gt;
                &amp;lt;Teams&amp;gt;255&amp;lt;/Teams&amp;gt;&lt;br /&gt;
                &amp;lt;Size&amp;gt;400 31 270&amp;lt;/Size&amp;gt;&lt;br /&gt;
                &amp;lt;TriggerVolumeId&amp;gt;75&amp;lt;/TriggerVolumeId&amp;gt;&lt;br /&gt;
                &amp;lt;ParentId&amp;gt;0&amp;lt;/ParentId&amp;gt;&lt;br /&gt;
                &amp;lt;Notes&amp;gt;&amp;lt;/Notes&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;PlayerOnly&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/TRGV&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need some BSL code.&lt;br /&gt;
&lt;br /&gt;
 var int inside_target_function;&lt;br /&gt;
 &lt;br /&gt;
 func void enter_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint enter_target_function&lt;br /&gt;
    inside_target_function = 1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void exit_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint exit_target_function&lt;br /&gt;
    inside_target_function = 0;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_are_not_gone(void)&lt;br /&gt;
 {&lt;br /&gt;
 	# CB: turn off the trigger volume and sleep for a second&lt;br /&gt;
 	# so as not to cause hideous performance loss&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	sleep 60&lt;br /&gt;
 	trigvolume_enable tv75 1&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_gone(string ai_name)&lt;br /&gt;
 {&lt;br /&gt;
 	if (inside_target_function eq 0)&lt;br /&gt;
 	{	&lt;br /&gt;
 		enter_target_function() # catch other &amp;quot;targets_gone&amp;quot; functions to let them do nothing&lt;br /&gt;
 &lt;br /&gt;
 		var int num_broken = env_broken(3001, 3018);&lt;br /&gt;
 		# if you only one target use scheme: env_broke(3001, 3001)&lt;br /&gt;
 &lt;br /&gt;
 		if (num_broken eq 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_gone();&lt;br /&gt;
 		}&lt;br /&gt;
 	&lt;br /&gt;
 		if (num_broken &amp;lt; 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_not_gone(); # to set check interval to one second&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		exit_target_function&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func targets_are_gone&lt;br /&gt;
 {&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	# [...]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
;Explanation:&lt;br /&gt;
&lt;br /&gt;
Player enters the TV, targets_gone() gets triggered. The variable &amp;quot;inside_target_function&amp;quot; should be 0 by default, so we will enter the &amp;quot;if&amp;quot; block. Next, we can assume that the player didn&#039;t destroy all glass objects, so &amp;quot;num_broken&amp;quot; will be less than 18; thus, targets_are_not_gone() gets called.&lt;br /&gt;
&lt;br /&gt;
The TV function targets_gone() &#039;&#039;would&#039;&#039; be triggered every frame, but targets_are_not_gone() creates a delay between checks: the TV gets deactivated for 60 frames. Then the TV becomes enabled again and will start anew until all glass objects got destroyed or player left the TV.&lt;br /&gt;
&lt;br /&gt;
In this case the targets_gone() function will do nothing because &amp;quot;inside_target_function&amp;quot; was set to 1 by the first call.&lt;br /&gt;
&lt;br /&gt;
targets_are_gone() eventually disables the TV to prevent memory overflow; this function also contains all the things (&amp;quot;[...]&amp;quot;) that you want to happen after the glass target is broken.&lt;br /&gt;
&lt;br /&gt;
====Texture exchange====&lt;br /&gt;
BSL command supported on Windows and Mac:&lt;br /&gt;
: env_texswap ID texture&lt;br /&gt;
&lt;br /&gt;
Might be useful to switch on/off static and animated textures. (News broadcast screen: running or off or smashed. Lava stream: flowing or stagnating or cooled down. Etc.)&lt;br /&gt;
&lt;br /&gt;
A similar effect can be achieved by showing/hiding geometries with different textures as EdT has demonstrated in a private test. That way it should also be possible to have different vertex coloring for an area.&lt;br /&gt;
&lt;br /&gt;
====Vertex coloring====&lt;br /&gt;
Vertex colors can be edited manually in Blender by setting up following 3 things:&lt;br /&gt;
* Properties Panel &amp;gt; Data &amp;gt; Color Attributes&amp;lt;!--only tested with Face Corner, Byte Color--&amp;gt;&lt;br /&gt;
* 3D viewport (left top) &amp;gt; change work mode to Vertex Paint&lt;br /&gt;
* 3D viewport (right top) &amp;gt; change to Viewport Shading to Solid mode (under the dropdown menu you can choose &amp;quot;flat&amp;quot; to have full saturation)&lt;br /&gt;
&lt;br /&gt;
{{divhide|Mod Tool}}&lt;br /&gt;
&lt;br /&gt;
[http://web.archive.org/web/20170529111607/http://softimage.wiki.softimage.com/xsidocs/tex_vcolor_CreatingColoratVerticesCAVMaps.htm SoftImage documentation.] Observation: The sniper tower from level 19 Syndicate Mountain Compound can be isolated and re-imported as it is. It will appear quite dark.&lt;br /&gt;
&lt;br /&gt;
If we remove &amp;quot;_color&amp;quot; from the object, the shadows will be gone next time we import the tower.&lt;br /&gt;
&lt;br /&gt;
Mod Tool: Explorer [8]&lt;br /&gt;
&lt;br /&gt;
 Object&lt;br /&gt;
  |&lt;br /&gt;
  +-- Polygon Mesh&lt;br /&gt;
        |&lt;br /&gt;
        +-- Cluster&lt;br /&gt;
              |&lt;br /&gt;
              +-- Polygon&lt;br /&gt;
              |     |&lt;br /&gt;
              |     +-- [...]&lt;br /&gt;
              |&lt;br /&gt;
              +-- NodeProperties&lt;br /&gt;
                    |&lt;br /&gt;
                    +-- &#039;&#039;&#039;_color&#039;&#039;&#039;&lt;br /&gt;
                    +-- texcoord (Explicit UVWs)&lt;br /&gt;
                          |&lt;br /&gt;
                          +-- Vertex_Color_Def&lt;br /&gt;
&lt;br /&gt;
So, how do we modify that data?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Single object shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If there&#039;s already a vertex color property, you can use Shift + W to activate the Paint Vertex Color Tool. With Control + W you can change the brush color. R + Hold Click + Move Mouse let you change the brush size. The more vertices (points) you have, the more detailed you can make the shadows/colors. But keep in mind that too many polygons can destroy collision, making characters fall through the ground.&lt;br /&gt;
&lt;br /&gt;
If there&#039;s no vertex color property, the first usage of Shift + W will create that property. But you can also manually create it via Property &amp;gt; Color under Vertices Map.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Level-wide shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:light_test_modtool.png|right|thumb]]&lt;br /&gt;
[[Image:light_test_ingame.png|right|thumb]]&lt;br /&gt;
&lt;br /&gt;
To get general shading/lighting you can set up light sources. &amp;quot;Infinite&amp;quot; lights are useful for global lighting, while &amp;quot;Light Box&amp;quot;, &amp;quot;Point&amp;quot;, &amp;quot;Neon&amp;quot; and &amp;quot;Spot&amp;quot; are more suitable as local light sources. They can be accessed via Primitives &amp;gt; Light.&lt;br /&gt;
&lt;br /&gt;
By default, a Mod Tool scene has one Infinite light, but it doesn&#039;t shine in every direction so you might want to add more Infinite lights. Let&#039;s say one Infinite light for each direction (+X, -X, +Y, -Y, +Z, -Z) with an intensity of circa 0.25 (night) or 0.75 (day).&lt;br /&gt;
&lt;br /&gt;
The illumination of those lights can be integrated into the vertex color property. There&#039;s some information [http://oni.bungie.org/forum/viewtopic.php?pid=29089#p29089 on OCF here]; the quoted information is in triplicate, so don&#039;t get confused by that: at first it&#039;s detailed, then summarized, then as a checklist.&lt;br /&gt;
&lt;br /&gt;
Basically, you can go with the checklist:&lt;br /&gt;
&lt;br /&gt;
* Property &amp;gt; Color At Vertices Map&lt;br /&gt;
* Property &amp;gt; Render Map&lt;br /&gt;
* In render map property page, under Sampling select Vertices Only&lt;br /&gt;
* Under Surface Color, choose Enable, then in the box below select Vertex _Color; if that option does not appear, click on the New button next to it&lt;br /&gt;
* Under Map, select Illumination only&lt;br /&gt;
* Finally, click on the button Regenerate Maps...&lt;br /&gt;
&lt;br /&gt;
This must be done for all objects separately.&lt;br /&gt;
&lt;br /&gt;
: [http://mods.oni2.net/system/files/vertex_color_script.txt There&#039;s a script here]&amp;lt;!--http://mods.oni2.net/node/352--&amp;gt; which can apply vertex color and render maps to all &#039;&#039;&#039;selected&#039;&#039;&#039; objects. Load it into the script editor with Alt + 4 and hit F5 to run it. (Be sure the script&#039;s language was set to VBScript.)&lt;br /&gt;
: The variable &amp;quot;overwrite_VC&amp;quot; can be changed.&lt;br /&gt;
:: With &amp;quot;1&amp;quot; all existing CAV maps of selected objects will be overwritten. This can take some time.&lt;br /&gt;
:: With &amp;quot;0&amp;quot; only selected objects without CAV maps will be the script&#039;s target.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes on ModTool view modes&#039;&#039;&#039;&lt;br /&gt;
* &amp;quot;Constant&amp;quot; let you see the colors of the vertex coloring only.&lt;br /&gt;
* &amp;quot;Textured Decal&amp;quot; let you see object textures only.&lt;br /&gt;
* &amp;quot;Shaded&amp;quot; let you see the illumination only.&lt;br /&gt;
* &amp;quot;Textured&amp;quot; let you see the textured object with illumination and vertex coloring.&lt;br /&gt;
{{divhide|end}}&lt;br /&gt;
&lt;br /&gt;
=====env_shade=====&lt;br /&gt;
If you use &#039;&#039;&#039;env_shade&#039;&#039;&#039;, use it with caution. It completely overwrites the vertex coloring.&lt;br /&gt;
&lt;br /&gt;
 # BSL command&lt;br /&gt;
 # env_shade obj_id obj_id R G B&lt;br /&gt;
 &lt;br /&gt;
 # examples&lt;br /&gt;
 env_shade 7 7			# object 7 will be black&lt;br /&gt;
 env_shade 7 7 0 0 0		# object 7 will be black&lt;br /&gt;
 env_shade 7 7 .31 .999 .5	# object 7 will be quite green&lt;br /&gt;
 env_shade 7 10 1 1 1		# object 7, 8, 9, 10 lose all their shading&lt;br /&gt;
&lt;br /&gt;
====Baked lightmaps====&lt;br /&gt;
A drawback of this method, AKA shadow maps, is the high number of [[XML:BINA/TMBD|TMBD]] changes and new textures for every wall, requiring a lot of memory. How to create shadow maps:&lt;br /&gt;
&lt;br /&gt;
* https://web.archive.org/web/20121105081823/http://www.game-artist.net/forums/support-tech-discussion/5622-burning-shadows-onto-texture-xsi.html&lt;br /&gt;
&amp;lt;!-- http://caffeineabuse.blogspot.de/2008/12/cast-shadow-only-lights-in-xsi.html might be also interesting --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on map options:&lt;br /&gt;
* &amp;quot;Surface color and illumination&amp;quot;: outputs used texture with added shadows&lt;br /&gt;
** Can be used to replace original texture&lt;br /&gt;
* &amp;quot;Illumination only&amp;quot;: output a texture that only contains the shadows&lt;br /&gt;
** Can be used on a new overlying, transparent surface&lt;br /&gt;
&lt;br /&gt;
====Standalone lightmaps====&lt;br /&gt;
With this approach there are two meshes, whereby the shadow effects on one mesh get drawn in front of the regular level texture.&lt;br /&gt;
&lt;br /&gt;
Compared to the &amp;quot;baked lightmaps&amp;quot; method, this needs more polygons of course. And these polygons are transparent, which is a problem with Oni&#039;s limited rendering ability for such textures. However, standalone lightmaps only need a few new textures if used wisely.&lt;br /&gt;
&lt;br /&gt;
Read [[Lightmapping levels]] to learn more.&lt;br /&gt;
&lt;br /&gt;
[[Image:Oni_Lightmaps_double_polygon_method.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Rooms&amp;gt;===&lt;br /&gt;
The Rooms tag is mandatory. It contains an import path to BNV and ghosts (*.dae) which are used to create pathfinding grids. For information on the binary data behind this, see [[OBD:AKVA|HERE]].&lt;br /&gt;
&lt;br /&gt;
Sample code from the master XML file:&lt;br /&gt;
 &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fundamentals&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;BNVs&#039;&#039;&#039; are &#039;&#039;&#039;volumes&#039;&#039;&#039; (sometimes also named &#039;&#039;&#039;rooms&#039;&#039;&#039;) that have a pathfinding grid assigned to them.&lt;br /&gt;
* For practical reasons you only need &#039;&#039;&#039;floors and ramps&#039;&#039;&#039; to build a BNV. (As seen [http://edt.oni2.net/images/Hideout_BNV.jpg HERE.])&lt;br /&gt;
** A BNV polygon can consist of 3 or more points, but it&#039;s recommended to use &#039;&#039;&#039;shapes with 4 points&#039;&#039;&#039; because the other shapes usually waste more grid space. At the moment you can import only &#039;&#039;&#039;[[wikt:convex|convex]]&#039;&#039;&#039; shapes.&lt;br /&gt;
* Secondly, there are so called &#039;&#039;&#039;ghosts&#039;&#039;&#039; (vertical quads) that connect &#039;&#039;&#039;neighboring BNVs&#039;&#039;&#039;. AI can only transit from BNV to another through ghosts.&lt;br /&gt;
: OniSplit gives error messages for ghosts that don&#039;t have 2 neighboring BNVs, for example:&lt;br /&gt;
 BNV Builder: Ghost &#039;grid2&#039; has no adjacencies at &amp;lt;-72,41 1,999 -166,6&amp;gt; and &amp;lt;-71 1,999 -168,21&amp;gt;, ignoring&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tolerance values&#039;&#039;&#039;&lt;br /&gt;
* Horizontal distance from room to ghost: 1&lt;br /&gt;
* Vertical distance from room to ghost: 18&lt;br /&gt;
* Ghost&#039;s horizontal dimension must be greater than 0&lt;br /&gt;
* Under optimal circumstances, pathfinding works on a plane that is +4 world units above or -0.5 below the pathfinding grid&lt;br /&gt;
* Normally characters can&#039;t pass over low vertical walls such as stairs/curbs if those don&#039;t have a ramp under them; near ground level (Y=0) is an exception where characters are allowed to step on a plane that is 4 world units above pathfinding grid; higher planes need a ramp&lt;br /&gt;
* Maximum angle of ramp you can go on is 70°; higher angles will make characters fall through to their death (in those cases you might want to add invisible walls/boxes to prevent them from touching the ramp)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;More notes on PF processing&#039;&#039;&#039;&lt;br /&gt;
* Actually, BNV and ghosts can have any name and don&#039;t need any texture.&lt;br /&gt;
* During pathfinding calculation, OniSplit creates a new folder called &amp;quot;temp&amp;quot; and a subfolder &amp;quot;grids&amp;quot;. There is a file named &amp;quot;&#039;&#039;levelname&#039;&#039;_grids.dae&amp;quot;. That file contains rooms with textures called &amp;quot;bnv_grid_&#039;&#039;N&#039;&#039;.tga&amp;quot; which mark obstacles in the pathfinding grid. Ghosts will have a transparent texture &amp;quot;&#039;&#039;&#039;_marker_ghost&#039;&#039;&#039;.tga&amp;quot;. You also get these when you export a level. Transparent ghosts make it easier to see the rest of your level if you have many of those planes.&lt;br /&gt;
* In Mod Tool, ghosts and rooms can be grouped under a null object. Right-click the null object to select all its children, then use &amp;quot;Selection Only [x]&amp;quot; as your saving option. That way all the planes can be quickly saved to a *.dae file.&lt;br /&gt;
* You can influence the pathfinding creation of dangerous zones using danger quads. Read about those [[#Marker textures|HERE]].&lt;br /&gt;
* Another kind of influence is the [[#&amp;lt;Model&amp;gt;|gunk flag]] IgnoreGrid. It can be used to tell OniSplit to ignore the object during pathfinding creation. The grids in that place will be white.&lt;br /&gt;
&lt;br /&gt;
[[Image:Pathfinding_grid.jpg|thumb|200px|right|&#039;&#039;&#039;ai2_showgrids = 1&#039;&#039;&#039; in action]]&lt;br /&gt;
&#039;&#039;&#039;BSL commands&#039;&#039;&#039;&lt;br /&gt;
* chr_show_bnv = 1&lt;br /&gt;
:: shows number of BNVs the player is standing on&lt;br /&gt;
* ai2_showgrids = 1&lt;br /&gt;
:: shows pathfinding grids&lt;br /&gt;
* ai2_chump&lt;br /&gt;
:: spawns a friendly Striker that follows the player if possible, makes also pathfinding grids visible&lt;br /&gt;
* ai2_chump_stop = 1&lt;br /&gt;
:: Striker stops following you&lt;br /&gt;
* ai2_chump_stop = 0&lt;br /&gt;
:: Striker follows you again&lt;br /&gt;
&lt;br /&gt;
====Pathfinding on uneven ground====&lt;br /&gt;
Pathfinding works on slightly uneven ground as long as the polygons are 0.5 world units beneath or 4 world units above the BNV.&lt;br /&gt;
&lt;br /&gt;
For greater surface irregularities, we can use a trick:&lt;br /&gt;
* The problematic polygons must be saved to a DAE file and then referenced in the model section as an individual object.&lt;br /&gt;
* Then the &amp;lt;GunkFlags&amp;gt; tag needs to be &#039;&#039;&#039;&#039;&#039;GridIgnore&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Additionally we create a plane (invisible if necessary) under the object so that Oni doesn&#039;t think there&#039;s a hole.&lt;br /&gt;
* The ghosts must be taller than the highest polygon to be walked on. (This has been tested up to a height of 2,000 world units.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms of too-small ghosts&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A) AI can&#039;t run at all.&lt;br /&gt;
&lt;br /&gt;
B) AI loses PF ability if the tracked enemy performs animations that are outside of the pathfinding volume. Here&#039;s a video (&amp;lt;nowiki&amp;gt;https://youtu.be/vfKPzP5hiCo&amp;lt;/nowiki&amp;gt;, dead link) showing these symptoms.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Missing boundaries&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say you have a BNV, tall ghosts, and a GridIgnore-flagged hill with trees and bushes and stuff.&lt;br /&gt;
&lt;br /&gt;
Why do AIs run up against the trees?&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; There are no red/orange grids that limit the AI&#039;s movement. Normally, objects will produce red pathfinding squares around them. But objects that are 20 world units above the BNV are ignored just like objects with the IgnoreGrid flag.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Add simple geometries like &#039;&#039;_marker_impassable fences&#039;&#039; or danger quads near the BNV.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Disappearing AIs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The ground is sometimes not solid, and the player and AIs are falling through it.&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; On GridIgnore-flagged uneven ground, AIs can fall through it when they are out of the player&#039;s view.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Use either &#039;&#039;&#039;chr_lock_active &#039;&#039;AI_name&#039;&#039;&#039;&#039;&#039; or &#039;&#039;&#039;chr_all_active = 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Debugging====&lt;br /&gt;
&#039;&#039;&#039;(OniSplit v0.9.93.0+)&#039;&#039;&#039;&lt;br /&gt;
[[Image:OniBrowser.jpg|thumb|200px|right|OniBrowser displaying level geometry plus PF and ghosts.]]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;env_show_ghostgqs = 1&#039;&#039;&#039; makes the ghost quads visible&lt;br /&gt;
** The original ghost quads can&#039;t be seen; per Neo, &amp;quot;they are not included in the octtree and bsp tree&amp;quot;&lt;br /&gt;
** To see them you must use the -debug option in the level creation command (available with OniSplit &#039;&#039;&#039;v0.9.93.0+&#039;&#039;&#039;)&lt;br /&gt;
 OniSplit.exe -create:level &#039;&#039;output_folder&#039;&#039; &#039;&#039;&#039;-debug&#039;&#039;&#039; &#039;&#039;input_folder&#039;&#039;/&#039;&#039;master_xml_file&#039;&#039;.xml&lt;br /&gt;
&lt;br /&gt;
Not all debugging/testing needs to be done in Oni. There is also a [http://mods.oni2.net/node/256 program] (Windows only) which can display the whole level.&lt;br /&gt;
&lt;br /&gt;
For example you can load an AKEV*.oni, select the level name, and use the hotkeys [B] and [P] to display BNVs and ghosts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bug prevention:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
After all testing is done, you should compile the level a last time without the -debug option.&lt;br /&gt;
&lt;br /&gt;
AIs appear to have trouble shooting through ghost quads that got registered in the octtree/BSP tree as seen here (&amp;lt;nowiki&amp;gt;https://www.youtube.com/watch?v=-ZugVBgBVKc&amp;lt;/nowiki&amp;gt;, dead link).&lt;br /&gt;
&lt;br /&gt;
====When OniSplit fails to connect PF quads====&lt;br /&gt;
[[Image:Pathfinding_creation__merge_polygons_to_fix_connections.jpg|thumb|200px|right|Fixed PF in compound level after underground construction...]]&lt;br /&gt;
It can help to merge polygons to one object and merge their edges. These become white. (Outer edges are blue.)&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Textures&amp;gt;===&lt;br /&gt;
====...used for exceptions====&lt;br /&gt;
The [[#textures_tag|textures tag]] is mandatory.&lt;br /&gt;
&lt;br /&gt;
AKEV textures will be imported by the master XML file automatically; you don&#039;t need to add them to that file.&lt;br /&gt;
&lt;br /&gt;
: With OniSplit v0.9.82-93.0, the textures&#039; formats will be DXT1 and (for transparent ones) BGRA4444.&lt;br /&gt;
: With OniSplit v0.9.94.0+ the textures&#039; formats will be BGR and (for transparent ones) RGBA.&lt;br /&gt;
&lt;br /&gt;
To change the default texture import format, use the Texture&#039;&#039;&#039;s&#039;&#039;&#039; tag. (Possible with OniSplit v0.9.94.0+.)&lt;br /&gt;
&lt;br /&gt;
To change the format/flag/gunk flag of a specific texture, use the Texture tag.&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&lt;br /&gt;
          &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;TwoSided&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;BGRA4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
          &amp;lt;/Textures&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use the gunk flag &amp;quot;TwoSided&amp;quot; to make surfaces visible from both sides.&lt;br /&gt;
* If the texture comes with the gunk flag &amp;quot;NoCollision&amp;quot; then all objects with that texture will have no collision. Characters would fall through it.&lt;br /&gt;
&lt;br /&gt;
Transparency and no collision together would make sense for a water-like substance. The Vago Biotech level uses this approach for the area with green toxic waste.&lt;br /&gt;
&lt;br /&gt;
[[Image:making_a_surface_transparent_and_twosided.png|thumb|200px|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures.png|thumb|200px|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;&amp;lt;br&amp;gt;one object with multiple textures, one per polygon cluster]]&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures_ingame.png|thumb|200px|right|&#039;&#039;&#039;Figure 3&#039;&#039;&#039;&amp;lt;br&amp;gt;blue: two-sided&amp;lt;br&amp;gt;glass: two-sided and transparent&amp;lt;br&amp;gt;random metal: no flag (one-sided)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TwoSided and transparent objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s also possible to set this in Mod Tool. For TwoSided-ness, use one image source for diffuse and transparency. (It won&#039;t work with two image sources even if both sources use the same image.)&lt;br /&gt;
&lt;br /&gt;
For transparency you must additionally use the three checkboxes:&lt;br /&gt;
* Transparency: Enable&lt;br /&gt;
* Transparency: Use Alpha&lt;br /&gt;
* Transparency: Invert&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;Figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Regular textures====&lt;br /&gt;
OniSplit automatically imports textures of objects in the [[#&amp;lt;Model&amp;gt;|&amp;lt;Model&amp;gt; section]]. Those objects could be considered as AKEV core geometry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;One texture per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Furniture and Physics objects are allowed to have only one texture per object. AKEV core geometry can have one texture or multiple textures – that&#039;s up to you to decide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multiple textures per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question:&#039;&#039;&#039; How do we apply multiple textures to an AKEV core object?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Answer:&#039;&#039;&#039; Assuming you are using Mod Tool the procedure will be as follows. Repeat this for each cluster you create (except for projection). See also &#039;&#039;&#039;Figure 2 and 3&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Select some polygons&lt;br /&gt;
* Go to Material &amp;gt; Phong&lt;br /&gt;
* Hit [7] to open Render Tree&lt;br /&gt;
* Add a texture and connect &amp;quot;Image&amp;quot; with &amp;quot;Phong&amp;quot;, choose &amp;quot;diffuse&amp;quot; as illumination mode&lt;br /&gt;
* Double-click &amp;quot;Image&amp;quot; to open Material page&lt;br /&gt;
* In the Texture Projection section, click on &amp;quot;New&amp;quot; and choose a suitable projection&lt;br /&gt;
** Do this only if there isn&#039;t a projection in the &amp;quot;Texture_Coordinates_AUTO&amp;quot; cluster yet&lt;br /&gt;
** OniSplit processes only one texture projection, see &#039;&#039;&#039;Figure 4&#039;&#039;&#039;&lt;br /&gt;
* Choose the texture and UV, then fine-tune the UV via Alt + 7&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_multiple_textures_one_projection.png|thumb|200px|right|&#039;&#039;&#039;Figure 4&#039;&#039;&#039;&amp;lt;br&amp;gt;use only one texture projection per object]]&lt;br /&gt;
&lt;br /&gt;
Caution: textures will be fixed to one set of flags. You can&#039;t use the same texture A for a one-sided cluster/object B and a two-sided cluster/object C. You would need to create a differently-named clone of that texture and apply that to cluster/object C.&lt;br /&gt;
&lt;br /&gt;
====Marker textures====&lt;br /&gt;
Marker textures are used to import certain objects with special flags. Import those objects alongside [[#&amp;lt;Model&amp;gt;|AKEV core]] geometry.&lt;br /&gt;
&lt;br /&gt;
Marker textures aren&#039;t imported automatically. Add those textures to the final package or plugin yourself, e.g. with some sort of script.&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
The flags Transparent, TwoSided and NoOcclusion are only set if the same texture source is used for diffuse and transparency and if transparency setting are enabled. See the subsection under &amp;quot;[[#...used for exceptions|...used for exceptions]]&amp;quot; called &amp;quot;TwoSided and transparent objects&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Danger quads&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pathfinding grids have different colored squares with different meanings.&lt;br /&gt;
* white/gray - clear space&lt;br /&gt;
* green light - near wall&lt;br /&gt;
* green - semi-passable&lt;br /&gt;
* green dark - stairs&lt;br /&gt;
* blue very light - border 1&lt;br /&gt;
* blue light - border 2&lt;br /&gt;
* blue - border 3&lt;br /&gt;
* blue dark - border 4&lt;br /&gt;
* &#039;&#039;&#039;orange - danger&#039;&#039;&#039;&lt;br /&gt;
* red - impassable&lt;br /&gt;
&lt;br /&gt;
For detailed information on colors, see [[OBD_talk:AKVA/0x24#EFFECTS_of_various_pathfinding_grid_tile_types|HERE]].&lt;br /&gt;
&lt;br /&gt;
Normally, OniSplit decide how to color the grids. But it&#039;s possible to add your own danger quads to fine-tune zones of higher danger. Those orange areas will be generated with the 4 different blue borders around it.&lt;br /&gt;
&lt;br /&gt;
Danger quads must have &amp;quot;&#039;&#039;&#039;_marker_danger&#039;&#039;&#039;&amp;quot; as texture name.&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided NoCollision Invisible NoOcclusion Danger&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;_marker_barrier&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!-- Originally this is only used for level-bounding invisible walls? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided(double-check) Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLLISION (boxes)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
AIs can get stuck in detailed geometry. This can be prevented with collision boxes. In-game the box will be invisible, but has collision so characters can&#039;t get through. The pathfinding grid will be red where it comes in contact with the box; the red is followed by a light green and then regular green.&lt;br /&gt;
&lt;br /&gt;
[[XML:OFGA|OFGAs]] use the COLLISION texture. Onisplit doesn&#039;t automatically apply gunk flags to it. You need to use XML tags for that. Typically it would be &amp;lt;GunkFlags&amp;gt;Invisible NoObjectCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Normally, characters can&#039;t move on stairs because they contain vertical rises. In this case you can use a sloping quad that is above or inside the staircases. It&#039;s possible to set the desired flags in the &amp;lt;Model&amp;gt; section, but doing so and exporting these self-made stair ramps is wasted time. Simply apply _marker_stairs to that quad and characters will be able to move on that surface.&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Stairs Transparent TwoSided Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
This has no effect on pathfinding creation. Regularly-textured stair geometry (which intersects the marker quad) will be flagged as NoCharacterCollision.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
texture: &#039;&#039;&#039;_marker_impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Transparent TwoSided (&amp;lt;-double-check this) Invisible NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Impassable walls are very similar to collision boxes except that particles can also collide with them. The pathfinding grids will be also red, light green, and green.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Blackness a.k.a. jello fix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_blackness&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: TwoSided NoCollision&lt;br /&gt;
&lt;br /&gt;
Simply black walls. No effect on pathfinding creation. The purpose of these walls in Oni is to block out areas outside of a level&#039;s outermost wall so that the Jello-cam cannot show the player other parts of the level when it escapes a wall. See [[Jello-cam]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Doors&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_door&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: DoorFrame Transparent TwoSided NoCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Don&#039;t use this.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Objects&amp;gt;===&lt;br /&gt;
Information on regular object lists can be looked up here:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
====Furniture.xml====&lt;br /&gt;
The AKEV core geometry is more or less the overall structure of the level while this furniture file adds standard objects (e.g. crates and desks) to it.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| - &lt;br /&gt;
| This tag marks the file as BINACJBO.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Furniture&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| This tag marks the file as FURN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Header&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag. Ignore it. Those flags were used in the past.&lt;br /&gt;
:None&lt;br /&gt;
:Locked&lt;br /&gt;
:PlacedInGame&lt;br /&gt;
:Temporary&lt;br /&gt;
:Gunk&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;OSD&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Class&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to a &#039;&#039;&#039;pre-compiled [[XML:OFGA|OFGA]] (*.oni) file&#039;&#039;&#039;. Use it as part of a relative path. Make sure that the OFGA comes with the files it needs: M3GM and TXMP.&lt;br /&gt;
&lt;br /&gt;
An OFGA can hold multiple M3GMs. That 3D content will then be integrated into the AKEV.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Particle&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| This name gets written into &amp;lt;Tag&amp;gt; inside ONLV (ENVP section) and can be used with BSL commands, e.g. you can take control over a particle via &#039;&#039;&#039;particle BSL_name start&#039;&#039;&#039;. For more commands, see [[XML:BINA/OBJC/PART#BSL_support|HERE]].&lt;br /&gt;
&lt;br /&gt;
Take care with the naming of new OFGA files. The particle name will be composed of 2 parts separated by an &amp;quot;_&amp;quot; underscore. When one tag is empty, the final name will contain an underscore nonetheless. &#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Example&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Objects&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Furniture&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Gunk&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-62.692 -29 108.35&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;181.522 356.021 178.114&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Class&amp;gt;furniture/V_tctf_bigvan.oni&amp;lt;/Class&amp;gt;&lt;br /&gt;
                &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/Furniture&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Objects&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Physics.xml====&lt;br /&gt;
This file is for objects with &amp;quot;physics&amp;quot;. Unlike AKEV core geometry or furniture, these objects can be animated.&lt;br /&gt;
&lt;br /&gt;
: A small video tutorial on [https://www.youtube.com/watch?v=CFNseg_2UxA how to create a simple animated object]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Physics&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Object Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Use a unique name for each object.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Tested with BSL command...&lt;br /&gt;
:obj_create ID [ID]&lt;br /&gt;
:obj_kill ID [ID]&lt;br /&gt;
:env_anim ID [ID]&lt;br /&gt;
:env_setanim ID [ID]&lt;br /&gt;
The scripting ID will be stored in the ONLV&#039;s OBOA instance.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;Object setup flags&lt;br /&gt;
:None&lt;br /&gt;
:InUse&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoGravity&lt;br /&gt;
:FaceCollision&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Physics&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag for an Object.&lt;br /&gt;
:None&lt;br /&gt;
:Static&lt;br /&gt;
:Linear&lt;br /&gt;
:Animated&lt;br /&gt;
:Newton (used with &amp;lt;Flags&amp;gt; FaceCollision to [https://www.youtube.com/watch?v=YICB7qugrtc make an object pushable])&lt;br /&gt;
:: For a pushable object don&#039;t use import sub-tags such as animation name, flags, etc. Just use &amp;lt;Import Path=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt; or &amp;lt;Import Url=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Scale&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects.&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;Import Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Import Url=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| This tag comes in two variants. It doesn&#039;t matter what variant you use.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag of Animation. For more information on those flags look [[XML:OBAN|OBAN]] page.&lt;br /&gt;
&lt;br /&gt;
;Object animation flags&lt;br /&gt;
:None&lt;br /&gt;
:Loop&lt;br /&gt;
:PingPong&lt;br /&gt;
:RandomStart&lt;br /&gt;
:AutoStart&lt;br /&gt;
:Local&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the end of an OBAN from a *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the start of an OBAN from a *.dae file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The XML code for physics can be written in two styles.&lt;br /&gt;
*The &#039;&#039;&#039;first style&#039;&#039;&#039; mimics the original structure found in extracted ONLV instances. This makes it &#039;&#039;&#039;easier to edit old levels and reimport them&#039;&#039;&#039; into the game.&lt;br /&gt;
*The &#039;&#039;&#039;second style&#039;&#039;&#039; was created with structured data (nested objects) in mind and is &#039;&#039;&#039;suited for totally new levels&#039;&#039;&#039; where animated objects must be created in a 3D editor at first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        &amp;lt;Object&amp;gt;&lt;br /&gt;
            &amp;lt;Geometry&amp;gt;M3GMDishBase.oni&amp;lt;/Geometry&amp;gt;&lt;br /&gt;
            &amp;lt;Animation&amp;gt;OBANDishBase.oni&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;Physics&amp;gt;Animated&amp;lt;/Physics&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;201&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Position&amp;gt;-197.729141 128.46283 -2501.46387&amp;lt;/Position&amp;gt;&lt;br /&gt;
            &amp;lt;Rotation&amp;gt;0.7071067 -1.545431E-08 1.545431E-08 0.7071068&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;Scale&amp;gt;2.109375&amp;lt;/Scale&amp;gt;&lt;br /&gt;
            &amp;lt;Name&amp;gt;object_DishBase&amp;lt;/Name&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 2&#039;&#039;&#039;&lt;br /&gt;
:For documentation purposes, the file here has been trimmed down.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Object Name=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;8&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Flags&amp;gt;FaceCollision&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;Import Url=&amp;quot;motorcycle/export.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;AutoStart&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;End&amp;gt;880&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02_stop&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Start&amp;gt;881&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, OniSplit takes the file &amp;quot;export.dae&amp;quot;, looks at the parts it contains, and creates geometry files from it.&lt;br /&gt;
* M3GMhubs_rear.oni&lt;br /&gt;
* M3GMhubs.oni&lt;br /&gt;
* M3GMmotorcycle.oni&lt;br /&gt;
It&#039;s convenient that hierarchies are supported here.&lt;br /&gt;
&lt;br /&gt;
The motorcycle is made of 3 parts so 3 object animations ([[XML:OBAN|OBAN]]) will be created up to frame 880. Then OniSplit creates 3 more OBANs starting from frame 881.&lt;br /&gt;
&lt;br /&gt;
The reason for the interruption at frame 880 is probably to give Barabas a little more camera time in the cutscene.&lt;br /&gt;
&lt;br /&gt;
;Notes about BSL usage:&lt;br /&gt;
&lt;br /&gt;
The Vago Lab cutscene script uses the motorcycle objects and animations like this:&lt;br /&gt;
 	env_show 8 0		# hide static motorcycle parts or else they would be visible&lt;br /&gt;
 	env_show 9 0		# while Konoko is still riding her animated motorcycle&lt;br /&gt;
 	env_show 10 0		# the static motorcycle is separated into objects 8, 9 and 10&lt;br /&gt;
 &lt;br /&gt;
 	# Static and animated objects are totally independent from each other.&lt;br /&gt;
 	# They are stored in different arrays so their script IDs can use the same numbers.&lt;br /&gt;
 &lt;br /&gt;
 	obj_create 8 10		# create all animation-ready motorcycle parts&lt;br /&gt;
 	env_anim 8 10		# animate those parts (not necessary if OBAN flag is &amp;quot;AutoStart&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 	# The first animations would loop because of &amp;quot;AutoStart&amp;quot;, so get the&lt;br /&gt;
 	# right timing to apply the other animations. &amp;quot;motorcycle02_stop&amp;quot;&lt;br /&gt;
 	# and the others will not loop because they don&#039;t have &amp;quot;AutoStart&amp;quot;.&lt;br /&gt;
 	env_setanim 8 hubs_stop&lt;br /&gt;
 	env_setanim 9 hubs_rear_stop&lt;br /&gt;
 	env_setanim 10 motorcycle02_stop&lt;br /&gt;
 &lt;br /&gt;
 	obj_kill 8 10		# delete all animated parts&lt;br /&gt;
 	env_show 9 1		# show static motorcycle model where Konoko parks her bike&lt;br /&gt;
&lt;br /&gt;
====Corpses.xml====&lt;br /&gt;
An empty Corpse element (&amp;lt;Corpse /&amp;gt;) is treated as unused and placed at the end of the array. If no such empty elements are provided, OniSplit automatically adds 5. OniSplit also ensures that there are at least 20 corpses in the array.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Corpses&amp;gt;&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Corpse&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Class&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| [[XML:ONCC|ONCC]]&#039;&#039;name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Transforms&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| There are 19 &amp;lt;Matrix&amp;gt; for each &amp;lt;Transforms&amp;gt; (which represents a body part).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Matrix&amp;gt;&lt;br /&gt;
| matrix&lt;br /&gt;
| Float 3x3 + float x3 for the last 3 values (X Y Z position). For more information about the matrix, see [[OBD:CRSA]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Bounding box of the whole corpse. Optional; if not provided, OniSplit will generate an approximate one. Currently it doesn&#039;t try to locate the ONCC to compute an exact bounding box.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Min&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Max&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Trimmed example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Corpses&amp;gt;&lt;br /&gt;
        &amp;lt;Corpse&amp;gt;&lt;br /&gt;
            &amp;lt;Class&amp;gt;generic_male_1&amp;lt;/Class&amp;gt;&lt;br /&gt;
            &amp;lt;Transforms&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.36488995 0.04620622 -0.9299034 -0.05580434 -0.9980576 -0.02769538 -0.9293768 0.04178688 0.366759717 -215.667755 1.603917 92.85312&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.2961557 -0.185628444 0.936928 -0.368288517 -0.9272724 -0.06730227 0.8812806 -0.32512787 -0.342981815 -216.51889 1.64218426 93.189&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.407847315 0.156575248 0.8995248 -0.238757968 -0.9326179 0.2705892 0.8812805 -0.3251278 -0.342982143 -215.239883 0.8405094 97.23532&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.439697325 0.467113584 0.767118752 0.0248355754 -0.8601105 0.5095029 0.8978026 -0.204975232 -0.389789373 -213.6234 1.46109009 100.80056&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.717241049 -0.179043233 0.673430443 0.4761817 -0.579636 -0.6612664 0.5087397 0.794962764 -0.3304816 -214.81662 1.56564879 92.5172348&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.3398023 0.1672905 0.925498843 0.7910236 -0.5831365 -0.185023025 0.5087395 0.7949628 -0.330481827 -211.71907 0.792413354 95.42558&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.1283634 0.227430075 0.965297 0.804142356 -0.59352535 0.032904774 0.5804117 0.7720126 -0.259073079 -210.372269 1.45546341 99.0937653&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.285799921 0.06851995 -0.955836535 -0.240357026 -0.970681965 0.00228381017 -0.927656651 0.230394751 0.2938901 -216.284851 1.5839076 91.29168&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.312039882 0.04875436 -0.948817253 -0.176752359 -0.9842264 0.00755515043 -0.9334825 0.1700632 0.31573534 -216.689789 1.68287766 89.9359055&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.356412441 -0.5390179 -0.763170958 0.0404523835 -0.82494843 0.5637587 -0.933452547 0.170058519 0.315826446 -217.422012 1.7979821 87.70907&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.101782769 -0.247171819 -0.9636112 0.5426916 -0.8256094 0.154451028 -0.8337422 -0.507223248 0.2181709 -217.747284 1.30605173 87.0125656&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.8154478 -0.150626346 0.558888733 -0.1200991 0.9885643 0.09119747 -0.566234052 0.00724477554 -0.8242127 -217.7402 2.065678 88.15346&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.4593738 -0.326781839 0.825947642 0.8874048 -0.1284554 0.442732215 -0.0385793857 0.9363295 0.348996729 -219.093979 1.81561315 89.08131&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9545983 -0.13777709 0.26412034 0.295387268 -0.322961926 0.899134 -0.0385792255 0.9363296 0.348996431 -220.3681 0.9092429 91.37218&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9715769 -0.0362956524 0.233924776 0.0276728421 -0.9988148 -0.0400396362 0.2351007 -0.0324283168 0.9714299 -222.775482 0.56178683 92.03825&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.979860842 -0.192433611 0.0533096045 0.193336874 0.9810555 -0.0122905634 -0.0499345176 0.0223497637 0.9985025 -216.8387 1.90143847 87.84845&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.863898 -0.399280578 0.3070101 0.171117 -0.340619326 -0.9244986 0.4737078 0.851207137 -0.225936681 -215.211975 1.58196676 87.93695&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.4673251 -0.0255063027 0.883717656 0.746463835 -0.524209559 -0.4098731 0.4737075 0.851207256 -0.225936785 -212.815842 0.47451216 88.78848&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.216871262 -0.007893051 0.976168454 0.3751846 0.9238389 -0.0758833 -0.9012231 0.3827002 0.203315422 -211.637314 0.410188764 91.0171051&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
            &amp;lt;/Transforms&amp;gt;&lt;br /&gt;
            &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
                &amp;lt;Min&amp;gt;-219.731216 -2.258905 84.47974&amp;lt;/Min&amp;gt;&lt;br /&gt;
                &amp;lt;Max&amp;gt;-207.518463 4.49535131 104.023239&amp;lt;/Max&amp;gt;&lt;br /&gt;
            &amp;lt;/BoundingBox&amp;gt;&lt;br /&gt;
        &amp;lt;/Corpse&amp;gt;&lt;br /&gt;
    &amp;lt;/Corpses&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[[Image:ONLV_CRSA_XSI_aided_import.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
:Some related information can be found at [[Authoring custom camera animations]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
For indirect import, see [http://oni.bungie.org/forum/viewtopic.php?id=2657 HERE] (OniTools v7.1.5+) on how to get corpse data.&lt;br /&gt;
&lt;br /&gt;
When you process your XML master file, use OniSplit version 0.9.94.0+. Older OniSplit versions like 0.9.86.0 may generate ONLV files that are not re-packable with newer versions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;(Export)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With Neo&#039;s matrix-to-Euler code, the rotations can be recovered from CRSA. But due to the character&#039;s hierarchy, things get messy again (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/CRSA_to_Mod_Tool_wip.png&amp;lt;/nowiki&amp;gt;, dead link). (WIP code (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/temp/CRSA_to_Mod_Tool.txt&amp;lt;/nowiki&amp;gt;, dead link))&lt;br /&gt;
&lt;br /&gt;
A workaround might be to save characters without animations, destroy their hierarchy, apply the local rotations / global translation and glue everything together again.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
	<entry>
		<id>https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43842</id>
		<title>Creating a level</title>
		<link rel="alternate" type="text/html" href="https://wiki.oni2.net/w/index.php?title=Creating_a_level&amp;diff=43842"/>
		<updated>2025-01-22T03:48:45Z</updated>

		<summary type="html">&lt;p&gt;Vortice: /* Fan-made levels */Fixed broken forum links to archive links.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page covers level creation from scratch. See [[Modifying an existing level]] if you want to change a vanilla level in the game.&lt;br /&gt;
&lt;br /&gt;
==Level releases and resources==&lt;br /&gt;
===Fan-made levels===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable autosort by-column-3&amp;quot;&lt;br /&gt;
!Date&lt;br /&gt;
!Name&lt;br /&gt;
!Level number&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Oni 2 Angel Studios Tour&lt;br /&gt;
|32&lt;br /&gt;
|-&lt;br /&gt;
|TBA&lt;br /&gt;
|Green Room&lt;br /&gt;
|26&lt;br /&gt;
|-&lt;br /&gt;
|2019/09/16&lt;br /&gt;
|[https://web.archive.org/web/20240527004257/http://oniforum.bungie.org/viewtopic.php?id=2965 Omega Tournament]&lt;br /&gt;
|31&lt;br /&gt;
|-&lt;br /&gt;
|2016/02/13&lt;br /&gt;
|[https://web.archive.org/web/20160224173743/http://oni.bungie.org/forum/viewtopic.php?id=2947 AI Battle]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2014/01/19&lt;br /&gt;
|[https://web.archive.org/web/20211202225410/http://oni.bungie.org/forum/viewtopic.php?id=2698 Wilderness Preserve]&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|2013/09/07&lt;br /&gt;
|[https://web.archive.org/web/20201127180732/http://oni.bungie.org/forum/viewtopic.php?id=2656 Island]&lt;br /&gt;
|29&lt;br /&gt;
|-&lt;br /&gt;
|2013/07/12&lt;br /&gt;
|[https://web.archive.org/web/20201127175459/http://oni.bungie.org/forum/viewtopic.php?id=2640 City]&lt;br /&gt;
|28&lt;br /&gt;
|-&lt;br /&gt;
|2013/06/01&lt;br /&gt;
|[https://web.archive.org/web/20201029102326/http://oni.bungie.org/forum/viewtopic.php?id=2619 Fight Club]&lt;br /&gt;
|25&lt;br /&gt;
|-&lt;br /&gt;
|2012/05/12&lt;br /&gt;
|[https://web.archive.org/web/20220701102842/http://oni.bungie.org/forum/viewtopic.php?id=2357 Old China]&lt;br /&gt;
|24&lt;br /&gt;
|-&lt;br /&gt;
|2012/03/18&lt;br /&gt;
|[https://web.archive.org/web/20211202220454/http://oni.bungie.org/forum/viewtopic.php?id=2302 Boss Battle]&lt;br /&gt;
|23&lt;br /&gt;
|-&lt;br /&gt;
|2012/02/12&lt;br /&gt;
|[https://web.archive.org/web/20201029113554/http://oni.bungie.org/forum/viewtopic.php?id=2271 De Dust Deluxe]&lt;br /&gt;
|22&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/23&lt;br /&gt;
|[https://web.archive.org/web/20201029114415/http://oni.bungie.org/forum/viewtopic.php?id=2242 Parkour Challenge 2]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2012/01/16&lt;br /&gt;
|[https://web.archive.org/web/20211205145843/http://oni.bungie.org/forum/viewtopic.php?id=2235 Parkour Challenge]&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/25&lt;br /&gt;
|[https://web.archive.org/web/20201029103607/http://oni.bungie.org/forum/viewtopic.php?id=2001 Mini-Partenon]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2011/10/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113340/http://oni.bungie.org/forum/viewtopic.php?id=2024 Muro&#039;s Lair - Preview]&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|2011/07/03&lt;br /&gt;
|[https://web.archive.org/web/20201029113724/http://oni.bungie.org/forum/viewtopic.php?id=1957 Hexagon]&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|2011/06/23&lt;br /&gt;
|[https://web.archive.org/web/20201029104928/http://oni.bungie.org/forum/viewtopic.php?id=1938 Junkyard]&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|2011/05/01&lt;br /&gt;
|[http://mods.oni2.net/node/178 Arena of Hurt (OZG)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/08&lt;br /&gt;
|[https://web.archive.org/web/20210117150652/http://oni.bungie.org/forum/viewtopic.php?id=1736 Arena of Hurt (OTA)]&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|2010/11/06&lt;br /&gt;
|[https://web.archive.org/web/20201029105217/http://oni.bungie.org/forum/viewtopic.php?pid=50565#p50565 Martian Colony] AKA &amp;quot;Silly World&amp;quot;&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2010/02/15&lt;br /&gt;
|[https://web.archive.org/web/20201029113916/http://oni.bungie.org/forum/viewtopic.php?id=1506 Maze]&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
|2008/09/16&lt;br /&gt;
|[http://mods.oni2.net/node/4 Arena of Pain]&lt;br /&gt;
|30&lt;br /&gt;
|-&lt;br /&gt;
|2024/05/20&lt;br /&gt;
|[https://gamebanana.com/mods/514707 Kitsune: Chapter 1]&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Forum tutorials on level creation===&lt;br /&gt;
* &#039;&#039;&#039;[http://oni.bungie.org/forum/viewtopic.php?id=2087 &amp;quot;Creating the Lair - A level tutorial&amp;quot;]&#039;&#039;&#039;&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?pid=53026 &amp;quot;Creating a Custom Oni Level (s10k video tutorials)&amp;quot;]&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?id=1515 &amp;quot;Creating new levels&amp;quot;]&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?pid=33838 &amp;quot;Create levels with pathfinding grids&amp;quot;]&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?id=2000 &amp;quot;More questions about levels&amp;quot;]&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?pid=37252#p37252 &amp;quot;Modding Existing levels - Beta&amp;quot; (&amp;quot;Moveable furniture&amp;quot; post)]&lt;br /&gt;
&lt;br /&gt;
===Wiki pages on level creation===&lt;br /&gt;
* [[Creating a level]] (you are here)&lt;br /&gt;
* [[Modifying an existing level]]&lt;br /&gt;
* [[New levels]]&amp;lt;!--notes and comments by geyser that should be revisited / merged with this page--&amp;gt;&lt;br /&gt;
* [[Lightmapping levels]]&lt;br /&gt;
&lt;br /&gt;
===Free asset sources===&lt;br /&gt;
* [http://vk.com/gameready Various game meshes]&lt;br /&gt;
* [http://web.archive.org/web/20230601050258/http://tutorialsforblender3d.com/Textures/Textures_index.html Various game textures]&lt;br /&gt;
* [https://www.textures.com Various game textures]&lt;br /&gt;
&lt;br /&gt;
==Engine limitations==&lt;br /&gt;
First you should be aware of the limitations that Oni will place on your level.&lt;br /&gt;
&lt;br /&gt;
* The triangle limit of a game level is approx. 520,000 (consider it 500,000 to be on the safe side).&lt;br /&gt;
* {{ModTool}} can save DAE files with a maximum of 64,000 triangles per object.&lt;br /&gt;
* When polygons are too tightly packed, the camera will look at too many of them and glitches will appear. The limit on visible GQs (Gunk Quads) is 8,192 (2&amp;lt;sup&amp;gt;13&amp;lt;/sup&amp;gt;), and higher numbers will cause render bugs and produce the console error message &amp;quot;Exceeded max visible GQs &#039;&#039;number&#039;&#039;&amp;quot;. There are limited solutions to this:&lt;br /&gt;
** Decrease the &#039;&#039;&#039;gs_farclipplane_set&#039;&#039;&#039; value.&lt;br /&gt;
** Hide objects via &#039;&#039;&#039;[[#.3CModel.3E|env_show]]&#039;&#039;&#039;.&lt;br /&gt;
** Hide objects by &#039;&#039;level design&#039;&#039;. For example, departments in a building could be quite detailed because the view of the other departments/rooms is blocked by walls.&lt;br /&gt;
* The camera can look at 2,049 transparent textures at once; one more, and Oni crashes.&lt;br /&gt;
* Characters are visible &#039;&#039;only&#039;&#039; within world coordinates {-4,099, -4,099, -4,099} to {4,099, 4,099, 4,099}.&lt;br /&gt;
* Geometry stops outside of (roughly) world coordinates -4,228 to 4,228 on the X and Z axes (vertical axis not tested).&lt;br /&gt;
* &#039;&#039;&#039;chr_debug_spheres = 1&#039;&#039;&#039; visualizes the collision spheres of characters, so you can check if they will fit through an entrance.&lt;br /&gt;
&lt;br /&gt;
==3D tools==&lt;br /&gt;
===Problems when using multiple different tools===&lt;br /&gt;
Re-saving a DAE file in &#039;&#039;&#039;Mod Tool&#039;&#039;&#039; which was originally made in &#039;&#039;&#039;SketchUp&#039;&#039;&#039; can result in a surprising change in size within Oni. This is due to a difference in the specification of a scale unit.&lt;br /&gt;
&lt;br /&gt;
: For example, the SketchUp DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.0254000&amp;quot; name=&amp;quot;inch&amp;quot; /&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: And the re-saved Mod Tool DAE file may have: &amp;lt;tt&amp;gt;&amp;lt;unit meter=&amp;quot;0.1&amp;quot; name=&amp;quot;decimetre&amp;quot;&amp;gt;&amp;lt;/unit&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case you&#039;ll need to open the new DAE in a text editor and change the length specification back.&lt;br /&gt;
&lt;br /&gt;
===Sketchup===&lt;br /&gt;
If you are working with Sketchup check out this pages:&lt;br /&gt;
* [http://oni.bungie.org/forum/viewtopic.php?id=2003 &amp;quot;Sketchup tutorials for making levels&amp;quot;]&lt;br /&gt;
* [[SketchUp tutorials and tips]]&lt;br /&gt;
&lt;br /&gt;
===Blender===&lt;br /&gt;
&#039;&#039;&#039;Scaling&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as Mod Tool and SketchUp: Caution with scaling: See [[#Problems when using multiple different tools|here]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pathfinding&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Be sure to uncheck automatic triangle creation when exporting (BNV) geometry used for pathfinding. Ghost (&#039;&#039;doors&#039;&#039;) must be quads. &lt;br /&gt;
&lt;br /&gt;
==Setting up a workflow==&lt;br /&gt;
If not noted differentely you need OniSplit v0.9.82.0 or a newer version. Onisplit can be downloaded [http://mods.oni2.net/node/38 HERE] (it also comes with the [[AE]] and is found in the Tools directory of the installation).&lt;br /&gt;
&lt;br /&gt;
The level import demo files can be downloaded [http://mods.oni2.net/node/299 HERE].&lt;br /&gt;
&lt;br /&gt;
First, put &#039;&#039;&#039;OniSplit.exe&#039;&#039;&#039; into the second &#039;&#039;&#039;lab&#039;&#039;&#039; folder alongside the XML files.&lt;br /&gt;
&lt;br /&gt;
Look at the file &#039;&#039;&#039;build.cmd&#039;&#039;&#039;. These are the two important lines:&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:level out lab.xml&lt;br /&gt;
 OniSplit.exe -import:pc out level3_Final.dat&lt;br /&gt;
&lt;br /&gt;
The first line creates the *.oni files from a master.xml file, in this case &#039;&#039;&#039;lab.xml&#039;&#039;&#039;. Once finalized, the resulting .oni files can be put into a new [[Making a mod package|AE package]].&lt;br /&gt;
&lt;br /&gt;
The second line creates level archives which can be used for fast tests. They don&#039;t require you to install a package through the AE Installer.&lt;br /&gt;
&lt;br /&gt;
Instead of &amp;quot;-nosep&amp;quot; you can now also use &amp;quot;-pc&amp;quot; for the import. Macs, however, do use &amp;quot;-sep&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
If the game crashes while loading at ~90% progress, be sure that the texture&#039;s x and y dimensions are powers of two: 64, 128, 256, 512….&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading at ~50-60% progress, be sure that the BINACJBOCharacters or AISA file has a player character defined.&lt;br /&gt;
&lt;br /&gt;
If the game crashes while loading ~5-10% progress, check if all your textures were inside the &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
:You can extract the AKEV file to XML, then search for the [[XML:AKEV#TXMA|TXMP Array]].&lt;br /&gt;
&lt;br /&gt;
:[http://mods.oni2.net/system/files/AKEV_texture_checker.txt THIS] script checks which textures are missing by comparing the AKEV*.xml with its *.oni files folder. Change the two paths so that it works for you: Alt+4, insert code, then F5.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;TXMP_marker_door&amp;quot; and &amp;quot;TXMP_marker_ghost&amp;quot; will be missing in the demo&#039;s &amp;quot;out&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
You can add this between the other two lines in build.cmd to prevent a crash.&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
;Polygon&lt;br /&gt;
:A polygon is a shape defined by points (vertices) in space. Polygons are the most fundamental building block in games. Oni uses only shapes with 3 and 4 points (triangles and quads). Other games might also use N-gons, shapes with more points.&lt;br /&gt;
;Face&lt;br /&gt;
:The &#039;&#039;&#039;surface of a polygon&#039;&#039;&#039; is also named face. The &#039;&#039;&#039;direction&#039;&#039;&#039; of a face in &#039;&#039;&#039;defined by its normal&#039;&#039;&#039;. If an object seems to have a hole, it might be that the polygon just has a &#039;&#039;&#039;flipped normal&#039;&#039;&#039; and is therefore wrongly rendered (displayed on screen).&lt;br /&gt;
;Normal&lt;br /&gt;
:Faces and even vertices themselves have directions. The normals of vertices determine how smooth or sharp edges will appear.&lt;br /&gt;
;Vertex (plural&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt; vertices)&lt;br /&gt;
:A point within a polygon.&lt;br /&gt;
:Vertex colors radiate from one vertex to another vertex, whereby their different color values blend into each other so that gradients can appear. &lt;br /&gt;
;Edge&lt;br /&gt;
:A line of two points within a polygon.&lt;br /&gt;
;Tris (triangles)&lt;br /&gt;
:Polygons made of 3 points.&lt;br /&gt;
;Quads&lt;br /&gt;
:Polygons made of 4 points. Planes. Rectangles.&lt;br /&gt;
:Internally, all quads get converted into two triangles and will affect the maximum triangle count accordingly.&lt;br /&gt;
;Level&lt;br /&gt;
:The term &amp;quot;level&amp;quot; is often used to shorten &amp;quot;level map&amp;quot; (buildings and terrain).&lt;br /&gt;
;Geometry&lt;br /&gt;
:Level geometry can be objects made of tris and/or quads.&lt;br /&gt;
:Oni differentiates between basically 3 types of level geometry:&lt;br /&gt;
:* Static objects (sometimes also named AKEV core geometry)&lt;br /&gt;
:* Animated objects&lt;br /&gt;
:* Pushable objects (not used in the original game)&lt;br /&gt;
;Static geometry&lt;br /&gt;
:* &#039;&#039;&#039;Unique level geometry with no functions&#039;&#039;&#039; (AKEV core geometry such as buildings and streets).&lt;br /&gt;
:* &#039;&#039;&#039;Repeating objects&#039;&#039;&#039; are flagged as &#039;&#039;&#039;furniture (FURN)&#039;&#039;&#039; although they can be outdoor objects such as boxes and containers. &amp;lt;!--Oni&#039;s story plays out most often inside buildings. So, there you go. --&amp;gt;FURN objects were used to be imported by an object collection, an CJBO. Nowadays, furniture collections can be used (again) for imports, but the individual objects are stored as OFGA files. This modularity is known in many game editors (like the Unreal Engine Editor). So, &#039;&#039;&#039;OFGA are nothing else than &amp;quot;game assets&amp;quot;.&#039;&#039;&#039; The drawback of OFGA is that they &#039;&#039;&#039;will not import with any vertex shading&#039;&#039;&#039;. Only their &#039;&#039;&#039;geometries&#039;&#039;&#039;, attached &#039;&#039;&#039;particle&#039;&#039;&#039; and &#039;&#039;&#039;gunk flags&#039;&#039;&#039; get copied into final (baked) level geometry.&lt;br /&gt;
:* &#039;&#039;&#039;Objects with actual functions&#039;&#039;&#039; (CJBO such as doors, consoles, triggers)&lt;br /&gt;
:** Some types of CJBO (spawn lists of weapons, characters, powerups and of course flags and patrol paths) are not considered as level geometry.&lt;br /&gt;
;[[XML:AKEV#AGQG|Gunk flags]]&lt;br /&gt;
:Properties directly associated with the polygons. Among others, these can be: Transparent, TwoSided, NoCollision, Invisible, NoObjectCollision, NoCharacterCollision, NoDecals, Furniture, Impassable.&lt;br /&gt;
;Baking&lt;br /&gt;
:When a level gets baked, all geometries get merged.&lt;br /&gt;
:*Unique level geometry will have vertex painting.&lt;br /&gt;
:*Objects derived from already compiled oni-files (shared classes) will have no vertex painting.&lt;br /&gt;
:*Animated and pushable objects will have no vertex shading.&lt;br /&gt;
;Vertex shading&lt;br /&gt;
:Vertex colors (vector data) can be painted onto core geometry.&lt;br /&gt;
:They are used as a rudimentary form of lightmapping (pixel data).&lt;br /&gt;
:Having vertex shading is still better than having no vertex shading at all. It makes the level appear more lifelike.&lt;br /&gt;
;Lightmapping&lt;br /&gt;
:In other games, lights and shadows are added to level geometry with lightmapping.&lt;br /&gt;
:There were experiments to bring lightmaps back to Oni. The technique come with a major drawback though. It doubles the triangle count and adds many textures.&lt;br /&gt;
;In-game&lt;br /&gt;
:When you are &amp;quot;inside&amp;quot; the game, running or playing it.&lt;br /&gt;
&lt;br /&gt;
==Level construction==&lt;br /&gt;
&#039;&#039;&#039;Visible environment&#039;&#039;&#039;&lt;br /&gt;
* A &#039;&#039;&#039;level map&#039;&#039;&#039; consists of visible geometry: terrain and buildings. This is also named the &#039;&#039;&#039;environment&#039;&#039;&#039; or for short &#039;&#039;&#039;env&#039;&#039;&#039;.&lt;br /&gt;
** Use &#039;&#039;&#039;quads&#039;&#039;&#039; of approximately 10 up to 20 meters in size to construct env geometry.&lt;br /&gt;
* Anything other than floors and simple walls will be made of triangles.&lt;br /&gt;
** Geometry from CJBO works best with triangles. Quads might show holes in-game.&lt;br /&gt;
&#039;&#039;&#039;Invisible pathfinding&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;AIs&#039;&#039;&#039; (or non-player characters, NPCs) need &#039;&#039;&#039;pathfinding&#039;&#039;&#039; data, usually shortened as &#039;&#039;&#039;bnv&#039;&#039;&#039;.&lt;br /&gt;
** Pathfinding data can be described as geometry, therefore as rooms. These &#039;&#039;&#039;bnv rooms&#039;&#039;&#039; are made of &#039;&#039;&#039;floors&#039;&#039;&#039; and are connected by &#039;&#039;&#039;ghost&#039;&#039;&#039; quads which work like doors. AIs can move from one room to another room only by passing a ghost. Therefore, ghosts have the same width as rooms in open terrain.&lt;br /&gt;
*** Use floor quads of approximately 10 meters in size to construct BNV floors.&lt;br /&gt;
*** Put ghost quads exactly on the edges of BNV floors with an angle of 90 degree.&lt;br /&gt;
&#039;&#039;&#039;Support for [[XML:BINA/ONIE|effects]]&#039;&#039;&#039;&lt;br /&gt;
* Effects such as decals that indicate damaged environment need level textures to be registered in [[XML:BINA/TMBD|TMBD]]. Make sure not to replace existing texture entries but to add your own so that the other levels remain unaffected.&lt;br /&gt;
&#039;&#039;&#039;Level logic&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BSL scripts bring levels fully to life. The logic is mostly event driven whereby different checkpoints and conditions must be reached.&lt;br /&gt;
* Checkpoints are actually [[XML:BINA/OBJC/TRGV|trigger volumes]] that can recognize entering and exiting characters.&lt;br /&gt;
* The second most important source of events are [[XML:BINA/OBJC/CHAR|character (script) functions]], especially the die function of enemies.&lt;br /&gt;
** To support good and less good players alike, NPC characters can feature the UpgradeDifficulty flag. Also, BSL scripts can detect the current [[BSL:Game_status|difficulty level]].&lt;br /&gt;
* [[XML:BINA/OBJC/TRIG|Laser triggers]] are mostly used to control [[XML:BINA/OBJC/TURR|turrets]]. [[XML:BINA/OBJC/CONS|Consoles]], triggers and [[XML:DOOR|door]] unlocking are used to set up very simple &amp;quot;riddles”.&lt;br /&gt;
* The creation of cut scenes is time-consuming quality work. Due to missing tools for streamlined workflows, it is totally okay for you to skip this.&lt;br /&gt;
** New synchronized FILM, OBAN and TRAM files are required for cut scenes. Not to mention sound files for dialog.&lt;br /&gt;
&lt;br /&gt;
==The master XML file==&lt;br /&gt;
&#039;&#039;The project file for level creation.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;master XML&#039;&#039;&#039; file&#039;s &#039;&#039;&#039;name determines&#039;&#039;&#039; the &#039;&#039;&#039;BSL folder name&#039;&#039;&#039; and the &#039;&#039;&#039;AKEV and ONLV file names&#039;&#039;&#039; in the output folder. File paths in the XML can be either absolute or relative.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mandatory files&#039;&#039;&#039; for level import:&lt;br /&gt;
* &#039;&#039;level_environment&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_bnv&#039;&#039;.dae&lt;br /&gt;
* &#039;&#039;level_textures.tga/jpg/png&#039;&#039;&lt;br /&gt;
* Character.xml or AISA with player&lt;br /&gt;
* ONSK name in &amp;lt;Sky&amp;gt; (in Windows, this can be a fake name; does the Mac need actual ONSK files?)&lt;br /&gt;
* ONLD file for the new level; read [[Making_a_mod_package#Mod_Info.cfg|HERE]] about making sure your level is unlocked (accessible on the Load Game screen)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Level SharedPath=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| The master XML file can link to other XML files. Most of them will be [[OBD:BINA/OBJC#OBJC_types|BINACJBO]] files. The file type is declared inside the file, so the file name itself doesn&#039;t have to contain the type. Ergo, &amp;quot;BINACJBOCharacter.xml&amp;quot; can be given a simpler name like &amp;quot;Character.xml&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some resources used by those XML files can be found in a &#039;&#039;&#039;shared&#039;&#039;&#039; folder. OniSplit copies textures and &amp;quot;physics&amp;quot; objects into the output folder; furniture objects will be integrated into the AKEV. Unused resources in the shared folder will be ignored. That way the final level archive or AE package contains only the necessary files, saving disk space for the end user.&lt;br /&gt;
&lt;br /&gt;
In the demo are various subfolders in the &#039;&#039;&#039;shared&#039;&#039;&#039; folder: consoles, doors, furniture, triggers and turrets. These file types do not need their file prefixes: CONS, DOOR, TRIG and OFGA. OniSplit will recognize them nonetheless.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Common mistake:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CJBO files &#039;&#039;&#039;need relative paths to the resource instead of just file names&#039;&#039;&#039;. Taking consoles, for example: a standard export to XML gives you &amp;quot;console_data&amp;quot;. But to use the shared resources these must be paths like &amp;quot;&#039;&#039;&#039;consoles/console_data.oni&#039;&#039;&#039;&amp;quot; as they are stored in &#039;&#039;&#039;shared/console/&#039;&#039;&#039;. Note how the demoed &#039;&#039;&#039;shared&#039;&#039;&#039; folder is placed next to the [http://mods.oni2.net/node/299 project (&amp;quot;lab&amp;quot;)] folder and the XML master file points to it using &amp;quot;../shared&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Environment&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Model&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Used to import level geometry and static objects. See [[#&amp;lt;Model&amp;gt;|HERE]] for detailed information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Node Id=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| informational (space for notes)&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Can be used with BSL commands such as ...&lt;br /&gt;
: [[#&amp;lt;Model&amp;gt;|env_show ID 1]] (use 0 to hide)&lt;br /&gt;
: [[#Breakable glass with BSL recognition|env_broken ID1 [ID2]]] (if a second ID is supplied then objects in the range ID1..ID2 get counted; &amp;quot;3001 3018&amp;quot; would cover 18 objects)&lt;br /&gt;
: [[#Texture exchange|env_texswap ID texture]] (no file prefix/suffix allowed)&lt;br /&gt;
: [[#env_shade|env_shade ID ID R G B]]&lt;br /&gt;
Static objects store their ID in [[XML:AKEV#IDXA_.28quad_group_id.29|one of AKEV&#039;s IDXA instances]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Rooms&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| For detailed information see [[#&amp;lt;Rooms&amp;gt;|HERE]].&lt;br /&gt;
&lt;br /&gt;
For a Google SketchUp BNV tutorial see [http://oni.bungie.org/forum/viewtopic.php?pid=36760#p36760 HERE].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import Path=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. BNV data, used to create pathfinding.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Textures&amp;gt; {{Anchor|textures_tag}}&lt;br /&gt;
| -&lt;br /&gt;
| With OniSplit v0.9.94.0+ you can use attributes to set the default import formats and max dimensions. For example:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Textures with a dimension that isn&#039;t a power of two (2&amp;lt;sup&amp;gt;x&amp;lt;/sup&amp;gt;) and textures larger than 512px on a side will be resized. For example, 2003x2000 will become 512x512. (What would 257x255 become?)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Texture Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| TXMP file name to generate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Flags&amp;gt;&lt;br /&gt;
| flag&lt;br /&gt;
| Optional tag. For list of flags see [[XML:TXMP|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Format&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
:DXT1&lt;br /&gt;
:BGR&lt;br /&gt;
:RGBA&lt;br /&gt;
:BGR555&lt;br /&gt;
:BGRA5551&lt;br /&gt;
:BGRA4444&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;GunkFlags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;AGQG (Gunk) flags (trimmed list)&lt;br /&gt;
see &#039;&#039;OniSplit -help enums&#039;&#039; for more flags&lt;br /&gt;
:None&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoObjectCollision&lt;br /&gt;
:NoCharacterCollision&lt;br /&gt;
:NoDecal&lt;br /&gt;
:TwoSided&lt;br /&gt;
:Invisible&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Image&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.tga/jpg file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Sky&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| ONSKfile.oni (without file pre- and suffix)&lt;br /&gt;
&lt;br /&gt;
The import doesn&#039;t work with an empty tag. &amp;lt;Sky&amp;gt;clear&amp;lt;/Sky&amp;gt; helps here; any other fictional name will also do.&lt;br /&gt;
&lt;br /&gt;
For detailed information see [[XML:ONSK|HERE]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Import&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to an OBJC (collection) file. Supported collection files for &amp;lt;Import&amp;gt; are:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[#Furniture.xml|Furniture.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[#Physics.xml|Physics.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
The following two collection files are &#039;&#039;&#039;NOT&#039;&#039;&#039; supported. You need to copy them as regular pre-compiled *.oni files into your mod package:&lt;br /&gt;
: [[XML:BINA/OBJC/MELE|Melee.xml]] (overrides global MELE; not used in vanilla levels)&lt;br /&gt;
: [[XML:BINA/OBJC/CMBT|Combat.xml]] (overrides global CMBT?; not used in vanilla levels)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Inside&#039;&#039;&#039; the following three supported collection files, provide links to pre-compiled (*.oni) class files: console, door and furniture collections. Use relative paths such as:&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;consoles/&#039;&#039;&#039;console_data&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;doors/&#039;&#039;&#039;TCdouble&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:: &amp;lt;code&amp;gt;&#039;&#039;&#039;furniture/&#039;&#039;&#039;V_tctf_bigvan&#039;&#039;&#039;.oni&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you are unsure about the folder structure refer back to the [http://mods.oni2.net/node/299 level import demo].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Films&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Import&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.xml file. OniSplit creates a [[XML:FILM|FILM]] file from it. Used for characters in cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Cameras&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Camera Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file. OniSplit creates an OBAN file from it. Used for cutscenes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;/&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Name for the OBAN file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a trimmed-down version of the master file &#039;&#039;&#039;lab.xml&#039;&#039;&#039; from the demo. It&#039;s meant to give you a first impression. We might upload a smaller demo someday with all features nonetheless.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Level SharedPath=&amp;quot;../shared&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Environment&amp;gt;&lt;br /&gt;
            &amp;lt;Model&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bomber_window.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;/Model&amp;gt;&lt;br /&gt;
            &amp;lt;Rooms&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Rooms&amp;gt;&lt;br /&gt;
            &amp;lt;Textures&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;bgra4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
            &amp;lt;/Textures&amp;gt;&lt;br /&gt;
        &amp;lt;/Environment&amp;gt;&lt;br /&gt;
        &amp;lt;Sky&amp;gt;sunset&amp;lt;/Sky&amp;gt;&lt;br /&gt;
        &amp;lt;Objects&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Character.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Furniture.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;TriggerVolume.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;Physics.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Objects&amp;gt;&lt;br /&gt;
        &amp;lt;Films&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun01.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
            &amp;lt;Import&amp;gt;films/BomberKonRun02.xml&amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Films&amp;gt;&lt;br /&gt;
        &amp;lt;Cameras&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam01.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam01&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
            &amp;lt;Camera Path=&amp;quot;cameras/BomberCam02.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;BomberCam02&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;/Camera&amp;gt;&lt;br /&gt;
        &amp;lt;/Cameras&amp;gt;&lt;br /&gt;
    &amp;lt;/Level&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Model&amp;gt;===&lt;br /&gt;
This tag is mandatory (it must be present to avoid errors); the model section contains one import path to the AKEV (level) geometry (*.dae) and can contain additional import paths for exceptions (*.dae).&lt;br /&gt;
&lt;br /&gt;
Data from the demo:&lt;br /&gt;
&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_env.dae&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;Import Path=&amp;quot;env/lab_motorcycle.dae&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Node Id=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;ScriptId&amp;gt;9&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
                        &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;/Node&amp;gt;&lt;br /&gt;
                &amp;lt;/Import&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;env_show&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The motorcycle has here scripting ID 9. You can show and hide the object with the BSL command &#039;&#039;&#039;env_show&#039;&#039;&#039;, where the second parameter means true or false. &#039;&#039;&#039;Never use 0 as an ID&#039;&#039;&#039; because it won&#039;t work.&lt;br /&gt;
&lt;br /&gt;
 env_show 9 1&lt;br /&gt;
 env_show 9 0&lt;br /&gt;
&lt;br /&gt;
EdT demonstrates env_show [https://www.youtube.com/watch?v=Em6wa5JTQNM here]. Note how the objects have collision.&lt;br /&gt;
&lt;br /&gt;
The last vanilla level (Syndicate Mountain Compound) has a big satellite dish platform that can be made hidden. Obviously, such objects/areas can be made to have pathfinding too.&lt;br /&gt;
&lt;br /&gt;
;More possible applications of env_show:&lt;br /&gt;
* ground/ceiling/objects for cutscenes that become partially destroyed&lt;br /&gt;
* destructible walls like in Deus Ex: Human Revolution (trigger volume, replacing punch anim with punch-through-wall anim)&lt;br /&gt;
* grids in front of ventilation shafts (a small door object could be an alternative)&lt;br /&gt;
** at the moment this can&#039;t be done because characters can&#039;t sneak under the top edge of the opening (the characters collision spheres are too big)&lt;br /&gt;
* managing object groups with trigger volumes (save multiple objects in one DAE file)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- atm, the effort is not worth the work&lt;br /&gt;
&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/TV_triggered_env_show.png&amp;lt;/nowiki&amp;gt; (dead link)&lt;br /&gt;
: edit: replace 0 by 25&lt;br /&gt;
&lt;br /&gt;
If the objects appear to flicker then we could replace the hide_all_object_groups() function with individual TV exit functions.&lt;br /&gt;
&lt;br /&gt;
 func hide_all_object_groups&lt;br /&gt;
 {&lt;br /&gt;
 	# env_show id [1|0]&lt;br /&gt;
 	env_show 1 0&lt;br /&gt;
 	env_show 2 0&lt;br /&gt;
 	# ...&lt;br /&gt;
 	env_show 25 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func show_object_group (int grpA, int grpB, int grpC, int grpD, int grpE, int grpF, int grpG, int grpH)&lt;br /&gt;
 {&lt;br /&gt;
 	env_show (grpA, 1)&lt;br /&gt;
 	env_show (grpB, 1)&lt;br /&gt;
 	env_show (grpC, 1)&lt;br /&gt;
 	env_show (grpD, 1)&lt;br /&gt;
 	env_show (grpE, 1)&lt;br /&gt;
 	env_show (grpF, 1)&lt;br /&gt;
 	env_show (grpG, 1)&lt;br /&gt;
 	env_show (grpH, 1)&lt;br /&gt;
 &lt;br /&gt;
 	# missing arguments are taken to be 0&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_25_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 &lt;br /&gt;
 	# show object group of entered TV and of neighboring TVs&lt;br /&gt;
 	# (center, north, north east, east, east south, south, south west, west, west north)&lt;br /&gt;
 	# there&#039;s a limit of 8 arguments per function&lt;br /&gt;
 	show_object_group 25 1 2 3 4 5 6 7&lt;br /&gt;
 	show_object_group 8&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # other examples&lt;br /&gt;
 func TV_6_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 0 0 00 0 00 00 00 00&lt;br /&gt;
 	show_object_group 22&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func TV_20_enter&lt;br /&gt;
 {&lt;br /&gt;
 	hide_all_object_groups&lt;br /&gt;
 	show_object_group 20 21 6 19&lt;br /&gt;
 }&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Import of object groups====&lt;br /&gt;
&#039;&#039;&#039;Mod Tool versus SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The meaning and behavior of &amp;quot;groups&amp;quot; greatly differs in these two programs.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In SketchUp&#039;&#039;&#039; you can group objects which enables you to easily duplicate all objects inside a group and to scale/rotate/translate them all together.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;In Mod Tool&#039;&#039;&#039; grouped objects are still loose, and duplicating a group won&#039;t duplicate the objects. To achieve the same effect as in SketchUp, you have to create a hierarchy where any one object is the &amp;quot;parent&amp;quot; and all others the &amp;quot;children&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Google SketchUp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a group, select two or more objects, right-click on the selection and choose &amp;quot;make group&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:ModTool_can_import_objs_in_hierarchies.jpg|right|thumb|Mod Tool can import objects in hierarchies to Oni.]]&lt;br /&gt;
&#039;&#039;&#039;Mod Tool&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either use the Explorer (A) or the Schematics (B) to create a hierarchy.&lt;br /&gt;
&lt;br /&gt;
:(A) In the Explorer window, drag and drop one or more objects onto another one.&lt;br /&gt;
&lt;br /&gt;
:(B) Open the constrain tab at the right side. Select parent object, click &amp;quot;Parent&amp;quot;, click the child object(s). Check the result in the Schematics window.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Mod Tool: caution when saving to DAE!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:A normal selection won&#039;t do. You have to select the object tree to successfully save a hierarchy. This is the same way that you do it with Oni characters.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=====Import of smart object groups=====&lt;br /&gt;
Let&#039;s say there are two groups. If an edit is made to one mesh, the clone in the other group is instantly changed the same way.&lt;br /&gt;
&lt;br /&gt;
So that&#039;s a smart group. In SketchUp this is named &amp;quot;component&amp;quot;. In Mod Tool it&#039;s named ???.&lt;br /&gt;
:(Can be imported from SketchUp DAE file but causes a crash when re-saving. I guess a script is needed to do the job.)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Breakable glass with BSL recognition====&lt;br /&gt;
Broken environmental objects can be recognized by the BSL command &#039;&#039;env_broken (ID_1, ID_N)&#039;&#039;. However, this requires additional code to work.&lt;br /&gt;
&lt;br /&gt;
An example is the training level. Let&#039;s determine how we can set up such a thing.&lt;br /&gt;
&lt;br /&gt;
First we need a [[XML:BINA/OBJC/TRGV|trigger volume]] like in level 1.&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;TRGV Id=&amp;quot;11495&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Locked&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-714.6615 -298 -555.2073&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;0 0 0&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Name&amp;gt;tv75&amp;lt;/Name&amp;gt;&lt;br /&gt;
                &amp;lt;Scripts&amp;gt;&lt;br /&gt;
                    &amp;lt;Entry&amp;gt;&amp;lt;/Entry&amp;gt;&lt;br /&gt;
                    &amp;lt;Inside&amp;gt;targets_gone&amp;lt;/Inside&amp;gt;&lt;br /&gt;
                    &amp;lt;Exit&amp;gt;&amp;lt;/Exit&amp;gt;&lt;br /&gt;
                &amp;lt;/Scripts&amp;gt;&lt;br /&gt;
                &amp;lt;Teams&amp;gt;255&amp;lt;/Teams&amp;gt;&lt;br /&gt;
                &amp;lt;Size&amp;gt;400 31 270&amp;lt;/Size&amp;gt;&lt;br /&gt;
                &amp;lt;TriggerVolumeId&amp;gt;75&amp;lt;/TriggerVolumeId&amp;gt;&lt;br /&gt;
                &amp;lt;ParentId&amp;gt;0&amp;lt;/ParentId&amp;gt;&lt;br /&gt;
                &amp;lt;Notes&amp;gt;&amp;lt;/Notes&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;PlayerOnly&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/TRGV&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need some BSL code.&lt;br /&gt;
&lt;br /&gt;
 var int inside_target_function;&lt;br /&gt;
 &lt;br /&gt;
 func void enter_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint enter_target_function&lt;br /&gt;
    inside_target_function = 1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void exit_target_function(void)&lt;br /&gt;
 {&lt;br /&gt;
    dprint exit_target_function&lt;br /&gt;
    inside_target_function = 0;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_are_not_gone(void)&lt;br /&gt;
 {&lt;br /&gt;
 	# CB: turn off the trigger volume and sleep for a second&lt;br /&gt;
 	# so as not to cause hideous performance loss&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	sleep 60&lt;br /&gt;
 	trigvolume_enable tv75 1&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func void targets_gone(string ai_name)&lt;br /&gt;
 {&lt;br /&gt;
 	if (inside_target_function eq 0)&lt;br /&gt;
 	{	&lt;br /&gt;
 		enter_target_function() # catch other &amp;quot;targets_gone&amp;quot; functions to let them do nothing&lt;br /&gt;
 &lt;br /&gt;
 		var int num_broken = env_broken(3001, 3018);&lt;br /&gt;
 		# if you only one target use scheme: env_broke(3001, 3001)&lt;br /&gt;
 &lt;br /&gt;
 		if (num_broken eq 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_gone();&lt;br /&gt;
 		}&lt;br /&gt;
 	&lt;br /&gt;
 		if (num_broken &amp;lt; 18)&lt;br /&gt;
 		{&lt;br /&gt;
 			targets_are_not_gone(); # to set check interval to one second&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		exit_target_function&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 func targets_are_gone&lt;br /&gt;
 {&lt;br /&gt;
 	trigvolume_enable tv75 0&lt;br /&gt;
 	# [...]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
;Explanation:&lt;br /&gt;
&lt;br /&gt;
Player enters the TV, targets_gone() gets triggered. The variable &amp;quot;inside_target_function&amp;quot; should be 0 by default, so we will enter the &amp;quot;if&amp;quot; block. Next, we can assume that the player didn&#039;t destroy all glass objects, so &amp;quot;num_broken&amp;quot; will be less than 18; thus, targets_are_not_gone() gets called.&lt;br /&gt;
&lt;br /&gt;
The TV function targets_gone() &#039;&#039;would&#039;&#039; be triggered every frame, but targets_are_not_gone() creates a delay between checks: the TV gets deactivated for 60 frames. Then the TV becomes enabled again and will start anew until all glass objects got destroyed or player left the TV.&lt;br /&gt;
&lt;br /&gt;
In this case the targets_gone() function will do nothing because &amp;quot;inside_target_function&amp;quot; was set to 1 by the first call.&lt;br /&gt;
&lt;br /&gt;
targets_are_gone() eventually disables the TV to prevent memory overflow; this function also contains all the things (&amp;quot;[...]&amp;quot;) that you want to happen after the glass target is broken.&lt;br /&gt;
&lt;br /&gt;
====Texture exchange====&lt;br /&gt;
BSL command supported on Windows and Mac:&lt;br /&gt;
: env_texswap ID texture&lt;br /&gt;
&lt;br /&gt;
Might be useful to switch on/off static and animated textures. (News broadcast screen: running or off or smashed. Lava stream: flowing or stagnating or cooled down. Etc.)&lt;br /&gt;
&lt;br /&gt;
A similar effect can be achieved by showing/hiding geometries with different textures as EdT has demonstrated in a private test. That way it should also be possible to have different vertex coloring for an area.&lt;br /&gt;
&lt;br /&gt;
====Vertex coloring====&lt;br /&gt;
Vertex colors can be edited manually in Blender by setting up following 3 things:&lt;br /&gt;
* Properties Panel &amp;gt; Data &amp;gt; Color Attributes&amp;lt;!--only tested with Face Corner, Byte Color--&amp;gt;&lt;br /&gt;
* 3D viewport (left top) &amp;gt; change work mode to Vertex Paint&lt;br /&gt;
* 3D viewport (right top) &amp;gt; change to Viewport Shading to Solid mode (under the dropdown menu you can choose &amp;quot;flat&amp;quot; to have full saturation)&lt;br /&gt;
&lt;br /&gt;
{{divhide|Mod Tool}}&lt;br /&gt;
&lt;br /&gt;
[http://web.archive.org/web/20170529111607/http://softimage.wiki.softimage.com/xsidocs/tex_vcolor_CreatingColoratVerticesCAVMaps.htm SoftImage documentation.] Observation: The sniper tower from level 19 Syndicate Mountain Compound can be isolated and re-imported as it is. It will appear quite dark.&lt;br /&gt;
&lt;br /&gt;
If we remove &amp;quot;_color&amp;quot; from the object, the shadows will be gone next time we import the tower.&lt;br /&gt;
&lt;br /&gt;
Mod Tool: Explorer [8]&lt;br /&gt;
&lt;br /&gt;
 Object&lt;br /&gt;
  |&lt;br /&gt;
  +-- Polygon Mesh&lt;br /&gt;
        |&lt;br /&gt;
        +-- Cluster&lt;br /&gt;
              |&lt;br /&gt;
              +-- Polygon&lt;br /&gt;
              |     |&lt;br /&gt;
              |     +-- [...]&lt;br /&gt;
              |&lt;br /&gt;
              +-- NodeProperties&lt;br /&gt;
                    |&lt;br /&gt;
                    +-- &#039;&#039;&#039;_color&#039;&#039;&#039;&lt;br /&gt;
                    +-- texcoord (Explicit UVWs)&lt;br /&gt;
                          |&lt;br /&gt;
                          +-- Vertex_Color_Def&lt;br /&gt;
&lt;br /&gt;
So, how do we modify that data?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Single object shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If there&#039;s already a vertex color property, you can use Shift + W to activate the Paint Vertex Color Tool. With Control + W you can change the brush color. R + Hold Click + Move Mouse let you change the brush size. The more vertices (points) you have, the more detailed you can make the shadows/colors. But keep in mind that too many polygons can destroy collision, making characters fall through the ground.&lt;br /&gt;
&lt;br /&gt;
If there&#039;s no vertex color property, the first usage of Shift + W will create that property. But you can also manually create it via Property &amp;gt; Color under Vertices Map.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Level-wide shading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:light_test_modtool.png|right|thumb]]&lt;br /&gt;
[[Image:light_test_ingame.png|right|thumb]]&lt;br /&gt;
&lt;br /&gt;
To get general shading/lighting you can set up light sources. &amp;quot;Infinite&amp;quot; lights are useful for global lighting, while &amp;quot;Light Box&amp;quot;, &amp;quot;Point&amp;quot;, &amp;quot;Neon&amp;quot; and &amp;quot;Spot&amp;quot; are more suitable as local light sources. They can be accessed via Primitives &amp;gt; Light.&lt;br /&gt;
&lt;br /&gt;
By default, a Mod Tool scene has one Infinite light, but it doesn&#039;t shine in every direction so you might want to add more Infinite lights. Let&#039;s say one Infinite light for each direction (+X, -X, +Y, -Y, +Z, -Z) with an intensity of circa 0.25 (night) or 0.75 (day).&lt;br /&gt;
&lt;br /&gt;
The illumination of those lights can be integrated into the vertex color property. There&#039;s some information [http://oni.bungie.org/forum/viewtopic.php?pid=29089#p29089 on OCF here]; the quoted information is in triplicate, so don&#039;t get confused by that: at first it&#039;s detailed, then summarized, then as a checklist.&lt;br /&gt;
&lt;br /&gt;
Basically, you can go with the checklist:&lt;br /&gt;
&lt;br /&gt;
* Property &amp;gt; Color At Vertices Map&lt;br /&gt;
* Property &amp;gt; Render Map&lt;br /&gt;
* In render map property page, under Sampling select Vertices Only&lt;br /&gt;
* Under Surface Color, choose Enable, then in the box below select Vertex _Color; if that option does not appear, click on the New button next to it&lt;br /&gt;
* Under Map, select Illumination only&lt;br /&gt;
* Finally, click on the button Regenerate Maps...&lt;br /&gt;
&lt;br /&gt;
This must be done for all objects separately.&lt;br /&gt;
&lt;br /&gt;
: [http://mods.oni2.net/system/files/vertex_color_script.txt There&#039;s a script here]&amp;lt;!--http://mods.oni2.net/node/352--&amp;gt; which can apply vertex color and render maps to all &#039;&#039;&#039;selected&#039;&#039;&#039; objects. Load it into the script editor with Alt + 4 and hit F5 to run it. (Be sure the script&#039;s language was set to VBScript.)&lt;br /&gt;
: The variable &amp;quot;overwrite_VC&amp;quot; can be changed.&lt;br /&gt;
:: With &amp;quot;1&amp;quot; all existing CAV maps of selected objects will be overwritten. This can take some time.&lt;br /&gt;
:: With &amp;quot;0&amp;quot; only selected objects without CAV maps will be the script&#039;s target.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes on ModTool view modes&#039;&#039;&#039;&lt;br /&gt;
* &amp;quot;Constant&amp;quot; let you see the colors of the vertex coloring only.&lt;br /&gt;
* &amp;quot;Textured Decal&amp;quot; let you see object textures only.&lt;br /&gt;
* &amp;quot;Shaded&amp;quot; let you see the illumination only.&lt;br /&gt;
* &amp;quot;Textured&amp;quot; let you see the textured object with illumination and vertex coloring.&lt;br /&gt;
{{divhide|end}}&lt;br /&gt;
&lt;br /&gt;
=====env_shade=====&lt;br /&gt;
If you use &#039;&#039;&#039;env_shade&#039;&#039;&#039;, use it with caution. It completely overwrites the vertex coloring.&lt;br /&gt;
&lt;br /&gt;
 # BSL command&lt;br /&gt;
 # env_shade obj_id obj_id R G B&lt;br /&gt;
 &lt;br /&gt;
 # examples&lt;br /&gt;
 env_shade 7 7			# object 7 will be black&lt;br /&gt;
 env_shade 7 7 0 0 0		# object 7 will be black&lt;br /&gt;
 env_shade 7 7 .31 .999 .5	# object 7 will be quite green&lt;br /&gt;
 env_shade 7 10 1 1 1		# object 7, 8, 9, 10 lose all their shading&lt;br /&gt;
&lt;br /&gt;
====Baked lightmaps====&lt;br /&gt;
A drawback of this method, AKA shadow maps, is the high number of [[XML:BINA/TMBD|TMBD]] changes and new textures for every wall, requiring a lot of memory. How to create shadow maps:&lt;br /&gt;
&lt;br /&gt;
* https://web.archive.org/web/20121105081823/http://www.game-artist.net/forums/support-tech-discussion/5622-burning-shadows-onto-texture-xsi.html&lt;br /&gt;
&amp;lt;!-- http://caffeineabuse.blogspot.de/2008/12/cast-shadow-only-lights-in-xsi.html might be also interesting --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on map options:&lt;br /&gt;
* &amp;quot;Surface color and illumination&amp;quot;: outputs used texture with added shadows&lt;br /&gt;
** Can be used to replace original texture&lt;br /&gt;
* &amp;quot;Illumination only&amp;quot;: output a texture that only contains the shadows&lt;br /&gt;
** Can be used on a new overlying, transparent surface&lt;br /&gt;
&lt;br /&gt;
====Standalone lightmaps====&lt;br /&gt;
With this approach there are two meshes, whereby the shadow effects on one mesh get drawn in front of the regular level texture.&lt;br /&gt;
&lt;br /&gt;
Compared to the &amp;quot;baked lightmaps&amp;quot; method, this needs more polygons of course. And these polygons are transparent, which is a problem with Oni&#039;s limited rendering ability for such textures. However, standalone lightmaps only need a few new textures if used wisely.&lt;br /&gt;
&lt;br /&gt;
Read [[Lightmapping levels]] to learn more.&lt;br /&gt;
&lt;br /&gt;
[[Image:Oni_Lightmaps_double_polygon_method.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Rooms&amp;gt;===&lt;br /&gt;
The Rooms tag is mandatory. It contains an import path to BNV and ghosts (*.dae) which are used to create pathfinding grids. For information on the binary data behind this, see [[OBD:AKVA|HERE]].&lt;br /&gt;
&lt;br /&gt;
Sample code from the master XML file:&lt;br /&gt;
 &amp;lt;Import Path=&amp;quot;env/lab_bnv.dae&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fundamentals&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;BNVs&#039;&#039;&#039; are &#039;&#039;&#039;volumes&#039;&#039;&#039; (sometimes also named &#039;&#039;&#039;rooms&#039;&#039;&#039;) that have a pathfinding grid assigned to them.&lt;br /&gt;
* For practical reasons you only need &#039;&#039;&#039;floors and ramps&#039;&#039;&#039; to build a BNV. (As seen [http://edt.oni2.net/images/Hideout_BNV.jpg HERE.])&lt;br /&gt;
** A BNV polygon can consist of 3 or more points, but it&#039;s recommended to use &#039;&#039;&#039;shapes with 4 points&#039;&#039;&#039; because the other shapes usually waste more grid space. At the moment you can import only &#039;&#039;&#039;[[wikt:convex|convex]]&#039;&#039;&#039; shapes.&lt;br /&gt;
* Secondly, there are so called &#039;&#039;&#039;ghosts&#039;&#039;&#039; (vertical quads) that connect &#039;&#039;&#039;neighboring BNVs&#039;&#039;&#039;. AI can only transit from BNV to another through ghosts.&lt;br /&gt;
: OniSplit gives error messages for ghosts that don&#039;t have 2 neighboring BNVs, for example:&lt;br /&gt;
 BNV Builder: Ghost &#039;grid2&#039; has no adjacencies at &amp;lt;-72,41 1,999 -166,6&amp;gt; and &amp;lt;-71 1,999 -168,21&amp;gt;, ignoring&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tolerance values&#039;&#039;&#039;&lt;br /&gt;
* Horizontal distance from room to ghost: 1&lt;br /&gt;
* Vertical distance from room to ghost: 18&lt;br /&gt;
* Ghost&#039;s horizontal dimension must be greater than 0&lt;br /&gt;
* Under optimal circumstances, pathfinding works on a plane that is +4 world units above or -0.5 below the pathfinding grid&lt;br /&gt;
* Normally characters can&#039;t pass over low vertical walls such as stairs/curbs if those don&#039;t have a ramp under them; near ground level (Y=0) is an exception where characters are allowed to step on a plane that is 4 world units above pathfinding grid; higher planes need a ramp&lt;br /&gt;
* Maximum angle of ramp you can go on is 70°; higher angles will make characters fall through to their death (in those cases you might want to add invisible walls/boxes to prevent them from touching the ramp)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;More notes on PF processing&#039;&#039;&#039;&lt;br /&gt;
* Actually, BNV and ghosts can have any name and don&#039;t need any texture.&lt;br /&gt;
* During pathfinding calculation, OniSplit creates a new folder called &amp;quot;temp&amp;quot; and a subfolder &amp;quot;grids&amp;quot;. There is a file named &amp;quot;&#039;&#039;levelname&#039;&#039;_grids.dae&amp;quot;. That file contains rooms with textures called &amp;quot;bnv_grid_&#039;&#039;N&#039;&#039;.tga&amp;quot; which mark obstacles in the pathfinding grid. Ghosts will have a transparent texture &amp;quot;&#039;&#039;&#039;_marker_ghost&#039;&#039;&#039;.tga&amp;quot;. You also get these when you export a level. Transparent ghosts make it easier to see the rest of your level if you have many of those planes.&lt;br /&gt;
* In Mod Tool, ghosts and rooms can be grouped under a null object. Right-click the null object to select all its children, then use &amp;quot;Selection Only [x]&amp;quot; as your saving option. That way all the planes can be quickly saved to a *.dae file.&lt;br /&gt;
* You can influence the pathfinding creation of dangerous zones using danger quads. Read about those [[#Marker textures|HERE]].&lt;br /&gt;
* Another kind of influence is the [[#&amp;lt;Model&amp;gt;|gunk flag]] IgnoreGrid. It can be used to tell OniSplit to ignore the object during pathfinding creation. The grids in that place will be white.&lt;br /&gt;
&lt;br /&gt;
[[Image:Pathfinding_grid.jpg|thumb|200px|right|&#039;&#039;&#039;ai2_showgrids = 1&#039;&#039;&#039; in action]]&lt;br /&gt;
&#039;&#039;&#039;BSL commands&#039;&#039;&#039;&lt;br /&gt;
* chr_show_bnv = 1&lt;br /&gt;
:: shows number of BNVs the player is standing on&lt;br /&gt;
* ai2_showgrids = 1&lt;br /&gt;
:: shows pathfinding grids&lt;br /&gt;
* ai2_chump&lt;br /&gt;
:: spawns a friendly Striker that follows the player if possible, makes also pathfinding grids visible&lt;br /&gt;
* ai2_chump_stop = 1&lt;br /&gt;
:: Striker stops following you&lt;br /&gt;
* ai2_chump_stop = 0&lt;br /&gt;
:: Striker follows you again&lt;br /&gt;
&lt;br /&gt;
====Pathfinding on uneven ground====&lt;br /&gt;
Pathfinding works on slightly uneven ground as long as the polygons are 0.5 world units beneath or 4 world units above the BNV.&lt;br /&gt;
&lt;br /&gt;
For greater surface irregularities, we can use a trick:&lt;br /&gt;
* The problematic polygons must be saved to a DAE file and then referenced in the model section as an individual object.&lt;br /&gt;
* Then the &amp;lt;GunkFlags&amp;gt; tag needs to be &#039;&#039;&#039;&#039;&#039;GridIgnore&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Additionally we create a plane (invisible if necessary) under the object so that Oni doesn&#039;t think there&#039;s a hole.&lt;br /&gt;
* The ghosts must be taller than the highest polygon to be walked on. (This has been tested up to a height of 2,000 world units.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms of too-small ghosts&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A) AI can&#039;t run at all.&lt;br /&gt;
&lt;br /&gt;
B) AI loses PF ability if the tracked enemy performs animations that are outside of the pathfinding volume. Here&#039;s a video (&amp;lt;nowiki&amp;gt;https://youtu.be/vfKPzP5hiCo&amp;lt;/nowiki&amp;gt;, dead link) showing these symptoms.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Missing boundaries&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say you have a BNV, tall ghosts, and a GridIgnore-flagged hill with trees and bushes and stuff.&lt;br /&gt;
&lt;br /&gt;
Why do AIs run up against the trees?&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; There are no red/orange grids that limit the AI&#039;s movement. Normally, objects will produce red pathfinding squares around them. But objects that are 20 world units above the BNV are ignored just like objects with the IgnoreGrid flag.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Add simple geometries like &#039;&#039;_marker_impassable fences&#039;&#039; or danger quads near the BNV.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Disappearing AIs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The ground is sometimes not solid, and the player and AIs are falling through it.&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Problem:&#039;&#039;&#039; On GridIgnore-flagged uneven ground, AIs can fall through it when they are out of the player&#039;s view.&lt;br /&gt;
: &#039;&#039;&#039;Solution:&#039;&#039;&#039; Use either &#039;&#039;&#039;chr_lock_active &#039;&#039;AI_name&#039;&#039;&#039;&#039;&#039; or &#039;&#039;&#039;chr_all_active = 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Debugging====&lt;br /&gt;
&#039;&#039;&#039;(OniSplit v0.9.93.0+)&#039;&#039;&#039;&lt;br /&gt;
[[Image:OniBrowser.jpg|thumb|200px|right|OniBrowser displaying level geometry plus PF and ghosts.]]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;env_show_ghostgqs = 1&#039;&#039;&#039; makes the ghost quads visible&lt;br /&gt;
** The original ghost quads can&#039;t be seen; per Neo, &amp;quot;they are not included in the octtree and bsp tree&amp;quot;&lt;br /&gt;
** To see them you must use the -debug option in the level creation command (available with OniSplit &#039;&#039;&#039;v0.9.93.0+&#039;&#039;&#039;)&lt;br /&gt;
 OniSplit.exe -create:level &#039;&#039;output_folder&#039;&#039; &#039;&#039;&#039;-debug&#039;&#039;&#039; &#039;&#039;input_folder&#039;&#039;/&#039;&#039;master_xml_file&#039;&#039;.xml&lt;br /&gt;
&lt;br /&gt;
Not all debugging/testing needs to be done in Oni. There is also a [http://mods.oni2.net/node/256 program] (Windows only) which can display the whole level.&lt;br /&gt;
&lt;br /&gt;
For example you can load an AKEV*.oni, select the level name, and use the hotkeys [B] and [P] to display BNVs and ghosts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bug prevention:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
After all testing is done, you should compile the level a last time without the -debug option.&lt;br /&gt;
&lt;br /&gt;
AIs appear to have trouble shooting through ghost quads that got registered in the octtree/BSP tree as seen here (&amp;lt;nowiki&amp;gt;https://www.youtube.com/watch?v=-ZugVBgBVKc&amp;lt;/nowiki&amp;gt;, dead link).&lt;br /&gt;
&lt;br /&gt;
====When OniSplit fails to connect PF quads====&lt;br /&gt;
[[Image:Pathfinding_creation__merge_polygons_to_fix_connections.jpg|thumb|200px|right|Fixed PF in compound level after underground construction...]]&lt;br /&gt;
It can help to merge polygons to one object and merge their edges. These become white. (Outer edges are blue.)&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Textures&amp;gt;===&lt;br /&gt;
====...used for exceptions====&lt;br /&gt;
The [[#textures_tag|textures tag]] is mandatory.&lt;br /&gt;
&lt;br /&gt;
AKEV textures will be imported by the master XML file automatically; you don&#039;t need to add them to that file.&lt;br /&gt;
&lt;br /&gt;
: With OniSplit v0.9.82-93.0, the textures&#039; formats will be DXT1 and (for transparent ones) BGRA4444.&lt;br /&gt;
: With OniSplit v0.9.94.0+ the textures&#039; formats will be BGR and (for transparent ones) RGBA.&lt;br /&gt;
&lt;br /&gt;
To change the default texture import format, use the Texture&#039;&#039;&#039;s&#039;&#039;&#039; tag. (Possible with OniSplit v0.9.94.0+.)&lt;br /&gt;
&lt;br /&gt;
To change the format/flag/gunk flag of a specific texture, use the Texture tag.&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&lt;br /&gt;
          &amp;lt;Textures Format=&amp;quot;BGR&amp;quot; AlphaFormat=&amp;quot;RGBA&amp;quot; MaxSize=&amp;quot;512&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Texture Name=&amp;quot;GOO&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;TwoSided&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;Format&amp;gt;BGRA4444&amp;lt;/Format&amp;gt;&lt;br /&gt;
                    &amp;lt;GunkFlags&amp;gt;NoCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
                    &amp;lt;Image&amp;gt;env/images/GOO.tga&amp;lt;/Image&amp;gt;&lt;br /&gt;
                &amp;lt;/Texture&amp;gt;&lt;br /&gt;
          &amp;lt;/Textures&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use the gunk flag &amp;quot;TwoSided&amp;quot; to make surfaces visible from both sides.&lt;br /&gt;
* If the texture comes with the gunk flag &amp;quot;NoCollision&amp;quot; then all objects with that texture will have no collision. Characters would fall through it.&lt;br /&gt;
&lt;br /&gt;
Transparency and no collision together would make sense for a water-like substance. The Vago Biotech level uses this approach for the area with green toxic waste.&lt;br /&gt;
&lt;br /&gt;
[[Image:making_a_surface_transparent_and_twosided.png|thumb|200px|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures.png|thumb|200px|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;&amp;lt;br&amp;gt;one object with multiple textures, one per polygon cluster]]&lt;br /&gt;
[[Image:AKEV_single_object_multiple_textures_ingame.png|thumb|200px|right|&#039;&#039;&#039;Figure 3&#039;&#039;&#039;&amp;lt;br&amp;gt;blue: two-sided&amp;lt;br&amp;gt;glass: two-sided and transparent&amp;lt;br&amp;gt;random metal: no flag (one-sided)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TwoSided and transparent objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s also possible to set this in Mod Tool. For TwoSided-ness, use one image source for diffuse and transparency. (It won&#039;t work with two image sources even if both sources use the same image.)&lt;br /&gt;
&lt;br /&gt;
For transparency you must additionally use the three checkboxes:&lt;br /&gt;
* Transparency: Enable&lt;br /&gt;
* Transparency: Use Alpha&lt;br /&gt;
* Transparency: Invert&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;Figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Regular textures====&lt;br /&gt;
OniSplit automatically imports textures of objects in the [[#&amp;lt;Model&amp;gt;|&amp;lt;Model&amp;gt; section]]. Those objects could be considered as AKEV core geometry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;One texture per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Furniture and Physics objects are allowed to have only one texture per object. AKEV core geometry can have one texture or multiple textures – that&#039;s up to you to decide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multiple textures per object&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question:&#039;&#039;&#039; How do we apply multiple textures to an AKEV core object?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Answer:&#039;&#039;&#039; Assuming you are using Mod Tool the procedure will be as follows. Repeat this for each cluster you create (except for projection). See also &#039;&#039;&#039;Figure 2 and 3&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Select some polygons&lt;br /&gt;
* Go to Material &amp;gt; Phong&lt;br /&gt;
* Hit [7] to open Render Tree&lt;br /&gt;
* Add a texture and connect &amp;quot;Image&amp;quot; with &amp;quot;Phong&amp;quot;, choose &amp;quot;diffuse&amp;quot; as illumination mode&lt;br /&gt;
* Double-click &amp;quot;Image&amp;quot; to open Material page&lt;br /&gt;
* In the Texture Projection section, click on &amp;quot;New&amp;quot; and choose a suitable projection&lt;br /&gt;
** Do this only if there isn&#039;t a projection in the &amp;quot;Texture_Coordinates_AUTO&amp;quot; cluster yet&lt;br /&gt;
** OniSplit processes only one texture projection, see &#039;&#039;&#039;Figure 4&#039;&#039;&#039;&lt;br /&gt;
* Choose the texture and UV, then fine-tune the UV via Alt + 7&lt;br /&gt;
&lt;br /&gt;
[[Image:AKEV_multiple_textures_one_projection.png|thumb|200px|right|&#039;&#039;&#039;Figure 4&#039;&#039;&#039;&amp;lt;br&amp;gt;use only one texture projection per object]]&lt;br /&gt;
&lt;br /&gt;
Caution: textures will be fixed to one set of flags. You can&#039;t use the same texture A for a one-sided cluster/object B and a two-sided cluster/object C. You would need to create a differently-named clone of that texture and apply that to cluster/object C.&lt;br /&gt;
&lt;br /&gt;
====Marker textures====&lt;br /&gt;
Marker textures are used to import certain objects with special flags. Import those objects alongside [[#&amp;lt;Model&amp;gt;|AKEV core]] geometry.&lt;br /&gt;
&lt;br /&gt;
Marker textures aren&#039;t imported automatically. Add those textures to the final package or plugin yourself, e.g. with some sort of script.&lt;br /&gt;
&lt;br /&gt;
 OniSplit.exe -create:txmp out env/markers/*.tga&lt;br /&gt;
&lt;br /&gt;
The flags Transparent, TwoSided and NoOcclusion are only set if the same texture source is used for diffuse and transparency and if transparency setting are enabled. See the subsection under &amp;quot;[[#...used for exceptions|...used for exceptions]]&amp;quot; called &amp;quot;TwoSided and transparent objects&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Danger quads&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pathfinding grids have different colored squares with different meanings.&lt;br /&gt;
* white/gray - clear space&lt;br /&gt;
* green light - near wall&lt;br /&gt;
* green - semi-passable&lt;br /&gt;
* green dark - stairs&lt;br /&gt;
* blue very light - border 1&lt;br /&gt;
* blue light - border 2&lt;br /&gt;
* blue - border 3&lt;br /&gt;
* blue dark - border 4&lt;br /&gt;
* &#039;&#039;&#039;orange - danger&#039;&#039;&#039;&lt;br /&gt;
* red - impassable&lt;br /&gt;
&lt;br /&gt;
For detailed information on colors, see [[OBD_talk:AKVA/0x24#EFFECTS_of_various_pathfinding_grid_tile_types|HERE]].&lt;br /&gt;
&lt;br /&gt;
Normally, OniSplit decide how to color the grids. But it&#039;s possible to add your own danger quads to fine-tune zones of higher danger. Those orange areas will be generated with the 4 different blue borders around it.&lt;br /&gt;
&lt;br /&gt;
Danger quads must have &amp;quot;&#039;&#039;&#039;_marker_danger&#039;&#039;&#039;&amp;quot; as texture name.&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided NoCollision Invisible NoOcclusion Danger&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;_marker_barrier&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!-- Originally this is only used for level-bounding invisible walls? --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Results in flags: Transparent TwoSided(double-check) Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLLISION (boxes)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
AIs can get stuck in detailed geometry. This can be prevented with collision boxes. In-game the box will be invisible, but has collision so characters can&#039;t get through. The pathfinding grid will be red where it comes in contact with the box; the red is followed by a light green and then regular green.&lt;br /&gt;
&lt;br /&gt;
[[XML:OFGA|OFGAs]] use the COLLISION texture. Onisplit doesn&#039;t automatically apply gunk flags to it. You need to use XML tags for that. Typically it would be &amp;lt;GunkFlags&amp;gt;Invisible NoObjectCollision&amp;lt;/GunkFlags&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_stairs&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Normally, characters can&#039;t move on stairs because they contain vertical rises. In this case you can use a sloping quad that is above or inside the staircases. It&#039;s possible to set the desired flags in the &amp;lt;Model&amp;gt; section, but doing so and exporting these self-made stair ramps is wasted time. Simply apply _marker_stairs to that quad and characters will be able to move on that surface.&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Stairs Transparent TwoSided Invisible NoObjectCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
This has no effect on pathfinding creation. Regularly-textured stair geometry (which intersects the marker quad) will be flagged as NoCharacterCollision.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
texture: &#039;&#039;&#039;_marker_impassable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: Transparent TwoSided (&amp;lt;-double-check this) Invisible NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Impassable walls are very similar to collision boxes except that particles can also collide with them. The pathfinding grids will be also red, light green, and green.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Blackness a.k.a. jello fix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_blackness&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: TwoSided NoCollision&lt;br /&gt;
&lt;br /&gt;
Simply black walls. No effect on pathfinding creation. The purpose of these walls in Oni is to block out areas outside of a level&#039;s outermost wall so that the Jello-cam cannot show the player other parts of the level when it escapes a wall. See [[Jello-cam]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Doors&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Texture: &#039;&#039;&#039;_marker_door&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Resulting flags: DoorFrame Transparent TwoSided NoCollision NoOcclusion&lt;br /&gt;
&lt;br /&gt;
Don&#039;t use this.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;Objects&amp;gt;===&lt;br /&gt;
Information on regular object lists can be looked up here:&lt;br /&gt;
: [[XML:BINA/OBJC/CHAR|Character.xml]] (has to contain player character if there&#039;s no AISA file with it)&lt;br /&gt;
: [[XML:BINA/OBJC/CONS|Console.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/DOOR|Door.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/FLAG|Flag.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/NEUT|Neutral.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PART|Particle.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PATR|PatrolPath.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/PWRU|PowerUp.xml]]&lt;br /&gt;
: [[XML:SNDD#BINACJBOSound.xml|Sound.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRIG|Trigger.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/TRGV|TriggerVolume.xml]]&lt;br /&gt;
: [[XML:BINA/OBJC/WEAP|Weapon.xml]]&lt;br /&gt;
&lt;br /&gt;
====Furniture.xml====&lt;br /&gt;
The AKEV core geometry is more or less the overall structure of the level while this furniture file adds standard objects (e.g. crates and desks) to it.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Objects&amp;gt;&lt;br /&gt;
| - &lt;br /&gt;
| This tag marks the file as BINACJBO.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Furniture&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| This tag marks the file as FURN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Header&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag. Ignore it. Those flags were used in the past.&lt;br /&gt;
:None&lt;br /&gt;
:Locked&lt;br /&gt;
:PlacedInGame&lt;br /&gt;
:Temporary&lt;br /&gt;
:Gunk&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;OSD&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Class&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
| File path to a &#039;&#039;&#039;pre-compiled [[XML:OFGA|OFGA]] (*.oni) file&#039;&#039;&#039;. Use it as part of a relative path. Make sure that the OFGA comes with the files it needs: M3GM and TXMP.&lt;br /&gt;
&lt;br /&gt;
An OFGA can hold multiple M3GMs. That 3D content will then be integrated into the AKEV.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Particle&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| string&lt;br /&gt;
| This name gets written into &amp;lt;Tag&amp;gt; inside ONLV (ENVP section) and can be used with BSL commands, e.g. you can take control over a particle via &#039;&#039;&#039;particle BSL_name start&#039;&#039;&#039;. For more commands, see [[XML:BINA/OBJC/PART#BSL_support|HERE]].&lt;br /&gt;
&lt;br /&gt;
Take care with the naming of new OFGA files. The particle name will be composed of 2 parts separated by an &amp;quot;_&amp;quot; underscore. When one tag is empty, the final name will contain an underscore nonetheless. &#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;streetlight&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;_streetlight&#039;&#039;&#039;&lt;br /&gt;
: FURN &amp;lt;Particle&amp;gt;test&amp;lt;/Particle&amp;gt; + OFGA &amp;lt;Tag&amp;gt;&amp;lt;/Tag&amp;gt; = &#039;&#039;&#039;test_&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Example&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Objects&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Furniture&amp;gt;&lt;br /&gt;
            &amp;lt;Header&amp;gt;&lt;br /&gt;
                &amp;lt;Flags&amp;gt;Gunk&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                &amp;lt;Position&amp;gt;-62.692 -29 108.35&amp;lt;/Position&amp;gt;&lt;br /&gt;
                &amp;lt;Rotation&amp;gt;181.522 356.021 178.114&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;/Header&amp;gt;&lt;br /&gt;
            &amp;lt;OSD&amp;gt;&lt;br /&gt;
                &amp;lt;Class&amp;gt;furniture/V_tctf_bigvan.oni&amp;lt;/Class&amp;gt;&lt;br /&gt;
                &amp;lt;Particle&amp;gt;&amp;lt;/Particle&amp;gt;&lt;br /&gt;
            &amp;lt;/OSD&amp;gt;&lt;br /&gt;
        &amp;lt;/Furniture&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Objects&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Physics.xml====&lt;br /&gt;
This file is for objects with &amp;quot;physics&amp;quot;. Unlike AKEV core geometry or furniture, these objects can be animated.&lt;br /&gt;
&lt;br /&gt;
: A small video tutorial on [https://www.youtube.com/watch?v=CFNseg_2UxA how to create a simple animated object]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Physics&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Object Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| string&lt;br /&gt;
| Use a unique name for each object.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;ScriptId&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| integer&lt;br /&gt;
| Tested with BSL command...&lt;br /&gt;
:obj_create ID [ID]&lt;br /&gt;
:obj_kill ID [ID]&lt;br /&gt;
:env_anim ID [ID]&lt;br /&gt;
:env_setanim ID [ID]&lt;br /&gt;
The scripting ID will be stored in the ONLV&#039;s OBOA instance.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
|&lt;br /&gt;
;Object setup flags&lt;br /&gt;
:None&lt;br /&gt;
:InUse&lt;br /&gt;
:NoCollision&lt;br /&gt;
:NoGravity&lt;br /&gt;
:FaceCollision&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Physics&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag for an Object.&lt;br /&gt;
:None&lt;br /&gt;
:Static&lt;br /&gt;
:Linear&lt;br /&gt;
:Animated&lt;br /&gt;
:Newton (used with &amp;lt;Flags&amp;gt; FaceCollision to [https://www.youtube.com/watch?v=YICB7qugrtc make an object pushable])&lt;br /&gt;
:: For a pushable object don&#039;t use import sub-tags such as animation name, flags, etc. Just use &amp;lt;Import Path=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt; or &amp;lt;Import Url=&amp;quot;...&amp;quot; &#039;&#039;&#039;/&#039;&#039;&#039;&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Position&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Rotation&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects. X Y Z rotation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Scale&amp;gt;&lt;br /&gt;
| float&lt;br /&gt;
| Optional tag of Object. Only used for non-animated objects.&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;Import Path=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Import Url=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| link&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| This tag comes in two variants. It doesn&#039;t matter what variant you use.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Animation Name=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| File path to *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Flags&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| flag&lt;br /&gt;
| Optional tag of Animation. For more information on those flags look [[XML:OBAN|OBAN]] page.&lt;br /&gt;
&lt;br /&gt;
;Object animation flags&lt;br /&gt;
:None&lt;br /&gt;
:Loop&lt;br /&gt;
:PingPong&lt;br /&gt;
:RandomStart&lt;br /&gt;
:AutoStart&lt;br /&gt;
:Local&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;End&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the end of an OBAN from a *.dae file.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Start&amp;gt;&lt;br /&gt;
| integer&lt;br /&gt;
| Optional tag of Animation. Frame number. Used to define the start of an OBAN from a *.dae file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The XML code for physics can be written in two styles.&lt;br /&gt;
*The &#039;&#039;&#039;first style&#039;&#039;&#039; mimics the original structure found in extracted ONLV instances. This makes it &#039;&#039;&#039;easier to edit old levels and reimport them&#039;&#039;&#039; into the game.&lt;br /&gt;
*The &#039;&#039;&#039;second style&#039;&#039;&#039; was created with structured data (nested objects) in mind and is &#039;&#039;&#039;suited for totally new levels&#039;&#039;&#039; where animated objects must be created in a 3D editor at first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        &amp;lt;Object&amp;gt;&lt;br /&gt;
            &amp;lt;Geometry&amp;gt;M3GMDishBase.oni&amp;lt;/Geometry&amp;gt;&lt;br /&gt;
            &amp;lt;Animation&amp;gt;OBANDishBase.oni&amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;Physics&amp;gt;Animated&amp;lt;/Physics&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;201&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Position&amp;gt;-197.729141 128.46283 -2501.46387&amp;lt;/Position&amp;gt;&lt;br /&gt;
            &amp;lt;Rotation&amp;gt;0.7071067 -1.545431E-08 1.545431E-08 0.7071068&amp;lt;/Rotation&amp;gt;&lt;br /&gt;
            &amp;lt;Scale&amp;gt;2.109375&amp;lt;/Scale&amp;gt;&lt;br /&gt;
            &amp;lt;Name&amp;gt;object_DishBase&amp;lt;/Name&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code style 2&#039;&#039;&#039;&lt;br /&gt;
:For documentation purposes, the file here has been trimmed down.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Physics&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
        &amp;lt;Object Name=&amp;quot;motorcycle&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;ScriptId&amp;gt;8&amp;lt;/ScriptId&amp;gt;&lt;br /&gt;
            &amp;lt;Flags&amp;gt;FaceCollision&amp;lt;/Flags&amp;gt;&lt;br /&gt;
            &amp;lt;Import Url=&amp;quot;motorcycle/export.dae&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Flags&amp;gt;AutoStart&amp;lt;/Flags&amp;gt;&lt;br /&gt;
                    &amp;lt;End&amp;gt;880&amp;lt;/End&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
                &amp;lt;Animation Name=&amp;quot;motorcycle02_stop&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;Start&amp;gt;881&amp;lt;/Start&amp;gt;&lt;br /&gt;
                &amp;lt;/Animation&amp;gt;&lt;br /&gt;
            &amp;lt;/Import&amp;gt;&lt;br /&gt;
        &amp;lt;/Object&amp;gt;&lt;br /&gt;
        [...]&lt;br /&gt;
    &amp;lt;/Physics&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, OniSplit takes the file &amp;quot;export.dae&amp;quot;, looks at the parts it contains, and creates geometry files from it.&lt;br /&gt;
* M3GMhubs_rear.oni&lt;br /&gt;
* M3GMhubs.oni&lt;br /&gt;
* M3GMmotorcycle.oni&lt;br /&gt;
It&#039;s convenient that hierarchies are supported here.&lt;br /&gt;
&lt;br /&gt;
The motorcycle is made of 3 parts so 3 object animations ([[XML:OBAN|OBAN]]) will be created up to frame 880. Then OniSplit creates 3 more OBANs starting from frame 881.&lt;br /&gt;
&lt;br /&gt;
The reason for the interruption at frame 880 is probably to give Barabas a little more camera time in the cutscene.&lt;br /&gt;
&lt;br /&gt;
;Notes about BSL usage:&lt;br /&gt;
&lt;br /&gt;
The Vago Lab cutscene script uses the motorcycle objects and animations like this:&lt;br /&gt;
 	env_show 8 0		# hide static motorcycle parts or else they would be visible&lt;br /&gt;
 	env_show 9 0		# while Konoko is still riding her animated motorcycle&lt;br /&gt;
 	env_show 10 0		# the static motorcycle is separated into objects 8, 9 and 10&lt;br /&gt;
 &lt;br /&gt;
 	# Static and animated objects are totally independent from each other.&lt;br /&gt;
 	# They are stored in different arrays so their script IDs can use the same numbers.&lt;br /&gt;
 &lt;br /&gt;
 	obj_create 8 10		# create all animation-ready motorcycle parts&lt;br /&gt;
 	env_anim 8 10		# animate those parts (not necessary if OBAN flag is &amp;quot;AutoStart&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 	# The first animations would loop because of &amp;quot;AutoStart&amp;quot;, so get the&lt;br /&gt;
 	# right timing to apply the other animations. &amp;quot;motorcycle02_stop&amp;quot;&lt;br /&gt;
 	# and the others will not loop because they don&#039;t have &amp;quot;AutoStart&amp;quot;.&lt;br /&gt;
 	env_setanim 8 hubs_stop&lt;br /&gt;
 	env_setanim 9 hubs_rear_stop&lt;br /&gt;
 	env_setanim 10 motorcycle02_stop&lt;br /&gt;
 &lt;br /&gt;
 	obj_kill 8 10		# delete all animated parts&lt;br /&gt;
 	env_show 9 1		# show static motorcycle model where Konoko parks her bike&lt;br /&gt;
&lt;br /&gt;
====Corpses.xml====&lt;br /&gt;
An empty Corpse element (&amp;lt;Corpse /&amp;gt;) is treated as unused and placed at the end of the array. If no such empty elements are provided, OniSplit automatically adds 5. OniSplit also ensures that there are at least 20 corpses in the array.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
!width=150px| XML tag&lt;br /&gt;
!width=120px| Content type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Corpses&amp;gt;&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| &amp;lt;Corpse&amp;gt;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Class&amp;gt;&lt;br /&gt;
| link&lt;br /&gt;
| [[XML:ONCC|ONCC]]&#039;&#039;name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Transforms&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| There are 19 &amp;lt;Matrix&amp;gt; for each &amp;lt;Transforms&amp;gt; (which represents a body part).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Matrix&amp;gt;&lt;br /&gt;
| matrix&lt;br /&gt;
| Float 3x3 + float x3 for the last 3 values (X Y Z position). For more information about the matrix, see [[OBD:CRSA]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
| -&lt;br /&gt;
| Bounding box of the whole corpse. Optional; if not provided, OniSplit will generate an approximate one. Currently it doesn&#039;t try to locate the ONCC to compute an exact bounding box.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Min&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;Max&amp;gt;&lt;br /&gt;
| float x3&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Trimmed example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;Oni&amp;gt;&lt;br /&gt;
    &amp;lt;Corpses&amp;gt;&lt;br /&gt;
        &amp;lt;Corpse&amp;gt;&lt;br /&gt;
            &amp;lt;Class&amp;gt;generic_male_1&amp;lt;/Class&amp;gt;&lt;br /&gt;
            &amp;lt;Transforms&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.36488995 0.04620622 -0.9299034 -0.05580434 -0.9980576 -0.02769538 -0.9293768 0.04178688 0.366759717 -215.667755 1.603917 92.85312&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.2961557 -0.185628444 0.936928 -0.368288517 -0.9272724 -0.06730227 0.8812806 -0.32512787 -0.342981815 -216.51889 1.64218426 93.189&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.407847315 0.156575248 0.8995248 -0.238757968 -0.9326179 0.2705892 0.8812805 -0.3251278 -0.342982143 -215.239883 0.8405094 97.23532&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.439697325 0.467113584 0.767118752 0.0248355754 -0.8601105 0.5095029 0.8978026 -0.204975232 -0.389789373 -213.6234 1.46109009 100.80056&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.717241049 -0.179043233 0.673430443 0.4761817 -0.579636 -0.6612664 0.5087397 0.794962764 -0.3304816 -214.81662 1.56564879 92.5172348&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.3398023 0.1672905 0.925498843 0.7910236 -0.5831365 -0.185023025 0.5087395 0.7949628 -0.330481827 -211.71907 0.792413354 95.42558&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.1283634 0.227430075 0.965297 0.804142356 -0.59352535 0.032904774 0.5804117 0.7720126 -0.259073079 -210.372269 1.45546341 99.0937653&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.285799921 0.06851995 -0.955836535 -0.240357026 -0.970681965 0.00228381017 -0.927656651 0.230394751 0.2938901 -216.284851 1.5839076 91.29168&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.312039882 0.04875436 -0.948817253 -0.176752359 -0.9842264 0.00755515043 -0.9334825 0.1700632 0.31573534 -216.689789 1.68287766 89.9359055&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.356412441 -0.5390179 -0.763170958 0.0404523835 -0.82494843 0.5637587 -0.933452547 0.170058519 0.315826446 -217.422012 1.7979821 87.70907&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.101782769 -0.247171819 -0.9636112 0.5426916 -0.8256094 0.154451028 -0.8337422 -0.507223248 0.2181709 -217.747284 1.30605173 87.0125656&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.8154478 -0.150626346 0.558888733 -0.1200991 0.9885643 0.09119747 -0.566234052 0.00724477554 -0.8242127 -217.7402 2.065678 88.15346&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.4593738 -0.326781839 0.825947642 0.8874048 -0.1284554 0.442732215 -0.0385793857 0.9363295 0.348996729 -219.093979 1.81561315 89.08131&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9545983 -0.13777709 0.26412034 0.295387268 -0.322961926 0.899134 -0.0385792255 0.9363296 0.348996431 -220.3681 0.9092429 91.37218&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;-0.9715769 -0.0362956524 0.233924776 0.0276728421 -0.9988148 -0.0400396362 0.2351007 -0.0324283168 0.9714299 -222.775482 0.56178683 92.03825&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.979860842 -0.192433611 0.0533096045 0.193336874 0.9810555 -0.0122905634 -0.0499345176 0.0223497637 0.9985025 -216.8387 1.90143847 87.84845&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.863898 -0.399280578 0.3070101 0.171117 -0.340619326 -0.9244986 0.4737078 0.851207137 -0.225936681 -215.211975 1.58196676 87.93695&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.4673251 -0.0255063027 0.883717656 0.746463835 -0.524209559 -0.4098731 0.4737075 0.851207256 -0.225936785 -212.815842 0.47451216 88.78848&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
                &amp;lt;Matrix&amp;gt;0.216871262 -0.007893051 0.976168454 0.3751846 0.9238389 -0.0758833 -0.9012231 0.3827002 0.203315422 -211.637314 0.410188764 91.0171051&amp;lt;/Matrix&amp;gt;&lt;br /&gt;
            &amp;lt;/Transforms&amp;gt;&lt;br /&gt;
            &amp;lt;BoundingBox&amp;gt;&lt;br /&gt;
                &amp;lt;Min&amp;gt;-219.731216 -2.258905 84.47974&amp;lt;/Min&amp;gt;&lt;br /&gt;
                &amp;lt;Max&amp;gt;-207.518463 4.49535131 104.023239&amp;lt;/Max&amp;gt;&lt;br /&gt;
            &amp;lt;/BoundingBox&amp;gt;&lt;br /&gt;
        &amp;lt;/Corpse&amp;gt;&lt;br /&gt;
    &amp;lt;/Corpses&amp;gt;&lt;br /&gt;
 &amp;lt;/Oni&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[[Image:ONLV_CRSA_XSI_aided_import.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
:Some related information can be found at [[Authoring custom camera animations]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
For indirect import, see [http://oni.bungie.org/forum/viewtopic.php?id=2657 HERE] (OniTools v7.1.5+) on how to get corpse data.&lt;br /&gt;
&lt;br /&gt;
When you process your XML master file, use OniSplit version 0.9.94.0+. Older OniSplit versions like 0.9.86.0 may generate ONLV files that are not re-packable with newer versions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;(Export)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With Neo&#039;s matrix-to-Euler code, the rotations can be recovered from CRSA. But due to the character&#039;s hierarchy, things get messy again (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/OniGalore/CRSA_to_Mod_Tool_wip.png&amp;lt;/nowiki&amp;gt;, dead link). (WIP code (&amp;lt;nowiki&amp;gt;https://dl.dropboxusercontent.com/u/139715/temp/CRSA_to_Mod_Tool.txt&amp;lt;/nowiki&amp;gt;, dead link))&lt;br /&gt;
&lt;br /&gt;
A workaround might be to save characters without animations, destroy their hierarchy, apply the local rotations / global translation and glue everything together again.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Vortice</name></author>
	</entry>
</feed>