1 using System; 2 using OpenBveApi.Math; 3 using TrainManager.Handles; 4 using TrainManager.Trains; 5 6 // ReSharper disable UnusedMember.Global 7 8 namespace OpenBve 9 { 10 /// <summary>This is a proxy class, which provides read-only access to variables, in a manner analagous to that found in .animated files </summary> 11 /// Notes: 12 /// A proxy class is required, as otherwise we start making a horrendous amount of stuff public which shouldn't be, when working with cross-assembly access. 13 /// Doing it this way, also allows for sensible scripting access, rather than climbing through multiple levels. 14 public static class Scripting 15 { 16 /// <summary> 17 /// Provides scripting access to signals 18 /// </summary> 19 public static class Signal 20 { 21 /// <summary>This method returns the current aspect of the selected section</summary> 22 /// <param name="Train">The train for which we wish to get the section index</param> 23 /// <param name="SectionIndex">The section to get the aspect for</param> 24 /// <param name="IsPartOfTrain">Defines whether we wish to get the section index for the selected train, or for when placed via a .SigF command</param> 25 /// <returns>The aspect of the selected signal</returns> CurrentAspect(TrainBase Train, int SectionIndex, bool IsPartOfTrain)26 public static int CurrentAspect(TrainBase Train, int SectionIndex, bool IsPartOfTrain) 27 { 28 if (IsPartOfTrain) 29 { 30 int nextSectionIndex = Train.CurrentSectionIndex + 1; 31 if (nextSectionIndex >= 0 & nextSectionIndex < Program.CurrentRoute.Sections.Length) 32 { 33 int a = Program.CurrentRoute.Sections[nextSectionIndex].CurrentAspect; 34 if (a >= 0 & a < Program.CurrentRoute.Sections[nextSectionIndex].Aspects.Length) 35 { 36 return Program.CurrentRoute.Sections[nextSectionIndex].Aspects[a].Number; 37 } 38 return 0; 39 } 40 } 41 else if (SectionIndex >= 0 & SectionIndex < Program.CurrentRoute.Sections.Length) 42 { 43 int a = Program.CurrentRoute.Sections[SectionIndex].CurrentAspect; 44 if (a >= 0 & a < Program.CurrentRoute.Sections[SectionIndex].Aspects.Length) 45 { 46 return Program.CurrentRoute.Sections[SectionIndex].Aspects[a].Number; 47 } 48 } 49 return 0; 50 } 51 } 52 53 /// <summary> 54 /// Provides scripting access to trains internal variables 55 /// </summary> 56 public static class Train 57 { 58 /// <summary>Returns the number of cars in this train</summary> 59 /// <param name="Train">The selected train</param> 60 /// <returns>The number of cars</returns> numberOfCars(TrainBase Train)61 public static int numberOfCars(TrainBase Train) 62 { 63 if (Train != null) 64 { 65 return Train.Cars.Length; 66 } 67 return 0; 68 } 69 70 /// <summary>Returns the speed of the selected car </summary> 71 /// <param name="Train">The selected train</param> 72 /// <param name="CarIndex">The car for which to get the speed</param> 73 /// <returns>The speed in m/s</returns> speed(TrainBase Train, int CarIndex)74 public static double speed(TrainBase Train, int CarIndex) 75 { 76 if (Train == null) 77 { 78 return 0; 79 } 80 if (CarIndex > Train.Cars.Length) 81 { 82 return Train.Cars[0].CurrentSpeed; 83 } 84 return Train.Cars[CarIndex].CurrentSpeed; 85 } 86 87 /// <summary>Returns the speed of the selected car, accounting for wheelslip and wheel lock</summary> 88 /// <param name="Train">The selected train</param> 89 /// <param name="CarIndex">The car for which to get the speed</param> 90 /// <returns>The speed in m/s</returns> speedometer(TrainBase Train, int CarIndex)91 public static double speedometer(TrainBase Train, int CarIndex) 92 { 93 if (Train == null) 94 { 95 return 0; 96 } 97 return CarIndex > Train.Cars.Length 98 ? Train.Cars[0].Specs.PerceivedSpeed 99 : Train.Cars[CarIndex].Specs.PerceivedSpeed; 100 } 101 102 /// <summary>Returns the acceleration of the selected car</summary> 103 /// <param name="Train">The selected train</param> 104 /// <param name="CarIndex">The car for which to get the acceleration</param> 105 /// <returns>The acceleration in m/s</returns> acceleration(TrainBase Train, int CarIndex)106 public static double acceleration(TrainBase Train, int CarIndex) 107 { 108 if (Train == null) 109 { 110 return 0; 111 } 112 return CarIndex > Train.Cars.Length 113 ? Train.Cars[0].Specs.Acceleration 114 : Train.Cars[CarIndex].Specs.Acceleration; 115 } 116 117 /// <summary>Returns the acceleration that the first motor car is currently generating in m/s</summary> 118 /// <param name="Train">The selected train</param> 119 /// <returns>The acceleration in m/s</returns> accelerationMotor(TrainBase Train)120 public static double accelerationMotor(TrainBase Train) 121 { 122 if (Train == null) return 0.0; 123 for (int j = 0; j < Train.Cars.Length; j++) 124 { 125 if (Train.Cars[j].Specs.IsMotorCar) 126 { 127 // hack: MotorAcceleration does not distinguish between forward/backward 128 if (Train.Cars[j].Specs.MotorAcceleration < 0.0) 129 { 130 return Train.Cars[j].Specs.MotorAcceleration* 131 (double) Math.Sign(Train.Cars[j].CurrentSpeed); 132 } 133 if (Train.Cars[j].Specs.MotorAcceleration > 0.0) 134 { 135 return Train.Cars[j].Specs.MotorAcceleration* 136 (double) Train.Handles.Reverser.Actual; 137 } 138 } 139 } 140 return 0.0; 141 } 142 143 /// <summary>Returns the acceleration that the selected car's motor is currently generating in m/s</summary> 144 /// <param name="Train">The selected train</param> 145 /// <param name="CarIndex">The selected car</param> 146 /// <returns>The acceleration in m/s</returns> accelerationMotor(TrainBase Train, int CarIndex)147 public static double accelerationMotor(TrainBase Train, int CarIndex) 148 { 149 if (Train == null || Train.Cars.Length <= CarIndex) return 0.0; 150 if (Train.Cars[CarIndex].Specs.IsMotorCar) 151 { 152 // hack: MotorAcceleration does not distinguish between forward/backward 153 if (Train.Cars[CarIndex].Specs.MotorAcceleration < 0.0) 154 { 155 return Train.Cars[CarIndex].Specs.MotorAcceleration* 156 (double) Math.Sign(Train.Cars[CarIndex].CurrentSpeed); 157 } 158 if (Train.Cars[CarIndex].Specs.MotorAcceleration > 0.0) 159 { 160 return Train.Cars[CarIndex].Specs.MotorAcceleration* 161 (double) Train.Handles.Reverser.Actual; 162 } 163 } 164 return 0.0; 165 } 166 167 /// <summary>Returns the cartesian distance to the nearest car of the selected train</summary> 168 /// <param name="Train">The selected train</param> 169 /// <param name="Position">The object's absolute in-game position</param> 170 /// <returns>The distance to the object</returns> distance(TrainBase Train, Vector3 Position)171 public static double distance(TrainBase Train, Vector3 Position) 172 { 173 if (Train == null) return 0.0; 174 double dist = double.MaxValue; 175 for (int j = 0; j < Train.Cars.Length; j++) 176 { 177 double fx = Train.Cars[j].FrontAxle.Follower.WorldPosition.X - Position.X; 178 double fy = Train.Cars[j].FrontAxle.Follower.WorldPosition.Y - Position.Y; 179 double fz = Train.Cars[j].FrontAxle.Follower.WorldPosition.Z - Position.Z; 180 double f = fx*fx + fy*fy + fz*fz; 181 if (f < dist) dist = f; 182 double rx = Train.Cars[j].RearAxle.Follower.WorldPosition.X - Position.X; 183 double ry = Train.Cars[j].RearAxle.Follower.WorldPosition.Y - Position.Y; 184 double rz = Train.Cars[j].RearAxle.Follower.WorldPosition.Z - Position.Z; 185 double r = rx*rx + ry*ry + rz*rz; 186 if (r < dist) dist = r; 187 } 188 return Math.Sqrt(dist); 189 } 190 191 /// <summary>Returns the cartesian distance to the selected car of the selected train</summary> 192 /// <param name="Train">The selected train</param> 193 /// <param name="CarIndex">The selected car</param> 194 /// <param name="Position">The object's absolute in-game position</param> 195 /// <returns>The distance to the object</returns> distance(TrainBase Train, int CarIndex, Vector3 Position)196 public static double distance(TrainBase Train, int CarIndex, Vector3 Position) 197 { 198 if (Train == null || Train.Cars.Length <= CarIndex) return 0.0; 199 double x = 0.5* 200 (Train.Cars[CarIndex].FrontAxle.Follower.WorldPosition.X + 201 Train.Cars[CarIndex].RearAxle.Follower.WorldPosition.X) - Position.X; 202 double y = 0.5* 203 (Train.Cars[CarIndex].FrontAxle.Follower.WorldPosition.Y + 204 Train.Cars[CarIndex].RearAxle.Follower.WorldPosition.Y) - Position.Y; 205 double z = 0.5* 206 (Train.Cars[CarIndex].FrontAxle.Follower.WorldPosition.Z + 207 Train.Cars[CarIndex].RearAxle.Follower.WorldPosition.Z) - Position.Z; 208 return Math.Sqrt(x*x + y*y + z*z); 209 } 210 211 /// <summary>Returns the track distance to the nearest car of the selected train</summary> 212 /// <param name="Train">The selected train</param> 213 /// <param name="TrackPosition">The object's track position</param> 214 /// <returns>The distance to the object</returns> trackDistance(TrainBase Train, double TrackPosition)215 public static double trackDistance(TrainBase Train, double TrackPosition) 216 { 217 if (Train == null) return 0.0; 218 double t0 = Train.FrontCarTrackPosition(); 219 double t1 = Train.RearCarTrackPosition(); 220 return TrackPosition > t0 ? TrackPosition - t0 : TrackPosition < t1 ? TrackPosition - t1 : 0.0; 221 } 222 223 /// <summary>Returns the track distance to the nearest car of the selected train</summary> 224 /// <param name="Train">The selected train</param> 225 /// <param name="CarIndex">The selected car</param> 226 /// <param name="TrackPosition">The object's track position</param> 227 /// <returns>The distance to the object</returns> trackDistance(TrainBase Train, int CarIndex, double TrackPosition)228 public static double trackDistance(TrainBase Train, int CarIndex, double TrackPosition) 229 { 230 if (Train == null) return 0.0; 231 if (Train.Cars.Length > CarIndex) 232 { 233 CarIndex = Train.Cars.Length - 1; 234 } 235 double t1 = Train.Cars[CarIndex].RearAxle.Follower.TrackPosition - Train.Cars[CarIndex].RearAxle.Position - 236 0.5*Train.Cars[CarIndex].Length; 237 return TrackPosition < t1 ? TrackPosition - t1 : 0.0; 238 } 239 240 /// <summary>Returns the main brake reservoir pressure of the selected car of the selected train</summary> 241 /// <param name="Train">The selected train</param> 242 /// <param name="CarIndex">The selected car</param> 243 /// <returns>The main brake reservoir pressure in Pa</returns> mainReservoir(TrainBase Train, int CarIndex)244 public static double mainReservoir(TrainBase Train, int CarIndex) 245 { 246 if (Train == null) return 0.0; 247 if (Train.Cars.Length > CarIndex) 248 { 249 return 0.0; 250 } 251 return Train.Cars[CarIndex].CarBrake.mainReservoir.CurrentPressure; 252 } 253 254 /// <summary>Returns the brake pipe pressure of the selected car of the selected train</summary> 255 /// <param name="Train">The selected train</param> 256 /// <param name="CarIndex">The selected car</param> 257 /// <returns>The brake pipe pressure in Pa</returns> brakePipe(TrainBase Train, int CarIndex)258 public static double brakePipe(TrainBase Train, int CarIndex) 259 { 260 if (Train == null) return 0.0; 261 if (Train.Cars.Length > CarIndex) 262 { 263 return 0.0; 264 } 265 return Train.Cars[CarIndex].CarBrake.brakePipe.CurrentPressure; 266 } 267 268 /// <summary>Returns the brake cylinder pressure of the selected car of the selected train</summary> 269 /// <param name="Train">The selected train</param> 270 /// <param name="CarIndex">The selected car</param> 271 /// <returns>The brake cylinder pressure in Pa</returns> brakeCylinder(TrainBase Train, int CarIndex)272 public static double brakeCylinder(TrainBase Train, int CarIndex) 273 { 274 if (Train == null) return 0.0; 275 if (Train.Cars.Length > CarIndex) 276 { 277 return 0.0; 278 } 279 return Train.Cars[CarIndex].CarBrake.brakeCylinder.CurrentPressure; 280 } 281 282 /// <summary>Returns the brake pipe pressure of the selected car of the selected train</summary> 283 /// <param name="Train">The selected train</param> 284 /// <param name="CarIndex">The selected car</param> 285 /// <returns>The brake pipe pressure in Pa</returns> straightAirPipe(TrainBase Train, int CarIndex)286 public static double straightAirPipe(TrainBase Train, int CarIndex) 287 { 288 if (Train == null) return 0.0; 289 if (Train.Cars.Length > CarIndex) 290 { 291 return 0.0; 292 } 293 return Train.Cars[CarIndex].CarBrake.straightAirPipe.CurrentPressure; 294 } 295 296 /// <summary>Returns the doors state of the selected train</summary> 297 /// <param name="Train">The selected train</param> 298 /// <returns>0.0 if all doors are closed, 1.0 if all doors are open, or a value in between</returns> doors(TrainBase Train)299 public static double doors(TrainBase Train) 300 { 301 if (Train == null) return 0.0; 302 double doorsState = 0.0; 303 for (int j = 0; j < Train.Cars.Length; j++) 304 { 305 for (int k = 0; k < Train.Cars[j].Doors.Length; k++) 306 { 307 if (Train.Cars[j].Doors[k].State > doorsState) 308 { 309 doorsState = Train.Cars[j].Doors[k].State; 310 } 311 } 312 } 313 return doorsState; 314 } 315 316 /// <summary>Returns the doors state of the selected car of the selected train</summary> 317 /// <param name="Train">The selected train</param> 318 /// <param name="CarIndex">The selected car</param> 319 /// <returns>0.0 if all doors are closed, 1.0 if all doors are open, or a value in between</returns> doors(TrainBase Train, int CarIndex)320 public static double doors(TrainBase Train, int CarIndex) 321 { 322 if (Train == null) return 0.0; 323 if (Train.Cars.Length <= CarIndex) 324 { 325 double doorsState = 0.0; 326 for (int k = 0; k < Train.Cars[CarIndex].Doors.Length; k++) 327 { 328 if (Train.Cars[CarIndex].Doors[k].State > doorsState) 329 { 330 doorsState = Train.Cars[CarIndex].Doors[k].State; 331 } 332 } 333 return doorsState; 334 } 335 return 0.0; 336 } 337 338 /// <summary>Returns the left-hand doors state of the selected train</summary> 339 /// <param name="Train">The selected train</param> 340 /// <returns>0.0 if all doors are closed, 1.0 if all doors are open, or a value in between</returns> leftDoors(TrainBase Train)341 public static double leftDoors(TrainBase Train) 342 { 343 if (Train == null) return 0.0; 344 double doorsState = 0.0; 345 for (int j = 0; j < Train.Cars.Length; j++) 346 { 347 for (int k = 0; k < Train.Cars[j].Doors.Length; k++) 348 { 349 if (Train.Cars[j].Doors[k].Direction == -1 & 350 Train.Cars[j].Doors[k].State > doorsState) 351 { 352 doorsState = Train.Cars[j].Doors[k].State; 353 } 354 } 355 } 356 return doorsState; 357 } 358 359 /// <summary>Returns the left-hand doors state of the selected car of the selected train</summary> 360 /// <param name="Train">The selected train</param> 361 /// <param name="CarIndex">The selected car</param> 362 /// <returns>0.0 if all doors are closed, 1.0 if all doors are open, or a value in between</returns> leftDoors(TrainBase Train, int CarIndex)363 public static double leftDoors(TrainBase Train, int CarIndex) 364 { 365 if (Train == null) return 0.0; 366 if (Train.Cars.Length <= CarIndex) 367 { 368 double doorsState = 0.0; 369 for (int k = 0; k < Train.Cars[CarIndex].Doors.Length; k++) 370 { 371 if (Train.Cars[CarIndex].Doors[k].Direction == -1 & 372 Train.Cars[CarIndex].Doors[k].State > doorsState) 373 { 374 doorsState = Train.Cars[CarIndex].Doors[k].State; 375 } 376 } 377 return doorsState; 378 } 379 return 0.0; 380 } 381 382 /// <summary>Returns the left-hand doors state of the selected train</summary> 383 /// <param name="Train">The selected train</param> 384 /// <returns>0.0 if all doors are closed, 1.0 if all doors are open, or a value in between</returns> rightDoors(TrainBase Train)385 public static double rightDoors(TrainBase Train) 386 { 387 if (Train == null) return 0.0; 388 double doorsState = 0.0; 389 for (int j = 0; j < Train.Cars.Length; j++) 390 { 391 for (int k = 0; k < Train.Cars[j].Doors.Length; k++) 392 { 393 if (Train.Cars[j].Doors[k].Direction == 1 & 394 Train.Cars[j].Doors[k].State > doorsState) 395 { 396 doorsState = Train.Cars[j].Doors[k].State; 397 } 398 } 399 } 400 return doorsState; 401 } 402 403 /// <summary>Returns the left-hand doors state of the selected car of the selected train</summary> 404 /// <param name="Train">The selected train</param> 405 /// <param name="CarIndex">The selected car</param> 406 /// <returns>0.0 if all doors are closed, 1.0 if all doors are open, or a value in between</returns> rightDoors(TrainBase Train, int CarIndex)407 public static double rightDoors(TrainBase Train, int CarIndex) 408 { 409 if (Train == null) return 0.0; 410 if (Train.Cars.Length <= CarIndex) 411 { 412 double doorsState = 0.0; 413 for (int k = 0; k < Train.Cars[CarIndex].Doors.Length; k++) 414 { 415 if (Train.Cars[CarIndex].Doors[k].Direction == 1 & 416 Train.Cars[CarIndex].Doors[k].State > doorsState) 417 { 418 doorsState = Train.Cars[CarIndex].Doors[k].State; 419 } 420 } 421 return doorsState; 422 } 423 return 0.0; 424 } 425 426 /// <summary>Returns whether the left doors are opening for the selected train</summary> 427 /// <param name="Train">The selected train</param> 428 /// <returns>True if the doors are opening, false otherwise</returns> leftDoorsTarget(TrainBase Train)429 public static bool leftDoorsTarget(TrainBase Train) 430 { 431 if (Train == null) return false; 432 for (int j = 0; j < Train.Cars.Length; j++) 433 { 434 for (int k = 0; k < Train.Cars.Length; k++) 435 { 436 if (Train.Cars[j].Doors[0].AnticipatedOpen) 437 { 438 return true; 439 } 440 } 441 } 442 return false; 443 } 444 445 /// <summary>Returns whether the left doors are opening for the selected car of the selected train</summary> 446 /// <param name="Train">The selected train</param> 447 /// <param name="CarIndex">The selected car</param> 448 /// <returns>True if the doors are opening, false otherwise</returns> leftDoorsTarget(TrainBase Train, int CarIndex)449 public static bool leftDoorsTarget(TrainBase Train, int CarIndex) 450 { 451 if (Train == null) return false; 452 if (Train.Cars.Length <= CarIndex) 453 { 454 if (Train.Cars[CarIndex].Doors[0].AnticipatedOpen) 455 { 456 return true; 457 } 458 459 } 460 return false; 461 } 462 463 /// <summary>Returns whether the left doors are opening for the selected train</summary> 464 /// <param name="Train">The selected train</param> 465 /// <returns>True if the doors are opening, false otherwise</returns> rightDoorsTarget(TrainBase Train)466 public static bool rightDoorsTarget(TrainBase Train) 467 { 468 if (Train == null) return false; 469 for (int j = 0; j < Train.Cars.Length; j++) 470 { 471 for (int k = 0; k < Train.Cars.Length; k++) 472 { 473 if (Train.Cars[j].Doors[1].AnticipatedOpen) 474 { 475 return true; 476 } 477 } 478 } 479 return false; 480 } 481 482 /// <summary>Returns whether the left doors are opening for the selected car of the selected train</summary> 483 /// <param name="Train">The selected train</param> 484 /// <param name="CarIndex">The selected car</param> 485 /// <returns>True if the doors are opening, false otherwise</returns> rightDoorsTarget(TrainBase Train, int CarIndex)486 public static bool rightDoorsTarget(TrainBase Train, int CarIndex) 487 { 488 if (Train == null) return false; 489 if (Train.Cars.Length <= CarIndex) 490 { 491 if (Train.Cars[CarIndex].Doors[1].AnticipatedOpen) 492 { 493 return true; 494 } 495 496 } 497 return false; 498 } 499 500 /// <summary>Returns the driver's selected reverser position for the selected train</summary> 501 /// <param name="Train">The selected train</param> 502 /// <returns>-1 for backwards, 0 for neutral, 1 for forwards</returns> reverserNotch(TrainBase Train)503 public static int reverserNotch(TrainBase Train) 504 { 505 if (Train == null) return 0; 506 return (int)Train.Handles.Reverser.Driver; 507 } 508 509 /// <summary>Returns the driver's selected power notch for the selected train</summary> 510 /// <param name="Train">The selected train</param> 511 /// <returns>The driver's selected power notch</returns> powerNotch(TrainBase Train)512 public static int powerNotch(TrainBase Train) 513 { 514 if (Train == null) return 0; 515 return Train.Handles.Power.Driver; 516 } 517 518 /// <summary>Returns the maximum power notch for the selected train</summary> 519 /// <param name="Train">The selected train</param> 520 /// <returns>The maximum power notch</returns> powerNotches(TrainBase Train)521 public static int powerNotches(TrainBase Train) 522 { 523 if (Train == null) return 0; 524 return Train.Handles.Power.MaximumNotch; 525 } 526 527 /// <summary>Returns the driver's selected brake notch for the selected train</summary> 528 /// <param name="Train">The selected train</param> 529 /// <returns>The driver's selected power notch</returns> brakeNotch(TrainBase Train)530 public static int brakeNotch(TrainBase Train) 531 { 532 if (Train == null) return 0; 533 return Train.Handles.Brake.Driver; 534 } 535 536 /// <summary>Returns the maximum brake notch for the selected train</summary> 537 /// <param name="Train">The selected train</param> 538 /// <returns>The maximum power notch</returns> brakeNotches(TrainBase Train)539 public static int brakeNotches(TrainBase Train) 540 { 541 if (Train == null) return 0; 542 return Train.Handles.Brake.MaximumNotch; 543 } 544 545 /// <summary>Returns the driver's selected brake notch (Including EB) for the selected train</summary> 546 /// <param name="Train">The selected train</param> 547 /// <returns>The driver's selected brake notch</returns> brakeNotchLinear(TrainBase Train)548 public static int brakeNotchLinear(TrainBase Train) 549 { 550 if (Train == null) return 0; 551 if (Train.Handles.Brake is AirBrakeHandle) 552 { 553 if (Train.Handles.EmergencyBrake.Driver) 554 { 555 return 3; 556 } 557 return (int) Train.Handles.Brake.Driver; 558 } 559 if (Train.Handles.HasHoldBrake) 560 { 561 if (Train.Handles.EmergencyBrake.Driver) 562 { 563 return (int) Train.Handles.Brake.MaximumNotch + 2; 564 } 565 if (Train.Handles.Brake.Driver > 0) 566 { 567 return (int) Train.Handles.Brake.Driver + 1; 568 } 569 return Train.Handles.HoldBrake.Driver ? 1 : 0; 570 } 571 if (Train.Handles.EmergencyBrake.Driver) 572 { 573 return (int) Train.Handles.Brake.MaximumNotch + 1; 574 } 575 return (int) Train.Handles.Brake.Driver; 576 } 577 578 /// <summary>Returns the maximum possible brake notch (Including EB) for the selected train</summary> 579 /// <param name="Train">The selected train</param> 580 /// <returns>The maximum possible brake notch</returns> brakeNotchesLinear(TrainBase Train)581 public static int brakeNotchesLinear(TrainBase Train) 582 { 583 if (Train == null) return 0; 584 if (Train.Handles.Brake is AirBrakeHandle) 585 { 586 return 3; 587 } 588 if (Train.Handles.HasHoldBrake) 589 { 590 return 2; 591 } 592 return Train.Handles.Brake.MaximumNotch + 1; 593 } 594 595 /// <summary>Returns whether EB is active for the selected train</summary> 596 /// <param name="Train">The selected train</param> 597 /// <returns>Whether EB is active</returns> emergencyBrake(TrainBase Train)598 public static bool emergencyBrake(TrainBase Train) 599 { 600 if (Train == null) return false; 601 return Train.Handles.EmergencyBrake.Driver; 602 } 603 604 /// <summary>Whether the selected train has an automatic air brake</summary> 605 /// <param name="Train">The selected train</param> 606 /// <returns>Whether the selected train has an automatic air brake</returns> hasAirBrake(TrainBase Train)607 public static bool hasAirBrake(TrainBase Train) 608 { 609 if (Train == null) return false; 610 return Train.Handles.Brake is AirBrakeHandle; 611 } 612 613 /// <summary>Whether the hold brake is currently active for the selected train</summary> 614 /// <param name="Train">The selected train</param> 615 /// <returns>Whether the hold brake is currently active</returns> holdBrake(TrainBase Train)616 public static bool holdBrake(TrainBase Train) 617 { 618 if (Train == null) return false; 619 return Train.Handles.HoldBrake.Driver; 620 } 621 622 /// <summary>Whether the selected train has a hold brake</summary> 623 /// <param name="Train">The selected train</param> 624 /// <returns>Whether the selected train has a hold brake</returns> hasHoldBrake(TrainBase Train)625 public static bool hasHoldBrake(TrainBase Train) 626 { 627 if (Train == null) return false; 628 return Train.Handles.HasHoldBrake; 629 } 630 631 /// <summary>Whether the constant speed devicee is currently active for the selected train</summary> 632 /// <param name="Train">The selected train</param> 633 /// <returns>Whether the constant speed device is currently active</returns> constantSpeed(TrainBase Train)634 public static bool constantSpeed(TrainBase Train) 635 { 636 if (Train == null) return false; 637 return Train.Specs.CurrentConstSpeed; 638 } 639 640 /// <summary>Whether the selected train has a constant speed device</summary> 641 /// <param name="Train">The selected train</param> 642 /// <returns>Whether the selected train has a constant speed device</returns> hasConstantSpeed(TrainBase Train)643 public static bool hasConstantSpeed(TrainBase Train) 644 { 645 if (Train == null) return false; 646 return Train.Specs.HasConstSpeed; 647 } 648 649 /// <summary>Whether the selected train uses a custom plugin</summary> 650 /// <param name="Train">The selected train</param> 651 /// <returns>True if the train uses a custom plugin, false otherwise</returns> hasPlugin(TrainBase Train)652 public static bool hasPlugin(TrainBase Train) 653 { 654 if (Train == null) return false; 655 if (Train.IsPlayerTrain && Train.Plugin != null) 656 { 657 return TrainManager.PlayerTrain.Plugin.IsDefault; 658 } 659 return false; 660 } 661 662 /// <summary>Whether the selected train has a hold brake</summary> 663 /// <param name="Train">The selected train</param> 664 /// <param name="pluginState">The plugin state to query</param> 665 /// <returns>The plugin state value</returns> pluginState(TrainBase Train, int pluginState)666 public static int pluginState(TrainBase Train, int pluginState) 667 { 668 if (Train == null || Train.Plugin == null) 669 { 670 return 0; 671 } 672 673 if (pluginState >= 0 & pluginState < Train.Plugin.Panel.Length) 674 { 675 return Train.Plugin.Panel[pluginState]; 676 } 677 return 0; 678 } 679 } 680 681 /// <summary> 682 /// Provides scripting access to in simulation variables 683 /// </summary> 684 public static class Simulation 685 { 686 /// <summary> 687 /// Gets the current in-simulation time 688 /// </summary> 689 /// <returns>Returns the number of seconds elapsed since midnight on the first day</returns> time()690 public static double time() 691 { 692 return Program.CurrentRoute.SecondsSinceMidnight; 693 } 694 695 /// <summary>Gets the camera distance in meters from the current object </summary> 696 /// <param name="Position">The absolute in-game position of the current object to test against</param> 697 /// <returns>The distance in meters</returns> CameraDistance(Vector3 Position)698 public static double CameraDistance(Vector3 Position) 699 { 700 double dx = Program.Renderer.Camera.AbsolutePosition.X - Position.X; 701 double dy = Program.Renderer.Camera.AbsolutePosition.Y - Position.Y; 702 double dz = Program.Renderer.Camera.AbsolutePosition.Z - Position.Z; 703 return Math.Sqrt(dx * dx + dy * dy + dz * dz); 704 } 705 } 706 } 707 } 708