The next patch should start to use http://www.flight-manuals-on-cd.com/B314.html
[fg:toms-fgdata.git] / Aircraft / Boeing314 / Nasal / Boeing314-marine.nas
1 # EXPORT : functions ending by export are called from xml
2 # CRON : functions ending by cron are called from timer
3 # SCHEDULE : functions ending by schedule are called from cron
4
5
6
7 # =================
8 # AUTOMATIC MOORING
9 # =================
10
11 Mooring = {};
12
13 Mooring.new = func {
14    var obj = { parents : [Mooring,System],
15
16                copilotcrew : nil,
17
18                anchor : Anchor.new(),
19
20                presets : nil,
21
22                MOORINGSEC : 5.0,
23                AIRPORTSEC : 3.0,
24                HARBOURSEC : 2.0,
25
26                BOATDEG : 0.0003,
27
28                APPROACHFT : 3000,
29                BOATFT : 10,                                            # crew in a boat
30                SEAFT : 0,
31            
32                DESCENTFTPS : -1.67                                     # 100 ft/min
33          };
34
35    obj.init();
36
37    return obj;
38 };
39
40 Mooring.init = func {
41    me.inherit_system("/systems/mooring");
42
43    me.presets = props.globals.getNode("/sim/presets");
44
45    me.presetseaplane();
46 }
47
48 Mooring.set_relation = func( copilot ) {
49    me.copilotcrew = copilot;
50 }
51
52 Mooring.allowedexport = func {
53    return me.anchor.allowedexport();
54 }
55
56 Mooring.schedule = func {
57    me.towerchange();
58    me.anchor.cut();
59 }
60
61 Mooring.dialogexport = func {
62    var dialog = me.itself["root"].getChild("dialog").getValue();
63    
64    # KSFO  Treasure Island ==> KSFO
65    var idcomment = split( " ", dialog );
66    var moorage = idcomment[0];
67
68    for(var i=0; i<size(me.itself["seaplane"]); i=i+1) {
69        var harbour = me.itself["seaplane"][ i ].getChild("airport-id").getValue();
70
71        if( harbour == moorage ) {
72            me.setmoorage( i, moorage );
73
74            me.dependency["tower"].setValue(moorage);
75            break;
76        }
77    }
78 }
79
80 Mooring.setmoorage = func( index, moorage ) {
81     var latitudedeg = 0.0;
82     var longitudedeg = 0.0;
83     var headingdeg = constant.DEG0;
84
85
86     # best mooring according to the wind
87     var index2 = me.findmoorage( index, constant.FALSE );
88     if( index2 >= 0 ) {
89         var location = me.itself["seaplane"][index].getChildren("location");
90
91         latitudedeg = location[ index2 ].getChild("latitude-deg").getValue();
92         longitudedeg = location[ index2 ].getChild("longitude-deg").getValue();
93         headingdeg = location[ index2 ].getChild("heading-deg").getValue();
94     }
95
96     me.setboatmoorage( index, index2, moorage );
97
98
99     # apply
100     me.presets.getChild("latitude-deg").setValue(latitudedeg);
101     me.presets.getChild("longitude-deg").setValue(longitudedeg);
102     me.presets.getChild("heading-deg").setValue(headingdeg);
103
104     # forces the computation of ground
105     me.presets.getChild("altitude-ft").setValue(-9999);
106
107     me.presets.getChild("airspeed-kt").setValue(0);
108
109     me.setadf( index, moorage );
110
111
112     # copilot feedback
113     var winddeg = me.noinstrument["wind"].getValue();
114     var crosswinddeg = constant.crosswinddeg( winddeg, headingdeg );
115     me.copilotcrew.crosswindexport( crosswinddeg );
116 }
117
118 Mooring.findmoorage = func( index, landing ) {
119     var result = -1;
120     var mooragedeg = 0;
121     var winddeg = 0.0;
122     var offsetdeg = 0.0;
123
124     var crosswinddeg = constant.DEG360;
125
126     var location = me.itself["seaplane"][index].getChildren("location");
127
128     if( me.itself["root-ctrl"].getChild("wind").getValue() or landing ) {
129         winddeg = me.noinstrument["wind"].getValue();
130
131         # boat waiting at the landing end
132         if( landing ) {
133             winddeg = winddeg + constant.DEG180;
134             if( winddeg > constant.DEG360 ) {
135                 winddeg = winddeg - constant.DEG360;
136             }
137         }
138     }
139     else {
140         winddeg = me.itself["root-ctrl"].getChild("heading-deg").getValue();
141     }
142
143
144     # best mooring according to the wind
145     for( var i=0; i<size(location); i=i+1) {
146          mooragedeg = location[ i ].getChild("heading-deg").getValue();
147          offsetdeg = constant.crosswinddeg( winddeg, mooragedeg );
148
149          if ( offsetdeg < crosswinddeg ) {
150               crosswinddeg = offsetdeg;
151               result = i;
152          }
153     }
154
155     return result;
156 }
157
158 Mooring.setadf = func( index, beacon ) {
159    if( me.itself["root-ctrl"].getChild("tower-adf").getValue() ) {
160        var frequency = 0.0;
161        var adf = me.itself["seaplane"][ index ].getNode("adf");
162
163        if( adf != nil ) {
164            frequency = adf.getChild("selected-khz");
165            if( frequency != nil ) {
166                frequencykz = frequency.getValue();
167                setprop("/instrumentation/adf/frequencies/selected-khz",frequencykz);
168            }
169            frequency = adf.getChild("standby-khz");
170            if( frequency != nil ) {
171                frequencykz = frequency.getValue();
172                setprop("/instrumentation/adf/frequencies/standby-khz",frequencykz);
173            }
174        }
175    }
176 }
177
178 Mooring.setboatmoorage = func( index, index2, tower ) {
179    if( index >= 0 ) {
180        var location = me.itself["seaplane"][ index ].getChildren("location");
181
182        var latitudedeg = location[ index2 ].getChild("latitude-deg").getValue();
183        var longitudedeg = location[ index2 ].getChild("longitude-deg").getValue();
184        var headingdeg = location[ index2 ].getChild("heading-deg").getValue();
185
186        me.setboatposition( latitudedeg, longitudedeg, headingdeg, tower );
187
188        me.setboataltitude( index );
189    }
190 }
191
192 Mooring.setboatposition = func( latitudedeg, longitudedeg, headingdeg, airport ) {
193    # behind to the right of the hull
194    latitudedeg = latitudedeg - me.BOATDEG * math.cos( headingdeg * constant.DEGTORAD );
195    longitudedeg = longitudedeg - me.BOATDEG * math.sin( headingdeg * constant.DEGTORAD );
196
197    me.dependency["boat"].getChild("latitude-deg").setValue( latitudedeg );
198    me.dependency["boat"].getChild("longitude-deg").setValue( longitudedeg );
199
200    me.itself["root"].getChild("boat-id").setValue(airport);
201 }
202
203 Mooring.setboataltitude = func( index ) {
204    if( index >= 0 ) {
205        # sea level, by default
206        var altitudeft = me.SEAFT;
207
208        # lake or river
209        if( me.itself["seaplane"][ index ].getNode("water-ft") != nil ) {
210            altitudeft = me.itself["seaplane"][ index ].getChild("water-ft").getValue();
211        }
212
213        me.setboatheight( altitudeft );
214    }
215 }
216
217 Mooring.setboatheight = func( altitudeft ) {
218    var modelft = altitudeft + me.dependency["boat"].getChild("offset-ft").getValue();
219    me.dependency["boat"].getChild("water-ft").setValue( modelft );
220
221    altitudeft = altitudeft + me.BOATFT;
222    me.dependency["boat"].getChild("altitude-ft").setValue( altitudeft );
223
224 }
225
226 # tower changed by dialog (destination or airport location)
227 Mooring.towerchange = func {
228    var change = constant.FALSE;
229    var descent = constant.FALSE;
230    var tower = me.dependency["tower"].getValue();
231
232
233    if( tower != me.itself["root"].getChild("boat-id").getValue() ) {
234        change = constant.TRUE;
235    }
236
237    elsif( me.noinstrument["agl"].getValue() < me.APPROACHFT and
238           me.noinstrument["vertical"].getValue() < me.DESCENTFTPS ) {
239        descent = constant.TRUE;
240    }
241
242
243    if( change or descent ) {
244        for(var i=0; i<size(me.itself["seaplane"]); i=i+1) {
245            var harbour = me.itself["seaplane"][ i ].getChild("airport-id").getValue();
246            if( harbour == tower ) {
247                # wind at location is changing
248                var index = me.findmoorage( i, constant.TRUE );
249
250                # boat waiting at the landing end
251                me.setboatmoorage( i, index, tower );
252
253                if( change ) {
254                    me.setadf( i, tower );
255                }
256
257                break;
258            }
259        }
260    }
261 }
262
263 # change of airport
264 Mooring.presetairport = func {
265    var airport = me.presets.getChild("airport-id").getValue();
266
267    if( airport != nil and airport != "" ) {
268        settimer(func{ me.presetseaplane(); },me.HARBOURSEC);
269    }
270
271    # unchanged
272    else {
273        settimer(func{ me.presetairport(); },me.AIRPORTSEC);
274    }
275 }
276
277 # automatic seaplane preset
278 Mooring.presetseaplane = func {
279    # wait for end of trim
280    if( getprop("/sim/sceneryloaded") ) {
281        settimer(func{ me.presetharbour(); },me.HARBOURSEC);
282    }
283
284    # wait for end of initialization
285    else {
286        settimer(func{ me.presetseaplane(); },me.HARBOURSEC);
287    }
288 }
289
290 # goes to the harbour, once one has the tower
291 Mooring.presetharbour = func {
292    if( me.itself["root-ctrl"].getChild("automatic").getValue() ) {
293        var found = constant.FALSE;
294        var airport = me.presets.getChild("airport-id").getValue();
295
296        if( airport != nil and airport != "" ) {
297            print( "searching for a moorage near ", airport );
298
299            for( var i=0; i<size(me.itself["seaplane"]); i=i+1 ) {
300                 var harbour = me.itself["seaplane"][ i ].getChild("airport-id").getValue();
301
302                 if( harbour == airport ) {
303                     me.setmoorage( i, airport );
304
305                     fgcommand("presets-commit", props.Node.new());
306
307                     # presets cuts the engines
308                     var eng = props.globals.getNode("/controls/engines");
309                     if (eng != nil) {
310                         foreach (var c; eng.getChildren("engine")) {
311                                  c.getNode("magnetos", 1).setIntValue(3);
312                         }
313                     }
314
315                     found = constant.TRUE;
316                     break;
317                 }
318            }
319        }
320
321        if( !found ) {
322            print( "no moorage found" );
323        }
324    }
325 }
326
327
328 # ======
329 # ANCHOR
330 # ======
331
332 Anchor = {};
333
334 Anchor.new = func {
335    var obj = { parents : [Anchor,System],
336
337                SPEEDFPS : 25
338              };
339
340    obj.init();
341
342    return obj;
343 };
344
345 Anchor.init = func {
346    me.inherit_system("/systems/mooring");
347
348    var park = me.dependency["rope"].getValue();
349
350    # external reaction
351    me.itself["root-ctrl"].getChild("anchor").setValue( park );
352 }
353
354 Anchor.allowedexport = func {
355     var result = constant.FALSE;
356
357     # airspeed may be greater than 15 kt at rest.
358     if( me.noinstrument["velocity"].getValue() < me.SPEEDFPS ) {
359         result = constant.TRUE;
360     }
361
362     return result;
363 }
364
365 Anchor.cut =func {
366    if( me.noinstrument["velocity"].getValue() >= me.SPEEDFPS ) {
367        if( me.dependency["rope"].getValue() ) {
368            controls.applyParkingBrake(1);
369        }
370    }
371 }