src/station_cmd.cpp
changeset 5838 9c3129cb019b
parent 5835 e0ff603ae0b7
child 5852 cb3f71b16e1a
equal deleted inserted replaced
5837:96b4b92b86ae 5838:9c3129cb019b
    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