diff --git a/findversion.sh b/findversion.sh old mode 100644 new mode 100755 diff --git a/src/aircraft.h b/src/aircraft.h index 2aa05ace57..603d78f8bc 100644 --- a/src/aircraft.h +++ b/src/aircraft.h @@ -127,4 +127,6 @@ struct Aircraft : public Vehicle { void OnNewDay(); }; +Station *GetTargetAirportIfValid(const Vehicle *v); + #endif /* AIRCRAFT_H */ diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index a858d162f3..8b3bdec89d 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -595,9 +595,9 @@ CommandCost CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uin } else { bool next_airport_has_hangar = true; StationID next_airport_index = v->u.air.targetairport; - const Station *st = GetStation(next_airport_index); + const Station *st = GetTargetAirportIfValid(v); /* If the station is not a valid airport or if it has no hangars */ - if (!st->IsValid() || st->airport_tile == 0 || st->Airport()->nof_depots == 0) { + if (st == NULL || st->Airport()->nof_depots == 0) { /* the aircraft has to search for a hangar on its own */ StationID station = FindNearestHangar(v); @@ -1023,9 +1023,16 @@ static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc) assert(v != NULL); assert(apc != NULL); - const Station *st = GetStation(v->u.air.targetairport); - /* Make sure we don't go to 0,0 if the airport has been removed. */ - TileIndex tile = (st->airport_tile != 0) ? st->airport_tile : st->xy; + /* In the case the station doesn't exit anymore, set target tile 0. + * It doesn't hurt much, aircraft will go to next order, nearest hangar + * or it will simply crash in next tick */ + TileIndex tile = 0; + + if (IsValidStationID(v->u.air.targetairport)) { + const Station *st = GetStation(v->u.air.targetairport); + /* Make sure we don't go to 0,0 if the airport has been removed. */ + tile = (st->airport_tile != 0) ? st->airport_tile : st->xy; + } int delta_x = v->x_pos - TileX(tile) * TILE_SIZE; int delta_y = v->y_pos - TileY(tile) * TILE_SIZE; @@ -1051,15 +1058,22 @@ static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc) static bool AircraftController(Vehicle *v) { int count; - const Station *st = GetStation(v->u.air.targetairport); - const AirportFTAClass *afc = st->Airport(); - const AirportMovingData *amd; + + StationID target = v->u.air.targetairport; + + /* NULL if station is invalid */ + const Station *st = IsValidStationID(target) ? GetStation(target) : NULL; + /* 0 if there is no station */ + TileIndex tile = 0; + if (st != NULL) { + tile = st->airport_tile; + if (tile == 0) tile = st->xy; + } + /* DUMMY if there is no station or no airport */ + const AirportFTAClass *afc = tile == 0 ? GetAirport(AT_DUMMY) : st->Airport(); /* prevent going to 0,0 if airport is deleted. */ - TileIndex tile = st->airport_tile; - if (tile == 0) { - tile = st->xy; - + if (st == NULL || st->airport_tile == 0) { /* Jump into our "holding pattern" state machine if possible */ if (v->u.air.pos >= afc->nofelements) { v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, afc); @@ -1075,7 +1089,7 @@ static bool AircraftController(Vehicle *v) } /* get airport moving data */ - amd = afc->MovingData(v->u.air.pos); + const AirportMovingData *amd = afc->MovingData(v->u.air.pos); int x = TileX(tile) * TILE_SIZE; int y = TileY(tile) * TILE_SIZE; @@ -1107,7 +1121,7 @@ static bool AircraftController(Vehicle *v) /* Helicopter landing. */ if (amd->flag & AMED_HELI_LOWER) { - if (st->airport_tile == 0) { + if (st == NULL) { /* FIXME - AircraftController -> if station no longer exists, do not land * 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 */ @@ -1118,7 +1132,7 @@ static bool AircraftController(Vehicle *v) } /* Vehicle is now at the airport. */ - v->tile = st->airport_tile; + v->tile = tile; /* Find altitude of landing position. */ int z = GetSlopeZ(x, y) + 1 + afc->delta_z; @@ -1272,10 +1286,10 @@ static void HandleCrashedAircraft(Vehicle *v) { v->u.air.crashed_counter++; - Station *st = GetStation(v->u.air.targetairport); + Station *st = GetTargetAirportIfValid(v); /* make aircraft crash down to the ground */ - if (v->u.air.crashed_counter < 500 && st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) { + if (v->u.air.crashed_counter < 500 && st == NULL && ((v->u.air.crashed_counter % 3) == 0) ) { uint z = GetSlopeZ(v->x_pos, v->y_pos); v->z_pos -= 1; if (v->z_pos == z) { @@ -1306,9 +1320,11 @@ static void HandleCrashedAircraft(Vehicle *v) /* clear runway-in on all airports, set by crashing plane * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc. * but they all share the same number */ - CLRBITS(st->airport_flags, RUNWAY_IN_block); - CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport - CLRBITS(st->airport_flags, RUNWAY_IN2_block); // intercontinental + if (st != NULL) { + CLRBITS(st->airport_flags, RUNWAY_IN_block); + CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport + CLRBITS(st->airport_flags, RUNWAY_IN2_block); // intercontinental + } MarkSingleVehicleDirty(v); @@ -1401,8 +1417,8 @@ static void ProcessAircraftOrder(Vehicle *v) * 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) { + const Station *st = GetTargetAirportIfValid(v); + if (st == NULL) { CommandCost ret; PlayerID old_player = _current_player; @@ -1456,16 +1472,15 @@ static void CrashAirplane(Vehicle *v) v->cargo.Truncate(0); v->Next()->cargo.Truncate(0); - const Station *st = GetStation(v->u.air.targetairport); + const Station *st = GetTargetAirportIfValid(v); StringID newsitem; - if (st->airport_tile == 0) { + if (st == NULL) { newsitem = STR_PLANE_CRASH_OUT_OF_FUEL; } else { SetDParam(1, st->index); newsitem = STR_A034_PLANE_CRASH_DIE_IN_FIREBALL; } - SetDParam(1, st->index); AddNewsItem(newsitem, NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), v->index, @@ -1541,7 +1556,8 @@ static void AircraftNextAirportPos_and_Order(Vehicle *v) v->current_order.type == OT_GOTO_DEPOT) v->u.air.targetairport = v->current_order.dest; - const AirportFTAClass *apc = GetStation(v->u.air.targetairport)->Airport(); + const Station *st = GetTargetAirportIfValid(v); + const AirportFTAClass *apc = st == NULL ? GetAirport(AT_DUMMY) : st->Airport(); v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, apc); } @@ -2185,6 +2201,24 @@ void Aircraft::Tick() } +/** Returns aircraft's target station if v->u.air.target_airport + * is a valid station with airport. + * @param v vehicle to get target airport for + * @return pointer to target station, NULL if invalid + */ +Station *GetTargetAirportIfValid(const Vehicle *v) +{ + assert(v->type == VEH_AIRCRAFT); + + StationID sid = v->u.air.targetairport; + + if (!IsValidStationID(sid)) return NULL; + + Station *st = GetStation(sid); + + return st->airport_tile == 0 ? NULL : st; +} + /** need to be called to load aircraft from old version */ void UpdateOldAircraft() { diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 294cda694a..2a6953ee89 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -335,7 +335,7 @@ void ShowRenameWaypointWindow(const Waypoint *wp) int id = wp->index; /* Are we allowed to change the name of the waypoint? */ - if (!CheckTileOwnership(wp->xy)) { + if (!IsTileType(wp->xy, MP_RAILWAY) || !CheckTileOwnership(wp->xy)) { ShowErrorMessage(_error_message, STR_CANT_CHANGE_WAYPOINT_NAME, TileX(wp->xy) * TILE_SIZE, TileY(wp->xy) * TILE_SIZE); return; diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index e94e20868d..84929804ce 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -271,7 +271,7 @@ CommandCost CmdChangePresidentName(TileIndex tile, uint32 flags, uint32 p1, uint free(p->president_name); p->president_name = strdup(_cmd_text); - if (p->name_1 == STR_SV_UNNAMED) { + if (p->name_1 == STR_SV_UNNAMED && p->name == NULL) { char buf[80]; snprintf(buf, lengthof(buf), "%s Transport", _cmd_text); diff --git a/src/openttd.cpp b/src/openttd.cpp index 516f453740..2afe86801c 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1401,6 +1401,14 @@ bool AfterLoadGame() wp->name = CopyFromOldName(wp->string); wp->string = STR_EMPTY; } + + for (uint i = 0; i < GetSignPoolSize(); i++) { + /* invalid signs are determined by si->ower == INVALID_PLAYER now */ + Sign *si = GetSign(i); + if (!si->IsValid() && si->name != NULL) { + si->owner = OWNER_NONE; + } + } } /* convert road side to my format. */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 05c4ceff50..46bb4f44a7 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -493,7 +493,7 @@ CommandCost CmdDeleteOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) } /* Give the item free */ - order->Free(); + delete order; u = GetFirstVehicleFromSharedList(v); DeleteOrderWarnings(u); diff --git a/src/players.cpp b/src/players.cpp index 0d82f822a7..62ca938bda 100644 --- a/src/players.cpp +++ b/src/players.cpp @@ -314,7 +314,7 @@ static void GenerateCompanyName(Player *p) t = ClosestTownFromTile(tile, (uint)-1); - if (IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST+1)) { + if (t->name == NULL && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1)) { str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_PLAYERNAME_START; strp = t->townnameparts; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 9369a45e4d..91378c0c34 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -166,7 +166,8 @@ static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, Roa } } } else { - cost.AddCost(_price.remove_road); + assert(IsDriveThroughStopTile(tile)); + cost.AddCost(_price.remove_road * 2); if (flags & DC_EXEC) { SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); MarkTileDirtyByTile(tile); @@ -468,9 +469,11 @@ CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) } break; case ROAD_TILE_CROSSING: - if (HasTileRoadType(tile, rt)) return_cmd_error(STR_1007_ALREADY_BUILT); all_bits = GetCrossingRoadBits(tile); if (pieces & ComplementRoadBits(all_bits)) goto do_clear; + pieces = all_bits; // we need to pay for both roadbits + + if (HasTileRoadType(tile, rt)) return_cmd_error(STR_1007_ALREADY_BUILT); break; default: @@ -518,15 +521,15 @@ CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) return CommandCost(EXPENSES_CONSTRUCTION, _price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4)); } - case MP_STATION: - if (!IsRoadStop(tile)) goto do_clear; - if (IsDriveThroughStopTile(tile)) { - if (pieces & ~AxisToRoadBits(DiagDirToAxis(GetRoadStopDir(tile)))) goto do_clear; - } else { - if (pieces & ~DiagDirToRoadBits(GetRoadStopDir(tile))) goto do_clear; - } + case MP_STATION: { + if (!IsDriveThroughStopTile(tile)) goto do_clear; + + RoadBits curbits = AxisToRoadBits(DiagDirToAxis(GetRoadStopDir(tile))); + if (pieces & ~curbits) goto do_clear; + pieces = curbits; // we need to pay for both roadbits + if (HasTileRoadType(tile, rt)) return_cmd_error(STR_1007_ALREADY_BUILT); - break; + } break; case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; @@ -612,6 +615,7 @@ do_clear:; } break; case MP_STATION: + assert(IsDriveThroughStopTile(tile)); SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); break; diff --git a/src/station.cpp b/src/station.cpp index a09727b558..bb13b32204 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -31,6 +31,7 @@ #include "variables.h" #include "settings_type.h" #include "command_func.h" +#include "aircraft.h" #include "table/sprites.h" #include "table/strings.h" @@ -73,6 +74,13 @@ Station::~Station() loading_vehicles.front()->LeaveStation(); } + Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_AIRCRAFT && IsNormalAircraft(v) && v->u.air.targetairport == this->index) { + v->u.air.targetairport = INVALID_STATION; + } + } + MarkDirty(); RebuildStationLists(); InvalidateWindowClasses(WC_STATION_LIST); diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index ca49b9673a..3200844756 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -51,6 +51,7 @@ static inline void SetTimetableParams(int param1, int param2, uint32 time) static void DrawTimetableWindow(Window *w) { const Vehicle *v = GetVehicle(w->window_number); + if (WP(w, order_d).sel >= v->num_orders * 2) WP(w, order_d).sel = -1; int selected = WP(w, order_d).sel; SetVScrollCount(w, v->num_orders * 2); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 7c82fc72d2..89744e2b33 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -629,6 +629,13 @@ void Vehicle::PreDestructor() } if (this->type == VEH_ROAD) ClearSlot(this); + if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) { + Station *st = GetTargetAirportIfValid(this); + if (st != NULL) { + const AirportFTA *layout = st->Airport()->layout; + CLRBITS(st->airport_flags, layout[this->u.air.previous_pos].block | layout[this->u.air.pos].block); + } + } if (this->type != VEH_TRAIN || (this->type == VEH_TRAIN && (IsFrontEngine(this) || IsFreeWagon(this)))) { InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile); diff --git a/src/waypoint.cpp b/src/waypoint.cpp index 635d1218fd..b70aa56d56 100644 --- a/src/waypoint.cpp +++ b/src/waypoint.cpp @@ -369,7 +369,7 @@ CommandCost CmdRenameWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 if (!IsValidWaypointID(p1)) return CMD_ERROR; wp = GetWaypoint(p1); - if (!CheckTileOwnership(wp->xy)) return CMD_ERROR; + if (!IsTileType(wp->xy, MP_RAILWAY) || !CheckTileOwnership(wp->xy)) return CMD_ERROR; if (!StrEmpty(_cmd_text)) { if (!IsUniqueWaypointName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);