Indicate these models want to use their own terrein handling code, until they switch...
[fg:toms-fgdata.git] / Aircraft / DR400-dauphin / Nasal / dr400.nas
1 ###############################################################################
2 ##
3 ##  Nasal for DR400-dauphin
4 ##
5 ##  dany93
6 ##  Clément de l'Hamaide - PAF Team - http://equipe-flightgear.forumactif.com
7 ##  This file is licensed under the GPL license version 2 or later.
8 ##
9 ###############################################################################
10
11 # Do terrain modelling ourselves.
12 setprop("sim/fdm/surface/override-level", 1);
13
14
15 #####################################
16 # Save data
17 #####################################
18
19 foreach( var config; props.globals.getNode("/sim/model/config").getChildren() ) {
20   aircraft.data.add(config);
21 }
22
23 #####################################
24 # Dialogs
25 #####################################
26
27 var config_dlg = gui.Dialog.new("/sim/gui/dialogs/config/dialog", getprop("/sim/aircraft-dir")~"/Dialogs/config.xml");
28
29 #####################################
30 # Canopy
31 #####################################
32
33 var canopy = aircraft.door.new("controls/canopy", 3);
34
35 ###############################################
36 #Fuel Management (+ Daniel Dubreuil, March 2013)
37 ###############################################
38
39   setprop("controls/fuel/selected-tank",-1);
40   setprop("/engines/engine/fuel-pressure-psi",0);
41   props.globals.initNode("consumables/fuel/tank[0]/selected",0,"BOOL");
42   props.globals.initNode("consumables/fuel/tank[1]/selected",0,"BOOL");
43   props.globals.initNode("consumables/fuel/tank[2]/selected",0,"BOOL");
44   props.globals.initNode("consumables/fuel/fuel-low",0,"INT");
45
46 #Feeding tank (to engine)
47
48   setlistener("controls/fuel/selected-tank", func() {
49   var sel_tank = getprop("controls/fuel/selected-tank");  
50
51      if (sel_tank == 0) {
52         setprop("consumables/fuel/tank[0]/selected",1);
53         setprop("fdm/jsbsim/propulsion/tank[0]/priority", 1);
54      }
55      else {
56         setprop("consumables/fuel/tank[0]/selected",0); 
57         setprop("fdm/jsbsim/propulsion/tank[0]/priority", 0);
58      };
59      if (sel_tank == 1) {
60         setprop("consumables/fuel/tank[1]/selected",1);
61         setprop("fdm/jsbsim/propulsion/tank[1]/priority", 1);
62      }
63      else {
64         setprop("consumables/fuel/tank[1]/selected",0);  
65         setprop("fdm/jsbsim/propulsion/tank[1]/priority", 0);
66      };
67      if (sel_tank == 2) {
68         setprop("consumables/fuel/tank[2]/selected",1);
69         setprop("fdm/jsbsim/propulsion/tank[2]/priority", 1);
70      }
71      else {
72         setprop("consumables/fuel/tank[2]/selected",0);
73         setprop("fdm/jsbsim/propulsion/tank[2]/priority", 0);
74      }
75   });
76
77 var Fuel = func {
78   
79   var engine_run = getprop("/engines/engine/running");
80   var pump_on = (getprop("/systems/electrical/outputs/fuel-pump") > 20) ? 1 : 0;
81   var fuel_level_0 = getprop("consumables/fuel/tank[0]/level-lbs");
82   var fuel_level_1 = getprop("consumables/fuel/tank[1]/level-lbs");
83   var fuel_level_2 = getprop("consumables/fuel/tank[2]/level-lbs");
84   var tank_selector0 = getprop("consumables/fuel/tank[0]/selected");
85   var tank_selector1 = getprop("consumables/fuel/tank[1]/selected");
86   var tank_selector2 = getprop("consumables/fuel/tank[2]/selected");
87   
88 #Fuel level low (15.43 lbs = 10 liters) in the selected tank
89 # two warning thresholds: light then sound
90
91   if ((fuel_level_0 < 15.43 and tank_selector0) or (fuel_level_1 < 15.43 and tank_selector1) or (fuel_level_2 < 15.43 and tank_selector2))
92     if ((fuel_level_0 < 1.5 and tank_selector0) or (fuel_level_1 < 5 and tank_selector1) or (fuel_level_2 < 1.5 and tank_selector2))
93       setprop("consumables/fuel/fuel-low",2);
94     else
95       setprop("consumables/fuel/fuel-low",1);
96   else
97       setprop("consumables/fuel/fuel-low",0);
98
99 #Fuel pressure 
100
101   if ((fuel_level_0 > 0.1 and tank_selector0) or (fuel_level_1 > 0.1 and tank_selector1) or (fuel_level_2 > 0.1 and tank_selector2))
102       if (pump_on)
103           interpolate("/engines/engine/fuel-pressure-psi", 4, 1); #300 mbar    
104       else 
105           if(engine_run)
106             interpolate("/engines/engine/fuel-pressure-psi", 4, 1); #300 mbar         
107           else 
108                interpolate("/engines/engine/fuel-pressure-psi", 0, 1);               
109   else 
110       interpolate("/engines/engine/fuel-pressure-psi", 0, 1);
111   
112 #Engine does not start if no fuel pressure 
113    
114   if(getprop("/engines/engine/fuel-pressure-psi") > 1){
115      if (tank_selector0)
116         setprop("fdm/jsbsim/propulsion/tank[0]/priority", 1);
117      else 
118         setprop("fdm/jsbsim/propulsion/tank[0]/priority", 0);
119      if (tank_selector1)
120         setprop("fdm/jsbsim/propulsion/tank[1]/priority", 1);
121      else 
122         setprop("fdm/jsbsim/propulsion/tank[1]/priority", 0);
123      if (tank_selector2)
124         setprop("fdm/jsbsim/propulsion/tank[2]/priority", 1);
125      else 
126         setprop("fdm/jsbsim/propulsion/tank[2]/priority", 0);
127   }
128   else {
129      setprop("fdm/jsbsim/propulsion/tank[0]/priority", 0);
130      setprop("fdm/jsbsim/propulsion/tank[1]/priority", 0);
131      setprop("fdm/jsbsim/propulsion/tank[2]/priority", 0);
132   }
133 };
134
135 ##########################################
136 # Horameter / Chrono
137 ##########################################
138
139 props.globals.initNode("/instrumentation/horameter/elapsed-time", 0, "INT");
140 props.globals.initNode("/instrumentation/chrono/elapsed-time", 0, "INT");
141
142 var chrono = aircraft.timer.new("/instrumentation/chrono/elapsed-time", 1);
143 var horameter = aircraft.timer.new("/instrumentation/horameter/elapsed-time", 1, 1);
144
145 setlistener("/instrumentation/horameter/running", func(running){
146   if(running.getBoolValue()){
147     horameter.start();
148   }else{
149     horameter.stop();
150   }
151 });
152
153
154 var floor = func(v) v < 0.0 ? -int(-v) - 1 : int(v);
155 var elapsedTime = 0;
156 var formatedTime = "";
157 var sec = 0;
158 var min = 0;
159 var hrs = 0;
160
161 var timeFormat = func{
162
163   elapsedTime = getprop("/instrumentation/chrono/elapsed-time");
164
165   hrs = floor(elapsedTime/3600);
166   min = floor(elapsedTime/60);
167   sec = elapsedTime;
168
169   formatedTime = sprintf("%02d:%02d:%02d", hrs, min-(60*hrs), sec-(60*min));
170   setprop("/instrumentation/chrono/formated-time", formatedTime);
171
172 }
173
174 ##############################################
175 ############### ENGINE SYSTEM ################
176 ##############################################
177
178 #Engine sensors class 
179 # ie: var Eng = Engine.new(engine number);
180 var Engine = {
181     new : func(eng_num){
182         m =               { parents : [Engine]};
183         m.air_temp =      props.globals.initNode("environment/temperature-degc");
184         m.oat =           m.air_temp.getValue() or 0;
185         m.eng =           props.globals.initNode("engines/engine["~eng_num~"]");
186         m.running =       0;
187         m.ot_target =     90;
188         m.mp =            m.eng.initNode("mp-inhg");
189         m.cutoff =        props.globals.initNode("controls/engines/engine["~eng_num~"]/cutoff");
190         m.mixture =       props.globals.initNode("engines/engine["~eng_num~"]/mixture");
191         m.mixture_lever = props.globals.initNode("controls/engines/engine["~eng_num~"]/mixture",1,"DOUBLE");
192         m.rpm =           m.eng.initNode("rpm",1);
193         m.oil_temp =      m.eng.initNode("oil-temp-c",m.oat,"DOUBLE");
194         m.cyl_temp =      m.eng.initNode("cyl-temp",m.oat,"DOUBLE");
195         m.carb_heat =     m.eng.initNode("carb-heat",0,"DOUBLE");
196         m.carb_temp =     m.eng.initNode("carb-temp-degc",m.oat,"DOUBLE");
197         m.oil_psi =       m.eng.initNode("oil-pressure-psi",0.0,"DOUBLE");
198         m.fuel_psi =      m.eng.initNode("fuel-psi-norm",0,"DOUBLE");
199         m.fuel_out =      m.eng.initNode("out-of-fuel",0,"BOOL");
200         m.fuel_switch =   props.globals.initNode("controls/fuel/switch-position",-1,"INT");
201         m.hpump =         props.globals.initNode("systems/hydraulics/pump-psi["~eng_num~"]",0,"DOUBLE");
202         m.Lrunning =      setlistener("engines/engine["~eng_num~"]/running",func (rn){m.running=rn.getValue()},0,0);
203         return m;
204     },
205 #### update ####
206     update : func(eng_num){
207         var rpm =     me.rpm.getValue();
208         var mp =      me.mp.getValue();
209         var OT =      me.oil_temp.getValue();
210         var mx =      me.mixture_lever.getValue();
211         var ctemp =   me.air_temp.getValue();
212         var cyltemp = me.cyl_temp.getValue();
213         var cheat =   me.carb_heat.getValue();
214         var cooling = (getprop("velocities/airspeed-kt") * 0.1) *2;
215         ###################################
216         ######### OIL TEMPERATURE #########
217         ###################################
218         cooling += (mx * 5);
219         var tgt  = me.ot_target + mp;
220         var tgt -= cooling;
221         if(me.running){
222                 if(OT < tgt) OT += rpm * 0.00001;
223                 if(OT > tgt) OT -= cooling * 0.001;
224                 }else{
225                 if(OT > me.air_temp.getValue()) OT-=0.001; 
226         }
227         me.oil_temp.setValue(OT);
228         ###################################
229         ##### CARBURATOR TEMPERATURE ######
230         ###################################
231         var et0 = getprop("/environment/temperature-degc");
232         # var cbt = et0 + 0.85 * mp; #carb temperature
233         if(props.globals.getNode("systems/electrical/outputs/carb-heat").getValue() > 24){
234           cheat += 0.01;
235           if(cheat > 15) cheat = 15;
236           setprop("engines/engine["~eng_num~"]/carb-heat", cheat);
237           # cbt += cheat;
238         }else{
239           cheat -= 0.05;
240           if(cheat < 0) cheat = 0;
241           setprop("engines/engine["~eng_num~"]/carb-heat", cheat);
242           # cbt += cheat;
243         }
244         ctemp = (rpm * 0.0029);
245         me.carb_temp.setValue(et0 - ctemp + cheat);
246         ######################################
247         ############ PROP FRICTION ###########
248         ######################################
249         if(!getprop("/fdm/jsbsim/propulsion/engine/set-running") and
250            getprop("/systems/electrical/outputs/starter") < 8) {
251            setprop("/fdm/jsbsim/propulsion/engine/friction-hp", 20);
252         }else{
253            setprop("/fdm/jsbsim/propulsion/engine/friction-hp", 0);
254         }
255     },
256 };
257
258 EngineMain = Engine.new(0);
259
260 ##########################################
261 # Mixture/Throttle controlled by mouse
262 ##########################################
263
264 var mousex =0;
265 var msx = 0;
266 var msxa = 0;
267 var mousey = 0;
268 var msy = 0;
269 var msya=0;
270
271 var mouse_accel=func{
272   msx=getprop("devices/status/mice/mouse/x") or 0;
273   mousex=msx-msxa;
274   mousex*=0.5;
275   msxa=msx;
276   msy=getprop("devices/status/mice/mouse/y") or 0;
277   mousey=msya-msy;
278   mousey*=0.5;
279   msya=msy;
280 #  settimer(mouse_accel, 0);
281 }
282
283 var set_levers = func(type,num,min,max){
284   var ctrl=[];
285   var cpld=-1;
286   if(type == "throttle"){
287     ctrl = ["controls/engines/engine[0]/throttle","controls/engines/engine[1]/throttle"];
288     cpld = "controls/throttle-coupled";
289   }elsif(type == "prop"){
290     ctrl = ["controls/engines/engine[0]/propeller-pitch","controls/engines/engine[1]/propeller-pitch"];
291     cpld = "controls/prop-coupled";
292   }elsif(type == "mixture"){
293     ctrl = ["controls/engines/engine[0]/mixture","controls/engines/engine[1]/mixture"];
294     cpld ="controls/mixture-coupled";
295   }
296
297   var amnt =mousey* getprop("controls/movement-scale");
298   var ttl = getprop(ctrl[num]) + amnt;
299   if(ttl > max) ttl = max;
300   if(ttl<min)ttl=min;
301   setprop(ctrl[num],ttl);
302   if(getprop(cpld))setprop(ctrl[1-num],ttl);
303 }
304
305 ##########################################
306 # Ground Detection
307 ##########################################
308
309 var terrain_survol = func {
310   var lat = getprop("/position/latitude-deg");
311   var lon = getprop("/position/longitude-deg");
312
313   var info = geodinfo(lat, lon);
314   if (info != nil) {
315     if (info[1] != nil){
316       if (info[1].solid !=nil){
317         setprop("/environment/terrain-type",info[1].solid);
318         if( !getprop("sim/freeze/replay-state") and 
319             !info[1].solid and 
320             ((getprop("/gear/gear[0]/compression-norm") > 0.12) or 
321             (getprop("/gear/gear[1]/compression-norm") > 0.12) or 
322             (getprop("/gear/gear[2]/compression-norm") > 0.12))){
323               setprop("sim/messages/copilot", "You are on water ! Press \"p\" to continue");
324           if(!getprop("sim/freeze/clock"))
325               setprop("sim/freeze/clock", 1);
326           if(!getprop("sim/freeze/master"))
327               setprop("sim/freeze/master", 1);
328           if(!getprop("sim/freeze/clock"))
329               setprop("sim/crashed", 1);
330             }
331         else{
332           if(getprop("sim/freeze/clock"))
333               setprop("sim/freeze/clock", 0);
334           if(getprop("sim/freeze/master"))
335               setprop("sim/freeze/master", 0);
336           if(getprop("sim/freeze/clock"))
337               setprop("sim/crashed", 0);
338         }
339       }
340     }
341   }
342 }
343
344 ##############################################
345 ######### AUTOSTART / AUTOSHUTDOWN ###########
346 ##############################################
347
348 setlistener("/sim/model/start-idling", func(idle){
349     var run= idle.getBoolValue();
350     if(run){
351     Startup();
352     }else{
353     Shutdown();
354     }
355 },0,0);
356
357 var Startup = func{
358   setprop("controls/fuel/selected-tank", 1);
359   FuelValve(0);
360   settimer( func { FuelValve(180); }, 0.3);
361   setprop("controls/fuel/tank/boost-pump", 1);
362   setprop("controls/engines/engine[0]/master-alt",1);
363   setprop("/controls/engines/engine[0]/magnetos",3);
364   setprop("controls/engines/engine[0]/mixture",1);
365   setprop("/controls/gear/brake-parking",0);
366   setprop("/controls/lighting/instruments-norm",1);
367   setprop("/instrumentation/comm[0]/power-btn",1);
368   setprop("/instrumentation/comm[0]/volume",1);
369   setprop("/instrumentation/nav[0]/power-btn",1);  
370   setprop("/instrumentation/nav[0]/volume",1);
371   setprop("/instrumentation/adf[0]/power-btn",1);
372   setprop("/instrumentation/adf[0]/volume",1);
373   setprop("/instrumentation/adf[0]/volume-norm",1);
374   setprop("controls/electric/battery-switch",1);
375   setprop("controls/switches/master-avionics",1);
376 #  setprop("sim/messages/copilot", "Now press \"s\" to start engine");
377   gui.popupTip("Now press \"s\" to start engine", 8);
378 }
379
380 var Shutdown = func{
381   setprop("controls/fuel/selected-tank", -1);
382   FuelValve(0);
383   setprop("controls/engines/engine[0]/master-alt",0);
384   setprop("/controls/engines/engine[0]/magnetos",0);
385   setprop("controls/engines/engine[0]/mixture",1);
386   setprop("/engines/engine[0]/rpm",0);
387   setprop("/engines/engine[0]/running",0);
388   setprop("/controls/gear/brake-parking",1);
389   setprop("/controls/lighting/instruments-norm",0);
390   setprop("/instrumentation/comm[0]/power-btn",0);
391   setprop("/instrumentation/comm[0]/volume",0);
392   setprop("/instrumentation/nav[0]/power-btn",0);
393   setprop("/instrumentation/nav[0]/volume",0);
394   setprop("/instrumentation/adf[0]/power-btn",0);
395   setprop("/instrumentation/adf[0]/volume",0);
396   setprop("/instrumentation/adf[0]/volume-norm",0);
397   setprop("controls/electric/battery-switch",0);
398   setprop("controls/switches/master-avionics",0);
399   setprop("controls/fuel/tank/boost-pump", 0);
400   #setprop("sim/messages/copilot", "Engine is stopped");
401   gui.popupTip("Engine is stopped");
402 }
403
404
405 ############################################
406 # ELT System from Cessna337
407 # Authors: Pavel Cueto, with A LOT of collaboration from Thorsten and AndersG
408 # Adaptation by Clément de l'Hamaide and Daniel Dubreuil for DR400-dauphin
409 ############################################
410
411 var eltmsg = func {
412   var lat = getprop("/position/latitude-string");
413   var lon = getprop("/position/longitude-string");
414   var aircraft = getprop("/sim/description");
415   var callsign = getprop("/sim/multiplay/callsign");
416
417   if(getprop("/sim/damaged")){
418      if(getprop("/instrumentation/elt/armed")) {
419         var help_string = "" ~ aircraft ~ " " ~ callsign ~ "  DAMAGED, requesting SAR service";
420         screen.log.write(help_string);
421       }
422     }
423   
424     if(getprop("/sim/crashed")){
425       if(getprop("/instrumentation/elt/armed")) {
426         var help_string = "ELT AutoMessage: " ~ aircraft ~ " " ~ callsign ~ " at " ~lat~" LAT "~lon~" LON, *** CRASHED ***";
427         setprop("/sim/multiplay/chat", help_string);
428         setprop("/sim/freeze/clock", 1);
429         setprop("/sim/freeze/master", 1);
430         setprop("/sim/crashed", 0);
431         screen.log.write("Press p to resume");
432       }
433     }
434
435   settimer(eltmsg, 0);  
436 }
437
438 setlistener("/instrumentation/elt/on", func(n) {
439   if(n.getBoolValue()){
440     var lat = getprop("/position/latitude-string");
441     var lon = getprop("/position/longitude-string");
442     var aircraft = getprop("/sim/description");
443     var callsign = getprop("/sim/multiplay/callsign");
444     var help_string = "ELT AutoMessage: " ~ aircraft ~ " " ~ callsign ~ " at " ~lat~" LAT "~lon~" LON, MAYDAY, MAYDAY, MAYDAY";
445     setprop("/sim/multiplay/chat", help_string);
446   }
447 });
448   
449 setlistener("/instrumentation/elt/test", func(n) {
450   if(n.getBoolValue()){
451     var lat = getprop("/position/latitude-string");
452     var lon = getprop("/position/longitude-string");
453     var aircraft = getprop("/sim/description");
454     var callsign = getprop("/sim/multiplay/callsign");
455     var help_string = "Testing ELT: " ~ aircraft ~ " " ~ callsign ~ " at " ~lat~" LAT "~lon~" LON";
456     screen.log.write(help_string);
457   }
458 });
459
460 ############################################
461 # Global loop function
462 # If you need to run nasal as loop, add it in this function
463 ############################################
464 global_system = func{
465
466   if(getprop("/systems/electrical/outputs/starter") > 18){
467     setprop("/controls/engines/engine[0]/starter",1);
468   }else{
469     setprop("/controls/engines/engine[0]/starter",0);
470   }
471
472   if(getprop("/systems/electrical/outputs/master-avionics") > 6){
473     setprop("/instrumentation/attitude-indicator/spin",10);
474   }else{
475     setprop("/instrumentation/attitude-indicator/spin",0);
476   }
477
478   Fuel();
479   mouse_accel();
480   terrain_survol();
481   timeFormat();
482   EngineMain.update(0);
483   if(getprop("/sim/model/config/breakable-gears")){
484     dr400.physics();
485   }
486
487   settimer(global_system, 0);
488
489 }
490
491
492 ############################################
493 # Upside down system
494 ############################################
495 var timeOfNegatifG = 0;
496 upsideDown_system = func{
497   if(getprop("/sim/mode/config/simulate-g-force")){
498     if(getprop("fdm/jsbsim/accelerations/Nz") < -0.5){
499       timeOfNegatifG += 1;
500       if(timeOfNegatifG > 4){
501         setprop("controls/fuel/tank/boost-pump", 0);
502         setprop("engines/engine/fuel-pressure-psi", 0);
503         timeOfNegatifG = 0;
504       }
505     }else{
506       timeOfNegatifG = 0;
507     }
508   }
509   settimer(upsideDown_system, 1);
510 }
511
512
513 ############################################
514 # crash-detect
515 ############################################
516
517 setlistener("fdm/jsbsim/systems/crash-detect/over-g-failure", func(n){
518   if(getprop("/sim/model/config/simulate-g-force") and n.getBoolValue()){
519     if (!getprop("/sim/crashed")){
520       setprop("/sim/crashed", 1);
521     }
522   }
523 });
524
525 setlistener("fdm/jsbsim/systems/crash-detect/crashed", func(n){
526   if(getprop("/sim/model/config/enable-crash") and n.getBoolValue()){
527     if (!getprop("/sim/crashed")){
528       setprop("/sim/crashed", 1);
529     }
530   }
531 });
532
533
534 var firstEngineStartup = setlistener("/engines/engine/running", func(val) {
535   if( val.getBoolValue() ) {
536     setprop("/engines/engine/has-been-started-at-least-once", 1);
537     removelistener(firstEngineStartup);
538   }
539 });
540
541 ##########################################
542 # SetListerner must be at the end of this file
543 ##########################################
544 setlistener("/sim/signals/fdm-initialized", func{
545   setprop("/environment/terrain-type",1);
546   setprop("/environment/terrain-load-resistance",1e+30);
547   setprop("/environment/terrain-friction-factor",1.05);
548   setprop("/environment/terrain-bumpiness",0);
549   setprop("/environment/terrain-rolling-friction",0.02);
550   setprop("/instrumentation/nav[0]/power-btn",0); #force OFF
551   setprop("/instrumentation/nav[1]/power-btn",0); #force OFF
552   setprop("/instrumentation/adf[0]/power-btn",0);
553   setprop("/instrumentation/adf[0]/volume",0);
554   setprop("/instrumentation/adf[0]/volume-norm",0);
555   setprop("/controls/lighting/nav-lights", 0);
556   setprop("/controls/lighting/landing-lights", 0);
557   setprop("/controls/electric/battery-switch", 0);
558 });
559
560 var nasalInit = setlistener("/sim/signals/fdm-initialized", func{
561
562   settimer(eltmsg, 2);
563   print('Emergency Locator Transmitter (ELT) loaded');
564
565   setlistener("controls/engines/engine[0]/throttle", func(throttle){
566     interpolate("controls/engines/engine[0]/throttle-hand", 0.2, 0.5);
567     setprop("controls/engines/engine[0]/throttle-hand", throttle.getValue()-0.06);
568     settimer(func { interpolate("controls/engines/engine[0]/throttle-hand", 0, 0.4); }, 3);
569   });
570
571   settimer(global_system, 2);
572   settimer(upsideDown_system, 2);
573   removelistener(nasalInit);
574 });