mirror of
https://github.com/l0k1/oprf_assets.git
synced 2024-11-21 15:08:03 +08:00
Add GCI radar
This commit is contained in:
parent
bbba81a080
commit
75a3133d83
2173
gci-radar/Models/gci-tower.ac
Normal file
2173
gci-radar/Models/gci-tower.ac
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyList>
|
<PropertyList>
|
||||||
|
|
||||||
<path>towerSnowy1.ac</path>
|
<path>gci-tower.ac</path>
|
||||||
|
|
||||||
<model>
|
<model>
|
||||||
<path>Aircraft/tower/Models/smoke.xml</path>
|
<path>Aircraft/tower/Models/smoke.xml</path>
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
285
gci-radar/Nasal/damage.nas
Normal file
285
gci-radar/Nasal/damage.nas
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
|
||||||
|
|
||||||
|
var TRUE = 1;
|
||||||
|
var FALSE = 0;
|
||||||
|
|
||||||
|
var hp = 80;
|
||||||
|
var hp_max = hp;
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var warhead_lbs = {
|
||||||
|
"AGM-65": 126.00,
|
||||||
|
"AGM-84": 488.00,
|
||||||
|
"AGM-88": 146.00,
|
||||||
|
"AGM65": 200.00,
|
||||||
|
"ALARM": 450.00,
|
||||||
|
"AM39-Exocet": 364.00,
|
||||||
|
"AS-37-Martel": 330.00,
|
||||||
|
"AS30L": 529.00,
|
||||||
|
"Exocet": 364.00,
|
||||||
|
"FAB-100": 92.59,
|
||||||
|
"FAB-250": 202.85,
|
||||||
|
"FAB-500": 564.38,
|
||||||
|
"GBU-12": 190.00,
|
||||||
|
"GBU-24": 945.00,
|
||||||
|
"GBU-31": 945.00,
|
||||||
|
"GBU12": 190.00,
|
||||||
|
"GBU16": 450.00,
|
||||||
|
"HVAR": 7.50,#P51
|
||||||
|
"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,
|
||||||
|
"MK-82": 192.00,
|
||||||
|
"MK-83": 445.00,
|
||||||
|
"MK-84": 945.00,
|
||||||
|
"OFAB-100": 92.59,
|
||||||
|
"RB-04E": 661.00,
|
||||||
|
"RB-05A": 353.00,
|
||||||
|
"RB-15F": 440.92,
|
||||||
|
"RB-75": 126.00,
|
||||||
|
"RN-14T": 800.00, #fictional, thermobaeric replacement for the RN-24 nuclear bomb
|
||||||
|
"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,
|
||||||
|
"SCALP": 992.00,
|
||||||
|
"Sea Eagle": 505.00,
|
||||||
|
"SeaEagle": 505.00,
|
||||||
|
"STORMSHADOW": 850.00,
|
||||||
|
"ZB-250": 236.99,
|
||||||
|
"ZB-500": 473.99,
|
||||||
|
};
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
#check distance w/ if statement here
|
||||||
|
|
||||||
|
if (contains(warhead_lbs, type)) {
|
||||||
|
#maxDist = maxDamageDistFromWarhead(warhead_lbs[type]);
|
||||||
|
} 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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elsif (cannon_types[last_vector[1]] != nil) {
|
||||||
|
# cannon hitting someone
|
||||||
|
print("cannon");
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var hit_count = 4;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxDamageDistFromWarhead = func (lbs) {
|
||||||
|
# very simple
|
||||||
|
var dist = 7*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 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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setlistener("/sim/multiplay/chat-history", incoming_listener, 0, 0);
|
498
gci-radar/Nasal/gci.nas
Normal file
498
gci-radar/Nasal/gci.nas
Normal file
@ -0,0 +1,498 @@
|
|||||||
|
# (c) 2018 pinto
|
||||||
|
# license: gplv2+
|
||||||
|
|
||||||
|
# v0.1 - just a very basic proof of concept at this point.
|
||||||
|
# will only report the closest bad guy, does no threat assessment.
|
||||||
|
# todo:
|
||||||
|
# test
|
||||||
|
# toggle radar on/off
|
||||||
|
# all the other requests that a gci can do (only handles BRAA right now)
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
### Variables
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
# prop_watch is a mp[x] boolean property set by that aircraft designer. the plane sets this to 1 when it wants to receive BRAA
|
||||||
|
# if the plane is not on the enemy list, and is one of the first ~10 to
|
||||||
|
# request a BRAA, then it will receive it.
|
||||||
|
var damage_prop = props.globals.getNode("/carrier/sunk");
|
||||||
|
var prop_watch = {
|
||||||
|
"MiG-21bis": [0,1,2],
|
||||||
|
"MiG-21MF-75": [0,1,2],
|
||||||
|
"QF-4E": [0,1,2]
|
||||||
|
};
|
||||||
|
|
||||||
|
var radar_stations = [
|
||||||
|
"gci",
|
||||||
|
"frigate",
|
||||||
|
];
|
||||||
|
|
||||||
|
var update_rate = 10; #how often the message should update in seconds
|
||||||
|
var hostile_radius = 300000; #max distance to check against, in meters
|
||||||
|
|
||||||
|
var true = 1;
|
||||||
|
var false = 0;
|
||||||
|
|
||||||
|
# request types
|
||||||
|
var NONE = 0;
|
||||||
|
var PICTURE = 1;
|
||||||
|
var BOGEYDOPE = 2;
|
||||||
|
var CUTOFF = 3;
|
||||||
|
|
||||||
|
var PENDING = 0;
|
||||||
|
var SENDING = 1;
|
||||||
|
var SENT = 2;
|
||||||
|
|
||||||
|
var output_prop = 0;
|
||||||
|
var radar_tx_output_prop = 11;
|
||||||
|
var enemy_node = props.globals.getNode("/enemies");
|
||||||
|
var player_node = props.globals.getNode("/ai/models");
|
||||||
|
var opfor_switch = props.globals.getNode("/enemies/opfor-switch"); # targets all non-opfor
|
||||||
|
var friend_switch = props.globals.getNode("/enemies/friend-switch"); # targets all opfor
|
||||||
|
##########################################
|
||||||
|
### Objects
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
var gci_contact = {
|
||||||
|
new: func(c, class) {
|
||||||
|
var m = {parents:[gci_contact]};
|
||||||
|
m.time_from_last_message = 0;
|
||||||
|
m.node = c;
|
||||||
|
m.model = remove_suffix(remove_suffix(split(".", split("/", c.getNode("sim/model/path").getValue())[-1])[0], "-model"), "-anim");
|
||||||
|
m.valid = c.getNode("valid");
|
||||||
|
m.callsign = c.getNode("callsign").getValue();
|
||||||
|
if ( contains(prop_watch, m.model) ) {
|
||||||
|
m.picture_node = c.getNode("sim/multiplay/generic/bool["~prop_watch[m.model][0]~"]");
|
||||||
|
m.bogeydope_node = c.getNode("sim/multiplay/generic/bool["~prop_watch[m.model][1]~"]");
|
||||||
|
m.cutoff_node = c.getNode("sim/multiplay/generic/bool["~prop_watch[m.model][2]~"]");
|
||||||
|
} else {
|
||||||
|
m.picture_node = -1;
|
||||||
|
m.bogeydope_node = -1;
|
||||||
|
m.cutoff_node = -1;
|
||||||
|
}
|
||||||
|
m.is_radar_station = find_match(m.model,radar_stations);
|
||||||
|
m.contact = radar_logic.Contact.new(c,class);
|
||||||
|
m.foe = false;
|
||||||
|
m.match = false;
|
||||||
|
m.request = NONE;
|
||||||
|
m.last_request = NONE;
|
||||||
|
m.request_status = PENDING;
|
||||||
|
m.msg_queue = [];
|
||||||
|
if (m.is_radar_station) {
|
||||||
|
m.radar_station_process_send();
|
||||||
|
} else {
|
||||||
|
m.process_send();
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
},
|
||||||
|
getValid: func() {
|
||||||
|
if (me.valid.getNode() == 0 and me.callsign != me.node.getNode("callsign").getValue()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
check_foe: func() {
|
||||||
|
me.foe = false;
|
||||||
|
if (opfor_switch.getValue() == true ) {
|
||||||
|
if (left(string.lc(me.callsign),5) != "opfor") {
|
||||||
|
me.foe = true;
|
||||||
|
}
|
||||||
|
} elsif (friend_switch.getValue() == true) {
|
||||||
|
if (left(string.lc(me.callsign),5) == "opfor") {
|
||||||
|
me.foe = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach (var cs; enemy_node.getChildren()) {
|
||||||
|
if (me.callsign == cs.getValue()) {
|
||||||
|
me.foe = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return me.foe;
|
||||||
|
},
|
||||||
|
update_request: func() {
|
||||||
|
if (me.picture_node == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#print("updating info");
|
||||||
|
if (me.picture_node.getValue() == true) {
|
||||||
|
me.request = PICTURE;
|
||||||
|
} elsif (me.bogeydope_node.getValue() == true) {
|
||||||
|
me.request = BOGEYDOPE;
|
||||||
|
} elsif (me.cutoff_node.getValue() == true) {
|
||||||
|
me.request = CUTOFF;
|
||||||
|
} else {
|
||||||
|
me.request = NONE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
check_node: func() {
|
||||||
|
#print('checking node');
|
||||||
|
if (me.picture_node == -1){
|
||||||
|
#print('watch node is -1');
|
||||||
|
return false;
|
||||||
|
} elsif (me.check_foe() == true) {
|
||||||
|
#print('check_foe is true');
|
||||||
|
return false;
|
||||||
|
} elsif (me.request == NONE) {
|
||||||
|
#print('node is false');
|
||||||
|
return false;
|
||||||
|
} elsif (systime() - me.time_from_last_message < update_rate) {
|
||||||
|
#print("update failed");
|
||||||
|
return false;
|
||||||
|
} elsif (me.request_status == SENT) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
me.time_from_last_message = systime();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
process_send: func() {
|
||||||
|
# messages are first in, first out order
|
||||||
|
# updates every 1.5 seconds
|
||||||
|
#print('in process_send()');
|
||||||
|
if (damage_prop.getValue() == 0) {
|
||||||
|
|
||||||
|
me.update_request();
|
||||||
|
|
||||||
|
#print('rqst: ' ~ me.request);
|
||||||
|
#print('last: ' ~ me.last_request);
|
||||||
|
#print('stat: ' ~ me.request_status);
|
||||||
|
#print('queue size: ' ~ size(me.msg_queue));
|
||||||
|
|
||||||
|
if (me.request == NONE) {
|
||||||
|
#print('setting request to none');
|
||||||
|
me.request_status = PENDING;
|
||||||
|
} elsif (me.request != NONE and me.request_status == PENDING and me.request_status != SENT and size(me.msg_queue) > 0) {
|
||||||
|
#print('setting status to sending');
|
||||||
|
me.request_status = SENDING;
|
||||||
|
} elsif (me.request_status == SENDING and size(me.msg_queue) == 0) {
|
||||||
|
#print('setting status to sent');
|
||||||
|
me.request_status = SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me.request == NONE or me.request_status == SENT) {
|
||||||
|
#print('emptying queue');
|
||||||
|
me.msg_queue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me.request != me.last_request) {
|
||||||
|
#print('setting status to pending and emptying queue');
|
||||||
|
me.request_status = PENDING;
|
||||||
|
me.msg_queue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
me.last_request = me.request;
|
||||||
|
|
||||||
|
if (size(me.msg_queue) > 0 and me.request_status == SENDING) {
|
||||||
|
#print("msg_queue: " ~ debug.dump(me.msg_queue));
|
||||||
|
setprop("/sim/multiplay/generic/string["~output_prop~"]",me.msg_queue[0]);
|
||||||
|
output_prop = output_prop > 9 ? 0 : output_prop + 1;
|
||||||
|
me.msg_queue = purge_from_vector(me.msg_queue,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settimer(func(){me.process_send();},1.3);
|
||||||
|
},
|
||||||
|
radar_station_process_send: func() {
|
||||||
|
# messages are first in, first out order
|
||||||
|
# updates every 1.5 seconds
|
||||||
|
#print('in process_send()');
|
||||||
|
|
||||||
|
if (size(me.msg_queue) > 0 and damage_prop.getValue() == 0) {
|
||||||
|
#print("msg_queue: " ~ debug.dump(me.msg_queue));
|
||||||
|
setprop("/sim/multiplay/generic/string["~radar_tx_output_prop~"]",me.msg_queue[0]);
|
||||||
|
radar_tx_output_prop = radar_tx_output_prop >= 16 ? 11 : radar_tx_output_prop + 1;
|
||||||
|
me.msg_queue = purge_from_vector(me.msg_queue,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
settimer(func(){me.radar_station_process_send();},1.3);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
### Functions
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
# gather up all contacts, so we can iterate over them
|
||||||
|
|
||||||
|
var cx_master_list = [];
|
||||||
|
|
||||||
|
var gather_contacts = func() {
|
||||||
|
# first we need to clean the contact list
|
||||||
|
for (var i = 0; i < size(cx_master_list); i = i + 1) {
|
||||||
|
if (cx_master_list[i] == nil) { break; }
|
||||||
|
if (!cx_master_list[i].getValid()) {
|
||||||
|
cx_master_list = purge_from_vector(cx_master_list, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var matching = false;
|
||||||
|
foreach(var mp; player_node.getChildren("multiplayer")) {
|
||||||
|
if (mp.getNode("valid").getValue() == 1) {
|
||||||
|
matching = false;
|
||||||
|
foreach(var cx; cx_master_list) {
|
||||||
|
if ( mp.getPath() == cx.contact.getNode().getPath() ) {
|
||||||
|
matching = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matching == false) {
|
||||||
|
cx = gci_contact.new(mp,0);
|
||||||
|
print("adding contact: " ~ cx.contact.get_Callsign());
|
||||||
|
append(cx_master_list,cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var check_requests = func(){
|
||||||
|
foreach (var cx; cx_master_list) {
|
||||||
|
if (cx.check_foe() == true or cx.check_node() == false) { continue; }
|
||||||
|
if (size(cx.msg_queue) > 0) { continue; } # msg queue should be reset or emptied when request changes.
|
||||||
|
if (cx.request == NONE) {
|
||||||
|
#print('reqest is none in check_requests');
|
||||||
|
continue;
|
||||||
|
} elsif (cx.request == PICTURE) {
|
||||||
|
var blue_coords = [];
|
||||||
|
var opfor_coords = [];
|
||||||
|
var match = false;
|
||||||
|
append(blue_coords, cx.contact.get_Coord());
|
||||||
|
foreach (var check; cx_master_list) {
|
||||||
|
if (!check_visible(check)) { continue; }
|
||||||
|
match = false;
|
||||||
|
if (check.check_foe()) {
|
||||||
|
foreach (var coord; opfor_coords) {
|
||||||
|
if (coord.distance_to(check.contact.get_Coord()) < 3 * NM2M) {
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match) { append(opfor_coords,check.contact.get_Coord()); }
|
||||||
|
} else {
|
||||||
|
foreach (var coord; blue_coords) {
|
||||||
|
if (coord.distance_to(check.contact.get_Coord()) < 3 * NM2M) {
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match) { append(blue_coords,check.contact.get_Coord()); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
#send message
|
||||||
|
var bearing = math.round(cx.contact.get_Coord().course_to(check.contact.get_Coord()),1);
|
||||||
|
var range = math.round(check.contact.get_Coord().distance_to(cx.contact.get_Coord()));
|
||||||
|
var altitude = math.round(check.contact.get_altitude(),1);
|
||||||
|
# requestor-callsign:unique-message-id:2:bearing:range:altitude:[BLUFOR=0|OPFOR=1]
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":2:" ~ bearing ~ ":" ~ range ~ ":" ~ altitude ~ ":" ~ check.check_foe());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size(cx.msg_queue) == 0) {
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":1:n:n:n:n");
|
||||||
|
} else {
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":0:d:d:d:d");
|
||||||
|
}
|
||||||
|
|
||||||
|
} elsif (cx.request == BOGEYDOPE) {
|
||||||
|
min_dist = hostile_radius;
|
||||||
|
closest = nil;
|
||||||
|
#print('checking bogey dope');
|
||||||
|
foreach (var check; cx_master_list) {
|
||||||
|
if (!check.check_foe()) { continue; }
|
||||||
|
var dist = cx.contact.get_Coord().distance_to(check.contact.get_Coord());
|
||||||
|
if ( dist > min_dist) { continue; }
|
||||||
|
if (!check_visible(check)) { continue; }
|
||||||
|
min_dist = dist;
|
||||||
|
closest = check;
|
||||||
|
}
|
||||||
|
if (closest != nil) {
|
||||||
|
var bearing = math.round(cx.contact.get_Coord().course_to(closest.contact.get_Coord()),1);
|
||||||
|
var range = math.round(closest.contact.get_Coord().distance_to(cx.contact.get_Coord()));
|
||||||
|
var altitude = math.round(closest.contact.get_altitude(),1);
|
||||||
|
var aspect = math.round(math.periodic(-180,180,closest.contact.get_heading() - closest.contact.get_Coord().course_to(cx.contact.get_Coord())));
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":3:" ~ bearing ~ ":" ~ range ~ ":" ~ altitude ~ ":" ~ aspect);
|
||||||
|
} else {
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":1:n:n:n:n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} elsif (cx.request == CUTOFF) {
|
||||||
|
min_dist = hostile_radius;
|
||||||
|
closest = nil;
|
||||||
|
foreach (var check; cx_master_list) {
|
||||||
|
if (!check.check_foe()) { continue; }
|
||||||
|
var dist = cx.contact.get_Coord().distance_to(check.contact.get_Coord());
|
||||||
|
if ( dist > min_dist) { continue; }
|
||||||
|
if (!check_visible(check)) { continue; }
|
||||||
|
min_dist = dist;
|
||||||
|
closest = check;
|
||||||
|
}
|
||||||
|
if (closest != nil) {
|
||||||
|
var bogey_speed = closest.contact.speed.getValue();
|
||||||
|
var cx_speed = cx.contact.speed.getValue();
|
||||||
|
var bogey_heading = closest.contact.heading.getValue();
|
||||||
|
var bearing = cx.contact.get_Coord().course_to(closest.contact.get_Coord());
|
||||||
|
var range = closest.contact.get_Coord().distance_to(cx.contact.get_Coord());
|
||||||
|
var altitude = math.round(closest.contact.get_altitude(),1);
|
||||||
|
var aspect = math.round(math.periodic(-180,180,closest.contact.get_heading() - closest.contact.get_Coord().course_to(cx.contact.get_Coord())));
|
||||||
|
# get_intercept(bearing, dist_m, runnerHeading, runnerSpeed, chaserSpeed)
|
||||||
|
var info = get_intercept(bearing, range, bogey_heading, bogey_speed * KT2MPS, cx_speed * KT2MPS);
|
||||||
|
if (info == nil) {
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":1:n:n:n:n");
|
||||||
|
} else {
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":4:" ~ int(info[1]) ~ ":" ~ int(info[0]) ~ ":" ~ altitude ~ ":" ~ aspect);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
append(cx.msg_queue, cx.callsign ~ ":" ~ get_random() ~ ":1:n:n:n:n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cx_data_transmit = func(){
|
||||||
|
#print('transmitting');
|
||||||
|
foreach (var cx; cx_master_list) {
|
||||||
|
if (!cx.is_radar_station) { continue; }
|
||||||
|
if (size(cx.msg_queue) > 0) { continue; }
|
||||||
|
if (cx.check_foe()) { continue; }
|
||||||
|
foreach (var tx; cx_master_list) {
|
||||||
|
if (tx != cx) {
|
||||||
|
append(cx.msg_queue,cx.callsign ~ ":" ~ get_random() ~ ":" ~ tx.callsign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var data_receive_callsigns = [];
|
||||||
|
var cx_data_receive = func() {
|
||||||
|
# clean out old data (15 seconds)
|
||||||
|
var time = systime();
|
||||||
|
var new_vec = [];
|
||||||
|
foreach (var rx; data_receive_callsigns){
|
||||||
|
if (time - rx[1] < 15) {
|
||||||
|
append(new_vec,rx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data_receive_callsigns = new_vec;
|
||||||
|
foreach (var cx; cx_master_list) {
|
||||||
|
for (var i = 11; i <= 15; i = i + 1) {
|
||||||
|
var msg = getprop(cx.node.getPath() ~ "/sim/multiplay/generic/string["~i~"]");
|
||||||
|
if (msg == "") { continue; }
|
||||||
|
if (msg == nil) { continue; }
|
||||||
|
msg = split(":",msg);
|
||||||
|
if (msg[0] != getprop("/sim/multiplay/callsign")) { continue; };
|
||||||
|
if (find_match(msg[2], data_receive_callsigns)) { continue; }
|
||||||
|
#print("adding cs to received list");
|
||||||
|
append(data_receive_callsigns,[msg[2],systime()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var check_visible = func(check) {
|
||||||
|
foreach(var rx; data_receive_callsigns) {
|
||||||
|
if (rx[0] == check.callsign) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (radar_logic.isNotBehindTerrain(check.node) == false){ return false; }
|
||||||
|
|
||||||
|
var target_heading = check.contact.heading.getValue();
|
||||||
|
var relative_bearing = math.abs(geo.normdeg180(check.contact.get_Coord().course_to(geo.aircraft_position()) - target_heading));
|
||||||
|
var target_radial_airspeed = (-1 * ( ( relative_bearing / 90 ) - 1 ) ) * check.node.getNode("velocities/true-airspeed-kt").getValue();
|
||||||
|
if ( math.abs(target_radial_airspeed) < 20 ) { return false; } # i.e. notching, landed aircraft
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var iter = 0;
|
||||||
|
var main_loop = func() {
|
||||||
|
#print("looping");
|
||||||
|
if (getprop("/carrier/sunk/") == 0) {
|
||||||
|
if (iter == 0) {
|
||||||
|
gather_contacts();
|
||||||
|
cx_data_transmit();
|
||||||
|
}
|
||||||
|
cx_data_receive();
|
||||||
|
check_requests();
|
||||||
|
}
|
||||||
|
iter = iter >= 7 ? 0 : iter + 1;
|
||||||
|
settimer(func(){main_loop();},1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var get_intercept = func(bearing, dist_m, runnerHeading, runnerSpeed, chaserSpeed) {
|
||||||
|
# from Leto
|
||||||
|
# needs: bearing, dist_m, runnerHeading, runnerSpeed, chaserSpeed
|
||||||
|
# dist_m > 0 and chaserSpeed > 0
|
||||||
|
|
||||||
|
#var bearing = 184;var dist_m=31000;var runnerHeading=186;var runnerSpeed= 200;var chaserSpeed=250;
|
||||||
|
|
||||||
|
var trigAngle = 90-bearing;
|
||||||
|
var RunnerPosition = [dist_m*math.cos(trigAngle*D2R), dist_m*math.sin(trigAngle*D2R),0];
|
||||||
|
var ChaserPosition = [0,0,0];
|
||||||
|
|
||||||
|
var VectorFromRunner = vector.Math.minus(ChaserPosition, RunnerPosition);
|
||||||
|
var runner_heading = 90-runnerHeading;
|
||||||
|
var RunnerVelocity = [runnerSpeed*math.cos(runner_heading*D2R), runnerSpeed*math.sin(runner_heading*D2R),0];
|
||||||
|
|
||||||
|
var a = chaserSpeed * chaserSpeed - runnerSpeed * runnerSpeed;
|
||||||
|
var b = 2 * vector.Math.dotProduct(VectorFromRunner, RunnerVelocity);
|
||||||
|
var c = -dist_m * dist_m;
|
||||||
|
|
||||||
|
if ((b*b-4*a*c)<0) {
|
||||||
|
# intercept not possible
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
var t1 = (-b+math.sqrt(b*b-4*a*c))/(2*a);
|
||||||
|
var t2 = (-b-math.sqrt(b*b-4*a*c))/(2*a);
|
||||||
|
|
||||||
|
var timeToIntercept = 0;
|
||||||
|
if (t1 > 0 and t2 > 0) {
|
||||||
|
timeToIntercept = math.min(t1, t2);
|
||||||
|
} else {
|
||||||
|
timeToIntercept = math.max(t1, t2);
|
||||||
|
}
|
||||||
|
var InterceptPosition = vector.Math.plus(RunnerPosition, vector.Math.product(timeToIntercept, RunnerVelocity));
|
||||||
|
|
||||||
|
var ChaserVelocity = vector.Math.product(1/timeToIntercept, vector.Math.minus(InterceptPosition, ChaserPosition));
|
||||||
|
|
||||||
|
var interceptAngle = vector.Math.angleBetweenVectors([0,1,0], ChaserVelocity);
|
||||||
|
var interceptHeading = geo.normdeg(ChaserVelocity[0]<0?-interceptAngle:interceptAngle);
|
||||||
|
#print("output:");
|
||||||
|
#print("time: " ~ timeToIntercept);
|
||||||
|
#print("heading: " ~ interceptHeading);
|
||||||
|
return [timeToIntercept, interceptHeading];
|
||||||
|
}
|
||||||
|
|
||||||
|
var purge_from_vector = func(vec, idx = nil, val = nil) {
|
||||||
|
if (idx == nil and val == nil) { return vec; }
|
||||||
|
var new_vec = [];
|
||||||
|
for (var i = 0; i < size(vec); i = i + 1) {
|
||||||
|
if ((idx != nil and i == idx) or (val != nil and val == vec[i])) { continue; }
|
||||||
|
append(new_vec, vec[i]);
|
||||||
|
}
|
||||||
|
return new_vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
var get_random = func() {
|
||||||
|
return int(rand() * 9999)
|
||||||
|
}
|
||||||
|
|
||||||
|
var find_match = func(val,vec) {
|
||||||
|
if (size(vec) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
foreach (var a; vec) {
|
||||||
|
#print(a);
|
||||||
|
if (a == val) { return 1; }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remove_suffix = func(s, x) {
|
||||||
|
var len = size(x);
|
||||||
|
if (substr(s, -len) == x)
|
||||||
|
return substr(s, 0, size(s) - len);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
main_loop();
|
450
gci-radar/Nasal/radar-logic.nas
Normal file
450
gci-radar/Nasal/radar-logic.nas
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
|
||||||
|
var encode3bits = func(first, second, third) {
|
||||||
|
var integer = first;
|
||||||
|
integer = integer + 2 * second;
|
||||||
|
integer = integer + 4 * third;
|
||||||
|
return integer;
|
||||||
|
}
|
||||||
|
var versionString = getprop("sim/version/flightgear");
|
||||||
|
var version = split(".", versionString);
|
||||||
|
var major = num(version[0]);
|
||||||
|
var minor = num(version[1]);
|
||||||
|
var pica = num(version[2]);
|
||||||
|
var pickingMethod = 0;
|
||||||
|
if ((major == 2017 and minor == 2 and pica >= 1) or (major == 2017 and minor > 2) or major > 2017) {
|
||||||
|
pickingMethod = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var FALSE = 0;
|
||||||
|
var TRUE = 1;
|
||||||
|
|
||||||
|
var AIR = 0;
|
||||||
|
var MARINE = 1;
|
||||||
|
var SURFACE = 2;
|
||||||
|
var ORDNANCE = 3;
|
||||||
|
|
||||||
|
var Contact = {
|
||||||
|
# For now only used in guided missiles, to make it compatible with Mirage 2000-5.
|
||||||
|
new: func(c, class) {
|
||||||
|
var obj = { parents : [Contact]};
|
||||||
|
#debug.benchmark("radar process1", func {
|
||||||
|
obj.rdrProp = c.getNode("radar");
|
||||||
|
obj.oriProp = c.getNode("orientation");
|
||||||
|
obj.velProp = c.getNode("velocities");
|
||||||
|
obj.posProp = c.getNode("position");
|
||||||
|
obj.heading = obj.oriProp.getNode("true-heading-deg");
|
||||||
|
#});
|
||||||
|
#debug.benchmark("radar process2", func {
|
||||||
|
obj.alt = obj.posProp.getNode("altitude-ft");
|
||||||
|
obj.lat = obj.posProp.getNode("latitude-deg");
|
||||||
|
obj.lon = obj.posProp.getNode("longitude-deg");
|
||||||
|
#});
|
||||||
|
#debug.benchmark("radar process3", func {
|
||||||
|
#As it is a geo.Coord object, we have to update lat/lon/alt ->and alt is in meters
|
||||||
|
obj.coord = geo.Coord.new();
|
||||||
|
obj.coord.set_latlon(obj.lat.getValue(), obj.lon.getValue(), obj.alt.getValue() * FT2M);
|
||||||
|
#});
|
||||||
|
#debug.benchmark("radar process4", func {
|
||||||
|
obj.pitch = obj.oriProp.getNode("pitch-deg");
|
||||||
|
obj.roll = obj.oriProp.getNode("roll-deg");
|
||||||
|
obj.speed = obj.velProp.getNode("true-airspeed-kt");
|
||||||
|
obj.vSpeed = obj.velProp.getNode("vertical-speed-fps");
|
||||||
|
obj.callsign = c.getNode("callsign", 1);
|
||||||
|
obj.shorter = c.getNode("model-shorter");
|
||||||
|
obj.orig_callsign = obj.callsign.getValue();
|
||||||
|
obj.name = c.getNode("name");
|
||||||
|
obj.sign = c.getNode("sign",1);
|
||||||
|
obj.valid = c.getNode("valid");
|
||||||
|
obj.painted = c.getNode("painted");
|
||||||
|
obj.unique = c.getNode("unique");
|
||||||
|
obj.validTree = 0;
|
||||||
|
#});
|
||||||
|
#debug.benchmark("radar process5", func {
|
||||||
|
#obj.transponderID = c.getNode("instrumentation/transponder/transmitted-id");
|
||||||
|
#});
|
||||||
|
#debug.benchmark("radar process6", func {
|
||||||
|
obj.acType = c.getNode("sim/model/ac-type");
|
||||||
|
obj.type = c.getName();
|
||||||
|
obj.index = c.getIndex();
|
||||||
|
obj.string = "ai/models/" ~ obj.type ~ "[" ~ obj.index ~ "]";
|
||||||
|
obj.shortString = obj.type ~ "[" ~ obj.index ~ "]";
|
||||||
|
#});
|
||||||
|
#debug.benchmark("radar process7", func {
|
||||||
|
obj.range = obj.rdrProp.getNode("range-nm");
|
||||||
|
obj.bearing = obj.rdrProp.getNode("bearing-deg");
|
||||||
|
obj.elevation = obj.rdrProp.getNode("elevation-deg");
|
||||||
|
#});
|
||||||
|
obj.deviation = nil;
|
||||||
|
|
||||||
|
obj.node = c;
|
||||||
|
obj.class = class;
|
||||||
|
|
||||||
|
obj.polar = [0,0];
|
||||||
|
obj.cartesian = [0,0];
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
isValid: func () {
|
||||||
|
var valid = me.valid.getValue();
|
||||||
|
if (valid == nil) {
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
if (me.callsign.getValue() != me.orig_callsign) {
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
},
|
||||||
|
|
||||||
|
isPainted: func () {
|
||||||
|
if (me.painted == nil) {
|
||||||
|
me.painted = me.node.getNode("painted");
|
||||||
|
}
|
||||||
|
if (me.painted == nil) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
var p = me.painted.getValue();
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
|
||||||
|
getUnique: func () {
|
||||||
|
if (me.unique == nil) {
|
||||||
|
me.unique = me.node.getNode("unique");
|
||||||
|
}
|
||||||
|
if (me.unique == nil) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
var u = me.unique.getValue();
|
||||||
|
return u;
|
||||||
|
},
|
||||||
|
|
||||||
|
getElevation: func() {
|
||||||
|
var e = 0;
|
||||||
|
e = me.elevation.getValue();
|
||||||
|
if(e == nil or e == 0) {
|
||||||
|
# AI/MP has no radar properties
|
||||||
|
var self = geo.aircraft_position();
|
||||||
|
me.get_Coord();
|
||||||
|
var angleInv = clamp(self.distance_to(me.coord)/self.direct_distance_to(me.coord), -1, 1);
|
||||||
|
e = (self.alt()>me.coord.alt()?-1:1)*math.acos(angleInv)*R2D;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
},
|
||||||
|
|
||||||
|
getNode: func () {
|
||||||
|
return me.node;
|
||||||
|
},
|
||||||
|
|
||||||
|
getFlareNode: func () {
|
||||||
|
return me.node.getNode("rotors/main/blade[3]/flap-deg");
|
||||||
|
},
|
||||||
|
|
||||||
|
getChaffNode: func () {
|
||||||
|
return me.node.getNode("rotors/main/blade[3]/position-deg");
|
||||||
|
},
|
||||||
|
|
||||||
|
setPolar: func(dist, angle) {
|
||||||
|
me.polar = [dist,angle];
|
||||||
|
},
|
||||||
|
|
||||||
|
setCartesian: func(x, y) {
|
||||||
|
me.cartesian = [x,y];
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: func(){
|
||||||
|
if(me.validTree != 0){
|
||||||
|
me.validTree.setValue(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Coord: func(){
|
||||||
|
me.coord.set_latlon(me.lat.getValue(), me.lon.getValue(), me.alt.getValue() * FT2M);
|
||||||
|
var TgTCoord = geo.Coord.new(me.coord);
|
||||||
|
return TgTCoord;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Callsign: func(){
|
||||||
|
var n = me.callsign.getValue();
|
||||||
|
if(n != "" and n != nil) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
if (me.name == nil) {
|
||||||
|
me.name = me.getNode().getNode("name");
|
||||||
|
}
|
||||||
|
if (me.name == nil) {
|
||||||
|
n = "";
|
||||||
|
} else {
|
||||||
|
n = me.name.getValue();
|
||||||
|
}
|
||||||
|
if(n != "" and n != nil) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
n = me.sign.getValue();
|
||||||
|
if(n != "" and n != nil) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return "UFO";
|
||||||
|
},
|
||||||
|
|
||||||
|
get_model: func(){
|
||||||
|
var n = "";
|
||||||
|
if (me.shorter == nil) {
|
||||||
|
me.shorter = me.node.getNode("model-shorter");
|
||||||
|
}
|
||||||
|
if (me.shorter != nil) {
|
||||||
|
n = me.shorter.getValue();
|
||||||
|
}
|
||||||
|
if(n != "" and n != nil) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
n = me.sign.getValue();
|
||||||
|
if(n != "" and n != nil) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
if (me.name == nil) {
|
||||||
|
me.name = me.getNode().getNode("name");
|
||||||
|
}
|
||||||
|
if (me.name == nil) {
|
||||||
|
n = "";
|
||||||
|
} else {
|
||||||
|
n = me.name.getValue();
|
||||||
|
}
|
||||||
|
if(n != "" and n != nil) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return me.get_Callsign();
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Speed: func(){
|
||||||
|
# return true airspeed
|
||||||
|
var n = me.speed.getValue();
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Longitude: func(){
|
||||||
|
var n = me.lon.getValue();
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Latitude: func(){
|
||||||
|
var n = me.lat.getValue();
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Pitch: func(){
|
||||||
|
var n = me.pitch.getValue();
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
isVirtual: func(){
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Roll: func(){
|
||||||
|
var n = me.roll.getValue();
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_heading : func(){
|
||||||
|
var n = me.heading.getValue();
|
||||||
|
if(n == nil)
|
||||||
|
{
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_bearing: func(){
|
||||||
|
var n = 0;
|
||||||
|
n = me.bearing.getValue();
|
||||||
|
if(n == nil or n == 0) {
|
||||||
|
# AI/MP has no radar properties
|
||||||
|
n = me.get_bearing_from_Coord(geo.aircraft_position());
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_bearing_from_Coord: func(MyAircraftCoord){
|
||||||
|
me.get_Coord();
|
||||||
|
var myBearing = 0;
|
||||||
|
if(me.coord.is_defined()) {
|
||||||
|
myBearing = MyAircraftCoord.course_to(me.coord);
|
||||||
|
}
|
||||||
|
return myBearing;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_reciprocal_bearing: func(){
|
||||||
|
return geo.normdeg(me.get_bearing() + 180);
|
||||||
|
},
|
||||||
|
|
||||||
|
get_deviation: func(true_heading_ref, coord){
|
||||||
|
me.deviation = - deviation_normdeg(true_heading_ref, me.get_bearing_from_Coord(coord));
|
||||||
|
return me.deviation;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_altitude: func(){
|
||||||
|
#Return Alt in feet
|
||||||
|
return me.alt.getValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
get_Elevation_from_Coord: func(MyAircraftCoord) {
|
||||||
|
me.get_Coord();
|
||||||
|
var value = (me.coord.alt() - MyAircraftCoord.alt()) / me.coord.direct_distance_to(MyAircraftCoord);
|
||||||
|
if (math.abs(value) > 1) {
|
||||||
|
# warning this else will fail if logged in as observer and see aircraft on other side of globe
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
var myPitch = math.asin(value) * R2D;
|
||||||
|
return myPitch;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_total_elevation_from_Coord: func(own_pitch, MyAircraftCoord){
|
||||||
|
var myTotalElevation = - deviation_normdeg(own_pitch, me.get_Elevation_from_Coord(MyAircraftCoord));
|
||||||
|
return myTotalElevation;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_total_elevation: func(own_pitch) {
|
||||||
|
me.deviation = - deviation_normdeg(own_pitch, me.getElevation());
|
||||||
|
return me.deviation;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_range: func() {
|
||||||
|
var r = 0;
|
||||||
|
if(me.range == nil or me.range.getValue() == nil or me.range.getValue() == 0) {
|
||||||
|
# AI/MP has no radar properties
|
||||||
|
me.get_Coord();
|
||||||
|
r = me.coord.direct_distance_to(geo.aircraft_position()) * M2NM;
|
||||||
|
} else {
|
||||||
|
r = me.range.getValue();
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_range_from_Coord: func(MyAircraftCoord) {
|
||||||
|
var myCoord = me.get_Coord();
|
||||||
|
var myDistance = 0;
|
||||||
|
if(myCoord.is_defined()) {
|
||||||
|
myDistance = MyAircraftCoord.direct_distance_to(myCoord) * M2NM;
|
||||||
|
}
|
||||||
|
return myDistance;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_type: func () {
|
||||||
|
return me.class;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_cartesian: func() {
|
||||||
|
return me.cartesian;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_polar: func() {
|
||||||
|
return me.polar;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var isNotBehindTerrain = func( mp ) {
|
||||||
|
|
||||||
|
###########
|
||||||
|
var pos = mp.getNode("position");
|
||||||
|
var alt = pos.getNode("altitude-ft").getValue();
|
||||||
|
var lat = pos.getNode("latitude-deg").getValue();
|
||||||
|
var lon = pos.getNode("longitude-deg").getValue();
|
||||||
|
if(alt == nil or lat == nil or lon == nil) {
|
||||||
|
return isVisible = 0;
|
||||||
|
}
|
||||||
|
var aircraftPos = geo.Coord.new().set_latlon(lat, lon, alt*0.3048);
|
||||||
|
#################
|
||||||
|
if (pickingMethod == 1) {
|
||||||
|
var myPos = geo.aircraft_position();
|
||||||
|
myPos.set_latlon(myPos.lat(),myPos.lon(),myPos.alt()+50);
|
||||||
|
var xyz = {"x":myPos.x(), "y":myPos.y(), "z":myPos.z()};
|
||||||
|
var dir = {"x":aircraftPos.x()-myPos.x(), "y":aircraftPos.y()-myPos.y(), "z":aircraftPos.z()-myPos.z()};
|
||||||
|
|
||||||
|
# Check for terrain between own aircraft and other:
|
||||||
|
v = get_cart_ground_intersection(xyz, dir);
|
||||||
|
if (v == nil) {
|
||||||
|
return 1;
|
||||||
|
#printf("No terrain, planes has clear view of each other");
|
||||||
|
} else {
|
||||||
|
var terrain = geo.Coord.new();
|
||||||
|
terrain.set_latlon(v.lat, v.lon, v.elevation);
|
||||||
|
var maxDist = myPos.direct_distance_to(aircraftPos);
|
||||||
|
var terrainDist = myPos.direct_distance_to(terrain);
|
||||||
|
if (terrainDist < maxDist) {
|
||||||
|
#printf("terrain found between SAM and aircraft %.1f meter away.", terrainDist);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
#print("The planes has clear view of each other");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var isVisible = 0;
|
||||||
|
var MyCoord = geo.aircraft_position();
|
||||||
|
|
||||||
|
# Because there is no terrain on earth that can be between these 2
|
||||||
|
if(MyCoord.alt() < 8900 and aircraftPos.alt() < 8900)
|
||||||
|
{
|
||||||
|
# Temporary variable
|
||||||
|
# A (our plane) coord in meters
|
||||||
|
var a = MyCoord.x();
|
||||||
|
var b = MyCoord.y();
|
||||||
|
var c = MyCoord.z();
|
||||||
|
# B (target) coord in meters
|
||||||
|
var d = aircraftPos.x();
|
||||||
|
var e = aircraftPos.y();
|
||||||
|
var f = aircraftPos.z();
|
||||||
|
var difa = d - a;
|
||||||
|
var difb = e - b;
|
||||||
|
var difc = f - c;
|
||||||
|
# direct Distance in meters
|
||||||
|
var myDistance = math.sqrt( math.pow((d-a),2) + math.pow((e-b),2) + math.pow((f-c),2)); #calculating distance ourselves to avoid another call to geo.nas (read: speed, probably).
|
||||||
|
var Aprime = geo.Coord.new();
|
||||||
|
|
||||||
|
# Here is to limit FPS drop on very long distance
|
||||||
|
var L = 500;
|
||||||
|
if(myDistance > 50000)
|
||||||
|
{
|
||||||
|
L = myDistance / 15;
|
||||||
|
}
|
||||||
|
var step = L;
|
||||||
|
var maxLoops = int(myDistance / L);
|
||||||
|
|
||||||
|
isVisible = 1;
|
||||||
|
# This loop will make travel a point between us and the target and check if there is terrain
|
||||||
|
for(var i = 1 ; i <= maxLoops ; i += 1)
|
||||||
|
{
|
||||||
|
#calculate intermediate step
|
||||||
|
#basically dividing the line into maxLoops number of steps, and checking at each step
|
||||||
|
#to ascii-art explain it:
|
||||||
|
# |us|----------|step 1|-----------|step 2|--------|step 3|----------|them|
|
||||||
|
#there will be as many steps as there is i
|
||||||
|
#every step will be equidistant
|
||||||
|
|
||||||
|
#also, if i == 0 then the first step will be our plane
|
||||||
|
|
||||||
|
var x = ((difa/(maxLoops+1))*i)+a;
|
||||||
|
var y = ((difb/(maxLoops+1))*i)+b;
|
||||||
|
var z = ((difc/(maxLoops+1))*i)+c;
|
||||||
|
#print("i:" ~ i ~ "|x,y,z | " ~ x ~ "," ~ y ~ "," ~ z);
|
||||||
|
Aprime.set_xyz(x,y,z);
|
||||||
|
var AprimeTerrainAlt = geo.elevation(Aprime.lat(), Aprime.lon());
|
||||||
|
if(AprimeTerrainAlt == nil)
|
||||||
|
{
|
||||||
|
AprimeTerrainAlt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(AprimeTerrainAlt > Aprime.alt())
|
||||||
|
{
|
||||||
|
#print("behind terrain");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isVisible = 1;
|
||||||
|
}
|
||||||
|
return isVisible;
|
||||||
|
}
|
||||||
|
}
|
303
gci-radar/Nasal/vector.nas
Normal file
303
gci-radar/Nasal/vector.nas
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
var Math = {
|
||||||
|
#
|
||||||
|
# Author: Nikolai V. Chr.
|
||||||
|
#
|
||||||
|
# Version 1.6
|
||||||
|
#
|
||||||
|
# When doing euler coords. to cartesian: +x = forw, +y = left, +z = up.
|
||||||
|
# FG struct. coords: +x = back, +y = right, +z = up.
|
||||||
|
#
|
||||||
|
# When doing euler angles (from pilots point of view): yaw = yaw left, pitch = rotate up, roll = roll right.
|
||||||
|
# FG rotations: heading = yaw right, pitch = rotate up, roll = roll right.
|
||||||
|
#
|
||||||
|
clamp: func(v, min, max) { v < min ? min : v > max ? max : v },
|
||||||
|
|
||||||
|
convertCoords: func (x,y,z) {
|
||||||
|
return [-x, -y, z];
|
||||||
|
},
|
||||||
|
|
||||||
|
convertAngles: func (heading,pitch,roll) {
|
||||||
|
return [-heading, pitch, roll];
|
||||||
|
},
|
||||||
|
|
||||||
|
# angle between 2 vectors. Returns 0-180 degrees.
|
||||||
|
angleBetweenVectors: func (a,b) {
|
||||||
|
a = me.normalize(a);
|
||||||
|
b = me.normalize(b);
|
||||||
|
me.value = me.clamp((me.dotProduct(a,b)/me.magnitudeVector(a))/me.magnitudeVector(b),-1,1);#just to be safe in case some floating point error makes it out of bounds
|
||||||
|
return R2D * math.acos(me.value);
|
||||||
|
},
|
||||||
|
|
||||||
|
# length of vector
|
||||||
|
magnitudeVector: func (a) {
|
||||||
|
return math.sqrt(math.pow(a[0],2)+math.pow(a[1],2)+math.pow(a[2],2));
|
||||||
|
},
|
||||||
|
|
||||||
|
# dot product of 2 vectors
|
||||||
|
dotProduct: func (a,b) {
|
||||||
|
return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
|
||||||
|
},
|
||||||
|
|
||||||
|
# rotate a vector. Order: roll, pitch, yaw
|
||||||
|
rollPitchYawVector: func (roll, pitch, yaw, vector) {
|
||||||
|
me.rollM = me.rollMatrix(roll);
|
||||||
|
me.pitchM = me.pitchMatrix(pitch);
|
||||||
|
me.yawM = me.yawMatrix(yaw);
|
||||||
|
me.rotation = me.multiplyMatrices(me.multiplyMatrices(me.yawM, me.pitchM), me.rollM);
|
||||||
|
return me.multiplyMatrixWithVector(me.rotation, vector);
|
||||||
|
},
|
||||||
|
|
||||||
|
# rotate a vector. Order: yaw, pitch, roll (like an aircraft)
|
||||||
|
yawPitchRollVector: func (yaw, pitch, roll, vector) {
|
||||||
|
me.rollM = me.rollMatrix(roll);
|
||||||
|
me.pitchM = me.pitchMatrix(pitch);
|
||||||
|
me.yawM = me.yawMatrix(yaw);
|
||||||
|
me.rotation = me.multiplyMatrices(me.multiplyMatrices(me.rollM, me.pitchM), me.yawM);
|
||||||
|
return me.multiplyMatrixWithVector(me.rotation, vector);
|
||||||
|
},
|
||||||
|
|
||||||
|
# multiply 3x3 matrix with vector
|
||||||
|
multiplyMatrixWithVector: func (matrix, vector) {
|
||||||
|
return [matrix[0]*vector[0]+matrix[1]*vector[1]+matrix[2]*vector[2],
|
||||||
|
matrix[3]*vector[0]+matrix[4]*vector[1]+matrix[5]*vector[2],
|
||||||
|
matrix[6]*vector[0]+matrix[7]*vector[1]+matrix[8]*vector[2]];
|
||||||
|
},
|
||||||
|
|
||||||
|
# multiply 2 3x3 matrices
|
||||||
|
multiplyMatrices: func (a,b) {
|
||||||
|
return [a[0]*b[0]+a[1]*b[3]+a[2]*b[6], a[0]*b[1]+a[1]*b[4]+a[2]*b[7], a[0]*b[2]+a[1]*b[5]+a[2]*b[8],
|
||||||
|
a[3]*b[0]+a[4]*b[3]+a[5]*b[6], a[3]*b[1]+a[4]*b[4]+a[5]*b[7], a[3]*b[2]+a[4]*b[5]+a[5]*b[8],
|
||||||
|
a[6]*b[0]+a[7]*b[3]+a[8]*b[6], a[6]*b[1]+a[7]*b[4]+a[8]*b[7], a[6]*b[2]+a[7]*b[5]+a[8]*b[8]];
|
||||||
|
},
|
||||||
|
|
||||||
|
# matrix for rolling
|
||||||
|
rollMatrix: func (roll) {
|
||||||
|
roll = roll * D2R;
|
||||||
|
return [1,0,0,
|
||||||
|
0,math.cos(roll),-math.sin(roll),
|
||||||
|
0,math.sin(roll), math.cos(roll)];
|
||||||
|
},
|
||||||
|
|
||||||
|
# matrix for pitching
|
||||||
|
pitchMatrix: func (pitch) {
|
||||||
|
pitch = pitch * D2R;
|
||||||
|
return [math.cos(pitch),0,-math.sin(pitch),
|
||||||
|
0,1,0,
|
||||||
|
math.sin(pitch),0,math.cos(pitch)];
|
||||||
|
},
|
||||||
|
|
||||||
|
# matrix for yawing
|
||||||
|
yawMatrix: func (yaw) {
|
||||||
|
yaw = yaw * D2R;
|
||||||
|
return [math.cos(yaw),-math.sin(yaw),0,
|
||||||
|
math.sin(yaw),math.cos(yaw),0,
|
||||||
|
0,0,1];
|
||||||
|
},
|
||||||
|
|
||||||
|
# vector to heading/pitch
|
||||||
|
cartesianToEuler: func (vector) {
|
||||||
|
me.horz = math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]);
|
||||||
|
if (me.horz != 0) {
|
||||||
|
me.pitch = math.atan2(vector[2],me.horz)*R2D;
|
||||||
|
me.hdg = math.asin(-vector[1]/me.horz)*R2D;
|
||||||
|
|
||||||
|
if (vector[0] < 0) {
|
||||||
|
# south
|
||||||
|
if (me.hdg >= 0) {
|
||||||
|
me.hdg = 180-me.hdg;
|
||||||
|
} else {
|
||||||
|
me.hdg = -180-me.hdg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
me.hdg = geo.normdeg(me.hdg);
|
||||||
|
} else {
|
||||||
|
me.pitch = vector[2]>=0?90:-90;
|
||||||
|
me.hdg = nil;
|
||||||
|
}
|
||||||
|
return [me.hdg, me.pitch];
|
||||||
|
},
|
||||||
|
|
||||||
|
# gives an vector that points up from fuselage
|
||||||
|
eulerToCartesian3Z: func (yaw_deg, pitch_deg, roll_deg) {
|
||||||
|
me.yaw = yaw_deg * D2R;
|
||||||
|
me.pitch = pitch_deg * D2R;
|
||||||
|
me.roll = roll_deg * D2R;
|
||||||
|
me.x = -math.cos(me.yaw)*math.sin(me.pitch)*math.cos(me.roll) + math.sin(me.yaw)*math.sin(me.roll);
|
||||||
|
me.y = -math.sin(me.yaw)*math.sin(me.pitch)*math.cos(me.roll) - math.cos(me.yaw)*math.sin(me.roll);
|
||||||
|
me.z = math.cos(me.pitch)*math.cos(me.roll);#roll changed from sin to cos, since the rotation matrix is wrong
|
||||||
|
return [me.x,me.y,me.z];
|
||||||
|
},
|
||||||
|
|
||||||
|
# gives an vector that points forward from fuselage
|
||||||
|
eulerToCartesian3X: func (yaw_deg, pitch_deg, roll_deg) {
|
||||||
|
me.yaw = yaw_deg * D2R;
|
||||||
|
me.pitch = pitch_deg * D2R;
|
||||||
|
me.roll = roll_deg * D2R;
|
||||||
|
me.x = math.cos(me.yaw)*math.cos(me.pitch);
|
||||||
|
me.y = math.sin(me.yaw)*math.cos(me.pitch);
|
||||||
|
me.z = math.sin(me.pitch);
|
||||||
|
return [me.x,me.y,me.z];
|
||||||
|
},
|
||||||
|
|
||||||
|
# gives an vector that points left from fuselage
|
||||||
|
eulerToCartesian3Y: func (yaw_deg, pitch_deg, roll_deg) {
|
||||||
|
me.yaw = yaw_deg * D2R;
|
||||||
|
me.pitch = pitch_deg * D2R;
|
||||||
|
me.roll = roll_deg * D2R;
|
||||||
|
me.x = -math.cos(me.yaw)*math.sin(me.pitch)*math.sin(me.roll) - math.sin(me.yaw)*math.cos(me.roll);
|
||||||
|
me.y = -math.sin(me.yaw)*math.sin(me.pitch)*math.sin(me.roll) + math.cos(me.yaw)*math.cos(me.roll);
|
||||||
|
me.z = math.cos(me.pitch)*math.sin(me.roll);
|
||||||
|
return [me.x,me.y,me.z];
|
||||||
|
},
|
||||||
|
|
||||||
|
# same as eulerToCartesian3X, except it needs no roll
|
||||||
|
eulerToCartesian2: func (yaw_deg, pitch_deg) {
|
||||||
|
me.yaw = yaw_deg * D2R;
|
||||||
|
me.pitch = pitch_deg * D2R;
|
||||||
|
me.x = math.cos(me.pitch) * math.cos(me.yaw);
|
||||||
|
me.y = math.cos(me.pitch) * math.sin(me.yaw);
|
||||||
|
me.z = math.sin(me.pitch);
|
||||||
|
return [me.x,me.y,me.z];
|
||||||
|
},
|
||||||
|
|
||||||
|
#pitch from coord1 to coord2 in degrees (takes curvature of earth into effect.)
|
||||||
|
getPitch: func (coord1, coord2) {
|
||||||
|
if (coord1.lat() == coord2.lat() and coord1.lon() == coord2.lon()) {
|
||||||
|
if (coord2.alt() > coord1.alt()) {
|
||||||
|
return 90;
|
||||||
|
} elsif (coord2.alt() < coord1.alt()) {
|
||||||
|
return -90;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (coord1.alt() != coord2.alt()) {
|
||||||
|
me.d12 = coord1.direct_distance_to(coord2);
|
||||||
|
me.coord3 = geo.Coord.new(coord1);
|
||||||
|
me.coord3.set_alt(coord1.alt()-me.d12*0.5);# this will increase the area of the triangle so that rounding errors dont get in the way.
|
||||||
|
me.d13 = coord1.alt()-me.coord3.alt();
|
||||||
|
if (me.d12 == 0) {
|
||||||
|
# on top of each other, maybe rounding error..
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
me.d32 = me.coord3.direct_distance_to(coord2);
|
||||||
|
if (math.abs(me.d13)+me.d32 < me.d12) {
|
||||||
|
# rounding errors somewhere..one triangle side is longer than other 2 sides combined.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
# standard formula for a triangle where all 3 side lengths are known:
|
||||||
|
me.len = (math.pow(me.d12, 2)+math.pow(me.d13,2)-math.pow(me.d32, 2))/(2 * me.d12 * math.abs(me.d13));
|
||||||
|
if (me.len < -1 or me.len > 1) {
|
||||||
|
# something went wrong, maybe rounding error..
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
me.angle = R2D * math.acos(me.len);
|
||||||
|
me.pitch = -1* (90 - me.angle);
|
||||||
|
#printf("d12 %.4f d32 %.4f d13 %.4f len %.4f pitch %.4f angle %.4f", me.d12, me.d32, me.d13, me.len, me.pitch, me.angle);
|
||||||
|
return me.pitch;
|
||||||
|
} else {
|
||||||
|
# same altitude
|
||||||
|
me.nc = geo.Coord.new();
|
||||||
|
me.nc.set_xyz(0,0,0); # center of earth
|
||||||
|
me.radiusEarth = coord1.direct_distance_to(me.nc);# current distance to earth center
|
||||||
|
me.d12 = coord1.direct_distance_to(coord2);
|
||||||
|
# standard formula for a triangle where all 3 side lengths are known:
|
||||||
|
me.len = (math.pow(me.d12, 2)+math.pow(me.radiusEarth,2)-math.pow(me.radiusEarth, 2))/(2 * me.d12 * me.radiusEarth);
|
||||||
|
if (me.len < -1 or me.len > 1) {
|
||||||
|
# something went wrong, maybe rounding error..
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
me.angle = R2D * math.acos(me.len);
|
||||||
|
me.pitch = -1* (90 - me.angle);
|
||||||
|
return me.pitch;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
# supply a normal to the plane, and a vector. The vector will be projected onto the plane, and that projection is returned as a vector.
|
||||||
|
projVectorOnPlane: func (planeNormal, vector) {
|
||||||
|
return me.minus(vector, me.product(me.dotProduct(vector,planeNormal)/math.pow(me.magnitudeVector(planeNormal),2), planeNormal));
|
||||||
|
},
|
||||||
|
|
||||||
|
# vector a - vector b
|
||||||
|
minus: func (a, b) {
|
||||||
|
return [a[0]-b[0], a[1]-b[1], a[2]-b[2]];
|
||||||
|
},
|
||||||
|
|
||||||
|
# vector a + vector b
|
||||||
|
plus: func (a, b) {
|
||||||
|
return [a[0]+b[0], a[1]+b[1], a[2]+b[2]];
|
||||||
|
},
|
||||||
|
|
||||||
|
# float * vector
|
||||||
|
product: func (scalar, vector) {
|
||||||
|
return [scalar*vector[0], scalar*vector[1], scalar*vector[2]]
|
||||||
|
},
|
||||||
|
|
||||||
|
# print vector to console
|
||||||
|
format: func (v) {
|
||||||
|
return sprintf("(%.1f, %.1f, %.1f)",v[0],v[1],v[2]);
|
||||||
|
},
|
||||||
|
|
||||||
|
# make vector length 1.0
|
||||||
|
normalize: func (v) {
|
||||||
|
me.mag = me.magnitudeVector(v);
|
||||||
|
return [v[0]/me.mag, v[1]/me.mag, v[2]/me.mag];
|
||||||
|
},
|
||||||
|
|
||||||
|
# rotation matrices
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#| 1 0 0 |
|
||||||
|
#| 0 cos(roll) -sin(roll) |
|
||||||
|
#| 0 sin(roll) cos(roll) |
|
||||||
|
#
|
||||||
|
#| cos(pitch) 0 -sin(pitch) |
|
||||||
|
#| 0 1 0 |
|
||||||
|
#| sin(pitch) 0 cos(pitch) |
|
||||||
|
#
|
||||||
|
#| cos(yaw) -sin(yaw) 0 |
|
||||||
|
#| sin(yaw) cos(yaw) 0 |
|
||||||
|
#| 0 0 1 |
|
||||||
|
#
|
||||||
|
# combined matrix from yaw, pitch, roll:
|
||||||
|
#
|
||||||
|
#| cos(yaw)cos(pitch) -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll) -cos(yaw)sin(pitch)cos(roll)+sin(yaw)sin(roll)|
|
||||||
|
#| sin(yaw)cos(pitch) -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll) -sin(yaw)sin(pitch)cos(roll)-cos(yaw)sin(roll)|
|
||||||
|
#| sin(pitch) cos(pitch)sin(roll) cos(pitch)cos(roll)|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
# Fix for geo.Coord: (not needed in FG 2017.4+)
|
||||||
|
geo.Coord.set_x = func(x) { me._cupdate(); me._pdirty = 1; me._x = x; me };
|
||||||
|
geo.Coord.set_y = func(y) { me._cupdate(); me._pdirty = 1; me._y = y; me };
|
||||||
|
geo.Coord.set_z = func(z) { me._cupdate(); me._pdirty = 1; me._z = z; me };
|
||||||
|
geo.Coord.set_lat = func(lat) { me._pupdate(); me._cdirty = 1; me._lat = lat * D2R; me };
|
||||||
|
geo.Coord.set_lon = func(lon) { me._pupdate(); me._cdirty = 1; me._lon = lon * D2R; me };
|
||||||
|
geo.Coord.set_alt = func(alt) { me._pupdate(); me._cdirty = 1; me._alt = alt; me };
|
||||||
|
geo.Coord.apply_course_distance2 = func(course, dist) {# this method in geo is not bad, just wanted to see if this way of doing it worked better.
|
||||||
|
me._pupdate();
|
||||||
|
course *= D2R;
|
||||||
|
var nc = geo.Coord.new();
|
||||||
|
nc.set_xyz(0,0,0); # center of earth
|
||||||
|
dist /= me.direct_distance_to(nc);# current distance to earth center
|
||||||
|
|
||||||
|
if (dist < 0.0) {
|
||||||
|
dist = abs(dist);
|
||||||
|
course = course - math.pi;
|
||||||
|
}
|
||||||
|
|
||||||
|
me._lat2 = math.asin(math.sin(me._lat) * math.cos(dist) + math.cos(me._lat) * math.sin(dist) * math.cos(course));
|
||||||
|
|
||||||
|
me._lon = me._lon + math.atan2(math.sin(course)*math.sin(dist)*math.cos(me._lat),math.cos(dist)-math.sin(me._lat)*math.sin(me._lat2));
|
||||||
|
|
||||||
|
while (me._lon <= -math.pi)
|
||||||
|
me._lon += math.pi*2;
|
||||||
|
while (me._lon > math.pi)
|
||||||
|
me._lon -= math.pi*2;
|
||||||
|
|
||||||
|
me._lat = me._lat2;
|
||||||
|
me._cdirty = 1;
|
||||||
|
me;
|
||||||
|
};
|
112
gci-radar/gci-set.xml
Normal file
112
gci-radar/gci-set.xml
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<PropertyList>
|
||||||
|
|
||||||
|
<environment>
|
||||||
|
<in-to-wind type="bool">false</in-to-wind>
|
||||||
|
</environment>
|
||||||
|
|
||||||
|
<sim>
|
||||||
|
<author>pinto</author>
|
||||||
|
<description>gci</description>
|
||||||
|
<status>alpha</status>
|
||||||
|
<aircraft-version>0.1</aircraft-version>
|
||||||
|
|
||||||
|
<flight-model>null</flight-model>
|
||||||
|
|
||||||
|
<aero></aero>
|
||||||
|
<aircraft-operator></aircraft-operator>
|
||||||
|
|
||||||
|
<model>
|
||||||
|
<path>Aircraft/gci-radar/Models/gci.xml</path>
|
||||||
|
<always-show-in-MP type="bool">true</always-show-in-MP>
|
||||||
|
</model>
|
||||||
|
|
||||||
|
<presets>
|
||||||
|
<onground>true</onground>
|
||||||
|
</presets>
|
||||||
|
|
||||||
|
<menubar>
|
||||||
|
<default>
|
||||||
|
<menu n="100">
|
||||||
|
<label>GCI</label>
|
||||||
|
<enabled type="bool">true</enabled>
|
||||||
|
<item>
|
||||||
|
<label>Targets</label>
|
||||||
|
<name>enemies</name>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-show</command>
|
||||||
|
<dialog-name>enemies</dialog-name>
|
||||||
|
</binding>
|
||||||
|
</item>
|
||||||
|
</menu>
|
||||||
|
</default>
|
||||||
|
</menubar>
|
||||||
|
|
||||||
|
<enemies>
|
||||||
|
<e1 userarchive="y" type="string">Leto</e1>
|
||||||
|
<e2 userarchive="y" type="string">swamp</e2>
|
||||||
|
<e3 userarchive="y" type="string">pinto</e3>
|
||||||
|
<e4 userarchive="y" type="string">fb237</e4>
|
||||||
|
<e5 userarchive="y" type="string">Wilco-1</e5>
|
||||||
|
<e6 userarchive="y" type="string">Kokos</e6>
|
||||||
|
<e7 userarchive="y" type="string">J-Mav16</e7>
|
||||||
|
<e8 userarchive="y" type="string">S</e8>
|
||||||
|
<e9 userarchive="y" type="string">Raider1</e9>
|
||||||
|
<e10 userarchive="y" type="string">Slobb</e10>
|
||||||
|
<e11 userarchive="y" type="string">5H1N0B1</e11>
|
||||||
|
<e12 userarchive="y" type="string">SNOWY1</e12>
|
||||||
|
<opfor-switch userarchive="y" type="bool">false</opfor-switch>
|
||||||
|
<friend-switch userarchive="y" type="bool">false</friend-switch>
|
||||||
|
</enemies>
|
||||||
|
|
||||||
|
<aircraft-data>
|
||||||
|
<!-- Properties that get saved to persist locally between FG sessions -->
|
||||||
|
<path>enemies/e1</path>
|
||||||
|
<path>enemies/e2</path>
|
||||||
|
<path>enemies/e3</path>
|
||||||
|
<path>enemies/e4</path>
|
||||||
|
<path>enemies/e5</path>
|
||||||
|
<path>enemies/e6</path>
|
||||||
|
<path>enemies/e7</path>
|
||||||
|
<path>enemies/e8</path>
|
||||||
|
<path>enemies/e9</path>
|
||||||
|
<path>enemies/e10</path>
|
||||||
|
<path>enemies/e11</path>
|
||||||
|
<path>enemies/e12</path>
|
||||||
|
<path>enemies/opfor-switch</path>
|
||||||
|
<path>enemies/friend-switch</path>
|
||||||
|
</aircraft-data>
|
||||||
|
|
||||||
|
<startup>
|
||||||
|
<splash-texture>Aircraft/gci-radar/splash1.png</splash-texture>
|
||||||
|
</startup>
|
||||||
|
|
||||||
|
<current-view>
|
||||||
|
<z-offset-dec-step type="double">0.0</z-offset-dec-step>
|
||||||
|
<z-offset-inc-step type="double">0.0</z-offset-inc-step>
|
||||||
|
|
||||||
|
<z-offset-min-m type="float">100.0</z-offset-min-m>
|
||||||
|
<z-offset-max-m type="float">2000.0</z-offset-max-m>
|
||||||
|
</current-view>
|
||||||
|
|
||||||
|
<multiplay>
|
||||||
|
<generic>
|
||||||
|
<int n="0" type="int">0</int>
|
||||||
|
</generic>
|
||||||
|
<visibility-range-nm type="int">500</visibility-range-nm>
|
||||||
|
</multiplay>
|
||||||
|
</sim>
|
||||||
|
|
||||||
|
<carrier>
|
||||||
|
<sunk type="bool">false</sunk>
|
||||||
|
</carrier>
|
||||||
|
|
||||||
|
<nasal>
|
||||||
|
<damage> <file>Aircraft/gci-radar/Nasal/damage.nas</file> </damage>
|
||||||
|
<radar_logic> <file>Aircraft/gci-radar/Nasal/radar-logic.nas</file> </radar_logic>
|
||||||
|
<gci> <file>Aircraft/gci-radar/Nasal/gci.nas</file> </gci>
|
||||||
|
<vector> <file>Aircraft/gci-radar/Nasal/vector.nas</file> </vector>
|
||||||
|
</nasal>
|
||||||
|
|
||||||
|
</PropertyList>
|
BIN
gci-radar/gui/1.png
Normal file
BIN
gci-radar/gui/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
BIN
gci-radar/gui/2.png
Normal file
BIN
gci-radar/gui/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 MiB |
348
gci-radar/gui/dialogs/enemies.xml
Normal file
348
gci-radar/gui/dialogs/enemies.xml
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<PropertyList>
|
||||||
|
<name>enemies</name>
|
||||||
|
<modal>false</modal>
|
||||||
|
<layout>vbox</layout>
|
||||||
|
<draggable>true</draggable>
|
||||||
|
<resizable>true</resizable>
|
||||||
|
<width>250</width>
|
||||||
|
<height>550</height>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<empty><stretch>1</stretch></empty>
|
||||||
|
|
||||||
|
<text>
|
||||||
|
<label>Targets</label>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<empty><stretch>1</stretch></empty>
|
||||||
|
|
||||||
|
<button>
|
||||||
|
<pref-width>16</pref-width>
|
||||||
|
<pref-height>16</pref-height>
|
||||||
|
<legend></legend>
|
||||||
|
<default>1</default>
|
||||||
|
<keynum>27</keynum>
|
||||||
|
<border>2</border>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-close</command>
|
||||||
|
</binding>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</button>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<text>
|
||||||
|
<label>Callsigns:</label>
|
||||||
|
<height>25</height>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>1</label>
|
||||||
|
<property>enemies/e1</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>2</label>
|
||||||
|
<property>enemies/e2</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>3</label>
|
||||||
|
<property>enemies/e3</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>4</label>
|
||||||
|
<property>enemies/e4</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>5</label>
|
||||||
|
<property>enemies/e5</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>6</label>
|
||||||
|
<property>enemies/e6</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>7</label>
|
||||||
|
<property>enemies/e7</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>8</label>
|
||||||
|
<property>enemies/e8</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>9</label>
|
||||||
|
<property>enemies/e9</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>10</label>
|
||||||
|
<property>enemies/e10</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>11</label>
|
||||||
|
<property>enemies/e11</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<input>
|
||||||
|
<width>250</width>
|
||||||
|
<height>25</height>
|
||||||
|
<label>12</label>
|
||||||
|
<property>enemies/e12</property>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>left</halign>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
<color>
|
||||||
|
<red>1</red>
|
||||||
|
<green>0.5</green>
|
||||||
|
<blue>0.5</blue>
|
||||||
|
</color>
|
||||||
|
<enable>
|
||||||
|
<not>
|
||||||
|
<property>enemies/opfor-switch</property>
|
||||||
|
</not>
|
||||||
|
<not>
|
||||||
|
<property>enemies/friend-switch</property>
|
||||||
|
</not>
|
||||||
|
</enable>
|
||||||
|
</input>
|
||||||
|
<checkbox>
|
||||||
|
<width>12</width>
|
||||||
|
<height>12</height>
|
||||||
|
<property>/enemies/opfor-switch</property>
|
||||||
|
<label>Target all non-OPFOR</label>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</checkbox>
|
||||||
|
<checkbox>
|
||||||
|
<width>12</width>
|
||||||
|
<height>12</height>
|
||||||
|
<property>/enemies/friend-switch</property>
|
||||||
|
<label>Target all OPFOR</label>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</checkbox>
|
||||||
|
</PropertyList>
|
Before Width: | Height: | Size: 823 KiB After Width: | Height: | Size: 823 KiB |
@ -1,330 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2015 onox
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<PropertyList>
|
|
||||||
|
|
||||||
<name>control-panel</name>
|
|
||||||
<layout>vbox</layout>
|
|
||||||
<width>250</width>
|
|
||||||
<resizable>false</resizable>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>hbox</layout>
|
|
||||||
|
|
||||||
<empty><stretch>true</stretch></empty>
|
|
||||||
<text>
|
|
||||||
<label>Control Panel</label>
|
|
||||||
</text>
|
|
||||||
<empty><stretch>true</stretch></empty>
|
|
||||||
|
|
||||||
<button>
|
|
||||||
<legend/>
|
|
||||||
<keynum>27</keynum>
|
|
||||||
<pref-width>16</pref-width>
|
|
||||||
<pref-height>16</pref-height>
|
|
||||||
<border>2</border>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-close</command>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
<hrule/>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>vbox</layout>
|
|
||||||
<padding>6</padding>
|
|
||||||
<text>
|
|
||||||
<label>Elevators</label>
|
|
||||||
</text>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>table</layout>
|
|
||||||
|
|
||||||
<!-- 3rd -->
|
|
||||||
<text>
|
|
||||||
<row>0</row>
|
|
||||||
<col>1</col>
|
|
||||||
<label>3rd</label>
|
|
||||||
</text>
|
|
||||||
|
|
||||||
<!-- 3rd -->
|
|
||||||
<button>
|
|
||||||
<row>1</row>
|
|
||||||
<col>1</col>
|
|
||||||
<visible>
|
|
||||||
<property>/carrier/elevators/elevator[2]/at-flight-deck</property>
|
|
||||||
</visible>
|
|
||||||
<legend>FLIGHT DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[2]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
<button>
|
|
||||||
<row>1</row>
|
|
||||||
<col>1</col>
|
|
||||||
<visible>
|
|
||||||
<not>
|
|
||||||
<property>/carrier/elevators/elevator[2]/at-flight-deck</property>
|
|
||||||
</not>
|
|
||||||
</visible>
|
|
||||||
<legend>HANGAR DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[2]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- 2nd -->
|
|
||||||
<text>
|
|
||||||
<row>2</row>
|
|
||||||
<col>1</col>
|
|
||||||
<label>2nd</label>
|
|
||||||
</text>
|
|
||||||
|
|
||||||
<!-- 2nd -->
|
|
||||||
<button>
|
|
||||||
<row>3</row>
|
|
||||||
<col>1</col>
|
|
||||||
<visible>
|
|
||||||
<property>/carrier/elevators/elevator[1]/at-flight-deck</property>
|
|
||||||
</visible>
|
|
||||||
<legend>FLIGHT DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[1]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
<button>
|
|
||||||
<row>3</row>
|
|
||||||
<col>1</col>
|
|
||||||
<visible>
|
|
||||||
<not>
|
|
||||||
<property>/carrier/elevators/elevator[1]/at-flight-deck</property>
|
|
||||||
</not>
|
|
||||||
</visible>
|
|
||||||
<legend>HANGAR DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[1]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- 4th -->
|
|
||||||
<text>
|
|
||||||
<row>4</row>
|
|
||||||
<col>0</col>
|
|
||||||
<label>4th</label>
|
|
||||||
</text>
|
|
||||||
<!-- 1st -->
|
|
||||||
<text>
|
|
||||||
<row>4</row>
|
|
||||||
<col>1</col>
|
|
||||||
<label>1st</label>
|
|
||||||
</text>
|
|
||||||
|
|
||||||
<!-- 4th -->
|
|
||||||
<button>
|
|
||||||
<row>5</row>
|
|
||||||
<col>0</col>
|
|
||||||
<visible>
|
|
||||||
<property>/carrier/elevators/elevator[3]/at-flight-deck</property>
|
|
||||||
</visible>
|
|
||||||
<legend>FLIGHT DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[3]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
<button>
|
|
||||||
<row>5</row>
|
|
||||||
<col>0</col>
|
|
||||||
<visible>
|
|
||||||
<not>
|
|
||||||
<property>/carrier/elevators/elevator[3]/at-flight-deck</property>
|
|
||||||
</not>
|
|
||||||
</visible>
|
|
||||||
<legend>HANGAR DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[3]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- 1st -->
|
|
||||||
<button>
|
|
||||||
<row>5</row>
|
|
||||||
<col>1</col>
|
|
||||||
<visible>
|
|
||||||
<property>/carrier/elevators/elevator[0]/at-flight-deck</property>
|
|
||||||
</visible>
|
|
||||||
<legend>FLIGHT DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[0]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
<button>
|
|
||||||
<row>5</row>
|
|
||||||
<col>1</col>
|
|
||||||
<visible>
|
|
||||||
<not>
|
|
||||||
<property>/carrier/elevators/elevator[0]/at-flight-deck</property>
|
|
||||||
</not>
|
|
||||||
</visible>
|
|
||||||
<legend>HANGAR DECK</legend>
|
|
||||||
<pref-width>100</pref-width>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
<property>/carrier/elevators/elevator[0]/at-flight-deck</property>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
<hrule/>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>vbox</layout>
|
|
||||||
<padding>6</padding>
|
|
||||||
<text>
|
|
||||||
<label>Flight Deck</label>
|
|
||||||
</text>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>vbox</layout>
|
|
||||||
|
|
||||||
<checkbox>
|
|
||||||
<halign>left</halign>
|
|
||||||
<label>Runway lighting</label>
|
|
||||||
<property>/controls/lighting/deck-lights</property>
|
|
||||||
<live>true</live>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
</binding>
|
|
||||||
</checkbox>
|
|
||||||
|
|
||||||
<checkbox>
|
|
||||||
<halign>left</halign>
|
|
||||||
<label>Antennas</label>
|
|
||||||
<property>/carrier/antennas/enabled</property>
|
|
||||||
<live>true</live>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
</binding>
|
|
||||||
</checkbox>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
<hrule/>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>vbox</layout>
|
|
||||||
<padding>6</padding>
|
|
||||||
<text>
|
|
||||||
<label>Debug</label>
|
|
||||||
</text>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>vbox</layout>
|
|
||||||
|
|
||||||
<checkbox>
|
|
||||||
<halign>left</halign>
|
|
||||||
<label>Enable ship movememnt</label>
|
|
||||||
<property>/carrier/fdm/settings/movement</property>
|
|
||||||
<live>true</live>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
</binding>
|
|
||||||
</checkbox>
|
|
||||||
|
|
||||||
<checkbox>
|
|
||||||
<halign>left</halign>
|
|
||||||
<label>Show Phalanx aim points</label>
|
|
||||||
<property>/carrier/phalanx/settings/show-debug-aim</property>
|
|
||||||
<live>true</live>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-apply</command>
|
|
||||||
</binding>
|
|
||||||
<binding>
|
|
||||||
<command>property-toggle</command>
|
|
||||||
</binding>
|
|
||||||
</checkbox>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
<hrule/>
|
|
||||||
|
|
||||||
<group>
|
|
||||||
<layout>hbox</layout>
|
|
||||||
<default-padding>6</default-padding>
|
|
||||||
|
|
||||||
<empty><stretch>true</stretch></empty>
|
|
||||||
|
|
||||||
<button>
|
|
||||||
<legend>Close</legend>
|
|
||||||
<default>true</default>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-close</command>
|
|
||||||
</binding>
|
|
||||||
</button>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
</PropertyList>
|
|
@ -1,39 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2015 onox
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<PropertyList>
|
|
||||||
|
|
||||||
<default>
|
|
||||||
|
|
||||||
<menu n="10">
|
|
||||||
<label>CVN-70</label>
|
|
||||||
<enabled type="bool">true</enabled>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<label>Control Panel</label>
|
|
||||||
<binding>
|
|
||||||
<command>dialog-show</command>
|
|
||||||
<dialog-name>control-panel</dialog-name>
|
|
||||||
</binding>
|
|
||||||
</item>
|
|
||||||
</menu>
|
|
||||||
|
|
||||||
</default>
|
|
||||||
|
|
||||||
</PropertyList>
|
|
@ -1,563 +0,0 @@
|
|||||||
AC3Db
|
|
||||||
MATERIAL "Color_M07" rgb 0.227 0.227 0.227 amb 1.000 1.000 1.000 emis 0.000 0.000 0.000 spec 0.500 0.500 0.500 shi 12 trans 0.000
|
|
||||||
MATERIAL "Color_M03" rgb 0.667 0.667 0.667 amb 1.000 1.000 1.000 emis 0.000 0.000 0.000 spec 0.500 0.500 0.500 shi 12 trans 0.000
|
|
||||||
MATERIAL "Translucent_Glass_Blue" rgb 0.392 0.584 0.929 amb 1.000 1.000 1.000 emis 0.000 0.000 0.000 spec 0.500 0.500 0.500 shi 12 trans 0.502
|
|
||||||
OBJECT world
|
|
||||||
name "Blender_exporter_v2.17__towerSnowy1.ac"
|
|
||||||
kids 5
|
|
||||||
OBJECT poly
|
|
||||||
name "door"
|
|
||||||
data 4
|
|
||||||
ID11
|
|
||||||
crease 40.0
|
|
||||||
numvert 4
|
|
||||||
2 2 0
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
1 2 0
|
|
||||||
numsurf 2
|
|
||||||
SURF 0X10
|
|
||||||
mat 0
|
|
||||||
refs 3
|
|
||||||
0 0 0
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 0
|
|
||||||
refs 3
|
|
||||||
1 0 0
|
|
||||||
0 0 0
|
|
||||||
3 0 0
|
|
||||||
kids 0
|
|
||||||
OBJECT poly
|
|
||||||
name "floor"
|
|
||||||
data 4
|
|
||||||
ID33
|
|
||||||
crease 40.0
|
|
||||||
numvert 32
|
|
||||||
3.75 13 -7.25
|
|
||||||
4 12 -3
|
|
||||||
3.75 13 -2.75
|
|
||||||
4 12 -7
|
|
||||||
4 12 -7
|
|
||||||
3.75 13 -7.25
|
|
||||||
4 12 -3
|
|
||||||
3.75 13 -2.75
|
|
||||||
8.25 13 -2.75
|
|
||||||
4 12 -3
|
|
||||||
8 12 -3
|
|
||||||
3.75 13 -2.75
|
|
||||||
3.75 13 -2.75
|
|
||||||
8.25 13 -2.75
|
|
||||||
4 12 -3
|
|
||||||
8 12 -3
|
|
||||||
3.75 13 -7.25
|
|
||||||
8 12 -7
|
|
||||||
4 12 -7
|
|
||||||
8.25 13 -7.25
|
|
||||||
8.25 13 -7.25
|
|
||||||
3.75 13 -7.25
|
|
||||||
8 12 -7
|
|
||||||
4 12 -7
|
|
||||||
8 12 -3
|
|
||||||
8.25 13 -7.25
|
|
||||||
8.25 13 -2.75
|
|
||||||
8 12 -7
|
|
||||||
8 12 -7
|
|
||||||
8 12 -3
|
|
||||||
8.25 13 -7.25
|
|
||||||
8.25 13 -2.75
|
|
||||||
numsurf 16
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
0 0 0
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
1 0 0
|
|
||||||
0 0 0
|
|
||||||
3 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
4 0 0
|
|
||||||
5 0 0
|
|
||||||
6 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
7 0 0
|
|
||||||
6 0 0
|
|
||||||
5 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
8 0 0
|
|
||||||
9 0 0
|
|
||||||
10 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
9 0 0
|
|
||||||
8 0 0
|
|
||||||
11 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
12 0 0
|
|
||||||
13 0 0
|
|
||||||
14 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
15 0 0
|
|
||||||
14 0 0
|
|
||||||
13 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
16 0 0
|
|
||||||
17 0 0
|
|
||||||
18 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
17 0 0
|
|
||||||
16 0 0
|
|
||||||
19 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
20 0 0
|
|
||||||
21 0 0
|
|
||||||
22 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
23 0 0
|
|
||||||
22 0 0
|
|
||||||
21 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
24 0 0
|
|
||||||
25 0 0
|
|
||||||
26 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
25 0 0
|
|
||||||
24 0 0
|
|
||||||
27 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
28 0 0
|
|
||||||
29 0 0
|
|
||||||
30 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
31 0 0
|
|
||||||
30 0 0
|
|
||||||
29 0 0
|
|
||||||
kids 0
|
|
||||||
OBJECT poly
|
|
||||||
name "glass"
|
|
||||||
data 4
|
|
||||||
ID19
|
|
||||||
crease 40.0
|
|
||||||
numvert 32
|
|
||||||
3 16 -8
|
|
||||||
8.25 13 -7.25
|
|
||||||
3.75 13 -7.25
|
|
||||||
9 16 -8
|
|
||||||
9 16 -8
|
|
||||||
3 16 -8
|
|
||||||
8.25 13 -7.25
|
|
||||||
3.75 13 -7.25
|
|
||||||
8.25 13 -2.75
|
|
||||||
9 16 -8
|
|
||||||
9 16 -2
|
|
||||||
8.25 13 -7.25
|
|
||||||
8.25 13 -7.25
|
|
||||||
8.25 13 -2.75
|
|
||||||
9 16 -8
|
|
||||||
9 16 -2
|
|
||||||
3 16 -8
|
|
||||||
3.75 13 -2.75
|
|
||||||
3 16 -2
|
|
||||||
3.75 13 -7.25
|
|
||||||
3.75 13 -7.25
|
|
||||||
3 16 -8
|
|
||||||
3.75 13 -2.75
|
|
||||||
3 16 -2
|
|
||||||
9 16 -2
|
|
||||||
3.75 13 -2.75
|
|
||||||
8.25 13 -2.75
|
|
||||||
3 16 -2
|
|
||||||
3 16 -2
|
|
||||||
9 16 -2
|
|
||||||
3.75 13 -2.75
|
|
||||||
8.25 13 -2.75
|
|
||||||
numsurf 16
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
0 0 0
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
1 0 0
|
|
||||||
0 0 0
|
|
||||||
3 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
4 0 0
|
|
||||||
5 0 0
|
|
||||||
6 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
7 0 0
|
|
||||||
6 0 0
|
|
||||||
5 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
8 0 0
|
|
||||||
9 0 0
|
|
||||||
10 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
9 0 0
|
|
||||||
8 0 0
|
|
||||||
11 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
12 0 0
|
|
||||||
13 0 0
|
|
||||||
14 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
15 0 0
|
|
||||||
14 0 0
|
|
||||||
13 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
16 0 0
|
|
||||||
17 0 0
|
|
||||||
18 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
17 0 0
|
|
||||||
16 0 0
|
|
||||||
19 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
20 0 0
|
|
||||||
21 0 0
|
|
||||||
22 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
23 0 0
|
|
||||||
22 0 0
|
|
||||||
21 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
24 0 0
|
|
||||||
25 0 0
|
|
||||||
26 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
25 0 0
|
|
||||||
24 0 0
|
|
||||||
27 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
28 0 0
|
|
||||||
29 0 0
|
|
||||||
30 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 2
|
|
||||||
refs 3
|
|
||||||
31 0 0
|
|
||||||
30 0 0
|
|
||||||
29 0 0
|
|
||||||
kids 0
|
|
||||||
OBJECT poly
|
|
||||||
name "roof"
|
|
||||||
data 4
|
|
||||||
ID27
|
|
||||||
crease 40.0
|
|
||||||
numvert 4
|
|
||||||
9 16 -2
|
|
||||||
3 16 -8
|
|
||||||
3 16 -2
|
|
||||||
9 16 -8
|
|
||||||
numsurf 2
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
0 0 0
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
1 0 0
|
|
||||||
0 0 0
|
|
||||||
3 0 0
|
|
||||||
kids 0
|
|
||||||
OBJECT poly
|
|
||||||
name "structure"
|
|
||||||
data 3
|
|
||||||
ID3
|
|
||||||
crease 40.0
|
|
||||||
numvert 48
|
|
||||||
8 0 -7
|
|
||||||
0 0 0
|
|
||||||
0 0 -7
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
8 0 0
|
|
||||||
8 3 0
|
|
||||||
2 0 0
|
|
||||||
8 0 0
|
|
||||||
2 2 0
|
|
||||||
1 2 0
|
|
||||||
0 0 0
|
|
||||||
1 0 0
|
|
||||||
0 3 0
|
|
||||||
0 3 -7
|
|
||||||
0 0 0
|
|
||||||
0 3 0
|
|
||||||
0 0 -7
|
|
||||||
0 3 -7
|
|
||||||
8 0 -7
|
|
||||||
0 0 -7
|
|
||||||
4 3 -7
|
|
||||||
8 12 -7
|
|
||||||
4 12 -7
|
|
||||||
8 0 -7
|
|
||||||
8 3 0
|
|
||||||
8 0 0
|
|
||||||
8 3 -3
|
|
||||||
8 12 -3
|
|
||||||
8 12 -7
|
|
||||||
0 3 0
|
|
||||||
4 3 -3
|
|
||||||
0 3 -7
|
|
||||||
8 3 0
|
|
||||||
8 3 -3
|
|
||||||
4 3 -7
|
|
||||||
4 12 -7
|
|
||||||
4 3 -3
|
|
||||||
4 12 -3
|
|
||||||
4 3 -7
|
|
||||||
8 12 -3
|
|
||||||
4 12 -7
|
|
||||||
4 12 -3
|
|
||||||
8 12 -7
|
|
||||||
8 12 -3
|
|
||||||
4 3 -3
|
|
||||||
8 3 -3
|
|
||||||
4 12 -3
|
|
||||||
numsurf 30
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
0 0 0
|
|
||||||
1 0 0
|
|
||||||
2 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
1 0 0
|
|
||||||
0 0 0
|
|
||||||
3 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
3 0 0
|
|
||||||
0 0 0
|
|
||||||
4 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
4 0 0
|
|
||||||
0 0 0
|
|
||||||
5 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
6 0 0
|
|
||||||
7 0 0
|
|
||||||
8 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
7 0 0
|
|
||||||
6 0 0
|
|
||||||
9 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
9 0 0
|
|
||||||
6 0 0
|
|
||||||
10 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
10 0 0
|
|
||||||
11 0 0
|
|
||||||
12 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
11 0 0
|
|
||||||
10 0 0
|
|
||||||
13 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
13 0 0
|
|
||||||
10 0 0
|
|
||||||
6 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
14 0 0
|
|
||||||
15 0 0
|
|
||||||
16 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
15 0 0
|
|
||||||
14 0 0
|
|
||||||
17 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
18 0 0
|
|
||||||
19 0 0
|
|
||||||
20 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
19 0 0
|
|
||||||
18 0 0
|
|
||||||
21 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
19 0 0
|
|
||||||
21 0 0
|
|
||||||
22 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
22 0 0
|
|
||||||
21 0 0
|
|
||||||
23 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
24 0 0
|
|
||||||
25 0 0
|
|
||||||
26 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
25 0 0
|
|
||||||
24 0 0
|
|
||||||
27 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
27 0 0
|
|
||||||
24 0 0
|
|
||||||
28 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
28 0 0
|
|
||||||
24 0 0
|
|
||||||
29 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
30 0 0
|
|
||||||
31 0 0
|
|
||||||
32 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
31 0 0
|
|
||||||
30 0 0
|
|
||||||
33 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
31 0 0
|
|
||||||
33 0 0
|
|
||||||
34 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
35 0 0
|
|
||||||
32 0 0
|
|
||||||
31 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
36 0 0
|
|
||||||
37 0 0
|
|
||||||
38 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
37 0 0
|
|
||||||
36 0 0
|
|
||||||
39 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
40 0 0
|
|
||||||
41 0 0
|
|
||||||
42 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
41 0 0
|
|
||||||
40 0 0
|
|
||||||
43 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
44 0 0
|
|
||||||
45 0 0
|
|
||||||
46 0 0
|
|
||||||
SURF 0X10
|
|
||||||
mat 1
|
|
||||||
refs 3
|
|
||||||
45 0 0
|
|
||||||
44 0 0
|
|
||||||
47 0 0
|
|
||||||
kids 0
|
|
@ -1,126 +0,0 @@
|
|||||||
var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
|
|
||||||
|
|
||||||
var TRUE = 1;
|
|
||||||
var FALSE = 0;
|
|
||||||
|
|
||||||
#
|
|
||||||
# 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 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
|
|
||||||
" 7.62 hit": 0.30, #UH-1
|
|
||||||
" 50 BMG hit": 0.20, #p-47
|
|
||||||
};
|
|
||||||
|
|
||||||
var players = {
|
|
||||||
"pinto": 1,
|
|
||||||
"OPFOR77": 2,
|
|
||||||
"Leto": 1,
|
|
||||||
"swamp": 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
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");
|
|
||||||
if (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 (cannon_types[last_vector[1]] != nil) {
|
|
||||||
# cannon hitting someone
|
|
||||||
print("cannon");
|
|
||||||
if (size(last_vector) > 2 and last_vector[2] == " "~callsign) {
|
|
||||||
print("cannon hit us");
|
|
||||||
process_hit(author);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var last_update_time = "/aa_tower/last-update-time";
|
|
||||||
var owning_team = "/aa_tower/owning_team";
|
|
||||||
var score_team_1 = "/aa_tower/score-team-1";
|
|
||||||
var score_team_2 = "/aa_tower/score-team-2";
|
|
||||||
setprop(last_update_time, -1);
|
|
||||||
setprop(owning_team, 0);
|
|
||||||
setprop(score_team_1, 0);
|
|
||||||
setprop(score_team_2, 0);
|
|
||||||
|
|
||||||
var process_hit = func (perp) {
|
|
||||||
print("processing hit by: " ~ perp);
|
|
||||||
if ( players[perp] != nil ) {
|
|
||||||
if ( players[perp] != getprop(owning_team) ) {
|
|
||||||
setprop(last_update_time,systime());
|
|
||||||
setprop(owning_team, players[perp]);
|
|
||||||
setprop("/aa_tower/score-team-" ~ players[perp], getprop("/aa_tower/score-team-" ~ players[perp]) + 1);
|
|
||||||
setprop("/sim/multiplay/chat","Ownership transferred to team: " ~ players[perp]);
|
|
||||||
write_xml();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var update = func () {
|
|
||||||
var o_t = getprop(owning_team);
|
|
||||||
if(o_t > 0) {
|
|
||||||
if(systime() > getprop(last_update_time) + 300) {
|
|
||||||
print("Adding point to team: " ~ o_t);
|
|
||||||
setprop("/sim/multiplay/chat","Adding point to team: " ~ o_t);
|
|
||||||
setprop("/aa_tower/score-team-" ~ o_t, getprop("/aa_tower/score-team-" ~ o_t) + 1);
|
|
||||||
setprop(last_update_time, systime());
|
|
||||||
write_xml();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settimer(func(){update();},10);
|
|
||||||
}
|
|
||||||
|
|
||||||
update();
|
|
||||||
|
|
||||||
var twr_base = "/aa_tower/";
|
|
||||||
var filename_base = getprop("/sim/fg-home") ~ "/Export/tower-";
|
|
||||||
var write_xml = func() {
|
|
||||||
io.write_properties( path: filename_base ~ rand() ~ ".xml", prop: twr_base );
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
|
|
||||||
setlistener("/sim/multiplay/chat-history", incoming_listener, 0, 0);
|
|
@ -1,44 +0,0 @@
|
|||||||
# Copyright (C) 2015 onox
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#io.include("Aircraft/ExpansionPack/Nasal/init.nas");
|
|
||||||
|
|
||||||
#with("updateloop");
|
|
||||||
|
|
||||||
# Number of iterations per second
|
|
||||||
var frequency = 60.0;
|
|
||||||
|
|
||||||
# Change in heading per second at full rudder deflection
|
|
||||||
var heading_ps = 0.5;
|
|
||||||
|
|
||||||
time_last = 0;
|
|
||||||
sim_speed = 1;
|
|
||||||
|
|
||||||
setprop("/carrier/pitch-deg",0);
|
|
||||||
setprop("/carrier/pitch-offset",0);
|
|
||||||
setprop("/carrier/roll-deg",0);
|
|
||||||
setprop("/carrier/roll-offset",0);
|
|
||||||
setprop("/carrier/sunk",0);
|
|
||||||
|
|
||||||
var PositionUpdater = func () {
|
|
||||||
|
|
||||||
# does a building need an FDM?
|
|
||||||
# nawwwwwww
|
|
||||||
|
|
||||||
settimer( PositionUpdater, 1/frequency );
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
PositionUpdater();
|
|
@ -1,125 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2015 onox
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<PropertyList>
|
|
||||||
|
|
||||||
<environment>
|
|
||||||
<in-to-wind type="bool">false</in-to-wind>
|
|
||||||
</environment>
|
|
||||||
|
|
||||||
<carrier>
|
|
||||||
<fdm>
|
|
||||||
<settings>
|
|
||||||
<!-- The maximum bank angle during full rudder deflection -->
|
|
||||||
<bank-limit type="double">15.0</bank-limit>
|
|
||||||
|
|
||||||
<!-- Frequency and overshoot of the oscillator used to
|
|
||||||
simulate heeling (roll).
|
|
||||||
-->
|
|
||||||
<heel-frequency type="double">0.5</heel-frequency>
|
|
||||||
<heel-overshoot type="double">4.0</heel-overshoot>
|
|
||||||
|
|
||||||
<!-- Frequency and overshoot of the oscillator used to
|
|
||||||
simulate trimming (pitch).
|
|
||||||
-->
|
|
||||||
<trim-frequency type="double">0.32</trim-frequency>
|
|
||||||
<trim-overshoot type="double">0.45</trim-overshoot>
|
|
||||||
|
|
||||||
<!-- The speed of the waves plus speed of the ship in knots
|
|
||||||
which generates the maximum overshoot of the trim
|
|
||||||
oscillation.
|
|
||||||
-->
|
|
||||||
<max-trim-oscillation-wave-kt type="double">30.0</max-trim-oscillation-wave-kt>
|
|
||||||
|
|
||||||
<!-- The speed of the waves in knots which generates the
|
|
||||||
maximum overshoot of the heel oscillation.
|
|
||||||
-->
|
|
||||||
<max-heel-oscillation-wave-kt type="double">20.0</max-heel-oscillation-wave-kt>
|
|
||||||
|
|
||||||
<movement type="bool">true</movement>
|
|
||||||
</settings>
|
|
||||||
</fdm>
|
|
||||||
</carrier>
|
|
||||||
|
|
||||||
<sim>
|
|
||||||
<author>pinto</author>
|
|
||||||
<description>tower</description>
|
|
||||||
<status>alpha</status>
|
|
||||||
<aircraft-version>0.1</aircraft-version>
|
|
||||||
|
|
||||||
<flight-model>null</flight-model>
|
|
||||||
|
|
||||||
<aero>KPN-D</aero>
|
|
||||||
<aircraft-operator>KPN</aircraft-operator>
|
|
||||||
|
|
||||||
<model>
|
|
||||||
<path>Aircraft/tower/Models/tower.xml</path>
|
|
||||||
|
|
||||||
<!-- Uncloak weather balloons visiting Earth -->
|
|
||||||
<always-show-in-MP type="bool">true</always-show-in-MP>
|
|
||||||
</model>
|
|
||||||
|
|
||||||
<sound>
|
|
||||||
<path>Sounds/sound.xml</path>
|
|
||||||
</sound>
|
|
||||||
|
|
||||||
<presets>
|
|
||||||
<onground>true</onground>
|
|
||||||
</presets>
|
|
||||||
|
|
||||||
<startup>
|
|
||||||
<splash-texture>Aircraft/tower/splash1.png</splash-texture>
|
|
||||||
</startup>
|
|
||||||
|
|
||||||
<current-view>
|
|
||||||
<deck-park type="bool">true</deck-park>
|
|
||||||
|
|
||||||
<z-offset-dec-step type="double">0.0</z-offset-dec-step>
|
|
||||||
<z-offset-inc-step type="double">0.0</z-offset-inc-step>
|
|
||||||
<can-change-z-offset type="bool">false</can-change-z-offset>
|
|
||||||
|
|
||||||
<z-offset-min-m type="float">100.0</z-offset-min-m>
|
|
||||||
<z-offset-max-m type="float">2000.0</z-offset-max-m>
|
|
||||||
</current-view>
|
|
||||||
|
|
||||||
<systems>
|
|
||||||
<autopilot>
|
|
||||||
<path>Systems/fbw.xml</path>
|
|
||||||
</autopilot>
|
|
||||||
<autopilot>
|
|
||||||
<path>Systems/fdm.xml</path>
|
|
||||||
</autopilot>
|
|
||||||
</systems>
|
|
||||||
<multiplay>
|
|
||||||
<generic>
|
|
||||||
<int n="0" type="int">0</int>
|
|
||||||
</generic>
|
|
||||||
</multiplay>
|
|
||||||
</sim>
|
|
||||||
|
|
||||||
<nasal>
|
|
||||||
<carrier>
|
|
||||||
<file>Aircraft/tower/Nasal/fdm.nas</file>
|
|
||||||
</carrier>
|
|
||||||
<damage>
|
|
||||||
<file>Aircraft/tower/Nasal/damage.nas</file>
|
|
||||||
</damage>
|
|
||||||
</nasal>
|
|
||||||
|
|
||||||
</PropertyList>
|
|
Loading…
Reference in New Issue
Block a user