remove README.Protocol and add a README that refers to the "real"
[fg:toms-fgdata.git] / Nasal / fuel.nas
1 # Properties under /consumables/fuel/tank[n]:
2 # + level-gal_us    - Current fuel load.  Can be set by user code.
3 # + level-lbs       - OUTPUT ONLY property, do not try to set
4 # + selected        - boolean indicating tank selection.
5 # + density-ppg     - Fuel density, in lbs/gallon.
6 # + capacity-gal_us - Tank capacity
7 #
8 # Properties under /engines/engine[n]:
9 # + fuel-consumed-lbs - Output from the FDM, zeroed by this script
10 # + out-of-fuel       - boolean, set by this code.
11
12
13 var UPDATE_PERIOD = 0.3;
14
15
16 update = func {
17         if (fuel_freeze) {
18                 return;
19         }
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         if (!consumed_fuel) {
29                 return;
30         }
31
32         var selected_tanks = [];
33         foreach (var t; tanks) {
34                 var cap = t.getNode("capacity-gal_us").getValue();
35                 if (cap > 0.01 and t.getNode("selected").getBoolValue()) {
36                         append(selected_tanks, t);
37                 }
38         }
39
40         # Subtract fuel from tanks, set auxilliary properties.  Set out-of-fuel
41         # when any one tank is dry.
42         var out_of_fuel = 0;
43         if (size(selected_tanks) == 0) {
44                 out_of_fuel = 1;
45         } else {
46                 var fuel_per_tank = consumed_fuel / size(selected_tanks);
47                 foreach (var t; selected_tanks) {
48                         var ppg = t.getNode("density-ppg").getValue();
49                         var lbs = t.getNode("level-gal_us").getValue() * ppg;
50                         lbs = lbs - fuel_per_tank;
51                         if (lbs < 0) {
52                                 lbs = 0;
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                         var gals = lbs / ppg;
62                         t.getNode("level-gal_us").setDoubleValue(gals);
63                         t.getNode("level-lbs").setDoubleValue(lbs);
64                 }
65         }
66
67         # Total fuel properties
68         var lbs = 0;
69         var gals = 0;
70         var cap = 0;
71
72         foreach (var t; tanks) {
73                 lbs += t.getNode("level-lbs").getValue();
74                 gals += t.getNode("level-gal_us").getValue();
75                 cap += t.getNode("capacity-gal_us").getValue();
76         }
77
78         total_lbs.setDoubleValue(lbs);
79         total_gals.setDoubleValue(gals);
80         total_norm.setDoubleValue(gals / cap);
81
82         foreach (var e; engines) {
83                 e.getNode("out-of-fuel").setBoolValue(out_of_fuel);
84         }
85 }
86
87
88 loop = func {
89         update();
90         settimer(loop, UPDATE_PERIOD);
91 }
92
93
94 init_double_prop = func(node, prop, val) {
95         if (node.getNode(prop) != nil) {
96                 val = num(node.getNode(prop).getValue());
97         }
98         node.getNode(prop, 1).setDoubleValue(val);
99 }
100
101
102
103 var tanks = [];
104 var engines = [];
105 var fuel_freeze = nil;
106 var total_gals = nil;
107 var total_lbs = nil;
108 var total_norm = nil;
109
110
111 var L = _setlistener("/sim/signals/fdm-initialized", func {
112         removelistener(L);
113
114         setlistener("/sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1);
115
116         total_gals = props.globals.getNode("/consumables/fuel/total-fuel-gals", 1);
117         total_lbs = props.globals.getNode("/consumables/fuel/total-fuel-lbs", 1);
118         total_norm = props.globals.getNode("/consumables/fuel/total-fuel-norm", 1);
119
120         engines = props.globals.getNode("engines", 1).getChildren("engine");
121         foreach (var e; engines) {
122                 e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
123                 e.getNode("out-of-fuel", 1).setBoolValue(0);
124         }
125
126         foreach (var t; props.globals.getNode("/consumables/fuel", 1).getChildren("tank")) {
127                 if (!size(t.getChildren())) {
128                         continue;           # skip native_fdm.cxx generated zombie tanks
129                 }
130                 append(tanks, t);
131                 init_double_prop(t, "level-gal_us", 0.0);
132                 init_double_prop(t, "level-lbs", 0.0);
133                 init_double_prop(t, "capacity-gal_us", 0.01); # not zero (div/zero issue)
134                 init_double_prop(t, "density-ppg", 6.0);      # gasoline
135
136                 if (t.getNode("selected") == nil) {
137                         t.getNode("selected", 1).setBoolValue(1);
138                 }
139         }
140
141         loop();
142 });
143
144