# Compatibility failure modes # # Loads FailureMgr with the failure modes that where previously hardcoded, # emulating former behavior and allowing backward compatibility. # # Copyright (C) 2014 Anton Gomez Alvedro # Based on previous work by Stuart Buchanan, Erobo & John Denker # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. io.include("Aircraft/Generic/Systems/failures.nas"); MTBF = 0; MCBF = 1; SERV = 0; JAM = 1; ENG = 2; var compat_modes = [ # Instruments { id: "instrumentation/adf", type: MTBF, failure: SERV, desc: "ADF" }, { id: "instrumentation/dme", type: MTBF, failure: SERV, desc: "DME" }, { id: "instrumentation/airspeed-indicator", type: MTBF, failure: SERV, desc: "ASI" }, { id: "instrumentation/altimeter", type: MTBF, failure: SERV, desc: "Altimeter" }, { id: "instrumentation/attitude-indicator", type: MTBF, failure: SERV, desc: "Attitude Indicator" }, { id: "instrumentation/heading-indicator", type: MTBF, failure: SERV, desc: "Heading Indicator" }, { id: "instrumentation/magnetic-compass", type: MTBF, failure: SERV, desc: "Magnetic Compass" }, { id: "instrumentation/nav/gs", type: MTBF, failure: SERV, desc: "Nav 1 Glideslope" }, { id: "instrumentation/nav/cdi", type: MTBF, failure: SERV, desc: "Nav 1 CDI" }, { id: "instrumentation/nav[1]/gs", type: MTBF, failure: SERV, desc: "Nav 2 Glideslope" }, { id: "instrumentation/nav[1]/cdi", type: MTBF, failure: SERV, desc: "Nav 2 CDI" }, { id: "instrumentation/slip-skid-ball", type: MTBF, failure: SERV, desc: "Slip/Skid Ball" }, { id: "instrumentation/turn-indicator", type: MTBF, failure: SERV, desc: "Turn Indicator" }, { id: "instrumentation/vertical-speed-indicator", type: MTBF, failure: SERV, desc: "VSI" }, # Systems { id: "systems/electrical", type: MTBF, failure: SERV, desc: "Electrical system" }, { id: "systems/pitot", type: MTBF, failure: SERV, desc: "Pitot system" }, { id: "systems/static", type: MTBF, failure: SERV, desc: "Static system" }, { id: "systems/vacuum", type: MTBF, failure: SERV, desc: "Vacuum system" }, # Controls { id: "controls/flight/aileron", type: MTBF, failure: JAM, desc: "Aileron" }, { id: "controls/flight/elevator", type: MTBF, failure: JAM, desc: "Elevator" }, { id: "controls/flight/rudder", type: MTBF, failure: JAM, desc: "Rudder" }, { id: "controls/flight/flaps", type: MCBF, failure: JAM, desc: "Flaps" }, { id: "controls/flight/speedbrake", type: MCBF, failure: JAM, desc: "Speed Brake" }, { id: "controls/gear", type: MCBF, failure: SERV, desc: "Gear", prop: "/gear", mcbf_prop: "/controls/gear/gear-down" } ]; ## # Handles the old failures.nas property tree interface, # sending the appropriate commands to the new FailureMgr. var compat_listener = func(prop) { var name = prop.getName(); var value = prop.getValue(); var id = string.replace(io.dirname(prop.getPath()), FailureMgr.proproot, ""); id = string.trim(id, 0, func(c) c == `/`); if (name == "serviceable") { FailureMgr.set_failure_level(id, value ? 0 : 1); return; } if (name == "failure-level") { setprop(io.dirname(prop.getPath()) ~ "/serviceable", value ? 0 : 1); return; } # mtbf and mcbf parameter handling var trigger = FailureMgr.get_trigger(id); if (trigger == nil or (trigger.type != "mcbf" and trigger.type != "mtbf")) return; if (value != 0) trigger.set_param(name, value) and trigger.arm(); else trigger.disarm(); } ## # Listens to FailureMgr events. Resets mcbf/mtbf params to zero so they can # be rearmed from the GUI. var trigger_listener = func(event) { var trigger = event.trigger; # Only control modes in our compat list, i.e. do not interfere # with custom scripts. if (trigger.type != "mtbf" and trigger.type != "mcbf") return; foreach (var m; compat_modes) { if (m.id == event.mode_id) { trigger.set_param(trigger.type, 0); break; } } } ## # Called from the ramdom-failures dialog to set the global MCBF parameter var apply_global_mcbf = func(value) { foreach (var mode; compat_modes) { mode.type != MCBF and continue; setprop(FailureMgr.proproot ~ mode.id ~ "/mcbf", value); } } ## # Called from the ramdom-failures dialog to set the global MTBF parameter var apply_global_mtbf = func(value) { foreach (var mode; compat_modes) { mode.type != MTBF and continue; setprop(FailureMgr.proproot ~ mode.id ~ "/mtbf", value); } } ## # Discover aircraft engines dynamically and add a failure mode to the # compat_modes table for each engine. var populate_engine_data = func { var engines = props.globals.getNode("/engines"); var engine_id = 0; foreach (var e; engines.getChildren("engine")) { var starter = e.getChild("starter"); var running = e.getChild("running"); (starter != nil and starter != "" and starter.getType() != "NONE") or (running != nil and running != "" and running.getType() != "NONE") or continue; var id = "engines/engine"; if (engine_id > 0) id = id ~ "[" ~ engine_id ~ "]"; var entry = { id: id, desc: "Engine " ~ (engine_id + 1), type: MTBF, failure: ENG }; append(compat_modes, entry); engine_id += 1; } } ## # Subscribes all failure modes that the old failures.nas module did, # and recreates the same property tree interface (more or less). var compat_setup = func { removelistener(lsnr); populate_engine_data(); foreach (var m; compat_modes) { var control_prop = contains(m, "prop") ? m.prop : m.id; FailureMgr.add_failure_mode( id: m.id, description: m.desc, actuator: if (m.failure == SERV) set_unserviceable(control_prop) elsif (m.failure == JAM) set_readonly(control_prop) else fail_engine(io.basename(control_prop))); # Recreate the prop tree interface var prop = FailureMgr.proproot ~ m.id; var n = props.globals.initNode(prop ~ "/serviceable", 1, "BOOL"); setlistener(n, compat_listener, 0, 0); setlistener(prop ~ "/failure-level", compat_listener, 0, 0); if (m.type == MTBF) { var trigger_type = "/mtbf"; FailureMgr.set_trigger(m.id, MtbfTrigger.new(0)); } else { var trigger_type = "/mcbf"; var control = contains(m, "mcbf_prop")? m.mcbf_prop : m.id; FailureMgr.set_trigger(m.id, McbfTrigger.new(control, 0)); } setprop(prop ~ trigger_type, 0); setlistener(prop ~ trigger_type, compat_listener, 0, 0); } FailureMgr.events["trigger-fired"].subscribe(trigger_listener); } var lsnr = setlistener("sim/signals/fdm-initialized", compat_setup);