57 #include "table/strings.h"
109 if (!T::IsValidID(t))
continue;
111 if (closest_station == INVALID_STATION) {
113 }
else if (closest_station != t) {
118 *st = (closest_station == INVALID_STATION) ? NULL : T::Get(closest_station);
139 for (
int dx = -3; dx <= 3; dx++) {
140 for (
int dy = -3; dy <= 3; dy++) {
196 #define M(x) ((x) - STR_SV_STNAME)
201 STATIONNAMING_AIRPORT,
202 STATIONNAMING_OILRIG,
204 STATIONNAMING_HELIPORT,
229 if (
GetIndustrySpec(indtype)->station_name == STR_UNDEFINED)
return false;
233 sni->
free_names &= ~(1 << M(STR_SV_STNAME_OILFIELD) | 1 << M(STR_SV_STNAME_MINES));
239 static const uint32 _gen_station_name_bits[] = {
242 1U << M(STR_SV_STNAME_AIRPORT),
243 1U << M(STR_SV_STNAME_OILFIELD),
244 1U << M(STR_SV_STNAME_DOCKS),
245 1U << M(STR_SV_STNAME_HELIPORT),
249 uint32 free_names = UINT32_MAX;
252 memset(indtypes, 0,
sizeof(indtypes));
255 FOR_ALL_STATIONS(s) {
256 if (s != st && s->
town == t) {
257 if (s->
indtype != IT_INVALID) {
260 if (name != STR_UNDEFINED) {
271 if (str == M(STR_SV_STNAME_FOREST)) {
272 str = M(STR_SV_STNAME_WOODS);
288 return STR_SV_STNAME_FALLBACK;
296 uint32 tmp = free_names & _gen_station_name_bits[name_class];
300 if (
HasBit(free_names, M(STR_SV_STNAME_MINES))) {
302 return STR_SV_STNAME_MINES;
308 if (
HasBit(free_names, M(STR_SV_STNAME)))
return STR_SV_STNAME;
310 if (
HasBit(free_names, M(STR_SV_STNAME_CENTRAL)))
return STR_SV_STNAME_CENTRAL;
314 if (
HasBit(free_names, M(STR_SV_STNAME_LAKESIDE)) &&
317 return STR_SV_STNAME_LAKESIDE;
321 if (
HasBit(free_names, M(STR_SV_STNAME_WOODS)) && (
332 if (
HasBit(free_names, M(STR_SV_STNAME_VALLEY)))
return STR_SV_STNAME_VALLEY;
334 if (
HasBit(free_names, M(STR_SV_STNAME_HEIGHTS)))
return STR_SV_STNAME_HEIGHTS;
338 static const int8 _direction_and_table[] = {
339 ~( (1 << M(STR_SV_STNAME_WEST)) | (1 << M(STR_SV_STNAME_EAST)) | (1 << M(STR_SV_STNAME_NORTH)) ),
340 ~( (1 << M(STR_SV_STNAME_SOUTH)) | (1 << M(STR_SV_STNAME_WEST)) | (1 << M(STR_SV_STNAME_NORTH)) ),
341 ~( (1 << M(STR_SV_STNAME_SOUTH)) | (1 << M(STR_SV_STNAME_EAST)) | (1 << M(STR_SV_STNAME_NORTH)) ),
342 ~( (1 << M(STR_SV_STNAME_SOUTH)) | (1 << M(STR_SV_STNAME_WEST)) | (1 << M(STR_SV_STNAME_EAST)) ),
345 free_names &= _direction_and_table[
349 tmp = free_names & ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6) | (1 << 7) | (1 << 12) | (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30));
350 return (tmp == 0) ? STR_SV_STNAME_FALLBACK : (STR_SV_STNAME +
FindFirstBit(tmp));
365 FOR_ALL_STATIONS(st) {
369 if (cur_dist < threshold) {
370 threshold = cur_dist;
387 case STATION_AIRPORT:
404 default: NOT_REACHED();
418 pt.y -= 32 * ZOOM_LVL_BASE;
433 FOR_ALL_BASE_STATIONS(st) {
459 for (uint i = 0; i < num_items; i++) {
484 int x1 =
max(x - rad, 0);
487 int y1 =
max(y - rad, 0);
507 FOR_ALL_INDUSTRIES(i) {
530 if (always_accepted != NULL) *always_accepted = 0;
539 int x1 =
max(x - rad, 0);
540 int y1 =
max(y - rad, 0);
547 for (
int yc = y1; yc != y2; yc++) {
548 for (
int xc = x1; xc != x2; xc++) {
550 AddAcceptedCargo(tile, acceptance, always_accepted);
569 if (!st->
rect.IsEmpty()) {
581 uint amt = acceptance[i];
599 if (old_acc == new_acc)
return;
605 static const StringID accept_msg[] = {
606 STR_NEWS_STATION_NOW_ACCEPTS_CARGO,
607 STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO,
609 static const StringID reject_msg[] = {
610 STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO,
611 STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO,
625 accepts[num_acc++] = i;
630 rejects[num_rej++] = i;
644 static void UpdateStationSignCoord(
BaseStation *st)
648 if (r->IsEmpty())
return;
682 CommandCost ret = (*st)->rect.BeforeAddRect(area.
tile, area.
w, area.
h, StationRect::ADD_TEST);
683 if (ret.
Failed())
return ret;
692 (*st)->string_id = GenerateStationName(*st, area.
tile, name_class);
715 UpdateStationSignCoord(st);
736 if (ret.
Failed())
return ret;
759 cost.
AddCost(_price[PR_BUILD_FOUNDATION]);
766 }
else if (allowed_z != flat_z) {
786 if (ret.
Failed())
return ret;
790 if (ret.
Failed())
return ret;
811 static CommandCost CheckFlatLandRailStation(
TileArea tile_area,
DoCommandFlag flags,
Axis axis, StationID *station,
RailType rt,
SmallVector<Train *, 4> &affected_vehicles,
StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
815 uint invalid_dirs = 5 << axis;
822 if (ret.
Failed())
return ret;
828 if (ret.
Failed())
return ret;
839 if (*station == INVALID_STATION) {
841 }
else if (*station != st) {
866 *affected_vehicles.
Append() = v;
870 if (ret.
Failed())
return ret;
877 if (ret.
Failed())
return ret;
904 if (ret.
Failed())
return ret;
923 if (*station == INVALID_STATION) {
925 }
else if (*station != st) {
949 uint num_roadbits = 0;
950 if (build_over_road) {
958 if (ret.
Failed())
return ret;
968 if (ret.
Failed())
return ret;
977 if (ret.
Failed())
return ret;
981 uint roadbits_to_build =
CountBits(rts) * 2 - num_roadbits;
982 cost.
AddCost(_price[PR_BUILD_ROAD] * roadbits_to_build);
1015 static inline byte *CreateSingle(byte *layout,
int n)
1018 do *layout++ = 0;
while (--i);
1019 layout[((n - 1) >> 1) - n] = 2;
1023 static inline byte *CreateMulti(byte *layout,
int n, byte b)
1026 do *layout++ = b;
while (--i);
1029 layout[n - 1 - n] = 0;
1043 if (statspec != NULL && statspec->lengths >= plat_len &&
1044 statspec->platforms[plat_len - 1] >= numtracks &&
1045 statspec->layouts[plat_len - 1][numtracks - 1]) {
1047 memcpy(layout, statspec->layouts[plat_len - 1][numtracks - 1],
1048 plat_len * numtracks);
1052 if (plat_len == 1) {
1053 CreateSingle(layout, numtracks);
1055 if (numtracks & 1) layout = CreateSingle(layout, plat_len);
1058 while (--numtracks >= 0) {
1059 layout = CreateMulti(layout, plat_len, 4);
1060 layout = CreateMulti(layout, plat_len, 6);
1076 template <
class T, StringID error_message>
1079 assert(*st == NULL);
1080 bool check_surrounding =
true;
1083 if (existing_station != INVALID_STATION) {
1084 if (adjacent && existing_station != station_to_join) {
1091 *st = T::GetIfValid(existing_station);
1092 check_surrounding = (*st == NULL);
1097 if (adjacent) check_surrounding =
false;
1101 if (check_surrounding) {
1104 if (ret.
Failed())
return ret;
1108 if (*st == NULL && station_to_join != INVALID_STATION) *st = T::GetIfValid(station_to_join);
1124 return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
1138 return FindJoiningBaseStation<Waypoint, STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST>(existing_waypoint, waypoint_to_join, adjacent, ta, wp);
1161 RailType rt = Extract<RailType, 0, 4>(p1);
1162 Axis axis = Extract<Axis, 4, 1>(p1);
1163 byte numtracks =
GB(p1, 8, 8);
1164 byte plat_len =
GB(p1, 16, 8);
1165 bool adjacent =
HasBit(p1, 24);
1168 byte spec_index =
GB(p2, 8, 8);
1169 StationID station_to_join =
GB(p2, 16, 16);
1173 if (ret.
Failed())
return ret;
1180 if (plat_len == 0 || numtracks == 0)
return CMD_ERROR;
1191 bool reuse = (station_to_join != NEW_STATION);
1192 if (!reuse) station_to_join = INVALID_STATION;
1193 bool distant_join = (station_to_join != INVALID_STATION);
1200 TileArea new_location(tile_org, w_org, h_org);
1203 StationID est = INVALID_STATION;
1207 if (cost.
Failed())
return cost;
1209 cost.
AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len);
1214 if (ret.
Failed())
return ret;
1216 ret =
BuildStationPart(&st, flags, reuse, new_location, STATIONNAMING_RAIL);
1217 if (ret.
Failed())
return ret;
1221 if (ret.
Failed())
return ret;
1229 if (statspec != NULL) {
1244 if (flags & DC_EXEC) {
1247 byte numtracks_orig;
1253 st->
rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
1255 if (statspec != NULL) {
1264 layout_ptr =
AllocaM(byte, numtracks * plat_len);
1267 numtracks_orig = numtracks;
1275 byte layout = *layout_ptr++;
1281 *affected_vehicles.
Append() = v;
1283 for (; v->
Next() != NULL; v = v->
Next()) { }
1308 if (statspec != NULL) {
1323 TriggerStationAnimation(st, tile,
SAT_BUILT);
1331 }
while (--numtracks);
1333 for (uint i = 0; i < affected_vehicles.
Length(); ++i) {
1335 Train *v = affected_vehicles[i];
1338 for (; v->
Next() != NULL; v = v->
Next()) { }
1345 update_reservation_area =
TileArea(tile_org, 1, numtracks_orig);
1347 update_reservation_area =
TileArea(tile_org, numtracks_orig, 1);
1361 platform_begin = next_tile;
1364 platform_end = next_tile;
1368 bool reservation =
false;
1369 for (
TileIndex t = platform_begin; !reservation && t <= platform_end; t += tile_offset) {
1391 static void MakeRailStationAreaSmaller(
BaseStation *st)
1398 if (ta.
w != 0 && ta.
h != 0) {
1472 if (ret.
Failed())
continue;
1475 T *st = T::GetByTile(tile);
1476 if (st == NULL)
continue;
1481 if (ret.
Failed())
continue;
1490 total_cost.
AddCost(-_price[PR_CLEAR_RAIL]);
1508 for (; temp->
Next() != NULL; temp = temp->
Next()) { }
1516 DoClearSquare(tile);
1522 st->rect.AfterRemoveTile(st, tile);
1528 affected_stations.
Include(st);
1534 for (; v->
Next() != NULL; v = v->
Next()) { }
1540 if (quantity == 0)
return error.
Failed() ? error :
CommandCost(STR_ERROR_THERE_IS_NO_STATION);
1542 for (T **stp = affected_stations.
Begin(); stp != affected_stations.
End(); stp++) {
1548 MakeRailStationAreaSmaller(st);
1549 UpdateStationSignCoord(st);
1555 st->UpdateVirtCoord();
1560 total_cost.
AddCost(quantity * removal_cost);
1584 if (ret.
Failed())
return ret;
1587 for (
Station **stp = affected_stations.
Begin(); stp != affected_stations.
End(); stp++) {
1635 if (ret.
Failed())
return ret;
1641 assert(ta.
w != 0 && ta.
h != 0);
1647 if (!st->TileBelongsToRailStation(tile))
continue;
1650 if (ret.
Failed())
return ret;
1652 cost.
AddCost(_price[PR_CLEAR_STATION_RAIL]);
1664 DoClearSquare(tile);
1673 st->rect.AfterRemoveRect(st, st->train_station);
1675 st->train_station.Clear();
1681 st->speclist = NULL;
1682 st->cached_anim_triggers = 0;
1686 st->UpdateVirtCoord();
1740 if (*primary_stop == NULL) {
1742 return primary_stop;
1746 while (stop->
next != NULL) stop = stop->
next;
1764 return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST>(existing_stop, station_to_join, adjacent, ta, st);
1785 bool type =
HasBit(p2, 0);
1786 bool is_drive_through =
HasBit(p2, 1);
1787 RoadTypes rts = Extract<RoadTypes, 2, 2>(p2);
1788 StationID station_to_join =
GB(p2, 16, 16);
1789 bool reuse = (station_to_join != NEW_STATION);
1790 if (!reuse) station_to_join = INVALID_STATION;
1791 bool distant_join = (station_to_join != INVALID_STATION);
1793 uint8 width = (uint8)
GB(p1, 0, 8);
1794 uint8 lenght = (uint8)
GB(p1, 8, 8);
1799 if (width == 0 || lenght == 0)
return CMD_ERROR;
1803 TileArea roadstop_area(tile, width, lenght);
1814 if (is_drive_through) {
1816 axis = Extract<Axis, 6, 1>(p2);
1820 ddir = Extract<DiagDirection, 6, 2>(p2);
1825 if (ret.
Failed())
return ret;
1829 StationID est = INVALID_STATION;
1830 ret =
CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rts);
1831 if (ret.
Failed())
return ret;
1836 if (ret.
Failed())
return ret;
1841 ret =
BuildStationPart(&st, flags, reuse, roadstop_area, STATIONNAMING_ROAD);
1842 if (ret.
Failed())
return ret;
1858 *currstop = road_stop;
1869 st->
rect.BeforeAddTile(cur_tile, StationRect::ADD_TRY);
1872 if (is_drive_through) {
1939 if (ret.
Failed())
return ret;
1954 assert(cur_stop != NULL);
1962 if (ret.
Failed())
return ret;
1966 if (*primary_stop == cur_stop) {
1968 *primary_stop = cur_stop->
next;
1970 if (*primary_stop == NULL) {
1976 while (pred->
next != cur_stop) pred = pred->
next;
1995 DoClearSquare(tile);
2003 FOR_ALL_ROADVEHICLES(v) {
2010 st->
rect.AfterRemoveTile(st, tile);
2041 uint8 width = (uint8)
GB(p1, 0, 8);
2042 uint8 height = (uint8)
GB(p1, 8, 8);
2045 if (width == 0 || height == 0)
return CMD_ERROR;
2049 TileArea roadstop_area(tile, width, height);
2052 CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
2053 bool had_success =
false;
2077 if ((flags &
DC_EXEC) && is_drive_through) {
2079 road_owner, tram_owner);
2093 return had_success ? cost : last_error;
2104 uint mindist = UINT_MAX;
2138 uint noise_reduction = distance / town_tolerance_distance;
2154 Town *t, *nearest = NULL;
2156 uint mindist = UINT_MAX - add;
2162 if (dist < mindist) {
2181 FOR_ALL_STATIONS(st) {
2206 StationID station_to_join =
GB(p2, 16, 16);
2207 bool reuse = (station_to_join != NEW_STATION);
2208 if (!reuse) station_to_join = INVALID_STATION;
2209 bool distant_join = (station_to_join != INVALID_STATION);
2210 byte airport_type =
GB(p1, 0, 8);
2211 byte layout =
GB(p1, 8, 8);
2218 if (ret.
Failed())
return ret;
2235 if (cost.
Failed())
return cost;
2243 StringID authority_refuse_message = STR_NULL;
2244 Town *authority_refuse_town = NULL;
2249 authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE;
2250 authority_refuse_town = nearest;
2256 FOR_ALL_STATIONS(st) {
2260 authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT;
2261 authority_refuse_town = t;
2265 if (authority_refuse_message != STR_NULL) {
2272 if (ret.
Failed())
return ret;
2278 if (ret.
Failed())
return ret;
2285 cost.
AddCost(_price[PR_BUILD_STATION_AIRPORT]);
2298 st->
rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY);
2310 AirportTileAnimationTrigger(st, iter,
AAT_BUILT);
2345 if (ret.
Failed())
return ret;
2369 if (!st->TileBelongsToAirport(tile_cur))
continue;
2372 if (ret.
Failed())
return ret;
2374 cost.
AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
2376 if (flags & DC_EXEC) {
2379 DoClearSquare(tile_cur);
2384 if (flags & DC_EXEC) {
2434 if (ret.
Failed())
return ret;
2453 if ((v->
owner == company) == include_company) {
2455 FOR_VEHICLE_ORDERS(v, order) {
2471 static const byte _dock_w_chk[4] = { 2, 1, 2, 1 };
2472 static const byte _dock_h_chk[4] = { 1, 2, 1, 2 };
2485 StationID station_to_join =
GB(p2, 16, 16);
2486 bool reuse = (station_to_join != NEW_STATION);
2487 if (!reuse) station_to_join = INVALID_STATION;
2488 bool distant_join = (station_to_join != INVALID_STATION);
2500 if (ret.
Failed())
return ret;
2505 if (ret.
Failed())
return ret;
2519 if (ret.
Failed())
return ret;
2527 _dock_w_chk[direction], _dock_h_chk[direction]);
2532 if (ret.
Failed())
return ret;
2538 if (ret.
Failed())
return ret;
2546 st->
rect.BeforeAddRect(dock_area.
tile, dock_area.
w, dock_area.
h, StationRect::ADD_TRY);
2579 if (ret.
Failed())
return ret;
2588 if (ret.
Failed())
return ret;
2591 DoClearSquare(tile1);
2593 MakeWaterKeepingClass(tile2, st->
owner);
2595 st->
rect.AfterRemoveTile(st, tile1);
2596 st->
rect.AfterRemoveTile(st, tile2);
2633 return &_station_display_datas[st][gfx];
2649 case SPR_RAIL_TRACK_X:
2650 snow_desert =
false;
2651 *overlay_offset =
RTO_X;
2654 case SPR_RAIL_TRACK_Y:
2655 snow_desert =
false;
2656 *overlay_offset =
RTO_Y;
2659 case SPR_RAIL_TRACK_X_SNOW:
2661 *overlay_offset =
RTO_X;
2664 case SPR_RAIL_TRACK_Y_SNOW:
2666 *overlay_offset =
RTO_Y;
2689 *ground = snow_desert ? SPR_FLAT_SNOW_DESERT_TILE : SPR_FLAT_GRASS_TILE;
2693 static void DrawTile_Station(
TileInfo *ti)
2701 uint32 relocation = 0;
2702 uint32 ground_relocation = 0;
2705 uint tile_layout = 0;
2717 if (statspec != NULL) {
2754 case APT_RADAR_GRASS_FENCE_SW:
2757 case APT_GRASS_FENCE_NE_FLAG:
2760 case APT_RADAR_FENCE_SW:
2763 case APT_RADAR_FENCE_NE:
2766 case APT_GRASS_FENCE_NE_FLAG_2:
2776 palette = COMPANY_SPRITE_COLOUR(owner);
2779 palette = PALETTE_TO_GREY;
2782 if (layout == NULL && (t == NULL || t->
seq == NULL)) t = GetStationTileLayout(
GetStationType(ti->
tile), gfx);
2792 if (!HasFoundationNW(ti->
tile, slope, z))
SetBit(edge_info, 0);
2793 if (!HasFoundationNE(ti->
tile, slope, z))
SetBit(edge_info, 1);
2795 if (image == 0)
goto draw_default_foundation;
2800 static const uint8 foundation_parts[] = {
2813 static const uint8 composite_foundation_parts[] = {
2815 0x00, 0xD1, 0xE4, 0xE0,
2817 0xCA, 0xC9, 0xC4, 0xC0,
2819 0xD2, 0x91, 0xE4, 0xA0,
2824 uint8 parts = composite_foundation_parts[ti->
tileh];
2835 goto draw_default_foundation;
2839 for (
int i = 0; i < 8; i++) {
2850 draw_default_foundation:
2856 DrawWaterClassGround(ti);
2858 if (sprite != 0) total_offset = sprite - SPR_IMG_BUOY;
2861 DrawWaterClassGround(ti);
2867 DrawShoreTile(ti->
tileh);
2869 DrawClearLandTile(ti, 3);
2873 if (layout != NULL) {
2883 t = &tmp_rail_layout;
2885 }
else if (statspec != NULL) {
2937 int32 total_offset = 0;
2952 DrawSprite(ground + overlay_offset, PAL_NONE, x, y);
2965 static int GetSlopePixelZ_Station(
TileIndex tile, uint x, uint y)
2990 td->
owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
2991 td->
owner[i] = road_owner;
2995 td->
owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
2996 td->
owner[i] = tram_owner;
3038 default: NOT_REACHED();
3039 case STATION_RAIL: str = STR_LAI_STATION_DESCRIPTION_RAILROAD_STATION;
break;
3040 case STATION_AIRPORT:
3041 str = (
IsHangar(tile) ? STR_LAI_STATION_DESCRIPTION_AIRCRAFT_HANGAR : STR_LAI_STATION_DESCRIPTION_AIRPORT);
3043 case STATION_TRUCK: str = STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA;
break;
3044 case STATION_BUS: str = STR_LAI_STATION_DESCRIPTION_BUS_STATION;
break;
3045 case STATION_OILRIG: str = STR_INDUSTRY_NAME_OIL_RIG;
break;
3046 case STATION_DOCK: str = STR_LAI_STATION_DESCRIPTION_SHIP_DOCK;
break;
3047 case STATION_BUOY: str = STR_LAI_STATION_DESCRIPTION_BUOY;
break;
3048 case STATION_WAYPOINT: str = STR_LAI_STATION_DESCRIPTION_WAYPOINT;
break;
3097 static void TileLoop_Station(
TileIndex tile)
3102 case STATION_AIRPORT:
3109 case STATION_OILRIG:
3119 static void AnimateTile_Station(
TileIndex tile)
3122 AnimateStationTile(tile);
3127 AnimateAirportTile(tile);
3132 static bool ClickTile_Station(
TileIndex tile)
3176 }
else if (x < stop) {
3178 uint16 spd =
max(0, (stop - x) * 20 - 15);
3179 if (spd < v->cur_speed) v->
cur_speed = spd;
3208 if (cargoes == 0)
return;
3247 static inline void byte_inc_sat(byte *p)
3264 StationCargoAmountMap waiting_per_source;
3266 for (StationCargoAmountMap::iterator i(waiting_per_source.begin()); i != waiting_per_source.end(); ++i) {
3268 if (source_station == NULL)
continue;
3275 static void UpdateStationRating(
Station *st)
3277 bool waiting_changed =
false;
3279 byte_inc_sat(&st->time_since_load);
3280 byte_inc_sat(&st->time_since_unload);
3283 FOR_ALL_CARGOSPECS(cs) {
3299 waiting_changed =
true;
3318 uint waiting_avg = waiting / (num_dests + 1);
3329 uint32 var10 = (st->last_vehicle_type ==
VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
3333 rating =
GB(callback, 0, 14);
3336 if (
HasBit(callback, 14)) rating -= 0x4000;
3342 if (b >= 0) rating += b >> 2;
3345 if (st->last_vehicle_type ==
VEH_SHIP) waittime >>= 2;
3347 (rating += 25, waittime > 12) ||
3348 (rating += 25, waittime > 6) ||
3349 (rating += 45, waittime > 3) ||
3350 (rating += 35,
true);
3357 (rating += 10,
true);
3364 (rating += 10, age >= 2) ||
3365 (rating += 10, age >= 1) ||
3366 (rating += 13,
true);
3376 if (rating <= 64 && waiting_avg >= 100) {
3377 int dec = Random() & 0x1F;
3378 if (waiting_avg < 200) dec &= 7;
3379 waiting -= (dec + 1) * num_dests;
3380 waiting_changed =
true;
3384 if (rating <= 127 && waiting != 0) {
3385 uint32 r = Random();
3386 if (rating <= (
int)
GB(r, 0, 7)) {
3388 waiting =
max((
int)waiting - (
int)((
GB(r, 8, 2) - 1) * num_dests), 0);
3389 waiting_changed =
true;
3396 static const uint WAITING_CARGO_THRESHOLD = 1 << 12;
3397 static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6;
3398 static const uint MAX_WAITING_CARGO = 1 << 15;
3400 if (waiting > WAITING_CARGO_THRESHOLD) {
3401 uint difference = waiting - WAITING_CARGO_THRESHOLD;
3402 waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
3404 waiting =
min(waiting, MAX_WAITING_CARGO);
3405 waiting_changed =
true;
3410 if (waiting_changed && waiting < ge->cargo.AvailableCount()) {
3424 StationID index = st->
index;
3425 if (waiting_changed) {
3448 for (std::list<Vehicle *>::iterator it(st->loading_vehicles.begin()); it != st->loading_vehicles.end(); ++it) {
3449 for (
Vehicle *v = *it; v != NULL; v = v->
Next()) {
3469 if (lg == NULL)
continue;
3472 Edge edge = it->second;
3481 bool updated =
false;
3483 FOR_ALL_ORDER_LISTS(l) {
3484 bool found_from =
false;
3485 bool found_to =
false;
3487 if (!order->IsType(OT_GOTO_STATION) && !order->IsType(OT_IMPLICIT))
continue;
3488 if (order->GetDestination() == from->
index) {
3490 if (found_to)
break;
3491 }
else if (order->GetDestination() == to->
index) {
3493 if (found_from)
break;
3496 if (!found_to || !found_from)
continue;
3553 DEBUG(misc, 0,
"Can't allocate link graph");
3562 }
else if (ge2.
link_graph == INVALID_LINK_GRAPH) {
3581 (*lg)[ge1.
node].UpdateEdge(ge2.
node, capacity, usage, mode);
3593 for (
const Vehicle *v = front; v != NULL; v = v->
Next()) {
3608 static void StationHandleSmallTick(
BaseStation *st)
3619 void OnTick_Station()
3621 if (_game_mode == GM_EDITOR)
return;
3624 FOR_ALL_BASE_STATIONS(st) {
3625 StationHandleSmallTick(st);
3649 FOR_ALL_STATIONS(st) {
3659 void ModifyStationRatingAround(
TileIndex tile,
Owner owner,
int amount, uint radius)
3663 FOR_ALL_STATIONS(st) {
3664 if (st->
owner == owner &&
3689 if (amount == 0)
return 0;
3701 DEBUG(misc, 0,
"Can't allocate link graph");
3706 if (lg != NULL) (*lg)[ge.
node].UpdateSupply(amount);
3722 static bool IsUniqueStationName(
const char *name)
3726 FOR_ALL_STATIONS(st) {
3727 if (st->
name != NULL && strcmp(st->
name, name) == 0)
return false;
3748 if (ret.
Failed())
return ret;
3754 if (!IsUniqueStationName(text))
return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
3782 uint min_x = (x > max_rad) ? x - max_rad : 0;
3783 uint max_x = x + location.
w + max_rad;
3784 uint min_y = (y > max_rad) ? y - max_rad : 0;
3785 uint max_y = y + location.
h + max_rad;
3792 for (uint cy = min_y; cy < max_y; cy++) {
3793 for (uint cx = min_x; cx < max_x; cx++) {
3799 if (st == NULL)
continue;
3806 if (rad_x < -rad || rad_x >= rad + location.
w)
continue;
3807 if (rad_y < -rad || rad_y >= rad + location.
h)
continue;
3834 if (amount == 0)
return 0;
3838 uint best_rating1 = 0;
3839 uint best_rating2 = 0;
3841 for (
Station *
const *st_iter = all_stations->
Begin(); st_iter != all_stations->
End(); ++st_iter) {
3858 if (st1 == NULL || st->
goods[type].
rating >= best_rating1) {
3859 st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->
goods[type].
rating;
3860 }
else if (st2 == NULL || st->
goods[type].
rating >= best_rating2) {
3866 if (st1 == NULL)
return 0;
3870 amount *= best_rating1 + 1;
3874 return UpdateStationWaiting(st1, type, amount, source_type, source_id);
3878 assert(st1 != NULL);
3879 assert(st2 != NULL);
3880 assert(best_rating1 != 0 || best_rating2 != 0);
3887 uint worst_cargo = amount * best_rating2 / (best_rating1 + best_rating2);
3888 assert(worst_cargo <= (amount - worst_cargo));
3891 uint moved = UpdateStationWaiting(st1, type, amount - worst_cargo, source_type, source_id);
3894 return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);
3900 DEBUG(misc, 0,
"Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
3907 st->
string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG);
3920 st->
rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
3938 st->
rect.AfterRemoveTile(st, tile);
3942 if (!st->
IsInUse())
delete st;
3974 case STATION_WAYPOINT:
4066 case STATION_WAYPOINT:
return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
4067 case STATION_AIRPORT:
return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
4072 case STATION_OILRIG:
4073 SetDParam(1, STR_INDUSTRY_NAME_OIL_RIG);
4092 case STATION_BUOY:
return RemoveBuoy(tile, flags);
4093 case STATION_DOCK:
return RemoveDock(tile, flags);
4108 case STATION_WAYPOINT:
4109 case STATION_RAIL: {
4116 case STATION_AIRPORT:
4144 for (SharesMap::const_iterator it = this->
shares.begin(); it != this->
shares.end(); ++it) {
4145 if (it->second == st) {
4146 return it->first - prev;
4163 assert(!this->
shares.empty());
4166 if (it->second != excluded && it->second != excluded2)
return it->second;
4171 uint end = it->first;
4172 uint begin = (it == this->
shares.begin() ? 0 : (--it)->first);
4173 uint interval = end - begin;
4174 if (interval >= this->
unrestricted)
return INVALID_STATION;
4177 SharesMap::const_iterator it2 = (rand < begin) ? this->
shares.upper_bound(rand) :
4178 this->
shares.upper_bound(rand + interval);
4180 if (it2->second != excluded && it2->second != excluded2)
return it2->second;
4185 uint end2 = it2->first;
4186 uint begin2 = (it2 == this->
shares.begin() ? 0 : (--it2)->first);
4187 uint interval2 = end2 - begin2;
4188 if (interval2 >= new_max)
return INVALID_STATION;
4189 new_max -= interval2;
4190 if (begin > begin2) {
4191 Swap(begin, begin2);
4193 Swap(interval, interval2);
4198 it3 = this->
shares.upper_bound(rand);
4199 }
else if (rand < begin2 - interval) {
4200 it3 = this->
shares.upper_bound(rand + interval);
4202 it3 = this->
shares.upper_bound(rand + interval + interval2);
4215 assert(!this->
shares.empty());
4216 SharesMap new_shares;
4218 for (SharesMap::iterator it(this->
shares.begin()); it != this->
shares.end(); ++it) {
4219 new_shares[++i] = it->second;
4220 if (it->first == this->unrestricted) this->
unrestricted = i;
4222 this->
shares.swap(new_shares);
4236 assert(!this->
shares.empty());
4238 uint removed_shares = 0;
4239 uint added_shares = 0;
4240 uint last_share = 0;
4241 SharesMap new_shares;
4242 for (SharesMap::iterator it(this->
shares.begin()); it != this->
shares.end(); ++it) {
4243 if (it->second == st) {
4245 uint share = it->first - last_share;
4246 if (flow == INT_MIN || (uint)(-flow) >= share) {
4247 removed_shares += share;
4248 if (it->first <= this->unrestricted) this->
unrestricted -= share;
4249 if (flow != INT_MIN) flow += share;
4250 last_share = it->first;
4253 removed_shares += (uint)(-flow);
4255 added_shares += (uint)(flow);
4257 if (it->first <= this->unrestricted) this->
unrestricted += flow;
4263 new_shares[it->first + added_shares - removed_shares] = it->second;
4264 last_share = it->first;
4267 new_shares[last_share + (uint)flow] = st;
4274 this->
shares.swap(new_shares);
4284 assert(!this->
shares.empty());
4286 uint last_share = 0;
4287 SharesMap new_shares;
4288 for (SharesMap::iterator it(this->
shares.begin()); it != this->
shares.end(); ++it) {
4290 if (it->first > this->unrestricted)
return;
4291 if (it->second == st) {
4292 flow = it->first - last_share;
4295 new_shares[it->first] = it->second;
4298 new_shares[it->first - flow] = it->second;
4300 last_share = it->first;
4302 if (flow == 0)
return;
4303 new_shares[last_share + flow] = st;
4304 this->
shares.swap(new_shares);
4305 assert(!this->
shares.empty());
4315 assert(!this->
shares.empty());
4317 uint next_share = 0;
4319 for (SharesMap::reverse_iterator it(this->
shares.rbegin()); it != this->
shares.rend(); ++it) {
4320 if (it->first < this->unrestricted)
return;
4322 flow = next_share - it->first;
4326 if (it->first == this->unrestricted)
return;
4327 if (it->second == st) found =
true;
4329 next_share = it->first;
4331 if (flow == 0)
return;
4332 SharesMap new_shares;
4333 new_shares[flow] = st;
4334 for (SharesMap::iterator it(this->
shares.begin()); it != this->
shares.end(); ++it) {
4335 if (it->second != st) {
4336 new_shares[flow + it->first] = it->second;
4341 this->
shares.swap(new_shares);
4342 assert(!this->
shares.empty());
4352 assert(runtime > 0);
4353 SharesMap new_shares;
4355 for (SharesMap::iterator i = this->
shares.begin(); i != this->
shares.end(); ++i) {
4356 share =
max(share + 1, i->first * 30 / runtime);
4357 new_shares[share] = i->second;
4360 this->
shares.swap(new_shares);
4371 FlowStatMap::iterator origin_it = this->find(origin);
4372 if (origin_it == this->end()) {
4373 this->insert(std::make_pair(origin,
FlowStat(via, flow)));
4375 origin_it->second.ChangeShare(via, flow);
4376 assert(!origin_it->second.GetShares()->empty());
4390 FlowStatMap::iterator prev_it = this->find(origin);
4391 if (prev_it == this->end()) {
4394 this->insert(std::make_pair(origin, fs));
4396 prev_it->second.ChangeShare(via, flow);
4397 prev_it->second.ChangeShare(INVALID_STATION, flow);
4398 assert(!prev_it->second.GetShares()->empty());
4408 for (FlowStatMap::iterator i = this->begin(); i != this->end(); ++i) {
4410 uint local = fs.
GetShare(INVALID_STATION);
4411 if (local > INT_MAX) {
4434 for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
4438 ret.
Push(f_it->first);
4439 this->erase(f_it++);
4453 for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4454 it->second.RestrictShare(via);
4464 for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4465 it->second.ReleaseShare(via);
4476 for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4477 ret += (--(i->second.GetShares()->end()))->first;
4490 for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4491 ret += i->second.GetShare(via);
4503 FlowStatMap::const_iterator i = this->find(from);
4504 if (i == this->end())
return 0;
4505 return (--(i->second.GetShares()->end()))->first;
4516 FlowStatMap::const_iterator i = this->find(from);
4517 if (i == this->end())
return 0;
4518 return i->second.GetShare(via);
4523 GetSlopePixelZ_Station,
4526 GetTileDesc_Station,
4527 GetTileTrackStatus_Station,
4529 AnimateTile_Station,
4531 ChangeTileOwner_Station,
4533 VehicleEnter_Station,
4534 GetFoundation_Station,
4535 TerraformTile_Station,