1
0
Fork 0
fgdata/Aircraft/Generic/aar.nas
mfranz 0e62263eaf generate some nodes if they don't exist yet (this was left out on purpose,
as missing nodes should point to more serious problems elsewhere, but this
state can happen in normal situations, too)
2006-11-25 17:49:23 +00:00

222 lines
5.7 KiB
Text

# Properties under /consumables/fuel/tank[n]:
# + level-gal_us - Current fuel load. Can be set by user code.
# + level-lbs - OUTPUT ONLY property, do not try to set
# + selected - boolean indicating tank selection.
# + density-ppg - Fuel density, in lbs/gallon.
# + capacity-gal_us - Tank capacity
#
# Properties under /engines/engine[n]:
# + fuel-consumed-lbs - Output from the FDM, zeroed by this script
# + out-of-fuel - boolean, set by this code.
var UPDATE_PERIOD = 0.3;
var enabled = nil;
var fuel_freeze = nil;
var ai_enabled = nil;
var engines = nil;
var tanks = nil;
var refuelingN = nil;
var aimodelsN = nil;
# initialize property if it doesn't exist, and set node type otherwise
init_prop = func(node, prop, val, type = "double") {
var n = node.getNode(prop);
if (n != nil) {
var v = n.getValue();
if (v != nil) {
val = v;
}
}
node = node.getNode(prop, 1);
if (type == "double") {
node.setDoubleValue(val);
} elsif (type == "bool") {
node.setBoolValue(val);
} elsif (type == "int") {
node.setIntValue(val);
}
}
update_loop = func {
# check for contact with tanker aircraft
var tankers = [];
if (ai_enabled) {
foreach (a; aimodelsN.getChildren("aircraft")) {
var contact = a.getNode("refuel/contact", 1).getBoolValue();
var tanker = a.getNode("tanker", 1).getBoolValue();
#var id = a.getNode("id").getValue();
#print("ai '", id, "' contact=", contact, " tanker=", tanker);
if (tanker and contact) {
append(tankers, a);
}
}
foreach (m; aimodelsN.getChildren("multiplayer")) {
var contact = m.getNode("refuel/contact", 1).getBoolValue();
var tanker = m.getNode("tanker", 1).getBoolValue();
#var id = m.getNode("id").getValue();
#print("mp '", id, "' contact=", contact, " tanker=", tanker);
if (tanker and contact) {
append(tankers, m);
}
}
}
var refueling = size(tankers) >= 1;
refuelingN.setBoolValue(refueling);
if (fuel_freeze) {
return settimer(update_loop, UPDATE_PERIOD);
}
# sum up consumed fuel
var total = 0;
foreach (var e; engines) {
total += e.getNode("fuel-consumed-lbs").getValue();
}
# calculate fuel received
if (refueling) {
# assume max flow rate is 6000 lbs/min (for KC135)
var received = 100 * UPDATE_PERIOD;
total -= received;
}
# make list of selected tanks
var selected_tanks = [];
foreach (var t; tanks) {
var cap = t.getNode("capacity-gal_us", 1).getValue();
if (cap != nil and cap > 0.01 and t.getNode("selected", 1).getBoolValue()) {
append(selected_tanks, t);
}
}
var out_of_fuel = 0;
if (size(selected_tanks) == 0) {
out_of_fuel = 1;
} else {
if (total >= 0) {
var fuelPerTank = total / size(selected_tanks);
foreach (var t; selected_tanks) {
var ppg = t.getNode("density-ppg").getValue();
var lbs = t.getNode("level-gal_us").getValue() * ppg;
lbs -= fuelPerTank;
if (lbs < 0) {
lbs = 0;
# Kill the engines if we're told to, otherwise simply
# deselect the tank.
if (t.getNode("kill-when-empty", 1).getBoolValue()) {
out_of_fuel = 1;
} else {
t.getNode("selected", 1).setBoolValue(0);
}
}
var gals = lbs / ppg;
t.getNode("level-gal_us").setDoubleValue(gals);
t.getNode("level-lbs").setDoubleValue(lbs);
}
} elsif (total < 0) {
#find the number of tanks which can accept fuel
var available = 0;
foreach (var t; selected_tanks) {
var ppg = t.getNode("density-ppg").getValue();
var capacity = t.getNode("capacity-gal_us").getValue() * ppg;
var lbs = t.getNode("level-gal_us").getValue() * ppg;
if (lbs < capacity) {
available += 1;
}
}
if (available > 0) {
var fuelPerTank = total / available;
# add fuel to each available tank
foreach (var t; selected_tanks) {
var ppg = t.getNode("density-ppg").getValue();
var capacity = t.getNode("capacity-gal_us").getValue() * ppg;
var lbs = t.getNode("level-gal_us").getValue() * ppg;
if (capacity - lbs >= fuelPerTank) {
lbs -= fuelPerTank;
} elsif (capacity - lbs < fuelPerTank) {
lbs = capacity;
}
t.getNode("level-gal_us").setDoubleValue(lbs / ppg);
t.getNode("level-lbs").setDoubleValue(lbs);
}
# print ("available ", available , " fuelPerTank " , fuelPerTank);
}
}
}
var gals = 0;
var lbs = 0;
var cap = 0;
foreach (var t; tanks) {
gals += t.getNode("level-gal_us", 1).getValue();
lbs += t.getNode("level-lbs", 1).getValue();
cap += t.getNode("capacity-gal_us", 1).getValue();
}
setprop("/consumables/fuel/total-fuel-gals", gals);
setprop("/consumables/fuel/total-fuel-lbs", lbs);
setprop("/consumables/fuel/total-fuel-norm", gals / cap);
foreach (var e; engines) {
e.getNode("out-of-fuel", 1).setBoolValue(out_of_fuel);
}
settimer(update_loop, UPDATE_PERIOD);
}
setlistener("/sim/signals/fdm-initialized", func {
fuel.updateFuel = func {} # kill $FG_ROOT/Nasal/fuel.nas' loop
refuelingN = props.globals.getNode("/systems/refuel/contact", 1);
refuelingN.setBoolValue(0);
aimodelsN = props.globals.getNode("ai/models", 1);
engines = props.globals.getNode("engines", 1).getChildren("engine");
tanks = props.globals.getNode("consumables/fuel", 1).getChildren("tank");
foreach (var e; engines) {
e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
e.getNode("out-of-fuel", 1).setBoolValue(0);
}
foreach (var t; tanks) {
init_prop(t, "level-gal_us", 0);
init_prop(t, "level-lbs", 0);
init_prop(t, "capacity-gal_us", 0.01); # Not zero (div/zero issue)
init_prop(t, "density-ppg", 6.0); # gasoline
init_prop(t, "selected", 1, "bool");
}
setlistener("sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1);
setlistener("sim/ai/enabled", func { ai_enabled = cmdarg().getBoolValue() }, 1);
update_loop();
});