<?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=Dundun92</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=Dundun92"/>
	<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/wiki/Special:Contributions/Dundun92"/>
	<updated>2026-11-05T08:14:11Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=45591</id>
		<title>HowTo/Use the WagonX Library</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=45591"/>
		<updated>2025-12-15T00:12:34Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Document Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--the next line is the page title--&amp;gt;&lt;br /&gt;
&amp;lt;!--HowTo/Use the WagonX Library--&amp;gt;&lt;br /&gt;
= Document Structure =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
The WagonX Tutorial set is written over several TrainzWiKi pages.  This page is an introduction to WagonX and its capabilities, designed and developed by Joseph Bennett (dundun92).  Other pages in the series are:&lt;br /&gt;
&amp;lt;/table&amp;gt; &lt;br /&gt;
# [[HowTo/WagonX - Technical Reference]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Traincar Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Locomotive Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
== A discussion about &amp;quot;properties&amp;quot; ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;So what is a &amp;quot;property&amp;quot; and what is its purpose in Trainz?&lt;br /&gt;
A Google search will reveal that a property in this context is a value or attribute of an object. In Trainz we generally call such objects &amp;lt;b&amp;gt;assets&amp;lt;/b&amp;gt;. An example might be a traincar (wagon/car/carriage) and that traincar has some standard properties such as weight, cargo or passengers.&lt;br /&gt;
&lt;br /&gt;
But the standard properties are rather limited and, if a content creator wanted to add extra properties such as texture replacement, then a Trainz script is required.  Creating such scripts is not easy even for experienced programmers. Maintaining scripts can create a huge amount of work if common scripts are replicated across many assets.&lt;br /&gt;
&lt;br /&gt;
This is where WagonX can help.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== WagonX and Properties ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;WagonX is a universal script library that simplifies adding properties and scripted features to your traincar assets.&lt;br /&gt;
You can create an asset with all the perks of scripted assets without touching any TrainzScript (GS) files, or having much knowledge of trainzscript. You can set up a number of asset options, as identified in the following list, in the config.txt file.  All the details are then automatically presented to the user in the View Details (property browser) dialog, making it easy to edit as needed.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== The WagonX Asset ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
*The &#039;&#039;&#039;JBV WagonX Script Library - &amp;lt;kuid:661805:500008&amp;gt;&#039;&#039;&#039; is available on the Download Station.&lt;br /&gt;
*It is suitable for asset with Trainz Builds 5.0 or higher.  The library uses script functions only available from that version.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;	&lt;br /&gt;
&amp;lt;table width=1200 bgcolor=#000000 cellpadding=1&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;table width=1196 bgcolor=#ffffff cellpadding=2&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;The &#039;&#039;&#039;The WagonX Library&#039;&#039;&#039; can be used to set:-&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;animations&#039;&#039;&#039; - stop or start&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;texture replacements&#039;&#039;&#039; - loaded from a textures library asset&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;head codes&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;lamps&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;ACS controlled couplers and hoses&#039;&#039;&#039; - loaded from a suitable couplers/hoses mesh library&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;sounds&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;PFX effects&#039;&#039;&#039; - such as smoke or dust&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;triggered effects&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;consist synchronisation&#039;&#039;&#039; - such as texture swapping for vehicles also using WagonX in a consist&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;...and much more.&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;&lt;br /&gt;
	This picture demonstrates entries in the config and the result in the Properties Browser in game.  The asset is the library author&#039;s Prestwin 1/277 EXP (&amp;lt;kuid2:661805:1:1&amp;gt;).&lt;br /&gt;
	&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table width=1500&amp;gt;&lt;br /&gt;
	&amp;lt;tr valign=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;td&amp;gt;&lt;br /&gt;
			[[File:WagonX Documentation2.jpg|left]]&lt;br /&gt;
		&amp;lt;/td&amp;gt; &lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
== Basic configuration for the config.txt and asset script ==&lt;br /&gt;
=== Background ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;&lt;br /&gt;
	The library implementation for WagonX is a bit different from other library assets (such as Bloodnoks ACS lib or superscript) and utilizes a new script referencing technique from David Pistelak’s scripted assets. The traincar’s config.txt does not directly reference the wagon.gs file. It instead must reference a (mostly) blank gs file that will hold the information for the WagonX gs file. In this case, this special file is named ref.gs and the class to used is eRef.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The asset script ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;You will need to create a Trainzscript file called &amp;quot;ref.gs&amp;quot; and include it with your asset files. &amp;lt;b&amp;gt;Do not add any other code to ref.gs as future updates to the WagonX library may break your asset.&amp;lt;/b&amp;gt; The content of ref.gs should be:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  include &amp;quot;WagonX.gs&amp;quot;&lt;br /&gt;
  class eRef isclass WagonX{};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Config.txt - first steps ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Let&#039;s start with the basic tags needed to make WagonX work.  You will need to include script and class tags, a script-include-table, and a kuid-table reference if you are using ACSLib to control couplers and coupled hoses. &amp;lt;b&amp;gt;The spelling and capitisation of the class name is important.&amp;lt;/b&amp;gt; &amp;lt;span style=&amp;quot;color: red; font-weight: 700;&amp;quot;&amp;gt;Do not reference an iteration of the kiud, only exactly as the one shown below, as this will prevent your asset from receiving updates and bug fixes for compatibility in future trainz versions.&amp;lt;/span&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The config entries should look like this:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--indent this bit so a block is created--&amp;gt;&lt;br /&gt;
  script-include-table&lt;br /&gt;
    {&lt;br /&gt;
      0    &amp;lt;kuid:661805:500008&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
  script     &amp;quot;ref.gs&amp;quot;&lt;br /&gt;
  class      &amp;quot;eRef&amp;quot; &lt;br /&gt;
  kuid-table&lt;br /&gt;
  {&lt;br /&gt;
    acslib     &amp;lt;kuid2:60850:89100&amp;gt;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;That&#039;s it for the initial referencing of the script into your asset. The rest of the information for the script library goes inside the extensions container, under a sub-container that must be named “wagon-x”, all of which will be explained in the next sections. The following is a general example of how an extensions container using ACS and WagonX might appear.  It may not be suitable for your application.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 extensions&lt;br /&gt;
 {&lt;br /&gt;
   max_permitted_speed-60850 &amp;quot;50mph&amp;quot;&lt;br /&gt;
   active-coupling-standard-60850&lt;br /&gt;
   {&lt;br /&gt;
     version-major                       &amp;quot;2&amp;quot;&lt;br /&gt;
     version-minor                       &amp;quot;0&amp;quot;&lt;br /&gt;
     brakes                              &amp;quot;vac&amp;quot;&lt;br /&gt;
     front&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
     back&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   wagon-x&lt;br /&gt;
   {&lt;br /&gt;
     acs&lt;br /&gt;
     {&lt;br /&gt;
       animated                            1&lt;br /&gt;
       use-jbv-animation                   0&lt;br /&gt;
       duration                            1.5&lt;br /&gt;
     }&lt;br /&gt;
     misc&lt;br /&gt;
     {&lt;br /&gt;
       begin-load-time                    5&lt;br /&gt;
       begin-unload-time                  5&lt;br /&gt;
       end-load-time                      1&lt;br /&gt;
       end-unload-time                    1&lt;br /&gt;
     }&lt;br /&gt;
     marker-lights&lt;br /&gt;
     {&lt;br /&gt;
       enabled                             1&lt;br /&gt;
       car-minimum-count                   1&lt;br /&gt;
       require-locomotive                  1&lt;br /&gt;
       front&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;null&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-front-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       back&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-white&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
     browser-properties&lt;br /&gt;
     {&lt;br /&gt;
       0&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        1&lt;br /&gt;
         name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_skin&amp;quot;&lt;br /&gt;
         description                &amp;quot;Sets the weathering type&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
         fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;null&amp;quot;&lt;br /&gt;
         effects                    &amp;quot;texture-albedo,texture-parameter&amp;quot;&lt;br /&gt;
         asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
         files-path                 &amp;quot;null&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;3,1;4,2;5&amp;quot;&lt;br /&gt;
         default-index              -1&lt;br /&gt;
         trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;Clean,Weathered,Dirty&amp;quot;&lt;br /&gt;
       }   &lt;br /&gt;
       1&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        0&lt;br /&gt;
         name                       &amp;quot;Handbrake State: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_handbrake&amp;quot;&lt;br /&gt;
         description                &amp;quot;Toggle the handbrake&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
         mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;handbrake-lever,braking-system&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;0,30;30&amp;quot;&lt;br /&gt;
         events                     &amp;quot;handbrake-release,handbrake-apply&amp;quot;&lt;br /&gt;
         duration                   3.2&lt;br /&gt;
         default-index              0&lt;br /&gt;
         trigger                    &amp;quot;both&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;release,apply&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Next Steps =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;This page has been a basic introduction to WagonX. Some basic tutorials to setup some WagonX properties can be found at the [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Basic Tutorials&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
You can find a locomotive tutorial at the [[HowTo/WagonX - Locomotive Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Locomotive Tutorial&amp;lt;/span&amp;gt;]] page and a traincar tutorial at the [[HowTo/WagonX - Traincar Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Traincar Tutorial&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
These tutorials are supported by a detailed WagonX reference at the [[HowTo/WagonX - Reference|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;WagonX Reference&amp;lt;/span&amp;gt;]] page.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
=Copyright Notice=&lt;br /&gt;
Much of the content on this page and child pages was derived from Dundun92&#039;s original Google Docs document.  Permission was granted to use that information here.&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--=Return to Index=&lt;br /&gt;
 &lt;br /&gt;
[[HowToGuides|&amp;lt;&amp;lt; How To Guides]]&lt;br /&gt;
[[Category:How-to guides]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Content creation]]&lt;br /&gt;
[[Category:WagonX]]--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=44473</id>
		<title>Class MapObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=44473"/>
		<updated>2025-05-18T02:43:18Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* GetMapObjectPosition */&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 in seconds over which the particles are to be created.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEmitParticles(0,100,10.0);&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>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=43685</id>
		<title>Class MapObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_MapObject&amp;diff=43685"/>
		<updated>2024-12-15T02:23:00Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* SetPFXEmitterEndColor */&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 Orientation 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 in seconds over which the particles are to be created.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 SetPFXEmitterEmitParticles(0,100,10.0);&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>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=42464</id>
		<title>HowTo/Use the WagonX Library</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=42464"/>
		<updated>2024-07-07T19:52:50Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Config.txt - first steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--the next line is the page title--&amp;gt;&lt;br /&gt;
&amp;lt;!--HowTo/Use the WagonX Library--&amp;gt;&lt;br /&gt;
= Document Structure =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
The WagonX Tutorial set is written over several TrainzWiKi pages.  This page is an introduction to WagonX and its capabilties.  Other pages in the series are:&lt;br /&gt;
&amp;lt;/table&amp;gt; &lt;br /&gt;
# [[HowTo/WagonX - Technical Reference]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Traincar Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Locomotive Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
== A discussion about &amp;quot;properties&amp;quot; ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;So what is a &amp;quot;property&amp;quot; and what is its purpose in Trainz?&lt;br /&gt;
A Google search will reveal that a property in this context is a value or attribute of an object. In Trainz we generally call such objects &amp;lt;b&amp;gt;assets&amp;lt;/b&amp;gt;. An example might be a traincar (wagon/car/carriage) and that traincar has some standard properties such as weight, cargo or passengers.&lt;br /&gt;
&lt;br /&gt;
But the standard properties are rather limited and, if a content creator wanted to add extra properties such as texture replacement, then a Trainz script is required.  Creating such scripts is not easy even for experienced programmers. Maintaining scripts can create a huge amount of work if common scripts are replicated across many assets.&lt;br /&gt;
&lt;br /&gt;
This is where WagonX can help.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== WagonX and Properties ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;WagonX is a universal script library that simplifies adding properties and scripted features to your traincar assets.&lt;br /&gt;
You can create an asset with all the perks of scripted assets without touching any TrainzScript (GS) files, or having much knowledge of trainzscript. You can set up a number of asset options, as identified in the following list, in the config.txt file.  All the details are then automatically presented to the user in the View Details (property browser) dialog, making it easy to edit as needed.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== The WagonX Asset ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
*The &#039;&#039;&#039;JBV WagonX Script Library - &amp;lt;kuid:661805:500008&amp;gt;&#039;&#039;&#039; is available on the Download Station.&lt;br /&gt;
*It is suitable for asset with Trainz Builds 5.0 or higher.  The library uses script functions only available from that version.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;	&lt;br /&gt;
&amp;lt;table width=1200 bgcolor=#000000 cellpadding=1&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;table width=1196 bgcolor=#ffffff cellpadding=2&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;The &#039;&#039;&#039;The WagonX Library&#039;&#039;&#039; can be used to set:-&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;animations&#039;&#039;&#039; - stop or start&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;texture replacements&#039;&#039;&#039; - loaded from a textures library asset&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;head codes&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;lamps&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;ACS controlled couplers and hoses&#039;&#039;&#039; - loaded from a suitable couplers/hoses mesh library&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;sounds&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;PFX effects&#039;&#039;&#039; - such as smoke or dust&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;triggered effects&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;consist synchronisation&#039;&#039;&#039; - such as texture swapping for vehicles also using WagonX in a consist&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;...and much more.&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;&lt;br /&gt;
	This picture demonstrates entries in the config and the result in the Properties Browser in game.  The asset is the library author&#039;s Prestwin 1/277 EXP (&amp;lt;kuid2:661805:1:1&amp;gt;).&lt;br /&gt;
	&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table width=1500&amp;gt;&lt;br /&gt;
	&amp;lt;tr valign=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;td&amp;gt;&lt;br /&gt;
			[[File:WagonX Documentation2.jpg|left]]&lt;br /&gt;
		&amp;lt;/td&amp;gt; &lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
== Basic configuration for the config.txt and asset script ==&lt;br /&gt;
=== Background ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;&lt;br /&gt;
	The library implementation for WagonX is a bit different from other library assets (such as Bloodnoks ACS lib or superscript) and utilizes a new script referencing technique from David Pistelak’s scripted assets. The traincar’s config.txt does not directly reference the wagon.gs file. It instead must reference a (mostly) blank gs file that will hold the information for the WagonX gs file. In this case, this special file is named ref.gs and the class to used is eRef.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The asset script ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;You will need to create a Trainzscript file called &amp;quot;ref.gs&amp;quot; and include it with your asset files. &amp;lt;b&amp;gt;Do not add any other code to ref.gs as future updates to the WagonX library may break your asset.&amp;lt;/b&amp;gt; The content of ref.gs should be:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  include &amp;quot;WagonX.gs&amp;quot;&lt;br /&gt;
  class eRef isclass WagonX{};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Config.txt - first steps ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Let&#039;s start with the basic tags needed to make WagonX work.  You will need to include script and class tags, a script-include-table, and a kuid-table reference if you are using ACSLib to control couplers and coupled hoses. &amp;lt;b&amp;gt;The spelling and capitisation of the class name is important.&amp;lt;/b&amp;gt; &amp;lt;span style=&amp;quot;color: red; font-weight: 700;&amp;quot;&amp;gt;Do not reference an iteration of the kiud, only exactly as the one shown below, as this will prevent your asset from receiving updates and bug fixes for compatibility in future trainz versions.&amp;lt;/span&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The config entries should look like this:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--indent this bit so a block is created--&amp;gt;&lt;br /&gt;
  script-include-table&lt;br /&gt;
    {&lt;br /&gt;
      0    &amp;lt;kuid:661805:500008&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
  script     &amp;quot;ref.gs&amp;quot;&lt;br /&gt;
  class      &amp;quot;eRef&amp;quot; &lt;br /&gt;
  kuid-table&lt;br /&gt;
  {&lt;br /&gt;
    acslib     &amp;lt;kuid2:60850:89100&amp;gt;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;That&#039;s it for the initial referencing of the script into your asset. The rest of the information for the script library goes inside the extensions container, under a sub-container that must be named “wagon-x”, all of which will be explained in the next sections. The following is a general example of how an extensions container using ACS and WagonX might appear.  It may not be suitable for your application.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 extensions&lt;br /&gt;
 {&lt;br /&gt;
   max_permitted_speed-60850 &amp;quot;50mph&amp;quot;&lt;br /&gt;
   active-coupling-standard-60850&lt;br /&gt;
   {&lt;br /&gt;
     version-major                       &amp;quot;2&amp;quot;&lt;br /&gt;
     version-minor                       &amp;quot;0&amp;quot;&lt;br /&gt;
     brakes                              &amp;quot;vac&amp;quot;&lt;br /&gt;
     front&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
     back&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   wagon-x&lt;br /&gt;
   {&lt;br /&gt;
     acs&lt;br /&gt;
     {&lt;br /&gt;
       animated                            1&lt;br /&gt;
       use-jbv-animation                   0&lt;br /&gt;
       duration                            1.5&lt;br /&gt;
     }&lt;br /&gt;
     misc&lt;br /&gt;
     {&lt;br /&gt;
       begin-load-time                    5&lt;br /&gt;
       begin-unload-time                  5&lt;br /&gt;
       end-load-time                      1&lt;br /&gt;
       end-unload-time                    1&lt;br /&gt;
     }&lt;br /&gt;
     marker-lights&lt;br /&gt;
     {&lt;br /&gt;
       enabled                             1&lt;br /&gt;
       car-minimum-count                   1&lt;br /&gt;
       require-locomotive                  1&lt;br /&gt;
       front&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;null&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-front-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       back&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-white&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
     browser-properties&lt;br /&gt;
     {&lt;br /&gt;
       0&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        1&lt;br /&gt;
         name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_skin&amp;quot;&lt;br /&gt;
         description                &amp;quot;Sets the weathering type&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
         fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;null&amp;quot;&lt;br /&gt;
         effects                    &amp;quot;texture-albedo,texture-parameter&amp;quot;&lt;br /&gt;
         asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
         files-path                 &amp;quot;null&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;3,1;4,2;5&amp;quot;&lt;br /&gt;
         default-index              -1&lt;br /&gt;
         trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;Clean,Weathered,Dirty&amp;quot;&lt;br /&gt;
       }   &lt;br /&gt;
       1&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        0&lt;br /&gt;
         name                       &amp;quot;Handbrake State: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_handbrake&amp;quot;&lt;br /&gt;
         description                &amp;quot;Toggle the handbrake&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
         mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;handbrake-lever,braking-system&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;0,30;30&amp;quot;&lt;br /&gt;
         events                     &amp;quot;handbrake-release,handbrake-apply&amp;quot;&lt;br /&gt;
         duration                   3.2&lt;br /&gt;
         default-index              0&lt;br /&gt;
         trigger                    &amp;quot;both&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;release,apply&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Next Steps =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;This page has been a basic introduction to WagonX. Some basic tutorials to setup some WagonX properties can be found at the [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Basic Tutorials&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
You can find a locomotive tutorial at the [[HowTo/WagonX - Locomotive Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Locomotive Tutorial&amp;lt;/span&amp;gt;]] page and a traincar tutorial at the [[HowTo/WagonX - Traincar Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Traincar Tutorial&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
These tutorials are supported by a detailed WagonX reference at the [[HowTo/WagonX - Reference|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;WagonX Reference&amp;lt;/span&amp;gt;]] page.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
=Copyright Notice=&lt;br /&gt;
Much of the content on this page and child pages was derived from Dundun92&#039;s original Google Docs document.  Permission was granted to use that information here.&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--=Return to Index=&lt;br /&gt;
 &lt;br /&gt;
[[HowToGuides|&amp;lt;&amp;lt; How To Guides]]&lt;br /&gt;
[[Category:How-to guides]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Content creation]]&lt;br /&gt;
[[Category:WagonX]]--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE186&amp;diff=41520</id>
		<title>Help:VE186</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE186&amp;diff=41520"/>
		<updated>2024-05-06T02:07:36Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Category code &#039;ZX - Material &#039;arc:fld:$(local)/hash-nn||kuid nnnnn nnnnn.tzarc|**&#039;&#039;material name&#039;&#039; is shared between multiple meshes in this asset but the material parameters conflict.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Material sharing]] is a recommended technique for improving performance. This asset contains meshes which share materials, but which are configured such that material sharing is inappropriate and will introduce unwanted and undefined behaviour. The resulting visual faults may be subtle or substantial, and may give different results on each run or on different Trainz installs.&lt;br /&gt;
&lt;br /&gt;
VE186 is a warning for assets with a [http://online.ts2009.com/mediaWiki/index.php/Trainz_Build_Versions Trainz Build] less than 4.5 or greater than 5.0, and an error for assets with a Trainz Build from 4.5 to 5.0.&lt;br /&gt;
&lt;br /&gt;
Trainz may also show diagnostic messages before this warning/error. These diagnostics will help identify which material attributes are mismatched.&lt;br /&gt;
&lt;br /&gt;
This warning/error always involves multiple [[render chunk]]s, typically across two or more mesh files. The warning/error will clear only once all of the involved [[render chunk]]s have been corrected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Background=&lt;br /&gt;
The first time the game encounters a named material in a given asset, that material is loaded with the material parameters that are defined for it (including texture slots and lighting parameters). If the same material name is subsequently encountered in another chunk or mesh of the same asset, then a new material is not loaded - the parameters already loaded are used. Those parameters might not be what was intended for that second material, and the rendering of the asset might therefore be incorrect. Also, as the sequence of loading meshes is not predictable, the resultant rendering will vary in different circumstances. To obtain correct, consistent rendering of the asset it is important to ensure that each material is loaded with the correct parameters for that material.&lt;br /&gt;
&lt;br /&gt;
=Automated Workaround=&lt;br /&gt;
Newer versions of Trainz will attempt to detect and work around this problem at runtime on older assets, by disabling material sharing for the assets. This workaround may reduce performance, but may help to stabilise the visual result. This workaround may or may not give the visual result that the content creator had in mind when they created the asset. For newer assets, this problem is simply considered an error. In either case, it is recommended that the content creator fix the problem so that the result is well defined and performs as expected.&lt;br /&gt;
&lt;br /&gt;
=Examples=&lt;br /&gt;
&lt;br /&gt;
The following examples will result in a warning/error.&lt;br /&gt;
&lt;br /&gt;
*  An asset uses the same material name for three different LOD meshes.  Two meshes are exported with one version of the material but the last is exported with a variation, such as a different material specular value.  &lt;br /&gt;
&lt;br /&gt;
*  As for the first example, but a texture is substituted, added or removed, for one of the meshes. &lt;br /&gt;
&lt;br /&gt;
*  As for the first example, but the two conflicting meshes are generic meshes (eg, an attachment mesh and a shadow mesh) that use the same material name and the materials in the two meshes have different property values.  The error is reported even though there is no texture resource for the material. &lt;br /&gt;
&lt;br /&gt;
*  An asset is created with two meshes both within their own source file.  The same notex material name is used for both meshes but there is a variation in the diffuse colour. &lt;br /&gt;
&lt;br /&gt;
Therefore:&lt;br /&gt;
* Do not use the same material name if the materials should have different parameters.&lt;br /&gt;
* If you use the same material name in different meshes then ensure that the material parameters are the same.&lt;br /&gt;
* Avoid material names (eg &#039;black_m&#039;) that are common in generic meshes that might subsequently be added to the asset.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE186&amp;diff=41519</id>
		<title>Help:VE186</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE186&amp;diff=41519"/>
		<updated>2024-05-06T02:07:15Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Category code &#039;ZX - Material &#039;arc:fld:$(local)/hash-nn||kuid nnnnn nnnnn.tzarc|**&#039;&#039;material name&#039;&#039; is shared between multiple meshes in this asset but the material parameters conflict.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Material sharing]] is a recommended technique for improving performance. This asset contains meshes which share materials, but which are configured such that material sharing is inappropriate and will introduce unwanted and undefined behaviour. The resulting visual faults may be subtle or substantial, and may give different results on each run or on different Trainz installs.&lt;br /&gt;
&lt;br /&gt;
VE186 is a warning for assets with a [http://online.ts2009.com/mediaWiki/index.php/Trainz_Build_Versions Trainz Build] less than 4.5, and an error for assets with a Trainz Build 4.5 to 5.0.&lt;br /&gt;
&lt;br /&gt;
Trainz may also show diagnostic messages before this warning/error. These diagnostics will help identify which material attributes are mismatched.&lt;br /&gt;
&lt;br /&gt;
This warning/error always involves multiple [[render chunk]]s, typically across two or more mesh files. The warning/error will clear only once all of the involved [[render chunk]]s have been corrected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Background=&lt;br /&gt;
The first time the game encounters a named material in a given asset, that material is loaded with the material parameters that are defined for it (including texture slots and lighting parameters). If the same material name is subsequently encountered in another chunk or mesh of the same asset, then a new material is not loaded - the parameters already loaded are used. Those parameters might not be what was intended for that second material, and the rendering of the asset might therefore be incorrect. Also, as the sequence of loading meshes is not predictable, the resultant rendering will vary in different circumstances. To obtain correct, consistent rendering of the asset it is important to ensure that each material is loaded with the correct parameters for that material.&lt;br /&gt;
&lt;br /&gt;
=Automated Workaround=&lt;br /&gt;
Newer versions of Trainz will attempt to detect and work around this problem at runtime on older assets, by disabling material sharing for the assets. This workaround may reduce performance, but may help to stabilise the visual result. This workaround may or may not give the visual result that the content creator had in mind when they created the asset. For newer assets, this problem is simply considered an error. In either case, it is recommended that the content creator fix the problem so that the result is well defined and performs as expected.&lt;br /&gt;
&lt;br /&gt;
=Examples=&lt;br /&gt;
&lt;br /&gt;
The following examples will result in a warning/error.&lt;br /&gt;
&lt;br /&gt;
*  An asset uses the same material name for three different LOD meshes.  Two meshes are exported with one version of the material but the last is exported with a variation, such as a different material specular value.  &lt;br /&gt;
&lt;br /&gt;
*  As for the first example, but a texture is substituted, added or removed, for one of the meshes. &lt;br /&gt;
&lt;br /&gt;
*  As for the first example, but the two conflicting meshes are generic meshes (eg, an attachment mesh and a shadow mesh) that use the same material name and the materials in the two meshes have different property values.  The error is reported even though there is no texture resource for the material. &lt;br /&gt;
&lt;br /&gt;
*  An asset is created with two meshes both within their own source file.  The same notex material name is used for both meshes but there is a variation in the diffuse colour. &lt;br /&gt;
&lt;br /&gt;
Therefore:&lt;br /&gt;
* Do not use the same material name if the materials should have different parameters.&lt;br /&gt;
* If you use the same material name in different meshes then ensure that the material parameters are the same.&lt;br /&gt;
* Avoid material names (eg &#039;black_m&#039;) that are common in generic meshes that might subsequently be added to the asset.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE213&amp;diff=40362</id>
		<title>Help:VE213</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE213&amp;diff=40362"/>
		<updated>2024-03-25T21:30:08Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Traincar asset has invalid bogey placement.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[KIND Traincar]] assets are required to have physically realistic spacing (eg. typically meters) present between the attachment points for each set of bogeys. This validation error results when the a.bog0 and a.bog1 bogey attachment points are at effectively identical locations on the y-axis.&lt;br /&gt;
&lt;br /&gt;
This validation results in an error at trainz-build 4.5 and higher.&lt;br /&gt;
In lower trainz-build assets, the validation is considered a warning for compatibility reasons, however it is likely to lead to undesirable runtime behaviour.&lt;br /&gt;
&lt;br /&gt;
Also, make sure there are no stray empties or lattices in your mesh file&lt;br /&gt;
&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=MiniBrowser&amp;diff=40240</id>
		<title>MiniBrowser</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=MiniBrowser&amp;diff=40240"/>
		<updated>2024-03-14T01:46:47Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* dirver-menu-button */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [[MiniBrowser]] is a trivial HTML renderer used for simple layout control within the Trainz game environment. It is specifically not a replacement for a real browser (see [[Trainz Online]] instead), is not remotely standards compliant, and does not support a full range of HTML tags. If a tag isn&#039;t mentioned here then it is NOT supported. There is no javascript support ([[Scripting|TrainzScript]] is used instead.) The [[MiniBrowser]] is used exclusively by the Trainz [[class Browser|Browser]] script object.&lt;br /&gt;
&lt;br /&gt;
Feature requests relating primarily to the MiniBrowser should be placed on the [[MiniBrowser Feature Requests]] page.&lt;br /&gt;
&lt;br /&gt;
Trainz HTML is NOT standards compliant and is best thought of as an HTML-alike chosen so users and developers are familiar with the style of syntax being used.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Supported Tags=&lt;br /&gt;
The MiniBrowser supports the following HTML tags:&lt;br /&gt;
&lt;br /&gt;
==HTML==&lt;br /&gt;
This tag wraps the entire HTML document. No parameters are supported. This tag should be at the top level of the document and should contain a single &#039;[[#BODY |BODY]]&#039; tag.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;html&amp;gt;&lt;br /&gt;
::...&lt;br /&gt;
:&amp;amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==BODY==&lt;br /&gt;
This tag wraps the entire body of the HTML document. The &#039;scale&#039; parameter is provided to force the document to be rescaled to a specified number of pixels wide, but its usage is strongly discouraged. This tag should exist within the &#039;[[#HTML |HTML]]&#039; tag and may contain any number of other elements.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;body scale=?&amp;gt;&lt;br /&gt;
::...&lt;br /&gt;
:&amp;amp;lt;/body&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==P (paragraph)==&lt;br /&gt;
This tag causes the contained elements to be formatted as a separate paragraph. This is similar to prefixing and suffixing the elements with a linebreak. Paragraph tag has no parameters.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;p&amp;gt;...&amp;amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==BR (linebreak)==&lt;br /&gt;
A forced linebreak. BR has no parameters.&lt;br /&gt;
&lt;br /&gt;
BR is an unclosed tag, unlike XHTML there is no &amp;amp;lt;br /&amp;gt; or &amp;amp;lt;/br&amp;gt;. In fact using such a thing will most likely be interpreted as an error by the Trainz HTML parser.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:...&amp;amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TABLE==&lt;br /&gt;
This tag forms a table element. Any number of &amp;amp;lt;[[#TR |TR]]&amp;gt; (table row) elements may be present within the &#039;TABLE&#039; tag and that is all it should contain directly. Table height cannot be specified, this can be controlled by setting each &amp;amp;lt;[[#TR |TR]]&amp;gt; element within the table to add up to the desired table height.&lt;br /&gt;
&lt;br /&gt;
Table does NOT support the following parameters; rules, summary, align. Nor does it support the &amp;amp;lt;TH&amp;gt; element (the same effect can be achieved by making the contents of a &amp;amp;lt;[[#TD |TD]]&amp;gt; [[#B |BOLD]] or even more so by the use of [[#FONT |FONT]]). Table is best thought of as a grid, like that of a spreadsheet or a table inserted into a document. Tables are described by &amp;amp;lt;[[#TR |TR]]&amp;gt;; a row in a table and &amp;amp;lt;[[#TD |TD]]&amp;gt;; a cell in a row. &lt;br /&gt;
&lt;br /&gt;
Tables are not askew, meaning if 1 row has 3 cells then all rows will have at least 3 cells, this does not mean the coder must put at least 3 &amp;amp;lt;[[#TD |TD]]&amp;gt;s in each &amp;amp;lt;[[#TR |TR]]&amp;gt; it means when formatted for display on screen the html render will organise the table as such (as it is uniform). Furthermore, cells conform to the dimensions of their siblings; meaning a cell has the same width as the widest cell in its column (controllable by width in &amp;amp;lt;[[#TD |TD]]&amp;gt;) and the same height as the tallest cell in its row (controllable by height in &amp;amp;lt;[[#TR |TR]]&amp;gt;). This is very important to keep in mind when using tables for formatting/layout purposes.&lt;br /&gt;
&lt;br /&gt;
The documentation on &amp;amp;lt;[[#TR |TR]]&amp;gt; and &amp;amp;lt;[[#TD |TD]]&amp;gt; have more information about the use of tables in Trainz HTML. For more info and a place to try out some of these properties of tables try the [http://www.w3schools.com/tags/tag_table.asp w3schools table tag page], but remember Trainz HTML is not the same as HTML proper.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All parameters are optional.&lt;br /&gt;
*cellpadding - specifies the minimum pixel space between the cell wall and its content. Default is 0.&lt;br /&gt;
*cellspacing - specifies the pixels between cells. Default is 0.&lt;br /&gt;
*width - specifies the pixel width of the table. If none is given the table will grow to fit its content. If width is given cell content will be wrapped if it would force table width beyond that.&lt;br /&gt;
*border - specifies the pixel width between the table and content around it. Default is 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;table cellpadding=? cellspacing=? border=? width=? inherit-font&amp;gt;...&amp;amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TR==&lt;br /&gt;
TR is Table Row. This tag forms a single horizontal row of a table. Any number of &#039;[[#TD |TD]]&#039; (table data) elements may be present within the &#039;TR&#039; tag and that is all it should directly contain. &amp;amp;lt;TR&amp;gt; does NOT support the following parameters; align, valign, char, charoff.&lt;br /&gt;
&lt;br /&gt;
All parameters are optional. Height, if specified, will limit how many pixels high this row can be, causing cells to expand in width if they were to approach this height.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When using tables for formatting it is important to remember that cell size is dependent upon both column and row (see &amp;amp;lt;[[#TD |TD]]&amp;gt; and/or &amp;amp;lt;[[#TABLE |TABLE]]&amp;gt; for more info) thus it may be useful to consider creating a &amp;amp;lt;TR&amp;gt; with no data that exists only to set up the size of the columns ie.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;tr&amp;gt; &amp;amp;lt;td width=&#039;20&#039;&amp;gt;&amp;amp;lt;/td&amp;gt; &amp;amp;lt;td width=&#039;50&#039;&amp;gt;&amp;amp;lt;/td&amp;gt; &amp;amp;lt;td width=&#039;200&#039;&amp;gt;&amp;amp;lt;/td&amp;gt; &amp;amp;lt;td width=&#039;20&#039;&amp;gt;&amp;amp;lt;/td&amp;gt;  &amp;amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
now unless a &amp;amp;lt;TR&amp;gt; with more than 4 &amp;amp;lt;[[#TD |TD]]&amp;gt;s is created, the formatting for all columns is already done and as this &amp;amp;lt;TR&amp;gt; has no height specified and no data in its &amp;amp;lt;[[#TD |TD]]&amp;gt; cells it will take up only the space specified by the &amp;amp;lt;[[#TABLE |TABLE]]&amp;gt;&#039;s border, cellspacing and cellpadding (default 0).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;tr height=? bgcolor=?&amp;gt;...&amp;amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TD==&lt;br /&gt;
TD is Table Data. This tag forms a single cell within a table row. &amp;amp;lt;TD&amp;gt; does NOT support the following parameters; abbr, axis, char, charoff, headers, height, scope.&lt;br /&gt;
&lt;br /&gt;
Height of a cell is controlled by the tallest cell in the row or by the &amp;amp;lt;[[#TR |TR]]&amp;gt; height parameter if it is specified.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;TD&amp;gt; is the work horse of tables, as the name implies all contents of a table are contained within a &amp;amp;lt;TD&amp;gt; tag. Anything can be placed within a cell, even a table eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt; &amp;lt;body&amp;gt;&lt;br /&gt;
  &amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt; &lt;br /&gt;
      &amp;lt;td&amp;gt;Some text &amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td&amp;gt;Some text &amp;lt;/td&amp;gt; &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt; &lt;br /&gt;
      &amp;lt;td&amp;gt;Some text &amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td&amp;gt;Some text &amp;lt;/td&amp;gt; &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt; &lt;br /&gt;
      &amp;lt;td&amp;gt; &lt;br /&gt;
        &amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;tr&amp;gt;&lt;br /&gt;
            &amp;lt;td&amp;gt;Some text in a sub table &amp;lt;/td&amp;gt;&lt;br /&gt;
            &amp;lt;td&amp;gt;Some other text in a sub table &amp;lt;/td&amp;gt;&lt;br /&gt;
          &amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
      &amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td&amp;gt;&amp;lt;---Wow thats a sub table over there &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
coping and pasting the above into the left pane of [http://www.w3schools.com/HTML/tryit.asp?filename=tryhtml_basic this Tryit window](open it in a new tab or window) and clicking &amp;quot;Edit and Click me &amp;gt;&amp;gt;&amp;quot; button will show you a table with a table in it on the right hand side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All parameters are optional.&lt;br /&gt;
*rowspan and colspan allows this cell to consume the space that would normally be allocated to neighboring cells on the right and bottom sides. Default values are 1, meaning the &amp;amp;lt;TD&amp;gt; spans its own cell and nothing more. [http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_table_span Visual example of spanning], but remember Trainz HTML is not the same as HTML proper.&lt;br /&gt;
*width - specifies the pixel width of this cell, useful for formatting.&lt;br /&gt;
*align - &#039;left&#039;, &#039;center&#039;, &#039;right&#039;. (default &#039;left&#039;.) Controls the horizontal alignment of the content data within the table cell.&lt;br /&gt;
*valign - &#039;top&#039;, &#039;center&#039;, &#039;bottom&#039; (default &#039;top&#039;) Controls the vertical alignment of the content data within the table cell.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;td rowspawn=? colspan=? width=? bgcolor=? align=? valign=?&amp;gt;...&amp;amp;lt;/td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==A==&lt;br /&gt;
A is the Anchor tag. This tag marks all contained elements as a hyperlink with the specified attributes. Hyperlinked text will be underlined.&lt;br /&gt;
&lt;br /&gt;
Tooltip text will be displayed when the mouse hovers over the hyperlinked elements.&lt;br /&gt;
&lt;br /&gt;
The href is the minor message in a [[Browser Messages |Browser-URL message]] sent by the [[class Browser |Browser]] to whomever is listening to it. ie. the major=&amp;quot;Browser-URL&amp;quot; minor=&amp;quot;live://button/horn&amp;quot; message is produced by a hyperlinked button (horn) in the driver user interface.&lt;br /&gt;
&lt;br /&gt;
A hyperlink is considered clicked when the user has pressed and released mouse button 1 while over it.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;a href=? target=? help-label=? mousedown=? disabled-href=? tooltip=?&amp;gt;...&amp;amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==IMG==&lt;br /&gt;
IMG is the IMaGe tag. This tag displays an image with the specified attributes. Does NOT support the alt or title tags. &lt;br /&gt;
&lt;br /&gt;
All parameters are optional however, the src or the kuid parameter needs to be filled out for anything to show up apart from a fill.&lt;br /&gt;
&lt;br /&gt;
The width and height parameters define the pixel size the image will occupy on screen, these can be made larger or smaller than the image&#039;s actual size to zoom, stretch or squash the image as needed. Keep in mind that users don&#039;t all use the same resolution, so it is usually best to make pictures either fixed size in a screen position via the use of tables or calculating a pixel size relative to the current resolution.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;img src=? mouseover=? kuid=? width=? height=? srcwidth=? srcheight=? color=? hflip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TRAINZ-TEXT==&lt;br /&gt;
A section of text that can be changed without having to recalculate or reset the entire HTML string in a [[class Browser |browser]]. &lt;br /&gt;
&lt;br /&gt;
In the Driver interface the speed panel shows the selected train&#039;s current speed, the current speed limit on its segment of track and the current world time. Below is the speed HTML, which is retrieved via the localisation method described in &amp;amp;lt;[[#FONT |FONT]]&amp;gt;;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;font color=#00FF00 locale=&#039;english&#039;&amp;gt;&amp;lt;b&amp;gt;&amp;lt;trainz-text id=&#039;speed&#039; text=&#039;0 KM/H&#039;&amp;gt;&amp;lt;/trainz-text&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This specifies green bold text that is bound to an id of &amp;quot;speed&amp;quot;. Now in every heartbeat in DriverModule.gs, the currently selected train&#039;s speed is calculated and applied to this trainz-text by calling SetTrainzText(&amp;quot;speed&amp;quot;, &amp;quot;10 kph&amp;quot;) [10 kph used only for illustrative purposes] on the [[class Browser |browser]] that contains the speed html.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The id parameter is required to be able to update this section of text via the SetTrainzText [[class Browser |browser]] call. The text parameter does not need to be filled out int HTML can be specified using the SetTrainzText method at a later time.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;trainz-text id=? text=?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==B==&lt;br /&gt;
B is Boldface. Causes any text in contained elements to be rendered as boldface. The bold tag has no parameters.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;b&amp;gt;...&amp;amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==NOWRAP==&lt;br /&gt;
Suppresses automatic word wrap in the contained elements. The nowrap tag has no parameters.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;nowrap&amp;gt;...&amp;amp;lt;/nowrap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==I==&lt;br /&gt;
I is the Italics tag. Causes any text in the contained elements to be rendered as italic. The italic tag has no parameters.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;i&amp;gt;...&amp;amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==FONT==&lt;br /&gt;
Causes the specified text attributes to be applied to any text in the contained elements. Text in Trainz HTML does not have to be enclosed in font tags, if none are found around any given text it will receive the default font settings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Localisation note; the follow statement has special meaning to the Trains HTML parser;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;font locale=generic&amp;gt;A_TAG&amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When a tag such as this is parsed, Trainz will look in the current users selected language [[class StringTable | string table]] of the current asset for a string with the name found between the &amp;amp;lt;font&amp;gt; &amp;amp;lt;/font&amp;gt; tags, in this case A_TAG. It will replace the entire statement from here &amp;quot;&amp;amp;lt;font... &amp;amp;lt;/font&amp;gt;&amp;quot; to here with what is found in the [[class StringTable | string table]]. An example of this at work is in the Driver interface where the camera types are defined in the string tables of the Driver asset [[config.txt file | config.txt]] in all available languages so that each camera button has the selected language tooltip for each camera mode.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;font size=? color=? locale=? face=?&amp;gt;...&amp;amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TRAINZ-OBJECT==&lt;br /&gt;
Documented below under [[#Embedded Objects |embedded objects]]. Embedded objects fill the style parameter. The width and height parameters specify the pixel size of the given object, eg. how big a button is.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:&amp;amp;lt;trainz-object width=? height=? style=?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Supported Characters=&lt;br /&gt;
The MiniBrowser parses its input from UTF-8 encoded HTML. The full range of unicode characters may be included without special escape sequences. The following escape sequences are permitted and may be necessary to prevent the characters from being parsed as HTML markup.&lt;br /&gt;
* &amp;amp;amp;nbsp; - the HTML non-breaking space character.&lt;br /&gt;
* &amp;amp;amp;gt; - the &amp;quot;greater than&amp;quot; character (&#039; &amp;amp;gt; &#039;) &lt;br /&gt;
* &amp;amp;amp;lt; - the &amp;quot;less than&amp;quot; character (&#039; &amp;amp;lt; &#039;)&lt;br /&gt;
* &amp;amp;amp;amp; - the &amp;quot;ampersand&amp;quot; character (&#039; &amp;amp;amp; &#039;)&lt;br /&gt;
* &amp;amp;amp;quot; - the &amp;quot;quote&amp;quot; character (&#039; &amp;amp;quot; &#039;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Embedded Objects=&lt;br /&gt;
The following embedded objects are supported by the trainz-object tag:&lt;br /&gt;
&lt;br /&gt;
==driver-menu-button==&lt;br /&gt;
:style=driver-menu-button name=?&lt;br /&gt;
&lt;br /&gt;
==dial==&lt;br /&gt;
Works like an analogue volume knob. A dial is used in the driver interface, in the dcc panel to control the speed/power of the train. These are its settings;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;trainz-object style=dial width=95 height=95 id=&#039;dcc&#039; &lt;br /&gt;
texture=&#039;newdriver/dcc/dcc_controller.tga&#039; min=0.1 max=0.9 &lt;br /&gt;
valmin=-1.0 valmax=1.0 step=0 clickstep=1 value=0.5&amp;gt;&amp;lt;/trainz-object&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Driver wraps the dial in an &amp;amp;lt;[[#A |A]]&amp;gt; as to receive messages from user interactions with it, it then uses the GetElementProperty(&amp;quot;dcc&amp;quot;, &amp;quot;value&amp;quot;) on the [[class Browser |Browser]] the dial resides in to extract its current value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Parameters explained;&lt;br /&gt;
*The style, width, height and id parameters belong to the [[#TRAINZ-OBJECT |TRAINZ-OBJECT]].&lt;br /&gt;
*The min and max parameters specify the rotation (as a percent between 0 and 1) the dial can have in the interface. For the driver speed knob its 0.1 to 0.9; imagining this as a clock face this means the dial is allowed to rotate between approximately 7 clockwise around to approximately 5 and vice versa anticlockwise anywhere between 5 and 7. The dial&#039;s rotation can never be clockwise between 5 and 7.&lt;br /&gt;
*valmin and valmax specify the values returned by the dial, that is how its values map to its rotation. Using the clockface analogy again, at approximately 7 the dial will return the value of -1, at approximately 5 it will return the value 1 and at 12 it will return 0.&lt;br /&gt;
*step specifies the minimum change that can occur in the dial, 0 means it can move completely freely, if step were 0.1 and the user had rotated it by 0.04 no rotation would be registered and the dial would snap back to its previous position.&lt;br /&gt;
*clickstep TBD&lt;br /&gt;
*value sets the initial starting position (as a percentage 0 to 1) of its range. 0.5 being half between max and min.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:style=dial texture=? min=? max=? valmin=? valmax=? step=? clickstep=? value=?&lt;br /&gt;
&lt;br /&gt;
==graphic-button==&lt;br /&gt;
:style=graphic-button text-color=? texture_off=? texture_on=? name=? toggle=?&lt;br /&gt;
&lt;br /&gt;
==thumbnail-downloader==&lt;br /&gt;
:style=thumbnail-downloader asset=? index=? thumb-size=? crop=?&lt;br /&gt;
&lt;br /&gt;
==button==&lt;br /&gt;
A Button is essentially 8 [[#IMG |image]]s; where only 1 is shown at a time determined by the button&#039;s on or off-ness and the user&#039;s cursor location.&lt;br /&gt;
&lt;br /&gt;
Buttons can be set either &#039;off&#039; or &#039;on&#039; by calling SetElementProperty(&amp;quot;button name&amp;quot;, &amp;quot;value&amp;quot;, &amp;quot;1&amp;quot;) [for on or &amp;quot;0&amp;quot; for off] on the [[class Browser |browser]] that contains the button. All buttons start in the off state.&lt;br /&gt;
&lt;br /&gt;
Both &#039;on&#039; and &#039;off&#039; states have 4 states within them for showing interaction with the cursor. Off is explained below, on is the same replacing &amp;quot;off&amp;quot; with &amp;quot;on&amp;quot;;&lt;br /&gt;
* &amp;quot;off&amp;quot; - button is in the off state and has no cursor interaction.&lt;br /&gt;
* &amp;quot;off-over&amp;quot; - button is in the off state and the cursor is hovering over the button.&lt;br /&gt;
* &amp;quot;off-down&amp;quot; - button is in the off state and the cursor has been clicked on the button, is held down (mouse button 1 is down) but the cursor is not (is no longer) hovering over the button meaning the user has dragged the cursor off the button after clicking it.&lt;br /&gt;
* &amp;quot;off-down-over&amp;quot; - button is in the off state and the cursor is hovering over the button and the cursor has been clicked on it and is being held down (mouse button 1 is down).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The size of a button is determined by the width and height parameters of its containing [[#TRAINZ-OBJECT |TRAINZ-OBJECT]] tag.&lt;br /&gt;
&lt;br /&gt;
Typically a button trainz-object will be contained within an &amp;amp;lt;[[#A |A]]&amp;gt; tag giving the appearance that buttons send messages. As buttons do not send clicked messages themselves, they do not directly know when they have been clicked on or off, this must be done manually by listening to the message that will be sent by the anchor tag and changing the buttons state using the SetElementProperty(&amp;quot;button name&amp;quot;, &amp;quot;value&amp;quot;, &amp;quot;1&amp;quot;) command on its containing browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
? represent image files within the asset.&lt;br /&gt;
:style=button id=&amp;amp;lt;button name&amp;gt; off=? off-over=? off-down=? off-down-over=? on=? on-over=? on-down=? on-down-over=? link-held=?&lt;br /&gt;
&lt;br /&gt;
==minimap==&lt;br /&gt;
:style=minimap&lt;br /&gt;
&lt;br /&gt;
==preview==&lt;br /&gt;
An asset preview as used in the Surveyor tabs.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;asset&amp;quot; - the kuid of the asset to be shown (pass KUID by KUID::GetHTMLString())&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
:style=preview asset=&amp;lt;asset-kuid&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==text-line==&lt;br /&gt;
:style=text-line background=? align=?&lt;br /&gt;
&lt;br /&gt;
==asset-picker==&lt;br /&gt;
:style=asset-picker background=? align=?&lt;br /&gt;
&lt;br /&gt;
==driver-order-bar==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Incorrect&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Is a very specific case. As the name implies it is the list of driver commands that appears at the bottom of the screen next to the current driver image in Driver. This is already created and managed for you, users probably don&#039;t want to make these in any useful way, just to mess around or break things.&lt;br /&gt;
&lt;br /&gt;
:style=driver-order-bar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;this isn&#039;t really accurate. i think you&#039;ll find this is already used elsewhere in the game (for example, in the driver command rule?) and in fact possibly isn&#039;t used by the main driver interface - it&#039;s likely that is not HTML although it&#039;s the same underlying control. this is a general-purpose control: the functionality is specific to assigning orders, but it should be fairly flexible what the calling script does with the orders.&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==clock==&lt;br /&gt;
:style=clock face-texture=? seconds-texture=? minutes-texture=? hours-texture=? seconds-visible=? minutes-visible=? hours-visible=? seconds=? minutes=? hours=?&lt;br /&gt;
&lt;br /&gt;
==slider==&lt;br /&gt;
Slider is a horizontal bar similar to a horizontal scroll bar with a linear range of values mapped to it, similar to the [[#dial |dial]]. &lt;br /&gt;
&lt;br /&gt;
There are several in the video settings menu/asset and those will be used as an example here. The most important attributes are;&lt;br /&gt;
*min the minimum value the slider represents (far left).&lt;br /&gt;
*max the maximum value the slider represents (far right).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:style=slider min=? max=? page-size=? draw-lines=? draw-marks=? thumb=? thumb-over=? less=? less-over=? more=? more-over=? thumb-width=? thumb-height=? theme=? background=? arrow-width=? arrow-height=?&lt;br /&gt;
&lt;br /&gt;
==browser==&lt;br /&gt;
[[class Browser |browser]] is updated through call to SetElementProperty(&amp;quot;component-name&amp;quot;,&amp;quot;html&amp;quot;,sub-browser html  string) from the parent browser level. An example of this at work can be found in the waybillmanager.gs&lt;br /&gt;
&lt;br /&gt;
:style=browser id=&#039;component-name&#039; width=? height=? clip=?&lt;br /&gt;
&lt;br /&gt;
==edit-box==&lt;br /&gt;
The edit box allows a text entry field such as that provided on the Routes Menu search field or the iTrainz Chat windows.&lt;br /&gt;
&lt;br /&gt;
:style=edit-box multi-line read-only masked link-on-focus-loss&lt;br /&gt;
&lt;br /&gt;
==static-line==&lt;br /&gt;
A divider line graphic.&lt;br /&gt;
&lt;br /&gt;
:style=static-line color=?&lt;br /&gt;
&lt;br /&gt;
==progress==&lt;br /&gt;
A progress bar.&lt;br /&gt;
&lt;br /&gt;
:style=progress progress=?&lt;br /&gt;
&lt;br /&gt;
==keyinput==&lt;br /&gt;
&lt;br /&gt;
:style=keyinput context=? id=?&lt;br /&gt;
&lt;br /&gt;
==score-gauge==&lt;br /&gt;
:style=score-gauge star-thresholds=? points=? high-score=?&lt;br /&gt;
&lt;br /&gt;
==date-picker==&lt;br /&gt;
:style=date-picker day=? month=? year=?&lt;br /&gt;
&lt;br /&gt;
==video==&lt;br /&gt;
&amp;lt;font color=red&amp;gt;Seems to be removed in TRS19?&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
This control plays back a video. Some platforms do not support this control; support can be tested through the &#039;PR_VideoPlayback&#039; product right. Video format support depends on the client system.&lt;br /&gt;
&lt;br /&gt;
*The play-on-load tag should be either &#039;1&#039; or &#039;0&#039; being yes or no respectively and it means exactly what it sounds like, should the video start playing once it has loaded.&lt;br /&gt;
*The is-video-looping is likewise a &#039;1&#039; or &#039;0&#039; value indicating the video should or shouldn&#039;t repeat once finished.&lt;br /&gt;
&lt;br /&gt;
:style=video play-on-load=? video-filename=? is-video-looping=?&lt;br /&gt;
&lt;br /&gt;
==internet-browser==&lt;br /&gt;
&amp;lt;font color=red&amp;gt;Seems to be removed in TRS19?&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
The internet browser is a native (eg. mozilla, safari, etc.) web browser which can be used to display information from this wiki. Some platforms do not support this control; support can be tested through the &#039;PR_WebBrowser&#039; product right. For platforms that do support this control, the exact feature set may vary.&lt;br /&gt;
&lt;br /&gt;
:style=internet-browser address=?&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=File:MpbrmetalExportBlender2.8beyond.png&amp;diff=40055</id>
		<title>File:MpbrmetalExportBlender2.8beyond.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=File:MpbrmetalExportBlender2.8beyond.png&amp;diff=40055"/>
		<updated>2024-02-18T01:51:51Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: Dundun92 uploaded a new version of &amp;amp;quot;File:MpbrmetalExportBlender2.8beyond.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The proper shader configuration for m.pbrmetal textures in Blender (2.8+)&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=39775</id>
		<title>Class Str</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=39775"/>
		<updated>2024-01-30T23:24:57Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Find */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Language Reference|API Hierarchy]]&lt;br /&gt;
**Str&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Str is a static class providing string utility functions not supported by the native string object. &lt;br /&gt;
*When used in game code these methods must be prefixed &#039;&#039;Str.&#039;&#039; to reference the class.&lt;br /&gt;
*Some of these methods directly amend their parameters rather than returning values via the method.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left==&lt;br /&gt;
{{MethodHeader|public void Left(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = count of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Left(s,5);        // s will now be equal to &amp;quot;After&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself consisting of its first &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mid==&lt;br /&gt;
{{MethodHeader|public void Mid(string s, int first, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;first&#039;&#039;&#039; = index of first character to retain.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Mid(s,3,4);           // s will now be equal to &amp;quot;tern&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself &#039;&#039;count&#039;&#039; characters long starting with the &#039;&#039;first&#039;&#039; character.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;I&amp;gt;To get the output specified you would need the following: Str.Mid(s,2,4); as the string array is zero based. This has been tested using TS2012 build 61388 and TANE. &amp;lt;/I&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Right==&lt;br /&gt;
{{MethodHeader|public void Right(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Right(s,4);           // s will now be equal to &amp;quot;noon&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself composed of the last &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
{{MethodHeader|Find(string s, string substr, int startingIndex)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string in which to search&lt;br /&gt;
*&#039;&#039;&#039;substr&#039;&#039;&#039; - substring to find&lt;br /&gt;
*&#039;&#039;&#039;startingIndex&#039;&#039;&#039; - where to start looking down the string i.e. skip the first &#039;n&#039; characters&lt;br /&gt;
;Returned Value&lt;br /&gt;
*index within string that substr starts at. &#039;-1&#039; if not found.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int i = Str.Find(&amp;quot;amazon&amp;quot;, &amp;quot;z&amp;quot;, 0) //returns 3&lt;br /&gt;
;Notes&lt;br /&gt;
*Searches for a substring within a string.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToInt==&lt;br /&gt;
{{MethodHeader|public native int ToInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of an integer.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Integer value of string parameter.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.ToInt(&amp;quot;1234&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to an integer.&lt;br /&gt;
*Method returns 0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToFloat==&lt;br /&gt;
{{MethodHeader|public native float ToFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of a floating point number.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Floating point value.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float length = Str.ToFloat(&amp;quot;1.5&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to a floating point number.&lt;br /&gt;
*Method returns 0.0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tokens==&lt;br /&gt;
{{MethodHeader|public native string[ ] Tokens(string s, string delimiters)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;delimiters&#039;&#039;&#039; = string of characters to use as token boundaries.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Array of string tokens.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string[] sentence = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;);     // sentence contains an array of four strings:&lt;br /&gt;
                                                            // [&amp;quot;Once&amp;quot;,&amp;quot;upon&amp;quot;,&amp;quot;a&amp;quot;,&amp;quot;time&amp;quot;].&lt;br /&gt;
 int wordCount = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;).size();  // returns 4&lt;br /&gt;
 string firstWord = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;)[0];   // returns &amp;quot;Once&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 string kuidStr = &amp;quot;&amp;lt;kuid:1234:5678&amp;gt;&amp;quot;&lt;br /&gt;
 string userID = Str.Tokens(kuidStr,&amp;quot;&amp;lt;:&amp;gt;&amp;quot;)[1];              // returns &amp;quot;1234&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Splits a string into an array of tokens using any of the characters in &#039;&#039;delimiters&#039;&#039; as token boundaries.&lt;br /&gt;
*Characters contained within the &#039;&#039;delimiters&#039;&#039; string are never returned.&lt;br /&gt;
*If &#039;&#039;delimiters&#039;&#039; is null or an empty string then white space will be assumed to define the token boundaries.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToLower==&lt;br /&gt;
{{MethodHeader|public native void ToLower(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToLower(&amp;quot;UPPER CASE STRING&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to lower case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToUpper==&lt;br /&gt;
{{MethodHeader|public native void ToUpper(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToUpper(&amp;quot;lower case string&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to upper case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimLeft==&lt;br /&gt;
{{MethodHeader|public native void TrimLeft(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimLeft(&amp;quot;Once upon a time&amp;quot;,&amp;quot;Once &amp;quot;);      // returns &amp;quot;upon a time&amp;quot;&lt;br /&gt;
 Str.TrimLeft(&amp;quot;      result&amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the front of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimRight==&lt;br /&gt;
{{MethodHeader|public native void TrimRight(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimRight(&amp;quot;Once upon a time&amp;quot;,&amp;quot; a time&amp;quot;);      // returns &amp;quot;Once upon&amp;quot;&lt;br /&gt;
 Str.TrimRight(&amp;quot;result        &amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the end of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackInt==&lt;br /&gt;
{{MethodHeader|public native int UnpackInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First integer value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.UnpackInt(&amp;quot;21st May 2008&amp;quot;);           // returns 21 and amends &#039;&#039;s&#039;&#039; to &amp;quot;st May 2008&amp;quot; &lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first integer value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackFloat==&lt;br /&gt;
{{MethodHeader|public native float UnpackFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First float value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float distance = Str.UnpackFloat(&amp;quot;21.5 miles&amp;quot;);   // returns 21.5 and amends &#039;&#039;s&#039;&#039; to &amp;quot; miles&amp;quot;.&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first floating point value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackString==&lt;br /&gt;
{{MethodHeader|public native string UnpackString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First string in &#039;&#039;s&#039;&#039;, excluding any leading white space.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Once upon a time&amp;quot;;&lt;br /&gt;
 string firstWord = UnpackString(s);     // returns &amp;quot;Once&amp;quot;, s becomes &amp;quot; upon a time&amp;quot;&lt;br /&gt;
 string secondWord = UnpackString(s);    // returns &amp;quot;upon&amp;quot;, s becomes &amp;quot; a time&amp;quot;&lt;br /&gt;
 string thirdWord = UnpackString(s);     // returns &amp;quot;a&amp;quot;,    s becomes &amp;quot; time&amp;quot;&lt;br /&gt;
 string fourthWord = UnpackString(s);    // returns &amp;quot;time&amp;quot;, s becomes &amp;quot;&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first word from the string parameter (using white space for word separation) and returns it in the method result. &lt;br /&gt;
*Any leading white space is removed from the string before parsing.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==CloneString==&lt;br /&gt;
{{MethodHeader|public string CloneString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = The string to clone.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*string - A new string in the current gamescript context which has contents that exactly match the original string.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string original=&amp;quot;Hello World!&amp;quot;&lt;br /&gt;
 string copy;&lt;br /&gt;
 copy=Str.CloneString(original);&lt;br /&gt;
;Notes&lt;br /&gt;
*CloneString() creates a copy of the string passed. &lt;br /&gt;
*Ordinarily &#039;copying&#039; a string will just create a new object that references the old string. This is not allowed across different contexts.&lt;br /&gt;
*CloneString() creates a new string for use in the current context.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#AlreadyThereStr|TrainUtil.AlreadyThereStr()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#CompareStrLists|TrainUtil.CompareStrLists()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#GetUpTo|TrainUtil.GetUpTo()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasPrefix|TrainUtil.HasPrefix()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasSufix|TrainUtil.HasSufix()]] &#039;&#039;(sic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#StrSubst|TrainUtil.StrSubst()]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=39587</id>
		<title>HowTo/Use the WagonX Library</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=39587"/>
		<updated>2024-01-07T04:29:46Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--the next line is the page title--&amp;gt;&lt;br /&gt;
&amp;lt;!--HowTo/Use the WagonX Library--&amp;gt;&lt;br /&gt;
= Document Structure =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
The WagonX Tutorial set is written over several TrainzWiKi pages.  This page is an introduction to WagonX and its capabilties.  Other pages in the series are:&lt;br /&gt;
&amp;lt;/table&amp;gt; &lt;br /&gt;
# [[HowTo/WagonX - Technical Reference]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Traincar Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Locomotive Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
== A discussion about &amp;quot;properties&amp;quot; ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;So what is a &amp;quot;property&amp;quot; and what is its purpose in Trainz?&lt;br /&gt;
A Google search will reveal that a property in this context is a value or attribute of an object. In Trainz we generally call such objects &amp;lt;b&amp;gt;assets&amp;lt;/b&amp;gt;. An example might be a traincar (wagon/car/carriage) and that traincar has some standard properties such as weight, cargo or passengers.&lt;br /&gt;
&lt;br /&gt;
But the standard properties are rather limited and, if a content creator wanted to add extra properties such as texture replacement, then a Trainz script is required.  Creating such scripts is not easy even for experienced programmers. Maintaining scripts can create a huge amount of work if common scripts are replicated across many assets.&lt;br /&gt;
&lt;br /&gt;
This is where WagonX can help.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== WagonX and Properties ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;WagonX is a universal script library that simplifies adding properties and scripted features to your traincar assets.&lt;br /&gt;
You can create an asset with all the perks of scripted assets without touching any TrainzScript (GS) files, or having much knowledge of trainzscript. You can set up a number of asset options, as identified in the following list, in the config.txt file.  All the details are then automatically presented to the user in the View Details (property browser) dialog, making it easy to edit as needed.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== The WagonX Asset ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
*The &#039;&#039;&#039;JBV WagonX Script Library - &amp;lt;kuid:661805:500008&amp;gt;&#039;&#039;&#039; is available on the Download Station.&lt;br /&gt;
*It is suitable for asset with Trainz Builds 5.0 or higher.  The library uses script functions only available from that version.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;	&lt;br /&gt;
&amp;lt;table width=1200 bgcolor=#000000 cellpadding=1&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;table width=1196 bgcolor=#ffffff cellpadding=2&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;The &#039;&#039;&#039;The WagonX Library&#039;&#039;&#039; can be used to set:-&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;animations&#039;&#039;&#039; - stop or start&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;texture replacements&#039;&#039;&#039; - loaded from a textures library asset&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;head codes&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;lamps&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;ACS controlled couplers and hoses&#039;&#039;&#039; - loaded from a suitable couplers/hoses mesh library&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;sounds&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;PFX effects&#039;&#039;&#039; - such as smoke or dust&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;triggered effects&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;consist synchronisation&#039;&#039;&#039; - such as texture swapping for vehicles also using WagonX in a consist&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;...and much more.&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;&lt;br /&gt;
	This picture demonstrates entries in the config and the result in the Properties Browser in game.  The asset is the library author&#039;s Prestwin 1/277 EXP (&amp;lt;kuid2:661805:1:1&amp;gt;).&lt;br /&gt;
	&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table width=1500&amp;gt;&lt;br /&gt;
	&amp;lt;tr valign=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;td&amp;gt;&lt;br /&gt;
			[[File:WagonX Documentation2.jpg|left]]&lt;br /&gt;
		&amp;lt;/td&amp;gt; &lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
== Basic configuration for the config.txt and asset script ==&lt;br /&gt;
=== Background ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;&lt;br /&gt;
	The library implementation for WagonX is a bit different from other library assets (such as Bloodnoks ACS lib or superscript) and utilizes a new script referencing technique from David Pistelak’s scripted assets. The traincar’s config.txt does not directly reference the wagon.gs file. It instead must reference a (mostly) blank gs file that will hold the information for the WagonX gs file. In this case, this special file is named ref.gs and the class to used is eRef.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The asset script ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;You will need to create a Trainzscript file called &amp;quot;ref.gs&amp;quot; and include it with your asset files. &amp;lt;b&amp;gt;Do not add any other code to ref.gs as future updates to the WagonX library may break your asset.&amp;lt;/b&amp;gt; The content of ref.gs should be:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  include &amp;quot;WagonX.gs&amp;quot;&lt;br /&gt;
  class eRef isclass WagonX{};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Config.txt - first steps ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Let&#039;s start with the basic tags needed to make WagonX work.  You will need to include script and class tags, a script-include-table, and a kuid-table reference if you are using ACSLib to control couplers and coupled hoses. &amp;lt;b&amp;gt;The spelling and capitisation of the class name is important.&amp;lt;/b&amp;gt; &amp;lt;span style=&amp;quot;color: red; font-weight: 700;&amp;quot;&amp;gt;Do not reference an iteration of the kiud, only exactly as the one shown below, as this will prevent your asset from receiving updates and bug fixes for compatibility in future trainz versions.&amp;lt;/span&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The config entries should look like this:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--indent this bit so a block is created--&amp;gt;&lt;br /&gt;
  script-include-table&lt;br /&gt;
    {&lt;br /&gt;
      0    &amp;lt;kuid:661805:500008&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
  script     &amp;quot;ref.gs&amp;quot;&lt;br /&gt;
  class      &amp;quot;eRef&amp;quot; &lt;br /&gt;
  kuid-table&lt;br /&gt;
  {&lt;br /&gt;
    acslib     &amp;lt;kuid2:60850:89100&amp;gt;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;That&#039;s it for the initial referencing of the script into your asset. The rest of the information for the script library goes inside the extensions container, under a sub-container that must be named “wagon-x”, all of which will be explained in the next sections. The following is a general example of how an extensions container using ACS and WagonX might appear.  It may not be suitable for your application.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 extensions&lt;br /&gt;
 {&lt;br /&gt;
   max_permitted_speed-60850 &amp;quot;50mph&amp;quot;&lt;br /&gt;
   active-coupling-standard-60850&lt;br /&gt;
   {&lt;br /&gt;
     version-major                       &amp;quot;2&amp;quot;&lt;br /&gt;
     version-minor                       &amp;quot;0&amp;quot;&lt;br /&gt;
     brakes                              &amp;quot;vac&amp;quot;&lt;br /&gt;
     front&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
     back&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   wagon-x&lt;br /&gt;
   {&lt;br /&gt;
     acs&lt;br /&gt;
     {&lt;br /&gt;
       animated                            1&lt;br /&gt;
       use-jbv-animation                   1&lt;br /&gt;
       duration                            1.5&lt;br /&gt;
     }&lt;br /&gt;
     misc&lt;br /&gt;
     {&lt;br /&gt;
       begin-load-time                    15&lt;br /&gt;
       begin-unload-time                  5&lt;br /&gt;
       end-load-time                      1&lt;br /&gt;
       end-unload-time                    1&lt;br /&gt;
     }&lt;br /&gt;
     marker-lights&lt;br /&gt;
     {&lt;br /&gt;
       enabled                             1&lt;br /&gt;
       car-minimum-count                   1&lt;br /&gt;
       require-locomotive                  1&lt;br /&gt;
       front&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;null&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-front-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       back&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-white&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
     browser-properties&lt;br /&gt;
     {&lt;br /&gt;
       0&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        1&lt;br /&gt;
         name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_skin&amp;quot;&lt;br /&gt;
         description                &amp;quot;Sets the weathering type&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
         fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;null&amp;quot;&lt;br /&gt;
         effects                    &amp;quot;texture-albedo,texture-parameter&amp;quot;&lt;br /&gt;
         asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
         files-path                 &amp;quot;null&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;3,1;4,2;5&amp;quot;&lt;br /&gt;
         default-index              -1&lt;br /&gt;
         trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;Clean,Weathered,Dirty&amp;quot;&lt;br /&gt;
       }   &lt;br /&gt;
       1&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        0&lt;br /&gt;
         name                       &amp;quot;Handbrake State: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_handbrake&amp;quot;&lt;br /&gt;
         description                &amp;quot;Toggle the handbrake&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
         mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;handbrake-lever,braking-system&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;0,30;30&amp;quot;&lt;br /&gt;
         events                     &amp;quot;handbrake-release,handbrake-apply&amp;quot;&lt;br /&gt;
         duration                   3.2&lt;br /&gt;
         default-index              0&lt;br /&gt;
         trigger                    &amp;quot;both&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;release,apply&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Next Steps =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;This page has been a basic introduction to WagonX. Some basic tutorials to setup some WagonX properties can be found at the [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Basic Tutorials&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
You can find a locomotive tutorial at the [[HowTo/WagonX - Locomotive Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Locomotive Tutorial&amp;lt;/span&amp;gt;]] page and a traincar tutorial at the [[HowTo/WagonX - Traincar Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Traincar Tutorial&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
These tutorials are supported by a detailed WagonX reference at the [[HowTo/WagonX - Reference|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;WagonX Reference&amp;lt;/span&amp;gt;]] page.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
=Copyright Notice=&lt;br /&gt;
Much of the content on this page and child pages was derived from Dundun92&#039;s original Google Docs document.  Permission was granted to use that information here.&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--=Return to Index=&lt;br /&gt;
 &lt;br /&gt;
[[HowToGuides|&amp;lt;&amp;lt; How To Guides]]&lt;br /&gt;
[[Category:How-to guides]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Content creation]]&lt;br /&gt;
[[Category:WagonX]]--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=39586</id>
		<title>HowTo/Use the WagonX Library</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=HowTo/Use_the_WagonX_Library&amp;diff=39586"/>
		<updated>2024-01-07T04:29:08Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Config.txt - first steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--the next line is the page title--&amp;gt;&lt;br /&gt;
&amp;lt;!--HowTo/Use the WagonX Library--&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color: red; font-weight: 700; font-size: 30px;&amp;quot;&amp;gt;Draft Only&amp;lt;/span&amp;gt;&lt;br /&gt;
= Document Structure =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
The WagonX Tutorial set is written over several TrainzWiKi pages.  This page is an introduction to WagonX and its capabilties.  Other pages in the series are:&lt;br /&gt;
&amp;lt;/table&amp;gt; &lt;br /&gt;
# [[HowTo/WagonX - Technical Reference]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Traincar Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Locomotive Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
== A discussion about &amp;quot;properties&amp;quot; ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;So what is a &amp;quot;property&amp;quot; and what is its purpose in Trainz?&lt;br /&gt;
A Google search will reveal that a property in this context is a value or attribute of an object. In Trainz we generally call such objects &amp;lt;b&amp;gt;assets&amp;lt;/b&amp;gt;. An example might be a traincar (wagon/car/carriage) and that traincar has some standard properties such as weight, cargo or passengers.&lt;br /&gt;
&lt;br /&gt;
But the standard properties are rather limited and, if a content creator wanted to add extra properties such as texture replacement, then a Trainz script is required.  Creating such scripts is not easy even for experienced programmers. Maintaining scripts can create a huge amount of work if common scripts are replicated across many assets.&lt;br /&gt;
&lt;br /&gt;
This is where WagonX can help.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== WagonX and Properties ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;WagonX is a universal script library that simplifies adding properties and scripted features to your traincar assets.&lt;br /&gt;
You can create an asset with all the perks of scripted assets without touching any TrainzScript (GS) files, or having much knowledge of trainzscript. You can set up a number of asset options, as identified in the following list, in the config.txt file.  All the details are then automatically presented to the user in the View Details (property browser) dialog, making it easy to edit as needed.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== The WagonX Asset ==&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
*The &#039;&#039;&#039;JBV WagonX Script Library - &amp;lt;kuid:661805:500008&amp;gt;&#039;&#039;&#039; is available on the Download Station.&lt;br /&gt;
*It is suitable for asset with Trainz Builds 5.0 or higher.  The library uses script functions only available from that version.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;	&lt;br /&gt;
&amp;lt;table width=1200 bgcolor=#000000 cellpadding=1&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;table width=1196 bgcolor=#ffffff cellpadding=2&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;The &#039;&#039;&#039;The WagonX Library&#039;&#039;&#039; can be used to set:-&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;animations&#039;&#039;&#039; - stop or start&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;texture replacements&#039;&#039;&#039; - loaded from a textures library asset&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;head codes&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;lamps&#039;&#039;&#039; - for UK vehicles&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;ACS controlled couplers and hoses&#039;&#039;&#039; - loaded from a suitable couplers/hoses mesh library&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;sounds&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;PFX effects&#039;&#039;&#039; - such as smoke or dust&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;triggered effects&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;consist synchronisation&#039;&#039;&#039; - such as texture swapping for vehicles also using WagonX in a consist&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[image:DotPoint.JPG|10px|link=]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&#039;&#039;&#039;...and much more.&#039;&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;&lt;br /&gt;
	This picture demonstrates entries in the config and the result in the Properties Browser in game.  The asset is the library author&#039;s Prestwin 1/277 EXP (&amp;lt;kuid2:661805:1:1&amp;gt;).&lt;br /&gt;
	&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table width=1500&amp;gt;&lt;br /&gt;
	&amp;lt;tr valign=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;td&amp;gt;&lt;br /&gt;
			[[File:WagonX Documentation2.jpg|left]]&lt;br /&gt;
		&amp;lt;/td&amp;gt; &lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
== Basic configuration for the config.txt and asset script ==&lt;br /&gt;
=== Background ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;&lt;br /&gt;
	The library implementation for WagonX is a bit different from other library assets (such as Bloodnoks ACS lib or superscript) and utilizes a new script referencing technique from David Pistelak’s scripted assets. The traincar’s config.txt does not directly reference the wagon.gs file. It instead must reference a (mostly) blank gs file that will hold the information for the WagonX gs file. In this case, this special file is named ref.gs and the class to used is eRef.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The asset script ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;You will need to create a Trainzscript file called &amp;quot;ref.gs&amp;quot; and include it with your asset files. &amp;lt;b&amp;gt;Do not add any other code to ref.gs as future updates to the WagonX library may break your asset.&amp;lt;/b&amp;gt; The content of ref.gs should be:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  include &amp;quot;WagonX.gs&amp;quot;&lt;br /&gt;
  class eRef isclass WagonX{};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Config.txt - first steps ===&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Let&#039;s start with the basic tags needed to make WagonX work.  You will need to include script and class tags, a script-include-table, and a kuid-table reference if you are using ACSLib to control couplers and coupled hoses. &amp;lt;b&amp;gt;The spelling and capitisation of the class name is important.&amp;lt;/b&amp;gt; &amp;lt;span style=&amp;quot;color: red; font-weight: 700;&amp;quot;&amp;gt;Do not reference an iteration of the kiud, only exactly as the one shown below, as this will prevent your asset from receiving updates and bug fixes for compatibility in future trainz versions.&amp;lt;/span&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The config entries should look like this:&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--indent this bit so a block is created--&amp;gt;&lt;br /&gt;
  script-include-table&lt;br /&gt;
    {&lt;br /&gt;
      0    &amp;lt;kuid:661805:500008&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
  script     &amp;quot;ref.gs&amp;quot;&lt;br /&gt;
  class      &amp;quot;eRef&amp;quot; &lt;br /&gt;
  kuid-table&lt;br /&gt;
  {&lt;br /&gt;
    acslib     &amp;lt;kuid2:60850:89100&amp;gt;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
	&amp;lt;td&amp;gt;That&#039;s it for the initial referencing of the script into your asset. The rest of the information for the script library goes inside the extensions container, under a sub-container that must be named “wagon-x”, all of which will be explained in the next sections. The following is a general example of how an extensions container using ACS and WagonX might appear.  It may not be suitable for your application.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 extensions&lt;br /&gt;
 {&lt;br /&gt;
   max_permitted_speed-60850 &amp;quot;50mph&amp;quot;&lt;br /&gt;
   active-coupling-standard-60850&lt;br /&gt;
   {&lt;br /&gt;
     version-major                       &amp;quot;2&amp;quot;&lt;br /&gt;
     version-minor                       &amp;quot;0&amp;quot;&lt;br /&gt;
     brakes                              &amp;quot;vac&amp;quot;&lt;br /&gt;
     front&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
     back&lt;br /&gt;
     {&lt;br /&gt;
       coupler                           &amp;quot;instanter|hook&amp;quot;&lt;br /&gt;
       vacbrake                          &amp;quot;twin&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   wagon-x&lt;br /&gt;
   {&lt;br /&gt;
     acs&lt;br /&gt;
     {&lt;br /&gt;
       animated                            1&lt;br /&gt;
       use-jbv-animation                   1&lt;br /&gt;
       duration                            1.5&lt;br /&gt;
     }&lt;br /&gt;
     misc&lt;br /&gt;
     {&lt;br /&gt;
       begin-load-time                    15&lt;br /&gt;
       begin-unload-time                  5&lt;br /&gt;
       end-load-time                      1&lt;br /&gt;
       end-unload-time                    1&lt;br /&gt;
     }&lt;br /&gt;
     marker-lights&lt;br /&gt;
     {&lt;br /&gt;
       enabled                             1&lt;br /&gt;
       car-minimum-count                   1&lt;br /&gt;
       require-locomotive                  1&lt;br /&gt;
       front&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;null&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-front-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       back&lt;br /&gt;
       {&lt;br /&gt;
         head&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-white&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         tail&lt;br /&gt;
         {&lt;br /&gt;
           mesh                              &amp;quot;lamp-back-red&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
     browser-properties&lt;br /&gt;
     {&lt;br /&gt;
       0&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        1&lt;br /&gt;
         name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_skin&amp;quot;&lt;br /&gt;
         description                &amp;quot;Sets the weathering type&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
         fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;null&amp;quot;&lt;br /&gt;
         effects                    &amp;quot;texture-albedo,texture-parameter&amp;quot;&lt;br /&gt;
         asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
         files-path                 &amp;quot;null&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;3,1;4,2;5&amp;quot;&lt;br /&gt;
         default-index              -1&lt;br /&gt;
         trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;Clean,Weathered,Dirty&amp;quot;&lt;br /&gt;
       }   &lt;br /&gt;
       1&lt;br /&gt;
       {&lt;br /&gt;
         enabled                    1&lt;br /&gt;
         property-visibility        0&lt;br /&gt;
         name                       &amp;quot;Handbrake State: &amp;quot;&lt;br /&gt;
         property-id                &amp;quot;p_handbrake&amp;quot;&lt;br /&gt;
         description                &amp;quot;Toggle the handbrake&amp;quot;&lt;br /&gt;
         kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
         mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
         meshes                     &amp;quot;handbrake-lever,braking-system&amp;quot;&lt;br /&gt;
         values                     &amp;quot;0;0,30;30&amp;quot;&lt;br /&gt;
         events                     &amp;quot;handbrake-release,handbrake-apply&amp;quot;&lt;br /&gt;
         duration                   3.2&lt;br /&gt;
         default-index              0&lt;br /&gt;
         trigger                    &amp;quot;both&amp;quot;&lt;br /&gt;
         display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
         display-values             &amp;quot;release,apply&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Next Steps =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;This page has been a basic introduction to WagonX. Some basic tutorials to setup some WagonX properties can be found at the [[HowTo/WagonX - Browser Properties Examples and Basic Tutorials|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Basic Tutorials&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
You can find a locomotive tutorial at the [[HowTo/WagonX - Locomotive Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Locomotive Tutorial&amp;lt;/span&amp;gt;]] page and a traincar tutorial at the [[HowTo/WagonX - Traincar Tutorial|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;Traincar Tutorial&amp;lt;/span&amp;gt;]] page.&amp;lt;br&amp;gt;&lt;br /&gt;
These tutorials are supported by a detailed WagonX reference at the [[HowTo/WagonX - Reference|&amp;lt;span style=&amp;quot;color: #0080ff&amp;quot;&amp;gt;WagonX Reference&amp;lt;/span&amp;gt;]] page.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
=Copyright Notice=&lt;br /&gt;
Much of the content on this page and child pages was derived from Dundun92&#039;s original Google Docs document.  Permission was granted to use that information here.&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--=Return to Index=&lt;br /&gt;
 &lt;br /&gt;
[[HowToGuides|&amp;lt;&amp;lt; How To Guides]]&lt;br /&gt;
[[Category:How-to guides]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Content creation]]&lt;br /&gt;
[[Category:WagonX]]--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=39517</id>
		<title>ACS Coupling System</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=39517"/>
		<updated>2023-12-21T02:55:58Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* The Script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Introduction===&lt;br /&gt;
&lt;br /&gt;
There are many and varied problems with the existing BlueStar standard - but the main ones are the inflexibility beyond the initial application (coupling mineral wagons and transition era locos), and the rather arcane numeric values put into the config.txt.&lt;br /&gt;
&lt;br /&gt;
A more readable, more flexible, and preferrably easily extensible datastructure in the config.txt was needed, and some way of standardising the logic (at the very minimum, an include file, but preferrably a library). It needed to support many more different types of coupler, vehicles with different couplers on each end, and so on. &lt;br /&gt;
&lt;br /&gt;
The ACS System is an extension of the BlueStar coupling standard for TRS models (effectively BlueStar V2) and provides for the effect of working couplings on rolling stock. From version 5 of the ACSLib ACS vehicles are compatible with older BlueStar/CoupleStar ones. &lt;br /&gt;
&lt;br /&gt;
To add ACS couplings it is necessary to edit the asset config file, add attachment points to the mesh (see below for an alternative which can sometimes be used) and to create a script or edit the existing one. Due to the fact that you need access to the source files of the asset and to be able to script it is an advanced technique that cannot easily be carried out by an end-user.&lt;br /&gt;
&lt;br /&gt;
For couplers implemented as meshes in the mesh-table (usually but not always animated), position and orientation tags can be used to locate the attached meshes:&lt;br /&gt;
&lt;br /&gt;
*For front couplings the tag &#039;position 0,Y,0&#039; should be added.&lt;br /&gt;
*For back couplings two tags are needed, &#039;position 0,Y,0&#039; and orientation &#039;0,0,3.14159&#039;&lt;br /&gt;
*in both cases the value Y is 0.46 metres inboard of the Y value of limfront and limback respectively.&lt;br /&gt;
&lt;br /&gt;
===The Attachment Points===&lt;br /&gt;
&lt;br /&gt;
All of the coupler, hoses and cables are attached to two points, one on the face of the front buffer beam (a.couple0) and one on the face of the rear beam (a.couple1). a.limfront should be 0.46m forward of a.couple0 and a.limback 0.46m rearward of a.couple1. a.couple0 and a.couple1 must be at x=0 and z=0.&lt;br /&gt;
&lt;br /&gt;
Create a.couple0 in top view and move it into position. Then clone and position it to create a.couple1 and rotate it 180°. The Y axis of the two coupler points should point towards 0,0,0.&lt;br /&gt;
&lt;br /&gt;
[[File:Acs attachments.png|border|middle|x375px]]&lt;br /&gt;
&lt;br /&gt;
===The Config File===&lt;br /&gt;
First off, here is an example config.txt fragment: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  max_permitted_speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
  active-coupling-standard-60850 {&lt;br /&gt;
    version-major &amp;quot;2&amp;quot;&lt;br /&gt;
    version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
    brakes &amp;quot;air&amp;quot;&lt;br /&gt;
    front {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbraketype &amp;quot;single&amp;quot;&lt;br /&gt;
      airbrakeside &amp;quot;left&amp;quot; &lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    back {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbraketype &amp;quot;single&amp;quot;&lt;br /&gt;
      airbrakeside &amp;quot;left&amp;quot; &lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, what does all this do, and what are the options?&lt;br /&gt;
====Extension Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is for TRS2006 compatibility - it&#039;s all going in the extensions container. This does work in TRS2004 as well. Watch for the caveat at the end though...&lt;br /&gt;
&lt;br /&gt;
====Max Permitted Speed====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      Max_Permitted_Speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not strictly part of the coupling code, but may as well mention it. This is for the Max Permitted Speed rule to tell how fast this vehicle should be permitted to travel. It will tell both AI drivers and the human driver (via the Custom HUD rule) what the maximum permitted speed is for the train they are driving, based on information from each vehicle. (And in a future version of the rule, more stuff too...)&lt;br /&gt;
====ACS Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      active-coupling-standard-60850 {&lt;br /&gt;
        ...&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the container within which all the config information will be held.&lt;br /&gt;
&lt;br /&gt;
====ACS Version====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        version-major &amp;quot;2&amp;quot;&lt;br /&gt;
        version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Version numbers. This is useful when later code needs to read earlier format config files. Should make extending the standard a lot easier.&lt;br /&gt;
&lt;br /&gt;
====Braking System====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        brakes &amp;quot;air&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Defines what type of braking system is fitted to this vehicle. Options are:&lt;br /&gt;
*&amp;quot;air&amp;quot;&lt;br /&gt;
*&amp;quot;vac&amp;quot;&lt;br /&gt;
*&amp;quot;dual&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
This is independant of what hoses are available - unbraked but through piped stock is an entirely possible combination, and is representable.&lt;br /&gt;
&lt;br /&gt;
====Position====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        front {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
        back {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Containers for the front and back of the vehicle. &#039;Front&#039; is defined as &amp;quot;the a.limfront end&amp;quot;, and &#039;back&#039; &amp;quot;the a.limback end&amp;quot;. Available options for both are the same, so I&#039;ll describe them just once.&lt;br /&gt;
====Coupler Type====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What type of coupler do we have on this end of the vehicle? Options are:&lt;br /&gt;
* &amp;quot;hook&amp;quot; -- connects to screwlink/instanter/3link/hst-emergency-bar.&lt;br /&gt;
* &amp;quot;3link&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;instanter&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;screwlink&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;hst-emergency-bar&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;bar-full&amp;quot; -- connects to &amp;quot;bar-none&amp;quot;. Half of a handed pair for when one vehicle has the entire bar coupling.&lt;br /&gt;
* &amp;quot;bar-none&amp;quot; -- connected to by &amp;quot;bar-full&amp;quot;. The other half of the handed pair.&lt;br /&gt;
* &amp;quot;bar&amp;quot; -- connects to self only. Used when both vehicles have half the bar coupling.&lt;br /&gt;
* &amp;quot;knuckle&amp;quot; - standard knuckle coupler.&lt;br /&gt;
* &amp;quot;tightlock&amp;quot; -- different to a standard knuckle, refers to a knuckle style coupler often fitted to multiple unit trains that also include electrical connections.&lt;br /&gt;
* &amp;quot;wedgelock&amp;quot; -- London Underground coupler.&lt;br /&gt;
* &amp;quot;bsi&amp;quot; -- Found on Sprinter DMUs and derived designs.&lt;br /&gt;
* &amp;quot;dellner&amp;quot; -- Also compatible with scharfenberg coupling.&lt;br /&gt;
* &amp;quot;scharfenberg&amp;quot; -- Also compatible with dellner coupling.&lt;br /&gt;
* &amp;quot;(other string identifier)&amp;quot; -- Any string that is not recognised from the above list is assumed to be a symmetrical meet-in-the-middle type of coupler.&lt;br /&gt;
&lt;br /&gt;
Certain couplers are purely compatible with other identical couplers, others are inter-compatible. Some produce handed pairs - e.g. a 3 link chain couples to a hook, and wagons with this coupling are typically fitted with both a hook and a chain.&lt;br /&gt;
&lt;br /&gt;
Multiple coupler options can be specified, and are separated with a vertical bar character. The earlier option is used in preference, so list the best coupler option first.&lt;br /&gt;
&lt;br /&gt;
A typical unfitted freight wagon with a 3 link coupling is specified as &amp;quot;3link|hook&amp;quot;. A vehicle fitted with a knuckle, screwlink and hook (e.g. a swingknuckle fitted locomotive) is specified as &amp;quot;knuckle|screwlink|hook&amp;quot;. A BR coaching stock dropknuckle (a knuckle and a hook, but no chain) is specified as &amp;quot;knuckle|hook&amp;quot;. If the vehicle also has an emergency screwlink which is not permanently fitted, then &amp;quot;knuckle|hook|screwlink&amp;quot; would be appropriate -- this would cause ACS to prefer the chain type coupler from the adjacent vehicle rather than using the emergency screwlink, which would only be used when necessary. A Victorian Railways transitional coupler (which has a chain and a knuckle, but no hook) is specified as &amp;quot;knuckle|3link&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dellner and Scharfenberg couplings are treated as compatible, so a dellner will also couple to a scharfenberg.&lt;br /&gt;
&lt;br /&gt;
If your coupler type isn&#039;t listed, define a standard name for it, and start using it. ACS supports arbitrary extension - any new coupler it hasn&#039;t seen before will be treated as a symmetrical coupler. ACS will tell you if it has connected to an identical coupler on the adjacent vehicle.&lt;br /&gt;
&lt;br /&gt;
If you need a new handed pair type (where the coupler on the end of one wagon is not the same as that on the end of another), then you will need to contact the ACS author to get one added.&lt;br /&gt;
&lt;br /&gt;
====Gangways====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passenger gangway between vehicles. Options are:&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;rubbing-plate&amp;quot;&lt;br /&gt;
*&amp;quot;gangway&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This is really intended for coaching stock - it is assumed that all gangways are compatible. I&#039;ve been considering a &#039;one piece&#039; gangway option - to aid with the centre of multiple unit trains, where there is no separation point (it will help with deciding which vehicle should display the gangway) - but I&#039;m not sure whether this is of sufficient benefit to include, as it involves a whole new set of logic here that most people won&#039;t use, and for the cases it is interesting, the same person has made both vehicles, and can therefore do it themselves... Comments please.&lt;br /&gt;
====Pipes for Air Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          airbraketype                      &amp;quot;single&amp;quot;&lt;br /&gt;
          airbrakeside                      &amp;quot;left&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for air brakes. Options for airbraketype are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
Twin is the UK standard two pipe air brake system (train pipe and brake pipe). Single is the US standard air brake system where reservoirs are charged from the brake pipe rather than the train pipe (this has appeared on some modern freightcars for reasons unknown, so is included). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Options for airbrakeside are:&lt;br /&gt;
*&amp;quot;left&amp;quot;&lt;br /&gt;
*&amp;quot;right&amp;quot;&lt;br /&gt;
Most traincars (UK, US, etc.) use left-sided airbrakes, so airbrakeside &amp;quot;left&amp;quot; will generally be used, but the right option was added to support both left and right-handed brake pipes on Australian content.&lt;br /&gt;
&lt;br /&gt;
====Pipes for Vac Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for Vacuum brakes. Options are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;high&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single is the UK default for fitted stock, high connections seems to be the standard on UK steam locos. Twin pipes (operating at two different vacuum levels) has been tried in the UK - and while not much fitted stock has the twin pipe system, most air brake, through vac piped stock seems to have two vac pipes.&lt;br /&gt;
====Multiple Working Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Multiple working connections. Options are: &lt;br /&gt;
*&amp;quot;(color)-(shape)&amp;quot; -- e.g. &amp;quot;blue-star&amp;quot; or &amp;quot;red-diamond&amp;quot;, etc&lt;br /&gt;
*&amp;quot;AAR&amp;quot; -- as used on GM locos&lt;br /&gt;
*&amp;quot;SR27&amp;quot; -- bagpipes&lt;br /&gt;
*&amp;quot;(other identifier string e.g. classname)&amp;quot;&lt;br /&gt;
====Train Heating====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Coach heating. Options are: &lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;steam&amp;quot;&lt;br /&gt;
*&amp;quot;electric&amp;quot; -- standard ETH&lt;br /&gt;
*&amp;quot;dual&amp;quot; -- both Steam and standard ETH&lt;br /&gt;
*&amp;quot;southern-electric&amp;quot; -- The Southern, who pioneered electric train heating in the UK, fitted heating that was compatible with their DC powered EMUs, and thus ran from the same voltage as the DC power supply. When the rest of BR went ETH, different standards were adopted, resulting in the Southern having a different and incompatible ETH standard...&lt;br /&gt;
&lt;br /&gt;
====Lighting Control Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          rch &amp;quot;high&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Through wiring for lighting control, to the Railway Clearing House standard. Also used more recently for other things - e.g. remote control via various methods - including TDM. I believe it is also used for signals to control doorlocks on stock so fitted - though I could be wrong on this. Options are:&lt;br /&gt;
*&amp;quot;high&amp;quot; -- positioned as is fairly standard on coaching stock&lt;br /&gt;
*&amp;quot;low&amp;quot; -- positioned as is fairly standard on streamlined locos, e.g. the front of a DVT, or a cl90&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
====Notes====&lt;br /&gt;
For all of these where &amp;quot;none&amp;quot; is an option, entirely missing out that line is equivalent to stating &amp;quot;none&amp;quot;. This should make stock which doesn&#039;t use most of the features much more palatable to produce. This will also help when extending the standard - as new features will automatically be assumed to be not present on stock built to older standards...&lt;br /&gt;
&lt;br /&gt;
That&#039;s all very well and good, but how is this supposed to be backwards compatible with the old bluestar standard?&lt;br /&gt;
&lt;br /&gt;
I&#039;m making the code fall back to reading the old config entries if it can&#039;t find the new ones. The real problem is that new stock will also have to include config.txt entries for the old bluestar, so that old vehicles know what to do when they couple to this one. Yes, this means that the old tags will never actually go away, but at least TRS2006 doesn&#039;t whinge about them so hard as of SP1...&lt;br /&gt;
&lt;br /&gt;
===The Script===&lt;br /&gt;
&lt;br /&gt;
Basic ACS handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void ACShandler(Message msg)&lt;br /&gt;
  {&lt;br /&gt;
    if(msg.dst == me)&lt;br /&gt;
    {&lt;br /&gt;
      // tokenize msg.minor into (&#039;|&#039;) separate strings&lt;br /&gt;
      string[] callback = Str.Tokens(msg.minor, &amp;quot;|&amp;quot;);&lt;br /&gt;
      &lt;br /&gt;
      if (callback.size() &amp;gt;= 3)&lt;br /&gt;
      {&lt;br /&gt;
        if (callback[1] == &amp;quot;back&amp;quot;)&lt;br /&gt;
        {&lt;br /&gt;
          if(callback[0] == &amp;quot;coupler&amp;quot;)&lt;br /&gt;
          {&lt;br /&gt;
            if(callback[2] != &amp;quot;none&amp;quot;)&lt;br /&gt;
            {&lt;br /&gt;
              //backCoupled = true;&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
              //backCoupled = false;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (callback[1] == &amp;quot;front&amp;quot;)&lt;br /&gt;
        {&lt;br /&gt;
          if(callback[0] == &amp;quot;coupler&amp;quot;)&lt;br /&gt;
          {&lt;br /&gt;
            if(callback[2] != &amp;quot;none&amp;quot;)&lt;br /&gt;
            {&lt;br /&gt;
              //frontCoupled = true;&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
              //frontCoupled = false;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        TrainzScript.Log(&amp;quot;ERROR: ACS Library returned invalid callback \&amp;quot;&amp;quot; + msg.minor + &amp;quot;\&amp;quot; - not divisible into at least 3 parts!&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=HowTo/WagonX_-_Browser_Properties_Examples_and_Basic_Tutorials&amp;diff=38965</id>
		<title>HowTo/WagonX - Browser Properties Examples and Basic Tutorials</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=HowTo/WagonX_-_Browser_Properties_Examples_and_Basic_Tutorials&amp;diff=38965"/>
		<updated>2023-10-01T23:38:30Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Creating a basic mesh toggle */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--the next line is the page title--&amp;gt;&lt;br /&gt;
&amp;lt;!--HowTo/WagonX - Browser Properties Examples and Basic Tutorials--&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color: red; font-weight: 700; font-size: 15px;&amp;quot;&amp;gt;Please note:  Much of this page still needs some validation.  If you find issues then please contact PCAS1986 in the Trainz Forums or in the Trainz Discord Server.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Document Structure =&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
The WagonX Tutorial set is written over several pages.  This page contains some example WagonX config containers and basic guidance for setting up those containers.  Other pages in the series are listed below:&lt;br /&gt;
&amp;lt;/table&amp;gt; &lt;br /&gt;
# [[HowTo/Use the WagonX Library]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Technical Reference]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Locomotive Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [[HowTo/WagonX - Traincar Tutorial]]&amp;lt;br&amp;gt;&lt;br /&gt;
# [https://docs.google.com/document/d/1jd5nZNQJI_gKQp-X2GjNCBij9fZGAwgJy_BgBiXf3_8/edit#bookmark=id.kupvwsc34hnk| The asset author&#039;s documentation]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Browser property tutorials=&lt;br /&gt;
&amp;lt;!--start of Browser property example--&amp;gt;&lt;br /&gt;
This tutorial takes you each step of creating a simple mesh toggle example. It is for a handbrake mesh, including animation, that the user may want to show (make visible) or hide (make invisible).  We will add each property tag and explain its purpose.&lt;br /&gt;
It may be useful to have the [[HowTo/WagonX - Technical Reference|WagonX Technical Reference]] page open in a browser to examine details of the various tags.&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt; &lt;br /&gt;
==Creating a basic mesh toggle==&lt;br /&gt;
*Start with an empty browser-properties container like this:&lt;br /&gt;
    &lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Add an empty property container and name it &amp;quot;0&amp;quot;.  The names are not used but should be unique.  When we add more properties, you should name them “1”, “2”, “3”, etc.&lt;br /&gt;
   &lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*There is no order required for each property, but using a standard order makes it easier to follow. Each tag is hyperlinked to the browser-property, so you can see more information about it.&lt;br /&gt;
The first tag to add is [[HowTo/WagonX - Technical Reference#enabled|enabled]]. This determines whether or not the property is activated. Set it to 1, since we want our property to work in-game.&lt;br /&gt;
&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Set the visibility of the property using [[HowTo/WagonX - Technical Reference#property-visibility|property-visibility]] and make that 1.  Note this value is an integer and doesn&#039;t require quotes around it. A value of 1 makes the property visible in both Surveyor and Driver. See the reference for other available values.&lt;br /&gt;
&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Set the [[HowTo/WagonX - Technical Reference#name|name]] of our property. The name will appear before the [[HowTo/WagonX - Technical Reference#display-values|display-values]], which we will get to in a moment. You also will want to add a space at the end; otherwise, the property name and display-value will appear as one word.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Set the [[HowTo/WagonX - Technical Reference#property-id|property-id]], which can be anything as long as it is unique and doesn&#039;t contain [[HowTo/WagonX - Technical Reference#Restricted_Characters|restricted characters]]. Trainz will use this to identify this property.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_meshToggle&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Set the [[HowTo/WagonX - Technical Reference#description|description]]. This will appear as the tool-tip when you hover over a browser-property.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_meshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the mesh&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Set the property [[HowTo/WagonX - Technical Reference#kind|kind]]. Since we want a mesh-attachment kind, we must also specify the [[HowTo/WagonX - Technical Reference#mesh-attachment-type|mesh-attachment-type]] which for this application is mesh-toggle.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_meshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Now add a [[HowTo/WagonX - Technical Reference#meshes|meshes]] tag to specify what mesh we want to toggle. The mesh name must exist in the config mesh-table. We will use the script author&#039;s prestwins handbrake lever for this demo.&lt;br /&gt;
&lt;br /&gt;
Here is part of the config mesh-table:&lt;br /&gt;
 handbrake-lever&lt;br /&gt;
 {&lt;br /&gt;
  mesh                                &amp;quot;mesh/handbrake.lm&amp;quot;&lt;br /&gt;
  anim                                &amp;quot;mesh/handbrake_scene.kin&amp;quot;&lt;br /&gt;
  auto-create                         1&lt;br /&gt;
  att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrakeMeshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the handbrake mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Add the [[HowTo/WagonX - Technical Reference#values|values]] tag. This determines what the state of the object will be at each index. The values tag varies depending on the kind, but looking at the values tag page, we see that for kind mesh-toggle, we set it at 0 to hide the mesh, and 1 to show the mesh. Each index is comma separated, so we will set the first one at 1, and the seccond one at 0.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrakeMeshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the handbrake mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,0&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Add the [[HowTo/WagonX - Technical Reference#default-index|default-index]]. This is an integer value starting from 0 and which indicates the position in a list.  0 is the first in the list, 1 is the second, and so on.  &amp;lt;i&amp;gt;(The reasons for this are somewhat historical but also based on how computers find things in memory.)&amp;lt;/i&amp;gt;  If we set it to 1, it will start at the second comma-separated values tag which is &amp;quot;0&amp;quot;.  If we set it at -1, it will pick a random index within the size of the values tag.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrakeMeshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the handbrake mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,0&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Add the [[HowTo/WagonX - Technical Reference#trigger|trigger]] tag. We want our property to activate when a user presses a button on the properties page, so we will set it to &amp;lt;b&amp;gt;user&amp;lt;/b&amp;gt;. If we set it to &amp;lt;b&amp;gt;event&amp;lt;/b&amp;gt;, however, we could make it activate based on an event within the train or in the world, such as handbrake apply, or enabling it when it gets dark, and disabling it when its daytime again, but for now, we will leave it at user.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrakeMeshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the handbrake mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,0&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Specify the [[HowTo/WagonX - Technical Reference#display-type|display-type]]. Looking at the options, we see that &amp;lt;b&amp;gt;link&amp;lt;/b&amp;gt; is what we want.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrakeMeshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the handbrake mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,0&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
*Finally, the last tag we need is the display-values tag, which we talked about earlier. Since we have two states for our property (specified in the values tag), we will create two comma-separated values for each state. We will call the first “Enabled”, and the second “Hidden”, which corresponds with the numbers we set in the values tag.&lt;br /&gt;
 browser-properties&lt;br /&gt;
 {&lt;br /&gt;
  0&lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Toggle Mesh: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrakeMeshToggle&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggles the handbrake mesh&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,0&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;Enabled,Hidden&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
And that&#039;s it! Run the asset into trainz, and when you view the properties, you should see your property appear:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--Insert pic of View Details with suitable property shown--&amp;gt;&lt;br /&gt;
[[File:Toggle_handbrake_mesh_in_View_Details.jpg]]&lt;br /&gt;
 &lt;br /&gt;
And when you click on the underlined part of your property, the property should change to “Hidden”, as we specified, and the handbrake on the underframe should disappear.&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Handbrake_mesh_show_%26_hide.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Browser-Property Examples =&lt;br /&gt;
== User-Triggered Properties ==&lt;br /&gt;
Here are a number of examples for user triggering - i.e. in the View Details property browser. Detailed information on the property browser tags can be found on the [[HowTo/WagonX - Reference|WagonX Reference]] page.&lt;br /&gt;
&amp;lt;!--start of mesh toggle property example--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
===Mesh-toggle property===&lt;br /&gt;
This property allows you to show or hide a mesh that is in the config mesh-table.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
   enabled               1 &lt;br /&gt;
   property-visibility   1&lt;br /&gt;
   name                  &amp;quot;Toggle: &amp;quot;&lt;br /&gt;
   property-id           &amp;quot;p_toggle&amp;quot;&lt;br /&gt;
   description           &amp;quot;Hide or display the roof mesh&amp;quot;&lt;br /&gt;
   kind                  &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type  &amp;quot;mesh-toggle&amp;quot;&lt;br /&gt;
   meshes                &amp;quot;roof&amp;quot;&lt;br /&gt;
   values                &amp;quot;0,1&amp;quot;&lt;br /&gt;
   duration              3 &lt;br /&gt;
   default-index         0&lt;br /&gt;
   trigger               &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type          &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values        &amp;quot;Hidden,Visible&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--start of texture-replacement property example--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
===texture-replacement property===&lt;br /&gt;
This allows the choice of a texture from either local texture files (i.e. contained within the asset), or from a texture group asset, to retexture or reskin a mesh. You could use it for swapping between clean, dirty or weathered textures, logos and also entire liveries. &lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--start of texture replacement using local texture files example--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt; &lt;br /&gt;
====Texture replacement using local texture files====&lt;br /&gt;
&lt;br /&gt;
For fx-replacement-type texture-replacement-texture, the comma and/or semicolon-separated values are the names of the files (ideally without the path or extension) to be referenced at that index. The values tag will contain a list of texture(.txt) files including a folder name if used.  This is an example of three textures.&lt;br /&gt;
&lt;br /&gt;
 values     &amp;quot;images/congleton.texture,images/burntisland.texture,images/buxton.texture,images/none.texture&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
If you have the same path (and same extension) for all your files, you can greatly reduce the clutter by just specifying the path and extension once using the files-path tag.  See the files-path and values usage below.  Note that the display-values tag contains similar information but that is for the user to see.&lt;br /&gt;
&lt;br /&gt;
 0&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Workflow Text: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_workflow&amp;quot;&lt;br /&gt;
   description                &amp;quot;Sets the Workflow&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type        &amp;quot;texture-replacement-texture&amp;quot;&lt;br /&gt;
   consist-property-sync      1&lt;br /&gt;
   meshes                     &amp;quot;null&amp;quot;&lt;br /&gt;
   effects                    &amp;quot;texture-extra&amp;quot;&lt;br /&gt;
   asset                      &amp;quot;null&amp;quot;&lt;br /&gt;
   files-path                 &amp;quot;images/,.texture&amp;quot;&lt;br /&gt;
   values                     &amp;quot;congleton,burntisland,buxton,none&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;list&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;Congleton,Burntisland,Buxton,None&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--start of texture replacement using a texture-group example--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt; &lt;br /&gt;
====Texture replacement using a texture-group library asset====&lt;br /&gt;
You will need to specify the texture group asset in the kuid-table and give it a name such as &amp;quot;texturelib&amp;quot; or &amp;quot;gwrtexturelib&amp;quot;,  The name should not have any spaces or other special characters.&lt;br /&gt;
This property container is set up to allow for three different variations of the the material used for the asset.  They are named in the &amp;quot;display-values&amp;quot; tag as Skin 1, Skin 2, and Skin 3. &lt;br /&gt;
Since it is a PBR material there are three textures used in the materail: the albedo, parameters, and normal.  The normal texture is common to all three versions so it need not be changed.&lt;br /&gt;
The &amp;quot;values&amp;quot; tag contains six numbers which are the numbers of the textures in the texture-group asset.  For Skin 1 the &amp;quot;12&amp;quot; refers to the albedo texture, and the &amp;quot;15&amp;quot; refers to the parameter texture. &amp;quot;13&amp;quot; and &amp;quot;16&amp;quot; are the pair for Skin2, and &amp;quot;14&amp;quot; and &amp;quot;17&amp;quot; are the pair for Skin 3.&lt;br /&gt;
The &amp;quot;effects&amp;quot; tag contains the texture effect names for meshes in the mesh-table.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
   enabled             1&lt;br /&gt;
   property-visibility 1&lt;br /&gt;
   name                &amp;quot;Weathering: &amp;quot;&lt;br /&gt;
   property-id         &amp;quot;p_skin&amp;quot;&lt;br /&gt;
   description         &amp;quot;Sets the weathering type&amp;quot;&lt;br /&gt;
   kind                &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
   meshes              &amp;quot;null&amp;quot;&lt;br /&gt;
   effects             &amp;quot;texture-albedo,texture-parameter&amp;quot;&lt;br /&gt;
   asset               &amp;quot;texturelib&amp;quot;&lt;br /&gt;
   files-path          &amp;quot;null&amp;quot;&lt;br /&gt;
   values              &amp;quot;12;15,13;16,14;17&amp;quot;&lt;br /&gt;
   default-index       -1&lt;br /&gt;
   trigger             &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type        &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values      &amp;quot;Skin 1,Skin 2,Skin 3&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Event-Triggered Properties ==&lt;br /&gt;
&amp;lt;!--start of loading-doors property example--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
===loading-doorsProperty ===&lt;br /&gt;
The ‘meshes’ tag references a mesh-table asset named ‘loading-doors’, and sets the frame to 30 when begin-load is called (to open the doors), and 0 when end-load is called (to close the door). The default index is 0 (the animation frame will be at 0), and the animation duration is 1.5 seconds.&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    0&lt;br /&gt;
   property-visibility        0&lt;br /&gt;
   property-id                &amp;quot;p_doors&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;loading-doors&amp;quot;&lt;br /&gt;
   values                     &amp;quot;0,30&amp;quot;&lt;br /&gt;
   trigger                    &amp;quot;event&amp;quot;&lt;br /&gt;
   events                     &amp;quot;end-load,begin-load&amp;quot;&lt;br /&gt;
   duration                   1.5&lt;br /&gt;
   default-index              0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
An alternate way to do it is use mesh-attachment-type &amp;quot;mesh-animation-state&amp;quot;, and set a bool int (0 or 1) for the values tag.&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    0&lt;br /&gt;
   property-visibility        0&lt;br /&gt;
   property-id                &amp;quot;p_doors&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-animation-state&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;loading-doors&amp;quot;&lt;br /&gt;
   values                     &amp;quot;0,1&amp;quot;&lt;br /&gt;
   trigger                    &amp;quot;event&amp;quot;&lt;br /&gt;
   events                     &amp;quot;end-load,begin-load&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If you want two doors to open at the same time, instead of creating another property, you can use a semicolon split in the values tag to change two in a single property:&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        0&lt;br /&gt;
   name                       &amp;quot;Handbrake State: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrake&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggle the handbrake&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;door-1,door-2&amp;quot;&lt;br /&gt;
   values                     &amp;quot;0;0,30;30&amp;quot;&lt;br /&gt;
   events                     &amp;quot;handbrake-release,handbrake-apply&amp;quot;&lt;br /&gt;
   duration                   3.0&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;both&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;release,apply&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--start of Weather-Based property example--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt; &lt;br /&gt;
===Weather-Based Texture Replacement===&lt;br /&gt;
The texture effect will change based on the weather. It will display a snowy texture when the weather type is 6 (medium snow), a wet, rainy texture when the weather type is 3 (rain), and a dry texture when the weather type is 0.&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        0&lt;br /&gt;
   property-id                &amp;quot;p_weather_skin&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type        &amp;quot;texture-replacement-texture&amp;quot;&lt;br /&gt;
   effects                    &amp;quot;texture-weather&amp;quot;&lt;br /&gt;
   files-path                 &amp;quot;images/,.texture&amp;quot;&lt;br /&gt;
   values                     &amp;quot;texture-snow,texture-rain,texture-dry&amp;quot;&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;event&amp;quot;&lt;br /&gt;
   events                     &amp;quot;weather-6,weather-3,weather-0&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--start of discussion about use of semicolons--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt; &lt;br /&gt;
== Using semicolons to set multiple values in one property ==&lt;br /&gt;
When assigning values for a certain property, you will specify the mesh/effect/sound, etc that needs to be edited, and specify how you want to manipulate it (fx-replacement-type, mesh-attachment-type, etc), and set the value for a certain index. For example, In a texture replacement where a texture is being replaced by an external texture-group asset, the property would look something like this.&lt;br /&gt;
&lt;br /&gt;
 0&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_skin_parameter&amp;quot;&lt;br /&gt;
   description                &amp;quot;Sets The Texture&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
   effects                    &amp;quot;texture-albedo&amp;quot;&lt;br /&gt;
   asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,2,3,4&amp;quot;&lt;br /&gt;
   default-index              -1&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;Skin1,Skin2,Skin3,Skin&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, the comma-separated numbers in the “values” tag indicate the index in the texture-group asset to find the texture; here are the first few lines for that. Texture indexes 0, 1, 2, and 3 are referenced for the albedo texture types, since we have 4 weathering types.&lt;br /&gt;
&lt;br /&gt;
 kuid                                    &amp;lt;kuid2:661805:500009:0&amp;gt;&lt;br /&gt;
 username                                &amp;quot;BR GrainHop Texture Group&amp;quot;&lt;br /&gt;
 kind                                    &amp;quot;texture-group&amp;quot;&lt;br /&gt;
 trainz-build                            5.0&lt;br /&gt;
 category-class                          &amp;quot;JO&amp;quot;&lt;br /&gt;
 author                                  &amp;quot;dundun92&amp;quot;&lt;br /&gt;
 contact-email                           &amp;quot;jbvector93@outlook.com&amp;quot;&lt;br /&gt;
 description                             &amp;quot;A texture group for my GrainHop wagons&amp;quot;&lt;br /&gt;
 textures&lt;br /&gt;
 {&lt;br /&gt;
   0                                   &amp;quot;270cgo/0albedo.texture&amp;quot;&lt;br /&gt;
   1                                   &amp;quot;270cgo/1albedo.texture&amp;quot;&lt;br /&gt;
   2                                   &amp;quot;270cgo/2albedo.texture&amp;quot;&lt;br /&gt;
   3                                   &amp;quot;270cgo/2albedo.texture&amp;quot;&lt;br /&gt;
   4                                   &amp;quot;270cgo/0parameter.texture&amp;quot;&lt;br /&gt;
   5                                   &amp;quot;270cgo/1parameter.texture&amp;quot;&lt;br /&gt;
   6                                   &amp;quot;270cgo/2parameter.texture&amp;quot;&lt;br /&gt;
   .........&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We specified the texture-group library in the kuid table, and referenced it in the “asset” tag.&lt;br /&gt;
 kuid-table&lt;br /&gt;
 {&lt;br /&gt;
   acslib                                &amp;lt;kuid2:60850:89100&amp;gt;&lt;br /&gt;
   meshlib                               &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   texturelib                            &amp;lt;kuid2:661805:500009&amp;gt;&lt;br /&gt;
   lamp                                  &amp;lt;kuid2:661805:500003&amp;gt;&lt;br /&gt;
   enginespec                            &amp;lt;kuid2:368699:50064&amp;gt;&lt;br /&gt;
   bogie                                 &amp;lt;kuid2:661805:400003&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
And then we specified the effect we wanted to change, (currently just the texture-albedo), inside the “effects” tag (this is not the effects tag below in this mesh table asset, but rather the one in the browser-properties at the top of this section!).&lt;br /&gt;
 body&lt;br /&gt;
   {&lt;br /&gt;
     mesh                                &amp;quot;mesh/body.lm&amp;quot;&lt;br /&gt;
     auto-create                         1&lt;br /&gt;
     att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
     effects&lt;br /&gt;
     {&lt;br /&gt;
       texture-albedo&lt;br /&gt;
       {&lt;br /&gt;
         kind                                &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         texture                             &amp;quot;covhopp-1_albedo.texture&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
       texture-normal&lt;br /&gt;
       {&lt;br /&gt;
         kind                                &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         texture                             &amp;quot;covhopp-1_normal.texture&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
       texture-parameter&lt;br /&gt;
       {&lt;br /&gt;
         kind                                &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
         texture                             &amp;quot;covhopp-1_parameter.texture&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
But say you want to replace the normal map as well. You would probably just create another browser property and specify the proper index for the normals.&lt;br /&gt;
      &lt;br /&gt;
 0&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_skin_parameter&amp;quot;&lt;br /&gt;
   description                &amp;quot;Sets The Paramenter Texture&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
   effects                    &amp;quot;texture-albedo&amp;quot;&lt;br /&gt;
   asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
   values                     &amp;quot;1,2,3,4&amp;quot;&lt;br /&gt;
   default-index              -1&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;Skin1,Skin2,Skin3,Skin4&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 1&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_skin_normal&amp;quot;&lt;br /&gt;
   description                &amp;quot;Sets The Normal Texture&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
   effects                    &amp;quot;texture-normal&amp;quot;&lt;br /&gt;
   asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
   values                     &amp;quot;7,8,9,10&amp;quot;&lt;br /&gt;
   default-index              -1&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;Skin1,Skin2,Skin3,Skin4&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But we can&#039;t forget the parameter map… that will require a third property. What&#039;s worse, we will now have three different properties in the view details page that will each have to be clicked on to change each map! Assigning properties this way can get tedious and create extra clutter in the config. Thankfully, for properties that share the same kind and type, it can all be done in a single property using semicolons:&lt;br /&gt;
      &lt;br /&gt;
 0&lt;br /&gt;
 {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        1&lt;br /&gt;
   name                       &amp;quot;Skin: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_skin&amp;quot;&lt;br /&gt;
   description                &amp;quot;Sets the weathering type&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;fx-replacement&amp;quot;&lt;br /&gt;
   fx-replacement-type        &amp;quot;texture-replacement&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;null&amp;quot;&lt;br /&gt;
   &amp;lt;b&amp;gt;effects                    &amp;quot;texture-albedo,texture-parameter,texture-normal&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
   asset                      &amp;quot;texturelib&amp;quot;&lt;br /&gt;
   files-path                 &amp;quot;null&amp;quot;&lt;br /&gt;
   &amp;lt;b&amp;gt;values                     &amp;quot;0;4;8,1;5;9,2;6;10,3;7;11&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
   default-index              -1&lt;br /&gt;
   trigger                    &amp;quot;user&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   &amp;lt;b&amp;gt;display-values             &amp;quot;Clean,Weathered,Dirty,Rusty&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Take note of the three tag entries above: the &amp;lt;b&amp;gt;effects&amp;lt;/b&amp;gt;, &amp;lt;b&amp;gt;values&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;display-values&amp;lt;/b&amp;gt; tags. The &amp;lt;b&amp;gt;display-values&amp;lt;/b&amp;gt; tag is what the user sees and can choose from. Our interest is in the remaining two tags as shown below:&lt;br /&gt;
&lt;br /&gt;
 effects                    &amp;quot;texture-albedo,texture-parameter,texture-normal&amp;quot;&lt;br /&gt;
 values                     &amp;quot;0;4;8,1;5;9,2;6;9,3;7;11&amp;quot; &lt;br /&gt;
&lt;br /&gt;
There are four user options and, since each option requires three textures, the total number of textures is 12. The &amp;lt;b&amp;gt;values&amp;lt;/b&amp;gt; tag contains a string of four groups of texture numbers separated by a comma.  Within each texture group the texture numbers are delimited by a semi colon.&lt;br /&gt;
&lt;br /&gt;
To clarify, we can list the three textures associated with each user choice:&lt;br /&gt;
&lt;br /&gt;
 0;4;8 -&amp;gt; Clean&lt;br /&gt;
 1;5;9 -&amp;gt; Weathered&lt;br /&gt;
 2;6;10 -&amp;gt; Dirty&lt;br /&gt;
 3;7;11 -&amp;gt; Rusty&lt;br /&gt;
 &lt;br /&gt;
The first column of 0,1,2,3 identify the albedo textures. The second column of 4,5,6,7 identify the parameters textures, The third column of 8,9,10,11 identify the normal textures.  Note that the numbers do not need to be in sequence or even consecutive.  All those numbers do is to identify the correct texture in the texture-group asset.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
This system works for other kinds of properties, too. In this case, we are setting the animation frame of both the handbrake-lever, and braking system at the same time using the same property (triggered by the same event).&lt;br /&gt;
        		  &lt;br /&gt;
  1      &lt;br /&gt;
  {&lt;br /&gt;
   enabled                    1&lt;br /&gt;
   property-visibility        0&lt;br /&gt;
   name                       &amp;quot;Handbrake State: &amp;quot;&lt;br /&gt;
   property-id                &amp;quot;p_handbrake&amp;quot;&lt;br /&gt;
   description                &amp;quot;Toggle the handbrake&amp;quot;&lt;br /&gt;
   kind                       &amp;quot;mesh-attachment&amp;quot;&lt;br /&gt;
   mesh-attachment-type       &amp;quot;mesh-animation-frame&amp;quot;&lt;br /&gt;
   meshes                     &amp;quot;handbrake-lever,braking-system&amp;quot;&lt;br /&gt;
   values                     &amp;quot;0;0,30;30&amp;quot;&lt;br /&gt;
   events                     &amp;quot;handbrake-release,handbrake-apply&amp;quot;&lt;br /&gt;
   duration                   3.2&lt;br /&gt;
   default-index              0&lt;br /&gt;
   trigger                    &amp;quot;both&amp;quot;&lt;br /&gt;
   display-type               &amp;quot;link&amp;quot;&lt;br /&gt;
   display-values             &amp;quot;release,apply&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--start of discussion about Naming ACS mesh-table attachments--&amp;gt;&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt; &lt;br /&gt;
== Naming ACS mesh-table attachments ==&lt;br /&gt;
Please refer to this page on the ACS coupling system for setting up the “active-coupling-standard-60850” extensions container (which will be required for the ACS coupling to work): [[ACS_Coupling_System|ACS Coupling System]]&lt;br /&gt;
&lt;br /&gt;
These are the mesh-table naming conventions you must use for the beginning of the name of each ACS attachment mesh. The others will vary depending on the “animated” property above. &amp;lt;b&amp;gt;You must spell them exactly as shown below&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*coupler&lt;br /&gt;
*gangway&lt;br /&gt;
*airbrake&lt;br /&gt;
*vacbrake&lt;br /&gt;
*multiworking&lt;br /&gt;
*heating&lt;br /&gt;
*rch&lt;br /&gt;
&lt;br /&gt;
If the “animated” tag in the acs container (see [[HowTo/WagonX_-_Technical_Reference#ACS|acs]]) is set to 1, then the naming is quite simple. It&#039;s one of the 7 callbacks above + a dash + “&amp;lt;i&amp;gt;front&amp;lt;/i&amp;gt;” or “&amp;lt;i&amp;gt;back&amp;lt;/i&amp;gt;”. The anim tag must be present to specify the animation for it. Frame 0 is the uncoupled state, and the last frame is the coupled state. This setup is shown below:&lt;br /&gt;
&lt;br /&gt;
 coupler-front&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;coupler-screwlink-animated.lm&amp;quot;&lt;br /&gt;
   anim                                &amp;quot;coupler-screwlink-animated_scene.kin&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple0&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 coupler-back&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;coupler-screwlink-animated.lm&amp;quot;&lt;br /&gt;
   anim                                &amp;quot;coupler-screwlink-animated_scene.kin&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple1&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 vacbrake-front&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;vacbrake-single-animated.lm&amp;quot;&lt;br /&gt;
   anim                                &amp;quot;vacbrake-single-animated_scene.kin&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple0&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 vacbrake-back&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;vacbrake-single-animated.lm&amp;quot;&lt;br /&gt;
   anim                                &amp;quot;vacbrake-single-animated_scene.kin&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple1&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If, however, you do not want to use animations, but want to use separate meshes for each state (coupled and uncoupled), it gets a bit more complicated. The naming will follow the same as above at first, but you must add a third piece to it to specify the exact type of ACS attachment this is. The information on what to put there is originally from the [[ACS_Coupling_SystemACS Coupling System|ACS page]], but the 7 callbacks have been added plus the sub-callback here to make it easier (the third callback options are the ones with a delta symbol &amp;amp;Delta; ). And for the uncoupled state, the third callback is “non” (e.g. coupler-front-screwlink, and coupler-front-none).&lt;br /&gt;
&lt;br /&gt;
*coupler&lt;br /&gt;
:*front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;hook&amp;lt;/b&amp;gt;&amp;quot; -- connects to screwlink/instanter/3link/hst-emergency-bar.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;3link&amp;lt;/b&amp;gt;&amp;quot; -- connects to hook.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;instanter&amp;lt;/b&amp;gt;&amp;quot; -- connects to hook.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;screwlink&amp;lt;/b&amp;gt;&amp;quot; -- connects to hook.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;hst-emergency-bar&amp;lt;/b&amp;gt;&amp;quot; -- connects to hook.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;bar-full&amp;lt;/b&amp;gt;&amp;quot; -- connects to &amp;quot;bar-none&amp;quot;. Half of a handed pair for when one vehicle has the entire bar coupling.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;bar-none&amp;lt;/b&amp;gt;&amp;quot; -- connected to by &amp;quot;bar-full&amp;quot;. The other half of the handed pair.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;bar&amp;lt;/b&amp;gt;&amp;quot; -- connects to self only. Used when both vehicles have half the bar coupling.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;knuckle&amp;lt;/b&amp;gt;&amp;quot; - standard knuckle coupler.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;tightlock&amp;lt;/b&amp;gt;&amp;quot; -- different from a standard knuckle, refers to a knuckle style coupler often fitted to multiple unit trains that also include electrical connections.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;wedgelock&amp;lt;/b&amp;gt;&amp;quot; -- London Underground coupler.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;bsi&amp;lt;/b&amp;gt;&amp;quot; -- Found on Sprinter DMUs and derived designs.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;dellner&amp;lt;/b&amp;gt;&amp;quot; -- Also compatible with Scharfenberg coupling.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;scharfenberg&amp;lt;/b&amp;gt;&amp;quot; -- Also compatible with dellner coupling.&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;(&amp;lt;b&amp;gt;other string identifier&amp;lt;/b&amp;gt;)&amp;quot; -- Any string that is not recognized from the above list is assumed to be a symmetrical meet-in-the-middle type of coupler.&lt;br /&gt;
::&amp;amp;Delta; “&amp;lt;b&amp;gt;none&amp;lt;/b&amp;gt;”&lt;br /&gt;
::Examples: &amp;lt;b&amp;gt;coupler-front-instanter&amp;lt;/b&amp;gt;, coupler-back-none&lt;br /&gt;
&lt;br /&gt;
*gangway&lt;br /&gt;
:*front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;rubbing-plate&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;gangway&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;none&amp;lt;/b&amp;gt;&lt;br /&gt;
::Example: &amp;lt;b&amp;gt;gangway-front-gangway&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*airbrake&lt;br /&gt;
:*front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;twin&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;single&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;none&amp;lt;/b&amp;gt;&lt;br /&gt;
::Example: &amp;lt;b&amp;gt;airbrake-back-none&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*vacbrake&lt;br /&gt;
:*front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;twin&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;single&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;high&amp;lt;/b&amp;gt;&lt;br /&gt;
::&amp;amp;Delta; &amp;lt;b&amp;gt;none&amp;lt;/b&amp;gt;&lt;br /&gt;
::Example: &amp;lt;b&amp;gt;vacbrake-back-twin&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*multiworking&lt;br /&gt;
::front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;(color)-(shape)&amp;quot; -- e.g. &amp;quot;&amp;lt;b&amp;gt;blue-star&amp;lt;/b&amp;gt;&amp;quot; or &amp;quot;&amp;lt;b&amp;gt;red-diamond&amp;lt;/b&amp;gt;&amp;quot;, etc&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;AAR&amp;lt;/b&amp;gt;&amp;quot; -- as used on GM locos&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;SR27&amp;lt;/b&amp;gt;&amp;quot; -- bagpipes&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;(other identifier string e.g. classname)&amp;quot;&lt;br /&gt;
::Example: &amp;lt;b&amp;gt;multiworking-front-blue-square&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*heating&lt;br /&gt;
::front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;none&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;steam&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;electric&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;dual&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;southern-electric&amp;lt;/b&amp;gt;&amp;quot; &lt;br /&gt;
::Example: &amp;lt;b&amp;gt;heating-back-steam&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*rch&lt;br /&gt;
::front/back&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;high&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;low&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::&amp;amp;Delta; &amp;quot;&amp;lt;b&amp;gt;none&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
::Example: &amp;lt;b&amp;gt;rch-back-high&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And an example how it would look inside a config.txt. The back attachments have been omitted for brevity. &lt;br /&gt;
  &lt;br /&gt;
 coupler-front-screwlink&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;coupler-screwlink-coupled.lm&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple0&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 coupler-front-none&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;coupler-screwlink-retracted.lm&amp;quot;&lt;br /&gt;
       auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple0&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 vacbrake-front-single&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;vacbrake-single-coupled.lm&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple0&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 vacbrake-front-none&lt;br /&gt;
 {&lt;br /&gt;
   mesh-asset                          &amp;lt;kuid2:661805:500002&amp;gt;&lt;br /&gt;
   mesh                                &amp;quot;vacbrake-single-retracted.lm&amp;quot;&lt;br /&gt;
   auto-create                         1&lt;br /&gt;
   att                                 &amp;quot;a.couple0&amp;quot;&lt;br /&gt;
   att-parent                          &amp;quot;default&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table width=1200&amp;gt;&lt;br /&gt;
=Copyright Notice=&lt;br /&gt;
Much of the content on this page and child pages was derived from Dundun92&#039;s original Google Docs document.  Permission was granted to use that information here.&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=38424</id>
		<title>ACS Coupling System</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=38424"/>
		<updated>2023-08-19T20:27:49Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* The Config File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Introduction===&lt;br /&gt;
&lt;br /&gt;
There are many and varied problems with the existing BlueStar standard - but the main ones are the inflexibility beyond the initial application (coupling mineral wagons and transition era locos), and the rather arcane numeric values put into the config.txt.&lt;br /&gt;
&lt;br /&gt;
A more readable, more flexible, and preferrably easily extensible datastructure in the config.txt was needed, and some way of standardising the logic (at the very minimum, an include file, but preferrably a library). It needed to support many more different types of coupler, vehicles with different couplers on each end, and so on. &lt;br /&gt;
&lt;br /&gt;
The ACS System is an extension of the BlueStar coupling standard for TRS models (effectively BlueStar V2) and provides for the effect of working couplings on rolling stock. From version 5 of the ACSLib ACS vehicles are compatible with older BlueStar/CoupleStar ones. &lt;br /&gt;
&lt;br /&gt;
To add ACS couplings it is necessary to edit the asset config file, add attachment points to the mesh (see below for an alternative which can sometimes be used) and to create a script or edit the existing one. Due to the fact that you need access to the source files of the asset and to be able to script it is an advanced technique that cannot easily be carried out by an end-user.&lt;br /&gt;
&lt;br /&gt;
For couplers implemented as meshes in the mesh-table (usually but not always animated), position and orientation tags can be used to locate the attached meshes:&lt;br /&gt;
&lt;br /&gt;
*For front couplings the tag &#039;position 0,Y,0&#039; should be added.&lt;br /&gt;
*For back couplings two tags are needed, &#039;position 0,Y,0&#039; and orientation &#039;0,0,3.14159&#039;&lt;br /&gt;
*in both cases the value Y is 0.46 metres inboard of the Y value of limfront and limback respectively.&lt;br /&gt;
&lt;br /&gt;
===The Attachment Points===&lt;br /&gt;
&lt;br /&gt;
All of the coupler, hoses and cables are attached to two points, one on the face of the front buffer beam (a.couple0) and one on the face of the rear beam (a.couple1). a.limfront should be 0.46m forward of a.couple0 and a.limback 0.46m rearward of a.couple1. a.couple0 and a.couple1 must be at x=0 and z=0.&lt;br /&gt;
&lt;br /&gt;
Create a.couple0 in top view and move it into position. Then clone and position it to create a.couple1 and rotate it 180°. The Y axis of the two coupler points should point towards 0,0,0.&lt;br /&gt;
&lt;br /&gt;
[[File:Acs attachments.png|border|middle|x375px]]&lt;br /&gt;
&lt;br /&gt;
===The Config File===&lt;br /&gt;
First off, here is an example config.txt fragment: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  max_permitted_speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
  active-coupling-standard-60850 {&lt;br /&gt;
    version-major &amp;quot;2&amp;quot;&lt;br /&gt;
    version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
    brakes &amp;quot;air&amp;quot;&lt;br /&gt;
    front {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbraketype &amp;quot;single&amp;quot;&lt;br /&gt;
      airbrakeside &amp;quot;left&amp;quot; &lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    back {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbraketype &amp;quot;single&amp;quot;&lt;br /&gt;
      airbrakeside &amp;quot;left&amp;quot; &lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, what does all this do, and what are the options?&lt;br /&gt;
====Extension Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is for TRS2006 compatibility - it&#039;s all going in the extensions container. This does work in TRS2004 as well. Watch for the caveat at the end though...&lt;br /&gt;
&lt;br /&gt;
====Max Permitted Speed====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      Max_Permitted_Speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not strictly part of the coupling code, but may as well mention it. This is for the Max Permitted Speed rule to tell how fast this vehicle should be permitted to travel. It will tell both AI drivers and the human driver (via the Custom HUD rule) what the maximum permitted speed is for the train they are driving, based on information from each vehicle. (And in a future version of the rule, more stuff too...)&lt;br /&gt;
====ACS Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      active-coupling-standard-60850 {&lt;br /&gt;
        ...&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the container within which all the config information will be held.&lt;br /&gt;
&lt;br /&gt;
====ACS Version====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        version-major &amp;quot;2&amp;quot;&lt;br /&gt;
        version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Version numbers. This is useful when later code needs to read earlier format config files. Should make extending the standard a lot easier.&lt;br /&gt;
&lt;br /&gt;
====Braking System====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        brakes &amp;quot;air&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Defines what type of braking system is fitted to this vehicle. Options are:&lt;br /&gt;
*&amp;quot;air&amp;quot;&lt;br /&gt;
*&amp;quot;vac&amp;quot;&lt;br /&gt;
*&amp;quot;dual&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
This is independant of what hoses are available - unbraked but through piped stock is an entirely possible combination, and is representable.&lt;br /&gt;
&lt;br /&gt;
====Position====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        front {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
        back {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Containers for the front and back of the vehicle. &#039;Front&#039; is defined as &amp;quot;the a.limfront end&amp;quot;, and &#039;back&#039; &amp;quot;the a.limback end&amp;quot;. Available options for both are the same, so I&#039;ll describe them just once.&lt;br /&gt;
====Coupler Type====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What type of coupler do we have on this end of the vehicle? Options are:&lt;br /&gt;
* &amp;quot;hook&amp;quot; -- connects to screwlink/instanter/3link/hst-emergency-bar.&lt;br /&gt;
* &amp;quot;3link&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;instanter&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;screwlink&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;hst-emergency-bar&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;bar-full&amp;quot; -- connects to &amp;quot;bar-none&amp;quot;. Half of a handed pair for when one vehicle has the entire bar coupling.&lt;br /&gt;
* &amp;quot;bar-none&amp;quot; -- connected to by &amp;quot;bar-full&amp;quot;. The other half of the handed pair.&lt;br /&gt;
* &amp;quot;bar&amp;quot; -- connects to self only. Used when both vehicles have half the bar coupling.&lt;br /&gt;
* &amp;quot;knuckle&amp;quot; - standard knuckle coupler.&lt;br /&gt;
* &amp;quot;tightlock&amp;quot; -- different to a standard knuckle, refers to a knuckle style coupler often fitted to multiple unit trains that also include electrical connections.&lt;br /&gt;
* &amp;quot;wedgelock&amp;quot; -- London Underground coupler.&lt;br /&gt;
* &amp;quot;bsi&amp;quot; -- Found on Sprinter DMUs and derived designs.&lt;br /&gt;
* &amp;quot;dellner&amp;quot; -- Also compatible with scharfenberg coupling.&lt;br /&gt;
* &amp;quot;scharfenberg&amp;quot; -- Also compatible with dellner coupling.&lt;br /&gt;
* &amp;quot;(other string identifier)&amp;quot; -- Any string that is not recognised from the above list is assumed to be a symmetrical meet-in-the-middle type of coupler.&lt;br /&gt;
&lt;br /&gt;
Certain couplers are purely compatible with other identical couplers, others are inter-compatible. Some produce handed pairs - e.g. a 3 link chain couples to a hook, and wagons with this coupling are typically fitted with both a hook and a chain.&lt;br /&gt;
&lt;br /&gt;
Multiple coupler options can be specified, and are separated with a vertical bar character. The earlier option is used in preference, so list the best coupler option first.&lt;br /&gt;
&lt;br /&gt;
A typical unfitted freight wagon with a 3 link coupling is specified as &amp;quot;3link|hook&amp;quot;. A vehicle fitted with a knuckle, screwlink and hook (e.g. a swingknuckle fitted locomotive) is specified as &amp;quot;knuckle|screwlink|hook&amp;quot;. A BR coaching stock dropknuckle (a knuckle and a hook, but no chain) is specified as &amp;quot;knuckle|hook&amp;quot;. If the vehicle also has an emergency screwlink which is not permanently fitted, then &amp;quot;knuckle|hook|screwlink&amp;quot; would be appropriate -- this would cause ACS to prefer the chain type coupler from the adjacent vehicle rather than using the emergency screwlink, which would only be used when necessary. A Victorian Railways transitional coupler (which has a chain and a knuckle, but no hook) is specified as &amp;quot;knuckle|3link&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dellner and Scharfenberg couplings are treated as compatible, so a dellner will also couple to a scharfenberg.&lt;br /&gt;
&lt;br /&gt;
If your coupler type isn&#039;t listed, define a standard name for it, and start using it. ACS supports arbitrary extension - any new coupler it hasn&#039;t seen before will be treated as a symmetrical coupler. ACS will tell you if it has connected to an identical coupler on the adjacent vehicle.&lt;br /&gt;
&lt;br /&gt;
If you need a new handed pair type (where the coupler on the end of one wagon is not the same as that on the end of another), then you will need to contact the ACS author to get one added.&lt;br /&gt;
&lt;br /&gt;
====Gangways====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passenger gangway between vehicles. Options are:&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;rubbing-plate&amp;quot;&lt;br /&gt;
*&amp;quot;gangway&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This is really intended for coaching stock - it is assumed that all gangways are compatible. I&#039;ve been considering a &#039;one piece&#039; gangway option - to aid with the centre of multiple unit trains, where there is no separation point (it will help with deciding which vehicle should display the gangway) - but I&#039;m not sure whether this is of sufficient benefit to include, as it involves a whole new set of logic here that most people won&#039;t use, and for the cases it is interesting, the same person has made both vehicles, and can therefore do it themselves... Comments please.&lt;br /&gt;
====Pipes for Air Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          airbraketype                      &amp;quot;single&amp;quot;&lt;br /&gt;
          airbrakeside                      &amp;quot;left&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for air brakes. Options for airbraketype are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
Twin is the UK standard two pipe air brake system (train pipe and brake pipe). Single is the US standard air brake system where reservoirs are charged from the brake pipe rather than the train pipe (this has appeared on some modern freightcars for reasons unknown, so is included). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Options for airbrakeside are:&lt;br /&gt;
*&amp;quot;left&amp;quot;&lt;br /&gt;
*&amp;quot;right&amp;quot;&lt;br /&gt;
Most traincars (UK, US, etc.) use left-sided airbrakes, so airbrakeside &amp;quot;left&amp;quot; will generally be used, but the right option was added to support both left and right-handed brake pipes on Australian content.&lt;br /&gt;
&lt;br /&gt;
====Pipes for Vac Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for Vacuum brakes. Options are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;high&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single is the UK default for fitted stock, high connections seems to be the standard on UK steam locos. Twin pipes (operating at two different vacuum levels) has been tried in the UK - and while not much fitted stock has the twin pipe system, most air brake, through vac piped stock seems to have two vac pipes.&lt;br /&gt;
====Multiple Working Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Multiple working connections. Options are: &lt;br /&gt;
*&amp;quot;(color)-(shape)&amp;quot; -- e.g. &amp;quot;blue-star&amp;quot; or &amp;quot;red-diamond&amp;quot;, etc&lt;br /&gt;
*&amp;quot;AAR&amp;quot; -- as used on GM locos&lt;br /&gt;
*&amp;quot;SR27&amp;quot; -- bagpipes&lt;br /&gt;
*&amp;quot;(other identifier string e.g. classname)&amp;quot;&lt;br /&gt;
====Train Heating====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Coach heating. Options are: &lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;steam&amp;quot;&lt;br /&gt;
*&amp;quot;electric&amp;quot; -- standard ETH&lt;br /&gt;
*&amp;quot;dual&amp;quot; -- both Steam and standard ETH&lt;br /&gt;
*&amp;quot;southern-electric&amp;quot; -- The Southern, who pioneered electric train heating in the UK, fitted heating that was compatible with their DC powered EMUs, and thus ran from the same voltage as the DC power supply. When the rest of BR went ETH, different standards were adopted, resulting in the Southern having a different and incompatible ETH standard...&lt;br /&gt;
&lt;br /&gt;
====Lighting Control Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          rch &amp;quot;high&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Through wiring for lighting control, to the Railway Clearing House standard. Also used more recently for other things - e.g. remote control via various methods - including TDM. I believe it is also used for signals to control doorlocks on stock so fitted - though I could be wrong on this. Options are:&lt;br /&gt;
*&amp;quot;high&amp;quot; -- positioned as is fairly standard on coaching stock&lt;br /&gt;
*&amp;quot;low&amp;quot; -- positioned as is fairly standard on streamlined locos, e.g. the front of a DVT, or a cl90&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
====Notes====&lt;br /&gt;
For all of these where &amp;quot;none&amp;quot; is an option, entirely missing out that line is equivalent to stating &amp;quot;none&amp;quot;. This should make stock which doesn&#039;t use most of the features much more palatable to produce. This will also help when extending the standard - as new features will automatically be assumed to be not present on stock built to older standards...&lt;br /&gt;
&lt;br /&gt;
That&#039;s all very well and good, but how is this supposed to be backwards compatible with the old bluestar standard?&lt;br /&gt;
&lt;br /&gt;
I&#039;m making the code fall back to reading the old config entries if it can&#039;t find the new ones. The real problem is that new stock will also have to include config.txt entries for the old bluestar, so that old vehicles know what to do when they couple to this one. Yes, this means that the old tags will never actually go away, but at least TRS2006 doesn&#039;t whinge about them so hard as of SP1...&lt;br /&gt;
&lt;br /&gt;
===The Script===&lt;br /&gt;
&lt;br /&gt;
(under construction)&lt;br /&gt;
&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=37702</id>
		<title>ACS Coupling System</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=37702"/>
		<updated>2023-07-06T00:37:46Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Pipes for Air Brakes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Introduction===&lt;br /&gt;
&lt;br /&gt;
There are many and varied problems with the existing BlueStar standard - but the main ones are the inflexibility beyond the initial application (coupling mineral wagons and transition era locos), and the rather arcane numeric values put into the config.txt.&lt;br /&gt;
&lt;br /&gt;
A more readable, more flexible, and preferrably easily extensible datastructure in the config.txt was needed, and some way of standardising the logic (at the very minimum, an include file, but preferrably a library). It needed to support many more different types of coupler, vehicles with different couplers on each end, and so on. &lt;br /&gt;
&lt;br /&gt;
The ACS System is an extension of the BlueStar coupling standard for TRS models (effectively BlueStar V2) and provides for the effect of working couplings on rolling stock. From version 5 of the ACSLib ACS vehicles are compatible with older BlueStar/CoupleStar ones. &lt;br /&gt;
&lt;br /&gt;
To add ACS couplings it is necessary to edit the asset config file, add attachment points to the mesh (see below for an alternative which can sometimes be used) and to create a script or edit the existing one. Due to the fact that you need access to the source files of the asset and to be able to script it is an advanced technique that cannot easily be carried out by an end-user.&lt;br /&gt;
&lt;br /&gt;
For couplers implemented as meshes in the mesh-table (usually but not always animated), position and orientation tags can be used to locate the attached meshes:&lt;br /&gt;
&lt;br /&gt;
*For front couplings the tag &#039;position 0,Y,0&#039; should be added.&lt;br /&gt;
*For back couplings two tags are needed, &#039;position 0,Y,0&#039; and orientation &#039;0,0,3.14159&#039;&lt;br /&gt;
*in both cases the value Y is 0.46 metres inboard of the Y value of limfront and limback respectively.&lt;br /&gt;
&lt;br /&gt;
===The Attachment Points===&lt;br /&gt;
&lt;br /&gt;
All of the coupler, hoses and cables are attached to two points, one on the face of the front buffer beam (a.couple0) and one on the face of the rear beam (a.couple1). a.limfront should be 0.46m forward of a.couple0 and a.limback 0.46m rearward of a.couple1. a.couple0 and a.couple1 must be at x=0 and z=0.&lt;br /&gt;
&lt;br /&gt;
Create a.couple0 in top view and move it into position. Then clone and position it to create a.couple1 and rotate it 180°. The Y axis of the two coupler points should point towards 0,0,0.&lt;br /&gt;
&lt;br /&gt;
[[File:Acs attachments.png|border|middle|x375px]]&lt;br /&gt;
&lt;br /&gt;
===The Config File===&lt;br /&gt;
First off, here is an example config.txt fragment: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  max_permitted_speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
  active-coupling-standard-60850 {&lt;br /&gt;
    version-major &amp;quot;2&amp;quot;&lt;br /&gt;
    version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
    brakes &amp;quot;air&amp;quot;&lt;br /&gt;
    front {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbrake &amp;quot;twin&amp;quot;&lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    back {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbrake &amp;quot;twin&amp;quot;&lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, what does all this do, and what are the options?&lt;br /&gt;
====Extension Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is for TRS2006 compatibility - it&#039;s all going in the extensions container. This does work in TRS2004 as well. Watch for the caveat at the end though...&lt;br /&gt;
&lt;br /&gt;
====Max Permitted Speed====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      Max_Permitted_Speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not strictly part of the coupling code, but may as well mention it. This is for the Max Permitted Speed rule to tell how fast this vehicle should be permitted to travel. It will tell both AI drivers and the human driver (via the Custom HUD rule) what the maximum permitted speed is for the train they are driving, based on information from each vehicle. (And in a future version of the rule, more stuff too...)&lt;br /&gt;
====ACS Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      active-coupling-standard-60850 {&lt;br /&gt;
        ...&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the container within which all the config information will be held.&lt;br /&gt;
&lt;br /&gt;
====ACS Version====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        version-major &amp;quot;2&amp;quot;&lt;br /&gt;
        version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Version numbers. This is useful when later code needs to read earlier format config files. Should make extending the standard a lot easier.&lt;br /&gt;
&lt;br /&gt;
====Braking System====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        brakes &amp;quot;air&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Defines what type of braking system is fitted to this vehicle. Options are:&lt;br /&gt;
*&amp;quot;air&amp;quot;&lt;br /&gt;
*&amp;quot;vac&amp;quot;&lt;br /&gt;
*&amp;quot;dual&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
This is independant of what hoses are available - unbraked but through piped stock is an entirely possible combination, and is representable.&lt;br /&gt;
&lt;br /&gt;
====Position====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        front {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
        back {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Containers for the front and back of the vehicle. &#039;Front&#039; is defined as &amp;quot;the a.limfront end&amp;quot;, and &#039;back&#039; &amp;quot;the a.limback end&amp;quot;. Available options for both are the same, so I&#039;ll describe them just once.&lt;br /&gt;
====Coupler Type====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What type of coupler do we have on this end of the vehicle? Options are:&lt;br /&gt;
* &amp;quot;hook&amp;quot; -- connects to screwlink/instanter/3link/hst-emergency-bar.&lt;br /&gt;
* &amp;quot;3link&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;instanter&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;screwlink&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;hst-emergency-bar&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;bar-full&amp;quot; -- connects to &amp;quot;bar-none&amp;quot;. Half of a handed pair for when one vehicle has the entire bar coupling.&lt;br /&gt;
* &amp;quot;bar-none&amp;quot; -- connected to by &amp;quot;bar-full&amp;quot;. The other half of the handed pair.&lt;br /&gt;
* &amp;quot;bar&amp;quot; -- connects to self only. Used when both vehicles have half the bar coupling.&lt;br /&gt;
* &amp;quot;knuckle&amp;quot; - standard knuckle coupler.&lt;br /&gt;
* &amp;quot;tightlock&amp;quot; -- different to a standard knuckle, refers to a knuckle style coupler often fitted to multiple unit trains that also include electrical connections.&lt;br /&gt;
* &amp;quot;wedgelock&amp;quot; -- London Underground coupler.&lt;br /&gt;
* &amp;quot;bsi&amp;quot; -- Found on Sprinter DMUs and derived designs.&lt;br /&gt;
* &amp;quot;dellner&amp;quot; -- Also compatible with scharfenberg coupling.&lt;br /&gt;
* &amp;quot;scharfenberg&amp;quot; -- Also compatible with dellner coupling.&lt;br /&gt;
* &amp;quot;(other string identifier)&amp;quot; -- Any string that is not recognised from the above list is assumed to be a symmetrical meet-in-the-middle type of coupler.&lt;br /&gt;
&lt;br /&gt;
Certain couplers are purely compatible with other identical couplers, others are inter-compatible. Some produce handed pairs - e.g. a 3 link chain couples to a hook, and wagons with this coupling are typically fitted with both a hook and a chain.&lt;br /&gt;
&lt;br /&gt;
Multiple coupler options can be specified, and are separated with a vertical bar character. The earlier option is used in preference, so list the best coupler option first.&lt;br /&gt;
&lt;br /&gt;
A typical unfitted freight wagon with a 3 link coupling is specified as &amp;quot;3link|hook&amp;quot;. A vehicle fitted with a knuckle, screwlink and hook (e.g. a swingknuckle fitted locomotive) is specified as &amp;quot;knuckle|screwlink|hook&amp;quot;. A BR coaching stock dropknuckle (a knuckle and a hook, but no chain) is specified as &amp;quot;knuckle|hook&amp;quot;. If the vehicle also has an emergency screwlink which is not permanently fitted, then &amp;quot;knuckle|hook|screwlink&amp;quot; would be appropriate -- this would cause ACS to prefer the chain type coupler from the adjacent vehicle rather than using the emergency screwlink, which would only be used when necessary. A Victorian Railways transitional coupler (which has a chain and a knuckle, but no hook) is specified as &amp;quot;knuckle|3link&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dellner and Scharfenberg couplings are treated as compatible, so a dellner will also couple to a scharfenberg.&lt;br /&gt;
&lt;br /&gt;
If your coupler type isn&#039;t listed, define a standard name for it, and start using it. ACS supports arbitrary extension - any new coupler it hasn&#039;t seen before will be treated as a symmetrical coupler. ACS will tell you if it has connected to an identical coupler on the adjacent vehicle.&lt;br /&gt;
&lt;br /&gt;
If you need a new handed pair type (where the coupler on the end of one wagon is not the same as that on the end of another), then you will need to contact the ACS author to get one added.&lt;br /&gt;
&lt;br /&gt;
====Gangways====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passenger gangway between vehicles. Options are:&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;rubbing-plate&amp;quot;&lt;br /&gt;
*&amp;quot;gangway&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This is really intended for coaching stock - it is assumed that all gangways are compatible. I&#039;ve been considering a &#039;one piece&#039; gangway option - to aid with the centre of multiple unit trains, where there is no separation point (it will help with deciding which vehicle should display the gangway) - but I&#039;m not sure whether this is of sufficient benefit to include, as it involves a whole new set of logic here that most people won&#039;t use, and for the cases it is interesting, the same person has made both vehicles, and can therefore do it themselves... Comments please.&lt;br /&gt;
====Pipes for Air Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          airbraketype                      &amp;quot;single&amp;quot;&lt;br /&gt;
          airbrakeside                      &amp;quot;left&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for air brakes. Options for airbraketype are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
Twin is the UK standard two pipe air brake system (train pipe and brake pipe). Single is the US standard air brake system where reservoirs are charged from the brake pipe rather than the train pipe (this has appeared on some modern freightcars for reasons unknown, so is included). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Options for airbrakeside are:&lt;br /&gt;
*&amp;quot;left&amp;quot;&lt;br /&gt;
*&amp;quot;right&amp;quot;&lt;br /&gt;
Most traincars (UK, US, etc.) use left-sided airbrakes, so airbrakeside &amp;quot;left&amp;quot; will generally be used, but the right option was added to support both left and right-handed brake pipes on Australian content.&lt;br /&gt;
&lt;br /&gt;
====Pipes for Vac Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for Vacuum brakes. Options are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;high&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single is the UK default for fitted stock, high connections seems to be the standard on UK steam locos. Twin pipes (operating at two different vacuum levels) has been tried in the UK - and while not much fitted stock has the twin pipe system, most air brake, through vac piped stock seems to have two vac pipes.&lt;br /&gt;
====Multiple Working Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Multiple working connections. Options are: &lt;br /&gt;
*&amp;quot;(color)-(shape)&amp;quot; -- e.g. &amp;quot;blue-star&amp;quot; or &amp;quot;red-diamond&amp;quot;, etc&lt;br /&gt;
*&amp;quot;AAR&amp;quot; -- as used on GM locos&lt;br /&gt;
*&amp;quot;SR27&amp;quot; -- bagpipes&lt;br /&gt;
*&amp;quot;(other identifier string e.g. classname)&amp;quot;&lt;br /&gt;
====Train Heating====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Coach heating. Options are: &lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;steam&amp;quot;&lt;br /&gt;
*&amp;quot;electric&amp;quot; -- standard ETH&lt;br /&gt;
*&amp;quot;dual&amp;quot; -- both Steam and standard ETH&lt;br /&gt;
*&amp;quot;southern-electric&amp;quot; -- The Southern, who pioneered electric train heating in the UK, fitted heating that was compatible with their DC powered EMUs, and thus ran from the same voltage as the DC power supply. When the rest of BR went ETH, different standards were adopted, resulting in the Southern having a different and incompatible ETH standard...&lt;br /&gt;
&lt;br /&gt;
====Lighting Control Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          rch &amp;quot;high&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Through wiring for lighting control, to the Railway Clearing House standard. Also used more recently for other things - e.g. remote control via various methods - including TDM. I believe it is also used for signals to control doorlocks on stock so fitted - though I could be wrong on this. Options are:&lt;br /&gt;
*&amp;quot;high&amp;quot; -- positioned as is fairly standard on coaching stock&lt;br /&gt;
*&amp;quot;low&amp;quot; -- positioned as is fairly standard on streamlined locos, e.g. the front of a DVT, or a cl90&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
====Notes====&lt;br /&gt;
For all of these where &amp;quot;none&amp;quot; is an option, entirely missing out that line is equivalent to stating &amp;quot;none&amp;quot;. This should make stock which doesn&#039;t use most of the features much more palatable to produce. This will also help when extending the standard - as new features will automatically be assumed to be not present on stock built to older standards...&lt;br /&gt;
&lt;br /&gt;
That&#039;s all very well and good, but how is this supposed to be backwards compatible with the old bluestar standard?&lt;br /&gt;
&lt;br /&gt;
I&#039;m making the code fall back to reading the old config entries if it can&#039;t find the new ones. The real problem is that new stock will also have to include config.txt entries for the old bluestar, so that old vehicles know what to do when they couple to this one. Yes, this means that the old tags will never actually go away, but at least TRS2006 doesn&#039;t whinge about them so hard as of SP1...&lt;br /&gt;
&lt;br /&gt;
===The Script===&lt;br /&gt;
&lt;br /&gt;
(under construction)&lt;br /&gt;
&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=37700</id>
		<title>ACS Coupling System</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=37700"/>
		<updated>2023-07-05T21:18:30Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* The Attachment Points */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Introduction===&lt;br /&gt;
&lt;br /&gt;
There are many and varied problems with the existing BlueStar standard - but the main ones are the inflexibility beyond the initial application (coupling mineral wagons and transition era locos), and the rather arcane numeric values put into the config.txt.&lt;br /&gt;
&lt;br /&gt;
A more readable, more flexible, and preferrably easily extensible datastructure in the config.txt was needed, and some way of standardising the logic (at the very minimum, an include file, but preferrably a library). It needed to support many more different types of coupler, vehicles with different couplers on each end, and so on. &lt;br /&gt;
&lt;br /&gt;
The ACS System is an extension of the BlueStar coupling standard for TRS models (effectively BlueStar V2) and provides for the effect of working couplings on rolling stock. From version 5 of the ACSLib ACS vehicles are compatible with older BlueStar/CoupleStar ones. &lt;br /&gt;
&lt;br /&gt;
To add ACS couplings it is necessary to edit the asset config file, add attachment points to the mesh (see below for an alternative which can sometimes be used) and to create a script or edit the existing one. Due to the fact that you need access to the source files of the asset and to be able to script it is an advanced technique that cannot easily be carried out by an end-user.&lt;br /&gt;
&lt;br /&gt;
For couplers implemented as meshes in the mesh-table (usually but not always animated), position and orientation tags can be used to locate the attached meshes:&lt;br /&gt;
&lt;br /&gt;
*For front couplings the tag &#039;position 0,Y,0&#039; should be added.&lt;br /&gt;
*For back couplings two tags are needed, &#039;position 0,Y,0&#039; and orientation &#039;0,0,3.14159&#039;&lt;br /&gt;
*in both cases the value Y is 0.46 metres inboard of the Y value of limfront and limback respectively.&lt;br /&gt;
&lt;br /&gt;
===The Attachment Points===&lt;br /&gt;
&lt;br /&gt;
All of the coupler, hoses and cables are attached to two points, one on the face of the front buffer beam (a.couple0) and one on the face of the rear beam (a.couple1). a.limfront should be 0.46m forward of a.couple0 and a.limback 0.46m rearward of a.couple1. a.couple0 and a.couple1 must be at x=0 and z=0.&lt;br /&gt;
&lt;br /&gt;
Create a.couple0 in top view and move it into position. Then clone and position it to create a.couple1 and rotate it 180°. The Y axis of the two coupler points should point towards 0,0,0.&lt;br /&gt;
&lt;br /&gt;
[[File:Acs attachments.png|border|middle|x375px]]&lt;br /&gt;
&lt;br /&gt;
===The Config File===&lt;br /&gt;
First off, here is an example config.txt fragment: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  max_permitted_speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
  active-coupling-standard-60850 {&lt;br /&gt;
    version-major &amp;quot;2&amp;quot;&lt;br /&gt;
    version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
    brakes &amp;quot;air&amp;quot;&lt;br /&gt;
    front {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbrake &amp;quot;twin&amp;quot;&lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    back {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbrake &amp;quot;twin&amp;quot;&lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, what does all this do, and what are the options?&lt;br /&gt;
====Extension Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is for TRS2006 compatibility - it&#039;s all going in the extensions container. This does work in TRS2004 as well. Watch for the caveat at the end though...&lt;br /&gt;
&lt;br /&gt;
====Max Permitted Speed====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      Max_Permitted_Speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not strictly part of the coupling code, but may as well mention it. This is for the Max Permitted Speed rule to tell how fast this vehicle should be permitted to travel. It will tell both AI drivers and the human driver (via the Custom HUD rule) what the maximum permitted speed is for the train they are driving, based on information from each vehicle. (And in a future version of the rule, more stuff too...)&lt;br /&gt;
====ACS Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      active-coupling-standard-60850 {&lt;br /&gt;
        ...&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the container within which all the config information will be held.&lt;br /&gt;
&lt;br /&gt;
====ACS Version====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        version-major &amp;quot;2&amp;quot;&lt;br /&gt;
        version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Version numbers. This is useful when later code needs to read earlier format config files. Should make extending the standard a lot easier.&lt;br /&gt;
&lt;br /&gt;
====Braking System====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        brakes &amp;quot;air&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Defines what type of braking system is fitted to this vehicle. Options are:&lt;br /&gt;
*&amp;quot;air&amp;quot;&lt;br /&gt;
*&amp;quot;vac&amp;quot;&lt;br /&gt;
*&amp;quot;dual&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
This is independant of what hoses are available - unbraked but through piped stock is an entirely possible combination, and is representable.&lt;br /&gt;
&lt;br /&gt;
====Position====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        front {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
        back {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Containers for the front and back of the vehicle. &#039;Front&#039; is defined as &amp;quot;the a.limfront end&amp;quot;, and &#039;back&#039; &amp;quot;the a.limback end&amp;quot;. Available options for both are the same, so I&#039;ll describe them just once.&lt;br /&gt;
====Coupler Type====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What type of coupler do we have on this end of the vehicle? Options are:&lt;br /&gt;
* &amp;quot;hook&amp;quot; -- connects to screwlink/instanter/3link/hst-emergency-bar.&lt;br /&gt;
* &amp;quot;3link&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;instanter&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;screwlink&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;hst-emergency-bar&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;bar-full&amp;quot; -- connects to &amp;quot;bar-none&amp;quot;. Half of a handed pair for when one vehicle has the entire bar coupling.&lt;br /&gt;
* &amp;quot;bar-none&amp;quot; -- connected to by &amp;quot;bar-full&amp;quot;. The other half of the handed pair.&lt;br /&gt;
* &amp;quot;bar&amp;quot; -- connects to self only. Used when both vehicles have half the bar coupling.&lt;br /&gt;
* &amp;quot;knuckle&amp;quot; - standard knuckle coupler.&lt;br /&gt;
* &amp;quot;tightlock&amp;quot; -- different to a standard knuckle, refers to a knuckle style coupler often fitted to multiple unit trains that also include electrical connections.&lt;br /&gt;
* &amp;quot;wedgelock&amp;quot; -- London Underground coupler.&lt;br /&gt;
* &amp;quot;bsi&amp;quot; -- Found on Sprinter DMUs and derived designs.&lt;br /&gt;
* &amp;quot;dellner&amp;quot; -- Also compatible with scharfenberg coupling.&lt;br /&gt;
* &amp;quot;scharfenberg&amp;quot; -- Also compatible with dellner coupling.&lt;br /&gt;
* &amp;quot;(other string identifier)&amp;quot; -- Any string that is not recognised from the above list is assumed to be a symmetrical meet-in-the-middle type of coupler.&lt;br /&gt;
&lt;br /&gt;
Certain couplers are purely compatible with other identical couplers, others are inter-compatible. Some produce handed pairs - e.g. a 3 link chain couples to a hook, and wagons with this coupling are typically fitted with both a hook and a chain.&lt;br /&gt;
&lt;br /&gt;
Multiple coupler options can be specified, and are separated with a vertical bar character. The earlier option is used in preference, so list the best coupler option first.&lt;br /&gt;
&lt;br /&gt;
A typical unfitted freight wagon with a 3 link coupling is specified as &amp;quot;3link|hook&amp;quot;. A vehicle fitted with a knuckle, screwlink and hook (e.g. a swingknuckle fitted locomotive) is specified as &amp;quot;knuckle|screwlink|hook&amp;quot;. A BR coaching stock dropknuckle (a knuckle and a hook, but no chain) is specified as &amp;quot;knuckle|hook&amp;quot;. If the vehicle also has an emergency screwlink which is not permanently fitted, then &amp;quot;knuckle|hook|screwlink&amp;quot; would be appropriate -- this would cause ACS to prefer the chain type coupler from the adjacent vehicle rather than using the emergency screwlink, which would only be used when necessary. A Victorian Railways transitional coupler (which has a chain and a knuckle, but no hook) is specified as &amp;quot;knuckle|3link&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dellner and Scharfenberg couplings are treated as compatible, so a dellner will also couple to a scharfenberg.&lt;br /&gt;
&lt;br /&gt;
If your coupler type isn&#039;t listed, define a standard name for it, and start using it. ACS supports arbitrary extension - any new coupler it hasn&#039;t seen before will be treated as a symmetrical coupler. ACS will tell you if it has connected to an identical coupler on the adjacent vehicle.&lt;br /&gt;
&lt;br /&gt;
If you need a new handed pair type (where the coupler on the end of one wagon is not the same as that on the end of another), then you will need to contact the ACS author to get one added.&lt;br /&gt;
&lt;br /&gt;
====Gangways====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passenger gangway between vehicles. Options are:&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;rubbing-plate&amp;quot;&lt;br /&gt;
*&amp;quot;gangway&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This is really intended for coaching stock - it is assumed that all gangways are compatible. I&#039;ve been considering a &#039;one piece&#039; gangway option - to aid with the centre of multiple unit trains, where there is no separation point (it will help with deciding which vehicle should display the gangway) - but I&#039;m not sure whether this is of sufficient benefit to include, as it involves a whole new set of logic here that most people won&#039;t use, and for the cases it is interesting, the same person has made both vehicles, and can therefore do it themselves... Comments please.&lt;br /&gt;
====Pipes for Air Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          airbraketype                      &amp;quot;single&amp;quot;&lt;br /&gt;
          airbrakeside                      &amp;quot;left&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for air brakes. Options for airbraketype are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
For airbraketype, twin is the UK standard two pipe air brake system (train pipe and brake pipe). Single is the US standard air brake system where reservoirs are charged from the brake pipe rather than the train pipe (this has appeared on some modern freightcars for reasons unknown, so is included). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Options for airbrakeside are:&lt;br /&gt;
*&amp;quot;left&amp;quot;&lt;br /&gt;
*&amp;quot;right&amp;quot;&lt;br /&gt;
For airbrakeside, most traincars (UK, US, etc.) use left-sided airbrakes, so airbrakeside &amp;quot;left&amp;quot; will generally be used, but the right option was added to support both left and right-handed brake pipes on Australian content.&lt;br /&gt;
&lt;br /&gt;
====Pipes for Vac Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for Vacuum brakes. Options are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;high&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single is the UK default for fitted stock, high connections seems to be the standard on UK steam locos. Twin pipes (operating at two different vacuum levels) has been tried in the UK - and while not much fitted stock has the twin pipe system, most air brake, through vac piped stock seems to have two vac pipes.&lt;br /&gt;
====Multiple Working Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Multiple working connections. Options are: &lt;br /&gt;
*&amp;quot;(color)-(shape)&amp;quot; -- e.g. &amp;quot;blue-star&amp;quot; or &amp;quot;red-diamond&amp;quot;, etc&lt;br /&gt;
*&amp;quot;AAR&amp;quot; -- as used on GM locos&lt;br /&gt;
*&amp;quot;SR27&amp;quot; -- bagpipes&lt;br /&gt;
*&amp;quot;(other identifier string e.g. classname)&amp;quot;&lt;br /&gt;
====Train Heating====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Coach heating. Options are: &lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;steam&amp;quot;&lt;br /&gt;
*&amp;quot;electric&amp;quot; -- standard ETH&lt;br /&gt;
*&amp;quot;dual&amp;quot; -- both Steam and standard ETH&lt;br /&gt;
*&amp;quot;southern-electric&amp;quot; -- The Southern, who pioneered electric train heating in the UK, fitted heating that was compatible with their DC powered EMUs, and thus ran from the same voltage as the DC power supply. When the rest of BR went ETH, different standards were adopted, resulting in the Southern having a different and incompatible ETH standard...&lt;br /&gt;
&lt;br /&gt;
====Lighting Control Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          rch &amp;quot;high&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Through wiring for lighting control, to the Railway Clearing House standard. Also used more recently for other things - e.g. remote control via various methods - including TDM. I believe it is also used for signals to control doorlocks on stock so fitted - though I could be wrong on this. Options are:&lt;br /&gt;
*&amp;quot;high&amp;quot; -- positioned as is fairly standard on coaching stock&lt;br /&gt;
*&amp;quot;low&amp;quot; -- positioned as is fairly standard on streamlined locos, e.g. the front of a DVT, or a cl90&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
====Notes====&lt;br /&gt;
For all of these where &amp;quot;none&amp;quot; is an option, entirely missing out that line is equivalent to stating &amp;quot;none&amp;quot;. This should make stock which doesn&#039;t use most of the features much more palatable to produce. This will also help when extending the standard - as new features will automatically be assumed to be not present on stock built to older standards...&lt;br /&gt;
&lt;br /&gt;
That&#039;s all very well and good, but how is this supposed to be backwards compatible with the old bluestar standard?&lt;br /&gt;
&lt;br /&gt;
I&#039;m making the code fall back to reading the old config entries if it can&#039;t find the new ones. The real problem is that new stock will also have to include config.txt entries for the old bluestar, so that old vehicles know what to do when they couple to this one. Yes, this means that the old tags will never actually go away, but at least TRS2006 doesn&#039;t whinge about them so hard as of SP1...&lt;br /&gt;
&lt;br /&gt;
===The Script===&lt;br /&gt;
&lt;br /&gt;
(under construction)&lt;br /&gt;
&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=File:Acs_attachments.png&amp;diff=37699</id>
		<title>File:Acs attachments.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=File:Acs_attachments.png&amp;diff=37699"/>
		<updated>2023-07-05T21:14:31Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: A List of attachments needed for the ACS coupling system.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A List of attachments needed for the ACS coupling system.&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=37698</id>
		<title>ACS Coupling System</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=ACS_Coupling_System&amp;diff=37698"/>
		<updated>2023-07-05T20:51:24Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Pipes for Air Brakes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Introduction===&lt;br /&gt;
&lt;br /&gt;
There are many and varied problems with the existing BlueStar standard - but the main ones are the inflexibility beyond the initial application (coupling mineral wagons and transition era locos), and the rather arcane numeric values put into the config.txt.&lt;br /&gt;
&lt;br /&gt;
A more readable, more flexible, and preferrably easily extensible datastructure in the config.txt was needed, and some way of standardising the logic (at the very minimum, an include file, but preferrably a library). It needed to support many more different types of coupler, vehicles with different couplers on each end, and so on. &lt;br /&gt;
&lt;br /&gt;
The ACS System is an extension of the BlueStar coupling standard for TRS models (effectively BlueStar V2) and provides for the effect of working couplings on rolling stock. From version 5 of the ACSLib ACS vehicles are compatible with older BlueStar/CoupleStar ones. &lt;br /&gt;
&lt;br /&gt;
To add ACS couplings it is necessary to edit the asset config file, add attachment points to the mesh (see below for an alternative which can sometimes be used) and to create a script or edit the existing one. Due to the fact that you need access to the source files of the asset and to be able to script it is an advanced technique that cannot easily be carried out by an end-user.&lt;br /&gt;
&lt;br /&gt;
For couplers implemented as meshes in the mesh-table (usually but not always animated), position and orientation tags can be used to locate the attached meshes:&lt;br /&gt;
&lt;br /&gt;
*For front couplings the tag &#039;position 0,Y,0&#039; should be added.&lt;br /&gt;
*For back couplings two tags are needed, &#039;position 0,Y,0&#039; and orientation &#039;0,0,3.14159&#039;&lt;br /&gt;
*in both cases the value Y is 0.46 metres inboard of the Y value of limfront and limback respectively.&lt;br /&gt;
&lt;br /&gt;
===The Attachment Points===&lt;br /&gt;
&lt;br /&gt;
All of the coupler, hoses and cables are attached to two points, one on the face of the front buffer beam (a.couple0) and one on the face of the rear beam (a.couple1). a.limfront should be 0.46m forward of a.couple0 and a.limback 0.46m rearward of a.couple1. a.couple0 and a.couple1 must be at x=0 and z=0.&lt;br /&gt;
&lt;br /&gt;
Create a.couple0 in top view and move it into position. Then clone and position it to create a.couple1 and rotate it 180°. The Y axis of the two coupler points should point towards 0,0,0.&lt;br /&gt;
&lt;br /&gt;
[[image:acs att points.jpg]]&lt;br /&gt;
&lt;br /&gt;
===The Config File===&lt;br /&gt;
First off, here is an example config.txt fragment: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  max_permitted_speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
  active-coupling-standard-60850 {&lt;br /&gt;
    version-major &amp;quot;2&amp;quot;&lt;br /&gt;
    version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
    brakes &amp;quot;air&amp;quot;&lt;br /&gt;
    front {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbrake &amp;quot;twin&amp;quot;&lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    back {&lt;br /&gt;
      coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
      gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
      airbrake &amp;quot;twin&amp;quot;&lt;br /&gt;
      vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
      multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
      heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
      rch &amp;quot;high&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, what does all this do, and what are the options?&lt;br /&gt;
====Extension Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extensions {&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is for TRS2006 compatibility - it&#039;s all going in the extensions container. This does work in TRS2004 as well. Watch for the caveat at the end though...&lt;br /&gt;
&lt;br /&gt;
====Max Permitted Speed====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      Max_Permitted_Speed-60850 &amp;quot;125mph&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not strictly part of the coupling code, but may as well mention it. This is for the Max Permitted Speed rule to tell how fast this vehicle should be permitted to travel. It will tell both AI drivers and the human driver (via the Custom HUD rule) what the maximum permitted speed is for the train they are driving, based on information from each vehicle. (And in a future version of the rule, more stuff too...)&lt;br /&gt;
====ACS Container====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      active-coupling-standard-60850 {&lt;br /&gt;
        ...&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the container within which all the config information will be held.&lt;br /&gt;
&lt;br /&gt;
====ACS Version====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        version-major &amp;quot;2&amp;quot;&lt;br /&gt;
        version-minor &amp;quot;0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Version numbers. This is useful when later code needs to read earlier format config files. Should make extending the standard a lot easier.&lt;br /&gt;
&lt;br /&gt;
====Braking System====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        brakes &amp;quot;air&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Defines what type of braking system is fitted to this vehicle. Options are:&lt;br /&gt;
*&amp;quot;air&amp;quot;&lt;br /&gt;
*&amp;quot;vac&amp;quot;&lt;br /&gt;
*&amp;quot;dual&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
This is independant of what hoses are available - unbraked but through piped stock is an entirely possible combination, and is representable.&lt;br /&gt;
&lt;br /&gt;
====Position====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        front {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
        back {&lt;br /&gt;
          ...&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Containers for the front and back of the vehicle. &#039;Front&#039; is defined as &amp;quot;the a.limfront end&amp;quot;, and &#039;back&#039; &amp;quot;the a.limback end&amp;quot;. Available options for both are the same, so I&#039;ll describe them just once.&lt;br /&gt;
====Coupler Type====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          coupler &amp;quot;knuckle|screwlink|hook&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What type of coupler do we have on this end of the vehicle? Options are:&lt;br /&gt;
* &amp;quot;hook&amp;quot; -- connects to screwlink/instanter/3link/hst-emergency-bar.&lt;br /&gt;
* &amp;quot;3link&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;instanter&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;screwlink&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;hst-emergency-bar&amp;quot; -- connects to hook.&lt;br /&gt;
* &amp;quot;bar-full&amp;quot; -- connects to &amp;quot;bar-none&amp;quot;. Half of a handed pair for when one vehicle has the entire bar coupling.&lt;br /&gt;
* &amp;quot;bar-none&amp;quot; -- connected to by &amp;quot;bar-full&amp;quot;. The other half of the handed pair.&lt;br /&gt;
* &amp;quot;bar&amp;quot; -- connects to self only. Used when both vehicles have half the bar coupling.&lt;br /&gt;
* &amp;quot;knuckle&amp;quot; - standard knuckle coupler.&lt;br /&gt;
* &amp;quot;tightlock&amp;quot; -- different to a standard knuckle, refers to a knuckle style coupler often fitted to multiple unit trains that also include electrical connections.&lt;br /&gt;
* &amp;quot;wedgelock&amp;quot; -- London Underground coupler.&lt;br /&gt;
* &amp;quot;bsi&amp;quot; -- Found on Sprinter DMUs and derived designs.&lt;br /&gt;
* &amp;quot;dellner&amp;quot; -- Also compatible with scharfenberg coupling.&lt;br /&gt;
* &amp;quot;scharfenberg&amp;quot; -- Also compatible with dellner coupling.&lt;br /&gt;
* &amp;quot;(other string identifier)&amp;quot; -- Any string that is not recognised from the above list is assumed to be a symmetrical meet-in-the-middle type of coupler.&lt;br /&gt;
&lt;br /&gt;
Certain couplers are purely compatible with other identical couplers, others are inter-compatible. Some produce handed pairs - e.g. a 3 link chain couples to a hook, and wagons with this coupling are typically fitted with both a hook and a chain.&lt;br /&gt;
&lt;br /&gt;
Multiple coupler options can be specified, and are separated with a vertical bar character. The earlier option is used in preference, so list the best coupler option first.&lt;br /&gt;
&lt;br /&gt;
A typical unfitted freight wagon with a 3 link coupling is specified as &amp;quot;3link|hook&amp;quot;. A vehicle fitted with a knuckle, screwlink and hook (e.g. a swingknuckle fitted locomotive) is specified as &amp;quot;knuckle|screwlink|hook&amp;quot;. A BR coaching stock dropknuckle (a knuckle and a hook, but no chain) is specified as &amp;quot;knuckle|hook&amp;quot;. If the vehicle also has an emergency screwlink which is not permanently fitted, then &amp;quot;knuckle|hook|screwlink&amp;quot; would be appropriate -- this would cause ACS to prefer the chain type coupler from the adjacent vehicle rather than using the emergency screwlink, which would only be used when necessary. A Victorian Railways transitional coupler (which has a chain and a knuckle, but no hook) is specified as &amp;quot;knuckle|3link&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dellner and Scharfenberg couplings are treated as compatible, so a dellner will also couple to a scharfenberg.&lt;br /&gt;
&lt;br /&gt;
If your coupler type isn&#039;t listed, define a standard name for it, and start using it. ACS supports arbitrary extension - any new coupler it hasn&#039;t seen before will be treated as a symmetrical coupler. ACS will tell you if it has connected to an identical coupler on the adjacent vehicle.&lt;br /&gt;
&lt;br /&gt;
If you need a new handed pair type (where the coupler on the end of one wagon is not the same as that on the end of another), then you will need to contact the ACS author to get one added.&lt;br /&gt;
&lt;br /&gt;
====Gangways====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          gangway &amp;quot;gangway&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passenger gangway between vehicles. Options are:&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;rubbing-plate&amp;quot;&lt;br /&gt;
*&amp;quot;gangway&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This is really intended for coaching stock - it is assumed that all gangways are compatible. I&#039;ve been considering a &#039;one piece&#039; gangway option - to aid with the centre of multiple unit trains, where there is no separation point (it will help with deciding which vehicle should display the gangway) - but I&#039;m not sure whether this is of sufficient benefit to include, as it involves a whole new set of logic here that most people won&#039;t use, and for the cases it is interesting, the same person has made both vehicles, and can therefore do it themselves... Comments please.&lt;br /&gt;
====Pipes for Air Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          airbraketype                      &amp;quot;single&amp;quot;&lt;br /&gt;
          airbrakeside                      &amp;quot;left&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for air brakes. Options for airbraketype are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
For airbraketype, twin is the UK standard two pipe air brake system (train pipe and brake pipe). Single is the US standard air brake system where reservoirs are charged from the brake pipe rather than the train pipe (this has appeared on some modern freightcars for reasons unknown, so is included). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Options for airbrakeside are:&lt;br /&gt;
*&amp;quot;left&amp;quot;&lt;br /&gt;
*&amp;quot;right&amp;quot;&lt;br /&gt;
For airbrakeside, most traincars (UK, US, etc.) use left-sided airbrakes, so airbrakeside &amp;quot;left&amp;quot; will generally be used, but the right option was added to support both left and right-handed brake pipes on Australian content.&lt;br /&gt;
&lt;br /&gt;
====Pipes for Vac Brakes====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          vacbrake &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Brake pipes for Vacuum brakes. Options are: &lt;br /&gt;
*&amp;quot;twin&amp;quot;&lt;br /&gt;
*&amp;quot;single&amp;quot;&lt;br /&gt;
*&amp;quot;high&amp;quot;&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single is the UK default for fitted stock, high connections seems to be the standard on UK steam locos. Twin pipes (operating at two different vacuum levels) has been tried in the UK - and while not much fitted stock has the twin pipe system, most air brake, through vac piped stock seems to have two vac pipes.&lt;br /&gt;
====Multiple Working Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          multiple-working &amp;quot;none&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Multiple working connections. Options are: &lt;br /&gt;
*&amp;quot;(color)-(shape)&amp;quot; -- e.g. &amp;quot;blue-star&amp;quot; or &amp;quot;red-diamond&amp;quot;, etc&lt;br /&gt;
*&amp;quot;AAR&amp;quot; -- as used on GM locos&lt;br /&gt;
*&amp;quot;SR27&amp;quot; -- bagpipes&lt;br /&gt;
*&amp;quot;(other identifier string e.g. classname)&amp;quot;&lt;br /&gt;
====Train Heating====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          heating-type &amp;quot;electric&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Coach heating. Options are: &lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
*&amp;quot;steam&amp;quot;&lt;br /&gt;
*&amp;quot;electric&amp;quot; -- standard ETH&lt;br /&gt;
*&amp;quot;dual&amp;quot; -- both Steam and standard ETH&lt;br /&gt;
*&amp;quot;southern-electric&amp;quot; -- The Southern, who pioneered electric train heating in the UK, fitted heating that was compatible with their DC powered EMUs, and thus ran from the same voltage as the DC power supply. When the rest of BR went ETH, different standards were adopted, resulting in the Southern having a different and incompatible ETH standard...&lt;br /&gt;
&lt;br /&gt;
====Lighting Control Cables====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
          rch &amp;quot;high&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Through wiring for lighting control, to the Railway Clearing House standard. Also used more recently for other things - e.g. remote control via various methods - including TDM. I believe it is also used for signals to control doorlocks on stock so fitted - though I could be wrong on this. Options are:&lt;br /&gt;
*&amp;quot;high&amp;quot; -- positioned as is fairly standard on coaching stock&lt;br /&gt;
*&amp;quot;low&amp;quot; -- positioned as is fairly standard on streamlined locos, e.g. the front of a DVT, or a cl90&lt;br /&gt;
*&amp;quot;none&amp;quot;&lt;br /&gt;
====Notes====&lt;br /&gt;
For all of these where &amp;quot;none&amp;quot; is an option, entirely missing out that line is equivalent to stating &amp;quot;none&amp;quot;. This should make stock which doesn&#039;t use most of the features much more palatable to produce. This will also help when extending the standard - as new features will automatically be assumed to be not present on stock built to older standards...&lt;br /&gt;
&lt;br /&gt;
That&#039;s all very well and good, but how is this supposed to be backwards compatible with the old bluestar standard?&lt;br /&gt;
&lt;br /&gt;
I&#039;m making the code fall back to reading the old config entries if it can&#039;t find the new ones. The real problem is that new stock will also have to include config.txt entries for the old bluestar, so that old vehicles know what to do when they couple to this one. Yes, this means that the old tags will never actually go away, but at least TRS2006 doesn&#039;t whinge about them so hard as of SP1...&lt;br /&gt;
&lt;br /&gt;
===The Script===&lt;br /&gt;
&lt;br /&gt;
(under construction)&lt;br /&gt;
&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=37656</id>
		<title>Class Str</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=37656"/>
		<updated>2023-07-02T06:47:35Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Find */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Language Reference|API Hierarchy]]&lt;br /&gt;
**Str&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Str is a static class providing string utility functions not supported by the native string object. &lt;br /&gt;
*When used in game code these methods must be prefixed &#039;&#039;Str.&#039;&#039; to reference the class.&lt;br /&gt;
*Some of these methods directly amend their parameters rather than returning values via the method.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left==&lt;br /&gt;
{{MethodHeader|public void Left(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = count of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Left(s,5);        // s will now be equal to &amp;quot;After&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself consisting of its first &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mid==&lt;br /&gt;
{{MethodHeader|public void Mid(string s, int first, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;first&#039;&#039;&#039; = index of first character to retain.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Mid(s,3,4);           // s will now be equal to &amp;quot;tern&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself &#039;&#039;count&#039;&#039; characters long starting with the &#039;&#039;first&#039;&#039; character.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;I&amp;gt;To get the output specified you would need the following: Str.Mid(s,2,4); as the string array is zero based. This has been tested using TS2012 build 61388 and TANE. &amp;lt;/I&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Right==&lt;br /&gt;
{{MethodHeader|public void Right(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Right(s,4);           // s will now be equal to &amp;quot;noon&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself composed of the last &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
{{MethodHeader|Find(string s, string substr, int startingIndex)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string in which to search&lt;br /&gt;
*&#039;&#039;&#039;substr&#039;&#039;&#039; - substring to find&lt;br /&gt;
*&#039;&#039;&#039;startingIndex&#039;&#039;&#039; - where to start looking down the string i.e. skip the first &#039;n&#039; characters&lt;br /&gt;
;Returned Value&lt;br /&gt;
*index within string that substr starts at. &#039;-1&#039; if not found.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int i = Str.Find(&amp;quot;z&amp;quot;, &amp;quot;amazon&amp;quot;, 0) //returns 4&lt;br /&gt;
;Notes&lt;br /&gt;
*Searches for a substring within a string.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToInt==&lt;br /&gt;
{{MethodHeader|public native int ToInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of an integer.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Integer value of string parameter.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.ToInt(&amp;quot;1234&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to an integer.&lt;br /&gt;
*Method returns 0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToFloat==&lt;br /&gt;
{{MethodHeader|public native float ToFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of a floating point number.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Floating point value.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float length = Str.ToFloat(&amp;quot;1.5&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to a floating point number.&lt;br /&gt;
*Method returns 0.0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tokens==&lt;br /&gt;
{{MethodHeader|public native string[ ] Tokens(string s, string delimiters)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;delimiters&#039;&#039;&#039; = string of characters to use as token boundaries.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Array of string tokens.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string[] sentence = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;);     // sentence contains an array of four strings:&lt;br /&gt;
                                                            // [&amp;quot;Once&amp;quot;,&amp;quot;upon&amp;quot;,&amp;quot;a&amp;quot;,&amp;quot;time&amp;quot;].&lt;br /&gt;
 int wordCount = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;).size();  // returns 4&lt;br /&gt;
 string firstWord = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;)[0];   // returns &amp;quot;Once&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 string kuidStr = &amp;quot;&amp;lt;kuid:1234:5678&amp;gt;&amp;quot;&lt;br /&gt;
 string userID = Str.Tokens(kuidStr,&amp;quot;&amp;lt;:&amp;gt;&amp;quot;)[1];              // returns &amp;quot;1234&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Splits a string into an array of tokens using any of the characters in &#039;&#039;delimiters&#039;&#039; as token boundaries.&lt;br /&gt;
*Characters contained within the &#039;&#039;delimiters&#039;&#039; string are never returned.&lt;br /&gt;
*If &#039;&#039;delimiters&#039;&#039; is null or an empty string then white space will be assumed to define the token boundaries.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToLower==&lt;br /&gt;
{{MethodHeader|public native void ToLower(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToLower(&amp;quot;UPPER CASE STRING&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to lower case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToUpper==&lt;br /&gt;
{{MethodHeader|public native void ToUpper(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToUpper(&amp;quot;lower case string&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to upper case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimLeft==&lt;br /&gt;
{{MethodHeader|public native void TrimLeft(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimLeft(&amp;quot;Once upon a time&amp;quot;,&amp;quot;Once &amp;quot;);      // returns &amp;quot;upon a time&amp;quot;&lt;br /&gt;
 Str.TrimLeft(&amp;quot;      result&amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the front of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimRight==&lt;br /&gt;
{{MethodHeader|public native void TrimRight(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimRight(&amp;quot;Once upon a time&amp;quot;,&amp;quot; a time&amp;quot;);      // returns &amp;quot;Once upon&amp;quot;&lt;br /&gt;
 Str.TrimRight(&amp;quot;result        &amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the end of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackInt==&lt;br /&gt;
{{MethodHeader|public native int UnpackInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First integer value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.UnpackInt(&amp;quot;21st May 2008&amp;quot;);           // returns 21 and amends &#039;&#039;s&#039;&#039; to &amp;quot;st May 2008&amp;quot; &lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first integer value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackFloat==&lt;br /&gt;
{{MethodHeader|public native float UnpackFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First float value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float distance = Str.UnpackFloat(&amp;quot;21.5 miles&amp;quot;);   // returns 21.5 and amends &#039;&#039;s&#039;&#039; to &amp;quot; miles&amp;quot;.&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first floating point value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackString==&lt;br /&gt;
{{MethodHeader|public native string UnpackString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First string in &#039;&#039;s&#039;&#039;, excluding any leading white space.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Once upon a time&amp;quot;;&lt;br /&gt;
 string firstWord = UnpackString(s);     // returns &amp;quot;Once&amp;quot;, s becomes &amp;quot; upon a time&amp;quot;&lt;br /&gt;
 string secondWord = UnpackString(s);    // returns &amp;quot;upon&amp;quot;, s becomes &amp;quot; a time&amp;quot;&lt;br /&gt;
 string thirdWord = UnpackString(s);     // returns &amp;quot;a&amp;quot;,    s becomes &amp;quot; time&amp;quot;&lt;br /&gt;
 string fourthWord = UnpackString(s);    // returns &amp;quot;time&amp;quot;, s becomes &amp;quot;&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first word from the string parameter (using white space for word separation) and returns it in the method result. &lt;br /&gt;
*Any leading white space is removed from the string before parsing.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==CloneString==&lt;br /&gt;
{{MethodHeader|public string CloneString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = The string to clone.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*string - A new string in the current gamescript context which has contents that exactly match the original string.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string original=&amp;quot;Hello World!&amp;quot;&lt;br /&gt;
 string copy;&lt;br /&gt;
 copy=Str.CloneString(original);&lt;br /&gt;
;Notes&lt;br /&gt;
*CloneString() creates a copy of the string passed. &lt;br /&gt;
*Ordinarily &#039;copying&#039; a string will just create a new object that references the old string. This is not allowed across different contexts.&lt;br /&gt;
*CloneString() creates a new string for use in the current context.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#AlreadyThereStr|TrainUtil.AlreadyThereStr()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#CompareStrLists|TrainUtil.CompareStrLists()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#GetUpTo|TrainUtil.GetUpTo()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasPrefix|TrainUtil.HasPrefix()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasSufix|TrainUtil.HasSufix()]] &#039;&#039;(sic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#StrSubst|TrainUtil.StrSubst()]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE170&amp;diff=37273</id>
		<title>Help:VE170</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE170&amp;diff=37273"/>
		<updated>2023-05-18T18:00:15Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Failed to open compiled texture &#039;&#039;texture-name&#039;&#039; for &#039;&#039;archive-file-name&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a general failure error for texture files.  It is usually one of two or more messages related to a failure to process a texture file - the other errors provide a more precise description of the problem.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 - VE170: Failed to open compiled texture &#039;coal_3.texture&#039; for &#039;arc:fld:$(local)/hash-2D||kuid2 1234 5678 2.tzarc|&#039;&lt;br /&gt;
&lt;br /&gt;
In this particular case the texture file was missing - the missing file was reported as error [[Help:VE165|VE165]].&lt;br /&gt;
&lt;br /&gt;
If VE170 is reported as the only error, it probably indicates a letter in the texture file is uppercase. For example, Coal_3B.texture should be coal_3b.texture. Also, make sure you are using forward slashes when referencing folders. Otherwise, it is likely an internal processing error.&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE220&amp;diff=37178</id>
		<title>Help:VE220</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE220&amp;diff=37178"/>
		<updated>2023-05-08T05:50:28Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This could mean the declared functions return type is different from the actual function.&lt;br /&gt;
&lt;br /&gt;
void GetSpeed(bool dir);&lt;br /&gt;
&lt;br /&gt;
int GetSpeed(bool dir)&lt;br /&gt;
{&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The declared function is void, but the actual function is int;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It could also mean you have the same function declared twice with different parameters:&lt;br /&gt;
&lt;br /&gt;
  int DetermineCarPosition(void);&lt;br /&gt;
  void SetTwoDigitCode(string code);&lt;br /&gt;
  &#039;&#039;&#039;void SetDestination(string code);&#039;&#039;&#039;&lt;br /&gt;
  void SetTexture(int index);&lt;br /&gt;
  void SetAttachment(int side, int middle, int high, int highbeam);&lt;br /&gt;
  &#039;&#039;&#039;void SetDestination(int index, int code);&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE220&amp;diff=37177</id>
		<title>Help:VE220</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE220&amp;diff=37177"/>
		<updated>2023-05-08T05:50:17Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This could mean the declared functions return type is different from the actual function.&lt;br /&gt;
&lt;br /&gt;
void GetSpeed(bool dir);&lt;br /&gt;
&lt;br /&gt;
int GetSpeed(bool dir)&lt;br /&gt;
{&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The declared function is void, but the actual function is int;&lt;br /&gt;
&lt;br /&gt;
It could also mean you have the same function declared twice with different parameters:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  int DetermineCarPosition(void);&lt;br /&gt;
  void SetTwoDigitCode(string code);&lt;br /&gt;
  &#039;&#039;&#039;void SetDestination(string code);&#039;&#039;&#039;&lt;br /&gt;
  void SetTexture(int index);&lt;br /&gt;
  void SetAttachment(int side, int middle, int high, int highbeam);&lt;br /&gt;
  &#039;&#039;&#039;void SetDestination(int index, int code);&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE220&amp;diff=37074</id>
		<title>Help:VE220</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE220&amp;diff=37074"/>
		<updated>2023-04-23T23:53:32Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: Created page with &amp;quot;This could mean the declared functions return type is different from the actual function.  void GetSpeed(bool dir);  int GetSpeed(bool dir) {      }  The declared function is ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This could mean the declared functions return type is different from the actual function.&lt;br /&gt;
&lt;br /&gt;
void GetSpeed(bool dir);&lt;br /&gt;
&lt;br /&gt;
int GetSpeed(bool dir)&lt;br /&gt;
{&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The declared function is void, but the actual function is int;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Corona_Effect&amp;diff=36988</id>
		<title>Corona Effect</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Corona_Effect&amp;diff=36988"/>
		<updated>2023-04-17T19:16:29Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Explanations and default values */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Corona effect kind is a [[&amp;quot;mesh-table&amp;quot; Container]] effect container. The following tags are supported:&lt;br /&gt;
&lt;br /&gt;
 kind &amp;quot;corona&amp;quot;&lt;br /&gt;
 att &amp;quot;&amp;quot;&lt;br /&gt;
 object-size 0.15&lt;br /&gt;
 max-size-mul 2.0&lt;br /&gt;
 mul-distance 60.0&lt;br /&gt;
 min-distance 1.0&lt;br /&gt;
 max-distance 315.0&lt;br /&gt;
 max-intensity 1.0&lt;br /&gt;
 texture-KUID &amp;amp;lt;KUID:-1:6349&amp;amp;gt;&lt;br /&gt;
 distance-fade 1&lt;br /&gt;
 directional 1&lt;br /&gt;
 frequency 0&lt;br /&gt;
 wave-shift 0&lt;br /&gt;
&lt;br /&gt;
===Explanations and default values===&lt;br /&gt;
&lt;br /&gt;
;att: Name of attachment point.&lt;br /&gt;
:*Compulsory (3.4)&lt;br /&gt;
&lt;br /&gt;
;object-size: Size of the corona in meters.&lt;br /&gt;
:*Optional. Default 0.15.&lt;br /&gt;
&lt;br /&gt;
;max-size-mul: ??&lt;br /&gt;
:*Optional. Default 2.0.&lt;br /&gt;
&lt;br /&gt;
;mul-distance: ??&lt;br /&gt;
:*Optional. Default 60.  &lt;br /&gt;
&lt;br /&gt;
;min-distance: Closest distance at which the corona disappears. &lt;br /&gt;
:*Optional. Default 1.0.&lt;br /&gt;
&lt;br /&gt;
;max-distance: Farthest distance at which corona will be visible.&lt;br /&gt;
:*Optional. Default 315.&lt;br /&gt;
&lt;br /&gt;
;max-intensity: Maximum visual intensity level.&lt;br /&gt;
:*Optional. Default 1.&lt;br /&gt;
&lt;br /&gt;
;texture-kuid: Specifies a user-defined texture for the corona by identifying the KUID of a &amp;quot;[[KIND_Texture | KIND_Texture]]&amp;quot; asset.&lt;br /&gt;
:*Optional. Default &amp;lt;kuid:-1:6349&amp;gt; (yellow/orange texture)  &lt;br /&gt;
&lt;br /&gt;
;distance-fade: Boolean value; 0 = does not fade with distance, 1 = fades with distance. &lt;br /&gt;
:*&#039;&#039;&#039;OBSOLETE - Do not use.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;directional: Boolean value indicating whether the corona effect has direction. A value of 0 means the corona is omnidirectional; a value of 1 indicates that the corona is directional along the negative z axis.&lt;br /&gt;
:*Optional. Default 1.&lt;br /&gt;
&lt;br /&gt;
;frequency: Frequency of flashing in flashes per second. 0.2 is one flash every 5 seconds; 0.5 is one flash every 2 seconds; 2 is one flash every half second.&lt;br /&gt;
:*Optional. Default 2.&lt;br /&gt;
&lt;br /&gt;
;wave-shift: A floating-point value ranging from -1 to 1. This value determines the duty cycle of a flashing corona: that is, the amount of time in the cycle for which the light is on.  Negative values give on times of less than half, positive values give on times of more than half.   Note that this number is not linear.&lt;br /&gt;
:*Optional. Default 0 (50% duty cycle).&lt;br /&gt;
&lt;br /&gt;
[[Category:Config Container]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- mul-distance = distance at which corona will start growing larger; maintains visibility of a light source, mimics signal light behavior&lt;br /&gt;
max-size-mul = Essentially, the maximum size of corona at a long distance, it shrinks as you get closer&lt;br /&gt;
&lt;br /&gt;
wave shift = not sure, probably allows occulting (on more than off) or quick flashing (off more than on) --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36987</id>
		<title>Class Str</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36987"/>
		<updated>2023-04-16T03:23:31Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Language Reference|API Hierarchy]]&lt;br /&gt;
**Str&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Str is a static class providing string utility functions not supported by the native string object. &lt;br /&gt;
*When used in game code these methods must be prefixed &#039;&#039;Str.&#039;&#039; to reference the class.&lt;br /&gt;
*Some of these methods directly amend their parameters rather than returning values via the method.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left==&lt;br /&gt;
{{MethodHeader|public void Left(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = count of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Left(s,5);        // s will now be equal to &amp;quot;After&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself consisting of its first &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mid==&lt;br /&gt;
{{MethodHeader|public void Mid(string s, int first, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;first&#039;&#039;&#039; = index of first character to retain.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Mid(s,3,4);           // s will now be equal to &amp;quot;tern&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself &#039;&#039;count&#039;&#039; characters long starting with the &#039;&#039;first&#039;&#039; character.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;I&amp;gt;To get the output specified you would need the following: Str.Mid(s,2,4); as the string array is zero based. This has been tested using TS2012 build 61388 and TANE. &amp;lt;/I&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Right==&lt;br /&gt;
{{MethodHeader|public void Right(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Right(s,4);           // s will now be equal to &amp;quot;noon&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself composed of the last &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
{{MethodHeader|Find(string s, string substr, int startingIndex)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string in which to search&lt;br /&gt;
*&#039;&#039;&#039;substr&#039;&#039;&#039; - substring to find&lt;br /&gt;
*&#039;&#039;&#039;startingIndex&#039;&#039;&#039; - where to start looking down the string i.e. skip the first &#039;n&#039; characters&lt;br /&gt;
;Returned Value&lt;br /&gt;
*index within string that substr starts at. &#039;-1&#039; if not found.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int i = Str.Find(&amp;quot;z&amp;quot;, &amp;quot;amazon&amp;quot;, 1) //returns 4&lt;br /&gt;
;Notes&lt;br /&gt;
*Searches for a substring within a string.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToInt==&lt;br /&gt;
{{MethodHeader|public native int ToInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of an integer.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Integer value of string parameter.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.ToInt(&amp;quot;1234&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to an integer.&lt;br /&gt;
*Method returns 0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToFloat==&lt;br /&gt;
{{MethodHeader|public native float ToFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of a floating point number.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Floating point value.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float length = Str.ToFloat(&amp;quot;1.5&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to a floating point number.&lt;br /&gt;
*Method returns 0.0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tokens==&lt;br /&gt;
{{MethodHeader|public native string[ ] Tokens(string s, string delimiters)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;delimiters&#039;&#039;&#039; = string of characters to use as token boundaries.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Array of string tokens.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string[] sentence = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;);     // sentence contains an array of four strings:&lt;br /&gt;
                                                            // [&amp;quot;Once&amp;quot;,&amp;quot;upon&amp;quot;,&amp;quot;a&amp;quot;,&amp;quot;time&amp;quot;].&lt;br /&gt;
 int wordCount = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;).size();  // returns 4&lt;br /&gt;
 string firstWord = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;)[0];   // returns &amp;quot;Once&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 string kuidStr = &amp;quot;&amp;lt;kuid:1234:5678&amp;gt;&amp;quot;&lt;br /&gt;
 string userID = Str.Tokens(kuidStr,&amp;quot;&amp;lt;:&amp;gt;&amp;quot;)[1];              // returns &amp;quot;1234&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Splits a string into an array of tokens using any of the characters in &#039;&#039;delimiters&#039;&#039; as token boundaries.&lt;br /&gt;
*Characters contained within the &#039;&#039;delimiters&#039;&#039; string are never returned.&lt;br /&gt;
*If &#039;&#039;delimiters&#039;&#039; is null or an empty string then white space will be assumed to define the token boundaries.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToLower==&lt;br /&gt;
{{MethodHeader|public native void ToLower(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToLower(&amp;quot;UPPER CASE STRING&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to lower case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToUpper==&lt;br /&gt;
{{MethodHeader|public native void ToUpper(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToUpper(&amp;quot;lower case string&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to upper case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimLeft==&lt;br /&gt;
{{MethodHeader|public native void TrimLeft(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimLeft(&amp;quot;Once upon a time&amp;quot;,&amp;quot;Once &amp;quot;);      // returns &amp;quot;upon a time&amp;quot;&lt;br /&gt;
 Str.TrimLeft(&amp;quot;      result&amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the front of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimRight==&lt;br /&gt;
{{MethodHeader|public native void TrimRight(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimRight(&amp;quot;Once upon a time&amp;quot;,&amp;quot; a time&amp;quot;);      // returns &amp;quot;Once upon&amp;quot;&lt;br /&gt;
 Str.TrimRight(&amp;quot;result        &amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the end of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackInt==&lt;br /&gt;
{{MethodHeader|public native int UnpackInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First integer value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.UnpackInt(&amp;quot;21st May 2008&amp;quot;);           // returns 21 and amends &#039;&#039;s&#039;&#039; to &amp;quot;st May 2008&amp;quot; &lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first integer value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackFloat==&lt;br /&gt;
{{MethodHeader|public native float UnpackFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First float value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float distance = Str.UnpackFloat(&amp;quot;21.5 miles&amp;quot;);   // returns 21.5 and amends &#039;&#039;s&#039;&#039; to &amp;quot; miles&amp;quot;.&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first floating point value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackString==&lt;br /&gt;
{{MethodHeader|public native string UnpackString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First string in &#039;&#039;s&#039;&#039;, excluding any leading white space.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Once upon a time&amp;quot;;&lt;br /&gt;
 string firstWord = UnpackString(s);     // returns &amp;quot;Once&amp;quot;, s becomes &amp;quot; upon a time&amp;quot;&lt;br /&gt;
 string secondWord = UnpackString(s);    // returns &amp;quot;upon&amp;quot;, s becomes &amp;quot; a time&amp;quot;&lt;br /&gt;
 string thirdWord = UnpackString(s);     // returns &amp;quot;a&amp;quot;,    s becomes &amp;quot; time&amp;quot;&lt;br /&gt;
 string fourthWord = UnpackString(s);    // returns &amp;quot;time&amp;quot;, s becomes &amp;quot;&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first word from the string parameter (using white space for word separation) and returns it in the method result. &lt;br /&gt;
*Any leading white space is removed from the string before parsing.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==CloneString==&lt;br /&gt;
{{MethodHeader|public string CloneString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = The string to clone.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*string - A new string in the current gamescript context which has contents that exactly match the original string.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string original=&amp;quot;Hello World!&amp;quot;&lt;br /&gt;
 string copy;&lt;br /&gt;
 copy=Str.CloneString(original);&lt;br /&gt;
;Notes&lt;br /&gt;
*CloneString() creates a copy of the string passed. &lt;br /&gt;
*Ordinarily &#039;copying&#039; a string will just create a new object that references the old string. This is not allowed across different contexts.&lt;br /&gt;
*CloneString() creates a new string for use in the current context.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#AlreadyThereStr|TrainUtil.AlreadyThereStr()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#CompareStrLists|TrainUtil.CompareStrLists()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#GetUpTo|TrainUtil.GetUpTo()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasPrefix|TrainUtil.HasPrefix()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasSufix|TrainUtil.HasSufix()]] &#039;&#039;(sic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#StrSubst|TrainUtil.StrSubst()]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36986</id>
		<title>Class Str</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36986"/>
		<updated>2023-04-16T03:22:17Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Language Reference|API Hierarchy]]&lt;br /&gt;
**Str&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Str is a static class providing string utility functions not supported by the native string object. &lt;br /&gt;
*When used in game code these methods must be prefixed &#039;&#039;Str.&#039;&#039; to reference the class.&lt;br /&gt;
*Some of these methods directly amend their parameters rather than returning values via the method.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left==&lt;br /&gt;
{{MethodHeader|public void Left(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = count of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Left(s,5);        // s will now be equal to &amp;quot;After&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself consisting of its first &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mid==&lt;br /&gt;
{{MethodHeader|public void Mid(string s, int first, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;first&#039;&#039;&#039; = index of first character to retain.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Mid(s,3,4);           // s will now be equal to &amp;quot;tern&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself &#039;&#039;count&#039;&#039; characters long starting with the &#039;&#039;first&#039;&#039; character.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;I&amp;gt;To get the output specified you would need the following: Str.Mid(s,2,4); as the string array is zero based. This has been tested using TS2012 build 61388 and TANE. &amp;lt;/I&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Right==&lt;br /&gt;
{{MethodHeader|public void Right(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Right(s,4);           // s will now be equal to &amp;quot;noon&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself composed of the last &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;be&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Find==&lt;br /&gt;
{{MethodHeader|Find(string s, string substr, int startingIndex)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string in which to search&lt;br /&gt;
*&#039;&#039;&#039;substr&#039;&#039;&#039; - substring to find&lt;br /&gt;
*&#039;&#039;&#039;startingIndex&#039;&#039;&#039; - where to start looking down the string i.e. skip the first &#039;n&#039; characters&lt;br /&gt;
;Returned Value&lt;br /&gt;
*index within string that substr starts at. &#039;-1&#039; if not found.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int i = Str.Find(&amp;quot;z&amp;quot;, &amp;quot;amazon&amp;quot;, 1) //returns 4&lt;br /&gt;
;Notes&lt;br /&gt;
*Searches for a substring within a string.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToInt==&lt;br /&gt;
{{MethodHeader|public native int ToInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of an integer.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Integer value of string parameter.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.ToInt(&amp;quot;1234&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to an integer.&lt;br /&gt;
*Method returns 0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToFloat==&lt;br /&gt;
{{MethodHeader|public native float ToFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of a floating point number.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Floating point value.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float length = Str.ToFloat(&amp;quot;1.5&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to a floating point number.&lt;br /&gt;
*Method returns 0.0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tokens==&lt;br /&gt;
{{MethodHeader|public native string[ ] Tokens(string s, string delimiters)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;delimiters&#039;&#039;&#039; = string of characters to use as token boundaries.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Array of string tokens.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string[] sentence = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;);     // sentence contains an array of four strings:&lt;br /&gt;
                                                            // [&amp;quot;Once&amp;quot;,&amp;quot;upon&amp;quot;,&amp;quot;a&amp;quot;,&amp;quot;time&amp;quot;].&lt;br /&gt;
 int wordCount = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;).size();  // returns 4&lt;br /&gt;
 string firstWord = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;)[0];   // returns &amp;quot;Once&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 string kuidStr = &amp;quot;&amp;lt;kuid:1234:5678&amp;gt;&amp;quot;&lt;br /&gt;
 string userID = Str.Tokens(kuidStr,&amp;quot;&amp;lt;:&amp;gt;&amp;quot;)[1];              // returns &amp;quot;1234&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Splits a string into an array of tokens using any of the characters in &#039;&#039;delimiters&#039;&#039; as token boundaries.&lt;br /&gt;
*Characters contained within the &#039;&#039;delimiters&#039;&#039; string are never returned.&lt;br /&gt;
*If &#039;&#039;delimiters&#039;&#039; is null or an empty string then white space will be assumed to define the token boundaries.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToLower==&lt;br /&gt;
{{MethodHeader|public native void ToLower(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToLower(&amp;quot;UPPER CASE STRING&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to lower case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToUpper==&lt;br /&gt;
{{MethodHeader|public native void ToUpper(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToUpper(&amp;quot;lower case string&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to upper case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimLeft==&lt;br /&gt;
{{MethodHeader|public native void TrimLeft(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimLeft(&amp;quot;Once upon a time&amp;quot;,&amp;quot;Once &amp;quot;);      // returns &amp;quot;upon a time&amp;quot;&lt;br /&gt;
 Str.TrimLeft(&amp;quot;      result&amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the front of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimRight==&lt;br /&gt;
{{MethodHeader|public native void TrimRight(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimRight(&amp;quot;Once upon a time&amp;quot;,&amp;quot; a time&amp;quot;);      // returns &amp;quot;Once upon&amp;quot;&lt;br /&gt;
 Str.TrimRight(&amp;quot;result        &amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the end of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackInt==&lt;br /&gt;
{{MethodHeader|public native int UnpackInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First integer value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.UnpackInt(&amp;quot;21st May 2008&amp;quot;);           // returns 21 and amends &#039;&#039;s&#039;&#039; to &amp;quot;st May 2008&amp;quot; &lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first integer value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackFloat==&lt;br /&gt;
{{MethodHeader|public native float UnpackFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First float value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float distance = Str.UnpackFloat(&amp;quot;21.5 miles&amp;quot;);   // returns 21.5 and amends &#039;&#039;s&#039;&#039; to &amp;quot; miles&amp;quot;.&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first floating point value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackString==&lt;br /&gt;
{{MethodHeader|public native string UnpackString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First string in &#039;&#039;s&#039;&#039;, excluding any leading white space.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Once upon a time&amp;quot;;&lt;br /&gt;
 string firstWord = UnpackString(s);     // returns &amp;quot;Once&amp;quot;, s becomes &amp;quot; upon a time&amp;quot;&lt;br /&gt;
 string secondWord = UnpackString(s);    // returns &amp;quot;upon&amp;quot;, s becomes &amp;quot; a time&amp;quot;&lt;br /&gt;
 string thirdWord = UnpackString(s);     // returns &amp;quot;a&amp;quot;,    s becomes &amp;quot; time&amp;quot;&lt;br /&gt;
 string fourthWord = UnpackString(s);    // returns &amp;quot;time&amp;quot;, s becomes &amp;quot;&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first word from the string parameter (using white space for word separation) and returns it in the method result. &lt;br /&gt;
*Any leading white space is removed from the string before parsing.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==CloneString==&lt;br /&gt;
{{MethodHeader|public string CloneString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = The string to clone.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*string - A new string in the current gamescript context which has contents that exactly match the original string.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string original=&amp;quot;Hello World!&amp;quot;&lt;br /&gt;
 string copy;&lt;br /&gt;
 copy=Str.CloneString(original);&lt;br /&gt;
;Notes&lt;br /&gt;
*CloneString() creates a copy of the string passed. &lt;br /&gt;
*Ordinarily &#039;copying&#039; a string will just create a new object that references the old string. This is not allowed across different contexts.&lt;br /&gt;
*CloneString() creates a new string for use in the current context.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#AlreadyThereStr|TrainUtil.AlreadyThereStr()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#CompareStrLists|TrainUtil.CompareStrLists()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#GetUpTo|TrainUtil.GetUpTo()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasPrefix|TrainUtil.HasPrefix()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasSufix|TrainUtil.HasSufix()]] &#039;&#039;(sic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#StrSubst|TrainUtil.StrSubst()]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Help:VE170&amp;diff=36985</id>
		<title>Help:VE170</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Help:VE170&amp;diff=36985"/>
		<updated>2023-04-16T01:56:17Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Failed to open compiled texture &#039;&#039;texture-name&#039;&#039; for &#039;&#039;archive-file-name&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a general failure error for texture files.  It is usually one of two or more messages related to a failure to process a texture file - the other errors provide a more precise description of the problem.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 - VE170: Failed to open compiled texture &#039;coal_3.texture&#039; for &#039;arc:fld:$(local)/hash-2D||kuid2 1234 5678 2.tzarc|&#039;&lt;br /&gt;
&lt;br /&gt;
In this particular case the texture file was missing - the missing file was reported as error [[Help:VE165|VE165]].&lt;br /&gt;
&lt;br /&gt;
If VE170 is reported as the only error, it probably indicates a letter in the texture file is uppercase. For example, Coal_3B.texture should be coal_3b.texture. Otherwise, it is likely an internal processing error.&lt;br /&gt;
[[Category:Validation Errors]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36941</id>
		<title>Class Str</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36941"/>
		<updated>2023-04-09T23:43:42Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* UnpackInt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Language Reference|API Hierarchy]]&lt;br /&gt;
**Str&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Str is a static class providing string utility functions not supported by the native string object. &lt;br /&gt;
*When used in game code these methods must be prefixed &#039;&#039;Str.&#039;&#039; to reference the class.&lt;br /&gt;
*Some of these methods directly amend their parameters rather than returning values via the method.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left==&lt;br /&gt;
{{MethodHeader|public void Left(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = count of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Left(s,5);        // s will now be equal to &amp;quot;After&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself consisting of its first &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mid==&lt;br /&gt;
{{MethodHeader|public void Mid(string s, int first, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;first&#039;&#039;&#039; = index of first character to retain.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Mid(s,3,4);           // s will now be equal to &amp;quot;tern&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself &#039;&#039;count&#039;&#039; characters long starting with the &#039;&#039;first&#039;&#039; character.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;I&amp;gt;To get the output specified you would need the following: Str.Mid(s,2,4); as the string array is zero based. This has been tested using TS2012 build 61388 and TANE. &amp;lt;/I&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Right==&lt;br /&gt;
{{MethodHeader|public void Right(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Right(s,4);           // s will now be equal to &amp;quot;noon&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself composed of the last &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToInt==&lt;br /&gt;
{{MethodHeader|public native int ToInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of an integer.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Integer value of string parameter.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.ToInt(&amp;quot;1234&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to an integer.&lt;br /&gt;
*Method returns 0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToFloat==&lt;br /&gt;
{{MethodHeader|public native float ToFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of a floating point number.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Floating point value.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float length = Str.ToFloat(&amp;quot;1.5&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to a floating point number.&lt;br /&gt;
*Method returns 0.0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tokens==&lt;br /&gt;
{{MethodHeader|public native string[ ] Tokens(string s, string delimiters)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;delimiters&#039;&#039;&#039; = string of characters to use as token boundaries.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Array of string tokens.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string[] sentence = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;);     // sentence contains an array of four strings:&lt;br /&gt;
                                                            // [&amp;quot;Once&amp;quot;,&amp;quot;upon&amp;quot;,&amp;quot;a&amp;quot;,&amp;quot;time&amp;quot;].&lt;br /&gt;
 int wordCount = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;).size();  // returns 4&lt;br /&gt;
 string firstWord = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;)[0];   // returns &amp;quot;Once&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 string kuidStr = &amp;quot;&amp;lt;kuid:1234:5678&amp;gt;&amp;quot;&lt;br /&gt;
 string userID = Str.Tokens(kuidStr,&amp;quot;&amp;lt;:&amp;gt;&amp;quot;)[1];              // returns &amp;quot;1234&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Splits a string into an array of tokens using any of the characters in &#039;&#039;delimiters&#039;&#039; as token boundaries.&lt;br /&gt;
*Characters contained within the &#039;&#039;delimiters&#039;&#039; string are never returned.&lt;br /&gt;
*If &#039;&#039;delimiters&#039;&#039; is null or an empty string then white space will be assumed to define the token boundaries.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToLower==&lt;br /&gt;
{{MethodHeader|public native void ToLower(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToLower(&amp;quot;UPPER CASE STRING&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to lower case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToUpper==&lt;br /&gt;
{{MethodHeader|public native void ToUpper(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToUpper(&amp;quot;lower case string&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to upper case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimLeft==&lt;br /&gt;
{{MethodHeader|public native void TrimLeft(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimLeft(&amp;quot;Once upon a time&amp;quot;,&amp;quot;Once &amp;quot;);      // returns &amp;quot;upon a time&amp;quot;&lt;br /&gt;
 Str.TrimLeft(&amp;quot;      result&amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the front of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimRight==&lt;br /&gt;
{{MethodHeader|public native void TrimRight(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimRight(&amp;quot;Once upon a time&amp;quot;,&amp;quot; a time&amp;quot;);      // returns &amp;quot;Once upon&amp;quot;&lt;br /&gt;
 Str.TrimRight(&amp;quot;result        &amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the end of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackInt==&lt;br /&gt;
{{MethodHeader|public native int UnpackInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First integer value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.UnpackInt(&amp;quot;21st May 2008&amp;quot;);           // returns 21 and amends &#039;&#039;s&#039;&#039; to &amp;quot;st May 2008&amp;quot; &lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first integer value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackFloat==&lt;br /&gt;
{{MethodHeader|public native float UnpackFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First float value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float distance = Str.UnpackFloat(&amp;quot;21.5 miles&amp;quot;);   // returns 21.5 and amends &#039;&#039;s&#039;&#039; to &amp;quot; miles&amp;quot;.&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first floating point value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackString==&lt;br /&gt;
{{MethodHeader|public native string UnpackString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First string in &#039;&#039;s&#039;&#039;, excluding any leading white space.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Once upon a time&amp;quot;;&lt;br /&gt;
 string firstWord = UnpackString(s);     // returns &amp;quot;Once&amp;quot;, s becomes &amp;quot; upon a time&amp;quot;&lt;br /&gt;
 string secondWord = UnpackString(s);    // returns &amp;quot;upon&amp;quot;, s becomes &amp;quot; a time&amp;quot;&lt;br /&gt;
 string thirdWord = UnpackString(s);     // returns &amp;quot;a&amp;quot;,    s becomes &amp;quot; time&amp;quot;&lt;br /&gt;
 string fourthWord = UnpackString(s);    // returns &amp;quot;time&amp;quot;, s becomes &amp;quot;&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first word from the string parameter (using white space for word separation) and returns it in the method result. &lt;br /&gt;
*Any leading white space is removed from the string before parsing.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==CloneString==&lt;br /&gt;
{{MethodHeader|public string CloneString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = The string to clone.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*string - A new string in the current gamescript context which has contents that exactly match the original string.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string original=&amp;quot;Hello World!&amp;quot;&lt;br /&gt;
 string copy;&lt;br /&gt;
 copy=Str.CloneString(original);&lt;br /&gt;
;Notes&lt;br /&gt;
*CloneString() creates a copy of the string passed. &lt;br /&gt;
*Ordinarily &#039;copying&#039; a string will just create a new object that references the old string. This is not allowed across different contexts.&lt;br /&gt;
*CloneString() creates a new string for use in the current context.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#AlreadyThereStr|TrainUtil.AlreadyThereStr()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#CompareStrLists|TrainUtil.CompareStrLists()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#GetUpTo|TrainUtil.GetUpTo()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasPrefix|TrainUtil.HasPrefix()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasSufix|TrainUtil.HasSufix()]] &#039;&#039;(sic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#StrSubst|TrainUtil.StrSubst()]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36940</id>
		<title>Class Str</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=Class_Str&amp;diff=36940"/>
		<updated>2023-04-09T23:43:30Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* UnpackFloat */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[TrainzScript Language Reference|API Hierarchy]]&lt;br /&gt;
**Str&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Str is a static class providing string utility functions not supported by the native string object. &lt;br /&gt;
*When used in game code these methods must be prefixed &#039;&#039;Str.&#039;&#039; to reference the class.&lt;br /&gt;
*Some of these methods directly amend their parameters rather than returning values via the method.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left==&lt;br /&gt;
{{MethodHeader|public void Left(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = count of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Left(s,5);        // s will now be equal to &amp;quot;After&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself consisting of its first &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mid==&lt;br /&gt;
{{MethodHeader|public void Mid(string s, int first, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;first&#039;&#039;&#039; = index of first character to retain.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Mid(s,3,4);           // s will now be equal to &amp;quot;tern&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself &#039;&#039;count&#039;&#039; characters long starting with the &#039;&#039;first&#039;&#039; character.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;I&amp;gt;To get the output specified you would need the following: Str.Mid(s,2,4); as the string array is zero based. This has been tested using TS2012 build 61388 and TANE. &amp;lt;/I&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Right==&lt;br /&gt;
{{MethodHeader|public void Right(string s, int count)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;count&#039;&#039;&#039; = number of characters to retain.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Afternoon&amp;quot;;&lt;br /&gt;
 Str.Right(s,4);           // s will now be equal to &amp;quot;noon&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Sets &#039;&#039;s&#039;&#039; to be a substring of itself composed of the last &#039;&#039;count&#039;&#039; characters.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToInt==&lt;br /&gt;
{{MethodHeader|public native int ToInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of an integer.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Integer value of string parameter.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = Str.ToInt(&amp;quot;1234&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to an integer.&lt;br /&gt;
*Method returns 0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToFloat==&lt;br /&gt;
{{MethodHeader|public native float ToFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string parameter, which should be a string representation of a floating point number.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Floating point value.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float length = Str.ToFloat(&amp;quot;1.5&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts &#039;&#039;s&#039;&#039; to a floating point number.&lt;br /&gt;
*Method returns 0.0 if the string cannot be converted.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tokens==&lt;br /&gt;
{{MethodHeader|public native string[ ] Tokens(string s, string delimiters)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;delimiters&#039;&#039;&#039; = string of characters to use as token boundaries.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*Array of string tokens.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string[] sentence = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;);     // sentence contains an array of four strings:&lt;br /&gt;
                                                            // [&amp;quot;Once&amp;quot;,&amp;quot;upon&amp;quot;,&amp;quot;a&amp;quot;,&amp;quot;time&amp;quot;].&lt;br /&gt;
 int wordCount = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;).size();  // returns 4&lt;br /&gt;
 string firstWord = Str.Tokens(&amp;quot;Once upon a time&amp;quot;,&amp;quot;&amp;quot;)[0];   // returns &amp;quot;Once&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 string kuidStr = &amp;quot;&amp;lt;kuid:1234:5678&amp;gt;&amp;quot;&lt;br /&gt;
 string userID = Str.Tokens(kuidStr,&amp;quot;&amp;lt;:&amp;gt;&amp;quot;)[1];              // returns &amp;quot;1234&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Splits a string into an array of tokens using any of the characters in &#039;&#039;delimiters&#039;&#039; as token boundaries.&lt;br /&gt;
*Characters contained within the &#039;&#039;delimiters&#039;&#039; string are never returned.&lt;br /&gt;
*If &#039;&#039;delimiters&#039;&#039; is null or an empty string then white space will be assumed to define the token boundaries.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToLower==&lt;br /&gt;
{{MethodHeader|public native void ToLower(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToLower(&amp;quot;UPPER CASE STRING&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to lower case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ToUpper==&lt;br /&gt;
{{MethodHeader|public native void ToUpper(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.ToUpper(&amp;quot;lower case string&amp;quot;);&lt;br /&gt;
;Notes&lt;br /&gt;
*Converts the string parameter &#039;&#039;s&#039;&#039; to upper case.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimLeft==&lt;br /&gt;
{{MethodHeader|public native void TrimLeft(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimLeft(&amp;quot;Once upon a time&amp;quot;,&amp;quot;Once &amp;quot;);      // returns &amp;quot;upon a time&amp;quot;&lt;br /&gt;
 Str.TrimLeft(&amp;quot;      result&amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the front of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==TrimRight==&lt;br /&gt;
{{MethodHeader|public native void TrimRight(string s, string trim)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
*&#039;&#039;&#039;trim&#039;&#039;&#039; = characters to remove&lt;br /&gt;
;Returned Value&lt;br /&gt;
*None&lt;br /&gt;
;Syntax&lt;br /&gt;
 Str.TrimRight(&amp;quot;Once upon a time&amp;quot;,&amp;quot; a time&amp;quot;);      // returns &amp;quot;Once upon&amp;quot;&lt;br /&gt;
 Str.TrimRight(&amp;quot;result        &amp;quot;,&amp;quot;&amp;quot;);               // returns &amp;quot;result&lt;br /&gt;
;Notes&lt;br /&gt;
*If &#039;&#039;trim&#039;&#039; is an empty string then all white space will be stripped from the end of the string.&lt;br /&gt;
*Method does not return a value.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackInt==&lt;br /&gt;
{{MethodHeader|public native int UnpackInt(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First integer value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 int n = UnpackInt(&amp;quot;21st May 2008&amp;quot;);           // returns 21 and amends &#039;&#039;s&#039;&#039; to &amp;quot;st May 2008&amp;quot; &lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first integer value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackFloat==&lt;br /&gt;
{{MethodHeader|public native float UnpackFloat(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First float value in &#039;&#039;s&#039;&#039;.&lt;br /&gt;
;Syntax&lt;br /&gt;
 float distance = Str.UnpackFloat(&amp;quot;21.5 miles&amp;quot;);   // returns 21.5 and amends &#039;&#039;s&#039;&#039; to &amp;quot; miles&amp;quot;.&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first floating point value found from the string parameter and returns it in the method result.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UnpackString==&lt;br /&gt;
{{MethodHeader|public native string UnpackString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = string to be processed.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*First string in &#039;&#039;s&#039;&#039;, excluding any leading white space.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string s = &amp;quot;Once upon a time&amp;quot;;&lt;br /&gt;
 string firstWord = UnpackString(s);     // returns &amp;quot;Once&amp;quot;, s becomes &amp;quot; upon a time&amp;quot;&lt;br /&gt;
 string secondWord = UnpackString(s);    // returns &amp;quot;upon&amp;quot;, s becomes &amp;quot; a time&amp;quot;&lt;br /&gt;
 string thirdWord = UnpackString(s);     // returns &amp;quot;a&amp;quot;,    s becomes &amp;quot; time&amp;quot;&lt;br /&gt;
 string fourthWord = UnpackString(s);    // returns &amp;quot;time&amp;quot;, s becomes &amp;quot;&amp;quot;&lt;br /&gt;
;Notes&lt;br /&gt;
*Strips the first word from the string parameter (using white space for word separation) and returns it in the method result. &lt;br /&gt;
*Any leading white space is removed from the string before parsing.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==CloneString==&lt;br /&gt;
{{MethodHeader|public string CloneString(string s)}}&lt;br /&gt;
;Parameters&lt;br /&gt;
*&#039;&#039;&#039;s&#039;&#039;&#039; = The string to clone.&lt;br /&gt;
;Returned Value&lt;br /&gt;
*string - A new string in the current gamescript context which has contents that exactly match the original string.&lt;br /&gt;
;Syntax&lt;br /&gt;
 string original=&amp;quot;Hello World!&amp;quot;&lt;br /&gt;
 string copy;&lt;br /&gt;
 copy=Str.CloneString(original);&lt;br /&gt;
;Notes&lt;br /&gt;
*CloneString() creates a copy of the string passed. &lt;br /&gt;
*Ordinarily &#039;copying&#039; a string will just create a new object that references the old string. This is not allowed across different contexts.&lt;br /&gt;
*CloneString() creates a new string for use in the current context.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Methods==&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#AlreadyThereStr|TrainUtil.AlreadyThereStr()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#CompareStrLists|TrainUtil.CompareStrLists()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#GetUpTo|TrainUtil.GetUpTo()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasPrefix|TrainUtil.HasPrefix()]]&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#HasSufix|TrainUtil.HasSufix()]] &#039;&#039;(sic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Class TrainUtil#StrSubst|TrainUtil.StrSubst()]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
[[Category:Script Class]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=M.pbrmetal&amp;diff=35959</id>
		<title>M.pbrmetal</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=M.pbrmetal&amp;diff=35959"/>
		<updated>2023-02-16T00:37:35Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Blender Material Configuration (2.8+) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[m.pbrmetal]] is the most basic PBR-based material type used in Trainz, and should be the default material type of choice for any mesh unless some specific feature of some other material type is required. All PBR materials are defined using a multitude of texture channels (not just a simple RGB image) which define various aspects of the material on a per-texel basis. One major advantage of this approach is that a single in-game [[material]] can be used to display various different real-world materials, rather than requiring multiple separate in-game materials with different parameters. Trainz uses a Metallic/Roughness style [[Physically Based Rendering|PBR workflow]].&lt;br /&gt;
&lt;br /&gt;
It should be noted that the &amp;quot;metal&amp;quot; in the name of this material refers to the physical property used in the lighting equations; it does not mean that the material is only appropriate for metallic surfaces.&lt;br /&gt;
&lt;br /&gt;
This page describes [[&amp;quot;Trainz-build&amp;quot; number|content format v4.6]] and assumes that the [[FBX file format]] is used as a data source for any meshes.&lt;br /&gt;
&lt;br /&gt;
=Texture Slots=&lt;br /&gt;
The following texture slots are used for this material. All textures should typically have the same dimensions unless they represent a uniform color, however this is not strictly enforced.&lt;br /&gt;
&lt;br /&gt;
==Albedo==&lt;br /&gt;
RGB: The [[albedo map]] defines the base color of each texel. The sRGB color space is used.&lt;br /&gt;
&lt;br /&gt;
Please note that there is no alpha channel support. For the most robust result, the alpha channel should be omitted or set to 1.0 (white). Note that unlike legacy Trainz materials, PBR materials do not autodetect opacity mode based on the texture in use. The content creator must select the appropriate material for their desired outcome. Runtime texture replacement should not expect to replace an opaque texture with a blended or masked texture and have the material update automatically.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Albedo Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbralbedomap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
==Normal==&lt;br /&gt;
RGB: Surface [[normal map]]. This defines which way the surface is facing, relative to the interpolated vertex normals. Since this is an XYZ format rather than color data, it should never be modified in Photoshop. Using Photoshop to add a fourth channel or copy/paste smaller textures into a [[texture atlas]] is acceptable. Per-pixel manipulation or use of filters on the &amp;quot;RGB&amp;quot; channels is not acceptable.&lt;br /&gt;
&lt;br /&gt;
A: [[Parallax Occlusion Map|Displacement height]]. 0.0 represents the deepest possible value, while 1.0 represents the shallowest possible value. While it is possible to paint this data in Photoshop, a linear color space must be used, and far superior results will be available through other data sources. The parallax height and the surface normal must be kept in sync, which means that a third-party tool must be used to generate the surface normal from the parallax height if you are painting this map manually.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Normal Texture Example with no Alpha Channel (Parallax)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbrnormalmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Normal Texture Example with Alpha Channel (Parallax)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbrnormalwithalpha.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
This texture is comprised of four separate channels which each form a separate data element. Linear color space (not sRGB) is used for these channels.&lt;br /&gt;
&lt;br /&gt;
[[File:pbrparametersall.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Emissive - Red Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersemissivemap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:R: Emissive. This causes the texture to have an internal glow, even when no external light is present. Used for phosphors, permanently-lit markings, etc. The glow color is based on the albedo. Note that this glow does not cast light upon surrounding surfaces except via the Bloom post-processing effect. You might want to consider making this a gray / dark gray color on some assets that you want more of the albedo color to show through indirect (ambient) lit surfaces.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Roughness - Green Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersroughnessmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:G: Roughness. Defines whether the surface reflections are shiny (0.0) or matte (1.0). See the [[Physically Based Rendering|PBR metal workflow]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Ambient Occlusion - Blue Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersambientocclusionmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:B: Ambient Occlusion. Defines whether the surface is exposed to ambient lighting conditions (1.0) or affected only by direct lighting (0.0).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Metallic - Alpha Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersmetallicmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:A: Metallicity. Defines whether the surface is metallic (1.0) with the albedo used to colorize reflected light, or dielectric (0.0) with the albedo used to colorize the surface. While intermediate values are not physically accurate, they may be used to emulate subsurfaces which are partially metallic. See the [[Physically Based Rendering|PBR metal workflow]] for details.&lt;br /&gt;
&lt;br /&gt;
=Examples=&lt;br /&gt;
The following images show this material type with a few basic configurations of roughness and metallicity, under identical environmental conditions.&lt;br /&gt;
&lt;br /&gt;
[[File:m.pbrmetal-0.png|border|middle|x200px]] [[File:m.pbrmetal-1.png|border|middle|x200px]] [[File:m.pbrmetal-2.png|border|middle|x200px]] [[File:m.pbrmetal-3.png|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_cast_iron.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(cast_iron).cdp Trainz Material - pbrmetal (cast iron)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_gloss_paint.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(gloss_paint).cdp Trainz Material - pbrmetal (gloss paint)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_painted_metal.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(painted_metal).cdp Trainz Material - pbrmetal (painted metal)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_rubber.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(rubber).cdp Trainz Material - pbrmetal (rubber)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_stainless_steel.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(stainless_steel).cdp Trainz Material - pbrmetal (stainless steel)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:chart_roughness_metallic.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset (route + objects) download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/pbr_roughness_metallic_chart_180831a.cdp PBR Roughness / Metallic Chart]&lt;br /&gt;
&lt;br /&gt;
=3ds Max Material Configuration=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Texture Assignment&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbrmetal3dsmaxtextureassignment.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Blender Material Configuration V2.79b=&lt;br /&gt;
&lt;br /&gt;
You must use the Blender Render option in Blender as the Cycles Render in V2.79b doesn&#039;t export the texture names associated with the material.  &lt;br /&gt;
&lt;br /&gt;
The albedo and normal textures have no special requirements but the parameters texture must use the Influence-&amp;gt;Specular-&amp;gt;Hardness tag (checkbox).  The value of the hardness is not exported by the Blender FBX exporter.  Sample settings are shown below.  Note that the normal texture does not use an alpha channel in this example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Blender_PBRMetal_albedo_setting.jpg|border|middle|x700px]]  [[File:Blender_PBRMetal_normal_setting.jpg|border|middle|x700px]]  [[File:Blender_PBRMetal_parameters_setting.jpg|border|middle|x700px]]&lt;br /&gt;
&lt;br /&gt;
=Blender Material Configuration (2.8+)=&lt;br /&gt;
&lt;br /&gt;
The shader node is a Principled BSDF shader and the FBX exporter supports the export of some texture names but not all.  The following connections should be made:&lt;br /&gt;
&lt;br /&gt;
Albedo texture to the Base Color input.&lt;br /&gt;
&lt;br /&gt;
Parameter texture to the Roughness input.&lt;br /&gt;
&lt;br /&gt;
The normal texture, via a normal converter set to Tangent, to the Normal input.&lt;br /&gt;
&lt;br /&gt;
The 3D view of the mesh does not show a true PBR render.&lt;br /&gt;
&lt;br /&gt;
You will need to update the texture.txt files created by the Trainz FBX importer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MpbrmetalExportBlender2.8beyond.png|border|middle|x700px]]&lt;br /&gt;
&lt;br /&gt;
=Maya LT Material Configuration=&lt;br /&gt;
&lt;br /&gt;
Maya LT uses a Phong shader and the parameters texture should be linked to the shader Cosine Power input via a Set Range node.  Note that the input and output of this node both use Value X.  The Normal Map must be passed through a Bump converter and then connected to the shader Normal input.  The Bump converter &amp;quot;Use as&amp;quot; value within the attributes editor must use the &amp;quot;Tangent Space Normals&amp;quot; option.  See the images below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note.  The material name shown in these images has &amp;quot;FBXASC046&amp;quot; where the full stops (periods) appear in the name box.m.pbrmetal.  Maya LT does not permit full stops (periods) in name and substitutes an underscore which doesn&#039;t work for Trainz.  FBXASC046 gets replaced with a full stop on export.  N3V are looking at this issue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Sample_pbrmetal_material.jpg|border|middle]]&lt;br /&gt;
[[File:Sample_pbrmetal_material_properties.jpg|border|middle]]  [[File:Bump_normal_converter_properties.jpg|border|middle]]&lt;br /&gt;
&lt;br /&gt;
=Substance Painter Export Preset=&lt;br /&gt;
&lt;br /&gt;
Export preset for Substance Painter. This preset puts every map you need into Albedo, Normal and Parameter texture channels. As result you will get 3 textures, ready for importing into game.&lt;br /&gt;
&lt;br /&gt;
The link below is a preset that has height maps enabled by default.   &lt;br /&gt;
&lt;br /&gt;
[https://www.dropbox.com/s/ukp3p8uw53332ay/Trainz2019_WithHeight.spexp?dl=0 Trainz 2019 Exporter with Height Maps Enabled]&lt;br /&gt;
&lt;br /&gt;
The link below contains a preset that does not have height maps enabled, which may be more useful to some on rollingstock.&lt;br /&gt;
&lt;br /&gt;
[https://www.dropbox.com/s/4gzmuzdy8g7nwzc/Trainz2019.spexp?dl=0 Trainz 2019 Exporter with Height Maps Disabled]&lt;br /&gt;
&lt;br /&gt;
==Installing the Preset==&lt;br /&gt;
&lt;br /&gt;
First download either or both presets to your computer from the links above. Open Substance Painter and navigate to File -&amp;gt; Import Resources. &lt;br /&gt;
&lt;br /&gt;
[[File:Step2.png]]&lt;br /&gt;
&lt;br /&gt;
At the top of the new window, click on &amp;quot;Add resources.&amp;quot; Then locate your preset you&#039;d like to import.&lt;br /&gt;
&lt;br /&gt;
[[File:Step3.png]]&lt;br /&gt;
&lt;br /&gt;
After selecting the preset Substance Painter should already recognize that it is an export preset. &lt;br /&gt;
&lt;br /&gt;
[[File:Step4.png]]&lt;br /&gt;
&lt;br /&gt;
In the dropdown window at the bottom right corner of the active window, you can select where you want to save it. You can either save this into your project file you are currently working on, or add it to your shelf. If you save it to your shelf you won&#039;t have to import it for every project, so this is the best method! After you are done, click Import.&lt;br /&gt;
&lt;br /&gt;
[[File:Step5N.png]]&lt;br /&gt;
&lt;br /&gt;
==Exporting Textures==&lt;br /&gt;
&lt;br /&gt;
When you are ready to export your textures from your project, navigate at the top left to File -&amp;gt; Export Textures. &lt;br /&gt;
&lt;br /&gt;
[[File:Step6.png]]&lt;br /&gt;
&lt;br /&gt;
In this new window, select the dropdown window near &amp;quot;Config&amp;quot; and select your Trainz 2019 preset from the dropdown window. After you select which texture size you want to export or which materials to export, hit export and your textures will export! At the top of the window will be the directory where your textures will export to. In my case, it is exporting to K:\Class 47\Textures\game\lit up. You can change the directory by simply clicking on it.&lt;br /&gt;
&lt;br /&gt;
[[File:Step7.png]]&lt;br /&gt;
&lt;br /&gt;
That&#039;s all you have to do! These presets will support all PBR materials including pbrmetalmasked, and glass. However to use alphas you will need to enable opacity in the Texture Set Settings.&lt;br /&gt;
&lt;br /&gt;
[[Category:Material types| ]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Content creation]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=M.pbrmetal&amp;diff=35958</id>
		<title>M.pbrmetal</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=M.pbrmetal&amp;diff=35958"/>
		<updated>2023-02-16T00:37:09Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: /* Blender Material Configuration (2.8+) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[m.pbrmetal]] is the most basic PBR-based material type used in Trainz, and should be the default material type of choice for any mesh unless some specific feature of some other material type is required. All PBR materials are defined using a multitude of texture channels (not just a simple RGB image) which define various aspects of the material on a per-texel basis. One major advantage of this approach is that a single in-game [[material]] can be used to display various different real-world materials, rather than requiring multiple separate in-game materials with different parameters. Trainz uses a Metallic/Roughness style [[Physically Based Rendering|PBR workflow]].&lt;br /&gt;
&lt;br /&gt;
It should be noted that the &amp;quot;metal&amp;quot; in the name of this material refers to the physical property used in the lighting equations; it does not mean that the material is only appropriate for metallic surfaces.&lt;br /&gt;
&lt;br /&gt;
This page describes [[&amp;quot;Trainz-build&amp;quot; number|content format v4.6]] and assumes that the [[FBX file format]] is used as a data source for any meshes.&lt;br /&gt;
&lt;br /&gt;
=Texture Slots=&lt;br /&gt;
The following texture slots are used for this material. All textures should typically have the same dimensions unless they represent a uniform color, however this is not strictly enforced.&lt;br /&gt;
&lt;br /&gt;
==Albedo==&lt;br /&gt;
RGB: The [[albedo map]] defines the base color of each texel. The sRGB color space is used.&lt;br /&gt;
&lt;br /&gt;
Please note that there is no alpha channel support. For the most robust result, the alpha channel should be omitted or set to 1.0 (white). Note that unlike legacy Trainz materials, PBR materials do not autodetect opacity mode based on the texture in use. The content creator must select the appropriate material for their desired outcome. Runtime texture replacement should not expect to replace an opaque texture with a blended or masked texture and have the material update automatically.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Albedo Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbralbedomap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
==Normal==&lt;br /&gt;
RGB: Surface [[normal map]]. This defines which way the surface is facing, relative to the interpolated vertex normals. Since this is an XYZ format rather than color data, it should never be modified in Photoshop. Using Photoshop to add a fourth channel or copy/paste smaller textures into a [[texture atlas]] is acceptable. Per-pixel manipulation or use of filters on the &amp;quot;RGB&amp;quot; channels is not acceptable.&lt;br /&gt;
&lt;br /&gt;
A: [[Parallax Occlusion Map|Displacement height]]. 0.0 represents the deepest possible value, while 1.0 represents the shallowest possible value. While it is possible to paint this data in Photoshop, a linear color space must be used, and far superior results will be available through other data sources. The parallax height and the surface normal must be kept in sync, which means that a third-party tool must be used to generate the surface normal from the parallax height if you are painting this map manually.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Normal Texture Example with no Alpha Channel (Parallax)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbrnormalmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Normal Texture Example with Alpha Channel (Parallax)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbrnormalwithalpha.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
This texture is comprised of four separate channels which each form a separate data element. Linear color space (not sRGB) is used for these channels.&lt;br /&gt;
&lt;br /&gt;
[[File:pbrparametersall.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Emissive - Red Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersemissivemap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:R: Emissive. This causes the texture to have an internal glow, even when no external light is present. Used for phosphors, permanently-lit markings, etc. The glow color is based on the albedo. Note that this glow does not cast light upon surrounding surfaces except via the Bloom post-processing effect. You might want to consider making this a gray / dark gray color on some assets that you want more of the albedo color to show through indirect (ambient) lit surfaces.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Roughness - Green Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersroughnessmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:G: Roughness. Defines whether the surface reflections are shiny (0.0) or matte (1.0). See the [[Physically Based Rendering|PBR metal workflow]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Ambient Occlusion - Blue Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersambientocclusionmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:B: Ambient Occlusion. Defines whether the surface is exposed to ambient lighting conditions (1.0) or affected only by direct lighting (0.0).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Parameters (Metallic - Alpha Channel) Texture Example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:[[File:pbrparametersmetallicmap1.jpg|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
:A: Metallicity. Defines whether the surface is metallic (1.0) with the albedo used to colorize reflected light, or dielectric (0.0) with the albedo used to colorize the surface. While intermediate values are not physically accurate, they may be used to emulate subsurfaces which are partially metallic. See the [[Physically Based Rendering|PBR metal workflow]] for details.&lt;br /&gt;
&lt;br /&gt;
=Examples=&lt;br /&gt;
The following images show this material type with a few basic configurations of roughness and metallicity, under identical environmental conditions.&lt;br /&gt;
&lt;br /&gt;
[[File:m.pbrmetal-0.png|border|middle|x200px]] [[File:m.pbrmetal-1.png|border|middle|x200px]] [[File:m.pbrmetal-2.png|border|middle|x200px]] [[File:m.pbrmetal-3.png|border|middle|x200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_cast_iron.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(cast_iron).cdp Trainz Material - pbrmetal (cast iron)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_gloss_paint.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(gloss_paint).cdp Trainz Material - pbrmetal (gloss paint)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_painted_metal.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(painted_metal).cdp Trainz Material - pbrmetal (painted metal)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_rubber.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(rubber).cdp Trainz Material - pbrmetal (rubber)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:trainz_material_stainless_steel.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/Trainz_Material_-_pbrmetal_(stainless_steel).cdp Trainz Material - pbrmetal (stainless steel)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:chart_roughness_metallic.jpg|border|middle|x512px]]&lt;br /&gt;
&lt;br /&gt;
Example asset (route + objects) download:&lt;br /&gt;
&lt;br /&gt;
[http://download.trainzportal.com/tutorials/pbr_roughness_metallic_chart_180831a.cdp PBR Roughness / Metallic Chart]&lt;br /&gt;
&lt;br /&gt;
=3ds Max Material Configuration=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Texture Assignment&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:pbrmetal3dsmaxtextureassignment.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Blender Material Configuration V2.79b=&lt;br /&gt;
&lt;br /&gt;
You must use the Blender Render option in Blender as the Cycles Render in V2.79b doesn&#039;t export the texture names associated with the material.  &lt;br /&gt;
&lt;br /&gt;
The albedo and normal textures have no special requirements but the parameters texture must use the Influence-&amp;gt;Specular-&amp;gt;Hardness tag (checkbox).  The value of the hardness is not exported by the Blender FBX exporter.  Sample settings are shown below.  Note that the normal texture does not use an alpha channel in this example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Blender_PBRMetal_albedo_setting.jpg|border|middle|x700px]]  [[File:Blender_PBRMetal_normal_setting.jpg|border|middle|x700px]]  [[File:Blender_PBRMetal_parameters_setting.jpg|border|middle|x700px]]&lt;br /&gt;
&lt;br /&gt;
=Blender Material Configuration (2.8+)=&lt;br /&gt;
&lt;br /&gt;
The shader node is a Principled BSDF shader and the FBX exporter supports the export of some texture names but not all.  The following connections should be made:&lt;br /&gt;
&lt;br /&gt;
Albedo texture to the Base Color input.&lt;br /&gt;
&lt;br /&gt;
Parameter texture to the Roughness input.&lt;br /&gt;
&lt;br /&gt;
The normal texture, via a normal converter set to Tangent, to the Normal input.&lt;br /&gt;
&lt;br /&gt;
The 3D view of the mesh does not show a true PBR render.&lt;br /&gt;
&lt;br /&gt;
You will need to update the texture.txt files created by the Trainz FBX importer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MpbrmetalExportBlender2.8beyond.png|border|middle|x600px]]&lt;br /&gt;
&lt;br /&gt;
=Maya LT Material Configuration=&lt;br /&gt;
&lt;br /&gt;
Maya LT uses a Phong shader and the parameters texture should be linked to the shader Cosine Power input via a Set Range node.  Note that the input and output of this node both use Value X.  The Normal Map must be passed through a Bump converter and then connected to the shader Normal input.  The Bump converter &amp;quot;Use as&amp;quot; value within the attributes editor must use the &amp;quot;Tangent Space Normals&amp;quot; option.  See the images below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note.  The material name shown in these images has &amp;quot;FBXASC046&amp;quot; where the full stops (periods) appear in the name box.m.pbrmetal.  Maya LT does not permit full stops (periods) in name and substitutes an underscore which doesn&#039;t work for Trainz.  FBXASC046 gets replaced with a full stop on export.  N3V are looking at this issue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Sample_pbrmetal_material.jpg|border|middle]]&lt;br /&gt;
[[File:Sample_pbrmetal_material_properties.jpg|border|middle]]  [[File:Bump_normal_converter_properties.jpg|border|middle]]&lt;br /&gt;
&lt;br /&gt;
=Substance Painter Export Preset=&lt;br /&gt;
&lt;br /&gt;
Export preset for Substance Painter. This preset puts every map you need into Albedo, Normal and Parameter texture channels. As result you will get 3 textures, ready for importing into game.&lt;br /&gt;
&lt;br /&gt;
The link below is a preset that has height maps enabled by default.   &lt;br /&gt;
&lt;br /&gt;
[https://www.dropbox.com/s/ukp3p8uw53332ay/Trainz2019_WithHeight.spexp?dl=0 Trainz 2019 Exporter with Height Maps Enabled]&lt;br /&gt;
&lt;br /&gt;
The link below contains a preset that does not have height maps enabled, which may be more useful to some on rollingstock.&lt;br /&gt;
&lt;br /&gt;
[https://www.dropbox.com/s/4gzmuzdy8g7nwzc/Trainz2019.spexp?dl=0 Trainz 2019 Exporter with Height Maps Disabled]&lt;br /&gt;
&lt;br /&gt;
==Installing the Preset==&lt;br /&gt;
&lt;br /&gt;
First download either or both presets to your computer from the links above. Open Substance Painter and navigate to File -&amp;gt; Import Resources. &lt;br /&gt;
&lt;br /&gt;
[[File:Step2.png]]&lt;br /&gt;
&lt;br /&gt;
At the top of the new window, click on &amp;quot;Add resources.&amp;quot; Then locate your preset you&#039;d like to import.&lt;br /&gt;
&lt;br /&gt;
[[File:Step3.png]]&lt;br /&gt;
&lt;br /&gt;
After selecting the preset Substance Painter should already recognize that it is an export preset. &lt;br /&gt;
&lt;br /&gt;
[[File:Step4.png]]&lt;br /&gt;
&lt;br /&gt;
In the dropdown window at the bottom right corner of the active window, you can select where you want to save it. You can either save this into your project file you are currently working on, or add it to your shelf. If you save it to your shelf you won&#039;t have to import it for every project, so this is the best method! After you are done, click Import.&lt;br /&gt;
&lt;br /&gt;
[[File:Step5N.png]]&lt;br /&gt;
&lt;br /&gt;
==Exporting Textures==&lt;br /&gt;
&lt;br /&gt;
When you are ready to export your textures from your project, navigate at the top left to File -&amp;gt; Export Textures. &lt;br /&gt;
&lt;br /&gt;
[[File:Step6.png]]&lt;br /&gt;
&lt;br /&gt;
In this new window, select the dropdown window near &amp;quot;Config&amp;quot; and select your Trainz 2019 preset from the dropdown window. After you select which texture size you want to export or which materials to export, hit export and your textures will export! At the top of the window will be the directory where your textures will export to. In my case, it is exporting to K:\Class 47\Textures\game\lit up. You can change the directory by simply clicking on it.&lt;br /&gt;
&lt;br /&gt;
[[File:Step7.png]]&lt;br /&gt;
&lt;br /&gt;
That&#039;s all you have to do! These presets will support all PBR materials including pbrmetalmasked, and glass. However to use alphas you will need to enable opacity in the Texture Set Settings.&lt;br /&gt;
&lt;br /&gt;
[[Category:Material types| ]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Content creation]]&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
	<entry>
		<id>https://wiki.trainzsimulator.com/index.php?title=File:MpbrmetalExportBlender2.8beyond.png&amp;diff=35957</id>
		<title>File:MpbrmetalExportBlender2.8beyond.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.trainzsimulator.com/index.php?title=File:MpbrmetalExportBlender2.8beyond.png&amp;diff=35957"/>
		<updated>2023-02-16T00:35:19Z</updated>

		<summary type="html">&lt;p&gt;Dundun92: The proper shader configuration for m.pbrmetal textures in Blender (2.8+)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The proper shader configuration for m.pbrmetal textures in Blender (2.8+)&lt;/div&gt;</summary>
		<author><name>Dundun92</name></author>
	</entry>
</feed>