public Person(string name, SpritesetInstance spriteset, bool destroy) { #if(DEBUG) if (_debug1 == null) _debug1 = new ColorInstance(Program._engine, Color.Magenta); if (_debug2 == null) _debug2 = new ColorInstance(Program._engine, Color.Red); #endif Name = name; DestroyOnMap = destroy; Speed = new Vector2f(1, 1); _innerSS = spriteset; Data = Program.CreateObject(); _base = _innerSS.GetBase(); _sprite = new Sprite(_innerSS.TextureAtlas.Texture); Mask = new Color(255, 255, 255); Scripts = new FunctionScript[5]; string d = GetDirectionAt(0); if (!String.IsNullOrEmpty(d)) Direction = d; }
public void SetScript(PersonScripts script, object instance) { if (instance == null || instance.ToString() == "") Scripts[(int)script] = null; else Scripts[(int)script] = new FunctionScript(instance); }
/// <summary>Creates a new sound buffer</summary> /// <param name="path">The on-disk path to the sound to load</param> /// <param name="radius">The radius for this sound</param> internal SoundBuffer(string path, double radius) { this.Origin = new PathOrigin(path, Program.CurrentHost); this.Radius = radius; this.Loaded = false; this.OpenAlBufferName = 0; this.Duration = 0.0; this.InternalVolumeFactor = 0.5; this.Ignore = false; this.PitchFunction = null; this.VolumeFunction = null; }
/// <summary>Creates a new sound buffer</summary> /// <param name="sound">The raw sound source, loaded via an API plugin</param> /// <param name="radius">The radius of the sound</param> internal SoundBuffer(OpenBveApi.Sounds.Sound sound, double radius) { this.Origin = new RawOrigin(sound); this.Radius = radius; this.Loaded = false; this.OpenAlBufferName = 0; this.Duration = 0.0; this.InternalVolumeFactor = 0.5; this.Ignore = false; this.PitchFunction = null; this.VolumeFunction = null; }
/// <summary>Creates a new sound buffer from the specified sound origin</summary> /// <param name="origin">The SoundOrigin describing where to load the sound from</param> internal SoundBuffer(SoundOrigin origin) { this.Origin = origin; this.Radius = 0.0; this.Loaded = false; this.OpenAlBufferName = 0; this.Duration = 0.0; this.InternalVolumeFactor = 0.5; this.Ignore = false; this.PitchFunction = null; this.VolumeFunction = null; }
/// <summary>Creates a new sound buffer</summary> /// <param name="host">The host application</param> /// <param name="path">The on-disk path to the sound to load</param> /// <param name="radius">The radius for this sound</param> internal SoundBuffer(HostInterface host, string path, double radius) { Origin = new PathOrigin(path, host); Radius = radius; Loaded = false; OpenAlBufferName = 0; _duration = 0.0; InternalVolumeFactor = 0.5; Ignore = false; PitchFunction = null; VolumeFunction = null; }
/// <summary>Creates a new sound buffer</summary> /// <param name="sound">The raw sound source, loaded via an API plugin</param> /// <param name="radius">The radius of the sound</param> internal SoundBuffer(Sound sound, double radius) { Origin = new RawOrigin(sound); Radius = radius; Loaded = false; OpenAlBufferName = 0; _duration = 0.0; InternalVolumeFactor = 0.5; Ignore = false; PitchFunction = null; VolumeFunction = null; }
/// <summary>Creates a new sound buffer from the specified sound origin</summary> /// <param name="origin">The SoundOrigin describing where to load the sound from</param> internal SoundBuffer(SoundOrigin origin) { Origin = origin; Radius = 0.0; Loaded = false; OpenAlBufferName = 0; _duration = 0.0; InternalVolumeFactor = 0.5; Ignore = false; PitchFunction = null; VolumeFunction = null; }
private async Task <ProcessResult> RunFunction(FunctionScript function) { ProcessResult processResult = new ProcessResult(); processResult.Id = function.Id; var ret = await _mediator.Send(function.Expression); foreach (var childFunction in function.ChildFunctions) { processResult.ChildResult.Add(await RunFunction(childFunction)); } return(processResult); }
private static bool CheckForConstantResult(FunctionScript Function) { if (Function.Instructions.Length == 1 && Function.Instructions[0] == Instructions.SystemConstant) { return true; } for (int i = 0; i < Function.Instructions.Length; i++) { if ((int) Function.Instructions[i] >= (int) Instructions.LogicalXor) { return false; } } return true; }
public PersonCommand(int cmd, bool imm, object code = null) { command = cmd; immediate = imm; if (code != null && (code is string || code is Jurassic.ConcatenatedString)) { string key = code.ToString(); if (!_cache.ContainsKey(key)) { script = new FunctionScript(code); _cache[key] = script; } else script = _cache[key]; } else script = null; }
public DelayScript(object code, int frames) { _script = new FunctionScript(code); _frames_left = frames; }
private static void SetDefaultMapScript(int type, object code) { if (code == null || (code is string && code.Equals(""))) _defscripts[type] = null; else _defscripts[type] = new FunctionScript(code); }
/// <summary> /// Compiles the loaded default map scripts for this map. /// </summary> private static void CompileMapScripts() { for (var i = 3; i < _map.Scripts.Count; ++i) { if (!String.IsNullOrEmpty(_map.Scripts[i])) _scripts[i - 3] = new FunctionScript(_map.Scripts[i]); else _scripts[i - 3] = null; } }
// get function script from postfix notation internal static FunctionScript GetFunctionScriptFromPostfixNotation(string Expression) { Expression = GetOptimizedPostfixNotation(Expression); System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture; FunctionScript Result = new FunctionScript(); string[] Arguments = Expression.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); Result.Instructions = new Instructions[16]; int n = 0; Result.Stack = new double[16]; int m = 0, s = 0; Result.Constants = new double[16]; int c = 0; for (int i = 0; i < Arguments.Length; i++) { double d; if (double.TryParse(Arguments[i], System.Globalization.NumberStyles.Float, Culture, out d)) { if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.SystemConstant; if (c >= Result.Constants.Length) Array.Resize<double>(ref Result.Constants, Result.Constants.Length << 1); Result.Constants[c] = d; n++; c++; s++; if (s >= m) m = s; } else { switch (Arguments[i].ToLowerInvariant()) { // system case "halt": throw new System.InvalidOperationException("The halt instruction was encountered in function script " + Expression); case "value": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.SystemValue; n++; s++; if (s >= m) m = s; break; case "delta": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.SystemDelta; n++; s++; if (s >= m) m = s; break; // stack case "~": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.StackCopy; n++; s++; if (s >= m) m = s; break; case "<>": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.StackSwap; n++; break; // math case "+": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathPlus; n++; s--; break; case "-": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathSubtract; n++; s--; break; case "minus": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathMinus; n++; break; case "*": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathTimes; n++; s--; break; case "/": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathDivide; n++; s--; break; case "reciprocal": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathReciprocal; n++; break; case "power": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathPower; n++; s--; break; case "++": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathIncrement; n++; break; case "--": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathDecrement; n++; break; case "fma": if (s < 3) throw new System.InvalidOperationException(Arguments[i] + " requires at least 3 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathFusedMultiplyAdd; n++; s -= 2; break; case "quotient": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathQuotient; n++; s--; break; case "mod": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathMod; n++; s--; break; case "floor": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathFloor; n++; break; case "ceiling": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathCeiling; n++; break; case "round": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathRound; n++; break; case "min": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathMin; n++; s--; break; case "max": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathMax; n++; s--; break; case "abs": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathAbs; n++; break; case "sign": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathSign; n++; break; case "exp": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathExp; n++; break; case "log": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathLog; n++; break; case "sqrt": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathSqrt; n++; break; case "sin": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathSin; n++; break; case "cos": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathCos; n++; break; case "tan": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathTan; n++; break; case "arctan": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.MathArcTan; n++; break; case "==": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareEqual; n++; s--; break; case "!=": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareUnequal; n++; s--; break; // conditionals case "<": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareLess; n++; s--; break; case ">": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareGreater; n++; s--; break; case "<=": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareLessEqual; n++; s--; break; case ">=": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareGreaterEqual; n++; s--; break; case "?": if (s < 3) throw new System.InvalidOperationException(Arguments[i] + " requires at least 3 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CompareConditional; n++; s -= 2; break; // logical case "!": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LogicalNot; n++; break; case "&": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LogicalAnd; n++; s--; break; case "|": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LogicalOr; n++; s--; break; case "!&": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LogicalNand; n++; s--; break; case "!|": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LogicalNor; n++; s--; break; case "^": if (s < 2) throw new System.InvalidOperationException(Arguments[i] + " requires at least 2 arguments on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LogicalXor; n++; s--; break; // time/camera case "time": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TimeSecondsSinceMidnight; n++; s++; if (s >= m) m = s; break; case "cameradistance": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.CameraDistance; n++; s++; if (s >= m) m = s; break; // train case "cars": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainCars; n++; s++; if (s >= m) m = s; break; case "speed": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainSpeed; n++; s++; if (s >= m) m = s; break; case "speedindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainSpeedOfCar; n++; break; case "speedometer": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainSpeedometer; n++; s++; if (s >= m) m = s; break; case "speedometerindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainSpeedometerOfCar; n++; break; case "acceleration": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainAcceleration; n++; s++; if (s >= m) m = s; break; case "accelerationindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainAccelerationOfCar; n++; break; case "accelerationmotor": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainAccelerationMotor; n++; s++; if (s >= m) m = s; break; case "accelerationmotorindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainAccelerationMotorOfCar; n++; break; case "distance": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainDistance; n++; s++; if (s >= m) m = s; break; case "distanceindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainDistanceToCar; n++; break; case "trackdistance": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainTrackDistance; n++; s++; if (s >= m) m = s; break; case "trackdistanceindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TrainTrackDistanceToCar; n++; break; // train: doors case "doors": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.Doors; n++; s++; if (s >= m) m = s; break; case "doorsindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.DoorsIndex; n++; break; case "leftdoors": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LeftDoors; n++; s++; if (s >= m) m = s; break; case "leftdoorsindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LeftDoorsIndex; n++; break; case "rightdoors": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.RightDoors; n++; s++; if (s >= m) m = s; break; case "rightdoorsindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.RightDoorsIndex; n++; break; case "leftdoorstarget": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LeftDoorsTarget; n++; s++; if (s >= m) m = s; break; case "leftdoorstargetindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.LeftDoorsTargetIndex; n++; break; case "rightdoorstarget": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.RightDoorsTarget; n++; s++; if (s >= m) m = s; break; case "rightdoorstargetindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.RightDoorsTargetIndex; n++; break; // train: handles case "reversernotch": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.ReverserNotch; n++; s++; if (s >= m) m = s; break; case "powernotch": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.PowerNotch; n++; s++; if (s >= m) m = s; break; case "powernotches": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.PowerNotches; n++; s++; if (s >= m) m = s; break; case "brakenotch": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeNotch; n++; s++; if (s >= m) m = s; break; case "brakenotches": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeNotches; n++; s++; if (s >= m) m = s; break; case "brakenotchlinear": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeNotchLinear; n++; s++; if (s >= m) m = s; break; case "brakenotcheslinear": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeNotchesLinear; n++; s++; if (s >= m) m = s; break; case "emergencybrake": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.EmergencyBrake; n++; s++; if (s >= m) m = s; break; case "hasairbrake": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.HasAirBrake; n++; s++; if (s >= m) m = s; break; case "holdbrake": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.HoldBrake; n++; s++; if (s >= m) m = s; break; case "hasholdbrake": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.HasHoldBrake; n++; s++; if (s >= m) m = s; break; case "constspeed": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.ConstSpeed; n++; s++; if (s >= m) m = s; break; case "hasconstspeed": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.HasConstSpeed; n++; s++; if (s >= m) m = s; break; // train: brake case "mainreservoir": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeMainReservoir; n++; s++; if (s >= m) m = s; break; case "mainreservoirindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeMainReservoirOfCar; n++; break; case "equalizingreservoir": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeEqualizingReservoir; n++; s++; if (s >= m) m = s; break; case "equalizingreservoirindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeEqualizingReservoirOfCar; n++; break; case "brakepipe": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeBrakePipe; n++; s++; if (s >= m) m = s; break; case "brakepipeindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeBrakePipeOfCar; n++; break; case "brakecylinder": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeBrakeCylinder; n++; s++; if (s >= m) m = s; break; case "brakecylinderindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeBrakeCylinderOfCar; n++; break; case "straightairpipe": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeStraightAirPipe; n++; s++; if (s >= m) m = s; break; case "straightairpipeindex": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.BrakeStraightAirPipeOfCar; n++; break; // train: safety case "hasplugin": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.SafetyPluginAvailable; n++; s++; if (s >= m) m = s; break; case "pluginstate": if (s < 1) throw new System.InvalidOperationException(Arguments[i] + " requires at least 1 argument on the stack in function script " + Expression); if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.SafetyPluginState; n++; break; // train: timetable case "timetable": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.TimetableVisible; n++; s++; if (s >= m) m = s; break; // sections case "section": if (n >= Result.Instructions.Length) Array.Resize<Instructions>(ref Result.Instructions, Result.Instructions.Length << 1); Result.Instructions[n] = Instructions.SectionAspectNumber; n++; s++; if (s >= m) m = s; break; // default default: throw new System.IO.InvalidDataException("Unknown command " + Arguments[i] + " encountered in function script " + Expression); } } } if (s != 1) { throw new System.InvalidOperationException("There must be exactly one argument left on the stack at the end in function script " + Expression); } Array.Resize<Instructions>(ref Result.Instructions, n); Array.Resize<double>(ref Result.Stack, m); Array.Resize<double>(ref Result.Constants, c); return Result; }
// execute function script private static void ExecuteFunctionScript(FunctionScript Function, TrainManager.Train Train, int CarIndex, World.Vector3D Position, double TrackPosition, int SectionIndex, bool IsPartOfTrain, double TimeElapsed) { int s = 0, c = 0; for (int i = 0; i < Function.Instructions.Length; i++) { switch (Function.Instructions[i]) { // system case Instructions.SystemHalt: i = Function.Instructions.Length; break; case Instructions.SystemConstant: Function.Stack[s] = Function.Constants[c]; s++; c++; break; case Instructions.SystemConstantArray: { int n = (int)Function.Instructions[i + 1]; for (int j = 0; j < n; j++) { Function.Stack[s + j] = Function.Constants[c + j]; } s += n; c += n; i++; } break; case Instructions.SystemValue: Function.Stack[s] = Function.LastResult; s++; break; case Instructions.SystemDelta: Function.Stack[s] = TimeElapsed; s++; break; // stack case Instructions.StackCopy: Function.Stack[s] = Function.Stack[s - 1]; s++; break; case Instructions.StackSwap: { double a = Function.Stack[s - 1]; Function.Stack[s - 1] = Function.Stack[s - 2]; Function.Stack[s - 2] = a; } break; // math case Instructions.MathPlus: Function.Stack[s - 2] += Function.Stack[s - 1]; s--; break; case Instructions.MathSubtract: Function.Stack[s - 2] -= Function.Stack[s - 1]; s--; break; case Instructions.MathMinus: Function.Stack[s - 1] = -Function.Stack[s - 1]; break; case Instructions.MathTimes: Function.Stack[s - 2] *= Function.Stack[s - 1]; s--; break; case Instructions.MathDivide: Function.Stack[s - 2] = Function.Stack[s - 1] == 0.0 ? 0.0 : Function.Stack[s - 2] / Function.Stack[s - 1]; s--; break; case Instructions.MathReciprocal: Function.Stack[s - 1] = Function.Stack[s - 1] == 0.0 ? 0.0 : 1.0 / Function.Stack[s - 1]; break; case Instructions.MathPower: { double a = Function.Stack[s - 2]; double b = Function.Stack[s - 1]; if (b == 2.0) { Function.Stack[s - 2] = a * a; } else if (b == 3.0) { Function.Stack[s - 2] = a * a * a; } else if (b == 4.0) { double t = a * a; Function.Stack[s - 2] = t * t; } else if (b == 5.0) { double t = a * a; Function.Stack[s - 2] = t * t * a; } else if (b == 6.0) { double t = a * a * a; Function.Stack[s - 2] = t * t; } else if (b == 7.0) { double t = a * a * a; Function.Stack[s - 2] = t * t * a; } else if (b == 8.0) { double t = a * a; t *= t; Function.Stack[s - 2] = t * t; } else if (b == 0.0) { Function.Stack[s - 2] = 1.0; } else if (b < 0.0) { Function.Stack[s - 2] = 0.0; } else { Function.Stack[s - 2] = Math.Pow(a, b); } s--; break; } case Instructions.MathIncrement: Function.Stack[s - 1] += 1.0; break; case Instructions.MathDecrement: Function.Stack[s - 1] -= 1.0; break; case Instructions.MathFusedMultiplyAdd: Function.Stack[s - 3] = Function.Stack[s - 3] * Function.Stack[s - 2] + Function.Stack[s - 1]; s -= 2; break; case Instructions.MathQuotient: Function.Stack[s - 2] = Function.Stack[s - 1] == 0.0 ? 0.0 : Math.Floor(Function.Stack[s - 2] / Function.Stack[s - 1]); s--; break; case Instructions.MathMod: Function.Stack[s - 2] = Function.Stack[s - 1] == 0.0 ? 0.0 : Function.Stack[s - 2] - Function.Stack[s - 1] * Math.Floor(Function.Stack[s - 2] / Function.Stack[s - 1]); s--; break; case Instructions.MathFloor: Function.Stack[s - 1] = Math.Floor(Function.Stack[s - 1]); break; case Instructions.MathCeiling: Function.Stack[s - 1] = Math.Ceiling(Function.Stack[s - 1]); break; case Instructions.MathRound: Function.Stack[s - 1] = Math.Round(Function.Stack[s - 1]); break; case Instructions.MathMin: Function.Stack[s - 2] = Function.Stack[s - 2] < Function.Stack[s - 1] ? Function.Stack[s - 2] : Function.Stack[s - 1]; s--; break; case Instructions.MathMax: Function.Stack[s - 2] = Function.Stack[s - 2] > Function.Stack[s - 1] ? Function.Stack[s - 2] : Function.Stack[s - 1]; s--; break; case Instructions.MathAbs: Function.Stack[s - 1] = Math.Abs(Function.Stack[s - 1]); break; case Instructions.MathSign: Function.Stack[s - 1] = Math.Sign(Function.Stack[s - 1]); break; case Instructions.MathExp: Function.Stack[s - 1] = Math.Exp(Function.Stack[s - 1]); break; case Instructions.MathLog: Function.Stack[s - 1] = Log(Function.Stack[s - 1]); break; case Instructions.MathSqrt: Function.Stack[s - 1] = Sqrt(Function.Stack[s - 1]); break; case Instructions.MathSin: Function.Stack[s - 1] = Math.Sin(Function.Stack[s - 1]); break; case Instructions.MathCos: Function.Stack[s - 1] = Math.Cos(Function.Stack[s - 1]); break; case Instructions.MathTan: Function.Stack[s - 1] = Tan(Function.Stack[s - 1]); break; case Instructions.MathArcTan: Function.Stack[s - 1] = Math.Atan(Function.Stack[s - 1]); break; // comparisons case Instructions.CompareEqual: Function.Stack[s - 2] = Function.Stack[s - 2] == Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareUnequal: Function.Stack[s - 2] = Function.Stack[s - 2] != Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareLess: Function.Stack[s - 2] = Function.Stack[s - 2] < Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareGreater: Function.Stack[s - 2] = Function.Stack[s - 2] > Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareLessEqual: Function.Stack[s - 2] = Function.Stack[s - 2] <= Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareGreaterEqual: Function.Stack[s - 2] = Function.Stack[s - 2] >= Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareConditional: Function.Stack[s - 3] = Function.Stack[s - 3] != 0.0 ? Function.Stack[s - 2] : Function.Stack[s - 1]; s -= 2; break; // logical case Instructions.LogicalNot: Function.Stack[s - 1] = Function.Stack[s - 1] != 0.0 ? 0.0 : 1.0; break; case Instructions.LogicalAnd: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 & Function.Stack[s - 1] != 0.0 ? 1.0 : 0.0; s--; break; case Instructions.LogicalOr: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 | Function.Stack[s - 1] != 0.0 ? 1.0 : 0.0; s--; break; case Instructions.LogicalNand: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 & Function.Stack[s - 1] != 0.0 ? 0.0 : 1.0; s--; break; case Instructions.LogicalNor: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 | Function.Stack[s - 1] != 0.0 ? 0.0 : 1.0; s--; break; case Instructions.LogicalXor: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 ^ Function.Stack[s - 1] != 0.0 ? 1.0 : 0.0; s--; break; // time/camera case Instructions.TimeSecondsSinceMidnight: Function.Stack[s] = Game.SecondsSinceMidnight; s++; break; case Instructions.CameraDistance: { double dx = World.AbsoluteCameraPosition.X - Position.X; double dy = World.AbsoluteCameraPosition.Y - Position.Y; double dz = World.AbsoluteCameraPosition.Z - Position.Z; Function.Stack[s] = Math.Sqrt(dx * dx + dy * dy + dz * dz); s++; } break; // train case Instructions.TrainCars: if (Train != null) { Function.Stack[s] = (double)Train.Cars.Length; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainSpeed: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.CurrentSpeed; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainSpeedOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentSpeed; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainSpeedometer: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.CurrentPerceivedSpeed; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainSpeedometerOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentPerceivedSpeed; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainAcceleration: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.CurrentAcceleration; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainAccelerationOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentAcceleration; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainAccelerationMotor: if (Train != null) { Function.Stack[s] = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { if (Train.Cars[j].Specs.IsMotorCar) { // hack: CurrentAccelerationOutput does not distinguish between forward/backward if (Train.Cars[j].Specs.CurrentAccelerationOutput < 0.0) { Function.Stack[s] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Math.Sign(Train.Cars[j].Specs.CurrentSpeed); } else if (Train.Cars[j].Specs.CurrentAccelerationOutput > 0.0) { Function.Stack[s] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Train.Specs.CurrentReverser.Actual; } else { Function.Stack[s] = 0.0; } break; } } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainAccelerationMotorOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { // hack: CurrentAccelerationOutput does not distinguish between forward/backward if (Train.Cars[j].Specs.CurrentAccelerationOutput < 0.0) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Math.Sign(Train.Cars[j].Specs.CurrentSpeed); } else if (Train.Cars[j].Specs.CurrentAccelerationOutput > 0.0) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Train.Specs.CurrentReverser.Actual; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainDistance: if (Train != null) { double dist = double.MaxValue; for (int j = 0; j < Train.Cars.Length; j++) { double fx = Train.Cars[j].FrontAxle.Follower.WorldPosition.X - Position.X; double fy = Train.Cars[j].FrontAxle.Follower.WorldPosition.Y - Position.Y; double fz = Train.Cars[j].FrontAxle.Follower.WorldPosition.Z - Position.Z; double f = fx * fx + fy * fy + fz * fz; if (f < dist) dist = f; double rx = Train.Cars[j].RearAxle.Follower.WorldPosition.X - Position.X; double ry = Train.Cars[j].RearAxle.Follower.WorldPosition.Y - Position.Y; double rz = Train.Cars[j].RearAxle.Follower.WorldPosition.Z - Position.Z; double r = rx * rx + ry * ry + rz * rz; if (r < dist) dist = r; } Function.Stack[s] = Math.Sqrt(dist); } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainDistanceToCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { double x = 0.5 * (Train.Cars[j].FrontAxle.Follower.WorldPosition.X + Train.Cars[j].RearAxle.Follower.WorldPosition.X) - Position.X; double y = 0.5 * (Train.Cars[j].FrontAxle.Follower.WorldPosition.Y + Train.Cars[j].RearAxle.Follower.WorldPosition.Y) - Position.Y; double z = 0.5 * (Train.Cars[j].FrontAxle.Follower.WorldPosition.Z + Train.Cars[j].RearAxle.Follower.WorldPosition.Z) - Position.Z; Function.Stack[s - 1] = Math.Sqrt(x * x + y * y + z * z); } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainTrackDistance: if (Train != null) { int r = Train.Cars.Length - 1; double t0 = Train.Cars[0].FrontAxle.Follower.TrackPosition - Train.Cars[0].FrontAxlePosition + 0.5 * Train.Cars[0].Length; double t1 = Train.Cars[r].RearAxle.Follower.TrackPosition - Train.Cars[r].RearAxlePosition - 0.5 * Train.Cars[r].Length; Function.Stack[s] = TrackPosition > t0 ? TrackPosition - t0 : TrackPosition < t1 ? TrackPosition - t1 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainTrackDistanceToCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { double p = 0.5 * (Train.Cars[j].FrontAxle.Follower.TrackPosition + Train.Cars[j].RearAxle.Follower.TrackPosition); Function.Stack[s - 1] = TrackPosition - p; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; // door case Instructions.Doors: if (Train != null) { double a = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s] = a; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.DoorsIndex: if (Train != null) { double a = 0.0; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s - 1] = a; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.LeftDoors: if (Train != null) { double a = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == -1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s] = a; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.LeftDoorsIndex: if (Train != null) { double a = 0.0; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == -1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s - 1] = a; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.RightDoors: if (Train != null) { double a = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == 1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s] = a; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.RightDoorsIndex: if (Train != null) { double a = 0.0; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == 1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s - 1] = a; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.LeftDoorsTarget: if (Train != null) { bool q = false; for (int j = 0; j < Train.Cars.Length; j++) { if (Train.Cars[j].Specs.AnticipatedLeftDoorsOpened) { q = true; break; } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.LeftDoorsTargetIndex: if (Train != null) { bool q = false; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.AnticipatedLeftDoorsOpened) { q = true; break; } } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.RightDoorsTarget: if (Train != null) { bool q = false; for (int j = 0; j < Train.Cars.Length; j++) { if (Train.Cars[j].Specs.AnticipatedRightDoorsOpened) { q = true; break; } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.RightDoorsTargetIndex: if (Train != null) { bool q = false; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.AnticipatedRightDoorsOpened) { q = true; break; } } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s - 1] = 0.0; } break; // handles case Instructions.ReverserNotch: if (Train != null) { Function.Stack[s] = (double)Train.Specs.CurrentReverser.Driver; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.PowerNotch: if (Train != null) { Function.Stack[s] = (double)Train.Specs.CurrentPowerNotch.Driver; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.PowerNotches: if (Train != null) { Function.Stack[s] = (double)Train.Specs.MaximumPowerNotch; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotch: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { Function.Stack[s] = (double)Train.Specs.AirBrake.Handle.Driver; } else { Function.Stack[s] = (double)Train.Specs.CurrentBrakeNotch.Driver; } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotches: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { Function.Stack[s] = 2.0; } else { Function.Stack[s] = (double)Train.Specs.MaximumBrakeNotch; } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotchLinear: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { if (Train.Specs.CurrentEmergencyBrake.Driver) { Function.Stack[s] = 3.0; } else { Function.Stack[s] = (double)Train.Specs.AirBrake.Handle.Driver; } } else if (Train.Specs.HasHoldBrake) { if (Train.Specs.CurrentEmergencyBrake.Driver) { Function.Stack[s] = (double)Train.Specs.MaximumBrakeNotch + 2.0; } else if (Train.Specs.CurrentBrakeNotch.Driver > 0) { Function.Stack[s] = (double)Train.Specs.CurrentBrakeNotch.Driver + 1.0; } else { Function.Stack[s] = Train.Specs.CurrentHoldBrake.Driver ? 1.0 : 0.0; } } else { if (Train.Specs.CurrentEmergencyBrake.Driver) { Function.Stack[s] = (double)Train.Specs.MaximumBrakeNotch + 1.0; } else { Function.Stack[s] = (double)Train.Specs.CurrentBrakeNotch.Driver; } } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotchesLinear: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { Function.Stack[s] = 3.0; } else if (Train.Specs.HasHoldBrake) { Function.Stack[s] = Train.Specs.MaximumBrakeNotch + 2.0; } else { Function.Stack[s] = Train.Specs.MaximumBrakeNotch + 1.0; } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.EmergencyBrake: if (Train != null) { Function.Stack[s] = Train.Specs.CurrentEmergencyBrake.Driver ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HasAirBrake: if (Train != null) { Function.Stack[s] = Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HoldBrake: if (Train != null) { Function.Stack[s] = Train.Specs.CurrentHoldBrake.Driver ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HasHoldBrake: if (Train != null) { Function.Stack[s] = Train.Specs.HasHoldBrake ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.ConstSpeed: if (Train != null) { Function.Stack[s] = Train.Specs.CurrentConstSpeed ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HasConstSpeed: if (Train != null) { Function.Stack[s] = Train.Specs.HasConstSpeed ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; // brake case Instructions.BrakeMainReservoir: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.MainReservoirCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeMainReservoirOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.MainReservoirCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeEqualizingReservoir: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.EqualizingReservoirCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeEqualizingReservoirOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.EqualizingReservoirCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeBrakePipe: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.BrakePipeCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeBrakePipeOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.BrakePipeCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeBrakeCylinder: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeBrakeCylinderOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.BrakeCylinderCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeStraightAirPipe: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.StraightAirPipeCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeStraightAirPipeOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.StraightAirPipeCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; // safety case Instructions.SafetyPluginAvailable: if (Train == TrainManager.PlayerTrain) { Function.Stack[s] = TrainManager.PlayerTrain.Specs.Safety.Mode == TrainManager.SafetySystem.Plugin ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.SafetyPluginState: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int n = (int)Math.Round(Function.Stack[s - 1]); if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.Plugin) { if (n >= 0 & n < PluginManager.CurrentPlugin.Panel.Length) { Function.Stack[s - 1] = (double)PluginManager.CurrentPlugin.Panel[n]; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; switch(n) { case 256: // ATS if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsSn) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Normal | Train.Specs.Safety.State == TrainManager.SafetyState.Initialization) { Function.Stack[s - 1] = 1.0; } } break; case 257: // ATS RUN (separate flashing) if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsSn) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Ringing) { Function.Stack[s - 1] = 1.0; } else if (Train.Specs.Safety.State == TrainManager.SafetyState.Emergency | Train.Specs.Safety.State == TrainManager.SafetyState.Pattern | Train.Specs.Safety.State == TrainManager.SafetyState.Service) { Function.Stack[s - 1] = 2.0; } } break; case 258: // ATS RUN (integrated flashing) if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsSn) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Ringing) { Function.Stack[s - 1] = 1.0; } else if (Train.Specs.Safety.State == TrainManager.SafetyState.Emergency | Train.Specs.Safety.State == TrainManager.SafetyState.Pattern | Train.Specs.Safety.State == TrainManager.SafetyState.Service) { if (((int)Math.Floor(2.0 * Game.SecondsSinceMidnight) & 1) == 0) { Function.Stack[s - 1] = 1.0; } else { Function.Stack[s - 1] = 0.0; } } } break; case 259: // P POWER if ((Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsSn | Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsP) & Train.Specs.Safety.Ats.AtsPAvailable) { Function.Stack[s - 1] = 1.0; } break; case 260: // PATTERN APPROACH if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsP) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Pattern | Train.Specs.Safety.State == TrainManager.SafetyState.Service) { Function.Stack[s - 1] = 1.0; } } break; case 261: // BRAKE RELEASE if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsP) { if (Train.Specs.Safety.Ats.AtsPOverride) { Function.Stack[s - 1] = 1.0; } } break; case 262: // BRAKE OPERATION if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsP) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Service & !Train.Specs.Safety.Ats.AtsPOverride) { Function.Stack[s - 1] = 1.0; } } break; case 263: // ATS-P if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsP) { Function.Stack[s - 1] = 1.0; } break; case 264: // FAILURE if (Train.Specs.Safety.Mode != TrainManager.SafetySystem.None) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Initialization) { Function.Stack[s - 1] = 1.0; } else if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.AtsP) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Ringing | Train.Specs.Safety.State == TrainManager.SafetyState.Emergency) { Function.Stack[s - 1] = 1.0; } } } break; case 265: // ATC if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.Atc) { Function.Stack[s - 1] = 1.0; } break; case 266: // ATC POWER if ((Train.Specs.Safety.Mode == TrainManager.SafetySystem.Atc | Train.Specs.Safety.Mode != TrainManager.SafetySystem.None & Train.Specs.Safety.Atc.AutomaticSwitch)) { Function.Stack[s - 1] = 1.0; } break; case 267: // ATC SERVICE if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.Atc) { if (Train.Specs.Safety.State == TrainManager.SafetyState.Service) { Function.Stack[s - 1] = 1.0; } } break; case 268: // ATC EMERGENCY if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.Atc) { if (!Train.Specs.Safety.Atc.Transmitting) { Function.Stack[s - 1] = 1.0; } } break; case 269: // EB if (Train.Specs.Safety.Mode != TrainManager.SafetySystem.None) { if (Train.Specs.Safety.Eb.BellState == TrainManager.SafetyState.Ringing) { Function.Stack[s - 1] = 1.0; } } break; case 270: // CONST SPEED if (Train.Specs.HasConstSpeed) { if (Train.Specs.CurrentConstSpeed) { Function.Stack[s - 1] = 1.0; } } break; case 271: // atc speedometer state if (Train.Specs.Safety.Mode == TrainManager.SafetySystem.Atc) { if (!Train.Specs.Safety.Atc.Transmitting) { Function.Stack[s - 1] = 0.0; } else { if (Train.Specs.Safety.Atc.SpeedRestriction < 4.1666) { Function.Stack[s - 1] = 1.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 6.9443) { Function.Stack[s - 1] = 2.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 12.4999) { Function.Stack[s - 1] = 3.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 15.2777) { Function.Stack[s - 1] = 4.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 18.0555) { Function.Stack[s - 1] = 5.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 20.8333) { Function.Stack[s - 1] = 6.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 24.9999) { Function.Stack[s - 1] = 7.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 27.7777) { Function.Stack[s - 1] = 8.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 30.5555) { Function.Stack[s - 1] = 9.0; } else if (Train.Specs.Safety.Atc.SpeedRestriction < 33.3333) { Function.Stack[s - 1] = 10.0; } else { Function.Stack[s - 1] = 11.0; } } } else { Function.Stack[s - 1] = 12.0; } break; } } } break; // timetable case Instructions.TimetableVisible: Function.Stack[s] = Timetable.CurrentTimetable == Timetable.TimetableState.Custom & Timetable.CustomTimetableAvailable ? 0.0 : -1.0; s++; break; // sections case Instructions.SectionAspectNumber: if (IsPartOfTrain) { int nextSectionIndex = Train.CurrentSectionIndex + 1; if (nextSectionIndex >= 0 & nextSectionIndex < Game.Sections.Length) { int a = Game.Sections[nextSectionIndex].CurrentAspect; if (a >= 0 & a < Game.Sections[nextSectionIndex].Aspects.Length) { Function.Stack[s] = (double)Game.Sections[nextSectionIndex].Aspects[a].Number; } else { Function.Stack[s] = 0; } } } else if (SectionIndex >= 0 & SectionIndex < Game.Sections.Length) { int a = Game.Sections[SectionIndex].CurrentAspect; if (a >= 0 & a < Game.Sections[SectionIndex].Aspects.Length) { Function.Stack[s] = (double)Game.Sections[SectionIndex].Aspects[a].Number; } else { Function.Stack[s] = 0; } } else { Function.Stack[s] = 0; } s++; break; // default default: throw new System.InvalidOperationException("The unknown instruction " + Function.Instructions[i].ToString() + " was encountered in ExecuteFunctionScript."); } } Function.LastResult = Function.Stack[s - 1]; }
private static void SetRenderScript(object code) { if (code == null || (code is string && (string)code == "")) _renderscript = null; else _renderscript = new FunctionScript(code); }
private static void SetLayerRenderer(int layer, object code) { if (layer > 0 && layer < _renderers.Length) { if (code == null || (code is string && (string)code == "")) _renderers[layer] = null; else _renderers[layer] = new FunctionScript(code); } }
private static void SetUpdateScript(object code) { if (code == null || (code is string && (string)code == "")) _updatescript = null; else _updatescript = new FunctionScript(code); }
public Task <bool> UpdateAsync(FunctionScript Entity, bool SaveChanges = false) { throw new NotImplementedException(); }
public Bytecode(Reader reader) { int scriptCodePos = 0; int jumpTablePos = 0; // Bytecode for (int scriptCodeSize = reader.ReadInt32(); scriptCodeSize > 0;) { int buffer = reader.ReadByte(); int blockSize = buffer & 0x7F; if ((buffer & 0x80) == 0) { for (int i = 0; i < blockSize; i++) { scriptCode[scriptCodePos++] = reader.ReadByte(); } scriptCodeSize -= blockSize; } else { for (int i = 0; i < blockSize; i++) { scriptCode[scriptCodePos++] = reader.ReadInt32(); } scriptCodeSize -= blockSize; } } for (int jumpTableSize = reader.ReadInt32(); jumpTableSize > 0;) { int buffer = reader.ReadByte(); int blockSize = buffer & 0x7F; if ((buffer & 0x80) == 0) { for (int i = 0; i < blockSize; i++) { jumpTable[jumpTablePos++] = reader.ReadByte(); } jumpTableSize -= blockSize; } else { for (int i = 0; i < blockSize; i++) { jumpTable[jumpTablePos++] = reader.ReadInt32(); } jumpTableSize -= blockSize; } } // Scripts int scriptCount = reader.ReadInt16(); for (int i = 0; i < scriptCount; i++) { ScriptInfo info = new ScriptInfo(); info.scriptCodePos_main = reader.ReadInt32(); info.scriptCodePos_draw = reader.ReadInt32(); info.scriptCodePos_startup = reader.ReadInt32(); scripts.Add(info); } foreach (ScriptInfo info in scripts) { info.jumpTablePos_main = reader.ReadInt32(); info.jumpTablePos_draw = reader.ReadInt32(); info.jumpTablePos_startup = reader.ReadInt32(); } // Functions int functionCount = reader.ReadInt16(); for (int i = 0; i < functionCount; i++) { FunctionScript info = new FunctionScript(); info.scriptCodePos = reader.ReadInt32(); functionList.Add(info); } foreach (FunctionScript info in functionList) { info.jumpTablePos = reader.ReadInt32(); } scriptCodeLength = scriptCodePos; jumpTableLength = jumpTablePos; }
// execute function script private static void ExecuteFunctionScript(FunctionScript Function, TrainManager.Train Train, int CarIndex, Vector3 Position, double TrackPosition, int SectionIndex, bool IsPartOfTrain, double TimeElapsed, int CurrentState) { int s = 0, c = 0; for (int i = 0; i < Function.Instructions.Length; i++) { switch (Function.Instructions[i]) { // system case Instructions.SystemHalt: i = Function.Instructions.Length; break; case Instructions.SystemConstant: Function.Stack[s] = Function.Constants[c]; s++; c++; break; case Instructions.SystemConstantArray: { int n = (int)Function.Instructions[i + 1]; for (int j = 0; j < n; j++) { Function.Stack[s + j] = Function.Constants[c + j]; } s += n; c += n; i++; } break; case Instructions.SystemValue: Function.Stack[s] = Function.LastResult; s++; break; case Instructions.SystemDelta: Function.Stack[s] = TimeElapsed; s++; break; // stack case Instructions.StackCopy: Function.Stack[s] = Function.Stack[s - 1]; s++; break; case Instructions.StackSwap: { double a = Function.Stack[s - 1]; Function.Stack[s - 1] = Function.Stack[s - 2]; Function.Stack[s - 2] = a; } break; // math case Instructions.MathPlus: Function.Stack[s - 2] += Function.Stack[s - 1]; s--; break; case Instructions.MathSubtract: Function.Stack[s - 2] -= Function.Stack[s - 1]; s--; break; case Instructions.MathMinus: Function.Stack[s - 1] = -Function.Stack[s - 1]; break; case Instructions.MathTimes: Function.Stack[s - 2] *= Function.Stack[s - 1]; s--; break; case Instructions.MathDivide: Function.Stack[s - 2] = Function.Stack[s - 1] == 0.0 ? 0.0 : Function.Stack[s - 2] / Function.Stack[s - 1]; s--; break; case Instructions.MathReciprocal: Function.Stack[s - 1] = Function.Stack[s - 1] == 0.0 ? 0.0 : 1.0 / Function.Stack[s - 1]; break; case Instructions.MathPower: { double a = Function.Stack[s - 2]; double b = Function.Stack[s - 1]; if (b == 2.0) { Function.Stack[s - 2] = a * a; } else if (b == 3.0) { Function.Stack[s - 2] = a * a * a; } else if (b == 4.0) { double t = a * a; Function.Stack[s - 2] = t * t; } else if (b == 5.0) { double t = a * a; Function.Stack[s - 2] = t * t * a; } else if (b == 6.0) { double t = a * a * a; Function.Stack[s - 2] = t * t; } else if (b == 7.0) { double t = a * a * a; Function.Stack[s - 2] = t * t * a; } else if (b == 8.0) { double t = a * a; t *= t; Function.Stack[s - 2] = t * t; } else if (b == 0.0) { Function.Stack[s - 2] = 1.0; } else if (b < 0.0) { Function.Stack[s - 2] = 0.0; } else { Function.Stack[s - 2] = Math.Pow(a, b); } s--; break; } case Instructions.MathRandom: { //Generates a random number between two given doubles double min = Function.Stack[s - 2]; double max = Function.Stack[s - 1]; var randomGenerator = new Random(); Function.Stack[s - 2] = min + randomGenerator.NextDouble() * (max - min); s--; } break; case Instructions.MathRandomInt: { //Generates a random number between two given doubles int min = (int)Function.Stack[s - 2]; int max = (int)Function.Stack[s - 1]; var randomGenerator = new Random(); Function.Stack[s - 2] = randomGenerator.Next(min,max); s--; } break; case Instructions.MathIncrement: Function.Stack[s - 1] += 1.0; break; case Instructions.MathDecrement: Function.Stack[s - 1] -= 1.0; break; case Instructions.MathFusedMultiplyAdd: Function.Stack[s - 3] = Function.Stack[s - 3] * Function.Stack[s - 2] + Function.Stack[s - 1]; s -= 2; break; case Instructions.MathQuotient: Function.Stack[s - 2] = Function.Stack[s - 1] == 0.0 ? 0.0 : Math.Floor(Function.Stack[s - 2] / Function.Stack[s - 1]); s--; break; case Instructions.MathMod: Function.Stack[s - 2] = Function.Stack[s - 1] == 0.0 ? 0.0 : Function.Stack[s - 2] - Function.Stack[s - 1] * Math.Floor(Function.Stack[s - 2] / Function.Stack[s - 1]); s--; break; case Instructions.MathFloor: Function.Stack[s - 1] = Math.Floor(Function.Stack[s - 1]); break; case Instructions.MathCeiling: Function.Stack[s - 1] = Math.Ceiling(Function.Stack[s - 1]); break; case Instructions.MathRound: Function.Stack[s - 1] = Math.Round(Function.Stack[s - 1]); break; case Instructions.MathMin: Function.Stack[s - 2] = Function.Stack[s - 2] < Function.Stack[s - 1] ? Function.Stack[s - 2] : Function.Stack[s - 1]; s--; break; case Instructions.MathMax: Function.Stack[s - 2] = Function.Stack[s - 2] > Function.Stack[s - 1] ? Function.Stack[s - 2] : Function.Stack[s - 1]; s--; break; case Instructions.MathAbs: Function.Stack[s - 1] = Math.Abs(Function.Stack[s - 1]); break; case Instructions.MathSign: Function.Stack[s - 1] = Math.Sign(Function.Stack[s - 1]); break; case Instructions.MathExp: Function.Stack[s - 1] = Math.Exp(Function.Stack[s - 1]); break; case Instructions.MathLog: Function.Stack[s - 1] = Log(Function.Stack[s - 1]); break; case Instructions.MathSqrt: Function.Stack[s - 1] = Sqrt(Function.Stack[s - 1]); break; case Instructions.MathSin: Function.Stack[s - 1] = Math.Sin(Function.Stack[s - 1]); break; case Instructions.MathCos: Function.Stack[s - 1] = Math.Cos(Function.Stack[s - 1]); break; case Instructions.MathTan: Function.Stack[s - 1] = Tan(Function.Stack[s - 1]); break; case Instructions.MathArcTan: Function.Stack[s - 1] = Math.Atan(Function.Stack[s - 1]); break; // comparisons case Instructions.CompareEqual: Function.Stack[s - 2] = Function.Stack[s - 2] == Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareUnequal: Function.Stack[s - 2] = Function.Stack[s - 2] != Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareLess: Function.Stack[s - 2] = Function.Stack[s - 2] < Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareGreater: Function.Stack[s - 2] = Function.Stack[s - 2] > Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareLessEqual: Function.Stack[s - 2] = Function.Stack[s - 2] <= Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareGreaterEqual: Function.Stack[s - 2] = Function.Stack[s - 2] >= Function.Stack[s - 1] ? 1.0 : 0.0; s--; break; case Instructions.CompareConditional: Function.Stack[s - 3] = Function.Stack[s - 3] != 0.0 ? Function.Stack[s - 2] : Function.Stack[s - 1]; s -= 2; break; // logical case Instructions.LogicalNot: Function.Stack[s - 1] = Function.Stack[s - 1] != 0.0 ? 0.0 : 1.0; break; case Instructions.LogicalAnd: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 & Function.Stack[s - 1] != 0.0 ? 1.0 : 0.0; s--; break; case Instructions.LogicalOr: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 | Function.Stack[s - 1] != 0.0 ? 1.0 : 0.0; s--; break; case Instructions.LogicalNand: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 & Function.Stack[s - 1] != 0.0 ? 0.0 : 1.0; s--; break; case Instructions.LogicalNor: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 | Function.Stack[s - 1] != 0.0 ? 0.0 : 1.0; s--; break; case Instructions.LogicalXor: Function.Stack[s - 2] = Function.Stack[s - 2] != 0.0 ^ Function.Stack[s - 1] != 0.0 ? 1.0 : 0.0; s--; break; case Instructions.CurrentObjectState: Function.Stack[s] = CurrentState; break; // time/camera case Instructions.TimeSecondsSinceMidnight: Function.Stack[s] = Game.SecondsSinceMidnight; s++; break; case Instructions.CameraDistance: { double dx = World.AbsoluteCameraPosition.X - Position.X; double dy = World.AbsoluteCameraPosition.Y - Position.Y; double dz = World.AbsoluteCameraPosition.Z - Position.Z; Function.Stack[s] = Math.Sqrt(dx * dx + dy * dy + dz * dz); s++; } break; case Instructions.CameraView: //Returns whether the camera is in interior or exterior mode if (World.CameraMode == World.CameraViewMode.Interior || World.CameraMode == World.CameraViewMode.InteriorLookAhead) { Function.Stack[s] = 0; } else { Function.Stack[s] = 1; } s++; break; // train case Instructions.TrainCars: if (Train != null) { Function.Stack[s] = (double)Train.Cars.Length; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainSpeed: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.CurrentSpeed; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainSpeedOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentSpeed; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainSpeedometer: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.CurrentPerceivedSpeed; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainSpeedometerOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentPerceivedSpeed; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainAcceleration: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.CurrentAcceleration; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainAccelerationOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentAcceleration; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainAccelerationMotor: if (Train != null) { Function.Stack[s] = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { if (Train.Cars[j].Specs.IsMotorCar) { // hack: CurrentAccelerationOutput does not distinguish between forward/backward if (Train.Cars[j].Specs.CurrentAccelerationOutput < 0.0) { Function.Stack[s] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Math.Sign(Train.Cars[j].Specs.CurrentSpeed); } else if (Train.Cars[j].Specs.CurrentAccelerationOutput > 0.0) { Function.Stack[s] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Train.Specs.CurrentReverser.Actual; } else { Function.Stack[s] = 0.0; } break; } } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainAccelerationMotorOfCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { // hack: CurrentAccelerationOutput does not distinguish between forward/backward if (Train.Cars[j].Specs.CurrentAccelerationOutput < 0.0) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Math.Sign(Train.Cars[j].Specs.CurrentSpeed); } else if (Train.Cars[j].Specs.CurrentAccelerationOutput > 0.0) { Function.Stack[s - 1] = Train.Cars[j].Specs.CurrentAccelerationOutput * (double)Train.Specs.CurrentReverser.Actual; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainDistance: if (Train != null) { double dist = double.MaxValue; for (int j = 0; j < Train.Cars.Length; j++) { double fx = Train.Cars[j].FrontAxle.Follower.WorldPosition.X - Position.X; double fy = Train.Cars[j].FrontAxle.Follower.WorldPosition.Y - Position.Y; double fz = Train.Cars[j].FrontAxle.Follower.WorldPosition.Z - Position.Z; double f = fx * fx + fy * fy + fz * fz; if (f < dist) dist = f; double rx = Train.Cars[j].RearAxle.Follower.WorldPosition.X - Position.X; double ry = Train.Cars[j].RearAxle.Follower.WorldPosition.Y - Position.Y; double rz = Train.Cars[j].RearAxle.Follower.WorldPosition.Z - Position.Z; double r = rx * rx + ry * ry + rz * rz; if (r < dist) dist = r; } Function.Stack[s] = Math.Sqrt(dist); } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.TrainDistanceToCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { double x = 0.5 * (Train.Cars[j].FrontAxle.Follower.WorldPosition.X + Train.Cars[j].RearAxle.Follower.WorldPosition.X) - Position.X; double y = 0.5 * (Train.Cars[j].FrontAxle.Follower.WorldPosition.Y + Train.Cars[j].RearAxle.Follower.WorldPosition.Y) - Position.Y; double z = 0.5 * (Train.Cars[j].FrontAxle.Follower.WorldPosition.Z + Train.Cars[j].RearAxle.Follower.WorldPosition.Z) - Position.Z; Function.Stack[s - 1] = Math.Sqrt(x * x + y * y + z * z); } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.TrainTrackDistance: if (Train != null) { int r = Train.Cars.Length - 1; double t0 = Train.Cars[0].FrontAxle.Follower.TrackPosition - Train.Cars[0].FrontAxlePosition + 0.5 * Train.Cars[0].Length; double t1 = Train.Cars[r].RearAxle.Follower.TrackPosition - Train.Cars[r].RearAxlePosition - 0.5 * Train.Cars[r].Length; Function.Stack[s] = TrackPosition > t0 ? TrackPosition - t0 : TrackPosition < t1 ? TrackPosition - t1 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.CurveRadius: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = (Train.Cars[j].FrontAxle.Follower.CurveRadius + Train.Cars[j].RearAxle.Follower.CurveRadius) / 2; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.FrontAxleCurveRadius: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].FrontAxle.Follower.CurveRadius; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.RearAxleCurveRadius: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].RearAxle.Follower.CurveRadius; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.CurveCant: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].FrontAxle.Follower.CurveCant; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.Odometer: if (Train == null) { Function.Stack[s] = 0.0; } else { Function.Stack[s] = Train.Cars[CarIndex].FrontAxle.Follower.Odometer; } s++; break; case Instructions.OdometerOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].FrontAxle.Follower.Odometer; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.TrainTrackDistanceToCar: if (Train != null) { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { double p = 0.5 * (Train.Cars[j].FrontAxle.Follower.TrackPosition + Train.Cars[j].RearAxle.Follower.TrackPosition); Function.Stack[s - 1] = TrackPosition - p; } else { Function.Stack[s - 1] = 0.0; } } else { Function.Stack[s - 1] = 0.0; } break; // door case Instructions.Doors: if (Train != null) { double a = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s] = a; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.DoorsIndex: if (Train != null) { double a = 0.0; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s - 1] = a; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.LeftDoors: if (Train != null) { double a = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == -1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s] = a; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.LeftDoorsIndex: if (Train != null) { double a = 0.0; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == -1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s - 1] = a; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.RightDoors: if (Train != null) { double a = 0.0; for (int j = 0; j < Train.Cars.Length; j++) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == 1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s] = a; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.RightDoorsIndex: if (Train != null) { double a = 0.0; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.Doors[k].Direction == 1 & Train.Cars[j].Specs.Doors[k].State > a) { a = Train.Cars[j].Specs.Doors[k].State; } } } Function.Stack[s - 1] = a; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.LeftDoorsTarget: if (Train != null) { bool q = false; for (int j = 0; j < Train.Cars.Length; j++) { if (Train.Cars[j].Specs.AnticipatedLeftDoorsOpened) { q = true; break; } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.LeftDoorsTargetIndex: if (Train != null) { bool q = false; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.AnticipatedLeftDoorsOpened) { q = true; break; } } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s - 1] = 0.0; } break; case Instructions.RightDoorsTarget: if (Train != null) { bool q = false; for (int j = 0; j < Train.Cars.Length; j++) { if (Train.Cars[j].Specs.AnticipatedRightDoorsOpened) { q = true; break; } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.RightDoorsTargetIndex: if (Train != null) { bool q = false; int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++) { if (Train.Cars[j].Specs.AnticipatedRightDoorsOpened) { q = true; break; } } } Function.Stack[s] = q ? 1.0 : 0.0; } else { Function.Stack[s - 1] = 0.0; } break; // handles case Instructions.ReverserNotch: if (Train != null) { Function.Stack[s] = (double)Train.Specs.CurrentReverser.Driver; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.PowerNotch: if (Train != null) { Function.Stack[s] = (double)Train.Specs.CurrentPowerNotch.Driver; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.PowerNotches: if (Train != null) { Function.Stack[s] = (double)Train.Specs.MaximumPowerNotch; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotch: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { Function.Stack[s] = (double)Train.Specs.AirBrake.Handle.Driver; } else { Function.Stack[s] = (double)Train.Specs.CurrentBrakeNotch.Driver; } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotches: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { Function.Stack[s] = 2.0; } else { Function.Stack[s] = (double)Train.Specs.MaximumBrakeNotch; } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotchLinear: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { if (Train.Specs.CurrentEmergencyBrake.Driver) { Function.Stack[s] = 3.0; } else { Function.Stack[s] = (double)Train.Specs.AirBrake.Handle.Driver; } } else if (Train.Specs.HasHoldBrake) { if (Train.Specs.CurrentEmergencyBrake.Driver) { Function.Stack[s] = (double)Train.Specs.MaximumBrakeNotch + 2.0; } else if (Train.Specs.CurrentBrakeNotch.Driver > 0) { Function.Stack[s] = (double)Train.Specs.CurrentBrakeNotch.Driver + 1.0; } else { Function.Stack[s] = Train.Specs.CurrentHoldBrake.Driver ? 1.0 : 0.0; } } else { if (Train.Specs.CurrentEmergencyBrake.Driver) { Function.Stack[s] = (double)Train.Specs.MaximumBrakeNotch + 1.0; } else { Function.Stack[s] = (double)Train.Specs.CurrentBrakeNotch.Driver; } } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeNotchesLinear: if (Train != null) { if (Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake) { Function.Stack[s] = 3.0; } else if (Train.Specs.HasHoldBrake) { Function.Stack[s] = Train.Specs.MaximumBrakeNotch + 2.0; } else { Function.Stack[s] = Train.Specs.MaximumBrakeNotch + 1.0; } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.EmergencyBrake: if (Train != null) { Function.Stack[s] = Train.Specs.CurrentEmergencyBrake.Driver ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.Klaxon: if (Train != null) { for (int j = 0; j < TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Sounds.Horns.Length; j++) { /* Return the index of the currently playing horn sound * * 1 ==> Primary horn * 2 ==> Secondary horn * 3 ==> Music horn */ if (Sounds.IsPlaying(TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Sounds.Horns[j].Sound.Source)) { Function.Stack[s] = j + 1; break; } if (j == TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Sounds.Horns.Length -1) { Function.Stack[s] = 0.0; } } } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HasAirBrake: if (Train != null) { Function.Stack[s] = Train.Cars[Train.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HoldBrake: if (Train != null) { Function.Stack[s] = Train.Specs.CurrentHoldBrake.Driver ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HasHoldBrake: if (Train != null) { Function.Stack[s] = Train.Specs.HasHoldBrake ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.ConstSpeed: if (Train != null) { Function.Stack[s] = Train.Specs.CurrentConstSpeed ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.HasConstSpeed: if (Train != null) { Function.Stack[s] = Train.Specs.HasConstSpeed ? 1.0 : 0.0; } else { Function.Stack[s] = 0.0; } s++; break; // brake case Instructions.BrakeMainReservoir: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.MainReservoirCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeMainReservoirOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.MainReservoirCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeEqualizingReservoir: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.EqualizingReservoirCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeEqualizingReservoirOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.EqualizingReservoirCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeBrakePipe: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.BrakePipeCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeBrakePipeOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.BrakePipeCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeBrakeCylinder: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeBrakeCylinderOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.BrakeCylinderCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; case Instructions.BrakeStraightAirPipe: if (Train != null) { Function.Stack[s] = Train.Cars[CarIndex].Specs.AirBrake.StraightAirPipeCurrentPressure; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.BrakeStraightAirPipeOfCar: if (Train == null) { Function.Stack[s - 1] = 0.0; } else { int j = (int)Math.Round(Function.Stack[s - 1]); if (j < 0) j += Train.Cars.Length; if (j >= 0 & j < Train.Cars.Length) { Function.Stack[s - 1] = Train.Cars[j].Specs.AirBrake.StraightAirPipeCurrentPressure; } else { Function.Stack[s - 1] = 0.0; } } break; // safety case Instructions.SafetyPluginAvailable: if (Train == TrainManager.PlayerTrain && Train.Plugin != null) { Function.Stack[s] = TrainManager.PlayerTrain.Plugin.IsDefault ? 0.0 : 1.0; } else { Function.Stack[s] = 0.0; } s++; break; case Instructions.SafetyPluginState: if (Train == null || Train.Plugin == null) { Function.Stack[s - 1] = 0.0; } else { int n = (int)Math.Round(Function.Stack[s - 1]); if (n >= 0 & n < Train.Plugin.Panel.Length) { Function.Stack[s - 1] = (double)Train.Plugin.Panel[n]; } else { Function.Stack[s - 1] = 0.0; } } break; // timetable case Instructions.TimetableVisible: Function.Stack[s] = Timetable.CurrentTimetable == Timetable.TimetableState.Custom & Timetable.CustomTimetableAvailable ? 0.0 : -1.0; s++; break; // sections case Instructions.SectionAspectNumber: if (IsPartOfTrain) { int nextSectionIndex = Train.CurrentSectionIndex + 1; if (nextSectionIndex >= 0 & nextSectionIndex < Game.Sections.Length) { int a = Game.Sections[nextSectionIndex].CurrentAspect; if (a >= 0 & a < Game.Sections[nextSectionIndex].Aspects.Length) { Function.Stack[s] = (double)Game.Sections[nextSectionIndex].Aspects[a].Number; } else { Function.Stack[s] = 0; } } } else if (SectionIndex >= 0 & SectionIndex < Game.Sections.Length) { int a = Game.Sections[SectionIndex].CurrentAspect; if (a >= 0 & a < Game.Sections[SectionIndex].Aspects.Length) { Function.Stack[s] = (double)Game.Sections[SectionIndex].Aspects[a].Number; } else { Function.Stack[s] = 0; } } else { Function.Stack[s] = 0; } s++; break; // default default: throw new System.InvalidOperationException("The unknown instruction " + Function.Instructions[i].ToString() + " was encountered in ExecuteFunctionScript."); } } Function.LastResult = Function.Stack[s - 1]; }
private void Start() { fs = GameObject.FindGameObjectWithTag("Console").GetComponent <FunctionScript>(); }