1
0
Fork 0
fgdata/Aircraft/Generic/Systems/compat_failure_modes.nas
Anton Gomez Alvedro c108f3b988 Bugfixes and improvements to the Failure Manager
- Fix: runtime exception in remove_failure_mode()
  - Fix: keep failure & trigger status on teleport.
  - Fix: allow random failures from the gui to be enabled/disabled multiple times.
  - Fix: mcbf/mtbf are set to zero when they fire, so they can be reactivated from the gui.
  - Fix: string casts of several trigger types had syntax errors.
  - Usability: screen messages related to failures now use positive logic:
         "condition 100%" instead of "failure level 0%"
  - Performance: Time triggers now use internal timers, instead of requiring being polled.
  - Reviewed Trigger interface for more rational usage. reset() is replaced by arm()/disarm()
  - Added a subscription interface to listen to FailureMgr events.
  - Added an internal log buffer to keep a record of relevant events and present them to gui elements.
  - Several usability improvements to the FailureMgr Nasal API.
2014-12-21 12:39:52 +01:00

218 lines
7.3 KiB
Text

# 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);