diff -r 45d0233e7d79 -r 187e3ef04cc9 src/aircraft_cmd.cpp --- a/src/aircraft_cmd.cpp Sat Mar 03 20:33:32 2007 +0000 +++ b/src/aircraft_cmd.cpp Sun Mar 04 04:25:36 2007 +0000 @@ -390,6 +390,9 @@ v->random_bits = VehicleRandomBits(); u->random_bits = VehicleRandomBits(); + v->vehicle_flags = 0; + if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); + VehiclePositionChanged(v); VehiclePositionChanged(u); @@ -859,21 +862,35 @@ } } -/** Special velocities for aircraft +/** + * Special velocities for aircraft */ enum AircraftSpeedLimits { - SPEED_LIMIT_NONE = 0, ///< No environmental speed limit. Speed limit is type dependent - SPEED_LIMIT_TAXI = 12, ///< Maximum speed of an aircraft while taxiing - SPEED_LIMIT_BROKEN = 27, ///< Maximum speed of an aircraft that is broken + SPEED_LIMIT_TAXI = 50, ///< Maximum speed of an aircraft while taxiing + 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 + SPEED_LIMIT_NONE = 0xFFFF ///< No environmental speed limit. Speed limit is type dependent }; -static bool UpdateAircraftSpeed(Vehicle *v, uint speed_limit) +/** + * Sets the new speed for an aircraft + * @param v The vehicle for which the speed should be obtained + * @param speed_limit The maximum speed the vehicle may have. + * @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) { - uint spd = v->acceleration * 2; + uint spd = v->acceleration * 16; byte t; + speed_limit = min(speed_limit, v->max_speed); + v->subspeed = (t=v->subspeed) + (byte)spd; - if (speed_limit == SPEED_LIMIT_NONE) speed_limit = v->max_speed; + + 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); /* adjust speed for broken vehicles */ @@ -888,13 +905,9 @@ if (!(v->direction & 1)) spd = spd * 3 / 4; - if (spd == 0) return false; - - if ((byte)++spd == 0) return true; - - v->progress = (t = v->progress) - (byte)spd; - - return t < v->progress; + spd += v->progress; + v->progress = (byte)spd; + return spd >> 8; } /** @@ -919,20 +932,28 @@ case DIR_NE: case DIR_E: case DIR_SE: - base_altitude += 15; + base_altitude += 10; break; default: break; } /* Make faster planes fly higher so that they can overtake slower ones */ - base_altitude += min(30 * (v->max_speed / 37), 90); + base_altitude += min(20 * (v->max_speed / 200), 90); return base_altitude; } +/** + * Controls the movement of an aircraft. This function actually moves the vehicle + * on the map and takes care of minor things like sound playback. + * @todo De-mystify the cur_speed values for helicopter rotors. + * @param v The vehicle that is moved. Must be the first vehicle of the chain + * @return Whether the position requested by the State Machine has been reached + */ static bool AircraftController(Vehicle *v) { + int count; const Station *st = GetStation(v->u.air.targetairport); /* prevent going to 0,0 if airport is deleted. */ @@ -955,7 +976,8 @@ if (--u->cur_speed == 32) SndPlayVehicleFx(SND_18_HELICOPTER, v); } else { u->cur_speed = 32; - if (UpdateAircraftSpeed(v, SPEED_LIMIT_NONE)) { + count = UpdateAircraftSpeed(v); + if (count > 0) { v->tile = 0; /* Reached altitude? */ @@ -963,7 +985,7 @@ v->cur_speed = 0; return true; } - SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos+1); + SetAircraftPosition(v, v->x_pos, v->y_pos, min(v->z_pos + count, 184)); } } return false; @@ -971,7 +993,8 @@ /* Helicopter landing. */ if (amd->flag & AMED_HELI_LOWER) { - if (UpdateAircraftSpeed(v, SPEED_LIMIT_NONE)) { + count = UpdateAircraftSpeed(v); + if (count > 0) { if (st->airport_tile == 0) { /* FIXME - AircraftController -> if station no longer exists, do not land * helicopter will circle until sign disappears, then go to next order @@ -985,7 +1008,7 @@ v->tile = st->airport_tile; /* Find altitude of landing position. */ - uint z = GetSlopeZ(x, y) + 1 + afc->delta_z; + int z = GetSlopeZ(x, y) + 1 + afc->delta_z; if (z == v->z_pos) { Vehicle *u = v->next->next; @@ -994,9 +1017,9 @@ if (u->cur_speed >= 80) return true; u->cur_speed += 4; } else if (v->z_pos > z) { - SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos-1); + SetAircraftPosition(v, v->x_pos, v->y_pos, max(v->z_pos - count, z)); } else { - SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos+1); + SetAircraftPosition(v, v->x_pos, v->y_pos, min(v->z_pos + count, z)); } } return false; @@ -1006,8 +1029,7 @@ uint dist = myabs(x + amd->x - v->x_pos) + myabs(y + amd->y - v->y_pos); /* Need exact position? */ - if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U)) - return true; + if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U)) return true; /* At final pos? */ if (dist == 0) { @@ -1029,71 +1051,82 @@ return false; } - if (!UpdateAircraftSpeed(v, ((amd->flag & AMED_NOSPDCLAMP) == 0) ? SPEED_LIMIT_TAXI : SPEED_LIMIT_NONE)) return false; + uint speed_limit = SPEED_LIMIT_TAXI; + bool hard_limit = true; + + if (amd->flag & AMED_NOSPDCLAMP) speed_limit = SPEED_LIMIT_NONE; + if (amd->flag & AMED_HOLD) { speed_limit = SPEED_LIMIT_HOLD; hard_limit = false; } + 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; } + + count = UpdateAircraftSpeed(v, speed_limit, hard_limit); + if (count == 0) return false; if (v->load_unload_time_rem != 0) v->load_unload_time_rem--; - /* Turn. Do it slowly if in the air. */ - Direction newdir = GetDirectionTowards(v, x + amd->x, y + amd->y); - if (newdir != v->direction) { - if (amd->flag & AMED_SLOWTURN) { - if (v->load_unload_time_rem == 0) v->load_unload_time_rem = 8; - v->direction = newdir; - } else { - v->cur_speed >>= 1; + do { + /* Turn. Do it slowly if in the air. */ + Direction newdir = GetDirectionTowards(v, x + amd->x, y + amd->y); + if (newdir != v->direction) { v->direction = newdir; - } - } - - /* Move vehicle. */ - GetNewVehiclePosResult gp = GetNewVehiclePos(v); - v->tile = gp.new_tile; - - /* If vehicle is in the air, use tile coordinate 0. */ - if (amd->flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0; - - /* Adjust Z for land or takeoff? */ - uint z = v->z_pos; - - if (amd->flag & AMED_TAKEOFF) { - z = min(z + 2, GetAircraftFlyingAltitude(v)); - } - - if (amd->flag & AMED_LAND) { - if (st->airport_tile == 0) { - v->u.air.state = FLYING; - AircraftNextAirportPos_and_Order(v); - /* get aircraft back on running altitude */ - SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); - return false; + if (amd->flag & AMED_SLOWTURN) { + if (v->load_unload_time_rem == 0) v->load_unload_time_rem = 8; + } else { + v->cur_speed >>= 1; + } } - uint curz = GetSlopeZ(x, y) + 1; - - if (curz > z) { - z++; - } else { - int t = max(1U, dist - 4); + /* Move vehicle. */ + GetNewVehiclePosResult gp = GetNewVehiclePos(v); + v->tile = gp.new_tile; + /* If vehicle is in the air, use tile coordinate 0. */ + // if (amd->flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0; - z -= ((z - curz) + t - 1) / t; - if (z < curz) z = curz; - } - } + /* Adjust Z for land or takeoff? */ + uint z = v->z_pos; - /* We've landed. Decrase speed when we're reaching end of runway. */ - if (amd->flag & AMED_BRAKE) { - uint curz = GetSlopeZ(x, y) + 1; - - if (z > curz) { - z--; - } else if (z < curz) { - z++; + if (amd->flag & AMED_TAKEOFF) { + z = min(z + 2, GetAircraftFlyingAltitude(v)); } - if (dist < 64 && v->cur_speed > 12) v->cur_speed -= 4; - } + if ((amd->flag & AMED_HOLD) && (z > 150)) z--; - SetAircraftPosition(v, gp.x, gp.y, z); + if (amd->flag & AMED_LAND) { + if (st->airport_tile == 0) { + /* Airport has been removed, abort the landing procedure */ + v->u.air.state = FLYING; + AircraftNextAirportPos_and_Order(v); + /* get aircraft back on running altitude */ + SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); + continue; + } + + uint curz = GetSlopeZ(x, y) + 1; + + if (curz > z) { + z++; + } else { + int t = max(1U, dist - 4); + + z -= ((z - curz) + t - 1) / t; + if (z < curz) z = curz; + } + } + + /* We've landed. Decrase speed when we're reaching end of runway. */ + if (amd->flag & AMED_BRAKE) { + uint curz = GetSlopeZ(x, y) + 1; + + if (z > curz) { + z--; + } else if (z < curz) { + z++; + } + + } + + SetAircraftPosition(v, gp.x, gp.y, z); + } while (--count != 0); return false; } @@ -1215,14 +1248,39 @@ const Order *order = GetVehicleOrder(v, v->cur_order_index); - if (order == NULL) { - v->current_order.type = OT_NOTHING; - v->current_order.flags = 0; + if (order == NULL|| (order->type == OT_DUMMY && !CheckForValidOrders(v))) { + /* + * We do not have an order. This can be divided into two cases: + * 1) we are heading to an invalid station. In this case we must + * find another airport to go to. If there is nowhere to go, + * we will destroy the aircraft as it otherwise will enter + * the holding pattern for the first airport, which can cause + * the plane to go into an undefined state when building an + * airport with the same StationID. + * 2) we are (still) heading to a (still) valid airport, then we + * can continue going there. This can happen when you are + * changing the aircraft's orders while in-flight or in for + * example a depot. However, when we have a current order to + * go to a depot, we have to keep that order so the aircraft + * actually stops. + */ + const Station *st = GetStation(v->u.air.targetairport); + if (!st->IsValid() || st->airport_tile == 0) { + int32 ret; + PlayerID old_player = _current_player; + + _current_player = v->owner; + ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR); + _current_player = old_player; + + if (CmdFailed(ret)) CrashAirplane(v); + } else if (v->current_order.type != OT_GOTO_DEPOT) { + v->current_order.type = OT_NOTHING; + v->current_order.flags = 0; + } return; } - if (order->type == OT_DUMMY && !CheckForValidOrders(v)) CrashAirplane(v); - if (order->type == v->current_order.type && order->flags == v->current_order.flags && order->dest == v->current_order.dest) @@ -1259,7 +1317,7 @@ if (CanFillVehicle(v) && ( v->current_order.flags & OF_FULL_LOAD || - (_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED)) + (_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)) )) { SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); if (LoadUnloadVehicle(v, false)) { @@ -2039,7 +2097,7 @@ AgeAircraftCargo(v); - for (uint i = 0; i != 6; i++) { + for (uint i = 0; i != 2; i++) { AircraftEventHandler(v, i); if (v->type != VEH_Aircraft) // In case it was deleted break;