Auto-Update shared Files

damage 1.4.10->1.4.11 (BUK-M2/Nasal/damage.nas)
damage 1.4.10->1.4.11 (depot/Nasal/damage.nas)
damage 1.4.10->1.4.11 (fleet/Nasal/damage.nas)
damage 1.4.10->1.4.11 (Frigate/Nasal/damage.nas)
damage 1.4.10->1.4.11 (gci-radar/Nasal/damage.nas)
damage 1.4.10->1.4.11 (groundtarget/Nasal/damage.nas)
damage 1.4.10->1.4.11 (MIM-104D/Nasal/damage.nas)
damage 1.4.10->1.4.11 (missile-frigate/Nasal/damage.nas)
damage 1.4.10->1.4.11 (S-200/Nasal/damage.nas)
damage 1.4.10->1.4.11 (S-300/Nasal/damage.nas)
damage 1.4.10->1.4.11 (S-75/Nasal/damage.nas)
damage 1.4.10->1.4.11 (SA-3/Nasal/damage.nas)
damage 1.4.10->1.4.11 (SA-6/Nasal/damage.nas)
damage 1.4.10->1.4.11 (ZSU-23/Nasal/damage.nas)
missile-code 1.1.6->1.1.7 (BUK-M2/Nasal/guided-missiles.nas)
missile-code 1.1.6->1.1.7 (MIM-104D/Nasal/guided-missiles.nas)
missile-code 1.1.6->1.1.7 (S-75/Nasal/guided-missiles.nas)
missile-code 1.1.6->1.1.7 (SA-3/Nasal/guided-missiles.nas)
missile-code 1.1.6->1.1.7 (SA-6/Nasal/guided-missiles.nas)
master
github-actions[bot] 4 months ago
parent a7e2485b6c
commit 277e173ef8

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -153,11 +153,13 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
var first_in_air_max_sec = 30;
#var versionString = getprop("sim/version/flightgear");
#var version = split(".", versionString);
#var major = num(version[0]);
#var minor = num(version[1]);
#var pica = num(version[2]);
var versionString = getprop("sim/version/flightgear");
var version = split(".", versionString);
var major = num(version[0]);
var minor = num(version[1]);
var pica = num(version[2]);
var sep_thread = getprop("payload/threading") != nil or !(major == 2020 and minor == 4);#Bug in 2020.4.0 threadsafe properties makes this needed.
var wingedGuideFactor = 0.1;
@ -914,7 +916,7 @@ var AIM = {
m.standby();# these loops will run until released or deleted.
#for multithreading
m.frameToggle = thread.newsem();
if (sep_thread) m.frameToggle = thread.newsem();
m.myMath = {parents:[vector.Math],};#personal vector library, to avoid using a mutex on it.
return AIM.active[m.ID] = m;
@ -927,13 +929,14 @@ var AIM = {
#
# Note: Must never be called from the flight loop thread.
#
if (me.deleted) return;
me.printCode("deleted weapon");
if (me["frameLoop"] != nil) {
me.frameLoop.stop();
me.frameLoop = nil;
}
me.deleted = 1;
thread.semup(me.frameToggle);
if (sep_thread) thread.semup(me.frameToggle);
if (me.first) {
me.resetFirst();
}
@ -943,17 +946,17 @@ var AIM = {
delete(AIM.flying, me.flyID);
if (me.tacview_support) {
if (tacview.starttime) {
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write("-"~me.tacviewID~"\n");
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
#lat,lon,alt,rdar,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
unlockMutex(mutexTimer);
}
} else {
delete(AIM.active, me.ID);
@ -1763,6 +1766,12 @@ var AIM = {
loadNode.remove();
if(!sep_thread) {
me.flightTimer = maketimer(0, me, me.flight);
me.flightTimer.start();
me.flight();
return;
}
# lets run the main flight loop in its own thread:
var frameTrigger = func {
thread.semup(me.frameToggle);
@ -2100,12 +2109,13 @@ var AIM = {
},
flight: func {
while(1==1) {
if(me.deleted) {
me.nofun = 1;
while(sep_thread or me.nofun) {
me.nofun = 0;
if(me.deleted or me["stopFlight"] == 1) {
return;
}
thread.semdown(me.frameToggle);
if (sep_thread) thread.semdown(me.frameToggle);
if(me.deleted) {
return;
}
@ -2182,10 +2192,10 @@ var AIM = {
if (!(me.canSwitch and me.reaquire)) {
me.printStats(me.type~": Target went away, deleting missile.");
#me.sendMessage(me.type~" missed "~me.callsign~": Target logged off.");
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],0]);
append(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],0]);
appendTimer(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
unlockMutex(mutexTimer);
AIM.setETA(nil);
return;
} else {
@ -2546,10 +2556,10 @@ var AIM = {
if (tacview.starttime and math.mod(me.counter, 3) == 0) {
me.nme = me.type=="es"?"Parachutist":me.type;
me.extra = me.type=="es"?"|0|0|0":"";
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(me.tacviewID~",T="~me.coord.lon()~"|"~me.coord.lat()~"|"~(me.alt_ft*FT2M)~me.extra~",Name="~me.nme~",Parent="~tacview.myplaneID~"\n");#,Type=Weapon+Missile
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
@ -2585,15 +2595,16 @@ var AIM = {
me.sndDistance = 0;
me.elapsed_last_snd = systime();
if (me.explodeSound) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.sndPropagate,[],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.sndPropagate,[],0]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],10]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],10]);
unlockMutex(mutexTimer);
}
AIM.setETA(nil);
me.stopFlight = 1;
return;
}
}
@ -2671,11 +2682,11 @@ var AIM = {
if (me.life_time - me.last_noti > me.noti_time and getprop("payload/armament/msg")) {
# notify in flight using Emesary.
me.last_noti = me.life_time;
thread.lock(mutexTimer);
lockMutex(mutexTimer);
var rdr = me.guidance=="radar";
var semiRdr = (me.guidance=="semi-radar" and !me.semiLostLock) or (me.guidance=="command" and me.guiding);# Continous wave illuminator active on the target
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
unlockMutex(mutexTimer);
}
me.last_dt = me.dt;
@ -2685,9 +2696,9 @@ var AIM = {
if (me.counter > -1 and !me.ai.getNode("valid").getBoolValue()) {
# TODO: Why is this placed so late? Don't remember.
me.ai.getNode("valid").setBoolValue(1);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
unlockMutex(mutexTimer);
}
#############################################################################################################
#
@ -3209,17 +3220,17 @@ var AIM = {
me.free = 1;
me.guiding = 0;
} elsif (me.blep.getID() != me["blepID"]) {
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.blepID = me.blep.getID();
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.blepIDtime = me.life_time;
me.t_coord_sampled = me.t_coord;
} elsif (me["blepIDtime"] != nil) {
me.dtTrack = me.life_time - me.blepIDtime;
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.ecefVel = me.blep.getECEFVelocity();
me.blep_coord = geo.Coord.new(me.blep.getCoord());
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.t_coord_sampled = geo.Coord.new();
# dead-reckon:
@ -3320,7 +3331,7 @@ var AIM = {
# target has released a new flare, lets check if it fools us
me.flareTime = me.life_time;
me.flareLast = me.flareNumber;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
#me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.flareLock = rand() < (1-me.flareResistance);
if (me.flareLock) {
# fooled by the flare
@ -3353,10 +3364,10 @@ var AIM = {
# target has released a new chaff, lets check if it blinds us
me.chaffLast = me.chaffNumber;
me.chaffTime = me.life_time;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.redux = me.guidance == "semi-radar" or me.guidance == "command" or me.guidance == "tvm"?(me.gnd_launch?0.5:0.75):1;
me.chaffChance = (1-me.chaffResistance)*me.redux;
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectDeg));# 70% less chance to be fooled if front aspect
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectNorm));# 70% less chance to be fooled if front aspect
if (me.chaffLock) {
me.printStats(me.type~": Missile locked on chaff from "~me.callsign);
@ -4210,7 +4221,7 @@ var AIM = {
if(me.life_time < me.arming_time) {
me.event = "landed disarmed";
#thread.lock(mutexTimer);
#append(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#appendTimer(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#thread.unlock(mutexTimer);
}
if (me.Tgt != nil and me.direct_dist_m == nil) {
@ -4418,16 +4429,16 @@ var AIM = {
me.coord = coordinates; # Set the current missile coordinates at the explosion point.
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
unlockMutex(mutexTimer);
}
var wh_mass = (event == "exploded" and !me.inert) ? me.weight_whead_lbm : 0; #will report 0 mass if did not have time to arm
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
unlockMutex(mutexTimer);
if (!me.inert) {
var phrase = nil;
@ -4452,28 +4463,28 @@ var AIM = {
if (phrase != nil) {
me.printStats("%s time %.1f", phrase, me.life_time);
if(getprop("payload/armament/msg") and hitPrimaryTarget and wh_mass > 0){
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
if (me.multiHit and !me.multiExplosion(coordinates, event, wh_mass) and me.Tgt != nil and me.Tgt.isVirtual()) {
phrase = sprintf(me.type~" "~event);
me.printStats("%s Reason: %s time %.1f", phrase, reason, me.life_time);
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
me.ai.getNode("valid", 1).setBoolValue(0);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
unlockMutex(mutexTimer);
if (event == "exploded" and !me.inert and wh_mass > 0) {
me.animate_explosion(hitGround);
me.explodeSound = 1;
@ -4500,13 +4511,13 @@ var AIM = {
if(getprop("payload/armament/msg") and wh_mass > 0){
var cs = damage.processCallsign(me.testMe.get_Callsign());
var cc = me.testMe.get_Coord();
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
unlockMutex(mutexTimer);
} elsif (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
@ -4520,9 +4531,9 @@ var AIM = {
var phrase = sprintf("%s %s: %.1f meters from: %s", me.type,event, min_distance, cs);# if we mention ourself then we need to explicit add ourself as author.
me.printStats(phrase);
if (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
}
@ -5498,21 +5509,21 @@ var AIM = {
me.explode_prop.setBoolValue(1);
me.explode_angle_prop.setDoubleValue((rand() - 0.5) * 50);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
append(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
append(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
unlockMutex(mutexTimer);
if (info == nil or !hitGround or getprop("payload/armament/enable-craters") == nil or !getprop("payload/armament/enable-craters")) {return;};
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func {
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func {
if (info[1] == nil) {
#print ("Building hit..smoking");
var static = geo.put_model(getprop("payload/armament/models") ~ "bomb_hit_smoke.xml", me.coord.lat(), me.coord.lon());
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
unlockMutex(mutexTimer);
}
} else if ((info[1] != nil) and info[1].solid) {
var crater_model = "";
@ -5531,14 +5542,14 @@ var AIM = {
var static = geo.put_model(crater_model, me.coord.lat(), me.coord.lon());
#print("put crater");
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
unlockMutex(mutexTimer);
}
}
}
}, [], 0.5]);
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
},
animate_dud: func {
@ -5745,79 +5756,79 @@ var AIM = {
printFlight: func {
if (DEBUG_FLIGHT) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printFlightDetails: func {
if (DEBUG_FLIGHT_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStats: func {
if (DEBUG_STATS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStatsDetails: func {
if (DEBUG_STATS_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuide: func {
if (DEBUG_GUIDANCE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuideDetails: func {
if (DEBUG_GUIDANCE_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printCode: func {
if (DEBUG_CODE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printSearch: func {
if (DEBUG_SEARCH) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printAlways: func {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
},
timerLoop: func {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
AIM.tq = AIM.timerQueue;
AIM.timerQueue = [];
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
foreach(var cmd; AIM.tq) {
AIM.timerCall(cmd);
}
@ -5858,7 +5869,7 @@ var AIM = {
setETA: func (eta, prev = -1) {
# Class method
thread.lock(mutexETA);
lockMutex(mutexETA);
if (eta == -1 and prev == AIM.lowestETA) {
AIM.lowestETA = nil;
} elsif (eta == nil) {
@ -5866,14 +5877,14 @@ var AIM = {
} elsif (AIM.lowestETA == nil or eta < AIM.lowestETA and eta < 1800) {
AIM.lowestETA = eta;
}
thread.unlock(mutexETA);
unlockMutex(mutexETA);
},
getETA: func {
# Class method
var retur = 0;
thread.lock(mutexETA);
lockMutex(mutexETA);
retur = AIM.lowestETA;
thread.unlock(mutexETA);
unlockMutex(mutexETA);
return retur;
},
@ -5885,6 +5896,22 @@ var AIM = {
setprop("ai/models/model-removed", me.ai.getPath());
},
};
var appendTimer = func (queue, cmd) {
if (sep_thread) {
append(AIM.timerQueue, cmd);
} else {
call(cmd[1], cmd[2], cmd[0], nil, var err = []);
debug.printerror(err);
}
}
var lockMutex = func (m) {
if (sep_thread) thread.lock(m);
}
var unlockMutex = func (m) {
if (sep_thread) thread.unlock(m);
}
var backtrace = func(desc = nil, dump_vars = 1, skip_level = 0, levels = 3) {
var d = (desc == nil) ? "" : " '" ~ desc ~ "'";
print("");
@ -5992,7 +6019,7 @@ var mutexTimer = thread.newlock();
var mutexETA = thread.newlock();
var defeatSpamFilter = func (str) {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
spams += 1;
if (spams == 15) {
spams = 1;
@ -6010,13 +6037,13 @@ var defeatSpamFilter = func (str) {
append(newList, spamList[i]);
}
spamList = newList;
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
}
var spamLoop = func {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
var spam = pop(spamList);
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
if (spam != nil) {
setprop("/sim/multiplay/chat", spam);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -153,11 +153,13 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
var first_in_air_max_sec = 30;
#var versionString = getprop("sim/version/flightgear");
#var version = split(".", versionString);
#var major = num(version[0]);
#var minor = num(version[1]);
#var pica = num(version[2]);
var versionString = getprop("sim/version/flightgear");
var version = split(".", versionString);
var major = num(version[0]);
var minor = num(version[1]);
var pica = num(version[2]);
var sep_thread = getprop("payload/threading") != nil or !(major == 2020 and minor == 4);#Bug in 2020.4.0 threadsafe properties makes this needed.
var wingedGuideFactor = 0.1;
@ -914,7 +916,7 @@ var AIM = {
m.standby();# these loops will run until released or deleted.
#for multithreading
m.frameToggle = thread.newsem();
if (sep_thread) m.frameToggle = thread.newsem();
m.myMath = {parents:[vector.Math],};#personal vector library, to avoid using a mutex on it.
return AIM.active[m.ID] = m;
@ -927,13 +929,14 @@ var AIM = {
#
# Note: Must never be called from the flight loop thread.
#
if (me.deleted) return;
me.printCode("deleted weapon");
if (me["frameLoop"] != nil) {
me.frameLoop.stop();
me.frameLoop = nil;
}
me.deleted = 1;
thread.semup(me.frameToggle);
if (sep_thread) thread.semup(me.frameToggle);
if (me.first) {
me.resetFirst();
}
@ -943,17 +946,17 @@ var AIM = {
delete(AIM.flying, me.flyID);
if (me.tacview_support) {
if (tacview.starttime) {
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write("-"~me.tacviewID~"\n");
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
#lat,lon,alt,rdar,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
unlockMutex(mutexTimer);
}
} else {
delete(AIM.active, me.ID);
@ -1763,6 +1766,12 @@ var AIM = {
loadNode.remove();
if(!sep_thread) {
me.flightTimer = maketimer(0, me, me.flight);
me.flightTimer.start();
me.flight();
return;
}
# lets run the main flight loop in its own thread:
var frameTrigger = func {
thread.semup(me.frameToggle);
@ -2100,12 +2109,13 @@ var AIM = {
},
flight: func {
while(1==1) {
if(me.deleted) {
me.nofun = 1;
while(sep_thread or me.nofun) {
me.nofun = 0;
if(me.deleted or me["stopFlight"] == 1) {
return;
}
thread.semdown(me.frameToggle);
if (sep_thread) thread.semdown(me.frameToggle);
if(me.deleted) {
return;
}
@ -2182,10 +2192,10 @@ var AIM = {
if (!(me.canSwitch and me.reaquire)) {
me.printStats(me.type~": Target went away, deleting missile.");
#me.sendMessage(me.type~" missed "~me.callsign~": Target logged off.");
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],0]);
append(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],0]);
appendTimer(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
unlockMutex(mutexTimer);
AIM.setETA(nil);
return;
} else {
@ -2546,10 +2556,10 @@ var AIM = {
if (tacview.starttime and math.mod(me.counter, 3) == 0) {
me.nme = me.type=="es"?"Parachutist":me.type;
me.extra = me.type=="es"?"|0|0|0":"";
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(me.tacviewID~",T="~me.coord.lon()~"|"~me.coord.lat()~"|"~(me.alt_ft*FT2M)~me.extra~",Name="~me.nme~",Parent="~tacview.myplaneID~"\n");#,Type=Weapon+Missile
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
@ -2585,15 +2595,16 @@ var AIM = {
me.sndDistance = 0;
me.elapsed_last_snd = systime();
if (me.explodeSound) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.sndPropagate,[],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.sndPropagate,[],0]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],10]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],10]);
unlockMutex(mutexTimer);
}
AIM.setETA(nil);
me.stopFlight = 1;
return;
}
}
@ -2671,11 +2682,11 @@ var AIM = {
if (me.life_time - me.last_noti > me.noti_time and getprop("payload/armament/msg")) {
# notify in flight using Emesary.
me.last_noti = me.life_time;
thread.lock(mutexTimer);
lockMutex(mutexTimer);
var rdr = me.guidance=="radar";
var semiRdr = (me.guidance=="semi-radar" and !me.semiLostLock) or (me.guidance=="command" and me.guiding);# Continous wave illuminator active on the target
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
unlockMutex(mutexTimer);
}
me.last_dt = me.dt;
@ -2685,9 +2696,9 @@ var AIM = {
if (me.counter > -1 and !me.ai.getNode("valid").getBoolValue()) {
# TODO: Why is this placed so late? Don't remember.
me.ai.getNode("valid").setBoolValue(1);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
unlockMutex(mutexTimer);
}
#############################################################################################################
#
@ -3209,17 +3220,17 @@ var AIM = {
me.free = 1;
me.guiding = 0;
} elsif (me.blep.getID() != me["blepID"]) {
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.blepID = me.blep.getID();
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.blepIDtime = me.life_time;
me.t_coord_sampled = me.t_coord;
} elsif (me["blepIDtime"] != nil) {
me.dtTrack = me.life_time - me.blepIDtime;
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.ecefVel = me.blep.getECEFVelocity();
me.blep_coord = geo.Coord.new(me.blep.getCoord());
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.t_coord_sampled = geo.Coord.new();
# dead-reckon:
@ -3320,7 +3331,7 @@ var AIM = {
# target has released a new flare, lets check if it fools us
me.flareTime = me.life_time;
me.flareLast = me.flareNumber;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
#me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.flareLock = rand() < (1-me.flareResistance);
if (me.flareLock) {
# fooled by the flare
@ -3353,10 +3364,10 @@ var AIM = {
# target has released a new chaff, lets check if it blinds us
me.chaffLast = me.chaffNumber;
me.chaffTime = me.life_time;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.redux = me.guidance == "semi-radar" or me.guidance == "command" or me.guidance == "tvm"?(me.gnd_launch?0.5:0.75):1;
me.chaffChance = (1-me.chaffResistance)*me.redux;
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectDeg));# 70% less chance to be fooled if front aspect
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectNorm));# 70% less chance to be fooled if front aspect
if (me.chaffLock) {
me.printStats(me.type~": Missile locked on chaff from "~me.callsign);
@ -4210,7 +4221,7 @@ var AIM = {
if(me.life_time < me.arming_time) {
me.event = "landed disarmed";
#thread.lock(mutexTimer);
#append(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#appendTimer(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#thread.unlock(mutexTimer);
}
if (me.Tgt != nil and me.direct_dist_m == nil) {
@ -4418,16 +4429,16 @@ var AIM = {
me.coord = coordinates; # Set the current missile coordinates at the explosion point.
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
unlockMutex(mutexTimer);
}
var wh_mass = (event == "exploded" and !me.inert) ? me.weight_whead_lbm : 0; #will report 0 mass if did not have time to arm
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
unlockMutex(mutexTimer);
if (!me.inert) {
var phrase = nil;
@ -4452,28 +4463,28 @@ var AIM = {
if (phrase != nil) {
me.printStats("%s time %.1f", phrase, me.life_time);
if(getprop("payload/armament/msg") and hitPrimaryTarget and wh_mass > 0){
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
if (me.multiHit and !me.multiExplosion(coordinates, event, wh_mass) and me.Tgt != nil and me.Tgt.isVirtual()) {
phrase = sprintf(me.type~" "~event);
me.printStats("%s Reason: %s time %.1f", phrase, reason, me.life_time);
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
me.ai.getNode("valid", 1).setBoolValue(0);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
unlockMutex(mutexTimer);
if (event == "exploded" and !me.inert and wh_mass > 0) {
me.animate_explosion(hitGround);
me.explodeSound = 1;
@ -4500,13 +4511,13 @@ var AIM = {
if(getprop("payload/armament/msg") and wh_mass > 0){
var cs = damage.processCallsign(me.testMe.get_Callsign());
var cc = me.testMe.get_Coord();
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
unlockMutex(mutexTimer);
} elsif (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
@ -4520,9 +4531,9 @@ var AIM = {
var phrase = sprintf("%s %s: %.1f meters from: %s", me.type,event, min_distance, cs);# if we mention ourself then we need to explicit add ourself as author.
me.printStats(phrase);
if (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
}
@ -5498,21 +5509,21 @@ var AIM = {
me.explode_prop.setBoolValue(1);
me.explode_angle_prop.setDoubleValue((rand() - 0.5) * 50);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
append(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
append(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
unlockMutex(mutexTimer);
if (info == nil or !hitGround or getprop("payload/armament/enable-craters") == nil or !getprop("payload/armament/enable-craters")) {return;};
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func {
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func {
if (info[1] == nil) {
#print ("Building hit..smoking");
var static = geo.put_model(getprop("payload/armament/models") ~ "bomb_hit_smoke.xml", me.coord.lat(), me.coord.lon());
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
unlockMutex(mutexTimer);
}
} else if ((info[1] != nil) and info[1].solid) {
var crater_model = "";
@ -5531,14 +5542,14 @@ var AIM = {
var static = geo.put_model(crater_model, me.coord.lat(), me.coord.lon());
#print("put crater");
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
unlockMutex(mutexTimer);
}
}
}
}, [], 0.5]);
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
},
animate_dud: func {
@ -5745,79 +5756,79 @@ var AIM = {
printFlight: func {
if (DEBUG_FLIGHT) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printFlightDetails: func {
if (DEBUG_FLIGHT_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStats: func {
if (DEBUG_STATS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStatsDetails: func {
if (DEBUG_STATS_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuide: func {
if (DEBUG_GUIDANCE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuideDetails: func {
if (DEBUG_GUIDANCE_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printCode: func {
if (DEBUG_CODE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printSearch: func {
if (DEBUG_SEARCH) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printAlways: func {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
},
timerLoop: func {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
AIM.tq = AIM.timerQueue;
AIM.timerQueue = [];
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
foreach(var cmd; AIM.tq) {
AIM.timerCall(cmd);
}
@ -5858,7 +5869,7 @@ var AIM = {
setETA: func (eta, prev = -1) {
# Class method
thread.lock(mutexETA);
lockMutex(mutexETA);
if (eta == -1 and prev == AIM.lowestETA) {
AIM.lowestETA = nil;
} elsif (eta == nil) {
@ -5866,14 +5877,14 @@ var AIM = {
} elsif (AIM.lowestETA == nil or eta < AIM.lowestETA and eta < 1800) {
AIM.lowestETA = eta;
}
thread.unlock(mutexETA);
unlockMutex(mutexETA);
},
getETA: func {
# Class method
var retur = 0;
thread.lock(mutexETA);
lockMutex(mutexETA);
retur = AIM.lowestETA;
thread.unlock(mutexETA);
unlockMutex(mutexETA);
return retur;
},
@ -5885,6 +5896,22 @@ var AIM = {
setprop("ai/models/model-removed", me.ai.getPath());
},
};
var appendTimer = func (queue, cmd) {
if (sep_thread) {
append(AIM.timerQueue, cmd);
} else {
call(cmd[1], cmd[2], cmd[0], nil, var err = []);
debug.printerror(err);
}
}
var lockMutex = func (m) {
if (sep_thread) thread.lock(m);
}
var unlockMutex = func (m) {
if (sep_thread) thread.unlock(m);
}
var backtrace = func(desc = nil, dump_vars = 1, skip_level = 0, levels = 3) {
var d = (desc == nil) ? "" : " '" ~ desc ~ "'";
print("");
@ -5992,7 +6019,7 @@ var mutexTimer = thread.newlock();
var mutexETA = thread.newlock();
var defeatSpamFilter = func (str) {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
spams += 1;
if (spams == 15) {
spams = 1;
@ -6010,13 +6037,13 @@ var defeatSpamFilter = func (str) {
append(newList, spamList[i]);
}
spamList = newList;
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
}
var spamLoop = func {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
var spam = pop(spamList);
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
if (spam != nil) {
setprop("/sim/multiplay/chat", spam);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -153,11 +153,13 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
var first_in_air_max_sec = 30;
#var versionString = getprop("sim/version/flightgear");
#var version = split(".", versionString);
#var major = num(version[0]);
#var minor = num(version[1]);
#var pica = num(version[2]);
var versionString = getprop("sim/version/flightgear");
var version = split(".", versionString);
var major = num(version[0]);
var minor = num(version[1]);
var pica = num(version[2]);
var sep_thread = getprop("payload/threading") != nil or !(major == 2020 and minor == 4);#Bug in 2020.4.0 threadsafe properties makes this needed.
var wingedGuideFactor = 0.1;
@ -914,7 +916,7 @@ var AIM = {
m.standby();# these loops will run until released or deleted.
#for multithreading
m.frameToggle = thread.newsem();
if (sep_thread) m.frameToggle = thread.newsem();
m.myMath = {parents:[vector.Math],};#personal vector library, to avoid using a mutex on it.
return AIM.active[m.ID] = m;
@ -927,13 +929,14 @@ var AIM = {
#
# Note: Must never be called from the flight loop thread.
#
if (me.deleted) return;
me.printCode("deleted weapon");
if (me["frameLoop"] != nil) {
me.frameLoop.stop();
me.frameLoop = nil;
}
me.deleted = 1;
thread.semup(me.frameToggle);
if (sep_thread) thread.semup(me.frameToggle);
if (me.first) {
me.resetFirst();
}
@ -943,17 +946,17 @@ var AIM = {
delete(AIM.flying, me.flyID);
if (me.tacview_support) {
if (tacview.starttime) {
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write("-"~me.tacviewID~"\n");
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
#lat,lon,alt,rdar,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
unlockMutex(mutexTimer);
}
} else {
delete(AIM.active, me.ID);
@ -1763,6 +1766,12 @@ var AIM = {
loadNode.remove();
if(!sep_thread) {
me.flightTimer = maketimer(0, me, me.flight);
me.flightTimer.start();
me.flight();
return;
}
# lets run the main flight loop in its own thread:
var frameTrigger = func {
thread.semup(me.frameToggle);
@ -2100,12 +2109,13 @@ var AIM = {
},
flight: func {
while(1==1) {
if(me.deleted) {
me.nofun = 1;
while(sep_thread or me.nofun) {
me.nofun = 0;
if(me.deleted or me["stopFlight"] == 1) {
return;
}
thread.semdown(me.frameToggle);
if (sep_thread) thread.semdown(me.frameToggle);
if(me.deleted) {
return;
}
@ -2182,10 +2192,10 @@ var AIM = {
if (!(me.canSwitch and me.reaquire)) {
me.printStats(me.type~": Target went away, deleting missile.");
#me.sendMessage(me.type~" missed "~me.callsign~": Target logged off.");
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],0]);
append(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],0]);
appendTimer(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
unlockMutex(mutexTimer);
AIM.setETA(nil);
return;
} else {
@ -2546,10 +2556,10 @@ var AIM = {
if (tacview.starttime and math.mod(me.counter, 3) == 0) {
me.nme = me.type=="es"?"Parachutist":me.type;
me.extra = me.type=="es"?"|0|0|0":"";
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(me.tacviewID~",T="~me.coord.lon()~"|"~me.coord.lat()~"|"~(me.alt_ft*FT2M)~me.extra~",Name="~me.nme~",Parent="~tacview.myplaneID~"\n");#,Type=Weapon+Missile
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
@ -2585,15 +2595,16 @@ var AIM = {
me.sndDistance = 0;
me.elapsed_last_snd = systime();
if (me.explodeSound) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.sndPropagate,[],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.sndPropagate,[],0]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],10]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],10]);
unlockMutex(mutexTimer);
}
AIM.setETA(nil);
me.stopFlight = 1;
return;
}
}
@ -2671,11 +2682,11 @@ var AIM = {
if (me.life_time - me.last_noti > me.noti_time and getprop("payload/armament/msg")) {
# notify in flight using Emesary.
me.last_noti = me.life_time;
thread.lock(mutexTimer);
lockMutex(mutexTimer);
var rdr = me.guidance=="radar";
var semiRdr = (me.guidance=="semi-radar" and !me.semiLostLock) or (me.guidance=="command" and me.guiding);# Continous wave illuminator active on the target
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
unlockMutex(mutexTimer);
}
me.last_dt = me.dt;
@ -2685,9 +2696,9 @@ var AIM = {
if (me.counter > -1 and !me.ai.getNode("valid").getBoolValue()) {
# TODO: Why is this placed so late? Don't remember.
me.ai.getNode("valid").setBoolValue(1);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
unlockMutex(mutexTimer);
}
#############################################################################################################
#
@ -3209,17 +3220,17 @@ var AIM = {
me.free = 1;
me.guiding = 0;
} elsif (me.blep.getID() != me["blepID"]) {
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.blepID = me.blep.getID();
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.blepIDtime = me.life_time;
me.t_coord_sampled = me.t_coord;
} elsif (me["blepIDtime"] != nil) {
me.dtTrack = me.life_time - me.blepIDtime;
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.ecefVel = me.blep.getECEFVelocity();
me.blep_coord = geo.Coord.new(me.blep.getCoord());
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.t_coord_sampled = geo.Coord.new();
# dead-reckon:
@ -3320,7 +3331,7 @@ var AIM = {
# target has released a new flare, lets check if it fools us
me.flareTime = me.life_time;
me.flareLast = me.flareNumber;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
#me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.flareLock = rand() < (1-me.flareResistance);
if (me.flareLock) {
# fooled by the flare
@ -3353,10 +3364,10 @@ var AIM = {
# target has released a new chaff, lets check if it blinds us
me.chaffLast = me.chaffNumber;
me.chaffTime = me.life_time;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.redux = me.guidance == "semi-radar" or me.guidance == "command" or me.guidance == "tvm"?(me.gnd_launch?0.5:0.75):1;
me.chaffChance = (1-me.chaffResistance)*me.redux;
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectDeg));# 70% less chance to be fooled if front aspect
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectNorm));# 70% less chance to be fooled if front aspect
if (me.chaffLock) {
me.printStats(me.type~": Missile locked on chaff from "~me.callsign);
@ -4210,7 +4221,7 @@ var AIM = {
if(me.life_time < me.arming_time) {
me.event = "landed disarmed";
#thread.lock(mutexTimer);
#append(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#appendTimer(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#thread.unlock(mutexTimer);
}
if (me.Tgt != nil and me.direct_dist_m == nil) {
@ -4418,16 +4429,16 @@ var AIM = {
me.coord = coordinates; # Set the current missile coordinates at the explosion point.
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
unlockMutex(mutexTimer);
}
var wh_mass = (event == "exploded" and !me.inert) ? me.weight_whead_lbm : 0; #will report 0 mass if did not have time to arm
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
unlockMutex(mutexTimer);
if (!me.inert) {
var phrase = nil;
@ -4452,28 +4463,28 @@ var AIM = {
if (phrase != nil) {
me.printStats("%s time %.1f", phrase, me.life_time);
if(getprop("payload/armament/msg") and hitPrimaryTarget and wh_mass > 0){
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
if (me.multiHit and !me.multiExplosion(coordinates, event, wh_mass) and me.Tgt != nil and me.Tgt.isVirtual()) {
phrase = sprintf(me.type~" "~event);
me.printStats("%s Reason: %s time %.1f", phrase, reason, me.life_time);
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
me.ai.getNode("valid", 1).setBoolValue(0);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
unlockMutex(mutexTimer);
if (event == "exploded" and !me.inert and wh_mass > 0) {
me.animate_explosion(hitGround);
me.explodeSound = 1;
@ -4500,13 +4511,13 @@ var AIM = {
if(getprop("payload/armament/msg") and wh_mass > 0){
var cs = damage.processCallsign(me.testMe.get_Callsign());
var cc = me.testMe.get_Coord();
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
unlockMutex(mutexTimer);
} elsif (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
@ -4520,9 +4531,9 @@ var AIM = {
var phrase = sprintf("%s %s: %.1f meters from: %s", me.type,event, min_distance, cs);# if we mention ourself then we need to explicit add ourself as author.
me.printStats(phrase);
if (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
}
@ -5498,21 +5509,21 @@ var AIM = {
me.explode_prop.setBoolValue(1);
me.explode_angle_prop.setDoubleValue((rand() - 0.5) * 50);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
append(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
append(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
unlockMutex(mutexTimer);
if (info == nil or !hitGround or getprop("payload/armament/enable-craters") == nil or !getprop("payload/armament/enable-craters")) {return;};
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func {
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func {
if (info[1] == nil) {
#print ("Building hit..smoking");
var static = geo.put_model(getprop("payload/armament/models") ~ "bomb_hit_smoke.xml", me.coord.lat(), me.coord.lon());
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
unlockMutex(mutexTimer);
}
} else if ((info[1] != nil) and info[1].solid) {
var crater_model = "";
@ -5531,14 +5542,14 @@ var AIM = {
var static = geo.put_model(crater_model, me.coord.lat(), me.coord.lon());
#print("put crater");
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
unlockMutex(mutexTimer);
}
}
}
}, [], 0.5]);
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
},
animate_dud: func {
@ -5745,79 +5756,79 @@ var AIM = {
printFlight: func {
if (DEBUG_FLIGHT) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printFlightDetails: func {
if (DEBUG_FLIGHT_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStats: func {
if (DEBUG_STATS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStatsDetails: func {
if (DEBUG_STATS_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuide: func {
if (DEBUG_GUIDANCE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuideDetails: func {
if (DEBUG_GUIDANCE_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printCode: func {
if (DEBUG_CODE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printSearch: func {
if (DEBUG_SEARCH) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printAlways: func {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
},
timerLoop: func {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
AIM.tq = AIM.timerQueue;
AIM.timerQueue = [];
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
foreach(var cmd; AIM.tq) {
AIM.timerCall(cmd);
}
@ -5858,7 +5869,7 @@ var AIM = {
setETA: func (eta, prev = -1) {
# Class method
thread.lock(mutexETA);
lockMutex(mutexETA);
if (eta == -1 and prev == AIM.lowestETA) {
AIM.lowestETA = nil;
} elsif (eta == nil) {
@ -5866,14 +5877,14 @@ var AIM = {
} elsif (AIM.lowestETA == nil or eta < AIM.lowestETA and eta < 1800) {
AIM.lowestETA = eta;
}
thread.unlock(mutexETA);
unlockMutex(mutexETA);
},
getETA: func {
# Class method
var retur = 0;
thread.lock(mutexETA);
lockMutex(mutexETA);
retur = AIM.lowestETA;
thread.unlock(mutexETA);
unlockMutex(mutexETA);
return retur;
},
@ -5885,6 +5896,22 @@ var AIM = {
setprop("ai/models/model-removed", me.ai.getPath());
},
};
var appendTimer = func (queue, cmd) {
if (sep_thread) {
append(AIM.timerQueue, cmd);
} else {
call(cmd[1], cmd[2], cmd[0], nil, var err = []);
debug.printerror(err);
}
}
var lockMutex = func (m) {
if (sep_thread) thread.lock(m);
}
var unlockMutex = func (m) {
if (sep_thread) thread.unlock(m);
}
var backtrace = func(desc = nil, dump_vars = 1, skip_level = 0, levels = 3) {
var d = (desc == nil) ? "" : " '" ~ desc ~ "'";
print("");
@ -5992,7 +6019,7 @@ var mutexTimer = thread.newlock();
var mutexETA = thread.newlock();
var defeatSpamFilter = func (str) {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
spams += 1;
if (spams == 15) {
spams = 1;
@ -6010,13 +6037,13 @@ var defeatSpamFilter = func (str) {
append(newList, spamList[i]);
}
spamList = newList;
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
}
var spamLoop = func {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
var spam = pop(spamList);
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
if (spam != nil) {
setprop("/sim/multiplay/chat", spam);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -153,11 +153,13 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
var first_in_air_max_sec = 30;
#var versionString = getprop("sim/version/flightgear");
#var version = split(".", versionString);
#var major = num(version[0]);
#var minor = num(version[1]);
#var pica = num(version[2]);
var versionString = getprop("sim/version/flightgear");
var version = split(".", versionString);
var major = num(version[0]);
var minor = num(version[1]);
var pica = num(version[2]);
var sep_thread = getprop("payload/threading") != nil or !(major == 2020 and minor == 4);#Bug in 2020.4.0 threadsafe properties makes this needed.
var wingedGuideFactor = 0.1;
@ -914,7 +916,7 @@ var AIM = {
m.standby();# these loops will run until released or deleted.
#for multithreading
m.frameToggle = thread.newsem();
if (sep_thread) m.frameToggle = thread.newsem();
m.myMath = {parents:[vector.Math],};#personal vector library, to avoid using a mutex on it.
return AIM.active[m.ID] = m;
@ -927,13 +929,14 @@ var AIM = {
#
# Note: Must never be called from the flight loop thread.
#
if (me.deleted) return;
me.printCode("deleted weapon");
if (me["frameLoop"] != nil) {
me.frameLoop.stop();
me.frameLoop = nil;
}
me.deleted = 1;
thread.semup(me.frameToggle);
if (sep_thread) thread.semup(me.frameToggle);
if (me.first) {
me.resetFirst();
}
@ -943,17 +946,17 @@ var AIM = {
delete(AIM.flying, me.flyID);
if (me.tacview_support) {
if (tacview.starttime) {
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write("-"~me.tacviewID~"\n");
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
#lat,lon,alt,rdar,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
unlockMutex(mutexTimer);
}
} else {
delete(AIM.active, me.ID);
@ -1763,6 +1766,12 @@ var AIM = {
loadNode.remove();
if(!sep_thread) {
me.flightTimer = maketimer(0, me, me.flight);
me.flightTimer.start();
me.flight();
return;
}
# lets run the main flight loop in its own thread:
var frameTrigger = func {
thread.semup(me.frameToggle);
@ -2100,12 +2109,13 @@ var AIM = {
},
flight: func {
while(1==1) {
if(me.deleted) {
me.nofun = 1;
while(sep_thread or me.nofun) {
me.nofun = 0;
if(me.deleted or me["stopFlight"] == 1) {
return;
}
thread.semdown(me.frameToggle);
if (sep_thread) thread.semdown(me.frameToggle);
if(me.deleted) {
return;
}
@ -2182,10 +2192,10 @@ var AIM = {
if (!(me.canSwitch and me.reaquire)) {
me.printStats(me.type~": Target went away, deleting missile.");
#me.sendMessage(me.type~" missed "~me.callsign~": Target logged off.");
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],0]);
append(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],0]);
appendTimer(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
unlockMutex(mutexTimer);
AIM.setETA(nil);
return;
} else {
@ -2546,10 +2556,10 @@ var AIM = {
if (tacview.starttime and math.mod(me.counter, 3) == 0) {
me.nme = me.type=="es"?"Parachutist":me.type;
me.extra = me.type=="es"?"|0|0|0":"";
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(me.tacviewID~",T="~me.coord.lon()~"|"~me.coord.lat()~"|"~(me.alt_ft*FT2M)~me.extra~",Name="~me.nme~",Parent="~tacview.myplaneID~"\n");#,Type=Weapon+Missile
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
@ -2585,15 +2595,16 @@ var AIM = {
me.sndDistance = 0;
me.elapsed_last_snd = systime();
if (me.explodeSound) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.sndPropagate,[],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.sndPropagate,[],0]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],10]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],10]);
unlockMutex(mutexTimer);
}
AIM.setETA(nil);
me.stopFlight = 1;
return;
}
}
@ -2671,11 +2682,11 @@ var AIM = {
if (me.life_time - me.last_noti > me.noti_time and getprop("payload/armament/msg")) {
# notify in flight using Emesary.
me.last_noti = me.life_time;
thread.lock(mutexTimer);
lockMutex(mutexTimer);
var rdr = me.guidance=="radar";
var semiRdr = (me.guidance=="semi-radar" and !me.semiLostLock) or (me.guidance=="command" and me.guiding);# Continous wave illuminator active on the target
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
unlockMutex(mutexTimer);
}
me.last_dt = me.dt;
@ -2685,9 +2696,9 @@ var AIM = {
if (me.counter > -1 and !me.ai.getNode("valid").getBoolValue()) {
# TODO: Why is this placed so late? Don't remember.
me.ai.getNode("valid").setBoolValue(1);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
unlockMutex(mutexTimer);
}
#############################################################################################################
#
@ -3209,17 +3220,17 @@ var AIM = {
me.free = 1;
me.guiding = 0;
} elsif (me.blep.getID() != me["blepID"]) {
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.blepID = me.blep.getID();
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.blepIDtime = me.life_time;
me.t_coord_sampled = me.t_coord;
} elsif (me["blepIDtime"] != nil) {
me.dtTrack = me.life_time - me.blepIDtime;
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.ecefVel = me.blep.getECEFVelocity();
me.blep_coord = geo.Coord.new(me.blep.getCoord());
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.t_coord_sampled = geo.Coord.new();
# dead-reckon:
@ -3320,7 +3331,7 @@ var AIM = {
# target has released a new flare, lets check if it fools us
me.flareTime = me.life_time;
me.flareLast = me.flareNumber;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
#me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.flareLock = rand() < (1-me.flareResistance);
if (me.flareLock) {
# fooled by the flare
@ -3353,10 +3364,10 @@ var AIM = {
# target has released a new chaff, lets check if it blinds us
me.chaffLast = me.chaffNumber;
me.chaffTime = me.life_time;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.redux = me.guidance == "semi-radar" or me.guidance == "command" or me.guidance == "tvm"?(me.gnd_launch?0.5:0.75):1;
me.chaffChance = (1-me.chaffResistance)*me.redux;
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectDeg));# 70% less chance to be fooled if front aspect
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectNorm));# 70% less chance to be fooled if front aspect
if (me.chaffLock) {
me.printStats(me.type~": Missile locked on chaff from "~me.callsign);
@ -4210,7 +4221,7 @@ var AIM = {
if(me.life_time < me.arming_time) {
me.event = "landed disarmed";
#thread.lock(mutexTimer);
#append(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#appendTimer(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#thread.unlock(mutexTimer);
}
if (me.Tgt != nil and me.direct_dist_m == nil) {
@ -4418,16 +4429,16 @@ var AIM = {
me.coord = coordinates; # Set the current missile coordinates at the explosion point.
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
unlockMutex(mutexTimer);
}
var wh_mass = (event == "exploded" and !me.inert) ? me.weight_whead_lbm : 0; #will report 0 mass if did not have time to arm
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
unlockMutex(mutexTimer);
if (!me.inert) {
var phrase = nil;
@ -4452,28 +4463,28 @@ var AIM = {
if (phrase != nil) {
me.printStats("%s time %.1f", phrase, me.life_time);
if(getprop("payload/armament/msg") and hitPrimaryTarget and wh_mass > 0){
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
if (me.multiHit and !me.multiExplosion(coordinates, event, wh_mass) and me.Tgt != nil and me.Tgt.isVirtual()) {
phrase = sprintf(me.type~" "~event);
me.printStats("%s Reason: %s time %.1f", phrase, reason, me.life_time);
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
me.ai.getNode("valid", 1).setBoolValue(0);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
unlockMutex(mutexTimer);
if (event == "exploded" and !me.inert and wh_mass > 0) {
me.animate_explosion(hitGround);
me.explodeSound = 1;
@ -4500,13 +4511,13 @@ var AIM = {
if(getprop("payload/armament/msg") and wh_mass > 0){
var cs = damage.processCallsign(me.testMe.get_Callsign());
var cc = me.testMe.get_Coord();
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
unlockMutex(mutexTimer);
} elsif (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
@ -4520,9 +4531,9 @@ var AIM = {
var phrase = sprintf("%s %s: %.1f meters from: %s", me.type,event, min_distance, cs);# if we mention ourself then we need to explicit add ourself as author.
me.printStats(phrase);
if (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
}
@ -5498,21 +5509,21 @@ var AIM = {
me.explode_prop.setBoolValue(1);
me.explode_angle_prop.setDoubleValue((rand() - 0.5) * 50);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
append(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
append(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
unlockMutex(mutexTimer);
if (info == nil or !hitGround or getprop("payload/armament/enable-craters") == nil or !getprop("payload/armament/enable-craters")) {return;};
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func {
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func {
if (info[1] == nil) {
#print ("Building hit..smoking");
var static = geo.put_model(getprop("payload/armament/models") ~ "bomb_hit_smoke.xml", me.coord.lat(), me.coord.lon());
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
unlockMutex(mutexTimer);
}
} else if ((info[1] != nil) and info[1].solid) {
var crater_model = "";
@ -5531,14 +5542,14 @@ var AIM = {
var static = geo.put_model(crater_model, me.coord.lat(), me.coord.lon());
#print("put crater");
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
unlockMutex(mutexTimer);
}
}
}
}, [], 0.5]);
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
},
animate_dud: func {
@ -5745,79 +5756,79 @@ var AIM = {
printFlight: func {
if (DEBUG_FLIGHT) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printFlightDetails: func {
if (DEBUG_FLIGHT_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStats: func {
if (DEBUG_STATS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStatsDetails: func {
if (DEBUG_STATS_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuide: func {
if (DEBUG_GUIDANCE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuideDetails: func {
if (DEBUG_GUIDANCE_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printCode: func {
if (DEBUG_CODE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printSearch: func {
if (DEBUG_SEARCH) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printAlways: func {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
},
timerLoop: func {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
AIM.tq = AIM.timerQueue;
AIM.timerQueue = [];
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
foreach(var cmd; AIM.tq) {
AIM.timerCall(cmd);
}
@ -5858,7 +5869,7 @@ var AIM = {
setETA: func (eta, prev = -1) {
# Class method
thread.lock(mutexETA);
lockMutex(mutexETA);
if (eta == -1 and prev == AIM.lowestETA) {
AIM.lowestETA = nil;
} elsif (eta == nil) {
@ -5866,14 +5877,14 @@ var AIM = {
} elsif (AIM.lowestETA == nil or eta < AIM.lowestETA and eta < 1800) {
AIM.lowestETA = eta;
}
thread.unlock(mutexETA);
unlockMutex(mutexETA);
},
getETA: func {
# Class method
var retur = 0;
thread.lock(mutexETA);
lockMutex(mutexETA);
retur = AIM.lowestETA;
thread.unlock(mutexETA);
unlockMutex(mutexETA);
return retur;
},
@ -5885,6 +5896,22 @@ var AIM = {
setprop("ai/models/model-removed", me.ai.getPath());
},
};
var appendTimer = func (queue, cmd) {
if (sep_thread) {
append(AIM.timerQueue, cmd);
} else {
call(cmd[1], cmd[2], cmd[0], nil, var err = []);
debug.printerror(err);
}
}
var lockMutex = func (m) {
if (sep_thread) thread.lock(m);
}
var unlockMutex = func (m) {
if (sep_thread) thread.unlock(m);
}
var backtrace = func(desc = nil, dump_vars = 1, skip_level = 0, levels = 3) {
var d = (desc == nil) ? "" : " '" ~ desc ~ "'";
print("");
@ -5992,7 +6019,7 @@ var mutexTimer = thread.newlock();
var mutexETA = thread.newlock();
var defeatSpamFilter = func (str) {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
spams += 1;
if (spams == 15) {
spams = 1;
@ -6010,13 +6037,13 @@ var defeatSpamFilter = func (str) {
append(newList, spamList[i]);
}
spamList = newList;
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
}
var spamLoop = func {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
var spam = pop(spamList);
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
if (spam != nil) {
setprop("/sim/multiplay/chat", spam);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -153,11 +153,13 @@ var slugs_to_lbm = SLUGS2LBM;# since various aircraft use this from outside miss
var first_in_air = 0;# first missile is in the air, other missiles should not write to MP.
var first_in_air_max_sec = 30;
#var versionString = getprop("sim/version/flightgear");
#var version = split(".", versionString);
#var major = num(version[0]);
#var minor = num(version[1]);
#var pica = num(version[2]);
var versionString = getprop("sim/version/flightgear");
var version = split(".", versionString);
var major = num(version[0]);
var minor = num(version[1]);
var pica = num(version[2]);
var sep_thread = getprop("payload/threading") != nil or !(major == 2020 and minor == 4);#Bug in 2020.4.0 threadsafe properties makes this needed.
var wingedGuideFactor = 0.1;
@ -914,7 +916,7 @@ var AIM = {
m.standby();# these loops will run until released or deleted.
#for multithreading
m.frameToggle = thread.newsem();
if (sep_thread) m.frameToggle = thread.newsem();
m.myMath = {parents:[vector.Math],};#personal vector library, to avoid using a mutex on it.
return AIM.active[m.ID] = m;
@ -927,13 +929,14 @@ var AIM = {
#
# Note: Must never be called from the flight loop thread.
#
if (me.deleted) return;
me.printCode("deleted weapon");
if (me["frameLoop"] != nil) {
me.frameLoop.stop();
me.frameLoop = nil;
}
me.deleted = 1;
thread.semup(me.frameToggle);
if (sep_thread) thread.semup(me.frameToggle);
if (me.first) {
me.resetFirst();
}
@ -943,17 +946,17 @@ var AIM = {
delete(AIM.flying, me.flyID);
if (me.tacview_support) {
if (tacview.starttime) {
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write("-"~me.tacviewID~"\n");
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
#lat,lon,alt,rdar,typeID,typ,unique,thrustOn,callsign, heading, pitch, speed, is_deleted=0
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [nil, -1, -1, 0, 0, me.typeID, "delete()", me.unique_id, 0,"", 0, 0, 0, 1], -1]);
unlockMutex(mutexTimer);
}
} else {
delete(AIM.active, me.ID);
@ -1763,6 +1766,12 @@ var AIM = {
loadNode.remove();
if(!sep_thread) {
me.flightTimer = maketimer(0, me, me.flight);
me.flightTimer.start();
me.flight();
return;
}
# lets run the main flight loop in its own thread:
var frameTrigger = func {
thread.semup(me.frameToggle);
@ -2100,12 +2109,13 @@ var AIM = {
},
flight: func {
while(1==1) {
if(me.deleted) {
me.nofun = 1;
while(sep_thread or me.nofun) {
me.nofun = 0;
if(me.deleted or me["stopFlight"] == 1) {
return;
}
thread.semdown(me.frameToggle);
if (sep_thread) thread.semdown(me.frameToggle);
if(me.deleted) {
return;
}
@ -2182,10 +2192,10 @@ var AIM = {
if (!(me.canSwitch and me.reaquire)) {
me.printStats(me.type~": Target went away, deleting missile.");
#me.sendMessage(me.type~" missed "~me.callsign~": Target logged off.");
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],0]);
append(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],0]);
appendTimer(AIM.timerQueue, [me,me.log,[me.callsign~" logged off. Deleting "~me.typeLong],0]);
unlockMutex(mutexTimer);
AIM.setETA(nil);
return;
} else {
@ -2546,10 +2556,10 @@ var AIM = {
if (tacview.starttime and math.mod(me.counter, 3) == 0) {
me.nme = me.type=="es"?"Parachutist":me.type;
me.extra = me.type=="es"?"|0|0|0":"";
thread.lock(tacview.mutexWrite);
lockMutex(tacview.mutexWrite);
tacview.write("#" ~ (systime() - tacview.starttime)~"\n");
tacview.write(me.tacviewID~",T="~me.coord.lon()~"|"~me.coord.lat()~"|"~(me.alt_ft*FT2M)~me.extra~",Name="~me.nme~",Parent="~tacview.myplaneID~"\n");#,Type=Weapon+Missile
thread.unlock(tacview.mutexWrite);
unlockMutex(tacview.mutexWrite);
}
}
@ -2585,15 +2595,16 @@ var AIM = {
me.sndDistance = 0;
me.elapsed_last_snd = systime();
if (me.explodeSound) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.sndPropagate,[],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.sndPropagate,[],0]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,me.del,[],10]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,me.del,[],10]);
unlockMutex(mutexTimer);
}
AIM.setETA(nil);
me.stopFlight = 1;
return;
}
}
@ -2671,11 +2682,11 @@ var AIM = {
if (me.life_time - me.last_noti > me.noti_time and getprop("payload/armament/msg")) {
# notify in flight using Emesary.
me.last_noti = me.life_time;
thread.lock(mutexTimer);
lockMutex(mutexTimer);
var rdr = me.guidance=="radar";
var semiRdr = (me.guidance=="semi-radar" and !me.semiLostLock) or (me.guidance=="command" and me.guiding);# Continous wave illuminator active on the target
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
thread.unlock(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.latN.getValue(), me.lonN.getValue(), me.altN.getValue()*FT2M,rdr,semiRdr,me.typeID,me.type,me.unique_id,me.thrust_lbf>0,(me.free or me.lostLOS or me.tooLowSpeed or me.flareLock or me.chaffLock)?"":me.callsign, me.hdg, me.pitch, me.new_speed_fps, 0], -1]);
unlockMutex(mutexTimer);
}
me.last_dt = me.dt;
@ -2685,9 +2696,9 @@ var AIM = {
if (me.counter > -1 and !me.ai.getNode("valid").getBoolValue()) {
# TODO: Why is this placed so late? Don't remember.
me.ai.getNode("valid").setBoolValue(1);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelAdded, [], -1]);
unlockMutex(mutexTimer);
}
#############################################################################################################
#
@ -3209,17 +3220,17 @@ var AIM = {
me.free = 1;
me.guiding = 0;
} elsif (me.blep.getID() != me["blepID"]) {
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.blepID = me.blep.getID();
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.blepIDtime = me.life_time;
me.t_coord_sampled = me.t_coord;
} elsif (me["blepIDtime"] != nil) {
me.dtTrack = me.life_time - me.blepIDtime;
thread.lock(me.blep.mutex);
lockMutex(me.blep.mutex);
me.ecefVel = me.blep.getECEFVelocity();
me.blep_coord = geo.Coord.new(me.blep.getCoord());
thread.unlock(me.blep.mutex);
unlockMutex(me.blep.mutex);
me.t_coord_sampled = geo.Coord.new();
# dead-reckon:
@ -3320,7 +3331,7 @@ var AIM = {
# target has released a new flare, lets check if it fools us
me.flareTime = me.life_time;
me.flareLast = me.flareNumber;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
#me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.flareLock = rand() < (1-me.flareResistance);
if (me.flareLock) {
# fooled by the flare
@ -3353,10 +3364,10 @@ var AIM = {
# target has released a new chaff, lets check if it blinds us
me.chaffLast = me.chaffNumber;
me.chaffTime = me.life_time;
me.aspectDeg = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.aspectNorm = me.aspectToExhaust(me.coord, me.Tgt) / 180;# 0 = viewing engine, 1 = front
me.redux = me.guidance == "semi-radar" or me.guidance == "command" or me.guidance == "tvm"?(me.gnd_launch?0.5:0.75):1;
me.chaffChance = (1-me.chaffResistance)*me.redux;
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectDeg));# 70% less chance to be fooled if front aspect
me.chaffLock = rand() < (me.chaffChance - (me.chaffChance * 0.70 * me.aspectNorm));# 70% less chance to be fooled if front aspect
if (me.chaffLock) {
me.printStats(me.type~": Missile locked on chaff from "~me.callsign);
@ -4210,7 +4221,7 @@ var AIM = {
if(me.life_time < me.arming_time) {
me.event = "landed disarmed";
#thread.lock(mutexTimer);
#append(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#appendTimer(AIM.timerQueue, [me,me.log,[me.typeLong~" landed disarmed."],0]);
#thread.unlock(mutexTimer);
}
if (me.Tgt != nil and me.direct_dist_m == nil) {
@ -4418,16 +4429,16 @@ var AIM = {
me.coord = coordinates; # Set the current missile coordinates at the explosion point.
if(getprop("payload/armament/msg")) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyInFlight, [me.coord.lat(), me.coord.lon(), me.coord.alt(),0,0,me.typeID,me.type,me.unique_id,0,"", me.hdg, me.pitch, 0, 0], -1]);
unlockMutex(mutexTimer);
}
var wh_mass = (event == "exploded" and !me.inert) ? me.weight_whead_lbm : 0; #will report 0 mass if did not have time to arm
thread.lock(mutexTimer);
append(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me,impact_report,[coordinates, wh_mass, "munition", me.type, me.new_speed_fps*FT2M],0]);
unlockMutex(mutexTimer);
if (!me.inert) {
var phrase = nil;
@ -4452,28 +4463,28 @@ var AIM = {
if (phrase != nil) {
me.printStats("%s time %.1f", phrase, me.life_time);
if(getprop("payload/armament/msg") and hitPrimaryTarget and wh_mass > 0){
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [coordinates.alt() - me.t_coord.alt(),range,me.callsign,coordinates.course_to(me.t_coord),reason,me.typeID, me.typeLong, 0], -1]);
unlockMutex(mutexTimer);
} else {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
if (me.multiHit and !me.multiExplosion(coordinates, event, wh_mass) and me.Tgt != nil and me.Tgt.isVirtual()) {
phrase = sprintf(me.type~" "~event);
me.printStats("%s Reason: %s time %.1f", phrase, reason, me.life_time);
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
}
me.ai.getNode("valid", 1).setBoolValue(0);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, me.setModelRemoved, [], -1]);
unlockMutex(mutexTimer);
if (event == "exploded" and !me.inert and wh_mass > 0) {
me.animate_explosion(hitGround);
me.explodeSound = 1;
@ -4500,13 +4511,13 @@ var AIM = {
if(getprop("payload/armament/msg") and wh_mass > 0){
var cs = damage.processCallsign(me.testMe.get_Callsign());
var cc = me.testMe.get_Coord();
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - cc.alt(),min_distance,cs,explode_coord.course_to(cc),"mhit1",me.typeID, me.typeLong,0], -1]);
unlockMutex(mutexTimer);
} elsif (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.log, [phrase], 0]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
@ -4520,9 +4531,9 @@ var AIM = {
var phrase = sprintf("%s %s: %.1f meters from: %s", me.type,event, min_distance, cs);# if we mention ourself then we need to explicit add ourself as author.
me.printStats(phrase);
if (wh_mass > 0) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyHit, [explode_coord.alt() - geo.aircraft_position().alt(),min_distance,cs,explode_coord.course_to(geo.aircraft_position()),"mhit2",me.typeID, me.typeLong, 1], -1]);
unlockMutex(mutexTimer);
}
me.sendout = 1;
}
@ -5498,21 +5509,21 @@ var AIM = {
me.explode_prop.setBoolValue(1);
me.explode_angle_prop.setDoubleValue((rand() - 0.5) * 50);
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
append(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
append(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func me.explode_prop.setBoolValue(0), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func me.explode_smoke_prop.setBoolValue(1), [], 0.5]);
appendTimer(AIM.timerQueue, [me, func {me.explode_smoke_prop.setBoolValue(0);if (me.first and size(keys(AIM.flying))>1) {me.resetFirst();}}, [], 3]);
unlockMutex(mutexTimer);
if (info == nil or !hitGround or getprop("payload/armament/enable-craters") == nil or !getprop("payload/armament/enable-craters")) {return;};
thread.lock(mutexTimer);
append(AIM.timerQueue, [me, func {
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [me, func {
if (info[1] == nil) {
#print ("Building hit..smoking");
var static = geo.put_model(getprop("payload/armament/models") ~ "bomb_hit_smoke.xml", me.coord.lat(), me.coord.lon());
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(), info[0], 2, 0, static], 0]);
unlockMutex(mutexTimer);
}
} else if ((info[1] != nil) and info[1].solid) {
var crater_model = "";
@ -5531,14 +5542,14 @@ var AIM = {
var static = geo.put_model(crater_model, me.coord.lat(), me.coord.lon());
#print("put crater");
if(getprop("payload/armament/msg") and info[0] != nil) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [AIM, AIM.notifyCrater, [me.coord.lat(), me.coord.lon(),info[0],siz, 0, static], 0]);
unlockMutex(mutexTimer);
}
}
}
}, [], 0.5]);
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
},
animate_dud: func {
@ -5745,79 +5756,79 @@ var AIM = {
printFlight: func {
if (DEBUG_FLIGHT) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printFlightDetails: func {
if (DEBUG_FLIGHT_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStats: func {
if (DEBUG_STATS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printStatsDetails: func {
if (DEBUG_STATS_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuide: func {
if (DEBUG_GUIDANCE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printGuideDetails: func {
if (DEBUG_GUIDANCE_DETAILS) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printCode: func {
if (DEBUG_CODE) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printSearch: func {
if (DEBUG_SEARCH) {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
}
},
printAlways: func {
thread.lock(mutexTimer);
append(AIM.timerQueue, [nil, printff, arg, -1]);
thread.unlock(mutexTimer);
lockMutex(mutexTimer);
appendTimer(AIM.timerQueue, [nil, printff, arg, -1]);
unlockMutex(mutexTimer);
},
timerLoop: func {
thread.lock(mutexTimer);
lockMutex(mutexTimer);
AIM.tq = AIM.timerQueue;
AIM.timerQueue = [];
thread.unlock(mutexTimer);
unlockMutex(mutexTimer);
foreach(var cmd; AIM.tq) {
AIM.timerCall(cmd);
}
@ -5858,7 +5869,7 @@ var AIM = {
setETA: func (eta, prev = -1) {
# Class method
thread.lock(mutexETA);
lockMutex(mutexETA);
if (eta == -1 and prev == AIM.lowestETA) {
AIM.lowestETA = nil;
} elsif (eta == nil) {
@ -5866,14 +5877,14 @@ var AIM = {
} elsif (AIM.lowestETA == nil or eta < AIM.lowestETA and eta < 1800) {
AIM.lowestETA = eta;
}
thread.unlock(mutexETA);
unlockMutex(mutexETA);
},
getETA: func {
# Class method
var retur = 0;
thread.lock(mutexETA);
lockMutex(mutexETA);
retur = AIM.lowestETA;
thread.unlock(mutexETA);
unlockMutex(mutexETA);
return retur;
},
@ -5885,6 +5896,22 @@ var AIM = {
setprop("ai/models/model-removed", me.ai.getPath());
},
};
var appendTimer = func (queue, cmd) {
if (sep_thread) {
append(AIM.timerQueue, cmd);
} else {
call(cmd[1], cmd[2], cmd[0], nil, var err = []);
debug.printerror(err);
}
}
var lockMutex = func (m) {
if (sep_thread) thread.lock(m);
}
var unlockMutex = func (m) {
if (sep_thread) thread.unlock(m);
}
var backtrace = func(desc = nil, dump_vars = 1, skip_level = 0, levels = 3) {
var d = (desc == nil) ? "" : " '" ~ desc ~ "'";
print("");
@ -5992,7 +6019,7 @@ var mutexTimer = thread.newlock();
var mutexETA = thread.newlock();
var defeatSpamFilter = func (str) {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
spams += 1;
if (spams == 15) {
spams = 1;
@ -6010,13 +6037,13 @@ var defeatSpamFilter = func (str) {
append(newList, spamList[i]);
}
spamList = newList;
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
}
var spamLoop = func {
thread.lock(mutexMsg);
lockMutex(mutexMsg);
var spam = pop(spamList);
thread.unlock(mutexMsg);
unlockMutex(mutexMsg);
if (spam != nil) {
setprop("/sim/multiplay/chat", spam);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -329,7 +329,7 @@ var DamageRecipient =
var tacID = left(md5(notification.Callsign~notification.UniqueIdentity~wh),6);
var elapsed = getprop("sim/time/elapsed-sec");
lastSeenTacObject[tacID] = elapsed;
if (notification.Kind == 2) {
if (notification.Kind == MOVE) {
var target = ",Color=Red";
if (wh=="Flare") wh=wh~",Type=Flare";
var content = sprintf("%s,T=%.6f|%.6f|%.2f|0|%.1f|%.1f,TAS=%.2f,AOA=0,Visible=1,Name=%s,%s\n",tacID,notification.Position.lon(),notification.Position.lat(),notification.Position.alt(),0,0,0,wh,target);
@ -346,13 +346,13 @@ var DamageRecipient =
}
if (notification.Kind == MOVE) {
if (thrustOn or index == 93 or index == 95) {
if (thrustOn or index == warheads["pilot"][0] or index == warheads["Flare"][0]) {
# visualize missile smoke trail
var smoke = 1;
if (index == 93) {
if (index == warheads["pilot"][0]) {
smoke = 0;
} elsif (index == 95) {
} elsif (index == warheads["Flare"][0]) {
smoke = 3;
if (notification.Position.distance_to(ownPos)*M2NM > 5) {
# Don't bother to show flares further than 5 nm
@ -406,7 +406,7 @@ var DamageRecipient =
return emesary.Transmitter.ReceiptStatus_OK;
}
if (index == 95 or index == 93) {
if (index == warheads["Flare"][0] or index == warheads["pilot"][0]) {
return emesary.Transmitter.ReceiptStatus_OK;
}
@ -979,15 +979,10 @@ var animate_flare = func {
flare_list = sort(flare_list, flare_sorter);
foreach(flare; flare_list) {
if (stime-flare[1] > flare_duration) {
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], DESTROY, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
continue;
@ -999,15 +994,10 @@ var animate_flare = func {
flare[2].apply_course_distance(flare[3], flare_dt*flare[5]);
flare[2].set_alt(flare[2].alt()-flare_dt*flare[4]);
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, 21+95);
msg.Flags = 0;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
flares_sent += 1;
@ -1045,15 +1035,10 @@ var flare_released = func {
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;
var msg = notifications.ObjectInFlightNotification.new("ffly", flare[6], MOVE, DamageRecipient.typeID2emesaryID(warheads["Flare"][0]));
msg.Position = flare[2];
msg.IsDistinct = 1;
msg.RemoteCallsign = "";
msg.UniqueIndex = flare[6];
msg.Pitch = 0;
msg.Heading = 0;
msg.u_fps = 0;
notifications.objectBridgedTransmitter.NotifyAll(msg);
recordOwnFlare(msg);
}

@ -59,81 +59,81 @@
],
"missile-code": [
{
"version": "1.1.6",
"version": "1.1.7",
"path": "BUK-M2/Nasal/guided-missiles.nas"
},
{
"version": "1.1.6",
"version": "1.1.7",
"path": "MIM-104D/Nasal/guided-missiles.nas"
},
{
"version": "1.1.6",
"version": "1.1.7",
"path": "S-75/Nasal/guided-missiles.nas"
},
{
"version": "1.1.6",
"version": "1.1.7",
"path": "SA-3/Nasal/guided-missiles.nas"
},
{
"version": "1.1.6",
"version": "1.1.7",
"path": "SA-6/Nasal/guided-missiles.nas"
}
],
"damage": [
{
"version": "1.4.10",
"version": "1.4.11",
"path": "BUK-M2/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "depot/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "fleet/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "Frigate/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "gci-radar/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "groundtarget/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "MIM-104D/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "missile-frigate/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "S-200/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "S-300/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "S-75/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "SA-3/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "SA-6/Nasal/damage.nas"
},
{
"version": "1.4.10",
"version": "1.4.11",
"path": "ZSU-23/Nasal/damage.nas"
}
],

Loading…
Cancel
Save