Phi: nicer scroll animation for METAR widget
[fg:fgdata.git] / Nasal / fuel.nas
1 # Fuel handling for the YASim FDM. Note that other FDMs (e.g. JSBSim)
2 # handle fuel within the FDM itself.
3 #
4 # Properties under /consumables/fuel/tank[n]:
5 # + level-lbs       - Current fuel load.  Can be set by user code.
6 # + selected        - boolean indicating tank selection.
7 # + capacity-gal_us - Tank capacity
8 #
9 # Properties under /engines/engine[n]:
10 # + fuel-consumed-lbs - Output from the FDM, zeroed by this script
11 # + out-of-fuel       - boolean, set by this code.
12
13
14 var UPDATE_PERIOD = 0.3;
15
16
17 var update = func {
18         if (fuel_freeze)
19                 return;
20
21         var consumed_fuel = 0;
22         foreach (var e; engines) {
23                 var fuel = e.getNode("fuel-consumed-lbs");
24                 consumed_fuel += fuel.getValue();
25                 fuel.setDoubleValue(0);
26         }
27
28         var selected_tanks = [];
29         foreach (var t; tanks) {
30                 var cap = t.getNode("capacity-gal_us",0);
31                 var selected = t.getNode("selected");
32                 if ((cap!=nil) and (cap.getValue() > 0.01) and (t.getNode("level-lbs") != nil) and
33                         (selected != nil) and selected.getBoolValue())
34                         append(selected_tanks, t);
35         }
36
37         # Subtract fuel from tanks, set auxiliary properties.  Set out-of-fuel
38         # when any one tank is dry.
39         var out_of_fuel = 0;
40         if (size(selected_tanks) == 0) {
41                 out_of_fuel = 1;
42         } else {
43                 var fuel_per_tank = consumed_fuel / size(selected_tanks);
44                 foreach (var t; selected_tanks) {
45                         var lbs = t.getNode("level-lbs");
46                         lbs.setDoubleValue(lbs.getValue() - fuel_per_tank);
47                         var empty = t.getNode("empty");
48                         if (empty == nil)
49                                 empty = (lbs.getValue() <= 0);
50                         else
51                                 empty = empty.getBoolValue();
52                         if( empty ) {
53                                 # Kill the engines if we're told to, otherwise simply
54                                 # deselect the tank.
55                                 if (t.getNode("kill-when-empty", 1).getBoolValue())
56                                         out_of_fuel = 1;
57                                 else
58                                         t.getNode("selected").setBoolValue(0);
59                         }
60                 }
61         }
62
63         foreach (var e; engines)
64                 e.getNode("out-of-fuel").setBoolValue(out_of_fuel);
65 }
66
67
68 var loop = func {
69         update();
70         settimer(loop, UPDATE_PERIOD);
71 }
72
73 var tanks = [];
74 var engines = [];
75 var fuel_freeze = nil;
76
77 var freeze_fuel_listener = nil;
78 var initialized = 0;
79
80 _setlistener("/sim/signals/fdm-initialized", func {
81         if (freeze_fuel_listener == nil)
82         {
83                 freeze_fuel_listener = setlistener("/sim/freeze/fuel", func(n) { fuel_freeze = n.getBoolValue() }, 1);
84         }
85
86         # Fuel sub-system is only used by YASim. Other FDMs (e.g. JSBSim)
87         # handle fuel themselves.
88         if (getprop("/sim/flight-model") != "yasim") { return; }
89
90         engines = props.globals.getNode("engines", 1).getChildren("engine");
91         foreach (var e; engines) {
92                 e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
93                 e.getNode("out-of-fuel", 1).setBoolValue(0);
94         }
95
96         # do the following stuff once only
97         if (initialized)
98                 return;
99         initialized = 1;
100
101         foreach (var t; props.globals.getNode("/consumables/fuel", 1).getChildren("tank")) {
102                 if (!t.getAttribute("children"))
103                         continue;           # skip native_fdm.cxx generated zombie tanks
104
105                 append(tanks, t);
106                 t.initNode("selected", 1, "BOOL");
107         }
108
109         loop();
110 });
111
112