2012-01-02 22:27:52 +00:00
|
|
|
# RWR routines.
|
2009-05-24 12:16:08 +00:00
|
|
|
|
|
|
|
# Alexis Bory (xiii)
|
|
|
|
|
|
|
|
var OurAlt = props.globals.getNode("position/altitude-ft");
|
|
|
|
var OurHdg = props.globals.getNode("orientation/heading-deg");
|
|
|
|
var EcmOn = props.globals.getNode("instrumentation/ecm/on-off", 1);
|
|
|
|
var EcmAlert1 = props.globals.getNode("instrumentation/ecm/alert-type1", 1);
|
|
|
|
var EcmAlert2 = props.globals.getNode("instrumentation/ecm/alert-type2", 1);
|
|
|
|
|
|
|
|
var our_alt = 0;
|
|
|
|
var Mp = props.globals.getNode("ai/models");
|
|
|
|
var tgts_list = [];
|
|
|
|
var ecm_alert1 = 0;
|
|
|
|
var ecm_alert2 = 0;
|
|
|
|
var ecm_alert1_last = 0;
|
|
|
|
var ecm_alert2_last = 0;
|
|
|
|
var u_ecm_signal = 0;
|
|
|
|
var u_ecm_signal_norm = 0;
|
|
|
|
var u_radar_standby = 0;
|
|
|
|
var u_ecm_type_num = 0;
|
|
|
|
|
2012-01-02 22:27:52 +00:00
|
|
|
var launched = 0;
|
|
|
|
|
2009-05-24 12:16:08 +00:00
|
|
|
init = func() {
|
2012-01-02 22:27:52 +00:00
|
|
|
if (! launched) {
|
|
|
|
radardist.init();
|
|
|
|
settimer(rwr_loop, 0.5);
|
|
|
|
launched = 1;
|
|
|
|
}
|
2009-05-24 12:16:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Main loop ###############
|
|
|
|
var rwr_loop = func() {
|
|
|
|
ecm_on = EcmOn.getBoolValue();
|
|
|
|
if ( ecm_on) {
|
|
|
|
our_alt = OurAlt.getValue();
|
|
|
|
tgts_list = [];
|
|
|
|
var raw_list = Mp.getChildren();
|
|
|
|
foreach( var c; raw_list ) {
|
|
|
|
var type = c.getName();
|
|
|
|
if (!c.getNode("valid", 1).getValue()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var HaveRadarNode = c.getNode("radar");
|
|
|
|
if (type == "multiplayer" or type == "tanker" and HaveRadarNode != nil) {
|
|
|
|
var u = Threat.new(c);
|
|
|
|
u_ecm_signal = 0;
|
|
|
|
u_ecm_signal_norm = 0;
|
|
|
|
u_radar_standby = 0;
|
|
|
|
u_ecm_type_num = 0;
|
|
|
|
if ( u.Range != nil) {
|
|
|
|
# Test if target has a radar. Compute if we are illuminated. This propery used by ECM
|
|
|
|
# over MP, should be standardized, like "ai/models/multiplayer[0]/radar/radar-standby".
|
|
|
|
var u_name = radardist.get_aircraft_name(u.string);
|
|
|
|
var u_maxrange = radardist.my_maxrange(u_name); # in kilometer, 0 is unknown or no radar.
|
|
|
|
var horizon = u.get_horizon( our_alt );
|
|
|
|
var u_rng = u.get_range();
|
|
|
|
var u_carrier = u.check_carrier_type();
|
|
|
|
if ( u.get_rdr_standby() == 0 and u_maxrange > 0 and u_rng < horizon ) {
|
|
|
|
# Test if we are in its radar field (hard coded 74°) or if we have a MPcarrier.
|
|
|
|
# Compute the signal strength.
|
|
|
|
var our_deviation_deg = deviation_normdeg(u.get_heading(), u.get_reciprocal_bearing());
|
|
|
|
if ( our_deviation_deg < 0 ) { our_deviation_deg *= -1 }
|
|
|
|
if ( our_deviation_deg < 37 or u_carrier == 1 ) {
|
|
|
|
u_ecm_signal = (((-our_deviation_deg/20)+2.5)*(!u_carrier )) + (-u_rng/20) + 2.6 + (u_carrier*1.8);
|
|
|
|
u_ecm_type_num = radardist.get_ecm_type_num(u_name);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
u_ecm_signal = 0;
|
|
|
|
}
|
|
|
|
# Compute global threat situation for undiscriminant warning lights
|
|
|
|
# and discrete (normalized) definition of threat strength.
|
|
|
|
if ( u_ecm_signal > 1 and u_ecm_signal < 3 ) {
|
|
|
|
EcmAlert1.setBoolValue(1);
|
|
|
|
ecm_alert1 = 1;
|
|
|
|
u_ecm_signal_norm = 2;
|
|
|
|
} elsif ( u_ecm_signal >= 3 ) {
|
|
|
|
EcmAlert2.setBoolValue(1);
|
|
|
|
ecm_alert2 = 1;
|
|
|
|
u_ecm_signal_norm = 1;
|
|
|
|
}
|
|
|
|
u.EcmSignal.setValue(u_ecm_signal);
|
|
|
|
u.EcmSignalNorm.setIntValue(u_ecm_signal_norm);
|
|
|
|
u.EcmTypeNum.setIntValue(u_ecm_type_num);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Summarize ECM alerts.
|
|
|
|
if ( ecm_alert1 == 0 and ecm_alert1_last == 0 ) { EcmAlert1.setBoolValue(0) }
|
|
|
|
if ( ecm_alert2 == 0 and ecm_alert1_last == 0 ) { EcmAlert2.setBoolValue(0) }
|
|
|
|
ecm_alert1_last = ecm_alert1; # And avoid alert blinking at each loop.
|
|
|
|
ecm_alert2_last = ecm_alert2;
|
|
|
|
ecm_alert1 = 0;
|
|
|
|
ecm_alert2 = 0;
|
|
|
|
} elsif ( size(tgts_list) > 0 ) {
|
|
|
|
foreach( u; tgts_list ) {
|
|
|
|
u.EcmSignal.setValue(0);
|
|
|
|
u.EcmSignalNorm.setIntValue(0);
|
|
|
|
u.EcmTypeNum.setIntValue(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
settimer(rwr_loop, 0.05);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Utilities.
|
|
|
|
var deviation_normdeg = func(our_heading, target_bearing) {
|
|
|
|
var dev_norm = our_heading - target_bearing;
|
|
|
|
while (dev_norm < -180) dev_norm += 360;
|
|
|
|
while (dev_norm > 180) dev_norm -= 360;
|
|
|
|
return(dev_norm);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setlistener("sim/signals/fdm-initialized", init);
|
|
|
|
|
|
|
|
# Target class
|
|
|
|
var Threat = {
|
|
|
|
new : func (c) {
|
|
|
|
var obj = { parents : [Threat]};
|
|
|
|
obj.RdrProp = c.getNode("radar");
|
|
|
|
obj.Heading = c.getNode("orientation/true-heading-deg");
|
|
|
|
obj.Alt = c.getNode("position/altitude-ft");
|
|
|
|
obj.AcType = c.getNode("sim/model/ac-type");
|
|
|
|
obj.type = c.getName();
|
|
|
|
obj.index = c.getIndex();
|
|
|
|
obj.string = "ai/models/" ~ obj.type ~ "[" ~ obj.index ~ "]";
|
|
|
|
obj.shortstring = obj.type ~ "[" ~ obj.index ~ "]";
|
|
|
|
obj.InstrTgts = props.globals.getNode("instrumentation/radar2/targets", 1);
|
|
|
|
obj.TgtsFiles = obj.InstrTgts.getNode(obj.shortstring, 1);
|
|
|
|
|
|
|
|
obj.Range = obj.RdrProp.getNode("range-nm");
|
|
|
|
obj.Bearing = obj.RdrProp.getNode("bearing-deg");
|
|
|
|
obj.Elevation = obj.RdrProp.getNode("elevation-deg");
|
|
|
|
obj.BBearing = obj.TgtsFiles.getNode("bearing-deg", 1);
|
|
|
|
obj.BHeading = obj.TgtsFiles.getNode("true-heading-deg", 1);
|
|
|
|
obj.RangeScore = obj.TgtsFiles.getNode("range-score", 1);
|
|
|
|
obj.RelBearing = obj.TgtsFiles.getNode("ddd-relative-bearing", 1);
|
|
|
|
obj.Carrier = obj.TgtsFiles.getNode("carrier", 1);
|
|
|
|
obj.EcmSignal = obj.TgtsFiles.getNode("ecm-signal", 1);
|
|
|
|
obj.EcmSignalNorm = obj.TgtsFiles.getNode("ecm-signal-norm", 1);
|
|
|
|
obj.EcmTypeNum = obj.TgtsFiles.getNode("ecm_type_num", 1);
|
|
|
|
|
|
|
|
obj.RadarStandby = c.getNode("sim/multiplay/generic/int[2]");
|
|
|
|
obj.deviation = nil;
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
},
|
|
|
|
get_heading : func {
|
|
|
|
var n = me.Heading.getValue();
|
|
|
|
me.BHeading.setValue(n);
|
|
|
|
return n;
|
|
|
|
},
|
|
|
|
get_bearing : func {
|
|
|
|
var n = me.Bearing.getValue();
|
|
|
|
me.BBearing.setValue(n);
|
|
|
|
return n;
|
|
|
|
},
|
|
|
|
set_relative_bearing : func(n) {
|
|
|
|
me.RelBearing.setValue(n);
|
|
|
|
},
|
|
|
|
get_reciprocal_bearing : func {
|
|
|
|
return geo.normdeg(me.get_bearing() + 180);
|
|
|
|
},
|
|
|
|
get_deviation : func(true_heading_ref) {
|
|
|
|
me.deviation = - deviation_normdeg(true_heading_ref, me.get_bearing());
|
|
|
|
return me.deviation;
|
|
|
|
},
|
|
|
|
get_altitude : func {
|
|
|
|
return me.Alt.getValue();
|
|
|
|
},
|
|
|
|
get_range : func {
|
|
|
|
return me.Range.getValue();
|
|
|
|
},
|
|
|
|
get_horizon : func(own_alt) {
|
|
|
|
var tgt_alt = me.get_altitude();
|
|
|
|
if ( tgt_alt != nil ) {
|
|
|
|
if ( own_alt < 0 ) { own_alt = 0.001 }
|
|
|
|
if ( debug.isnan(tgt_alt)) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if ( tgt_alt < 0 ) { tgt_alt = 0.001 }
|
|
|
|
return radardist.radar_horizon( own_alt, tgt_alt );
|
|
|
|
} else {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
check_carrier_type : func {
|
|
|
|
var type = "none";
|
|
|
|
var carrier = 0;
|
|
|
|
if ( me.AcType != nil ) { type = me.AcType.getValue() }
|
|
|
|
if ( type == "MP-Nimitz" or type == "MP-Eisenhower" or type == "MP-Vinson") { carrier = 1 }
|
|
|
|
# This works only after the mp-carrier model has been loaded. Before that it is seen like a common aircraft.
|
|
|
|
me.Carrier.setBoolValue(carrier);
|
|
|
|
return carrier;
|
|
|
|
},
|
|
|
|
get_rdr_standby : func {
|
|
|
|
var s = 0;
|
|
|
|
if ( me.RadarStandby != nil ) {
|
|
|
|
s = me.RadarStandby.getValue();
|
|
|
|
if (s == nil) { s = 0 } elsif (s != 1) { s = 0 }
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
list : [],
|
|
|
|
};
|
|
|
|
|
|
|
|
|