User Tools

Site Tools


manual:subwaysim:vehicle_development:vehicle_lua

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
manual:subwaysim:vehicle_development:vehicle_lua [2026/01/13 08:08] – [Coupling Configuration] dcsmanual:subwaysim:vehicle_development:vehicle_lua [2026/01/13 19:57] (current) dcs
Line 32: Line 32:
  author = "$GameDeveloper",  author = "$GameDeveloper",
  
- emptyMass = 37.0, + emptyMass = 37.0, 
- vmax = 70,+ vmax = 70,
  
- length = 12.64,+ length = 12.64,
  frontToFirstBogie = 2.53,  frontToFirstBogie = 2.53,
  rearToLastBogie = 2.53,  rearToLastBogie = 2.53,
Line 170: Line 170:
  
 ---@type RailVehicle_DataTable ---@type RailVehicle_DataTable
-local GI1E_b  = TableUtil.deepCopy(GI1E_a); +local GI1E_b  = TableUtil.deepCopy(GI1E_a); 
-GI1E_b.components  = GI1E_a.components; -- TODO +GI1E_b.components  = GI1E_a.components; -- TODO 
-GI1E_b.contentName  = "Berlin_GI1E_b"; +GI1E_b.contentName  = "Berlin_GI1E_b"; 
-GI1E_b.blueprintFilename  = "/SubwaySim_Berlin/Vehicles/GI1E/BP_GI1E_B.BP_GI1E_B"; +GI1E_b.blueprintFilename  = "/SubwaySim_Berlin/Vehicles/GI1E/BP_GI1E_B.BP_GI1E_B"; 
-GI1E_b.lights.headLights = nil; +GI1E_b.lights.headLights = nil; 
-GI1E_b.lights.tailLights = nil;+GI1E_b.lights.tailLights = nil;
 GI1E_b.couplingFront.couplingBoneName = "Coupling_Rotation3"; GI1E_b.couplingFront.couplingBoneName = "Coupling_Rotation3";
 GI1E_b.couplingRear.couplingBoneName = "Coupling_Rotation4"; GI1E_b.couplingRear.couplingBoneName = "Coupling_Rotation4";
Line 568: Line 568:
 ---- ----
  
-(Continuation follows: copying variants with `deepCopy`, defining TrainCompositions, and registering content via `g_contentManager:addContent()`.)+===== Creating a Variant Vehicle using deepCopy ===== 
 + 
 +In this section, we create a **variant** of an existing vehicle by copying an already defined `RailVehicle_DataTable` and adjusting only the values that differ. 
 + 
 +This approach is very common and highly recommended, especially for: 
 +  * A- and B-cars 
 +  * Direction-dependent variants 
 +  * Slightly different vehicle bodies sharing the same base configuration 
 + 
 +Instead of defining the entire vehicle again, we reuse the existing data. 
 + 
 +---- 
 + 
 +==== Copying the Base Vehicle ==== 
 + 
 +<code lua> 
 +---@type RailVehicle_DataTable 
 +local GI1E_b = TableUtil.deepCopy(GI1E_a); 
 +</code> 
 + 
 +This line creates a **deep copy** of the previously defined vehicle `GI1E_a`. 
 + 
 +Important points: 
 +  * All values from `GI1E_a` are copied into `GI1E_b` 
 +  * Nested tables (lights, brakes, couplings, etc.) are copied as well 
 +  * Changes made to `GI1E_b` do **not** affect `GI1E_a` 
 + 
 +This gives us a fully independent vehicle configuration that starts as a 1:1 copy. 
 + 
 +---- 
 + 
 +==== Reusing Component Definitions ==== 
 + 
 +<code lua> 
 +GI1E_b.components = GI1E_a.components; -- TODO 
 +</code> 
 + 
 +Here, the component list is explicitly reused. 
 + 
 +This means: 
 +  * Both vehicles use the same Lua components (LightManager, AudioManager, PIS, etc.) 
 +  * This is safe as long as the component behavior is identical 
 +  * The comment `-- TODO` indicates that this could be changed later if needed 
 + 
 +This avoids unnecessary duplication of identical component lists. 
 + 
 +---- 
 + 
 +==== Changing the Content Name ==== 
 + 
 +<code lua> 
 +GI1E_b.contentName = "Berlin_GI1E_b"; 
 +</code> 
 + 
 +Each vehicle must have a **unique `contentName`**. 
 + 
 +Even though `GI1E_b` is based on `GI1E_a`, it must be registered as a separate vehicle in the Content Manager. 
 + 
 +This name is later used: 
 +  * in train compositions 
 +  * when spawning vehicles 
 +  * internally by the game 
 + 
 +---- 
 + 
 +==== Assigning a Different Blueprint ==== 
 + 
 +<code lua> 
 +GI1E_b.blueprintFilename = "/SubwaySim_Berlin/Vehicles/GI1E/BP_GI1E_B.BP_GI1E_B"; 
 +</code> 
 + 
 +The B-car uses a **different Vehicle Blueprint**. 
 + 
 +Typical reasons for this: 
 +  * Different interior layout 
 +  * No driver cab 
 +  * Different light setup 
 +  * Different coupling setup 
 + 
 +Even though most logic is shared, the physical Blueprint can differ. 
 + 
 +---- 
 + 
 +==== Removing Head- and Taillights ==== 
 + 
 +<code lua> 
 +GI1E_b.lights.headLights = nil; 
 +GI1E_b.lights.tailLights = nil; 
 +</code> 
 + 
 +In this case, the B-car does **not** have its own headlights or taillights. 
 + 
 +By setting these entries to `nil`: 
 +  * The light definitions inherited from `GI1E_a` are removed 
 +  * The vehicle will not attempt to control head- or taillights 
 +  * This prevents duplicated or incorrect lighting inside a train consist 
 + 
 +This is typical for intermediate cars in a multiple-unit train. 
 + 
 +---- 
 + 
 +==== Adjusting Coupling Bone Names ==== 
 + 
 +<code lua> 
 +GI1E_b.couplingFront.couplingBoneName = "Coupling_Rotation3"; 
 +GI1E_b.couplingRear.couplingBoneName  = "Coupling_Rotation4"; 
 +</code> 
 + 
 +The B-car uses **different coupling bones** than the A-car. 
 + 
 +Reasons for this include: 
 +  * Different skeleton layout 
 +  * Additional coupling bones for internal train connections 
 +  * Separate animation channels for different couplers 
 + 
 +Only the bone names are changed — all other coupling parameters remain the same. 
 + 
 +---- 
 + 
 +==== Summary: Differences Between GI1E_a and GI1E_b ==== 
 + 
 +^ Aspect ^ GI1E_a (A-car) ^ GI1E_b (B-car) ^ 
 +| Base data | Fully defined | Copied from GI1E_a | 
 +| Blueprint | BP_GI1E_A | BP_GI1E_B | 
 +| Lights | Head- and tail lights present | No head- or tail lights | 
 +| Coupling bones | Rotation1 / Rotation2 | Rotation3 / Rotation4 | 
 +| Components | Own list | Reused from GI1E_a | 
 +| contentName | Berlin_GI1E_a | Berlin_GI1E_b | 
 + 
 +Using `TableUtil.deepCopy` keeps your Lua files cleanmaintainable, and easy to extend when creating multiple vehicle variants. 
 + 
 +---- 
 + 
 +===== Train Compositions and Content Registration ===== 
 + 
 +At the end of the file comes one of the most important parts:   
 +**Train compositions** and the registration of all DataTables in the **Content Manager**. 
 + 
 +Without these steps, the game would know that the vehicle exists as a data table — but it would not know: 
 +  * how to spawn it as a full train consist, 
 +  * and it would not load the content at all. 
 + 
 +---- 
 + 
 +==== What is a TrainComposition_DataTable? ==== 
 + 
 +`TrainComposition_DataTable` defines a **complete train consist** (multiple vehicles in a fixed order). 
 + 
 +AI trains in SubwaySim 2 are usually spawned using **train compositions**, not single vehicles. 
 + 
 +That is why this section is essential for AI vehicles. 
 + 
 +---- 
 + 
 +==== Example: GI1E_1x (one train unit) ==== 
 + 
 +<code lua> 
 +---@type TrainComposition_DataTable 
 +local GI1E_1x = { 
 +    contentType     = "trainComposition", 
 +    contentName     = "Berlin_GI1e_1x", 
 + 
 +    title           = "GI1e x1", 
 +    author          = "Simuverse GmbH", 
 + 
 +    -- not required for AI trains 
 +    description         = "", 
 +    previewFilename     = "", 
 +    hidden              = true, 
 + 
 +    vehicles = { 
 +        { contentName = "Berlin_GI1E_a", forward = true  }, 
 +        { contentName = "Berlin_GI1E_b", forward = true  }, 
 +        { contentName = "Berlin_GI1E_b", forward = false }, 
 +        { contentName = "Berlin_GI1E_a", forward = false }, 
 +    }, 
 +}; 
 +</code> 
 + 
 +^ Field ^ Meaning ^ 
 +| `contentType = "trainComposition"` | Defines that this table is a train composition. | 
 +| `contentName` | Internal unique identifier for this consist. Used by the Content Manager and spawners. | 
 +| `title` | Display name (used in menus or debug lists). | 
 +| `author` | Author name. | 
 +| `hidden = true` | Hides this composition from the vehicle selection menu. Very common for AI-only trains. | 
 +| `vehicles` | The ordered list of vehicles that form the train consist. | 
 + 
 +---- 
 + 
 +==== The vehicles list ==== 
 + 
 +The most important part is the `vehicles = { ... }` block. 
 + 
 +Each entry uses: 
 + 
 +^ Field ^ Meaning ^ 
 +| `contentName` | Refers to a vehicle previously defined and registered (e.g. `Berlin_GI1E_a`). | 
 +| `forward` | Defines the orientation of that vehicle inside the consist. `true` means forward-facing, `false` means reversed. | 
 + 
 +This is where you can clearly see why `contentName` is so important: 
 +It acts as the unique key that links your **vehicle DataTables** into a full train consist. 
 + 
 +---- 
 + 
 +==== Example: GI1E_2x (two units coupled) ==== 
 + 
 +The 2x consist simply repeats the same unit again, resulting in a longer AI train. 
 + 
 +<code lua> 
 +---@type TrainComposition_DataTable 
 +local GI1E_2x = { 
 +    contentType     = "trainComposition", 
 +    contentName     = "Berlin_GI1e_2x", 
 + 
 +    title           = "GI1e x2", 
 +    author          = "Simuverse GmbH", 
 + 
 +    -- not required for AI trains 
 +    description         = "", 
 +    previewFilename     = "", 
 +    hidden              = true, 
 + 
 +    vehicles = { 
 +        { contentName = "Berlin_GI1E_a", forward = true  }, 
 +        { contentName = "Berlin_GI1E_b", forward = true  }, 
 +        { contentName = "Berlin_GI1E_b", forward = false }, 
 +        { contentName = "Berlin_GI1E_a", forward = false }, 
 + 
 +        { contentName = "Berlin_GI1E_a", forward = true  }, 
 +        { contentName = "Berlin_GI1E_b", forward = true  }, 
 +        { contentName = "Berlin_GI1E_b", forward = false }, 
 +        { contentName = "Berlin_GI1E_a", forward = false }, 
 +    }, 
 +}; 
 +</code> 
 + 
 +---- 
 + 
 +==== Registering Content with the Content Manager ==== 
 + 
 +At the very end, we must register all content tables so SubwaySim 2 actually loads them. 
 + 
 +<code lua> 
 +g_contentManager:addContent(GI1E_a)
 +g_contentManager:addContent(GI1E_b); 
 +g_contentManager:addContent(GI1E_1x); 
 +g_contentManager:addContent(GI1E_2x); 
 +</code> 
 + 
 +This does two things: 
 +  * It tells the game: **"These DataTables exist and should be loaded."** 
 +  * It makes the `contentName` entries usable by the spawning and AI systems. 
 + 
 +Important: 
 +  * We pass the **local Lua variables** here (e.g. `GI1E_a`), not the string names. 
 +  * If you forget to register a table, it will not exist in the game content system. 
 + 
 +---- 
 + 
 +==== Summary ==== 
 + 
 +  * `RailVehicle_DataTable` defines **single vehicles** 
 +  * `TrainComposition_DataTable` defines **AI train consists** 
 +  * `g_contentManager:addContent(...)` is required so SubwaySim 2 loads the vehicles and compositions at all 
 + 
 +With this section completed, the vehicle and its AI train compositions are fully registered and can be used by SubwaySim 2. 
 + 
 +---- 
 + 
 +===== What's Next? ===== 
 + 
 +This page covered the setup of a **simple vehicle.lua**, mainly intended for AI-operated trains. 
 + 
 +If you want to create more advanced vehicles — such as player-driven trains, vehicles with interactive cabs, advanced systems, or extended logic — you will find further detailed information in the following chapters: 
 + 
 +  * **[[manual:subwaysim:vehicle_development:complex_vehicle_blueprint|Complex Vehicle Blueprint]]**   
 +    Learn how to build advanced vehicle Blueprints with interactive components, cab logic, and extended systems. 
 + 
 +  * **[[manual:subwaysim:vehicle_development:complex_vehicle_lua|Complex Vehicle.lua]]**   
 +    Explore advanced Lua setups including player controls, extended systems, and complex vehicle behavior. 
 + 
 +These chapters expand on the foundations explained here and guide you step by step towards fully-featured, player-ready vehicles. 
 + 
  
  
 {{page>manual:footer}} {{page>manual:footer}}
  
manual/subwaysim/vehicle_development/vehicle_lua.1768288129.txt.gz · Last modified: by dcs

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki