########################################## # 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); } }; controls.applyParkingBrake = func (v) { if (!v) { return; } var left_broken = getprop("/fdm/jsbsim/gear/unit[1]/broken"); var right_broken =getprop("/fdm/jsbsim/gear/unit[2]/broken"); var p = "/controls/gear/brake-parking"; var orig_p = getprop(p); # We assume one non-broken gear is enough to apply the parking brake if (orig_p or !left_broken or !right_broken) { setprop(p, var i = !orig_p); return i; } return orig_p; }; ########################################## # Click Sounds ########################################## var click = func (name, timeout=0.1) { var sound_prop = "/sim/model/c172p/sound/click-" ~ name; # 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); }; ########################################## # Ground Detection ########################################## # Do terrain modelling ourselves. #setprop("sim/fdm/surface/override-level", 1); var terrain_survol_loop = func { var lat = getprop("/position/latitude-deg"); var lon = getprop("/position/longitude-deg"); var info = geodinfo(lat, lon); if (info != nil) { if (info[1] != nil){ if (info[1].solid !=nil) setprop("/environment/terrain-type",info[1].solid); if (info[1].load_resistance !=nil) setprop("/environment/terrain-load-resistance",info[1].load_resistance); if (info[1].friction_factor !=nil) setprop("/environment/terrain-friction-factor",info[1].friction_factor); if (info[1].bumpiness !=nil) setprop("/environment/terrain-bumpiness",info[1].bumpiness); if (info[1].rolling_friction !=nil) setprop("/environment/terrain-rolling-friction",info[1].rolling_friction); if (info[1].names !=nil) setprop("/environment/terrain-names",info[1].names[0]); } }else{ setprop("/environment/terrain",1); setprop("/environment/terrain-load-resistance",1e+30); setprop("/environment/terrain-friction-factor",1.05); setprop("/environment/terrain-bumpiness",0); setprop("/environment/terrain-rolling-friction",0.02); } if(!getprop("sim/freeze/replay-state") and !getprop("/environment/terrain-type") and getprop("/position/altitude-agl-ft") < 3.0){ setprop("sim/messages/copilot", "You are on water !"); setprop("sim/freeze/clock", 1); setprop("sim/freeze/master", 1); setprop("sim/crashed", 1); } } var reset_system = func { if (getprop("/fdm/jsbsim/running")) { c172p.autostart(0); setprop("/controls/switches/starter", 1); var engineRunning = setlistener("/engines/active-engine/running", func{ if (getprop("/engines/active-engine/running")) { setprop("/controls/switches/starter", 0); removelistener(engineRunning); } }); } # 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/killed", 0); setprop("/fdm/jsbsim/contact/unit[4]/z-position", 50); setprop("/fdm/jsbsim/contact/unit[5]/z-position", 50); # Note: these separate flags exist because PUI's element # only accepts booleans. var p = getprop("fdm/jsbsim/bushkit"); setprop("/sim/model/c172p/bushkit_flag_0",0); setprop("/sim/model/c172p/bushkit_flag_1",0); setprop("/sim/model/c172p/bushkit_flag_2",0); setprop("/sim/model/c172p/bushkit_flag_3",0); setprop("/sim/model/c172p/bushkit_flag_4",0); if (p == 0) { setprop("/sim/model/c172p/bushkit_flag_0",1); } if (p == 1) { setprop("/sim/model/c172p/bushkit_flag_1",1); } if (p == 2) { setprop("/sim/model/c172p/bushkit_flag_2",1); } if (p == 3) { setprop("/sim/model/c172p/bushkit_flag_3",1); } if (p == 4) { setprop("/sim/model/c172p/bushkit_flag_4",1); } } ############################################ # Global loop function # If you need to run nasal as loop, add it in this function ############################################ var global_system_loop = func{ # terrain_survol_loop was incorporated during damage system creation. # "Unimplemented" crash detection system requires this self terrain modelling (I think) # If we end up not using it, then we can remove it. #terrain_survol_loop(); c172p.physics_loop(); c172p.weather_effects_loop(); } ########################################## # SetListerner must be at the end of this file ########################################## #setlistener("/sim/signals/fdm-initialized", func{ # setprop("/environment/terrain-type",1); # setprop("/environment/terrain-load-resistance",1e+30); # setprop("/environment/terrain-friction-factor",1.05); # setprop("/environment/terrain-bumpiness",0); # setprop("/environment/terrain-rolling-friction",0.02); #}); 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")); 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); update_pax(); var nasalInit = setlistener("/sim/signals/fdm-initialized", func{ # 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")); # Set alt alert of KAP 140 autopilot to 20_000 ft to get rid of annoying beep setlistener("/autopilot/KAP140/settings/target-alt-ft", func (n) { if (n.getValue() == 0) { kap140.altPreselect = 20000; setprop("/autopilot/KAP140/settings/target-alt-ft", kap140.altPreselect); } }); reset_system(); var c172_timer = maketimer(0.25, func{global_system_loop()}); c172_timer.start(); });