Skip to content

Commit

Permalink
Automatic merge of T1.5.1-145-g5f2ded579 and 12 pull requests
Browse files Browse the repository at this point in the history
- Pull request #652 at 918fdb1: Add button functions to Raildriver
- Pull request #706 at 570ab21: Extended door functionality
- Pull request #719 at 13a1638: Upgraded to MonoGame 3.8.0 (+ small update for other libraries)
- Pull request #722 at fb9079e: Fix Windows Forms deprecations in ActivityEditor
- Pull request #732 at 9cffa6d: Improvements for air brakes
- Pull request #740 at b3e66ca: Refactored the circuit breaker and the traction cut-off relay in order to use the same design pattern as the C# signal scripts (compatible with current scripts)
- Pull request #744 at 3c2dc07: Fixed and improved cabview control conditions related to power supply state
- Pull request #746 at 4609acb: Website release 1.5.1
- Pull request #748 at 4f0e878: latitude/longitude fix for bug 1393111
- Pull request #749 at db5764c: OpenRailway Map
- Pull request #753 at ab8fe32: Extends CabControls for user input
- Pull request #754 at 70a1325: Container weights: https://blueprints.launchpad.net/or/+spec/container-weights
  • Loading branch information
openrails-bot committed Dec 9, 2022
14 parents 854144b + 5f2ded5 + 918fdb1 + 570ab21 + 13a1638 + fb9079e + 9cffa6d + b3e66ca + 3c2dc07 + 4609acb + 4f0e878 + db5764c + ab8fe32 + 70a1325 commit 329e0d5
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 24 deletions.
47 changes: 36 additions & 11 deletions Source/Documentation/Manual/features-rollingstock.rst
Expand Up @@ -599,6 +599,8 @@ Here below a sample of a ``.load-or`` file::
"Shape" : "COMMON_Container_3d\\Cont_40ftHC\\container-40ftHC_Triton.s",
"ContainerType" : "C40ftHC",
"IntrinsicShapeOffset": [0,1.175,0],
"EmptyMassKG": 2100.,
"MaxMassWhenLoadedKG": 28000.,
}
}

Expand All @@ -621,20 +623,30 @@ Here below a sample of a ``.load-or`` file::
container with respect to the container shape file coordinates. Unfortunately often such
offset is not [0,0,0], which would be advisable for newly produced containers. A simple way to
state such offset is to use the ``Show Bounding Info`` of ``Shape Viewer``.
- "EmptyMassKG" is an optional parameter that defines the tare (weight when empty) of the
container. If the parameter is not present, OR uses a default parameter, specific for that
ContainerType.
- "MaxMassWhenLoadedKG" is an optional parameter that defines the sum of the tare plus the maximum
allowed payload. As above, if the parameter is not present, OR uses a default parameter, specific for that
ContainerType.


Pre-setting a .wag file to accommodate containers
-------------------------------------------------

As a minimum following block must be present in the .wag file for a double stacker::

ORTSFreightAnims (
WagonEmptyWeight ( 12.575t )
LoadingAreaLength ( 12.20 )
AboveLoadingAreaLength ( 12.20 )
DoubleStacker ()
Offset( 0 0.34 0 )
IntakePoint ( 0 6.0 Container)
)

- WagonEmptyWeight is the weight of the wagon, when it has neither containers nor other
weighing freight animations on board
- LoadingAreaLength is the length in meters of the loading area available for containers
- AboveLoadingAreaLength is the length in meters of the above loading area available
for containers (parameter not needed if not double stacker)
Expand Down Expand Up @@ -694,9 +706,9 @@ shown here::

Wagon (
WagonData ( DTTX_620040_A ATW.DTTX_620040 )
LoadData ( 20cmacgm common.containerdata CenterFront)
LoadData ( 20hamburgsud common.containerdata CenterRear)
LoadData ( 40msc common.containerdata Above)
LoadData ( 20cmacgm common.containerdata CenterFront Empty)
LoadData ( 20hamburgsud common.containerdata CenterRear Loaded)
LoadData ( 40msc common.containerdata Above Random)
UiD ( 11 )
)

Expand All @@ -707,7 +719,17 @@ present. The meaning of the parameters is as follows:
- The first parameter is the name of the ``.load-or`` file
- The second parameter is the path (having ``Trainset`` as base path) where the ``.load-or``
file resides
- The third parameter indicates where the container is allocated on the wagon.
- The third parameter indicates where the container is allocated on the wagon
- The fourth parameter, which is optional, defines the load state of the related container,
which is used to derive the weight of the container. If ``Empty`` is present, the weight
of the empty container is used as actual weight; if ``Loaded`` is present, the maximum
weight (tare + payload) of the container is used; if ``Random`` is present, the weight
is computed as follows: a random number between 0 and 100 is generated. If the number is
below 31, the container is considered empty; else the number is used as percentage of the
maximum weight of the container (tare + payload). The weight of the containers are added to
the empty weight of the wagon, to compute the total weight of the wagon. If the parameter
is not present, the ``Random`` value is assumed.


The entry for the container allocated ``Above`` must be the last one.

Expand All @@ -733,18 +755,19 @@ A minimum ``FreightAnimations`` entry in a ``.wag`` file to have the same pre-lo
set as in the previous paragraph is as follows::

ORTSFreightAnims (
WagonEmptyWeight ( 12.575t )
LoadingAreaLength ( 14.6 )
AboveLoadingAreaLength ( 16.15 )
DoubleStacker ()
Offset( 0 0.34 0 )
IntakePoint ( 0 6.0 Container)
LoadData ( 20cmacgm common.containerdata CenterFront)
LoadData ( 20hamburgsud common.containerdata CenterRear)
LoadData ( 40msc common.containerdata Above)
LoadData ( 20cmacgm common.containerdata CenterFront Empty)
LoadData ( 20hamburgsud common.containerdata CenterRear Loaded)
LoadData ( 40msc common.containerdata Above Random)
)

As can be seen, the syntax of the ``LoadData`` entries is the same as in the case of
the ``.con`` file.
the ``.con`` file. Also here the fourth parameter is optional.

Obviously, using ``.wag`` files for this type of info, a different ``.wag`` file must
be created for every desired pre-loaded set of containers.
Expand Down Expand Up @@ -1048,9 +1071,9 @@ The ``.load-stations-loads-or`` file is a Json file. An example is shown here be
{
"LoadStationID" : { "wfile" : "w-005354+014849.w", "UiD" : 21, },
"LoadData" : [
{ "File" : "40HCcai", "Folder" : "common.containerdata", "StackLocation" : 0, },
{ "File" : "40HCcai", "Folder" : "common.containerdata", "StackLocation" : 0, },
{ "File" : "20cmacgm", "Folder" : "common.containerdata", "StackLocation" : 2, },
{ "File" : "40HCcai", "Folder" : "common.containerdata", "StackLocation" : 0, "LoadState" : "Empty"},
{ "File" : "40HCcai", "Folder" : "common.containerdata", "StackLocation" : 0, "LoadState" : "Loaded"},
{ "File" : "20cmacgm", "Folder" : "common.containerdata", "StackLocation" : 2, "LoadState" : "Random"},
{ "File" : "20kline", "Folder" : "common.containerdata", "StackLocation" : 2, },
{ "File" : "45HCtriton", "Folder" : "common.containerdata", "StackLocation" : 5, },
{ "File" : "45HCtriton", "Folder" : "common.containerdata", "StackLocation" : 5, },
Expand Down Expand Up @@ -1081,6 +1104,8 @@ The file can define the population at startup of many container stations.
index refers to a child stack location.
- If more than a container is defined for a stack location, they are stacked one above the
other.
- The ``LoadState`` parameter is optional, and has the same meaning and values as the
parameter of the same name which can be present in .con or .wag files.

The container station population file must be written taking into account the constraints
of the stack locations (container length must be smaller than stack location lenght,
Expand Down
10 changes: 10 additions & 0 deletions Source/ORTS.Common/enums.cs
Expand Up @@ -72,4 +72,14 @@ public enum LoadPosition
Above
}

/// <summary>
/// Defines the loading state of a load (e.g. a container) on a wagon
/// </summary>
public enum LoadState
{
Random,
Empty,
Loaded,
}

}
12 changes: 10 additions & 2 deletions Source/Orts.Formats.Msts/ActivityFile.cs
Expand Up @@ -296,6 +296,7 @@ public struct LoadData
public string Name;
public string Folder;
public LoadPosition LoadPosition;
public LoadState LoadState;
}

/// <summary>
Expand Down Expand Up @@ -1341,8 +1342,15 @@ public class Wagon {
loadData.Folder = stf.ReadString();
var positionString = stf.ReadString();
Enum.TryParse(positionString, out loadData.LoadPosition);
LoadDataList.Add(loadData);
stf.MustMatch(")");
var state = stf.ReadString();
if (state != ")")
{
Enum.TryParse(state, out loadData.LoadState);
LoadDataList.Add(loadData);
stf.MustMatch(")");
}
else
LoadDataList.Add(loadData);
}),
});
}
Expand Down
5 changes: 4 additions & 1 deletion Source/Orts.Formats.OR/ContainerFile.cs
Expand Up @@ -65,7 +65,8 @@ public class ContainerParameters
public string ShapeFileName;
public string ContainerType;
public Vector3 IntrinsicShapeOffset = new Vector3(0f, 1.17f, 0f);

public float EmptyMassKG = -1;
public float MaxMassWhenLoadedKG = -1;

public ContainerParameters(JsonReader json)
{
Expand All @@ -80,6 +81,8 @@ bool TryParse(JsonReader item)
case "Shape": ShapeFileName = item.AsString(ShapeFileName); break;
case "ContainerType": ContainerType = item.AsString("40ftHC"); break;
case "IntrinsicShapeOffset[]": IntrinsicShapeOffset = item.AsVector3(Vector3.Zero); break;
case "EmptyMassKG": EmptyMassKG = item.AsFloat(-1); break;
case "MaxMassWhenLoadedKG": MaxMassWhenLoadedKG = item.AsFloat(-1); break;
default: return false;
}
return true;
Expand Down
4 changes: 4 additions & 0 deletions Source/Orts.Formats.OR/LoadStationsPopulationFile.cs
Expand Up @@ -22,7 +22,9 @@
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Orts.Formats.Msts;
using Orts.Parsers.OR;
using ORTS.Common;

namespace Orts.Formats.OR
{
Expand Down Expand Up @@ -113,6 +115,7 @@ public class LoadDataEntry
public string FileName;
public string FolderName;
public int StackLocation;
public LoadState LoadState;

public LoadDataEntry(JsonReader json)
{
Expand All @@ -126,6 +129,7 @@ bool TryParse(JsonReader item)
case "File": FileName = item.AsString(""); break;
case "Folder": FolderName = item.AsString(""); break;
case "StackLocation": StackLocation = item.AsInteger(0); break;
case "LoadState": Enum.TryParse(item.AsString(""), out LoadState); break;
default: return false;
}
return true;
Expand Down
31 changes: 28 additions & 3 deletions Source/Orts.Simulation/Simulation/Container.cs
Expand Up @@ -66,14 +66,17 @@ public enum Status
public string ShapeFileName;
public string BaseShapeFileFolderSlash;
public float MassKG = 2000;
public float EmptyMassKG;
public float MaxMassWhenLoadedKG;
public float WidthM = 2.44f;
public float LengthM = 12.19f;
public float HeightM = 2.59f;
public ContainerType ContainerType = ContainerType.C40ft;
public bool Flipped = false;
public static float Length20ftM = 6.095f;
public static float Length40ftM = 12.19f;

public static float[] DefaultEmptyMassKG = { 0, 2160, 3900, 4100, 4500, 4700, 4900, 5040 };
public static float[] DefaultMaxMassWhenLoadedKG = { 0, 24000, 30500, 30500, 30500, 30500, 30500, 30500 };
public WorldPosition WorldPosition = new WorldPosition(); // current position of the container
public float RealRelativeYOffset = 0;
public float RealRelativeZOffset = 0;
Expand Down Expand Up @@ -117,6 +120,8 @@ public virtual void Copy(Container containerCopy)
ComputeDimensions();
Flipped = containerCopy.Flipped;
MassKG = containerCopy.MassKG;
EmptyMassKG = containerCopy.EmptyMassKG;
MaxMassWhenLoadedKG = containerCopy.MaxMassWhenLoadedKG;
}

public Container(BinaryReader inf, FreightAnimationDiscrete freightAnimDiscrete, ContainerHandlingItem containerStation, bool fromContainerStation, int stackLocationIndex = 0)
Expand All @@ -134,6 +139,8 @@ public Container(BinaryReader inf, FreightAnimationDiscrete freightAnimDiscrete,
ComputeDimensions();
Flipped = inf.ReadBoolean();
MassKG = inf.ReadSingle();
EmptyMassKG = inf.ReadSingle();
MaxMassWhenLoadedKG = inf.ReadSingle();
if (fromContainerStation)
{
// compute WorldPosition starting from offsets and position of container station
Expand Down Expand Up @@ -231,6 +238,8 @@ public void Save(BinaryWriter outf, bool fromContainerStation = false)
outf.Write((int)ContainerType);
outf.Write(Flipped);
outf.Write(MassKG);
outf.Write(EmptyMassKG);
outf.Write(MaxMassWhenLoadedKG);
if (fromContainerStation)
{

Expand All @@ -254,6 +263,8 @@ public void LoadFromContainerFile(string loadFilePath, string baseFolder)
ComputeDimensions();
IntrinsicShapeOffset = containerParameters.IntrinsicShapeOffset;
IntrinsicShapeOffset.Z *= -1;
EmptyMassKG = containerParameters.EmptyMassKG != -1 ? containerParameters.EmptyMassKG : DefaultEmptyMassKG[(int)ContainerType] ;
MaxMassWhenLoadedKG = containerParameters.MaxMassWhenLoadedKG != -1 ? containerParameters.MaxMassWhenLoadedKG : DefaultMaxMassWhenLoadedKG[(int)ContainerType];
}

public void ComputeWorldPosition (FreightAnimationDiscrete freightAnimDiscrete)
Expand Down Expand Up @@ -511,14 +522,14 @@ public void PreloadContainerStation(PickupObj thisWorldObj)
Trace.TraceWarning($"Ignored missing load {loadFilePath}");
continue;
}
Preload(loadFilePath, loadDataEntry.StackLocation);
Preload(loadFilePath, loadDataEntry.StackLocation, loadDataEntry.LoadState);
}
break;
}
}
}

public void Preload(string loadFilePath, int stackLocationIndex)
public void Preload(string loadFilePath, int stackLocationIndex, LoadState loadState)
{
Container container;
container = new Container(null, loadFilePath, this);
Expand All @@ -531,6 +542,20 @@ public void Preload(string loadFilePath, int stackLocationIndex)
container.LoadFromContainerFile(loadFilePath, Simulator.BasePath + @"\trains\trainset\");
ContainerManager.LoadedContainers.Add(loadFilePath, container);
}
switch (loadState)
{
case LoadState.Empty:
container.MassKG = container.EmptyMassKG;
break;
case LoadState.Loaded:
container.MassKG = container.MaxMassWhenLoadedKG;
break;
case LoadState.Random:
var loadPercent = Simulator.Random.Next(101);
if (loadPercent < 30) container.MassKG = container.EmptyMassKG;
else container.MassKG = container.MaxMassWhenLoadedKG * loadPercent / 100f;
break;
}
var stackLocation = StackLocations[stackLocationIndex];
if (stackLocation.Containers != null && stackLocation.Containers.Count >= stackLocation.MaxStackedContainers)
Trace.TraceWarning("Stack Location {0} is full, can't lay down container", stackLocationIndex);
Expand Down
34 changes: 31 additions & 3 deletions Source/Orts.Simulation/Simulation/RollingStocks/MSTSWagon.cs
Expand Up @@ -853,8 +853,17 @@ public virtual void LoadFromWagFile(string wagFilePath)
if (!FreightAnimations.MSTSFreightAnimEnabled) FreightShapeFileName = null;
if (FreightAnimations.WagonEmptyWeight != -1)
{

MassKG = FreightAnimations.WagonEmptyWeight + FreightAnimations.FreightWeight + FreightAnimations.StaticFreightWeight;
// Computes mass when it carries containers
float totalContainerMassKG = 0;
if (FreightAnimations.Animations != null)
{
foreach (var anim in FreightAnimations.Animations)
if (anim is FreightAnimationDiscrete discreteAnim && discreteAnim.Container != null)
{
totalContainerMassKG += discreteAnim.Container.MassKG;
}
}
MassKG = FreightAnimations.WagonEmptyWeight + FreightAnimations.FreightWeight + FreightAnimations.StaticFreightWeight + totalContainerMassKG;

if (FreightAnimations.StaticFreightAnimationsPresent) // If it is static freight animation, set wagon physics to full wagon value
{
Expand Down Expand Up @@ -1955,7 +1964,6 @@ public override void Update(float elapsedClockSeconds)
FreightAnimations.LoadedOne = null;
FreightAnimations.FreightType = PickupType.None;
}
if (FreightAnimations.WagonEmptyWeight != -1) MassKG = FreightAnimations.WagonEmptyWeight + FreightAnimations.FreightWeight + FreightAnimations.StaticFreightWeight;
if (WaitForAnimationReady && WeightLoadController.CommandStartTime + FreightAnimations.UnloadingStartDelay <= Simulator.ClockTime)
{
WaitForAnimationReady = false;
Expand All @@ -1964,6 +1972,26 @@ public override void Update(float elapsedClockSeconds)
WeightLoadController.StartDecrease(WeightLoadController.MinimumValue);
}
}

if (WagonType != WagonTypes.Tender && AuxWagonType != "AuxiliaryTender" && WagonType != WagonTypes.Engine)
{
// Updates mass when it carries containers
float totalContainerMassKG = 0;
if (FreightAnimations?.Animations != null)
{
foreach (var anim in FreightAnimations.Animations)
if (anim is FreightAnimationDiscrete discreteAnim && discreteAnim.Container != null)
{
totalContainerMassKG += discreteAnim.Container.MassKG;
}
}

// Updates the mass of the wagon considering all types of loads
if (FreightAnimations != null && FreightAnimations.WagonEmptyWeight != -1)
{
MassKG = FreightAnimations.WagonEmptyWeight + FreightAnimations.FreightWeight + FreightAnimations.StaticFreightWeight + totalContainerMassKG;
}
}
}

private void UpdateLocomotiveLoadPhysics()
Expand Down

0 comments on commit 329e0d5

Please sign in to comment.