|
@@ -95,174 +95,176 @@ Station::~Station()
|
|
|
DeleteWindowById(WC_STATION_VIEW, index);
|
|
|
|
|
|
/* Now delete all orders that go to the station */
|
|
|
RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index);
|
|
|
|
|
|
/* Remove all news items */
|
|
|
DeleteStationNews(this->index);
|
|
|
|
|
|
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
|
|
this->goods[c].cargo.Truncate(0);
|
|
|
}
|
|
|
|
|
|
CargoPacket::InvalidateAllFrom(this->index);
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Invalidating of the JoinStation window has to be done
|
|
|
* after removing item from the pool.
|
|
|
* @param index index of deleted item
|
|
|
*/
|
|
|
void BaseStation::PostDestructor(size_t index)
|
|
|
{
|
|
|
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Get the primary road stop (the first road stop) that the given vehicle can load/unload.
|
|
|
* @param v the vehicle to get the first road stop for
|
|
|
* @return the first roadstop that this vehicle can load at
|
|
|
*/
|
|
|
RoadStop *Station::GetPrimaryRoadStop(const RoadVehicle *v) const
|
|
|
{
|
|
|
RoadStop *rs = this->GetPrimaryRoadStop(v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK);
|
|
|
|
|
|
for (; rs != NULL; rs = rs->next) {
|
|
|
/* The vehicle cannot go to this roadstop (different roadtype) */
|
|
|
if ((GetRoadTypes(rs->xy) & v->compatible_roadtypes) == ROADTYPES_NONE) continue;
|
|
|
/* The vehicle is articulated and can therefor not go the a standard road stop */
|
|
|
if (IsStandardRoadStopTile(rs->xy) && v->HasArticulatedPart()) continue;
|
|
|
|
|
|
/* The vehicle can actually go to this road stop. So, return it! */
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
return rs;
|
|
|
}
|
|
|
|
|
|
/** Called when new facility is built on the station. If it is the first facility
|
|
|
/**
|
|
|
* Called when new facility is built on the station. If it is the first facility
|
|
|
* it initializes also 'xy' and 'random_bits' members */
|
|
|
void Station::AddFacility(StationFacility new_facility_bit, TileIndex facil_xy)
|
|
|
{
|
|
|
if (this->facilities == FACIL_NONE) {
|
|
|
this->xy = facil_xy;
|
|
|
this->random_bits = Random();
|
|
|
}
|
|
|
this->facilities |= new_facility_bit;
|
|
|
this->owner = _current_company;
|
|
|
this->build_date = _date;
|
|
|
}
|
|
|
|
|
|
void Station::MarkTilesDirty(bool cargo_change) const
|
|
|
{
|
|
|
TileIndex tile = this->train_station.tile;
|
|
|
int w, h;
|
|
|
|
|
|
if (tile == INVALID_TILE) return;
|
|
|
|
|
|
/* cargo_change is set if we're refreshing the tiles due to cargo moving
|
|
|
* around. */
|
|
|
if (cargo_change) {
|
|
|
/* Don't waste time updating if there are no custom station graphics
|
|
|
* that might change. Even if there are custom graphics, they might
|
|
|
* not change. Unfortunately we have no way of telling. */
|
|
|
if (this->num_specs == 0) return;
|
|
|
}
|
|
|
|
|
|
for (h = 0; h < train_station.h; h++) {
|
|
|
for (w = 0; w < train_station.w; w++) {
|
|
|
if (this->TileBelongsToRailStation(tile)) {
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
}
|
|
|
tile += TileDiffXY(1, 0);
|
|
|
}
|
|
|
tile += TileDiffXY(-w, 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* virtual */ uint Station::GetPlatformLength(TileIndex tile) const
|
|
|
{
|
|
|
assert(this->TileBelongsToRailStation(tile));
|
|
|
|
|
|
TileIndexDiff delta = (GetRailStationAxis(tile) == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
|
|
|
|
|
|
TileIndex t = tile;
|
|
|
uint len = 0;
|
|
|
do {
|
|
|
t -= delta;
|
|
|
len++;
|
|
|
} while (IsCompatibleTrainStationTile(t, tile));
|
|
|
|
|
|
t = tile;
|
|
|
do {
|
|
|
t += delta;
|
|
|
len++;
|
|
|
} while (IsCompatibleTrainStationTile(t, tile));
|
|
|
|
|
|
return len - 1;
|
|
|
}
|
|
|
|
|
|
/* virtual */ uint Station::GetPlatformLength(TileIndex tile, DiagDirection dir) const
|
|
|
{
|
|
|
TileIndex start_tile = tile;
|
|
|
uint length = 0;
|
|
|
assert(IsRailStationTile(tile));
|
|
|
assert(dir < DIAGDIR_END);
|
|
|
|
|
|
do {
|
|
|
length++;
|
|
|
tile += TileOffsByDiagDir(dir);
|
|
|
} while (IsCompatibleTrainStationTile(tile, start_tile));
|
|
|
|
|
|
return length;
|
|
|
}
|
|
|
|
|
|
/** Determines the catchment radius of the station
|
|
|
/**
|
|
|
* Determines the catchment radius of the station
|
|
|
* @return The radius
|
|
|
*/
|
|
|
uint Station::GetCatchmentRadius() const
|
|
|
{
|
|
|
uint ret = CA_NONE;
|
|
|
|
|
|
if (_settings_game.station.modified_catchment) {
|
|
|
if (this->bus_stops != NULL) ret = max<uint>(ret, CA_BUS);
|
|
|
if (this->truck_stops != NULL) ret = max<uint>(ret, CA_TRUCK);
|
|
|
if (this->train_station.tile != INVALID_TILE) ret = max<uint>(ret, CA_TRAIN);
|
|
|
if (this->dock_tile != INVALID_TILE) ret = max<uint>(ret, CA_DOCK);
|
|
|
if (this->airport.tile != INVALID_TILE) ret = max<uint>(ret, this->airport.GetSpec()->catchment);
|
|
|
} else {
|
|
|
if (this->bus_stops != NULL || this->truck_stops != NULL || this->train_station.tile != INVALID_TILE || this->dock_tile != INVALID_TILE || this->airport.tile != INVALID_TILE) {
|
|
|
ret = CA_UNMODIFIED;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Determines catchment rectangle of this station
|
|
|
* @return clamped catchment rectangle
|
|
|
*/
|
|
|
Rect Station::GetCatchmentRect() const
|
|
|
{
|
|
|
assert(!this->rect.IsEmpty());
|
|
|
|
|
|
/* Compute acceptance rectangle */
|
|
|
int catchment_radius = this->GetCatchmentRadius();
|
|
|
|
|
|
Rect ret = {
|
|
|
max<int>(this->rect.left - catchment_radius, 0),
|
|
|
max<int>(this->rect.top - catchment_radius, 0),
|
|
|
min<int>(this->rect.right + catchment_radius, MapMaxX()),
|
|
|
min<int>(this->rect.bottom + catchment_radius, MapMaxY())
|
|
|
};
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/** Rect and pointer to IndustryVector */
|
|
|
struct RectAndIndustryVector {
|
|
|
Rect rect;
|
|
|
IndustryVector *industries_near;
|
|
|
};
|
|
|
|