Optica.nas 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. # Edgley OA-7 Optica
  2. #
  3. # Gary Neely aka 'Buckaroo'
  4. #
  5. # Set up the livery machine
  6. aircraft.livery.init("Aircraft/Optica/Models/Liveries");
  7. # Set up screen message windows
  8. var Optica_screenmssg = screen.window.new(nil, -150, 2, 5);
  9. var Optica_screenmssg2 = screen.window.new(nil, -180, 2, 5);
  10. # Doors
  11. var Optica_door_left = aircraft.door.new("/controls/doors/left", 1);
  12. var Optica_door_right = aircraft.door.new("/controls/doors/right", 1);
  13. var Optica_doors_left = func {
  14. if (getprop("/controls/doors/left/position-norm")) { # Can always close an open door
  15. Optica_door_left.toggle();
  16. return 0;
  17. }
  18. if (getprop("/gear/gear[1]/wow")) { # At least be on the ground
  19. Optica_door_left.toggle()
  20. }
  21. else {
  22. Optica_screenmssg.fg = [1, 1, 1, 1];
  23. Optica_screenmssg.write("What, without a parachute?!");
  24. }
  25. }
  26. var Optica_doors_right = func {
  27. if (getprop("/controls/doors/right/position-norm")) {
  28. Optica_door_right.toggle();
  29. return 0;
  30. }
  31. if (getprop("/gear/gear[1]/wow")) {
  32. Optica_door_right.toggle()
  33. }
  34. else {
  35. Optica_screenmssg.fg = [1, 1, 1, 1];
  36. Optica_screenmssg.write("What, without a parachute?!");
  37. }
  38. }
  39. # Magneto and starter stuff:
  40. # Disabled keyboard engine starter message
  41. var starter_null = func {
  42. Optica_screenmssg.fg = [1, 1, 1, 1];
  43. Optica_screenmssg.write("Use the starter switch.");
  44. }
  45. var Optica_magnetos = props.globals.getNode("/engines/engine[0]/magnetos");
  46. var Optica_ignition = props.globals.getNode("/controls/switches/ignition");
  47. var Optica_starter = props.globals.getNode("/controls/engines/engine[0]/starter");
  48. #var starter_used defined in Optica_ammeter.nas
  49. var ignition_switch = func(i,j) { # i: inc/dec indicator, j: modup indicator
  50. var ign = Optica_ignition.getValue();
  51. if (j > 0) { # Are we coming off a starter try?
  52. if (ign == 4) {
  53. Optica_starter.setValue(0); # Disengage starter
  54. Optica_ignition.setValue(3); # Return ignition to 'Both' setting
  55. }
  56. return 0;
  57. }
  58. if (i > 0) { # Augmenting switch status?
  59. if (ign < 3) { # Augmenting magneto selection?
  60. controls.stepMagnetos(1);
  61. ign = ign + 1;
  62. }
  63. else { # Engage starter
  64. ign = 4;
  65. if (getprop("/systems/electrical/outputs/starter")) {
  66. Optica_starter.setValue(1);
  67. starter_used.setValue(600); # See Optica_ammeter.nas
  68. }
  69. }
  70. }
  71. else { # Decrementing switch status
  72. if (ign > 0 and ign < 5) { # Augmenting magneto selection?
  73. controls.stepMagnetos(-1);
  74. ign = ign - 1;
  75. }
  76. }
  77. Optica_ignition.setValue(ign);
  78. }
  79. # Throttle mappings:
  80. # The Optica with the Lycoming 260 HP engine is reported to have a substantial deadband in the middle
  81. # of the throttle range where there is very little throttle response. While I don't know the exact range,
  82. # I can build in an adjustable approximation to give a feel for the effect.
  83. # Mapping throttle control input to FDM output:
  84. # Modeled such that the normal range 0.3-0.7 has reduced effect
  85. var t_input = [0, 0.3, 0.7, 1];
  86. var t_output = [0, 0.3, 0.5, 1];
  87. var throttle_pos = props.globals.getNode("/controls/engines/engine[0]/throttle");
  88. var throttle_pos_fdm = props.globals.getNode("/controls/engines/engine[0]/throttle-fdm");
  89. setlistener("/controls/engines/engine[0]/throttle", func {
  90. # Find lower and upper indices for throttle position
  91. # in t_input, t1 and t2:
  92. var t1=0;
  93. var t2=1;
  94. for(var i=1; i<size(t_input); i+=1) {
  95. if (throttle_pos.getValue() <= t_input[i]) {
  96. t2 = i; t1 = i-1;
  97. break;
  98. }
  99. }
  100. # Interpolate difference of t_pos between indices and
  101. # use same interpolation in t_output:
  102. var frac = (throttle_pos.getValue() - t_input[t1]) / (t_input[t2] - t_input[t1]);
  103. throttle_pos_fdm.setValue((t_output[t2] - t_output[t1]) * frac + t_output[t1]);
  104. });
  105. # Friction thumb-wheel
  106. # In the real aircraft, this adjusts the friction on the mixture and throttle levers. Since that's not of concern
  107. # in the simulator, I use this thumb-wheel to adjust the degree of mixture adjustment between course and fine.
  108. var friction_control = props.globals.getNode("/controls/switches/friction");
  109. var mixture_setting = props.globals.getNode("/controls/engines/engine[0]/mixture");
  110. var Optica_mixture = func(i) {
  111. var delta = 0.01;
  112. if (friction_control.getValue()) { delta = 0.05; }
  113. var mixture = mixture_setting.getValue();
  114. if (i) { # Increment mixture
  115. mixture += delta;
  116. if (mixture > 1) { mixture = 1; }
  117. }
  118. else { # Decrement mixture
  119. mixture -= delta;
  120. if (mixture < 0) { mixture = 0; }
  121. }
  122. mixture_setting.setValue(mixture);
  123. }
  124. var Mixture_Report = func {
  125. var mixture = "fine";
  126. if (friction_control.getValue()) { mixture = "course"; }
  127. Optica_screenmssg.fg = [1, 1, 1, 1];
  128. Optica_screenmssg.write("Mixture adjust "~mixture~".");
  129. }
  130. # Flap switch
  131. # There are no detents in the Optica, so setting flaps is a matter of engaging a double-throw switch to
  132. # engage the electric motor that move the flaps.
  133. var flaps_pos = props.globals.getNode("/controls/flight/flaps");
  134. var flaps_sw = props.globals.getNode("/controls/switches/flaps");
  135. #var Optica_flaps = func(i) {
  136. # var flaps = flaps_pos.getValue();
  137. # if (i) { # Lower flaps
  138. # flaps += 0.01;
  139. # if (flaps > 1) { flaps = 1; }
  140. # }
  141. # else { # Raise flaps
  142. # flaps -= 0.01;
  143. # if (flaps < 0) { flaps = 0; }
  144. # }
  145. # flaps_pos.setValue(flaps);
  146. #}
  147. # Replaces the default controls.flapsDown function.
  148. controls.flapsDown = func(i) {
  149. if (i == 0) { # Center flap switch on mod-up control release
  150. flaps_sw.setValue(0);
  151. }
  152. elsif (i == 1) { # Deploy flaps
  153. flaps_sw.setValue(-1); # Switch to 'Down' position
  154. var flaps = flaps_pos.getValue(); # Increment flap position
  155. flaps += 0.01;
  156. if (flaps > 1) { flaps = 1; }
  157. flaps_pos.setValue(flaps);
  158. }
  159. else { # -1, Retract flaps
  160. flaps_sw.setValue(1); # Switch to 'Up' position
  161. var flaps = flaps_pos.getValue(); # Decrement flap position
  162. flaps -= 0.01;
  163. if (flaps < 0) { flaps = 0; }
  164. flaps_pos.setValue(flaps);
  165. }
  166. }
  167. # Stall warning based on AoA
  168. var stall_check = func {
  169. if (getprop("orientation/alpha-deg") > 13.0 and !getprop("gear/gear[1]/wow")) {
  170. setprop("sim/alarms/stall-warning",1);
  171. }
  172. else {
  173. setprop("sim/alarms/stall-warning",0);
  174. }
  175. settimer(stall_check, 0);
  176. }
  177. var sound_stuff = func {
  178. var mp = getprop("/engines/engine/mp-inhg");
  179. mp = mp * 0.0167 + 0.5; # Crude re-scaling MP value for sound;
  180. var sound_agl = getprop("position/gear-agl-m"); # For diminished engine noise as we recede from ground
  181. if (sound_agl == nil) { sound_agl = 0; }
  182. elsif (sound_agl > 15) { sound_agl = 15; } # max effect at 15m
  183. elsif (sound_agl < 0) { sound_agl = 0; }
  184. setprop("sim/Optica/sound-agl",sound_agl);
  185. sound_agl = 1 - sound_agl * 0.024; # Factor effect by .024 (0-0.36 volume reduction)
  186. var volume_engine = mp * sound_agl;
  187. if (volume_engine > 1) { volume_engine = 1; }
  188. if (volume_engine < 0) { volume_engine = 0; }
  189. setprop("sim/Optica/sound/volume-engine", volume_engine);
  190. settimer(sound_stuff, 0);
  191. }
  192. # Other stuff:
  193. # Establish which settings are saved on exit
  194. var Optica_Savedata = func {
  195. aircraft.data.add("/instrumentation/oat/mode"); # Temp reporting mode C/F
  196. }
  197. # Initialization:
  198. setlistener("/sim/signals/fdm-initialized", func {
  199. # Start the fuel system. The Optica uses a customized
  200. # fuel routine. See Optica_fuel.nas
  201. FuelInit();
  202. EngineInit(); # See Optica-engines.nas
  203. #InstrumentationInit(); # See Optica_instrumentation_drivers.nas
  204. Optica_Savedata();
  205. sound_stuff();
  206. stall_check();
  207. });
  208. # Fast start-up for testing purposes
  209. var QuickStart = func{
  210. setprop("controls/fuel/selected-tank",0);
  211. setprop("engines/engine[0]/out-of-fuel",0);
  212. setprop("controls/engines/engine[0]/magnetos",3);
  213. setprop("controls/engines/engine[0]/throttle",0);
  214. setprop("controls/engines/engine[0]/throttle-fdm",0);
  215. setprop("controls/switches/ignition",3);
  216. setprop("controls/switches/alternator",1);
  217. setprop("controls/switches/battery",1);
  218. setprop("controls/switches/fuelpump",1);
  219. setprop("engines/engine[0]/fuel-press",35);
  220. setprop("controls/engines/engine[0]/mixture",1);
  221. setprop("engines/engine[0]/rpm",900);
  222. setprop("engines/engine[0]/running",1);
  223. setprop("controls/switches/avionics",1);
  224. setprop("controls/flight/flaps",0.2);
  225. }