31 #include "industry_map.h" |
31 #include "industry_map.h" |
32 #include "newgrf_callbacks.h" |
32 #include "newgrf_callbacks.h" |
33 #include "newgrf_station.h" |
33 #include "newgrf_station.h" |
34 #include "yapf/yapf.h" |
34 #include "yapf/yapf.h" |
35 #include "date.h" |
35 #include "date.h" |
|
36 #include "helpers.hpp" |
36 |
37 |
37 typedef enum StationRectModes |
38 typedef enum StationRectModes |
38 { |
39 { |
39 RECT_MODE_TEST = 0, |
40 RECT_MODE_TEST = 0, |
40 RECT_MODE_TRY, |
41 RECT_MODE_TRY, |
980 /* Does the authority allow this? */ |
981 /* Does the authority allow this? */ |
981 if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile_org)) return CMD_ERROR; |
982 if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile_org)) return CMD_ERROR; |
982 if (!ValParamRailtype(p2 & 0xF)) return CMD_ERROR; |
983 if (!ValParamRailtype(p2 & 0xF)) return CMD_ERROR; |
983 |
984 |
984 /* unpack parameters */ |
985 /* unpack parameters */ |
985 axis = p1 & 1; |
986 axis = (Axis)(p1 & 1); |
986 numtracks = GB(p1, 8, 8); |
987 numtracks = GB(p1, 8, 8); |
987 plat_len = GB(p1, 16, 8); |
988 plat_len = GB(p1, 16, 8); |
988 /* w = length, h = num_tracks */ |
989 /* w = length, h = num_tracks */ |
989 if (axis == AXIS_X) { |
990 if (axis == AXIS_X) { |
990 w_org = plat_len; |
991 w_org = plat_len; |
1050 |
1051 |
1051 /* Check if the given station class is valid */ |
1052 /* Check if the given station class is valid */ |
1052 if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR; |
1053 if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR; |
1053 |
1054 |
1054 /* Check if we can allocate a custom stationspec to this station */ |
1055 /* Check if we can allocate a custom stationspec to this station */ |
1055 statspec = GetCustomStationSpec(GB(p2, 8, 8), GB(p2, 16, 8)); |
1056 statspec = GetCustomStationSpec((StationClassID)GB(p2, 8, 8), GB(p2, 16, 8)); |
1056 specindex = AllocateSpecToStation(statspec, st, flags & DC_EXEC); |
1057 specindex = AllocateSpecToStation(statspec, st, flags & DC_EXEC); |
1057 if (specindex == -1) return CMD_ERROR; |
1058 if (specindex == -1) return CMD_ERROR; |
1058 |
1059 |
1059 if (statspec != NULL) { |
1060 if (statspec != NULL) { |
1060 /* Perform NewStation checks */ |
1061 /* Perform NewStation checks */ |
1095 StationRect_BeforeAddRect(st, tile_org, w_org, h_org, RECT_MODE_TRY); |
1096 StationRect_BeforeAddRect(st, tile_org, w_org, h_org, RECT_MODE_TRY); |
1096 |
1097 |
1097 tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); |
1098 tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); |
1098 track = AxisToTrack(axis); |
1099 track = AxisToTrack(axis); |
1099 |
1100 |
1100 layout_ptr = alloca(numtracks * plat_len); |
1101 layout_ptr = (byte*)alloca(numtracks * plat_len); |
1101 GetStationLayout(layout_ptr, numtracks, plat_len, statspec); |
1102 GetStationLayout(layout_ptr, numtracks, plat_len, statspec); |
1102 |
1103 |
1103 numtracks_orig = numtracks; |
1104 numtracks_orig = numtracks; |
1104 |
1105 |
1105 do { |
1106 do { |
1106 TileIndex tile = tile_org; |
1107 TileIndex tile = tile_org; |
1107 int w = plat_len; |
1108 int w = plat_len; |
1108 do { |
1109 do { |
1109 byte layout = *layout_ptr++; |
1110 byte layout = *layout_ptr++; |
1110 MakeRailStation(tile, st->owner, st->index, axis, layout, GB(p2, 0, 4)); |
1111 MakeRailStation(tile, st->owner, st->index, axis, layout, (RailType)GB(p2, 0, 4)); |
1111 SetCustomStationSpecIndex(tile, specindex); |
1112 SetCustomStationSpecIndex(tile, specindex); |
1112 SetStationTileRandomBits(tile, GB(Random(), 0, 4)); |
1113 SetStationTileRandomBits(tile, GB(Random(), 0, 4)); |
1113 |
1114 |
1114 if (statspec != NULL) { |
1115 if (statspec != NULL) { |
1115 /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */ |
1116 /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */ |
1422 int32 cost; |
1423 int32 cost; |
1423 int32 ret; |
1424 int32 ret; |
1424 bool type = !!p2; |
1425 bool type = !!p2; |
1425 |
1426 |
1426 /* Saveguard the parameters */ |
1427 /* Saveguard the parameters */ |
1427 if (!IsValidDiagDirection(p1)) return CMD_ERROR; |
1428 if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR; |
1428 |
1429 |
1429 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
1430 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
1430 |
1431 |
1431 if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) |
1432 if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) |
1432 return CMD_ERROR; |
1433 return CMD_ERROR; |
1433 |
1434 |
1434 ret = CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL); |
1435 ret = CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL); |
1435 if (CmdFailed(ret)) return ret; |
1436 if (CmdFailed(ret)) return ret; |
1436 cost = ret; |
1437 cost = ret; |
1437 |
1438 |
1438 st = GetStationAround(tile, 1, 1, -1); |
1439 st = GetStationAround(tile, 1, 1, INVALID_STATION); |
1439 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1440 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1440 |
1441 |
1441 /* Find a station close to us */ |
1442 /* Find a station close to us */ |
1442 if (st == NULL) { |
1443 if (st == NULL) { |
1443 st = GetClosestStationFromTile(tile, 8, _current_player); |
1444 st = GetClosestStationFromTile(tile, 8, _current_player); |
1498 |
1499 |
1499 st->build_date = _date; |
1500 st->build_date = _date; |
1500 |
1501 |
1501 StationRect_BeforeAddTile(st, tile, RECT_MODE_TRY); |
1502 StationRect_BeforeAddTile(st, tile, RECT_MODE_TRY); |
1502 |
1503 |
1503 MakeRoadStop(tile, st->owner, st->index, type, p1); |
1504 MakeRoadStop(tile, st->owner, st->index, type ? RS_TRUCK : RS_BUS, (DiagDirection)p1); |
1504 |
1505 |
1505 UpdateStationVirtCoordDirty(st); |
1506 UpdateStationVirtCoordDirty(st); |
1506 UpdateStationAcceptance(st, false); |
1507 UpdateStationAcceptance(st, false); |
1507 RebuildStationLists(); |
1508 RebuildStationLists(); |
1508 InvalidateWindow(WC_STATION_LIST, st->owner); |
1509 InvalidateWindow(WC_STATION_LIST, st->owner); |
1694 |
1695 |
1695 ret = CheckFlatLandBelow(tile, w, h, flags, 0, NULL); |
1696 ret = CheckFlatLandBelow(tile, w, h, flags, 0, NULL); |
1696 if (CmdFailed(ret)) return ret; |
1697 if (CmdFailed(ret)) return ret; |
1697 cost = ret; |
1698 cost = ret; |
1698 |
1699 |
1699 st = GetStationAround(tile, w, h, -1); |
1700 st = GetStationAround(tile, w, h, INVALID_STATION); |
1700 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1701 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1701 |
1702 |
1702 /* Find a station close to us */ |
1703 /* Find a station close to us */ |
1703 if (st == NULL) { |
1704 if (st == NULL) { |
1704 st = GetClosestStationFromTile(tile, 8, _current_player); |
1705 st = GetClosestStationFromTile(tile, 8, _current_player); |
1971 } |
1972 } |
1972 |
1973 |
1973 /* middle */ |
1974 /* middle */ |
1974 st = GetStationAround( |
1975 st = GetStationAround( |
1975 tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), |
1976 tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), |
1976 _dock_w_chk[direction], _dock_h_chk[direction], -1); |
1977 _dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION); |
1977 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1978 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1978 |
1979 |
1979 /* Find a station close to us */ |
1980 /* Find a station close to us */ |
1980 if (st == NULL) { |
1981 if (st == NULL) { |
1981 st = GetClosestStationFromTile(tile, 8, _current_player); |
1982 st = GetClosestStationFromTile(tile, 8, _current_player); |
2107 if (callback != CALLBACK_FAILED) tile = (callback & ~1) + GetRailStationAxis(ti->tile); |
2108 if (callback != CALLBACK_FAILED) tile = (callback & ~1) + GetRailStationAxis(ti->tile); |
2108 } |
2109 } |
2109 |
2110 |
2110 /* Ensure the chosen tile layout is valid for this custom station */ |
2111 /* Ensure the chosen tile layout is valid for this custom station */ |
2111 if (statspec->renderdata != NULL) { |
2112 if (statspec->renderdata != NULL) { |
2112 t = &statspec->renderdata[tile < statspec->tiles ? tile : GetRailStationAxis(ti->tile)]; |
2113 t = &statspec->renderdata[tile < statspec->tiles ? tile : (uint)GetRailStationAxis(ti->tile)]; |
2113 } |
2114 } |
2114 } |
2115 } |
2115 } |
2116 } |
2116 |
2117 |
2117 if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationGfx(ti->tile)]; |
2118 if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationGfx(ti->tile)]; |
2505 (rating += 20, waiting > 100) || |
2506 (rating += 20, waiting > 100) || |
2506 (rating += 10, true); |
2507 (rating += 10, true); |
2507 } |
2508 } |
2508 |
2509 |
2509 { |
2510 { |
2510 int or = ge->rating; // old rating |
2511 int or_ = ge->rating; // old rating |
2511 |
2512 |
2512 // only modify rating in steps of -2, -1, 0, 1 or 2 |
2513 // only modify rating in steps of -2, -1, 0, 1 or 2 |
2513 ge->rating = rating = or + clamp(clamp(rating, 0, 255) - or, -2, 2); |
2514 ge->rating = rating = or_ + clamp(clamp(rating, 0, 255) - or_, -2, 2); |
2514 |
2515 |
2515 // if rating is <= 64 and more than 200 items waiting, remove some random amount of goods from the station |
2516 // if rating is <= 64 and more than 200 items waiting, remove some random amount of goods from the station |
2516 if (rating <= 64 && waiting >= 200) { |
2517 if (rating <= 64 && waiting >= 200) { |
2517 int dec = Random() & 0x1F; |
2518 int dec = Random() & 0x1F; |
2518 if (waiting < 400) dec &= 7; |
2519 if (waiting < 400) dec &= 7; |
2930 StationRect_BeforeAddTile(st, tile, RECT_MODE_FORCE); |
2931 StationRect_BeforeAddTile(st, tile, RECT_MODE_FORCE); |
2931 } |
2932 } |
2932 } |
2933 } |
2933 |
2934 |
2934 |
2935 |
2935 const TileTypeProcs _tile_type_station_procs = { |
2936 extern const TileTypeProcs _tile_type_station_procs = { |
2936 DrawTile_Station, /* draw_tile_proc */ |
2937 DrawTile_Station, /* draw_tile_proc */ |
2937 GetSlopeZ_Station, /* get_slope_z_proc */ |
2938 GetSlopeZ_Station, /* get_slope_z_proc */ |
2938 ClearTile_Station, /* clear_tile_proc */ |
2939 ClearTile_Station, /* clear_tile_proc */ |
2939 GetAcceptedCargo_Station, /* get_accepted_cargo_proc */ |
2940 GetAcceptedCargo_Station, /* get_accepted_cargo_proc */ |
2940 GetTileDesc_Station, /* get_tile_desc_proc */ |
2941 GetTileDesc_Station, /* get_tile_desc_proc */ |
3062 } |
3063 } |
3063 } |
3064 } |
3064 |
3065 |
3065 if (st->num_specs != 0) { |
3066 if (st->num_specs != 0) { |
3066 /* Allocate speclist memory when loading a game */ |
3067 /* Allocate speclist memory when loading a game */ |
3067 if (st->speclist == NULL) st->speclist = calloc(st->num_specs, sizeof(*st->speclist)); |
3068 if (st->speclist == NULL) CallocT(&st->speclist, st->num_specs); |
3068 for (i = 0; i < st->num_specs; i++) SlObject(&st->speclist[i], _station_speclist_desc); |
3069 for (i = 0; i < st->num_specs; i++) SlObject(&st->speclist[i], _station_speclist_desc); |
3069 } |
3070 } |
3070 } |
3071 } |
3071 |
3072 |
3072 static void Save_STNS(void) |
3073 static void Save_STNS(void) |
3153 FOR_ALL_VEHICLES(v) { |
3154 FOR_ALL_VEHICLES(v) { |
3154 if (v->type == VEH_Road && v->u.road.slot != NULL) v->u.road.slot->num_vehicles++; |
3155 if (v->type == VEH_Road && v->u.road.slot != NULL) v->u.road.slot->num_vehicles++; |
3155 } |
3156 } |
3156 } |
3157 } |
3157 |
3158 |
3158 const ChunkHandler _station_chunk_handlers[] = { |
3159 extern const ChunkHandler _station_chunk_handlers[] = { |
3159 { 'STNS', Save_STNS, Load_STNS, CH_ARRAY }, |
3160 { 'STNS', Save_STNS, Load_STNS, CH_ARRAY }, |
3160 { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, CH_ARRAY | CH_LAST}, |
3161 { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, CH_ARRAY | CH_LAST}, |
3161 }; |
3162 }; |
3162 |
3163 |
3163 |
3164 |