Index: src/aircraft_cmd.cpp =================================================================== --- src/aircraft_cmd.cpp (revision 10586) +++ src/aircraft_cmd.cpp (working copy) @@ -33,6 +33,7 @@ #include "date.h" #include "spritecache.h" #include "cargotype.h" +#include "indexed_queue.hpp" void Aircraft::UpdateDeltaXY(Direction direction) { @@ -46,6 +47,7 @@ case ENDTAKEOFF: case LANDING: case HELILANDING: + case DESCENT: case FLYING: x = MKIT(24, 24, -1, -1); break; default: x = MKIT( 2, 2, -1, -1); break; } @@ -76,7 +78,7 @@ static void CrashAirplane(Vehicle *v); static void AircraftNextAirportPos_and_Order(Vehicle *v); -static byte GetAircraftFlyingAltitude(const Vehicle *v); +static uint32 GetAircraftFlyingAltitude(const Vehicle *v); static const SpriteID _aircraft_sprite[] = { 0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD, @@ -416,6 +418,9 @@ v->random_bits = VehicleRandomBits(); u->random_bits = VehicleRandomBits(); + // TODO: Change to OOP + v->u.air.desired_speed = 1; + v->vehicle_flags = 0; if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); @@ -821,7 +826,7 @@ EndVehicleMove(u); } -static void SetAircraftPosition(Vehicle *v, int x, int y, int z) +static void SetAircraftPosition(Vehicle *v, int x, int y, int32 z) { v->x_pos = x; v->y_pos = y; @@ -907,6 +912,7 @@ */ enum AircraftSpeedLimits { SPEED_LIMIT_TAXI = 50, ///< Maximum speed of an aircraft while taxiing + SPEED_LIMIT_LANDING = 100, ///< Maximum speed of an aircraft while landing SPEED_LIMIT_APPROACH = 230, ///< Maximum speed of an aircraft on finals SPEED_LIMIT_BROKEN = 320, ///< Maximum speed of an aircraft that is broken SPEED_LIMIT_HOLD = 425, ///< Maximum speed of an aircraft that flies the holding pattern @@ -920,26 +926,35 @@ * @param hard_limit If true, the limit is directly enforced, otherwise the plane is slowed down gradually * @return The number of position updates needed within the tick */ -static int UpdateAircraftSpeed(Vehicle *v, uint speed_limit = SPEED_LIMIT_NONE, bool hard_limit = true) +static int UpdateAircraftSpeed(Vehicle *v, uint speed_limit = SPEED_LIMIT_NONE * _patches.aircraft_speed_coeff, bool hard_limit = true) { - uint spd = v->acceleration * 16; + uint16 spd = v->acceleration * 16; byte t; + uint16 new_speed; if (v->u.air.cached_max_speed < speed_limit) { if (v->cur_speed < speed_limit) hard_limit = false; - speed_limit = v->u.air.cached_max_speed; + speed_limit = v->u.air.cached_max_speed * _patches.aircraft_speed_coeff; } - speed_limit = min(speed_limit, v->max_speed); + new_speed = v->max_speed * _patches.aircraft_speed_coeff; - v->subspeed = (t=v->subspeed) + (byte)spd; + speed_limit = min(speed_limit, v->max_speed * _patches.aircraft_speed_coeff); + // Don't go faster than max + if(v->u.air.desired_speed > new_speed) { + v->u.air.desired_speed = new_speed; + } + +// spd = v->cur_speed + v->acceleration; + v->subspeed = (t=v->subspeed) + (uint16)spd; + if (!hard_limit && v->cur_speed > speed_limit) speed_limit = v->cur_speed - (v->cur_speed / 48); - spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit); + spd = min(v->cur_speed + (spd >> 8) * _patches.aircraft_speed_coeff + (v->subspeed < t), speed_limit); /* adjust speed for broken vehicles */ - if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN); + if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN * _patches.aircraft_speed_coeff); /* updates statusbar only if speed have changed to save CPU time */ if (spd != v->cur_speed) { @@ -948,6 +963,15 @@ InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); } + if(v->u.air.state == FLYING && v->subtype == 0 && v->u.air.desired_speed == 0) { + if(spd > 0) + spd = 0; + } + + // If landing, do not speed up! + if((v->u.air.state == LANDING || v->u.air.state == ENDLANDING) && spd > SPEED_LIMIT_LANDING) + spd = min(v->cur_speed, spd); + if (!(v->direction & 1)) spd = spd * 3 / 4; spd += v->progress; @@ -962,8 +986,10 @@ * @param v The vehicle. Should be an aircraft * @returns Altitude in pixel units */ -static byte GetAircraftFlyingAltitude(const Vehicle *v) +static uint32 GetAircraftFlyingAltitude(const Vehicle *v) { + uint32 queue_adjust; + /* Make sure Aircraft fly no lower so that they don't conduct * CFITs (controlled flight into terrain) */ @@ -986,7 +1012,13 @@ /* Make faster planes fly higher so that they can overtake slower ones */ base_altitude += min(20 * (v->max_speed / 200), 90); - return base_altitude; + + queue_adjust = 0; + if(v->queue_item != NULL) + queue_adjust = 32 * v->queue_item->getQueue()->getPos(v->queue_item)-1; + + + return base_altitude + queue_adjust; } /** @@ -1038,6 +1070,10 @@ const Station *st = GetStation(v->u.air.targetairport); const AirportFTAClass *afc = st->Airport(); const AirportMovingData *amd; + uint desired_dist; +// int tilesMoved; + uint32 z,curz; + bool checkSuccess; /* prevent going to 0,0 if airport is deleted. */ TileIndex tile = st->airport_tile; @@ -1097,7 +1133,7 @@ v->tile = st->airport_tile; /* Find altitude of landing position. */ - int z = GetSlopeZ(x, y) + 1 + afc->delta_z; + int32 z = GetSlopeZ(x, y) + 1 + afc->delta_z; if (z == v->z_pos) { Vehicle *u = v->next->next; @@ -1117,6 +1153,94 @@ /* Get distance from destination pos to current pos. */ uint dist = myabs(x + amd->x - v->x_pos) + myabs(y + amd->y - v->y_pos); + // Clear queues when there's no patch + if(_patches.aircraft_queueing == false && v->queue_item != NULL) { + v->queue_item->getQueue()->midDelete(v->queue_item); + v->queue_item = NULL; + v->z_pos = GetAircraftFlyingAltitude(v); + } + + // If target airport is VERY busy (queue larger than 3), always add to queue + if(st->airport_queue->getSize() > 3 && v->u.air.state == FLYING) { + // If it's already in the queue, don't re-add it + // Otherwise, add it to queue - but don't add helicopters! + // otherwise, helicopters will be part of the queue and can't land separately! + if(v->queue_item == NULL && (_patches.aircraft_queueing == true && v->subtype != 0)) { + // Add to queue + v->queue_item = st->airport_queue->push(v); + if(v->queue_item != NULL) + { checkSuccess = true; + } else { + checkSuccess = false; + } + assert(checkSuccess); + } + } + + // If the aircraft is flying and is within range of an airport, add it to the queue + if(dist < 1000 && v->u.air.state == FLYING) { + // If it's already in the queue, don't re-add it + // Otherwise, add it to queue - but don't add helicopters! + // otherwise, helicopters will be part of the queue and can't land separately! + if(v->queue_item == NULL && _patches.aircraft_queueing == true && v->subtype != 0) { + // Add to queue + v->queue_item = st->airport_queue->push(v); + } + } + + // Calculate desired distance + if(v->subtype != 0) { + // Aircraft (Note to self: Original distance multiplier was 250) + // Increased to see if it helps + if(v->queue_item != NULL) + desired_dist = v->queue_item->getQueue()->getPos(v->queue_item) * 300; + else + desired_dist = st->airport_queue->getSize() * 300; + } else { + // Helicopters + if(v->queue_item != NULL) + desired_dist = v->queue_item->getQueue()->getPos(v->queue_item) * 75; + else + desired_dist = st->helicopter_queue->getSize() * 75; + } + + // Add helicopters to their own queue, if in range of airport + if(dist < 1000 && v->u.air.state == FLYING && v->subtype == 0 && v->queue_item == NULL) { + v->queue_item = st->helicopter_queue->push(v); + } + + // Try to reach desired distance +// if(myabs(desired_dist - dist) < 20) { +// // At or close to desired distance, maintain a good cruising speed +// v->u.air.desired_speed = min(v->max_speed * _patches.aircraft_speed_coeff, 36 * _patches.aircraft_speed_coeff); +// } else { +// if(dist < desired_dist && v->queue_item != NULL) { +// // Too close, slow down, but only if not near end of queue +// if(v->queue_item->getQueue()->getPos(v->queue_item) > 2) +// v->u.air.desired_speed = min(v->max_speed * _patches.aircraft_speed_coeff, 15 * _patches.aircraft_speed_coeff); +// else +// v->u.air.desired_speed = v->u.air.desired_speed = min(v->max_speed * _patches.aircraft_speed_coeff, 36 * _patches.aircraft_speed_coeff); +// } else { +// // Too far, speed up +// v->u.air.desired_speed = v->max_speed * _patches.aircraft_speed_coeff; +// } +// } + + // All helicopters other than one in front stay in line + if(v->queue_item != NULL) { + if(v->u.air.state == FLYING && v->subtype == 0 + && v->queue_item->getQueue()->getPos(v->queue_item) != 1) { + if(dist < desired_dist) { + v->cur_speed = 0; + v->u.air.desired_speed = 0; + } + } + } + + // Slow down if above desired speed + if(v->u.air.state == FLYING && v->cur_speed > v->u.air.desired_speed * _patches.aircraft_speed_coeff) + v->cur_speed--; + /* Need exact position? */ if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U)) return true; @@ -1148,6 +1272,15 @@ if (amd->flag & AMED_LAND) { speed_limit = SPEED_LIMIT_APPROACH; hard_limit = false; } if (amd->flag & AMED_BRAKE) { speed_limit = SPEED_LIMIT_TAXI; hard_limit = false; } + if(v->u.air.state == DESCENT) + { speed_limit = SPEED_LIMIT_APPROACH; + } + + if(v->u.air.state == ENDLANDING) + { speed_limit = SPEED_LIMIT_LANDING; + hard_limit = false; + } + count = UpdateAircraftSpeed(v, speed_limit, hard_limit); if (count == 0) return false; @@ -1191,7 +1324,7 @@ // if (amd->flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0; /* Adjust Z for land or takeoff? */ - uint z = v->z_pos; + z = v->z_pos; if (amd->flag & AMED_TAKEOFF) { z = min(z + 2, GetAircraftFlyingAltitude(v)); @@ -1210,7 +1343,7 @@ continue; } - uint curz = GetSlopeZ(x, y) + 1; + curz = GetSlopeZ(x, y) + 1; if (curz > z) { z++; @@ -1222,18 +1355,42 @@ } } + + // Slow down fast aircraft as they approach the airport + if(dist < 500 && v->cur_speed > 592) + { + v->cur_speed -=2; + } + /* We've landed. Decrase speed when we're reaching end of runway. */ if (amd->flag & AMED_BRAKE) { - uint curz = GetSlopeZ(x, y) + 1; + curz = GetSlopeZ(x, y) + 1; - if (z > curz) { - z--; - } else if (z < curz) { - z++; - } +// if (z > curz) { +// z--; +// } else if (z < curz) { +// z++; +// } + // We've landed, so clamp aircraft to the ground + z = GetSlopeZ(x, y) + 1; + } + curz = z; + if(v->queue_item != NULL) + { + curz = GetAircraftFlyingAltitude(v); + } + + if(curz < z) + { + z--; + } else if(curz > z) + { + z++; + } + SetAircraftPosition(v, gp.x, gp.y, z); } while (--count != 0); return false; @@ -1694,6 +1851,8 @@ static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc) { Station *st = GetStation(v->u.air.targetairport); + bool can_land; + can_land = false; /* runway busy or not allowed to use this airstation, circle */ if (apc->flags & (v->subtype == AIR_HELICOPTER ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES) && @@ -1705,14 +1864,82 @@ byte landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING; const AirportFTA *current = apc->layout[v->u.air.pos].next; while (current != NULL) { - if (current->heading == landingtype) { + if (current->heading == landingtype || current->heading == DESCENT) { + // Check to see if we're going to land at an airport. + + // Fisrt, check queue - if we are on top, or if it's empty, + // we can land. + + // Just in case the code in AircraftController code misses, + // We check before the aircraft lands. + + // If it's already in the queue, don't re-add it + // Otherwise, add it to queue - but do helicopters seperately! + // Otherwise, helicopters will be part of the queue and can't land separately! + if(!(v->queue_item != NULL) && (_patches.aircraft_queueing == true && v->subtype != 0)) { + // Add to queue + v->queue_item = st->airport_queue->push(v); + } + + if(!(v->queue_item != NULL) && (_patches.aircraft_queueing == true && v->subtype == 0)) { + // Add to queue + v->queue_item = st->helicopter_queue->push(v); + } + /* save speed before, since if AirportHasBlock is false, it resets them to 0 * we don't want that for plane in air * hack for speed thingie */ uint16 tcur_speed = v->cur_speed; uint16 tsubspeed = v->subspeed; - if (!AirportHasBlock(v, current, apc)) { - v->u.air.state = landingtype; // LANDING / HELILANDING + // If we're on top, go in + if(st->airport_queue->getTop() == v && (_patches.aircraft_queueing == true && v->subtype != 0)) { + if (!AirportHasBlock(v, current, apc)) { + can_land = true; + if(st->airport_type != AT_SMALL && st->airport_type != AT_COMMUTER && st->airport_type != AT_LARGE) { + st->airport_queue->pop(); + v->queue_item = NULL; + } + } else { + can_land = false; + } + } + + // Helicopters have their own queue + if(v->subtype == 0 && st->helicopter_queue->getTop() == v && _patches.aircraft_queueing == true) { + if (!AirportHasBlock(v, current, apc)) { + can_land = true; + st->helicopter_queue->pop(); + v->queue_item = NULL; + } else { + can_land = false; + } + } else { + if(v->subtype == 0) { + can_land = false; + if(st->helicopter_queue->getPos(st->helicopter_queue->getItem(v)) != 1) + { + v->u.air.desired_speed = 0; + } + } + } + + if(_patches.aircraft_queueing == false) { // || v->subtype == 0 + if (!AirportHasBlock(v, current, apc)) { + can_land = true; + } else { + can_land = false; + } + } + + + if(can_land == true) { + if(st->airport_type == AT_SMALL || st->airport_type == AT_COMMUTER || st->airport_type == AT_LARGE) { + v->u.air.state = DESCENT; + return; + } else { + v->u.air.state = landingtype; // LANDING / HELILANDING + } + /* it's a bit dirty, but I need to set position to next position, otherwise * if there are multiple runways, plane won't know which one it took (because * they all have heading LANDING). And also occupy that block! */ @@ -1749,6 +1976,55 @@ } } +static void AircraftEventHandler_Descending(Vehicle *v, const AirportFTAClass *apc) +{ + Station *st = GetStation(v->u.air.targetairport); + const AirportFTA *current = apc->layout[v->u.air.pos].next; + uint16 tempSpeed, tempSubspeed; + Vehicle *vtemp = NULL; + + // Save speed in case flying + tempSpeed = v->cur_speed; + tempSubspeed = v->subspeed; + + if(!AirportHasBlock(v, current, apc) ) + { + v->u.air.pos = current->next_position; + SETBITS(st->airport_flags, apc->layout[v->u.air.pos].block); + v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING; + vtemp = st->airport_queue->pop(); // Pop the item + if(vtemp != NULL) + { vtemp->queue_item = NULL; // Set its queue_item to NULL - This was a major pain to debug :( + } + if(st->airport_queue->getTop() != NULL) { // Now that we're landing, have the next aircraft immediately start descending! + st->airport_queue->getTop()->u.air.state = DESCENT; + } + //v->queue_item = NULL; + } else { + v->u.air.state = FLYING; + + // We're flying: restore speed + v->cur_speed = tempSpeed; + v->subspeed = tempSubspeed; + + } + +// AircraftLandAirplane(v); // maybe crash airplane + + /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ +// if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) { +// /* only the vehicle owner needs to calculate the rest (locally) */ +// const Player* p = GetPlayer(v->owner); +// if (EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) || +// (p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) { +// /* send the aircraft to the hangar at next airport */ +// _current_player = _local_player; +// DoCommandP(v->tile, v->index, DEPOT_SERVICE, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); +// _current_player = OWNER_NONE; +// } +// } +} + static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc) { v->u.air.state = HELIENDLANDING; @@ -1814,6 +2090,7 @@ AircraftEventHandler_AtTerminal, // TERM8 = 20 AircraftEventHandler_AtTerminal, // HELIPAD3 = 21 AircraftEventHandler_AtTerminal, // HELIPAD4 = 22 + AircraftEventHandler_Descending, // DESCENT = 23 }; static void AirportClearBlock(const Vehicle *v, const AirportFTAClass *apc) @@ -1943,6 +2220,13 @@ if (current_pos->block == next->block) airport_flags ^= next->block; Station* st = GetStation(v->u.air.targetairport); + + // Do NOT slow down aircraft when in DESCENT state - my descent code also seems to affect landing + if(HASBITS(st->airport_flags, airport_flags) && (v->u.air.state == DESCENT || v->u.air.state == LANDING)) + { + return false; + } + if (HASBITS(st->airport_flags, airport_flags)) { v->cur_speed = 0; v->subspeed = 0; @@ -2132,7 +2416,7 @@ /* set airport_flags to 0 for all airports just to be sure */ Station *st; FOR_ALL_STATIONS(st) { - st->airport_flags = 0; // reset airport + st->airport_flags = 0LL; // reset airport - A simple "0" will only clear 32 bits, we use 64 } Vehicle *v_oldstyle; Index: src/aircraft_gui.cpp =================================================================== --- src/aircraft_gui.cpp (revision 10586) +++ src/aircraft_gui.cpp (working copy) @@ -282,14 +282,14 @@ switch (v->current_order.type) { case OT_GOTO_STATION: { SetDParam(0, v->current_order.dest); - SetDParam(1, v->cur_speed * 10 / 16); + SetDParam(1, (v->cur_speed * 10 / 16) / _patches.aircraft_speed_coeff); str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; } break; case OT_GOTO_DEPOT: { /* Aircrafts always go to a station, even if you say depot */ SetDParam(0, v->current_order.dest); - SetDParam(1, v->cur_speed * 10 / 16); + SetDParam(1, (v->cur_speed * 10 / 16) / _patches.aircraft_speed_coeff); if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) { str = STR_HEADING_FOR_HANGAR + _patches.vehicle_speed; } else { @@ -304,7 +304,7 @@ default: if (v->num_orders == 0) { str = STR_NO_ORDERS + _patches.vehicle_speed; - SetDParam(0, v->cur_speed * 10 / 16); + SetDParam(0, (v->cur_speed * 10 / 16) / _patches.aircraft_speed_coeff); } else { str = STR_EMPTY; } Index: src/airport.h =================================================================== --- src/airport.h (revision 10586) +++ src/airport.h (working copy) @@ -10,7 +10,7 @@ enum {MAX_TERMINALS = 10}; enum {MAX_HELIPADS = 4}; enum {MAX_ELEMENTS = 255}; -enum {MAX_HEADINGS = 22}; +enum {MAX_HEADINGS = 23}; // Airport types enum { @@ -64,7 +64,8 @@ TERM7 = 19, TERM8 = 20, HELIPAD3 = 21, - HELIPAD4 = 22 + HELIPAD4 = 22, + DESCENT = 23 }; /* Movement Blocks on Airports */ @@ -111,7 +112,8 @@ OUT_WAY_block2 = 1ULL << 31, // end of new blocks - NOTHING_block = 1ULL << 30; + NOTHING_block = 1ULL << 30, + APPROACH_block = 1ULL << 32LL; // Above 32 bits MUST specify long long (64 bit) type! struct AirportMovingData { int16 x; Index: src/airport_movement.h =================================================================== --- src/airport_movement.h (revision 10586) +++ src/airport_movement.h (working copy) @@ -26,7 +26,7 @@ }; // Country Airfield (small) 4x3 -static const AirportMovingData _airport_moving_data_country[22] = { +static const AirportMovingData _airport_moving_data_country[23] = { { 53, 3, AMED_EXACTPOS, {DIR_SE} }, // 00 In Hangar { 53, 27, 0, {DIR_N} }, // 01 Taxi to right outside depot { 32, 23, AMED_EXACTPOS, {DIR_NW} }, // 02 Terminal 1 @@ -42,17 +42,18 @@ { 3, 40, AMED_NOSPDCLAMP | AMED_BRAKE, {DIR_N} }, // 12 Just landed, brake until end of runway { 7, 40, 0, {DIR_N} }, // 13 Just landed, turn around and taxi 1 square { 53, 40, 0, {DIR_N} }, // 14 Taxi from runway to crossing - { -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 15 Fly around waiting for a landing spot (north-east) - { 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 16 Fly around waiting for a landing spot (north-west) - { 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 17 Fly around waiting for a landing spot (south-west) - { 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 18 Fly around waiting for a landing spot (south) + { 546, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 15 Fly around waiting for a landing spot (north-east) + { 646, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 16 Fly around waiting for a landing spot (north-west) + { 646, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 17 Fly around waiting for a landing spot (south-west) + { 546, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 18 Fly around waiting for a landing spot (south) { 44, 37, AMED_HELI_RAISE, {DIR_N} }, // 19 Helicopter takeoff { 44, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 20 In position above landing spot helicopter { 44, 40, AMED_HELI_LOWER, {DIR_N} }, // 21 Helicopter landing + { 207, 40, AMED_SLOWTURN, {DIR_N} }, // 22 Extra "APPROACH" step for landing }; // Commuter Airfield (small) 5x4 -static const AirportMovingData _airport_moving_data_commuter[37] = { +static const AirportMovingData _airport_moving_data_commuter[38] = { { 69, 3, AMED_EXACTPOS, {DIR_SE} }, // 00 In Hangar { 72, 22, 0, {DIR_N} }, // 01 Taxi to right outside depot { 8, 22, AMED_EXACTPOS, {DIR_SW} }, // 01 Taxi to right outside depot @@ -74,10 +75,14 @@ { 3, 54, AMED_NOSPDCLAMP | AMED_BRAKE, {DIR_N} }, // 18 Just landed, brake until end of runway { 12, 54, 0, {DIR_NW} }, // 19 Just landed, turn around and taxi { 8, 32, 0, {DIR_NW} }, // 20 Taxi from runway to crossing - { -31, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 21 Fly around waiting for a landing spot (north-east) - { 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 22 Fly around waiting for a landing spot (north-west) - { 193, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 23 Fly around waiting for a landing spot (south-west) - { 225, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 24 Fly around waiting for a landing spot (south) + { 646, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 21 Fly around waiting for a landing spot (north-east) + { 746, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 22 Fly around waiting for a landing spot (north-west) + { 746, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 23 Fly around waiting for a landing spot (south-west) + { 646, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 24 Fly around waiting for a landing spot (south) +// { -31, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 21 Fly around waiting for a landing spot (north-east) +// { 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 22 Fly around waiting for a landing spot (north-west) +// { 193, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 23 Fly around waiting for a landing spot (south-west) +// { 225, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 24 Fly around waiting for a landing spot (south) // Helicopter { 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 25 Bufferspace before helipad { 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 26 Bufferspace before helipad @@ -91,6 +96,7 @@ { 64, 22, AMED_HELI_LOWER, {DIR_N} }, // 34 Land in front of hangar { 40, 8, AMED_EXACTPOS, {DIR_N} }, // pre-helitakeoff helipad 1 { 56, 8, AMED_EXACTPOS, {DIR_N} }, // pre-helitakeoff helipad 2 + { 157, 40, AMED_SLOWTURN, {DIR_N} }, // 37 Extra "APPROACH" step for landing }; // City Airport (large) 6x6 @@ -113,18 +119,23 @@ { 20, 87, AMED_NOSPDCLAMP | AMED_BRAKE, {DIR_N} }, // 15 Just landed, brake until end of runway { 20, 87, 0, {DIR_N} }, // 16 Just landed, turn around and taxi 1 square /* NOT USED */ { 36, 71, 0, {DIR_N} }, // 17 Taxi from runway to crossing - { 160, 87, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 18 Fly around waiting for a landing spot (north-east) +// { 160, 87, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 18 Fly around waiting for a landing spot (north-east) + { 546, 1, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 18 Fly around waiting for a landing spot (north-east) { 140, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 19 Final approach fix - { 257, 1, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 20 Fly around waiting for a landing spot (south-west) - { 273, 49, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 21 Fly around waiting for a landing spot (south) +// { 257, 1, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 20 Fly around waiting for a landing spot (south-west) +// { 273, 49, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 21 Fly around waiting for a landing spot (south) + { 646, 1, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 20 Fly around waiting for a landing spot (south-west) + { 646, 149, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 21 Fly around waiting for a landing spot (south) { 44, 63, AMED_HELI_RAISE, {DIR_N} }, // 22 Helicopter takeoff { 28, 74, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 23 In position above landing spot helicopter { 28, 74, AMED_HELI_LOWER, {DIR_N} }, // 24 Helicopter landing - { 145, 1, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 25 Fly around waiting for a landing spot (north-west) +// { 145, 1, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 25 Fly around waiting for a landing spot (north-west) + { 546, 149, AMED_HOLD | AMED_SLOWTURN, {DIR_N} }, // 25 Fly around waiting for a landing spot (north-west) { -32, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 26 Initial approach fix (north) { 300, -48, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 27 Initial approach fix (south) { 140, -48, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 28 Intermediadate Approach fix (south), IAF (west) { -32, 120, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} }, // 29 Initial approach fix (east) + { 180, 49, AMED_SLOWTURN, {DIR_N} }, // 37 Extra "APPROACH" step for landing }; // Metropolitan Airport (metropolitan) - 2 runways @@ -407,23 +418,24 @@ { 5, 255, AIRPORT_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, 0, 0, 4 }, { 6, 0, AIRPORT_BUSY_block, 7 }, // takeoff - { 7, TAKEOFF, AIRPORT_BUSY_block, 8 }, + { 7, TAKEOFF, AIRPORT_BUSY_block , 8 }, { 8, STARTTAKEOFF, NOTHING_block, 9 }, { 9, ENDTAKEOFF, NOTHING_block, 0 }, // landing { 10, FLYING, NOTHING_block, 15 }, { 10, LANDING, 0, 11 }, { 10, HELILANDING, 0, 20 }, - { 11, LANDING, AIRPORT_BUSY_block, 12 }, - { 12, 0, AIRPORT_BUSY_block, 13 }, - { 13, ENDLANDING, AIRPORT_BUSY_block, 14 }, { 13, TERM2, 0, 5 }, { 13, 0, 0, 14 }, - { 14, 0, AIRPORT_BUSY_block, 1 }, + { 11, LANDING, RUNWAY_OUT_block , 12 }, + { 12, 0, RUNWAY_OUT_block, 13 }, + { 13, ENDLANDING, AIRPORT_BUSY_block , 14 }, { 13, TERM2, 0, 5 }, { 13, 0, 0, 14 }, + { 14, 0, AIRPORT_BUSY_block , 1 }, // In air - { 15, 0, NOTHING_block, 16 }, - { 16, 0, NOTHING_block, 17 }, - { 17, 0, NOTHING_block, 18 }, - { 18, 0, NOTHING_block, 10 }, + { 15, FLYING, NOTHING_block, 16 }, { 15, DESCENT, APPROACH_block, 22 }, + { 16, FLYING, NOTHING_block, 17 }, { 16, DESCENT, APPROACH_block, 22 }, + { 17, FLYING, NOTHING_block, 18 }, { 17, DESCENT, APPROACH_block, 22 }, + { 18, FLYING, NOTHING_block, 15 }, { 18, DESCENT, APPROACH_block, 22 }, { 19, HELITAKEOFF, NOTHING_block, 0 }, - { 20, HELILANDING, AIRPORT_BUSY_block, 21 }, - { 21, HELIENDLANDING, AIRPORT_BUSY_block, 1 }, + { 20, HELILANDING, AIRPORT_BUSY_block , 21 }, + { 21, HELIENDLANDING, AIRPORT_BUSY_block , 1 }, + { 22, DESCENT, APPROACH_block, 22}, { 22, LANDING, APPROACH_block , 11 }, { 22, FLYING, NOTHING_block, 15 }, // Extra step for landing { MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE }; @@ -456,10 +468,15 @@ { 19, 0, RUNWAY_IN_OUT_block, 20 }, { 20, ENDLANDING, IN_WAY_block, 2 }, // In Air - { 21, 0, NOTHING_block, 22 }, - { 22, 0, NOTHING_block, 23 }, - { 23, 0, NOTHING_block, 24 }, - { 24, 0, NOTHING_block, 16 }, + { 21, FLYING, NOTHING_block, 22 }, { 21, DESCENT, APPROACH_block, 37 }, + { 22, FLYING, NOTHING_block, 23 }, { 22, DESCENT, APPROACH_block, 37 }, + { 23, FLYING, NOTHING_block, 24 }, { 23, DESCENT, APPROACH_block, 37 }, + { 24, FLYING, NOTHING_block, 21 }, { 24, DESCENT, APPROACH_block, 37 }, + +// { 21, 0, NOTHING_block, 22 }, +// { 22, 0, NOTHING_block, 23 }, +// { 23, 0, NOTHING_block, 24 }, +// { 24, 0, NOTHING_block, 16 }, // Helicopter -- stay in air in special place as a buffer to choose from helipads { 25, HELILANDING, PRE_HELIPAD_block, 26 }, { 26, HELIENDLANDING, PRE_HELIPAD_block, 26 }, { 26, HELIPAD1, 0, 27 }, { 26, HELIPAD2, 0, 28 }, { 26, HANGAR, 0, 33 }, @@ -475,6 +492,7 @@ { 34, 0, TAXIWAY_BUSY_block, 1 }, { 35, 0, HELIPAD1_block, 31 }, { 36, 0, HELIPAD2_block, 32 }, + { 37, DESCENT, APPROACH_block, 37}, { 37, LANDING, APPROACH_block , 17 }, { 37, FLYING, NOTHING_block, 21 }, // Extra step for landing { MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE }; @@ -503,19 +521,24 @@ { 16, 0, RUNWAY_IN_OUT_block, 17 }, /* not used, left for compatibility */ { 17, ENDLANDING, IN_WAY_block, 7 }, // In Air - { 18, 0, NOTHING_block, 25 }, +// { 18, 0, NOTHING_block, 25 }, + { 18, FLYING, NOTHING_block, 20 }, { 18, DESCENT, APPROACH_block, 30 }, { 19, 0, NOTHING_block, 20 }, - { 20, 0, NOTHING_block, 21 }, - { 21, 0, NOTHING_block, 13 }, +// { 20, 0, NOTHING_block, 21 }, + { 20, FLYING, NOTHING_block, 21 }, { 20, DESCENT, APPROACH_block, 30 }, +// { 21, 0, NOTHING_block, 13 }, + { 21, FLYING, NOTHING_block, 25 }, { 21, DESCENT, APPROACH_block, 30 }, // helicopter { 22, HELITAKEOFF, NOTHING_block, 0 }, { 23, HELILANDING, IN_WAY_block, 24 }, { 24, HELIENDLANDING, IN_WAY_block, 17 }, - { 25, 0, NOTHING_block, 20}, +// { 25, 0, NOTHING_block, 20}, + { 25, FLYING, NOTHING_block, 18 }, { 25, DESCENT, APPROACH_block, 30 }, { 26, 0, NOTHING_block, 19}, { 27, 0, NOTHING_block, 28}, { 28, 0, NOTHING_block, 19}, { 29, 0, NOTHING_block, 26}, + { 30, DESCENT, APPROACH_block, 30}, { 30, LANDING, APPROACH_block , 14 }, { 30, FLYING, NOTHING_block, 18 }, // Extra step for landing { MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE }; Index: src/helpers.hpp =================================================================== --- src/helpers.hpp (revision 10586) +++ src/helpers.hpp (working copy) @@ -40,7 +40,7 @@ /** returns the absolute value of (scalar) variable. @note assumes variable to be signed */ -template static inline T myabs(T a) { return a < (T)0 ? -a : a; } +template static inline T myabs(T a) { return a < (T)0 ? 0-a : a; } /** returns the (absolute) difference between two (scalar) variables */ template static inline T delta(T a, T b) { return a < b ? b - a : a - b; } Index: src/indexed_queue.hpp =================================================================== --- src/indexed_queue.hpp (revision 0) +++ src/indexed_queue.hpp (revision 0) @@ -0,0 +1,417 @@ +#ifndef INDEXED_QUEUE_HPP +#define INDEXED_QUEUE_HPP + +/* Since we are using C++ now, I will be using classes instead of structs + * More OOP, less hacks, and finally the queue can be properly generic using + * templates instead of only using one type for its behaviors. + * + * Unless otherwise stated, functions will return a pointer to an item of the + * templated type if it is expected to return one, otherwise returns a boolean + * indicating success or failure. + */ +template // T is the type of data the queue is storing +class IndexedItem { + template friend class IndexedQueue; + +public: + IndexedItem(); + ~IndexedItem(); + T* getData(); + bool setData(T *); + IndexedQueue *getQueue(); +private: + T *item; + uint32 position; + IndexedItem *above; + IndexedItem *below; + IndexedQueue *queue; + +}; + +template // T is the type of data the queue is storing +class IndexedQueue { +public: + IndexedQueue(); //Constructor + ~IndexedQueue();// Destructor + IndexedItem *push(T *); // Push into queue (bottom) + T* pop(); // Pop from queue (top) + IndexedItem *pushBack(T *); // Pushes into top (acts like a stack) + T* getTop(); // Get the top without popping it + void clear(); // Delete all items in the queue + uint32 getSize(); // Returns size of queue + + /* The next two items are the unique items and the reason why I had + * to implement a new queue instead of using the existing queue code. + */ + bool midDelete(IndexedItem *); // Deletes a known item from anywhere in the queue + uint32 getPos(IndexedItem *); // Get the position of an item in the queue (uint32) + + // Returns the IndexedItem that contains the data. + // Runs in linear time! + IndexedItem *getItem(T *); + +private: + IndexedItem *top; // Top of queue + IndexedItem *bottom; //Bottom of queue + void clean(); + + /* Dirty means "position" in the items is incorrect + * and needs to be rebuilt. + */ + bool dirty; + uint32 size; + + // Offset for "position" in queue - allows for O(1) pushes & pops + uint32 offset; + +}; + +/*************************************************************** + * MSVC++ is pretty picky about compiling template code + * They must be in the same file! + * http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 + ***************************************************************/ +// Indexed Queue code + +template // T is the type of data the queue is storing +IndexedQueue::IndexedQueue() +{ + top = NULL; + bottom = NULL; + dirty = false; + size = 0; + offset = 0; + return; +} + +template // T is the type of data the queue is storing +IndexedQueue::~IndexedQueue() +{ + clear(); + clean(); + return; +} + + +template IndexedItem *IndexedQueue::push(T *data) +{ + IndexedItem *newItem; + + // Do not push NULLs + assert(data != NULL); + if(data == NULL) + { return NULL; + } + + if(size == 0x7FFFFFFF) + return NULL; + + newItem = new IndexedItem(); + + if(newItem == NULL) + { return NULL; + } + + newItem->setData(data); + + if(size == 0) { + assert(top == NULL); + assert(bottom == NULL); + newItem->setData(data); + newItem->position = 1; + newItem->queue = this; + newItem->above = NULL; + newItem->below = NULL; + bottom = newItem; + top = newItem; + //v->queue_item = newItem; + size = 1; + return newItem; + } + + bottom->below = newItem; + newItem->above = bottom; + newItem->below = NULL; + newItem->setData(data); + newItem->position = bottom->position + 1; + newItem->queue = this; +// v->queue_item = newItem; + bottom = newItem; + size++; + return newItem; + +} + + +template // T is the type of data the queue is storing +T* IndexedQueue::pop() +{ + T* data; + IndexedItem *oldItem; + if(size == 0) + return NULL; + + oldItem = top; + + assert(oldItem != NULL); + +// top->data->queue_breakdown = false; + + top = oldItem->below; + if(top != NULL) + top->above = NULL; + + // Had one item, now empty + if(size == 1) { + bottom = NULL; + top = NULL; + size = 0; + offset = 0; + dirty = false; + data = oldItem->getData(); + oldItem->queue = NULL; +// data->queue_item = NULL; + delete oldItem; + return data; + } + + // Top was above bottom - now top *IS* bottom + if(size == 2) + bottom->above = NULL; + + data = oldItem->getData(); + oldItem->queue = NULL; + +// data->queue_item = NULL; + + delete oldItem; + + offset++; + size--; + + if(offset > 0x7FFFFFFF) { + dirty = true; + clean(); + } + return data; + +} + +template // T is the type of data the queue is storing +IndexedItem *IndexedQueue::pushBack(T *data) +{ + IndexedItem *newItem; + + // Do not push NULLs + assert(data != NULL); + + if(size == 0x7FFFFFFF) + return NULL; + + newItem = new IndexedItem(); + + if(newItem == NULL) + return NULL; + + if(size == 0) { + assert(top == NULL); + assert(bottom == NULL); + newItem->setData(data); + newItem->position = 1; + newItem->queue = this; + newItem->above = NULL; + newItem->below = NULL; + bottom = newItem; + top = newItem; +// v->queue_item = newItem; + size = 1; + return newItem; + } + + top->above = newItem; + newItem->below = top; + newItem->above = NULL; + newItem->setData(data); + newItem->position = 1; + newItem->queue = this; +// v->queue_item = newItem; + top = newItem; + size++; + + // Numbering is messed up now + dirty = true; + return newItem; +} + +template // T is the type of data the queue is storing +T* IndexedQueue::getTop() +{ + if(size != 0) + return top->getData(); + else + return NULL; +} + +template // T is the type of data the queue is storing +void IndexedQueue::clear() +{ + clean(); + while(pop() != NULL) { + // What? Expecting something? The clearing is done + // in the while statement above - I don't need anything here! + } + clean(); + return; +} + +template // T is the type of data the queue is storing +uint32 IndexedQueue::getSize() +{ + if(this != NULL) + { return size; + } + else + { return 0; + } +} + + + /* The next two items are the unique items and the reason why I had + * to implement a new queue instead of using the existing queue code. + */ +template // T is the type of data the queue is storing +bool IndexedQueue::midDelete(IndexedItem *current) +{ +// IndexedItem* current; + IndexedItem *above; + IndexedItem *below; + +// current = data; + if(current == NULL) + return false; + +// data->queue_breakdown = false; + + if(current == top) + top = current->below; + + if(current == bottom) + bottom = current->above; + + above = current->above; + below = current->below; + + if(above != NULL) + above->below = below; + + if(below != NULL) + below->above = above; + +// current->queue_item = NULL; + + delete current; + + size--; + dirty = true; + return true; +} + +template // T is the type of data the queue is storing +uint32 IndexedQueue::getPos(IndexedItem *current){ + if(dirty) + clean(); + + if(current == NULL) + return 0; + + return current->position - offset; +} + +template // T is the type of data the queue is storing +void IndexedQueue::clean() +{ + bool done; + uint32 currentSize; + IndexedItem *currItem; + done = false; + + if(this == NULL) { // non-existant queue + return; + } + + // Empty queue + if(top == NULL) { + assert(bottom == NULL); + assert(size == 0); + offset = 0; + dirty = false; + return; + } + + currItem = top; + offset = 0; + + currentSize = 1; + while(done == false) { + currItem->position = currentSize; + currItem = currItem->below; + if(currItem == NULL) { + done = true; + assert(size == currentSize); + } + currentSize++; + } + + // Congrats! We now have a clean queue! + dirty = false; + return; +} + +template // T is the type of data the queue is storing +IndexedItem *IndexedQueue::getItem(T *data) +{ + IndexedItem *currentItem = top; + + if(currentItem == NULL) + return NULL; + + do { + if(currentItem->getData() == data) + return currentItem; + } while(currentItem->below != NULL); + + return NULL; + +} + +template // T is the type of data the queue is storing +IndexedItem::IndexedItem() { + item = NULL; + above = NULL; + below = NULL; + position = 0; + queue = NULL; +} + +template // T is the type of data the queue is storing +IndexedItem::~IndexedItem() { +} + +template // T is the type of data the queue is storing +T* IndexedItem::getData() { + return item; +} + +template // T is the type of data the queue is storing +bool IndexedItem::setData(T *data) { + item = data; + return true; +} + +template // T is the type of data the queue is storing +IndexedQueue *IndexedItem::getQueue() +{ + return queue; +} + +#endif \ No newline at end of file Index: src/lang/american.txt =================================================================== --- src/lang/american.txt (revision 10586) +++ src/lang/american.txt (working copy) @@ -1193,6 +1193,9 @@ STR_CONFIG_PATCHES_YAPF_ROAD :{LTBLUE}Use YAPF for roadvehs: {ORANGE}{STRING} STR_CONFIG_PATCHES_YAPF_RAIL :{LTBLUE}Use YAPF for trains: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AIRQUEUE :{LTBLUE}Queue aircraft at airports{ORANGE} +STR_CONFIG_PATCHES_AIR_COEFF :{LTBLUE}Aircraft speedup (1=TTD default, 8=fastest):{ORANGE} {STRING} + STR_TEMPERATE_LANDSCAPE :Temperate landscape STR_SUB_ARCTIC_LANDSCAPE :Sub-arctic landscape STR_SUB_TROPICAL_LANDSCAPE :Sub-tropical landscape Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 10586) +++ src/lang/english.txt (working copy) @@ -1193,6 +1193,9 @@ STR_CONFIG_PATCHES_YAPF_ROAD :{LTBLUE}Use YAPF for roadvehs: {ORANGE}{STRING1} STR_CONFIG_PATCHES_YAPF_RAIL :{LTBLUE}Use YAPF for trains: {ORANGE}{STRING1} +STR_CONFIG_PATCHES_AIRQUEUE :{LTBLUE}Queue aircraft at airports{ORANGE} +STR_CONFIG_PATCHES_AIR_COEFF :{LTBLUE}Aircraft speedup (1=TTD default, 8=fastest):{ORANGE} {STRING} + STR_TEMPERATE_LANDSCAPE :Temperate landscape STR_SUB_ARCTIC_LANDSCAPE :Sub-arctic landscape STR_SUB_TROPICAL_LANDSCAPE :Sub-tropical landscape Index: src/newgrf.cpp =================================================================== --- src/newgrf.cpp (revision 10586) +++ src/newgrf.cpp (working copy) @@ -4689,7 +4689,7 @@ | (0 << 0x0C) // newagerating | ((_patches.build_on_slopes ? 1 : 0) << 0x0D) // buildonslopes | ((_patches.full_load_any ? 1 : 0) << 0x0E) // fullloadany - | (1 << 0x0F) // planespeed - TODO depends on patch when implemented + | (1 << 0x0F) // planespeed | (0 << 0x10) // moreindustriesperclimate - obsolete | (0 << 0x11) // moretoylandfeatures | (1 << 0x12) // newstations Index: src/newgrf_engine.cpp =================================================================== --- src/newgrf_engine.cpp (revision 10586) +++ src/newgrf_engine.cpp (working copy) @@ -314,6 +314,7 @@ return AMS_TTDP_HELI_TAKEOFF_HELIPORT; } + case DESCENT: case FLYING: return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER; @@ -400,6 +401,7 @@ /* @todo Need to find which terminal (or hanger) we've come from. How? */ return AMA_TTDP_PAD1_TO_TAKEOFF; + case DESCENT: case FLYING: return AMA_TTDP_IN_FLIGHT; Index: src/openttd.cpp =================================================================== --- src/openttd.cpp (revision 10586) +++ src/openttd.cpp (working copy) @@ -1592,7 +1592,7 @@ case DIAGDIR_SW: if ((v->x_pos & 0xF) != TILE_SIZE - 1) continue; break; case DIAGDIR_NW: if ((v->y_pos & 0xF) != 0) continue; break; } - } else if (v->z_pos > GetSlopeZ(v->x_pos, v->y_pos)) { + } else if (v->z_pos > (int)(GetSlopeZ(v->x_pos, v->y_pos))) { v->tile = GetNorthernBridgeEnd(v->tile); } else { continue; Index: src/settings.cpp =================================================================== --- src/settings.cpp (revision 10586) +++ src/settings.cpp (working copy) @@ -1414,6 +1414,8 @@ SDT_CONDBOOL(Patches, gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_GRADUAL_LOADING, NULL), SDT_CONDBOOL(Patches, road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL), SDT_CONDBOOL(Patches, adjacent_stations, 62, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ADJACENT_STATIONS, NULL), + SDT_BOOL(Patches, aircraft_queueing, 0, 0, false, STR_CONFIG_PATCHES_AIRQUEUE, NULL), + SDT_VAR(Patches, aircraft_speed_coeff, SLE_UINT16, 0, 0, 1, 1, 8,0, STR_CONFIG_PATCHES_AIR_COEFF, NULL), /***************************************************************************/ /* Economy section of the GUI-configure patches window */ Index: src/settings_gui.cpp =================================================================== --- src/settings_gui.cpp (revision 10586) +++ src/settings_gui.cpp (working copy) @@ -683,6 +683,7 @@ "gradual_loading", "road_stop_on_town_road", "adjacent_stations", + "aircraft_queueing", }; static const char *_patches_economy[] = { @@ -740,6 +741,7 @@ "disable_elrails", "freight_trains", "timetabling", + "aircraft_speed_coeff", }; struct PatchEntry { @@ -982,7 +984,7 @@ { WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, RESIZE_NONE, 10, 11, 369, 0, 13, STR_CONFIG_PATCHES_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, { WWT_PANEL, RESIZE_NONE, 10, 0, 369, 14, 41, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 380, 0x0, STR_NULL}, +{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 390, 0x0, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 3, 10, 96, 16, 27, STR_CONFIG_PATCHES_GUI, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 3, 97, 183, 16, 27, STR_CONFIG_PATCHES_CONSTRUCTION, STR_NULL}, @@ -994,7 +996,7 @@ }; static const WindowDesc _patches_selection_desc = { - WDP_CENTER, WDP_CENTER, 370, 381, + WDP_CENTER, WDP_CENTER, 370, 391, WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _patches_selection_widgets, Index: src/station.cpp =================================================================== --- src/station.cpp (revision 10586) +++ src/station.cpp (working copy) @@ -50,6 +50,11 @@ last_vehicle_type = VEH_INVALID; + // Create queues + airport_queue = new IndexedQueue; + helicopter_queue = new IndexedQueue; + + random_bits = 0; // Random() must be called when station is really built (DC_EXEC) waiting_triggers = 0; } @@ -77,6 +82,12 @@ /* Subsidies need removal as well */ DeleteSubsidyWithStation(index); + // Remove queues + airport_queue->clear(); + helicopter_queue->clear(); + delete airport_queue; + delete helicopter_queue; + free(speclist); xy = 0; Index: src/station.h =================================================================== --- src/station.h (revision 10586) +++ src/station.h (working copy) @@ -138,6 +138,10 @@ byte facilities; byte airport_type; + // TODO: Update to OOP + IndexedQueue *airport_queue; // airport queue + IndexedQueue *helicopter_queue; // airport queue + /* trainstation width/height */ byte trainst_w, trainst_h; Index: src/station_cmd.cpp =================================================================== --- src/station_cmd.cpp (revision 10586) +++ src/station_cmd.cpp (working copy) @@ -42,6 +42,7 @@ #include "road.h" #include "cargotype.h" #include "strings.h" +#include "queue.h" /** * Called if a new block is added to the station-pool @@ -1641,7 +1642,7 @@ st->airport_tile = tile; st->AddFacility(FACIL_AIRPORT, tile); st->airport_type = (byte)p1; - st->airport_flags = 0; + st->airport_flags = 0LL; // A simple "0" will only clear 32 bits, we use 64 st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY); @@ -1670,6 +1671,9 @@ st_auto_delete.Release(); } + st->airport_queue = new IndexedQueue; + st->helicopter_queue = new IndexedQueue; + return cost; } @@ -1718,6 +1722,18 @@ DeleteStationIfEmpty(st); } + if(st->airport_queue != NULL) { + st->airport_queue->clear(); + delete st->airport_queue; + st->airport_queue = NULL; // Prevent bad pointer + } + + if(st->helicopter_queue != NULL) { + st->helicopter_queue->clear(); + delete st->helicopter_queue; + st->helicopter_queue = NULL; + } + return cost; } @@ -2689,7 +2705,7 @@ MakeOilrig(tile, st->index); st->owner = OWNER_NONE; - st->airport_flags = 0; + st->airport_flags = 0LL; // A simple "0" will only clear 32 bits, we use 64 st->airport_type = AT_OILRIG; st->xy = tile; st->bus_stops = NULL; @@ -2726,7 +2742,7 @@ st->dock_tile = 0; st->airport_tile = 0; st->facilities &= ~(FACIL_AIRPORT | FACIL_DOCK); - st->airport_flags = 0; + st->airport_flags = 0LL; // A simple "0" will only clear 32 bits, we use 64 UpdateStationVirtCoordDirty(st); if (st->facilities == 0) delete st; } @@ -2833,6 +2849,10 @@ } for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache(); + + // Create new queues for loaded stations + st->airport_queue = new IndexedQueue; + st->helicopter_queue = new IndexedQueue; } } Index: src/variables.h =================================================================== --- src/variables.h (revision 10586) +++ src/variables.h (working copy) @@ -175,6 +175,9 @@ bool extra_dynamite; // extra dynamite bool road_stop_on_town_road; // allow building of drive-through road stops on town owned roads + bool aircraft_queueing; // Queue aircraft at airports. + uint aircraft_speed_coeff; // Coefficient of aircraft speed, based on Benben's patch + bool never_expire_vehicles; // never expire vehicles byte extend_vehicle_life; // extend vehicle life by this many years Index: src/vehicle.cpp =================================================================== --- src/vehicle.cpp (revision 10586) +++ src/vehicle.cpp (working copy) @@ -151,7 +151,7 @@ const TileInfo *ti = (const TileInfo*)data; if (v->tile != ti->tile || v->type == VEH_DISASTER) return NULL; - if (v->z_pos > ti->z) return NULL; + if (v->z_pos > (int)(ti->z)) return NULL; _error_message = VehicleInTheWayErrMsg(v); return v; @@ -303,6 +303,8 @@ v->group_id = DEFAULT_GROUP; v->fill_percent_te_id = INVALID_TE_ID; + v->queue_item = NULL; + return v; } Index: src/vehicle.h =================================================================== --- src/vehicle.h (revision 10586) +++ src/vehicle.h (working copy) @@ -11,6 +11,7 @@ #include "road.h" #include "cargopacket.h" #include "texteff.hpp" +#include "indexed_queue.hpp" /** The returned bits of VehicleEnterTile. */ enum VehicleEnterTileStatus { @@ -182,6 +183,9 @@ byte previous_pos; StationID targetairport; byte state; + uint16 desired_speed; // Speed aircraft desires to maintain, used to + // decrease traffic to busy airports. + }; struct VehicleRoad { @@ -236,7 +240,7 @@ int32 x_pos; // coordinates int32 y_pos; - byte z_pos; + int32 z_pos; // Was byte, changed for aircraft queueing DirectionByte direction; // facing byte spritenum; // currently displayed sprite index @@ -261,8 +265,8 @@ uint16 max_speed; // maximum speed uint16 cur_speed; // current speed byte subspeed; // fractional speed - byte acceleration; // used by train & aircraft - byte progress; + uint16 acceleration; // used by train & aircraft + uint16 progress; uint32 motion_counter; byte vehstatus; // Status @@ -326,6 +330,13 @@ uint32 current_order_time; ///< How many ticks have passed since this order started. int32 lateness_counter; ///< How many ticks late (or early if negative) this vehicle is. + // TODO: bring up to date with OOP + // Current position in a vehicle queue - can only belong to one queue at a time + IndexedItem* queue_item; + + // True if the aircraft is already put on the top of the queue due to a breakdown + bool queue_breakdown; + union { VehicleRail rail; VehicleAir air; Index: src/viewport.cpp =================================================================== --- src/viewport.cpp (revision 10586) +++ src/viewport.cpp (working copy) @@ -68,7 +68,7 @@ TileSpriteToDraw *next; int32 x; int32 y; - byte z; + int32 z; }; struct ChildScreenSpriteToDraw { @@ -92,8 +92,8 @@ int32 ymax; ChildScreenSpriteToDraw *child; byte unk16; - byte zmin; - byte zmax; + int32 zmin; + int32 zmax; }; /* Quick hack to know how much memory to reserve when allocating from the spritelist @@ -462,7 +462,7 @@ _offset_ground_sprites = true; } -static void AddCombinedSprite(SpriteID image, SpriteID pal, int x, int y, byte z) +static void AddCombinedSprite(SpriteID image, SpriteID pal, int x, int y, int32 z) { const ViewportDrawer *vd = _cur_vd; Point pt = RemapCoords(x, y, z); @@ -478,7 +478,7 @@ } -void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, byte dz, byte z) +void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int32 dz, int32 z) { ViewportDrawer *vd = _cur_vd; ParentSpriteToDraw *ps; Index: src/viewport.h =================================================================== --- src/viewport.h (revision 10586) +++ src/viewport.h (working copy) @@ -48,7 +48,7 @@ void DrawGroundSprite(SpriteID image, SpriteID pal); void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z); -void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, byte dz, byte z); +void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, int32 dz, int32 z); void *AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2); void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y);