Update damage

This commit is contained in:
Nikolai V. Chr
2023-09-26 07:11:27 +02:00
parent 541e7ecdd5
commit 271e387d19
18 changed files with 1214 additions and 297 deletions

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -27,9 +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
############################################################################################################################
var TRUE = 1;
var FALSE = 0;
srand();
var hp = hp_max;
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
@@ -62,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.
@@ -164,7 +163,11 @@ var warheads = {
"pilot": [93, 0.00,1,0],# ejected pilot
"BETAB-500ShP": [94, 1160.00,1,0],
"Flare": [95, 0.00,0,0],
"3M9": [96, 125.00,0,0],# 3M9 Missile used with 2K12/SA-6
"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,17 +185,21 @@ 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,
"Mig-28": AIR_RADAR,
"SA-6": AIR_RADAR,#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"SA-6": "gnd-06",#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"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",
@@ -203,7 +210,7 @@ var radar_signatures = {
var id2warhead = [];
var launched = {};# callsign: elapsed-sec
var approached = {};# callsign: uniqueID
var heavy_smoke = [61,62,63,65,92,96];
var heavy_smoke = [61,62,63,65,92,96,97];
var k = keys(warheads);
@@ -241,6 +248,10 @@ for(var myid = 0;myid<size(k);myid+=1) {
}
}
var crater_model0 = getprop("payload/armament/models") ~ "crater_small.xml";
var crater_model1 = getprop("payload/armament/models") ~ "crater_big.xml";
var crater_model2 = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
#==================================================================
# Notification processing
#==================================================================
@@ -281,6 +292,7 @@ var DamageRecipient =
# " Flags=",notification.Flags,
# " Radar=",bits.test(notification.Flags, 0),
# " Thrust=",bits.test(notification.Flags, 1));
# " CWI=",bits.test(notification.Flags, 2));
#
# todo:
# animate missiles
@@ -301,7 +313,8 @@ var DamageRecipient =
var bearing = ownPos.course_to(notification.Position);
var radarOn = bits.test(notification.Flags, 0);
var thrustOn = bits.test(notification.Flags, 1);
var index = notification.SecondaryKind-21;
var CWIOn = bits.test(notification.Flags, 2);
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
var typ = id2warhead[index];
if (notification.Kind == MOVE) {
@@ -334,7 +347,7 @@ var DamageRecipient =
dynamics["noti_"~notification.Callsign~"_"~notification.UniqueIdentity] = [systime()-(time_before_delete-1.6), notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.u_fps, notification.Heading, notification.Pitch,-1]
}
if (tacview_supported and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
if (tacview_supported and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
if (tacview.starttime) {
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity),6);
if (notification.Kind == DESTROY) {
@@ -348,7 +361,7 @@ var DamageRecipient =
var extra2 = typ[2]==0?",Type=Weapon+Missile":",Type=Weapon+Bomb";
extra2 = typ[4]=="Flare"?",Type=Flare":extra2;
extra2 = typp=="Parachutist"?"":extra2;
var color = radarOn?",Color=Red":",Color=Yellow";
var color = radarOn or CWIOn?",Color=Red":",Color=Yellow";
thread.lock(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(tacID~",T="~notification.Position.lon()~"|"~notification.Position.lat()~"|"~notification.Position.alt()~extra~",Name="~typp~color~extra2~"\n");
@@ -376,9 +389,10 @@ var DamageRecipient =
setprop("payload/armament/MLW-launcher", notification.Callsign);
setprop("payload/armament/MLW-count", getprop("payload/armament/MLW-count")+1);
var out = sprintf("Missile Launch Warning from %03d degrees.", bearing);
if (rwr_to_screen) screen.log.write(out, 1,1,0);# temporary till someone models a RWR in RIO seat
if (rwr_to_screen) screen.log.write(out, 1,0.5,0);# temporary till someone models a RWR in RIO seat
print(out);
damageLog.push(sprintf("Missile Launch Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (m28_auto) mig28.missileLaunch();
}
}
}
@@ -386,19 +400,30 @@ var DamageRecipient =
# Missile approach warning:
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign != callsign) return emesary.Transmitter.ReceiptStatus_OK;
if (!radarOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
var heading = getprop("orientation/heading-deg");
var clock = geo.normdeg(bearing - heading);
setprop("payload/armament/MAW-bearing", bearing);
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
if (!radarOn and !CWIOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
#var heading = getprop("orientation/heading-deg");
#var clock = geo.normdeg(bearing - heading);
if (radarOn) {
setprop("payload/armament/MAW-bearing", bearing);
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];
if (appr == nil or elapsed - appr > 450) {
printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,1,0);# temporary till someone models a RWR in RIO seat
if (radarOn) {
#printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,0.5,0);# temporary till someone models a RWR in RIO seat
} else {
#printf("Missile Approach Warning");
damageLog.push(sprintf("Missile Approach Warning from %s.", notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning (semi-active)."), 1,0.5,0);# temporary till someone models a RWR in RIO seat
}
approached[notification.Callsign~notification.UniqueIdentity] = elapsed;
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
@@ -415,11 +440,11 @@ var DamageRecipient =
# debug.dump(notification);
#
#
if (tacview_supported and tacview.starttime and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
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);
@@ -439,9 +464,10 @@ var DamageRecipient =
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign == callsign and getprop("payload/armament/msg") == 1) {
#damage enabled and were getting hit
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (notification.SecondaryKind < 0 and hitable_by_cannon) {
# cannon hit
if (m28_auto) mig28.engagedBy(notification.Callsign, 0);
var probability = id2shell[-1*notification.SecondaryKind-1][1];
var typ = id2shell[-1*notification.SecondaryKind-1][2];
var hit_count = notification.Distance;
@@ -455,10 +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
@@ -549,21 +576,18 @@ var DamageRecipient =
}
if (notification.Kind == CREATE and getprop("payload/armament/enable-craters") == 1 and statics["obj_"~notification.UniqueIdentity] == nil) {
if (notification.SecondaryKind == 0) {# TODO: make a hash with all the models
var crater_model = getprop("payload/armament/models") ~ "crater_small.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model0, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
#static is a PropertyNode inside /models
}
} elsif (notification.SecondaryKind == 1) {
var crater_model = getprop("payload/armament/models") ~ "crater_big.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model1, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
} elsif (notification.SecondaryKind == 2) {
var crater_model = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model2, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
@@ -586,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");
@@ -863,6 +909,7 @@ var flare_update_time = 0.4;
var flare_duration = 8;
var flare_terminal_speed = 50;#m/s
var flares_max_process_per_loop = 4;
var flare_sequencer = -120;
var flare_sorter = func(a, b) {
if(a[0] < b[0]){
@@ -945,7 +992,9 @@ var flare_released = func {
getprop("orientation/heading-deg"),
FT2M*getprop("velocities/speed-down-fps"),
FT2M*math.sqrt(getprop("velocities/speed-north-fps")*getprop("velocities/speed-north-fps")+getprop("velocities/speed-east-fps")*getprop("velocities/speed-east-fps")),
int(rand()*240)-120];
flare_sequencer];
flare_sequencer += 1;
if (flare_sequencer > 120) flare_sequencer = -120;
append(flare_list, flare);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
@@ -1087,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;
}
@@ -1116,6 +1205,51 @@ var repairYasim = func {
}
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("engines/engine[7]")) {
var e7 = compat_failure_modes.fail_engine("engine[7]");
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
}
}
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
@@ -1233,7 +1367,7 @@ var processCallsigns = func () {
var painted = 0;
var paint_list = [];
foreach (var player; players) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == 1 and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
var callsign = player.getChild("callsign").getValue();
callsign_struct[callsign] = player;
var str6 = player.getNode("sim/multiplay/generic/string[6]");
@@ -1247,6 +1381,8 @@ 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:
@@ -1293,16 +1429,16 @@ processCallsignsTimer.start();
var code_ct = func () {
#ANTIC
if (getprop("payload/armament/msg")) {
setprop("sim/rendering/redout/enabled", TRUE);
setprop("sim/rendering/redout/enabled", 1);
#call(func{fgcommand('dialog-close', multiplayer.dialog.dialog.prop())},nil,var err= []);# props.Node.new({"dialog-name": "location-in-air"}));
call(func{multiplayer.dialog.del();},nil,var err= []);
if (!m28_auto) call(func{multiplayer.dialog.del();},nil,var err= []);
if (!getprop("gear/gear[0]/wow")) {
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "WeightAndFuel"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "system-failures"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "instrument-failures"}))},nil,var err2 = []);
}
setprop("sim/freeze/fuel",0);
setprop("/sim/speed-up", 1);
if (!m28_auto) setprop("/sim/speed-up", 1);
setprop("/gui/map/draw-traffic", 0);
setprop("/sim/marker-pins/traffic", 0);
setprop("/sim/gui/dialogs/map-canvas/draw-TFC", 0);
@@ -1317,7 +1453,7 @@ code_ctTimer.simulatedTime = 1;
setprop("/sim/failure-manager/display-on-screen", FALSE);
setprop("/sim/failure-manager/display-on-screen", 0);
code_ctTimer.start();
@@ -1337,6 +1473,22 @@ var re_init = func (node) {
}
stopLaunch();
damageLog.push("Aircraft was repaired due to re-init.");
# Remove all 3D craters and re-place them. Due to re-init can remove some of them.
foreach (var thekey ; keys(statics)) {
var sta = statics[thekey];
if (sta[0] != nil) {
sta[0].remove();
if (sta[5] == 0) {# TODO: make a hash with all the models
sta[0] = geo.put_model(crater_model0, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 1) {
sta[0] = geo.put_model(crater_model1, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 2) {
sta[0] = geo.put_model(crater_model2, sta[1], sta[2], sta[3], sta[4]);
}
}
}
}
#==================================================================
@@ -1401,10 +1553,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");
@@ -1412,7 +1579,9 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
#screen.property_display.add("payload/armament/spike-air");
#screen.property_display.add("payload/armament/spike-gnd-20");
#screen.property_display.add("payload/armament/spike-gnd-02");
#screen.property_display.add("payload/armament/spike-gnd-11");
#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-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");

View File

@@ -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();

View File

@@ -27,9 +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
############################################################################################################################
var TRUE = 1;
var FALSE = 0;
srand();
var hp = hp_max;
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
@@ -62,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.
@@ -164,7 +163,11 @@ var warheads = {
"pilot": [93, 0.00,1,0],# ejected pilot
"BETAB-500ShP": [94, 1160.00,1,0],
"Flare": [95, 0.00,0,0],
"3M9": [96, 125.00,0,0],# 3M9 Missile used with 2K12/SA-6
"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,17 +185,21 @@ 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,
"Mig-28": AIR_RADAR,
"SA-6": AIR_RADAR,#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"SA-6": "gnd-06",#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"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",
@@ -203,7 +210,7 @@ var radar_signatures = {
var id2warhead = [];
var launched = {};# callsign: elapsed-sec
var approached = {};# callsign: uniqueID
var heavy_smoke = [61,62,63,65,92,96];
var heavy_smoke = [61,62,63,65,92,96,97];
var k = keys(warheads);
@@ -241,6 +248,10 @@ for(var myid = 0;myid<size(k);myid+=1) {
}
}
var crater_model0 = getprop("payload/armament/models") ~ "crater_small.xml";
var crater_model1 = getprop("payload/armament/models") ~ "crater_big.xml";
var crater_model2 = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
#==================================================================
# Notification processing
#==================================================================
@@ -281,6 +292,7 @@ var DamageRecipient =
# " Flags=",notification.Flags,
# " Radar=",bits.test(notification.Flags, 0),
# " Thrust=",bits.test(notification.Flags, 1));
# " CWI=",bits.test(notification.Flags, 2));
#
# todo:
# animate missiles
@@ -301,7 +313,8 @@ var DamageRecipient =
var bearing = ownPos.course_to(notification.Position);
var radarOn = bits.test(notification.Flags, 0);
var thrustOn = bits.test(notification.Flags, 1);
var index = notification.SecondaryKind-21;
var CWIOn = bits.test(notification.Flags, 2);
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
var typ = id2warhead[index];
if (notification.Kind == MOVE) {
@@ -334,7 +347,7 @@ var DamageRecipient =
dynamics["noti_"~notification.Callsign~"_"~notification.UniqueIdentity] = [systime()-(time_before_delete-1.6), notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.u_fps, notification.Heading, notification.Pitch,-1]
}
if (tacview_supported and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
if (tacview_supported and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
if (tacview.starttime) {
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity),6);
if (notification.Kind == DESTROY) {
@@ -348,7 +361,7 @@ var DamageRecipient =
var extra2 = typ[2]==0?",Type=Weapon+Missile":",Type=Weapon+Bomb";
extra2 = typ[4]=="Flare"?",Type=Flare":extra2;
extra2 = typp=="Parachutist"?"":extra2;
var color = radarOn?",Color=Red":",Color=Yellow";
var color = radarOn or CWIOn?",Color=Red":",Color=Yellow";
thread.lock(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(tacID~",T="~notification.Position.lon()~"|"~notification.Position.lat()~"|"~notification.Position.alt()~extra~",Name="~typp~color~extra2~"\n");
@@ -376,9 +389,10 @@ var DamageRecipient =
setprop("payload/armament/MLW-launcher", notification.Callsign);
setprop("payload/armament/MLW-count", getprop("payload/armament/MLW-count")+1);
var out = sprintf("Missile Launch Warning from %03d degrees.", bearing);
if (rwr_to_screen) screen.log.write(out, 1,1,0);# temporary till someone models a RWR in RIO seat
if (rwr_to_screen) screen.log.write(out, 1,0.5,0);# temporary till someone models a RWR in RIO seat
print(out);
damageLog.push(sprintf("Missile Launch Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (m28_auto) mig28.missileLaunch();
}
}
}
@@ -386,19 +400,30 @@ var DamageRecipient =
# Missile approach warning:
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign != callsign) return emesary.Transmitter.ReceiptStatus_OK;
if (!radarOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
var heading = getprop("orientation/heading-deg");
var clock = geo.normdeg(bearing - heading);
setprop("payload/armament/MAW-bearing", bearing);
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
if (!radarOn and !CWIOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
#var heading = getprop("orientation/heading-deg");
#var clock = geo.normdeg(bearing - heading);
if (radarOn) {
setprop("payload/armament/MAW-bearing", bearing);
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];
if (appr == nil or elapsed - appr > 450) {
printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,1,0);# temporary till someone models a RWR in RIO seat
if (radarOn) {
#printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,0.5,0);# temporary till someone models a RWR in RIO seat
} else {
#printf("Missile Approach Warning");
damageLog.push(sprintf("Missile Approach Warning from %s.", notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning (semi-active)."), 1,0.5,0);# temporary till someone models a RWR in RIO seat
}
approached[notification.Callsign~notification.UniqueIdentity] = elapsed;
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
@@ -415,11 +440,11 @@ var DamageRecipient =
# debug.dump(notification);
#
#
if (tacview_supported and tacview.starttime and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
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);
@@ -439,9 +464,10 @@ var DamageRecipient =
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign == callsign and getprop("payload/armament/msg") == 1) {
#damage enabled and were getting hit
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (notification.SecondaryKind < 0 and hitable_by_cannon) {
# cannon hit
if (m28_auto) mig28.engagedBy(notification.Callsign, 0);
var probability = id2shell[-1*notification.SecondaryKind-1][1];
var typ = id2shell[-1*notification.SecondaryKind-1][2];
var hit_count = notification.Distance;
@@ -455,10 +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
@@ -549,21 +576,18 @@ var DamageRecipient =
}
if (notification.Kind == CREATE and getprop("payload/armament/enable-craters") == 1 and statics["obj_"~notification.UniqueIdentity] == nil) {
if (notification.SecondaryKind == 0) {# TODO: make a hash with all the models
var crater_model = getprop("payload/armament/models") ~ "crater_small.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model0, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
#static is a PropertyNode inside /models
}
} elsif (notification.SecondaryKind == 1) {
var crater_model = getprop("payload/armament/models") ~ "crater_big.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model1, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
} elsif (notification.SecondaryKind == 2) {
var crater_model = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model2, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
@@ -586,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");
@@ -863,6 +909,7 @@ var flare_update_time = 0.4;
var flare_duration = 8;
var flare_terminal_speed = 50;#m/s
var flares_max_process_per_loop = 4;
var flare_sequencer = -120;
var flare_sorter = func(a, b) {
if(a[0] < b[0]){
@@ -945,7 +992,9 @@ var flare_released = func {
getprop("orientation/heading-deg"),
FT2M*getprop("velocities/speed-down-fps"),
FT2M*math.sqrt(getprop("velocities/speed-north-fps")*getprop("velocities/speed-north-fps")+getprop("velocities/speed-east-fps")*getprop("velocities/speed-east-fps")),
int(rand()*240)-120];
flare_sequencer];
flare_sequencer += 1;
if (flare_sequencer > 120) flare_sequencer = -120;
append(flare_list, flare);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
@@ -1087,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;
}
@@ -1116,6 +1205,51 @@ var repairYasim = func {
}
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("engines/engine[7]")) {
var e7 = compat_failure_modes.fail_engine("engine[7]");
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
}
}
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
@@ -1233,7 +1367,7 @@ var processCallsigns = func () {
var painted = 0;
var paint_list = [];
foreach (var player; players) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == 1 and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
var callsign = player.getChild("callsign").getValue();
callsign_struct[callsign] = player;
var str6 = player.getNode("sim/multiplay/generic/string[6]");
@@ -1247,6 +1381,8 @@ 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:
@@ -1293,16 +1429,16 @@ processCallsignsTimer.start();
var code_ct = func () {
#ANTIC
if (getprop("payload/armament/msg")) {
setprop("sim/rendering/redout/enabled", TRUE);
setprop("sim/rendering/redout/enabled", 1);
#call(func{fgcommand('dialog-close', multiplayer.dialog.dialog.prop())},nil,var err= []);# props.Node.new({"dialog-name": "location-in-air"}));
call(func{multiplayer.dialog.del();},nil,var err= []);
if (!m28_auto) call(func{multiplayer.dialog.del();},nil,var err= []);
if (!getprop("gear/gear[0]/wow")) {
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "WeightAndFuel"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "system-failures"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "instrument-failures"}))},nil,var err2 = []);
}
setprop("sim/freeze/fuel",0);
setprop("/sim/speed-up", 1);
if (!m28_auto) setprop("/sim/speed-up", 1);
setprop("/gui/map/draw-traffic", 0);
setprop("/sim/marker-pins/traffic", 0);
setprop("/sim/gui/dialogs/map-canvas/draw-TFC", 0);
@@ -1317,7 +1453,7 @@ code_ctTimer.simulatedTime = 1;
setprop("/sim/failure-manager/display-on-screen", FALSE);
setprop("/sim/failure-manager/display-on-screen", 0);
code_ctTimer.start();
@@ -1337,6 +1473,22 @@ var re_init = func (node) {
}
stopLaunch();
damageLog.push("Aircraft was repaired due to re-init.");
# Remove all 3D craters and re-place them. Due to re-init can remove some of them.
foreach (var thekey ; keys(statics)) {
var sta = statics[thekey];
if (sta[0] != nil) {
sta[0].remove();
if (sta[5] == 0) {# TODO: make a hash with all the models
sta[0] = geo.put_model(crater_model0, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 1) {
sta[0] = geo.put_model(crater_model1, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 2) {
sta[0] = geo.put_model(crater_model2, sta[1], sta[2], sta[3], sta[4]);
}
}
}
}
#==================================================================
@@ -1401,10 +1553,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");
@@ -1412,7 +1579,9 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
#screen.property_display.add("payload/armament/spike-air");
#screen.property_display.add("payload/armament/spike-gnd-20");
#screen.property_display.add("payload/armament/spike-gnd-02");
#screen.property_display.add("payload/armament/spike-gnd-11");
#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-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");

View File

@@ -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();

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -27,9 +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
############################################################################################################################
var TRUE = 1;
var FALSE = 0;
srand();
var hp = hp_max;
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
@@ -62,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.
@@ -164,7 +163,11 @@ var warheads = {
"pilot": [93, 0.00,1,0],# ejected pilot
"BETAB-500ShP": [94, 1160.00,1,0],
"Flare": [95, 0.00,0,0],
"3M9": [96, 125.00,0,0],# 3M9 Missile used with 2K12/SA-6
"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,17 +185,21 @@ 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,
"Mig-28": AIR_RADAR,
"SA-6": AIR_RADAR,#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"SA-6": "gnd-06",#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"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",
@@ -203,7 +210,7 @@ var radar_signatures = {
var id2warhead = [];
var launched = {};# callsign: elapsed-sec
var approached = {};# callsign: uniqueID
var heavy_smoke = [61,62,63,65,92,96];
var heavy_smoke = [61,62,63,65,92,96,97];
var k = keys(warheads);
@@ -241,6 +248,10 @@ for(var myid = 0;myid<size(k);myid+=1) {
}
}
var crater_model0 = getprop("payload/armament/models") ~ "crater_small.xml";
var crater_model1 = getprop("payload/armament/models") ~ "crater_big.xml";
var crater_model2 = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
#==================================================================
# Notification processing
#==================================================================
@@ -281,6 +292,7 @@ var DamageRecipient =
# " Flags=",notification.Flags,
# " Radar=",bits.test(notification.Flags, 0),
# " Thrust=",bits.test(notification.Flags, 1));
# " CWI=",bits.test(notification.Flags, 2));
#
# todo:
# animate missiles
@@ -301,7 +313,8 @@ var DamageRecipient =
var bearing = ownPos.course_to(notification.Position);
var radarOn = bits.test(notification.Flags, 0);
var thrustOn = bits.test(notification.Flags, 1);
var index = notification.SecondaryKind-21;
var CWIOn = bits.test(notification.Flags, 2);
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
var typ = id2warhead[index];
if (notification.Kind == MOVE) {
@@ -334,7 +347,7 @@ var DamageRecipient =
dynamics["noti_"~notification.Callsign~"_"~notification.UniqueIdentity] = [systime()-(time_before_delete-1.6), notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.u_fps, notification.Heading, notification.Pitch,-1]
}
if (tacview_supported and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
if (tacview_supported and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
if (tacview.starttime) {
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity),6);
if (notification.Kind == DESTROY) {
@@ -348,7 +361,7 @@ var DamageRecipient =
var extra2 = typ[2]==0?",Type=Weapon+Missile":",Type=Weapon+Bomb";
extra2 = typ[4]=="Flare"?",Type=Flare":extra2;
extra2 = typp=="Parachutist"?"":extra2;
var color = radarOn?",Color=Red":",Color=Yellow";
var color = radarOn or CWIOn?",Color=Red":",Color=Yellow";
thread.lock(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(tacID~",T="~notification.Position.lon()~"|"~notification.Position.lat()~"|"~notification.Position.alt()~extra~",Name="~typp~color~extra2~"\n");
@@ -376,9 +389,10 @@ var DamageRecipient =
setprop("payload/armament/MLW-launcher", notification.Callsign);
setprop("payload/armament/MLW-count", getprop("payload/armament/MLW-count")+1);
var out = sprintf("Missile Launch Warning from %03d degrees.", bearing);
if (rwr_to_screen) screen.log.write(out, 1,1,0);# temporary till someone models a RWR in RIO seat
if (rwr_to_screen) screen.log.write(out, 1,0.5,0);# temporary till someone models a RWR in RIO seat
print(out);
damageLog.push(sprintf("Missile Launch Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (m28_auto) mig28.missileLaunch();
}
}
}
@@ -386,19 +400,30 @@ var DamageRecipient =
# Missile approach warning:
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign != callsign) return emesary.Transmitter.ReceiptStatus_OK;
if (!radarOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
var heading = getprop("orientation/heading-deg");
var clock = geo.normdeg(bearing - heading);
setprop("payload/armament/MAW-bearing", bearing);
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
if (!radarOn and !CWIOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
#var heading = getprop("orientation/heading-deg");
#var clock = geo.normdeg(bearing - heading);
if (radarOn) {
setprop("payload/armament/MAW-bearing", bearing);
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];
if (appr == nil or elapsed - appr > 450) {
printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,1,0);# temporary till someone models a RWR in RIO seat
if (radarOn) {
#printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,0.5,0);# temporary till someone models a RWR in RIO seat
} else {
#printf("Missile Approach Warning");
damageLog.push(sprintf("Missile Approach Warning from %s.", notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning (semi-active)."), 1,0.5,0);# temporary till someone models a RWR in RIO seat
}
approached[notification.Callsign~notification.UniqueIdentity] = elapsed;
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
@@ -415,11 +440,11 @@ var DamageRecipient =
# debug.dump(notification);
#
#
if (tacview_supported and tacview.starttime and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
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);
@@ -439,9 +464,10 @@ var DamageRecipient =
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign == callsign and getprop("payload/armament/msg") == 1) {
#damage enabled and were getting hit
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (notification.SecondaryKind < 0 and hitable_by_cannon) {
# cannon hit
if (m28_auto) mig28.engagedBy(notification.Callsign, 0);
var probability = id2shell[-1*notification.SecondaryKind-1][1];
var typ = id2shell[-1*notification.SecondaryKind-1][2];
var hit_count = notification.Distance;
@@ -455,10 +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
@@ -549,21 +576,18 @@ var DamageRecipient =
}
if (notification.Kind == CREATE and getprop("payload/armament/enable-craters") == 1 and statics["obj_"~notification.UniqueIdentity] == nil) {
if (notification.SecondaryKind == 0) {# TODO: make a hash with all the models
var crater_model = getprop("payload/armament/models") ~ "crater_small.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model0, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
#static is a PropertyNode inside /models
}
} elsif (notification.SecondaryKind == 1) {
var crater_model = getprop("payload/armament/models") ~ "crater_big.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model1, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
} elsif (notification.SecondaryKind == 2) {
var crater_model = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model2, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
@@ -586,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");
@@ -863,6 +909,7 @@ var flare_update_time = 0.4;
var flare_duration = 8;
var flare_terminal_speed = 50;#m/s
var flares_max_process_per_loop = 4;
var flare_sequencer = -120;
var flare_sorter = func(a, b) {
if(a[0] < b[0]){
@@ -945,7 +992,9 @@ var flare_released = func {
getprop("orientation/heading-deg"),
FT2M*getprop("velocities/speed-down-fps"),
FT2M*math.sqrt(getprop("velocities/speed-north-fps")*getprop("velocities/speed-north-fps")+getprop("velocities/speed-east-fps")*getprop("velocities/speed-east-fps")),
int(rand()*240)-120];
flare_sequencer];
flare_sequencer += 1;
if (flare_sequencer > 120) flare_sequencer = -120;
append(flare_list, flare);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
@@ -1087,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;
}
@@ -1116,6 +1205,51 @@ var repairYasim = func {
}
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("engines/engine[7]")) {
var e7 = compat_failure_modes.fail_engine("engine[7]");
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
}
}
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
@@ -1233,7 +1367,7 @@ var processCallsigns = func () {
var painted = 0;
var paint_list = [];
foreach (var player; players) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == 1 and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
var callsign = player.getChild("callsign").getValue();
callsign_struct[callsign] = player;
var str6 = player.getNode("sim/multiplay/generic/string[6]");
@@ -1247,6 +1381,8 @@ 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:
@@ -1293,16 +1429,16 @@ processCallsignsTimer.start();
var code_ct = func () {
#ANTIC
if (getprop("payload/armament/msg")) {
setprop("sim/rendering/redout/enabled", TRUE);
setprop("sim/rendering/redout/enabled", 1);
#call(func{fgcommand('dialog-close', multiplayer.dialog.dialog.prop())},nil,var err= []);# props.Node.new({"dialog-name": "location-in-air"}));
call(func{multiplayer.dialog.del();},nil,var err= []);
if (!m28_auto) call(func{multiplayer.dialog.del();},nil,var err= []);
if (!getprop("gear/gear[0]/wow")) {
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "WeightAndFuel"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "system-failures"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "instrument-failures"}))},nil,var err2 = []);
}
setprop("sim/freeze/fuel",0);
setprop("/sim/speed-up", 1);
if (!m28_auto) setprop("/sim/speed-up", 1);
setprop("/gui/map/draw-traffic", 0);
setprop("/sim/marker-pins/traffic", 0);
setprop("/sim/gui/dialogs/map-canvas/draw-TFC", 0);
@@ -1317,7 +1453,7 @@ code_ctTimer.simulatedTime = 1;
setprop("/sim/failure-manager/display-on-screen", FALSE);
setprop("/sim/failure-manager/display-on-screen", 0);
code_ctTimer.start();
@@ -1337,6 +1473,22 @@ var re_init = func (node) {
}
stopLaunch();
damageLog.push("Aircraft was repaired due to re-init.");
# Remove all 3D craters and re-place them. Due to re-init can remove some of them.
foreach (var thekey ; keys(statics)) {
var sta = statics[thekey];
if (sta[0] != nil) {
sta[0].remove();
if (sta[5] == 0) {# TODO: make a hash with all the models
sta[0] = geo.put_model(crater_model0, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 1) {
sta[0] = geo.put_model(crater_model1, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 2) {
sta[0] = geo.put_model(crater_model2, sta[1], sta[2], sta[3], sta[4]);
}
}
}
}
#==================================================================
@@ -1401,10 +1553,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");
@@ -1412,7 +1579,9 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
#screen.property_display.add("payload/armament/spike-air");
#screen.property_display.add("payload/armament/spike-gnd-20");
#screen.property_display.add("payload/armament/spike-gnd-02");
#screen.property_display.add("payload/armament/spike-gnd-11");
#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-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");

View File

@@ -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();

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -27,9 +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
############################################################################################################################
var TRUE = 1;
var FALSE = 0;
srand();
var hp = hp_max;
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
@@ -62,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.
@@ -164,7 +163,11 @@ var warheads = {
"pilot": [93, 0.00,1,0],# ejected pilot
"BETAB-500ShP": [94, 1160.00,1,0],
"Flare": [95, 0.00,0,0],
"3M9": [96, 125.00,0,0],# 3M9 Missile used with 2K12/SA-6
"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,17 +185,21 @@ 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,
"Mig-28": AIR_RADAR,
"SA-6": AIR_RADAR,#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"SA-6": "gnd-06",#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"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",
@@ -203,7 +210,7 @@ var radar_signatures = {
var id2warhead = [];
var launched = {};# callsign: elapsed-sec
var approached = {};# callsign: uniqueID
var heavy_smoke = [61,62,63,65,92,96];
var heavy_smoke = [61,62,63,65,92,96,97];
var k = keys(warheads);
@@ -241,6 +248,10 @@ for(var myid = 0;myid<size(k);myid+=1) {
}
}
var crater_model0 = getprop("payload/armament/models") ~ "crater_small.xml";
var crater_model1 = getprop("payload/armament/models") ~ "crater_big.xml";
var crater_model2 = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
#==================================================================
# Notification processing
#==================================================================
@@ -281,6 +292,7 @@ var DamageRecipient =
# " Flags=",notification.Flags,
# " Radar=",bits.test(notification.Flags, 0),
# " Thrust=",bits.test(notification.Flags, 1));
# " CWI=",bits.test(notification.Flags, 2));
#
# todo:
# animate missiles
@@ -301,7 +313,8 @@ var DamageRecipient =
var bearing = ownPos.course_to(notification.Position);
var radarOn = bits.test(notification.Flags, 0);
var thrustOn = bits.test(notification.Flags, 1);
var index = notification.SecondaryKind-21;
var CWIOn = bits.test(notification.Flags, 2);
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
var typ = id2warhead[index];
if (notification.Kind == MOVE) {
@@ -334,7 +347,7 @@ var DamageRecipient =
dynamics["noti_"~notification.Callsign~"_"~notification.UniqueIdentity] = [systime()-(time_before_delete-1.6), notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.u_fps, notification.Heading, notification.Pitch,-1]
}
if (tacview_supported and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
if (tacview_supported and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
if (tacview.starttime) {
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity),6);
if (notification.Kind == DESTROY) {
@@ -348,7 +361,7 @@ var DamageRecipient =
var extra2 = typ[2]==0?",Type=Weapon+Missile":",Type=Weapon+Bomb";
extra2 = typ[4]=="Flare"?",Type=Flare":extra2;
extra2 = typp=="Parachutist"?"":extra2;
var color = radarOn?",Color=Red":",Color=Yellow";
var color = radarOn or CWIOn?",Color=Red":",Color=Yellow";
thread.lock(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(tacID~",T="~notification.Position.lon()~"|"~notification.Position.lat()~"|"~notification.Position.alt()~extra~",Name="~typp~color~extra2~"\n");
@@ -376,9 +389,10 @@ var DamageRecipient =
setprop("payload/armament/MLW-launcher", notification.Callsign);
setprop("payload/armament/MLW-count", getprop("payload/armament/MLW-count")+1);
var out = sprintf("Missile Launch Warning from %03d degrees.", bearing);
if (rwr_to_screen) screen.log.write(out, 1,1,0);# temporary till someone models a RWR in RIO seat
if (rwr_to_screen) screen.log.write(out, 1,0.5,0);# temporary till someone models a RWR in RIO seat
print(out);
damageLog.push(sprintf("Missile Launch Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (m28_auto) mig28.missileLaunch();
}
}
}
@@ -386,19 +400,30 @@ var DamageRecipient =
# Missile approach warning:
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign != callsign) return emesary.Transmitter.ReceiptStatus_OK;
if (!radarOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
var heading = getprop("orientation/heading-deg");
var clock = geo.normdeg(bearing - heading);
setprop("payload/armament/MAW-bearing", bearing);
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
if (!radarOn and !CWIOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
#var heading = getprop("orientation/heading-deg");
#var clock = geo.normdeg(bearing - heading);
if (radarOn) {
setprop("payload/armament/MAW-bearing", bearing);
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];
if (appr == nil or elapsed - appr > 450) {
printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,1,0);# temporary till someone models a RWR in RIO seat
if (radarOn) {
#printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,0.5,0);# temporary till someone models a RWR in RIO seat
} else {
#printf("Missile Approach Warning");
damageLog.push(sprintf("Missile Approach Warning from %s.", notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning (semi-active)."), 1,0.5,0);# temporary till someone models a RWR in RIO seat
}
approached[notification.Callsign~notification.UniqueIdentity] = elapsed;
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
@@ -415,11 +440,11 @@ var DamageRecipient =
# debug.dump(notification);
#
#
if (tacview_supported and tacview.starttime and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
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);
@@ -439,9 +464,10 @@ var DamageRecipient =
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign == callsign and getprop("payload/armament/msg") == 1) {
#damage enabled and were getting hit
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (notification.SecondaryKind < 0 and hitable_by_cannon) {
# cannon hit
if (m28_auto) mig28.engagedBy(notification.Callsign, 0);
var probability = id2shell[-1*notification.SecondaryKind-1][1];
var typ = id2shell[-1*notification.SecondaryKind-1][2];
var hit_count = notification.Distance;
@@ -455,10 +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
@@ -549,21 +576,18 @@ var DamageRecipient =
}
if (notification.Kind == CREATE and getprop("payload/armament/enable-craters") == 1 and statics["obj_"~notification.UniqueIdentity] == nil) {
if (notification.SecondaryKind == 0) {# TODO: make a hash with all the models
var crater_model = getprop("payload/armament/models") ~ "crater_small.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model0, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
#static is a PropertyNode inside /models
}
} elsif (notification.SecondaryKind == 1) {
var crater_model = getprop("payload/armament/models") ~ "crater_big.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model1, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
} elsif (notification.SecondaryKind == 2) {
var crater_model = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model2, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
@@ -586,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");
@@ -863,6 +909,7 @@ var flare_update_time = 0.4;
var flare_duration = 8;
var flare_terminal_speed = 50;#m/s
var flares_max_process_per_loop = 4;
var flare_sequencer = -120;
var flare_sorter = func(a, b) {
if(a[0] < b[0]){
@@ -945,7 +992,9 @@ var flare_released = func {
getprop("orientation/heading-deg"),
FT2M*getprop("velocities/speed-down-fps"),
FT2M*math.sqrt(getprop("velocities/speed-north-fps")*getprop("velocities/speed-north-fps")+getprop("velocities/speed-east-fps")*getprop("velocities/speed-east-fps")),
int(rand()*240)-120];
flare_sequencer];
flare_sequencer += 1;
if (flare_sequencer > 120) flare_sequencer = -120;
append(flare_list, flare);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
@@ -1087,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;
}
@@ -1116,6 +1205,51 @@ var repairYasim = func {
}
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("engines/engine[7]")) {
var e7 = compat_failure_modes.fail_engine("engine[7]");
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
}
}
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
@@ -1233,7 +1367,7 @@ var processCallsigns = func () {
var painted = 0;
var paint_list = [];
foreach (var player; players) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == 1 and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
var callsign = player.getChild("callsign").getValue();
callsign_struct[callsign] = player;
var str6 = player.getNode("sim/multiplay/generic/string[6]");
@@ -1247,6 +1381,8 @@ 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:
@@ -1293,16 +1429,16 @@ processCallsignsTimer.start();
var code_ct = func () {
#ANTIC
if (getprop("payload/armament/msg")) {
setprop("sim/rendering/redout/enabled", TRUE);
setprop("sim/rendering/redout/enabled", 1);
#call(func{fgcommand('dialog-close', multiplayer.dialog.dialog.prop())},nil,var err= []);# props.Node.new({"dialog-name": "location-in-air"}));
call(func{multiplayer.dialog.del();},nil,var err= []);
if (!m28_auto) call(func{multiplayer.dialog.del();},nil,var err= []);
if (!getprop("gear/gear[0]/wow")) {
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "WeightAndFuel"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "system-failures"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "instrument-failures"}))},nil,var err2 = []);
}
setprop("sim/freeze/fuel",0);
setprop("/sim/speed-up", 1);
if (!m28_auto) setprop("/sim/speed-up", 1);
setprop("/gui/map/draw-traffic", 0);
setprop("/sim/marker-pins/traffic", 0);
setprop("/sim/gui/dialogs/map-canvas/draw-TFC", 0);
@@ -1317,7 +1453,7 @@ code_ctTimer.simulatedTime = 1;
setprop("/sim/failure-manager/display-on-screen", FALSE);
setprop("/sim/failure-manager/display-on-screen", 0);
code_ctTimer.start();
@@ -1337,6 +1473,22 @@ var re_init = func (node) {
}
stopLaunch();
damageLog.push("Aircraft was repaired due to re-init.");
# Remove all 3D craters and re-place them. Due to re-init can remove some of them.
foreach (var thekey ; keys(statics)) {
var sta = statics[thekey];
if (sta[0] != nil) {
sta[0].remove();
if (sta[5] == 0) {# TODO: make a hash with all the models
sta[0] = geo.put_model(crater_model0, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 1) {
sta[0] = geo.put_model(crater_model1, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 2) {
sta[0] = geo.put_model(crater_model2, sta[1], sta[2], sta[3], sta[4]);
}
}
}
}
#==================================================================
@@ -1401,10 +1553,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");
@@ -1412,7 +1579,9 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
#screen.property_display.add("payload/armament/spike-air");
#screen.property_display.add("payload/armament/spike-gnd-20");
#screen.property_display.add("payload/armament/spike-gnd-02");
#screen.property_display.add("payload/armament/spike-gnd-11");
#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-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");

View File

@@ -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();

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -1206,40 +1206,49 @@ var repairYasim = func {
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !contains(FailureMgr.get_failure_modes(), "engines/engine")) {
if (getprop("engines/engine/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[1]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[2]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[3]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[4]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[5]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[6]/n1") != nil and !hasMode("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]")) {
if (getprop("engines/engine[7]/n1") != nil and !hasMode("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);
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);

View File

@@ -27,9 +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
############################################################################################################################
var TRUE = 1;
var FALSE = 0;
srand();
var hp = hp_max;
setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
@@ -62,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.
@@ -164,7 +163,11 @@ var warheads = {
"pilot": [93, 0.00,1,0],# ejected pilot
"BETAB-500ShP": [94, 1160.00,1,0],
"Flare": [95, 0.00,0,0],
"3M9": [96, 125.00,0,0],# 3M9 Missile used with 2K12/SA-6
"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,17 +185,21 @@ 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,
"Mig-28": AIR_RADAR,
"SA-6": AIR_RADAR,#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"SA-6": "gnd-06",#Air radar tone chosen so that there is at least some lock tone until asset-specific is created
"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",
@@ -203,7 +210,7 @@ var radar_signatures = {
var id2warhead = [];
var launched = {};# callsign: elapsed-sec
var approached = {};# callsign: uniqueID
var heavy_smoke = [61,62,63,65,92,96];
var heavy_smoke = [61,62,63,65,92,96,97];
var k = keys(warheads);
@@ -241,6 +248,10 @@ for(var myid = 0;myid<size(k);myid+=1) {
}
}
var crater_model0 = getprop("payload/armament/models") ~ "crater_small.xml";
var crater_model1 = getprop("payload/armament/models") ~ "crater_big.xml";
var crater_model2 = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
#==================================================================
# Notification processing
#==================================================================
@@ -281,6 +292,7 @@ var DamageRecipient =
# " Flags=",notification.Flags,
# " Radar=",bits.test(notification.Flags, 0),
# " Thrust=",bits.test(notification.Flags, 1));
# " CWI=",bits.test(notification.Flags, 2));
#
# todo:
# animate missiles
@@ -301,7 +313,8 @@ var DamageRecipient =
var bearing = ownPos.course_to(notification.Position);
var radarOn = bits.test(notification.Flags, 0);
var thrustOn = bits.test(notification.Flags, 1);
var index = notification.SecondaryKind-21;
var CWIOn = bits.test(notification.Flags, 2);
var index = DamageRecipient.emesaryID2typeID(notification.SecondaryKind);
var typ = id2warhead[index];
if (notification.Kind == MOVE) {
@@ -334,7 +347,7 @@ var DamageRecipient =
dynamics["noti_"~notification.Callsign~"_"~notification.UniqueIdentity] = [systime()-(time_before_delete-1.6), notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.u_fps, notification.Heading, notification.Pitch,-1]
}
if (tacview_supported and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
if (tacview_supported and (getprop("sim/multiplay/txhost") != "mpserver.opredflag.com" or m28_auto)) {
if (tacview.starttime) {
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity),6);
if (notification.Kind == DESTROY) {
@@ -348,7 +361,7 @@ var DamageRecipient =
var extra2 = typ[2]==0?",Type=Weapon+Missile":",Type=Weapon+Bomb";
extra2 = typ[4]=="Flare"?",Type=Flare":extra2;
extra2 = typp=="Parachutist"?"":extra2;
var color = radarOn?",Color=Red":",Color=Yellow";
var color = radarOn or CWIOn?",Color=Red":",Color=Yellow";
thread.lock(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(tacID~",T="~notification.Position.lon()~"|"~notification.Position.lat()~"|"~notification.Position.alt()~extra~",Name="~typp~color~extra2~"\n");
@@ -376,9 +389,10 @@ var DamageRecipient =
setprop("payload/armament/MLW-launcher", notification.Callsign);
setprop("payload/armament/MLW-count", getprop("payload/armament/MLW-count")+1);
var out = sprintf("Missile Launch Warning from %03d degrees.", bearing);
if (rwr_to_screen) screen.log.write(out, 1,1,0);# temporary till someone models a RWR in RIO seat
if (rwr_to_screen) screen.log.write(out, 1,0.5,0);# temporary till someone models a RWR in RIO seat
print(out);
damageLog.push(sprintf("Missile Launch Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (m28_auto) mig28.missileLaunch();
}
}
}
@@ -386,19 +400,30 @@ var DamageRecipient =
# Missile approach warning:
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign != callsign) return emesary.Transmitter.ReceiptStatus_OK;
if (!radarOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
var heading = getprop("orientation/heading-deg");
var clock = geo.normdeg(bearing - heading);
setprop("payload/armament/MAW-bearing", bearing);
setprop("payload/armament/MAW-active", 1);# resets every 1 seconds
if (!radarOn and !CWIOn) return emesary.Transmitter.ReceiptStatus_OK;# this should be little more complex later
#var heading = getprop("orientation/heading-deg");
#var clock = geo.normdeg(bearing - heading);
if (radarOn) {
setprop("payload/armament/MAW-bearing", bearing);
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];
if (appr == nil or elapsed - appr > 450) {
printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,1,0);# temporary till someone models a RWR in RIO seat
if (radarOn) {
#printf("Missile Approach Warning from %03d degrees.", bearing);
damageLog.push(sprintf("Missile Approach Warning from %03d degrees from %s.", bearing, notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning from %03d degrees.", bearing), 1,0.5,0);# temporary till someone models a RWR in RIO seat
} else {
#printf("Missile Approach Warning");
damageLog.push(sprintf("Missile Approach Warning from %s.", notification.Callsign));
if (rwr_to_screen) screen.log.write(sprintf("Missile Approach Warning (semi-active)."), 1,0.5,0);# temporary till someone models a RWR in RIO seat
}
approached[notification.Callsign~notification.UniqueIdentity] = elapsed;
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (m28_auto) mig28.engagedBy(notification.Callsign, 1);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
@@ -415,11 +440,11 @@ var DamageRecipient =
# debug.dump(notification);
#
#
if (tacview_supported and tacview.starttime and getprop("sim/multiplay/txhost") != "mpserver.opredflag.com") {
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);
@@ -439,9 +464,10 @@ var DamageRecipient =
var callsign = processCallsign(getprop("sim/multiplay/callsign"));
if (notification.RemoteCallsign == callsign and getprop("payload/armament/msg") == 1) {
#damage enabled and were getting hit
if (m28_auto) mig28.engagedBy(notification.Callsign);
if (notification.SecondaryKind < 0 and hitable_by_cannon) {
# cannon hit
if (m28_auto) mig28.engagedBy(notification.Callsign, 0);
var probability = id2shell[-1*notification.SecondaryKind-1][1];
var typ = id2shell[-1*notification.SecondaryKind-1][2];
var hit_count = notification.Distance;
@@ -455,10 +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
@@ -549,21 +576,18 @@ var DamageRecipient =
}
if (notification.Kind == CREATE and getprop("payload/armament/enable-craters") == 1 and statics["obj_"~notification.UniqueIdentity] == nil) {
if (notification.SecondaryKind == 0) {# TODO: make a hash with all the models
var crater_model = getprop("payload/armament/models") ~ "crater_small.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model0, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
#static is a PropertyNode inside /models
}
} elsif (notification.SecondaryKind == 1) {
var crater_model = getprop("payload/armament/models") ~ "crater_big.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model1, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
} elsif (notification.SecondaryKind == 2) {
var crater_model = getprop("payload/armament/models") ~ "bomb_hit_smoke.xml";
var static = geo.put_model(crater_model, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
var static = geo.put_model(crater_model2, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading);
if (static != nil) {
statics["obj_"~notification.UniqueIdentity] = [static, notification.Position.lat(), notification.Position.lon(), notification.Position.alt(), notification.Heading, notification.SecondaryKind];
}
@@ -586,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");
@@ -863,6 +909,7 @@ var flare_update_time = 0.4;
var flare_duration = 8;
var flare_terminal_speed = 50;#m/s
var flares_max_process_per_loop = 4;
var flare_sequencer = -120;
var flare_sorter = func(a, b) {
if(a[0] < b[0]){
@@ -945,7 +992,9 @@ var flare_released = func {
getprop("orientation/heading-deg"),
FT2M*getprop("velocities/speed-down-fps"),
FT2M*math.sqrt(getprop("velocities/speed-north-fps")*getprop("velocities/speed-north-fps")+getprop("velocities/speed-east-fps")*getprop("velocities/speed-east-fps")),
int(rand()*240)-120];
flare_sequencer];
flare_sequencer += 1;
if (flare_sequencer > 120) flare_sequencer = -120;
append(flare_list, flare);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
@@ -1087,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;
}
@@ -1116,6 +1205,51 @@ var repairYasim = func {
}
}
var setupYasimEngines = func {
if (getprop("engines/engine/n1") != nil and !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("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 !hasMode("engines/engine[7]")) {
var e7 = compat_failure_modes.fail_engine("engine[7]");
FailureMgr.add_failure_mode("engines/engine[7]", "Engine 8", e7);
}
}
settimer(setupYasimEngines, 150);
var hasMode = func (test) {
# Tests if a failure mode exist already
var modes = FailureMgr.get_failure_modes();
foreach(mode;modes) {
if (mode["id"]==test) return 1;
}
return 0;
}
setlistener("/sim/signals/reinit", repairYasim);
hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
@@ -1233,7 +1367,7 @@ var processCallsigns = func () {
var painted = 0;
var paint_list = [];
foreach (var player; players) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
if(player.getChild("valid") != nil and player.getChild("valid").getValue() == 1 and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) {
var callsign = player.getChild("callsign").getValue();
callsign_struct[callsign] = player;
var str6 = player.getNode("sim/multiplay/generic/string[6]");
@@ -1247,6 +1381,8 @@ 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:
@@ -1293,16 +1429,16 @@ processCallsignsTimer.start();
var code_ct = func () {
#ANTIC
if (getprop("payload/armament/msg")) {
setprop("sim/rendering/redout/enabled", TRUE);
setprop("sim/rendering/redout/enabled", 1);
#call(func{fgcommand('dialog-close', multiplayer.dialog.dialog.prop())},nil,var err= []);# props.Node.new({"dialog-name": "location-in-air"}));
call(func{multiplayer.dialog.del();},nil,var err= []);
if (!m28_auto) call(func{multiplayer.dialog.del();},nil,var err= []);
if (!getprop("gear/gear[0]/wow")) {
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "WeightAndFuel"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "system-failures"}))},nil,var err2 = []);
call(func{fgcommand('dialog-close', props.Node.new({"dialog-name": "instrument-failures"}))},nil,var err2 = []);
}
setprop("sim/freeze/fuel",0);
setprop("/sim/speed-up", 1);
if (!m28_auto) setprop("/sim/speed-up", 1);
setprop("/gui/map/draw-traffic", 0);
setprop("/sim/marker-pins/traffic", 0);
setprop("/sim/gui/dialogs/map-canvas/draw-TFC", 0);
@@ -1317,7 +1453,7 @@ code_ctTimer.simulatedTime = 1;
setprop("/sim/failure-manager/display-on-screen", FALSE);
setprop("/sim/failure-manager/display-on-screen", 0);
code_ctTimer.start();
@@ -1337,6 +1473,22 @@ var re_init = func (node) {
}
stopLaunch();
damageLog.push("Aircraft was repaired due to re-init.");
# Remove all 3D craters and re-place them. Due to re-init can remove some of them.
foreach (var thekey ; keys(statics)) {
var sta = statics[thekey];
if (sta[0] != nil) {
sta[0].remove();
if (sta[5] == 0) {# TODO: make a hash with all the models
sta[0] = geo.put_model(crater_model0, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 1) {
sta[0] = geo.put_model(crater_model1, sta[1], sta[2], sta[3], sta[4]);
} elsif (sta[5] == 2) {
sta[0] = geo.put_model(crater_model2, sta[1], sta[2], sta[3], sta[4]);
}
}
}
}
#==================================================================
@@ -1401,10 +1553,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");
@@ -1412,7 +1579,9 @@ setlistener("sim/signals/exit", writeDamageLog, 0, 0);
#screen.property_display.add("payload/armament/spike-air");
#screen.property_display.add("payload/armament/spike-gnd-20");
#screen.property_display.add("payload/armament/spike-gnd-02");
#screen.property_display.add("payload/armament/spike-gnd-11");
#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-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");

View File

@@ -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();