########################################## # Autostart ########################################## var autostart = func (msg=1) { if (getprop("/engines/active-engine/running")) { if (msg) gui.popupTip("Engine already running", 5); return; } # Reset battery charge and circuit breakers electrical.reset_battery_and_circuit_breakers(); # Setting levers and switches for startup setprop("/controls/switches/magnetos", 3); setprop("/controls/engines/current-engine/throttle", 0.2); var auto_mixture = getprop("/fdm/jsbsim/engine/auto-mixture"); setprop("/controls/engines/current-engine/mixture", auto_mixture); setprop("/controls/flight/elevator-trim", 0.0); setprop("/controls/switches/master-bat", 1); setprop("/controls/switches/master-alt", 1); setprop("/controls/switches/master-avionics", 1); if (getprop("controls/panel/glass")) { setprop("/controls/switches/master-avionics2", 1); } # Setting lights setprop("/controls/lighting/nav-lights", 1); setprop("/controls/lighting/strobe", 1); setprop("/controls/lighting/beacon", 1); # Setting instrument lights if needed var light_level = 1-getprop("/rendering/scene/diffuse/red"); if (light_level > .6) { if (!getprop("/controls/panel/glass")){ if (getprop("/controls/lighting/instruments-norm") == 0) { if (light_level > .8) light_level = .8; setprop("/controls/lighting/instruments-norm", light_level); } setprop("/controls/switches/dome-red", 1); } if (getprop("/controls/panel/glass")) { if (getprop("/controls/lighting/swcb-norm") == 0) { setprop("/controls/lighting/swcb-norm", .55); } if (getprop("/controls/lighting/avionics-norm") == 0) { setprop("/controls/lighting/avionics-norm", .6); } if (getprop("/controls/lighting/stby-norm") == 0) { setprop("/controls/lighting/stby-norm", .8); } } } else { if (getprop("/controls/panel/glass")) { if (getprop("/controls/lighting/swcb-norm") == 0) { setprop("/controls/lighting/swcb-norm", .35); } if (getprop("/controls/lighting/avionics-norm") == 0) { setprop("/controls/lighting/avionics-norm", .35); } if (getprop("/controls/lighting/stby-norm") == 0) { setprop("/controls/lighting/stby-norm", .75); } } } if (getprop("/controls/panel/glass")) { setprop("/controls/switches/stby-batt", 2); } # Setting amphibious landing gear if needed if (getprop("/fdm/jsbsim/bushkit")==4){ if (getprop("/fdm/jsbsim/hydro/active-norm")) { setprop("controls/gear/gear-down-command", 0); setprop("/fdm/jsbsim/gear/gear-pos-norm", 0); } else { setprop("controls/gear/gear-down-command", 1); setprop("/fdm/jsbsim/gear/gear-pos-norm", 1); } } # Setting flaps to 0 setprop("/controls/flight/flaps", 0.0); # Set the altimeter var pressure_sea_level = getprop("/environment/pressure-sea-level-inhg"); setprop("/instrumentation/altimeter/setting-inhg", pressure_sea_level); # Set heading offset var magnetic_variation = getprop("/environment/magnetic-variation-deg"); setprop("/instrumentation/heading-indicator/offset-deg", -magnetic_variation); # Pre-flight inspection setprop("/sim/model/c172p/cockpit/control-lock-placed", 0); setprop("/controls/gear/brake-parking", 0); setprop("/sim/model/c172p/securing/chock", 0); setprop("/sim/model/c172p/securing/cowl-plugs-visible", 0); setprop("/sim/model/c172p/securing/pitot-cover-visible", 0); setprop("/sim/model/c172p/securing/tiedownL-visible", 0); setprop("/sim/model/c172p/securing/tiedownR-visible", 0); setprop("/sim/model/c172p/securing/tiedownT-visible", 0); # Setting max oil level var oil_enabled = getprop("/engines/active-engine/oil_consumption_allowed"); var oil_level = getprop("/engines/active-engine/oil-level"); if (oil_enabled and oil_level < 5.0) { if (getprop("/controls/engines/active-engine") == 0) { setprop("/engines/active-engine/oil-level", 7.0); } else { setprop("/engines/active-engine/oil-level", 8.0); }; }; # removing any ice from the carburetor setprop("/engines/active-engine/carb_ice", 0.0); setprop("/engines/active-engine/carb_icing_rate", 0.0); setprop("/engines/active-engine/volumetric-efficiency-factor", 0.85); # Removing any contamination from water setprop("/consumables/fuel/tank[0]/water-contamination", 0.0); setprop("/consumables/fuel/tank[1]/water-contamination", 0.0); setprop("/consumables/fuel/tank[0]/sample-water-contamination", 0.0); setprop("/consumables/fuel/tank[1]/sample-water-contamination", 0.0); # set fuel configuration set_fuel(); setprop("/controls/engines/engine[0]/primer-lever", 0); setprop("/controls/engines/engine/primer", 3); # All set, starting engine setprop("/controls/switches/starter", 1); setprop("/engines/active-engine/auto-start", 1); var engine_running_check_delay = 5.0; settimer(func { if (!getprop("/engines/active-engine/running")) { gui.popupTip("The autostart failed to start the engine. You must lean the mixture and start the engine manually.", 5); } setprop("/controls/switches/starter", 0); setprop("/engines/active-engine/auto-start", 0); }, engine_running_check_delay); }; ########################################## # Brakes ########################################## controls.applyBrakes = func (v, which = 0) { if (which <= 0 and !getprop("/fdm/jsbsim/gear/unit[1]/broken")) { interpolate("/controls/gear/brake-left", v, controls.fullBrakeTime); } if (which >= 0 and !getprop("/fdm/jsbsim/gear/unit[2]/broken")) { interpolate("/controls/gear/brake-right", v, controls.fullBrakeTime); } }; ########################################## # Set Fuel Configuration ########################################## var set_fuel = func { # Checking for minimal fuel level var fuel_level_left_default = getprop("/consumables/fuel/tank[0]/level-norm"); var fuel_level_right_default = getprop("/consumables/fuel/tank[1]/level-norm"); var fuel_level_left_integral = getprop("/consumables/fuel/tank[2]/level-norm"); var fuel_level_right_integral = getprop("/consumables/fuel/tank[3]/level-norm"); # Check which tanks are being used var integral_tanks = getprop("/fdm/jsbsim/fuel/tank"); if (integral_tanks) { if (fuel_level_left_integral < 0.25) setprop("/consumables/fuel/tank[2]/level-norm", 0.25); if (fuel_level_right_integral < 0.25) setprop("/consumables/fuel/tank[3]/level-norm", 0.25); setprop("/consumables/fuel/tank[2]/selected", 1); setprop("/consumables/fuel/tank[3]/selected", 1); setprop("/consumables/fuel/tank[0]/selected", 0); setprop("/consumables/fuel/tank[1]/selected", 0); } else { if (fuel_level_left_default < 0.25) setprop("/consumables/fuel/tank[0]/level-norm", 0.25); if (fuel_level_right_default < 0.25) setprop("/consumables/fuel/tank[1]/level-norm", 0.25); setprop("/consumables/fuel/tank[0]/selected", 1); setprop("/consumables/fuel/tank[1]/selected", 1); setprop("/consumables/fuel/tank[2]/selected", 0); setprop("/consumables/fuel/tank[3]/selected", 0); } setprop("sim/model/open-pfuel-cap", 0); setprop("sim/model/open-sfuel-cap", 0); setprop("sim/model/open-pfuel-sump", 0); setprop("sim/model/open-sfuel-sump", 0); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-left-fuel-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-right-fuel-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-fuel-both-tanks-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-left-fuel-sample-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-right-fuel-sample-dialog"})); }; ########################################## # Fuel Contamination ########################################## var fuel_contamination = func { var chance = rand(); # Chance of contamination is 1 % if (getprop("/consumables/fuel/contamination_allowed") and chance < 0.01) { # Quantity of water is much more likely to be small than large, since # it's given by x^6 (76 % of the time it will be lower than 0.2) var water = math.pow(rand(), 6); setprop("/consumables/fuel/tank[0]/water-contamination", water); # level of water in the right tank will be the same as in the left tank +- 0.1 water = water + 0.2 * (rand() - 0.5); water = std.max(0.0, std.min(water, 1.0)); setprop("/consumables/fuel/tank[1]/water-contamination", water); } else { setprop("/consumables/fuel/tank[0]/water-contamination", 0.0); setprop("/consumables/fuel/tank[1]/water-contamination", 0.0); }; }; ########################################## # Take Fuel Sample ########################################## var take_fuel_sample = func(index) { var fuel = getprop("/consumables/fuel/tank", index, "level-gal_us"); var water = getprop("/consumables/fuel/tank", index, "water-contamination"); # Remove 50 ml of fuel setprop("/consumables/fuel/tank", index, "level-gal_us", fuel - 0.0132086); # Remove a bit of water if contaminated if (water > 0.0) { var sample_water = std.min(0.2, water); water = water - sample_water; setprop("/consumables/fuel/tank", index, "water-contamination", water); setprop("/consumables/fuel/tank", index, "sample-water-contamination", sample_water); }; }; ########################################## # Return Fuel Sample ########################################## var return_fuel_sample = func(index) { var fuel = getprop("/consumables/fuel/tank", index, "level-gal_us"); var water = getprop("/consumables/fuel/tank", index, "water-contamination"); var sample_water = getprop("/consumables/fuel/tank", index, "sample-water-contamination"); # Add back the 50 ml of fuel setprop("/consumables/fuel/tank", index, "level-gal_us", fuel + 0.0132086); # Add back the (contaminated) water if (sample_water > 0.0) { water = water + sample_water; setprop("/consumables/fuel/tank", index, "water-contamination", water); setprop("/consumables/fuel/tank", index, "sample-water-contamination", 0.0); }; }; ########################################## # Preflight control surface check: left aileron ########################################## var control_surface_check_left_aileron = func { var auto_coordination = getprop("/controls/flight/auto-coordination"); setprop("/controls/flight/auto-coordination", 0); interpolate("/controls/flight/aileron", 1.0, 0.5, -1.0, 1.0, 0.0, 0.5); settimer(func(){ setprop("/controls/flight/auto-coordination", auto_coordination); }, 2.0); }; ########################################## # Preflight control surface check: right aileron ########################################## var control_surface_check_right_aileron = func { var auto_coordination = getprop("/controls/flight/auto-coordination"); setprop("/controls/flight/auto-coordination", 0); interpolate("/controls/flight/aileron", -1.0, 0.5, 1.0, 1.0, 0.0, 0.5); settimer(func(){ setprop("/controls/flight/auto-coordination", auto_coordination); }, 2.0); }; ########################################## # Preflight control surface check: elevator ########################################## var control_surface_check_elevator = func { interpolate("/controls/flight/elevator", 1.0, 0.8, -1.0, 1.6, 0.0, 0.8); }; ########################################## # Preflight control surface check: rudder ########################################## var control_surface_check_rudder = func { interpolate("/controls/flight/rudder", -1.0, 0.8, 1.0, 1.6, 0.0, 0.8); }; ########################################## # Switches Save State ########################################## var switches_save_state = func { if (!getprop("/instrumentation/save-switches-state")) { setprop("/controls/engines/engine[0]/primer", 0); setprop("/controls/engines/engine[0]/primer-lever", 0); setprop("/controls/engines/engine[0]/use-primer", 0); setprop("/controls/engines/current-engine/throttle", 0.0); setprop("/controls/engines/current-engine/mixture", 0.0); #setprop("/controls/circuit-breakers/aircond", 1); setprop("/controls/circuit-breakers/autopilot", 1); setprop("/controls/circuit-breakers/bcnlt", 1); setprop("/controls/circuit-breakers/flaps", 1); setprop("/controls/circuit-breakers/instr", 1); setprop("/controls/circuit-breakers/intlt", 1); setprop("/controls/circuit-breakers/landing", 1); setprop("/controls/circuit-breakers/master", 1); setprop("/controls/circuit-breakers/navlt", 1); setprop("/controls/circuit-breakers/pitot-heat", 1); setprop("/controls/circuit-breakers/radio1", 1); setprop("/controls/circuit-breakers/radio2", 1); setprop("/controls/circuit-breakers/radio3", 1); setprop("/controls/circuit-breakers/radio4", 1); setprop("/controls/circuit-breakers/radio5", 1); setprop("/controls/circuit-breakers/strobe", 1); setprop("/controls/circuit-breakers/turn-coordinator", 1); setprop("/controls/switches/master-avionics", 0); setprop("/controls/switches/starter", 0); setprop("/controls/switches/master-alt", 0); setprop("/controls/switches/master-bat", 0); setprop("/controls/switches/magnetos", 0); setprop("/controls/switches/dome-white", 0); setprop("/controls/switches/dome-red", 0); setprop("/controls/lighting/nav-lights", 0); setprop("/controls/lighting/beacon", 0); setprop("/controls/lighting/strobe", 0); setprop("/controls/lighting/taxi-light", 0); setprop("/controls/lighting/landing-lights", 0); setprop("/controls/lighting/instruments-norm", 0.0); setprop("/controls/lighting/radio-norm", 0.0); setprop("/controls/lighting/dome-white-norm", 1.0); setprop("/controls/lighting/gps-norm", 0.0); setprop("/controls/lighting/gearled", 0); setprop("/controls/gear/water-rudder", 0); setprop("/controls/gear/water-rudder-down", 0); setprop("/controls/gear/brake-parking", 1); setprop("/controls/flight/flaps", 0.0); setprop("/surface-positions/flap-pos-norm", 0.0); setprop("/controls/flight/elevator-trim", 0.0); setprop("/controls/anti-ice/engine[0]/carb-heat", 0); setprop("/controls/anti-ice/engine[1]/carb-heat", 0); setprop("/controls/anti-ice/pitot-heat", 0); setprop("/environment/aircraft-effects/cabin-heat-set", 0.0); setprop("/environment/aircraft-effects/cabin-air-set", 0.0); setprop("/consumables/fuel/tank[0]/level-norm", 0.0); setprop("/consumables/fuel/tank[1]/level-norm", 0.0); setprop("/consumables/fuel/tank[2]/level-norm", 0.0); setprop("/consumables/fuel/tank[3]/level-norm", 0.0); if (getprop("/sim/model/c172p/ruddertrim-visible")) setprop("/controls/flight/rudder-trim", 0); if (getprop("controls/panel/glass")) { electrical.reset_battery_and_circuit_breakers(); setprop("/controls/switches/master-avionics", 0); setprop("/controls/switches/master-avionics2", 0); } }; }; ########################################## # Click Sounds ########################################## var click = func (name, timeout=0.1, delay=0) { var sound_prop = "/sim/model/c172p/sound/click-" ~ name; settimer(func { # Play the sound setprop(sound_prop, 1); # Reset the property after 0.2 seconds so that the sound can be # played again. settimer(func { setprop(sound_prop, 0); }, timeout); }, delay); }; ########################################## # Thunder Sound ########################################## var speed_of_sound = func (t, re) { # Compute speed of sound in m/s # # t = temperature in Celsius # re = amount of water vapor in the air # Compute virtual temperature using mixing ratio (amount of water vapor) # Ratio of gas constants of dry air and water vapor: 287.058 / 461.5 = 0.622 var T = 273.15 + t; var v_T = T * (1 + re/0.622)/(1 + re); # Compute speed of sound using adiabatic index, gas constant of air, # and virtual temperature in Kelvin. return math.sqrt(1.4 * 287.058 * v_T); }; var thunder = func (name) { var thunderCalls = 0; var lightning_pos_x = getprop("/environment/lightning/lightning-pos-x"); var lightning_pos_y = getprop("/environment/lightning/lightning-pos-y"); var lightning_distance = math.sqrt(math.pow(lightning_pos_x, 2) + math.pow(lightning_pos_y, 2)); # On the ground, thunder can be heard up to 16 km. Increase this value # a bit because the aircraft is usually in the air. if (lightning_distance > 20000) return; var t = getprop("/environment/temperature-degc"); var re = getprop("/environment/relative-humidity") / 100; var delay_seconds = lightning_distance / speed_of_sound(t, re); # Maximum volume at 5000 meter var lightning_distance_norm = std.min(1.0, 1 / math.pow(lightning_distance / 5000.0, 2)); settimer(func { var thunder1 = getprop("/sim/model/c172p/sound/click-thunder1"); var thunder2 = getprop("/sim/model/c172p/sound/click-thunder2"); var thunder3 = getprop("/sim/model/c172p/sound/click-thunder3"); if (!thunder1) { thunderCalls = 1; setprop("/sim/model/c172p/sound/lightning/dist1", lightning_distance_norm); } else if (!thunder2) { thunderCalls = 2; setprop("/sim/model/c172p/sound/lightning/dist2", lightning_distance_norm); } else if (!thunder3) { thunderCalls = 3; setprop("/sim/model/c172p/sound/lightning/dist3", lightning_distance_norm); } else return; # Play the sound (sound files are about 9 seconds) click("thunder" ~ thunderCalls, 9.0, 0); }, delay_seconds); }; var reset_system = func { if (getprop("/fdm/jsbsim/running")) { c172p.autostart(0); } # These properties are aliased to MP properties in /sim/multiplay/generic/. # This aliasing seems to work in both ways, because the two properties below # appear to receive the random values from the MP properties during initialization. # Therefore, override these random values with the proper values we want. props.globals.getNode("/fdm/jsbsim/crash", 0).setBoolValue(0); props.globals.getNode("/fdm/jsbsim/gear/unit[0]/broken", 0).setBoolValue(0); props.globals.getNode("/fdm/jsbsim/gear/unit[1]/broken", 0).setBoolValue(0); props.globals.getNode("/fdm/jsbsim/gear/unit[2]/broken", 0).setBoolValue(0); props.globals.getNode("/fdm/jsbsim/pontoon-damage/left-pontoon", 0).setIntValue(0); props.globals.getNode("/fdm/jsbsim/pontoon-damage/right-pontoon", 0).setIntValue(0); setprop("/engines/active-engine/kill-engine", 0); set_fuel(); } ############################################ # Engine coughing sound ############################################ setlistener("/engines/active-engine/killed", func (node) { if (node.getValue() and getprop("/engines/active-engine/running")) { click("coughing-engine-sound", 0.7, 0); }; }); ############################################ # Static objects: right safety cone ############################################ var StaticModel = { new: func (name, file) { var m = { parents: [StaticModel], model: nil, model_file: file, object_name: name }; setlistener("/sim/" ~ name ~ "/enable", func (node) { if (node.getBoolValue()) { m.add(); } else { m.remove(); } }); return m; }, add: func { var manager = props.globals.getNode("/models", 1); var i = 0; for (; 1; i += 1) { if (manager.getChild("model", i, 0) == nil) { break; } } var position = geo.aircraft_position().set_alt(getprop("/position/ground-elev-m")); if (me.object_name == "anchorbuoy") { me.model = geo.put_model(me.model_file, getprop("/fdm/jsbsim/mooring/anchor-lat"), getprop("/fdm/jsbsim/mooring/anchor-lon"), getprop("/position/ground-elev-m"), getprop("/orientation/heading-deg")); } else { me.model = geo.put_model(me.model_file, position, getprop("/orientation/heading-deg")); } }, remove: func { if (me.model != nil) { me.model.remove(); me.model = nil; } } }; StaticModel.new("coneR", "Aircraft/c172p/Models/Exterior/safety-cone/safety-cone_R.xml"); StaticModel.new("coneL", "Aircraft/c172p/Models/Exterior/safety-cone/safety-cone_L.xml"); StaticModel.new("gpu", "Aircraft/c172p/Models/Exterior/external-power/external-power.xml"); StaticModel.new("ladder", "Aircraft/c172p/Models/Exterior/ladder/ladder.xml"); StaticModel.new("fueltanktrailer", "Aircraft/c172p/Models/Exterior/fueltanktrailer/fueltanktrailer.ac"); StaticModel.new("externalheater", "Aircraft/c172p/Models/Exterior/external-heater/RedDragonEnginePreHeater.ac"); # Mooring anchor and rope StaticModel.new("anchorbuoy", "Aircraft/c172p/Models/Effects/pontoon/mooring.xml"); # external electrical disconnect when groundspeed higher than 0.1ktn (replace later with distance less than 0.01...) var ad_timer = maketimer(0.1, func { groundspeed = getprop("/velocities/groundspeed-kt") or 0; if (groundspeed > 0.1) { setprop("/controls/electric/external-power", "false"); } }); ad_timer.start(); ############################################ # Global loop function # If you need to run nasal as loop, add it in this function ############################################ var global_system_loop = func { c172p.physics_loop(); } ########################################## # SetListerner must be at the end of this file ########################################## var set_limits = func (node) { if (node.getValue() == 1) { var limits = props.globals.getNode("/limits/mass-and-balance-180hp"); } else { var limits = props.globals.getNode("/limits/mass-and-balance-160hp"); } var ac_limits = props.globals.getNode("/limits/mass-and-balance"); # Get the mass limits of the current engine var ramp_mass = limits.getNode("maximum-ramp-mass-lbs"); var takeoff_mass = limits.getNode("maximum-takeoff-mass-lbs"); var landing_mass = limits.getNode("maximum-landing-mass-lbs"); # Get the actual mass limit nodes of the aircraft var ac_ramp_mass = ac_limits.getNode("maximum-ramp-mass-lbs"); var ac_takeoff_mass = ac_limits.getNode("maximum-takeoff-mass-lbs"); var ac_landing_mass = ac_limits.getNode("maximum-landing-mass-lbs"); # Set the mass limits of the aircraft ac_ramp_mass.unalias(); ac_takeoff_mass.unalias(); ac_landing_mass.unalias(); ac_ramp_mass.alias(ramp_mass); ac_takeoff_mass.alias(takeoff_mass); ac_landing_mass.alias(landing_mass); }; setlistener("/controls/engines/active-engine", func (node) { # Set new mass limits for Fuel and Payload Settings dialog set_limits(node); # Emit a sound because the engine has been replaced click("engine-repair", 6.0); }, 0, 0); var update_pax = func { var state = 0; state = bits.switch(state, 0, getprop("pax/co-pilot/present")); state = bits.switch(state, 1, getprop("pax/left-passenger/present")); state = bits.switch(state, 2, getprop("pax/right-passenger/present")); state = bits.switch(state, 3, getprop("pax/pilot/present")); setprop("/payload/pax-state", state); }; setlistener("/pax/co-pilot/present", update_pax, 0, 0); setlistener("/pax/left-passenger/present", update_pax, 0, 0); setlistener("/pax/right-passenger/present", update_pax, 0, 0); setlistener("/pax/pilot/present", update_pax, 0, 0); update_pax(); var update_securing = func { var state = 0; state = bits.switch(state, 0, getprop("/sim/model/c172p/securing/pitot-cover-visible")); state = bits.switch(state, 1, getprop("/sim/model/c172p/securing/chock-visible")); state = bits.switch(state, 2, getprop("/sim/model/c172p/securing/tiedownL-visible")); state = bits.switch(state, 3, getprop("/sim/model/c172p/securing/tiedownR-visible")); state = bits.switch(state, 4, getprop("/sim/model/c172p/securing/tiedownT-visible")); setprop("/payload/securing-state", state); }; setlistener("/sim/model/c172p/securing/pitot-cover-visible", update_securing, 0, 0); setlistener("/sim/model/c172p/securing/chock-visible", update_securing, 0, 0); setlistener("/sim/model/c172p/securing/tiedownL-visible", update_securing, 0, 0); setlistener("/sim/model/c172p/securing/tiedownR-visible", update_securing, 0, 0); setlistener("/sim/model/c172p/securing/tiedownT-visible", update_securing, 0, 0); update_securing(); var log_cabin_temp = func { if (getprop("/sim/model/c172p/enable-fog-frost")) { var temp_degc = getprop("/fdm/jsbsim/heat/cabin-air-temp-degc"); if (temp_degc >= 32) logger.screen.red("Cabin temperature exceeding 90F/32C!"); elsif (temp_degc <= 0) logger.screen.red("Cabin temperature falling below 32F/0C!"); } }; var cabin_temp_timer = maketimer(30.0, log_cabin_temp); var log_fog_frost = func { if (getprop("/sim/model/c172p/enable-fog-frost")) { logger.screen.white("Wait until fog/frost clears up or decrease cabin air temperature"); } }; var fog_frost_timer = maketimer(30.0, log_fog_frost); var dialog_battery_reload = func { electrical.reset_battery_and_circuit_breakers(); gui.popupTip("The battery is now fully charged!"); } var c172_timer = maketimer(0.25, func{global_system_loop()}); setlistener("/sim/signals/fdm-initialized", func { # Randomize callsign of new users to avoid them blocking # other new users on multiplayer if (getprop("/sim/multiplay/callsign") == "callsign") { var digit = func { return math.round(rand()*9); }; var new_callsign = "FG-" ~ digit() ~ digit() ~ digit() ~ digit(); setprop("/sim/multiplay/callsign", new_callsign); }; # Use Nasal to make some properties persistent. does # not work reliably. aircraft.data.add("/sim/model/c172p/immat-on-panel"); aircraft.data.load(); # Initialize mass limits set_limits(props.globals.getNode("/controls/engines/active-engine")); # Close all caps and doors setlistener("/engines/active-engine/cranking", func (node) { setprop("sim/model/show-dip-stick", 0); setprop("sim/model/open-pfuel-cap", 0); setprop("sim/model/open-sfuel-cap", 0); setprop("sim/model/open-pfuel-sump", 0); setprop("sim/model/open-sfuel-sump", 0); setprop("sim/model/door-positions/oilDoor/position-norm", 0); setprop("sim/model/c172p/securing/cowl-plugs-visible", 0); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-oil-dialog-160"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-oil-dialog-180"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-left-fuel-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-right-fuel-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-left-fuel-sample-dialog"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "c172p-right-fuel-sample-dialog"})); }, 0, 0); setlistener("/engines/active-engine/running", func (node) { var autostart = getprop("/engines/active-engine/auto-start"); var cranking = getprop("/engines/active-engine/cranking"); if (autostart and cranking and node.getBoolValue()) { setprop("/controls/switches/starter", 0); setprop("/engines/active-engine/auto-start", 0); } }, 0, 0); # Checking if switches should be moved back to default position (in case save state is off) switches_save_state(); # Checking if fuel contamination is allowed, and if so generating a random situation fuel_contamination(); # Listening for lightning strikes setlistener("/environment/lightning/lightning-pos-y", thunder); reset_system(); var onground = getprop("/sim/presets/onground") or ""; if (!onground) { state_manager(); } # set user defined pilot view or initialize it if (getprop("sim/current-view/view-number") == 0){ settimer(func { if (getprop("sim/current-view/user/x-offset-m") != nil){ setprop("sim/current-view/x-offset-m", getprop("sim/current-view/user/x-offset-m")); } else { setprop("sim/current-view/user/x-offset-m", getprop("sim/view/config/x-offset-m")); } if (getprop("sim/current-view/user/y-offset-m") != nil){ setprop("sim/current-view/y-offset-m", getprop("sim/current-view/user/y-offset-m")); } else { setprop("sim/current-view/user/y-offset-m", getprop("sim/view/config/y-offset-m")); } if (getprop("sim/current-view/user/z-offset-m") != nil){ setprop("sim/current-view/z-offset-m", getprop("sim/current-view/user/z-offset-m")); } else { setprop("sim/current-view/user/z-offset-m", getprop("sim/view/config/z-offset-m")); } if (getprop("sim/current-view/user/default-field-of-view-deg") != nil){ setprop("sim/current-view/field-of-view", getprop("sim/current-view/user/default-field-of-view-deg")); } else { setprop("sim/current-view/user/default-field-of-view-deg", getprop("sim/view/config/default-field-of-view-deg")); } if (getprop("sim/current-view/user/pitch-offset-deg") != nil){ setprop("sim/current-view/pitch-offset-deg", getprop("sim/current-view/user/pitch-offset-deg")); } else { setprop("sim/current-view/user/pitch-offset-deg", getprop("sim/view/config/pitch-offset-deg")); } }, 1); } c172_timer.start(); }); setlistener("/sim/model/c172p/cabin-air-temp-in-range", func (node) { if (node.getValue()) { cabin_temp_timer.stop(); logger.screen.green("Cabin temperature between 32F/0C and 90F/32C"); } else { log_cabin_temp(); cabin_temp_timer.start(); } }, 1, 0); setlistener("/sim/model/c172p/fog-or-frost-increasing", func (node) { if (node.getValue()) { log_fog_frost(); fog_frost_timer.start(); } else { fog_frost_timer.stop(); } }, 1, 0); # season-winter is a conversion value, see c172p-ground-effects.xml setprop("/sim/startup/season-winter", getprop("/sim/startup/season") == "winter"); setlistener("/sim/startup/season", func (node) { setprop("/sim/startup/season-winter", node.getValue() == "winter"); }, 0, 0); # rudder trim setting changes, manual or automatic setlistener("/sim/model/c172p/ruddertrim-visible", func (node) { if (node.getValue()) { setprop("/controls/flight/rudder-trim", 0); } else setprop("/controls/flight/rudder-trim", 0.02); }, 0, 0); #fuel tank configuration switch setlistener("/fdm/jsbsim/fuel/tank", func (node) { # Set fuel configuration set_fuel(); }, 0, 0);