1
0
Fork 0

Add additional runway selection so the runway in use doesn't change as you roll past mid-point. Also fix possible bug for north-south runways.

This commit is contained in:
stuart 2008-05-03 19:46:47 +00:00
parent 7513200f8e
commit b6b4b5fe77

View file

@ -48,7 +48,7 @@
</color> </color>
</text> </text>
<text> <text>
<halign>left</halign> <halign>left</halign>
<property>/sim/multiplay/chat-menu/entry[1]</property> <property>/sim/multiplay/chat-menu/entry[1]</property>
<live>true</live> <live>true</live>
<color> <color>
@ -130,7 +130,7 @@
<![CDATA[ <![CDATA[
var text = ""; var text = "";
var topNode = "/sim/multiplay/chat-menu/config"; var topNode = "/sim/multiplay/chat-menu/config";
setprop("/sim/multiplay/chat-menu/entry", "1"); setprop("/sim/multiplay/chat-menu/entry", "1");
setprop("/sim/multiplay/chat-menu/entry[1]", "2"); setprop("/sim/multiplay/chat-menu/entry[1]", "2");
setprop("/sim/multiplay/chat-menu/entry[2]", "3"); setprop("/sim/multiplay/chat-menu/entry[2]", "3");
@ -141,18 +141,17 @@
setprop("/sim/multiplay/chat-menu/entry[7]", "8"); setprop("/sim/multiplay/chat-menu/entry[7]", "8");
setprop("/sim/multiplay/chat-menu/entry[8]", "9"); setprop("/sim/multiplay/chat-menu/entry[8]", "9");
setprop("/sim/multiplay/chat-menu/entry[9]", "0"); setprop("/sim/multiplay/chat-menu/entry[9]", "0");
# Get the conversation tree. # Get the conversation tree.
var entryNodes = props.globals.getNode("/sim/multiplay/chat-menu").getChildren("entry"); var entryNodes = props.globals.getNode("/sim/multiplay/chat-menu").getChildren("entry");
var pos = props.globals.getNode(topNode); var pos = props.globals.getNode(topNode);
# Get various substitution values. # Get various substitution values.
var callsign = getprop("/sim/multiplay/callsign"); var callsign = getprop("/sim/multiplay/callsign");
# Simple rounding of altitude to 100 ft. # Simple rounding of altitude to 100 ft.
var altitude = int(getprop("/position/altitude-ft")/100) * 100; var altitude = int(getprop("/position/altitude-ft")/100) * 100;
var type = getprop("/sim/description"); var type = getprop("/sim/description");
if (type != "") if (type != "")
{ {
@ -163,7 +162,7 @@
# Get the nearest airport. # Get the nearest airport.
var airport = airportinfo(); var airport = airportinfo();
# Get the complement of each runway to create a full set. # Get the complement of each runway to create a full set.
foreach (var rwy; keys(airport.runways)) { foreach (var rwy; keys(airport.runways)) {
if (!string.isdigit(rwy[0])) if (!string.isdigit(rwy[0]))
@ -177,54 +176,74 @@
width: r.width, heading: math.mod(r.heading + 180, 360), width: r.width, heading: math.mod(r.heading + 180, 360),
threshold1: r.threshold2, threshold1: r.threshold2,
}; };
} }
# Determine the active runway. We have two ways to do this: # Determine the active runway. We have two ways to do this:
# - If the aircraft is on the ground (or very close to it), we'll try to determine # - If the aircraft is on the ground (or very close to it), we'll try to determine
# the runway it is closest to. # the runway it is closest to, and facing the correct direction for.
# - If the aircraft is in the air, we'll work out the active runway based on the wind. # - If the aircraft is in the air, we'll work out the active runway based on the wind.
var active_runway = ""; var active_runway = "";
var on_ground = (getprop("/position/altitude-agl-ft") < 100); var on_ground = (getprop("/position/altitude-agl-ft") < 100);
if (on_ground) if (on_ground)
{ {
# To find out the closest runway to the aircrafts position, we'll look at the heading # To find out the closest runway to the aircrafts position, we'll look at the heading
# required to go from the aircraft's current position to the center of each runway. # required to go from the aircraft's current position to the center of each runway.
# The closer this is to the runways real heading, the more likely this is the runway # The closer this is to the runways real heading, the more likely this is the runway
# we're on. Note that we can't rely on /sim/atc/runway, as this is only set on # we're on. Note that we can't rely on /sim/atc/runway, as this is only set on
# initialization. # initialization.
var max = 360; var max = 360;
var loc = geo.aircraft_position(); var loc = geo.aircraft_position();
foreach (var r; keys(airport.runways)) { foreach (var r; keys(airport.runways)) {
var curr = airport.runways[r]; var curr = airport.runways[r];
var p = geo.Coord.new(); var p = geo.Coord.new();
p.set_latlon(curr.lat, curr.lon, airport.elevation); p.set_latlon(curr.lat, curr.lon, airport.elevation);
var course = loc.course_to(p); var course = loc.course_to(p) - curr.heading;
var deviation = math.abs(course - curr.heading); while (course >= 180) course -= 360;
while (course < -180) course += 360;
var deviation = math.abs(course);
if (deviation < max) if (deviation < max)
{ {
active_runway = r; active_runway = r;
max = deviation; max = deviation;
} }
} }
# It may be the case that we're taxiing down the runway, past the mid-point.
# If the aircraft is facing the "wrong" way for this runway, then take the
# reciprocal runway.
var heading = getprop("/orientation/heading-magnetic-deg");
var deviation = heading - airport.runways[active_runway].heading;
while (deviation >= 180) deviation -= 360;
while (deviation < -180) deviation += 360;
deviation = math.abs(deviation);
if (deviation > 90)
{
var number = math.mod(num(substr(active_runway, 0, 2)) + 18, 36);
var side = substr(active_runway, 2, 1);
active_runway = sprintf("%02d%s", number, side == "R" ? "L" : side == "L" ? "R" : side);
}
} }
else else
{ {
var wind_speed = getprop("/environment/wind-speed-kt"); var wind_speed = getprop("/environment/wind-speed-kt");
var wind_from = wind_speed ? getprop("/environment/wind-from-heading-deg") : 270; var wind_from = wind_speed ? getprop("/environment/wind-from-heading-deg") : 270;
var max = -1; var max = -1;
foreach (var r; keys(airport.runways)) { foreach (var r; keys(airport.runways)) {
var curr = airport.runways[r]; var curr = airport.runways[r];
var wind = wind_from - curr.heading; var wind = wind_from - curr.heading;
while (wind >= 180) wind -= 360; while (wind >= 180) wind -= 360;
while (wind < -180) wind += 360; while (wind < -180) wind += 360;
var deviation = math.abs(wind) + 1e-20; var deviation = math.abs(wind) + 1e-20;
var v = (0.01 * curr.length + 0.01 * curr.width) / deviation; var v = (0.01 * curr.length + 0.01 * curr.width) / deviation;
@ -232,23 +251,23 @@
max = v; max = v;
active_runway = r; active_runway = r;
} }
} }
} }
# Find our distance and cardinal direction to the airport. # Find our distance and cardinal direction to the airport.
var directions = split(",", "North,North East,East,South East,South,South West,West,North West"); var directions = split(",", "North,North East,East,South East,South,South West,West,North West");
var loc = geo.aircraft_position(); var loc = geo.aircraft_position();
var airportloc = geo.Coord.new(); var airportloc = geo.Coord.new();
airportloc.set_latlon(airport.lat, airport.lon, airport.elevation); airportloc.set_latlon(airport.lat, airport.lon, airport.elevation);
# We want the course _from_ the airport to the aircraft - for reporting ".. approaching from the SW" # We want the course _from_ the airport to the aircraft - for reporting ".. approaching from the SW"
var airport_course = airportloc.course_to(loc); var airport_course = airportloc.course_to(loc);
var airport_distance = int((airportloc.distance_to(loc) / 1609) + 0.5); var airport_distance = int((airportloc.distance_to(loc) / 1609) + 0.5);
# Get an index into our array of directions. # Get an index into our array of directions.
var dir = int(math.mod((airport_course + 22.5), 360) / 45); var dir = int(math.mod((airport_course + 22.5), 360) / 45);
var airport_direction = directions[dir]; var airport_direction = directions[dir];
# Now launch the keyboard listener. # Now launch the keyboard listener.
var kbdevent = setlistener("/devices/status/keyboard/event", func (event) { var kbdevent = setlistener("/devices/status/keyboard/event", func (event) {
@ -257,58 +276,58 @@
return; return;
var key = event.getNode("key"); var key = event.getNode("key");
if (handle_key(key.getValue())) if (handle_key(key.getValue()))
key.setValue(-1); # drop key event key.setValue(-1); # drop key event
}); });
var handle_key = func (key) { var handle_key = func (key) {
# We only handle keys 0-9 and Esc # We only handle keys 0-9 and Esc
if (key == 27) if (key == 27)
{ {
# escape -> cancel # escape -> cancel
removelistener(kbdevent); removelistener(kbdevent);
gui.popdown(); gui.popdown();
fgcommand("dialog-close", props.Node.new({"dialog-name": "chat-menu"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "chat-menu"}));
return 1; return 1;
} }
if ((key < `0`) or (key > `9`)) if ((key < `0`) or (key > `9`))
{ {
# pass the event back. # pass the event back.
return 0; return 0;
} }
if (key == `0`) if (key == `0`)
{ {
# Go back one level. # Go back one level.
text = ""; text = "";
if (pos.getName() != "config") if (pos.getName() != "config")
{ {
# Build up the chat string again. # Build up the chat string again.
pos = pos.getParent(); pos = pos.getParent();
var p = pos; var p = pos;
while ((p.getName() != "config") and while ((p.getName() != "config") and
(p.getChild("name").getValue() != nil)) (p.getChild("name").getValue() != nil))
{ {
var t = string.trim(p.getChild("name").getValue()); var t = string.trim(p.getChild("name").getValue());
# Entries that begin with "[" are silent. # Entries that begin with "[" are silent.
if (t[0] != `[`) if (t[0] != `[`)
{ {
text = t ~ " " ~ text; text = t ~ " " ~ text;
} }
p = p.getParent(); p = p.getParent();
} }
} }
updateDialog(); updateDialog();
} }
if (key == `1`) if (key == `1`)
{ {
# Go to edit mode using the inline editor. # Go to edit mode using the inline editor.
@ -317,18 +336,18 @@
multiplayer.compose_message(text); multiplayer.compose_message(text);
fgcommand("dialog-close", props.Node.new({"dialog-name": "chat-menu"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "chat-menu"}));
} }
if ((key > `1`) and (key <= `9`)) if ((key > `1`) and (key <= `9`))
{ {
# Select the appropriate new node and update. # Select the appropriate new node and update.
# The index starts from position 2. # The index starts from position 2.
var i = key - `2`; var i = key - `2`;
if (i > (size(pos.getChildren("menu")) -1)) if (i > (size(pos.getChildren("menu")) -1))
{ {
# Drop out if the user has entered a too large value. # Drop out if the user has entered a too large value.
return 0; return 0;
} }
var t = entryNodes[i].getValue(); var t = entryNodes[i].getValue();
@ -351,16 +370,16 @@
fgcommand("dialog-close", props.Node.new({"dialog-name": "chat-menu"})); fgcommand("dialog-close", props.Node.new({"dialog-name": "chat-menu"}));
} }
else else
{ {
# We've got more tree to traverse. # We've got more tree to traverse.
updateDialog(); updateDialog();
} }
} }
# If we got here, we consumed the event # If we got here, we consumed the event
return 1; return 1;
} }
# Substitute simple values into the string. # Substitute simple values into the string.
# The values we handle are # The values we handle are
# #
@ -373,47 +392,47 @@
# #
var subvals = func (str) { var subvals = func (str) {
var t = ""; var t = "";
for (var p = 0; p < size(str); p += 1) for (var p = 0; p < size(str); p += 1)
{ {
if (str[p] == `!`) t ~= airport_direction; if (str[p] == `!`) t ~= airport_direction;
elsif (str[p] == `^`) t ~= airport_distance; elsif (str[p] == `^`) t ~= airport_distance;
elsif (str[p] == `(`) t ~= active_runway; elsif (str[p] == `(`) t ~= active_runway;
elsif (str[p] == `*`) t ~= airport.name; elsif (str[p] == `*`) t ~= airport.name;
elsif (str[p] == `%`) t ~= type; elsif (str[p] == `%`) t ~= type;
elsif (str[p] == `#`) t ~= callsign; elsif (str[p] == `#`) t ~= callsign;
elsif (str[p] == `$`) t ~= altitude; elsif (str[p] == `$`) t ~= altitude;
else t ~= chr(str[p]); else t ~= chr(str[p]);
} }
return t; return t;
} }
var updateDialog = func { var updateDialog = func {
var children = pos.getChildren("menu"); var children = pos.getChildren("menu");
var i = 0; var i = 0;
foreach(var c; children) foreach(var c; children)
{ {
var p = i + 2; var p = i + 2;
var txt = p ~ ': ' ~ subvals(c.getChild("name").getValue()); var txt = p ~ ': ' ~ subvals(c.getChild("name").getValue());
if (i < 9) if (i < 9)
{ {
entryNodes[i].setValue(txt); entryNodes[i].setValue(txt);
} }
i = i + 1; i = i + 1;
} }
# Set the rest of the dialog to blank. # Set the rest of the dialog to blank.
while (i <= 9) while (i <= 9)
{ {
entryNodes[i].setValue(""); entryNodes[i].setValue("");
i = i + 1; i = i + 1;
} }
# Write the popup. # Write the popup.
gui.popupTip(text, 1000000); gui.popupTip(text, 1000000);
} }
# Start by updating the dialog. # Start by updating the dialog.