src/station_cmd.cpp
branchNewGRF_ports
changeset 10184 fcf5fb2548eb
parent 6878 7d1ff2f621c7
child 10210 a2131f7a315d
equal deleted inserted replaced
10179:eec5a7dcbf61 10184:fcf5fb2548eb
     9 #include "cmd_helper.h"
     9 #include "cmd_helper.h"
    10 #include "debug.h"
    10 #include "debug.h"
    11 #include "tile_cmd.h"
    11 #include "tile_cmd.h"
    12 #include "landscape.h"
    12 #include "landscape.h"
    13 #include "station_map.h"
    13 #include "station_map.h"
    14 #include "station.h"
       
    15 #include "viewport_func.h"
    14 #include "viewport_func.h"
    16 #include "command_func.h"
    15 #include "command_func.h"
    17 #include "town.h"
    16 #include "town.h"
    18 #include "news.h"
    17 #include "news_func.h"
    19 #include "saveload.h"
    18 #include "saveload.h"
    20 #include "airport.h"
    19 #include "airport.h"
    21 #include "sprite.h"
    20 #include "sprite.h"
    22 #include "depot.h"
    21 #include "depot.h"
    23 #include "train.h"
    22 #include "train.h"
    42 #include "window_func.h"
    41 #include "window_func.h"
    43 #include "date_func.h"
    42 #include "date_func.h"
    44 #include "vehicle_func.h"
    43 #include "vehicle_func.h"
    45 #include "string_func.h"
    44 #include "string_func.h"
    46 #include "signal_func.h"
    45 #include "signal_func.h"
       
    46 #include "oldpool_func.h"
    47 
    47 
    48 #include "table/sprites.h"
    48 #include "table/sprites.h"
    49 #include "table/strings.h"
    49 #include "table/strings.h"
    50 
    50 
    51 DEFINE_OLD_POOL_GENERIC(Station, Station)
    51 DEFINE_OLD_POOL_GENERIC(Station, Station)
   131 												 st->fsmportsspeclist[1].spec->size_y[st->FSMport_layout_set],
   131 												 st->fsmportsspeclist[1].spec->size_y[st->FSMport_layout_set],
   132 												 st->FSMport_orientation);
   132 												 st->FSMport_orientation);
   133 	return st->airport_tile + ToTileIndexDiff(keydepot);
   133 	return st->airport_tile + ToTileIndexDiff(keydepot);
   134 }
   134 }
   135 
   135 
   136 RoadStop* GetRoadStopByTile(TileIndex tile, RoadStop::Type type)
   136 RoadStop* GetRoadStopByTile(TileIndex tile, RoadStopType type)
   137 {
   137 {
   138 	const Station* st = GetStationByTile(tile);
   138 	const Station* st = GetStationByTile(tile);
   139 
   139 
   140 	for (RoadStop *rs = st->GetPrimaryRoadStop(type);; rs = rs->next) {
   140 	for (RoadStop *rs = st->GetPrimaryRoadStop(type);; rs = rs->next) {
   141 		if (rs->xy == tile) return rs;
   141 		if (rs->xy == tile) return rs;
   142 		assert(rs->next != NULL);
   142 		assert(rs->next != NULL);
   143 	}
   143 	}
   144 }
   144 }
   145 
   145 
   146 
   146 
   147 static uint GetNumRoadStopsInStation(const Station* st, RoadStop::Type type)
   147 static uint GetNumRoadStopsInStation(const Station* st, RoadStopType type)
   148 {
   148 {
   149 	uint num = 0;
   149 	uint num = 0;
   150 
   150 
   151 	assert(st != NULL);
   151 	assert(st != NULL);
   152 	for (const RoadStop *rs = st->GetPrimaryRoadStop(type); rs != NULL; rs = rs->next) {
   152 	for (const RoadStop *rs = st->GetPrimaryRoadStop(type); rs != NULL; rs = rs->next) {
   492 	for (uint i = 0; i < num_items; i++) {
   492 	for (uint i = 0; i < num_items; i++) {
   493 		SetDParam(i + 1, GetCargo(cargo[i])->name);
   493 		SetDParam(i + 1, GetCargo(cargo[i])->name);
   494 	}
   494 	}
   495 
   495 
   496 	SetDParam(0, st->index);
   496 	SetDParam(0, st->index);
   497 	AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0);
   497 	AddNewsItem(msg, NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, DNC_NONE, st->xy, 0);
   498 }
   498 }
   499 
   499 
   500 /**
   500 /**
   501 * Get a list of the cargo types being produced around the tile (in a rectangle).
   501 * Get a list of the cargo types being produced around the tile (in a rectangle).
   502 * @param produced: Destination array of produced cargo
   502 * @param produced: Destination array of produced cargo
   526 	assert(w > 0);
   526 	assert(w > 0);
   527 	assert(h > 0);
   527 	assert(h > 0);
   528 
   528 
   529 	for (int yc = y1; yc != y2; yc++) {
   529 	for (int yc = y1; yc != y2; yc++) {
   530 		for (int xc = x1; xc != x2; xc++) {
   530 		for (int xc = x1; xc != x2; xc++) {
   531 			if (!(IsInsideBS(xc, x, w) && IsInsideBS(yc, y, h))) {
   531 			TileIndex tile = TileXY(xc, yc);
   532 				TileIndex tile = TileXY(xc, yc);
   532 
   533 
   533 			if (!IsTileType(tile, MP_STATION)) {
   534 				GetProducedCargoProc *gpc = _tile_type_procs[GetTileType(tile)]->get_produced_cargo_proc;
   534 				GetProducedCargoProc *gpc = _tile_type_procs[GetTileType(tile)]->get_produced_cargo_proc;
   535 				if (gpc != NULL) {
   535 				if (gpc != NULL) {
   536 					CargoID cargos[2] = { CT_INVALID, CT_INVALID };
   536 					CargoID cargos[256]; // Required for CBID_HOUSE_PRODUCE_CARGO.
       
   537 					memset(cargos, CT_INVALID, 256);
   537 
   538 
   538 					gpc(tile, cargos);
   539 					gpc(tile, cargos);
   539 					for (uint i = 0; i < lengthof(cargos); ++i) {
   540 					for (uint i = 0; i < lengthof(cargos); ++i) {
   540 						if (cargos[i] != CT_INVALID) produced[cargos[i]]++;
   541 						if (cargos[i] != CT_INVALID) produced[cargos[i]]++;
   541 					}
   542 					}
  1385 
  1386 
  1386 	return cost;
  1387 	return cost;
  1387 }
  1388 }
  1388 
  1389 
  1389 /**
  1390 /**
  1390  * @param truck_station Determines whether a stop is RoadStop::BUS or RoadStop::TRUCK
  1391  * @param truck_station Determines whether a stop is ROADSTOP_BUS or ROADSTOP_TRUCK
  1391  * @param st The Station to do the whole procedure for
  1392  * @param st The Station to do the whole procedure for
  1392  * @return a pointer to where to link a new RoadStop*
  1393  * @return a pointer to where to link a new RoadStop*
  1393  */
  1394  */
  1394 static RoadStop **FindRoadStopSpot(bool truck_station, Station* st)
  1395 static RoadStop **FindRoadStopSpot(bool truck_station, Station* st)
  1395 {
  1396 {
  1484 
  1485 
  1485 	/* ensure that in case of error (or no DC_EXEC) the new road stop gets deleted upon return */
  1486 	/* ensure that in case of error (or no DC_EXEC) the new road stop gets deleted upon return */
  1486 	AutoPtrT<RoadStop> rs_auto_delete(road_stop);
  1487 	AutoPtrT<RoadStop> rs_auto_delete(road_stop);
  1487 
  1488 
  1488 	if (st != NULL &&
  1489 	if (st != NULL &&
  1489 			GetNumRoadStopsInStation(st, RoadStop::BUS) + GetNumRoadStopsInStation(st, RoadStop::TRUCK) >= RoadStop::LIMIT) {
  1490 			GetNumRoadStopsInStation(st, ROADSTOP_BUS) + GetNumRoadStopsInStation(st, ROADSTOP_TRUCK) >= RoadStop::LIMIT) {
  1490 		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
  1491 		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
  1491 	}
  1492 	}
  1492 
  1493 
  1493 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  1494 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  1494 	 * to test if everything is OK. In this case we need to delete it before return. */
  1495 	 * to test if everything is OK. In this case we need to delete it before return. */
  1529 		/*initialize an empty station */
  1530 		/*initialize an empty station */
  1530 		st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile);
  1531 		st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile);
  1531 
  1532 
  1532 		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
  1533 		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
  1533 
  1534 
  1534 		RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
  1535 		RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
  1535 		if (is_drive_through) {
  1536 		if (is_drive_through) {
  1536 			MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, rts, (Axis)p1, town_owned_road);
  1537 			MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, rts, (Axis)p1, town_owned_road);
  1537 		} else {
  1538 		} else {
  1538 			MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
  1539 			MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
  1539 		}
  1540 		}
  1575 
  1576 
  1576 	RoadStop **primary_stop;
  1577 	RoadStop **primary_stop;
  1577 	RoadStop *cur_stop;
  1578 	RoadStop *cur_stop;
  1578 	if (is_truck) { // truck stop
  1579 	if (is_truck) { // truck stop
  1579 		primary_stop = &st->truck_stops;
  1580 		primary_stop = &st->truck_stops;
  1580 		cur_stop = GetRoadStopByTile(tile, RoadStop::TRUCK);
  1581 		cur_stop = GetRoadStopByTile(tile, ROADSTOP_TRUCK);
  1581 	} else {
  1582 	} else {
  1582 		primary_stop = &st->bus_stops;
  1583 		primary_stop = &st->bus_stops;
  1583 		cur_stop = GetRoadStopByTile(tile, RoadStop::BUS);
  1584 		cur_stop = GetRoadStopByTile(tile, ROADSTOP_BUS);
  1584 	}
  1585 	}
  1585 
  1586 
  1586 	assert(cur_stop != NULL);
  1587 	assert(cur_stop != NULL);
  1587 
  1588 
  1588 	/* don't do the check for drive-through road stops when company bankrupts */
  1589 	/* don't do the check for drive-through road stops when company bankrupts */
  1974 	const Vehicle *v;
  1975 	const Vehicle *v;
  1975 	FOR_ALL_VEHICLES(v) {
  1976 	FOR_ALL_VEHICLES(v) {
  1976 		if (player == INVALID_PLAYER || v->owner == player) {
  1977 		if (player == INVALID_PLAYER || v->owner == player) {
  1977 			const Order *order;
  1978 			const Order *order;
  1978 			FOR_VEHICLE_ORDERS(v, order) {
  1979 			FOR_VEHICLE_ORDERS(v, order) {
  1979 				if (order->type == OT_GOTO_STATION && order->dest == station) {
  1980 				if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == station) {
  1980 					return true;
  1981 					return true;
  1981 				}
  1982 				}
  1982 			}
  1983 			}
  1983 		}
  1984 		}
  1984 	}
  1985 	}
  2288 
  2289 
  2289 	/* station_land array has been increased from 82 elements to 114
  2290 	/* station_land array has been increased from 82 elements to 114
  2290 	 * but this is something else. If AI builds station with 114 it looks all weird */
  2291 	 * but this is something else. If AI builds station with 114 it looks all weird */
  2291 	DrawGroundSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE);
  2292 	DrawGroundSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE);
  2292 
  2293 
  2293 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
  2294 	if (HasCatenary(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
  2294 
  2295 
  2295 	if (HasBit(roadtypes, ROADTYPE_TRAM)) {
  2296 	if (HasBit(roadtypes, ROADTYPE_TRAM)) {
  2296 		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
  2297 		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
  2297 		DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
  2298 		DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
  2298 		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
  2299 		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
  2299 	}
  2300 	}
       
  2301 
       
  2302 	/* End now if buildings are invisible */
       
  2303 	if (IsInvisibilitySet(TO_BUILDINGS)) return;
  2300 
  2304 
  2301 	const DrawTileSeqStruct *dtss;
  2305 	const DrawTileSeqStruct *dtss;
  2302 	foreach_draw_tile_seq(dtss, t->seq) {
  2306 	foreach_draw_tile_seq(dtss, t->seq) {
  2303 		SpriteID image = dtss->image.sprite;
  2307 		SpriteID image = dtss->image.sprite;
  2304 		if (relocation == 0 || HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
  2308 		if (relocation == 0 || HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
  2510 	215, 195, 175, 155, 135, 115, 95, 75, 55, 35, 15, 0
  2514 	215, 195, 175, 155, 135, 115, 95, 75, 55, 35, 15, 0
  2511 };
  2515 };
  2512 
  2516 
  2513 static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
  2517 static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
  2514 {
  2518 {
       
  2519 	StationID station_id = GetStationIndex(tile);
       
  2520 	if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
       
  2521 
  2515 	if (v->type == VEH_TRAIN) {
  2522 	if (v->type == VEH_TRAIN) {
  2516 		if (IsRailwayStation(tile) && IsFrontEngine(v) &&
  2523 		if (IsRailwayStation(tile) && IsFrontEngine(v) &&
  2517 				!IsCompatibleTrainStationTile(tile + TileOffsByDiagDir(DirToDiagDir(v->direction)), tile)) {
  2524 				!IsCompatibleTrainStationTile(tile + TileOffsByDiagDir(DirToDiagDir(v->direction)), tile)) {
  2518 			StationID station_id = GetStationIndex(tile);
  2525 			DiagDirection dir = DirToDiagDir(v->direction);
  2519 
  2526 
  2520 			if ((!(v->current_order.flags & OFB_NON_STOP) && !_patches.new_nonstop) ||
  2527 			x &= 0xF;
  2521 					(v->current_order.type == OT_GOTO_STATION && v->current_order.dest == station_id)) {
  2528 			y &= 0xF;
  2522 				if (!(_patches.new_nonstop && v->current_order.flags & OFB_NON_STOP) &&
  2529 
  2523 						v->current_order.type != OT_LEAVESTATION &&
  2530 			if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
  2524 						v->last_station_visited != station_id) {
  2531 			if (y == TILE_SIZE / 2) {
  2525 					DiagDirection dir = DirToDiagDir(v->direction);
  2532 				if (dir != DIAGDIR_SE && dir != DIAGDIR_SW) x = TILE_SIZE - 1 - x;
  2526 
  2533 				if (x == 12) return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); /* enter station */
  2527 					x &= 0xF;
  2534 				if (x < 12) {
  2528 					y &= 0xF;
  2535 					uint16 spd;
  2529 
  2536 
  2530 					if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
  2537 					v->vehstatus |= VS_TRAIN_SLOWING;
  2531 					if (y == TILE_SIZE / 2) {
  2538 					spd = _enter_station_speedtable[x];
  2532 						if (dir != DIAGDIR_SE && dir != DIAGDIR_SW) x = TILE_SIZE - 1 - x;
  2539 					if (spd < v->cur_speed) v->cur_speed = spd;
  2533 						if (x == 12) return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); /* enter station */
       
  2534 						if (x < 12) {
       
  2535 							uint16 spd;
       
  2536 
       
  2537 							v->vehstatus |= VS_TRAIN_SLOWING;
       
  2538 							spd = _enter_station_speedtable[x];
       
  2539 							if (spd < v->cur_speed) v->cur_speed = spd;
       
  2540 						}
       
  2541 					}
       
  2542 				}
  2540 				}
  2543 			}
  2541 			}
  2544 		}
  2542 		}
  2545 	} else if (v->type == VEH_ROAD) {
  2543 	} else if (v->type == VEH_ROAD) {
  2546 		if (v->u.road.state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)v->u.road.state) && v->u.road.frame == 0) {
  2544 		if (v->u.road.state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)v->u.road.state) && v->u.road.frame == 0) {
  2553 					byte side = ((DirToDiagDir(v->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (v->u.road.overtaking == 0)) ? 0 : 1;
  2551 					byte side = ((DirToDiagDir(v->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (v->u.road.overtaking == 0)) ? 0 : 1;
  2554 
  2552 
  2555 					if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
  2553 					if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
  2556 
  2554 
  2557 					/* Check if the vehicle is stopping at this road stop */
  2555 					/* Check if the vehicle is stopping at this road stop */
  2558 					if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
  2556 					if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
  2559 							v->current_order.dest == GetStationIndex(tile)) {
  2557 							v->current_order.GetDestination() == GetStationIndex(tile)) {
  2560 						SetBit(v->u.road.state, RVS_IS_STOPPING);
  2558 						SetBit(v->u.road.state, RVS_IS_STOPPING);
  2561 						rs->AllocateDriveThroughBay(side);
  2559 						rs->AllocateDriveThroughBay(side);
  2562 					}
  2560 					}
  2563 
  2561 
  2564 					/* Indicate if vehicle is using second bay. */
  2562 					/* Indicate if vehicle is using second bay. */
  3030 		RebuildStationLists();
  3028 		RebuildStationLists();
  3031 		InvalidateWindowClasses(WC_STATION_LIST);
  3029 		InvalidateWindowClasses(WC_STATION_LIST);
  3032 	} else {
  3030 	} else {
  3033 		if (IsDriveThroughStopTile(tile)) {
  3031 		if (IsDriveThroughStopTile(tile)) {
  3034 			/* Remove the drive-through road stop */
  3032 			/* Remove the drive-through road stop */
  3035 			DoCommand(tile, 0, (GetStationType(tile) == STATION_TRUCK) ? RoadStop::TRUCK : RoadStop::BUS, DC_EXEC | DC_BANKRUPT, CMD_REMOVE_ROAD_STOP);
  3033 			DoCommand(tile, 0, (GetStationType(tile) == STATION_TRUCK) ? ROADSTOP_TRUCK : ROADSTOP_BUS, DC_EXEC | DC_BANKRUPT, CMD_REMOVE_ROAD_STOP);
  3036 			assert(IsTileType(tile, MP_ROAD));
  3034 			assert(IsTileType(tile, MP_ROAD));
  3037 			/* Change owner of tile and all roadtypes */
  3035 			/* Change owner of tile and all roadtypes */
  3038 			ChangeTileOwner(tile, old_player, new_player);
  3036 			ChangeTileOwner(tile, old_player, new_player);
  3039 		} else {
  3037 		} else {
  3040 			DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
  3038 			DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);