mirror of
https://github.com/l0k1/oprf_assets.git
synced 2024-11-01 07:41:15 +08:00
Add GCI code to frigate
This commit is contained in:
parent
75a3133d83
commit
bc03e36559
@ -317,6 +317,9 @@
|
||||
<damage>
|
||||
<file>Aircraft/Frigate/Nasal/damage.nas</file>
|
||||
</damage>
|
||||
<gci>
|
||||
<file>Aircraft/Frigate/Nasal/gci.nas</file>
|
||||
</gci>
|
||||
</nasal>
|
||||
|
||||
<input>
|
||||
|
@ -14,7 +14,7 @@
|
||||
</placer>
|
||||
|
||||
<offsets>
|
||||
<x-m>7</x-m>
|
||||
<x-m>0</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
</offsets>
|
||||
@ -50,30 +50,30 @@
|
||||
<particle>
|
||||
<start>
|
||||
<color>
|
||||
<red><value> 0.4 </value></red>
|
||||
<green><value> 0.5 </value></green>
|
||||
<blue><value> 0.5 </value></blue>
|
||||
<alpha><value> 0.5 </value></alpha>
|
||||
<red><value> 0.9 </value></red>
|
||||
<green><value> 1 </value></green>
|
||||
<blue><value> 1 </value></blue>
|
||||
<alpha><value> 0.75 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>1.0</value>
|
||||
<value>0.25</value>
|
||||
</size>
|
||||
</start>
|
||||
|
||||
<end>
|
||||
<color>
|
||||
<red><value> 0.4 </value></red>
|
||||
<green><value> 0.5 </value></green>
|
||||
<blue><value> 0.5 </value></blue>
|
||||
<red><value> 0.9 </value></red>
|
||||
<green><value> 1 </value></green>
|
||||
<blue><value> 1 </value></blue>
|
||||
<alpha><value> 0.1 </value></alpha>
|
||||
</color>
|
||||
<size>
|
||||
<value>6</value>
|
||||
<value>16</value>
|
||||
</size>
|
||||
</end>
|
||||
|
||||
<life-sec>
|
||||
<value>4</value>
|
||||
<value>16</value>
|
||||
</life-sec>
|
||||
|
||||
<mass-kg> 0.5 </mass-kg>
|
||||
|
@ -81,6 +81,7 @@ var incoming_listener = func {
|
||||
var last_vector = split(":", last);
|
||||
var author = last_vector[0];
|
||||
var callsign = getprop("sim/multiplay/callsign");
|
||||
callsign = size(callsign) < 8 ? callsign : left(callsign,7);
|
||||
if (size(last_vector) > 1 and author != callsign) {
|
||||
# not myself
|
||||
#print("not me");
|
||||
@ -197,6 +198,11 @@ var incoming_listener = func {
|
||||
print("cannon");
|
||||
if (size(last_vector) > 2 and last_vector[2] == " "~callsign) {
|
||||
print("cannon hit us");
|
||||
if (size(last_vector) < 4) {
|
||||
# msg is either missing number of hits, or has no trailing dots from spam filter.
|
||||
print('"'~last~'" is not a legal hit message, tell the shooter to upgrade his OPRF plane :)');
|
||||
return;
|
||||
}
|
||||
var last3 = split(" ", last_vector[3]);
|
||||
#print("last3[2]: " ~ last3[2]);
|
||||
#print("last3[1]: " ~ last3[1]);
|
||||
@ -211,12 +217,12 @@ var incoming_listener = func {
|
||||
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;
|
||||
#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);
|
||||
#printf("Took %.1f%% damage from cannon! %s systems was hit.", probability*hit_count*100, damaged_sys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,11 +36,20 @@ setprop("/carrier/roll-deg",0);
|
||||
setprop("/carrier/roll-offset",0);
|
||||
setprop("/carrier/sunk",0);
|
||||
|
||||
var arrived = 0;
|
||||
|
||||
var PositionUpdater = func () {
|
||||
|
||||
settimer( PositionUpdater, 1/frequency );
|
||||
|
||||
|
||||
var position = geo.aircraft_position();
|
||||
|
||||
if ( arrived == 0 and getprop("/carrier/sunk") == 0 and getprop("/autopilot/route-manager/wp-last/dist") != nil and getprop("/autopilot/route-manager/wp-last/dist") < 1 ) {
|
||||
setprop("/sim/multiplay/chat",getprop("sim/multiplay/callsign") ~ " has arrived safely!");
|
||||
print("arrived");
|
||||
arrived = 1;
|
||||
#return;
|
||||
}
|
||||
|
||||
var time_now = getprop("/sim/time/elapsed-sec");
|
||||
var dt = (time_now - time_last) * sim_speed;
|
||||
@ -91,6 +100,8 @@ var PositionUpdater = func () {
|
||||
setprop("/position/altitude-ft",getprop("/position/altitude-ft") - ( sink_rate ));
|
||||
setprop("/carrier/pitch-offset",getprop("/carrier/pitch-offset") + ( pitch_rate ));
|
||||
setprop("/carrier/roll-offset",getprop("/carrier/roll-offset") + ( roll_rate ));
|
||||
|
||||
print("sunk");
|
||||
}
|
||||
|
||||
#set pitch
|
||||
|
499
Frigate/Nasal/gci.nas
Normal file
499
Frigate/Nasal/gci.nas
Normal file
@ -0,0 +1,499 @@
|
||||
# (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();
|
Loading…
Reference in New Issue
Block a user