public override void Copy(MSTSWagon copy) { base.Copy(copy); EOT eotcopy = (EOT)copy; EOTLevel = eotcopy.EOTLevel; }
public FreightAnimationViewer(Viewer viewer, MSTSWagon wagon, string wagonFolderSlash, FreightAnimation animation) { Animation = animation; FreightShape = new AnimatedShape(viewer, wagonFolderSlash + animation.ShapeFileName + '\0' + wagonFolderSlash, new WorldPosition(wagon.WorldPosition), ShapeFlags.ShadowCaster); if (FreightShape.SharedShape.LodControls.Length > 0) { foreach (var lodControl in FreightShape.SharedShape.LodControls) { if (lodControl.DistanceLevels.Length > 0) { foreach (var distanceLevel in lodControl.DistanceLevels) { if (distanceLevel.SubObjects.Length > 0 && distanceLevel.SubObjects[0].ShapePrimitives.Length > 0 && distanceLevel.SubObjects[0].ShapePrimitives[0].Hierarchy.Length > 0) { distanceLevel.SubObjects[0].ShapePrimitives[0].Hierarchy[0] = distanceLevel.SubObjects[0].ShapePrimitives[0].Hierarchy.Length; } } } } } if (FreightShape.XNAMatrices.Length > 0 && animation is FreightAnimationStatic && (animation as FreightAnimationStatic).Flipped) { var flipper = Matrix.Identity; flipper.M11 = -1; flipper.M33 = -1; FreightShape.XNAMatrices[0] *= flipper; } }
public FreightAnimations(FreightAnimations copyFACollection, MSTSWagon wagon) { foreach (FreightAnimation freightAnim in copyFACollection.Animations) { if (freightAnim is FreightAnimationContinuous) { Animations.Add(new FreightAnimationContinuous(freightAnim as FreightAnimationContinuous, wagon)); if ((Animations.Last() as FreightAnimationContinuous).FullAtStart) { LoadedOne = Animations.Last() as FreightAnimationContinuous; } } else if (freightAnim is FreightAnimationStatic) { Animations.Add(new FreightAnimationStatic(freightAnim as FreightAnimationStatic)); } else if (freightAnim is FreightAnimationDiscrete) { Animations.Add(new FreightAnimationDiscrete(freightAnim as FreightAnimationDiscrete)); } } FreightWeight = copyFACollection.FreightWeight; FreightType = copyFACollection.FreightType; MSTSFreightAnimEnabled = copyFACollection.MSTSFreightAnimEnabled; WagonEmptyWeight = copyFACollection.WagonEmptyWeight; LoadingStartDelay = copyFACollection.LoadingStartDelay; UnloadingStartDelay = copyFACollection.UnloadingStartDelay; IsGondola = copyFACollection.IsGondola; }
public BatterySwitch(MSTSWagon wagon) { Wagon = wagon; Timer = new Timer(Wagon); Timer.Setup(DelayS); }
public static void Save(BinaryWriter outf, TrainCar car) { MSTSWagon wagon = (MSTSWagon)car; // extend this when we introduce other types of rolling stock outf.Write(wagon.WagFilePath); wagon.Save(outf); }
public float FullCentreOfGravityM_Y = -9999; // get centre of gravity after adjusted for freight animation public FreightAnimationContinuous(STFReader stf, MSTSWagon wagon) { stf.MustMatch("("); stf.ParseBlock(new STFReader.TokenProcessor[] { new STFReader.TokenProcessor("intakepoint", () => { wagon.IntakePointList.Add(new IntakePoint(stf)); wagon.IntakePointList.Last().LinkedFreightAnim = this; LinkedIntakePoint = wagon.IntakePointList.Last(); }), new STFReader.TokenProcessor("shape", () => { ShapeFileName = stf.ReadStringBlock(null); }), new STFReader.TokenProcessor("maxheight", () => { MaxHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, 0); }), new STFReader.TokenProcessor("minheight", () => { MinHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, 0); }), new STFReader.TokenProcessor("freightweightwhenfull", () => { FreightWeightWhenFull = stf.ReadFloatBlock(STFReader.UNITS.Mass, 0); }), new STFReader.TokenProcessor("fullatstart", () => { FullAtStart = stf.ReadBoolBlock(true); }), // additions to manage consequences of variable weight on friction and brake forces new STFReader.TokenProcessor("fullortsdavis_a", () => { FullORTSDavis_A = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }), new STFReader.TokenProcessor("fullortsdavis_b", () => { FullORTSDavis_B = stf.ReadFloatBlock(STFReader.UNITS.Resistance, -1); }), new STFReader.TokenProcessor("fullortsdavis_c", () => { FullORTSDavis_C = stf.ReadFloatBlock(STFReader.UNITS.ResistanceDavisC, -1); }), new STFReader.TokenProcessor("fullortswagonfrontalarea", () => { FullORTSWagonFrontalAreaM2 = stf.ReadFloatBlock(STFReader.UNITS.AreaDefaultFT2, -1); }), new STFReader.TokenProcessor("fullortsdavisdragconstant", () => { FullORTSDavisDragConstant = stf.ReadFloatBlock(STFReader.UNITS.Any, -1); }), new STFReader.TokenProcessor("fullmaxbrakeforce", () => { FullMaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }), new STFReader.TokenProcessor("fullmaxhandbrakeforce", () => { FullMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }), new STFReader.TokenProcessor("fullcentreofgravity_y", () => { FullCentreOfGravityM_Y = stf.ReadFloatBlock(STFReader.UNITS.Distance, -1); }) }); }
public Pantograph(MSTSWagon wagon) { Wagon = wagon; State = PantographState.Down; DelayS = 0f; TimeS = 0f; }
public FreightAnimationsViewer(Viewer viewer, MSTSWagon wagon, string wagonFolderSlash) { foreach (var animation in wagon.FreightAnimations.Animations) { if (animation.ShapeFileName != null) { Animations.Add(new FreightAnimationViewer(viewer, wagon, wagonFolderSlash, animation)); } } }
/// <summary> /// This initializer is called when we are making a new copy of a locomotive already /// loaded in memory. We use this one to speed up loading by eliminating the /// need to parse the wag file multiple times. /// NOTE: you must initialize all the same variables as you parsed above /// </summary> public override void Copy(MSTSWagon copy) { base.Copy(copy); // each derived level initializes its own variables MSTSDieselLocomotive locoCopy = (MSTSDieselLocomotive)copy; EngineRPM = locoCopy.EngineRPM; IdleRPM = locoCopy.IdleRPM; MaxRPM = locoCopy.MaxRPM; MaxRPMChangeRate = locoCopy.MaxRPMChangeRate; MaximumDieselEnginePowerW = locoCopy.MaximumDieselEnginePowerW; PercentChangePerSec = locoCopy.PercentChangePerSec; LocomotiveMaxRailOutputPowerW = locoCopy.LocomotiveMaxRailOutputPowerW; EngineRPMderivation = locoCopy.EngineRPMderivation; EngineRPMold = locoCopy.EngineRPMold; MaxDieselLevelL = locoCopy.MaxDieselLevelL; DieselUsedPerHourAtMaxPowerL = locoCopy.DieselUsedPerHourAtMaxPowerL; DieselUsedPerHourAtIdleL = locoCopy.DieselUsedPerHourAtIdleL; DieselFlowLps = 0.0f; InitialMassKg = MassKG; if (this.CarID.StartsWith("0")) { DieselLevelL = locoCopy.DieselLevelL; } else { DieselLevelL = locoCopy.MaxDieselLevelL; } if (locoCopy.GearBoxController != null) { GearBoxController = new MSTSNotchController(locoCopy.GearBoxController); } DieselEngines = new DieselEngines(locoCopy.DieselEngines, this); if (DieselEngines[0].GearBox != null) { GearBox = DieselEngines[0].GearBox; } for (int i = 1; i < DieselEngines.Count; i++) { if (DieselEngines[i].GearBox == null && locoCopy.DieselEngines[i].GearBox != null) { DieselEngines[i].GearBox = new GearBox(GearBox, DieselEngines[i]); } } foreach (DieselEngine de in DieselEngines) { de.Initialize(true); } }
/// <summary> /// This initializer is called when we are making a new copy of a car already /// loaded in memory. We use this one to speed up loading by eliminating the /// need to parse the wag file multiple times. /// NOTE: you must initialize all the same variables as you parsed above /// </summary> public override void Copy(MSTSWagon copy) { base.Copy(copy); // each derived level initializes its own variables // for example //CabSoundFileName = locoCopy.CabSoundFileName; //CVFFileName = locoCopy.CVFFileName; MSTSElectricLocomotive locoCopy = (MSTSElectricLocomotive)copy; PowerSupply.Copy(locoCopy.PowerSupply); }
public FreightAnimationContinuous(STFReader stf, MSTSWagon wagon) { stf.MustMatch("("); stf.ParseBlock(new STFReader.TokenProcessor[] { new STFReader.TokenProcessor("intakepoint", () => { wagon.IntakePointList.Add(new IntakePoint(stf)); wagon.IntakePointList.Last().LinkedFreightAnim = this; LinkedIntakePoint = wagon.IntakePointList.Last(); }), new STFReader.TokenProcessor("shape", () => { ShapeFileName = stf.ReadStringBlock(null); }), new STFReader.TokenProcessor("maxheight", () => { MaxHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, 0); }), new STFReader.TokenProcessor("minheight", () => { MinHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, 0); }), new STFReader.TokenProcessor("freightweightwhenfull", () => { FreightWeightWhenFull = stf.ReadFloatBlock(STFReader.UNITS.Mass, 0); }), new STFReader.TokenProcessor("fullatstart", () => { FullAtStart = stf.ReadBoolBlock(true); }), }); }
public FreightAnimations(FreightAnimations copyFACollection, MSTSWagon wagon) { foreach (FreightAnimation freightAnim in copyFACollection.Animations) { if (freightAnim is FreightAnimationContinuous) { Animations.Add(new FreightAnimationContinuous(freightAnim as FreightAnimationContinuous, wagon)); if ((Animations.Last() as FreightAnimationContinuous).FullAtStart) { LoadedOne = Animations.Last() as FreightAnimationContinuous; } } else if (freightAnim is FreightAnimationStatic) { Animations.Add(new FreightAnimationStatic(freightAnim as FreightAnimationStatic)); } else if (freightAnim is FreightAnimationDiscrete) { Animations.Add(new FreightAnimationDiscrete(freightAnim as FreightAnimationDiscrete)); } } FreightWeight = copyFACollection.FreightWeight; FreightType = copyFACollection.FreightType; MSTSFreightAnimEnabled = copyFACollection.MSTSFreightAnimEnabled; WagonEmptyWeight = copyFACollection.WagonEmptyWeight; LoadingStartDelay = copyFACollection.LoadingStartDelay; UnloadingStartDelay = copyFACollection.UnloadingStartDelay; IsGondola = copyFACollection.IsGondola; // additions to manage consequences of variable weight on friction and brake forces EmptyORTSDavis_A = copyFACollection.EmptyORTSDavis_A; EmptyORTSDavis_B = copyFACollection.EmptyORTSDavis_B; EmptyORTSDavis_C = copyFACollection.EmptyORTSDavis_C; EmptyORTSWagonFrontalAreaM2 = copyFACollection.EmptyORTSWagonFrontalAreaM2; EmptyORTSDavisDragConstant = copyFACollection.EmptyORTSDavisDragConstant; EmptyMaxBrakeForceN = copyFACollection.EmptyMaxBrakeForceN; EmptyMaxHandbrakeForceN = copyFACollection.EmptyMaxHandbrakeForceN; EmptyCentreOfGravityM_Y = copyFACollection.EmptyCentreOfGravityM_Y; ContinuousFreightAnimationsPresent = copyFACollection.ContinuousFreightAnimationsPresent; StaticFreightAnimationsPresent = copyFACollection.StaticFreightAnimationsPresent; }
void buttonToggleElectricTrainSupplyCable_Click(Control arg1, Point arg2) { MSTSWagon wagon = Viewer.PlayerTrain.Cars[CarPosition] as MSTSWagon; if (wagon.PowerSupply != null) { new ConnectElectricTrainSupplyCableCommand(Viewer.Log, (Viewer.PlayerTrain.Cars[CarPosition] as MSTSWagon), !wagon.PowerSupply.FrontElectricTrainSupplyCableConnected); if (wagon.PowerSupply.FrontElectricTrainSupplyCableConnected) { Viewer.Simulator.Confirmer.Information(Viewer.Catalog.GetString("Front ETS cable connected")); } else { Viewer.Simulator.Confirmer.Information(Viewer.Catalog.GetString("Front ETS cable disconnected")); } } else { Viewer.Simulator.Confirmer.Information(Viewer.Catalog.GetString("This car doesn't have an ETS system")); } }
public static TrainCar Load(Simulator simulator, string wagFilePath, bool initialize = true) { GenericWAGFile wagFile = SharedGenericWAGFileManager.Get(wagFilePath); TrainCar car; if (wagFile.OpenRails != null && wagFile.OpenRails.DLL != null) { // wag file specifies an external DLL try { // TODO search the path list string wagFolder = Path.GetDirectoryName(wagFilePath); string dllPath = FindTrainCarPlugin(wagFolder, wagFile.OpenRails.DLL); Assembly customDLL = Assembly.LoadFrom(dllPath); object[] args = new object[] { wagFilePath }; car = (TrainCar)customDLL.CreateInstance("ORTS.CustomCar", true, BindingFlags.CreateInstance, null, args, null, null); return(car); } catch (Exception error) { Trace.WriteLine(new FileLoadException(wagFile.OpenRails.DLL, error)); // on error, fall through and try loading without the custom dll } } if (!wagFile.IsEngine) { // its an ordinary MSTS wagon car = new MSTSWagon(simulator, wagFilePath); } else { // its an ordinary MSTS engine of some type. if (wagFile.Engine.Type == null) { throw new InvalidDataException(wagFilePath + "\r\n\r\nEngine type missing"); } switch (wagFile.Engine.Type.ToLower()) { // TODO complete parsing of proper car types case "electric": car = new MSTSElectricLocomotive(simulator, wagFilePath); break; case "steam": car = new MSTSSteamLocomotive(simulator, wagFilePath); break; case "diesel": car = new MSTSDieselLocomotive(simulator, wagFilePath); break; case "control": car = new MSTSControlTrailerCar(simulator, wagFilePath); break; default: throw new InvalidDataException(wagFilePath + "\r\n\r\nUnknown engine type: " + wagFile.Engine.Type); } } MSTSWagon wagon = car as MSTSWagon; if (car != null) { wagon.Load(); if (initialize) { wagon.Initialize(); } } return(car); }
public MSTSWagonViewer(Viewer viewer, MSTSWagon car) : base(viewer, car) { var wagonFolderSlash = Path.GetDirectoryName(car.WagFilePath) + @"\"; TrainCarShape = car.MainShapeFileName != string.Empty ? new PoseableShape(viewer, wagonFolderSlash + car.MainShapeFileName + '\0' + wagonFolderSlash, car.WorldPosition, ShapeFlags.ShadowCaster) : new PoseableShape(viewer, null, car.WorldPosition); if (car.FreightShapeFileName != null) { car.HasFreightAnim = true; FreightShape = new AnimatedShape(viewer, wagonFolderSlash + car.FreightShapeFileName + '\0' + wagonFolderSlash, new WorldPosition(car.WorldPosition), ShapeFlags.ShadowCaster); // Reproducing MSTS "bug" of not allowing tender animation in case both minLevel and maxLevel are 0 or maxLevel < minLevel if (MSTSWagon.WagonType == TrainCar.WagonTypes.Tender && MSTSWagon.FreightAnimMaxLevelM != 0 && MSTSWagon.FreightAnimFlag > 0 && MSTSWagon.FreightAnimMaxLevelM > MSTSWagon.FreightAnimMinLevelM) { // Force allowing animation: if (FreightShape.SharedShape.LodControls.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives[0].Hierarchy.Length > 0) { FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives[0].Hierarchy[0] = 1; } } } if (car.InteriorShapeFileName != null) { InteriorShape = new AnimatedShape(viewer, wagonFolderSlash + car.InteriorShapeFileName + '\0' + wagonFolderSlash, car.WorldPosition, ShapeFlags.Interior, 30.0f); } RunningGear = new AnimatedPart(TrainCarShape); Pantograph1 = new AnimatedPart(TrainCarShape); Pantograph2 = new AnimatedPart(TrainCarShape); LeftDoor = new AnimatedPart(TrainCarShape); RightDoor = new AnimatedPart(TrainCarShape); Mirrors = new AnimatedPart(TrainCarShape); Wipers = new AnimatedPart(TrainCarShape); UnloadingParts = new AnimatedPart(TrainCarShape); if (car.FreightAnimations != null) { FreightAnimations = new FreightAnimationsViewer(viewer, car, wagonFolderSlash); } LoadCarSounds(wagonFolderSlash); //if (!(MSTSWagon is MSTSLocomotive)) // LoadTrackSounds(); Viewer.SoundProcess.AddSoundSource(this, new TrackSoundSource(MSTSWagon, Viewer)); // Determine if it has first pantograph. So we can match unnamed panto parts correctly for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.SharedShape.MatrixNames[i].Contains('1')) { if (TrainCarShape.SharedShape.MatrixNames[i].ToUpper().StartsWith("PANTO")) { HasFirstPanto = true; break; } } } // Check bogies and wheels to find out what we have. for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.SharedShape.MatrixNames[i].Equals("BOGIE1")) { bogieMatrix1 = i; numBogie1 += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("BOGIE2")) { bogieMatrix2 = i; numBogie2 += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("BOGIE")) { bogieMatrix1 = i; numBogie += 1; } // For now, the total axle count consisting of axles that are part of the bogie are being counted. if (TrainCarShape.SharedShape.MatrixNames[i].Contains("WHEELS")) { if (TrainCarShape.SharedShape.MatrixNames[i].Length == 8) { var tpmatrix = TrainCarShape.SharedShape.GetParentMatrix(i); if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS11") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS12") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS13") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS21") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS22") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS23") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS11") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS12") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS13") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS21") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS21") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS23") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } } } } // Match up all the matrices with their parts. for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.Hierarchy[i] == -1) { MatchMatrixToPart(car, i, 0); } } car.SetUpWheels(); // If we have two pantographs, 2 is the forwards pantograph, unlike when there's only one. if (!car.Flipped && !Pantograph1.Empty() && !Pantograph2.Empty()) { AnimatedPart.Swap(ref Pantograph1, ref Pantograph2); } Pantograph1.SetState(MSTSWagon.Pantographs[1].CommandUp); Pantograph2.SetState(MSTSWagon.Pantographs[2].CommandUp); LeftDoor.SetState(MSTSWagon.DoorLeftOpen); RightDoor.SetState(MSTSWagon.DoorRightOpen); Mirrors.SetState(MSTSWagon.MirrorOpen); UnloadingParts.SetState(MSTSWagon.UnloadingPartsOpen); InitializeUserInputCommands(); }
public ScriptedPassengerCarPowerSupply(MSTSWagon wagon) { Wagon = wagon; BatterySwitch = new BatterySwitch(Wagon); }
public void AddPlayers(MSGPlayer player, OnlinePlayer p) { if (Players.ContainsKey(player.user)) { return; } if (MPManager.Client != null && player.user == MPManager.Client.UserName) { return; //do not add self//WARNING: may need to worry about train number here } if (p == null) { p = new OnlinePlayer(null, null); } p.url = player.url; p.LeadingLocomotiveID = player.leadingID; p.con = MPManager.Simulator.BasePath + "\\TRAINS\\CONSISTS\\" + player.con; p.path = MPManager.Simulator.RoutePath + "\\PATHS\\" + player.path; Train train = new Train(MPManager.Simulator); train.TrainType = Train.TRAINTYPE.REMOTE; if (MPManager.IsServer()) //server needs to worry about correct train number { } else { train.Number = player.num; } if (player.con.Contains("tilted")) { train.IsTilting = true; } int direction = player.dir; train.travelled = player.Travelled; train.TrainMaxSpeedMpS = player.trainmaxspeed; if (MPManager.IsServer()) { try { #if ACTIVITY_EDITOR AIPath aiPath = new AIPath(MPManager.Simulator.TDB, MPManager.Simulator.TSectionDat, p.path, MPManager.Simulator.TimetableMode, MPManager.Simulator.orRouteConfig); #else AIPath aiPath = new AIPath(MPManager.Simulator.TDB, MPManager.Simulator.TSectionDat, p.path); #endif } catch (Exception) { MPManager.BroadCast((new MSGMessage(player.user, "Warning", "Server does not have path file provided, signals may always be red for you.")).ToString()); } } try { train.RearTDBTraveller = new Traveller(MPManager.Simulator.TSectionDat, MPManager.Simulator.TDB.TrackDB.TrackNodes, player.TileX, player.TileZ, player.X, player.Z, direction == 1 ? Traveller.TravellerDirection.Forward : Traveller.TravellerDirection.Backward); } catch (Exception e) { if (MPManager.IsServer()) { MPManager.BroadCast((new MSGMessage(player.user, "Error", "MultiPlayer Error:" + e.Message)).ToString()); } else { throw new Exception(); } } for (var i = 0; i < player.cars.Length; i++)// cars.Length-1; i >= 0; i--) { { string wagonFilePath = MPManager.Simulator.BasePath + @"\trains\trainset\" + player.cars[i]; TrainCar car = null; try { car = RollingStock.Load(MPManager.Simulator, wagonFilePath); car.CarLengthM = player.lengths[i] / 100.0f; } catch (Exception error) { System.Console.WriteLine(error.Message); car = MPManager.Instance().SubCar(wagonFilePath, player.lengths[i]); } if (car == null) { continue; } bool flip = true; if (player.flipped[i] == 0) { flip = false; } car.Flipped = flip; car.CarID = player.ids[i]; train.Cars.Add(car); car.Train = train; MSTSWagon w = (MSTSWagon)car; if (w != null) { w.SignalEvent((player.pantofirst == 1 ? PowerSupplyEvent.RaisePantograph : PowerSupplyEvent.LowerPantograph), 1); w.SignalEvent((player.pantosecond == 1 ? PowerSupplyEvent.RaisePantograph : PowerSupplyEvent.LowerPantograph), 2); w.SignalEvent((player.pantothird == 1 ? PowerSupplyEvent.RaisePantograph : PowerSupplyEvent.LowerPantograph), 3); w.SignalEvent((player.pantofourth == 1 ? PowerSupplyEvent.RaisePantograph : PowerSupplyEvent.LowerPantograph), 4); } }// for each rail car if (train.Cars.Count == 0) { throw (new Exception("The train of player " + player.user + " is empty from ")); } p.Username = player.user; train.ControlMode = Train.TRAIN_CONTROL.EXPLORER; train.CheckFreight(); train.InitializeBrakes(); bool canPlace = true; Train.TCSubpathRoute tempRoute = train.CalculateInitialTrainPosition(ref canPlace); if (tempRoute.Count == 0 || !canPlace) { MPManager.BroadCast((new MSGMessage(p.Username, "Error", "Cannot be placed into the game")).ToString());//server will broadcast this error throw new InvalidDataException("Remote train original position not clear"); } train.SetInitialTrainRoute(tempRoute); train.CalculatePositionOfCars(); train.ResetInitialTrainRoute(tempRoute); train.CalculatePositionOfCars(); train.AITrainBrakePercent = 100; //if (MPManager.Instance().AllowedManualSwitch) train.InitializeSignals(false); for (int iCar = 0; iCar < train.Cars.Count; iCar++) { var car = train.Cars[iCar]; if (car.CarID == p.LeadingLocomotiveID) { train.LeadLocomotive = car; (train.LeadLocomotive as MSTSLocomotive).Headlight = player.headlight; (train.LeadLocomotive as MSTSLocomotive).UsingRearCab = player.frontorrearcab == "R" ? true : false; } if (car is MSTSLocomotive && MPManager.IsServer()) { MPManager.Instance().AddOrRemoveLocomotive(player.user, train.Number, iCar, true); } } if (train.LeadLocomotive == null) { train.LeadNextLocomotive(); if (train.LeadLocomotive != null) { p.LeadingLocomotiveID = train.LeadLocomotive.CarID; } else { p.LeadingLocomotiveID = "NA"; } } if (train.LeadLocomotive != null) { train.Name = train.GetTrainName(train.LeadLocomotive.CarID); } else if (train.Cars != null && train.Cars.Count > 0) { train.Name = train.GetTrainName(train.Cars[0].CarID); } else if (player != null && player.user != null) { train.Name = player.user; } if (MPManager.IsServer()) { train.InitializeSignals(false); } p.Train = train; Players.Add(player.user, p); MPManager.Instance().AddOrRemoveTrain(train, true); }
public MSTSWagonViewer(Viewer viewer, MSTSWagon car) : base(viewer, car) { string steamTexture = viewer.Simulator.BasePath + @"\GLOBAL\TEXTURES\smokemain.ace"; string dieselTexture = viewer.Simulator.BasePath + @"\GLOBAL\TEXTURES\dieselsmoke.ace"; // Particle Drawers called in Wagon so that wagons can also have steam effects. ParticleDrawers = ( from effect in MSTSWagon.EffectData select new KeyValuePair <string, List <ParticleEmitterViewer> >(effect.Key, new List <ParticleEmitterViewer>( from data in effect.Value select new ParticleEmitterViewer(viewer, data, car.WorldPosition)))).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Initaialise particle viewers for special steam effects foreach (var emitter in ParticleDrawers) { // Exhaust for steam heating boiler if (emitter.Key.ToLowerInvariant() == "heatingsteamboilerfx") { HeatingSteamBoiler.AddRange(emitter.Value); } foreach (var drawer in HeatingSteamBoiler) { drawer.Initialize(dieselTexture); } // Exhaust for HEP/Power Generator if (emitter.Key.ToLowerInvariant() == "wagongeneratorfx") { WagonGenerator.AddRange(emitter.Value); } foreach (var drawer in WagonGenerator) { drawer.Initialize(dieselTexture); } // Smoke for wood/coal fire if (emitter.Key.ToLowerInvariant() == "wagonsmokefx") { WagonSmoke.AddRange(emitter.Value); } foreach (var drawer in WagonSmoke) { drawer.Initialize(steamTexture); } // Steam leak in heating hose if (emitter.Key.ToLowerInvariant() == "heatinghosefx") { HeatingHose.AddRange(emitter.Value); } foreach (var drawer in HeatingHose) { drawer.Initialize(steamTexture); } } var wagonFolderSlash = Path.GetDirectoryName(car.WagFilePath) + @"\"; TrainCarShape = car.MainShapeFileName != string.Empty ? new PoseableShape(viewer, wagonFolderSlash + car.MainShapeFileName + '\0' + wagonFolderSlash, car.WorldPosition, ShapeFlags.ShadowCaster) : new PoseableShape(viewer, null, car.WorldPosition); // This insection initialises the MSTS style freight animation - can either be for a coal load, which will adjust with usage, or a static animation, such as additional shape. if (car.FreightShapeFileName != null) { car.HasFreightAnim = true; FreightShape = new AnimatedShape(viewer, wagonFolderSlash + car.FreightShapeFileName + '\0' + wagonFolderSlash, new WorldPosition(car.WorldPosition), ShapeFlags.ShadowCaster); // Reproducing MSTS "bug" of not allowing tender animation in case both minLevel and maxLevel are 0 or maxLevel < minLevel // Applies to both a standard tender locomotive or a tank locomotive (where coal load is on same "wagon" as the locomotive - for the coal load on a tender or tank locomotive - in operation it will raise or lower with caol usage if (MSTSWagon.WagonType == TrainCar.WagonTypes.Tender || MSTSWagon is MSTSSteamLocomotive) { var NonTenderSteamLocomotive = MSTSWagon as MSTSSteamLocomotive; if ((MSTSWagon.WagonType == TrainCar.WagonTypes.Tender || MSTSWagon is MSTSLocomotive && (MSTSWagon.EngineType == TrainCar.EngineTypes.Steam && NonTenderSteamLocomotive.IsTenderRequired == 0.0)) && MSTSWagon.FreightAnimMaxLevelM != 0 && MSTSWagon.FreightAnimFlag > 0 && MSTSWagon.FreightAnimMaxLevelM > MSTSWagon.FreightAnimMinLevelM) { // Force allowing animation: if (FreightShape.SharedShape.LodControls.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives.Length > 0 && FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives[0].Hierarchy.Length > 0) { FreightShape.SharedShape.LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives[0].Hierarchy[0] = 1; } } } } if (car.InteriorShapeFileName != null) { InteriorShape = new AnimatedShape(viewer, wagonFolderSlash + car.InteriorShapeFileName + '\0' + wagonFolderSlash, car.WorldPosition, ShapeFlags.Interior, 30.0f); } RunningGear = new AnimatedPart(TrainCarShape); Pantograph1 = new AnimatedPart(TrainCarShape); Pantograph2 = new AnimatedPart(TrainCarShape); Pantograph3 = new AnimatedPart(TrainCarShape); Pantograph4 = new AnimatedPart(TrainCarShape); LeftDoor = new AnimatedPart(TrainCarShape); RightDoor = new AnimatedPart(TrainCarShape); Mirrors = new AnimatedPart(TrainCarShape); Wipers = new AnimatedPart(TrainCarShape); UnloadingParts = new AnimatedPart(TrainCarShape); Bell = new AnimatedPart(TrainCarShape); if (car.FreightAnimations != null) { FreightAnimations = new FreightAnimationsViewer(viewer, car, wagonFolderSlash); } LoadCarSounds(wagonFolderSlash); //if (!(MSTSWagon is MSTSLocomotive)) // LoadTrackSounds(); Viewer.SoundProcess.AddSoundSource(this, new TrackSoundSource(MSTSWagon, Viewer)); // Determine if it has first pantograph. So we can match unnamed panto parts correctly for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.SharedShape.MatrixNames[i].Contains('1')) { if (TrainCarShape.SharedShape.MatrixNames[i].ToUpper().StartsWith("PANTO")) { HasFirstPanto = true; break; } } } // Check bogies and wheels to find out what we have. for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.SharedShape.MatrixNames[i].Equals("BOGIE1")) { bogieMatrix1 = i; numBogie1 += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("BOGIE2")) { bogieMatrix2 = i; numBogie2 += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("BOGIE")) { bogieMatrix1 = i; } // For now, the total axle count consisting of axles that are part of the bogie are being counted. if (TrainCarShape.SharedShape.MatrixNames[i].Contains("WHEELS")) { if (TrainCarShape.SharedShape.MatrixNames[i].Length == 8) { var tpmatrix = TrainCarShape.SharedShape.GetParentMatrix(i); if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS11") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS12") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS13") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS21") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS22") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS23") && tpmatrix == bogieMatrix1) { bogie1Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS11") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS12") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS13") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS21") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS21") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } if (TrainCarShape.SharedShape.MatrixNames[i].Equals("WHEELS23") && tpmatrix == bogieMatrix2) { bogie2Axles += 1; } } } } // Match up all the matrices with their parts. for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.Hierarchy[i] == -1) { MatchMatrixToPart(car, i, 0); } } car.SetUpWheels(); // If we have two pantographs, 2 is the forwards pantograph, unlike when there's only one. if (!car.Flipped && !Pantograph1.Empty() && !Pantograph2.Empty()) { AnimatedPart.Swap(ref Pantograph1, ref Pantograph2); } Pantograph1.SetState(MSTSWagon.Pantographs[1].CommandUp); Pantograph2.SetState(MSTSWagon.Pantographs[2].CommandUp); if (MSTSWagon.Pantographs.List.Count > 2) { Pantograph3.SetState(MSTSWagon.Pantographs[3].CommandUp); } if (MSTSWagon.Pantographs.List.Count > 3) { Pantograph4.SetState(MSTSWagon.Pantographs[4].CommandUp); } LeftDoor.SetState(MSTSWagon.DoorLeftOpen); RightDoor.SetState(MSTSWagon.DoorRightOpen); Mirrors.SetState(MSTSWagon.MirrorOpen); UnloadingParts.SetState(MSTSWagon.UnloadingPartsOpen); InitializeUserInputCommands(); }
// For copy public FreightAnimationContinuous(FreightAnimationContinuous freightAnimContin, MSTSWagon wagon) { wagon.IntakePointList.Add(new IntakePoint(freightAnimContin.LinkedIntakePoint)); wagon.IntakePointList.Last().LinkedFreightAnim = this; LinkedIntakePoint = wagon.IntakePointList.Last(); ShapeFileName = freightAnimContin.ShapeFileName; MaxHeight = freightAnimContin.MaxHeight; MinHeight = freightAnimContin.MinHeight; FreightWeightWhenFull = freightAnimContin.FreightWeightWhenFull; FullAtStart = freightAnimContin.FullAtStart; LoadPerCent = freightAnimContin.LoadPerCent; }
public ToggleAngleCockBCommand(CommandLog log, MSTSWagon car, bool toState) : base(log, toState) { Receiver = car; Redo(); }
public WagonHandbrakeCommand(CommandLog log, MSTSWagon car, bool toState) : base(log, toState) { Receiver = car; Redo(); }
public FreightAnimations(STFReader stf, MSTSWagon wagon) { stf.MustMatch("("); bool empty = true; stf.ParseBlock(new[] { new STFReader.TokenProcessor("mstsfreightanimenabled", () => { MSTSFreightAnimEnabled = stf.ReadBoolBlock(true); }), new STFReader.TokenProcessor("wagonemptyweight", () => { WagonEmptyWeight = stf.ReadFloatBlock(STFReader.UNITS.Mass, -1); }), new STFReader.TokenProcessor("loadingstartdelay", () => { UnloadingStartDelay = stf.ReadFloatBlock(STFReader.UNITS.None, 0); }), new STFReader.TokenProcessor("unloadingstartdelay", () => { UnloadingStartDelay = stf.ReadFloatBlock(STFReader.UNITS.None, 0); }), new STFReader.TokenProcessor("isgondola", () => { IsGondola = stf.ReadBoolBlock(false); }), new STFReader.TokenProcessor("freightanimcontinuous", () => { Animations.Add(new FreightAnimationContinuous(stf, wagon)); if (wagon.WeightLoadController == null) { wagon.WeightLoadController = new MSTSNotchController(0, 1, 0.01f); } if ((Animations.Last() as FreightAnimationContinuous).FullAtStart) { if (empty) { empty = false; FreightType = wagon.IntakePointList.Last().Type; LoadedOne = Animations.Last() as FreightAnimationContinuous; FreightWeight += LoadedOne.FreightWeightWhenFull; LoadedOne.LoadPerCent = 100; } else { (Animations.Last() as FreightAnimationContinuous).FullAtStart = false; Trace.TraceWarning("The wagon can't be full with two different materials, only first is retained"); } } }), new STFReader.TokenProcessor("freightanimstatic", () => { Animations.Add(new FreightAnimationStatic(stf)); StaticFreightWeight += (Animations.Last() as FreightAnimationStatic).FreightWeight; }), /* new STFReader.TokenProcessor("freightanimdiscrete", ()=> * { * ORTSFreightAnims.Add(new FreightAnimDiscrete(stf)); * if ((ORTSFreightAnims.Last() as FreightAnimDiscrete).LoadedAtStart) * { * if (empty) * { * empty = false; * DiscreteLoadedOne = ORTSFreightAnims.Last() as FreightAnimDiscrete; * FreightWeight += DiscreteLoadedOne.LoadWeight; * } * else * { * (ORTSFreightAnims.Last() as FreightAnimContinuous).FullAtStart = false; * Trace.TraceWarning("The wagon can't be full with two different materials, only first is retained"); * } * } * }),*/ }); }
public WagonBrakeHoseConnectCommand(CommandLog log, MSTSWagon car, bool toState) : base(log, toState) { Receiver = car; Redo(); }
// For copy public FreightAnimationContinuous(FreightAnimationContinuous freightAnimContin, MSTSWagon wagon) { if (freightAnimContin.LinkedIntakePoint != null) { wagon.IntakePointList.Add(new IntakePoint(freightAnimContin.LinkedIntakePoint)); wagon.IntakePointList.Last().LinkedFreightAnim = this; LinkedIntakePoint = wagon.IntakePointList.Last(); } ShapeFileName = freightAnimContin.ShapeFileName; MaxHeight = freightAnimContin.MaxHeight; MinHeight = freightAnimContin.MinHeight; FreightWeightWhenFull = freightAnimContin.FreightWeightWhenFull; FullAtStart = freightAnimContin.FullAtStart; LoadPerCent = freightAnimContin.LoadPerCent; // additions to manage consequences of variable weight on friction and brake forces FullORTSDavis_A = freightAnimContin.FullORTSDavis_A; FullORTSDavis_B = freightAnimContin.FullORTSDavis_B; FullORTSDavis_C = freightAnimContin.FullORTSDavis_C; FullORTSWagonFrontalAreaM2 = freightAnimContin.FullORTSWagonFrontalAreaM2; FullORTSDavisDragConstant = freightAnimContin.FullORTSDavisDragConstant; FullMaxBrakeForceN = freightAnimContin.FullMaxBrakeForceN; FullMaxHandbrakeForceN = freightAnimContin.FullMaxHandbrakeForceN; FullCentreOfGravityM_Y = freightAnimContin.FullCentreOfGravityM_Y; }
public ToggleBleedOffValveCommand(CommandLog log, MSTSWagon car, bool toState) : base(log, toState) { Receiver = car; Redo(); }
public bool StaticFreightAnimationsPresent = false; // Flag to indicate that a continuous freight animation is present public FreightAnimations(STFReader stf, MSTSWagon wagon) { stf.MustMatch("("); bool empty = true; stf.ParseBlock(new[] { new STFReader.TokenProcessor("mstsfreightanimenabled", () => { MSTSFreightAnimEnabled = stf.ReadBoolBlock(true); }), new STFReader.TokenProcessor("wagonemptyweight", () => { WagonEmptyWeight = stf.ReadFloatBlock(STFReader.UNITS.Mass, -1); }), new STFReader.TokenProcessor("loadingstartdelay", () => { UnloadingStartDelay = stf.ReadFloatBlock(STFReader.UNITS.None, 0); }), new STFReader.TokenProcessor("unloadingstartdelay", () => { UnloadingStartDelay = stf.ReadFloatBlock(STFReader.UNITS.None, 0); }), new STFReader.TokenProcessor("isgondola", () => { IsGondola = stf.ReadBoolBlock(false); }), // additions to manage consequences of variable weight on friction and brake forces new STFReader.TokenProcessor("emptyortsdavis_a", () => { EmptyORTSDavis_A = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }), new STFReader.TokenProcessor("emptyortsdavis_b", () => { EmptyORTSDavis_B = stf.ReadFloatBlock(STFReader.UNITS.Resistance, -1); }), new STFReader.TokenProcessor("emptyortsdavis_c", () => { EmptyORTSDavis_C = stf.ReadFloatBlock(STFReader.UNITS.ResistanceDavisC, -1); }), new STFReader.TokenProcessor("emptyortswagonfrontalarea", () => { EmptyORTSWagonFrontalAreaM2 = stf.ReadFloatBlock(STFReader.UNITS.AreaDefaultFT2, -1); }), new STFReader.TokenProcessor("emptyortsdavisdragconstant", () => { EmptyORTSDavisDragConstant = stf.ReadFloatBlock(STFReader.UNITS.Any, -1); }), new STFReader.TokenProcessor("emptymaxbrakeforce", () => { EmptyMaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }), new STFReader.TokenProcessor("emptymaxhandbrakeforce", () => { EmptyMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }), new STFReader.TokenProcessor("emptycentreofgravity_y", () => { EmptyCentreOfGravityM_Y = stf.ReadFloatBlock(STFReader.UNITS.Distance, -1); }), new STFReader.TokenProcessor("freightanimcontinuous", () => { Animations.Add(new FreightAnimationContinuous(stf, wagon)); FullPhysicsContinuousOne = Animations.Last() as FreightAnimationContinuous; if (wagon.WeightLoadController == null) { wagon.WeightLoadController = new MSTSNotchController(0, 1, 0.01f); } if ((Animations.Last() as FreightAnimationContinuous).FullAtStart) { if (empty) { empty = false; FreightType = wagon.IntakePointList.Last().Type; LoadedOne = Animations.Last() as FreightAnimationContinuous; FreightWeight += LoadedOne.FreightWeightWhenFull; LoadedOne.LoadPerCent = 100; } else { (Animations.Last() as FreightAnimationContinuous).FullAtStart = false; Trace.TraceWarning("The wagon can't be full with two different materials, only first is retained"); } } ContinuousFreightAnimationsPresent = true; }), new STFReader.TokenProcessor("freightanimstatic", () => { Animations.Add(new FreightAnimationStatic(stf)); StaticFreightWeight += (Animations.Last() as FreightAnimationStatic).FreightWeight; StaticFreightAnimationsPresent = true; FullPhysicsStaticOne = Animations.Last() as FreightAnimationStatic; }), /* new STFReader.TokenProcessor("freightanimdiscrete", ()=> * { * ORTSFreightAnims.Add(new FreightAnimDiscrete(stf)); * if ((ORTSFreightAnims.Last() as FreightAnimDiscrete).LoadedAtStart) * { * if (empty) * { * empty = false; * DiscreteLoadedOne = ORTSFreightAnims.Last() as FreightAnimDiscrete; * FreightWeight += DiscreteLoadedOne.LoadWeight; * } * else * { * (ORTSFreightAnims.Last() as FreightAnimContinuous).FullAtStart = false; * Trace.TraceWarning("The wagon can't be full with two different materials, only first is retained"); * } * } * }),*/ }); }
public Pantographs(MSTSWagon wagon) { Wagon = wagon; }
void MatchMatrixToPart(MSTSWagon car, int matrix, int bogieMatrix) { var matrixName = TrainCarShape.SharedShape.MatrixNames[matrix].ToUpper(); // Gate all RunningGearPartIndexes on this! var matrixAnimated = TrainCarShape.SharedShape.Animations != null && TrainCarShape.SharedShape.Animations.Count > 0 && TrainCarShape.SharedShape.Animations[0].anim_nodes.Count > matrix && TrainCarShape.SharedShape.Animations[0].anim_nodes[matrix].controllers.Count > 0; if (matrixName.StartsWith("WHEELS") && (matrixName.Length == 7 || matrixName.Length == 8 || matrixName.Length == 9)) { // Standard WHEELS length would be 8 to test for WHEELS11. Came across WHEELS tag that used a period(.) between the last 2 numbers, changing max length to 9. // Changing max length to 9 is not a problem since the initial WHEELS test will still be good. var m = TrainCarShape.SharedShape.GetMatrixProduct(matrix); //someone uses wheel to animate fans, thus check if the wheel is not too high (lower than 3m), will animate it as real wheel if (m.M42 < 3) { var id = 0; // Model makers are not following the standard rules, For example, one tender uses naming convention of wheels11/12 instead of using Wheels1,2,3 when not part of a bogie. // The next 2 lines will sort out these axles. var tmatrix = TrainCarShape.SharedShape.GetParentMatrix(matrix); if (matrixName.Length == 8 && bogieMatrix == 0 && tmatrix == 0) // In this test, both tmatrix and bogieMatrix are 0 since these wheels are not part of a bogie. { matrixName = TrainCarShape.SharedShape.MatrixNames[matrix].Substring(0, 7); // Changing wheel name so that it reflects its actual use since it is not p } if (matrixName.Length == 8 || matrixName.Length == 9) { Int32.TryParse(matrixName.Substring(6, 1), out id); } if (matrixName.Length == 8 || matrixName.Length == 9 || !matrixAnimated) { WheelPartIndexes.Add(matrix); } else { RunningGear.AddMatrix(matrix); } var pmatrix = TrainCarShape.SharedShape.GetParentMatrix(matrix); car.AddWheelSet(m.M43, id, pmatrix, matrixName.ToString(), bogie1Axles, bogie2Axles); } // Standard wheels are processed above, but wheels used as animated fans that are greater than 3m are processed here. else { RunningGear.AddMatrix(matrix); } } else if (matrixName.StartsWith("BOGIE") && matrixName.Length <= 6) //BOGIE1 is valid, BOGIE11 is not, it is used by some modelers to indicate this is part of bogie1 { if (matrixName.Length == 6) { var id = 1; Int32.TryParse(matrixName.Substring(5), out id); var m = TrainCarShape.SharedShape.GetMatrixProduct(matrix); car.AddBogie(m.M43, matrix, id, matrixName.ToString(), numBogie1, numBogie2); bogieMatrix = matrix; // Bogie matrix needs to be saved for test with axles. } else { // Since the string content is BOGIE, Int32.TryParse(matrixName.Substring(5), out id) is not needed since its sole purpose is to // parse the string number from the string. var id = 1; var m = TrainCarShape.SharedShape.GetMatrixProduct(matrix); car.AddBogie(m.M43, matrix, id, matrixName.ToString(), numBogie1, numBogie2); bogieMatrix = matrix; // Bogie matrix needs to be saved for test with axles. } // Bogies contain wheels! for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.Hierarchy[i] == matrix) { MatchMatrixToPart(car, i, bogieMatrix); } } } else if (matrixName.StartsWith("WIPER")) // wipers { Wipers.AddMatrix(matrix); } else if (matrixName.StartsWith("DOOR")) // doors (left / right) { if (matrixName.StartsWith("DOOR_D") || matrixName.StartsWith("DOOR_E") || matrixName.StartsWith("DOOR_F")) { LeftDoor.AddMatrix(matrix); } else if (matrixName.StartsWith("DOOR_A") || matrixName.StartsWith("DOOR_B") || matrixName.StartsWith("DOOR_C")) { RightDoor.AddMatrix(matrix); } } else if (matrixName.StartsWith("PANTOGRAPH")) //pantographs (1/2) { switch (matrixName) { case "PANTOGRAPHBOTTOM1": case "PANTOGRAPHBOTTOM1A": case "PANTOGRAPHBOTTOM1B": case "PANTOGRAPHMIDDLE1": case "PANTOGRAPHMIDDLE1A": case "PANTOGRAPHMIDDLE1B": case "PANTOGRAPHTOP1": case "PANTOGRAPHTOP1A": case "PANTOGRAPHTOP1B": Pantograph1.AddMatrix(matrix); break; case "PANTOGRAPHBOTTOM2": case "PANTOGRAPHBOTTOM2A": case "PANTOGRAPHBOTTOM2B": case "PANTOGRAPHMIDDLE2": case "PANTOGRAPHMIDDLE2A": case "PANTOGRAPHMIDDLE2B": case "PANTOGRAPHTOP2": case "PANTOGRAPHTOP2A": case "PANTOGRAPHTOP2B": Pantograph2.AddMatrix(matrix); break; default: //someone used other language if (matrixName.Contains("1")) { Pantograph1.AddMatrix(matrix); } else if (matrixName.Contains("2")) { Pantograph2.AddMatrix(matrix); } else if (matrixName.Contains("3")) { Pantograph3.AddMatrix(matrix); } else if (matrixName.Contains("4")) { Pantograph4.AddMatrix(matrix); } else { if (HasFirstPanto) { Pantograph1.AddMatrix(matrix); //some may have no first panto, will put it as panto 2 } else { Pantograph2.AddMatrix(matrix); } } break; } } else if (matrixName.StartsWith("MIRROR")) // mirrors { Mirrors.AddMatrix(matrix); } else if (matrixName.StartsWith("UNLOADINGPARTS")) // unloading parts { UnloadingParts.AddMatrix(matrix); } else if (matrixName.StartsWith("PANTO")) // TODO, not sure why this is needed, see above! { Trace.TraceInformation("Pantograph matrix with unusual name {1} in shape {0}", TrainCarShape.SharedShape.FilePath, matrixName); if (matrixName.Contains("1")) { Pantograph1.AddMatrix(matrix); } else if (matrixName.Contains("2")) { Pantograph2.AddMatrix(matrix); } else if (matrixName.Contains("3")) { Pantograph3.AddMatrix(matrix); } else if (matrixName.Contains("4")) { Pantograph4.AddMatrix(matrix); } else { if (HasFirstPanto) { Pantograph1.AddMatrix(matrix); //some may have no first panto, will put it as panto 2 } else { Pantograph2.AddMatrix(matrix); } } } else if (matrixName.StartsWith("ORTSBELL")) // wipers { Bell.AddMatrix(matrix); } else { if (matrixAnimated && matrix != 0) { RunningGear.AddMatrix(matrix); } for (var i = 0; i < TrainCarShape.Hierarchy.Length; i++) { if (TrainCarShape.Hierarchy[i] == matrix) { MatchMatrixToPart(car, i, 0); } } } }