mirror of
https://github.com/l0k1/oprf_assets.git
synced 2024-11-21 15:08:03 +08:00
Update shooting SAMs again :)
This commit is contained in:
parent
dd44318c9a
commit
541e7ecdd5
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -51,3 +51,33 @@ objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -678,4 +678,4 @@ var decode_point = func(aircrafts_data, callsign, str) {
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
|
@ -153,19 +153,11 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
|
||||
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
|
||||
var first_in_air_max_sec = 30;
|
||||
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
var offsetMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
offsetMethod = 1;
|
||||
}
|
||||
#var versionString = getprop("sim/version/flightgear");
|
||||
#var version = split(".", versionString);
|
||||
#var major = num(version[0]);
|
||||
#var minor = num(version[1]);
|
||||
#var pica = num(version[2]);
|
||||
|
||||
var wingedGuideFactor = 0.1;
|
||||
|
||||
@ -193,27 +185,28 @@ var contactPoint = nil;
|
||||
# get_type() - (AIR, MARINE, SURFACE or ORDNANCE)
|
||||
# getUnique() - Used when comparing 2 targets to each other and determining if they are the same target.
|
||||
# isValid() - If this target is valid
|
||||
# getElevation()
|
||||
# get_bearing()
|
||||
# get_Callsign()
|
||||
# get_range()
|
||||
# getElevation() - Pitch to target from launch vehicle
|
||||
# get_bearing() - Bearing to target from launch vehicle
|
||||
# get_Callsign()
|
||||
# get_range() - NM
|
||||
# get_Coord()
|
||||
# get_altitude()
|
||||
# get_altitude() - FT
|
||||
# get_Pitch()
|
||||
# get_Speed()
|
||||
# get_heading()
|
||||
# get_uBody()
|
||||
# get_vBody()
|
||||
# get_wBody()
|
||||
# get_uBody() - Body velocities in ft/s. Forward component.
|
||||
# get_vBody() - Right component
|
||||
# get_wBody() - Down component
|
||||
# getLastGroundTrackBlep() - Used for sample guidance
|
||||
# getFlareNode() - Used for flares.
|
||||
# getChaffNode() - Used for chaff.
|
||||
# isPainted() - Tells if this target is still being radar tracked by the launch platform, only used in semi-radar guided missiles.
|
||||
# isLaserPainted() - Tells if this target is still being tracked by the launch platform, only used by laser guided ordnance.
|
||||
# isRadiating(coord) - Tell if anti-radiation missile is hit by radiation from target. coord is the weapon position.
|
||||
# isCommandActive()
|
||||
# isSpikingMe() - Tells if the target is STT locked on launch platform.
|
||||
# isCommandActive() - If surface based launcher is still tracking (command guidance) or have a search blep (TVM) on target.
|
||||
# isVirtual() - Tells if the target is just a position, and should not be considered for damage.
|
||||
# get_closure_rate() - closure rate in kt
|
||||
# get_closure_rate() - closure rate in kt to launch platform
|
||||
|
||||
var AIM = {
|
||||
lowestETA: nil,
|
||||
@ -312,6 +305,8 @@ var AIM = {
|
||||
m.radarZ = getprop(m.nodeString~"FCS-z"); # In future I will add direction to it also, for now its center gimbal is along -x axis.
|
||||
m.expand_min = getprop(m.nodeString~"expand-min-fire-range"); # Bool. Default false. If min fire range should expand with closing rate. Mainly use this for A/A missiles.
|
||||
m.asc = getprop(m.nodeString~"attack-steering-cue-enabled");# Bool. ASC enabled.
|
||||
m.powerOnRequired = getprop(m.nodeString~"requires-power-on"); # Bool. ASC enabled.
|
||||
m.powerOnBatteryTime = getprop(m.nodeString~"power-on-battery-time"); # Seconds.
|
||||
# navigation, guiding and seekerhead
|
||||
m.max_seeker_dev = getprop(m.nodeString~"seeker-field-deg") / 2; # missiles own seekers total FOV diameter.
|
||||
m.guidance = getprop(m.nodeString~"guidance"); # heat/radar/semi-radar/tvm/laser/gps/gps-laser/vision/unguided/level/gyro-pitch/radiation/inertial/remote/remote-stable/command/sample
|
||||
@ -412,6 +407,14 @@ var AIM = {
|
||||
m.eject_speed = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnRequired == nil) {
|
||||
m.powerOnRequired = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnBatteryTime == nil) {
|
||||
m.powerOnBatteryTime = 0;# infinite
|
||||
}
|
||||
|
||||
if (m.rail_forward == 1) {
|
||||
m.rail_pitch_deg = 0;
|
||||
m.rail_head_deg = 0;
|
||||
@ -720,6 +723,7 @@ var AIM = {
|
||||
m.contacts = [];# contacts that should be considered to lock onto. In slave it will only lock to the first.
|
||||
m.warm = 1;# normalized warm/cold
|
||||
m.ready_standby_time = 0;# time when started from standby
|
||||
m.power_on_time = 0;# time when started from standby
|
||||
m.cooling = 0;
|
||||
m.slave_to_radar = m.seam_support?1:0;
|
||||
m.seeker_last_time = 0;
|
||||
@ -729,6 +733,11 @@ var AIM = {
|
||||
m.cooling_last_time = 0;
|
||||
m.cool_total_time = 0;
|
||||
|
||||
m.powerOn = 0;
|
||||
m.powerAvailable = m.powerOnBatteryTime;
|
||||
m.powerOnPassedTime = 0;
|
||||
m.powerOnLastCheck = 0;
|
||||
|
||||
#
|
||||
# Emesary damage system
|
||||
#
|
||||
@ -1351,7 +1360,11 @@ var AIM = {
|
||||
# do NOT call this after launch
|
||||
# see also release(vect)
|
||||
if (me.status == MISSILE_FLYING) return;
|
||||
me.contacts = vect;
|
||||
me.contacts = vect;
|
||||
},
|
||||
|
||||
clearTgt: func {
|
||||
me.Tgt = nil;
|
||||
},
|
||||
|
||||
commandDir: func (heading_deg, pitch_deg) {
|
||||
@ -1408,6 +1421,28 @@ var AIM = {
|
||||
return me.cooling;
|
||||
},
|
||||
|
||||
togglePowerOn: func {
|
||||
me.powerOn = !me.powerOn;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
setPowerOn: func (enable) {
|
||||
me.powerOn = enable;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
isPowerOn: func {
|
||||
return me.powerOn;
|
||||
},
|
||||
|
||||
hasPowerEnough: func {
|
||||
return !me.powerOnRequired or me.powerOnBatteryTime == 0 or me.powerAvailable > me.powerOnBatteryTime * 0.05;
|
||||
},
|
||||
|
||||
start: func {
|
||||
if (me.status == MISSILE_STANDBY) {
|
||||
me.status = MISSILE_STARTING;
|
||||
@ -1421,9 +1456,17 @@ var AIM = {
|
||||
if (me.status != MISSILE_FLYING) {
|
||||
me.status = MISSILE_STANDBY;
|
||||
#printf("stop #%3d %s", me.ID, me.type);
|
||||
if (me.guidance == "radiation") {
|
||||
me.Tgt = nil;
|
||||
me.contacts = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getStatus: func {
|
||||
return me.status;
|
||||
},
|
||||
|
||||
isCaged: func () {
|
||||
if (!me.seam_support) return me.status != MISSILE_FLYING;
|
||||
return me.caged;
|
||||
@ -1484,6 +1527,9 @@ var AIM = {
|
||||
me.elapsed_last = systime();
|
||||
me.status = MISSILE_FLYING;
|
||||
|
||||
me.powerOnLastCheck = 0;# switch to use me.life_time from elapsed sim time.
|
||||
me.powerOn = 1;# If pilot releases while power off, we make sure it on now.
|
||||
|
||||
if (vect!= nil) {
|
||||
|
||||
# sets a vector of contacts the weapons will try to lock onto
|
||||
@ -1549,7 +1595,7 @@ var AIM = {
|
||||
me.railEnd = vector.Math.plus(me.railBegin, vector.Math.product(me.rail_dist_m, me.railvec));
|
||||
}
|
||||
}
|
||||
if (offsetMethod and (!me.rail or me.rail_forward)) {
|
||||
if (!me.rail or me.rail_forward) {
|
||||
var pos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
init_coord = geo.Coord.new();
|
||||
init_coord.set_xyz(pos.x, pos.y, pos.z);
|
||||
@ -2094,6 +2140,13 @@ var AIM = {
|
||||
|
||||
me.life_time += me.dt;
|
||||
|
||||
me.consumeBattery(me.life_time);
|
||||
if (!me.hasPowerEnough()) {
|
||||
# Smart weapon reduced to dumb weapon
|
||||
me.free = 1;
|
||||
me.printStats("Ran out of battery, stopped guiding");
|
||||
}
|
||||
|
||||
me.handleMidFlightFunc();
|
||||
|
||||
if (me.hasGuided and me.maddog) {
|
||||
@ -2394,12 +2447,8 @@ var AIM = {
|
||||
# missile on rail, lets move it on the rail
|
||||
if (me.rail_forward) {
|
||||
var init_coord = nil;
|
||||
if (offsetMethod) {
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(me.x, me.y, me.z, OurPitch.getValue());
|
||||
}
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(-me.railPos[0], -me.railPos[1], me.railPos[2], OurPitch.getValue(), OurHdg.getValue());
|
||||
}
|
||||
@ -2723,8 +2772,13 @@ var AIM = {
|
||||
} else {
|
||||
me.remote_control_pitch = 0;
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] != nil) {
|
||||
if (me.settings["seeker_fov"] != nil) {
|
||||
me.max_seeker_dev = me.settings.seeker_fov;
|
||||
me.printStats("Seeker FOV switched to %s",me.max_seeker_dev);
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] == 1) {
|
||||
me.mfFunction = nil;
|
||||
me.printStats("Midflight function finished");
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2872,7 +2926,7 @@ var AIM = {
|
||||
}
|
||||
|
||||
if (!me.simple_drag) {
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.35;
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.15;
|
||||
if (mach < 1.1) {
|
||||
me.Cdi = (me.Cd_base+me.Cd_delta*me.deploy)*N;# N = normal force in G
|
||||
} else {
|
||||
@ -3337,7 +3391,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
checkForLOS: func () {
|
||||
if (pickingMethod and me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
if (me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
me.xyz = {"x":me.coord.x(), "y":me.coord.y(), "z":me.coord.z()};
|
||||
me.directionLOS = {"x":me.t_coord.x()-me.coord.x(), "y":me.t_coord.y()-me.coord.y(), "z":me.t_coord.z()-me.coord.z()};
|
||||
|
||||
@ -3456,6 +3510,10 @@ var AIM = {
|
||||
me.printStats(me.type~": Passed minimum speed for guiding after %.1f seconds. Target %d%% inside view.", me.life_time, me.normFOV*100);
|
||||
}
|
||||
}
|
||||
if (me.guidance == "gps" or me.guidance == "inertial" or me.guidance == "sample") {
|
||||
# To make sure deviation_deg is updated in midflight function.
|
||||
me.FOV_check(me.hdg, me.pitch, me.curr_deviation_h, me.curr_deviation_e, me.max_seeker_dev, me.myMath);
|
||||
}
|
||||
if (me.chaffLock and (me.guidance == "command" or me.guidance == "semi-radar" or me.guidance == "tvm") and (me.life_time - me.chaffLockTime) > (me.gnd_launch?4:6)) {
|
||||
me.chaffLock = 0;
|
||||
me.printStats(me.type~": Chaff dissipated, regained track.");
|
||||
@ -4285,7 +4343,7 @@ var AIM = {
|
||||
|
||||
notifyInFlight: func (lat,lon,alt,rdar,semiRdr,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0) {
|
||||
## thrustON cannot be named 'thrust' as FG for some reason will then think its a function (probably fixed by the way call() now is used)
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, 21+typeID);
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
if (lat != nil) {
|
||||
msg.Position.set_latlon(lat,lon,alt);
|
||||
} else {
|
||||
@ -4324,7 +4382,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
notifyHit: func (RelativeAltitude, Distance, callsign, Bearing, reason, typeID, type, self) {
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, 21+typeID);
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
msg.RelativeAltitude = RelativeAltitude;
|
||||
msg.Bearing = Bearing;
|
||||
msg.Distance = Distance;
|
||||
@ -4516,11 +4574,27 @@ var AIM = {
|
||||
}
|
||||
},
|
||||
|
||||
consumeBattery: func (curr_time) {
|
||||
if (me.powerOnRequired) {
|
||||
me.powerOnPassedTime = curr_time-me.powerOnLastCheck;
|
||||
me.powerAvailable += (me.powerOn?-1:1)*me.powerOnPassedTime;
|
||||
me.powerAvailable = math.clamp(me.powerAvailable, 0, me.powerOnBatteryTime);
|
||||
me.powerOnLastCheck = curr_time;
|
||||
}
|
||||
},
|
||||
|
||||
standby: func {
|
||||
# looping in standby mode
|
||||
if (deltaSec.getValue()==0) {
|
||||
# paused
|
||||
settimer(func me.standby(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In standby(%d)",me.status);
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4541,8 +4615,11 @@ var AIM = {
|
||||
# looping in starting mode
|
||||
#print("startup");
|
||||
if (deltaSec.getValue()==0) {
|
||||
# Paused
|
||||
settimer(func me.startup(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In startup()");
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4550,7 +4627,11 @@ var AIM = {
|
||||
me.standby();
|
||||
return;
|
||||
}
|
||||
if (me.ready_standby_time != 0 and getprop("sim/time/elapsed-sec") > (me.ready_standby_time+me.ready_time)) {
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if (me.ready_standby_time != 0 and me.hasPowerEnough() and ((!me.powerOnRequired and me.curr_time > (me.ready_standby_time+me.ready_time)) or (me.powerOnRequired and (me.powerOn and me.curr_time > me.power_on_time + me.ready_time)))) {
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.search();
|
||||
return;
|
||||
@ -4752,6 +4833,7 @@ var AIM = {
|
||||
if (deltaSec.getValue()==0) {
|
||||
settimer(func me.search(), 0.5);
|
||||
}
|
||||
me.printCode("In search()");
|
||||
if (me.deleted) {
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_FLYING ) {
|
||||
@ -4765,13 +4847,21 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_LOCK) {
|
||||
# Locked.
|
||||
me.printSearch("in search loop, but locked!");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
|
||||
|
||||
me.printSearch("searching");
|
||||
@ -5130,6 +5220,15 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
me.reset_seeker();
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (!me.Tgt.isValid()) {
|
||||
# Lost of lock due to target disapearing:
|
||||
# return to search mode.
|
||||
@ -5143,6 +5242,7 @@ var AIM = {
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
me.printSearch("lock (caged:%d slave:%d point:%s same:%d noCommon:%d)",me.caged,me.slave_to_radar,contactPoint!=nil,me.getContact() == me.Tgt,me.noCommonTarget);
|
||||
# Time interval since lock time or last track loop.
|
||||
#if (me.status == MISSILE_LOCK) {
|
||||
@ -5158,13 +5258,16 @@ var AIM = {
|
||||
me.coolingSyst();
|
||||
me.computeSeekerPos();
|
||||
if (me.status != MISSILE_STANDBY ) {#TODO: should this also check for starting up?
|
||||
me.in_view = me.check_t_in_fov();
|
||||
|
||||
if (!me.in_view) {
|
||||
me.printSearch("out of view");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
# This code does not seem needed anymore:
|
||||
#me.in_view = me.check_t_in_fov();
|
||||
#
|
||||
#if (!me.in_view) {
|
||||
# if (me.noCommonTarget and me.guidance == "radiation") me.Tgt = nil;#Hack, todo fix this
|
||||
# me.printSearch("out of view");
|
||||
# me.return_to_search();
|
||||
# return;
|
||||
#}
|
||||
|
||||
if (!me.caged or me.slave_to_radar) {
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
@ -5184,7 +5287,8 @@ var AIM = {
|
||||
# Notice: seeker_xxxx_target is used both for denoting where seeker should move towards and where the target is. In this case its the latter:
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
me.testSeeker();
|
||||
if (!me.inBeam or (me.guidance == "semi-radar" and !me.is_painted(me.Tgt))) {
|
||||
me.tagt = me.Tgt;# Used in checkForLock
|
||||
if (!me.inBeam or !me.checkForLock()) {
|
||||
me.printSearch("out of beam or no beam for fox 1");
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.Tgt = nil;
|
||||
@ -5298,6 +5402,7 @@ var AIM = {
|
||||
if (me.seeMe != nil and me.seeMe) {
|
||||
return 1;
|
||||
}
|
||||
return target.isSpikingMe();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
@ -5319,15 +5424,6 @@ var AIM = {
|
||||
me.moveSeeker();
|
||||
},
|
||||
|
||||
clamp_min_max: func (v, mm) {
|
||||
if ( v < -mm ) {
|
||||
v = -mm;
|
||||
} elsif ( v > mm ) {
|
||||
v = mm;
|
||||
}
|
||||
return(v);
|
||||
},
|
||||
|
||||
clamp: func(v, min, max) { v < min ? min : v > max ? max : v },
|
||||
|
||||
animation_flags_props: func {
|
||||
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -51,3 +51,33 @@ objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -27,7 +27,7 @@
|
||||
#i.e. change to [notifications.ArmamentInFlightNotification.new(nil), notifications.ArmamentNotification.new(nil)];
|
||||
var geoRoutedNotifications = [notifications.ArmamentInFlightNotification.new()];
|
||||
var geoBridgedTransmitter = emesary.Transmitter.new("geoOutgoingBridge");
|
||||
var geooutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("patriotmp.geo",geoRoutedNotifications, 18, "", geoBridgedTransmitter);
|
||||
var geooutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.geo",geoRoutedNotifications, 18, "", geoBridgedTransmitter);
|
||||
|
||||
# bridge should be tuned to be around 90% of the packet size full.
|
||||
geooutgoingBridge.TransmitFrequencySeconds = 0.75;
|
||||
@ -38,7 +38,7 @@ emesary_mp_bridge.IncomingMPBridge.startMPBridge(geoRoutedNotifications, 18, eme
|
||||
#----- bridge hit (armament) notifications
|
||||
var hitRoutedNotifications = [notifications.ArmamentNotification.new(),notifications.StaticNotification.new()];
|
||||
var hitBridgedTransmitter = emesary.Transmitter.new("armamentNotificationBridge");
|
||||
var hitoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("patriotmp.hit",hitRoutedNotifications, 19, "", hitBridgedTransmitter);
|
||||
var hitoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.hit",hitRoutedNotifications, 19, "", hitBridgedTransmitter);
|
||||
hitoutgoingBridge.TransmitFrequencySeconds = 1.5;
|
||||
hitoutgoingBridge.MPStringMaxLen = 120;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(hitRoutedNotifications, 19, emesary.GlobalTransmitter);
|
||||
@ -46,8 +46,38 @@ emesary_mp_bridge.IncomingMPBridge.startMPBridge(hitRoutedNotifications, 19, eme
|
||||
#----- bridge object notifications
|
||||
var objectRoutedNotifications = [notifications.ObjectInFlightNotification.new()];
|
||||
var objectBridgedTransmitter = emesary.Transmitter.new("objectNotificationBridge");
|
||||
var objectoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("patriotmp.object",objectRoutedNotifications, 17, "", objectBridgedTransmitter);
|
||||
var objectoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.object",objectRoutedNotifications, 17, "", objectBridgedTransmitter);
|
||||
objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -678,4 +678,4 @@ var decode_point = func(aircrafts_data, callsign, str) {
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
|
@ -153,19 +153,11 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
|
||||
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
|
||||
var first_in_air_max_sec = 30;
|
||||
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
var offsetMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
offsetMethod = 1;
|
||||
}
|
||||
#var versionString = getprop("sim/version/flightgear");
|
||||
#var version = split(".", versionString);
|
||||
#var major = num(version[0]);
|
||||
#var minor = num(version[1]);
|
||||
#var pica = num(version[2]);
|
||||
|
||||
var wingedGuideFactor = 0.1;
|
||||
|
||||
@ -193,27 +185,28 @@ var contactPoint = nil;
|
||||
# get_type() - (AIR, MARINE, SURFACE or ORDNANCE)
|
||||
# getUnique() - Used when comparing 2 targets to each other and determining if they are the same target.
|
||||
# isValid() - If this target is valid
|
||||
# getElevation()
|
||||
# get_bearing()
|
||||
# get_Callsign()
|
||||
# get_range()
|
||||
# getElevation() - Pitch to target from launch vehicle
|
||||
# get_bearing() - Bearing to target from launch vehicle
|
||||
# get_Callsign()
|
||||
# get_range() - NM
|
||||
# get_Coord()
|
||||
# get_altitude()
|
||||
# get_altitude() - FT
|
||||
# get_Pitch()
|
||||
# get_Speed()
|
||||
# get_heading()
|
||||
# get_uBody()
|
||||
# get_vBody()
|
||||
# get_wBody()
|
||||
# get_uBody() - Body velocities in ft/s. Forward component.
|
||||
# get_vBody() - Right component
|
||||
# get_wBody() - Down component
|
||||
# getLastGroundTrackBlep() - Used for sample guidance
|
||||
# getFlareNode() - Used for flares.
|
||||
# getChaffNode() - Used for chaff.
|
||||
# isPainted() - Tells if this target is still being radar tracked by the launch platform, only used in semi-radar guided missiles.
|
||||
# isLaserPainted() - Tells if this target is still being tracked by the launch platform, only used by laser guided ordnance.
|
||||
# isRadiating(coord) - Tell if anti-radiation missile is hit by radiation from target. coord is the weapon position.
|
||||
# isCommandActive()
|
||||
# isSpikingMe() - Tells if the target is STT locked on launch platform.
|
||||
# isCommandActive() - If surface based launcher is still tracking (command guidance) or have a search blep (TVM) on target.
|
||||
# isVirtual() - Tells if the target is just a position, and should not be considered for damage.
|
||||
# get_closure_rate() - closure rate in kt
|
||||
# get_closure_rate() - closure rate in kt to launch platform
|
||||
|
||||
var AIM = {
|
||||
lowestETA: nil,
|
||||
@ -312,6 +305,8 @@ var AIM = {
|
||||
m.radarZ = getprop(m.nodeString~"FCS-z"); # In future I will add direction to it also, for now its center gimbal is along -x axis.
|
||||
m.expand_min = getprop(m.nodeString~"expand-min-fire-range"); # Bool. Default false. If min fire range should expand with closing rate. Mainly use this for A/A missiles.
|
||||
m.asc = getprop(m.nodeString~"attack-steering-cue-enabled");# Bool. ASC enabled.
|
||||
m.powerOnRequired = getprop(m.nodeString~"requires-power-on"); # Bool. ASC enabled.
|
||||
m.powerOnBatteryTime = getprop(m.nodeString~"power-on-battery-time"); # Seconds.
|
||||
# navigation, guiding and seekerhead
|
||||
m.max_seeker_dev = getprop(m.nodeString~"seeker-field-deg") / 2; # missiles own seekers total FOV diameter.
|
||||
m.guidance = getprop(m.nodeString~"guidance"); # heat/radar/semi-radar/tvm/laser/gps/gps-laser/vision/unguided/level/gyro-pitch/radiation/inertial/remote/remote-stable/command/sample
|
||||
@ -412,6 +407,14 @@ var AIM = {
|
||||
m.eject_speed = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnRequired == nil) {
|
||||
m.powerOnRequired = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnBatteryTime == nil) {
|
||||
m.powerOnBatteryTime = 0;# infinite
|
||||
}
|
||||
|
||||
if (m.rail_forward == 1) {
|
||||
m.rail_pitch_deg = 0;
|
||||
m.rail_head_deg = 0;
|
||||
@ -720,6 +723,7 @@ var AIM = {
|
||||
m.contacts = [];# contacts that should be considered to lock onto. In slave it will only lock to the first.
|
||||
m.warm = 1;# normalized warm/cold
|
||||
m.ready_standby_time = 0;# time when started from standby
|
||||
m.power_on_time = 0;# time when started from standby
|
||||
m.cooling = 0;
|
||||
m.slave_to_radar = m.seam_support?1:0;
|
||||
m.seeker_last_time = 0;
|
||||
@ -729,6 +733,11 @@ var AIM = {
|
||||
m.cooling_last_time = 0;
|
||||
m.cool_total_time = 0;
|
||||
|
||||
m.powerOn = 0;
|
||||
m.powerAvailable = m.powerOnBatteryTime;
|
||||
m.powerOnPassedTime = 0;
|
||||
m.powerOnLastCheck = 0;
|
||||
|
||||
#
|
||||
# Emesary damage system
|
||||
#
|
||||
@ -1351,7 +1360,11 @@ var AIM = {
|
||||
# do NOT call this after launch
|
||||
# see also release(vect)
|
||||
if (me.status == MISSILE_FLYING) return;
|
||||
me.contacts = vect;
|
||||
me.contacts = vect;
|
||||
},
|
||||
|
||||
clearTgt: func {
|
||||
me.Tgt = nil;
|
||||
},
|
||||
|
||||
commandDir: func (heading_deg, pitch_deg) {
|
||||
@ -1408,6 +1421,28 @@ var AIM = {
|
||||
return me.cooling;
|
||||
},
|
||||
|
||||
togglePowerOn: func {
|
||||
me.powerOn = !me.powerOn;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
setPowerOn: func (enable) {
|
||||
me.powerOn = enable;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
isPowerOn: func {
|
||||
return me.powerOn;
|
||||
},
|
||||
|
||||
hasPowerEnough: func {
|
||||
return !me.powerOnRequired or me.powerOnBatteryTime == 0 or me.powerAvailable > me.powerOnBatteryTime * 0.05;
|
||||
},
|
||||
|
||||
start: func {
|
||||
if (me.status == MISSILE_STANDBY) {
|
||||
me.status = MISSILE_STARTING;
|
||||
@ -1421,9 +1456,17 @@ var AIM = {
|
||||
if (me.status != MISSILE_FLYING) {
|
||||
me.status = MISSILE_STANDBY;
|
||||
#printf("stop #%3d %s", me.ID, me.type);
|
||||
if (me.guidance == "radiation") {
|
||||
me.Tgt = nil;
|
||||
me.contacts = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getStatus: func {
|
||||
return me.status;
|
||||
},
|
||||
|
||||
isCaged: func () {
|
||||
if (!me.seam_support) return me.status != MISSILE_FLYING;
|
||||
return me.caged;
|
||||
@ -1484,6 +1527,9 @@ var AIM = {
|
||||
me.elapsed_last = systime();
|
||||
me.status = MISSILE_FLYING;
|
||||
|
||||
me.powerOnLastCheck = 0;# switch to use me.life_time from elapsed sim time.
|
||||
me.powerOn = 1;# If pilot releases while power off, we make sure it on now.
|
||||
|
||||
if (vect!= nil) {
|
||||
|
||||
# sets a vector of contacts the weapons will try to lock onto
|
||||
@ -1549,7 +1595,7 @@ var AIM = {
|
||||
me.railEnd = vector.Math.plus(me.railBegin, vector.Math.product(me.rail_dist_m, me.railvec));
|
||||
}
|
||||
}
|
||||
if (offsetMethod and (!me.rail or me.rail_forward)) {
|
||||
if (!me.rail or me.rail_forward) {
|
||||
var pos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
init_coord = geo.Coord.new();
|
||||
init_coord.set_xyz(pos.x, pos.y, pos.z);
|
||||
@ -2094,6 +2140,13 @@ var AIM = {
|
||||
|
||||
me.life_time += me.dt;
|
||||
|
||||
me.consumeBattery(me.life_time);
|
||||
if (!me.hasPowerEnough()) {
|
||||
# Smart weapon reduced to dumb weapon
|
||||
me.free = 1;
|
||||
me.printStats("Ran out of battery, stopped guiding");
|
||||
}
|
||||
|
||||
me.handleMidFlightFunc();
|
||||
|
||||
if (me.hasGuided and me.maddog) {
|
||||
@ -2394,12 +2447,8 @@ var AIM = {
|
||||
# missile on rail, lets move it on the rail
|
||||
if (me.rail_forward) {
|
||||
var init_coord = nil;
|
||||
if (offsetMethod) {
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(me.x, me.y, me.z, OurPitch.getValue());
|
||||
}
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(-me.railPos[0], -me.railPos[1], me.railPos[2], OurPitch.getValue(), OurHdg.getValue());
|
||||
}
|
||||
@ -2723,8 +2772,13 @@ var AIM = {
|
||||
} else {
|
||||
me.remote_control_pitch = 0;
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] != nil) {
|
||||
if (me.settings["seeker_fov"] != nil) {
|
||||
me.max_seeker_dev = me.settings.seeker_fov;
|
||||
me.printStats("Seeker FOV switched to %s",me.max_seeker_dev);
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] == 1) {
|
||||
me.mfFunction = nil;
|
||||
me.printStats("Midflight function finished");
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2872,7 +2926,7 @@ var AIM = {
|
||||
}
|
||||
|
||||
if (!me.simple_drag) {
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.35;
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.15;
|
||||
if (mach < 1.1) {
|
||||
me.Cdi = (me.Cd_base+me.Cd_delta*me.deploy)*N;# N = normal force in G
|
||||
} else {
|
||||
@ -3337,7 +3391,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
checkForLOS: func () {
|
||||
if (pickingMethod and me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
if (me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
me.xyz = {"x":me.coord.x(), "y":me.coord.y(), "z":me.coord.z()};
|
||||
me.directionLOS = {"x":me.t_coord.x()-me.coord.x(), "y":me.t_coord.y()-me.coord.y(), "z":me.t_coord.z()-me.coord.z()};
|
||||
|
||||
@ -3456,6 +3510,10 @@ var AIM = {
|
||||
me.printStats(me.type~": Passed minimum speed for guiding after %.1f seconds. Target %d%% inside view.", me.life_time, me.normFOV*100);
|
||||
}
|
||||
}
|
||||
if (me.guidance == "gps" or me.guidance == "inertial" or me.guidance == "sample") {
|
||||
# To make sure deviation_deg is updated in midflight function.
|
||||
me.FOV_check(me.hdg, me.pitch, me.curr_deviation_h, me.curr_deviation_e, me.max_seeker_dev, me.myMath);
|
||||
}
|
||||
if (me.chaffLock and (me.guidance == "command" or me.guidance == "semi-radar" or me.guidance == "tvm") and (me.life_time - me.chaffLockTime) > (me.gnd_launch?4:6)) {
|
||||
me.chaffLock = 0;
|
||||
me.printStats(me.type~": Chaff dissipated, regained track.");
|
||||
@ -4285,7 +4343,7 @@ var AIM = {
|
||||
|
||||
notifyInFlight: func (lat,lon,alt,rdar,semiRdr,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0) {
|
||||
## thrustON cannot be named 'thrust' as FG for some reason will then think its a function (probably fixed by the way call() now is used)
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, 21+typeID);
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
if (lat != nil) {
|
||||
msg.Position.set_latlon(lat,lon,alt);
|
||||
} else {
|
||||
@ -4324,7 +4382,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
notifyHit: func (RelativeAltitude, Distance, callsign, Bearing, reason, typeID, type, self) {
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, 21+typeID);
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
msg.RelativeAltitude = RelativeAltitude;
|
||||
msg.Bearing = Bearing;
|
||||
msg.Distance = Distance;
|
||||
@ -4516,11 +4574,27 @@ var AIM = {
|
||||
}
|
||||
},
|
||||
|
||||
consumeBattery: func (curr_time) {
|
||||
if (me.powerOnRequired) {
|
||||
me.powerOnPassedTime = curr_time-me.powerOnLastCheck;
|
||||
me.powerAvailable += (me.powerOn?-1:1)*me.powerOnPassedTime;
|
||||
me.powerAvailable = math.clamp(me.powerAvailable, 0, me.powerOnBatteryTime);
|
||||
me.powerOnLastCheck = curr_time;
|
||||
}
|
||||
},
|
||||
|
||||
standby: func {
|
||||
# looping in standby mode
|
||||
if (deltaSec.getValue()==0) {
|
||||
# paused
|
||||
settimer(func me.standby(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In standby(%d)",me.status);
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4541,8 +4615,11 @@ var AIM = {
|
||||
# looping in starting mode
|
||||
#print("startup");
|
||||
if (deltaSec.getValue()==0) {
|
||||
# Paused
|
||||
settimer(func me.startup(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In startup()");
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4550,7 +4627,11 @@ var AIM = {
|
||||
me.standby();
|
||||
return;
|
||||
}
|
||||
if (me.ready_standby_time != 0 and getprop("sim/time/elapsed-sec") > (me.ready_standby_time+me.ready_time)) {
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if (me.ready_standby_time != 0 and me.hasPowerEnough() and ((!me.powerOnRequired and me.curr_time > (me.ready_standby_time+me.ready_time)) or (me.powerOnRequired and (me.powerOn and me.curr_time > me.power_on_time + me.ready_time)))) {
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.search();
|
||||
return;
|
||||
@ -4752,6 +4833,7 @@ var AIM = {
|
||||
if (deltaSec.getValue()==0) {
|
||||
settimer(func me.search(), 0.5);
|
||||
}
|
||||
me.printCode("In search()");
|
||||
if (me.deleted) {
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_FLYING ) {
|
||||
@ -4765,13 +4847,21 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_LOCK) {
|
||||
# Locked.
|
||||
me.printSearch("in search loop, but locked!");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
|
||||
|
||||
me.printSearch("searching");
|
||||
@ -5130,6 +5220,15 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
me.reset_seeker();
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (!me.Tgt.isValid()) {
|
||||
# Lost of lock due to target disapearing:
|
||||
# return to search mode.
|
||||
@ -5143,6 +5242,7 @@ var AIM = {
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
me.printSearch("lock (caged:%d slave:%d point:%s same:%d noCommon:%d)",me.caged,me.slave_to_radar,contactPoint!=nil,me.getContact() == me.Tgt,me.noCommonTarget);
|
||||
# Time interval since lock time or last track loop.
|
||||
#if (me.status == MISSILE_LOCK) {
|
||||
@ -5158,13 +5258,16 @@ var AIM = {
|
||||
me.coolingSyst();
|
||||
me.computeSeekerPos();
|
||||
if (me.status != MISSILE_STANDBY ) {#TODO: should this also check for starting up?
|
||||
me.in_view = me.check_t_in_fov();
|
||||
|
||||
if (!me.in_view) {
|
||||
me.printSearch("out of view");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
# This code does not seem needed anymore:
|
||||
#me.in_view = me.check_t_in_fov();
|
||||
#
|
||||
#if (!me.in_view) {
|
||||
# if (me.noCommonTarget and me.guidance == "radiation") me.Tgt = nil;#Hack, todo fix this
|
||||
# me.printSearch("out of view");
|
||||
# me.return_to_search();
|
||||
# return;
|
||||
#}
|
||||
|
||||
if (!me.caged or me.slave_to_radar) {
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
@ -5184,7 +5287,8 @@ var AIM = {
|
||||
# Notice: seeker_xxxx_target is used both for denoting where seeker should move towards and where the target is. In this case its the latter:
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
me.testSeeker();
|
||||
if (!me.inBeam or (me.guidance == "semi-radar" and !me.is_painted(me.Tgt))) {
|
||||
me.tagt = me.Tgt;# Used in checkForLock
|
||||
if (!me.inBeam or !me.checkForLock()) {
|
||||
me.printSearch("out of beam or no beam for fox 1");
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.Tgt = nil;
|
||||
@ -5298,6 +5402,7 @@ var AIM = {
|
||||
if (me.seeMe != nil and me.seeMe) {
|
||||
return 1;
|
||||
}
|
||||
return target.isSpikingMe();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
@ -5319,15 +5424,6 @@ var AIM = {
|
||||
me.moveSeeker();
|
||||
},
|
||||
|
||||
clamp_min_max: func (v, mm) {
|
||||
if ( v < -mm ) {
|
||||
v = -mm;
|
||||
} elsif ( v > mm ) {
|
||||
v = mm;
|
||||
}
|
||||
return(v);
|
||||
},
|
||||
|
||||
clamp: func(v, min, max) { v < min ? min : v > max ? max : v },
|
||||
|
||||
animation_flags_props: func {
|
||||
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -27,18 +27,18 @@
|
||||
#i.e. change to [notifications.ArmamentInFlightNotification.new(nil), notifications.ArmamentNotification.new(nil)];
|
||||
var geoRoutedNotifications = [notifications.ArmamentInFlightNotification.new()];
|
||||
var geoBridgedTransmitter = emesary.Transmitter.new("geoOutgoingBridge");
|
||||
var geooutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("sa2mp.geo",geoRoutedNotifications, 18, "", geoBridgedTransmitter);
|
||||
var geooutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.geo",geoRoutedNotifications, 18, "", geoBridgedTransmitter);
|
||||
|
||||
# bridge should be tuned to be around 90% of the packet size full.
|
||||
geooutgoingBridge.TransmitFrequencySeconds = 0.75;
|
||||
geooutgoingBridge.MPStringMaxLen = 225;
|
||||
geooutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(geoRoutedNotifications, 18, emesary.GlobalTransmitter);
|
||||
|
||||
|
||||
#----- bridge hit (armament) notifications
|
||||
var hitRoutedNotifications = [notifications.ArmamentNotification.new(),notifications.StaticNotification.new()];
|
||||
var hitBridgedTransmitter = emesary.Transmitter.new("armamentNotificationBridge");
|
||||
var hitoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("sa2mp.hit",hitRoutedNotifications, 19, "", hitBridgedTransmitter);
|
||||
var hitoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.hit",hitRoutedNotifications, 19, "", hitBridgedTransmitter);
|
||||
hitoutgoingBridge.TransmitFrequencySeconds = 1.5;
|
||||
hitoutgoingBridge.MPStringMaxLen = 120;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(hitRoutedNotifications, 19, emesary.GlobalTransmitter);
|
||||
@ -46,8 +46,38 @@ emesary_mp_bridge.IncomingMPBridge.startMPBridge(hitRoutedNotifications, 19, eme
|
||||
#----- bridge object notifications
|
||||
var objectRoutedNotifications = [notifications.ObjectInFlightNotification.new()];
|
||||
var objectBridgedTransmitter = emesary.Transmitter.new("objectNotificationBridge");
|
||||
var objectoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("sa2mp.object",objectRoutedNotifications, 17, "", objectBridgedTransmitter);
|
||||
var objectoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.object",objectRoutedNotifications, 17, "", objectBridgedTransmitter);
|
||||
objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -678,4 +678,4 @@ var decode_point = func(aircrafts_data, callsign, str) {
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
|
@ -153,19 +153,11 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
|
||||
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
|
||||
var first_in_air_max_sec = 30;
|
||||
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
var offsetMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
offsetMethod = 1;
|
||||
}
|
||||
#var versionString = getprop("sim/version/flightgear");
|
||||
#var version = split(".", versionString);
|
||||
#var major = num(version[0]);
|
||||
#var minor = num(version[1]);
|
||||
#var pica = num(version[2]);
|
||||
|
||||
var wingedGuideFactor = 0.1;
|
||||
|
||||
@ -193,27 +185,28 @@ var contactPoint = nil;
|
||||
# get_type() - (AIR, MARINE, SURFACE or ORDNANCE)
|
||||
# getUnique() - Used when comparing 2 targets to each other and determining if they are the same target.
|
||||
# isValid() - If this target is valid
|
||||
# getElevation()
|
||||
# get_bearing()
|
||||
# get_Callsign()
|
||||
# get_range()
|
||||
# getElevation() - Pitch to target from launch vehicle
|
||||
# get_bearing() - Bearing to target from launch vehicle
|
||||
# get_Callsign()
|
||||
# get_range() - NM
|
||||
# get_Coord()
|
||||
# get_altitude()
|
||||
# get_altitude() - FT
|
||||
# get_Pitch()
|
||||
# get_Speed()
|
||||
# get_heading()
|
||||
# get_uBody()
|
||||
# get_vBody()
|
||||
# get_wBody()
|
||||
# get_uBody() - Body velocities in ft/s. Forward component.
|
||||
# get_vBody() - Right component
|
||||
# get_wBody() - Down component
|
||||
# getLastGroundTrackBlep() - Used for sample guidance
|
||||
# getFlareNode() - Used for flares.
|
||||
# getChaffNode() - Used for chaff.
|
||||
# isPainted() - Tells if this target is still being radar tracked by the launch platform, only used in semi-radar guided missiles.
|
||||
# isLaserPainted() - Tells if this target is still being tracked by the launch platform, only used by laser guided ordnance.
|
||||
# isRadiating(coord) - Tell if anti-radiation missile is hit by radiation from target. coord is the weapon position.
|
||||
# isCommandActive()
|
||||
# isSpikingMe() - Tells if the target is STT locked on launch platform.
|
||||
# isCommandActive() - If surface based launcher is still tracking (command guidance) or have a search blep (TVM) on target.
|
||||
# isVirtual() - Tells if the target is just a position, and should not be considered for damage.
|
||||
# get_closure_rate() - closure rate in kt
|
||||
# get_closure_rate() - closure rate in kt to launch platform
|
||||
|
||||
var AIM = {
|
||||
lowestETA: nil,
|
||||
@ -312,6 +305,8 @@ var AIM = {
|
||||
m.radarZ = getprop(m.nodeString~"FCS-z"); # In future I will add direction to it also, for now its center gimbal is along -x axis.
|
||||
m.expand_min = getprop(m.nodeString~"expand-min-fire-range"); # Bool. Default false. If min fire range should expand with closing rate. Mainly use this for A/A missiles.
|
||||
m.asc = getprop(m.nodeString~"attack-steering-cue-enabled");# Bool. ASC enabled.
|
||||
m.powerOnRequired = getprop(m.nodeString~"requires-power-on"); # Bool. ASC enabled.
|
||||
m.powerOnBatteryTime = getprop(m.nodeString~"power-on-battery-time"); # Seconds.
|
||||
# navigation, guiding and seekerhead
|
||||
m.max_seeker_dev = getprop(m.nodeString~"seeker-field-deg") / 2; # missiles own seekers total FOV diameter.
|
||||
m.guidance = getprop(m.nodeString~"guidance"); # heat/radar/semi-radar/tvm/laser/gps/gps-laser/vision/unguided/level/gyro-pitch/radiation/inertial/remote/remote-stable/command/sample
|
||||
@ -412,6 +407,14 @@ var AIM = {
|
||||
m.eject_speed = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnRequired == nil) {
|
||||
m.powerOnRequired = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnBatteryTime == nil) {
|
||||
m.powerOnBatteryTime = 0;# infinite
|
||||
}
|
||||
|
||||
if (m.rail_forward == 1) {
|
||||
m.rail_pitch_deg = 0;
|
||||
m.rail_head_deg = 0;
|
||||
@ -720,6 +723,7 @@ var AIM = {
|
||||
m.contacts = [];# contacts that should be considered to lock onto. In slave it will only lock to the first.
|
||||
m.warm = 1;# normalized warm/cold
|
||||
m.ready_standby_time = 0;# time when started from standby
|
||||
m.power_on_time = 0;# time when started from standby
|
||||
m.cooling = 0;
|
||||
m.slave_to_radar = m.seam_support?1:0;
|
||||
m.seeker_last_time = 0;
|
||||
@ -729,6 +733,11 @@ var AIM = {
|
||||
m.cooling_last_time = 0;
|
||||
m.cool_total_time = 0;
|
||||
|
||||
m.powerOn = 0;
|
||||
m.powerAvailable = m.powerOnBatteryTime;
|
||||
m.powerOnPassedTime = 0;
|
||||
m.powerOnLastCheck = 0;
|
||||
|
||||
#
|
||||
# Emesary damage system
|
||||
#
|
||||
@ -1351,7 +1360,11 @@ var AIM = {
|
||||
# do NOT call this after launch
|
||||
# see also release(vect)
|
||||
if (me.status == MISSILE_FLYING) return;
|
||||
me.contacts = vect;
|
||||
me.contacts = vect;
|
||||
},
|
||||
|
||||
clearTgt: func {
|
||||
me.Tgt = nil;
|
||||
},
|
||||
|
||||
commandDir: func (heading_deg, pitch_deg) {
|
||||
@ -1408,6 +1421,28 @@ var AIM = {
|
||||
return me.cooling;
|
||||
},
|
||||
|
||||
togglePowerOn: func {
|
||||
me.powerOn = !me.powerOn;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
setPowerOn: func (enable) {
|
||||
me.powerOn = enable;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
isPowerOn: func {
|
||||
return me.powerOn;
|
||||
},
|
||||
|
||||
hasPowerEnough: func {
|
||||
return !me.powerOnRequired or me.powerOnBatteryTime == 0 or me.powerAvailable > me.powerOnBatteryTime * 0.05;
|
||||
},
|
||||
|
||||
start: func {
|
||||
if (me.status == MISSILE_STANDBY) {
|
||||
me.status = MISSILE_STARTING;
|
||||
@ -1421,9 +1456,17 @@ var AIM = {
|
||||
if (me.status != MISSILE_FLYING) {
|
||||
me.status = MISSILE_STANDBY;
|
||||
#printf("stop #%3d %s", me.ID, me.type);
|
||||
if (me.guidance == "radiation") {
|
||||
me.Tgt = nil;
|
||||
me.contacts = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getStatus: func {
|
||||
return me.status;
|
||||
},
|
||||
|
||||
isCaged: func () {
|
||||
if (!me.seam_support) return me.status != MISSILE_FLYING;
|
||||
return me.caged;
|
||||
@ -1484,6 +1527,9 @@ var AIM = {
|
||||
me.elapsed_last = systime();
|
||||
me.status = MISSILE_FLYING;
|
||||
|
||||
me.powerOnLastCheck = 0;# switch to use me.life_time from elapsed sim time.
|
||||
me.powerOn = 1;# If pilot releases while power off, we make sure it on now.
|
||||
|
||||
if (vect!= nil) {
|
||||
|
||||
# sets a vector of contacts the weapons will try to lock onto
|
||||
@ -1549,7 +1595,7 @@ var AIM = {
|
||||
me.railEnd = vector.Math.plus(me.railBegin, vector.Math.product(me.rail_dist_m, me.railvec));
|
||||
}
|
||||
}
|
||||
if (offsetMethod and (!me.rail or me.rail_forward)) {
|
||||
if (!me.rail or me.rail_forward) {
|
||||
var pos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
init_coord = geo.Coord.new();
|
||||
init_coord.set_xyz(pos.x, pos.y, pos.z);
|
||||
@ -2094,6 +2140,13 @@ var AIM = {
|
||||
|
||||
me.life_time += me.dt;
|
||||
|
||||
me.consumeBattery(me.life_time);
|
||||
if (!me.hasPowerEnough()) {
|
||||
# Smart weapon reduced to dumb weapon
|
||||
me.free = 1;
|
||||
me.printStats("Ran out of battery, stopped guiding");
|
||||
}
|
||||
|
||||
me.handleMidFlightFunc();
|
||||
|
||||
if (me.hasGuided and me.maddog) {
|
||||
@ -2394,12 +2447,8 @@ var AIM = {
|
||||
# missile on rail, lets move it on the rail
|
||||
if (me.rail_forward) {
|
||||
var init_coord = nil;
|
||||
if (offsetMethod) {
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(me.x, me.y, me.z, OurPitch.getValue());
|
||||
}
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(-me.railPos[0], -me.railPos[1], me.railPos[2], OurPitch.getValue(), OurHdg.getValue());
|
||||
}
|
||||
@ -2723,8 +2772,13 @@ var AIM = {
|
||||
} else {
|
||||
me.remote_control_pitch = 0;
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] != nil) {
|
||||
if (me.settings["seeker_fov"] != nil) {
|
||||
me.max_seeker_dev = me.settings.seeker_fov;
|
||||
me.printStats("Seeker FOV switched to %s",me.max_seeker_dev);
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] == 1) {
|
||||
me.mfFunction = nil;
|
||||
me.printStats("Midflight function finished");
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2872,7 +2926,7 @@ var AIM = {
|
||||
}
|
||||
|
||||
if (!me.simple_drag) {
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.35;
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.15;
|
||||
if (mach < 1.1) {
|
||||
me.Cdi = (me.Cd_base+me.Cd_delta*me.deploy)*N;# N = normal force in G
|
||||
} else {
|
||||
@ -3337,7 +3391,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
checkForLOS: func () {
|
||||
if (pickingMethod and me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
if (me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
me.xyz = {"x":me.coord.x(), "y":me.coord.y(), "z":me.coord.z()};
|
||||
me.directionLOS = {"x":me.t_coord.x()-me.coord.x(), "y":me.t_coord.y()-me.coord.y(), "z":me.t_coord.z()-me.coord.z()};
|
||||
|
||||
@ -3456,6 +3510,10 @@ var AIM = {
|
||||
me.printStats(me.type~": Passed minimum speed for guiding after %.1f seconds. Target %d%% inside view.", me.life_time, me.normFOV*100);
|
||||
}
|
||||
}
|
||||
if (me.guidance == "gps" or me.guidance == "inertial" or me.guidance == "sample") {
|
||||
# To make sure deviation_deg is updated in midflight function.
|
||||
me.FOV_check(me.hdg, me.pitch, me.curr_deviation_h, me.curr_deviation_e, me.max_seeker_dev, me.myMath);
|
||||
}
|
||||
if (me.chaffLock and (me.guidance == "command" or me.guidance == "semi-radar" or me.guidance == "tvm") and (me.life_time - me.chaffLockTime) > (me.gnd_launch?4:6)) {
|
||||
me.chaffLock = 0;
|
||||
me.printStats(me.type~": Chaff dissipated, regained track.");
|
||||
@ -4285,7 +4343,7 @@ var AIM = {
|
||||
|
||||
notifyInFlight: func (lat,lon,alt,rdar,semiRdr,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0) {
|
||||
## thrustON cannot be named 'thrust' as FG for some reason will then think its a function (probably fixed by the way call() now is used)
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, 21+typeID);
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
if (lat != nil) {
|
||||
msg.Position.set_latlon(lat,lon,alt);
|
||||
} else {
|
||||
@ -4324,7 +4382,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
notifyHit: func (RelativeAltitude, Distance, callsign, Bearing, reason, typeID, type, self) {
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, 21+typeID);
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
msg.RelativeAltitude = RelativeAltitude;
|
||||
msg.Bearing = Bearing;
|
||||
msg.Distance = Distance;
|
||||
@ -4516,11 +4574,27 @@ var AIM = {
|
||||
}
|
||||
},
|
||||
|
||||
consumeBattery: func (curr_time) {
|
||||
if (me.powerOnRequired) {
|
||||
me.powerOnPassedTime = curr_time-me.powerOnLastCheck;
|
||||
me.powerAvailable += (me.powerOn?-1:1)*me.powerOnPassedTime;
|
||||
me.powerAvailable = math.clamp(me.powerAvailable, 0, me.powerOnBatteryTime);
|
||||
me.powerOnLastCheck = curr_time;
|
||||
}
|
||||
},
|
||||
|
||||
standby: func {
|
||||
# looping in standby mode
|
||||
if (deltaSec.getValue()==0) {
|
||||
# paused
|
||||
settimer(func me.standby(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In standby(%d)",me.status);
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4541,8 +4615,11 @@ var AIM = {
|
||||
# looping in starting mode
|
||||
#print("startup");
|
||||
if (deltaSec.getValue()==0) {
|
||||
# Paused
|
||||
settimer(func me.startup(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In startup()");
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4550,7 +4627,11 @@ var AIM = {
|
||||
me.standby();
|
||||
return;
|
||||
}
|
||||
if (me.ready_standby_time != 0 and getprop("sim/time/elapsed-sec") > (me.ready_standby_time+me.ready_time)) {
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if (me.ready_standby_time != 0 and me.hasPowerEnough() and ((!me.powerOnRequired and me.curr_time > (me.ready_standby_time+me.ready_time)) or (me.powerOnRequired and (me.powerOn and me.curr_time > me.power_on_time + me.ready_time)))) {
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.search();
|
||||
return;
|
||||
@ -4752,6 +4833,7 @@ var AIM = {
|
||||
if (deltaSec.getValue()==0) {
|
||||
settimer(func me.search(), 0.5);
|
||||
}
|
||||
me.printCode("In search()");
|
||||
if (me.deleted) {
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_FLYING ) {
|
||||
@ -4765,13 +4847,21 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_LOCK) {
|
||||
# Locked.
|
||||
me.printSearch("in search loop, but locked!");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
|
||||
|
||||
me.printSearch("searching");
|
||||
@ -5130,6 +5220,15 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
me.reset_seeker();
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (!me.Tgt.isValid()) {
|
||||
# Lost of lock due to target disapearing:
|
||||
# return to search mode.
|
||||
@ -5143,6 +5242,7 @@ var AIM = {
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
me.printSearch("lock (caged:%d slave:%d point:%s same:%d noCommon:%d)",me.caged,me.slave_to_radar,contactPoint!=nil,me.getContact() == me.Tgt,me.noCommonTarget);
|
||||
# Time interval since lock time or last track loop.
|
||||
#if (me.status == MISSILE_LOCK) {
|
||||
@ -5158,13 +5258,16 @@ var AIM = {
|
||||
me.coolingSyst();
|
||||
me.computeSeekerPos();
|
||||
if (me.status != MISSILE_STANDBY ) {#TODO: should this also check for starting up?
|
||||
me.in_view = me.check_t_in_fov();
|
||||
|
||||
if (!me.in_view) {
|
||||
me.printSearch("out of view");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
# This code does not seem needed anymore:
|
||||
#me.in_view = me.check_t_in_fov();
|
||||
#
|
||||
#if (!me.in_view) {
|
||||
# if (me.noCommonTarget and me.guidance == "radiation") me.Tgt = nil;#Hack, todo fix this
|
||||
# me.printSearch("out of view");
|
||||
# me.return_to_search();
|
||||
# return;
|
||||
#}
|
||||
|
||||
if (!me.caged or me.slave_to_radar) {
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
@ -5184,7 +5287,8 @@ var AIM = {
|
||||
# Notice: seeker_xxxx_target is used both for denoting where seeker should move towards and where the target is. In this case its the latter:
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
me.testSeeker();
|
||||
if (!me.inBeam or (me.guidance == "semi-radar" and !me.is_painted(me.Tgt))) {
|
||||
me.tagt = me.Tgt;# Used in checkForLock
|
||||
if (!me.inBeam or !me.checkForLock()) {
|
||||
me.printSearch("out of beam or no beam for fox 1");
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.Tgt = nil;
|
||||
@ -5298,6 +5402,7 @@ var AIM = {
|
||||
if (me.seeMe != nil and me.seeMe) {
|
||||
return 1;
|
||||
}
|
||||
return target.isSpikingMe();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
@ -5319,15 +5424,6 @@ var AIM = {
|
||||
me.moveSeeker();
|
||||
},
|
||||
|
||||
clamp_min_max: func (v, mm) {
|
||||
if ( v < -mm ) {
|
||||
v = -mm;
|
||||
} elsif ( v > mm ) {
|
||||
v = mm;
|
||||
}
|
||||
return(v);
|
||||
},
|
||||
|
||||
clamp: func(v, min, max) { v < min ? min : v > max ? max : v },
|
||||
|
||||
animation_flags_props: func {
|
||||
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -27,7 +27,7 @@
|
||||
#i.e. change to [notifications.ArmamentInFlightNotification.new(nil), notifications.ArmamentNotification.new(nil)];
|
||||
var geoRoutedNotifications = [notifications.ArmamentInFlightNotification.new()];
|
||||
var geoBridgedTransmitter = emesary.Transmitter.new("geoOutgoingBridge");
|
||||
var geooutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("patriotmp.geo",geoRoutedNotifications, 18, "", geoBridgedTransmitter);
|
||||
var geooutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.geo",geoRoutedNotifications, 18, "", geoBridgedTransmitter);
|
||||
|
||||
# bridge should be tuned to be around 90% of the packet size full.
|
||||
geooutgoingBridge.TransmitFrequencySeconds = 0.75;
|
||||
@ -38,7 +38,7 @@ emesary_mp_bridge.IncomingMPBridge.startMPBridge(geoRoutedNotifications, 18, eme
|
||||
#----- bridge hit (armament) notifications
|
||||
var hitRoutedNotifications = [notifications.ArmamentNotification.new(),notifications.StaticNotification.new()];
|
||||
var hitBridgedTransmitter = emesary.Transmitter.new("armamentNotificationBridge");
|
||||
var hitoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("patriotmp.hit",hitRoutedNotifications, 19, "", hitBridgedTransmitter);
|
||||
var hitoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.hit",hitRoutedNotifications, 19, "", hitBridgedTransmitter);
|
||||
hitoutgoingBridge.TransmitFrequencySeconds = 1.5;
|
||||
hitoutgoingBridge.MPStringMaxLen = 120;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(hitRoutedNotifications, 19, emesary.GlobalTransmitter);
|
||||
@ -46,8 +46,38 @@ emesary_mp_bridge.IncomingMPBridge.startMPBridge(hitRoutedNotifications, 19, eme
|
||||
#----- bridge object notifications
|
||||
var objectRoutedNotifications = [notifications.ObjectInFlightNotification.new()];
|
||||
var objectBridgedTransmitter = emesary.Transmitter.new("objectNotificationBridge");
|
||||
var objectoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("patriotmp.object",objectRoutedNotifications, 17, "", objectBridgedTransmitter);
|
||||
var objectoutgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("mp.object",objectRoutedNotifications, 17, "", objectBridgedTransmitter);
|
||||
objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -678,4 +678,4 @@ var decode_point = func(aircrafts_data, callsign, str) {
|
||||
return aircrafts_data;
|
||||
}
|
||||
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
register_extension("point", "P", ContactPoint, encode_point, decode_point);
|
||||
|
@ -153,19 +153,11 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
|
||||
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
|
||||
var first_in_air_max_sec = 30;
|
||||
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
var offsetMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
offsetMethod = 1;
|
||||
}
|
||||
#var versionString = getprop("sim/version/flightgear");
|
||||
#var version = split(".", versionString);
|
||||
#var major = num(version[0]);
|
||||
#var minor = num(version[1]);
|
||||
#var pica = num(version[2]);
|
||||
|
||||
var wingedGuideFactor = 0.1;
|
||||
|
||||
@ -193,27 +185,28 @@ var contactPoint = nil;
|
||||
# get_type() - (AIR, MARINE, SURFACE or ORDNANCE)
|
||||
# getUnique() - Used when comparing 2 targets to each other and determining if they are the same target.
|
||||
# isValid() - If this target is valid
|
||||
# getElevation()
|
||||
# get_bearing()
|
||||
# get_Callsign()
|
||||
# get_range()
|
||||
# getElevation() - Pitch to target from launch vehicle
|
||||
# get_bearing() - Bearing to target from launch vehicle
|
||||
# get_Callsign()
|
||||
# get_range() - NM
|
||||
# get_Coord()
|
||||
# get_altitude()
|
||||
# get_altitude() - FT
|
||||
# get_Pitch()
|
||||
# get_Speed()
|
||||
# get_heading()
|
||||
# get_uBody()
|
||||
# get_vBody()
|
||||
# get_wBody()
|
||||
# get_uBody() - Body velocities in ft/s. Forward component.
|
||||
# get_vBody() - Right component
|
||||
# get_wBody() - Down component
|
||||
# getLastGroundTrackBlep() - Used for sample guidance
|
||||
# getFlareNode() - Used for flares.
|
||||
# getChaffNode() - Used for chaff.
|
||||
# isPainted() - Tells if this target is still being radar tracked by the launch platform, only used in semi-radar guided missiles.
|
||||
# isLaserPainted() - Tells if this target is still being tracked by the launch platform, only used by laser guided ordnance.
|
||||
# isRadiating(coord) - Tell if anti-radiation missile is hit by radiation from target. coord is the weapon position.
|
||||
# isCommandActive()
|
||||
# isSpikingMe() - Tells if the target is STT locked on launch platform.
|
||||
# isCommandActive() - If surface based launcher is still tracking (command guidance) or have a search blep (TVM) on target.
|
||||
# isVirtual() - Tells if the target is just a position, and should not be considered for damage.
|
||||
# get_closure_rate() - closure rate in kt
|
||||
# get_closure_rate() - closure rate in kt to launch platform
|
||||
|
||||
var AIM = {
|
||||
lowestETA: nil,
|
||||
@ -312,6 +305,8 @@ var AIM = {
|
||||
m.radarZ = getprop(m.nodeString~"FCS-z"); # In future I will add direction to it also, for now its center gimbal is along -x axis.
|
||||
m.expand_min = getprop(m.nodeString~"expand-min-fire-range"); # Bool. Default false. If min fire range should expand with closing rate. Mainly use this for A/A missiles.
|
||||
m.asc = getprop(m.nodeString~"attack-steering-cue-enabled");# Bool. ASC enabled.
|
||||
m.powerOnRequired = getprop(m.nodeString~"requires-power-on"); # Bool. ASC enabled.
|
||||
m.powerOnBatteryTime = getprop(m.nodeString~"power-on-battery-time"); # Seconds.
|
||||
# navigation, guiding and seekerhead
|
||||
m.max_seeker_dev = getprop(m.nodeString~"seeker-field-deg") / 2; # missiles own seekers total FOV diameter.
|
||||
m.guidance = getprop(m.nodeString~"guidance"); # heat/radar/semi-radar/tvm/laser/gps/gps-laser/vision/unguided/level/gyro-pitch/radiation/inertial/remote/remote-stable/command/sample
|
||||
@ -412,6 +407,14 @@ var AIM = {
|
||||
m.eject_speed = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnRequired == nil) {
|
||||
m.powerOnRequired = 0;
|
||||
}
|
||||
|
||||
if (m.powerOnBatteryTime == nil) {
|
||||
m.powerOnBatteryTime = 0;# infinite
|
||||
}
|
||||
|
||||
if (m.rail_forward == 1) {
|
||||
m.rail_pitch_deg = 0;
|
||||
m.rail_head_deg = 0;
|
||||
@ -720,6 +723,7 @@ var AIM = {
|
||||
m.contacts = [];# contacts that should be considered to lock onto. In slave it will only lock to the first.
|
||||
m.warm = 1;# normalized warm/cold
|
||||
m.ready_standby_time = 0;# time when started from standby
|
||||
m.power_on_time = 0;# time when started from standby
|
||||
m.cooling = 0;
|
||||
m.slave_to_radar = m.seam_support?1:0;
|
||||
m.seeker_last_time = 0;
|
||||
@ -729,6 +733,11 @@ var AIM = {
|
||||
m.cooling_last_time = 0;
|
||||
m.cool_total_time = 0;
|
||||
|
||||
m.powerOn = 0;
|
||||
m.powerAvailable = m.powerOnBatteryTime;
|
||||
m.powerOnPassedTime = 0;
|
||||
m.powerOnLastCheck = 0;
|
||||
|
||||
#
|
||||
# Emesary damage system
|
||||
#
|
||||
@ -1351,7 +1360,11 @@ var AIM = {
|
||||
# do NOT call this after launch
|
||||
# see also release(vect)
|
||||
if (me.status == MISSILE_FLYING) return;
|
||||
me.contacts = vect;
|
||||
me.contacts = vect;
|
||||
},
|
||||
|
||||
clearTgt: func {
|
||||
me.Tgt = nil;
|
||||
},
|
||||
|
||||
commandDir: func (heading_deg, pitch_deg) {
|
||||
@ -1408,6 +1421,28 @@ var AIM = {
|
||||
return me.cooling;
|
||||
},
|
||||
|
||||
togglePowerOn: func {
|
||||
me.powerOn = !me.powerOn;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
setPowerOn: func (enable) {
|
||||
me.powerOn = enable;
|
||||
if (me.powerOn) {
|
||||
me.power_on_time = getprop("sim/time/elapsed-sec");
|
||||
}
|
||||
},
|
||||
|
||||
isPowerOn: func {
|
||||
return me.powerOn;
|
||||
},
|
||||
|
||||
hasPowerEnough: func {
|
||||
return !me.powerOnRequired or me.powerOnBatteryTime == 0 or me.powerAvailable > me.powerOnBatteryTime * 0.05;
|
||||
},
|
||||
|
||||
start: func {
|
||||
if (me.status == MISSILE_STANDBY) {
|
||||
me.status = MISSILE_STARTING;
|
||||
@ -1421,9 +1456,17 @@ var AIM = {
|
||||
if (me.status != MISSILE_FLYING) {
|
||||
me.status = MISSILE_STANDBY;
|
||||
#printf("stop #%3d %s", me.ID, me.type);
|
||||
if (me.guidance == "radiation") {
|
||||
me.Tgt = nil;
|
||||
me.contacts = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getStatus: func {
|
||||
return me.status;
|
||||
},
|
||||
|
||||
isCaged: func () {
|
||||
if (!me.seam_support) return me.status != MISSILE_FLYING;
|
||||
return me.caged;
|
||||
@ -1484,6 +1527,9 @@ var AIM = {
|
||||
me.elapsed_last = systime();
|
||||
me.status = MISSILE_FLYING;
|
||||
|
||||
me.powerOnLastCheck = 0;# switch to use me.life_time from elapsed sim time.
|
||||
me.powerOn = 1;# If pilot releases while power off, we make sure it on now.
|
||||
|
||||
if (vect!= nil) {
|
||||
|
||||
# sets a vector of contacts the weapons will try to lock onto
|
||||
@ -1549,7 +1595,7 @@ var AIM = {
|
||||
me.railEnd = vector.Math.plus(me.railBegin, vector.Math.product(me.rail_dist_m, me.railvec));
|
||||
}
|
||||
}
|
||||
if (offsetMethod and (!me.rail or me.rail_forward)) {
|
||||
if (!me.rail or me.rail_forward) {
|
||||
var pos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
init_coord = geo.Coord.new();
|
||||
init_coord.set_xyz(pos.x, pos.y, pos.z);
|
||||
@ -2094,6 +2140,13 @@ var AIM = {
|
||||
|
||||
me.life_time += me.dt;
|
||||
|
||||
me.consumeBattery(me.life_time);
|
||||
if (!me.hasPowerEnough()) {
|
||||
# Smart weapon reduced to dumb weapon
|
||||
me.free = 1;
|
||||
me.printStats("Ran out of battery, stopped guiding");
|
||||
}
|
||||
|
||||
me.handleMidFlightFunc();
|
||||
|
||||
if (me.hasGuided and me.maddog) {
|
||||
@ -2394,12 +2447,8 @@ var AIM = {
|
||||
# missile on rail, lets move it on the rail
|
||||
if (me.rail_forward) {
|
||||
var init_coord = nil;
|
||||
if (offsetMethod) {
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(me.x, me.y, me.z, OurPitch.getValue());
|
||||
}
|
||||
me.geodPos = aircraftToCart({x:-me.x, y:me.y, z: -me.z});
|
||||
me.coord.set_xyz(me.geodPos.x, me.geodPos.y, me.geodPos.z);
|
||||
} else {
|
||||
me.coord = me.getGPS(-me.railPos[0], -me.railPos[1], me.railPos[2], OurPitch.getValue(), OurHdg.getValue());
|
||||
}
|
||||
@ -2723,8 +2772,13 @@ var AIM = {
|
||||
} else {
|
||||
me.remote_control_pitch = 0;
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] != nil) {
|
||||
if (me.settings["seeker_fov"] != nil) {
|
||||
me.max_seeker_dev = me.settings.seeker_fov;
|
||||
me.printStats("Seeker FOV switched to %s",me.max_seeker_dev);
|
||||
}
|
||||
if (me.settings["abort_midflight_function"] == 1) {
|
||||
me.mfFunction = nil;
|
||||
me.printStats("Midflight function finished");
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2872,7 +2926,7 @@ var AIM = {
|
||||
}
|
||||
|
||||
if (!me.simple_drag) {
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.35;
|
||||
if (me.vector_thrust and me.thrust_lbf>0) N=N*0.15;
|
||||
if (mach < 1.1) {
|
||||
me.Cdi = (me.Cd_base+me.Cd_delta*me.deploy)*N;# N = normal force in G
|
||||
} else {
|
||||
@ -3337,7 +3391,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
checkForLOS: func () {
|
||||
if (pickingMethod and me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
if (me.guidance != "gps" and me.guidance != "gps-laser" and me.guidance != "unguided" and me.guidance != "inertial" and me.guidance != "sample") {
|
||||
me.xyz = {"x":me.coord.x(), "y":me.coord.y(), "z":me.coord.z()};
|
||||
me.directionLOS = {"x":me.t_coord.x()-me.coord.x(), "y":me.t_coord.y()-me.coord.y(), "z":me.t_coord.z()-me.coord.z()};
|
||||
|
||||
@ -3456,6 +3510,10 @@ var AIM = {
|
||||
me.printStats(me.type~": Passed minimum speed for guiding after %.1f seconds. Target %d%% inside view.", me.life_time, me.normFOV*100);
|
||||
}
|
||||
}
|
||||
if (me.guidance == "gps" or me.guidance == "inertial" or me.guidance == "sample") {
|
||||
# To make sure deviation_deg is updated in midflight function.
|
||||
me.FOV_check(me.hdg, me.pitch, me.curr_deviation_h, me.curr_deviation_e, me.max_seeker_dev, me.myMath);
|
||||
}
|
||||
if (me.chaffLock and (me.guidance == "command" or me.guidance == "semi-radar" or me.guidance == "tvm") and (me.life_time - me.chaffLockTime) > (me.gnd_launch?4:6)) {
|
||||
me.chaffLock = 0;
|
||||
me.printStats(me.type~": Chaff dissipated, regained track.");
|
||||
@ -4285,7 +4343,7 @@ var AIM = {
|
||||
|
||||
notifyInFlight: func (lat,lon,alt,rdar,semiRdr,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0) {
|
||||
## thrustON cannot be named 'thrust' as FG for some reason will then think its a function (probably fixed by the way call() now is used)
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, 21+typeID);
|
||||
var msg = notifications.ArmamentInFlightNotification.new("mfly", unique, is_deleted?damage.DESTROY:damage.MOVE, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
if (lat != nil) {
|
||||
msg.Position.set_latlon(lat,lon,alt);
|
||||
} else {
|
||||
@ -4324,7 +4382,7 @@ var AIM = {
|
||||
},
|
||||
|
||||
notifyHit: func (RelativeAltitude, Distance, callsign, Bearing, reason, typeID, type, self) {
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, 21+typeID);
|
||||
var msg = notifications.ArmamentNotification.new("mhit", 4, damage.DamageRecipient.typeID2emesaryID(typeID));
|
||||
msg.RelativeAltitude = RelativeAltitude;
|
||||
msg.Bearing = Bearing;
|
||||
msg.Distance = Distance;
|
||||
@ -4516,11 +4574,27 @@ var AIM = {
|
||||
}
|
||||
},
|
||||
|
||||
consumeBattery: func (curr_time) {
|
||||
if (me.powerOnRequired) {
|
||||
me.powerOnPassedTime = curr_time-me.powerOnLastCheck;
|
||||
me.powerAvailable += (me.powerOn?-1:1)*me.powerOnPassedTime;
|
||||
me.powerAvailable = math.clamp(me.powerAvailable, 0, me.powerOnBatteryTime);
|
||||
me.powerOnLastCheck = curr_time;
|
||||
}
|
||||
},
|
||||
|
||||
standby: func {
|
||||
# looping in standby mode
|
||||
if (deltaSec.getValue()==0) {
|
||||
# paused
|
||||
settimer(func me.standby(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In standby(%d)",me.status);
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4541,8 +4615,11 @@ var AIM = {
|
||||
# looping in starting mode
|
||||
#print("startup");
|
||||
if (deltaSec.getValue()==0) {
|
||||
# Paused
|
||||
settimer(func me.startup(), 0.5);
|
||||
return;
|
||||
}
|
||||
me.printCode("In startup()");
|
||||
if(me.seam_support and me.uncage_auto) {
|
||||
me.caged = 1;
|
||||
}
|
||||
@ -4550,7 +4627,11 @@ var AIM = {
|
||||
me.standby();
|
||||
return;
|
||||
}
|
||||
if (me.ready_standby_time != 0 and getprop("sim/time/elapsed-sec") > (me.ready_standby_time+me.ready_time)) {
|
||||
|
||||
me.curr_time = getprop("sim/time/elapsed-sec");
|
||||
me.consumeBattery(me.curr_time);
|
||||
|
||||
if (me.ready_standby_time != 0 and me.hasPowerEnough() and ((!me.powerOnRequired and me.curr_time > (me.ready_standby_time+me.ready_time)) or (me.powerOnRequired and (me.powerOn and me.curr_time > me.power_on_time + me.ready_time)))) {
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.search();
|
||||
return;
|
||||
@ -4752,6 +4833,7 @@ var AIM = {
|
||||
if (deltaSec.getValue()==0) {
|
||||
settimer(func me.search(), 0.5);
|
||||
}
|
||||
me.printCode("In search()");
|
||||
if (me.deleted) {
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_FLYING ) {
|
||||
@ -4765,13 +4847,21 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif ( me.status == MISSILE_LOCK) {
|
||||
# Locked.
|
||||
me.printSearch("in search loop, but locked!");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
|
||||
|
||||
me.printSearch("searching");
|
||||
@ -5130,6 +5220,15 @@ var AIM = {
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (me.powerOnRequired and (!me.powerOn or (me.powerOnBatteryTime > 0 and me.powerAvailable < me.powerOnBatteryTime * 0.05))) {
|
||||
me.status = MISSILE_STARTING;
|
||||
me.reset_seeker();
|
||||
# Stand by.
|
||||
me.SwSoundVol.setDoubleValue(0);
|
||||
me.SwSoundOnOff.setBoolValue(0);
|
||||
#me.trackWeak = 1;
|
||||
me.standby();
|
||||
return;
|
||||
} elsif (!me.Tgt.isValid()) {
|
||||
# Lost of lock due to target disapearing:
|
||||
# return to search mode.
|
||||
@ -5143,6 +5242,7 @@ var AIM = {
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
me.consumeBattery(getprop("sim/time/elapsed-sec"));
|
||||
me.printSearch("lock (caged:%d slave:%d point:%s same:%d noCommon:%d)",me.caged,me.slave_to_radar,contactPoint!=nil,me.getContact() == me.Tgt,me.noCommonTarget);
|
||||
# Time interval since lock time or last track loop.
|
||||
#if (me.status == MISSILE_LOCK) {
|
||||
@ -5158,13 +5258,16 @@ var AIM = {
|
||||
me.coolingSyst();
|
||||
me.computeSeekerPos();
|
||||
if (me.status != MISSILE_STANDBY ) {#TODO: should this also check for starting up?
|
||||
me.in_view = me.check_t_in_fov();
|
||||
|
||||
if (!me.in_view) {
|
||||
me.printSearch("out of view");
|
||||
me.return_to_search();
|
||||
return;
|
||||
}
|
||||
# This code does not seem needed anymore:
|
||||
#me.in_view = me.check_t_in_fov();
|
||||
#
|
||||
#if (!me.in_view) {
|
||||
# if (me.noCommonTarget and me.guidance == "radiation") me.Tgt = nil;#Hack, todo fix this
|
||||
# me.printSearch("out of view");
|
||||
# me.return_to_search();
|
||||
# return;
|
||||
#}
|
||||
|
||||
if (!me.caged or me.slave_to_radar) {
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
@ -5184,7 +5287,8 @@ var AIM = {
|
||||
# Notice: seeker_xxxx_target is used both for denoting where seeker should move towards and where the target is. In this case its the latter:
|
||||
me.convertGlobalToSeekerViewDirection(me.Tgt.get_bearing(), me.Tgt.getElevation(), OurHdg.getValue(), OurPitch.getValue(), OurRoll.getValue());
|
||||
me.testSeeker();
|
||||
if (!me.inBeam or (me.guidance == "semi-radar" and !me.is_painted(me.Tgt))) {
|
||||
me.tagt = me.Tgt;# Used in checkForLock
|
||||
if (!me.inBeam or !me.checkForLock()) {
|
||||
me.printSearch("out of beam or no beam for fox 1");
|
||||
me.status = MISSILE_SEARCH;
|
||||
me.Tgt = nil;
|
||||
@ -5298,6 +5402,7 @@ var AIM = {
|
||||
if (me.seeMe != nil and me.seeMe) {
|
||||
return 1;
|
||||
}
|
||||
return target.isSpikingMe();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
@ -5319,15 +5424,6 @@ var AIM = {
|
||||
me.moveSeeker();
|
||||
},
|
||||
|
||||
clamp_min_max: func (v, mm) {
|
||||
if ( v < -mm ) {
|
||||
v = -mm;
|
||||
} elsif ( v > mm ) {
|
||||
v = mm;
|
||||
}
|
||||
return(v);
|
||||
},
|
||||
|
||||
clamp: func(v, min, max) { v < min ? min : v > max ? max : v },
|
||||
|
||||
animation_flags_props: func {
|
||||
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -51,3 +51,33 @@ objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -51,3 +51,33 @@ objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -1,427 +1,427 @@
|
||||
var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
|
||||
var encode3bits = func(first, second, third) {
|
||||
var integer = first;
|
||||
integer = integer + 2 * second;
|
||||
integer = integer + 4 * third;
|
||||
return integer;
|
||||
}
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
|
||||
var AIR = 0;
|
||||
var MARINE = 1;
|
||||
var SURFACE = 2;
|
||||
var ORDNANCE = 3;
|
||||
|
||||
var Contact = {
|
||||
# For now only used in guided missiles, to make it compatible with Mirage 2000-5.
|
||||
new: func(c, class) {
|
||||
var obj = { parents : [Contact]};
|
||||
#debug.benchmark("radar process1", func {
|
||||
obj.rdrProp = c.getNode("radar");
|
||||
obj.oriProp = c.getNode("orientation");
|
||||
obj.velProp = c.getNode("velocities");
|
||||
obj.posProp = c.getNode("position");
|
||||
obj.heading = obj.oriProp.getNode("true-heading-deg");
|
||||
#});
|
||||
#debug.benchmark("radar process2", func {
|
||||
obj.alt = obj.posProp.getNode("altitude-ft");
|
||||
obj.lat = obj.posProp.getNode("latitude-deg");
|
||||
obj.lon = obj.posProp.getNode("longitude-deg");
|
||||
#});
|
||||
#debug.benchmark("radar process3", func {
|
||||
#As it is a geo.Coord object, we have to update lat/lon/alt ->and alt is in meters
|
||||
obj.coord = geo.Coord.new();
|
||||
obj.coord.set_latlon(obj.lat.getValue(), obj.lon.getValue(), obj.alt.getValue() * FT2M);
|
||||
#});
|
||||
#debug.benchmark("radar process4", func {
|
||||
obj.pitch = obj.oriProp.getNode("pitch-deg");
|
||||
obj.roll = obj.oriProp.getNode("roll-deg");
|
||||
obj.speed = obj.velProp.getNode("true-airspeed-kt");
|
||||
obj.vSpeed = obj.velProp.getNode("vertical-speed-fps");
|
||||
obj.callsign = c.getNode("callsign", 1);
|
||||
obj.shorter = c.getNode("model-shorter");
|
||||
obj.orig_callsign = obj.callsign.getValue();
|
||||
obj.name = c.getNode("name");
|
||||
obj.sign = c.getNode("sign",1);
|
||||
obj.valid = c.getNode("valid");
|
||||
obj.painted = c.getNode("painted");
|
||||
obj.unique = c.getNode("unique");
|
||||
obj.validTree = 0;
|
||||
#});
|
||||
#debug.benchmark("radar process5", func {
|
||||
#obj.transponderID = c.getNode("instrumentation/transponder/transmitted-id");
|
||||
#});
|
||||
#debug.benchmark("radar process6", func {
|
||||
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 ~ "]";
|
||||
#});
|
||||
#debug.benchmark("radar process7", func {
|
||||
obj.range = obj.rdrProp.getNode("range-nm");
|
||||
obj.bearing = obj.rdrProp.getNode("bearing-deg");
|
||||
obj.elevation = obj.rdrProp.getNode("elevation-deg");
|
||||
obj.ubody = obj.rdrProp.getNode("velocities/uBody-fps");
|
||||
obj.vbody = obj.rdrProp.getNode("velocities/vBody-fps");
|
||||
obj.wbody = obj.rdrProp.getNode("velocities/wBody-fps");
|
||||
#});
|
||||
obj.deviation = nil;
|
||||
|
||||
obj.node = c;
|
||||
obj.class = class;
|
||||
|
||||
obj.polar = [0,0];
|
||||
obj.cartesian = [0,0];
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
get_uBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.ubody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = me.get_Speed()*KT2FPS;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
get_vBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.vbody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = 0;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
get_wBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.wbody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = 0;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
isValid: func () {
|
||||
var valid = me.valid.getValue();
|
||||
if (valid == nil) {
|
||||
valid = 0;
|
||||
}
|
||||
if (me.callsign.getValue() != me.orig_callsign) {
|
||||
valid = 0;
|
||||
}
|
||||
return valid;
|
||||
},
|
||||
|
||||
isPainted: func () {
|
||||
if (getprop("/carrier/sunk") == 1) {
|
||||
return 0;
|
||||
}
|
||||
return isNotBehindTerrain(me.node)[0];
|
||||
},
|
||||
|
||||
isCommandActive: func {
|
||||
if (getprop("/carrier/sunk") == 1) {
|
||||
return 0;
|
||||
}
|
||||
return isNotBehindTerrain(me.node)[0];
|
||||
},
|
||||
|
||||
getUnique: func () {
|
||||
if (me.unique == nil) {
|
||||
me.unique = me.node.getNode("unique");
|
||||
}
|
||||
if (me.unique == nil) {
|
||||
return nil;
|
||||
}
|
||||
var u = me.unique.getValue();
|
||||
return u;
|
||||
},
|
||||
|
||||
getElevation: func() {
|
||||
var e = 0;
|
||||
e = me.elevation.getValue();
|
||||
if(e == nil or e == 0) {
|
||||
# AI/MP has no radar properties
|
||||
var self = geo.aircraft_position();
|
||||
self.set_alt(self.alt()+fire_control.radar_elevation_above_terrain_m);
|
||||
me.get_Coord();
|
||||
var angleInv = clamp(self.distance_to(me.coord)/self.direct_distance_to(me.coord), -1, 1);
|
||||
e = (self.alt()>me.coord.alt()?-1:1)*math.acos(angleInv)*R2D;
|
||||
}
|
||||
return e;
|
||||
},
|
||||
|
||||
getNode: func () {
|
||||
return me.node;
|
||||
},
|
||||
|
||||
getFlareNode: func () {
|
||||
return me.node.getNode("rotors/main/blade[3]/flap-deg");
|
||||
},
|
||||
|
||||
getChaffNode: func () {
|
||||
return me.node.getNode("rotors/main/blade[3]/position-deg");
|
||||
},
|
||||
|
||||
setPolar: func(dist, angle) {
|
||||
me.polar = [dist,angle];
|
||||
},
|
||||
|
||||
setCartesian: func(x, y) {
|
||||
me.cartesian = [x,y];
|
||||
},
|
||||
|
||||
remove: func(){
|
||||
if(me.validTree != 0){
|
||||
me.validTree.setValue(0);
|
||||
}
|
||||
},
|
||||
|
||||
get_Coord: func(){
|
||||
me.coord.set_latlon(me.lat.getValue(), me.lon.getValue(), me.alt.getValue() * FT2M);
|
||||
var TgTCoord = geo.Coord.new(me.coord);
|
||||
return TgTCoord;
|
||||
},
|
||||
|
||||
get_Callsign: func(){
|
||||
var n = me.callsign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
if (me.name == nil) {
|
||||
me.name = me.getNode().getNode("name");
|
||||
}
|
||||
if (me.name == nil) {
|
||||
n = "";
|
||||
} else {
|
||||
n = me.name.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
n = me.sign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
return "UFO";
|
||||
},
|
||||
|
||||
get_model: func(){
|
||||
var n = "";
|
||||
if (me.shorter == nil) {
|
||||
me.shorter = me.node.getNode("model-shorter");
|
||||
}
|
||||
if (me.shorter != nil) {
|
||||
n = me.shorter.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
n = me.sign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
if (me.name == nil) {
|
||||
me.name = me.getNode().getNode("name");
|
||||
}
|
||||
if (me.name == nil) {
|
||||
n = "";
|
||||
} else {
|
||||
n = me.name.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
return me.get_Callsign();
|
||||
},
|
||||
|
||||
get_Speed: func(){
|
||||
# return true airspeed
|
||||
var n = me.speed.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Longitude: func(){
|
||||
var n = me.lon.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Latitude: func(){
|
||||
var n = me.lat.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Pitch: func(){
|
||||
var n = me.pitch.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
isVirtual: func(){
|
||||
return 0;
|
||||
},
|
||||
|
||||
get_Roll: func(){
|
||||
var n = me.roll.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_heading : func(){
|
||||
var n = me.heading.getValue();
|
||||
if(n == nil)
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
get_bearing: func(){
|
||||
var n = 0;
|
||||
n = me.bearing.getValue();
|
||||
if(n == nil or n == 0) {
|
||||
# AI/MP has no radar properties
|
||||
n = me.get_bearing_from_Coord(geo.aircraft_position());
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
get_bearing_from_Coord: func(MyAircraftCoord){
|
||||
me.get_Coord();
|
||||
var myBearing = 0;
|
||||
if(me.coord.is_defined()) {
|
||||
myBearing = MyAircraftCoord.course_to(me.coord);
|
||||
}
|
||||
return myBearing;
|
||||
},
|
||||
|
||||
get_reciprocal_bearing: func(){
|
||||
return geo.normdeg(me.get_bearing() + 180);
|
||||
},
|
||||
|
||||
get_deviation: func(true_heading_ref, coord){
|
||||
me.deviation = - deviation_normdeg(true_heading_ref, me.get_bearing_from_Coord(coord));
|
||||
return me.deviation;
|
||||
},
|
||||
|
||||
get_altitude: func(){
|
||||
#Return Alt in feet
|
||||
return me.alt.getValue();
|
||||
},
|
||||
|
||||
get_Elevation_from_Coord: func(MyAircraftCoord) {
|
||||
me.get_Coord();
|
||||
var value = (me.coord.alt() - MyAircraftCoord.alt()) / me.coord.direct_distance_to(MyAircraftCoord);
|
||||
if (math.abs(value) > 1) {
|
||||
# warning this else will fail if logged in as observer and see aircraft on other side of globe
|
||||
return 0;
|
||||
}
|
||||
var myPitch = math.asin(value) * R2D;
|
||||
return myPitch;
|
||||
},
|
||||
|
||||
get_total_elevation_from_Coord: func(own_pitch, MyAircraftCoord){
|
||||
var myTotalElevation = - deviation_normdeg(own_pitch, me.get_Elevation_from_Coord(MyAircraftCoord));
|
||||
return myTotalElevation;
|
||||
},
|
||||
|
||||
get_total_elevation: func(own_pitch) {
|
||||
me.deviation = - deviation_normdeg(own_pitch, me.getElevation());
|
||||
return me.deviation;
|
||||
},
|
||||
|
||||
get_range: func() {
|
||||
var r = 0;
|
||||
if(me.range == nil or me.range.getValue() == nil or me.range.getValue() == 0) {
|
||||
# AI/MP has no radar properties
|
||||
me.get_Coord();
|
||||
r = me.coord.direct_distance_to(geo.aircraft_position()) * M2NM;
|
||||
} else {
|
||||
r = me.range.getValue();
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
get_range_from_Coord: func(MyAircraftCoord) {
|
||||
var myCoord = me.get_Coord();
|
||||
var myDistance = 0;
|
||||
if(myCoord.is_defined()) {
|
||||
myDistance = MyAircraftCoord.direct_distance_to(myCoord) * M2NM;
|
||||
}
|
||||
return myDistance;
|
||||
},
|
||||
|
||||
get_type: func () {
|
||||
return me.class;
|
||||
},
|
||||
|
||||
get_cartesian: func() {
|
||||
return me.cartesian;
|
||||
},
|
||||
|
||||
get_polar: func() {
|
||||
return me.polar;
|
||||
},
|
||||
};
|
||||
|
||||
var isNotBehindTerrain = func( mp ) {
|
||||
var pos = mp.getNode("position");
|
||||
var alt = pos.getNode("altitude-ft").getValue();
|
||||
var lat = pos.getNode("latitude-deg").getValue();
|
||||
var lon = pos.getNode("longitude-deg").getValue();
|
||||
if(alt == nil or lat == nil or lon == nil) {
|
||||
return [0,0]; # invisible and not in front of terrain
|
||||
}
|
||||
var aircraftPos = geo.Coord.new().set_latlon(lat, lon, alt*FT2M);
|
||||
|
||||
var myPos = geo.aircraft_position();
|
||||
|
||||
myPos.set_alt(myPos.alt()+fire_control.radar_elevation_above_terrain_m);
|
||||
|
||||
var target_distance = myPos.direct_distance_to(aircraftPos);
|
||||
|
||||
call(func {
|
||||
if (target_distance*0.001 > 3.57*(math.sqrt(myPos.alt())+math.sqrt(alt*FT2M))) {
|
||||
# behind earth curvature
|
||||
#print("behind earth curvature");
|
||||
return [0,0]; # invisible and not in front of terrain
|
||||
}
|
||||
},nil,nil,var err =[]);
|
||||
|
||||
var xyz = {"x":myPos.x(), "y":myPos.y(), "z":myPos.z()};
|
||||
var dir = {"x":aircraftPos.x()-myPos.x(), "y":aircraftPos.y()-myPos.y(), "z":aircraftPos.z()-myPos.z()};
|
||||
|
||||
# Check for terrain between own aircraft and other:
|
||||
v = get_cart_ground_intersection(xyz, dir);
|
||||
if (v == nil) {
|
||||
return [1,0]; # visible and not in front of terrain
|
||||
#printf("No terrain, planes has clear view of each other");
|
||||
} else {
|
||||
var terrain = geo.Coord.new();
|
||||
terrain.set_latlon(v.lat, v.lon, v.elevation);
|
||||
var maxDist = myPos.direct_distance_to(aircraftPos);
|
||||
var terrainDist = myPos.direct_distance_to(terrain);
|
||||
if (terrainDist < maxDist-1) {
|
||||
#printf("terrain found between me and aircraft %.1f meter away.", terrainDist);
|
||||
return [0,0]; # visible and not in front of terrain
|
||||
} else {
|
||||
#print("The planes has clear view of each other");
|
||||
return [1,1]; # visible and in front of terrain
|
||||
}
|
||||
}
|
||||
var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
|
||||
var encode3bits = func(first, second, third) {
|
||||
var integer = first;
|
||||
integer = integer + 2 * second;
|
||||
integer = integer + 4 * third;
|
||||
return integer;
|
||||
}
|
||||
var versionString = getprop("sim/version/flightgear");
|
||||
var version = split(".", versionString);
|
||||
var major = num(version[0]);
|
||||
var minor = num(version[1]);
|
||||
var pica = num(version[2]);
|
||||
var pickingMethod = 0;
|
||||
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||
pickingMethod = 1;
|
||||
}
|
||||
|
||||
var AIR = 0;
|
||||
var MARINE = 1;
|
||||
var SURFACE = 2;
|
||||
var ORDNANCE = 3;
|
||||
|
||||
var Contact = {
|
||||
# For now only used in guided missiles, to make it compatible with Mirage 2000-5.
|
||||
new: func(c, class) {
|
||||
var obj = { parents : [Contact]};
|
||||
#debug.benchmark("radar process1", func {
|
||||
obj.rdrProp = c.getNode("radar");
|
||||
obj.oriProp = c.getNode("orientation");
|
||||
obj.velProp = c.getNode("velocities");
|
||||
obj.posProp = c.getNode("position");
|
||||
obj.heading = obj.oriProp.getNode("true-heading-deg");
|
||||
#});
|
||||
#debug.benchmark("radar process2", func {
|
||||
obj.alt = obj.posProp.getNode("altitude-ft");
|
||||
obj.lat = obj.posProp.getNode("latitude-deg");
|
||||
obj.lon = obj.posProp.getNode("longitude-deg");
|
||||
#});
|
||||
#debug.benchmark("radar process3", func {
|
||||
#As it is a geo.Coord object, we have to update lat/lon/alt ->and alt is in meters
|
||||
obj.coord = geo.Coord.new();
|
||||
obj.coord.set_latlon(obj.lat.getValue(), obj.lon.getValue(), obj.alt.getValue() * FT2M);
|
||||
#});
|
||||
#debug.benchmark("radar process4", func {
|
||||
obj.pitch = obj.oriProp.getNode("pitch-deg");
|
||||
obj.roll = obj.oriProp.getNode("roll-deg");
|
||||
obj.speed = obj.velProp.getNode("true-airspeed-kt");
|
||||
obj.vSpeed = obj.velProp.getNode("vertical-speed-fps");
|
||||
obj.callsign = c.getNode("callsign", 1);
|
||||
obj.shorter = c.getNode("model-shorter");
|
||||
obj.orig_callsign = obj.callsign.getValue();
|
||||
obj.name = c.getNode("name");
|
||||
obj.sign = c.getNode("sign",1);
|
||||
obj.valid = c.getNode("valid");
|
||||
obj.painted = c.getNode("painted");
|
||||
obj.unique = c.getNode("unique");
|
||||
obj.validTree = 0;
|
||||
#});
|
||||
#debug.benchmark("radar process5", func {
|
||||
#obj.transponderID = c.getNode("instrumentation/transponder/transmitted-id");
|
||||
#});
|
||||
#debug.benchmark("radar process6", func {
|
||||
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 ~ "]";
|
||||
#});
|
||||
#debug.benchmark("radar process7", func {
|
||||
obj.range = obj.rdrProp.getNode("range-nm");
|
||||
obj.bearing = obj.rdrProp.getNode("bearing-deg");
|
||||
obj.elevation = obj.rdrProp.getNode("elevation-deg");
|
||||
obj.ubody = obj.rdrProp.getNode("velocities/uBody-fps");
|
||||
obj.vbody = obj.rdrProp.getNode("velocities/vBody-fps");
|
||||
obj.wbody = obj.rdrProp.getNode("velocities/wBody-fps");
|
||||
#});
|
||||
obj.deviation = nil;
|
||||
|
||||
obj.node = c;
|
||||
obj.class = class;
|
||||
|
||||
obj.polar = [0,0];
|
||||
obj.cartesian = [0,0];
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
get_uBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.ubody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = me.get_Speed()*KT2FPS;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
get_vBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.vbody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = 0;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
get_wBody: func {
|
||||
var body = nil;
|
||||
if (me.ubody != nil) {
|
||||
body = me.wbody.getValue();
|
||||
}
|
||||
if(body == nil) {
|
||||
body = 0;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
|
||||
isValid: func () {
|
||||
var valid = me.valid.getValue();
|
||||
if (valid == nil) {
|
||||
valid = 0;
|
||||
}
|
||||
if (me.callsign.getValue() != me.orig_callsign) {
|
||||
valid = 0;
|
||||
}
|
||||
return valid;
|
||||
},
|
||||
|
||||
isPainted: func () {
|
||||
if (getprop("/carrier/sunk") == 1) {
|
||||
return 0;
|
||||
}
|
||||
return isNotBehindTerrain(me.node)[0];
|
||||
},
|
||||
|
||||
isCommandActive: func {
|
||||
if (getprop("/carrier/sunk") == 1) {
|
||||
return 0;
|
||||
}
|
||||
return isNotBehindTerrain(me.node)[0];
|
||||
},
|
||||
|
||||
getUnique: func () {
|
||||
if (me.unique == nil) {
|
||||
me.unique = me.node.getNode("unique");
|
||||
}
|
||||
if (me.unique == nil) {
|
||||
return nil;
|
||||
}
|
||||
var u = me.unique.getValue();
|
||||
return u;
|
||||
},
|
||||
|
||||
getElevation: func() {
|
||||
var e = 0;
|
||||
e = me.elevation.getValue();
|
||||
if(e == nil or e == 0) {
|
||||
# AI/MP has no radar properties
|
||||
var self = geo.aircraft_position();
|
||||
self.set_alt(self.alt()+fire_control.radar_elevation_above_terrain_m);
|
||||
me.get_Coord();
|
||||
var angleInv = clamp(self.distance_to(me.coord)/self.direct_distance_to(me.coord), -1, 1);
|
||||
e = (self.alt()>me.coord.alt()?-1:1)*math.acos(angleInv)*R2D;
|
||||
}
|
||||
return e;
|
||||
},
|
||||
|
||||
getNode: func () {
|
||||
return me.node;
|
||||
},
|
||||
|
||||
getFlareNode: func () {
|
||||
return me.node.getNode("rotors/main/blade[3]/flap-deg");
|
||||
},
|
||||
|
||||
getChaffNode: func () {
|
||||
return me.node.getNode("rotors/main/blade[3]/position-deg");
|
||||
},
|
||||
|
||||
setPolar: func(dist, angle) {
|
||||
me.polar = [dist,angle];
|
||||
},
|
||||
|
||||
setCartesian: func(x, y) {
|
||||
me.cartesian = [x,y];
|
||||
},
|
||||
|
||||
remove: func(){
|
||||
if(me.validTree != 0){
|
||||
me.validTree.setValue(0);
|
||||
}
|
||||
},
|
||||
|
||||
get_Coord: func(){
|
||||
me.coord.set_latlon(me.lat.getValue(), me.lon.getValue(), me.alt.getValue() * FT2M);
|
||||
var TgTCoord = geo.Coord.new(me.coord);
|
||||
return TgTCoord;
|
||||
},
|
||||
|
||||
get_Callsign: func(){
|
||||
var n = me.callsign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
if (me.name == nil) {
|
||||
me.name = me.getNode().getNode("name");
|
||||
}
|
||||
if (me.name == nil) {
|
||||
n = "";
|
||||
} else {
|
||||
n = me.name.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
n = me.sign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
return "UFO";
|
||||
},
|
||||
|
||||
get_model: func(){
|
||||
var n = "";
|
||||
if (me.shorter == nil) {
|
||||
me.shorter = me.node.getNode("model-shorter");
|
||||
}
|
||||
if (me.shorter != nil) {
|
||||
n = me.shorter.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
n = me.sign.getValue();
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
if (me.name == nil) {
|
||||
me.name = me.getNode().getNode("name");
|
||||
}
|
||||
if (me.name == nil) {
|
||||
n = "";
|
||||
} else {
|
||||
n = me.name.getValue();
|
||||
}
|
||||
if(n != "" and n != nil) {
|
||||
return n;
|
||||
}
|
||||
return me.get_Callsign();
|
||||
},
|
||||
|
||||
get_Speed: func(){
|
||||
# return true airspeed
|
||||
var n = me.speed.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Longitude: func(){
|
||||
var n = me.lon.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Latitude: func(){
|
||||
var n = me.lat.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_Pitch: func(){
|
||||
var n = me.pitch.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
isVirtual: func(){
|
||||
return 0;
|
||||
},
|
||||
|
||||
get_Roll: func(){
|
||||
var n = me.roll.getValue();
|
||||
return n;
|
||||
},
|
||||
|
||||
get_heading : func(){
|
||||
var n = me.heading.getValue();
|
||||
if(n == nil)
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
get_bearing: func(){
|
||||
var n = 0;
|
||||
n = me.bearing.getValue();
|
||||
if(n == nil or n == 0) {
|
||||
# AI/MP has no radar properties
|
||||
n = me.get_bearing_from_Coord(geo.aircraft_position());
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
get_bearing_from_Coord: func(MyAircraftCoord){
|
||||
me.get_Coord();
|
||||
var myBearing = 0;
|
||||
if(me.coord.is_defined()) {
|
||||
myBearing = MyAircraftCoord.course_to(me.coord);
|
||||
}
|
||||
return myBearing;
|
||||
},
|
||||
|
||||
get_reciprocal_bearing: func(){
|
||||
return geo.normdeg(me.get_bearing() + 180);
|
||||
},
|
||||
|
||||
get_deviation: func(true_heading_ref, coord){
|
||||
me.deviation = - deviation_normdeg(true_heading_ref, me.get_bearing_from_Coord(coord));
|
||||
return me.deviation;
|
||||
},
|
||||
|
||||
get_altitude: func(){
|
||||
#Return Alt in feet
|
||||
return me.alt.getValue();
|
||||
},
|
||||
|
||||
get_Elevation_from_Coord: func(MyAircraftCoord) {
|
||||
me.get_Coord();
|
||||
var value = (me.coord.alt() - MyAircraftCoord.alt()) / me.coord.direct_distance_to(MyAircraftCoord);
|
||||
if (math.abs(value) > 1) {
|
||||
# warning this else will fail if logged in as observer and see aircraft on other side of globe
|
||||
return 0;
|
||||
}
|
||||
var myPitch = math.asin(value) * R2D;
|
||||
return myPitch;
|
||||
},
|
||||
|
||||
get_total_elevation_from_Coord: func(own_pitch, MyAircraftCoord){
|
||||
var myTotalElevation = - deviation_normdeg(own_pitch, me.get_Elevation_from_Coord(MyAircraftCoord));
|
||||
return myTotalElevation;
|
||||
},
|
||||
|
||||
get_total_elevation: func(own_pitch) {
|
||||
me.deviation = - deviation_normdeg(own_pitch, me.getElevation());
|
||||
return me.deviation;
|
||||
},
|
||||
|
||||
get_range: func() {
|
||||
var r = 0;
|
||||
if(me.range == nil or me.range.getValue() == nil or me.range.getValue() == 0) {
|
||||
# AI/MP has no radar properties
|
||||
me.get_Coord();
|
||||
r = me.coord.direct_distance_to(geo.aircraft_position()) * M2NM;
|
||||
} else {
|
||||
r = me.range.getValue();
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
get_range_from_Coord: func(MyAircraftCoord) {
|
||||
var myCoord = me.get_Coord();
|
||||
var myDistance = 0;
|
||||
if(myCoord.is_defined()) {
|
||||
myDistance = MyAircraftCoord.direct_distance_to(myCoord) * M2NM;
|
||||
}
|
||||
return myDistance;
|
||||
},
|
||||
|
||||
get_type: func () {
|
||||
return me.class;
|
||||
},
|
||||
|
||||
get_cartesian: func() {
|
||||
return me.cartesian;
|
||||
},
|
||||
|
||||
get_polar: func() {
|
||||
return me.polar;
|
||||
},
|
||||
};
|
||||
|
||||
var isNotBehindTerrain = func( mp ) {
|
||||
var pos = mp.getNode("position");
|
||||
var alt = pos.getNode("altitude-ft").getValue();
|
||||
var lat = pos.getNode("latitude-deg").getValue();
|
||||
var lon = pos.getNode("longitude-deg").getValue();
|
||||
if(alt == nil or lat == nil or lon == nil) {
|
||||
return [0,0]; # invisible and not in front of terrain
|
||||
}
|
||||
var aircraftPos = geo.Coord.new().set_latlon(lat, lon, alt*FT2M);
|
||||
|
||||
var myPos = geo.aircraft_position();
|
||||
|
||||
myPos.set_alt(myPos.alt()+fire_control.radar_elevation_above_terrain_m);
|
||||
|
||||
var target_distance = myPos.direct_distance_to(aircraftPos);
|
||||
|
||||
call(func {
|
||||
if (target_distance*0.001 > 3.57*(math.sqrt(myPos.alt())+math.sqrt(alt*FT2M))) {
|
||||
# behind earth curvature
|
||||
#print("behind earth curvature");
|
||||
return [0,0]; # invisible and not in front of terrain
|
||||
}
|
||||
},nil,nil,var err =[]);
|
||||
|
||||
var xyz = {"x":myPos.x(), "y":myPos.y(), "z":myPos.z()};
|
||||
var dir = {"x":aircraftPos.x()-myPos.x(), "y":aircraftPos.y()-myPos.y(), "z":aircraftPos.z()-myPos.z()};
|
||||
|
||||
# Check for terrain between own aircraft and other:
|
||||
v = get_cart_ground_intersection(xyz, dir);
|
||||
if (v == nil) {
|
||||
return [1,0]; # visible and not in front of terrain
|
||||
#printf("No terrain, planes has clear view of each other");
|
||||
} else {
|
||||
var terrain = geo.Coord.new();
|
||||
terrain.set_latlon(v.lat, v.lon, v.elevation);
|
||||
var maxDist = myPos.direct_distance_to(aircraftPos);
|
||||
var terrainDist = myPos.direct_distance_to(terrain);
|
||||
if (terrainDist < maxDist-1) {
|
||||
#printf("terrain found between me and aircraft %.1f meter away.", terrainDist);
|
||||
return [0,0]; # visible and not in front of terrain
|
||||
} else {
|
||||
#print("The planes has clear view of each other");
|
||||
return [1,1]; # visible and in front of terrain
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
@ -87,6 +87,48 @@ var ArmamentInFlightNotification =
|
||||
new_class.Flags = 0; # 8 bits for whatever.
|
||||
new_class.UniqueIdentity = _unique;
|
||||
|
||||
new_class.isValid = func {
|
||||
var valid = "";
|
||||
var limitMin = -124;
|
||||
var limitMax = 123;
|
||||
# 1 byte integer
|
||||
if (int(me.Kind) > limitMax or int(me.Kind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Kind is "~me.Kind;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.SecondaryKind) > limitMax or int(me.SecondaryKind) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.SecondaryKind is "~me.SecondaryKind;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int((me.u_fps-3348)*0.03703) > limitMax or int((me.u_fps-3348)*0.03703) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.u_fps is "~me.u_fps;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(me.Pitch*1.38) > limitMax or int(me.Pitch*1.38) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Pitch is "~me.Pitch;
|
||||
}
|
||||
# 1 byte float
|
||||
if (int(geo.normdeg180(me.Heading)/1.54) > limitMax or int(geo.normdeg180(me.Heading)/1.54) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Heading is "~me.Heading;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.Flags) > limitMax or int(me.Flags) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.Flags is "~me.Flags;
|
||||
}
|
||||
# 1 byte integer
|
||||
if (int(me.UniqueIdentity) > limitMax or int(me.UniqueIdentity) < limitMin) {
|
||||
valid ~= "|ArmamentInFlight.UniqueIdentity is "~me.UniqueIdentity;
|
||||
}
|
||||
# 7 byte string
|
||||
if (size(me.RemoteCallsign) > 7) {
|
||||
valid ~= "|ArmamentInFlight.RemoteCallsign is "~me.RemoteCallsign;
|
||||
}
|
||||
if (valid != "") {
|
||||
print("\nEMESARY ENCODING WILL FAIL:");
|
||||
print(" "~valid);
|
||||
}
|
||||
};
|
||||
|
||||
new_class.GetBridgeMessageNotificationTypeKey = func {
|
||||
return new_class.NotificationType~"."~new_class.Ident~"."~new_class.UniqueIndex;
|
||||
};
|
||||
@ -257,4 +299,4 @@ var ObjectInFlightNotification =
|
||||
};
|
||||
return new_class;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -51,3 +51,33 @@ objectoutgoingBridge.TransmitFrequencySeconds = 0.2;
|
||||
objectoutgoingBridge.MessageLifeTime = 1;
|
||||
objectoutgoingBridge.MPStringMaxLen = 150;
|
||||
emesary_mp_bridge.IncomingMPBridge.startMPBridge(objectRoutedNotifications, 17, emesary.GlobalTransmitter);
|
||||
|
||||
#
|
||||
# debug all messages - this can be removed when testing isn't required.
|
||||
var debugRecipient = emesary.Recipient.new("Debug");
|
||||
debugRecipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType != "FrameNotification") {
|
||||
print ("recv(0): type=",notification.NotificationType, " fromIncoming=",notification.FromIncomingBridge);
|
||||
|
||||
if (notification.NotificationType == "ArmamentInFlightNotification") {
|
||||
print("recv(1): ",notification.NotificationType, " ", notification.Ident);
|
||||
debug.dump(notification);
|
||||
|
||||
} else if (notification.NotificationType == "ArmamentNotification") {
|
||||
if (notification.FromIncomingBridge) {
|
||||
print("recv(2): ",notification.NotificationType, " ", notification.Ident,
|
||||
" Kind=",notification.Kind,
|
||||
" SecondaryKind=",notification.SecondaryKind,
|
||||
" RelativeAltitude=",notification.RelativeAltitude,
|
||||
" Distance=",notification.Distance,
|
||||
" Bearing=",notification.Bearing,
|
||||
" RemoteCallsign=",notification.RemoteCallsign);
|
||||
debug.dump(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking
|
||||
}
|
||||
# uncomment next line to activate debug recipient.
|
||||
#emesary.GlobalTransmitter.Register(debugRecipient);
|
@ -27,7 +27,7 @@ var mlw_max=getprop("payload/d-config/mlw_max"); #
|
||||
var auto_flare_caller = getprop("payload/d-config/auto_flare_caller"); # If damage.nas should detect flare releases, or if function is called from somewhere in aircraft
|
||||
############################################################################################################################
|
||||
|
||||
|
||||
srand();
|
||||
var hp = hp_max;
|
||||
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
|
||||
|
||||
@ -60,6 +60,7 @@ var shells = {
|
||||
"DEFA 554": [14,0.060], # 30x113mm Mirage, 220g
|
||||
"20mm APDS": [15,0.030], # CIWS
|
||||
"LAU-10": [16,0.500], # 127mm, ~4-7kg warhead
|
||||
# Max id is 41
|
||||
};
|
||||
|
||||
# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
|
||||
@ -165,6 +166,8 @@ var warheads = {
|
||||
"3M9": [96, 125.00,0,0],# 3M9M3 Missile used with 2K12/SA-6
|
||||
"5V28V": [97, 478.00,0,0],# Missile used with S-200D/SA-5
|
||||
"AIM-9X": [98, 20.80,0,0],
|
||||
"R-23R": [99, 55.00,0,0],# mig23 fox 1
|
||||
# Max id is 180
|
||||
};
|
||||
|
||||
var AIR_RADAR = "air";
|
||||
@ -182,9 +185,12 @@ var radar_signatures = {
|
||||
"m2000-5B": AIR_RADAR,
|
||||
"MiG-21bis": AIR_RADAR,
|
||||
"MiG-21MF-75": AIR_RADAR,
|
||||
"Mig-23MLD": AIR_RADAR,
|
||||
"MiG-29": AIR_RADAR,
|
||||
"SU-27": AIR_RADAR,
|
||||
"EC-137R": AIR_RADAR,
|
||||
"E-3R": AIR_RADAR,
|
||||
"E-3": AIR_RADAR,
|
||||
"RC-137R": AIR_RADAR,
|
||||
"E-8R": AIR_RADAR,
|
||||
"EC-137D": AIR_RADAR,
|
||||
@ -193,7 +199,7 @@ var radar_signatures = {
|
||||
"s-200": "gnd-05",
|
||||
"ZSU-23-4M": "gnd-23",
|
||||
"S-75": "gnd-02",
|
||||
"buk-m2": "gnd-11",
|
||||
"buk-m2": "gnd-17",
|
||||
"s-300": "gnd-20",
|
||||
"MIM104D": "gnd-p2",
|
||||
"missile_frigate": "gnd-nk",
|
||||
@ -308,7 +314,7 @@ var DamageRecipient =
|
||||
var radarOn = bits.test(notification.Flags, 0);
|
||||
var thrustOn = bits.test(notification.Flags, 1);
|
||||
var CWIOn = bits.test(notification.Flags, 2);
|
||||
var index = notification.SecondaryKind-21;
|
||||
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
|
||||
var typ = id2warhead[index];
|
||||
|
||||
if (notification.Kind == MOVE) {
|
||||
@ -402,6 +408,7 @@ var DamageRecipient =
|
||||
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
|
||||
} elsif (CWIOn) {
|
||||
setprop("payload/armament/MAW-semiactive", 1);# resets every 1 seconds
|
||||
if (notification.Callsign != nil) setprop("payload/armament/MAW-semiactive-callsign", notification.Callsign);# resets every 1 seconds
|
||||
}
|
||||
MAW_elapsed = elapsed;
|
||||
var appr = approached[notification.Callsign~notification.UniqueIdentity];
|
||||
@ -435,9 +442,9 @@ var DamageRecipient =
|
||||
#
|
||||
if (tacview_supported and tacview.starttime and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
|
||||
var node = getCallsign(notification.RemoteCallsign);
|
||||
if (node != nil and notification.SecondaryKind > 20) {
|
||||
if (node != nil and (notification.SecondaryKind > 20 or notification.SecondaryKind < -40)) {
|
||||
# its a warhead
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var lbs = wh[1];
|
||||
var hitCoord = geo.Coord.new();
|
||||
hitCoord.set_latlon(node.getNode("position/latitude-deg").getValue(), node.getNode("position/longitude-deg").getValue(), node.getNode("position/altitude-ft").getValue()*FT2M+notification.RelativeAltitude);
|
||||
@ -474,11 +481,11 @@ var DamageRecipient =
|
||||
damageLog.push(sprintf("%s hit you with %d %s.", notification.Callsign, hit_count, typ));
|
||||
nearby_explosion();
|
||||
}
|
||||
} elsif (notification.SecondaryKind > 20) {
|
||||
} elsif (notification.SecondaryKind > 20 or notification.SecondaryKind < -40) {
|
||||
# its a warhead
|
||||
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
|
||||
var dist = notification.Distance;
|
||||
var wh = id2warhead[notification.SecondaryKind - 21];
|
||||
var wh = id2warhead[DamageRecipient.emesaryID2typeID(notification.SecondaryKind)];
|
||||
var type = wh[4];#test code
|
||||
if (wh[3] == 1) {
|
||||
# cluster munition
|
||||
@ -603,7 +610,29 @@ var DamageRecipient =
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
return new_class;
|
||||
}
|
||||
},
|
||||
|
||||
typeID2emesaryID: func (typeID) {
|
||||
if (typeID <= 100) {
|
||||
return typeID + 21;
|
||||
} elsif (typeID <= 180) {
|
||||
return (typeID - 100) * -1 - 40;
|
||||
} else {
|
||||
print("Missile TypeID too large value, max is 180");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
emesaryID2typeID: func (emesaryID) {
|
||||
if (emesaryID > 20) {
|
||||
return emesaryID - 21;
|
||||
} elsif (emesaryID < -40) {
|
||||
return (emesaryID + 40) * -1 + 100;
|
||||
} else {
|
||||
print("Missile emesaryID not a warhead");
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
damage_recipient = DamageRecipient.new("DamageRecipient");
|
||||
@ -1107,6 +1136,46 @@ var fail_systems = func (probability, factor = 100) {#this factor needs tuning a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rand() < probability and rand() < probability and getprop("sim/flight-model") == "yasim") {
|
||||
setprop("consumables/fuel/tank[0]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-norm", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-norm", 0);
|
||||
# Somtimes these needs to be set too:
|
||||
setprop("consumables/fuel/tank[0]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[1]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[2]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[3]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[4]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[5]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[6]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[7]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[8]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[9]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[10]/level-lbs", 0);
|
||||
setprop("consumables/fuel/tank[11]/level-lbs", 0);
|
||||
# these will make the fraction indicator in fuel dialog not work after relocation, but they are needed:
|
||||
setprop("consumables/fuel/tank[0]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[1]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[2]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[3]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[4]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[5]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[6]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[7]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[8]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[9]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[10]/capacity-m3", 0);
|
||||
setprop("consumables/fuel/tank[11]/capacity-m3", 0);
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
@ -1136,6 +1205,42 @@ var repairYasim = func {
|
||||
}
|
||||
}
|
||||
|
||||
var setupYasimEngines = func {
|
||||
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
|
||||
var e0 = compat_failure_modes.fail_engine("engine");
|
||||
FailureMgr.add_failure_mode("engines/engine", "Engine 1", e0);
|
||||
}
|
||||
if (getprop("engines/engine[1]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[1]")) {
|
||||
var e1 = compat_failure_modes.fail_engine("engine[1]");
|
||||
FailureMgr.add_failure_mode("engines/engine[1]", "Engine 2", e1);
|
||||
}
|
||||
if (getprop("engines/engine[2]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[2]")) {
|
||||
var e2 = compat_failure_modes.fail_engine("engine[2]");
|
||||
FailureMgr.add_failure_mode("engines/engine[2]", "Engine 3", e2);
|
||||
}
|
||||
if (getprop("engines/engine[3]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[3]")) {
|
||||
var e3 = compat_failure_modes.fail_engine("engine[3]");
|
||||
FailureMgr.add_failure_mode("engines/engine[3]", "Engine 4", e3);
|
||||
}
|
||||
if (getprop("engines/engine[4]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[4]")) {
|
||||
var e4 = compat_failure_modes.fail_engine("engine[4]");
|
||||
FailureMgr.add_failure_mode("engines/engine[4]", "Engine 5", e4);
|
||||
}
|
||||
if (getprop("engines/engine[5]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[5]")) {
|
||||
var e5 = compat_failure_modes.fail_engine("engine[5]");
|
||||
FailureMgr.add_failure_mode("engines/engine[5]", "Engine 6", e5);
|
||||
}
|
||||
if (getprop("engines/engine[6]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[6]")) {
|
||||
var e6 = compat_failure_modes.fail_engine("engine[6]");
|
||||
FailureMgr.add_failure_mode("engines/engine[6]", "Engine 7", e6);
|
||||
}
|
||||
if (getprop("engines/engine[7]/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine[7]")) {
|
||||
var e7 = compat_failure_modes.fail_engine("engine[7]");
|
||||
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
|
||||
}
|
||||
}
|
||||
settimer(setupYasimEngines, 300);
|
||||
|
||||
setlistener("/sim/signals/reinit", repairYasim);
|
||||
|
||||
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
|
||||
@ -1268,6 +1373,7 @@ var processCallsigns = func () {
|
||||
if (getprop("sim/time/elapsed-sec")-MAW_elapsed > 1.1) {
|
||||
setprop("payload/armament/MAW-active", 0);# resets every 1.1 seconds without warning
|
||||
setprop("payload/armament/MAW-semiactive", 0);
|
||||
setprop("payload/armament/MAW-semiactive-callsign", "");
|
||||
}
|
||||
|
||||
# spike handling:
|
||||
@ -1438,11 +1544,25 @@ var writeDamageLog = func {
|
||||
io.close(file);
|
||||
}
|
||||
|
||||
var unitTest = func {
|
||||
for (var i= 0; i<=180;i+=1) {
|
||||
var em = DamageRecipient.typeID2emesaryID(i);
|
||||
var b = DamageRecipient.emesaryID2typeID(em);
|
||||
if (b != i) {
|
||||
print("unit test failed for index "~i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("unit test passed");
|
||||
}
|
||||
#unitTest();
|
||||
|
||||
setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
|
||||
#screen.property_display.add("payload/armament/MAW-bearing");
|
||||
#screen.property_display.add("payload/armament/MAW-active");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive");
|
||||
#screen.property_display.add("payload/armament/MAW-semiactive-callsign");
|
||||
#screen.property_display.add("payload/armament/MLW-bearing");
|
||||
#screen.property_display.add("payload/armament/MLW-count");
|
||||
#screen.property_display.add("payload/armament/MLW-launcher");
|
||||
@ -1452,7 +1572,7 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
|
||||
#screen.property_display.add("payload/armament/spike-gnd-02");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-05");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-06");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-11");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-17");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-23");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-p2");
|
||||
#screen.property_display.add("payload/armament/spike-gnd-nk");
|
@ -2,7 +2,7 @@ var Math = {
|
||||
#
|
||||
# Authors: Nikolai V. Chr, Axel Paccalin.
|
||||
#
|
||||
# Version 2.01
|
||||
# Version 2.02
|
||||
#
|
||||
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||
@ -287,13 +287,13 @@ var Math = {
|
||||
}
|
||||
if (coord1.alt() != coord2.alt()) {
|
||||
me.d12 = coord1.direct_distance_to(coord2);
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
if (me.d12 == 0) {
|
||||
# on top of each other, maybe rounding error..
|
||||
return 0;
|
||||
}
|
||||
me.coord3 = geo.Coord.new(coord1);
|
||||
me.coord3.set_alt(coord1.alt()-me.d12*5);# this will increase the area of the triangle so that rounding errors dont get in the way. Changed to 5 May 2023, which gives more presision than 0.5 when c1 and c2 are very close.
|
||||
me.d13 = coord1.alt()-me.coord3.alt();
|
||||
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||
@ -479,4 +479,4 @@ var unitTest = {
|
||||
printf("These two should be the same %s = %s",Math.format(aircraft),Math.format(aircraft2));
|
||||
},
|
||||
};
|
||||
#unitTest.start();
|
||||
#unitTest.start();
|
||||
|
Loading…
Reference in New Issue
Block a user