|
@@ -70,71 +70,48 @@ Station::~Station()
|
|
|
|
|
|
DeleteWindowById(WC_STATION_VIEW, index);
|
|
|
|
|
|
/* Now delete all orders that go to the station */
|
|
|
RemoveOrderFromAllVehicles(OT_GOTO_STATION, index);
|
|
|
|
|
|
/* Subsidies need removal as well */
|
|
|
DeleteSubsidyWithStation(index);
|
|
|
|
|
|
xy = 0;
|
|
|
|
|
|
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
|
|
goods[c].cargo.Truncate(0);
|
|
|
}
|
|
|
|
|
|
this->QuickFree();
|
|
|
}
|
|
|
|
|
|
void Station::QuickFree()
|
|
|
{
|
|
|
DeleteName(this->string_id);
|
|
|
free(this->speclist);
|
|
|
}
|
|
|
|
|
|
void *Station::operator new(size_t size)
|
|
|
{
|
|
|
Station *st = AllocateRaw();
|
|
|
return st;
|
|
|
}
|
|
|
|
|
|
void *Station::operator new(size_t size, int st_idx)
|
|
|
{
|
|
|
if (!AddBlockIfNeeded(&_Station_pool, st_idx))
|
|
|
error("Stations: failed loading savegame: too many stations");
|
|
|
|
|
|
Station *st = GetStation(st_idx);
|
|
|
return st;
|
|
|
}
|
|
|
|
|
|
void Station::operator delete(void *p)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void Station::operator delete(void *p, int st_idx)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
/** 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(byte new_facility_bit, TileIndex facil_xy)
|
|
|
{
|
|
|
if (facilities == 0) {
|
|
|
xy = facil_xy;
|
|
|
random_bits = Random();
|
|
|
}
|
|
|
facilities |= new_facility_bit;
|
|
|
owner = _current_player;
|
|
|
build_date = _date;
|
|
|
}
|
|
|
|
|
|
void Station::MarkDirty() const
|
|
|
{
|
|
|
if (sign.width_1 != 0) {
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, index, 1);
|
|
|
|
|
|
/* We use ZOOM_LVL_MAX here, as every viewport can have an other zoom,
|
|
|
* and there is no way for us to know which is the biggest. So make the
|
|
|
* biggest area dirty, and we are safe for sure. */
|
|
|
MarkAllViewportsDirty(
|
|
|
sign.left - 6,
|
|
|
sign.top,
|
|
@@ -155,72 +132,48 @@ void Station::MarkTilesDirty(bool cargo_
|
|
|
* 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 < trainst_h; h++) {
|
|
|
for (w = 0; w < trainst_w; w++) {
|
|
|
if (TileBelongsToRailStation(tile)) {
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
}
|
|
|
tile += TileDiffXY(1, 0);
|
|
|
}
|
|
|
tile += TileDiffXY(-w, 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool Station::TileBelongsToRailStation(TileIndex tile) const
|
|
|
{
|
|
|
return IsTileType(tile, MP_STATION) && GetStationIndex(tile) == index && IsRailwayStation(tile);
|
|
|
}
|
|
|
|
|
|
/*static*/ Station *Station::AllocateRaw()
|
|
|
{
|
|
|
Station *st = NULL;
|
|
|
|
|
|
/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
|
|
|
* TODO - This is just a temporary stage, this will be removed. */
|
|
|
for (st = GetStation(0); st != NULL; st = (st->index + 1U < GetStationPoolSize()) ? GetStation(st->index + 1U) : NULL) {
|
|
|
if (!st->IsValid()) {
|
|
|
StationID index = st->index;
|
|
|
|
|
|
memset(st, 0, sizeof(Station));
|
|
|
st->index = index;
|
|
|
return st;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Check if we can add a block to the pool */
|
|
|
if (AddBlockToPool(&_Station_pool)) return AllocateRaw();
|
|
|
|
|
|
_error_message = STR_3008_TOO_MANY_STATIONS_LOADING;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
|
|
|
/** Obtain the length of a platform
|
|
|
* @pre tile must be a railway station tile
|
|
|
* @param tile A tile that contains the platform in question
|
|
|
* @return The length of the platform
|
|
|
*/
|
|
|
uint Station::GetPlatformLength(TileIndex tile) const
|
|
|
{
|
|
|
TileIndex t;
|
|
|
TileIndexDiff delta;
|
|
|
uint len = 0;
|
|
|
assert(TileBelongsToRailStation(tile));
|
|
|
|
|
|
delta = (GetRailStationAxis(tile) == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
|
|
|
|
|
|
t = tile;
|
|
|
do {
|
|
|
t -= delta;
|
|
|
len++;
|
|
|
} while (IsCompatibleTrainStationTile(t, tile));
|
|
|
|
|
|
t = tile;
|
|
|
do {
|
|
|
t += delta;
|
|
|
len++;
|
|
@@ -405,136 +358,82 @@ bool StationRect::AfterRemoveTile(Statio
|
|
|
bool StationRect::AfterRemoveRect(Station *st, TileIndex tile, int w, int h)
|
|
|
{
|
|
|
assert(PtInExtendedRect(TileX(tile), TileY(tile)));
|
|
|
assert(PtInExtendedRect(TileX(tile) + w - 1, TileY(tile) + h - 1));
|
|
|
|
|
|
bool empty = AfterRemoveTile(st, tile);
|
|
|
if (w != 1 || h != 1) empty = empty || AfterRemoveTile(st, TILE_ADDXY(tile, w - 1, h - 1));
|
|
|
return empty;
|
|
|
}
|
|
|
|
|
|
StationRect& StationRect::operator = (Rect src)
|
|
|
{
|
|
|
left = src.left;
|
|
|
top = src.top;
|
|
|
right = src.right;
|
|
|
bottom = src.bottom;
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
/* RoadStop implementation */
|
|
|
/************************************************************************/
|
|
|
|
|
|
/** Allocates a new RoadStop onto the pool, or recycles an unsed one
|
|
|
* @return a pointer to the new roadstop
|
|
|
*/
|
|
|
void *RoadStop::operator new(size_t size)
|
|
|
{
|
|
|
RoadStop *rs = AllocateRaw();
|
|
|
return rs;
|
|
|
}
|
|
|
|
|
|
/** Gets a RoadStop with a given index and allocates it when needed
|
|
|
* @return a pointer to the roadstop
|
|
|
*/
|
|
|
void *RoadStop::operator new(size_t size, int index)
|
|
|
{
|
|
|
if (!AddBlockIfNeeded(&_RoadStop_pool, index)) {
|
|
|
error("RoadStops: failed loading savegame: too many RoadStops");
|
|
|
}
|
|
|
|
|
|
RoadStop *rs = GetRoadStop(index);
|
|
|
return rs;
|
|
|
}
|
|
|
|
|
|
void RoadStop::operator delete(void *p)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void RoadStop::operator delete(void *p, int index)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
/** Initializes a RoadStop */
|
|
|
RoadStop::RoadStop(TileIndex tile) :
|
|
|
xy(tile),
|
|
|
status(3), // stop is free
|
|
|
num_vehicles(0),
|
|
|
next(NULL)
|
|
|
{
|
|
|
DEBUG(ms, cDebugCtorLevel, "I+ at %d[0x%x]", tile, tile);
|
|
|
}
|
|
|
|
|
|
/** De-Initializes a RoadStops. This includes clearing all slots that vehicles might
|
|
|
* have and unlinks it from the linked list of road stops at the given station
|
|
|
*/
|
|
|
RoadStop::~RoadStop()
|
|
|
{
|
|
|
/* Clear the slot assignment of all vehicles heading for this road stop */
|
|
|
if (num_vehicles != 0) {
|
|
|
Vehicle *v;
|
|
|
|
|
|
FOR_ALL_VEHICLES(v) {
|
|
|
if (v->type == VEH_ROAD && v->u.road.slot == this) ClearSlot(v);
|
|
|
}
|
|
|
}
|
|
|
assert(num_vehicles == 0);
|
|
|
|
|
|
DEBUG(ms, cDebugCtorLevel , "I- at %d[0x%x]", xy, xy);
|
|
|
|
|
|
xy = INVALID_TILE;
|
|
|
}
|
|
|
|
|
|
/** Low-level function for allocating a RoadStop on the pool */
|
|
|
RoadStop *RoadStop::AllocateRaw()
|
|
|
{
|
|
|
RoadStop *rs;
|
|
|
|
|
|
/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
|
|
|
* TODO - This is just a temporary stage, this will be removed. */
|
|
|
for (rs = GetRoadStop(0); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
|
|
|
if (!rs->IsValid()) {
|
|
|
RoadStopID index = rs->index;
|
|
|
|
|
|
memset(rs, 0, sizeof(*rs));
|
|
|
rs->index = index;
|
|
|
|
|
|
return rs;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Check if we can add a block to the pool */
|
|
|
if (AddBlockToPool(&_RoadStop_pool)) return AllocateRaw();
|
|
|
|
|
|
return NULL;
|
|
|
xy = 0;
|
|
|
}
|
|
|
|
|
|
/** Determines whether a RoadStop is a valid (i.e. existing) one */
|
|
|
bool RoadStop::IsValid() const
|
|
|
{
|
|
|
return xy != INVALID_TILE;
|
|
|
return xy != 0;
|
|
|
}
|
|
|
|
|
|
/** Checks whether there is a free bay in this road stop */
|
|
|
bool RoadStop::HasFreeBay() const
|
|
|
{
|
|
|
return GB(status, 0, MAX_BAY_COUNT) != 0;
|
|
|
}
|
|
|
|
|
|
/** Checks whether the given bay is free in this road stop */
|
|
|
bool RoadStop::IsFreeBay(uint nr) const
|
|
|
{
|
|
|
assert(nr < MAX_BAY_COUNT);
|
|
|
return HASBIT(status, nr);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Allocates a bay
|
|
|
* @return the allocated bay number
|
|
|
* @pre this->HasFreeBay()
|
|
|
*/
|
|
|
uint RoadStop::AllocateBay()
|
|
|
{
|
|
|
assert(HasFreeBay());
|
|
|
|