c108f3b988
- 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.
218 lines
7.3 KiB
Text
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);
|