--- a/src/aircraft_cmd.cpp Wed Jun 13 11:17:30 2007 +0000
+++ b/src/aircraft_cmd.cpp Wed Jun 13 11:45:14 2007 +0000
@@ -33,6 +33,35 @@
#include "spritecache.h"
#include "cargotype.h"
+void Aircraft::UpdateDeltaXY(Direction direction)
+{
+ uint32 x;
+#define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
+ switch (this->subtype) {
+ default: NOT_REACHED();
+ case AIR_AIRCRAFT:
+ case AIR_HELICOPTER:
+ switch (this->u.air.state) {
+ case ENDTAKEOFF:
+ case LANDING:
+ case HELILANDING:
+ case FLYING: x = MKIT(24, 24, -1, -1); break;
+ default: x = MKIT( 2, 2, -1, -1); break;
+ }
+ this->z_height = 5;
+ break;
+ case AIR_SHADOW: this->z_height = 1; x = MKIT(2, 2, 0, 0); break;
+ case AIR_ROTOR: this->z_height = 1; x = MKIT(2, 2, -1, -1); break;
+ }
+#undef MKIT
+
+ this->x_offs = GB(x, 0, 8);
+ this->y_offs = GB(x, 8, 8);
+ this->sprite_width = GB(x, 16, 8);
+ this->sprite_height = GB(x, 24, 8);
+}
+
+
/** this maps the terminal to its corresponding state and block flag
* currently set for 10 terms, 4 helipads */
static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22};
@@ -198,9 +227,9 @@
height = spr->height;
}
-static int32 EstimateAircraftCost(const AircraftVehicleInfo *avi)
+static int32 EstimateAircraftCost(EngineID engine, const AircraftVehicleInfo *avi)
{
- return avi->base_cost * (_eco->GetPrice(CEconomy::AIRCRAFT_BASE) >> 3) >> 5;
+ return GetEngineProperty(engine, 0x0B, avi->base_cost) * (_eco->GetPrice(CEconomy::AIRCRAFT_BASE) >> 3) >> 5;
}
@@ -241,7 +270,7 @@
if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_player)) return_cmd_error(STR_AIRCRAFT_NOT_AVAILABLE);
const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
- int32 value = EstimateAircraftCost(avi);
+ int32 value = EstimateAircraftCost(p1, avi);
/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
if (flags & DC_QUERY_COST) return value;
@@ -269,7 +298,8 @@
Vehicle *u = vl[1]; // shadow
v->unitnumber = unit_num;
- v->type = u->type = VEH_AIRCRAFT;
+ v = new (v) Aircraft();
+ u = new (u) Aircraft();
v->direction = DIR_SE;
v->owner = u->owner = _current_player;
@@ -286,15 +316,8 @@
u->z_pos = GetSlopeZ(x, y);
v->z_pos = u->z_pos + 1;
- v->x_offs = v->y_offs = -1;
// u->delta_x = u->delta_y = 0;
- v->sprite_width = v->sprite_height = 2;
- v->z_height = 5;
-
- u->sprite_width = u->sprite_height = 2;
- u->z_height = 1;
-
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
u->vehstatus = VS_HIDDEN | VS_UNCLICKABLE | VS_SHADOW;
@@ -322,9 +345,11 @@
v->engine_type = p1;
v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER);
+ v->UpdateDeltaXY(INVALID_DIR);
v->value = value;
u->subtype = AIR_SHADOW;
+ u->UpdateDeltaXY(INVALID_DIR);
/* Danger, Will Robinson!
* If the aircraft is refittable, but cannot be refitted to
@@ -404,15 +429,12 @@
u->next = w;
- w->type = VEH_AIRCRAFT;
+ w = new (w) Aircraft();
w->direction = DIR_N;
w->owner = _current_player;
w->x_pos = v->x_pos;
w->y_pos = v->y_pos;
w->z_pos = v->z_pos + 5;
- w->x_offs = w->y_offs = -1;
- w->sprite_width = w->sprite_height = 2;
- w->z_height = 1;
w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
w->spritenum = 0xFF;
w->subtype = AIR_ROTOR;
@@ -420,6 +442,7 @@
w->random_bits = VehicleRandomBits();
/* Use rotor's air.state to store the rotor animation frame */
w->u.air.state = HRS_ROTOR_STOPPED;
+ w->UpdateDeltaXY(INVALID_DIR);
VehiclePositionChanged(w);
}
@@ -597,6 +620,7 @@
* @param p2 various bitstuffed elements
* - p2 = (bit 0-7) - the new cargo type to refit to
* - p2 = (bit 8-15) - the new cargo subtype to refit to
+ * - p2 = (bit 16) - refit only this vehicle (ignored)
* @return cost of refit or error
*/
int32 CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
@@ -695,6 +719,7 @@
if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) {
// printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
// v->u.air.targetairport = st->index;
+ if (v->current_order.type == OT_LOADING) v->LeaveStation();
v->current_order.type = OT_GOTO_DEPOT;
v->current_order.flags = OF_NON_STOP;
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
@@ -1068,6 +1093,7 @@
* helicopter will circle until sign disappears, then go to next order
* what to do when it is the only order left, right now it just stays in 1 place */
v->u.air.state = FLYING;
+ UpdateAircraftCache(v);
AircraftNextAirportPos_and_Order(v);
return false;
}
@@ -1182,6 +1208,7 @@
if (st->airport_tile == 0) {
/* Airport has been removed, abort the landing procedure */
v->u.air.state = FLYING;
+ UpdateAircraftCache(v);
AircraftNextAirportPos_and_Order(v);
/* get aircraft back on running altitude */
SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
@@ -1384,50 +1411,11 @@
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
}
-/** Mark all views dirty for an aircraft.
- * @param v vehicle to be redrawn.
- */
-static void MarkAircraftDirty(Vehicle *v)
-{
- v->cur_image = GetAircraftImage(v, v->direction);
- if (v->subtype == AIR_HELICOPTER) v->next->next->cur_image = GetRotorImage(v);
- MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
-}
-
-static void HandleAircraftLoading(Vehicle *v, int mode)
+void Aircraft::MarkDirty()
{
- switch (v->current_order.type) {
- case OT_LOADING: {
- if (mode != 0) return;
- if (--v->load_unload_time_rem != 0) return;
-
- if (CanFillVehicle(v) && (
- v->current_order.flags & OF_FULL_LOAD ||
- (_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED))
- )) {
- SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC);
- if (LoadUnloadVehicle(v, false)) {
- InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
- MarkAircraftDirty(v);
- }
- return;
- }
-
- Order b = v->current_order;
- v->LeaveStation();
- v->current_order.Free();
- MarkAircraftDirty(v);
- if (!(b.flags & OF_NON_STOP)) return;
- break;
- }
-
- case OT_DUMMY: break;
-
- default: return;
- }
-
- v->cur_order_index++;
- InvalidateVehicleOrder(v);
+ this->cur_image = GetAircraftImage(this, this->direction);
+ if (this->subtype == AIR_HELICOPTER) this->next->next->cur_image = GetRotorImage(this);
+ MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1);
}
static void CrashAirplane(Vehicle *v)
@@ -1509,31 +1497,13 @@
0);
}
- Order old_order = v->current_order;
v->BeginLoading();
- v->current_order.flags = 0;
-
- if (old_order.type == OT_GOTO_STATION &&
- v->current_order.dest == v->last_station_visited) {
- v->current_order.flags =
- (old_order.flags & (OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER)) | OF_NON_STOP;
- }
-
- SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC);
- LoadUnloadVehicle(v, true);
- MarkAircraftDirty(v);
- InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
- InvalidateWindowClasses(WC_AIRCRAFT_LIST);
-}
-
-static void AircraftLand(Vehicle *v)
-{
- v->sprite_width = v->sprite_height = 2;
}
static void AircraftLandAirplane(Vehicle *v)
{
- AircraftLand(v);
+ v->UpdateDeltaXY(INVALID_DIR);
+
if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
SndPlayVehicleFx(SND_17_SKID_PLANE, v);
}
@@ -1692,8 +1662,8 @@
static void AircraftEventHandler_StartTakeOff(Vehicle *v, const AirportFTAClass *apc)
{
- v->sprite_width = v->sprite_height = 24; // ??? no idea what this is
v->u.air.state = ENDTAKEOFF;
+ v->UpdateDeltaXY(INVALID_DIR);
}
static void AircraftEventHandler_EndTakeOff(Vehicle *v, const AirportFTAClass *apc)
@@ -1706,15 +1676,16 @@
static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc)
{
const Player* p = GetPlayer(v->owner);
- v->sprite_width = v->sprite_height = 24; // ??? no idea what this is
v->u.air.state = FLYING;
+ v->UpdateDeltaXY(INVALID_DIR);
+
/* get the next position to go to, differs per airport */
AircraftNextAirportPos_and_Order(v);
/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
* unless it is due for renewal but the engine is no longer available */
if (v->owner == _local_player && (
- EngineHasReplacementForPlayer(p, v->engine_type) ||
+ EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) ||
((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) &&
HASBIT(GetEngine(v->engine_type)->player_avail, _local_player))
)) {
@@ -1765,13 +1736,14 @@
static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *apc)
{
+ v->u.air.state = ENDLANDING;
AircraftLandAirplane(v); // maybe crash airplane
- v->u.air.state = ENDLANDING;
+
/* 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) ||
+ 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;
@@ -1783,8 +1755,8 @@
static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc)
{
- AircraftLand(v); // helicopters don't crash
v->u.air.state = HELIENDLANDING;
+ v->UpdateDeltaXY(INVALID_DIR);
}
static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *apc)
@@ -1885,7 +1857,7 @@
byte prev_state = v->u.air.state;
_aircraft_state_handlers[v->u.air.state](v, apc);
if (v->u.air.state != FLYING) v->u.air.previous_pos = prev_pos;
- if (v->u.air.state != prev_state) UpdateAircraftCache(v);
+ if (v->u.air.state != prev_state || v->u.air.pos != prev_pos) UpdateAircraftCache(v);
return true;
}
@@ -1895,6 +1867,7 @@
if (current->next == NULL) {
if (AirportSetBlocks(v, current, apc)) {
v->u.air.pos = current->next_position;
+ UpdateAircraftCache(v);
} // move to next position
return false;
}
@@ -1905,6 +1878,7 @@
if (v->u.air.state == current->heading || current->heading == TO_ALL) {
if (AirportSetBlocks(v, current, apc)) {
v->u.air.pos = current->next_position;
+ UpdateAircraftCache(v);
} // move to next position
return false;
}
@@ -2132,7 +2106,7 @@
HandleAircraftSmoke(v);
ProcessAircraftOrder(v);
- HandleAircraftLoading(v, loop);
+ v->HandleLoading(loop != 0);
if (v->current_order.type >= OT_LOADING) return;
@@ -2209,6 +2183,7 @@
if (v->u.air.state >= FLYING) { // circle around
v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, ap);
v->u.air.state = FLYING;
+ UpdateAircraftCache(v);
/* landing plane needs to be reset to flying height (only if in pause mode upgrade,
* in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING */
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
@@ -2222,6 +2197,7 @@
for (uint cnt = 0; cnt < ap->nofelements; cnt++) {
if (ap->layout[cnt].heading == takeofftype) {
v->u.air.pos = ap->layout[cnt].position;
+ UpdateAircraftCache(v);
break;
}
}