diff --git a/Nasal/damage.nas b/Nasal/damage.nas new file mode 100644 index 0000000..d73118c --- /dev/null +++ b/Nasal/damage.nas @@ -0,0 +1,479 @@ +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, +}; + +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] == " aim7 at" or last_vector[1] == " aim9 at" + or last_vector[1] == " aim120 at" or last_vector[1] == " RB-24J fired at" or last_vector[1] == " RB-74 fired at" + or last_vector[1] == " RB-71 fired at" or last_vector[1] == " RB-15F fired at" + or last_vector[1] == " RB-99 fired at" or last_vector[1] == " KN-06 fired 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) { # + # 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; + 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] == " 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 = 6*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 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 callsign_struct = {}; +var getCallsign = func (callsign) { + var node = callsign_struct[callsign]; + return node; +} + +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(); + + +var logTime = func{ + #log time and date for outputing ucsv files for converting into KML files for google earth. + if (getprop("logging/log[0]/enabled") == TRUE and getprop("sim/time/utc/year") != nil) { + var date = getprop("sim/time/utc/year")~"/"~getprop("sim/time/utc/month")~"/"~getprop("sim/time/utc/day"); + var time = getprop("sim/time/utc/hour")~":"~getprop("sim/time/utc/minute")~":"~getprop("sim/time/utc/second"); + + setprop("logging/date-log", date); + setprop("logging/time-log", time); + } +} + +var ct = func (type) { + if (type == "c-u") { + setprop("sim/ct/c-u", 1); + } + if (type == "rl" and getprop("gear/gear[0]/wow") != TRUE) { + setprop("sim/ct/rl", 1); + } + if (type == "rp" and getprop("gear/gear[0]/wow") != TRUE) { + setprop("sim/ct/rp", 1); + } + if (type == "a") { + setprop("sim/ct/a", 1); + } + if (type == "lst") { + setprop("sim/ct/list", 1); + } + if (type == "ifa" and getprop("gear/gear[0]/wow") != TRUE) { + setprop("sim/ct/ifa", 1); + } + if (type == "sf" and getprop("gear/gear[0]/wow") != TRUE) { + setprop("sim/ct/sf", 1); + } +} + +var lf = -1; +var ll = 0; + +var code_ct = func () { + var cu = getprop("sim/ct/c-u"); + if (cu == nil or cu != 1) { + cu = 0; + } + var a = getprop("sim/ct/a"); + if (a == nil or a != 1) { + a = 0; + } + var ff = getprop("sim/freeze/fuel"); + if (ff == nil) { + ff = 0; + } elsif (ff == 1) { + setprop("sim/ct/ff", 1); + } + ff = getprop("sim/ct/ff"); + if (ff == nil or ff != 1) { + ff = 0; + } + var cl = 0; + if (cl > (ll*1.05) and getprop("gear/gear[0]/wow") != TRUE) { + setprop("sim/ct/rl", 1); + } + ll = cl; + var rl = getprop("sim/ct/rl"); + if (rl == nil or rl != 1) { + rl = 0; + } + var rp = getprop("sim/ct/rp"); + if (rp == nil or rp != 1) { + rp = 0; + } + var cf = getprop("/consumables/fuel/tank[0]/level-gal_us") + +getprop("/consumables/fuel/tank[1]/level-gal_us") + +getprop("/consumables/fuel/tank[2]/level-gal_us") + +getprop("/consumables/fuel/tank[3]/level-gal_us") + +getprop("/consumables/fuel/tank[4]/level-gal_us"); + if (cf != nil and lf != -1 and cf > (lf*1.1) and getprop("gear/gear[0]/wow") != TRUE and getprop("/systems/refuel/contact") == FALSE) { + setprop("sim/ct/rf", 1); + } + var rf = getprop("sim/ct/rf"); + if (rf == nil or rf != 1) { + rf = 0; + } + lf = cf == nil?0:cf; + var dm = !getprop("/controls/armament/mp-messaging"); + if (dm == nil or dm != 1) { + dm = 0; + } + var tm = 0;#getprop("sim/ja37/radar/look-through-terrain"); + if (tm == nil or tm != 1) { + tm = 0; + } + var rd = 0;#!getprop("sim/ja37/radar/doppler-enabled"); + if (rd == nil or rd != 1) { + rd = 0; + } + var ml = getprop("sim/ct/list"); + if (ml == nil or ml != 1) { + ml = 0; + } + var sf = getprop("sim/ct/sf"); + if (sf == nil or sf != 1) { + sf = 0; + } + var ifa = getprop("sim/ct/ifa"); + if (ifa == nil or ifa != 1) { + ifa = 0; + } + var final = "ct"~cu~ff~rl~rf~rp~a~dm~tm~rd~ml~sf~ifa; + setprop("sim/multiplay/generic/string[15]", final); + settimer(code_ct, 2); +} + +var not = func { + if (getprop("/controls/armament/mp-messaging") == TRUE and getprop("gear/gear[0]/wow") != TRUE) { + var ct = getprop("sim/multiplay/generic/string[15]") ; + var msg = "I might be chea"~"ting.."; + if (ct != nil) { + msg = "I might be chea"~"ting.."~ct; + var spl = split("ct", ct); + if (size(spl) > 1) { + var bits = spl[1]; + msg = "I "; + if (bits == "000000000000") { + settimer(not, 60); + return; + } + if (substr(bits,0,1) == "1") { + msg = msg~"Used CT"~"RL-U.."; + } + if (substr(bits,1,1) == "1") { + msg = msg~"Use fuelf"~"reeze.."; + } + if (substr(bits,2,1) == "1") { + msg = msg~"Relo"~"aded in air.."; + } + if (substr(bits,3,1) == "1") { + msg = msg~"Refue"~"led in air.."; + } + if (substr(bits,4,1) == "1") { + msg = msg~"Repa"~"ired not on ground.."; + } + if (substr(bits,5,1) == "1") { + msg = msg~"Used time"~"warp.."; + } + if (substr(bits,6,1) == "1") { + msg = msg~"Have dam"~"age off.."; + } + if (substr(bits,7,1) == "1") { + msg = msg~"Have Ter"~"rain mask. off.."; + } + if (substr(bits,8,1) == "1") { + msg = msg~"Have Dop"~"pler off.."; + } + if (substr(bits,9,1) == "1") { + msg = msg~"Had mp-l"~"ist on.."; + } + if (substr(bits,10,1) == "1") { + msg = msg~"Had s-fai"~"lures open.."; + } + if (substr(bits,11,1) == "1") { + msg = msg~"Had i-fa"~"ilures open.."; + } + } + } + setprop("/sim/multiplay/chat", msg); + } + settimer(not, 60); +} + +var changeGuiLoad = func() +{#return; + var searchname1 = "mp-list"; + var searchname2 = "instrument-failures"; + var searchname3 = "system-failures"; + var state = 0; + + foreach(var menu ; props.globals.getNode("/sim/menubar/default").getChildren("menu")) { + foreach(var item ; menu.getChildren("item")) { + foreach(var name ; item.getChildren("name")) { + if(name.getValue() == searchname1) { + #var e = item.getNode("enabled").getValue(); + #var path = item.getPath(); + #item.remove(); + #item = props.globals.getNode(path,1); + #item.getNode("enabled",1).setBoolValue(FALSE); + #item.getNode("binding").remove(); + #item.getNode("name",1).setValue(searchname1); + item.getNode("binding/command").setValue("nasal"); + item.getNode("binding/script").setValue("missile.loadMPList()"); + #item.getNode("enabled",1).setBoolValue(TRUE); + } + if(name.getValue() == searchname2) { + item.getNode("binding/command").setValue("nasal"); + item.getNode("binding/dialog-name").remove(); + item.getNode("binding/script",1).setValue("missile.loadIFail()"); + } + if(name.getValue() == searchname3) { + item.getNode("binding/command").setValue("nasal"); + item.getNode("binding/dialog-name").remove(); + item.getNode("binding/script",1).setValue("missile.loadSysFail()"); + } + } + } + } + fgcommand("reinit", props.Node.new({"subsystem":"gui"})); +} + +var loadMPList = func () { + ct("lst");multiplayer.dialog.show(); +} + +var loadSysFail = func () { + ct("sf");fgcommand("dialog-show", props.Node.new({"dialog-name":"system-failures"})); +} + +var loadIFail = func () { + ct("ifa");fgcommand("dialog-show", props.Node.new({"dialog-name":"instrument-failures"})); +} + +changeGuiLoad(); +settimer(code_ct, 5); +settimer(not, 11); + +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