diff --git a/MQ-9-JSBSim-set.xml b/MQ-9-JSBSim-set.xml index 474de5a..3acc05a 100755 --- a/MQ-9-JSBSim-set.xml +++ b/MQ-9-JSBSim-set.xml @@ -483,6 +483,10 @@ Aircraft/MQ-9/Nasal/ENAV.nas + + Aircraft/MQ-9/Nasal/damage.nas + + - \ No newline at end of file + diff --git a/MQ-9-JSBSim2-set.xml b/MQ-9-JSBSim2-set.xml index 882aa7a..94e048d 100755 --- a/MQ-9-JSBSim2-set.xml +++ b/MQ-9-JSBSim2-set.xml @@ -337,6 +337,10 @@ Aircraft/MQ-9/Nasal/ENAV.nas + + Aircraft/MQ-9/Nasal/damage.nas + + - \ No newline at end of file + diff --git a/Models/Liveries/Default.jpg b/Models/Liveries/Default.jpg index 1f45307..7ac1df4 100644 Binary files a/Models/Liveries/Default.jpg and b/Models/Liveries/Default.jpg differ diff --git a/Nasal/damage.nas b/Nasal/damage.nas new file mode 100644 index 0000000..f81c8f6 --- /dev/null +++ b/Nasal/damage.nas @@ -0,0 +1,276 @@ +# +# Install: Include this code into an aircraft to make it damagable. (remember to add it to the -set file) +# +# Author: Nikolai V. Chr. (with some improvement by Onox and Pinto) +# +# + + +var clamp = func(v, min, max) { v < min ? min : v > max ? max : v } + +var TRUE = 1; +var FALSE = 0; + +var warhead_lbs = { + "aim-120": 44.00, + "AIM120": 44.00, + "RB-99": 44.00, + "aim-7": 88.00, + "RB-71": 88.00, + "aim-9": 20.80, + "AIM-9": 20.80, + "RB-24": 20.80, + "RB-24J": 20.80, + "RB-74": 20.80, + "R74": 16.00, + "MATRA-R530": 55.00, + "Meteor": 55.00, + "AIM-54": 135.00, + "Matra R550 Magic 2": 27.00, + "Matra MICA": 30.00, + "RB-15F": 440.92, + "SCALP": 992.00, + "KN-06": 315.00, + "GBU12": 190.00, + "GBU16": 450.00, + "Sea Eagle": 505.00, + "AGM65": 200.00, + "RB-04E": 661.00, + "RB-05A": 353.00, + "RB-75": 126.00, + "M90": 500.00, + "M71": 200.00, + "MK-82": 192.00, + "LAU-68": 10.00, + "M317": 145.00, + "GBU-31": 945.00, +}; + +var incoming_listener = func { + var history = getprop("/sim/multiplay/chat-history"); + var hist_vector = split("\n", history); + if (size(hist_vector) > 0) { + var last = hist_vector[size(hist_vector)-1]; + var last_vector = split(":", last); + var author = last_vector[0]; + var callsign = getprop("sim/multiplay/callsign"); + if (size(last_vector) > 1 and author != callsign) { + # not myself + #print("not me"); + var m2000 = FALSE; + if (find(" at " ~ callsign ~ ". Release ", last_vector[1]) != -1) { + # a m2000 is firing at us + m2000 = TRUE; + } + if (last_vector[1] == " FOX2 at" or last_vector[1] == " Fox 1 at" or last_vector[1] == " Fox 2 at" or last_vector[1] == " Fox 3 at" + or last_vector[1] == " Greyhound at" or last_vector[1] == " Bombs away at" or last_vector[1] == " Bruiser at" or last_vector[1] == " Rifle at" or last_vector[1] == " Bird away at" + or last_vector[1] == " aim7 at" or last_vector[1] == " aim9 at" + or last_vector[1] == " aim120 at" + or m2000 == TRUE) { + # air2air being fired + if (size(last_vector) > 2 or m2000 == TRUE) { + #print("Missile launch detected at"~last_vector[2]~" from "~author); + if (m2000 == TRUE or last_vector[2] == " "~callsign) { + # its being fired at me + #print("Incoming!"); + var enemy = getCallsign(author); + if (enemy != nil) { + #print("enemy identified"); + var bearingNode = enemy.getNode("radar/bearing-deg"); + if (bearingNode != nil) { + #print("bearing to enemy found"); + var bearing = bearingNode.getValue(); + var heading = getprop("orientation/heading-deg"); + var clock = bearing - heading; + while(clock < 0) { + clock = clock + 360; + } + while(clock > 360) { + clock = clock - 360; + } + #print("incoming from "~clock); + if (clock >= 345 or clock < 15) { + playIncomingSound("12"); + } elsif (clock >= 15 and clock < 45) { + playIncomingSound("1"); + } elsif (clock >= 45 and clock < 75) { + playIncomingSound("2"); + } elsif (clock >= 75 and clock < 105) { + playIncomingSound("3"); + } elsif (clock >= 105 and clock < 135) { + playIncomingSound("4"); + } elsif (clock >= 135 and clock < 165) { + playIncomingSound("5"); + } elsif (clock >= 165 and clock < 195) { + playIncomingSound("6"); + } elsif (clock >= 195 and clock < 225) { + playIncomingSound("7"); + } elsif (clock >= 225 and clock < 255) { + playIncomingSound("8"); + } elsif (clock >= 255 and clock < 285) { + playIncomingSound("9"); + } elsif (clock >= 285 and clock < 315) { + playIncomingSound("10"); + } elsif (clock >= 315 and clock < 345) { + playIncomingSound("11"); + } else { + playIncomingSound(""); + } + return; + } + } + } + } + } elsif (1==1) { # mirage: getprop("/controls/armament/mp-messaging") + # latest version of failure manager and taking damage enabled + #print("damage enabled"); + var last1 = split(" ", last_vector[1]); + if(size(last1) > 2 and last1[size(last1)-1] == "exploded" ) { + #print("missile hitting someone"); + if (size(last_vector) > 3 and last_vector[3] == " "~callsign) { + #print("that someone is me!"); + var type = last1[1]; + if (type == "Matra" or type == "Sea") { + for (var i = 2; i < size(last1)-1; i += 1) { + type = type~" "~last1[i]; + } + } + var number = split(" ", last_vector[2]); + var distance = num(number[1]); + #print(type~"|"); + if(distance != nil) { + var dist = distance; + + if (type == "M90") { + var prob = rand()*0.5; + var failed = fail_systems(prob); + var percent = 100 * prob; + printf("Took %.1f%% damage from %s clusterbombs at %0.1f meters. %s systems was hit", percent,type,dist,failed); + nearby_explosion(); + return; + } + + distance = clamp(distance-3, 0, 1000000); + var maxDist = 0; + + if (contains(warhead_lbs, type)) { + maxDist = maxDamageDistFromWarhead(warhead_lbs[type]); + } else { + return; + } + + var diff = maxDist-distance; + if (diff < 0) { + diff = 0; + } + + diff = diff * diff; + + var probability = diff / (maxDist*maxDist); + + var failed = fail_systems(probability); + var percent = 100 * probability; + printf("Took %.1f%% damage from %s missile at %0.1f meters. %s systems was hit", percent,type,dist,failed); + nearby_explosion(); + } + } + } elsif (last_vector[1] == " M70 rocket hit" or last_vector[1] == " M55 cannon shell hit" or last_vector[1] == " KCA cannon shell hit" or last_vector[1] == " Gun Splash On " or last_vector[1] == " M61A1 shell hit" or last_vector[1] == " GAU-8/A hit") { + # cannon hitting someone + #print("cannon"); + if (size(last_vector) > 2 and last_vector[2] == " "~callsign) { + # that someone is me! + #print("hitting me"); + + var probability = 0.20; # take 20% damage from each hit + if (last_vector[1] == " M70 rocket hit" or last_vector[1] == " Gun Splash On " or last_vector[1] == " GAU-8/A hit") { + probability = 0.30; + } + var failed = fail_systems(probability); + printf("Took %.1f%% damage from cannon! %s systems was hit.", probability*100, failed); + nearby_explosion(); + } + } + } + } + } +} + +var maxDamageDistFromWarhead = func (lbs) { + # very simple + var dist = 3*math.sqrt(lbs); + + return dist; +} + +var fail_systems = func (probability) { + var failure_modes = FailureMgr._failmgr.failure_modes; + var mode_list = keys(failure_modes); + var failed = 0; + foreach(var failure_mode_id; mode_list) { + if (rand() < probability) { + FailureMgr.set_failure_level(failure_mode_id, 1); + failed += 1; + } + } + return failed; +}; + +var playIncomingSound = func (clock) { + setprop("sound/incoming"~clock, 1); + settimer(func {stopIncomingSound(clock);},3); +} + +var stopIncomingSound = func (clock) { + setprop("sound/incoming"~clock, 0); +} + +var callsign_struct = {}; +var getCallsign = func (callsign) { + var node = callsign_struct[callsign]; + return node; +} + +var nearby_explosion = func { + setprop("damage/sounds/nearby-explode-on", 0); + settimer(nearby_explosion_a, 0); +} + +var nearby_explosion_a = func { + setprop("damage/sounds/nearby-explode-on", 1); + settimer(nearby_explosion_b, 0.5); +} + +var nearby_explosion_b = func { + setprop("damage/sounds/nearby-explode-on", 0); +} + +var processCallsigns = func () { + callsign_struct = {}; + var players = props.globals.getNode("ai/models").getChildren(); + foreach (var player; players) { + if(player.getChild("valid") != nil and player.getChild("valid").getValue() == TRUE and player.getChild("callsign") != nil and player.getChild("callsign").getValue() != "" and player.getChild("callsign").getValue() != nil) { + var callsign = player.getChild("callsign").getValue(); + callsign_struct[callsign] = player; + } + } + settimer(processCallsigns, 1.5); +} + +processCallsigns(); + +setlistener("/sim/multiplay/chat-history", incoming_listener, 0, 0); + +#setprop("/sim/failure-manager/display-on-screen", FALSE); + +var re_init = func { + # repair the aircraft + + var failure_modes = FailureMgr._failmgr.failure_modes; + var mode_list = keys(failure_modes); + + foreach(var failure_mode_id; mode_list) { + FailureMgr.set_failure_level(failure_mode_id, 0); + } +} + +setlistener("/sim/signals/reinit", re_init, 0, 0); \ No newline at end of file