rwr.nas 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. # RWR routines.
  2. # Alexis Bory (xiii)
  3. var OurAlt = props.globals.getNode("position/altitude-ft");
  4. var OurHdg = props.globals.getNode("orientation/heading-deg");
  5. var EcmOn = props.globals.getNode("instrumentation/ecm/on-off", 1);
  6. var EcmAlert1 = props.globals.getNode("instrumentation/ecm/alert-type1", 1);
  7. var EcmAlert2 = props.globals.getNode("instrumentation/ecm/alert-type2", 1);
  8. var our_alt = 0;
  9. var Mp = props.globals.getNode("ai/models");
  10. var tgts_list = [];
  11. var ecm_alert1 = 0;
  12. var ecm_alert2 = 0;
  13. var ecm_alert1_last = 0;
  14. var ecm_alert2_last = 0;
  15. var u_ecm_signal = 0;
  16. var u_ecm_signal_norm = 0;
  17. var u_radar_standby = 0;
  18. var u_ecm_type_num = 0;
  19. var launched = 0;
  20. init = func() {
  21. if (! launched) {
  22. radardist.init();
  23. settimer(rwr_loop, 0.5);
  24. launched = 1;
  25. }
  26. }
  27. # Main loop ###############
  28. var rwr_loop = func() {
  29. ecm_on = EcmOn.getBoolValue();
  30. if ( ecm_on) {
  31. our_alt = OurAlt.getValue();
  32. tgts_list = [];
  33. var raw_list = Mp.getChildren();
  34. foreach( var c; raw_list ) {
  35. var type = c.getName();
  36. if (!c.getNode("valid", 1).getValue()) {
  37. continue;
  38. }
  39. var HaveRadarNode = c.getNode("radar");
  40. if (type == "multiplayer" or type == "tanker" and HaveRadarNode != nil) {
  41. var u = Threat.new(c);
  42. u_ecm_signal = 0;
  43. u_ecm_signal_norm = 0;
  44. u_radar_standby = 0;
  45. u_ecm_type_num = 0;
  46. if ( u.Range != nil) {
  47. # Test if target has a radar. Compute if we are illuminated. This propery used by ECM
  48. # over MP, should be standardized, like "ai/models/multiplayer[0]/radar/radar-standby".
  49. var u_name = radardist.get_aircraft_name(u.string);
  50. var u_maxrange = radardist.my_maxrange(u_name); # in kilometer, 0 is unknown or no radar.
  51. var horizon = u.get_horizon( our_alt );
  52. var u_rng = u.get_range();
  53. var u_carrier = u.check_carrier_type();
  54. if ( u.get_rdr_standby() == 0 and u_maxrange > 0 and u_rng < horizon ) {
  55. # Test if we are in its radar field (hard coded 74°) or if we have a MPcarrier.
  56. # Compute the signal strength.
  57. var our_deviation_deg = deviation_normdeg(u.get_heading(), u.get_reciprocal_bearing());
  58. if ( our_deviation_deg < 0 ) { our_deviation_deg *= -1 }
  59. if ( our_deviation_deg < 37 or u_carrier == 1 ) {
  60. u_ecm_signal = (((-our_deviation_deg/20)+2.5)*(!u_carrier )) + (-u_rng/20) + 2.6 + (u_carrier*1.8);
  61. u_ecm_type_num = radardist.get_ecm_type_num(u_name);
  62. }
  63. } else {
  64. u_ecm_signal = 0;
  65. }
  66. # Compute global threat situation for undiscriminant warning lights
  67. # and discrete (normalized) definition of threat strength.
  68. if ( u_ecm_signal > 1 and u_ecm_signal < 3 ) {
  69. EcmAlert1.setBoolValue(1);
  70. ecm_alert1 = 1;
  71. u_ecm_signal_norm = 2;
  72. } elsif ( u_ecm_signal >= 3 ) {
  73. EcmAlert2.setBoolValue(1);
  74. ecm_alert2 = 1;
  75. u_ecm_signal_norm = 1;
  76. }
  77. u.EcmSignal.setValue(u_ecm_signal);
  78. u.EcmSignalNorm.setIntValue(u_ecm_signal_norm);
  79. u.EcmTypeNum.setIntValue(u_ecm_type_num);
  80. }
  81. }
  82. }
  83. # Summarize ECM alerts.
  84. if ( ecm_alert1 == 0 and ecm_alert1_last == 0 ) { EcmAlert1.setBoolValue(0) }
  85. if ( ecm_alert2 == 0 and ecm_alert1_last == 0 ) { EcmAlert2.setBoolValue(0) }
  86. ecm_alert1_last = ecm_alert1; # And avoid alert blinking at each loop.
  87. ecm_alert2_last = ecm_alert2;
  88. ecm_alert1 = 0;
  89. ecm_alert2 = 0;
  90. } elsif ( size(tgts_list) > 0 ) {
  91. foreach( u; tgts_list ) {
  92. u.EcmSignal.setValue(0);
  93. u.EcmSignalNorm.setIntValue(0);
  94. u.EcmTypeNum.setIntValue(0);
  95. }
  96. }
  97. settimer(rwr_loop, 0.05);
  98. }
  99. # Utilities.
  100. var deviation_normdeg = func(our_heading, target_bearing) {
  101. var dev_norm = our_heading - target_bearing;
  102. while (dev_norm < -180) dev_norm += 360;
  103. while (dev_norm > 180) dev_norm -= 360;
  104. return(dev_norm);
  105. }
  106. setlistener("sim/signals/fdm-initialized", init);
  107. # Target class
  108. var Threat = {
  109. new : func (c) {
  110. var obj = { parents : [Threat]};
  111. obj.RdrProp = c.getNode("radar");
  112. obj.Heading = c.getNode("orientation/true-heading-deg");
  113. obj.Alt = c.getNode("position/altitude-ft");
  114. obj.AcType = c.getNode("sim/model/ac-type");
  115. obj.type = c.getName();
  116. obj.index = c.getIndex();
  117. obj.string = "ai/models/" ~ obj.type ~ "[" ~ obj.index ~ "]";
  118. obj.shortstring = obj.type ~ "[" ~ obj.index ~ "]";
  119. obj.InstrTgts = props.globals.getNode("instrumentation/radar2/targets", 1);
  120. obj.TgtsFiles = obj.InstrTgts.getNode(obj.shortstring, 1);
  121. obj.Range = obj.RdrProp.getNode("range-nm");
  122. obj.Bearing = obj.RdrProp.getNode("bearing-deg");
  123. obj.Elevation = obj.RdrProp.getNode("elevation-deg");
  124. obj.BBearing = obj.TgtsFiles.getNode("bearing-deg", 1);
  125. obj.BHeading = obj.TgtsFiles.getNode("true-heading-deg", 1);
  126. obj.RangeScore = obj.TgtsFiles.getNode("range-score", 1);
  127. obj.RelBearing = obj.TgtsFiles.getNode("ddd-relative-bearing", 1);
  128. obj.Carrier = obj.TgtsFiles.getNode("carrier", 1);
  129. obj.EcmSignal = obj.TgtsFiles.getNode("ecm-signal", 1);
  130. obj.EcmSignalNorm = obj.TgtsFiles.getNode("ecm-signal-norm", 1);
  131. obj.EcmTypeNum = obj.TgtsFiles.getNode("ecm_type_num", 1);
  132. obj.RadarStandby = c.getNode("sim/multiplay/generic/int[2]");
  133. obj.deviation = nil;
  134. return obj;
  135. },
  136. get_heading : func {
  137. var n = me.Heading.getValue();
  138. me.BHeading.setValue(n);
  139. return n;
  140. },
  141. get_bearing : func {
  142. var n = me.Bearing.getValue();
  143. me.BBearing.setValue(n);
  144. return n;
  145. },
  146. set_relative_bearing : func(n) {
  147. me.RelBearing.setValue(n);
  148. },
  149. get_reciprocal_bearing : func {
  150. return geo.normdeg(me.get_bearing() + 180);
  151. },
  152. get_deviation : func(true_heading_ref) {
  153. me.deviation = - deviation_normdeg(true_heading_ref, me.get_bearing());
  154. return me.deviation;
  155. },
  156. get_altitude : func {
  157. return me.Alt.getValue();
  158. },
  159. get_range : func {
  160. return me.Range.getValue();
  161. },
  162. get_horizon : func(own_alt) {
  163. var tgt_alt = me.get_altitude();
  164. if ( tgt_alt != nil ) {
  165. if ( own_alt < 0 ) { own_alt = 0.001 }
  166. if ( debug.isnan(tgt_alt)) {
  167. return(0);
  168. }
  169. if ( tgt_alt < 0 ) { tgt_alt = 0.001 }
  170. return radardist.radar_horizon( own_alt, tgt_alt );
  171. } else {
  172. return(0);
  173. }
  174. },
  175. check_carrier_type : func {
  176. var type = "none";
  177. var carrier = 0;
  178. if ( me.AcType != nil ) { type = me.AcType.getValue() }
  179. if ( type == "MP-Nimitz" or type == "MP-Eisenhower" or type == "MP-Vinson") { carrier = 1 }
  180. # This works only after the mp-carrier model has been loaded. Before that it is seen like a common aircraft.
  181. me.Carrier.setBoolValue(carrier);
  182. return carrier;
  183. },
  184. get_rdr_standby : func {
  185. var s = 0;
  186. if ( me.RadarStandby != nil ) {
  187. s = me.RadarStandby.getValue();
  188. if (s == nil) { s = 0 } elsif (s != 1) { s = 0 }
  189. }
  190. return s;
  191. },
  192. list : [],
  193. };