--- a/src/aircraft_cmd.cpp Mon Aug 13 09:21:57 2007 +0000
+++ b/src/aircraft_cmd.cpp Mon Aug 13 20:01:30 2007 +0000
@@ -67,8 +67,8 @@
static bool AirportMove(Vehicle *v, const AirportFTAClass *apc);
static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *apc);
static bool AirportHasBlock(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *apc);
-static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *apc);
-static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc);
+static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *apc, const AirportFTA *current);
+static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc, const AirportFTA *current);
static void CrashAirplane(Vehicle *v);
static void AircraftNextAirportPos_and_Order(Vehicle *v);
@@ -425,7 +425,6 @@
assert(i != apc->nof_depots); //asserts if depot not found
if (st->airport_tile + ToTileIndexDiff(depots) == tile) {
- assert(apc->layout[i].heading == HANGAR);
/* adjust all the initial position data by the orientation of the airport */
AirportMovingData amd = RotateAMDbyOrientation(*apc->MovingData(i), st->fsmportsspeclist[1].spec->size_x[st->FSMport_layout_set],
@@ -1632,9 +1631,9 @@
/* FindFreeTerminal:
* 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */
if (v->subtype == AIR_HELICOPTER) {
- if (!AirportFindFreeHelipad(v, apc)) return; // helicopter
+ if (!AirportFindFreeHelipad(v, apc, NULL)) return; // helicopter
} else {
- if (!AirportFindFreeTerminal(v, apc)) return; // airplane
+ if (!AirportFindFreeTerminal(v, apc, NULL)) return; // airplane
}
} else { // Else prepare for launch.
/* airplane goto state takeoff, helicopter to helitakeoff */
@@ -1829,9 +1828,9 @@
//if present, select terminal using that instruction, checking blocks first
//if not, continue with these default actions
- if (AirportFindFreeTerminal(v, apc)) return;
+ if (AirportFindFreeTerminal(v, apc, &apc->layout[v->u.air.pos])) return;
}
- v->u.air.state = HANGAR;
+ v->u.air.state = (apc->nof_depots != 0) ? HANGAR : TAKEOFF;
}
@@ -1848,7 +1847,7 @@
* the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes
* must go to a hangar. */
if (v->current_order.type == OT_GOTO_STATION) {
- if (AirportFindFreeHelipad(v, apc)) return;
+ if (AirportFindFreeHelipad(v, apc, NULL)) return;
}
v->u.air.state = (apc->nof_depots != 0) ? HANGAR : HELITAKEOFF;
}
@@ -1949,9 +1948,31 @@
/* there are choices to choose from, choose the one that
* matches our heading */
do {
- if (v->u.air.state == current->heading || current->heading == TO_ALL) {
+ if (v->u.air.state == current->heading || current->heading == TO_ALL || (current->heading >= 0x7B && current->heading <= 0x7E)) {
if (st->airport_flags.BlocksAreFree(¤t->reserveblock) || //if can reserve blocks
- v->u.air.owned_blocks.HasBlocks(¤t->reserveblock)) { //or vehicle already has blocks
+ v->u.air.owned_blocks.CanReserveBlocks(¤t->reserveblock, &st->airport_flags)) { //or vehicle already has blocks
+
+ /* handle special commands */
+ if (current->heading == 0x7B) { //force change of heading
+ v->u.air.state = current->special;
+ }
+ if (current->heading == 0x7D) { //choose helipad
+ if (v->current_order.type == OT_GOTO_STATION) {
+ if (!AirportFindFreeHelipad(v, apc, current)) {
+ current = current->next;
+ continue;
+ }
+ }
+ }
+ if (current->heading == 0x7E) { //choose terminal
+ if (v->current_order.type == OT_GOTO_STATION) {
+ if (!AirportFindFreeTerminal(v, apc, current)) {
+ current = current->next;
+ continue;
+ }
+ }
+ }
+
/* release blocks on airport */
v->u.air.owned_blocks.ReleaseBlocks(¤t->releaseblock);
st->airport_flags.ReleaseBlocks(¤t->releaseblock);
@@ -2024,7 +2045,7 @@
return num;
}
-static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *apc)
+static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *apc, const AirportFTA *current)
{
/* example of more terminalgroups
* {0,HANGAR,NOTHING_block,1}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER_block,1}, {0,0,N,1},
@@ -2038,28 +2059,29 @@
*/
if (apc->terminals[0] > 1) {
Station *st = GetStation(v->u.air.targetairport);
- AirportFTA *temp = apc->layout[v->u.air.pos].next;
-
- while (temp != NULL) {
- if (temp->heading == 0x7E) {
- if (!st->airport_flags.HasBlocks(&temp->reserveblock)) {
- /* read which group do we want to go to?
- * (the first free group) */
- uint target_group = temp->next_position + 1;
- /* at what terminal does the group start?
- * that means, sum up all terminals of
- * groups with lower number */
- uint group_start = 0;
- for (uint i = 1; i < target_group; i++) {
- group_start += apc->terminals[i];
- }
+ /* forget any existing terminal reservations the aircraft has */
+ st->airport_flags.ReleaseLowerBlocks(&v->u.air.owned_blocks);
+ v->u.air.owned_blocks.ReleaseLowerBlocks(&v->u.air.owned_blocks);
- uint group_end = group_start + apc->terminals[target_group];
- if (FreeTerminal(v, group_start + 1, group_end)) return true;
- }
+ if (current == NULL) {
+ /* choose from any terminal, no block restrictions */
+ return FreeTerminal(v, 1, GetNumTerminals(apc));
+ } else {
+ /* read which group do we want to go to?
+ * (the first free group) */
+ uint target_group = current->special + 1;
+
+ /* at what terminal does the group start?
+ * that means, sum up all terminals of
+ * groups with lower number */
+ uint group_start = 0;
+ for (uint i = 1; i < target_group; i++) {
+ group_start += apc->terminals[i];
}
- temp = temp->next;
+
+ uint group_end = group_start + apc->terminals[target_group];
+ if (FreeTerminal(v, group_start + 1, group_end)) return true;
}
return false;
}
@@ -2076,37 +2098,37 @@
}
-static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc)
+static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc, const AirportFTA *current)
{
/* if an airport doesn't have helipads, use terminals */
- if (apc->helipads == NULL) return AirportFindFreeTerminal(v, apc);
+ if (apc->helipads == NULL) return AirportFindFreeTerminal(v, apc, current);
/* if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal() */
if (apc->helipads[0] > 1) {
Station* st = GetStation(v->u.air.targetairport);
- AirportFTA* temp = apc->layout[v->u.air.pos].next;
-
- while (temp != NULL) {
- if (temp->heading == 0x7D) {
- if (!st->airport_flags.HasBlocks(&temp->reserveblock)) {
-
- /* read which group do we want to go to?
- * (the first free group) */
- uint target_group = temp->next_position + 1;
- /* at what terminal does the group start?
- * that means, sum up all terminals of
- * groups with lower number */
- uint group_start = MAX_TERMINALS + 1;
- for (uint i = 1; i < target_group; i++) {
- group_start += apc->helipads[i];
- }
+ /* forget any existing terminal reservations the aircraft has */
+ st->airport_flags.ReleaseLowerBlocks(&v->u.air.owned_blocks);
+ v->u.air.owned_blocks.ReleaseLowerBlocks(&v->u.air.owned_blocks);
- uint group_end = group_start + apc->helipads[target_group];
- if (FreeTerminal(v, group_start, group_end)) return true;
- }
+ if (current == NULL) {
+ /* choose from any terminal, no block restrictions */
+ return FreeTerminal(v, 1, GetNumTerminals(apc));
+ } else {
+ /* read which group do we want to go to?
+ * (the first free group) */
+ uint target_group = current->special + 1;
+
+ /* at what terminal does the group start?
+ * that means, sum up all terminals of
+ * groups with lower number */
+ uint group_start = MAX_TERMINALS + 1;
+ for (uint i = 1; i < target_group; i++) {
+ group_start += apc->helipads[i];
}
- temp = temp->next;
+
+ uint group_end = group_start + apc->helipads[target_group];
+ if (FreeTerminal(v, group_start + 1, group_end)) return true;
}
return false;
} else {