<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.trainzsimulator.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pw3r</id>
	<title>TrainzOnline - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.trainzsimulator.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pw3r"/>
	<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/wiki/Special:Contributions/Pw3r"/>
	<updated>2026-11-05T08:46:02Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=%22Motor%22_container&amp;diff=47576</id>
		<title>&quot;Motor&quot; container</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=%22Motor%22_container&amp;diff=47576"/>
		<updated>2026-09-30T23:29:43Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* throttle-notches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Motor container is a top-level [[config.txt file]] entry used by [[KIND Engine|Enginespec]] and [[KIND Steam-engine|Steam Enginespec]] assets.&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
The Motor container supports the following tags. Each tag is show here with its default value.&lt;br /&gt;
&lt;br /&gt;
 motor&lt;br /&gt;
 {&lt;br /&gt;
     resistance                     1.7&lt;br /&gt;
     adhesion                       5.0&lt;br /&gt;
     maxvoltage                     600.0&lt;br /&gt;
     maxspeed                       33.3&lt;br /&gt;
     brakeratio                     55000&lt;br /&gt;
     max-accel                      3500&lt;br /&gt;
     max-decel                      9000&lt;br /&gt;
     throttle-notches               8&lt;br /&gt;
     axle-count                     6&lt;br /&gt;
     surface-area                   80.0&lt;br /&gt;
     moving-friction-coefficient    0.03&lt;br /&gt;
     air-drag-coefficient           0.00017&lt;br /&gt;
     full-throttle-speed            33.0&lt;br /&gt;
     driving-wheel-weight-ratio     1.0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====resistance====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &#039;&#039;Not used&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====adhesion====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &#039;&#039;Not used&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====maxvoltage====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Voltage to &#039;&#039;traction motors&#039;&#039;. This is used to scale the ammeter displayed in the cab. (Power is volts times amps - increasing the voltage means reducing the ammeter...)&lt;br /&gt;
&lt;br /&gt;
====maxspeed====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Maximum speed in DCC mode.&lt;br /&gt;
&lt;br /&gt;
====brakeratio====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Coefficient between the pressure in brake cylinder and the brake force.&lt;br /&gt;
&lt;br /&gt;
====max-accel====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Accelerative force available in DCC mode. Note - this is a force, not a rate of acceleration. The rate of acceleration will depend on the mass of the train as well.&lt;br /&gt;
&lt;br /&gt;
====max-decel====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Decelerative force available in DCC mode. Note - this is a force, not a rate of deceleration. The rate of deceleration will depend on the mass of the train as well.&lt;br /&gt;
&lt;br /&gt;
==== throttle-notches ====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Description: Specifies the number of throttle notches in the cabin. By default, all (non-steam) locos have 8 throttle notches, but this may be overridden with this tag. Note that this has no impact on train power output, unless the engine also enables the [[KIND_Engine#throttle-power-extended-notch-range|throttle-power-extended-notch-range]] or [[KIND_Engine#dynamic-brake-extended-notch-range|dynamic-brake-extended-notch-range]] options, and provides the relevant data in the power output graphs.&lt;br /&gt;
&lt;br /&gt;
====axle-count====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of axles on this vehicle. Used in rolling [[#Resistance_calculations |resistance calculations]].&lt;br /&gt;
&lt;br /&gt;
====surface-area====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Frontal surface area (sq ft) of vehicle. Used in air [[#Resistance_calculations |resistance calculations]].&lt;br /&gt;
&lt;br /&gt;
====moving-friction-coefficient====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Used in rolling [[#Resistance_calculations |resistance calculations]].&lt;br /&gt;
&lt;br /&gt;
====air-drag-coefficient====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Used in air [[#Resistance_calculations |resistance calculations]].&lt;br /&gt;
&lt;br /&gt;
====full-throttle-speed====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Obsolete- no longer used. (Previously: maximum speed with DCC throttle at 100%)&lt;br /&gt;
&lt;br /&gt;
====driving-wheel-weight-ratio====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Ratio (between 0.0 and 1.0) of the weight of this vehicle bearing down on driven wheels. Used by steam locos only.&lt;br /&gt;
&lt;br /&gt;
==Resistance calculations==&lt;br /&gt;
&lt;br /&gt;
These calculations occur according to Davis formula:&lt;br /&gt;
&lt;br /&gt;
R = (1.3·m + 29·axle-count) + moving-friction-coefficient·m·V + air-drag-coefficient·surface-area·V^2 + 20·m·G&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R = total resistance in lb. including grade resistance&amp;lt;br&amp;gt;&lt;br /&gt;
V = speed - mph&amp;lt;br&amp;gt;&lt;br /&gt;
m = weight of the vehicle (tons)&amp;lt;br&amp;gt;&lt;br /&gt;
G = % grade (upgrade +, downgrade -)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Config Container|motor-container]]&lt;br /&gt;
{{cont-Engine|motor-container}}&lt;br /&gt;
{{ORP-bot|motor-container}}&amp;lt;div&amp;gt;{{FUN-bot|motor-container}}&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Engine&amp;diff=47575</id>
		<title>KIND Engine</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Engine&amp;diff=47575"/>
		<updated>2026-09-30T23:16:25Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Engine]] assets control the engine behaviour of [[KIND_Traincar|traincar]] assets, including power output and braking capabilities.&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* [[KIND Steam-engine]]&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;engine&amp;quot;&lt;br /&gt;
 [[throttle-power_container|throttle-power]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[dynamic-brake_container|dynamic-brake]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[motor_container|motor]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[mass_container|mass]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[volume_container|volume]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[pressure_container|pressure]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[flowsize_container|flowsize]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 throttle-power-extended-notch-range 0&lt;br /&gt;
 dynamic-brake-extended-notch-range 0&lt;br /&gt;
 autopilot-stop-distance 5.0&lt;br /&gt;
 autopilot-crawl-distance 20.0&lt;br /&gt;
 autopilot-caution-speed-multiplier 0.5&lt;br /&gt;
 throttle-adjustment-rate 0.01&lt;br /&gt;
 scale &amp;quot;&amp;quot;&lt;br /&gt;
 epbrakes &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====throttle-power====&lt;br /&gt;
:Type: [[throttle-power_container|throttle-power Container]]&lt;br /&gt;
:Desc: Specifies the power output (in kN) of the engine for a given throttle notch and train speed.&lt;br /&gt;
&lt;br /&gt;
====dynamic-brake====&lt;br /&gt;
:Type: [[dynamic-brake_container|dynamic-brake Container]]&lt;br /&gt;
:Desc: Specifies the power output (in kN) of the dynamic brake for a given throttle notch and train speed.&lt;br /&gt;
&lt;br /&gt;
====throttle-power-extended-notch-range====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Whether this engine asset specifies more than the default of 8 throttle notches in the throttle-power graph.&lt;br /&gt;
:Vers: Requires a minimum of trainz-version 5.8&lt;br /&gt;
&lt;br /&gt;
====dynamic-brake-extended-notch-range====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Whether this engine asset specifies more than the default of 8 throttle notches in the dynamic-brake graph.&lt;br /&gt;
:Vers: Requires a minimum of trainz-version 5.8&lt;br /&gt;
&lt;br /&gt;
====motor====&lt;br /&gt;
:Type: [[motor_container|motor Container]]&lt;br /&gt;
:Desc: Sets various values related to the train motor/engine, along with some resistance values.&lt;br /&gt;
&lt;br /&gt;
====mass====&lt;br /&gt;
:Type: [[mass_container|mass Container]]&lt;br /&gt;
:Desc: Sets various mass values for the train.&lt;br /&gt;
&lt;br /&gt;
====volume====&lt;br /&gt;
:Type: [[volume_container|volume Container]]&lt;br /&gt;
:Desc: Sets various volume values for the train braking system.&lt;br /&gt;
&lt;br /&gt;
====pressure====&lt;br /&gt;
:Type: [[pressure_container|pressure Container]]&lt;br /&gt;
:Desc: Sets various pressure values for the train braking system.&lt;br /&gt;
&lt;br /&gt;
====flowsize====&lt;br /&gt;
:Type: [[flowsize_container|flowsize Container]]&lt;br /&gt;
:Desc: Sets various flow size values for the train braking system.&lt;br /&gt;
&lt;br /&gt;
====scale====&lt;br /&gt;
:Type: Obsolete&lt;br /&gt;
:Desc: Obsolete&lt;br /&gt;
&lt;br /&gt;
====epbrakes====&lt;br /&gt;
:Type: Obsolete&lt;br /&gt;
:Desc: Obsolete&lt;br /&gt;
&lt;br /&gt;
====autopilot-stop-distance====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: How far (in meters) in front of a typical obstruction (red light, etc.) the AI will attempt to stop the train. Changing this value can help fine-tune the accuracy of the AI&#039;s movement, however attempting to make the train stop too close to a target may result in overruns in some cases. This tag is intended for special-case usage only.&lt;br /&gt;
&lt;br /&gt;
====autopilot-crawl-distance====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: Once this distance (in meters) from the intended stopping position has been reached, the AI will &#039;crawl&#039; rather than attempt to speed up to reach its destination. Changing this value can help fine-tune the accuracy of the AI&#039;s movement, however attempting to make the train stop too close to a target may result in overruns in some cases. This tag is intended for special-case usage only.&lt;br /&gt;
&lt;br /&gt;
====autopilot-caution-speed-multiplier====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: The AI will slow to this multiple of the speed limit when operating under caution conditions. This can be set to 1.0 in order to effectively remove caution-speed driving, however this can increase the risk of overruns in some cases&lt;br /&gt;
&lt;br /&gt;
====throttle-adjustment-rate====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: Defines the adjustment rate at which the engine&#039;s throttle will adjust to match the train&#039;s throttle. Increasing this rate will make the engine more responsive at the possible cost of audio or driving realism. In DCC mode, a minimum value of 0.1 is used.&lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
Sample [[config.txt file]] for an enginespec asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TBD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND]]&lt;br /&gt;
&lt;br /&gt;
[[Category:TBD]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Traincar&amp;diff=47574</id>
		<title>KIND Traincar</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Traincar&amp;diff=47574"/>
		<updated>2026-09-30T23:15:33Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* engine */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ORP-top}}&lt;br /&gt;
[[KIND Traincar]] provides the basis for all individual train Vehicles, for example, a single item of the locomotive, a single item of rollingstock, or a single tender.&lt;br /&gt;
&lt;br /&gt;
This asset type inherits all trackside positioning and mesh display characteristics, and adds Vehicle-specific functionality such as physics and control mechanisms.&lt;br /&gt;
&lt;br /&gt;
This page describes [[trainz-build]] 4.1.&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND Scenery-trackside]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* &#039;&#039;none.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
Each traincar asset supports the following tags. Each tag is shown here with its default value.&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;traincar&amp;quot;&lt;br /&gt;
 cabinsway 1.0&lt;br /&gt;
 company &amp;quot;QueenslandRail&amp;quot;&lt;br /&gt;
 ditch_color 0,0,0&lt;br /&gt;
 low_beam_value 2,2,2&lt;br /&gt;
 high_beam_value 1,1,1&lt;br /&gt;
 interior-light-texture &amp;quot;&amp;quot;&lt;br /&gt;
 interior-light-color 0.0, 0.0, 0.0&lt;br /&gt;
 flash_scale 1&lt;br /&gt;
 engine 0&lt;br /&gt;
 real-engine 1&lt;br /&gt;
 enginespec (KUID)&lt;br /&gt;
 enginesound (KUID)&lt;br /&gt;
 fonts 1&lt;br /&gt;
 hornsound (KUID)&lt;br /&gt;
 cabin_muffle 0.4&lt;br /&gt;
 light_color 0,0,0&lt;br /&gt;
 mass 37000&lt;br /&gt;
 max-coupler-gap 0.08&lt;br /&gt;
 pantograph (KUID)&lt;br /&gt;
 smoke_shade 0.09&lt;br /&gt;
 smoke_random 2.9&lt;br /&gt;
 smoke_slowlife 3&lt;br /&gt;
 smoke_fastlife 0&lt;br /&gt;
 smoke_height 0.8&lt;br /&gt;
 smoke_fastspeed 10&lt;br /&gt;
 suspension-stiffness 0.75&lt;br /&gt;
 suspension-damping 0.3&lt;br /&gt;
 suspension-pitch-limit 1.0&lt;br /&gt;
 suspension-roll-limit 5.0&lt;br /&gt;
 tender 0&lt;br /&gt;
 use-coupler-sounds 1&lt;br /&gt;
 disable-extra-track-sounds 0&lt;br /&gt;
 max-tractive-effort 0&lt;br /&gt;
 fonts-path &amp;quot;&amp;quot;&lt;br /&gt;
 [[vehicle-running-numbers_container|vehicle-running-numbers]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[classification-signals_container|classification-signals]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[bogeys_container|bogeys]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 origin &amp;quot;AU&amp;quot;                    (obsolete)&lt;br /&gt;
 paintshed-template-used (KUID) (obsolete)&lt;br /&gt;
 paintshed-skin-used (KUID)     (obsolete)&lt;br /&gt;
 product-id &amp;quot;&amp;quot;                  (obsolete)&lt;br /&gt;
 product-version ?              (obsolete)&lt;br /&gt;
 product-type &amp;quot;&amp;quot;                (obsolete)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
====cabin_muffle====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Steam 1.0, Other 0.4&lt;br /&gt;
:Desc: Amount that the enginesound volume should be reduced to when in-cab. Default of 0.4 is 40% volume, intended to represent a fully enclosed and noise deadened cab. Steam locos default to no muffling at all (steam loco cabs are very frequently not fully enclosed, let alone fitted with noise deadening material).&lt;br /&gt;
&lt;br /&gt;
====cabinsway====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 1.0&lt;br /&gt;
:Desc: Controls the amount of &#039;sway&#039; the interior view has as the vehicle takes corners. A bigger number will result in more sway.&lt;br /&gt;
&lt;br /&gt;
====company====&lt;br /&gt;
:Type: English Text String&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Queensland Rail&lt;br /&gt;
:Desc: Text string to indicate which railway company or organisation this vehicle is in service with as represented.&lt;br /&gt;
&lt;br /&gt;
====disable-extra-track-sounds====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0 (false)&lt;br /&gt;
:Desc: Disables extra track sounds for this vehicle. Useful for making drivable ships, aircraft, road vehicles, etc. - anything that should not make wheel-on-rail type sounds.&lt;br /&gt;
&lt;br /&gt;
====ditch_color====&lt;br /&gt;
:Type: Color(RGB)&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0,0,0&lt;br /&gt;
:Desc: Color of ditch lights (values are integer between 0 and 255, comma separated for red, green, and blue).&lt;br /&gt;
&lt;br /&gt;
====engine====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Compulsory: Yes (from 3.4)&lt;br /&gt;
:Default: 0&lt;br /&gt;
:Desc: If 1, vehicle is a locomotive (i.e. it has an engine), if 0, vehicle is an unpowered traincar.&lt;br /&gt;
&lt;br /&gt;
====enginesound====&lt;br /&gt;
:Type: KUID&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: [[KIND Enginesound|Enginesound Asset]] to use with this locomotive.&lt;br /&gt;
&lt;br /&gt;
====enginespec====&lt;br /&gt;
:Type: KUID&lt;br /&gt;
:Compulsory: Yes&lt;br /&gt;
:Desc: [[KIND Engine|Enginespec Asset]] to use with this locomotive. Defines locomotive performance characteristics.&lt;br /&gt;
&lt;br /&gt;
====flash_scale====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 1&lt;br /&gt;
:Desc: Sets the speed that the ditch lights flash at.&lt;br /&gt;
&lt;br /&gt;
====fonts====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 1&lt;br /&gt;
:Desc: Number of running-number fonts to use on this locomotive. The value must be from 0 to 5.&lt;br /&gt;
&lt;br /&gt;
See [[Alpha_Numbers|Alpha Numbers]] for further information regarding Alpha Numbers (aka running-numbers) on traincars.&lt;br /&gt;
&lt;br /&gt;
====fonts-path====&lt;br /&gt;
:Type: Text&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: Text to use when determining where running numbers are stored. This text will be concatenated with &amp;quot;_alpha_numbers&amp;quot; to provide the path to the images to be used for the running numbers.  For example if the supplied text is &amp;quot;my_loco&amp;quot; then the path, relative to the asset folder, will be &amp;quot;my_loco_alpha_numbers&amp;quot;.&lt;br /&gt;
See [[Alpha_Numbers|Alpha Numbers]] for further information regarding Alpha Numbers (aka running-numbers) on traincars.&lt;br /&gt;
&lt;br /&gt;
====high_beam_value====&lt;br /&gt;
:Type: Decimal array &lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 1,1,1&lt;br /&gt;
:Desc: Comma separated sequence of decimal values.  Used to configure the brightness of the lights when in high beam mode. First number applies to first headlight point, and so on. Values are divisors - e.g. a value of 2 means half brightness.&lt;br /&gt;
&lt;br /&gt;
====interior-light-texture====&lt;br /&gt;
:Type: [[Texture|Texture_file]]&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: The name of the texture resource (with the &#039;.texture.txt&#039; part omitted) that you want to illuminate the interior. The effect will be applied to ALL materials which use the specified texture.&lt;br /&gt;
&lt;br /&gt;
====interior-light-color====&lt;br /&gt;
:Type: Decimal array&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0.75,0.75,0.75&lt;br /&gt;
:Desc: This specifies the RGB level of self-illumination to be applied.  The default is a reasonable starting point. The effect will be on by default but can be turned off by script or via the traincar&#039;s property editor. When it is on the effect is independent of the time of day. As a result the interior mesh will appear to be lit by night and also brighter by day, you may have to increase the opacity of your windows to compensate for this.  The effect is independent of traincar headlights or any night-mesh containers.&lt;br /&gt;
&lt;br /&gt;
====hornsound====&lt;br /&gt;
:Type: KUID&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: [[KIND Hornsound|Hornsound Asset]] to play when loco&#039;s horn is blown.&lt;br /&gt;
&lt;br /&gt;
====light_color====&lt;br /&gt;
:Type: Color(RGB)&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0,0,0&lt;br /&gt;
:Desc: Color of headlight (values are integer between 0 and 255, comma separated for red, green, and blue).&lt;br /&gt;
&lt;br /&gt;
====low_beam_value====&lt;br /&gt;
:Type: Decimal array&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 2,2,2&lt;br /&gt;
:Desc: Comma separated sequence of decimal values.  Used to configure the brightness of the lights when in low beam mode. First number applies to first headlight point, and so on. Values are divisors - e.g. a value of 2 means half brightness.&lt;br /&gt;
&lt;br /&gt;
====mass====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: Yes (from 3.4)&lt;br /&gt;
:Default: 37000&lt;br /&gt;
:Desc: Mass of the vehicle in Kilograms when empty - i.e. the tare weight, not the gross weight. The mass of any products loaded into queues will be added to this by the game.&lt;br /&gt;
&lt;br /&gt;
====max-coupler-gap====&lt;br /&gt;
:Type: decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0.08&lt;br /&gt;
:Desc: Specifies the amount of permissible coupler slack on this vehicle in Metres. Note: The observable slack between any two vehicles will be the average of the values for each vehicle. Cannot be zero.&lt;br /&gt;
&lt;br /&gt;
====max-tractive-effort====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0&lt;br /&gt;
:Desc: Maximum tractive effort this vehicle can put into the track in Newtons. (Only used for Diesel and Electric locos - Steam locos use a different system defined in the enginespec.)&lt;br /&gt;
&lt;br /&gt;
====pantograph====&lt;br /&gt;
:Type: KUID&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: [[KIND Pantograph|Pantograph Asset]] to attach to pantograph attachment points.&lt;br /&gt;
&lt;br /&gt;
====smoke_fastlife====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0&lt;br /&gt;
:Desc: Length of time (seconds) smoke particles will exist for when vehicle is moving &#039;fast&#039;.&lt;br /&gt;
&lt;br /&gt;
====smoke_fastspeed====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 10&lt;br /&gt;
:Desc: Speed (m/s) at which traincar is considered to be moving &#039;fast&#039;.&lt;br /&gt;
&lt;br /&gt;
====smoke_height====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0.8&lt;br /&gt;
:Desc: Additional speed for &#039;slow&#039; smoke to make it drift higher from the traincar.&lt;br /&gt;
&lt;br /&gt;
====smoke_random====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 2.9&lt;br /&gt;
:Desc: Controls the amount of randomness introduced into the direction of new smoke particles. Larger numbers mean more randomness.&lt;br /&gt;
&lt;br /&gt;
====smoke_shade====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0.09&lt;br /&gt;
:Desc: Value in the range (0.0 ... 1.0) which controls the color (including Alpha - so 0.0 will be transparent, 0.1 a dark mist, 1.0 a thick white) of each smoke particle. The alpha value will decay to zero (transparent) over the life of the particle.&lt;br /&gt;
&lt;br /&gt;
====smoke_slowlife====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 3&lt;br /&gt;
:Desc: Length of time (seconds) smoke particles will exist for when vehicle is moving &#039;slow&#039;.&lt;br /&gt;
&lt;br /&gt;
====suspension-damping====&lt;br /&gt;
:Type: Float&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0.3&lt;br /&gt;
:Desc: Degree of suspension damping, where 0.0 to  &amp;lt; 1.0 is under-damped (will oscillate back and forward to gradually settle), 1.0 is critically damped (will move back to equilibrium as quickly as possible), &amp;gt;1.0 is overdamped (will move back to equilibrium more slowly). Defaults to 0.3.  The value must be positive.&lt;br /&gt;
&lt;br /&gt;
====suspension-stiffness====&lt;br /&gt;
:Type: Float&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0.75&lt;br /&gt;
:Desc: The stiffness of the suspension, from 0.0 to 1.0 where 0.0 is floppy and 1.0 is completely rigid. Defaults to 0.75.&lt;br /&gt;
&lt;br /&gt;
====suspension-pitch-limit====&lt;br /&gt;
:Type: Float&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 1.0&lt;br /&gt;
:Desc: Maximum pitch angle of the vehicle, in degrees. Must be positive.&lt;br /&gt;
&lt;br /&gt;
====suspension-roll-limit====&lt;br /&gt;
:Type: Float&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 5&lt;br /&gt;
:Desc: Maximum roll angle of the vehicle, in degrees. Must be positive.&lt;br /&gt;
&lt;br /&gt;
====tender====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0 (False)&lt;br /&gt;
:Desc: Used by the AI to determine if it should take this vehicle with the loco when doing orders like &#039;run round&#039;.&lt;br /&gt;
&lt;br /&gt;
====use-coupler-sounds====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 1 (True)&lt;br /&gt;
:Desc: Enables or disables the coupler slack sounds for this specific vehicle.&lt;br /&gt;
&lt;br /&gt;
====classification-signals====&lt;br /&gt;
:Type: [[classification-signals_container|classification-signals container]]&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: Lists the supported classification signals. Added in [[Trainz A New Era]].&lt;br /&gt;
&lt;br /&gt;
====vehicle-running-numbers====&lt;br /&gt;
:Type: [[vehicle-running-numbers_container|vehicle-running-numbers container]]&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: Defines the behaviour of automatic random running-number generation. Added in [[Trainz A New Era]].&lt;br /&gt;
&lt;br /&gt;
====tunnelcamoffset====&lt;br /&gt;
:Type: Decimal Array&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: 0,0,5&lt;br /&gt;
:Desc: Defines the position of the camera, relative to the cab viewpoint, when the vehicle is travelling in a tunnel.&lt;br /&gt;
&lt;br /&gt;
====tail-lights====&lt;br /&gt;
:Type: [[tail-lights_container|tail-lights container]]&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: Lists the supported tail lights. Added in [[Trainz A New Era]].&lt;br /&gt;
&lt;br /&gt;
====bogeys====&lt;br /&gt;
:Type: [[Bogeys_container|Bogeys Container]]&lt;br /&gt;
:Compulsory: Yes (from 3.4)&lt;br /&gt;
:Default: Nothing&lt;br /&gt;
:Desc: Specifies what bogies are attached where, and with what modifiers. Documented separately [[Bogeys_container|here]].&lt;br /&gt;
&lt;br /&gt;
==Obsolete Tags==&lt;br /&gt;
The following tags will be recognised as valid in earlier builds, but obsolete for this build.&lt;br /&gt;
*		max_permitted_speed&lt;br /&gt;
*		bluestar_coupler&lt;br /&gt;
*		bluestar_brake&lt;br /&gt;
*		bluestar_multiple&lt;br /&gt;
*		bluestar_shell&lt;br /&gt;
*		bluestar_walk&lt;br /&gt;
*		bluestar_trainheat&lt;br /&gt;
*		origin&lt;br /&gt;
*		backlength&lt;br /&gt;
*		backpivot&lt;br /&gt;
*		frontlength&lt;br /&gt;
*		frontpivot&lt;br /&gt;
*		paintshed-template-used&lt;br /&gt;
*		paintshed-skin-used&lt;br /&gt;
*		real-engine&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Attachment Point Usage==&lt;br /&gt;
[[KIND Traincar]] assets have a variety of [[Vehicle Attachment Points|system-defined attachment points]] names.&lt;br /&gt;
&lt;br /&gt;
==mesh-table Usage==&lt;br /&gt;
[[KIND Traincar]] assets have some system-defined [[&amp;quot;mesh-table&amp;quot; container]] names which are reserved for the following uses:&lt;br /&gt;
* &amp;quot;default-night&amp;quot; - A regular mesh with this name will be shown in &amp;quot;night conditions&amp;quot; while the train headlights are active. No custom rendering effects are applied to this mesh. It is recommended that this mesh is set as &amp;quot;auto-create 0&amp;quot;. You may wish to consider setting an emissive color on this mesh in your modelling software (eg. Max.)&lt;br /&gt;
* &amp;quot;default-night-forward&amp;quot; - A regular mesh with this name will be shown when the forward-facing headlights are lit. No custom rendering effects are applied to this mesh. It is recommended that this mesh is set as &amp;quot;auto-create 0&amp;quot;. You may wish to consider setting an emissive color on this mesh in your modelling software (eg. Max.)&lt;br /&gt;
* &amp;quot;default-night-backward&amp;quot; - A regular mesh with this name will be shown when the backward-facing headlights are lit. No custom rendering effects are applied to this mesh. It is recommended that this mesh is set as &amp;quot;auto-create 0&amp;quot;. You may wish to consider setting an emissive color on this mesh in your modelling software (eg. Max.)&lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
Sample [[config.txt file]] for a traincar asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind                   &amp;quot;traincar&amp;quot;&lt;br /&gt;
 engine                 1&lt;br /&gt;
 mass                   100000&lt;br /&gt;
 max-tractive-effort    400000&lt;br /&gt;
 &lt;br /&gt;
 max-coupler-gap        0.1&lt;br /&gt;
 &lt;br /&gt;
 interior               &amp;lt;kuid:523:666&amp;gt;&lt;br /&gt;
 enginespec             &amp;lt;kuid:-1:42004221&amp;gt;&lt;br /&gt;
 enginesound            &amp;lt;kuid:-1:42003000&amp;gt;&lt;br /&gt;
 hornsound              &amp;lt;kuid:-1:42003101&amp;gt;&lt;br /&gt;
 pantograph             &amp;lt;kuid:-1:101395&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 smoke_shade            0.3&lt;br /&gt;
 smoke_random           2.5&lt;br /&gt;
 smoke_slowlife         6&lt;br /&gt;
 smoke_fastlife         0.8&lt;br /&gt;
 smoke_height           1.7&lt;br /&gt;
 smoke_fastspeed        1.6&lt;br /&gt;
 &lt;br /&gt;
 fonts                  2&lt;br /&gt;
 fonts-path             &amp;quot;traincar&amp;quot;&lt;br /&gt;
 interior-light-texture &amp;quot;traincar-interior&amp;quot;&lt;br /&gt;
 interior-light-color 0.75, 0.75, 0.75&lt;br /&gt;
 &lt;br /&gt;
 [[%22mesh-table%22_Container|mesh-table]] {&lt;br /&gt;
   default {&lt;br /&gt;
     mesh               &amp;quot;traincar-body.im&amp;quot;&lt;br /&gt;
     auto-create        1&lt;br /&gt;
   }&lt;br /&gt;
   shadow {&lt;br /&gt;
     mesh               &amp;quot;shadow\traincar-shadow.im&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 [[Bogeys_container|bogeys]] {&lt;br /&gt;
   0 {&lt;br /&gt;
     reversed           0&lt;br /&gt;
     rotation-permitted 0&lt;br /&gt;
     sideplay-permitted 0&lt;br /&gt;
     bogey              &amp;lt;KUID2:xxxxx:yyyyy:zzz&amp;gt;&lt;br /&gt;
   }&lt;br /&gt;
   1 {&lt;br /&gt;
     reversed           0&lt;br /&gt;
     bogey              &amp;lt;KUID2:xxxxx:yyyyy:zzz&amp;gt;&lt;br /&gt;
   }&lt;br /&gt;
   2 {&lt;br /&gt;
     reversed           0&lt;br /&gt;
     sideplay-permitted 1&lt;br /&gt;
     bogey              &amp;lt;KUID2:xxxxx:yyyyy:zzz&amp;gt;&lt;br /&gt;
   }&lt;br /&gt;
   3 {&lt;br /&gt;
     reversed           0&lt;br /&gt;
     sideplay-permitted 1&lt;br /&gt;
     bogey              &amp;lt;KUID2:xxxxx:yyyyy:zzz&amp;gt;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 company                &amp;quot;Company Name&amp;quot;&lt;br /&gt;
 description            &amp;quot;Textual description of traincar in English&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
* [[Media:SD40-2.zip]] - The MAX source for the [[Auran]] [[TS2009]] SD40-2 traincar. Distributed from the TrainzDev site for education purposes only. No license for the reproduction or redistribution of the included model or textures is granted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND|T]]&lt;br /&gt;
{{ORP-bot}}&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Engine&amp;diff=47573</id>
		<title>KIND Engine</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Engine&amp;diff=47573"/>
		<updated>2026-09-30T23:11:08Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Engine]] assets control the engine behaviour of traincar assets, including power output and braking capabilities.&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* [[KIND Steam-engine]]&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;engine&amp;quot;&lt;br /&gt;
 [[throttle-power_container|throttle-power]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[dynamic-brake_container|dynamic-brake]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[motor_container|motor]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[mass_container|mass]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[volume_container|volume]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[pressure_container|pressure]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[flowsize_container|flowsize]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 throttle-power-extended-notch-range 0&lt;br /&gt;
 dynamic-brake-extended-notch-range 0&lt;br /&gt;
 autopilot-stop-distance 5.0&lt;br /&gt;
 autopilot-crawl-distance 20.0&lt;br /&gt;
 autopilot-caution-speed-multiplier 0.5&lt;br /&gt;
 throttle-adjustment-rate 0.01&lt;br /&gt;
 scale &amp;quot;&amp;quot;&lt;br /&gt;
 epbrakes &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====throttle-power====&lt;br /&gt;
:Type: [[throttle-power_container|throttle-power Container]]&lt;br /&gt;
:Desc: Specifies the power output (in kN) of the engine for a given throttle notch and train speed.&lt;br /&gt;
&lt;br /&gt;
====dynamic-brake====&lt;br /&gt;
:Type: [[dynamic-brake_container|dynamic-brake Container]]&lt;br /&gt;
:Desc: Specifies the power output (in kN) of the dynamic brake for a given throttle notch and train speed.&lt;br /&gt;
&lt;br /&gt;
====throttle-power-extended-notch-range====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Whether this engine asset specifies more than the default of 8 throttle notches in the throttle-power graph.&lt;br /&gt;
:Vers: Requires a minimum of trainz-version 5.8&lt;br /&gt;
&lt;br /&gt;
====dynamic-brake-extended-notch-range====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Whether this engine asset specifies more than the default of 8 throttle notches in the dynamic-brake graph.&lt;br /&gt;
:Vers: Requires a minimum of trainz-version 5.8&lt;br /&gt;
&lt;br /&gt;
====motor====&lt;br /&gt;
:Type: [[motor_container|motor Container]]&lt;br /&gt;
:Desc: Sets various values related to the train motor/engine, along with some resistance values.&lt;br /&gt;
&lt;br /&gt;
====mass====&lt;br /&gt;
:Type: [[mass_container|mass Container]]&lt;br /&gt;
:Desc: Sets various mass values for the train.&lt;br /&gt;
&lt;br /&gt;
====volume====&lt;br /&gt;
:Type: [[volume_container|volume Container]]&lt;br /&gt;
:Desc: Sets various volume values for the train braking system.&lt;br /&gt;
&lt;br /&gt;
====pressure====&lt;br /&gt;
:Type: [[pressure_container|pressure Container]]&lt;br /&gt;
:Desc: Sets various pressure values for the train braking system.&lt;br /&gt;
&lt;br /&gt;
====flowsize====&lt;br /&gt;
:Type: [[flowsize_container|flowsize Container]]&lt;br /&gt;
:Desc: Sets various flow size values for the train braking system.&lt;br /&gt;
&lt;br /&gt;
====scale====&lt;br /&gt;
:Type: Obsolete&lt;br /&gt;
:Desc: Obsolete&lt;br /&gt;
&lt;br /&gt;
====epbrakes====&lt;br /&gt;
:Type: Obsolete&lt;br /&gt;
:Desc: Obsolete&lt;br /&gt;
&lt;br /&gt;
====autopilot-stop-distance====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: How far (in meters) in front of a typical obstruction (red light, etc.) the AI will attempt to stop the train. Changing this value can help fine-tune the accuracy of the AI&#039;s movement, however attempting to make the train stop too close to a target may result in overruns in some cases. This tag is intended for special-case usage only.&lt;br /&gt;
&lt;br /&gt;
====autopilot-crawl-distance====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: Once this distance (in meters) from the intended stopping position has been reached, the AI will &#039;crawl&#039; rather than attempt to speed up to reach its destination. Changing this value can help fine-tune the accuracy of the AI&#039;s movement, however attempting to make the train stop too close to a target may result in overruns in some cases. This tag is intended for special-case usage only.&lt;br /&gt;
&lt;br /&gt;
====autopilot-caution-speed-multiplier====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: The AI will slow to this multiple of the speed limit when operating under caution conditions. This can be set to 1.0 in order to effectively remove caution-speed driving, however this can increase the risk of overruns in some cases&lt;br /&gt;
&lt;br /&gt;
====throttle-adjustment-rate====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: Defines the adjustment rate at which the engine&#039;s throttle will adjust to match the train&#039;s throttle. Increasing this rate will make the engine more responsive at the possible cost of audio or driving realism. In DCC mode, a minimum value of 0.1 is used.&lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
Sample [[config.txt file]] for an enginespec asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TBD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND]]&lt;br /&gt;
&lt;br /&gt;
[[Category:TBD]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=%22Volume%22_container&amp;diff=47572</id>
		<title>&quot;Volume&quot; container</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=%22Volume%22_container&amp;diff=47572"/>
		<updated>2026-09-30T23:04:19Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Volume container is a top-level [[config.txt file]] entry used by [[KIND Engine|Enginespec]] and [[KIND Steam-engine|Steam Enginespec]] assets. It specifies the volume of the various pipes and reservoirs in the train braking system.&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
The Volume container supports the following tags. Each tag is show here with its default value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 volume&lt;br /&gt;
 {&lt;br /&gt;
     scale 1.0&lt;br /&gt;
     trainbrakepipe 0.2&lt;br /&gt;
     epreservoirpipe 0.2&lt;br /&gt;
     no3pipe 0.2&lt;br /&gt;
     no4pipe 0.2&lt;br /&gt;
     auxreservoir 0.0384678&lt;br /&gt;
     autobrakecylinder 0.00969387&lt;br /&gt;
     vacuumbrakepipe 0.0&lt;br /&gt;
     vacuumbrakereservoir 0.0&lt;br /&gt;
     vacuumbrakecylinder 0.0&lt;br /&gt;
     mainreservoir 1.0&lt;br /&gt;
     equaliser 0.5&lt;br /&gt;
     independantbrakecylinder 0.0103239&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====scale====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Sets the scale for the given pressure values. This allows an engine asset to provide values in imperial units, and then rescale them to the expected SI units.&lt;br /&gt;
&lt;br /&gt;
====trainbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: brake pipe volume.&lt;br /&gt;
&lt;br /&gt;
====epreservoirpipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For electro pneumatic braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====no3pipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Independent brake pipe.&lt;br /&gt;
&lt;br /&gt;
====no4pipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Bail pipe volume.&lt;br /&gt;
&lt;br /&gt;
====auxreservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Auxiliary reservoir volume.&lt;br /&gt;
&lt;br /&gt;
====autobrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Brake cylinder volume.&lt;br /&gt;
&lt;br /&gt;
====vacuumbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For vacuum braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====vacuumbrakereservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For vacuum braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====vacuumbrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For vacuum braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====mainreservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Main reservoir volume.&lt;br /&gt;
&lt;br /&gt;
====equaliser====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Equalising reservoir volume.&lt;br /&gt;
&lt;br /&gt;
====independantbrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Loco brake cylinder volume.&lt;br /&gt;
&lt;br /&gt;
==Example volume container==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TBD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Config Container|V]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=%22Flowsize%22_container&amp;diff=47571</id>
		<title>&quot;Flowsize&quot; container</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=%22Flowsize%22_container&amp;diff=47571"/>
		<updated>2026-09-30T23:03:38Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Flowsize container is a top-level [[config.txt file]] entry used by [[KIND Engine|Enginespec]] and [[KIND Steam-engine|Steam Enginespec]] assets. It controls the rate at which pressure can move between the various pipes and reservoirs in the train braking system.&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
The Flowsize container supports the following tags. Each tag is show here with its default value.&lt;br /&gt;
&lt;br /&gt;
 flowsize&lt;br /&gt;
 {&lt;br /&gt;
     trainbrakepipe 170000&lt;br /&gt;
     epreservoirpipe 0.1&lt;br /&gt;
     no3pipe 0.1&lt;br /&gt;
     no4pipe 0.1&lt;br /&gt;
     auxreservoirvent 0.1&lt;br /&gt;
     auxreservoir_no3 0.1&lt;br /&gt;
     auxreservoir_trainbrakepipe 0.1&lt;br /&gt;
     autobrakecylindervent 0.1&lt;br /&gt;
     equaliser_mainreservoir 0.06&lt;br /&gt;
     equaliservent 0.06&lt;br /&gt;
     equaliserventhandleoff 0.1&lt;br /&gt;
     equaliserventemergency 0.1&lt;br /&gt;
     no3pipevent 1.5&lt;br /&gt;
     no3pipe_mainreservoir 0.1&lt;br /&gt;
     compressor 5&lt;br /&gt;
     trainbrakepipe_reservoir 1&lt;br /&gt;
     trainbrakepipevent 0.06&lt;br /&gt;
     no3pipe_autobrakecylinder 0.1&lt;br /&gt;
     epreservoirpipe_autobrakecylinder 0.1&lt;br /&gt;
     mainreservoir_ep 0.1&lt;br /&gt;
     vacuumbrakepipe 0.1&lt;br /&gt;
     vacuumbrakepipereleasevent 0.1&lt;br /&gt;
     vacuumbrakepipevent 0.1&lt;br /&gt;
     vacuumbrakereservoir_vacuumbrakepipe 0.1&lt;br /&gt;
     vacuumbrakecylinder_vacuumbrakepipe 0.1&lt;br /&gt;
     highspeedexhauster_vacuumbrakepipe 0.1&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====trainbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====epreservoirpipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====no3pipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====no4pipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====auxreservoirvent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====auxreservoir_no3====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====auxreservoir_trainbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====autobrakecylindervent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====equaliser_mainreservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====equaliservent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====equaliserventhandleoff====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====equaliserventemergency====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====no3pipevent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====no3pipe_mainreservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====compressor====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====trainbrakepipe_reservoir====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====trainbrakepipevent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====no3pipe_autobrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====epreservoirpipe_autobrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====mainreservoir_ep====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====vacuumbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====vacuumbrakepipereleasevent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====vacuumbrakepipevent====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====vacuumbrakereservoir_vacuumbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====vacuumbrakecylinder_vacuumbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
====highspeedexhauster_vacuumbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: &lt;br /&gt;
&lt;br /&gt;
==Example flowsize container==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TBD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Config Container|F]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Engine&amp;diff=47570</id>
		<title>KIND Engine</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Engine&amp;diff=47570"/>
		<updated>2026-09-30T22:59:33Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Engine]] assets contain diesel or electric loco engine performance characteristics.&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* [[KIND Steam-engine]]&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;engine&amp;quot;&lt;br /&gt;
 [[throttle-power_container|throttle-power]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[dynamic-brake_container|dynamic-brake]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[pressure_container|pressure]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[mass_container|mass]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[motor_container|motor]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[flowsize_container|flowsize]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 [[volume_container|volume]]&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 scale &amp;quot;&amp;quot;&lt;br /&gt;
 epbrakes &amp;quot;&amp;quot;&lt;br /&gt;
 autopilot-stop-distance 5.0&lt;br /&gt;
 autopilot-crawl-distance 20.0&lt;br /&gt;
 autopilot-caution-speed-multiplier 0.5&lt;br /&gt;
 throttle-adjustment-rate 0.01&lt;br /&gt;
 throttle-power-extended-notch-range 0&lt;br /&gt;
 dynamic-brake-extended-notch-range 0&lt;br /&gt;
&lt;br /&gt;
====throttle-power====&lt;br /&gt;
:Type: [[throttle-power_container|throttle-power Container]]&lt;br /&gt;
:Desc: Specifies the power output (in kN) of the engine for a given throttle notch and train speed.&lt;br /&gt;
&lt;br /&gt;
====dynamic-brake====&lt;br /&gt;
:Type: [[dynamic-brake_container|dynamic-brake Container]]&lt;br /&gt;
:Desc: Specifies the power output (in kN) of the dynamic brake for a given throttle notch and train speed.&lt;br /&gt;
&lt;br /&gt;
====throttle-power-extended-notch-range====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Whether this engine asset specifies more than the default of 8 throttle notches, in the throttle-power graph.&lt;br /&gt;
:Vers: Requires a minimum of trainz-version 5.8&lt;br /&gt;
&lt;br /&gt;
====dynamic-brake-extended-notch-range====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Whether this engine asset specifies more than the default of 8 throttle notches, in the dynamic-brake graph.&lt;br /&gt;
:Vers: Requires a minimum of trainz-version 5.8&lt;br /&gt;
&lt;br /&gt;
====pressure====&lt;br /&gt;
:Type: [[pressure_container|pressure Container]]&lt;br /&gt;
:Desc: TBD&lt;br /&gt;
&lt;br /&gt;
====mass====&lt;br /&gt;
:Type: [[mass_container|mass Container]]&lt;br /&gt;
:Desc: TBD&lt;br /&gt;
&lt;br /&gt;
====motor====&lt;br /&gt;
:Type: [[motor_container|motor Container]]&lt;br /&gt;
:Desc: TBD&lt;br /&gt;
&lt;br /&gt;
====flowsize====&lt;br /&gt;
:Type: [[flowsize_container|flowsize Container]]&lt;br /&gt;
:Desc: TBD&lt;br /&gt;
&lt;br /&gt;
====volume====&lt;br /&gt;
:Type: [[volume_container|volume Container]]&lt;br /&gt;
:Desc: TBD&lt;br /&gt;
&lt;br /&gt;
====scale====&lt;br /&gt;
:Type: Obsolete&lt;br /&gt;
:Desc: Obsolete&lt;br /&gt;
&lt;br /&gt;
====epbrakes====&lt;br /&gt;
:Type: Obsolete&lt;br /&gt;
:Desc: Obsolete&lt;br /&gt;
&lt;br /&gt;
====autopilot-stop-distance====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: How far (in meters) in front of a typical obstruction (red light, etc.) the AI will attempt to stop the train. Changing this value can help fine-tune the accuracy of the AI&#039;s movement, however attempting to make the train stop too close to a target may result in overruns in some cases. This tag is intended for special-case usage only.&lt;br /&gt;
&lt;br /&gt;
====autopilot-crawl-distance====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: Once this distance (in meters) from the intended stopping position has been reached, the AI will &#039;crawl&#039; rather than attempt to speed up to reach its destination. Changing this value can help fine-tune the accuracy of the AI&#039;s movement, however attempting to make the train stop too close to a target may result in overruns in some cases. This tag is intended for special-case usage only.&lt;br /&gt;
&lt;br /&gt;
====autopilot-caution-speed-multiplier====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: The AI will slow to this multiple of the speed limit when operating under caution conditions. This can be set to 1.0 in order to effectively remove caution-speed driving, however this can increase the risk of overruns in some cases&lt;br /&gt;
&lt;br /&gt;
====throttle-adjustment-rate====&lt;br /&gt;
:Type: float&lt;br /&gt;
:Desc: Defines the adjustment rate at which the engine&#039;s throttle will adjust to match the train&#039;s throttle. Increasing this rate will make the engine more responsive at the possible cost of audio or driving realism. In DCC mode, a minimum value of 0.1 is used.&lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
Sample [[config.txt file]] for an enginespec asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TBD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND]]&lt;br /&gt;
&lt;br /&gt;
[[Category:TBD]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47559</id>
		<title>KIND Enginesound</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47559"/>
		<updated>2026-09-17T09:40:58Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Enginesound]] assets are locomotive enginesounds.&lt;br /&gt;
&lt;br /&gt;
There is only one enginesound asset type, which may be used for Steam, Diesel or Electric locomotives.&lt;br /&gt;
&lt;br /&gt;
Most modern diesel/electric engine sounds use the &amp;quot;ramping sound&amp;quot; configuration, which plays a looped sound file matched to the standard 8 throttle notches. Transition sounds can also be provided for changing up/down a throttle notch.&lt;br /&gt;
&lt;br /&gt;
Trainz also supports a non-ramped configuration, which plays a single engine sound loop and applies a frequency shift based on train speed.&lt;br /&gt;
&lt;br /&gt;
Steam engine sounds play a number of individual &#039;chuff&#039; files at low speed, then switch to a series of frequency shifted loop sounds at higher speeds.&lt;br /&gt;
&lt;br /&gt;
NOTE: As engine sounds are positional, all files should be &#039;mono&#039; (i.e. single channel). If stereo files are provided then positional effects may not work, or the sound may not play at all.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* &#039;&#039;none.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-duration 1.5&lt;br /&gt;
 engine-sound-ramp-up-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 engine-sound-ramp-down-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 speedup 2.2&lt;br /&gt;
 isfading 0&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====isramping====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Specifies whether the asset uses the &#039;ramping&#039; sound style (default true). When enabled, the enginesound must provide 8 &amp;quot;Idle X.wav&amp;quot; files, one for each throttle notch.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-duration====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Decimal.&lt;br /&gt;
:Desc: Sets the default duration of the transition sounds used to change between notches. If the individual ramp-up/down tags are not provided, or have insufficient values, this value will be used for the unspecified lengths.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-up-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;start.wav&amp;quot;, through to &amp;quot;up 7 - 8.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-down-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;stop.wav&amp;quot;, through to &amp;quot;down 8 - 7.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0. &lt;br /&gt;
&lt;br /&gt;
====speedup====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Used only when isramping is false. This controls the rate of frequency change for the sound loop based on speed. A value of 1.0 would mean the top frequency used is as much again as the base frequency - in other words, the frequency of the sound played would double over the speed range of the vehicle.&lt;br /&gt;
&lt;br /&gt;
====isfading====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Used only when isramping is false. If true, the engine sound loops volume will fade in (i.e. get louder) as loco speed increases.&lt;br /&gt;
&lt;br /&gt;
====number-slow-sounds====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Specifies the number of &#039;chuff&#039; sounds in a steam enginesound. These will be played in sequence as the loco crawls forward at low speed.&lt;br /&gt;
&lt;br /&gt;
====number-cylinders====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of cylinders in the locomotive for a steam enginesound. This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
====number-power-strokes====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of power strokes in the locomotive for a steam enginesound (should generally be left at the default, 2). This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
:Refer to [[TS12 Doppler]] for usage examples.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
====Diesel====&lt;br /&gt;
Sample [[config.txt file]] for a diesel type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-up-durations 14.706,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
 engine-sound-ramp-down-durations 12.286,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
&lt;br /&gt;
====Electric====&lt;br /&gt;
Sample [[config.txt file]] for an electric type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 0&lt;br /&gt;
 isfading 0&lt;br /&gt;
 speedup 4.0&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
Sample [[config.txt file]] for a steam type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wave file naming==&lt;br /&gt;
&lt;br /&gt;
====Ramping====&lt;br /&gt;
In a &#039;ramping&#039; diesel/electric enginesound, the following &#039;idle&#039; sound files are expected:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! idle 1.wav&lt;br /&gt;
! engine idle / notch 1 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 2.wav&lt;br /&gt;
! notch 2 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 3.wav&lt;br /&gt;
! notch 3 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 4.wav&lt;br /&gt;
! notch 4 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 5.wav&lt;br /&gt;
! notch 5 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 6.wav&lt;br /&gt;
! notch 6 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 7.wav&lt;br /&gt;
! notch 7 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 8.wav&lt;br /&gt;
! notch 8 sound&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following transition sounds are also supported, but any individual file can be omitted if no transition is required/desired.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! start.wav&lt;br /&gt;
! engine startup&lt;br /&gt;
|-&lt;br /&gt;
! stop.wav&lt;br /&gt;
! engine shutdown&lt;br /&gt;
|-&lt;br /&gt;
! up 1 - 2.wav&lt;br /&gt;
! transition between notch 1 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! up 2 - 3.wav&lt;br /&gt;
! transition between notch 2 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! up 3 - 4.wav&lt;br /&gt;
! transition between notch 3 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! up 4 - 5.wav&lt;br /&gt;
! transition between notch 4 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! up 5 - 6.wav&lt;br /&gt;
! transition between notch 5 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! up 6 - 7.wav&lt;br /&gt;
! transition between notch 6 and notch 7&lt;br /&gt;
|-&lt;br /&gt;
! up 7 - 8.wav&lt;br /&gt;
! transition between notch 7 and notch 8&lt;br /&gt;
|-&lt;br /&gt;
! down 2 - 1.wav&lt;br /&gt;
! transition between notch 2 and notch 1&lt;br /&gt;
|-&lt;br /&gt;
! down 3 - 2.wav&lt;br /&gt;
! transition between notch 3 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! down 4 - 3.wav&lt;br /&gt;
! transition between notch 4 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! down 5 - 4.wav&lt;br /&gt;
! transition between notch 5 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! down 6 - 5.wav&lt;br /&gt;
! transition between notch 6 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! down 7 - 6.wav&lt;br /&gt;
! transition between notch 7 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! down 8 - 7.wav&lt;br /&gt;
! transition between notch 8 and notch 7&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Non-ramping====&lt;br /&gt;
&lt;br /&gt;
In a non ramping engine sound only one file is used: engine_loop.wav.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
&lt;br /&gt;
These are background sounds for when the loco is stationary. The fast will be played when the loco has just stopped, and if it is left for a while, the sound will progress down to &#039;med&#039; and then eventually &#039;slow&#039;.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_fast.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_med.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_slow.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The low speed &#039;chuff&#039; sounds are named &amp;quot;piston_strokeX.wav&amp;quot;, where X is an index from 1 to the value specified by the &#039;number-slow-sounds&#039; tag.&lt;br /&gt;
&lt;br /&gt;
For example, if number-slow-sounds is set to &#039;4&#039; (the default).&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke1.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke2.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke3.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke4.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following loops are played as the loco picks up speed. They are frequency shifted to match the wheel rotation speed, so the audible &#039;chuffs&#039; within the loop maintain synchronisation with the drive bogie animation. They also vary in volume based on the regulator setting of the locomotive.&lt;br /&gt;
&lt;br /&gt;
This system enables sound files to be shared between locomotives with different wheel sizes. 60RPM (which is one revolution per second) on a 2 cylinder loco will produce four chuffs per second irrespective of the wheel size - the only difference this makes is what speed the train will be doing when the drive wheels are rotating at 60RPM.&lt;br /&gt;
&lt;br /&gt;
Any individual file can be omitted from this set - the system will use what files are available and use adjacent files to cover for any missing files.&lt;br /&gt;
&lt;br /&gt;
It is anticipated that a sound creator will pick and choose which wave files are used based on what recordings are available, and that a released enginespec will not have all sound files present - particularly the higher speed ones, which are likely to be irrelevant for most locos, but are provided just in case...&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_30RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_35RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_40RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_50RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_60RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_75RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_90RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_100RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_125RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_150RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_175RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_250RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_300RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_350RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_500RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_700RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_800RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1000RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_2000RPM.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Earlier assets may instead provide a single steam loop sound, titled &amp;quot;steam_loop.wav&amp;quot;. If only this file is present, modern Trainz code will use it with a default of 50RPM, in order to maintain compatibility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following file is also played continually in the background. It&#039;s volume will vary based on train speed.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! smoke_stack_hiss.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND|E]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47558</id>
		<title>KIND Enginesound</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47558"/>
		<updated>2026-09-17T09:40:36Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* Diesel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Enginesound]] assets are locomotive enginesounds.&lt;br /&gt;
&lt;br /&gt;
There is only one enginesound asset type, which may be used for Steam, Diesel or Electric locomotives.&lt;br /&gt;
&lt;br /&gt;
Most modern diesel/electric engine sounds use the &amp;quot;ramping sound&amp;quot; configuration, which plays a looped sound file matched to the standard 8 throttle notches. Transition sounds can also be provided for changing up/down a throttle notch.&lt;br /&gt;
&lt;br /&gt;
Trainz also supports a non-ramped configuration, which plays a single engine sound loop and applies a frequency shift based on train speed.&lt;br /&gt;
&lt;br /&gt;
Steam engine sounds play a number of individual &#039;chuff&#039; files at low speed, then switch to a series of frequency shifted loop sounds at higher speeds.&lt;br /&gt;
&lt;br /&gt;
NOTE: As engine sounds are positional, all files should be &#039;mono&#039; (i.e. single channel). If stereo files are provided then positional effects may not work, or the sound may not play at all.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* &#039;&#039;none.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-duration 1.5&lt;br /&gt;
 engine-sound-ramp-up-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 engine-sound-ramp-down-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 speedup 2.2&lt;br /&gt;
 isfading 0&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====isramping====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Specifies whether the asset uses the &#039;ramping&#039; sound style (default true). When enabled, the enginesound must provide 8 &amp;quot;Idle X.wav&amp;quot; files, one for each throttle notch.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-duration====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Decimal.&lt;br /&gt;
:Desc: Sets the default duration of the transition sounds used to change between notches. If the individual ramp-up/down tags are not provided, or have insufficient values, this value will be used for the unspecified lengths.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-up-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;start.wav&amp;quot;, through to &amp;quot;up 7 - 8.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-down-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;stop.wav&amp;quot;, through to &amp;quot;down 8 - 7.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0. &lt;br /&gt;
&lt;br /&gt;
====speedup====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Used only when isramping is false. This controls the rate of frequency change for the sound loop based on speed. A value of 1.0 would mean the top frequency used is as much again as the base frequency - in other words, the frequency of the sound played would double over the speed range of the vehicle.&lt;br /&gt;
&lt;br /&gt;
====isfading====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Used only when isramping is false. If true, the engine sound loops volume will fade in (i.e. get louder) as loco speed increases.&lt;br /&gt;
&lt;br /&gt;
====number-slow-sounds====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Specifies the number of &#039;chuff&#039; sounds in a steam enginesound. These will be played in sequence as the loco crawls forward at low speed.&lt;br /&gt;
&lt;br /&gt;
====number-cylinders====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of cylinders in the locomotive for a steam enginesound. This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
====number-power-strokes====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of power strokes in the locomotive for a steam enginesound (should generally be left at the default, 2). This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
:Refer to [[TS12 Doppler]] for usage examples.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
====Diesel====&lt;br /&gt;
Sample [[config.txt file]] for a diesel type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-up-durations 14.706,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
 engine-sound-ramp-down-durations 12.286,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
&lt;br /&gt;
====Electric====&lt;br /&gt;
Sample [[config.txt file]] for an electric type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 0&lt;br /&gt;
 isfading 0&lt;br /&gt;
 speedup 4.0&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
Sample [[config.txt file]] for a steam type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wave file naming==&lt;br /&gt;
&lt;br /&gt;
====Ramping====&lt;br /&gt;
In a &#039;ramping&#039; diesel/electric enginesound, the following &#039;idle&#039; sound files are expected:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! idle 1.wav&lt;br /&gt;
! engine idle / notch 1 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 2.wav&lt;br /&gt;
! notch 2 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 3.wav&lt;br /&gt;
! notch 3 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 4.wav&lt;br /&gt;
! notch 4 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 5.wav&lt;br /&gt;
! notch 5 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 6.wav&lt;br /&gt;
! notch 6 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 7.wav&lt;br /&gt;
! notch 7 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 8.wav&lt;br /&gt;
! notch 8 sound&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following transition sounds are also supported, but any individual file can be omitted if no transition is required/desired.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! start.wav&lt;br /&gt;
! engine startup&lt;br /&gt;
|-&lt;br /&gt;
! stop.wav&lt;br /&gt;
! engine shutdown&lt;br /&gt;
|-&lt;br /&gt;
! up 1 - 2.wav&lt;br /&gt;
! transition between notch 1 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! up 2 - 3.wav&lt;br /&gt;
! transition between notch 2 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! up 3 - 4.wav&lt;br /&gt;
! transition between notch 3 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! up 4 - 5.wav&lt;br /&gt;
! transition between notch 4 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! up 5 - 6.wav&lt;br /&gt;
! transition between notch 5 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! up 6 - 7.wav&lt;br /&gt;
! transition between notch 6 and notch 7&lt;br /&gt;
|-&lt;br /&gt;
! up 7 - 8.wav&lt;br /&gt;
! transition between notch 7 and notch 8&lt;br /&gt;
|-&lt;br /&gt;
! down 2 - 1.wav&lt;br /&gt;
! transition between notch 2 and notch 1&lt;br /&gt;
|-&lt;br /&gt;
! down 3 - 2.wav&lt;br /&gt;
! transition between notch 3 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! down 4 - 3.wav&lt;br /&gt;
! transition between notch 4 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! down 5 - 4.wav&lt;br /&gt;
! transition between notch 5 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! down 6 - 5.wav&lt;br /&gt;
! transition between notch 6 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! down 7 - 6.wav&lt;br /&gt;
! transition between notch 7 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! down 8 - 7.wav&lt;br /&gt;
! transition between notch 8 and notch 7&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Non-ramping====&lt;br /&gt;
&lt;br /&gt;
In a non ramping engine sound only one file is used: engine_loop.wav.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
&lt;br /&gt;
These are background sounds for when the loco is stationary. The fast will be played when the loco has just stopped, and if it is left for a while, the sound will progress down to &#039;med&#039; and then eventually &#039;slow&#039;.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_fast.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_med.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_slow.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The low speed &#039;chuff&#039; sounds are named &amp;quot;piston_strokeX.wav&amp;quot;, where X is an index from 1 to the value specified by the &#039;number-slow-sounds&#039; tag.&lt;br /&gt;
&lt;br /&gt;
For example, if number-slow-sounds is set to &#039;4&#039; (the default).&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke1.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke2.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke3.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke4.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following loops are played as the loco picks up speed. They are frequency shifted to match the wheel rotation speed, so the audible &#039;chuffs&#039; within the loop maintain synchronisation with the drive bogie animation. They also vary in volume based on the regulator setting of the locomotive.&lt;br /&gt;
&lt;br /&gt;
This system enables sound files to be shared between locomotives with different wheel sizes. 60RPM (which is one revolution per second) on a 2 cylinder loco will produce four chuffs per second irrespective of the wheel size - the only difference this makes is what speed the train will be doing when the drive wheels are rotating at 60RPM.&lt;br /&gt;
&lt;br /&gt;
Any individual file can be omitted from this set - the system will use what files are available and use adjacent files to cover for any missing files.&lt;br /&gt;
&lt;br /&gt;
It is anticipated that a sound creator will pick and choose which wave files are used based on what recordings are available, and that a released enginespec will not have all sound files present - particularly the higher speed ones, which are likely to be irrelevant for most locos, but are provided just in case...&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_30RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_35RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_40RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_50RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_60RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_75RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_90RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_100RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_125RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_150RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_175RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_250RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_300RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_350RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_500RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_700RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_800RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1000RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_2000RPM.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Earlier assets may instead provide a single steam loop sound, titled &amp;quot;steam_loop.wav&amp;quot;. If only this file is present, modern Trainz code will use it with a default of 50RPM, in order to maintain compatibility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following file is also played continually in the background. It&#039;s volume will vary based on train speed.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! smoke_stack_hiss.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND|E]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47557</id>
		<title>KIND Enginesound</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47557"/>
		<updated>2026-09-17T09:40:06Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Enginesound]] assets are locomotive enginesounds.&lt;br /&gt;
&lt;br /&gt;
There is only one enginesound asset type, which may be used for Steam, Diesel or Electric locomotives.&lt;br /&gt;
&lt;br /&gt;
Most modern diesel/electric engine sounds use the &amp;quot;ramping sound&amp;quot; configuration, which plays a looped sound file matched to the standard 8 throttle notches. Transition sounds can also be provided for changing up/down a throttle notch.&lt;br /&gt;
&lt;br /&gt;
Trainz also supports a non-ramped configuration, which plays a single engine sound loop and applies a frequency shift based on train speed.&lt;br /&gt;
&lt;br /&gt;
Steam engine sounds play a number of individual &#039;chuff&#039; files at low speed, then switch to a series of frequency shifted loop sounds at higher speeds.&lt;br /&gt;
&lt;br /&gt;
NOTE: As engine sounds are positional, all files should be &#039;mono&#039; (i.e. single channel). If stereo files are provided then positional effects may not work, or the sound may not play at all.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* &#039;&#039;none.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-duration 1.5&lt;br /&gt;
 engine-sound-ramp-up-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 engine-sound-ramp-down-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 speedup 2.2&lt;br /&gt;
 isfading 0&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====isramping====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Specifies whether the asset uses the &#039;ramping&#039; sound style (default true). When enabled, the enginesound must provide 8 &amp;quot;Idle X.wav&amp;quot; files, one for each throttle notch.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-duration====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Decimal.&lt;br /&gt;
:Desc: Sets the default duration of the transition sounds used to change between notches. If the individual ramp-up/down tags are not provided, or have insufficient values, this value will be used for the unspecified lengths.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-up-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;start.wav&amp;quot;, through to &amp;quot;up 7 - 8.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-down-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;stop.wav&amp;quot;, through to &amp;quot;down 8 - 7.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0. &lt;br /&gt;
&lt;br /&gt;
====speedup====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Used only when isramping is false. This controls the rate of frequency change for the sound loop based on speed. A value of 1.0 would mean the top frequency used is as much again as the base frequency - in other words, the frequency of the sound played would double over the speed range of the vehicle.&lt;br /&gt;
&lt;br /&gt;
====isfading====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Used only when isramping is false. If true, the engine sound loops volume will fade in (i.e. get louder) as loco speed increases.&lt;br /&gt;
&lt;br /&gt;
====number-slow-sounds====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Specifies the number of &#039;chuff&#039; sounds in a steam enginesound. These will be played in sequence as the loco crawls forward at low speed.&lt;br /&gt;
&lt;br /&gt;
====number-cylinders====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of cylinders in the locomotive for a steam enginesound. This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
====number-power-strokes====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of power strokes in the locomotive for a steam enginesound (should generally be left at the default, 2). This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
:Refer to [[TS12 Doppler]] for usage examples.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
====Diesel====&lt;br /&gt;
Sample [[config.txt file]] for a diesel type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-up-durations 14.706,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
 engine-sound-ramp-down-durations 12.286,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
&lt;br /&gt;
====Electric====&lt;br /&gt;
Sample [[config.txt file]] for an electric type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 0&lt;br /&gt;
 isfading 0&lt;br /&gt;
 speedup 4.0&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
Sample [[config.txt file]] for a steam type &#039;enginesound&#039; asset, with the standard tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wave file naming==&lt;br /&gt;
&lt;br /&gt;
====Diesel====&lt;br /&gt;
In a &#039;ramping&#039; diesel/electric enginesound, the following &#039;idle&#039; sound files are expected:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! idle 1.wav&lt;br /&gt;
! engine idle / notch 1 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 2.wav&lt;br /&gt;
! notch 2 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 3.wav&lt;br /&gt;
! notch 3 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 4.wav&lt;br /&gt;
! notch 4 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 5.wav&lt;br /&gt;
! notch 5 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 6.wav&lt;br /&gt;
! notch 6 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 7.wav&lt;br /&gt;
! notch 7 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 8.wav&lt;br /&gt;
! notch 8 sound&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following transition sounds are also supported, but any individual file can be omitted if no transition is required/desired.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! start.wav&lt;br /&gt;
! engine startup&lt;br /&gt;
|-&lt;br /&gt;
! stop.wav&lt;br /&gt;
! engine shutdown&lt;br /&gt;
|-&lt;br /&gt;
! up 1 - 2.wav&lt;br /&gt;
! transition between notch 1 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! up 2 - 3.wav&lt;br /&gt;
! transition between notch 2 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! up 3 - 4.wav&lt;br /&gt;
! transition between notch 3 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! up 4 - 5.wav&lt;br /&gt;
! transition between notch 4 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! up 5 - 6.wav&lt;br /&gt;
! transition between notch 5 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! up 6 - 7.wav&lt;br /&gt;
! transition between notch 6 and notch 7&lt;br /&gt;
|-&lt;br /&gt;
! up 7 - 8.wav&lt;br /&gt;
! transition between notch 7 and notch 8&lt;br /&gt;
|-&lt;br /&gt;
! down 2 - 1.wav&lt;br /&gt;
! transition between notch 2 and notch 1&lt;br /&gt;
|-&lt;br /&gt;
! down 3 - 2.wav&lt;br /&gt;
! transition between notch 3 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! down 4 - 3.wav&lt;br /&gt;
! transition between notch 4 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! down 5 - 4.wav&lt;br /&gt;
! transition between notch 5 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! down 6 - 5.wav&lt;br /&gt;
! transition between notch 6 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! down 7 - 6.wav&lt;br /&gt;
! transition between notch 7 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! down 8 - 7.wav&lt;br /&gt;
! transition between notch 8 and notch 7&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Non-ramping====&lt;br /&gt;
&lt;br /&gt;
In a non ramping engine sound only one file is used: engine_loop.wav.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
&lt;br /&gt;
These are background sounds for when the loco is stationary. The fast will be played when the loco has just stopped, and if it is left for a while, the sound will progress down to &#039;med&#039; and then eventually &#039;slow&#039;.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_fast.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_med.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_slow.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The low speed &#039;chuff&#039; sounds are named &amp;quot;piston_strokeX.wav&amp;quot;, where X is an index from 1 to the value specified by the &#039;number-slow-sounds&#039; tag.&lt;br /&gt;
&lt;br /&gt;
For example, if number-slow-sounds is set to &#039;4&#039; (the default).&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke1.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke2.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke3.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke4.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following loops are played as the loco picks up speed. They are frequency shifted to match the wheel rotation speed, so the audible &#039;chuffs&#039; within the loop maintain synchronisation with the drive bogie animation. They also vary in volume based on the regulator setting of the locomotive.&lt;br /&gt;
&lt;br /&gt;
This system enables sound files to be shared between locomotives with different wheel sizes. 60RPM (which is one revolution per second) on a 2 cylinder loco will produce four chuffs per second irrespective of the wheel size - the only difference this makes is what speed the train will be doing when the drive wheels are rotating at 60RPM.&lt;br /&gt;
&lt;br /&gt;
Any individual file can be omitted from this set - the system will use what files are available and use adjacent files to cover for any missing files.&lt;br /&gt;
&lt;br /&gt;
It is anticipated that a sound creator will pick and choose which wave files are used based on what recordings are available, and that a released enginespec will not have all sound files present - particularly the higher speed ones, which are likely to be irrelevant for most locos, but are provided just in case...&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_30RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_35RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_40RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_50RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_60RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_75RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_90RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_100RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_125RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_150RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_175RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_250RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_300RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_350RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_500RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_700RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_800RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1000RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_2000RPM.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Earlier assets may instead provide a single steam loop sound, titled &amp;quot;steam_loop.wav&amp;quot;. If only this file is present, modern Trainz code will use it with a default of 50RPM, in order to maintain compatibility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following file is also played continually in the background. It&#039;s volume will vary based on train speed.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! smoke_stack_hiss.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND|E]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47556</id>
		<title>KIND Enginesound</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=KIND_Enginesound&amp;diff=47556"/>
		<updated>2026-09-17T07:57:15Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[KIND Enginesound]] assets are locomotive enginesounds.&lt;br /&gt;
&lt;br /&gt;
There is only one enginesound asset type, which may be used for Steam, Diesel or Electric locomotives.&lt;br /&gt;
&lt;br /&gt;
Most modern diesel/electric engine sounds use the &amp;quot;ramping sound&amp;quot; configuration, which plays a looped sound file matched to the standard 8 throttle notches. Transition sounds can also be provided for changing up/down a throttle notch.&lt;br /&gt;
&lt;br /&gt;
Trainz also supports a non-ramped configuration, which plays a single engine sound loop and applies a frequency shift based on train speed.&lt;br /&gt;
&lt;br /&gt;
Steam engine sounds play a number of individual &#039;chuff&#039; files at low speed, then switch to a series of frequency shifted loop sounds at higher speeds.&lt;br /&gt;
&lt;br /&gt;
NOTE: As engine sounds are positional, all files should be &#039;mono&#039; (i.e. single channel). If stereo files are provided then positional effects may not work, or the sound may not play at all.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==KIND Hierarchy==&lt;br /&gt;
===Parent Classes===&lt;br /&gt;
* [[KIND TrainzBaseSpec]]&lt;br /&gt;
===Child Classes===&lt;br /&gt;
* &#039;&#039;none.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-duration 1.5&lt;br /&gt;
 engine-sound-ramp-up-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 engine-sound-ramp-down-durations 0.0,1.5,1.5,1.5,1.5,1.5,1.5,1.5&lt;br /&gt;
 speedup 2.2&lt;br /&gt;
 isfading 0&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====isramping====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Specifies whether the asset uses the &#039;ramping&#039; sound style (default true). When enabled, the enginesound must provide 8 &amp;quot;Idle X.wav&amp;quot; files, one for each throttle notch.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-duration====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Decimal.&lt;br /&gt;
:Desc: Sets the default duration of the transition sounds used to change between notches. If the individual ramp-up/down tags are not provided, or have insufficient values, this value will be used for the unspecified lengths.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-up-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;start.wav&amp;quot;, through to &amp;quot;up 7 - 8.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0.&lt;br /&gt;
&lt;br /&gt;
====engine-sound-ramp-down-durations====&lt;br /&gt;
:New tag for trainz-build 3.6&lt;br /&gt;
:Type: Float list (normally 8 values)&lt;br /&gt;
:Desc: Sets the duration (in seconds) of each throttle notch transition sound, from &amp;quot;stop.wav&amp;quot;, through to &amp;quot;down 8 - 7.wav&amp;quot;.&lt;br /&gt;
:Note: If a specific transition sound is not provided, the duration should be entered as 0. &lt;br /&gt;
&lt;br /&gt;
====speedup====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Used only when isramping is false. This controls the rate of frequency change for the sound loop based on speed. A value of 1.0 would mean the top frequency used is as much again as the base frequency - in other words, the frequency of the sound played would double over the speed range of the vehicle.&lt;br /&gt;
&lt;br /&gt;
====isfading====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Desc: Used only when isramping is false. If true, the engine sound loops volume will fade in (i.e. get louder) as loco speed increases.&lt;br /&gt;
&lt;br /&gt;
====number-slow-sounds====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Specifies the number of &#039;chuff&#039; sounds in a steam enginesound. These will be played in sequence as the loco crawls forward at low speed.&lt;br /&gt;
&lt;br /&gt;
====number-cylinders====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of cylinders in the locomotive for a steam enginesound. This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
====number-power-strokes====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Desc: Number of power strokes in the locomotive for a steam enginesound (should generally be left at the default, 2). This controls the rate of the low speed chuff sounds, and the frequency shift rate for the loop sounds.&lt;br /&gt;
&lt;br /&gt;
:Refer to [[TS12 Doppler]] for usage examples.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
====Diesel====&lt;br /&gt;
Sample [[config.txt file]] for a diesel type &#039;enginesound&#039; asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 1&lt;br /&gt;
 engine-sound-ramp-up-durations 14.706,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
 engine-sound-ramp-down-durations 12.286,7.086,4.241,4.861,3.017,2.245,2.278,5.119&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Electric====&lt;br /&gt;
Sample [[config.txt file]] for an electric type &#039;enginesound&#039; asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 isramping 0&lt;br /&gt;
 isfading 0&lt;br /&gt;
 speedup 4.0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
Sample [[config.txt file]] for a steam type &#039;enginesound&#039; asset, with the Standard Tags excluded for brevity:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;enginesound&amp;quot;&lt;br /&gt;
 number-slow-sounds 4&lt;br /&gt;
 number-cylinders 2&lt;br /&gt;
 number-power-strokes 2&lt;br /&gt;
&lt;br /&gt;
==Wave file naming==&lt;br /&gt;
&lt;br /&gt;
====Diesel====&lt;br /&gt;
In a &#039;ramping&#039; diesel/electric enginesound, the following &#039;idle&#039; sound files are expected:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! idle 1.wav&lt;br /&gt;
! engine idle / notch 1 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 2.wav&lt;br /&gt;
! notch 2 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 3.wav&lt;br /&gt;
! notch 3 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 4.wav&lt;br /&gt;
! notch 4 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 5.wav&lt;br /&gt;
! notch 5 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 6.wav&lt;br /&gt;
! notch 6 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 7.wav&lt;br /&gt;
! notch 7 sound&lt;br /&gt;
|-&lt;br /&gt;
! idle 8.wav&lt;br /&gt;
! notch 8 sound&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The following transition sounds are also supported, but any individual file can be omitted if no transition is required/desired.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! start.wav&lt;br /&gt;
! engine startup&lt;br /&gt;
|-&lt;br /&gt;
! stop.wav&lt;br /&gt;
! engine shutdown&lt;br /&gt;
|-&lt;br /&gt;
! up 1 - 2.wav&lt;br /&gt;
! transition between notch 1 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! up 2 - 3.wav&lt;br /&gt;
! transition between notch 2 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! up 3 - 4.wav&lt;br /&gt;
! transition between notch 3 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! up 4 - 5.wav&lt;br /&gt;
! transition between notch 4 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! up 5 - 6.wav&lt;br /&gt;
! transition between notch 5 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! up 6 - 7.wav&lt;br /&gt;
! transition between notch 6 and notch 7&lt;br /&gt;
|-&lt;br /&gt;
! up 7 - 8.wav&lt;br /&gt;
! transition between notch 7 and notch 8&lt;br /&gt;
|-&lt;br /&gt;
! down 2 - 1.wav&lt;br /&gt;
! transition between notch 2 and notch 1&lt;br /&gt;
|-&lt;br /&gt;
! down 3 - 2.wav&lt;br /&gt;
! transition between notch 3 and notch 2&lt;br /&gt;
|-&lt;br /&gt;
! down 4 - 3.wav&lt;br /&gt;
! transition between notch 4 and notch 3&lt;br /&gt;
|-&lt;br /&gt;
! down 5 - 4.wav&lt;br /&gt;
! transition between notch 5 and notch 4&lt;br /&gt;
|-&lt;br /&gt;
! down 6 - 5.wav&lt;br /&gt;
! transition between notch 6 and notch 5&lt;br /&gt;
|-&lt;br /&gt;
! down 7 - 6.wav&lt;br /&gt;
! transition between notch 7 and notch 6&lt;br /&gt;
|-&lt;br /&gt;
! down 8 - 7.wav&lt;br /&gt;
! transition between notch 8 and notch 7&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Non-ramping====&lt;br /&gt;
&lt;br /&gt;
In a non ramping engine sound only one file is used: engine_loop.wav.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Steam====&lt;br /&gt;
&lt;br /&gt;
These are background sounds for when the loco is stationary. The fast will be played when the loco has just stopped, and if it is left for a while, the sound will progress down to &#039;med&#039; and then eventually &#039;slow&#039;.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_fast.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_med.wav&lt;br /&gt;
|-&lt;br /&gt;
! loco_stationary_slow.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The low speed &#039;chuff&#039; sounds are named &amp;quot;piston_strokeX.wav&amp;quot;, where X is an index from 1 to the value specified by the &#039;number-slow-sounds&#039; tag.&lt;br /&gt;
&lt;br /&gt;
For example, if number-slow-sounds is set to &#039;4&#039; (the default).&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke1.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke2.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke3.wav&lt;br /&gt;
|-&lt;br /&gt;
! piston_stroke4.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These loops are played as the loco picks up speed. They are frequency shifted to match the wheel rotation speed, so the audible &#039;chuffs&#039; within the loop maintain synchronisation with the drive bogie animation. They also vary in volume based on the regulator setting of the locomotive.&lt;br /&gt;
&lt;br /&gt;
This system enables sound files to be shared between locomotives with different wheel sizes. 60RPM (which is one revolution per second) on a 2 cylinder loco will produce four chuffs per second irrespective of the wheel size - the only difference this makes is what speed the train will be doing when the drive wheels are rotating at 60RPM.&lt;br /&gt;
&lt;br /&gt;
Any individual file can be omitted from this set - the system will use what files are available and use adjacent files to cover for any missing files.&lt;br /&gt;
&lt;br /&gt;
It is anticipated that a sound creator will pick and choose which wave files are used based on what recordings are available, and that a released enginespec will not have all sound files present - particularly the higher speed ones, which are likely to be irrelevant for most locos, but are provided just in case...&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_30RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_35RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_40RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_50RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_60RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_75RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_90RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_100RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_125RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_150RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_175RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_250RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_300RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_350RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_500RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_700RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_800RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1000RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1200RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1400RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_1600RPM.wav&lt;br /&gt;
|-&lt;br /&gt;
! steam_loop_2000RPM.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Earlier assets may instead provide a single steam loop sound, titled &amp;quot;steam_loop.wav&amp;quot;. If only this file is present, modern Trainz code will use it with a default of 50RPM, in order to maintain compatibility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a background hiss noise that is played continually.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2 cellspacing=0 style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! smoke_stack_hiss.wav&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Downloads==&lt;br /&gt;
&#039;&#039;Attach sample files here?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Asset KIND|E]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE289&amp;diff=47555</id>
		<title>Help:VE289</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE289&amp;diff=47555"/>
		<updated>2026-09-17T07:20:20Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Enginesound is missing &#039;&amp;lt;file&amp;gt;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A required sound file for an enginesound asset was not found.&lt;br /&gt;
&lt;br /&gt;
Solving this will either mean providing the listed sound file, or adjusting the asset config to match the provided sounds.&lt;br /&gt;
&lt;br /&gt;
See asset kind [[KIND_Enginesound|enginesound]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE289&amp;diff=47554</id>
		<title>Help:VE289</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE289&amp;diff=47554"/>
		<updated>2026-09-17T07:13:51Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Enginesound is missing &amp;#039;&amp;lt;file&amp;gt;&amp;#039;&amp;#039;&amp;#039;&amp;#039;  Category:Validation Errors&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Enginesound is missing &#039;&amp;lt;file&amp;gt;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE287&amp;diff=47298</id>
		<title>Help:VE287</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE287&amp;diff=47298"/>
		<updated>2026-08-10T02:53:05Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;No soundscript entry found with trigger &amp;#039;&amp;lt;trigger&amp;gt;&amp;#039;.&amp;#039;&amp;#039;&amp;#039;  A tag in this asset refers to a sound trigger named &amp;#039;&amp;lt;trigger&amp;gt;&amp;#039;, but the asset&amp;#039;s &amp;#039;soundscript&amp;#039; container has no ent...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;No soundscript entry found with trigger &#039;&amp;lt;trigger&amp;gt;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A tag in this asset refers to a sound trigger named &#039;&amp;lt;trigger&amp;gt;&#039;, but the asset&#039;s &#039;soundscript&#039; container has no entry with that name, so the sound cannot be triggered.&lt;br /&gt;
&lt;br /&gt;
Check that the trigger name on the tag exactly matches a trigger defined in the &#039;soundscript&#039; container. Either correct the tag value to match an existing trigger, or add the missing trigger to the &#039;soundscript&#039; container.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE286&amp;diff=47297</id>
		<title>Help:VE286</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE286&amp;diff=47297"/>
		<updated>2026-08-10T02:52:27Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Tag &#039;&amp;lt;name&amp;gt;&#039; is not a valid float, and has been parsed as a legacy compatibility value (&amp;lt;value&amp;gt;).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A number in an [[KIND_Engine|engine]] assets [[Throttle-power_container|throttle-power]] or [[Dynamic-brake_container|dynamic-brake]] graph is not written as a valid decimal. This most commonly happens when a speed value uses a comma as the decimal separator (for example &amp;quot;3,8&amp;quot; instead of &amp;quot;3.8&amp;quot;), or contains stray characters.&lt;br /&gt;
&lt;br /&gt;
To avoid breakages on older assets, content targeted at trainz-build 5.7 and earlier will use a legacy reader, which takes the leading part of the value and ignores the rest. If this reader encounters invalid characters it will log this error, and the numeric value it settled on.&lt;br /&gt;
&lt;br /&gt;
For content with a trainz-build &amp;gt;=5.8, the game uses a more strict reader, which will report errors on invalid characters. To maintain the existing behaviour on an engine, the error should be resolved by removing the invalid characters and everything that follows. Alternatively, the value may be corrected to the original intent (e.g. change &amp;quot;3,8&amp;quot; to &amp;quot;3.8&amp;quot;), but note that this may affect existing trains and could break Sessions that use them.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE286&amp;diff=47296</id>
		<title>Help:VE286</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE286&amp;diff=47296"/>
		<updated>2026-08-10T02:52:04Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Tag &#039;&amp;lt;name&amp;gt;&#039; is not a valid float, and has been parsed as a legacy compatibility value (&amp;lt;value&amp;gt;).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A number in an [[KIND_Engine|engine]] assets [[Throttle-power_container|throttle-power]] or [[Dynamic-brake_container|dynamic-brake]] graph is not written as a valid decimal. This most commonly happens when a speed value uses a comma as the decimal separator (for example &#039;3,8&#039; instead of &#039;3.8&#039;), or contains stray characters.&lt;br /&gt;
&lt;br /&gt;
To avoid breakages on older assets, content targeted at trainz-build 5.7 and earlier will use a legacy reader, which takes the leading part of the value and ignores the rest. If this reader encounters invalid characters it will log this error, and the numeric value it settled on.&lt;br /&gt;
&lt;br /&gt;
For content with a trainz-build &amp;gt;=5.8, the game uses a more strict reader, which will report errors on invalid characters. To maintain the existing behaviour on an engine, the error should be resolved by removing the invalid characters and everything that follows. Alternatively, the value may be corrected to the original intent (e.g. change &amp;quot;3,8&amp;quot; to &amp;quot;3.8&amp;quot;), but note that this may affect existing trains and could break Sessions that use them.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE286&amp;diff=47295</id>
		<title>Help:VE286</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE286&amp;diff=47295"/>
		<updated>2026-08-10T02:50:57Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Tag &amp;#039;&amp;lt;name&amp;gt;&amp;#039; is not a valid float, and has been parsed as a legacy compatibility value (&amp;lt;value&amp;gt;).&amp;#039;&amp;#039;&amp;#039;  A number in an engine spec power or brake gra...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Tag &#039;&amp;lt;name&amp;gt;&#039; is not a valid float, and has been parsed as a legacy compatibility value (&amp;lt;value&amp;gt;).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A number in an [[Engine specification|engine spec]] power or brake graph is not written as a plain decimal. This most commonly happens when a speed value uses a comma as the decimal separator (for example &#039;3,8&#039; instead of &#039;3.8&#039;), or contains stray characters.&lt;br /&gt;
&lt;br /&gt;
To avoid breakages on older assets, content targeted at trainz-build 5.7 and earlier will use a legacy reader, which takes the leading part of the value and ignores the rest. If this reader encounters invalid characters it will log this error, and the numeric value it settled on.&lt;br /&gt;
&lt;br /&gt;
For content with a trainz-build &amp;gt;=5.8, the game uses a more strict reader, which will report errors on invalid characters. To maintain the existing behaviour on an engine, the error should be resolved by removing the invalid characters and everything that follows. Alternatively, the value may be corrected to the original intent (e.g. change &amp;quot;3,8&amp;quot; to &amp;quot;3.8&amp;quot;), but note that this may affect existing trains and could break Sessions that use them.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE285&amp;diff=47294</id>
		<title>Help:VE285</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE285&amp;diff=47294"/>
		<updated>2026-08-10T02:44:36Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Empty attachment name in mesh file: &amp;lt;file&amp;gt; (original name: &amp;#039;&amp;lt;name&amp;gt;&amp;#039;).&amp;#039;&amp;#039;&amp;#039;  An attachment point in this mesh has no usable name. This usually happens when an attachment point...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Empty attachment name in mesh file: &amp;lt;file&amp;gt; (original name: &#039;&amp;lt;name&amp;gt;&#039;).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An attachment point in this mesh has no usable name. This usually happens when an attachment point is left with a blank or invalid name in the 3D modelling tool, or its name is lost during export.&lt;br /&gt;
&lt;br /&gt;
Attachment points must be uniquely named so that config and script can reference them. Give every attachment point a valid name and re-export the mesh.&lt;br /&gt;
&lt;br /&gt;
From trainz-build 5.8 this is reported as an error; on earlier assets it is a warning.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE284&amp;diff=47293</id>
		<title>Help:VE284</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE284&amp;diff=47293"/>
		<updated>2026-08-10T02:44:01Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Empty bone name in mesh file: &amp;lt;file&amp;gt; (original name: &amp;#039;&amp;lt;name&amp;gt;&amp;#039;).&amp;#039;&amp;#039;&amp;#039;  A bone in this mesh&amp;#039;s skeleton has no usable name. This usually happens when a bone is left unnamed in t...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Empty bone name in mesh file: &amp;lt;file&amp;gt; (original name: &#039;&amp;lt;name&amp;gt;&#039;).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A bone in this mesh&#039;s skeleton has no usable name. This usually happens when a bone is left unnamed in the 3D modelling tool, or its name is lost or stripped during export.&lt;br /&gt;
&lt;br /&gt;
Bones must be uniquely named so that animations and attachments can reference them. Give every bone a valid name and re-export the mesh.&lt;br /&gt;
&lt;br /&gt;
From trainz-build 5.8 this is reported as an error; on earlier assets it is a warning.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE283&amp;diff=47292</id>
		<title>Help:VE283</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE283&amp;diff=47292"/>
		<updated>2026-08-10T02:43:24Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Bone &amp;#039;&amp;lt;bone&amp;gt;&amp;#039; parent mismatch between LODs: &amp;lt;lod1&amp;gt;: &amp;#039;&amp;lt;parent1&amp;gt;&amp;#039;, &amp;lt;lod2&amp;gt;: &amp;#039;&amp;lt;parent2&amp;gt;&amp;#039; (in &amp;lt;file&amp;gt;).&amp;#039;&amp;#039;&amp;#039;  The named bone has a different parent bone in two of the mesh&amp;#039;s levels...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Bone &#039;&amp;lt;bone&amp;gt;&#039; parent mismatch between LODs: &amp;lt;lod1&amp;gt;: &#039;&amp;lt;parent1&amp;gt;&#039;, &amp;lt;lod2&amp;gt;: &#039;&amp;lt;parent2&amp;gt;&#039; (in &amp;lt;file&amp;gt;).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The named bone has a different parent bone in two of the mesh&#039;s levels of detail (LODs). Trainz expects every LOD of a mesh to share the same skeleton hierarchy, so that animations behave identically no matter which LOD is displayed.&lt;br /&gt;
&lt;br /&gt;
Check the skeleton in each LOD and make the parent of the named bone the same across all of them, then re-export.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE282&amp;diff=47291</id>
		<title>Help:VE282</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE282&amp;diff=47291"/>
		<updated>2026-08-10T02:42:30Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;No power data for topmost notch in &amp;#039;&amp;lt;container&amp;gt;&amp;#039; container. Power curve expects &amp;lt;count&amp;gt; throttle notches, but highest found was &amp;lt;value&amp;gt;.&amp;#039;&amp;#039;&amp;#039;  An engine asset...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;No power data for topmost notch in &#039;&amp;lt;container&amp;gt;&#039; container. Power curve expects &amp;lt;count&amp;gt; throttle notches, but highest found was &amp;lt;value&amp;gt;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
An [[KIND_Engine|engine]] assets [[Throttle-power_container|throttle-power]] or [[Dynamic-brake_container|dynamic-brake]] graph does not provide data all the way up to the highest throttle notch. When the top notches have no data, the highest notch that does have data is reused for everything above it, which makes those higher notches behave identically and serve no purpose.&lt;br /&gt;
&lt;br /&gt;
Either add power data for the missing top notch(es), or reduce the motor&#039;s &#039;throttle-notches&#039; so it matches the range of data you have provided. You do not need an entry for every notch in between - the game interpolates gaps - but the topmost notch must be present, as data is never extrapolated beyond the provided range.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE281&amp;diff=47290</id>
		<title>Help:VE281</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE281&amp;diff=47290"/>
		<updated>2026-08-10T02:41:41Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notch data in the &#039;&amp;lt;container&amp;gt;&#039; container is out of order. Each notch must be greater than the last.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The notch entries in an [[KIND_Engine|engine]] assets [[Throttle-power_container|throttle-power]] or [[Dynamic-brake_container|dynamic-brake]] graph must be listed in ascending order, as the graph reader relies on ordering to interpolate between notches. Out-of-order notches would produce an incorrect power output.&lt;br /&gt;
&lt;br /&gt;
List the notch sub-containers so that each notch number is greater than the one before it.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE281&amp;diff=47289</id>
		<title>Help:VE281</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE281&amp;diff=47289"/>
		<updated>2026-08-10T02:40:40Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Notch data in the &amp;#039;&amp;lt;container&amp;gt;&amp;#039; container is out of order. Each notch must be greater than the last.&amp;#039;&amp;#039;&amp;#039;  The notch entries in an engine spec power or brake graph must be li...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notch data in the &#039;&amp;lt;container&amp;gt;&#039; container is out of order. Each notch must be greater than the last.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The notch entries in an engine spec power or brake graph must be listed in ascending order, as the graph reader relies on ordering to interpolate between notches. Out-of-order notches would produce an incorrect power output.&lt;br /&gt;
&lt;br /&gt;
List the notch sub-containers so that each notch number is greater than the one before it.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE280&amp;diff=47288</id>
		<title>Help:VE280</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE280&amp;diff=47288"/>
		<updated>2026-08-10T02:36:27Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notch &#039;&amp;lt;value&amp;gt;&#039; in the &#039;&amp;lt;container&amp;gt;&#039; container is beyond valid range and will not be used.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A notch number in an [[KIND_Engine|engine]] assets [[Throttle-power_container|throttle-power]] or [[Dynamic-brake_container|dynamic-brake]] graph is higher than the number of throttle notches the engine actually has, so the data for that notch will never be used.&lt;br /&gt;
&lt;br /&gt;
Remove the out-of-range notch data, or correct the notch numbering so it falls within the engine&#039;s throttle notch count. If your engine genuinely has more than 8 throttle notches and you want data for each, set the motor&#039;s &#039;throttle-notches&#039; and enable the extended-notch-range option for that container (requires trainz-build 5.8 and later); otherwise the graph assumes 8 notches.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE280&amp;diff=47287</id>
		<title>Help:VE280</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE280&amp;diff=47287"/>
		<updated>2026-08-10T02:36:08Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notch &#039;&amp;lt;value&amp;gt;&#039; in the &#039;&amp;lt;container&amp;gt;&#039; container is beyond valid range and will not be used.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A notch number in an [[KIND_Engine|engine]] assets [[Throttle-power_container|throttle-power]] or [[Dynamic-brake_container|dynamic-brake] graph is higher than the number of throttle notches the engine actually has, so the data for that notch will never be used.&lt;br /&gt;
&lt;br /&gt;
Remove the out-of-range notch data, or correct the notch numbering so it falls within the engine&#039;s throttle notch count. If your engine genuinely has more than 8 throttle notches and you want data for each, set the motor&#039;s &#039;throttle-notches&#039; and enable the extended-notch-range option for that container (requires trainz-build 5.8 and later); otherwise the graph assumes 8 notches.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE280&amp;diff=47286</id>
		<title>Help:VE280</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE280&amp;diff=47286"/>
		<updated>2026-08-10T02:34:53Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Notch &amp;#039;&amp;lt;value&amp;gt;&amp;#039; in the &amp;#039;&amp;lt;container&amp;gt;&amp;#039; container is beyond valid range and will not be used.&amp;#039;&amp;#039;&amp;#039;  A notch number in an engine asset power or brake graph is hig...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notch &#039;&amp;lt;value&amp;gt;&#039; in the &#039;&amp;lt;container&amp;gt;&#039; container is beyond valid range and will not be used.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A notch number in an [[KIND_Engine|engine]] asset power or brake graph is higher than the number of throttle notches the engine actually has, so the data for that notch will never be used.&lt;br /&gt;
&lt;br /&gt;
Remove the out-of-range notch data, or correct the notch numbering so it falls within the engine&#039;s throttle notch count. If your engine genuinely has more than 8 throttle notches and you want data for each, set the motor&#039;s &#039;throttle-notches&#039; and enable the extended-notch-range option for that container (requires trainz-build 5.8 and later); otherwise the graph assumes 8 notches.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE279&amp;diff=47285</id>
		<title>Help:VE279</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE279&amp;diff=47285"/>
		<updated>2026-08-10T02:32:05Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;The &amp;#039;&amp;lt;tag&amp;gt;&amp;#039; tag in voiceover line &amp;#039;&amp;lt;line&amp;gt;&amp;#039; conflicts with &amp;#039;variations&amp;#039; container and must be removed.&amp;#039;&amp;#039;&amp;#039;  A voiceover line provides a &amp;#039;variations&amp;#039; container (used to supply...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The &#039;&amp;lt;tag&amp;gt;&#039; tag in voiceover line &#039;&amp;lt;line&amp;gt;&#039; conflicts with &#039;variations&#039; container and must be removed.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A voiceover line provides a &#039;variations&#039; container (used to supply several alternative recordings or subtitles for the same line), but it also has a top-level &#039;&amp;lt;tag&amp;gt;&#039; such as &#039;audio-file&#039; or &#039;subtitle&#039;. A line must use one approach or the other, not both.&lt;br /&gt;
&lt;br /&gt;
To resolve the error, move the top-level data into the &#039;variations&#039; container.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE278&amp;diff=47284</id>
		<title>Help:VE278</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE278&amp;diff=47284"/>
		<updated>2026-08-10T02:29:20Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Missing driving instructor line: &amp;lt;name&amp;gt;.&amp;#039;&amp;#039;&amp;#039;  A driving instructor (voiceover) asset does not provide one of the lines Trainz expects/supports it to define. The name of the ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Missing driving instructor line: &amp;lt;name&amp;gt;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A driving instructor (voiceover) asset does not provide one of the lines Trainz expects/supports it to define. The name of the missing line is shown in the message.&lt;br /&gt;
&lt;br /&gt;
Some lines are optional, and will only generate warnings when missing. Such warnings can be safely ignored, and simply mean the runtime code will not play a voice-over for that event.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE276&amp;diff=47283</id>
		<title>Help:VE276</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE276&amp;diff=47283"/>
		<updated>2026-08-10T02:25:00Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Mismatched &#039;conflicts-with-queues&#039; data. Queue &#039;&amp;lt;queue&amp;gt;&#039; specifies &#039;&amp;lt;other queue&amp;gt;&#039; as a conflict but the reverse is not true.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A product queue lists another queue in its &#039;[[&amp;quot;Queues&amp;quot;_container#conflicts-with-queues|conflicts-with-queues]]&#039; data, but that other queue does not list this one back. Queue conflicts must be declared on both queues so the relationship is unambiguous.&lt;br /&gt;
&lt;br /&gt;
Add the matching conflict entry to the other queue, so each queue lists the other. On older assets the mismatched conflict is ignored and reported as a warning; from trainz-build 5.7 it is an error.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE276&amp;diff=47282</id>
		<title>Help:VE276</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE276&amp;diff=47282"/>
		<updated>2026-08-10T02:22:26Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Mismatched &amp;#039;conflicts-with-queues&amp;#039; data. Queue &amp;#039;&amp;lt;queue&amp;gt;&amp;#039; specifies &amp;#039;&amp;lt;other queue&amp;gt;&amp;#039; as a conflict but the reverse is not true.&amp;#039;&amp;#039;&amp;#039;  A product queue lists another queue in its...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Mismatched &#039;conflicts-with-queues&#039; data. Queue &#039;&amp;lt;queue&amp;gt;&#039; specifies &#039;&amp;lt;other queue&amp;gt;&#039; as a conflict but the reverse is not true.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A product queue lists another queue in its &#039;conflicts-with-queues&#039; data, but that other queue does not list this one back. Queue conflicts must be declared on both queues so the relationship is unambiguous.&lt;br /&gt;
&lt;br /&gt;
Add the matching conflict entry to the other queue, so each queue lists the other. On older assets the mismatched conflict is ignored and reported as a warning; from trainz-build 5.7 it is an error.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE272&amp;diff=47281</id>
		<title>Help:VE272</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE272&amp;diff=47281"/>
		<updated>2026-08-10T02:19:29Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;No overridden function found when calling inherited().&amp;#039;&amp;#039;&amp;#039;  Reported by the TrainzScript compiler when a function calls &amp;#039;inherited()&amp;#039;, but no function of the same name e...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;No overridden function found when calling inherited().&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Reported by the [[TrainzScript]] compiler when a function calls &#039;inherited()&#039;, but no function of the same name exists in any parent class. At runtime this call would throw a script exception.&lt;br /&gt;
&lt;br /&gt;
&#039;inherited()&#039; should only be used inside a function that genuinely overrides a parent class function. If the function is new (not an override), remove the &#039;inherited()&#039; call. If it is meant to be an override, check that a parent class really declares a matching function, and that the parameter list matches.&lt;br /&gt;
&lt;br /&gt;
For assets with trainz-build &amp;gt;=5.6 this is an error; on earlier content it is a warning.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47280</id>
		<title>Help:VE271</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47280"/>
		<updated>2026-08-10T02:15:15Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The specified TCB flags are invalid, please check the wiki for valid configurations.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The track circuit block (TCB) detector flags on this asset include an invalid combination. TCB flags are given as a semicolon-separated list and fall into two groups:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Traffic type&#039;&#039;&#039; - E.g. &#039;Freight&#039;, &#039;Passenger&#039;. These may be combined with each other and with any track type.&lt;br /&gt;
* &#039;&#039;&#039;Track type&#039;&#039;&#039; - E.g. &#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;YardShunting&#039;, etc. These may only be combined with each other in certain configurations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following track type combinations are not allowed and cause this error:&lt;br /&gt;
* &#039;MainLine&#039; cannot be combined with any branch-line type (&#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
* Yard types cannot be combined with other track types (&#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
&lt;br /&gt;
You may combine multiple flags within the same group - for example a block can be both &#039;YardReceiving&#039; and &#039;YardDeparture&#039;.&lt;br /&gt;
&lt;br /&gt;
To fix this error, correct the flag list so it does not mix incompatible track categories.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47279</id>
		<title>Help:VE271</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47279"/>
		<updated>2026-08-10T02:14:23Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The specified TCB flags are invalid, please check the wiki for valid configurations.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The track circuit block (TCB) detector flags on this asset include an invalid combination. TCB flags are given as a semicolon-separated list and fall into two groups:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Traffic type&#039;&#039;&#039; - E.g. &#039;Freight&#039;, &#039;Passenger&#039;. These may be combined with each other and with any track type.&lt;br /&gt;
* &#039;&#039;&#039;Track type&#039;&#039;&#039; - E.g. &#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;YardShunting&#039;, etc. These may only be combined with each other in certain configurations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following track type combinations are not allowed and cause this error:&lt;br /&gt;
* &#039;MainLine&#039; cannot be combined with any branch-line type (&#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
* Yard types cannot be combined with other track types (&#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You may combine multiple flags within the same group - for example a block can be both &#039;YardReceiving&#039; and &#039;YardDeparture&#039;, or can be both &#039;BranchLine&#039; and a &#039;Siding&#039;.&lt;br /&gt;
&lt;br /&gt;
To fix this error, correct the flag list so it does not mix incompatible track categories.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47278</id>
		<title>Help:VE271</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47278"/>
		<updated>2026-08-10T02:13:30Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The specified TCB flags are invalid, please check the wiki for valid configurations.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The track circuit block (TCB) detector flags on this asset include an invalid combination. TCB flags are given as a semicolon-separated list and fall into two groups:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Traffic type&#039;&#039;&#039; - E.g. &#039;Freight&#039;, &#039;Passenger&#039;. These may be combined with each other and with any track type.&lt;br /&gt;
* &#039;&#039;&#039;Track type&#039;&#039;&#039; - E.g. &#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;YardShunting&#039;, etc. These may only be combined with each other in certain configurations.&lt;br /&gt;
&lt;br /&gt;
The following track type combinations are not allowed and cause this error:&lt;br /&gt;
* &#039;MainLine&#039; cannot be combined with any branch-line type (&#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
* Yard types cannot be combined with other track types (&#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
&lt;br /&gt;
You may combine multiple flags within the same group - for example a block can be both &#039;YardReceiving&#039; and &#039;YardDeparture&#039;.&lt;br /&gt;
&lt;br /&gt;
To fix this error, correct the flag list so it does not mix incompatible track categories.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47277</id>
		<title>Help:VE271</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE271&amp;diff=47277"/>
		<updated>2026-08-10T02:12:44Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;The specified TCB flags are invalid, please check the wiki for valid configurations.&amp;#039;&amp;#039;&amp;#039;  The track circuit block (TCB) detector flags on this tag include a contradictory co...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The specified TCB flags are invalid, please check the wiki for valid configurations.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The track circuit block (TCB) detector flags on this tag include a contradictory combination. TCB flags are given as a semicolon-separated list and fall into two groups:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Traffic type&#039;&#039;&#039; - E.g. &#039;Freight&#039;, &#039;Passenger&#039;. These may be combined with each other and with any track type.&lt;br /&gt;
* &#039;&#039;&#039;Track type&#039;&#039;&#039; - E.g. &#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;YardShunting&#039;, etc. These may only be combined with each other in certain configurations.&lt;br /&gt;
&lt;br /&gt;
The following track type combinations are not allowed and cause this error:&lt;br /&gt;
* &#039;MainLine&#039; cannot be combined with any branch-line type (&#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
* Yard types cannot be combined with other track types (&#039;MainLine&#039;, &#039;BranchLine&#039;, &#039;Siding&#039; or &#039;Spur&#039;).&lt;br /&gt;
&lt;br /&gt;
You may combine multiple flags within the same group - for example a block can be both &#039;YardReceiving&#039; and &#039;YardDeparture&#039;.&lt;br /&gt;
&lt;br /&gt;
To fix this error, correct the flag list so it does not mix incompatible track categories.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE270&amp;diff=47276</id>
		<title>Help:VE270</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE270&amp;diff=47276"/>
		<updated>2026-08-10T02:03:44Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Density LOD multiplier in level &amp;lt;level&amp;gt; is not in descending order.&amp;#039;&amp;#039;&amp;#039;  The density multipliers used across an asset&amp;#039;s levels of detail must decrease as the levels get lowe...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Density LOD multiplier in level &amp;lt;level&amp;gt; is not in descending order.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The density multipliers used across an asset&#039;s levels of detail must decrease as the levels get lower (less detailed). The named level specifies a density that is higher than a preceding level, or is negative, which is not valid.&lt;br /&gt;
&lt;br /&gt;
Adjust the density multipliers so that each successive LOD level is lower than the one before it.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE269&amp;diff=47275</id>
		<title>Help:VE269</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE269&amp;diff=47275"/>
		<updated>2026-08-10T02:02:46Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Texture table is incorrectly indexed, some textures may be unloadable.&amp;#039;&amp;#039;&amp;#039;  The textures in this asset&amp;#039;s texture table must be numbered consecutively, starting at 0 with no ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Texture table is incorrectly indexed, some textures may be unloadable.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The textures in this asset&#039;s texture table must be numbered consecutively, starting at 0 with no gaps (0, 1, 2, ...). Trainz reads the entries in order and stops at the first missing number, so any textures numbered after a gap are never loaded.&lt;br /&gt;
&lt;br /&gt;
Renumber the texture entries so they are consecutive with no missing indices. The number of textures the game loads should then match the number you have defined.&lt;br /&gt;
&lt;br /&gt;
From trainz-build 5.4 this is reported as an error; on earlier assets it is a warning.&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=%22Soundscript%22_container&amp;diff=46307</id>
		<title>&quot;Soundscript&quot; container</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=%22Soundscript%22_container&amp;diff=46307"/>
		<updated>2026-06-05T07:06:20Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* sound-asset */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ORP-top}}&lt;br /&gt;
A container type tag for defining asset sounds.&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
Each soundscript subcontainer supports the following tags. Each tag is shown here with its default value.&lt;br /&gt;
&lt;br /&gt;
  repeat-delay  0,0&lt;br /&gt;
  distance      50,150&lt;br /&gt;
  ambient       0&lt;br /&gt;
  attachment    &amp;quot;&amp;quot;&lt;br /&gt;
  nostartdelay  0&lt;br /&gt;
  priority      1&lt;br /&gt;
  trigger       &amp;quot;&amp;quot;&lt;br /&gt;
  volume        1&lt;br /&gt;
  value-range   0,0&lt;br /&gt;
  sound-asset&lt;br /&gt;
  sound&lt;br /&gt;
  {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
====ambient====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Default: 0&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: If true this is an &#039;ambient&#039; sound, ambient sounds are played in 2D and do not make use of 3D positioning in the world other than to affect volume. Unlike positional sounds, ambient sounds may be stereo.&lt;br /&gt;
&lt;br /&gt;
====attachment====&lt;br /&gt;
:Type: Attachment point&lt;br /&gt;
:Default: &amp;quot;&amp;quot;&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: Point to attach the sound source to. Attachment points are specified in the mesh file during creation.&lt;br /&gt;
&lt;br /&gt;
====distance====&lt;br /&gt;
:Type: Decimal Pair&lt;br /&gt;
:Default: 50,150&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: The minimum distance (first value, in meters) defines the radius within which the sound remains at 100% volume. Beyond that distance, the sound volume will begin to decay naturally. The maximum distance (second value, in meters) defines a radius beyond which the game need no longer play the sound. This does not mean that the sound will fade to zero by the maximum distance, but rather that the sound may cut off abruptly beyond that point. It is up to the content creator to choose an appropriate maximum distance - smaller is better for performance, but overly small values may result in the sound audibly cutting off. Many Trainz editions ignore the configured maximum distance value and instead perform their own optimized calculation of the appropriate value.&lt;br /&gt;
&lt;br /&gt;
====nostartdelay====&lt;br /&gt;
:Type: Boolean&lt;br /&gt;
:Default: 0&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: If added and true this tag specifies that the sound will play immediately once triggered. By default sounds have a random start delay between 0 &amp;amp; 4 seconds. Start delay should be left active in most cases, as turning it off may cause significant audio artifacts when several identical sounds are in proximity.&lt;br /&gt;
&lt;br /&gt;
====priority====&lt;br /&gt;
:Type: Integer&lt;br /&gt;
:Default: 1&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: Sets the priority of the sound, if their are not enough sound channels available higher priority sounds will be played first. Defaults to 1, can be negative.&lt;br /&gt;
&lt;br /&gt;
====repeat-delay====&lt;br /&gt;
:Type: Decimal Pair&lt;br /&gt;
:Default: 0,0&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: Time range (in seconds) to delay, after the sound finishes playing, before playing the sound again. To set a constant delay either set both these values the same or only provide one of them, otherwise a random value between them will be chosen. When used with a trigger event (see the &#039;trigger&#039; tag), a positive value indicates that the sound should not repeat, but should wait until triggered again.&lt;br /&gt;
&lt;br /&gt;
====sound====&lt;br /&gt;
:Type: Container&lt;br /&gt;
:Default: {}&lt;br /&gt;
:Compulsory: Yes&lt;br /&gt;
:Desc: Contains list of the sound files to play. If the list has more than one entry then one file will be picked at random from the list.  The value of each tag in this container is the filename of a WAV sound file.  Filenames are relative to the base directory of the asset, i.e. relative to the location of the config file.&lt;br /&gt;
&lt;br /&gt;
:Valid WAV files are:&lt;br /&gt;
:* Uncompressed.&lt;br /&gt;
:* 8 or 16 bit&lt;br /&gt;
:* Mono, Stereo or Surround&lt;br /&gt;
&lt;br /&gt;
:Sampling rate can be 22kHz (22,050Hz) or 44kHz (44,100Hz).  The higher sampling rate doubles the size of the file for no significant improvement in quality, and is not recommended.  For some purposes there are additional requirements - for instance directional sounds must be mono.&lt;br /&gt;
&lt;br /&gt;
====sound-asset====&lt;br /&gt;
:Type: KUID&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: The asset to source the sound files from. Allows the creation of &amp;quot;sound library&amp;quot; assets, so that sound files can be shared between multiple other assets. Defaults to the current asset.&lt;br /&gt;
&lt;br /&gt;
====trigger====&lt;br /&gt;
:Type: String&lt;br /&gt;
:Default: &amp;quot;&amp;quot;&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: The &#039;trigger&#039; tag gives your sound a name that can allow it to be played from [[Scripting|TrainzScript]] (see: Class MapObject), animations and certain predefined events. (At least one of these &amp;quot;predefined events&amp;quot; is to use the word &amp;quot;toggle&amp;quot; when including a soundscript container in the config.txt of a &amp;quot;MOjunction&amp;quot;.  This will make the sound fire each time the turnout is switched)&lt;br /&gt;
&lt;br /&gt;
====value-range====&lt;br /&gt;
:Type: Float pair&lt;br /&gt;
:Default: 0,0 (off)&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: 2 numbers, where the numbers are not the same, which set the start and end times for the sound to play. Midnight is 0.5, midday = 0.0 or 1.0. (TBD.  This is a bit vague.)&lt;br /&gt;
&lt;br /&gt;
====volume====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Default: 1&lt;br /&gt;
:Compulsory: No&lt;br /&gt;
:Desc: Specifies the volume gain of the sound. Defaults to 1 (100%).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Example Config.txt==&lt;br /&gt;
Sample [[config.txt file]] for a map asset that has a different day and night background sounds:&lt;br /&gt;
&lt;br /&gt;
  kind map&lt;br /&gt;
  kuid &amp;lt;KUID:0:0&amp;gt;&lt;br /&gt;
  soundscript&lt;br /&gt;
  {&lt;br /&gt;
    morning&lt;br /&gt;
    {&lt;br /&gt;
      ambient 1&lt;br /&gt;
      value-range 1, 0.1&lt;br /&gt;
      volume 0.3&lt;br /&gt;
      sound&lt;br /&gt;
      {&lt;br /&gt;
        0 &amp;quot;ctry_day_1.wav&amp;quot;&lt;br /&gt;
        1 &amp;quot;ctry_day_2.wav&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    night&lt;br /&gt;
    {&lt;br /&gt;
      ambient 1&lt;br /&gt;
      value-range 0, 0.9&lt;br /&gt;
      volume 0.3&lt;br /&gt;
      sound&lt;br /&gt;
      {&lt;br /&gt;
        0 &amp;quot;night_loop.wav&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Config Container|Soundscript container]]&lt;br /&gt;
{{ORP-bot|Soundscript container}}&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=HowTo/Search_for_objects_in_the_world&amp;diff=46065</id>
		<title>HowTo/Search for objects in the world</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=HowTo/Search_for_objects_in_the_world&amp;diff=46065"/>
		<updated>2026-03-25T23:04:14Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* Named Object Searches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Scripted asset may sometimes wish to search for other objects within the world, either in bulk lists, or for a specific single object. This page is intended to provide an overview of how this is achieved in the latest versions of Trainz. Details about certain legacy search methods and the best modern techniques to update them to are also provided in the final section of this page.&lt;br /&gt;
&lt;br /&gt;
==Object Identification==&lt;br /&gt;
Scripted objects identified in script using several different methods, many of which have become obsolete as Trainz and the script environment has grown in complexity. As of trainz-build 4.5 (TANE SP2 and later) scripted objects should be identified using their GameObjectID, where present. This ID format has been designed to be future-proof/extensible, should the need arise, and supports various lookup and generic storage functions as per the legacy integer and string based IDs. For more information about legacy ID formats, see [[HowTo/Search_for_objects_in_the_world#Legacy_Search_Functions|here]].&lt;br /&gt;
&lt;br /&gt;
The GameObjectID class is defined within GameObjectID.gs, which can be found in the Trainz core script folder (resources/scripts). For the most up to date and accurate usage instructions please see the comments within that file.&lt;br /&gt;
&lt;br /&gt;
==Named Object Searches==&lt;br /&gt;
It is occasionally desirable for scripted assets to be able to search for objects within the world. Most commonly, this is a requirement of session rules, which frequently require a session creator to specify target trains, junctions, signals, etc, in order to perform some gameplay function. Occasionally, placable assets such as industries etc may also require this feature. One such example is the Interlocking Tower asset type, which performs complex management of track blocks using management of user defined signals, junctions and crossings.&lt;br /&gt;
&lt;br /&gt;
As of trainz-build 4.5 (TANE SP2 and later) manual object searches are performed via the World.GetNamedObjectList() function. This function takes both a [[Category_List|category list]] and a partial name, allowing for very specific searches, or quite broad ones. Once called, this function returns an object of type AsyncObjectSearchResult, which is used to monitor for the search completion, and then to retrieve the results. For the most up to date and accurate information on how to use GetNamedObjectList and AsyncObjectSearchResult, please see their script comments in World.gs and AsyncObjectSearch.gs (respectively), which can be found in the Trainz core script folder (resources/scripts).&lt;br /&gt;
&lt;br /&gt;
Usage example:&lt;br /&gt;
&lt;br /&gt;
 thread void SearchForTrains()&lt;br /&gt;
 {&lt;br /&gt;
   // Start a search for any traincars within the world&lt;br /&gt;
   AsyncObjectSearchResult searchObj = World.GetNamedObjectList(AssetCategory.TrainCar, &amp;quot;&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   // Sniff for search related messages, and then wait for either completion or failure&lt;br /&gt;
   Sniff(searchObj, &amp;quot;ObjectSearch&amp;quot;, &amp;quot;&amp;quot;, true);&lt;br /&gt;
   Message msg;&lt;br /&gt;
   wait()&lt;br /&gt;
   {&lt;br /&gt;
     on &amp;quot;ObjectSearch&amp;quot;, &amp;quot;Failure&amp;quot;, msg:&lt;br /&gt;
       if (msg.src == searchObj)&lt;br /&gt;
         break;&lt;br /&gt;
       continue;&lt;br /&gt;
     &lt;br /&gt;
     on &amp;quot;ObjectSearch&amp;quot;, &amp;quot;AsyncLoadComplete&amp;quot;, msg:&lt;br /&gt;
       if (msg.src == searchObj)&lt;br /&gt;
         break;&lt;br /&gt;
       continue;&lt;br /&gt;
   };&lt;br /&gt;
   &lt;br /&gt;
   // Check the results&lt;br /&gt;
   int errCode = searchObj.GetSearchErrorCode();&lt;br /&gt;
   if (errCode != AsyncObjectSearchResult.ERROR_NONE)&lt;br /&gt;
   {&lt;br /&gt;
     // TODO: Add any error handling here, such as waiting and reattempting the&lt;br /&gt;
     // search later, showing an error message, throwing script exceptions, etc.&lt;br /&gt;
     return;&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   // Get the search results&lt;br /&gt;
   NamedObjectInfo[] results = searchObj.GetResults();&lt;br /&gt;
   &lt;br /&gt;
   // TODO: Add any processing of the results here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Storing References to Specific Objects==&lt;br /&gt;
As shown in the example above, named object searches return their results as an array of NamedObjectInfo objects. Currently, this class has 4 member variables:&lt;br /&gt;
* objectRef - A reference to the object, if it is currently loaded&lt;br /&gt;
* objectId - The GameObjectID for the object (see GameObjectID.gs)&lt;br /&gt;
* localisedUsername - The localised name of the object, for displaying to the player&lt;br /&gt;
* categoryString - A category string, usable to further determine the exact type and features of the object&lt;br /&gt;
&lt;br /&gt;
Any script which wishes to save a reference to specific named object should /always/ do so via the GameObjectID. This is currently the /only/ safe and reliable way to store and later retrieve a specific object. If the object is currently loaded it is of course also safe to access and store a reference to the object itself, but note that Trainz may choose to unload the object at any time (if it is inactive, and sufficiently far enough away from the player, etc). Attempts to use an object which native code has unloaded may result in native call errors. To avoid this scripts should call Router.DoesGameObjectStillExist() before attempting to use any object reference that has been stored for some time.&lt;br /&gt;
&lt;br /&gt;
Unlike the named object itself, a referenced GameObjectID will never be deleted by native code, and may be held by a script indefinitely. It can also be stored directly into a [[Soup]] database for storage and retrieval between runs of the game, over a network, etc. For details about saving a GameObjectID into a Soup database please see the comments in Soup.gs, located in the core Trainz script folder (resources/scripts).&lt;br /&gt;
&lt;br /&gt;
In addition to Soup storage, a GameObjectID can be serialised to a string for *temporary* storage. This allows scripts to do things like store the ID directly in a trainzhttp link, etc (provided it is also appropriately escaped). However, it is crucial to note that the format of this string is *not* guaranteed and may change between versions of the game. As such, no attempt should be made to machine parse it, save it between runs or send it over a network. To convert the string back into a GameObjectID, use Router.SerialiseGameObjectIDFromString().&lt;br /&gt;
&lt;br /&gt;
It is also safe to cache and store the localised display name for an object, but it is important to remember that objects can be renamed, and that this object name may become out of date at any time. As such, scripts which store it should remember to update their cache whenever an opportunity arises (e.g. during any validation steps).&lt;br /&gt;
&lt;br /&gt;
==Searching for Specific Objects by ID==&lt;br /&gt;
Several functions exist for looking up an object which has been saved via it&#039;s GameObjectID. Each of these serves a slightly different use-case, so it&#039;s important to understand them all before selecting the one that best suits the needs of a specific script.&lt;br /&gt;
&lt;br /&gt;
Two functions exist to retrieve a loaded object via it&#039;s ID. These both behave identically, and will return a reference to a matching object *only* if that object exists and is currently loaded. In all other cases the functions will return null. There is no way to determine the cause of a null result using these functions.&lt;br /&gt;
&lt;br /&gt;
 GameObject objectRef1 = World.GetGameObjectByIDIfLoaded(mySavedID);&lt;br /&gt;
 &lt;br /&gt;
 GameObject objectRef2 = Router.GetGameObject(mySavedID);&lt;br /&gt;
&lt;br /&gt;
Another function exists to allow scripts to search for objects which are not currently loaded, and to optionally request that they are loaded. Scripts should only request loading of objects when absolutely necessary, and scripts which abuse this feature may have their requests ignored by native code in order to maintain performance. As this function may take a considerable amount of time to run, it uses an AsyncObjectSearchResult, much like the named object list functions described above.&lt;br /&gt;
&lt;br /&gt;
 AsyncObjectSearchResult searchObj = World.GetGameObjectByID(mySavedID, false);&lt;br /&gt;
&lt;br /&gt;
As with GetNamedObjectList(), calling scripts must Sniff the returned search object and wait for the appropriate result message(s) to be posted. To avoid the need for frequent code duplication another function also exists which allows threaded objects to perform this functionality in a pseudo-synchronous way.&lt;br /&gt;
&lt;br /&gt;
 GameObject loadedObjectRef = World.SynchronouslyLoadGameObjectByID(mySavedID);&lt;br /&gt;
&lt;br /&gt;
This function will throw exceptions if used incorrectly (e.g. if called outside of a thread function) so be sure to read and understand the comments on the function itself, before attempting to use it.&lt;br /&gt;
&lt;br /&gt;
==Script Library Lookups==&lt;br /&gt;
Script [[KIND_Library|library assets]] are unique within script in that they exist without any visual presence to the end player, and are shared across all scripts that access them. i.e. It is not possible to instantiate multiple instances of the same library asset within a single script context. This makes them extremely useful for managing, organising or communicating between other scripted asset types. For more information about library assets, see the [[KIND_Library]] page.&lt;br /&gt;
&lt;br /&gt;
As libraries are added to the world by script, and the not the player or session creator, they require a script accessible function to create and load them. This function is TrainzScriptBase.GetLibrary(). When this function is called the library asset will be immediately loaded and returned by Trainz native code. Once loaded into the current script context, the library will remain loaded, and any future calls to GetLibrary() will return the same instance.&lt;br /&gt;
&lt;br /&gt;
Example usage:&lt;br /&gt;
 public void Init(Asset asset)&lt;br /&gt;
 {&lt;br /&gt;
   inherited(asset);&lt;br /&gt;
   &lt;br /&gt;
   // Load our shared library asset&lt;br /&gt;
   KUID libraryKuid = asset.LookupKUIDTable(&amp;quot;shared-library&amp;quot;);&lt;br /&gt;
   m_sharedLibrary = World.GetLibrary(libraryKuid);&lt;br /&gt;
   &lt;br /&gt;
   // TODO: Add any library specific init, registration, etc code here&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Legacy Search Functions==&lt;br /&gt;
Prior to trainz-build 4.5 (TANE SP1 and earlier) all world objects were loaded on Route/Session load, and remained that way until the session was ended. As Routes grow larger and larger this technique becomes unmanageable, and it is thus necessary for Trainz (and it&#039;s scripted assets) to support the unloading of objects which are not currently gameplay relevant. As a result of this, numerous script functions have been declared obsolete, as they are incompatible with this concept. Below is a summary of these functions and a mention of their modern replacements.&lt;br /&gt;
&lt;br /&gt;
Note that none of the legacy functions listed here will operate correctly if the game has the &amp;quot;[[Compatibility mode]]&amp;quot; setting set to &amp;quot;Maximise performance&amp;quot; or &amp;quot;Show errors on legacy calls&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=====GameObject.GetId()=====&lt;br /&gt;
All GameObject instances within a Router are assigned a numeric integer ID. This ID was traditionally retrieved via this function. As the ID varies between runs it was never safe for long term storage, but it was suitable for short term storage and lookup. As objects can now be unloaded at any time, and these IDs then reused by totally different objects, the function has been declared obsolete. Any scripts which use it should be updated to instead use GameObjectID and the related storage functions. See the comments on GameObjectID.gs for more information.&lt;br /&gt;
&lt;br /&gt;
=====GameObject.GetName()=====&lt;br /&gt;
In addition to their integer ID certain GameObject types also supported a &amp;quot;script name&amp;quot;, which was generally automatically assigned on creation, but could also be edited by the player in some scenarios. Despite the script comments in certain older versions of Trainz, this name was never &#039;&#039;guaranteed&#039;&#039; unique, but it was generally considered to be so for ease of use (and that assumption rarely failed). This script name was typically used for object identification in medium to long term storage, including within Soups for session config, savegames, etc. Any scripts which use it should be updated to instead use GameObjectID and the related storage functions. See the comments on GameObjectID.gs for more information.&lt;br /&gt;
&lt;br /&gt;
=====Router.GetGameObject(int)=====&lt;br /&gt;
Much like GetGameObject(GameObjectID), this function would return any loaded object with the integer Router ID passed. As this ID format is now considered obsolete, so is this lookup function. Any scripts which use it should be updated to instead use GameObjectID and that function variant (or the async search functions on World). See the comments on GameObjectID.gs for more information.&lt;br /&gt;
&lt;br /&gt;
=====Router.GetGameObject(string)=====&lt;br /&gt;
Much like GetGameObject(GameObjectID), this function would return any loaded object with the &amp;quot;script name&amp;quot; string passed. As this ID format is now considered obsolete, so is this lookup function. Any scripts which use it should be updated to instead use GameObjectID and that function variant (or the async search functions on World). See the comments on GameObjectID.gs for more information.&lt;br /&gt;
&lt;br /&gt;
=====World.Get*List()=====&lt;br /&gt;
Prior to GetNamedObjectList() multiple functions existed on World to manually retrieve lists of objects of a specific type (e.g. GetIndustryList(), GetTrainList(), etc). These search functions were slow, and scripts would often stall Trainz while the searches were performed. Because of this, and the fact that the functions can now only return those objects that are currently loaded, they have been declared obsolete. Any scripts which use them for custom functionality should be updated to instead call World.GetNamedObjectList() with an appropriate category string. See the comments on this function and the AsyncObjectSearchResult in World.gs for more information on their use. Alternatively, any scripts using them for PropertyObject &amp;quot;list&amp;quot; types may be better served by the new &amp;quot;map-object&amp;quot; type, detailed [[PropertyObject#GetPropertyType|here]].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Asynchronous_Route_Streaming| Asynchronous Route Streaming]]&lt;br /&gt;
* [[Compatibility_mode| Compatibility Mode Setting]]&lt;br /&gt;
* [[HowTo/Upgrade_obsolete_script_functions| How to update obsolete script functions]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Embedded_web_browser&amp;diff=46064</id>
		<title>Embedded web browser</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Embedded_web_browser&amp;diff=46064"/>
		<updated>2026-03-25T22:05:14Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This page refers to a legacy game feature available in TS2009, TS2010 and TS12. It was removed in [[Trainz: A New Era]].&lt;br /&gt;
&lt;br /&gt;
The [[Embedded web browser]] was a full-featured web client built using [http://www.mozilla.org/ mozilla], and embedded into the TS2009/TS2010 product range. It was used for rendering actual web content and static html content, not as a replacement for the existing in-game [[MiniBrowser]] which is used for script-driven user interface.&lt;br /&gt;
&lt;br /&gt;
The browser was not intended to replace a standalone browser application such as Internet Explorer or FireFox, but rather to provide integrated access to the Trainz community and online resources without having to leave the game environment. It&#039;s expected that most users continue to use their regular browsers when outside the Trainz environment, and indeed, the same web content can be accessed from the regular browser. The advantage of the [[Embedded web browser]] was the convenience of accessing online content linked from in-game sources.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Limitations==&lt;br /&gt;
The [[Embedded web browser]] has the following limitations when compared to a standalone browser application:&lt;br /&gt;
* There is no plugin support. Hence, no Flash playback support.&lt;br /&gt;
* There is no ability to download arbitrary files. Trainz content may be download via [[Download Station]] helper links.&lt;br /&gt;
* The [[Embedded web browser]] is restricted to browsing the Trainz Online site.&lt;br /&gt;
Some of these restrictions are technical in nature, and some are due to security concerns. Specifically, N3V intend that the [[Embedded web browser]] is useful to novice users without any security concerns, and without the requirement for N3V or the user to regularly update the browser software to prevent the security flaws du jour.&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Embedded_web_browser&amp;diff=46063</id>
		<title>Embedded web browser</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Embedded_web_browser&amp;diff=46063"/>
		<updated>2026-03-25T22:04:43Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This page refers to a legacy game feature available in TS2009, TS2010 and TS12. It was removed in [[Trainz: A New Era]].&lt;br /&gt;
&lt;br /&gt;
The [[Embedded web browser]] was a full-featured web client built using [http://www.mozilla.org/ mozilla], and embedded into the TS2009/TS2010 product range. It was used for rendering actual web content and static html content, not as a replacement for the existing in-game [[MiniBrowser]] which is used for script-driven user interface.&lt;br /&gt;
&lt;br /&gt;
The [[Embedded web browser]] was not intended to replace a standalone browser application such as Internet Explorer or FireFox, but rather to provide integrated access to the Trainz community and online resources without having to leave the game environment. It&#039;s expected that most users continue to use their regular browsers when outside the Trainz environment, and indeed, the same web content can be accessed from the regular browser. The advantage of the [[Embedded web browser]] was the convenience of accessing online content linked from in-game sources.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Limitations==&lt;br /&gt;
The [[Embedded web browser]] has the following limitations when compared to a standalone browser application:&lt;br /&gt;
* There is no plugin support. Hence, no Flash playback support.&lt;br /&gt;
* There is no ability to download arbitrary files. Trainz content may be download via [[Download Station]] helper links.&lt;br /&gt;
* The [[Embedded web browser]] is restricted to browsing the Trainz Online site.&lt;br /&gt;
Some of these restrictions are technical in nature, and some are due to security concerns. Specifically, N3V intend that the [[Embedded web browser]] is useful to novice users without any security concerns, and without the requirement for N3V or the user to regularly update the browser software to prevent the security flaws du jour.&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Embedded_web_browser&amp;diff=46062</id>
		<title>Embedded web browser</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Embedded_web_browser&amp;diff=46062"/>
		<updated>2026-03-25T22:01:10Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This page refers to a legacy game feature in TS2009 and TS2010. It was removed in TS12.&lt;br /&gt;
&lt;br /&gt;
The [[Embedded web browser]] was a full-featured web client built using [http://www.mozilla.org/ mozilla], and embedded into the TS2009/TS2010 product range. It was used for rendering actual web content and static html content, not as a replacement for the existing in-game [[MiniBrowser]] which is used for script-driven user interface.&lt;br /&gt;
&lt;br /&gt;
The [[Embedded web browser]] was not intended to replace a standalone browser application such as Internet Explorer or FireFox, but rather to provide integrated access to the Trainz community and online resources without having to leave the game environment. It&#039;s expected that most users continue to use their regular browsers when outside the Trainz environment, and indeed, the same web content can be accessed from the regular browser. The advantage of the [[Embedded web browser]] was the convenience of accessing online content linked from in-game sources.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Limitations==&lt;br /&gt;
The [[Embedded web browser]] has the following limitations when compared to a standalone browser application:&lt;br /&gt;
* There is no plugin support. Hence, no Flash playback support.&lt;br /&gt;
* There is no ability to download arbitrary files. Trainz content may be download via [[Download Station]] helper links.&lt;br /&gt;
* The [[Embedded web browser]] is restricted to browsing the Trainz Online site.&lt;br /&gt;
Some of these restrictions are technical in nature, and some are due to security concerns. Specifically, N3V intend that the [[Embedded web browser]] is useful to novice users without any security concerns, and without the requirement for N3V or the user to regularly update the browser software to prevent the security flaws du jour.&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=46003</id>
		<title>Class MapObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=46003"/>
		<updated>2026-03-10T05:23:29Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* SetPFXEmitterConeSize */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Library Reference|API Hierarchy]]&lt;br /&gt;
**[[Class GSObject|GSObject]]&lt;br /&gt;
***[[Class GameObject|GameObject]]&lt;br /&gt;
****[[Class PropertyObject|PropertyObject]]&lt;br /&gt;
****[[Class TrainzGameObject|TrainzGameObject]]&lt;br /&gt;
*****[[Class MeshObject|MeshObject]]&lt;br /&gt;
******MapObject&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*This class extends MeshObject to include product queues. &lt;br /&gt;
*A MapObject can have a number of product queues as defined in the queues section of the config.txt file for the asset.&lt;br /&gt;
*The class also provides methods to control particle emissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MapObject Messages==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{TableHeader|width=50%|margin=15px}}&lt;br /&gt;
|-&lt;br /&gt;
|bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Major&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Minor&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Source&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot; |&#039;&#039;&#039;Destination&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Details||?||MapObject&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Schedule||?||MapObject&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===AdjustMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void AdjustMapObjectPosition(float dx, float dy, float dz)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;dx&#039;&#039;&#039; = The distance (m) to move the object along its x axis (right).&lt;br /&gt;
*&#039;&#039;&#039;dy&#039;&#039;&#039; = The distance (m) to move the object along its y axis (foward).&lt;br /&gt;
*&#039;&#039;&#039;dz&#039;&#039;&#039; = The distance (m) to move the object along its z axis (upward).&lt;br /&gt;
;Returned Value&lt;br /&gt;
* None.&lt;br /&gt;
;Syntax&lt;br /&gt;
 AdjustMapObjectPosition(x, y, z);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native Orientation GetMapObjectOrientation(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute orientation of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float angel_z = cabin.Loco.GetMapObjectOrientation().rz;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectOrientation() which immediately follows a call to SetMapObjectOrientation() is not guaranteed to return the input orientation, since various other orientation restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native WorldCoordinate GetMapObjectPosition(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute position of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float axis_z = cabin.Loco.GetMapObjectPosition().z;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectPosition() which immediately follows a call to SetMapObjectPosition() is not guaranteed to return the input position, since various other position restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterLifetime(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value of the lifetime of the effect at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float lifetime GetPFXEmitterLifetime(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxRate = GetPFXEmitterMaxRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minRtae = GetPFXEmitterMinRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Minimum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterPhysicsDelay(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value for the physics delay in emission.&lt;br /&gt;
;Syntax&lt;br /&gt;
 GetPFXEmitterPhysicsDelay(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterRate(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Rate of particle creation per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 particlesPerSecond = GetPFXEmitterRate(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterVelocity(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float speed = GetPFXEmitterVelocity(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueue===&lt;br /&gt;
{{MethodHeader|public native ProductQueue GetQueue(string queueName)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;queueName&#039;&#039;&#039; = Name of the product queue to be returned.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*A reference to the queue if possible, null otherwise.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue queue = GetQueue(&amp;quot;passengers&amp;quot;);&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueues===&lt;br /&gt;
{{MethodHeader|public native ProductQueue[ ] GetQueues(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*None&lt;br /&gt;
;Returned Value&lt;br /&gt;
*An array of product queues, if there are no queues the array will be empty.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue[] queues = GetQueues();&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===PlaySoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void PlaySoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 PlaySoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Plays the specified sound event from the asset&#039;s SoundScript. &lt;br /&gt;
*SoundScripts are defined as sub-containers in the soundscript container of the asset&#039;s configuration. &lt;br /&gt;
*For details on creating assets with SoundScripts, see [[&amp;quot;Soundscript&amp;quot; container|here]]. &lt;br /&gt;
*This method will start playing the sound. &lt;br /&gt;
*Depending on the SoundScript configuration, the sound will either be played just once or played continuously in a looping cycle such that [[#StopSoundScriptEvent|StopSoundScriptEvent()]] will need to be called to stop it.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectOrientation(Orientation orientation)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;orientation&#039;&#039;&#039; =  The new orientation intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectOrientation(or);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly reorients this MapObject to the specified absolute orientation, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) Various object parameters and game states may restrict or remove the ability to reorient objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectPosition(WorldCoordinate position)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;position&#039;&#039;&#039; =  The new position intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectPosition(pos);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly repositions this MapObject to the specified absolute position, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) This function may be VERY slow and should generally not be used. Various object parameters and game states may restrict or remove the ability to position objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterConeSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterConeSize(int id, float x, float y, float z)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;x,y,z&#039;&#039;&#039; = New X,Y and Z components of the particle cone size.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterConeSize(0,2.0,3.0,2.0);&lt;br /&gt;
;Notes&lt;br /&gt;
* This function was broken during development of TS2009, and hasn&#039;t worked for almost 20 years. It&#039;s confirmed it will be fixed in a future release, but as it was broken for so long it will now only function on content with a trainz-build &amp;gt;= 5.8&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEmitParticles===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEmitParticles(int id, int number,float time)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;number&#039;&#039;&#039; = The number of particles to emit.&lt;br /&gt;
*&#039;&#039;&#039;time&#039;&#039;&#039; = The time period that this particle emission is for (ie. this would typically be the amount of time that has passed since this was last called, for this particular emitter).&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEmitParticles(0, 2, 0.1);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEndColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEndColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterLifetime(int id, int phase, float life)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;life&#039;&#039;&#039; = The new lifetime of particles in seconds at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterLifetime(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxRate(int id, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new maximum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new maximum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinRate(int id, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new minimum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new minimum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterPhysicsDelay(int id, int phase, float value)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; = The new physics delay value to set for the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterPhysicsDelay(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterRate(int id, int phase, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = New rate of particle creation per second at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterRate(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterStartColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterStartColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterTexture===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterTexture(int id, KUID textureKUID)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;textureKUID&#039;&#039;&#039; = The kuid of the new texture.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Notes&lt;br /&gt;
Not currently supported! In older Trainz versions this would change the texture for a particle emitter, but this has not been supported since TANE.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterVelocity(int id, int phase, float velocity)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;velocity&#039;&#039;&#039; = New velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterVelocity(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===StopSoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void StopSoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 StopSoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Terminates a looped sound script previously started with [[#PlaySoundScriptEvent|PlaySoundScriptEvent()]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=46002</id>
		<title>Class MapObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=46002"/>
		<updated>2026-03-10T05:22:54Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* SetPFXEmitterConeSize */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Library Reference|API Hierarchy]]&lt;br /&gt;
**[[Class GSObject|GSObject]]&lt;br /&gt;
***[[Class GameObject|GameObject]]&lt;br /&gt;
****[[Class PropertyObject|PropertyObject]]&lt;br /&gt;
****[[Class TrainzGameObject|TrainzGameObject]]&lt;br /&gt;
*****[[Class MeshObject|MeshObject]]&lt;br /&gt;
******MapObject&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*This class extends MeshObject to include product queues. &lt;br /&gt;
*A MapObject can have a number of product queues as defined in the queues section of the config.txt file for the asset.&lt;br /&gt;
*The class also provides methods to control particle emissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MapObject Messages==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{TableHeader|width=50%|margin=15px}}&lt;br /&gt;
|-&lt;br /&gt;
|bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Major&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Minor&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Source&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot; |&#039;&#039;&#039;Destination&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Details||?||MapObject&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Schedule||?||MapObject&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===AdjustMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void AdjustMapObjectPosition(float dx, float dy, float dz)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;dx&#039;&#039;&#039; = The distance (m) to move the object along its x axis (right).&lt;br /&gt;
*&#039;&#039;&#039;dy&#039;&#039;&#039; = The distance (m) to move the object along its y axis (foward).&lt;br /&gt;
*&#039;&#039;&#039;dz&#039;&#039;&#039; = The distance (m) to move the object along its z axis (upward).&lt;br /&gt;
;Returned Value&lt;br /&gt;
* None.&lt;br /&gt;
;Syntax&lt;br /&gt;
 AdjustMapObjectPosition(x, y, z);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native Orientation GetMapObjectOrientation(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute orientation of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float angel_z = cabin.Loco.GetMapObjectOrientation().rz;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectOrientation() which immediately follows a call to SetMapObjectOrientation() is not guaranteed to return the input orientation, since various other orientation restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native WorldCoordinate GetMapObjectPosition(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute position of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float axis_z = cabin.Loco.GetMapObjectPosition().z;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectPosition() which immediately follows a call to SetMapObjectPosition() is not guaranteed to return the input position, since various other position restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterLifetime(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value of the lifetime of the effect at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float lifetime GetPFXEmitterLifetime(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxRate = GetPFXEmitterMaxRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minRtae = GetPFXEmitterMinRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Minimum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterPhysicsDelay(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value for the physics delay in emission.&lt;br /&gt;
;Syntax&lt;br /&gt;
 GetPFXEmitterPhysicsDelay(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterRate(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Rate of particle creation per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 particlesPerSecond = GetPFXEmitterRate(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterVelocity(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float speed = GetPFXEmitterVelocity(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueue===&lt;br /&gt;
{{MethodHeader|public native ProductQueue GetQueue(string queueName)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;queueName&#039;&#039;&#039; = Name of the product queue to be returned.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*A reference to the queue if possible, null otherwise.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue queue = GetQueue(&amp;quot;passengers&amp;quot;);&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueues===&lt;br /&gt;
{{MethodHeader|public native ProductQueue[ ] GetQueues(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*None&lt;br /&gt;
;Returned Value&lt;br /&gt;
*An array of product queues, if there are no queues the array will be empty.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue[] queues = GetQueues();&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===PlaySoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void PlaySoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 PlaySoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Plays the specified sound event from the asset&#039;s SoundScript. &lt;br /&gt;
*SoundScripts are defined as sub-containers in the soundscript container of the asset&#039;s configuration. &lt;br /&gt;
*For details on creating assets with SoundScripts, see [[&amp;quot;Soundscript&amp;quot; container|here]]. &lt;br /&gt;
*This method will start playing the sound. &lt;br /&gt;
*Depending on the SoundScript configuration, the sound will either be played just once or played continuously in a looping cycle such that [[#StopSoundScriptEvent|StopSoundScriptEvent()]] will need to be called to stop it.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectOrientation(Orientation orientation)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;orientation&#039;&#039;&#039; =  The new orientation intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectOrientation(or);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly reorients this MapObject to the specified absolute orientation, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) Various object parameters and game states may restrict or remove the ability to reorient objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectPosition(WorldCoordinate position)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;position&#039;&#039;&#039; =  The new position intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectPosition(pos);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly repositions this MapObject to the specified absolute position, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) This function may be VERY slow and should generally not be used. Various object parameters and game states may restrict or remove the ability to position objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterConeSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterConeSize(int id, float x, float y, float z)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;x,y,z&#039;&#039;&#039; = New X,Y and Z components of the particle cone size.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterConeSize(0,2.0,3.0,2.0);&lt;br /&gt;
;Notes&lt;br /&gt;
* This function was bugged in TS2009, and hasn&#039;t worked for almost 20 years. It&#039;s confirmed it will be fixed in a future release, but as it was broken for so long it will now only function on content with a trainz-build &amp;gt;= 5.8&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEmitParticles===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEmitParticles(int id, int number,float time)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;number&#039;&#039;&#039; = The number of particles to emit.&lt;br /&gt;
*&#039;&#039;&#039;time&#039;&#039;&#039; = The time period that this particle emission is for (ie. this would typically be the amount of time that has passed since this was last called, for this particular emitter).&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEmitParticles(0, 2, 0.1);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEndColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEndColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterLifetime(int id, int phase, float life)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;life&#039;&#039;&#039; = The new lifetime of particles in seconds at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterLifetime(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxRate(int id, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new maximum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new maximum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinRate(int id, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new minimum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new minimum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterPhysicsDelay(int id, int phase, float value)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; = The new physics delay value to set for the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterPhysicsDelay(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterRate(int id, int phase, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = New rate of particle creation per second at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterRate(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterStartColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterStartColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterTexture===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterTexture(int id, KUID textureKUID)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;textureKUID&#039;&#039;&#039; = The kuid of the new texture.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Notes&lt;br /&gt;
Not currently supported! In older Trainz versions this would change the texture for a particle emitter, but this has not been supported since TANE.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterVelocity(int id, int phase, float velocity)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;velocity&#039;&#039;&#039; = New velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterVelocity(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===StopSoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void StopSoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 StopSoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Terminates a looped sound script previously started with [[#PlaySoundScriptEvent|PlaySoundScriptEvent()]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=45953</id>
		<title>Class MapObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=45953"/>
		<updated>2026-02-24T00:25:48Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* SetPFXEmitterTexture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Library Reference|API Hierarchy]]&lt;br /&gt;
**[[Class GSObject|GSObject]]&lt;br /&gt;
***[[Class GameObject|GameObject]]&lt;br /&gt;
****[[Class PropertyObject|PropertyObject]]&lt;br /&gt;
****[[Class TrainzGameObject|TrainzGameObject]]&lt;br /&gt;
*****[[Class MeshObject|MeshObject]]&lt;br /&gt;
******MapObject&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*This class extends MeshObject to include product queues. &lt;br /&gt;
*A MapObject can have a number of product queues as defined in the queues section of the config.txt file for the asset.&lt;br /&gt;
*The class also provides methods to control particle emissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MapObject Messages==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{TableHeader|width=50%|margin=15px}}&lt;br /&gt;
|-&lt;br /&gt;
|bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Major&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Minor&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Source&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot; |&#039;&#039;&#039;Destination&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Details||?||MapObject&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Schedule||?||MapObject&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===AdjustMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void AdjustMapObjectPosition(float dx, float dy, float dz)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;dx&#039;&#039;&#039; = The distance (m) to move the object along its x axis (right).&lt;br /&gt;
*&#039;&#039;&#039;dy&#039;&#039;&#039; = The distance (m) to move the object along its y axis (foward).&lt;br /&gt;
*&#039;&#039;&#039;dz&#039;&#039;&#039; = The distance (m) to move the object along its z axis (upward).&lt;br /&gt;
;Returned Value&lt;br /&gt;
* None.&lt;br /&gt;
;Syntax&lt;br /&gt;
 AdjustMapObjectPosition(x, y, z);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native Orientation GetMapObjectOrientation(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute orientation of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float angel_z = cabin.Loco.GetMapObjectOrientation().rz;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectOrientation() which immediately follows a call to SetMapObjectOrientation() is not guaranteed to return the input orientation, since various other orientation restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native WorldCoordinate GetMapObjectPosition(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute position of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float axis_z = cabin.Loco.GetMapObjectPosition().z;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectPosition() which immediately follows a call to SetMapObjectPosition() is not guaranteed to return the input position, since various other position restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterLifetime(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value of the lifetime of the effect at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float lifetime GetPFXEmitterLifetime(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxRate = GetPFXEmitterMaxRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minRtae = GetPFXEmitterMinRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Minimum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterPhysicsDelay(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value for the physics delay in emission.&lt;br /&gt;
;Syntax&lt;br /&gt;
 GetPFXEmitterPhysicsDelay(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterRate(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Rate of particle creation per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 particlesPerSecond = GetPFXEmitterRate(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterVelocity(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float speed = GetPFXEmitterVelocity(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueue===&lt;br /&gt;
{{MethodHeader|public native ProductQueue GetQueue(string queueName)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;queueName&#039;&#039;&#039; = Name of the product queue to be returned.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*A reference to the queue if possible, null otherwise.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue queue = GetQueue(&amp;quot;passengers&amp;quot;);&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueues===&lt;br /&gt;
{{MethodHeader|public native ProductQueue[ ] GetQueues(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*None&lt;br /&gt;
;Returned Value&lt;br /&gt;
*An array of product queues, if there are no queues the array will be empty.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue[] queues = GetQueues();&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===PlaySoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void PlaySoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 PlaySoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Plays the specified sound event from the asset&#039;s SoundScript. &lt;br /&gt;
*SoundScripts are defined as sub-containers in the soundscript container of the asset&#039;s configuration. &lt;br /&gt;
*For details on creating assets with SoundScripts, see [[&amp;quot;Soundscript&amp;quot; container|here]]. &lt;br /&gt;
*This method will start playing the sound. &lt;br /&gt;
*Depending on the SoundScript configuration, the sound will either be played just once or played continuously in a looping cycle such that [[#StopSoundScriptEvent|StopSoundScriptEvent()]] will need to be called to stop it.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectOrientation(Orientation orientation)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;orientation&#039;&#039;&#039; =  The new orientation intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectOrientation(or);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly reorients this MapObject to the specified absolute orientation, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) Various object parameters and game states may restrict or remove the ability to reorient objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectPosition(WorldCoordinate position)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;position&#039;&#039;&#039; =  The new position intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectPosition(pos);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly repositions this MapObject to the specified absolute position, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) This function may be VERY slow and should generally not be used. Various object parameters and game states may restrict or remove the ability to position objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterConeSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterConeSize(int id, float x, float y, float z)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;x,y,z&#039;&#039;&#039; = New X,Y and Z components of the particle cone size.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterConeSize(0,2.0,3.0,2.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEmitParticles===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEmitParticles(int id, int number,float time)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;number&#039;&#039;&#039; = The number of particles to emit.&lt;br /&gt;
*&#039;&#039;&#039;time&#039;&#039;&#039; = The time period that this particle emission is for (ie. this would typically be the amount of time that has passed since this was last called, for this particular emitter).&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEmitParticles(0, 2, 0.1);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEndColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEndColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterLifetime(int id, int phase, float life)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;life&#039;&#039;&#039; = The new lifetime of particles in seconds at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterLifetime(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxRate(int id, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new maximum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new maximum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinRate(int id, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new minimum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new minimum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterPhysicsDelay(int id, int phase, float value)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; = The new physics delay value to set for the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterPhysicsDelay(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterRate(int id, int phase, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = New rate of particle creation per second at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterRate(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterStartColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterStartColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterTexture===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterTexture(int id, KUID textureKUID)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;textureKUID&#039;&#039;&#039; = The kuid of the new texture.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Notes&lt;br /&gt;
Not currently supported! In older Trainz versions this would change the texture for a particle emitter, but this has not been supported since TANE.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterVelocity(int id, int phase, float velocity)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;velocity&#039;&#039;&#039; = New velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterVelocity(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===StopSoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void StopSoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 StopSoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Terminates a looped sound script previously started with [[#PlaySoundScriptEvent|PlaySoundScriptEvent()]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=45952</id>
		<title>Class MapObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=45952"/>
		<updated>2026-02-24T00:21:44Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* SetPFXEmitterEmitParticles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Library Reference|API Hierarchy]]&lt;br /&gt;
**[[Class GSObject|GSObject]]&lt;br /&gt;
***[[Class GameObject|GameObject]]&lt;br /&gt;
****[[Class PropertyObject|PropertyObject]]&lt;br /&gt;
****[[Class TrainzGameObject|TrainzGameObject]]&lt;br /&gt;
*****[[Class MeshObject|MeshObject]]&lt;br /&gt;
******MapObject&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*This class extends MeshObject to include product queues. &lt;br /&gt;
*A MapObject can have a number of product queues as defined in the queues section of the config.txt file for the asset.&lt;br /&gt;
*The class also provides methods to control particle emissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MapObject Messages==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{TableHeader|width=50%|margin=15px}}&lt;br /&gt;
|-&lt;br /&gt;
|bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Major&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Minor&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot;|&#039;&#039;&#039;Source&#039;&#039;&#039;||bgcolor=&amp;quot;#EEEEEE&amp;quot; |&#039;&#039;&#039;Destination&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Details||?||MapObject&lt;br /&gt;
|-&lt;br /&gt;
|[[MapObject Messages|MapObject]]||View-Schedule||?||MapObject&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Methods==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===AdjustMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void AdjustMapObjectPosition(float dx, float dy, float dz)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;dx&#039;&#039;&#039; = The distance (m) to move the object along its x axis (right).&lt;br /&gt;
*&#039;&#039;&#039;dy&#039;&#039;&#039; = The distance (m) to move the object along its y axis (foward).&lt;br /&gt;
*&#039;&#039;&#039;dz&#039;&#039;&#039; = The distance (m) to move the object along its z axis (upward).&lt;br /&gt;
;Returned Value&lt;br /&gt;
* None.&lt;br /&gt;
;Syntax&lt;br /&gt;
 AdjustMapObjectPosition(x, y, z);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native Orientation GetMapObjectOrientation(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute orientation of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float angel_z = cabin.Loco.GetMapObjectOrientation().rz;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectOrientation() which immediately follows a call to SetMapObjectOrientation() is not guaranteed to return the input orientation, since various other orientation restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native WorldCoordinate GetMapObjectPosition(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
* None.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*The absolute position of this MapObject.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float axis_z = cabin.Loco.GetMapObjectPosition().z;&lt;br /&gt;
;Notes&lt;br /&gt;
* A call to GetMapObjectPosition() which immediately follows a call to SetMapObjectPosition() is not guaranteed to return the input position, since various other position restrictions may be in effect.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterLifetime(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value of the lifetime of the effect at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float lifetime GetPFXEmitterLifetime(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxRate = GetPFXEmitterMaxRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMaxSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float maxsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinRate(int id)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Maximum rate of emissions per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minRtae = GetPFXEmitterMinRate(0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterMinSize(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Minimum size of particle at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float minsize = GetPFXEmitterMinSize();&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterPhysicsDelay(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Value for the physics delay in emission.&lt;br /&gt;
;Syntax&lt;br /&gt;
 GetPFXEmitterPhysicsDelay(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterRate(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Rate of particle creation per second.&lt;br /&gt;
;Syntax&lt;br /&gt;
 particlesPerSecond = GetPFXEmitterRate(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native float GetPFXEmitterVelocity(int id, int phase)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float speed = GetPFXEmitterVelocity(0,0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueue===&lt;br /&gt;
{{MethodHeader|public native ProductQueue GetQueue(string queueName)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;queueName&#039;&#039;&#039; = Name of the product queue to be returned.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*A reference to the queue if possible, null otherwise.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue queue = GetQueue(&amp;quot;passengers&amp;quot;);&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===GetQueues===&lt;br /&gt;
{{MethodHeader|public native ProductQueue[ ] GetQueues(void)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*None&lt;br /&gt;
;Returned Value&lt;br /&gt;
*An array of product queues, if there are no queues the array will be empty.&lt;br /&gt;
;Syntax&lt;br /&gt;
 ProductQueue[] queues = GetQueues();&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===PlaySoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void PlaySoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 PlaySoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Plays the specified sound event from the asset&#039;s SoundScript. &lt;br /&gt;
*SoundScripts are defined as sub-containers in the soundscript container of the asset&#039;s configuration. &lt;br /&gt;
*For details on creating assets with SoundScripts, see [[&amp;quot;Soundscript&amp;quot; container|here]]. &lt;br /&gt;
*This method will start playing the sound. &lt;br /&gt;
*Depending on the SoundScript configuration, the sound will either be played just once or played continuously in a looping cycle such that [[#StopSoundScriptEvent|StopSoundScriptEvent()]] will need to be called to stop it.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectOrientation===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectOrientation(Orientation orientation)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;orientation&#039;&#039;&#039; =  The new orientation intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectOrientation(or);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly reorients this MapObject to the specified absolute orientation, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) Various object parameters and game states may restrict or remove the ability to reorient objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetMapObjectPosition===&lt;br /&gt;
{{MethodHeader|public native void SetMapObjectPosition(WorldCoordinate position)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;position&#039;&#039;&#039; =  The new position intended for this MapObject.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetMapObjectPosition(pos);&lt;br /&gt;
;Notes&lt;br /&gt;
*Instantly repositions this MapObject to the specified absolute position, as best possible. This will not successfully reposition a MapObject which has a parent relationship (for example, a Trackside object.) This function may be VERY slow and should generally not be used. Various object parameters and game states may restrict or remove the ability to position objects.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterConeSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterConeSize(int id, float x, float y, float z)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;x,y,z&#039;&#039;&#039; = New X,Y and Z components of the particle cone size.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterConeSize(0,2.0,3.0,2.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEmitParticles===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEmitParticles(int id, int number,float time)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;number&#039;&#039;&#039; = The number of particles to emit.&lt;br /&gt;
*&#039;&#039;&#039;time&#039;&#039;&#039; = The time period that this particle emission is for (ie. this would typically be the amount of time that has passed since this was last called, for this particular emitter).&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEmitParticles(0, 2, 0.1);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterEndColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterEndColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterEndColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterLifetime===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterLifetime(int id, int phase, float life)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;life&#039;&#039;&#039; = The new lifetime of particles in seconds at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterLifetime(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxRate(int id, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new maximum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMaxSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMaxSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new maximum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMaxSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinRate(int id, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = The new minimum rate of emission per second.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinRate(0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterMinSize===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterMinSize(int id, int phase, float newsize)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;newsize&#039;&#039;&#039; = The new minimum size of particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterMinSize(0,0,10);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterPhysicsDelay===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterPhysicsDelay(int id, int phase, float value)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; = The new physics delay value to set for the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterPhysicsDelay(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterRate===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterRate(int id, int phase, float rate)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;rate&#039;&#039;&#039; = New rate of particle creation per second at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterRate(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterStartColor===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterStartColor(int id, int phase, float r, float g, float b, float a)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;r,g,b&#039;&#039;&#039; = Red, green and blue components of the required color.&lt;br /&gt;
*&#039;&#039;&#039;a&#039;&#039;&#039; = Alpha value of the color.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,128,128,128,64);&lt;br /&gt;
 SetPFXEmitterStartColor(0,0,0.5,0.5,0.5,0.25);&lt;br /&gt;
;Notes&lt;br /&gt;
*Red, green, blue and alpha may be entered as integer or float values in the ranges 0..255 and 0.0..1.0 respectively.&lt;br /&gt;
*Both of the examples above give the same result.&lt;br /&gt;
*Note that 1,1,1,1 will be interpreted as float input and will produce white, whereas 2,2,2,2 will be interpreted as integers and will give a result which is almost black.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterTexture===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterTexture(int id, KUID textureKUID)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;textureKUID&#039;&#039;&#039; = The kuid of the new texture.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterTexture(0,&amp;lt;kuid:1234:5678&amp;gt;);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SetPFXEmitterVelocity===&lt;br /&gt;
{{MethodHeader|public native void SetPFXEmitterVelocity(int id, int phase, float velocity)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;id&#039;&#039;&#039; = The ID of the particle effect, starting at zero and in the order defined in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;phase&#039;&#039;&#039; = The phase of the effect, if there is only one phase use zero.&lt;br /&gt;
*&#039;&#039;&#039;velocity&#039;&#039;&#039; = New velocity in metres per second along the direction vector of emitted particles at the specified phase.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterVelocity(0,0,5.0);&lt;br /&gt;
;Notes&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===StopSoundScriptEvent===&lt;br /&gt;
{{MethodHeader|public native void StopSoundScriptEvent(string soundTrigger)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
&#039;&#039;&#039;soundTrigger&#039;&#039;&#039; = Name of the sound event to start playing, this equates to the &#039;&#039;trigger&#039;&#039; tag of the sound script subcontainer in &#039;&#039;config.txt&#039;&#039;.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 StopSoundScriptEvent(&amp;quot;dayloop&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Terminates a looped sound script previously started with [[#PlaySoundScriptEvent|PlaySoundScriptEvent()]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=%22Volume%22_container&amp;diff=45938</id>
		<title>&quot;Volume&quot; container</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=%22Volume%22_container&amp;diff=45938"/>
		<updated>2026-02-18T01:13:32Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: /* no4pipe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Volume container is a top-level [[config.txt file]] entry used by [[KIND Engine|Enginespec]] and [[KIND Steam-engine|Steam Enginespec]] assets.&lt;br /&gt;
&lt;br /&gt;
==Supported Tags==&lt;br /&gt;
&lt;br /&gt;
The Volume container supports the following tags. Each tag is show here with its default value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 volume&lt;br /&gt;
 {&lt;br /&gt;
     scale 1.0&lt;br /&gt;
     trainbrakepipe 0.2&lt;br /&gt;
     epreservoirpipe 0.2&lt;br /&gt;
     no3pipe 0.2&lt;br /&gt;
     no4pipe 0.2&lt;br /&gt;
     auxreservoir 0.0384678&lt;br /&gt;
     autobrakecylinder 0.00969387&lt;br /&gt;
     vacuumbrakepipe 0.0&lt;br /&gt;
     vacuumbrakereservoir 0.0&lt;br /&gt;
     vacuumbrakecylinder 0.0&lt;br /&gt;
     mainreservoir 1.0&lt;br /&gt;
     equaliser 0.5&lt;br /&gt;
     independantbrakecylinder 0.0103239&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====scale====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Sets the scale for the given pressure values. This allows an engine asset to provide values in imperial units, and then rescale them to the expected SI units.&lt;br /&gt;
&lt;br /&gt;
====trainbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: brake pipe volume.&lt;br /&gt;
&lt;br /&gt;
====epreservoirpipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For electro pneumatic braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====no3pipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Independent brake pipe.&lt;br /&gt;
&lt;br /&gt;
====no4pipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Bail pipe volume.&lt;br /&gt;
&lt;br /&gt;
====auxreservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Auxiliary reservoir volume.&lt;br /&gt;
&lt;br /&gt;
====autobrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Brake cylinder volume.&lt;br /&gt;
&lt;br /&gt;
====vacuumbrakepipe====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For vacuum braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====vacuumbrakereservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For vacuum braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====vacuumbrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: For vacuum braking - not currently in use, generally leave this setting.&lt;br /&gt;
&lt;br /&gt;
====mainreservoir====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Main reservoir volume.&lt;br /&gt;
&lt;br /&gt;
====equaliser====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Equalising reservoir volume.&lt;br /&gt;
&lt;br /&gt;
====independantbrakecylinder====&lt;br /&gt;
:Type: Decimal&lt;br /&gt;
:Desc: Loco brake cylinder volume.&lt;br /&gt;
&lt;br /&gt;
==Example volume container==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TBD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Config Container|V]]&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=TNI_Physics_Interface&amp;diff=45931</id>
		<title>TNI Physics Interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=TNI_Physics_Interface&amp;diff=45931"/>
		<updated>2026-02-16T02:28:42Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TNIPhysics is a builtin TNILibrary within Trainz which allows [[KIND tni-physics-plugin|physics plugin]] assets to control all the internal train physics for any traincar. This includes engine physics, braking systems and shared systems such as track/air resistance. It doesn&#039;t currently include systems such as random motion, coupling interactions, collisions or derailments.&lt;br /&gt;
&lt;br /&gt;
Before continuing, it is recommended you first familiarise yourself with the following pages:&lt;br /&gt;
* [[TrainzNativeInterface]] - For an overview of TNI and the associated licensing requirements&lt;br /&gt;
* [[TNI Core Interface]] - For details of the core TNI functionality, object types, etc.&lt;br /&gt;
* [[KIND tni-physics-plugin]] - For the specification of the physics plugin asset kind.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: This page is a work in progress. If you notice anything out of date, please advise N3V Games.&#039;&#039;&lt;br /&gt;
&#039;&#039;The original release of TNI Physics was in TRS19 SP3 in April 2021. However information and systems may change over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
TNIPhysics is initialised at game startup, and will automatically locate and load any installed TNI physics plugin assets at world/map load time. All TNIPhysics plugins must have a QueryProcessingPriority function, which will allow Trainz to determine which of the user&#039;s installed plugins is best suited to handle each specific vehicle. TNIPhysics will make all physics update calls through the plugin&#039;s LibraryCall interface.&lt;br /&gt;
&lt;br /&gt;
The specific function calls supported by TNIPhysics are detailed in the next section.&lt;br /&gt;
&lt;br /&gt;
==TNIPhysics Library Calls==&lt;br /&gt;
&lt;br /&gt;
====Init====&lt;br /&gt;
TNIPhysics will call the plugin library DLL with the function name &amp;quot;Init&amp;quot; on initialization. This call can safely be ignored if no initialisation is necessary. This function expects no return object, and takes no parameters.&lt;br /&gt;
&lt;br /&gt;
====QueryProcessingPriority====&lt;br /&gt;
This function is called from Trainz code to query the processing priority of a plugin for a given traincar. The function will be called across every plugin for every vehicle at load/creation time and when switching control modes (DCC vs cab). Whichever plugin returns the highest priority result will process the vehicle&#039;s physics. It has a single TNIPhysicsVehicle as the param, and expects a TNIInteger return result. The TNIPhysics_Priority enum defines a list of example return values, but the programmer is not constrained to using these defines.&lt;br /&gt;
*TNIPhysics_PriorityInvalid - Never use this plugin (-127)&lt;br /&gt;
*TNIPhysics_PriorityLowest - Only use this plugin if there&#039;s no other option (-20)&lt;br /&gt;
*TNIPhysics_PriorityLow - Prefer not using this plugin, but it might work ok (-10)&lt;br /&gt;
*TNIPhysics_PriorityDefault - This plugin can handle the request adequately (0). The builtin core plugin asset always returns this value.&lt;br /&gt;
*TNIPhysics_PriorityHigh - This plugin is somewhat specialised to handle the request (10)&lt;br /&gt;
*TNIPhysics_PriorityHighest - This plugin was built exactly for this request (20)&lt;br /&gt;
&lt;br /&gt;
====RegisterVehicle====&lt;br /&gt;
This function is called from Trainz code on the plugin which returns the highest valid result from a call to &amp;quot;QueryProcessingPriority&amp;quot;. It notifies a physics plugin that it has been selected to manage the vehicle, and should perform any appropriate internal initialisation. This function takes a single TNIPhysicsVehicle param (being the vehicle to register) and expects no return object.&lt;br /&gt;
&lt;br /&gt;
====UnregisterVehicle====&lt;br /&gt;
This function is the counter to RegisterVehicle, and instructs a plugin that it is no longer managing the physics for a particular vehicle. This will occur when the vehicle is deleted, or Trainz hands it over to a more appropriate plugin (based on the result of a call to the &amp;quot;QueryProcessingPriority&amp;quot; function). This function takes a single TNIPhysicsVehicle param (being the vehicle to unregister) and expects no return object. &lt;br /&gt;
&lt;br /&gt;
When called, the plugin should discard any internal data is has for the specified vehicle. If Trainz required anything to be saved, then a TNIP_SaveVehicleState command will have already been run.&lt;br /&gt;
&lt;br /&gt;
====ProcessPhysicsCommands====&lt;br /&gt;
The main vehicle update function. This function is called from Trainz code to process a physics command stream for a specific vehicle. The function takes a TNIArray object which contains the TNIPhysicsVehicle (element 0) and a TNIStream (element 1) containing the commands to run (see enum TNIPhysicsPluginCommand for a list of physics commands and their params). Trainz expects a TNIStream return result, containing a list of physics update commands to Trainz from the plugin (see enum TNIPhysicsGameCommand).&lt;br /&gt;
&lt;br /&gt;
==Physics Commands==&lt;br /&gt;
The ProcessPhysicsCommands LibraryCall uses incoming and outgoing command buffers to communicate physics information with Trainz.&lt;br /&gt;
The command buffer data is sequential - each command ID is written as a 16 bit integer, and will be followed followed by any relevant command parameters (see enum TNIPhysicsPluginCommand for specific command details).&lt;br /&gt;
&lt;br /&gt;
As this is a raw command stream it is critical that the programmer carefully reads the documentation on each specific command, and correctly reads off each parameter value, even if they are not being used by the plugin. Failure to correctly read all command parameters will result in corruption of the stream, and undefinied application behaviour.&lt;br /&gt;
&lt;br /&gt;
The stream has no terminating value, but stream end may be detected using the TNIStreamTell and TNIStreamGetSize functions, or simply by reading commands until failure is detected (e.g. &amp;lt;code&amp;gt;while (TNIStreamReadInt16(commandStream, 0))&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The programmer must employ similar practices when writing the reply command stream. I.e. Each command is written as a 16 bit integer (TNIStreamWriteInt16), and must be followed by the parameters detailed in enum TNIPhysicsGameCommand. Failure to write data in the correct format will result in undefined behaviour within the application.&lt;br /&gt;
&lt;br /&gt;
==Incoming Commands (TNIPhysicsPluginCommand)==&lt;br /&gt;
The following describes the possible physics commands the game may issue to a plugin, as per &amp;lt;code&amp;gt;enum TNIPhysicsPluginCommand&amp;lt;/code&amp;gt;. Commands and parameters will be written, in sequence, to the TNIStream param passed to the ProcessPhysicsCommands library call.&lt;br /&gt;
&lt;br /&gt;
====TNIP_UpdatePhysicsForVehicle====&lt;br /&gt;
The main physics update function. This is regularly called by Trainz code to update the traincar physics for a particular time period. This function takes two extra params for the front and rear coupled vehicles, but keep in mind these may be using different TNI plugins.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The time interval to update for.&lt;br /&gt;
*TNIPhysicsVehicle - The front coupled vehicle.&lt;br /&gt;
*TNIPhysicsVehicle - The rear coupled vehicle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_AdjustMomentum====&lt;br /&gt;
Called from Trainz to notify of an adjustment to a vehicles momentum. This is typically used to apply the results of coupler physics interactions. Vehicles for which the plugin does not internally track momentum can safely ignore this call.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new vehicle momentum.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_FinaliseFramePhysics====&lt;br /&gt;
Called by Trainz to notify that all updates relating to this vehicle for the current frame are complete. This includes all plugin updates and all coupler interactions. Plugins may use this as an appropriate location to synchronise plugin state to that of the game, or apply visible state changes only. At the time this call is made it is &amp;quot;too late&amp;quot; to perform or apply physics calculations for a given frame.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The time interval that&#039;s been updated.&lt;br /&gt;
*double - The final momentum for this frame.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_NormalisePhysicsData====&lt;br /&gt;
Called following an external physics state update in order to perform any physics-mode-specific follow up validation/correction. Examples include after physics/control state replication in multiplayer.&lt;br /&gt;
&lt;br /&gt;
This command takes no parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SaveVehicleState====&lt;br /&gt;
Called by Trainz code to request save data for a specific vehicle. If the plugin maintains any internal state for the specified vehicle then this function should save that state, so that players are able to save and reload with seamless physics behaviour. The save state should be returned to the game by adding a TNIP_ReturnSaveState command to the library call result stream (see TNIPhysicsGameCommand for more). If the plugin tracks no state for the vehicle passed, then this call can be safely ignored. That said, it is courteous to return known/common save data, even if this plugin itself may not use/require it, as it aids in seemless plugin switchover during gameplay.&lt;br /&gt;
&lt;br /&gt;
This command takes no parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_LoadVehicleState====&lt;br /&gt;
Called by Trainz code to load previously saved vehicle state. Note that this is always called during load, even if the plugin does not produce any save state when TNIP_SaveVehicleState is called. Also note that the passed soup param may have been produced by a different plugin.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNISoup - A saved soup generated by a previous TNIP_SaveVehicleState call on this or another plugin. The soup will contain an AssetID param for the plugin that produced it, using the tag name &amp;quot;plugin-kuid&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SteamEngine_AddCoalToFire====&lt;br /&gt;
Called by Trainz code to add coal to a steam engine. For example, when the player uses the manual &amp;quot;Shovel coal&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The volume (not mass) of coal to add.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ScriptFunctionCall====&lt;br /&gt;
Called from script to execute custom behaviour within the plugin. This will be added when a script calls Vehicle.LibraryCallPhysicsPlugin().&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNILabel - The name of the plugin function to execute. If the function name is unrecognised or unsupported, the plugin should log an error and ignore it. (The TNISoup param must still be read though, to avoid the command stream being corrupted.)&lt;br /&gt;
*TNISoup - An optional TNISoup to be included with the command. This is used to pass more parameters to the custom plugin function, where required. Parsing code must handle the possibility that the parameter is null, even if the extra parameters are not optional for the plugin code. Similarly, plugins must not make assumptions about the validity of the soup data, and should either appropriately handle all inputs or ignore the command entirely.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Outgoing Commands (TNIPhysicsGameCommand)==&lt;br /&gt;
The following describes the possible physics commands a plugin may issue to the game, as per &amp;lt;code&amp;gt;enum TNIPhysicsGameCommand&amp;lt;/code&amp;gt;. A TNIPhysics plugin may write these commands (and their params) to the TNIStream being returned from a ProcessPhysicsCommands library call.&lt;br /&gt;
&lt;br /&gt;
====TNIP_UpdateVehicleBegin====&lt;br /&gt;
Specifies which vehicle a sequence of update commands refers to. Use of this command is not necessary, and by default any written commands will update the vehicle which ProcessPhysicsCommands() was called for. If, however, the plugin wishes to run commands for connection data on one of the coupled vehicles (such as brake pipes, etc) then this is used to specify that vehicle.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNIPhysicsVehicle - The vehicle to start updating.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_UpdateVehicleEnd====&lt;br /&gt;
Used to mark the end of a vehicle update stream. This will set the update vehicle to null. Following this, a new TNIP_UpdateVehicleBegin command *must* be written before any further update commands.&lt;br /&gt;
&lt;br /&gt;
This command takes no parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ReturnSaveState====&lt;br /&gt;
Used to return the generated save state for a TNIP_SaveVehicleState command (documented above, in TNIPhysicsPluginCommand).&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNISoup - A soup containing the saved plugin state. The plugin should write enough state to adequately restore its current internal state for the given vehicle on reload. It is also courtesy to return known/common save data which this plugin itself may not use/require, but which may be useful/expected by other plugins (this aids in seemless plugin switchover during gameplay).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetResistanceForce====&lt;br /&gt;
Sets the current resistant force for train movement. This includes all track resistance, slope resistance, and internal engine resistances.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current resistance force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBrakingForce====&lt;br /&gt;
Sets the current braking force for the train. This is the force from any/all applied brakes.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current braking force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEngineForce====&lt;br /&gt;
Sets the force currently being output by the engine.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current engine force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetAppliedEngineForce====&lt;br /&gt;
Sets the force currently being applied to the wheels by the engine. In other words, this is the engine force minus any wheelslip.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current applied engine force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelslipForce====&lt;br /&gt;
Sets the amount of force currently being lost to wheelslip.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current wheelslip force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetCurrentDrawn====&lt;br /&gt;
Updates the current drawn stat.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current being drawn, in Amps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetPFXEnergyUseAmount====&lt;br /&gt;
Updates the &amp;quot;energy use&amp;quot; stat, which is used to generate the PFX &amp;quot;load&amp;quot; variable. This currently has no effect on traincar physics, just particle effects (smoke).&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The energy use for the current time interval.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelMomentum====&lt;br /&gt;
Sets the current forward momentum for a traincar (i.e. this value will be negative if the traincar is not moving forwards).&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new forward momentum for the updated traincar, in Newton seconds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_AddWheelMomentum====&lt;br /&gt;
Adds momentum to the updated traincar. A negative (or positive, for backward travelling traincars) value may be used to remove momentum.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The momentum to add onto the traincar, in Newton seconds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetExtraEngineMass====&lt;br /&gt;
Sets the amount of &#039;extra&#039; engine mass a vehicle currently has. This is typically the fuel mass (water and coal) for steam locos.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current extra engine mass, in kg.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEngineParam====&lt;br /&gt;
Sets the value of a named engine param, as returned by the script &amp;lt;code&amp;gt;GetEngineParam()&amp;lt;/code&amp;gt; function on Vehicle. This is used to add support for custom named parameters, attempting to override the natively supported params may not work.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNILabel - The name of the engine parameter to add/update.&lt;br /&gt;
*double - The new value of the parameter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEngineThrottle====&lt;br /&gt;
Sets the current engine throttle. This should gradually move toward the throttle setting, with some amount of latency.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new engine throttle amount (0 to 1).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetCompressorActive====&lt;br /&gt;
Sets whether the brake system compressor is active.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*int8_t - The new compressor state (0- off, 1-on).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEqualiserPressure====&lt;br /&gt;
Sets the pressure of the brake system equaliser.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new equaliser pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetMainReservoirPressure====&lt;br /&gt;
Sets the pressure of the brake system main reservoir.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new main reservoir pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetAuxReservoirPressure====&lt;br /&gt;
Sets the pressure of the brake system auxiliary reservoir.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new auxiliary reservoir pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetAutoBrakeCylinderPressure====&lt;br /&gt;
Sets the pressure of the brake cylinder.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new brake cylinder pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetIndependentBrakeCylinderPressure====&lt;br /&gt;
Sets the pressure of the independent/loco brake cylinder.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new independent/loco brake cylinder pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetTrainBrakePipePressure====&lt;br /&gt;
Sets the pressure of the main train brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new train brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEpReservoirPipePressure====&lt;br /&gt;
Sets the pressure of the electro-pneumatic brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new electro-pneumatic brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetNo3PipePressure====&lt;br /&gt;
Sets the pressure of the no3 brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new no3 brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetNo4PipePressure====&lt;br /&gt;
Sets the pressure of the no4 brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new no4 brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBrakePressureFlowRate====&lt;br /&gt;
Notifies of the brake pressure flow rate.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new brake pressure flow rate, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Steam Engine Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetCoalLevel====&lt;br /&gt;
Sets the coal level in a steam locomotive. This is the current ratio between the minimum (0) and maximum (1) coal levels for the firebox. i.e., a reading of 0 indicates the fire is at minimum coal, not that it&#039;s necessarily &amp;quot;empty&amp;quot;, and a value over 1 indicates the fire is over-filled with coal.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current coal level in the firebox.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWaterLevel====&lt;br /&gt;
Sets the water level in a steam locomotive. This is the current ratio between the minimum (0) and maximum (1) water levels for the boiler, as would be shown on the cab gauge(s). i.e., a reading of 0 indicates the boiler is at or below minimum, not that it&#039;s necessarily &amp;quot;empty&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current water level in the boiler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBoilerPressure====&lt;br /&gt;
Sets the current pressure within the boiler, in pascals.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new boiler pressure, in pascals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetSteamChestPressure====&lt;br /&gt;
Sets the current pressure within the steam chest, in pascals.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new steam chest pressure, in pascals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetThrashing====&lt;br /&gt;
Sets the amount the engine is being &#039;thrashed&#039;, as returned to script by a call to &amp;lt;code&amp;gt;Locomotive.GetEngineParam(&amp;quot;thrashing&amp;quot;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The amount the engine is being &#039;thrashed&#039;, 0 to 1 for normal engine operation, &amp;gt;1 for thrashing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ConsumeCoal====&lt;br /&gt;
Informs Trainz to consume an amount of coal product, for use as steam engine fuel. The caller should first verify that there is sufficient fuel to meet the request, using TNIPhysicsGetVehicleCoalAvailable().&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*int32_t - The amount of product to consume.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ConsumeWater====&lt;br /&gt;
Informs Trainz to consume an amount of water product, for use as steam engine fuel. The caller should first verify that there is sufficient fuel to meet the request, using TNIPhysicsGetVehicleWaterAvailable().&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*int32_t - The amount of product to consume.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Effect Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelAngularVelocity====&lt;br /&gt;
Sets the angular velocity of the wheels on a steam locomotive. This affects the value of the &amp;quot;cyclespeed2&amp;quot; PFX variable.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The angular velocity of the driving wheels, in m/s.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelAnimationData====&lt;br /&gt;
Sets the animation data for the wheels of a traincar. Two values are always written here, but which is used will depend on the type of wheel animation which being used by the traincar.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The current wheel rotation, from 0 to 2PI.&lt;br /&gt;
*float - The wheel velocity, in m/s.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBrakeReleaseSoundFade====&lt;br /&gt;
Sets the volume of the brake release sound on this traincar.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The new brake release sound volume, 0 to 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetPFXVariableValue====&lt;br /&gt;
Sets the value of a named PFX variable. See validation/steam-mode.txt for a list of valid variable names.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNILabel - The name of the variable to update.&lt;br /&gt;
*float - The new value of the variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Script Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetPluginFeatureSupport====&lt;br /&gt;
Specifies the custom features which this plugin supports, so that they can be queried by script. This API is optional, but plugins should normally specify at least one feature ID, to allow scripts to query which plugin is running.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNIArray - An array of string IDs (using TNILabel) for the supported features. This may be empty or null, but it must be written to avoid corrupting the command stream. Each string ID should be prefixed with the plugins base (i.e. versionless) KUID, followed by an English human readable feature string. For example:  &amp;quot;&amp;lt;kuid:1111:2222&amp;gt;/diesel-consumption&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
When this is called, the supplied feature list will completely replace any existing feature list. I.e. You must always provide the complete list of supported features for the current vehicle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ScriptPostMessage====&lt;br /&gt;
Posts a message to the vehicle script. This can be used to trigger the execution of custom script code from the plugin, if any script supports it. The posted message will use the &#039;major&#039; value of &amp;quot;TNIPhysicsPlugin&amp;quot;. The &#039;minor&#039; value is specified by the first parameter to this command.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNIString - The value to use for Message.minor. Must not be empty.&lt;br /&gt;
*TNISoup - An optional TNISoup to be included with the message. This allows custom data/parameters to be provided to script. This may be null but it must be written to avoid command stream corruption.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Accessor Commands (TNIPhysics.h)==&lt;br /&gt;
Basic accessors for TNIPhysicsVehicle member variables, including those on the frame data, engine spec or steam engine spec.&lt;br /&gt;
&lt;br /&gt;
===TNIGameObjectID/Matching Accessors===&lt;br /&gt;
{{MethodHeader|const TNIGameObjectID* TNIPhysicsGetVehicleID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNIGameObjectID* TNIPhysicsGetVehicleTrainID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsDoesVehicleMatchID(const TNIPhysicsVehicle* vehicle, const TNIGameObjectID* id)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===AssetID/Config Accessors===&lt;br /&gt;
{{MethodHeader|const TNIAssetID* TNIPhysicsGetVehicleAssetID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNISoup* TNIPhysicsGetVehicleAssetConfig(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNIAssetID* TNIPhysicsGetVehicleEngineAssetID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNISoup* TNIPhysicsGetVehicleEngineAssetConfig(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNIAssetID* TNIPhysicsGetVehicleTrackAssetID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNISoup* TNIPhysicsGetVehicleTrackAssetConfig(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Train State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetTrainLocoCount(const TNIPhysicsVehicle* vehicle}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Train Control Settings===&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehiclePhysicsModelSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleTractionSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleThrottleSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleSteamRegulatorSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleSteamCutoffSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleTrainBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleDynamicBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleLocoBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleEpBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBailTimeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleHandBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleSandingSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleCoalRateSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleInjector1Setting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleInjector2Setting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBlowerSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleCustomSetting(const TNIPhysicsVehicle* vehicle, const TNILabel* settingName)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleVelocity(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleIsStopped(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelMomentum(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelslip(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelslipTractionMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelslipMomentumMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEngineForce(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEngineThrottle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleThrottleGraphOutput(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleDynamicBrakeGraphOutput(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleIsDerailed(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleAllowsUserControl(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleIsAutomaticFireman(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|uint32_t TNIPhysicsGetVehicleCoalAvailable(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|uint32_t TNIPhysicsGetVehicleWaterAvailable(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleSandingTractionMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleScriptTractionMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle Brake Pressure State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEqualiserPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMainReservoirPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleNo3PipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleTrainBrakePipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEpReservoirPipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleNo4PipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAuxReservoirPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAutoBrakeCylinderPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleIndependentBrakeCylinderPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleScriptBrakePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBrakePipeEfficiency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleCompressorEfficiency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleCompressorActive(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBrakeReleaseSoundFade(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle Track State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleTrackGradient(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleTrackCurveAngle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle Spec Accessors===&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleEngineType(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMaximumTractiveEffort(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelDiameter(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxSpeed(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxDCCAcceleration(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxDCCDeceleration(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxVoltage(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetEngineBrakeRatio(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleThrottleAdjustmentRate(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAxleCount(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleSurfaceArea(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMovingFrictionCoefficient(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAirDragCoefficient(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleDrivingWheelWeightRatio(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Flowsize Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_TrainBrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EpReservoirPipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No4Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirToNo3Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirToTrainBrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AutoBrakeCylinderVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirToAutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserMainReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserVentHandleOff(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserVentEmergency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3PipeVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3PipeMainReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_Compressor(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_TrainBrakePipeReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_TrainBrakePipeVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3PipeToAutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EpReservoirPipeToAutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_MainReservoirEP(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Volume Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_Equaliser(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_MainReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_No3Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_TrainBrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_EpReservoirPipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_No4Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_AuxReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_AutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_IndependentBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Pressure Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_BrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_BrakeInitial(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_BrakeFull(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_IndBrakeFull(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_Compressor(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Steam Engine Spec Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonVolumeMin(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonVolumeMax(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonArea(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonLength(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int TNIPhysicsGetSteamEnginePistonAngularOffsetsCount(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonAngularOffset(const TNIPhysicsVehicle* vehicle, int i)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineTractiveEffortConstant(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineHandBrakeMaxForce(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineTestSpeed(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineTestCutoff(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBurnRate(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBurnRateIdle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineMinFireTemperature(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineMaxFireTemperature(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxEfficiency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxHeatingSurfaceArea(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxPlateThickness(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxThermalConductivity(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBlowerEffect(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBlowerMaxFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineStartingCoal(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineIdealCoalMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineMaxFireCoalMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFuelEnergy(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFuelSpecificHeatCapacity(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerVolume(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerVolumeMin(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerVolumeMax(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerFusiblePlugVolume(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSteamChestVolume(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSteamChestMaxFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineValveLapPercent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerEfficency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerEfficencyIdle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerEfficencyMin(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerHeatLoss(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineInitialBoilerTemperature(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSuperheatingConstant(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineStartingWater(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineStartingBoilerSteam(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveLowPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveLowFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveHighPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveHighFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineCoalShovelMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineWaterInjectorRate(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineWaterInjectorRate2(const TNIPhysicsVehicle* vehicle)}}&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=TNI_Physics_Interface&amp;diff=45930</id>
		<title>TNI Physics Interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=TNI_Physics_Interface&amp;diff=45930"/>
		<updated>2026-02-16T02:27:39Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TNIPhysics is a builtin TNILibrary within Trainz which allows [[KIND tni-physics-plugin|physics plugin]] assets to control all the internal train physics for any traincar. This includes engine physics, braking systems and shared systems such as track/air resistance. It doesn&#039;t currently include systems such as random motion, coupling interactions, collisions or derailments.&lt;br /&gt;
&lt;br /&gt;
Before continuing, it is recommended you first familiarise yourself with the following pages:&lt;br /&gt;
* [[TrainzNativeInterface]] - For an overview of TNI and the associated licensing requirements&lt;br /&gt;
* [[TNI Core Interface]] - For details of the core TNI functionality, object types, etc.&lt;br /&gt;
* [[KIND tni-physics-plugin]] - For the specification of the physics plugin asset kind.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: This page is a work in progress. If you notice anything out of date, please advise N3V Games.&#039;&#039;&lt;br /&gt;
&#039;&#039;The original release of TNI Physics was in TRS19 SP3 in April 2021. However information and systems may change over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
TNIPhysics is initialised at game startup, and will automatically locate and load any installed TNI physics plugin assets at world/map load time. All TNIPhysics plugins must have a QueryProcessingPriority function, which will allow Trainz to determine which of the user&#039;s installed plugins is best suited to handle each specific vehicle. TNIPhysics will make all physics update calls through the plugin&#039;s LibraryCall interface.&lt;br /&gt;
&lt;br /&gt;
The specific function calls supported by TNIPhysics are detailed in the next section.&lt;br /&gt;
&lt;br /&gt;
==TNIPhysics Library Calls==&lt;br /&gt;
&lt;br /&gt;
====Init====&lt;br /&gt;
TNIPhysics will call the plugin library DLL with the function name &amp;quot;Init&amp;quot; on initialization. This call can safely be ignored if no initialisation is necessary. This function expects no return object, and takes no parameters.&lt;br /&gt;
&lt;br /&gt;
====QueryProcessingPriority====&lt;br /&gt;
This function is called from Trainz code to query the processing priority of a plugin for a given traincar. The function will be called across every plugin for every vehicle at load/creation time and when switching control modes (DCC vs cab). Whichever plugin returns the highest priority result will process the vehicle&#039;s physics. It has a single TNIPhysicsVehicle as the param, and expects a TNIInteger return result. The TNIPhysics_Priority enum defines a list of example return values, but the programmer is not constrained to using these defines.&lt;br /&gt;
*TNIPhysics_PriorityInvalid - Never use this plugin (-127)&lt;br /&gt;
*TNIPhysics_PriorityLowest - Only use this plugin if there&#039;s no other option (-20)&lt;br /&gt;
*TNIPhysics_PriorityLow - Prefer not using this plugin, but it might work ok (-10)&lt;br /&gt;
*TNIPhysics_PriorityDefault - This plugin can handle the request adequately (0). The builtin core plugin asset always returns this value.&lt;br /&gt;
*TNIPhysics_PriorityHigh - This plugin is somewhat specialised to handle the request (10)&lt;br /&gt;
*TNIPhysics_PriorityHighest - This plugin was built exactly for this request (20)&lt;br /&gt;
&lt;br /&gt;
====RegisterVehicle====&lt;br /&gt;
This function is called from Trainz code on the plugin which returns the highest valid result from a call to &amp;quot;QueryProcessingPriority&amp;quot;. It notifies a physics plugin that it has been selected to manage the vehicle, and should perform any appropriate internal initialisation. This function takes a single TNIPhysicsVehicle param (being the vehicle to register) and expects no return object.&lt;br /&gt;
&lt;br /&gt;
====UnregisterVehicle====&lt;br /&gt;
This function is the counter to RegisterVehicle, and instructs a plugin that it is no longer managing the physics for a particular vehicle. This will occur when the vehicle is deleted, or Trainz hands it over to a more appropriate plugin (based on the result of a call to the &amp;quot;QueryProcessingPriority&amp;quot; function). This function takes a single TNIPhysicsVehicle param (being the vehicle to unregister) and expects no return object. &lt;br /&gt;
&lt;br /&gt;
When called, the plugin should discard any internal data is has for the specified vehicle. If Trainz required anything to be saved, then a TNIP_SaveVehicleState command will have already been run.&lt;br /&gt;
&lt;br /&gt;
====ProcessPhysicsCommands====&lt;br /&gt;
The main vehicle update function. This function is called from Trainz code to process a physics command stream for a specific vehicle. The function takes a TNIArray object which contains the TNIPhysicsVehicle (element 0) and a TNIStream (element 1) containing the commands to run (see enum TNIPhysicsPluginCommand for a list of physics commands and their params). Trainz expects a TNIStream return result, containing a list of physics update commands to Trainz from the plugin (see enum TNIPhysicsGameCommand).&lt;br /&gt;
&lt;br /&gt;
==Physics Commands==&lt;br /&gt;
The ProcessPhysicsCommands LibraryCall uses incoming and outgoing command buffers to communicate physics information with Trainz.&lt;br /&gt;
The command buffer data is sequential - each command ID is written as a 16 bit integer, and will be followed followed by any relevant command parameters (see enum TNIPhysicsPluginCommand for specific command details).&lt;br /&gt;
&lt;br /&gt;
As this is a raw command stream it is critical that the programmer carefully reads the documentation on each specific command, and correctly reads off each parameter value, even if they are not being used by the plugin. Failure to correctly read all command parameters will result in corruption of the stream, and undefinied application behaviour.&lt;br /&gt;
&lt;br /&gt;
The stream has no terminating value, but stream end may be detected using the TNIStreamTell and TNIStreamGetSize functions, or simply by reading commands until failure is detected (e.g. &amp;lt;code&amp;gt;while (TNIStreamReadInt16(commandStream, 0))&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The programmer must employ similar practices when writing the reply command stream. I.e. Each command is written as a 16 bit integer (TNIStreamWriteInt16), and must be followed by the parameters detailed in enum TNIPhysicsGameCommand. Failure to write data in the correct format will result in undefined behaviour within the application.&lt;br /&gt;
&lt;br /&gt;
==Incoming Commands (TNIPhysicsPluginCommand)==&lt;br /&gt;
The following describes the possible physics commands the game may issue to a plugin, as per &amp;lt;code&amp;gt;enum TNIPhysicsPluginCommand&amp;lt;/code&amp;gt;. Commands and parameters will be written, in sequence, to the TNIStream param passed to the ProcessPhysicsCommands library call.&lt;br /&gt;
&lt;br /&gt;
====TNIP_UpdatePhysicsForVehicle====&lt;br /&gt;
The main physics update function. This is regularly called by Trainz code to update the traincar physics for a particular time period. This function takes two extra params for the front and rear coupled vehicles, but keep in mind these may be using different TNI plugins.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The time interval to update for.&lt;br /&gt;
*TNIPhysicsVehicle - The front coupled vehicle.&lt;br /&gt;
*TNIPhysicsVehicle - The rear coupled vehicle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_AdjustMomentum====&lt;br /&gt;
Called from Trainz to notify of an adjustment to a vehicles momentum. This is typically used to apply the results of coupler physics interactions. Vehicles for which the plugin does not internally track momentum can safely ignore this call.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new vehicle momentum.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_FinaliseFramePhysics====&lt;br /&gt;
Called by Trainz to notify that all updates relating to this vehicle for the current frame are complete. This includes all plugin updates and all coupler interactions. Plugins may use this as an appropriate location to synchronise plugin state to that of the game, or apply visible state changes only. At the time this call is made it is &amp;quot;too late&amp;quot; to perform or apply physics calculations for a given frame.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The time interval that&#039;s been updated.&lt;br /&gt;
*double - The final momentum for this frame.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_NormalisePhysicsData====&lt;br /&gt;
Called following an external physics state update in order to perform any physics-mode-specific follow up validation/correction. Examples include after physics/control state replication in multiplayer.&lt;br /&gt;
&lt;br /&gt;
This command takes no parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SaveVehicleState====&lt;br /&gt;
Called by Trainz code to request save data for a specific vehicle. If the plugin maintains any internal state for the specified vehicle then this function should save that state, so that players are able to save and reload with seamless physics behaviour. The save state should be returned to the game by adding a TNIP_ReturnSaveState command to the library call result stream (see TNIPhysicsGameCommand for more). If the plugin tracks no state for the vehicle passed, then this call can be safely ignored. That said, it is courteous to return known/common save data, even if this plugin itself may not use/require it, as it aids in seemless plugin switchover during gameplay.&lt;br /&gt;
&lt;br /&gt;
This command takes no parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_LoadVehicleState====&lt;br /&gt;
Called by Trainz code to load previously saved vehicle state. Note that this is always called during load, even if the plugin does not produce any save state when TNIP_SaveVehicleState is called. Also note that the passed soup param may have been produced by a different plugin.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNISoup - A saved soup generated by a previous TNIP_SaveVehicleState call on this or another plugin. The soup will contain an AssetID param for the plugin that produced it, using the tag name &amp;quot;plugin-kuid&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SteamEngine_AddCoalToFire====&lt;br /&gt;
Called by Trainz code to add coal to a steam engine. For example, when the player uses the manual &amp;quot;Shovel coal&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The volume (not mass) of coal to add.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ScriptFunctionCall====&lt;br /&gt;
Called from script to execute custom behaviour within the plugin. This will be added when a script calls Vehicle.LibraryCallPhysicsPlugin().&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNILabel - The name of the plugin function to execute. If the function name is unrecognised or unsupported, the plugin should log an error and ignore it. (The TNISoup param must still be read though, to avoid the command stream being corrupted.)&lt;br /&gt;
*TNISoup - An optional TNISoup to be included with the command. This is used to pass more parameters to the custom plugin function, where required. Parsing code must handle the possibility that the parameter is null, even if the extra parameters are not optional for the plugin code. Similarly, plugins must not make assumptions about the validity of the soup data, and should either appropriately handle all inputs or ignore the command entirely.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Outgoing Commands (TNIPhysicsGameCommand)==&lt;br /&gt;
The following describes the possible physics commands a plugin may issue to the game, as per &amp;lt;code&amp;gt;enum TNIPhysicsGameCommand&amp;lt;/code&amp;gt;. A TNIPhysics plugin may write these commands (and their params) to the TNIStream being returned from a ProcessPhysicsCommands library call.&lt;br /&gt;
&lt;br /&gt;
====TNIP_UpdateVehicleBegin====&lt;br /&gt;
Specifies which vehicle a sequence of update commands refers to. Use of this command is not necessary, and by default any written commands will update the vehicle which ProcessPhysicsCommands() was called for. If, however, the plugin wishes to run commands for connection data on one of the coupled vehicles (such as brake pipes, etc) then this is used to specify that vehicle.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNIPhysicsVehicle - The vehicle to start updating.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_UpdateVehicleEnd====&lt;br /&gt;
Used to mark the end of a vehicle update stream. This will set the update vehicle to null. Following this, a new TNIP_UpdateVehicleBegin command *must* be written before any further update commands.&lt;br /&gt;
&lt;br /&gt;
This command takes no parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ReturnSaveState====&lt;br /&gt;
Used to return the generated save state for a TNIP_SaveVehicleState command (documented above, in TNIPhysicsPluginCommand).&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNISoup - A soup containing the saved plugin state. The plugin should write enough state to adequately restore its current internal state for the given vehicle on reload. It is also courtesy to return known/common save data which this plugin itself may not use/require, but which may be useful/expected by other plugins (this aids in seemless plugin switchover during gameplay).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetResistanceForce====&lt;br /&gt;
Sets the current resistant force for train movement. This includes all track resistance, slope resistance, and internal engine resistances.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current resistance force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBrakingForce====&lt;br /&gt;
Sets the current braking force for the train. This is the force from any/all applied brakes.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current braking force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEngineForce====&lt;br /&gt;
Sets the force currently being output by the engine.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current engine force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetAppliedEngineForce====&lt;br /&gt;
Sets the force currently being applied to the wheels by the engine. In other words, this is the engine force minus any wheelslip.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current applied engine force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelslipForce====&lt;br /&gt;
Sets the amount of force currently being lost to wheelslip.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current wheelslip force, in Newtons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetCurrentDrawn====&lt;br /&gt;
Updates the current drawn stat.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current being drawn, in Amps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetPFXEnergyUseAmount====&lt;br /&gt;
Updates the &amp;quot;energy use&amp;quot; stat, which is used to generate the PFX &amp;quot;load&amp;quot; variable. This currently has no effect on traincar physics, just particle effects (smoke).&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The energy use for the current time interval.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelMomentum====&lt;br /&gt;
Sets the current forward momentum for a traincar (i.e. this value will be negative if the traincar is not moving forwards).&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new forward momentum for the updated traincar, in Newton seconds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_AddWheelMomentum====&lt;br /&gt;
Adds momentum to the updated traincar. A negative (or positive, for backward travelling traincars) value may be used to remove momentum.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The momentum to add onto the traincar, in Newton seconds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetExtraEngineMass====&lt;br /&gt;
Sets the amount of &#039;extra&#039; engine mass a vehicle currently has. This is typically the fuel mass (water and coal) for steam locos.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current extra engine mass, in kg.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEngineParam====&lt;br /&gt;
Sets the value of a named engine param, as returned by the script &amp;lt;code&amp;gt;GetEngineParam()&amp;lt;/code&amp;gt; function on Vehicle. This is used to add support for custom named parameters, attempting to override the natively supported params may not work.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNILabel - The name of the engine parameter to add/update.&lt;br /&gt;
*double - The new value of the parameter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEngineThrottle====&lt;br /&gt;
Sets the current engine throttle. This should gradually move toward the throttle setting, with some amount of latency.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new engine throttle amount (0 to 1).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetCompressorActive====&lt;br /&gt;
Sets whether the brake system compressor is active.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*int8_t - The new compressor state (0- off, 1-on).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEqualiserPressure====&lt;br /&gt;
Sets the pressure of the brake system equaliser.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new equaliser pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetMainReservoirPressure====&lt;br /&gt;
Sets the pressure of the brake system main reservoir.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new main reservoir pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetAuxReservoirPressure====&lt;br /&gt;
Sets the pressure of the brake system auxiliary reservoir.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new auxiliary reservoir pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetAutoBrakeCylinderPressure====&lt;br /&gt;
Sets the pressure of the brake cylinder.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new brake cylinder pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetIndependentBrakeCylinderPressure====&lt;br /&gt;
Sets the pressure of the independent/loco brake cylinder.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new independent/loco brake cylinder pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetTrainBrakePipePressure====&lt;br /&gt;
Sets the pressure of the main train brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new train brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetEpReservoirPipePressure====&lt;br /&gt;
Sets the pressure of the electro-pneumatic brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new electro-pneumatic brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetNo3PipePressure====&lt;br /&gt;
Sets the pressure of the no3 brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new no3 brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetNo4PipePressure====&lt;br /&gt;
Sets the pressure of the no4 brake pipe.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new no4 brake pipe pressure, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBrakePressureFlowRate====&lt;br /&gt;
Notifies of the brake pressure flow rate.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new brake pressure flow rate, in g/m^3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Steam Engine Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetCoalLevel====&lt;br /&gt;
Sets the coal level in a steam locomotive. This is the current ratio between the minimum (0) and maximum (1) coal levels for the firebox. i.e., a reading of 0 indicates the fire is at minimum coal, not that it&#039;s necessarily &amp;quot;empty&amp;quot;, and a value over 1 indicates the fire is over-filled with coal.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current coal level in the firebox.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWaterLevel====&lt;br /&gt;
Sets the water level in a steam locomotive. This is the current ratio between the minimum (0) and maximum (1) water levels for the boiler, as would be shown on the cab gauge(s). i.e., a reading of 0 indicates the boiler is at or below minimum, not that it&#039;s necessarily &amp;quot;empty&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The current water level in the boiler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBoilerPressure====&lt;br /&gt;
Sets the current pressure within the boiler, in pascals.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new boiler pressure, in pascals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetSteamChestPressure====&lt;br /&gt;
Sets the current pressure within the steam chest, in pascals.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The new steam chest pressure, in pascals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetThrashing====&lt;br /&gt;
Sets the amount the engine is being &#039;thrashed&#039;, as returned to script by a call to &amp;lt;code&amp;gt;Locomotive.GetEngineParam(&amp;quot;thrashing&amp;quot;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*double - The amount the engine is being &#039;thrashed&#039;, 0 to 1 for normal engine operation, &amp;gt;1 for thrashing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ConsumeCoal====&lt;br /&gt;
Informs Trainz to consume an amount of coal product, for use as steam engine fuel. The caller should first verify that there is sufficient fuel to meet the request, using TNIPhysicsGetVehicleCoalAvailable().&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*int32_t - The amount of product to consume.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ConsumeWater====&lt;br /&gt;
Informs Trainz to consume an amount of water product, for use as steam engine fuel. The caller should first verify that there is sufficient fuel to meet the request, using TNIPhysicsGetVehicleWaterAvailable().&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*int32_t - The amount of product to consume.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Effect Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelAngularVelocity====&lt;br /&gt;
Sets the angular velocity of the wheels on a steam locomotive. This affects the value of the &amp;quot;cyclespeed2&amp;quot; PFX variable.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The angular velocity of the driving wheels, in m/s.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetWheelAnimationData====&lt;br /&gt;
Sets the animation data for the wheels of a traincar. Two values are always written here, but which is used will depend on the type of wheel animation which being used by the traincar.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The current wheel rotation, from 0 to 2PI.&lt;br /&gt;
*float - The wheel velocity, in m/s.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetBrakeReleaseSoundFade====&lt;br /&gt;
Sets the volume of the brake release sound on this traincar.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*float - The new brake release sound volume, 0 to 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetPFXVariableValue====&lt;br /&gt;
Sets the value of a named PFX variable. See validation/steam-mode.txt for a list of valid variable names.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNILabel - The name of the variable to update.&lt;br /&gt;
*float - The new value of the variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Script Commands===&lt;br /&gt;
&lt;br /&gt;
====TNIP_SetPluginFeatureSupport====&lt;br /&gt;
Specifies the custom features which this plugin supports, so that they can be queried by script. This API is optional, but plugins should normally specify at least one feature ID, to allow scripts to query which plugin is running.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNIArray - An array of string IDs (using TNILabel) for the supported features. This may be empty or null, but it must be written to avoid corrupting the command stream. Each string ID should be prefixed with the plugins base (i.e. versionless) KUID, followed by an English human readable feature string. For example:  &amp;quot;&amp;lt;kuid:1111:2222&amp;gt;/diesel-consumption&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
When this is called, the supplied feature list will completely replace any existing feature list. I.e. You must always provide the complete list of supported features for the current vehicle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====TNIP_ScriptPostMessage====&lt;br /&gt;
Posts a message to the vehicle script. This can be used to trigger the execution of custom script code from the plugin, if any script supports it. The posted message will use the &#039;major&#039; value of &amp;quot;TNIPhysicsPlugin&amp;quot;. The &#039;minor&#039; value is specified by the first parameter to this command.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*TNIString - The value to use for Message.minor. Must not be empty.&lt;br /&gt;
*TNISoup - An optional TNISoup to be included with the message. This allows custom data/parameters to be provided to script. This may be null but it must be written to avoid command stream corruption.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Accessor Commands (TNIPhysics.h)==&lt;br /&gt;
Basic accessors for TNIPhysicsVehicle member variables, including those on the frame data, engine spec or steam engine spec.&lt;br /&gt;
&lt;br /&gt;
==TNIGameObjectID/Matching Accessors==&lt;br /&gt;
{{MethodHeader|const TNIGameObjectID* TNIPhysicsGetVehicleID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNIGameObjectID* TNIPhysicsGetVehicleTrainID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsDoesVehicleMatchID(const TNIPhysicsVehicle* vehicle, const TNIGameObjectID* id)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===AssetID/Config Accessors===&lt;br /&gt;
{{MethodHeader|const TNIAssetID* TNIPhysicsGetVehicleAssetID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNISoup* TNIPhysicsGetVehicleAssetConfig(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNIAssetID* TNIPhysicsGetVehicleEngineAssetID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNISoup* TNIPhysicsGetVehicleEngineAssetConfig(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNIAssetID* TNIPhysicsGetVehicleTrackAssetID(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|const TNISoup* TNIPhysicsGetVehicleTrackAssetConfig(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===AssetID/Config Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetTrainLocoCount(const TNIPhysicsVehicle* vehicle}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Train Control Settings===&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehiclePhysicsModelSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleTractionSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleThrottleSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleSteamRegulatorSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleSteamCutoffSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleTrainBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleDynamicBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleLocoBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleEpBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBailTimeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleHandBrakeSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleSandingSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleCoalRateSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleInjector1Setting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleInjector2Setting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBlowerSetting(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleCustomSetting(const TNIPhysicsVehicle* vehicle, const TNILabel* settingName)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleVelocity(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleIsStopped(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelMomentum(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelslip(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelslipTractionMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelslipMomentumMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEngineForce(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEngineThrottle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleThrottleGraphOutput(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleDynamicBrakeGraphOutput(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleIsDerailed(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleAllowsUserControl(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|bool TNIPhysicsGetVehicleIsAutomaticFireman(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|uint32_t TNIPhysicsGetVehicleCoalAvailable(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|uint32_t TNIPhysicsGetVehicleWaterAvailable(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleSandingTractionMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleScriptTractionMultiplier(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle Brake Pressure State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEqualiserPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMainReservoirPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleNo3PipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleTrainBrakePipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleEpReservoirPipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleNo4PipePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAuxReservoirPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAutoBrakeCylinderPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleIndependentBrakeCylinderPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleScriptBrakePressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBrakePipeEfficiency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleCompressorEfficiency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleCompressorActive(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleBrakeReleaseSoundFade(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle Track State Accessors===&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleTrackGradient(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleTrackCurveAngle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vehicle Spec Accessors===&lt;br /&gt;
{{MethodHeader|int8_t TNIPhysicsGetVehicleEngineType(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMaximumTractiveEffort(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleWheelDiameter(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxSpeed(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxDCCAcceleration(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxDCCDeceleration(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleMaxVoltage(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetEngineBrakeRatio(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleThrottleAdjustmentRate(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAxleCount(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleSurfaceArea(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleMovingFrictionCoefficient(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleAirDragCoefficient(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|double TNIPhysicsGetVehicleDrivingWheelWeightRatio(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Flowsize Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_TrainBrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EpReservoirPipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No4Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirToNo3Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirToTrainBrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AutoBrakeCylinderVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_AuxReservoirToAutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserMainReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserVentHandleOff(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserVentEmergency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EqualiserVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3PipeVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3PipeMainReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_Compressor(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_TrainBrakePipeReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_TrainBrakePipeVent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_No3PipeToAutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_EpReservoirPipeToAutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleFlowsize_MainReservoirEP(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Volume Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_Equaliser(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_MainReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_No3Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_TrainBrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_EpReservoirPipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_No4Pipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_AuxReservoir(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_AutoBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehicleVolume_IndependentBrakeCylinder(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Engine Spec Pressure Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_BrakePipe(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_BrakeInitial(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_BrakeFull(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_IndBrakeFull(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetVehiclePressure_Compressor(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Steam Engine Spec Accessors===&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonVolumeMin(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonVolumeMax(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonArea(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonLength(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|int TNIPhysicsGetSteamEnginePistonAngularOffsetsCount(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEnginePistonAngularOffset(const TNIPhysicsVehicle* vehicle, int i)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineTractiveEffortConstant(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineHandBrakeMaxForce(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineTestSpeed(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineTestCutoff(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBurnRate(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBurnRateIdle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineMinFireTemperature(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineMaxFireTemperature(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxEfficiency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxHeatingSurfaceArea(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxPlateThickness(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFireboxThermalConductivity(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBlowerEffect(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBlowerMaxFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineStartingCoal(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineIdealCoalMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineMaxFireCoalMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFuelEnergy(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineFuelSpecificHeatCapacity(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerVolume(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerVolumeMin(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerVolumeMax(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerFusiblePlugVolume(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSteamChestVolume(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSteamChestMaxFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineValveLapPercent(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerEfficency(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerEfficencyIdle(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerEfficencyMin(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineBoilerHeatLoss(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineInitialBoilerTemperature(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSuperheatingConstant(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineStartingWater(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineStartingBoilerSteam(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveLowPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveLowFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveHighPressure(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineSafetyValveHighFlow(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineCoalShovelMass(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineWaterInjectorRate(const TNIPhysicsVehicle* vehicle)}}&lt;br /&gt;
{{MethodHeader|float TNIPhysicsGetSteamEngineWaterInjectorRate2(const TNIPhysicsVehicle* vehicle)}}&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=TNI_Core_Interface&amp;diff=45929</id>
		<title>TNI Core Interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=TNI_Core_Interface&amp;diff=45929"/>
		<updated>2026-02-16T02:19:30Z</updated>

		<summary type="html">&lt;p&gt;Pw3r: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [[TNI Core Interface]] is a protocol and associated functions which allows communication between Trainz and a third-party [[TrainzNativeInterface|TNI plugin]].&lt;br /&gt;
&lt;br /&gt;
=DLL Development=&lt;br /&gt;
All TNI plugin DLLs must be written in C/C++. Due to the code-signing requirements imposed by the TNI developer agreement, it is not possible to create TNI plugin DLLs in other languages. At the current time, all TNI plugin DLLs must compile under Microsoft Visual Studio 2013&#039;s subset of C++11. TNI DLLs may use the following external headers and techniques:&lt;br /&gt;
&lt;br /&gt;
* The TrainzNativeInterface SDK headers, which provide the [[TNI Core Interface]] and other component interfaces.&lt;br /&gt;
* The C standard library allocators and utility functions.&lt;br /&gt;
* The C++ STL (Standard Template Library) containers, allocators, and utility functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TNI DLLs must not use the following external headers and techniques unless a specific exception is granted.&lt;br /&gt;
&lt;br /&gt;
* Windows Platform SDK.&lt;br /&gt;
* File, network, permissions, process, or other &amp;quot;system access&amp;quot; or &amp;quot;external access&amp;quot; headers.&lt;br /&gt;
* Third-party DLLs.&lt;br /&gt;
* Third-pary source code which does not follow these requirements.&lt;br /&gt;
* Assembly language.&lt;br /&gt;
* Bytecode machines, JIT compilers, and other forms of state machine whose runtime characteristics cannot be determined in advance; i.e. programs which effectively treat input data as source code.&lt;br /&gt;
* The plugin may use C++ exceptions internally, but must not allow exceptions to be propagated back to the calling code.&lt;br /&gt;
* The plugin must not throw or attempt to catch native exceptions (win32 exceptions, posix signals, etc.)&lt;br /&gt;
&lt;br /&gt;
The TNI developer may use whatever build pipeline they like during development. When submitting to [[N3V Games]] for final build and code-signing, only a single folder of source files is accepted- a vanilla project file will be provided by N3V Games engineers which includes these files, the TNI SDK, and nothing else.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==DLL Entry Point==&lt;br /&gt;
The TNI DLL must provide a standard entry point function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================================================================&lt;br /&gt;
// Name: TNIEntryPoint&lt;br /&gt;
// Desc: DLL Entry point. Creates a TNILibrary for the specified context.&lt;br /&gt;
// Parm: context - The context which we are being loaded into.&lt;br /&gt;
// Retn: TNILibrary* - A new library which represents this plugin in the &lt;br /&gt;
//       specified context.&lt;br /&gt;
//=============================================================================&lt;br /&gt;
extern &amp;quot;C&amp;quot; TNI_ENTRYPOINT_DECL TNILibrary* TNIEntryPoint(TNIContext* context)&lt;br /&gt;
{&lt;br /&gt;
  // If there are no other libraries yet, and we maintain shared state, then we should&lt;br /&gt;
  // initialise the shared state here.&lt;br /&gt;
  // ..&lt;br /&gt;
&lt;br /&gt;
  // Create a TNILibrary that Trainz can use to call our dispatch function.&lt;br /&gt;
  TNILibraryInitData info;&lt;br /&gt;
  info.m_libraryVersion = 1;&lt;br /&gt;
  info.m_libraryCall = &amp;amp;MyLibraryCall;&lt;br /&gt;
  info.m_shutdownCall = &amp;amp;MyLibraryShutdown;&lt;br /&gt;
&lt;br /&gt;
  TNIString* libraryName = TNIAllocString(&amp;quot;MyTNIPlugin&amp;quot;);&lt;br /&gt;
  TNILibrary* library = TNIAllocLibrary(context, libraryName, info);&lt;br /&gt;
  TNIRelease(libraryName);&lt;br /&gt;
  &lt;br /&gt;
  // .. perform per-context initialisation here.&lt;br /&gt;
  &lt;br /&gt;
  return library;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The TNIAllocLibrary() function usage above also configured some callback functions, which should look something like this: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================================================================&lt;br /&gt;
// Name: MyLibraryCall&lt;br /&gt;
// Desc: Called by Trainz to perform one of the library function calls provided &lt;br /&gt;
//       by this library.&lt;br /&gt;
// Parm: context - The context in which this library resides.&lt;br /&gt;
// Parm: library - The library object, typically created by TNIEntryPoint().&lt;br /&gt;
// Parm: functionName - The function to perform.&lt;br /&gt;
// Parm: params - The parameters to the function.&lt;br /&gt;
// Retn: TNIObject* - The return value from the function.&lt;br /&gt;
//=============================================================================&lt;br /&gt;
TNIObject* MyLibraryCall(TNIContext* context, const TNILibrary* library, const TNILabel* functionName, const TNIObject* params)&lt;br /&gt;
{&lt;br /&gt;
  if (functionName == ...)&lt;br /&gt;
  {&lt;br /&gt;
     .. do something ..&lt;br /&gt;
    return ...;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return nullptr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//=============================================================================&lt;br /&gt;
// Name: MyLibraryShutdown&lt;br /&gt;
// Desc: Called when the specified library is being destroyed.&lt;br /&gt;
// Parm: context - The context in which the library was loaded.&lt;br /&gt;
// Parm: library - The library which is being destroyed. You may temporarily &lt;br /&gt;
//       reference this library within this function, however on return you  &lt;br /&gt;
//       must leave the reference count as you found it.&lt;br /&gt;
//=============================================================================&lt;br /&gt;
void MyLibraryShutdown(TNIContext* context, TNILibrary* library)&lt;br /&gt;
{&lt;br /&gt;
  // Perform any necessary library shutdown.&lt;br /&gt;
  // ..&lt;br /&gt;
  &lt;br /&gt;
  // If this is the last TNILibrary for this plugin and we maintain shared state, we should also&lt;br /&gt;
  // release the shared state now.&lt;br /&gt;
  // ..&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=TrainzNativeInterface.h=&lt;br /&gt;
&lt;br /&gt;
The TNI core interface is designed to abstract the passing of data between Trainz and the TNI plugin DLLs. All data is represented by an opaque polymorphic object basetype, TNIObject. The objects are reference counted, with simple reference-count rules:&lt;br /&gt;
&lt;br /&gt;
* Ownership of function parameters is held by the caller throughout the function call. They may be retained by the callee if they are required to persist after the function returns. The callee is then responsible for ensuring that they are released at a later time. For mutable object types such as TNIArray, the caller should not modify the array after the callee returns, since it has no way to know if the callee has kept a reference to the array- instead, it should release its own reference to the array. Exceptions are permitted where shared access is considered beneficial, but these must be clearly documented at every use site.&lt;br /&gt;
* Ownership of function return values is passed to the caller. For mutable object types such as TNIArray, the callee should not keep its own reference to the return value since the caller could further modify the object.&lt;br /&gt;
* Care must be taken to avoid reference count cycles where two objects directly or indirectly reference each other (e.g. a-&amp;gt;b-&amp;gt;a or a-&amp;gt;b-&amp;gt;c-&amp;gt;a) as this prevents the objects from ever being released, causing a memory leak.&lt;br /&gt;
&lt;br /&gt;
The core interface attempts to be as safe as possible against common programming errors. Pointer parameters are checked to ensure that they are not null, and so on. However, it is not feasible to make any native-code program completely bullet proof. Typical programming mistakes such as use-after-free, use-before-initialisation, memory leaks, and so on will cause Trainz to crash and are considered serious bugs with the TNI plugin that triggered the crash. Plugins which show repeated stability issues will be withdrawn from circulation.&lt;br /&gt;
&lt;br /&gt;
The following TNIObject-derived classes are provided by the [[TNI Core Interface]]:&lt;br /&gt;
&lt;br /&gt;
==TNIObject==&lt;br /&gt;
TNIObject is the polymorphic base class for all the entire TNI object hierarchy. All TNIObjects are considered opaque types, are constructed via helper functions provided in the TrainzNativeInterface DLL, and are released with TNIRelease().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// TNI OBJECT TYPES&lt;br /&gt;
// ============================================================================&lt;br /&gt;
enum&lt;br /&gt;
{&lt;br /&gt;
  TNI_CLASS_NONE = 0,&lt;br /&gt;
  TNI_CLASS_OBJECT = 1,&lt;br /&gt;
  TNI_CLASS_STRING = 2,&lt;br /&gt;
  TNI_CLASS_ARRAY = 3,&lt;br /&gt;
  TNI_CLASS_CONTEXT = 4,&lt;br /&gt;
  TNI_CLASS_LIBRARY = 5,&lt;br /&gt;
  TNI_CLASS_STREAM = 6,&lt;br /&gt;
  TNI_CLASS_GRAPHICS = 7,&lt;br /&gt;
  TNI_CLASS_VECTOR = 8,&lt;br /&gt;
  TNI_CLASS_ASSETID = 9,&lt;br /&gt;
  TNI_CLASS_LABEL = 10,&lt;br /&gt;
  TNI_CLASS_BUFFER = 11,&lt;br /&gt;
  TNI_CLASS_SOUP = 12,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetObjectClass&lt;br /&gt;
// Desc: Return the type of the specified object, as per the above enumeration&lt;br /&gt;
//       values.&lt;br /&gt;
// Parm: object - the object to query. It is safe to pass a NULL value here.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
uint32_t TNIGetObjectClass(const TNIObject* object);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIReference&lt;br /&gt;
// Desc: Add a reference to the specified object. The object will be released&lt;br /&gt;
//       when the reference count drops to zero.&lt;br /&gt;
// Parm: object - The object to which we will add a reference. It is safe to&lt;br /&gt;
//       pass a NULL value here.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
void TNIReference(const TNIObject* object);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIRelease&lt;br /&gt;
// Desc: Remove a reference to the specified object. The object will be &lt;br /&gt;
//       released when the reference count drops to zero. TNIRelease() should&lt;br /&gt;
//       be called exactly once for each call to TNIReference() and once for&lt;br /&gt;
//       any function return value (for example, from TNIAllocString().)&lt;br /&gt;
// Parm: object - The object from which we will remove a reference. It is safe&lt;br /&gt;
//       to pass a NULL value here.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
void TNIRelease(const TNIObject* object);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TNIString==&lt;br /&gt;
TNIString provides a simple string class. The raw string data is zero-terminated in the usual C fashion, and is encoded as UTF-8. UTF-8 is a superset of ASCII, so ASCII strings can be stored directly in a TNIString with no conversion necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIAllocString&lt;br /&gt;
// Desc: Allocates a TNIString given a zero-terminated UTF8 text buffer.&lt;br /&gt;
// Parm: utf8text - The UTF-8 text buffer. The contents of the buffer are&lt;br /&gt;
//       copied into the TNIString. The function results are undefined if this&lt;br /&gt;
//       parameter does not represent a valid UTF-8 encoded string.&lt;br /&gt;
// Retn: TNIString - The newly allocated TNIString.&lt;br /&gt;
// Note: You must eventually release the allocated string using TNIRelease().&lt;br /&gt;
// Note: If &#039;utf8text&#039; is nullptr, the returned TNIString is an empty string.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
TNIString* TNIAllocString(const char* utf8text);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetStringText&lt;br /&gt;
// Desc: Retrieves a pointer to the internal text buffer of the TNIString&lt;br /&gt;
//       object. This is a read-only reference, and remains valid only while&lt;br /&gt;
//       (1) you hold a reference to the TNIString, and (2) you do not modify&lt;br /&gt;
//       the TNIString.&lt;br /&gt;
// Parm: string - The TNIString object to query.&lt;br /&gt;
// Retn: const char* - A temporary pointer to the internal string text, in&lt;br /&gt;
//       utf8 encoding.&lt;br /&gt;
// Note: If &#039;string&#039; is a nullptr, the return value is a pointer to an empty&lt;br /&gt;
//       string.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
const char* TNIGetStringText(const TNIString* string);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetStringSize&lt;br /&gt;
// Desc: Returns the size in bytes of the specified string.&lt;br /&gt;
// Parm: string - A TNIString object, or nullptr.&lt;br /&gt;
// Retn: size_t - The size in bytes of the text string. Note that this is the&lt;br /&gt;
//       size of the UTF-8 encoded text data, not including zero termination,&lt;br /&gt;
//       and not including any overheads. If the string is null or empty, this&lt;br /&gt;
//       returns zero.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
size_t TNIGetStringSize(const TNIString* string);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNISetStringText&lt;br /&gt;
// Desc: Modifies the TNIString to a copy of the supplied UTF-8 encoded text&lt;br /&gt;
//       buffer.&lt;br /&gt;
// Parm: string - The existing TNIString object to modify. Modifying the string&lt;br /&gt;
//       invalidates any pointer previously returned by TNIGetStringText().&lt;br /&gt;
// Parm: utf8text - The UTF-8 text buffer. The contents of the buffer are copied&lt;br /&gt;
//       into the TNIString. The function results are undefined if this&lt;br /&gt;
//       parameter does not represent a valid UTF-8 encoded string.&lt;br /&gt;
// Note: If &#039;string&#039; is a nullptr, this function does nothing.&lt;br /&gt;
// Note: If &#039;utf8text&#039; is a nullptr, it is considered an empty string.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
void TNISetStringText(TNIString* string, const char* utf8text);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIAppendStringText&lt;br /&gt;
// Desc: Appends the supplied UTF-8 encoded text buffer to the TNIString.&lt;br /&gt;
// Parm: string - The existing TNIString object to modify. Modifying the string&lt;br /&gt;
//       invalidates any pointer previously returned by TNIGetStringText().&lt;br /&gt;
// Parm: utf8text - The UTF-8 text buffer. The contents of the buffer are copied&lt;br /&gt;
//       into the TNIString. The function results are undefined if this&lt;br /&gt;
//       parameter does not represent a valid UTF-8 encoded string.&lt;br /&gt;
// Note: If &#039;string&#039; is a nullptr, this function does nothing.&lt;br /&gt;
// Note: If &#039;utf8text&#039; is a nullptr, this function does nothing.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
void TNIAppendStringText(TNIString* string, const char* utf8text);&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// HELPER FUNCTIONS&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// The &amp;quot;cast&amp;quot; functions do not follow the normal semantics of returning a&lt;br /&gt;
// referenced object. They return the same object that you pass in, with no&lt;br /&gt;
// additional references taken. You should discard the cast result and release&lt;br /&gt;
// the original object when complete.&lt;br /&gt;
const TNIString* TNICastString(const TNIObject* object);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TNILabel==&lt;br /&gt;
TNILabel provide an immutable string class which is designed to provide an efficient enumeration. Only one TNILabel object can exist for any unique string, so these objects can be rapidly compared by pointer equality. It is intended that you will create one TNILabel object for each enumeration during initialisation, and will then use these objects rather than creating new objects at runtime.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIAllocLabel&lt;br /&gt;
// Desc: Returns a label object for the specified text. Only one label object&lt;br /&gt;
//       can exist for a given label at any time- repeated calls to this&lt;br /&gt;
//       function with the same text string will result in the same object&lt;br /&gt;
//       being returned (although the refcount is increased with each call.)&lt;br /&gt;
//       It is safe to rely on this property, so you can directly compare the&lt;br /&gt;
//       returned pointer for equality or inequality.&lt;br /&gt;
//       This is a relatively slow function; you should call it once to&lt;br /&gt;
//       generate the label, then store the label for as long as you need to&lt;br /&gt;
//       use it. You should not attempt to regenerate the same label for each&lt;br /&gt;
//       usage.&lt;br /&gt;
// Parm: utf8text - The text which corresponds to the label. A null or empty&lt;br /&gt;
//       string will result in a nullptr label; this is not considered an&lt;br /&gt;
//       error.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
TNILabel* TNIAllocLabel(const char* utf8text);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetLabelDebugText&lt;br /&gt;
// Desc: Returns a string representation of the label, for debugging purposes.&lt;br /&gt;
//       Note that there is no guarantee that this representation matches the&lt;br /&gt;
//       string passed to TNIAllocLabel, and it should not be machine parsed.&lt;br /&gt;
// Parm: label - The label to query.&lt;br /&gt;
// Retn: const char* - A utf8-encoded string representing the label for the&lt;br /&gt;
//       purposes of debug logging. The returned string is not owned by the&lt;br /&gt;
//       caller but references a buffer internal to the label object.&lt;br /&gt;
//       If &#039;label&#039; is nullptr, the result will be the empty string.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
const char* TNIGetLabelDebugText(const TNILabel* label);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TNIAssetID==&lt;br /&gt;
TNIAssetID encodes a KUID or other Asset ID. You should avoid making any assumptions about the meaning of the data encoded in an TNIAssetID, as the interpretation is subject to change without notice.&lt;br /&gt;
&lt;br /&gt;
==TNIArray==&lt;br /&gt;
TNIArray provides an indexed element array containing TNIObjects. Space for the entire array is allocated when the size is set. Random access within the array is very fast.&lt;br /&gt;
&lt;br /&gt;
==TNISoup==&lt;br /&gt;
TNISoup provides a key-value mapping, similar in concept to the [[class Soup]] and the [[config.txt]] file format. Keys are TNILabel objects, and values are TNIObjects.&lt;br /&gt;
&lt;br /&gt;
==TNIVector==&lt;br /&gt;
TNIVector provides an immutable indexed element array containing 32-bit floating point values. Values for the entire vector are defined during construction. Random access within the vector is very fast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TNIContext==&lt;br /&gt;
TNIContext provides the operating context in which the TNI plugin is operating. Trainz supports multiple concurrent TNI Contexts, and DLLs are typically shared between contexts, so the plugin must correctly track which context any given object or function call is made in. The TNI plugin should not leak data between contexts, although it may share non-context-specific resources internally in a manner which is opaque to the parent context. Each TNIContext is likely to run in a different thread of execution, although this is not guaranteed. Any internal storage maintained by the TNI plugin should be keyed to its parent context to prevent race conditions and other threading concerns. Access to private shared state must be protected by appropriate thread-safe locks.&lt;br /&gt;
&lt;br /&gt;
TNIContext objects are created by the host process, and cannot be created or destroyed by TNI plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetContextVersionCode&lt;br /&gt;
// Desc: Returns the Trainz Version code for this context.&lt;br /&gt;
// Parm: context - The context to query.&lt;br /&gt;
// Retn: uint32_t - The version code.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
uint32_t TNIGetContextVersionCode(const TNIContext* context);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetContextLibrary&lt;br /&gt;
// Desc: Looks up a library in the specified context by name.&lt;br /&gt;
// Parm: context - The context to query.&lt;br /&gt;
// Parm: libraryName - The unique name of the library to return.&lt;br /&gt;
// Retn: TNILibrary* - The located library object, or NULL on failure.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
TNILibrary* TNIGetContextLibrary(const TNIContext* context, const TNIString* libraryName);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All TNI libraries within the same context are available to each other by name. This allows plugins to reference each other. Care must be taken to avoid reference count cycles when accessing a library in this fashion- there should always be a clear &amp;quot;parent&amp;quot; and &amp;quot;child&amp;quot; relationship between any two libraries, with the parent referencing the child and the child never referencing the parent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TNILibrary==&lt;br /&gt;
The TNI plugin DLL entry point is expected to construct a TNILibrary descriptor and return it to Trainz. This serves as the public interface to the plugin, and may be accessed by Trainz native code, [[TrainzScript]], and other TNI plugins. TNILibrary objects are context-specific, so multiple TNILibrary objects may be created for a single plugin DLL.&lt;br /&gt;
&lt;br /&gt;
The plugin DLL may be unloaded at any point while there are no TNILibrary objects in existence for that plugin. The plugin should create any shared state when the first TNILibrary object is created, and release any shared state when the last TNILibrary object has is released.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIAllocLibrary&lt;br /&gt;
// Desc: Allocate a new library in the specified context, given a unique &lt;br /&gt;
//       library name and the initialisation data.&lt;br /&gt;
// Parm: context - The context in which this library is being created.&lt;br /&gt;
// Parm: libraryName - The name of this library, which frequently matches the&lt;br /&gt;
//       name of the plugin in which it is implemented (although it is possible&lt;br /&gt;
//       for a single plugin to export multiple libraries). Each library&lt;br /&gt;
//       created in a given context must have a unique name.&lt;br /&gt;
// Parm: libraryInitData - A TNILibraryInitData structure which describes&lt;br /&gt;
//       the library to be created.&lt;br /&gt;
// Retn: TNILibrary* - A valid object on success, or NULL on failure.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
TNILibrary* TNIAllocLibrary(TNIContext* context, const TNIString* libraryName, const TNILibraryInitData&amp;amp; libraryInitData);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNIGetLibraryVersion&lt;br /&gt;
// Desc: Returns the developer-specified version for the given library.&lt;br /&gt;
// Parm: library - The library to query.&lt;br /&gt;
// Retn: uint32_t - the developer-specified version for the given library. &lt;br /&gt;
//       Returns zero on failure.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
uint32_t TNIGetLibraryVersion(const TNILibrary* library);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ============================================================================&lt;br /&gt;
// Name: TNICallLibraryFunction&lt;br /&gt;
// Desc: Calls into the specified library&#039;s LibraryCall function.&lt;br /&gt;
// Parm: library - The library on which to make the call.&lt;br /&gt;
// Parm: functionName - The name of the function to call. Must be a non-empty &lt;br /&gt;
//       string.&lt;br /&gt;
// Parm: params - NULL, or a TNIObject object.&lt;br /&gt;
// Retn: TNIObject* - The return value from the LibraryCall function, which may&lt;br /&gt;
//       be NULL or a valid TNIObject. Returns NULL on failure. It is the &lt;br /&gt;
//       caller&#039;s responsibility to release the returned object.&lt;br /&gt;
// ============================================================================&lt;br /&gt;
TNIObject* TNICallLibraryFunction(const TNILibrary* library, const TNILabel* functionName, const TNIObject* params);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TNIBuffer==&lt;br /&gt;
TNIBuffer provides untyped binary data storage. This is used in scenarios where large amounts of complex-type data needs to be rapidly created and passed between systems. This should be considered a last-resort mechanism, used only when the cost of the other object types is prohibitive.&lt;br /&gt;
&lt;br /&gt;
==TNIStream==&lt;br /&gt;
TNIStream provides a mechanism for serialising both data and TNIObjects into a &amp;quot;command buffer&amp;quot; which can be passed to another system. This is used in scenarios where large numbers of commands must be rapidly packed and later replayed. The writer and reader must agree on the stream format- the reader must make the appropriate calls to match what the writer used when constructing the stream. It is strongly recommended that some form of version negotiation is used to allow future changes to any streamed formats. TNIObjects are written to a TNIStream by reference- the TNIObjects themselves are not serialised or copied.&lt;br /&gt;
&lt;br /&gt;
This should be considered a last-resort mechanism, used only where the cost of the other object types is prohibitive.&lt;br /&gt;
&lt;br /&gt;
==TNIGameObjectID==&lt;br /&gt;
A TNIGameObjectID is used to identify Trainz game objects such as trains, script libraries, etc. It can be considered equivalent to the GameObjectID script class.&lt;br /&gt;
&lt;br /&gt;
Code should only ever compare TNIGameObjectID objects using the explicit matching functions, such as TNIDoGameObjectIDsMatch(const TNIGameObjectID *, const TNIGameObjectID *).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Threading=&lt;br /&gt;
Trainz is a preemptively multithreaded environment, which means that TNI functions need to be safe against certain thread usage. There are certain guarantees and limitations which are relevant to TNI development:&lt;br /&gt;
&lt;br /&gt;
* For any given TNIContext, only one thread will be making calls into TNI DLLs at a time. There is no guarantee that it will always be the same thread, only that multiple threads won&#039;t do it simultaneously. Because of this, don&#039;t use thread_local storage.&lt;br /&gt;
* For any given TNI Plugin, multiple threads may call into your TNI DLL functions simultaneously on behalf of different TNIContexts. If you use global variables or file-scope static variables, you must protect them with appropriate thread-safe locks.&lt;br /&gt;
* Never use function-scope static variables, as they are not thread-safe on Windows.&lt;br /&gt;
* TNIObjects may be used on any thread.&lt;br /&gt;
* TNIObjects may be read by multiple threads simultaneously.&lt;br /&gt;
* TNIObjects must not be accessed on any thread while being modified on another thread. If you are in doubt as to whether a particular function may modify the state of a TNIObject, you should assume that it does.&lt;br /&gt;
* TNIReference() and TNIRelease() modify the state of the TNIObject.&lt;br /&gt;
* You may create your own worker threads using the TNI threading API, but you may not make TNILibrary or TNIContext calls from those threads.&lt;br /&gt;
* You may not create threads using other APIs.&lt;/div&gt;</summary>
		<author><name>Pw3r</name></author>
	</entry>
</feed>