|
@@ -418,25 +418,25 @@ void Station::GetTileArea(TileArea *ta,
|
|
|
*/
|
|
|
void Station::UpdateVirtCoord()
|
|
|
{
|
|
|
Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
|
|
|
|
|
|
pt.y -= 32;
|
|
|
if ((this->facilities & FACIL_AIRPORT) && this->airport_type == AT_OILRIG) pt.y -= 16;
|
|
|
|
|
|
SetDParam(0, this->index);
|
|
|
SetDParam(1, this->facilities);
|
|
|
this->sign.UpdatePosition(pt.x, pt.y, STR_VIEWPORT_STATION);
|
|
|
|
|
|
InvalidateWindow(WC_STATION_VIEW, this->index);
|
|
|
SetWindowDirty(WC_STATION_VIEW, this->index);
|
|
|
}
|
|
|
|
|
|
/** Update the virtual coords needed to draw the station sign for all stations. */
|
|
|
void UpdateAllStationVirtCoords()
|
|
|
{
|
|
|
BaseStation *st;
|
|
|
|
|
|
FOR_ALL_BASE_STATIONS(st) {
|
|
|
st->UpdateVirtCoord();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -612,25 +612,25 @@ void UpdateStationAcceptance(Station *st
|
|
|
/* Old cargo is no longer accepted */
|
|
|
rejects[num_rej++] = i;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Show news message if there are any changes */
|
|
|
if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
|
|
|
if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
|
|
|
}
|
|
|
|
|
|
/* redraw the station view since acceptance changed */
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ACCEPTLIST);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ACCEPTLIST);
|
|
|
}
|
|
|
|
|
|
static void UpdateStationSignCoord(BaseStation *st)
|
|
|
{
|
|
|
const StationRect *r = &st->rect;
|
|
|
|
|
|
if (r->IsEmpty()) return; // no tiles belong to this station
|
|
|
|
|
|
/* clamp sign coord to be inside the station rect */
|
|
|
st->xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom));
|
|
|
st->UpdateVirtCoord();
|
|
|
}
|
|
@@ -1144,25 +1144,25 @@ CommandCost CmdBuildRailStation(TileInde
|
|
|
if (IsRailStationTile(v->tile)) SetRailStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true);
|
|
|
TryPathReserve(v, true, true);
|
|
|
for (; v->Next() != NULL; v = v->Next()) ;
|
|
|
if (IsRailStationTile(v->tile)) SetRailStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), true);
|
|
|
}
|
|
|
|
|
|
st->MarkTilesDirty(false);
|
|
|
st->UpdateVirtCoord();
|
|
|
UpdateStationAcceptance(st, false);
|
|
|
st->RecomputeIndustriesNear();
|
|
|
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
|
|
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
static void MakeRailStationAreaSmaller(BaseStation *st)
|
|
|
{
|
|
|
TileArea ta = st->train_station;
|
|
|
|
|
|
restart:
|
|
|
|
|
|
/* too small? */
|
|
@@ -1301,25 +1301,25 @@ CommandCost RemoveFromRailBaseStation(Ti
|
|
|
for (T **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
|
|
|
T *st = *stp;
|
|
|
|
|
|
/* now we need to make the "spanned" area of the railway station smaller
|
|
|
* if we deleted something at the edges.
|
|
|
* we also need to adjust train_tile. */
|
|
|
MakeRailStationAreaSmaller(st);
|
|
|
UpdateStationSignCoord(st);
|
|
|
|
|
|
/* if we deleted the whole station, delete the train facility. */
|
|
|
if (st->train_station.tile == INVALID_TILE) {
|
|
|
st->facilities &= ~FACIL_TRAIN;
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
st->UpdateVirtCoord();
|
|
|
DeleteStationIfEmpty(st);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
total_cost.AddCost(quantity * removal_cost);
|
|
|
return total_cost;
|
|
|
}
|
|
|
|
|
|
/** Remove a single tile from a rail station.
|
|
|
* This allows for custom-built station with holes and weird layouts
|
|
|
* @param start tile of station piece to remove
|
|
@@ -1336,25 +1336,25 @@ CommandCost CmdRemoveFromRailStation(Til
|
|
|
if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
|
|
|
|
|
|
TileArea ta(start, end);
|
|
|
SmallVector<Station *, 4> affected_stations;
|
|
|
|
|
|
CommandCost ret = RemoveFromRailBaseStation(ta, affected_stations, flags, _price.remove_rail_station, HasBit(p2, 0));
|
|
|
if (ret.Failed()) return ret;
|
|
|
|
|
|
/* Do all station specific functions here. */
|
|
|
for (Station **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
|
|
|
Station *st = *stp;
|
|
|
|
|
|
if (st->train_station.tile == INVALID_TILE) InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
if (st->train_station.tile == INVALID_TILE) SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
st->MarkTilesDirty(false);
|
|
|
st->RecomputeIndustriesNear();
|
|
|
}
|
|
|
|
|
|
/* Now apply the rail cost to the number that we deleted */
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/** Remove a single tile from a waypoint.
|
|
|
* This allows for custom-built waypoint with holes and weird layouts
|
|
|
* @param start tile of waypoint piece to remove
|
|
|
* @param flags operation to perform
|
|
@@ -1424,25 +1424,25 @@ CommandCost RemoveRailStation(T *st, DoC
|
|
|
|
|
|
st->train_station.tile = INVALID_TILE;
|
|
|
st->train_station.w = 0;
|
|
|
st->train_station.h = 0;
|
|
|
|
|
|
st->facilities &= ~FACIL_TRAIN;
|
|
|
|
|
|
free(st->speclist);
|
|
|
st->num_specs = 0;
|
|
|
st->speclist = NULL;
|
|
|
st->cached_anim_triggers = 0;
|
|
|
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
|
|
|
st->UpdateVirtCoord();
|
|
|
DeleteStationIfEmpty(st);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Remove a rail road station
|
|
|
* @param tile TileIndex been queried
|
|
|
* @param flags operation to perform
|
|
|
* @return cost or failure of operation
|
|
@@ -1627,25 +1627,25 @@ CommandCost CmdBuildRoadStop(TileIndex t
|
|
|
RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
|
|
|
if (is_drive_through) {
|
|
|
MakeDriveThroughRoadStop(tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts, (Axis)p1);
|
|
|
} else {
|
|
|
MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
|
|
|
}
|
|
|
|
|
|
st->UpdateVirtCoord();
|
|
|
UpdateStationAcceptance(st, false);
|
|
|
st->RecomputeIndustriesNear();
|
|
|
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
|
|
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
|
|
|
}
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
|
|
|
static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
|
|
{
|
|
|
if (v->type == VEH_ROAD) RoadVehicle::From(v)->state &= RVSB_ROAD_STOP_TRACKDIR_MASK;
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
@@ -1692,25 +1692,25 @@ static CommandCost RemoveRoadStop(TileIn
|
|
|
*primary_stop = cur_stop->next;
|
|
|
/* removed the only stop? */
|
|
|
if (*primary_stop == NULL) {
|
|
|
st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
|
|
|
}
|
|
|
} else {
|
|
|
/* tell the predecessor in the list to skip this stop */
|
|
|
RoadStop *pred = *primary_stop;
|
|
|
while (pred->next != cur_stop) pred = pred->next;
|
|
|
pred->next = cur_stop->next;
|
|
|
}
|
|
|
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
|
|
|
delete cur_stop;
|
|
|
|
|
|
/* Make sure no vehicle is going to the old roadstop */
|
|
|
RoadVehicle *v;
|
|
|
FOR_ALL_ROADVEHICLES(v) {
|
|
|
if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
|
|
|
v->dest_tile == tile) {
|
|
|
v->dest_tile = v->GetOrderStationLocation(st->index);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
DoClearSquare(tile);
|
|
@@ -1992,28 +1992,28 @@ CommandCost CmdBuildAirport(TileIndex ti
|
|
|
|
|
|
TILE_LOOP(tile_cur, w, h, tile) {
|
|
|
MakeAirport(tile_cur, st->owner, st->index, *b);
|
|
|
b++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
st->UpdateVirtCoord();
|
|
|
UpdateStationAcceptance(st, false);
|
|
|
st->RecomputeIndustriesNear();
|
|
|
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
|
|
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
|
|
|
|
|
|
if (_settings_game.economy.station_noise_level) {
|
|
|
InvalidateWindow(WC_TOWN_VIEW, st->town->index);
|
|
|
SetWindowDirty(WC_TOWN_VIEW, st->town->index);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Remove an airport
|
|
|
* @param tile TileIndex been queried
|
|
|
* @param flags operation to perform
|
|
|
* @return cost or failure of operation
|
|
|
*/
|
|
@@ -2057,28 +2057,28 @@ static CommandCost RemoveAirport(TileInd
|
|
|
|
|
|
/* Go get the final noise level, that is base noise minus factor from distance to town center.
|
|
|
* And as for construction, always remove it, even if the setting is not set, in order to avoid the
|
|
|
* need of recalculation */
|
|
|
Town *nearest = AirportGetNearestTown(afc, tile);
|
|
|
nearest->noise_reached -= GetAirportNoiseLevelForTown(afc, nearest->xy, tile);
|
|
|
|
|
|
st->rect.AfterRemoveRect(st, tile, w, h);
|
|
|
|
|
|
st->airport_tile = INVALID_TILE;
|
|
|
st->facilities &= ~FACIL_AIRPORT;
|
|
|
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
|
|
|
|
|
|
if (_settings_game.economy.station_noise_level) {
|
|
|
InvalidateWindow(WC_TOWN_VIEW, st->town->index);
|
|
|
SetWindowDirty(WC_TOWN_VIEW, st->town->index);
|
|
|
}
|
|
|
|
|
|
st->UpdateVirtCoord();
|
|
|
st->RecomputeIndustriesNear();
|
|
|
DeleteStationIfEmpty(st);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Tests whether the company's vehicles have this station in orders
|
|
@@ -2202,25 +2202,25 @@ CommandCost CmdBuildDock(TileIndex tile,
|
|
|
|
|
|
st->rect.BeforeAddRect(
|
|
|
tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
|
|
|
_dock_w_chk[direction], _dock_h_chk[direction], StationRect::ADD_TRY);
|
|
|
|
|
|
MakeDock(tile, st->owner, st->index, direction, wc);
|
|
|
|
|
|
st->UpdateVirtCoord();
|
|
|
UpdateStationAcceptance(st, false);
|
|
|
st->RecomputeIndustriesNear();
|
|
|
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
|
|
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_SHIPS);
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Remove a dock
|
|
|
* @param tile TileIndex been queried
|
|
|
* @param flags operation to perform
|
|
|
* @return cost or failure of operation
|
|
|
*/
|
|
|
static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
|
|
@@ -2237,25 +2237,25 @@ static CommandCost RemoveDock(TileIndex
|
|
|
if (flags & DC_EXEC) {
|
|
|
DoClearSquare(tile1);
|
|
|
MakeWaterKeepingClass(tile2, st->owner);
|
|
|
|
|
|
st->rect.AfterRemoveTile(st, tile1);
|
|
|
st->rect.AfterRemoveTile(st, tile2);
|
|
|
|
|
|
MarkTileDirtyByTile(tile2);
|
|
|
|
|
|
st->dock_tile = INVALID_TILE;
|
|
|
st->facilities &= ~FACIL_DOCK;
|
|
|
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_SHIPS);
|
|
|
st->UpdateVirtCoord();
|
|
|
st->RecomputeIndustriesNear();
|
|
|
DeleteStationIfEmpty(st);
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_dock);
|
|
|
}
|
|
|
|
|
|
#include "table/station_land.h"
|
|
|
|
|
|
const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
|
|
|
{
|
|
@@ -2814,27 +2814,27 @@ static void UpdateStationRating(Station
|
|
|
|
|
|
waiting = min(waiting, MAX_WAITING_CARGO);
|
|
|
waiting_changed = true;
|
|
|
}
|
|
|
|
|
|
if (waiting_changed) ge->cargo.Truncate(waiting);
|
|
|
}
|
|
|
}
|
|
|
} while (++ge != endof(st->goods));
|
|
|
|
|
|
StationID index = st->index;
|
|
|
if (waiting_changed) {
|
|
|
InvalidateWindow(WC_STATION_VIEW, index); // update whole window
|
|
|
SetWindowDirty(WC_STATION_VIEW, index); // update whole window
|
|
|
} else {
|
|
|
InvalidateWindowWidget(WC_STATION_VIEW, index, SVW_RATINGLIST); // update only ratings list
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, index, SVW_RATINGLIST); // update only ratings list
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* called for every station each tick */
|
|
|
static void StationHandleSmallTick(BaseStation *st)
|
|
|
{
|
|
|
if ((st->facilities & FACIL_WAYPOINT) != 0 || !st->IsInUse()) return;
|
|
|
|
|
|
byte b = st->delete_ctr + 1;
|
|
|
if (b >= 185) b = 0;
|
|
|
st->delete_ctr = b;
|
|
|
|
|
@@ -2882,25 +2882,25 @@ void ModifyStationRatingAround(TileIndex
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
|
|
|
{
|
|
|
st->goods[type].cargo.Append(new CargoPacket(st->index, amount, source_type, source_id));
|
|
|
SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
|
|
|
|
|
|
StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type);
|
|
|
|
|
|
InvalidateWindow(WC_STATION_VIEW, st->index);
|
|
|
SetWindowDirty(WC_STATION_VIEW, st->index);
|
|
|
st->MarkTilesDirty(true);
|
|
|
}
|
|
|
|
|
|
static bool IsUniqueStationName(const char *name)
|
|
|
{
|
|
|
const Station *st;
|
|
|
|
|
|
FOR_ALL_STATIONS(st) {
|
|
|
if (st->name != NULL && strcmp(st->name, name) == 0) return false;
|
|
|
}
|
|
|
|
|
|
return true;
|