diff --git a/BUK-M2/BUK-M2-set.xml b/BUK-M2/BUK-M2-set.xml
index d75e1b4..6f47649 100644
--- a/BUK-M2/BUK-M2-set.xml
+++ b/BUK-M2/BUK-M2-set.xml
@@ -60,6 +60,7 @@
pinto
BUK-M2
+ BUK-M2 is a modern Russian self-propelled surface to air missile system.
alpha
0.1
@@ -87,6 +88,19 @@
Aircraft/BUK-M2/splash1.png
+
+
+ exterior
+ true
+ gui/1.png
+
+
+ exterior
+ true
+ gui/2.png
+
+
+
true
@@ -106,6 +120,10 @@
+
+ true
+
+
Systems/fbw.xml
@@ -119,8 +137,10 @@
+ 250
0
+ 0
@@ -138,9 +158,41 @@
+ -
+
+ enemies
+
+ dialog-show
+ enemies
+
+
+ -
+
+ enemies
+
+ dialog-show
+ priority
+
+
+
+
+
+ enemies/e1
+ enemies/e2
+ enemies/e3
+ enemies/e4
+ enemies/e5
+ enemies/e6
+ enemies/e7
+ enemies/e8
+ enemies/e9
+ enemies/e10
+ enemies/e11
+ enemies/e12
+
@@ -149,33 +201,33 @@
false
- 4.15986
- -2.70311
- 3.67645
+ 2.00744
+ -1.27342
+ 4.26168
false
- -0.02697
- -0.98148
- 3.94307
+ 2.00744
+ -0.42511
+ 4.26168
false
- 4.15986
- 2.70311
- 3.67645
+ 2.00744
+ 0.42511
+ 4.26168
false
- -0.02697
- 0.98148
- 3.94307
+ 2.00744
+ 1.27342
+ 4.26168
false
@@ -195,44 +247,54 @@
Aircraft/BUK-M2/Models/Armament/Weapons/
+ true
+ true
+ rotors/main/blade[0]/flap-deg
+ rotors/main/blade[1]/flap-deg
+ rotors/main/blade[2]/flap-deg
+ true
+ 1
+ controls/armament
+ station
true
true
-
+
- false
- 0.0
0.00
0.15
- 0.1
radar
- APN
+ APN0506
true
- 31
+ 31
360
- 360
- 24
- 18000
- 6000
- 8
- 18
- 1576
- 145
- 900
- 0.15
- 1.312336
+ 170
+ 24
+ 16500
+ 0
+ 15
+ 0
+ 1576
+ 145
+ 900
+ 0.25
+ 1.312336
2
- 0.35
- 120
+ 0.5
+ 60
3000
0
- 2.0
- 200
- true
- 5.5
+ 1.6
+ 200
+ true
+ 5.5
false
- 30
+ 24
+ 0.95
+ 3
+ 1
A
Bird away
+ true
@@ -250,6 +312,38 @@
+
+
+ -1
+ -1
+ -1
+ -1
+ -1
+ -1
+ -1
+ -1
+ 4
+ 600
+ 100
+
+
+
+ Leto
+ swamp
+ pinto
+ fb237
+ Wilco-1
+ Kokos
+ J-Mav16
+ S
+ Raider1
+ Slobb
+ 5H1N0B1
+ SNOWY1
+
+
+ 0
+ 1
@@ -261,6 +355,9 @@
Aircraft/BUK-M2/Nasal/radar-logic.nas
+
+ Aircraft/BUK-M2/Nasal/vector.nas
+
Aircraft/BUK-M2/Nasal/guided-missiles.nas
diff --git a/BUK-M2/Hud/hud.xml b/BUK-M2/Hud/hud.xml
index 2632408..c07114c 100644
--- a/BUK-M2/Hud/hud.xml
+++ b/BUK-M2/Hud/hud.xml
@@ -84,7 +84,7 @@
false
-
+
+
+ Main Store
+
+ none
+
+ KN-06
+ 50
+
+
+
+
+ Aircraft/fleet/Models/Armament/Weapons/
+ true
+ true
+ rotors/main/blade[0]/flap-deg
+ rotors/main/blade[1]/flap-deg
+ rotors/main/blade[2]/flap-deg
+ true
+ 1
+ controls/armament
+ station
+ true
+ true
+
+ 0.00
+ 0.15
+ 0.1
+ radar
+ APN
+ true
+ 85
+ 360
+ 220
+ 22
+ 90000
+ 77000
+ 0.25
+ 8.0
+ 3920
+ 315
+ 2800
+ 0.20
+ 2.11349
+ 2
+ 0.25
+ 160
+ true
+ 3000
+ 75000
+ 0.85
+ 200
+ true
+ 7.5
+ false
+ 90
+ 0.95
+ 3
+ A
+ Bird away
+
+
+
+ false
+ 0.0
+ false
+ 0.00
+ radar
+ true
+ 38.8
+ 360
+ 360
+ 30
+ 9000
+ 1500
+ 4.0
+ 15.0
+ 291
+ 44
+ 0.5
+ 0.2739
+ 3.0
+ 1.6
+ 0.9
+ 90
+ 30
+ 0
+ 0.35
+ true
+ 5
+ false
+ A/A
+ Chickenbeater
+
+
+
+
+
@@ -331,6 +482,27 @@
SNOWY1
+
+
+ Aircraft/fleet/Nasal/fdm.nas
+
+
+ Aircraft/fleet/Nasal/damage.nas
+
+
+ Aircraft/fleet/Nasal/radar-logic.nas
+
+
+ Aircraft/fleet/Nasal/vector.nas
+
+
+ Aircraft/fleet/Nasal/guided-missiles.nas
+
+
+ Aircraft/fleet/Nasal/fire-control.nas
+
+
+
diff --git a/gci-radar/Nasal/damage.nas b/gci-radar/Nasal/damage.nas
index ad8f6b5..eb3714b 100644
--- a/gci-radar/Nasal/damage.nas
+++ b/gci-radar/Nasal/damage.nas
@@ -1,38 +1,70 @@
-var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
+#
+# Install: Include this code into an aircraft to make it damagable. (remember to add it to the -set file)
+#
+# Authors: Nikolai V. Chr. and Pinto (with improvement by Onox)
+#
+#
+
+
+############################ Config ######################################################################################
+var full_damage_dist_m =10;# Can vary from aircraft to aircraft depending on how many failure modes it has.
+ # Many modes (like Viggen) ought to have lower number like zero.
+ # Few modes (like F-14) ought to have larger number such as 3.
+ # For assets this should be average radius of the asset.
+var use_hitpoints_instead_of_failure_modes_bool = 1;# mainly used by assets that don't have failure modes.
+var hp_max = 80;# given a direct hit, how much pounds of warhead is needed to kill. Only used if hitpoints is enabled.
+var hitable_by_air_munitions = 0; # if anti-air can do damage
+var hitable_by_cannon = 1; # if cannon can do damage
+var hitable_by_ground_munitions = 1;# if anti-ground/marine can do damage
+var is_fleet = 0; # Is really 7 ships, 3 of which has offensive missiles.
+##########################################################################################################################
+
+##
+## TODO:
+## Include mechanics for hitting fleet
+## Move all to emesary
+##
+
var TRUE = 1;
var FALSE = 0;
-var hp = 80;
-var hp_max = hp;
-
+var hp = hp_max;
var cannon_types = {
- " M70 rocket hit": 0.25, #135mm
- " M55 cannon shell hit": 0.10, # 30mm
- " KCA cannon shell hit": 0.10, # 30mm
- " Gun Splash On ": 0.10, # 30mm
- " M61A1 shell hit": 0.05, # 20mm
- " GAU-8/A hit": 0.10, # 30mm
- " BK27 cannon hit": 0.07, # 27mm
- " GSh-30 hit": 0.10, # 30mm
- " GSh-23 hit": 0.065,# 23mm
- " 7.62 hit": 0.005,# 7.62mm
- " 50 BMG hit": 0.015,# 12.7mm
- " S-5 rocket hit": 0.20, #55mm
-};
-
-
-
+ #
+ # 0.20 means a direct hit will disable 20% of the failure modes on average.
+ # or, 0.20 also means a direct hit can do 20 hitpoints damage.
+ #
+ " M70 rocket hit": 0.250, #135mm
+ " S-5 rocket hit": 0.200, # 55mm
+ " M55 cannon shell hit": 0.100, # 30mm
+ " KCA cannon shell hit": 0.100, # 30mm
+ " Gun Splash On ": 0.100, # 30mm
+ " GSh-30 hit": 0.100, # 30mm
+ " GAU-8/A hit": 0.100, # 30mm
+ " BK27 cannon hit": 0.070, # 27mm
+ " GSh-23 hit": 0.065, # 23mm
+ " M61A1 shell hit": 0.050, # 20mm
+ " 50 BMG hit": 0.015, # 12.7mm (non-explosive)
+ " 7.62 hit": 0.005, # 7.62mm (non-explosive)
+};
+
+# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
+
var warhead_lbs = {
+ # Anti-ground/marine warheads (sorted alphabetically)
"AGM-65": 126.00,
"AGM-84": 488.00,
"AGM-88": 146.00,
"AGM65": 200.00,
+ "AGM-154A": 493.00,
+ "AGM-158": 1000.00,
"ALARM": 450.00,
"AM39-Exocet": 364.00,
"AS-37-Martel": 330.00,
"AS30L": 529.00,
+ "CBU-87": 10.00,# bomblet warhead. Mix of armour piecing and HE.
"Exocet": 364.00,
"FAB-100": 92.59,
"FAB-250": 202.85,
@@ -46,12 +78,10 @@ var warhead_lbs = {
"KAB-500": 564.38,
"Kh-25MP": 197.53,
"Kh-66": 244.71,
- "KN-06": 315.00,
"LAU-68": 10.00,
- "M317": 145.00,
"M71": 200.00,
"M71R": 200.00,
- "M90": 500.00,
+ "M90": 3.00,# bomblet warhead.
"MK-82": 192.00,
"MK-83": 445.00,
"MK-84": 945.00,
@@ -64,8 +94,7 @@ var warhead_lbs = {
"RN-18T": 1200.00, #fictional, thermobaeric replacement for the RN-28 nuclear bomb
"RS-2US": 28.66,
"S-21": 245.00,
- "S-24": 271.00,
- "S530D": 66.00,
+ "S-24": 271.00,
"SCALP": 992.00,
"Sea Eagle": 505.00,
"SeaEagle": 505.00,
@@ -74,6 +103,82 @@ var warhead_lbs = {
"ZB-500": 473.99,
};
+var warhead_air_lbs = {
+ # Anti-air warheads (sorted alphabetically)
+ "aim-120": 44.00,
+ "AIM-120": 44.00,
+ "AIM-54": 135.00,
+ "aim-7": 88.00,
+ "AIM-7": 88.00,
+ "aim-9": 20.80,
+ "AIM-9": 20.80,
+ "AIM120": 44.00,
+ "AIM132": 22.05,
+ "AIM9": 20.80,
+ "KN-06": 315.00,
+ "M317": 145.00,
+ "Magic-2": 27.00,
+ "Matra MICA": 30.00,
+ "Matra R550 Magic 2": 27.00,
+ "MATRA-R530": 55.00,
+ "MatraMica": 30.00,
+ "MatraMicaIR": 30.00,
+ "MatraR550Magic2": 27.00,
+ "Meteor": 55.00,
+ "MICA-EM": 30.00,
+ "MICA-IR": 30.00,
+ "R-13M": 16.31,
+ "R-27R1": 85.98,
+ "R-27T1": 85.98,
+ "R-3R": 16.31,
+ "R-3S": 16.31,
+ "R-55": 20.06,
+ "R-60": 6.60,
+ "R-60M": 7.70,
+ "R-73E": 16.31,
+ "R-77": 49.60,
+ "R74": 16.00,
+ "RB-05A": 353.00,
+ "RB-24": 20.80,
+ "RB-24J": 20.80,
+ "RB-71": 88.00,
+ "RB-74": 20.80,
+ "RB-99": 44.00,
+ "S530D": 66.00,
+};
+
+var cluster = {
+ # cluster munition list
+ "M90": nil,
+ "CBU-87": nil,
+};
+
+var fireMsgs = {
+
+ # F14
+ " FOX3 at": nil, # radar
+ " FOX2 at": nil, # heat
+ " FOX1 at": nil, # semi-radar
+
+ # Generic
+ " Fox 1 at": nil, # semi-radar
+ " Fox 2 at": nil, # heat
+ " Fox 3 at": nil, # radar
+ " Greyhound at": nil, # cruise missile
+ " Bombs away at": nil, # bombs
+ " Bruiser at": nil, # anti-ship
+ " Rifle at": nil, # TV guided
+ " Sniper at": nil, # anti-radiation
+
+ # SAM, fleet and missile frigate
+ " Bird away at": nil, # G/A
+
+ # F15
+ " aim7 at": nil,
+ " aim9 at": nil,
+ " aim120 at": nil,
+};
+
var incoming_listener = func {
var history = getprop("/sim/multiplay/chat-history");
var hist_vector = split("\n", history);
@@ -82,6 +187,7 @@ var incoming_listener = func {
var last_vector = split(":", last);
var author = last_vector[0];
var callsign = getprop("sim/multiplay/callsign");
+ callsign = size(callsign) < 8 ? callsign : left(callsign,7);
if (size(last_vector) > 1 and author != callsign) {
# not myself
#print("not me");
@@ -90,67 +196,10 @@ var incoming_listener = func {
# 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 m2000 == TRUE) {
+ if (contains(fireMsgs, last_vector[1]) 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");
+ warn(last_vector,m2000,callsign,author);
+ } elsif (getprop("payload/armament/msg")) {
var last1 = split(" ", last_vector[1]);
if(size(last1) > 2 and last1[size(last1)-1] == "exploded" ) {
#print("missile hitting someone");
@@ -168,56 +217,113 @@ var incoming_listener = func {
if(distance != nil) {
var dist = distance;
- #check distance w/ if statement here
+ if (contains(cluster, type)) {
+ # cluster munition
+ var lbs = warhead_lbs[type];
+ var maxDist = maxDamageDistFromWarhead(lbs);
+ var distance = math.max(0,rand()*2-full_damage_dist_m);#being 0 to 2 meters from a bomblet on average.
+ var diff = maxDist-distance;
+ diff = diff * diff;
+ var probability = diff / (maxDist*maxDist);
+ if (use_hitpoints_instead_of_failure_modes_bool) {
+ var hpDist = maxDamageDistFromWarhead(hp_max);
+ probability = (maxDist/hpDist)*probability;
+ }
+ var failed = fail_systems(probability, hp_max);
+ var percent = 100 * prob;
+ printf("Took %.1f%% damage from %s clusterbomb at %0.1f meters from bomblet. %s systems was hit", percent,type,distance,failed);
+ nearby_explosion();
+ return;
+ }
+
+ distance = math.max(distance-full_damage_dist_m, 0);
- if (contains(warhead_lbs, type)) {
- #maxDist = maxDamageDistFromWarhead(warhead_lbs[type]);
+ var maxDist = 0;# distance where the explosion dont hurt us anymore
+ var lbs = 0;
+
+ if (hitable_by_ground_munitions and contains(warhead_lbs, type)) {
+ lbs = warhead_lbs[type];
+ maxDist = maxDamageDistFromWarhead(lbs);#3*sqrt(lbs)
+ } elsif (hitable_by_air_munitions and contains(warhead_air_lbs, type)) {
+ lbs = warhead_air_lbs[type];
+ maxDist = maxDamageDistFromWarhead(lbs);
} else {
return;
}
-
- if (type == "M90" and distance < 300) {
- var failed = fail_systems(warhead_lbs[type]/2);
- return;
- } elsif (distance < 150) {
- var prob = 1;
- if ( distance > 50 ) {
- distance = distance - 50;
- prob = 1 - (distance/100);
- }
+
+ var diff = maxDist-distance;
+ if (diff < 0) {
+ diff = 0;
+ }
+ diff = diff * diff;
+
+ var probability = diff / (maxDist*maxDist);
+
+ if (use_hitpoints_instead_of_failure_modes_bool) {
+ var hpDist = maxDamageDistFromWarhead(hp_max);
+ probability = (maxDist/hpDist)*probability;
}
-
- var failed = fail_systems(warhead_lbs[type] * prob);
- #ar percent = 100 * probability;
- #printf("Took %.1f%% damage from %s missile at %0.1f meters. %s systems was hit", percent,type,dist,failed);
+ var failed = fail_systems(probability, hp_max);
+ 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();
+
+ ####
+ # I don't remember all the considerations that went into our original warhead damage model.
+ # But looking at the formula it looks like they all do 100% damage at 0 meter hit,
+ # and warhead size is only used to determine the decrease of damage with distance increase.
+ # It sorta gets the job done though, so I am hesitant to advocate that warheads above a certain
+ # size should give 100% damage for some distance, and that warheads smaller than certain size should
+ # not give 100% damage even on direct hit.
+ # Anyway, for hitpoint based assets, this is now the case. Maybe we should consider to also do something
+ # similar for failure mode based aircraft. ~Nikolai
+ ####
+
+ ## example 1: ##
+ # 300 lbs warhead, 50 meters distance
+ # maxDist=52
+ # diff = 52-50 = 2
+ # diff^2 = 4
+ # prob = 4/2700 = 0.15%
+
+ ## example 2: ##
+ # 300 lbs warhead, 25 meters distance
+ # maxDist=52
+ # diff = 52-25 = 27
+ # diff^2 = 729
+ # prob = 729/2700 = 27%
}
}
- } elsif (cannon_types[last_vector[1]] != nil) {
- # cannon hitting someone
- print("cannon");
+ } elsif (hitable_by_cannon and cannon_types[last_vector[1]] != nil) {
if (size(last_vector) > 2 and last_vector[2] == " "~callsign) {
- print("cannon hit us");
- var last3 = split(" ", last_vector[3]);
- #print("last3[2]: " ~ last3[2]);
- #print("last3[1]: " ~ last3[1]);
- if(size(last3) > 2) {
- if ( last3[2] == "hits" ) {
- var hit_count = num(last3[1]);
+ if (size(last_vector) < 4) {
+ # msg is either missing number of hits, or has no trailing dots from spam filter.
+ print('"'~last~'" is not a legal hit message, tell the shooter to upgrade his OPRF plane :)');
+ return;
+ }
+ var last3 = split(" ", last_vector[3]);
+ if(size(last3) > 2 and size(last3[2]) > 2 and last3[2] == "hits" ) {
+ var probability = cannon_types[last_vector[1]];
+ var hit_count = num(last3[1]);
+ if (hit_count != nil) {
+ var damaged_sys = 0;
+ for (var i = 1; i <= hit_count; i = i + 1) {
+ var failed = fail_systems(probability);
+ damaged_sys = damaged_sys + failed;
+ }
+
+ printf("Took %.1f%% x %2d damage from cannon! %s systems was hit.", probability*100, hit_count, damaged_sys);
+ nearby_explosion();
}
} else {
- var hit_count = 4;
+ var probability = cannon_types[last_vector[1]];
+ #print("probability: " ~ probability);
+
+ var failed = fail_systems(probability * 3);# Old messages is assumed to be 3 hits
+ printf("Took %.1f%% x 3 damage from cannon! %s systems was hit.", probability*100, failed);
+ nearby_explosion();
}
- var damaged_sys = 0;
- var probability = cannon_types[last_vector[1]];
- for (var i = 1; i <= hit_count; i = i + 1) {
- var failed = fail_systems(probability);
- damaged_sys = damaged_sys + failed;
- }
- # that someone is me!
- #print("hitting me");
-
- printf("Took %.1f%% damage from cannon! %s systems was hit.", probability*hit_count*100, damaged_sys);
}
}
}
@@ -226,22 +332,132 @@ var incoming_listener = func {
}
var maxDamageDistFromWarhead = func (lbs) {
- # very simple
- var dist = 7*math.sqrt(lbs);
-
+ # Calc at what distance the warhead will do zero damage every time.
+ var dist = 3*math.sqrt(lbs);
return dist;
}
-var fail_systems = func (damage) {
- hp = hp - damage;
- print("HP: " ~ hp ~ "/" ~ hp_max);
-
- if ( hp < 0 ) {
- setprop("/carrier/sunk/",1);
- setprop("/sim/multiplay/generic/int[0]",1);
- }
+var fail_systems = func (probability, factor = 100) {#this factor needs tuning after all asset hitpoints have been evaluated.
+ if (fleet) {
+ return fail_fleet_systems(probability, factor);
+ } elsif (use_hitpoints_instead_of_failure_modes_bool) {
+ hp -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ printf("HP: %d/%d", hp, hp_max);
+ setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
+ if ( hp < 0 ) {
+ setprop("/carrier/sunk/",1);#we are dead
+ setprop("/sim/multiplay/generic/int[2]",1);#radar off
+ setprop("/sim/multiplay/generic/int[0]",1);#smoke on
+ setprop("/sim/messages/copilot", getprop("sim/multiplay/callsign")~" dead.");
+ }
+ return -1;
+ } else {
+ 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;
+ }
};
+hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
+
+var fail_fleet_systems = func (probability, factor) {
+ var no = 7;
+ while (no > 6 or hp_f[no] < 0) {
+ no = int(rand()*7);
+ if (hp_f[no] < 0) {
+ if (rand() > 0.9) {
+ armament.defeatSpamFilter("You shot one of our already sinking ships, you are just mean.");
+ hp_f[no] -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ print("HP["~no~"]: " ~ hp_f[no] ~ "/" ~ hp_max);
+ return;
+ }
+ }
+ }
+ hp_f[no] -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ printf("HP[%d]: %d/%d", no, hp_f[no], hp_max);
+ #setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
+ if ( hp_f[no] < 0 ) {
+ setprop("/sim/multiplay/generic/bool["~(no+40)~"]",1);
+ armament.defeatSpamFilter("So you sank one of our ships, we will get you for that!");
+ if (!getprop("/carrier/disabled") and hp_f[0]<0 and hp_f[1]<0 and hp_f[2]<0) {
+ setprop("/carrier/disabled",1);
+ armament.defeatSpamFilter("Captain our offensive capability is crippled!");
+ }
+ if (hp_f[0]<0 and hp_f[1]<0 and hp_f[2]<0 and hp_f[3]<0 and hp_f[4]<0 and hp_f[5]<0 and hp_f[6]<0) {
+ setprop("/carrier/sunk",1);
+ setprop("/sim/multiplay/generic/int[2]",1);#radar off
+ setprop("/sim/messages/copilot", getprop("sim/multiplay/callsign")~" dead.");
+ armament.defeatSpamFilter("S.O.S. Heeelp");
+ } else {
+ armament.defeatSpamFilter("This is not over yet..");
+ }
+ }
+ return -1;
+};
+
+var warn = func (last_vector,m2000,callsign,author) {
+ 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;
+ }
+ }
+ }
+ }
+}
+
var playIncomingSound = func (clock) {
setprop("sound/incoming"~clock, 1);
settimer(func {stopIncomingSound(clock);},3);
@@ -251,6 +467,20 @@ 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];
@@ -266,20 +496,25 @@ var processCallsigns = func () {
callsign_struct[callsign] = player;
}
}
- settimer(processCallsigns, 1.5);
+ settimer(processCallsigns, 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");
+setlistener("/sim/multiplay/chat-history", incoming_listener, 0, 0);
- setprop("logging/date-log", date);
- setprop("logging/time-log", time);
+# prevent flooding the pilots screen with failure modes that fail when getting hit.
+setprop("/sim/failure-manager/display-on-screen", FALSE);
+
+var re_init = func {
+ # repair the aircraft at relocation to another airport.
+
+ 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/multiplay/chat-history", incoming_listener, 0, 0);
\ No newline at end of file
+setlistener("/sim/signals/reinit", re_init, 0, 0);
diff --git a/gci-radar/Nasal/gci.nas b/gci-radar/Nasal/gci.nas
index 41253a5..1534491 100644
--- a/gci-radar/Nasal/gci.nas
+++ b/gci-radar/Nasal/gci.nas
@@ -17,7 +17,6 @@
# request a BRAA, then it will receive it.
var damage_prop = props.globals.getNode("/carrier/sunk");
var prop_watch = {
- "MiG-15bis": [0,1,2],
"MiG-21bis": [0,1,2],
"MiG-21MF-75": [0,1,2],
"QF-4E": [0,1,2],
@@ -447,7 +446,12 @@ var get_intercept = func(bearing, dist_m, runnerHeading, runnerSpeed, chaserSpee
}
var t1 = (-b+math.sqrt(b*b-4*a*c))/(2*a);
var t2 = (-b-math.sqrt(b*b-4*a*c))/(2*a);
-
+
+ if (t1 < 0 and t2 < 0) {
+ # intercept not possible
+ return nil;
+ }
+
var timeToIntercept = 0;
if (t1 > 0 and t2 > 0) {
timeToIntercept = math.min(t1, t2);
diff --git a/gci-radar/gci-set.xml b/gci-radar/gci-set.xml
index d92b5d2..771ed49 100644
--- a/gci-radar/gci-set.xml
+++ b/gci-radar/gci-set.xml
@@ -93,14 +93,21 @@
0
+ 0
- 500
+
false
+
+
+
+ true
+
+
Aircraft/gci-radar/Nasal/damage.nas
diff --git a/groundtarget/Nasal/damage.nas b/groundtarget/Nasal/damage.nas
index d740cee..d91e582 100644
--- a/groundtarget/Nasal/damage.nas
+++ b/groundtarget/Nasal/damage.nas
@@ -1,37 +1,70 @@
-var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
+#
+# Install: Include this code into an aircraft to make it damagable. (remember to add it to the -set file)
+#
+# Authors: Nikolai V. Chr. and Pinto (with improvement by Onox)
+#
+#
+
+
+############################ Config ######################################################################################
+var full_damage_dist_m = 2;# Can vary from aircraft to aircraft depending on how many failure modes it has.
+ # Many modes (like Viggen) ought to have lower number like zero.
+ # Few modes (like F-14) ought to have larger number such as 3.
+ # For assets this should be average radius of the asset.
+var use_hitpoints_instead_of_failure_modes_bool = 1;# mainly used by assets that don't have failure modes.
+var hp_max = 5;# given a direct hit, how much pounds of warhead is needed to kill. Only used if hitpoints is enabled.
+var hitable_by_air_munitions = 0; # if anti-air can do damage
+var hitable_by_cannon = 1; # if cannon can do damage
+var hitable_by_ground_munitions = 1;# if anti-ground/marine can do damage
+var is_fleet = 0; # Is really 7 ships, 3 of which has offensive missiles.
+##########################################################################################################################
+
+##
+## TODO:
+## Include mechanics for hitting fleet
+## Move all to emesary
+##
+
var TRUE = 1;
var FALSE = 0;
-var hp = 2500;
-var hp_max = hp;
+var hp = hp_max;
var cannon_types = {
- " M70 rocket hit": 0.25, #135mm
- " M55 cannon shell hit": 0.10, # 30mm
- " KCA cannon shell hit": 0.10, # 30mm
- " Gun Splash On ": 0.10, # 30mm
- " M61A1 shell hit": 0.05, # 20mm
- " GAU-8/A hit": 0.10, # 30mm
- " BK27 cannon hit": 0.07, # 27mm
- " GSh-30 hit": 0.10, # 30mm
- " GSh-23 hit": 0.065,# 23mm
- " 7.62 hit": 0.005,# 7.62mm
- " 50 BMG hit": 0.015,# 12.7mm
- " S-5 rocket hit": 0.20, #55mm
-};
-
-
-
+ #
+ # 0.20 means a direct hit will disable 20% of the failure modes on average.
+ # or, 0.20 also means a direct hit can do 20 hitpoints damage.
+ #
+ " M70 rocket hit": 0.250, #135mm
+ " S-5 rocket hit": 0.200, # 55mm
+ " M55 cannon shell hit": 0.100, # 30mm
+ " KCA cannon shell hit": 0.100, # 30mm
+ " Gun Splash On ": 0.100, # 30mm
+ " GSh-30 hit": 0.100, # 30mm
+ " GAU-8/A hit": 0.100, # 30mm
+ " BK27 cannon hit": 0.070, # 27mm
+ " GSh-23 hit": 0.065, # 23mm
+ " M61A1 shell hit": 0.050, # 20mm
+ " 50 BMG hit": 0.015, # 12.7mm (non-explosive)
+ " 7.62 hit": 0.005, # 7.62mm (non-explosive)
+};
+
+# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
+
var warhead_lbs = {
+ # Anti-ground/marine warheads (sorted alphabetically)
"AGM-65": 126.00,
"AGM-84": 488.00,
"AGM-88": 146.00,
"AGM65": 200.00,
+ "AGM-154A": 493.00,
+ "AGM-158": 1000.00,
"ALARM": 450.00,
"AM39-Exocet": 364.00,
"AS-37-Martel": 330.00,
"AS30L": 529.00,
+ "CBU-87": 10.00,# bomblet warhead. Mix of armour piecing and HE.
"Exocet": 364.00,
"FAB-100": 92.59,
"FAB-250": 202.85,
@@ -45,12 +78,10 @@ var warhead_lbs = {
"KAB-500": 564.38,
"Kh-25MP": 197.53,
"Kh-66": 244.71,
- "KN-06": 315.00,
"LAU-68": 10.00,
- "M317": 145.00,
"M71": 200.00,
"M71R": 200.00,
- "M90": 500.00,
+ "M90": 3.00,# bomblet warhead.
"MK-82": 192.00,
"MK-83": 445.00,
"MK-84": 945.00,
@@ -63,8 +94,7 @@ var warhead_lbs = {
"RN-18T": 1200.00, #fictional, thermobaeric replacement for the RN-28 nuclear bomb
"RS-2US": 28.66,
"S-21": 245.00,
- "S-24": 271.00,
- "S530D": 66.00,
+ "S-24": 271.00,
"SCALP": 992.00,
"Sea Eagle": 505.00,
"SeaEagle": 505.00,
@@ -73,6 +103,81 @@ var warhead_lbs = {
"ZB-500": 473.99,
};
+var warhead_air_lbs = {
+ # Anti-air warheads (sorted alphabetically)
+ "aim-120": 44.00,
+ "AIM-120": 44.00,
+ "AIM-54": 135.00,
+ "aim-7": 88.00,
+ "AIM-7": 88.00,
+ "aim-9": 20.80,
+ "AIM-9": 20.80,
+ "AIM120": 44.00,
+ "AIM132": 22.05,
+ "AIM9": 20.80,
+ "KN-06": 315.00,
+ "M317": 145.00,
+ "Magic-2": 27.00,
+ "Matra MICA": 30.00,
+ "Matra R550 Magic 2": 27.00,
+ "MATRA-R530": 55.00,
+ "MatraMica": 30.00,
+ "MatraMicaIR": 30.00,
+ "MatraR550Magic2": 27.00,
+ "Meteor": 55.00,
+ "MICA-EM": 30.00,
+ "MICA-IR": 30.00,
+ "R-13M": 16.31,
+ "R-27R1": 85.98,
+ "R-27T1": 85.98,
+ "R-3R": 16.31,
+ "R-3S": 16.31,
+ "R-55": 20.06,
+ "R-60": 6.60,
+ "R-60M": 7.70,
+ "R-73E": 16.31,
+ "R-77": 49.60,
+ "R74": 16.00,
+ "RB-05A": 353.00,
+ "RB-24": 20.80,
+ "RB-24J": 20.80,
+ "RB-71": 88.00,
+ "RB-74": 20.80,
+ "RB-99": 44.00,
+ "S530D": 66.00,
+};
+
+var cluster = {
+ # cluster munition list
+ "M90": nil,
+ "CBU-87": nil,
+};
+
+var fireMsgs = {
+
+ # F14
+ " FOX3 at": nil, # radar
+ " FOX2 at": nil, # heat
+ " FOX1 at": nil, # semi-radar
+
+ # Generic
+ " Fox 1 at": nil, # semi-radar
+ " Fox 2 at": nil, # heat
+ " Fox 3 at": nil, # radar
+ " Greyhound at": nil, # cruise missile
+ " Bombs away at": nil, # bombs
+ " Bruiser at": nil, # anti-ship
+ " Rifle at": nil, # TV guided
+ " Sniper at": nil, # anti-radiation
+
+ # SAM, fleet and missile frigate
+ " Bird away at": nil, # G/A
+
+ # F15
+ " aim7 at": nil,
+ " aim9 at": nil,
+ " aim120 at": nil,
+};
var incoming_listener = func {
var history = getprop("/sim/multiplay/chat-history");
@@ -82,6 +187,7 @@ var incoming_listener = func {
var last_vector = split(":", last);
var author = last_vector[0];
var callsign = getprop("sim/multiplay/callsign");
+ callsign = size(callsign) < 8 ? callsign : left(callsign,7);
if (size(last_vector) > 1 and author != callsign) {
# not myself
#print("not me");
@@ -90,67 +196,10 @@ var incoming_listener = func {
# 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 m2000 == TRUE) {
+ if (contains(fireMsgs, last_vector[1]) 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");
+ warn(last_vector,m2000,callsign,author);
+ } elsif (getprop("payload/armament/msg")) {
var last1 = split(" ", last_vector[1]);
if(size(last1) > 2 and last1[size(last1)-1] == "exploded" ) {
#print("missile hitting someone");
@@ -168,56 +217,113 @@ var incoming_listener = func {
if(distance != nil) {
var dist = distance;
- #check distance w/ if statement here
+ if (contains(cluster, type)) {
+ # cluster munition
+ var lbs = warhead_lbs[type];
+ var maxDist = maxDamageDistFromWarhead(lbs);
+ var distance = math.max(0,rand()*2-full_damage_dist_m);#being 0 to 2 meters from a bomblet on average.
+ var diff = maxDist-distance;
+ diff = diff * diff;
+ var probability = diff / (maxDist*maxDist);
+ if (use_hitpoints_instead_of_failure_modes_bool) {
+ var hpDist = maxDamageDistFromWarhead(hp_max);
+ probability = (maxDist/hpDist)*probability;
+ }
+ var failed = fail_systems(probability, hp_max);
+ var percent = 100 * prob;
+ printf("Took %.1f%% damage from %s clusterbomb at %0.1f meters from bomblet. %s systems was hit", percent,type,distance,failed);
+ nearby_explosion();
+ return;
+ }
+
+ distance = math.max(distance-full_damage_dist_m, 0);
- if (contains(warhead_lbs, type)) {
- #maxDist = maxDamageDistFromWarhead(warhead_lbs[type]);
+ var maxDist = 0;# distance where the explosion dont hurt us anymore
+ var lbs = 0;
+
+ if (hitable_by_ground_munitions and contains(warhead_lbs, type)) {
+ lbs = warhead_lbs[type];
+ maxDist = maxDamageDistFromWarhead(lbs);#3*sqrt(lbs)
+ } elsif (hitable_by_air_munitions and contains(warhead_air_lbs, type)) {
+ lbs = warhead_air_lbs[type];
+ maxDist = maxDamageDistFromWarhead(lbs);
} else {
return;
}
-
- if (type == "M90" and distance < 300) {
- var failed = fail_systems(warhead_lbs[type]/2);
- return;
- } elsif (distance < 150) {
- var prob = 1;
- if ( distance > 50 ) {
- distance = distance - 50;
- prob = 1 - (distance/100);
- }
+
+ var diff = maxDist-distance;
+ if (diff < 0) {
+ diff = 0;
+ }
+ diff = diff * diff;
+
+ var probability = diff / (maxDist*maxDist);
+
+ if (use_hitpoints_instead_of_failure_modes_bool) {
+ var hpDist = maxDamageDistFromWarhead(hp_max);
+ probability = (maxDist/hpDist)*probability;
}
-
- var failed = fail_systems(warhead_lbs[type] * prob);
- #ar percent = 100 * probability;
- #printf("Took %.1f%% damage from %s missile at %0.1f meters. %s systems was hit", percent,type,dist,failed);
+ var failed = fail_systems(probability, hp_max);
+ 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();
+
+ ####
+ # I don't remember all the considerations that went into our original warhead damage model.
+ # But looking at the formula it looks like they all do 100% damage at 0 meter hit,
+ # and warhead size is only used to determine the decrease of damage with distance increase.
+ # It sorta gets the job done though, so I am hesitant to advocate that warheads above a certain
+ # size should give 100% damage for some distance, and that warheads smaller than certain size should
+ # not give 100% damage even on direct hit.
+ # Anyway, for hitpoint based assets, this is now the case. Maybe we should consider to also do something
+ # similar for failure mode based aircraft. ~Nikolai
+ ####
+
+ ## example 1: ##
+ # 300 lbs warhead, 50 meters distance
+ # maxDist=52
+ # diff = 52-50 = 2
+ # diff^2 = 4
+ # prob = 4/2700 = 0.15%
+
+ ## example 2: ##
+ # 300 lbs warhead, 25 meters distance
+ # maxDist=52
+ # diff = 52-25 = 27
+ # diff^2 = 729
+ # prob = 729/2700 = 27%
}
}
- } elsif (cannon_types[last_vector[1]] != nil) {
- # cannon hitting someone
- print("cannon");
+ } elsif (hitable_by_cannon and cannon_types[last_vector[1]] != nil) {
if (size(last_vector) > 2 and last_vector[2] == " "~callsign) {
- print("cannon hit us");
- var last3 = split(" ", last_vector[3]);
- #print("last3[2]: " ~ last3[2]);
- #print("last3[1]: " ~ last3[1]);
- if(size(last3) > 2) {
- if ( last3[2] == "hits" ) {
- var hit_count = num(last3[1]);
+ if (size(last_vector) < 4) {
+ # msg is either missing number of hits, or has no trailing dots from spam filter.
+ print('"'~last~'" is not a legal hit message, tell the shooter to upgrade his OPRF plane :)');
+ return;
+ }
+ var last3 = split(" ", last_vector[3]);
+ if(size(last3) > 2 and size(last3[2]) > 2 and last3[2] == "hits" ) {
+ var probability = cannon_types[last_vector[1]];
+ var hit_count = num(last3[1]);
+ if (hit_count != nil) {
+ var damaged_sys = 0;
+ for (var i = 1; i <= hit_count; i = i + 1) {
+ var failed = fail_systems(probability);
+ damaged_sys = damaged_sys + failed;
+ }
+
+ printf("Took %.1f%% x %2d damage from cannon! %s systems was hit.", probability*100, hit_count, damaged_sys);
+ nearby_explosion();
}
} else {
- var hit_count = 4;
+ var probability = cannon_types[last_vector[1]];
+ #print("probability: " ~ probability);
+
+ var failed = fail_systems(probability * 3);# Old messages is assumed to be 3 hits
+ printf("Took %.1f%% x 3 damage from cannon! %s systems was hit.", probability*100, failed);
+ nearby_explosion();
}
- var damaged_sys = 0;
- var probability = cannon_types[last_vector[1]];
- for (var i = 1; i <= hit_count; i = i + 1) {
- var failed = fail_systems(probability);
- damaged_sys = damaged_sys + failed;
- }
- # that someone is me!
- #print("hitting me");
-
- printf("Took %.1f%% damage from cannon! %s systems was hit.", probability*hit_count*100, damaged_sys);
}
}
}
@@ -226,22 +332,132 @@ var incoming_listener = func {
}
var maxDamageDistFromWarhead = func (lbs) {
- # very simple
- var dist = 7*math.sqrt(lbs);
-
+ # Calc at what distance the warhead will do zero damage every time.
+ var dist = 3*math.sqrt(lbs);
return dist;
}
-var fail_systems = func (damage) {
- hp = hp - damage;
- print("HP: " ~ hp ~ "/" ~ hp_max);
-
- if ( hp < 0 ) {
- setprop("/carrier/sunk/",1);
- setprop("/sim/multiplay/generic/int[0]",1);
- }
+var fail_systems = func (probability, factor = 100) {#this factor needs tuning after all asset hitpoints have been evaluated.
+ if (fleet) {
+ return fail_fleet_systems(probability, factor);
+ } elsif (use_hitpoints_instead_of_failure_modes_bool) {
+ hp -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ printf("HP: %d/%d", hp, hp_max);
+ setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
+ if ( hp < 0 ) {
+ setprop("/carrier/sunk/",1);#we are dead
+ setprop("/sim/multiplay/generic/int[2]",1);#radar off
+ setprop("/sim/multiplay/generic/int[0]",1);#smoke on
+ setprop("/sim/messages/copilot", getprop("sim/multiplay/callsign")~" dead.");
+ }
+ return -1;
+ } else {
+ 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;
+ }
};
+hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
+
+var fail_fleet_systems = func (probability, factor) {
+ var no = 7;
+ while (no > 6 or hp_f[no] < 0) {
+ no = int(rand()*7);
+ if (hp_f[no] < 0) {
+ if (rand() > 0.9) {
+ armament.defeatSpamFilter("You shot one of our already sinking ships, you are just mean.");
+ hp_f[no] -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ print("HP["~no~"]: " ~ hp_f[no] ~ "/" ~ hp_max);
+ return;
+ }
+ }
+ }
+ hp_f[no] -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ printf("HP[%d]: %d/%d", no, hp_f[no], hp_max);
+ #setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
+ if ( hp_f[no] < 0 ) {
+ setprop("/sim/multiplay/generic/bool["~(no+40)~"]",1);
+ armament.defeatSpamFilter("So you sank one of our ships, we will get you for that!");
+ if (!getprop("/carrier/disabled") and hp_f[0]<0 and hp_f[1]<0 and hp_f[2]<0) {
+ setprop("/carrier/disabled",1);
+ armament.defeatSpamFilter("Captain our offensive capability is crippled!");
+ }
+ if (hp_f[0]<0 and hp_f[1]<0 and hp_f[2]<0 and hp_f[3]<0 and hp_f[4]<0 and hp_f[5]<0 and hp_f[6]<0) {
+ setprop("/carrier/sunk",1);
+ setprop("/sim/multiplay/generic/int[2]",1);#radar off
+ setprop("/sim/messages/copilot", getprop("sim/multiplay/callsign")~" dead.");
+ armament.defeatSpamFilter("S.O.S. Heeelp");
+ } else {
+ armament.defeatSpamFilter("This is not over yet..");
+ }
+ }
+ return -1;
+};
+
+var warn = func (last_vector,m2000,callsign,author) {
+ 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;
+ }
+ }
+ }
+ }
+}
+
var playIncomingSound = func (clock) {
setprop("sound/incoming"~clock, 1);
settimer(func {stopIncomingSound(clock);},3);
@@ -251,6 +467,20 @@ 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];
@@ -266,20 +496,25 @@ var processCallsigns = func () {
callsign_struct[callsign] = player;
}
}
- settimer(processCallsigns, 1.5);
+ settimer(processCallsigns, 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");
+setlistener("/sim/multiplay/chat-history", incoming_listener, 0, 0);
- setprop("logging/date-log", date);
- setprop("logging/time-log", time);
+# prevent flooding the pilots screen with failure modes that fail when getting hit.
+setprop("/sim/failure-manager/display-on-screen", FALSE);
+
+var re_init = func {
+ # repair the aircraft at relocation to another airport.
+
+ 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/multiplay/chat-history", incoming_listener, 0, 0);
\ No newline at end of file
+setlistener("/sim/signals/reinit", re_init, 0, 0);
diff --git a/groundtarget/Nasal/fdm.nas b/groundtarget/Nasal/fdm.nas
index 1471021..cf95a8e 100644
--- a/groundtarget/Nasal/fdm.nas
+++ b/groundtarget/Nasal/fdm.nas
@@ -33,12 +33,19 @@ setprop("/carrier/pitch-offset",0);
setprop("/carrier/roll-deg",0);
setprop("/carrier/roll-offset",0);
setprop("/carrier/sunk",0);
-
+var arrived = 0;
var PositionUpdater = func () {
settimer( PositionUpdater, 1/frequency );
var position = geo.aircraft_position();
+
+ if ( arrived == 0 and getprop("/carrier/sunk") == 0 and getprop("/autopilot/route-manager/wp-last/dist") != nil and getprop("/autopilot/route-manager/wp-last/dist") < 1 ) {
+ setprop("/sim/multiplay/chat",getprop("sim/multiplay/callsign") ~ " has arrived safely!");
+ print("arrived");
+ arrived = 1;
+ #return;
+ }
var time_now = getprop("/sim/time/elapsed-sec");
var dt = (time_now - time_last) * sim_speed;
@@ -53,7 +60,7 @@ var PositionUpdater = func () {
if ( getprop("/carrier/sunk") == 0 and getprop("/autopilot/route-manager/active") == 1 ) {
#for event
- var speed = 50;
+ var speed = 25;
var cur_waypoint = getprop("/autopilot/route-manager/current-wp");
var cur_wp_lon = getprop("/autopilot/route-manager/route/wp[" ~ cur_waypoint ~ "]/longitude-deg");
var cur_wp_lat = getprop("/autopilot/route-manager/route/wp[" ~ cur_waypoint ~ "]/latitude-deg");
@@ -68,7 +75,7 @@ var PositionUpdater = func () {
# Set new position
setprop("/position/latitude-deg", position.lat());
setprop("/position/longitude-deg", position.lon());
- var g_alt = getprop("/position/ground-elev-ft");
+ var g_alt = getprop("/position/ground-elev-ft")+1;
setprop("/position/altitude-ft",g_alt);
diff --git a/groundtarget/truck-set.xml b/groundtarget/truck-set.xml
index ab4de28..e6326c6 100644
--- a/groundtarget/truck-set.xml
+++ b/groundtarget/truck-set.xml
@@ -127,6 +127,12 @@
+
+
+
+ true
+
+
diff --git a/missile-frigate/Hud/hud.xml b/missile-frigate/Hud/hud.xml
index 2632408..2f2f716 100644
--- a/missile-frigate/Hud/hud.xml
+++ b/missile-frigate/Hud/hud.xml
@@ -37,53 +37,6 @@
variable
-->
-
- Ladder
- pitch
- -60
- -90
- 120
- 180
-
-
-
- /sim/current-view/name
- Approach View
-
-
-
-
- /orientation/roll-deg
- -1.0
-
-
-
- /orientation/pitch-deg
- -1.0
-
-
- 30
- 8
- 1.0
- 100
- 0
- 0.0
- false
- false
- true
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
- false
-
-
Wind Angle Runway
-300
@@ -100,170 +53,6 @@
-
- Height
- -300
- 80
- 200
- 25
-
-
-
-
- /sim/current-view/name
- Landing Signal Officer View
-
-
- /sim/current-view/name
- Approach View
-
-
-
-
- false
- HEIGHT:
- left
-
-
- /sim/current-view/height
-
-
-
- 0.25
-
-
-
- /sim/current-view/height
- VERY LOW
-
-
- /sim/current-view/distance
- 1
-
-
-
-
-
-
-
- Gear
- -300
- 60
- 200
- 25
-
-
-
-
- /sim/current-view/name
- Landing Signal Officer View
-
-
- /sim/current-view/name
- Approach View
-
-
-
-
- false
- GEAR:
- left
-
-
- /sim/current-view/gear
-
-
-
- 0.25
-
-
-
- /sim/current-view/gear
- 1
-
-
- /sim/current-view/distance
- 1
-
-
-
-
-
-
-
- Flap
- -300
- 40
- 200
- 25
-
-
-
-
- /sim/current-view/name
- Landing Signal Officer View
-
-
- /sim/current-view/name
- Approach View
-
-
-
-
- false
- FLAPS:
- left
-
-
- /sim/current-view/flap
-
-
-
- 0.25
-
-
-
- /sim/current-view/flap
- 1
-
-
- /sim/current-view/distance
- 1
-
-
-
-
-
-
-
- Hook
- -300
- 20
- 200
- 25
-
-
-
-
- /sim/current-view/name
- Landing Signal Officer View
-
-
- /sim/current-view/name
- Approach View
-
-
-
-
- false
- HOOK:
- left
-
-
- /sim/current-view/hook
-
-
-
Magnetic Heading
-300
diff --git a/missile-frigate/Nasal/damage.nas b/missile-frigate/Nasal/damage.nas
index cb831e3..124b433 100644
--- a/missile-frigate/Nasal/damage.nas
+++ b/missile-frigate/Nasal/damage.nas
@@ -1,37 +1,70 @@
-var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
+#
+# Install: Include this code into an aircraft to make it damagable. (remember to add it to the -set file)
+#
+# Authors: Nikolai V. Chr. and Pinto (with improvement by Onox)
+#
+#
+
+
+############################ Config ######################################################################################
+var full_damage_dist_m =20;# Can vary from aircraft to aircraft depending on how many failure modes it has.
+ # Many modes (like Viggen) ought to have lower number like zero.
+ # Few modes (like F-14) ought to have larger number such as 3.
+ # For assets this should be average radius of the asset.
+var use_hitpoints_instead_of_failure_modes_bool = 1;# mainly used by assets that don't have failure modes.
+var hp_max =200;# given a direct hit, how much pounds of warhead is needed to kill. Only used if hitpoints is enabled.
+var hitable_by_air_munitions = 0; # if anti-air can do damage
+var hitable_by_cannon = 1; # if cannon can do damage
+var hitable_by_ground_munitions = 1;# if anti-ground/marine can do damage
+var is_fleet = 0; # Is really 7 ships, 3 of which has offensive missiles.
+##########################################################################################################################
+
+##
+## TODO:
+## Include mechanics for hitting fleet
+## Move all to emesary
+##
+
var TRUE = 1;
var FALSE = 0;
-var hp = 200;
-var hp_max = hp;
+var hp = hp_max;
var cannon_types = {
- " M70 rocket hit": 0.25, #135mm
- " M55 cannon shell hit": 0.10, # 30mm
- " KCA cannon shell hit": 0.10, # 30mm
- " Gun Splash On ": 0.10, # 30mm
- " M61A1 shell hit": 0.05, # 20mm
- " GAU-8/A hit": 0.10, # 30mm
- " BK27 cannon hit": 0.07, # 27mm
- " GSh-30 hit": 0.10, # 30mm
- " GSh-23 hit": 0.065,# 23mm
- " 7.62 hit": 0.005,# 7.62mm
- " 50 BMG hit": 0.015,# 12.7mm
- " S-5 rocket hit": 0.20, #55mm
-};
-
-
-
+ #
+ # 0.20 means a direct hit will disable 20% of the failure modes on average.
+ # or, 0.20 also means a direct hit can do 20 hitpoints damage.
+ #
+ " M70 rocket hit": 0.250, #135mm
+ " S-5 rocket hit": 0.200, # 55mm
+ " M55 cannon shell hit": 0.100, # 30mm
+ " KCA cannon shell hit": 0.100, # 30mm
+ " Gun Splash On ": 0.100, # 30mm
+ " GSh-30 hit": 0.100, # 30mm
+ " GAU-8/A hit": 0.100, # 30mm
+ " BK27 cannon hit": 0.070, # 27mm
+ " GSh-23 hit": 0.065, # 23mm
+ " M61A1 shell hit": 0.050, # 20mm
+ " 50 BMG hit": 0.015, # 12.7mm (non-explosive)
+ " 7.62 hit": 0.005, # 7.62mm (non-explosive)
+};
+
+# lbs of warheads is explosive+fragmentation+fuse, so total warhead mass.
+
var warhead_lbs = {
+ # Anti-ground/marine warheads (sorted alphabetically)
"AGM-65": 126.00,
"AGM-84": 488.00,
"AGM-88": 146.00,
"AGM65": 200.00,
+ "AGM-154A": 493.00,
+ "AGM-158": 1000.00,
"ALARM": 450.00,
"AM39-Exocet": 364.00,
"AS-37-Martel": 330.00,
"AS30L": 529.00,
+ "CBU-87": 10.00,# bomblet warhead. Mix of armour piecing and HE.
"Exocet": 364.00,
"FAB-100": 92.59,
"FAB-250": 202.85,
@@ -45,12 +78,10 @@ var warhead_lbs = {
"KAB-500": 564.38,
"Kh-25MP": 197.53,
"Kh-66": 244.71,
- "KN-06": 315.00,
"LAU-68": 10.00,
- "M317": 145.00,
"M71": 200.00,
"M71R": 200.00,
- "M90": 500.00,
+ "M90": 3.00,# bomblet warhead.
"MK-82": 192.00,
"MK-83": 445.00,
"MK-84": 945.00,
@@ -63,8 +94,7 @@ var warhead_lbs = {
"RN-18T": 1200.00, #fictional, thermobaeric replacement for the RN-28 nuclear bomb
"RS-2US": 28.66,
"S-21": 245.00,
- "S-24": 271.00,
- "S530D": 66.00,
+ "S-24": 271.00,
"SCALP": 992.00,
"Sea Eagle": 505.00,
"SeaEagle": 505.00,
@@ -73,6 +103,82 @@ var warhead_lbs = {
"ZB-500": 473.99,
};
+var warhead_air_lbs = {
+ # Anti-air warheads (sorted alphabetically)
+ "aim-120": 44.00,
+ "AIM-120": 44.00,
+ "AIM-54": 135.00,
+ "aim-7": 88.00,
+ "AIM-7": 88.00,
+ "aim-9": 20.80,
+ "AIM-9": 20.80,
+ "AIM120": 44.00,
+ "AIM132": 22.05,
+ "AIM9": 20.80,
+ "KN-06": 315.00,
+ "M317": 145.00,
+ "Magic-2": 27.00,
+ "Matra MICA": 30.00,
+ "Matra R550 Magic 2": 27.00,
+ "MATRA-R530": 55.00,
+ "MatraMica": 30.00,
+ "MatraMicaIR": 30.00,
+ "MatraR550Magic2": 27.00,
+ "Meteor": 55.00,
+ "MICA-EM": 30.00,
+ "MICA-IR": 30.00,
+ "R-13M": 16.31,
+ "R-27R1": 85.98,
+ "R-27T1": 85.98,
+ "R-3R": 16.31,
+ "R-3S": 16.31,
+ "R-55": 20.06,
+ "R-60": 6.60,
+ "R-60M": 7.70,
+ "R-73E": 16.31,
+ "R-77": 49.60,
+ "R74": 16.00,
+ "RB-05A": 353.00,
+ "RB-24": 20.80,
+ "RB-24J": 20.80,
+ "RB-71": 88.00,
+ "RB-74": 20.80,
+ "RB-99": 44.00,
+ "S530D": 66.00,
+};
+
+var cluster = {
+ # cluster munition list
+ "M90": nil,
+ "CBU-87": nil,
+};
+
+var fireMsgs = {
+
+ # F14
+ " FOX3 at": nil, # radar
+ " FOX2 at": nil, # heat
+ " FOX1 at": nil, # semi-radar
+
+ # Generic
+ " Fox 1 at": nil, # semi-radar
+ " Fox 2 at": nil, # heat
+ " Fox 3 at": nil, # radar
+ " Greyhound at": nil, # cruise missile
+ " Bombs away at": nil, # bombs
+ " Bruiser at": nil, # anti-ship
+ " Rifle at": nil, # TV guided
+ " Sniper at": nil, # anti-radiation
+
+ # SAM, fleet and missile frigate
+ " Bird away at": nil, # G/A
+
+ # F15
+ " aim7 at": nil,
+ " aim9 at": nil,
+ " aim120 at": nil,
+};
+
var incoming_listener = func {
var history = getprop("/sim/multiplay/chat-history");
var hist_vector = split("\n", history);
@@ -81,6 +187,7 @@ var incoming_listener = func {
var last_vector = split(":", last);
var author = last_vector[0];
var callsign = getprop("sim/multiplay/callsign");
+ callsign = size(callsign) < 8 ? callsign : left(callsign,7);
if (size(last_vector) > 1 and author != callsign) {
# not myself
#print("not me");
@@ -89,67 +196,10 @@ var incoming_listener = func {
# 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 m2000 == TRUE) {
+ if (contains(fireMsgs, last_vector[1]) 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");
+ warn(last_vector,m2000,callsign,author);
+ } elsif (getprop("payload/armament/msg")) {
var last1 = split(" ", last_vector[1]);
if(size(last1) > 2 and last1[size(last1)-1] == "exploded" ) {
#print("missile hitting someone");
@@ -167,56 +217,113 @@ var incoming_listener = func {
if(distance != nil) {
var dist = distance;
- #check distance w/ if statement here
+ if (contains(cluster, type)) {
+ # cluster munition
+ var lbs = warhead_lbs[type];
+ var maxDist = maxDamageDistFromWarhead(lbs);
+ var distance = math.max(0,rand()*2-full_damage_dist_m);#being 0 to 2 meters from a bomblet on average.
+ var diff = maxDist-distance;
+ diff = diff * diff;
+ var probability = diff / (maxDist*maxDist);
+ if (use_hitpoints_instead_of_failure_modes_bool) {
+ var hpDist = maxDamageDistFromWarhead(hp_max);
+ probability = (maxDist/hpDist)*probability;
+ }
+ var failed = fail_systems(probability, hp_max);
+ var percent = 100 * prob;
+ printf("Took %.1f%% damage from %s clusterbomb at %0.1f meters from bomblet. %s systems was hit", percent,type,distance,failed);
+ nearby_explosion();
+ return;
+ }
+
+ distance = math.max(distance-full_damage_dist_m, 0);
- if (contains(warhead_lbs, type)) {
- #maxDist = maxDamageDistFromWarhead(warhead_lbs[type]);
+ var maxDist = 0;# distance where the explosion dont hurt us anymore
+ var lbs = 0;
+
+ if (hitable_by_ground_munitions and contains(warhead_lbs, type)) {
+ lbs = warhead_lbs[type];
+ maxDist = maxDamageDistFromWarhead(lbs);#3*sqrt(lbs)
+ } elsif (hitable_by_air_munitions and contains(warhead_air_lbs, type)) {
+ lbs = warhead_air_lbs[type];
+ maxDist = maxDamageDistFromWarhead(lbs);
} else {
return;
}
-
- if (type == "M90" and distance < 300) {
- var failed = fail_systems(warhead_lbs[type]/2);
- return;
- } elsif (distance < 150) {
- var prob = 1;
- if ( distance > 50 ) {
- distance = distance - 50;
- prob = 1 - (distance/100);
- }
+
+ var diff = maxDist-distance;
+ if (diff < 0) {
+ diff = 0;
+ }
+ diff = diff * diff;
+
+ var probability = diff / (maxDist*maxDist);
+
+ if (use_hitpoints_instead_of_failure_modes_bool) {
+ var hpDist = maxDamageDistFromWarhead(hp_max);
+ probability = (maxDist/hpDist)*probability;
}
-
- var failed = fail_systems(warhead_lbs[type] * prob);
- #ar percent = 100 * probability;
- #printf("Took %.1f%% damage from %s missile at %0.1f meters. %s systems was hit", percent,type,dist,failed);
+ var failed = fail_systems(probability, hp_max);
+ 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();
+
+ ####
+ # I don't remember all the considerations that went into our original warhead damage model.
+ # But looking at the formula it looks like they all do 100% damage at 0 meter hit,
+ # and warhead size is only used to determine the decrease of damage with distance increase.
+ # It sorta gets the job done though, so I am hesitant to advocate that warheads above a certain
+ # size should give 100% damage for some distance, and that warheads smaller than certain size should
+ # not give 100% damage even on direct hit.
+ # Anyway, for hitpoint based assets, this is now the case. Maybe we should consider to also do something
+ # similar for failure mode based aircraft. ~Nikolai
+ ####
+
+ ## example 1: ##
+ # 300 lbs warhead, 50 meters distance
+ # maxDist=52
+ # diff = 52-50 = 2
+ # diff^2 = 4
+ # prob = 4/2700 = 0.15%
+
+ ## example 2: ##
+ # 300 lbs warhead, 25 meters distance
+ # maxDist=52
+ # diff = 52-25 = 27
+ # diff^2 = 729
+ # prob = 729/2700 = 27%
}
}
- } elsif (cannon_types[last_vector[1]] != nil) {
- # cannon hitting someone
- print("cannon");
+ } elsif (hitable_by_cannon and cannon_types[last_vector[1]] != nil) {
if (size(last_vector) > 2 and last_vector[2] == " "~callsign) {
- print("cannon hit us");
- var last3 = split(" ", last_vector[3]);
- #print("last3[2]: " ~ last3[2]);
- #print("last3[1]: " ~ last3[1]);
- if(size(last3) > 2) {
- if ( last3[2] == "hits" ) {
- var hit_count = num(last3[1]);
+ if (size(last_vector) < 4) {
+ # msg is either missing number of hits, or has no trailing dots from spam filter.
+ print('"'~last~'" is not a legal hit message, tell the shooter to upgrade his OPRF plane :)');
+ return;
+ }
+ var last3 = split(" ", last_vector[3]);
+ if(size(last3) > 2 and size(last3[2]) > 2 and last3[2] == "hits" ) {
+ var probability = cannon_types[last_vector[1]];
+ var hit_count = num(last3[1]);
+ if (hit_count != nil) {
+ var damaged_sys = 0;
+ for (var i = 1; i <= hit_count; i = i + 1) {
+ var failed = fail_systems(probability);
+ damaged_sys = damaged_sys + failed;
+ }
+
+ printf("Took %.1f%% x %2d damage from cannon! %s systems was hit.", probability*100, hit_count, damaged_sys);
+ nearby_explosion();
}
} else {
- var hit_count = 4;
+ var probability = cannon_types[last_vector[1]];
+ #print("probability: " ~ probability);
+
+ var failed = fail_systems(probability * 3);# Old messages is assumed to be 3 hits
+ printf("Took %.1f%% x 3 damage from cannon! %s systems was hit.", probability*100, failed);
+ nearby_explosion();
}
- var damaged_sys = 0;
- var probability = cannon_types[last_vector[1]];
- for (var i = 1; i <= hit_count; i = i + 1) {
- var failed = fail_systems(probability);
- damaged_sys = damaged_sys + failed;
- }
- # that someone is me!
- #print("hitting me");
-
- printf("Took %.1f%% damage from cannon! %s systems was hit.", probability*hit_count*100, damaged_sys);
}
}
}
@@ -225,22 +332,132 @@ var incoming_listener = func {
}
var maxDamageDistFromWarhead = func (lbs) {
- # very simple
- var dist = 7*math.sqrt(lbs);
-
+ # Calc at what distance the warhead will do zero damage every time.
+ var dist = 3*math.sqrt(lbs);
return dist;
}
-var fail_systems = func (damage) {
- hp = hp - damage;
- print("HP: " ~ hp ~ "/" ~ hp_max);
-
- if ( hp < 0 ) {
- setprop("/carrier/sunk/",1);
- setprop("/sim/multiplay/generic/int[0]",1);
- }
+var fail_systems = func (probability, factor = 100) {#this factor needs tuning after all asset hitpoints have been evaluated.
+ if (fleet) {
+ return fail_fleet_systems(probability, factor);
+ } elsif (use_hitpoints_instead_of_failure_modes_bool) {
+ hp -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ printf("HP: %d/%d", hp, hp_max);
+ setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
+ if ( hp < 0 ) {
+ setprop("/carrier/sunk/",1);#we are dead
+ setprop("/sim/multiplay/generic/int[2]",1);#radar off
+ setprop("/sim/multiplay/generic/int[0]",1);#smoke on
+ setprop("/sim/messages/copilot", getprop("sim/multiplay/callsign")~" dead.");
+ }
+ return -1;
+ } else {
+ 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;
+ }
};
+hp_f = [hp_max,hp_max,hp_max,hp_max,hp_max,hp_max,hp_max];
+
+var fail_fleet_systems = func (probability, factor) {
+ var no = 7;
+ while (no > 6 or hp_f[no] < 0) {
+ no = int(rand()*7);
+ if (hp_f[no] < 0) {
+ if (rand() > 0.9) {
+ armament.defeatSpamFilter("You shot one of our already sinking ships, you are just mean.");
+ hp_f[no] -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ print("HP["~no~"]: " ~ hp_f[no] ~ "/" ~ hp_max);
+ return;
+ }
+ }
+ }
+ hp_f[no] -= factor * probability*(0.75+rand()*0.25);# from 75 to 100% damage
+ printf("HP[%d]: %d/%d", no, hp_f[no], hp_max);
+ #setprop("sam/damage", math.max(0,100*hp/hp_max));#used in HUD
+ if ( hp_f[no] < 0 ) {
+ setprop("/sim/multiplay/generic/bool["~(no+40)~"]",1);
+ armament.defeatSpamFilter("So you sank one of our ships, we will get you for that!");
+ if (!getprop("/carrier/disabled") and hp_f[0]<0 and hp_f[1]<0 and hp_f[2]<0) {
+ setprop("/carrier/disabled",1);
+ armament.defeatSpamFilter("Captain our offensive capability is crippled!");
+ }
+ if (hp_f[0]<0 and hp_f[1]<0 and hp_f[2]<0 and hp_f[3]<0 and hp_f[4]<0 and hp_f[5]<0 and hp_f[6]<0) {
+ setprop("/carrier/sunk",1);
+ setprop("/sim/multiplay/generic/int[2]",1);#radar off
+ setprop("/sim/messages/copilot", getprop("sim/multiplay/callsign")~" dead.");
+ armament.defeatSpamFilter("S.O.S. Heeelp");
+ } else {
+ armament.defeatSpamFilter("This is not over yet..");
+ }
+ }
+ return -1;
+};
+
+var warn = func (last_vector,m2000,callsign,author) {
+ 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;
+ }
+ }
+ }
+ }
+}
+
var playIncomingSound = func (clock) {
setprop("sound/incoming"~clock, 1);
settimer(func {stopIncomingSound(clock);},3);
@@ -250,6 +467,20 @@ 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];
@@ -265,20 +496,25 @@ var processCallsigns = func () {
callsign_struct[callsign] = player;
}
}
- settimer(processCallsigns, 1.5);
+ settimer(processCallsigns, 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");
+setlistener("/sim/multiplay/chat-history", incoming_listener, 0, 0);
- setprop("logging/date-log", date);
- setprop("logging/time-log", time);
+# prevent flooding the pilots screen with failure modes that fail when getting hit.
+setprop("/sim/failure-manager/display-on-screen", FALSE);
+
+var re_init = func {
+ # repair the aircraft at relocation to another airport.
+
+ 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/multiplay/chat-history", incoming_listener, 0, 0);
\ No newline at end of file
+setlistener("/sim/signals/reinit", re_init, 0, 0);
diff --git a/missile-frigate/Nasal/fdm.nas b/missile-frigate/Nasal/fdm.nas
index b66e145..ea98b4f 100644
--- a/missile-frigate/Nasal/fdm.nas
+++ b/missile-frigate/Nasal/fdm.nas
@@ -30,11 +30,14 @@ sink_rate = .025;
pitch_rate = .007;
roll_rate = .007;
+var last_speed = 4;
+
setprop("/carrier/pitch-deg",0);
setprop("/carrier/pitch-offset",0);
setprop("/carrier/roll-deg",0);
setprop("/carrier/roll-offset",0);
setprop("/carrier/sunk",0);
+setprop("/carrier/aground",0);
var PositionUpdater = func () {
@@ -48,34 +51,67 @@ var PositionUpdater = func () {
time_last = time_now;
+ var heading = getprop("/orientation/heading-deg");
+ var speed = getprop("/velocities/groundspeed-kt");
var rudder = getprop("/surface-positions/rudder-pos-norm");
-
- if ( getprop("/carrier/sunk") == 0 and getprop("/autopilot/route-manager/active") == 1 ) {
+ var aground_pos = geo.Coord.new().set_latlon(position.lat(),position.lon());
+ aground_pos.apply_course_distance(heading,25);
+ var aground = geodinfo(aground_pos.lat(), aground_pos.lon())[1].solid;
+ if ( aground == 0 ) {
+ aground_pos.apply_course_distance(heading,-50);
+ aground = geodinfo(aground_pos.lat(), aground_pos.lon())[1].solid;
+ }
+ if ( aground == 1 ) {
+ setprop("/carrier/aground",1);
+ setprop("/carrier/sunk",1);
+ }
- #for event
- var speed = 15;
- var cur_waypoint = getprop("/autopilot/route-manager/current-wp");
- var cur_wp_lon = getprop("/autopilot/route-manager/route/wp[" ~ cur_waypoint ~ "]/longitude-deg");
- var cur_wp_lat = getprop("/autopilot/route-manager/route/wp[" ~ cur_waypoint ~ "]/latitude-deg");
- var rm_destination = geo.Coord.new().set_latlon(cur_wp_lat,cur_wp_lon);
-
-
- var heading = position.course_to(rm_destination);
-
+ if ( aground == 1 ) {
+ speed = 0;
+ }
+ #print(speed);
var distance = speed * globals.KT2MPS * dt;
position.apply_course_distance(heading, distance);
+ # check if we've ran aground
+
# Set new position
setprop("/position/latitude-deg", position.lat());
setprop("/position/longitude-deg", position.lon());
- var g_alt = getprop("/position/ground-elev-ft");
- setprop("/position/altitude-ft",g_alt);
-
- # Update heading
- var course = heading + rudder * heading_ps * dt;
- setprop("/orientation/heading-deg", course);
+ if ( getprop("/carrier/sunk") == 0 ) {
+
+ # Update heading
+ var course = heading + rudder * heading_ps * dt;
+ setprop("/orientation/heading-deg", course);
+ setprop("/position/altitude-ft",getprop("/position/ground-elev-ft"));
+
+# } elsif ( getprop("/carrier/sunk") == 0 and getprop("/autopilot/route-manager/active") == 1 ) {
+#
+# #for event
+# var speed = 15;
+# var cur_waypoint = getprop("/autopilot/route-manager/current-wp");
+# var cur_wp_lon = getprop("/autopilot/route-manager/route/wp[" ~ cur_waypoint ~ "]/longitude-deg");
+# var cur_wp_lat = getprop("/autopilot/route-manager/route/wp[" ~ cur_waypoint ~ "]/latitude-deg");
+# var rm_destination = geo.Coord.new().set_latlon(cur_wp_lat,cur_wp_lon);
+#
+#
+# var heading = position.course_to(rm_destination);
+#
+# var distance = speed * globals.KT2MPS * dt;
+# position.apply_course_distance(heading, distance);
+#
+# # Set new position
+# setprop("/position/latitude-deg", position.lat());
+# setprop("/position/longitude-deg", position.lon());
+# var g_alt = getprop("/position/ground-elev-ft");
+# setprop("/position/altitude-ft",g_alt);
+#
+# # Update heading
+# var course = heading + rudder * heading_ps * dt;
+# setprop("/orientation/heading-deg", course);
+#
} elsif ( getprop("/carrier/sunk") == 1 ) {
setprop("/carrier/fbw/target/groundspeed-kt",0);
setprop("/controls/engines/engine/throttle",0);
@@ -85,9 +121,11 @@ var PositionUpdater = func () {
setprop("/position/longitude-deg", position.lon());
#calculate sinking.
- setprop("/position/altitude-ft",getprop("/position/altitude-ft") - ( sink_rate ));
- setprop("/carrier/pitch-offset",getprop("/carrier/pitch-offset") + ( pitch_rate ));
- setprop("/carrier/roll-offset",getprop("/carrier/roll-offset") + ( roll_rate ));
+ if ( getprop("carrier/aground") != 1 ) {
+ setprop("/position/altitude-ft",getprop("/position/altitude-ft") - ( sink_rate ));
+ setprop("/carrier/pitch-offset",getprop("/carrier/pitch-offset") + ( pitch_rate ));
+ setprop("/carrier/roll-offset",getprop("/carrier/roll-offset") + ( roll_rate ));
+ }
}
#set pitch
diff --git a/missile-frigate/Sim/views.xml b/missile-frigate/Sim/views.xml
index 42ecc06..a0b2ce8 100644
--- a/missile-frigate/Sim/views.xml
+++ b/missile-frigate/Sim/views.xml
@@ -121,50 +121,6 @@
-
- Landing Signal Officer View
- lookfrom
- false
-
- true
- 0
-
- 180
- -19.7208
- 21.925
- 100.307
- 2.5
- 60
- 0.1f
-
-
-
-
- Approach View
- lookfrom
- false
-
-
- /position/latitude-deg
- /position/longitude-deg
- /position/altitude-ft
- /orientation/heading-runway-deg
- /orientation/pitch-deg
- /orientation/roll-deg
-
- -15.4979
- 21.9
- -8.315
-
- 180
- 3
- 25
- 0.1f
-
-
-
Flight Deck Aft View
lookfrom
@@ -259,22 +215,4 @@
-
- Bridge View
- lookfrom
- true
-
- true
- 0
-
- 29.2083
- 33.235233
- 19.45
-
- -2
- 45
- 0.1f
-
-
-
diff --git a/missile-frigate/Systems/fbw.xml b/missile-frigate/Systems/fbw.xml
index 42678fb..7fde0fe 100644
--- a/missile-frigate/Systems/fbw.xml
+++ b/missile-frigate/Systems/fbw.xml
@@ -31,24 +31,4 @@
-
- Flight Deck Antennas Position
- noise-spike
-
-
- /carrier/antennas/enabled
-
- 0.0
-
-
- 1.0
-
-
-
-
- 0.2
-
-
diff --git a/missile-frigate/missile-frigate-set.xml b/missile-frigate/missile-frigate-set.xml
index 03ac6ef..579f1af 100644
--- a/missile-frigate/missile-frigate-set.xml
+++ b/missile-frigate/missile-frigate-set.xml
@@ -55,6 +55,7 @@
true
+ manual
@@ -75,10 +76,6 @@
true
-
- Sounds/sound.xml
-
-
true
@@ -113,6 +110,9 @@
Systems/fdm.xml
+
+ Aircraft/missile-frigate/autopilot.xml
+
Systems/views.xml
@@ -120,7 +120,8 @@
- 0
+
+ 0
@@ -137,9 +138,34 @@
+ -
+ Targets
+ enemies
+
+ dialog-show
+ enemies
+
+
+
+
+
+ enemies/e1
+ enemies/e2
+ enemies/e3
+ enemies/e4
+ enemies/e5
+ enemies/e6
+ enemies/e7
+ enemies/e8
+ enemies/e9
+ enemies/e10
+ enemies/e11
+ enemies/e12
+
+
@@ -229,41 +255,51 @@
Aircraft/missile-frigate/Models/Armament/Weapons/
+ true
+ true
+ rotors/main/blade[0]/flap-deg
+ rotors/main/blade[1]/flap-deg
+ rotors/main/blade[2]/flap-deg
+ true
+ 1
+ controls/armament
+ station
true
true
- false
- 0.0
0.00
- 0.15
- 0.1
+ 0.15
+ 0.1
radar
- APN
+ APN
true
85
360
- 360
+ 220
22
- 100000
- 80000
+ 90000
+ 77000
0.25
- 12.0
+ 8.0
3920
315
- 2800
- 0.15
- 2.11349
+ 2800
+ 0.20
+ 2.11349
2
0.25
160
+ true
3000
75000
0.85
- 200
+ 200
true
7.5
false
90
+ 0.95
+ 3
A
Bird away
@@ -271,6 +307,7 @@
false
0.0
+ false
0.00
radar
true
@@ -344,6 +381,21 @@
+
+
+ Leto
+ swamp
+ pinto
+ fb237
+ Wilco-1
+ Kokos
+ J-Mav16
+ S
+ Raider1
+ Slobb
+ 5H1N0B1
+ SNOWY1
+
@@ -352,6 +404,18 @@
Aircraft/missile-frigate/Nasal/damage.nas
+
+ Aircraft/missile-frigate/Nasal/radar-logic.nas
+
+
+ Aircraft/missile-frigate/Nasal/vector.nas
+
+
+ Aircraft/missile-frigate/Nasal/guided-missiles.nas
+
+
+ Aircraft/missile-frigate/Nasal/fire-control.nas
+